I rotate a vector using the following code:
var newVectorX = Math.Cos(step) * normalizedVector.X
- Math.Sin(step) * normalizedVector.Y;
var newVectorY = - Math.Sin(step) * (normalizedVector.X )
+ Math.Cos(step) * normalizedVector.Y;
I tried to create a 2x2 matrix so I just can multiply my normalized vector with the matrix. The result would be the new rotated vector instead the coordinates.
Unfortunately System.Windows.Media.Matrix doesn't support 2x2 matrices. I couldn't find any implementation of this rotation matrix so far. How would you implement this?
Actually, System.Windows.Media.Matrix is exactly what you need. While it may seem that you want a 2x2 matrix, using a 3x3 matrix allows for translations too. Just use a System.Windows.Media.Matrix and ignore the part you don't need.
Matrix rotate = Matrix.Identity;
rotate.Rotate(step * 180 / Math.PI); // Rotate() takes degrees
Vector newVector = rotate.Transform(normalizedVector);
Related
I have this formula to rotate around a sphere
double naX = o.Node.Angle.X;
double naY = o.Node.Angle.Y;
double x = o.DrawingPosition.X - 4.0 * Math.Cos(naX) * Math.Sin(naY);
double y = o.DrawingPosition.Y - 4.0 * Math.Sin(naX) * Math.Sin(naY);
double z = o.DrawingPosition.Z - 4.0 * Math.Cos(naY);
Where 4.0 is the radius to follow and o.DrawingPosition is the center
I want it to rotate along the transform x axis (I have a quaternion and a unit vector normalized for calculated for the Z -1 normal) but if I add offsets the angles won't match
naX += _rotationTicks;
naY += _rotationTicks;
For example, it will follow a infinite shaped trajectory, how can I calculate the correct rotation so it behaves like a perfect circle?
Edit:
I found this answer on Rotating body from spherical coordinates
But the main core difference is that both the XY rotation angles and the origins are arbitrary values, there is a forward vector calculated with a quaternion to determine facing like this:
var quat = System.Numerics.Quaternion.CreateFromYawPitchRoll((float)o.Node.Angle.X, (float)o.Node.Angle.Y, 0);
var dirVec = new Vector3(0, -1, 0).ToNumerics();
var downwards = quat.Multiply(dirVec); // it can be backwards, left, right, etc, changing the unit vector from dirVec
Thanks in advance.
I am getting 2d coordinates from Vector3. I have to correct positions to get right results. Indeed it seems I get correct positions like this but I do not know how to correct position when rotated.
Here my worldViewMatrix that I do operations but those operations not passed to my VertexData then I try to correct positions.
WorldViewMatrix = Matrix.Scaling(Scale) * Matrix.RotationX(Rotation.X) * Matrix.RotationY(Rotation.Y) * Matrix.RotationZ(Rotation.Z) * Matrix.Translation(Position.X, Position.Y, Position.Z) * viewProj;
I am trying to correct it like:
public Vector2 Convert_3Dto2D(Vector3 position, Vector3 translation, Vector3 scale, Vector3 rotation, Matrix viewProj, RenderForm_EX form)
{position += translation;
position += translation;
position = Vector3.Multiply(position, scale);
//ROTATION ?
var project = Vector3.Project(position, 0, 0, form.ClientSize.Width, form.ClientSize.Height, 0, 1, viewProj);
Console.WriteLine(project.X+" "+ project.Y);
return new Vector2(project.X, project.Y);
}
What can I do to correct rotated position ?
If you can, post a little more information about "correct positions". I will take a stab at this and assume you want to move your vertex into world space, then work out what pixel it occupies.
Usually you order multiplying your order by
Translate * Rotate * Scale;
if you want Viewprojection to apply correctly, I believe it should be at the start. V * (t * r * s).
The following link on gamedev stackexchange goes into this. matrix order
Also, your project takes in a Vector3 that has been already multiplied into wvp matrix, I dont see you have multiplied it in your convert_3dto2d function.
Basically, execute a TRS matrix multiply on your original vert, then multiply your WVP matrix then execute your project. You will then get your screen space pixel.
I stumbled on a working concept for a fast rotation & orientation system today, based on a two-term quaternion that represents either a rotation about the X axis (1,0,0) in the form w + ix, a rotation about the Y axis (0,1,0) in the form w + jy, or a rotation about the Z axis (0,0,1) in the form w + kz.
They're similar to complex numbers, but a) are half-angled and double-sided like all quaternions (they're simply quaternions with two of three imaginary terms zeroed out), and b) represent rotations about one of three 3D axes specifically.
My problem and question is...I can't find any representation of such a system online and have no idea what to search for. What are these complex numbers called? Who else has done something like this before? Where can I find more information on the path I'm headed down? It seems too good to be true and I want to find the other shoe before it drops on me.
Practical example I worked out (an orientation quaternion from Tait-Bryan angles):
ZQuat Y, YQuat P, XQuat R; // yaw, pitch, roll
float w = Y.W * P.W;
float x = -Y.Z * P.Y;
float y = Y.W * P.Y;
float z = Y.Z * P.W;
Quaternion O; // orientation
O.W = x * R.W + w * R.X;
O.X = y * R.W + z * R.X;
O.Y = z * R.W - y * R.X;
O.Z = w * R.W - x * R.X;
Quaternions in 2D would degenerate to just being a single component being no diferrent than an rotation angle. That's propably why you do not find anything. With quaternions you do f.e. not have the problem of gimbal lock, appearing when two rotation axes align because of rotation order. In normal 2D space you do not have more than a single rotation axis, so it has neither order (how do you sort a single element) and there are no axes to align. The lack of rotation axes in 2D is because you get a rotation axis when being perpendicular to two other axes.
This gives 3 axes for 3D:
X&Y=>Z
X&Z=>Y
Y&Z=>X
But only one for 2D:
X&Y=>Z
This is my Transform. I got it from an example of a simple 2D camera.
public Matrix Transform(GraphicsDevice graphicsDevice)
{
float ViewportWidth = graphicsDevice.Viewport.Width;
float ViewportHeight = graphicsDevice.Viewport.Height;
matrixTransform =
Matrix.CreateTranslation(new Vector3(-cameraPosition.X, -cameraPosition.Y, 0)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
Matrix.CreateTranslation(
new Vector3(ViewportWidth * 0.5f, ViewportHeight * 0.5f, 0));
return matrixTransform;
}
If I understand it correctly, it allows for a roll(rotation), sprite scale change on zoom, and translation between world and camera for simple up, down, left, right controls. However, it does not alter the Z depth.
But what I need is for the game world to zoom, not just the sprites drawn. And I assume in order to do this I need to change the Z distance between the camera and the world matrix.
I am VERY NEW to programming and have only a simple understanding of matrix in general. I have even less understanding as to how XNA uses them in the draw method. And so far I feel like pulling my hair out from a fruitless search for answers... I just need the world coordinates to scale on zoom, so that before my mouse at a pre-zoom X.60 Y.60 will be at X.600 Y.600 post-zoom (ie: zoom level 0.1). But my mouse has not moved, only the world got bigger in view (or shrank).
I know this question is old, but this is in case anyone comes across this problem and can't find a solution. #RogueDeus was trying to convert scaled input coordinates when he was zooming in or out with his camera. In order to scale the mouse, all you need is to get the inverse matrix of the scale.
So if his scale matrix was created as this:
Matrix.CreateScale(zoom, zoom, 0);
The mouse coordinates should be inverse scaled and shifted by the necessary translation:
float ViewportWidth = graphicsDevice.Viewport.Width;
float ViewportHeight = graphicsDevice.Viewport.Height;
Matrix scale = Matrix.CreateScale(zoom, zoom, 0);
Matrix inputScalar = Matrix.Invert(scale);
...
public MouseState transformMouse(MouseState mouse)
{
/// Shifts the position to 0-relative
Vector2 newPosition = new Vector2(mouse.X - ViewportWidth,
mouse.Y - ViewportHeight);
/// Scales the input to a proper size
newPosition = Vector2.Transform(newPosition, InputScalar);
return new MouseState((int)newPosition.X, (int)newPosition.Y,
mouse.ScrollWheelValue, mouse.LeftButton,
mouse.MiddleButton, mouse.RightButton,
mouse.XButton1, mouse.XButton2);
}
You are using 2D coordinates, therefore the Z coordinate is of absolutely no importance. In fact, the scale matrix you are using ( Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) ) multiply the Z coordinate by 0, effectively setting it to 0.
As this scale matrix is in the view matrix, it will scale the entire world. I am not sure to really understand your problem. Could you try to explain it a litle more, please?
I seem to have figured out how to get the coordinates to scale...
I was assuming that the current mouse status would reflect the world matrix its clicked on, but apparently it never actually does this. It is always linked to the view matrix. (The screen itself) and that value needs to scale along with the world matrix (in the transform).
So as the transform is effected by Zoom in the Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) so too does the mouseState X & Y coordinates need to be scaled by it to virtually mirror the world matrix.
//Offsets any cam location by a zoom scaled window bounds
Vector2 CamCenterOffset
{
get { return new Vector2((game.Window.ClientBounds.Height / Zoom)
* 0.5f, (game.Window.ClientBounds.Width / Zoom) * 0.5f);
}
}
//Scales the mouse.X and mouse.Y by the same Zoom as everything.
Vector2 MouseCursorInWorld
{
get
{
currMouseState = Mouse.GetState();
return cameraPosition + new Vector2(currMouseState.X / Zoom,
currMouseState.Y / Zoom);
}
}
I'm making an XNA game and have run into a small problem figuring out a bit of vector math.
I have a class representing a 2D object with X and Y integer coordinates and a Rotation float. What I need is to have a Vector2 property for Position that gets and sets X and Y as a Vector2 that has been transformed using the Rotation float. This way I can just do something like;
Position += new Vector2((thumbstick.X * scrollSpeed), -(thumbstick.Y * scrollSpeed));
and the object will move in it's own upward direction, rather than the View's upward direction.
So far this is what I have...I think the set is right, but for += changes it needs a get as well and the answer just isn't coming to me right now... >.>
public Vector2 Position
{
get
{
// What goes here? :S
}
set
{
X = value.X * (int)Math.Cos(this.Rotation);
Y = value.Y * (int)Math.Cos(this.Rotation);
}
}
No, both are incorrect.
A 2D vector transforms like this:
x' = x*cos(angle) - y*sin(angle)
y' = x*sin(angle) + y*cos(angle)
where the angle is measured in radians, zero angle is along the positive x-axis, and increases in the counterclockwise direction as you rotate around the z-axis out of plane. The center of rotation is at the end of the vector being transformed, so imagine the vector with origin at (0,0), end at (x,y) rotation through an angle until it becomes a vector with origin at (0,0) and end at (x', y').
You can also use the Matrix helper methods to create a Z rotation matrix then multiply your vector by this to rotate it. Something like this:
Vector v1;
Matrix rot = Matrix.CreateRotationZ(angle);
Vector v2 = v1 * rot;
I think this is a bad idea. Keep all of your objects' X and Y co-ordinates in the same planes instead of each having their own axes. By all means have a Position and Heading properties and consider having a Move method which takes your input vector and does the maths to update position and heading.