I am trying hard to figure out how to make pitch yaw and roll independent between them.
As soon as I rotate something in the z axis (pitch) the second rotation (yaxis yaw) depends on the results of the first and the third rotation (x axis, roll) depends on the other two. So instead of having independent pitch,yaw,roll I get a mixture of the three of them, ugly.
I wish it was possible to store the object angles in an array [pitch,yaw,roll] and then decode those angles during the transformation so that yawing put the object in a given position and then it took the angle corresponding to the pitch, but not a compound of both...
I have seen references to an 'arbitrary axis rotation matrix'. Would it be useful to get the desired results???
1) apply yaw (gl.glRotatef(beta, 0.0f, 1.0f, 0.0f);)
2) get the resulting axis of manually rotating the vector (1.0f,0.0f,0.0f) arround beta
3) apply pitch using the axis got in 2
{and for roll... if 1,2,3 are correct}
4) rotate the axis got in 2 arround its x for a roll
5) apply roll using the axis got in 4
Would it work? Any better solution? I would like keeping my object local orientations in the [pitch,yaw,roll] format.
I have been struggling with it for days, I would like to avoid using quaternions if possible. The 3D objects are stored relatively to 0,0,0 and looking along {1,0,0} and transformed to their destination and angles each frame, so the gimbal lock problem should probably be avoided easily.
In other words, my camera is working fine, World coordinates are being correctly made, but I do not know how or where object-local-transformations based on yaw,pith,roll should be applied.
The results should be read from the array [y,p,r] and combinations of them should not overlap.
Actually my transformations are:
gl.glLoadIdentity();
float[] scalation = transform.getScalation();
gl.glScalef(scalation[0], scalation[1], scalation[2]);
float[] translation = transform.getTranslation();
gl.glTranslatef(translation[0], translation[1], translation[2]);
float[] rotation = transform.getRotation();
gl.glRotatef(rotation[0], 1.0f, 0.0f, 0.0f);
gl.glRotatef(rotation[1], 0.0f, 1.0f, 0.0f);
gl.glRotatef(rotation[2], 0.0f, 0.0f, 1.0f);
The orientation always depends on angles order. You can't make them indipendent. You rotate vectors multipling them by matrices, and matrix multiplication is not commutative. You can choose one order and be consistent with it.
For these problems, a common choice is the ZYX orientation method (first roll, then pitch and at the end yaw).
My personal reference when I work with angles is this document, that helps me a lot.
if you use yaw/pitch/roll, your final orientation will always depend on the amounts and order in which you apply them. you can choose other schemes if you want readability or simplicity. i like choosing a forward vector (F), and calculating a right and up vector based on a canonical 'world up' vector, then just filling in the matrix columns. You could add an extra 'axis spin' angle term, if you like. It's a bit like a quaternion, but more human-readable. I use this representation for controlling a basic WASD-style camera.
Accumulating (yaw, pitch, roll) rotations requires to keep a transformation matrix, which is the product of the separate transformations, in the order in which they occur. The resulting matrix is a rotation around some axis and some angle.
Related
I am making program which reads texture that should be applied to the mesh and generates some shapes which should be displayed on their triangles. I am converting points in a way that originally shape appears to be lying on XZ (in openGL way of marking axes, so Y is vertical, Z goes towards camera, X to the right). Now I have no idea how to properly measure angle between actual normal of traingle and vertical normal (I mean (0, 1, 0)) of image. I know, that it's probably basic, but my mind refuses to cooperate on 3D graphics tasks recently.
Currently I use
angles.x = glm::orientedAngle(glm::vec2(normalOfTriangle.z, normalOfTriangle.y), glm::vec2(1.0f, 0.0f));
angles.y = glm::orientedAngle(glm::vec2(normalOfTriangle.x, normalOfTriangle.z), glm::vec2(1.0f, 0.0f));
angles.z = glm::orientedAngle(glm::vec2(normalOfTriangle.x, normalOfTriangle.y), glm::vec2(1.0f, 0.0f));
angles = angles + glm::vec3(-glm::half_pi<float>(), 0.0f, glm::half_pi<float>());
Which given my way of thinking should give proper results, but the faces of cube that should have normal parallel to Z axis appear to be unrotated in Z.
My logic bases on that I measure angle from each axis, and then rotate each axis by such angle for it to be vertical. But as I said, my mind glitches, and I cannot find proper way to do it. Can somebody please help?
I have a question regarding a tutorial that I have been following on the rotation of the camera's view direction in OpenGL.
Whilst I appreciate that prospective respondents are not the authors of the tutorial, I think that this is likely to be a situation which most intermediate-experienced graphics programmers have encountered before so I will seek the advice of members on this topic.
Here is a link to the video to which I refer: https://www.youtube.com/watch?v=7oNLw9Bct1k.
The goal of the tutorial is to create a basic first person camera which the user controls via movement of the mouse.
Here is the function that handles cursor movement (with some variables/members renamed to conform with my personal conventions):
glm::vec2 Movement { OldCursorPosition - NewCursorPosition };
// camera rotates on y-axis when mouse moved left/right (orientation is { 0.0F, 1.0F, 0.0F }):
MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.x) / 2, MVP.view.orientation)
* glm::vec4(MVP.view.direction, 0.0F);
glm::vec3 RotateAround { glm::cross(MVP.view.direction, MVP.view.orientation) };
/* why is camera rotating around cross product of view direction and view orientation
rather than just rotating around x-axis when mouse is moved up/down..? : */
MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.y) / 2, RotateAround)
* glm::vec4(MVP.view.direction, 0.0F);
OldCursorPosition = NewCursorPosition;
What I struggle to understand is why obtaining the cross product is even required. What I would naturally expect is for the camera to rotate around the y-axis when the mouse is moved from left to right, and for the camera to rotate around the x-axis when the mouse is moved up and down. I just can't get my head around why the cross product is even relevant.
From my understanding, the cross product will return a vector which is perpendicular to two other vectors; in this case that is the cross product of the view direction and view orientation, but why would one want a cross product of these two vectors? Shouldn't the camera just rotate on the x-axis for up/down movement and then on the y-axis for left/right movement...? What am I missing/overlooking here?
Finally, when I run the program, I can't visually detect any rotation on the z-axis despite the fact that the rotation scalar 'RotateAround' has a z-value greater than or less than 0 on every call to the the function subsequent to the first (which suggests that the camera should rotate at least partially on the z-axis).
Perhaps this is just due to my lack of intuition, but if I change the line:
MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.y) / 2, RotateAround)
* glm::vec4(MVP.view.direction, 0.0F);
To:
MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.y) / 2, glm::vec3(1.0F, 0.0F, 0.0F))
* glm::vec4(MVP.view.direction, 0.0F);
So that the rotation only happens on the x-axis rather than partially on the x-axis and partially on the z-axis, and then run the program, I can't really notice much of a difference to the workings of the camera. It feels like maybe there is a difference but I can't articulate what this is.
The problem here is frame of reference.
rather than just rotating around x-axis when mouse is moved up/down..?
What you consider x axis? If that's an axis of global frame of reference or paralleled one, then yes. If that's x axis for frame of reference, partially constricted by camera's position, then, in general answer is no. Depends on order of rotations are done and if MVP gets saved between movements.
Provided that in code her MVP gets modified by rotation, this means it gets changed. If Camera would make 180 degrees around x axis, the direction of x axis would change to opposite one.
If camera would rotate around y axis (I assume ISO directions for ground vehicle), direction would change as well. If camera would rotate around global y by 90 degrees, then around global x by 45 degrees, in result you'll see that view had been tilted by 45 degrees sideways.
Order of rotation around constrained frame of reference for ground-bound vehicles (and possibly, for character of classic 3d shooter) is : around y, around x, around z. For aerial vehicles with airplane-like controls it is around z, around x, around y. In orbital space z and x are inverted, if I remember right (z points down).
You have to do the cross product because after multiple mouse moves the camera is now differently oriented. The original x-axis you wanted to rotate around is NOT the same x-axis you want to rotate around now. You must calculate the vector that is currently pointed straight out the side of the camera and rotate around that. This is considered the "right" vector. This is the cross product of the view and up vectors, where view is the "target" vector (down the camera's z axis, where you are looking) and up is straight up out of the camera up the camera's y-axis. These axes must be updated as the camera moves. Calculating the view and up vectors does not require a cross product as you should be applying rotations to these depending on your movements along the way. The view and up should update by rotations, but if you want to rotate around the x-axis (pitch) you must do a cross product.
So at the moment am working on a game for my coursework which is based around the idea of flying a rocket, I spent too much time thinking about the physics behind it that I completely ignored getting it to move properly.
For example when I were to draw a cone with the top pointing to the sky, and I rotate it on the X axis it rotates properly however if I translate it on the Y axis it moves on the global Y axis instead on it's local coordinate system which would have the Y axis pointing out of the cone's top.
My question is does openGL have a local coordinate system or would I have to somehow make my own transformation matrices, and if so how would I go about doing that.
The way I am doing the transformation and rotation is as follows:
glPushMatrix();
glTranslatef(llmX, llmY + acceleration, llmZ);
glRotatef(rotX, 1.0f, 0.0f, 0.0f);
glRotatef(rotY, 0.0f, 0.0f, 1.0f);
drawRocket();
glPopMatrix();
Here is a picture better explaining what I mean hopefully offers a better explanation.
EDIT: I find it really weird that the rotations seem to work one after the other as in if I rotate it on the X axis once and then proceed to rotate it on the Z axis it rotates from the already rotated X axis instead of the world X axis.
Hoping somebody could help me with understanding this, really need to get it working for my project.
Thank you.
If you are using a translation matrix for moving up (i.e. moving in positive Y direction), no matter where you are in on the matrix stack or in the transformation process, you are going to move the vertices in the positive Y direction.
If you instead want it move in the rotated direction, I suggest translating along the Y axis first, and then rotate to your desired angle. Essentially, push the matrices in the opposite fashion.
I would like to get angle between object and another object. This must be vertical and horizontal angle.
I Have the coordinates of:
posX, posY, posZ
objectX, objectY, objectZ
I tried:
glRotatef( atan2(objectY - posY,objectX - posX)* 180.0f / 3.14f, 0.0f, 0.0f, 1.0f );
glRotatef( atan2(objectZ - posZ,objectX - posX)* 180.0f / 3.14f, 0.0f, 1.0f, 0.0f );
but sometime don't working correctly
Strictly speaking, if you just have two "objects," there's no angle between them. You need a frame of reference.
For example, two points in 2-D don't have an angle between them. If you treat one as the origin, however, you're probably going to want to measure the angle between the second point and the x-axis.
Similarly, in 3-D, you need to have a frame of reference. You won't actually get 1 angle, but 2. One angle goes around the z-axis by 2PI, and the second goes up and down (angle from the xy-plane) PI. Check out Spherical Coordinates to get a good explanation.
With this in mind, you want to:
Translate your first object to the origin.
Translate your second object by the same amount.
Convert the second object's position from cartesian coordinates to spherical coordinates. That link will help.
But wait! What if you care about the orientation of that first object? EG, it's a character looking some direction. You probably want that angle to be dependent on which way he's looking. If he's looking right at it, you probably want 0 radians (0 degrees), and if it's behind him, you probably want PI radians (180 degrees).
The process is the same as above, but you first must transform that second object from world space into "character" space - that coordinate system relevant to that first object. It's mathematically the same as transforming something into camera space. From there just convert the new position of your object from cartesian to spherical coordinates to get your angles.
Suggestions
Don't hardcore π into your code. Use a #define, preferably from a standard or very widely used library.
Don't use the Fixed Function Pipeline. It has been deprecated for I think ~8 years now. It is slow and not customizable.
If you're having a tough time with rotation, it's probably because you're letting OpenGL do it for you. Manage your own rotation matrix. Then you know exactly what you're doing.
You shouldn't need glRotatef to find the angle anyway. OpenGL is just for drawing. Given two objects, you should be able to figure out the angle between them without making any calls to OpenGL. In fact, you shouldn't call OpenGL.
I am trying to make a very simple object rotate around a fixed point in 3dspace.
Basically my object is created from a single D3DXVECTOR3, which indicates the current position of the object, relative to a single constant point. Lets just say 0,0,0.
I already calculate my angle based on the current in game time of the day.
But how can i apply that angle to the position, so it will rotate?
:(?
Sorry im pretty new to Directx.
So are you trying to plot the sun or the moon?
If so then one assumes your celestial object is something like a sphere that has (0,0,0) as its center point.
Probably the easiest way to rotate it into position is to do something like the following
D3DXMATRIX matRot;
D3DXMATRIX matTrans;
D3DXMatrixRotationX( &matRot, angle );
D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, orbitRadius );
D3DXMATRIX matFinal = matTrans * matRot;
Then Set that matrix as your world matrix.
What it does is it creates a rotation matrix to rotate the object by "angle" around the XAxis (ie in the Y-Z plane); It then creates a matrix that pushes it out to the appropriate place at the 0 angle (orbitRadius may be better off as the 3rd parameter in the translation call, depending on where your zero point is). The final line multiplies these 2 matrices together. Matrix multiplications are non commutative (ie M1 * M2 != M2 * M1). What the above does is move the object orbitRadius units along the Z-axis and then it rotates that around the point (0, 0, 0). You can think of rotating an object that is held in your hand. If orbitRadius is the distance from your elbow to your hand then any rotation around your elbow (at 0,0,0) is going to form an arc through the air.
I hope that helps, but I would really recommend doing some serious reading up on Linear Algebra. The more you know the easier questions like this will be to solve yourself :)