C# XNA - Calculating next point in a vector direction - c#

lets say i have two points A & B in my 3D Space
now i want to start calculate points from A to B in direction of B and i want to continue calculation farther from B on the same line.
How t do it ?
what i am actually working on is bullets from plane.

If I understood your question correctly, you should first get the direction vector by calculating
dir = B - A
and then you can continue the travel by
C = B + dir
Otherwise, please clarify your question, like for example what you mean by "calculate points from A to B", because mathematically there is an infinite amount of points between A and B.
Edit:
If you want to trace a bullet path you have two options:
1) You implement it as hitscan weapon like done in many FPS; any bullets fired will immediately hit where they were aimed. This can be best achieved by doing a raytrace via Ray.Intersects and is probably the simplest and least computationally intensive way to do it. Of course, it's also not terribly realistic.
2) You make the bullet a physical entity in your world and move it during your Update() call via a "normal" combination of current position vector and movement/velocity vector, doing a manual collision detection with any hittable surfaces and objects. The advantage of this is that you can implement proper physics like travel time, drop, friction, etc., however it is also orders of magnitude more difficult to implement in a robust way. If you want to go this way, I suggest using either a pre-made physics API (like Bullet, but I'm not sure if there's a version for XNA) or at least doing extensive Google research on the subject, so you can avoid the many pitfalls of collision detection with fast-moving objects.

its a try to implement a 2D technique in 3D, i calculate the following once
position = start;
dx = destination.X - start.X;
dy = destination.Y - start.Y;
dz = destination.Z - start.Z;
distance = (float)Math.Sqrt( dx * dx + dy * dy + dz * dz );
scale = 2f / distance;
then i go on calculating
position.X += dx * scale;
position.Y += dy * scale;
position.Z += dz * scale;
but the result is still is not working of 3D Space, i am getting result for only 2 Dimension, the third axis is not being changed

Related

Unity C# Trig Functions in movement

I'm creating an fps game in unity and chose to not use the included First Person Controller script to reduce complexity. The camera object will constantly be set to the players position and can rotate. I have created a script containing the following code for movement:
float v = Input.GetAxis("Vertical");
float h = Input.GetAxis("Horizontal");
Vector2 rotation = new Vector2(
Mathf.Cos(cam.transform.eulerAngles.y * deg2rad), (Mathf.Sin(cam.transform.eulerAngles.y * deg2rad))
);
rb.velocity = (
new Vector3(
(-rotation.x * h * speed) + (rotation.y * v * speed),
rb.velocity.y,
(-rotation.y * h * speed) + (-rotation.x * v * speed)
)
);
When I test out the game, the movement is correct along the x-axis in both directions, but is unusual when the players y rotation becomes something other than being aligned with the x-axis (Like moving the player backwards will actually move them forwards and visa-versa).
I'm open to an alternative besides using trig functions for the movement, as I have already used transform.forward and transform.right, but they didn't work entirely.
First thing I'd say is that unless you're intending to learn trig and geometrical functions then you should not reinvent the wheel. As you've stated you want to create a FPS game so really you should leverage the scripts and prefabs that others have created to enable the creation of your game.
If you don't want to use the inbuilt FPS Controller script I'd recommend using a free Asset package named '3rdPerson+Fly'. It appears a bit complex at first however you'll learn about states and stackable behaviours/modes which is going to get you an outcome much faster than creating from scratch. You'll also get the flexibility and openness that comes with a non-inbuilt package. This way you can peek at the inner workings if desired or simply build on top of them. Don't fall for NIH (Not Invented Here) syndrome and stand on the shoulders of giants instead :)
Good luck!
The issue you're having is likely caused by the fact that sin and cos can't determine by themselves which "quadrant" they're in. For example 30 degree angle is the same as a 150 degree angle as far as Sin is concerned.
This video is a fast and good explanation of the issue:
https://www.youtube.com/watch?v=736Wkg8uxA8

Unity C# Firing a projectile at a target rotating around moving axis

I'm developing a 3D spacegame where the camera is in a constant 2D (top down) state. I am able to fire a projectile of speed (s) at a target moving at a given velocity and hit it every time. Great! Okay so what if that target has an angular velocity around a parent? I noticed that if the target has a parent object that is rotating, my projection isn't correct since it doesn't account for the angular velocity.
My initial code was built around the assumption that:
Position_target + Velocity_target * t = Position_shooter + Velocity_shooter * t + Bulletspeed * t
I assume that the shooter is stationary (or potentially moving) and needs to fire a bullet with a constant magnitude.
I simplify the above to this
Delta_Position = Position_target - Position_shooter
Delta_Velocity = Velocity_target - Velocity_shooter
Delta_Position + Delta_Velocity * t = BulletSpeed * t
Squaring both sides I come to a quadratic equation where I can solve for t given determinant outcomes or zeros. This works perfect. I return a t value and then project the target's position and current velocity out to that t, and then I have turret scripts that rotate at a given angular velocity towards that point. If the turret says its looking at that point within 1% on all axis, it fires the bullet at speed(s) and its a 100% hit if the target doesn't alter its course or velocity.
I started adding components on my ships / asteroids that were a child of the parent object, like a turret attached to a ship where the turret itself is a target. If the ship is rotating around an axis (for example Y axis) and the turret is not at x=0 and z=0 my projection no longer works. I thought that using r * sin ( theta + omega * t) as the angular velocity component for the X position and r * cos ( theta + omega * t) for the Z position could work. Theta is the current rotation (with respect to world coordinates) and the omega is the eulerAngle rotation around the y axis.
I've quickly realized this only works with rotating around the y axis, and I can't put the sin into a quadratic equation because I can't extract the t from it so I can't really project this appropriately. I tried using hyperbolics but it was the same situation. I can create an arbitrary t, let's say t=2, and calculate where the object will be in 2 seconds. But I am struggling to find a way to implement the bullet speed projection with this.
Position_targetparent + Velocity_targetparent * t + [ANGULAR VELOCITY COMPONENT] = Position_shooter + Velocity_shooter * t + Bulletspeed * t
Delta_Position_X + Delta_Velocity_X * t + S * t = r * sin (theta + Omegay * t)
Delta_Position_Z + Delta_Velocity_Z * t + S * t = r * cos (theta + Omegay * t)
From here I have been spinning my wheels endlessly trying to figure out a workable solution for this. I am using the eulerAngle.y for the omega which works well. Ultimately I just need that instantaneous point in space that I should fire at which is a product of the speed of the bullet and the distance of the projection, and then my turrets aiming scripts will take care of the rest.
I have been looking at a spherical coordinate system based around the parents position (the center of the rotation)
Vector3 deltaPosition = target.transform.position - target.transform.root.position;
r = deltaPosition .magnitude;
float theta = Mathf.Acos(deltaPosition.z / r);
float phi = Mathf.Atan2(deltaPosition.y,deltaPosition.x);
float xPos = r * Mathf.Sin(theta) * Mathf.Cos(phi)
float yPos = r * Mathf.Sin(theta) * Mathf.Sin(phi)
float zPos = r * Mathf.Cos(theta)
Vector3 currentRotation = transform.root.gameObject.transform.rotation.eulerAngles * Mathf.Deg2Rad;
Vector3 angularVelocity = transform.root.gameObject.GetComponent<Rigidbody>().angularVelocity;
I can calculate the position of the object given these angles ... but I am struggling to turn this into something I can use with the omega * t (angular velocity) approach.
I am wondering if there is a more elegant approach to this problem, or if someone can point me in the right direction of a formula to help me think this through? I am not the best with Quaternions and EulerAngles but I am learning them slowly. Maybe there's something clever I can do with those?
Although the math is likely still tough, I suspect you can simplify the math substantially by having the "target" calculate its future position in local space. And then having it call that location to its parent, have that calculate it in local space, and so on up the hierarchy until you reach world space. Once you have its future position in world space you can aim your turret at that target.
For example an orbiting ship should be able to calculate its future orbit easily. This is an equation for an ellipse. Which can then send that local position to its parent (planet) which is presumably also orbiting and calculate that position relative to itself. The planet will then send this local position to its own parent (Star) and so on. Until you get to world space.
You can further simplify this math by making the bullet's travel time constant (flexible speed), so you can simplify figuring out the future position at a specific time. Depending on the scale of your game, the actual difference in speed might not be that different.
Another idea: Instead of doing all the calculations from brute force, you could "simulate" the target object forward in time. Make sure all the code that affects is position can be run separate from your actual update loop. Simply advance the clock way ahead, and see its future position without actually moving it. Then go back to the present and fire the gun at its future position.
I suggest to solve this problem approximately.
If you can describe the position of your target by a function over time, f(t), then you can approximate it using an divide and conquer strategy like this:
Algorithm (pseudo code):
Let f(t:float):Vector3 be a function that calculates the position of the target at time t
Let g(p:Vector3):float be a function that calculates how long the bullet would need to reach p
float begin = 0 // Lower bound of bullet travel time to hit the target
float end = g(target.position) // Upper bound
// Find an upper bound so that the bullet can hit the target between begin and end time
while g(f(end)) > end:
begin = end
end = end * 2 // Exponential growth for fast convergence
// Add break condition in case the target can't be hit (faster than bullet)
end
// Narrow down the possible aim target, doubling the precision in every step
for i = 1...[precision]:
float center = begin + (end - begin) / 2
float travelTime = g(f(center))
if travelTime > center: // Bullet can't reach target
begin = center
else // Bullet overtook target
end = center
end
end
float finalTravelTime = begin + (end - begin) / 2
Vector3 aimPosition = f(finalTravelTime) // You should aim here...
You need to experiment with the value for [precision]. It should be as small as possible, but large enough for the bullet to always hit the target.
You can also use another break condition, like restricting the absolute error (distance of the bullet to the target at the finalTravelTime).
In case that the target can travel faster than the bullet, you need to add a break condition on the upper bounds loop, otherwise it can become an infinite loop.
Why this is useful:
Instead of calculating a complex equality function to determine the time of impact, you can approximate it with a rather simple position function and this method.
This algorithm is independent of the actual position function, thus works with various enemy movements, as long as the future position can be calculated.
Downsides:
This function calculates f(t) many times, this can be CPU intensive for a complex f(t).
Also it is only an approximation, where the precision of the result gets worse the further the travel time is.
Note:
I wrote this algorithm from the top of my head.
I don't guarantee the correctness of the pseudo code, but the algorithm should work.

How to determine an 360° angle from relative direction?

I have a minimap on the screen and having problems to determine the angle to a target relative to the camera.
Here is some drawing of what I mean with some examples of camera position and direction:
The black triangles represent the camera.
The black arrows define their forward direction.
The blue arrows are the direction to the target (= red dot in the middle) from the camera.
The circles in the specific cameras define the wanted orientation of its red dot.
Here's my code so far:
//Anchored position around minimap circle
void CalculateScreenPos(){
Vector3 dir = transform.position - cam.position; //xz distance
dir.y = 0;
angle = Angle360(cam.forward.normalized, dir.normalized, cam.right);
Vector2 desiredPosition = new Vector2(
eX * -Mathf.Cos(angle * Mathf.PI/180f) * dir.z,
eY * Mathf.Sin(angle * Mathf.PI/180f) * dir.x
);
minimapBlip.anchoredPosition = desiredPosition;
}
public static float Angle360(Vector3 from, Vector3 to, Vector3 right)
{
float angle = Vector3.Angle(from, to);
return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle;
}
But the angle seems not working properly, found out that it ranges from
0° + cam.eulerXAngles.x to 360° - cam.eulerAngles.x
So it works when the cam is never looking to the ground or sky.
How do I get rid of the unwanted added x-eulerAngles by not substracting/adding it again to the angle?
angle -= cam.transform.eulerAngles.x
is a bad choice as when the result of Angle360 is 360, it gets substracted again, leading immediatly to a wrong angle.
Also the circle can be an ellipsoid, that's why I have put eX and eY in the desired position that determine the extends of the ellipse.
I don't know what data type you are using e.g. cam.position, cam.heading, etc. but some general guidance that will help you debug this problem.
Write a unit test. Prepare some canned data, both for input (e.g. set cam.position/cam.heading, transform, etc.) and output (the expected angle). Do this for a few cases, e.g. all the six examples you've shown. This makes it easier to repeat your test, and understand which case isn't working - you might see a pattern. It also makes it easy to run your code through a debugger.
Break your functions into logical units of work. What does Angle360 do? I guess you understand what it is supposed to do, but I think it is really two functions
Get the angle between the two vectors (current direction and target direction)
Rotate map (or something like that)
Write tests for those broken out functions. You're just using some library angle difference function - is it behaving as you expect?
Name your variables. You have a vector called right - what is that? There's no comment. Is it right as in 'correct', or as in 'opposite of left'? Why is it Vector3.Angle(right, to), and why not Vector3.Angle(to, right)?
Generally you are performing some math and getting tripped up because your code is not clear, things are not well named, and the approach is not clear. Break the problem into smaller pieces and the issue will become obvious.
I solved it:
angle = Mathf.Atan2(heading.x, heading.z) * Mathf.Rad2Deg-Camera.main.transform.eulerAngles.y;
Vector2 desiredPosition = new Vector2(
eX * -Mathf.Cos((angle+90) * Mathf.Deg2Rad),
eY * Mathf.Sin((angle+90) * Mathf.Deg2Rad)
);
Thanks for the help so far and happy coding :D

Correctly rendering a mirror in XNA

I have my code I wrote for displaying a mirror as a plane with a texture from a RenderTarget2D each frame.
This all works perfectly fine, but I still think that there is something wrong in the way the reflection goes (like, the mirror isn't looking exacly where it's supposed to be looking).
There's a screenshot of the mirror that doesn't really look bad, the distort mainly occurs when the player gets close to the mirror.
Here is my code for creating the mirror texture, notice that the mirror is rotated by 15 degrees on the X axis.
RenderTarget2D rt;
...
rt = new RenderTarget2D(device, (int)(graphics.PreferredBackBufferWidth * 1.5), (int)(graphics.PreferredBackBufferHeight * 1.5));
...
device.SetRenderTarget(rt);
device.Clear(Color.Black);
Vector3 camerafinalPosition = camera.position;
if (camera.isCrouched) camerafinalPosition.Y -= (camera.characterOffset.Y * 6 / 20);
Vector3 mirrorPos = new Vector3((room.boundingBoxes[8].Min.X + room.boundingBoxes[8].Max.X) / 2, (room.boundingBoxes[8].Min.Y + room.boundingBoxes[8].Max.Y) / 2, (room.boundingBoxes[8].Min.Z + room.boundingBoxes[8].Max.Z) / 2);
Vector3 cameraFinalTarget = new Vector3((2 * mirrorPos.X) - camera.position.X, (2 * mirrorPos.Y) - camerafinalPosition.Y, camera.position.Z);
cameraFinalTarget = Vector3.Transform(cameraFinalTarget - mirrorPos, Matrix.CreateRotationX(MathHelper.ToRadians(-15))) + mirrorPos;
Matrix mirrorLookAt = Matrix.CreateLookAt(mirrorPos, cameraFinalTarget, Vector3.Up);
room.DrawRoom(mirrorLookAt, camera.projection, camera.position, camera.characterOffset, camera.isCrouched);
device.SetRenderTarget(null);
And then the mirror is being drawn using the rt texture.
I supposed something isn't completly right with the reflection physics or the way I create the LookAt matrix, Thanks for the help.
I didn't use XNA, but I did some Managed C# DX long time ago, so I don't remember too much, but are you sure mirrorLookAt should point to a cameraFinalTarget? Because basically the Matrix.CreateLookAt should create a matrix out of from-to-up vectors - 'to' in your example is a point where mirror aims. You need to calculate a vector from camera position to mirror position and then reflect it, and I don't see that in your code.
Unless your room.DrawRoom method doesn't calculate another mirrorLookAt matrix, I'm pretty sure your mirror target vector is the problem.
edit: Your reflection vector would be
Vector3 vectorToMirror = new Vector3(mirrorPos.X-camera.position.Y, mirrorPos.Y-camera.position.Y, mirrorPos.Z-camera.position.Z);
Vector3 mirrorReflectionVector = new Vector3(vectorToMirror-2*(Vector3.Dot(vectorToMirror, mirrorNormal)) * mirrorNormal);
Also I don't remember if the mirrorReflectionVector shouldn't be inverted (whether it is pointing to mirror or from mirror). Just check both ways and you'll see. Then you create your mirrorLookAt from
Matrix mirrorLookAt = Matrix.CreateLookAt(mirrorPos, mirrorReflectionVector, Vector3.Up);
Though I don't know wher the normal of your mirror is. Also, I've noticed 1 line I can't really understand
if (camera.isCrouched) camerafinalPosition.Y -= (camera.characterOffset.Y * 6 / 20);
What's the point of that? Let's assume your camera is crouched - shouldn't its Y value be lowered already? I don't know how do you render your main camera, but look at the mirror's rendering position - it's way lower than your main eye. I don't know how do you use your IsCrouched member, but If you want to lower the camera just write yourself a method Crouch() or anything similar, that would lower the Y value a little. Later on you're using your DrawRoom method, in which you pass camera.position parameter - yet, it's not "lowered" by crouch value, it's just "pure" camera.position. That may be the reason it's not rendering properly. Let me know If that helped you anything.

Calculating Velocity Between Two Points [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have an enemy ship and a player ship.
I would like the enemy ship to always fly towards the player in a direct line, at all times, even when the player is moving.
I'm going about this using the Ray class for C# XNA.
I have two vector coordinates, the position/origin of the ray (the players current position), and the Direction of the ray (the enemy's current position). I'd like the enemy's position to gradually move towards the players position.
I have this code so far.
enemyPlayerTrack.Position = playerPos;
enemyPlayerTrack.Direction = enemyPos;
I'm unsure whether I need another vector for velocity or not.
In the end, the enemy will be drawn to the screen with a new position with this code:
enemyWorldMatrix = Matrix.CreateTranslation(new Vector3(x, y, z));
Without a mathematical background, I'm having trouble creating a velocity to bridge the two vectors closer and closer.
We choose some speed s. Then the direction of the player from the enemy is:
dir_x = player_x - enemy_x
dir_y = player_y - enemy_y
Overall speed s = sqrt(vel_x^2 + vel_y)^2, so we scale the dir vector to give us the speed:
factor = s / sqrt(dir_x^2 + dir_y^2)
vel_x = dir_x * factor
vel_y = dir_y * factor
So now the enemy will always fly at the same speed, directed towards the player. But if the player is near the enemy, the enemy will overshoot and keep bouncing back and forth over the player. So we limit the speed:
distance = sqrt(dir_x^2 + dir_y^2)
delay_to_reaching_player = 2 // some measure of time
enemy_speed = min(s, distance/delay_to_reaching_player)
This way, by setting the delay, the enemy will slow down as it approaches the player, once it gets close enough to stop moving at its maximum speed (s).
I don't have XNA in front of me, so this is just pseudocode...
The total delta between the two should be simply:
var delta = playerPosition - enemyPosition;
This gives direction, but will usually have the wrong magnitude; so we can rescale that to a unit-vector via:
var magnitude = Math.Sqrt(delta.x * delta.x + delta.y * delta.y +
delta.z * delta.z); // however many dimensions you have...
var unitDelta = delta / magnitude; // assuming non-zero; if zero, don't move
var newVelocity = unitDelta * enemySpeed;
Note, however, that this defies momentum, and is very basic (it doesn't account for the player's velocity - it'll feel like the AI is stupid).
If you have a vector from the enemy -> player, you basically have a translation that you can apply to the enemy to get it to jump to the players position. You need to get back to a 'unit' by normalising the vector which will set the vectors overall length to '1' but have it still point in the direction of the player, then you can multiply this value by the velocity you actually want to get a vector to translate the enemy by to move it towards the player
As people have already answered - to get a unit you need sum the products of both components of the vector and then take the square root. This ties to pythagoras theorem e.g.:
If you take the components of a vector say
(2,2)
Which would be this:
2
^
|
|
--> 2
And then draw a line between the origin (0,0) and the point where the vector ends meet - you get a triangle...
2
^
/|
/ |
--> 2
This line represents the magnitude of the vector, you take the sum of the squares of both components and then sqrt it to get the length of this line:
2 * 2 + 2 * 2 = 8
sqrt(8) = 2.82
So this vector is 2.82 long - meaning the 2 and 2 values are 2.82 times the size of a single unit vector
To get components that are '1' long or a 'unit', we need to normalise the vector - we do this by dividing each component by the magnitude
2 / 2.82 = 0.70
Which sounds about right - I know the angle of this vector is 45 degrees (up 2 across 2 must be a perfect diagonal) so you can check it using cosine or sine since cosine/sine provides the horizontal or vertical unit length of a vectors component for the given angle
sin(45) or cos(45) = 0.70
Spot on
So now you know that the angle towards the player uses a 1 length vector with the following components
(0.7, 0.7)
To move the enemy 3 units towards the player, you'd simply multiply the components by 3
0.7 * 3 = 2.1
So
(2.1, 2.1)
Would move the enemy 3 units towards the player in this physics step
Does this help at all?

Categories

Resources