i am making 3D Simulation of Solar System
for every planet i have an instance of class Celestial Body. I am using the following code for revolution and rotation of sun, planets & their moons.
world = Matrix.CreateTranslation(0,0,0) * Matrix.CreateRotationY(rotation) * Matrix.CreateTranslation(position) * Matrix.CreateRotationY(revolution);
rotation is my float variable for rotation of planet around its own axis
revolution is my float variable for revolution of planet in orbit
position is to my vector3 variable to put the body in orbit or at its radius from center e.g postion = new Vector3(70,0,0)
Now it works really fine.
But the problem is i need to locate \ get the position of my planet, to where it has been translated after the Matrix multiplication literally in x,y,x co-ordinates.
How To ? get the current X , Y , Z coordinates of my planet
the other option for me would be to use some maths formula that calculates a 2D circle for me.
I think what you're looking for is Matrix.Translation. This gives you the x, y, z co-odinates of the matrix that it's called on in a Vector3.
So, to get the new position, you should use
Vector3 newPosition = world.Translation;
after your calculations.
Related
I have the following scenario:
I am working on a top-down 2-dimensional (XZ plane) game and i need to calculate the difference
of the characters movement direction (moveDir) to the look direction (lookDir).
I would like to calculate a 2D Vector (xy) that holds the following information:
The X value should range from -1 (character facing backwards) to 1 (facing forwards)
The Y value should also range from -1 (character facing left) to 1 (facing right).
To calculate the X value I can use the dot product of moveDir and lookDir.
However, I dont understand how to correctly calculate the Y value. I assume that I have to use the signedAngle between moveDir and lookDir, as the signedAngle returns a value of -90 if the character is facing left and 90 if its facing right.
I could probably even use the signedAngle between the vectors for calculating both X and Y values, as a signedAngle of 0 has the same meaning as a dot product of 1 (and also the same applies to a signedAngle of 180 and the dot product of -1).
How do I calculate the missing part?
I figured out the following solution (pseudocode):
y = 1 - absoluteValue(dotProduct(lookDir, moveDir))
if (signedAngle(lookDir, moveDir) <= 0
y *= -1
As said assuming both moveDir and lookDir are normalized vectors I think you can simply use Vector2.Dot for the first one:
var x = Vector2.Dot(moveDir, lookDir);
this will return a value between 1 (lookDir == moveDir => looking "forward") and -1 (lookDir == -moveDir => looking "back") and 0 would mean it is perpendicular.
Then for "left" and "right" you can cheat a little bit and basically do the same but using Vector3.Cross (note that even though you only want 2D vectors Unity is a 3D engine after all) in order to first obtain a vector that supposedly is "right" like e.g.
var y = Vector2.Dot(lookDir, Vector3.Cross(moveDir, Vector3.forward).normalized);
to explain this a bit
we use Vector3.forward which is basically (0, 0, 1) (a vector pointing into the screen away from you) since you are dealing with Vector2 vectors which move on the XY plane. So in order to get a perpendicular vector to a Vector2 we first need a vector that is perpendicular to all of them on the third axis
Vector3.Cross uses left hand rule
so
Vector3.Cross(moveDir, Vector3.forward)
returns a Vector pointing 90° to the "right" from the moveDir
Vector3 and Vector2 are implicitly convertible into each other which will simply ignore the Z component or use 0
OR as Fredy pointed out you can also simply use
var y = Mathf.Sin(Vector2.SignedAngle(lookDir, moveDir) * Mathf.Deg2Rad);
which basically does the same and is probably less complicated ;)
The simple way to get player front position at specific distance
Vectro3 forward = player.transform.forward * distance;
Vector3 newPlayerFronPosition= player.transform.position + new Vector3(forward.x, forward.y, forward.z);
newPlayerFronPosition= new Vector3(newPlayerFronPosition.x, newPlayerFronPosition.y - 4f, newPlayerFronPosition.z);
navigationCanvas.transform.position = newPlayerFronPosition;
navigationCanvas.transform.rotation = camRotationToWatch.transform.rotation;
its actually working fine but the problem is as my player move up or down the navCanvas become appear ver near to my player. How to mainitain spcific distance all the time.?? that no matter player look above or down the navcanvas display at specfic distance.(position)
disatnceUICam = Vector3.Distance(newPlayerFronPosition, player.transform.position);
I also logged the distance and surprisingly it the distance is changing when i am moving up or down. its changing from 6 to 12 as i am looking up to down.
If I've understood you correctly, and you want a point on in front of your player transform on the X Z Plane a set distance from the forward of your player, you should try something like this:
Vector3 horizontalForward = new Vector3(
player.transform.position.x + player.transform.forward.x,
player.transform.position.y,
player.transform.position.z + player.transform.forward.z
).normalized * distance;
I suspect what you're describing is occurring because the transform of your 'player' variable is connected to the direction of your game camera. As the camera looks up, the world position of your forward changes relative to the camera. Using just the X and Z will produce a varying distance as your camera transform rotates around the X Axis. Perhaps this diagram will illustrate what I mean a little better:
Sorry the hypotenuse is a little wonky but you get the idea right?
I am developing a game in XNA (C#), I am wondering how to use 2 versions of transformation. In my idea, the works of this functions are:
(Assume that vectors are originated from Matrix.Identity)
Vector2 resultVec = Vector2.Transform(sourceVector, destinationMatrix); is used for Position vectors transformation.
Vector2 resultVec = Vector2.TransformNormal(sourceVector, destinationMatrix); used for transforming Velocity vectors.
Is that true?. Who knows the explanation in detail, please help!
The simple answer is that -
Vector2.Transform() applies the entire Matrix to the vector while
Vector2.TransformNormal() only applies the Scale and Rotational parts of the Matrix to the vector.
With transformation, functions will multiply the source vector with the produced matrices.
Transform() is used for vectors representing the positions in 2D or 3D space. This will, in detail, take the Transpose (T operator) of the Invert matrix represents your Coordinate.
In Math: retVec = T(M ^ -1) x srcVec.
TransformNormal() used for direction, tangent vectors. This reserves the matrix.
In Math: retVect = srcVec x M.
To transform a vector from one matrix/coordinate to another (say M1 to M2): retVec = Transform by M1 -> then transform by invert of M2:
Vector2 retVec = Vector2.Transform(vectorInSource, M1);
Matrix invertDestMatrix = Matrix.Invert(M2);
outVect= Vector2.Transform(retVec , invertDestMatrix);
I have two objects in a game, which for this purpose can be considered points on a 2d plane, but I use Vector3s because the game itself is 3d.
I have a game camera which I want to align perpendicularly (also on the plane) to the two objects, so that they are both in view of the camera. Due to the nature of the game, the objects could be in any imaginable configuration of positions, so the directional vector between them could have any direction.
Part1: How do I get the perpendicular angle from the two positional vectors?
I have:
Vector3 object1Position; // x and z are relevant
Vector3 object2Position;
I need:
float cameraEulerAngleY;
Part2: Now, because of the way the game's assets are modelled, I want to only allow the camera to view within a 180 degree 'cone'. So if the camera passes a certain point, it should use the exact opposite position the above math might produce.
An image is attached of what I need, the circles are the objects, the box is the camera.
I hope this post is clear and you guys won't burn me alive for being total rubbish at vector math :P
greetings,
Draknir
You'll need to specify a distance from the object line, and an up vector:
Vector3 center = 0.5 * (object2position + object2position)
Vector3 vec12 = object2position - object1position
Vector3 normal = Cross(vec12, up)
normal.Normalize()
Vector3 offset = distance * normal
Vector3 cameraA = center + offset
Vector3 cameraB = center - offset
< choose which camera position you want >
Instead of using Euler angles, you should probably use something like LookAt() to orient your camera.
Assuming Y is always 0 (you mentioned "X and Z" are your relevant components), then you can use some 2-d math for this:
1.Find any perpendicular vector (there are two). You can get this by calculating the difference between the two vectors, swapping the components, and negating one of them.
Vector3 difference = (object1Position - object2Position);
Vector3 perpendicular = new Vector3(difference.z, 0, -difference.x);
2.Using your separating plane's normal, flip the direction of your new vector if it's pointing opposite of intended.
Vector3 separatingPlaneNormal = ...; // down?
if(Vector3.Dot(separatingPlaneNormal, perpendicular ) < 0)
{
perpendicular = -perpendicular ;
}
// done.
Well, for the first bit, if you have points (x1, y1) and (x2, y2) describing the positions of your objects, just think of it in terms of triangles. The angle you're looking for ought to be described by
arctan((y2-y1)/(x2-x1))+90
I don't completely understand what you want to do with the second part, though.
I have two squares in 3D space. I want to find the x,y,z angles between them. I started by finding the normal vectors for both of the squares and I am trying to figure out how to get the angle between them.
I am using XNA (C#) Vector3 objects.
I have calculated the normal vectors as follows:
Vector3 normal1 = (Vector3.Cross(sq1.corners[0] - sq1.corners[1], sq1.corners[0] - sq1.corners[2]));
Vector3 normal2 = (Vector3.Cross(sq2.corners[0] - sq2.corners[1], sq2.corners[0] - sq2.corners[2]));
I want to find the euler rotation that will get normal1 facing the same way as normal2
First, you can calculate the axis and amount of rotation (assuming an arbitrary axis):
Vector3 axis = Vector3.Cross(normal1, normal2);
axis.Normalize();
double angle = Math.Acos(Vector3.Dot(normal1, normal2) / normal1.Length() / normal2.Length());
If the normals are normalized, then the calculation of the angle reduces to
double angle = Math.Acos(Vector3.Dot(normal1, normal2));
Then you can transform this to euler angles with the function from here