Linear 1D audio balance with OpenAL - c#

I've already asked this question on the OpenTK forums but there doesn't seem to be anyone able to respond. (http://www.opentk.com/node/3638)
In OpenTK, I'm trying to get a balance value of -1 to 1 converted to the left/right audio channels. When 0 (default value) both sides should be at 100% gain. When 1 100% for right and 0% for left and the opposite for -1. I'm having a hard time trying to get this to work in OAL seeing as this is actually my first time working with it.
So far I've tried:
After OAL initialization:
AL.DistanceModel(ALDistanceModel.LinearDistanceClamped);
For each new source:
AL.Source(SourceId, ALSourcef.MaxDistance, 1f);
AL.Source(SourceId, ALSourceb.SourceRelative, false);
For setting the balance:
float balance = 0f; //(-1f to 1f)
OpenTK.Vector3 position = new OpenTK.Vector3(balance, 0f, 0f);
AL.Source(SourceId, ALSource3f.Position, ref position);
This will make the audio go just above 100% on the left channel and 0% on the right for all negative values of balance and just above 100% right 0% left for all positive values, so I'm kinda stuck.
How should I go about doing this? Any help is appreciated!
Gr.Viller
BTW: This looks like a near-duplicate of the unanswered OpenAL 2d panning C++.

Using the OpenAL Soft mailing list I've got the answer I needed:
In FNA we do something like this, but it's probably not ideal (if not just incorrect):
https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/Audio/SoundEffectInstance.cs#L58
I know for sure that this doesn't provide hard panning, but you probably didn't really want to do hard pans anyway. We do that work to keep things at the 1.0f distance, but if attenuation isn't required for your project, you can turn that off and possibly save some time/effort:
https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/Audio/OpenALDevice.cs#L102
-Ethan
TL;DR:
Disable the distance system with:
AL.DistanceModel(ALDistanceModel.None);
Then set the balance like this:
AL.Source(SourceId, ALSource3f.Position, balance, 0f, (float)Math.Sqrt(1 - Math.Pow(balance, 2)));
Basically creating a half-circle on the Z-axis to always keep the same distance from the listener while shifting the direction to the audio.

Related

Finding average rotation from an array of different points

My name is Stanley and I need help :).
I am attempting to find the average rotation from an array of positions. (Stay with me here). If you are confused with what I mean, just like I am myself, then here is an example. I am making a boating game and there are raycast hits that find four points at each corner of the boat. In order to make the floating look realistic, I made it so that the average y position of all four points would be the y position of the boat. But the average rotation I cannot seem to figure out.
I have done some tests if there is a point at 0,0,0 and 1,1,0 and 0,1,1 the average rotation using xyz coordinates is -25,-25,50 and I can't seem to figure out the math behind it. (I eyeballed the final rotation in unity and it looks pretty spot on, that is how I got that number.) If anyone has seen anything about this online like an equation or way of solving this it would be a huge help.
Thanks Everyone
Stan.
I dont know whether I understood you correctly, but how exactly do u get an average rotation of (-25, -25, 50)? What I would do is (if the number of points are always three) create a plane, calculate the normal of that plane and trying to figure out what combination of rotation matrices lead to the corresponding components.
If your three points are (0,0,0), (1,1,0), (0,1,1) the corresponding plane's normal would be (-1, 1, -1), and from that you could deduce what the rotations must be in order to get a reference vector (lets say (1,0,0)) that satisfies R_X(a) * R_Y(b) * R_Z(c) * (1,0,0) = (-1, 1, -1)
But I guess thats not what you want, do you?

How to make a perfect cube

In Unity, I create a cube with scale 1,1,1. Position is 0,1,0.
Then I placed it above a plane which is 15,1,5000. Position is 0,0,0.
I checked if the cube is below 1 in Y-axis, this will mean to me that the cube fall on the plane. I can control this cube by going left or right. If I go to left, there's no issue. If I go to right, my position becomes 0.9999998~. This makes my checking of falling become true even though the cube is still on the plane. Somehow, the cube seems not be be a perfect cube. Hope someone can enlighten me on why is this happening. Thanks!
This may not be the answer you want, but - in poor words - computers' arithmetic is finite (search for floating point arithmetic). So, the "perfect cube" that you're looking for does not exist in the finite representation a machine could perform.
Moreover, Unity has its own physics engine that (like all physics engines) approximates the calculus of real world during each operation (translation, rotation, scaling).
The only way in which you can overcome the problem is by doing comparisons not with exact values (0, 1) but with ranges.
To maintain "order" in the coordinate system of your scene you could also - at fixed intervals - "adjust" your values, so, for example, manually setting the coordinate value to 1 if it is between 0.95 and 1.05 (adjust the values with your world's coordinate system, of course).
Related note: in your comment you say "But my point is that why it seems like the cube is not perfect 1x1x1. Somehow it's like 1x1x0.9999998". The fact is that a VR system, like Unity, does not maintain the objects' size in memory, but their vertices' coordinates. You feel like the object's dimensions have changed due to the translation, but this is not true in a strict way: it's just a finite approximation of the vertices' values for their X, Y, Z.

AI : fire on moving object

i try to to make an AI in C# (with unity) that can predict the estimated position of a moving object to hit it with a bullet
the moving object have a movement speed of 5f and the bullet have a speed of 7f
my problem is that the time my bullet travel to my estimated position my "enemy" already moved further and the bullet don't hit
do you know a formula or code that i can adapt to improve my targeting AI ? (already looking for that in google but don't find anything usefull)
thank
An answer to your question from unreal engine forums
Here is the top answer from there in case the link dies. I did not write this code I simply found it with a quick google of your problem which you stated you already tried.
Link answer:
Get the "velocity" of the target player. Multiply by the time the bullet will take to travel to the target. Then get the position of the target, add the velocity*time vector, and that's the position you should aim at. You can either hard-code the travel time (half a second, or whatever,) or you can in turn measure the distance between AI and player, and divide by bullet travel time, to come up with an approximate travel time. You can also apply a differential equation to calculate the exact time of impact and exact direction, but that requires a little more math and is slightly harder to write out, so I think the above will work best for you.
Simply:
Distance = Length(Target_Position - Firing_Position)
Time = Distance / Bullet_Speed
Predicted_Position = Target_Position + (Target_Velocity * Time)

Continuous aim to target in Malmo

Malmo is Microsoft's AI framework for Minecraft, consisting of a mod for the game itself, and a multi-platform framework for sending inputs and receiving data about the world.
Minecraft's aiming is cylindrical. It's stored in a yaw (left and right) and pitch (up and down) instead of a full-on rotation quaternion. Yaw goes from -180 degrees at the far left and wraps to 180 at the far right. Pitch goes from -90 pointing directly up (zenith) to 90 directly down (nadir). In my code I store these as a Vector2 (recreated to work much like XNA's) such that X represents Yaw, and Y represents Pitch.
I'm having trouble creating a continuous aiming to target algorithm so that the AI is able to aim its camera to a given target yaw and pitch. Because the only way to do so while still allowing continuous movement is through continuous aiming (setting yaw and pitch velocities, rather than values), I need to repeatedly increment the yaw and pitch towards the target direction.
I do this by storing the target direction in a nullable property. If the property is null, that means not to change the aim. Otherwise, subtract the distance between the stored value (target aim) and the current aim (supplied via parameter) each time the update method is called. It then scales the difference so that either yaw or pitch is 1 (max speed), and the other is correctly proportioned for that. This proportioned Vector2 velocity is split into its yaw and pitch, and then sent to the client via the turn and pitch commands. Once within 10 degrees of the target direction, the target is set to null.
On paper, it seems like this would make the camera's aim go directly towards the target direction (excluding yaw wraparounds). However, the client's pitch usually goes straight past the target direction, despite the the update method sending a pitch command that says to go the opposite direction. This means the pitch somehow gets "stuck" at the zenith and nadir, but fixes itself and "turns around" and gets stuck at the opposite pole after a couple seconds. The amount of time spent stuck before turning around seems to increase exponentially (or maybe quadratically) each time.
Here's the source code of my aim update method:
public void UpdateAim(Observations obs)
{
// AimTarget is a Vector2? property
if (AimTarget == null || obs == null)
{
return;
}
if (AimTarget.Value.Distance(obs.Aim) < AIM_CLOSE_ENOUGH) // < 10
{
Logger.LogInfo("Reached {0}", AimTarget.Value);
Look(Vector2.Zero);
AimTarget = null;
return;
}
double deltaYaw = AimTarget.Value.X - obs.Aim.X;
double deltaPitch = AimTarget.Value.Y - obs.Aim.Y;
// These two are stored as private Vector2 fields
deltaAim = new Vector2(deltaYaw, deltaPitch);
scaledAim = deltaAim / Math.Max(Math.Abs(deltaAim.X), Math.Abs(deltaAim.Y));
Look(scaledAim); // sets continuous aim velocity
}
And the (simplified) source code of Look(Vector2):
public void Look(Vector2 direction)
{
// Agent is an AgentHost property
Agent.sendCommand("turn " + velocity);
Agent.sendCommand("pitch " + velocity);
}
UpdateAim() is called 20 times a second (although I have tried as high as 50 times a second and as low as 5) during the main game loop.
At the end of the last time I ran the AI (which got stuck at the nadir), my aiming debug data looked like this:
// Format: (yaw, pitch)
Target Aim: (134.75, 27.90)
Actual In-Game Aim: (-6.50, 90.00) // Lines up with MC's debug screen
Delta Aim : (145.17, -62.10) // Total degrees needed to go in yaw and pitch
Scaled Aim Velocity: (1.00, -0.43)
The scaled aim velocity is what is supplied to Look(). As you can see, the pitch velocity was negative as it was supposed to be, but the actual in-game aim remains at 90 and for some reason doesn't get corrected. Am I doing the math right?
From all what I can see, the math is elegant and checks out. If the pitch velocity is negative at the nadir and it doesn't move down, to me it looks like Agent.sendCommand not doing its job properly.
When setting the speed, does it remain at the speed you set it to until another one is set? Or do speeds get added to each other? What happens if the pitch is out of bounds?
You probably managed to fix this ages ago, but just in case, here are a few thoughts:
In your Look() method, you have the following:
Agent.sendCommand("turn " + velocity);
Agent.sendCommand("pitch " + velocity);
I assume the repeated use of velocity is a typo made when you simplified the code for SO use? Otherwise this would certainly explain the behaviour.
Your scaling code is interesting - is there any reason why you need to keep the ratio of yaw velocity to delta velocity the same? i.e do you really need the Math.Max(Math.Abs(deltaAim.X), Math.Abs(deltaAim.Y)) term? The two movements (yaw and pitch) are totally independent, so there's no reason to scale them dependently, unless it improves performance in some clever way I've not spotted.
You may need to take oscillations / damping into account. Imagine your yaw is correct (deltaYaw == 0). Your scaling means that your pitch delta velocity is always going to be at the maximum value (1, or -1 depending on direction). In other words, even if the delta pitch is only 0.0001, you'll still be adjusting at maximum speed and will significantly overshoot. (Obviously the use of AIM_CLOSE_ENOUGH will help with this, but I image it's still possible to get oscillations - especially if you have a high turnSpeedDegs set - see http://microsoft.github.io/malmo/0.17.0/Schemas/MissionHandlers.html#element_ContinuousMovementCommands)
For an example of this sort of thing working, take a look at the cart_test.py sample - https://github.com/Microsoft/malmo/blob/master/Malmo/samples/Python_examples/cart_test.py
Here's the relevant code snippet. yaw_to_mob is the target yaw, and yaw is the player's current yaw.
# Find shortest angular distance between the two yaws, preserving sign:
deltaYaw = yaw_to_mob - yaw
while deltaYaw < -180:
deltaYaw += 360;
while deltaYaw > 180:
deltaYaw -= 360;
deltaYaw /= 180.0;
# And turn:
agent_host.sendCommand("turn " + str(deltaYaw))
If you want to see the oscillation problem in action, by the way, take a look at the MazeRunner.py sample (same location as cart_test.py) and increase the turnSpeedDegs by a factor of two or three. Minecraft updates the pitch/yaw at render tick time, not world tick time, so slower render speeds will create bigger oscillation problems.

How to calculate bounce angle?

I played around with it for a while, but I simply can't figure it out.
I made a tank that fires missiles, and when the missiles hit the walls, I want them to bounce off, but I want them to bounce off to the right angle.
Right now I haven't got any obstacles, the missiles just bounce off when they get outside the viewportRectangle I made.
Is the solution I'm looking for quite advanced?
Is there a relativly simple way to do it?
You might think that because your walls are aligned with the coordinate axes that it makes sense to write special case code (for a vertical wall, negate the x-coordinate of the velocity; for a horizontal wall, negate the y-coordinate of the velocity). However, once you've got the game working well with vertical and horizontal walls, probably the next thing you'll think is, "what about walls at arbitrary angles?" So it's worth thinking about the general case from the beginning.
In the general case, suppose your missile has velocity v and hits a wall with surface normal n.
Split v into components u perpendicular to the wall and w parallel to it.
Where:
u = (v · n / n · n) n
w = v − u
Here, v · n is the dot product of the vectors v and n. See the link for an explanation of how to compute it. The dot product n · n evaluates to the square of the length of the normal vector; if you always keep your normals in the form of unit vectors then n · n = 1 and you can omit the division.
After bouncing, the component of motion parallel to the wall is affected by friction f, and the component perpendicular to the wall is affected by elasticity, which can be given in the form of a coefficient of restitution r.
So the velocity after the collision is v′ = f w − r u. In a perfectly elastic, frictionless collision, v′ = w − u; that is, the motion is reflected about the normal at the point of collision, as in the diagram given in Bill's answer.
This approach works just the same in three dimensions too.
(Obviously this is a very simplified notion of bouncing; it takes no account of angular momentum or deformation. But for many kinds of video games this kind of simplification is perfectly adequate.)
I think an easier way to do this is to use the velocity of the missile instead of calculating angles. Say you have a missile that has xVelocity and yVelocity to represent its movement horizontally and vertically. Those velocities can be positive or negative to represent left, right, up, or down.
If a missile hits a top or bottom border reverse the sign of the yVelocity.
If a missile hits a left or right border reverse the sign of the xVelocity.
This will keep the movement in the opposite axis the same.
Borrowing the image from ChrisF's answer, let's say the missile starts out at position I.
With the xVelocity and yVelocity both being positive (in 2D graphics right and down are typically positive) the missile will travel in the direction indicated. Let's just assign values of
xVelocity = 3
yVelocity = 4
When the missile hits the wall at position C, its xVelocity shouldn't change, but its yVelocity should be reversed to -4 so that it travels back in the up direction, but keeps going to the right.
The benefit to this method is that you only need to keep track of a missile's xPosition, yPosition, xVelocity, and yVelocity. Using just these four components and your game's update rate, the missile will always get redrawn at the correct position. Once you get into more complicated obstacles that are not at straight angles or are moving, it will be a lot easier to work with X and Y velocities than with angles.
For perfect particles (& light) the angle of reflection is equal to the angle of incidence, as illustrated by this diagram (from commons.wikimedia.org).
The Wikipedia page on reflection is quite good at explaining how it works.
It's a little bit more complicated when you take into account the elasticity and materials of the object and the obstacles, but this is probably good enough for most applications.
I've had this problem, the only way I found was separating the axes of collision!
Try it:
x += velocity * Math.cos(angle * Math.PI /180);
y += velocity * Math.sin(angle * Math.PI /180);
if (x < 0 || x > canvas.width) {
angle = 180 - angle;
}
else if (y < 0 ||y > canvas.height) {
angle = 360 - angle;
}
I hope this helps you!
As an aside to the specific physics question you are asking, I would recommend the book "Beginning Math and Physics for Game Programmers" by Wendy Stahler. I found it quite useful for my game/physics programming projects.
The code that accompanies the book is C++ but if you know C#, it would be pretty easy to make the conversion.
Have a good one!
180-a will not work in all instances, unless you are merely working a bounce on a top surface when X is increasing.
One direction to head is the XNA forums or pick up XNA sample code. It is C# and it is for building games. I am not stating you want to build your games in XNA, but it is a great tool, and it is free.
Not complicated at all - pseudo-code:
angleObjectHitWall = a;
bounceAngle = 180-a;
Of course this is a very simple calculation, and is totally irrelevant once you start to take into account factors such as material, gravity, walls which aren't straight, etc...
This is really a physics question, so if you are not a physicist (and since you are asking this question, I'm going to take it that you are not) it will require a lot of reading and brainstorming to get it right.
I suggest reading this wikipedia entry to get the basic idea about the depth of your question.
If you only want to make it "look plausible" then I wouldn't worry about it too much and use Bill the Lizard's answer, however if you want to make it right you will have quite an adventure. Don't let this scare you tho! Good luck!
a = 2w - b
where:
a => resulting angle
w => wall or floor or ceiling angle
b => ball angle
This is what I come up after trying to find the simplest formula for computing just the resulting angle of ball bouncing the walls, ceiling and floor. The result could go beyond +360 or -360 degrees but they are still equivalent angle.For example if the ceiling angle is 270deg and the ball angle is 30deg, the resulting angle is 510deg which is equivalent to +150deg or -210 deg. If you'll use 90deg for the ceiling instead of 270deg, the result is still 150deg.
if(!Collide(Missle, Mainchar)){
(Velocity.x)*-1;
(Velocity.y)*-1;
}
It works and is simple, good luck.

Categories