I have a 3D world that works well with a camera and game objects. When the camera 'renders' it positions the matrix in the location of the camera. To do this, I call the following code:
gl.glMultMatrixf(rotationArray,0);
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
Now when each object gets rendered, I call this for each object. (Note that I push and pop the matrices appropriately)
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
gl.glMultMatrixf(rotationArray,0);
Now my question comes into play of when I bring models into the world, I need certain Meshes to pivot not around the 0,0,0 point, but around a different point. I have an object called Mesh that has an ArrayList of submeshes. Each mesh (and submesh) have a pivot point location. (an x,y and z float).
Where do I translate the matricies so I pivot around the designated point? I've tried all sorts of combinations and nothing works!
Example:
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
gl.glMultMatrixf(rotationArray,0);
gl.glTranslatef(pivotPoint.getX(),pivotPoint.getY(),pivotPoint.getZ());
and I've tried
gl.glTranslatef(pivotPoint.getX(),pivotPoint.getY(),pivotPoint.getZ());
gl.glMultMatrixf(rotationArray,0);
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
This comes down to rotation around an arbitrary point. Traditionally when you rotate an object, you usually rotate it around the object's center but in this case you have a separate pivot point.
The process of rotating an object around any arbitrary point is:
Translate by -(RotationPoint)
Rotate
Translate by +(RotationPoint)
Related
I want to rotate a object(Some thing like 3d cube ) without touching the surface , say I have a specific x,y,z axis UI and when I change this axis value From the UI , It in turn should turn the 3D object .
The rotation of your object, when being drawn, is set by some variables (a rotation matrix, or a quaternion or such).
Your UI will provide some values, either by widgets you retrieve the values from or by sending events. Using these values you adjust the drawing controlling variable and issue a full redraw of the scene.
OpenGL is not a scene graph. It doesn't maintain a scene, it just draws points, lines or triangles to a pixel based framebuffer. As soon as a primitive (point, line, triangle) has been drawn OpenGL has no recollection about it whatsoever. You want something altered => >ou redraw the whole scene.
The concept you're looking for is a "track ball". Here's some info:
Trackball
In an Android app I want to draw a running leg. To output the top part of the leg I do something like:
// legCX,legCY is the location on screen about which the leg rotates.
Matrix m = new Matrix();
m.postTranslate(-legCX,-legCY);
m.postRotate(legRot);
m.postTranslate(legCX,legCY);
I then set the matrix to the canvas and draw the leg.
How do I draw the second part of the leg below the knee? It rotates at a different rate than the leg above it and has a center point which moves with the leg above it. I tried the following, but it turns out that the end result is rotation around some single point which doesn't follow the leg above.
Matrix m = new Matrix();
m.postTranslate(-legCX,-legCY);
m.postRotate(legRot);
m.postTranslate(0,-legLength);
m.postRotate(footRot);
m.postTranslate(0,legLength);
m.postTranslate(legCX,legCY);
I suspect that it's probably necessary to do the two rotations in two different Matrix objects and then combine them somehow, but I can't figure out how exactly to do that.
EDIT:
This type of matrix seems to be called a "transformation matrix". Combining multiple operations is called composition of transformations. However, none of the pages on this topic mention how to do a series of translations and rotations.
Surely, if you can use a matrix to do rotation about one point, it must be possible to do multiple matrix operations somehow to allow rotation about one point and then an additional rotation around a different point.
I've tried looking at pages on skeletal animation, but I can't make head nor tail of what they're talking about.
If I understand you problem correctly, you have a relative rotation case. You can try to search for double pendulum, see fig.
Using rotation matrix the new coordinates of point p1 rotated around point p0 can be found like
The new coordinates of point p2 rotated around point p1 will be
Finally, the new coordinates of point p2 rotated around point p0 will be
Order of matrices multiplication matters as well the sign of the angles.
I'm afraid this is going to be language-agnostic - I'm actually doing something similar at the moment in Android, but I'm both learning android and matrix math! You seem to know how to use matrices in Android so I'm guessing this won't be a problem.
So - let's say we've got two meshes (where a mesh is the thing that you can draw independently to the screen): UpperLeg and LowerLeg.
For UpperLeg you're going to have the point where the mesh rotates (RotationPoint)(in the real world I guess this would be the hip) and you're going to have the point where the LowerLeg attaches to it (AttachmentPoint)(in the real world I guess this would be the knee).
For LowerLeg you're going to have the point where the mesh rotates (RotationPoint)(in the real world I guess this would be the knee).
UpperLeg.AttachmentPoint = LowerLeg.RotationPoint (that way your leg won't fall off).
Let's now imagine that you've got two amounts of rotation (one for UpperLeg and one for LowerLeg): UpperLeg.Rotation and LowerLeg.Rotation.
(One the subject of rotation - if you haven't heard of Quaternions, you should look - it amazes me that some guy from 1846 came up with these - they basically encapsulate the concept of rotation, can be turned into rotation matrices, can be combined (by multiplication) and don't suffer from Gimbal-lock).
First up you you rotate UpperLeg by:
Moving the UpperLeg mesh so that UpperLeg.RotationPoint is the origin
Rotating by UpperLeg.Rotation
Moving the UpperLeg mesh so that it is where it needs to be in the real world.
I see that you're doing this.
So for the LowerLeg it'd be:
Moving the LowerLeg mesh so that LowerLeg.RotationPoint is the origin
Rotating by (UpperLeg.Rotation combined with LowerLeg.Rotation)
Moving the LowerLeg mesh by the same amount that the UpperLeg mesh was moved by in step 3
Moving the LowerLeg mesh by the Vector which is (the Vector from UpperLeg.RotationPoint to UpperLeg.AttachmentPoint) rotated by UpperLeg.Rotation.
The above steps can be combined and optimized.
Essentially I'm saying:
Rotate LowerLeg as it needs to be rotated, then shove it where it needs to go - where it needs to go will be determined by where UpperLeg went, plus how you get to where LowerLeg is attached to UpperLeg.
This is my first post here so, if I've broken any cardinal rules, please let me know what they are.
We use Camera to do 3D transformations in canvas.We usually rotate camera and get it's Matrix then translate it.But Camera also has translate method.The results of using methods are different.
My question is : What is difference between Camera.translate and Matrix.preTranslate or Matrix.postTranslate?
The reason there are both, is because matrix multiplication must be done in a certain order to achieve the proper result (as you may already know).
The sequence of translations/rotations/scales are done in reverse order as you type them.
So if you do something like this:
Camera.rotate(15, 0, 0);
Camera.scale(.5f, .5f, .5f);
Camera.translate(70, 70, 70);
You're first translating 70,70,70 then scaling by 50% in all directions, then rotating 15 degrees about the X axis.
So Matrix has a pre and post translate (well, pre and post everything), because maybe you want to actually rotate it first by 15 degrees and then translate it, and then finally scale it.
So that answers the pre and post translates. Now the reason Camera has a straight rotate and translate is for people that know how this works already (like me!), so I never use Matrix or Camera for that matter, because I can simply do my rotations and translations directly on the Canvas. You can too as long as you know that translations, scales, and rotates are done in reverse order.
Also, if you know what I have told you, it gives you more power. You can do a sequence of 10 matrices without surrounding them in multiple Matrix objects for each one (for example you want to do a swing motion that swings outward AND rotates about the center to simulate centrifugal force). This would need to be done with multiple rotates and translations (surrounded by multiple Matrix objects being passed into one another), but if you know how each translate works, you can simply do a series of .translate(), .rotate(), and .scale().
This information is especially useful if you ever do 3D graphics, because that's when these matrices give people headaches.
I hope this helps!
The result would be visually the same if you i.e. do not touch the canvas but rotate the camera 90 degs or keep camera still but rotate the canvas it looks at by -90 degs.
in OpenGL ES 1, I have a Rubic cube that consists of 27 smaller cubes. i want a rotation which causes a particular small cube becoming exactly in front of the viewpoint. so i need two vectors. one is the vector that comes from the origin of the object to that particular cube. and another is the vector that comes from origin to the viewpoint. then the cross product of them gives me the axis of the rotation and the dot product gives me the angle.
but i cant convert the (0,0,1) -which is the vector that comes from the origin to the viewpoint in world coordinate- to object coordinates.
how can i do that? how can i convert "world coordinates to object coordinates"?
It's easier to rotate the camera around than it is rotating the object in front of a stationary camera.
You can do what you asked for by placing the camera at the origin (center) of the rubic cube, giving it the opposite direction from the small cube, and than translating z backwards.
I know it doesn't answer the question in the title, but I think it's a simpler solution. (As for your question, I keep world and object coordinates same, and set the object scale as needed when rendering).
I am having trouble rotating my 3D objects in Open GL. I start each draw frame by loading the identity (glLoadIdentity()) and then I push and pop on the stack according to what I need (for the camera, etc). I then want 3D objects to be able to roll, pitch and yaw and then have them displayed correctly.
Here is the catch... I want to be able to do incremental rotations as if I was flying an airplane. So every time the up button is pushed the object rotates around it's own x axis. But then if the object is pitched down and chooses to yaw, the rotation should then be around the object's up vector and not the Y axis.
I've tried doing the following:
glRotatef(pitchTotal, 1,0,0);
glRotatef(yawTotal, 0,1,0);
glRotate(rollTotal, 0,0,1);
and those don't seem to work. (Keeping in mind that the vectors are being computed correctly)I've also tried...
glRotatef(pitchTotal, 1,0,0);
glRotatef(yawTotal, 0,1,0);
glRotate(rollTotal, 0,0,1);
and I still get weird rotations.
Long story short... What is the proper way to rotate a 3D object in Open GL using the object's look, right and up vector?
You need to do the yaw rotation around (around Y) before you do the pitch one. Otherwise, the pitch will be off.
E.g. you have a 45 degrees downward pitch and a 180 degrees yaw. By doing the pitch first, and then rotate the yaw around the airplane's Y vector, the airplane would end up pointing up and backwards despite the pitch being downwards. By doing the yaw first, the plane points backwards, then the pitch around the plane's X vector will make it point downwards correctly.
The same logic applies for roll, which needs to be applied last.
So your code should be :
glRotatef(yawTotal, 0,1,0);
glRotatef(pitchTotal, 1,0,0);
glRotatef(rollTotal, 0,0,1);
Cumulative rotations will suffer from gimbal lock. Look at it this way: suppose you are in an aeroplane, flying level. You apply a yaw of 90 degrees anticlockwise. You then apply a roll of 90 degrees clockwise. You then apply a yaw of 90 degrees clockwise.
Your plane is now pointing straight downward — the total effect is a pitch of 90 degrees clockwise. But if you just tried to add up the different rotations then you'd end up with a roll of 90 degrees, and no pitch whatsoever because you at no point applied pitch to the plane.
Trying to store and update rotation as three separate angles doesn't work.
Common cited solutions are to use a quaternion or to store the object orientation directly as a matrix. The matrix solution is easier to build because you can prototype it with OpenGL's built-in matrix stacks. Most people also seem to find matrices easier to understand than quaternions.
So, assuming you want to go matrix, your prototype might do something like (please forgive my lack of decent Java knowledge; I'm going to write C essentially):
GLfloat myOrientation[16];
// to draw the object:
glMultMatrixf(myOrientation);
/* drawing here */
// to apply roll, assuming the modelview stack is active:
glPushMatrix(); // backup what's already on the stack
glLoadIdentity(); // start with the identity
glRotatef(angle, 0, 0, 1);
glMultMatrixf(myOrientation); // premultiply the current orientation by the roll
// update our record of orientation
glGetFloatv(GL_MODELVIEW_MATRIX, myOrientation);
glPopMatrix();
You possibly don't want to use the OpenGL stack in shipping code because it's not really built for this sort of use and so performance may be iffy. But you can prototype and profile rather than making an assumption. You also need to consider floating point precision problems — really you should be applying a step that ensures myOrientation is still orthonormal after it has been adjusted.
It's probably easiest to check Google for that, but briefly speaking you'll use the dot product to remove erroneous crosstalk from two of the axes to the third, then to remove from one of the first two axes from the second, then renormalise all three.
Thanks for the responses. The first response pointed me in the right direction, the second response helped a little too, but ultimately it boiled down to a combination of both. Initially, your 3D object should have a member variable which is a float array size 16. [0-15]. You then have to initialize it to the identity matrix. Then the member methods of your 3D object like "yawObject(float amount)" just know that you are yawing the object from "the objects point of view" and not the world, which would allow the incremental rotation. Inside the yawObject method (or pitch,roll ojbect) you need to call the Matrix.rotateM(myfloatarray,0,angle,0,1,0). That will store the new rotation matrix (as describe in the first response). You can then when you are about to draw your object, multiply the model matrix by the myfloatarray matrix using gl.glMultMatrix.
Good luck and let me know if you need more information than that.