I had an old project where i was calculating my view matrix like this
float4x4 world = m_Frame.GetWorldMat();
float4x4 orthoN = world;
orthoN.XAxis.x = world.XAxis.x;
orthoN.XAxis.y = world.YAxis.x;
orthoN.XAxis.z = world.ZAxis.x;
orthoN.YAxis.x = world.XAxis.y;
orthoN.YAxis.y = world.YAxis.y;
orthoN.YAxis.z = world.ZAxis.y;
orthoN.ZAxis.x = world.XAxis.z;
orthoN.ZAxis.y = world.YAxis.z;
orthoN.ZAxis.z = world.ZAxis.z;
orthoN.WAxis.x = -float3::dotProduct( world.XAxis, world.WAxis );
orthoN.WAxis.y = -float3::dotProduct( world.YAxis, world.WAxis );
orthoN.WAxis.z = -float3::dotProduct( world.ZAxis, world.WAxis );
m_mView = orthoN;
but now im trying to do it with openGL implementing the GLM library objects
i figured doing it this way would work
m_mView = glm::inverse( m_Frame.GetWorldMat() );
this didn't seem to work. am i doing something incorrect? if everything looks fine I will take the assumption i am doing something else wrong and its not my view.
example number results both ways:
my results were weird with the glm::inverse i got
1.0, -0.12, -0.85, 0.0,
0.0, 0.87, -0.85, 0.0,
0.0, -0.12, 0.14, 0.0,
0.0, -0.12, -0.85, 1.0
with the first method I got whole numbers
1.0, 0.0, 0.0, 0.0,
5.0, 6.0, 4.0, 0.0,
35.0, 36.0, 36.0, 0.0,
-1250, -1255, -1285, 1.0
Assuming that m_Frame.GetWorldMat() gives you view to world transform, you should invert the matrix to get the world to view transform. Both snippets do the same.
In the older code, you're doing this by transposing the upper 3x3 matrix, which shows that the original matrix consisted only rotation, since rotation is orthogonal, its inverse is its transpose. The origin translation is also inverted rightly.
In the second snippet you do the same using GLM only that it'll be slightly less performant since it doesn't know M is orthogonal (pure rotation); so instead of transposing it'll do a proper inverse operation using Cramer 's rule. If you want, you can avoid this by using the transpose function that GLM provides. Make sure you don't transpose the whole 4x4 matrix but only the upper 3x3 matrix. Then handle the origin translation separately as you did in the previous code.
However, as for the end result, both would give you the same output (approximately). You can verify this by printing them or inspecting the values in the debugger.
Related
I'm trying to render a series of 2D shapes (Rectangle, Circle) etc in modern opengl, hopefully without the use of any transformation matrices. I would like for me to be able to specify the coordinates for say a rectangle of 2 triangles like so:
float V[] = { 20.0, 20.0, 0.0,
40.0, 20.0, 0.0,
40.0, 40.0, 0.0,
40.0, 40.0, 0.0,
20.0, 40.0, 0.0,
20.0, 20.0, 0.0 }
You can see that the vertex coordinates are specified in viewport? space (I believe thats what its called). Now, when this get rendered by opengl, it doesnt work because clip space goes from -1.0 to 1.0 with the origin in the center.
What would be the correct way for me to handle this? I initially thought adjusting glClipControl to upper left and 0 to 1 would work, but it didnt. With clip control set to upper left and 0 to 1, the origin was still at the center, but it did allow for the Y-Axis to increase as it moved downward (which is a start).
Ideally, I would love to get opengl to have 0.0,0.0 to be the top left and 1.0, 1.0 to be the bottom right, then I just normalise each vertex position, but I have no idea how to get opengl to use that type of coordinate system.
One can easily do these transformation without matrices in the vertex shader:
// From pixels to 0-1
vPos.xy /= vResolution.xy;
// Flip Y so that 0 is top
vPos.y = (1.-vPos.y);
// Map to NDC -1,+1
vPos.xy = vPos.xy*2.-1.;
I dont understand how this GluLookAt works in OpenGl.
I would like to know how to transform this two lines :
gluLookAt(5.0, 15.0, 2.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0);
gluLookAt(5.0, 0.0, 5.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0);
using glRotatef and glTranslatef.
After some searches, it seems to exist a way for making that thing :
glRotatef();
glRotatef();
glTranslatef(5.0,15.0,2.0);
glRotatef();
glRotatef();
glTranslatef(5.0,0.0,5.0);
So just by using two rotations and one translation.
But I dont understand how can i find the angles and the axes of these rotations.
I tried to explain how the functions work below. Hope it makes you understand the concept. For rotation and translation you can check this link to see how it is handled.
struct Triple
{
float x,y,z;
}
//CameraPosition
Triple Cp(a,b,c); //initialise your camera position
//LookatPosition
Triple Lp(e,f,g); //initialise your lookat position
//Up vector
Triple Up(k,l,m); //initialise your up vector
UpdateCamera()
{
//Update Cp, Lp here
//if you move your camera use translatef to update camera position
//if you want to change looking direction use correct rotation and translation to update your lookat position
//if you need to change up vector simply change it to
Up = Triple(knew,lnew,mnew);
}
display()
{
gluLookAt(Cp.x,Cp.y,Cp.z,Lp.x,Lp.y,Lp.z,Up.x,Up.y,Up.z);
//Your object drawings Here
}
I'd like to sidestep the glRotate and glTranslate and use glLoadMatrix instead (glLoadMatrix replaces the current matrix on the stack use glMultMatrix if you want to multiply): you would then use an array of floats containing the matrix in column major order:
xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, camP) -dot(yaxis, camP) -dot(zaxis, camP) 1
where
zaxis = normal(At - camP)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)
and camP the position of the camera, At the point the camera is looking at and Up the up-vector.
I'm programming a simple application in OpenGL. I have a model that I want to rotate around its center (local coordinate), then translate it along with its local coordinate, too. I've done two scenarios,
rotate then translate, and vice versa. In the first scenario, I got the rotation correct but the model then translate based on the world coordinate not the model (local) coordinate. When I translate first, I got the translation right but the rotation is no longer around the model center.
here's the code,
glPushMatrix();
// ignore this
/*glRotatef(_zRoll, 0.0, 0.0, 1.0);
glRotatef(_yTilt, 1.0, 0.0, 0.0);
glRotatef(_xPan, 0.0, 1.0, 0.0);*/
glScalef(scale, scale, scale);
glTranslatef(0.0, 0.0, -2.0);
glTranslatef(_xTranslate, _yTranslate, _zTranslate); // The required translation
// The required rotation
glRotatef(_yangle, 0.0, 1.0, 0.0);
glRotatef(_zangle, 0.0, 0.0, 1.0);
glRotatef(_xangle, 1.0, 0.0, 0.0);
glTranslatef(coord.x, coord.y, coord.z); // translate to the model center
glCallList(aHelix);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glPopMatrix();
glutSwapBuffers();
I think I understand now what you're looking for. I will attempt to restate what you want, so please correct me if I am mistaken.
Let's take a simple model with the following vertex coordinates (columns are vertices):
[3 2 3 4]
[5 2 3 2]
[0 0 0 0]
[1 1 1 1]
So the first point is at x=3, y=5, z=0. Drawing this model we get:
If we simply rotate the model (in this case by 43°) and then translate it in the Y direction (up), say 4 units, we get this:
The model has now moved 4 units in the Y direction, but in the world coordinate frame. As I understand it, the result above is what you DO NOT want.
If instead we translate the model in the direction it is pointing after rotation, we get this:
This, I believe, is what you DO want. Here's the code I used.
glTranslatef(3.0, 3.0, 0.0);
glTranslatef(-2.728, 2.924, 0.0);
glRotatef(43.0, 0.0, 0.0, 1.0);
glTranslatef(-3.0, -3.0, 0.0);
I first rotate the model by 43 degrees and then translate it according to the updated local Y direction. I got the hardcoded translation vector by taking the vector [0 4 0 0] and rotating it using the same 43° rotation matrix I used for the model. This isn't straightforward to do programmatically (at least in the fixed pipeline) and it gets worse with subsequent rotations.
It turns out, though, that you get the exact same results (which you can verify manually) by performing the translation by [0 4 0 0] first, followed by the rotation:
glTranslatef(3.0, 3.0, 0.0);
glRotatef(43.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 4.0, 0.0);
glTranslatef(-3.0, -3.0, 0.0);
Here's the result of the second set of code for comparison:
The problem is that if you do any subsequent rotations/translations, your coordinate systems still get all messed up. To get around this, you need to make sure you're using an accumulator for your rotations and translations and applying them all at once to the original model rather than making small incremental changes. So, for each press of the up-arrow key, add some incremental value to your _yTranslate variable, for each press of the "rotate" button, add or subtract some value from _zangle, and so on.
Suppose I have a point at (250,125,-20).
After the following transformation,
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(100.0, 50.0, 0.0);
glRotatef(-25.0, 0.0, 1.0, 0.0);
How can I get the value of current coordinates of that point?
Need I write a subroutine to multiply a matrix to a vector?
Are there any built-in solutions?
You can't get the coordinates for a specific vertex (point) after a transformation, however for this particular case you can get the ModelViewMatrix after the translate/rotate is applied.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(100.0, 50.0, 0.0);
glRotatef(-25.0, 0.0, 1.0, 0.0);
glGetFloatv(GL_MODELVIEW_MATRIX , *your_matrix*);
//print your matrix to check if that is the desired transformation coordinates
There is no magic tape in OpenGL, you will have to write your own framework e.g: for every objects in your world a class where you hold the vertices and what data you find relevant.
Greetings all,
As seen in the image,
I have an object named O (set of linestripes).Its object-coordinate system is (x',y',z').
I translate,rotate this object in my OpenGL scene using following code snippet:
glPushMatrix();
glTranslatef(Oz, Oy,Oz);
glRotatef(rotationX , 1.0, 0.0, 0.0);
glRotatef(rotationY, 0.0, 1.0, 0.0);
glRotatef(rotationZ, 0.0, 0.0, 1.0);
contour->render();
glPopMatrix()
;
I have a point called H ,which is translated to (hx,hy,hz) world coordinates using
glPushMatrix();
glTranslatef(hx,hy,hz);
glPopMatrix();
If I am correct, (Oz,Oy,Oz) and (hx,hy,hz) are world coordinates.
Now,what I want todo is calculate the position of H (hx,hy,hz) relative to O's object-coordinate system.(x',y',z');
As I understood,I can do this by calculating inverse transformations of object O and apply them to point H.
Any tips on this? Does OpenGL gives any functions for inverse-matrix calculation ? If I somehow found inverse-matrices what the order of multiplying them ?
Note : I want to implement "hammer" like tool where at point H ,I draw a sphere with radius R.User can use this sphere to chop the object O like a hammer.I have implemented this in 2D ,so I can use the same algorithm if I can calculate the hammer position
relative to (x',y',z')
Thanks in advance.
Inverting the matrix would be the general solution, but as far as I can see this isn't actually a "general" problem. Rather than undoing an arbitrary transformation, you are trying to do the reverse of a known sequence of transformations, each of which can be inverted very simply. If your object-to-world transformation is:
glTranslatef(Ox, Oy, Oz);
glRotatef(rotationX , 1.0, 0.0, 0.0);
glRotatef(rotationY, 0.0, 1.0, 0.0);
glRotatef(rotationZ, 0.0, 0.0, 1.0);
Then the world-to-object inverse is just:
glRotatef(-rotationZ, 0.0, 0.0, 1.0);
glRotatef(-rotationY, 0.0, 1.0, 0.0);
glRotatef(-rotationX , 1.0, 0.0, 0.0);
glTranslatef(-Ox, -Oy, -Oz);
Basically, just back out each applied transformation in the opposite order originally applied.
Yes, basically you're right that you can perform this operation by the translation matrix
M = O^-1 * H
any like you already guessed you need the inverse of O for this. OpenGL is not a math library though, it only deals with rendering stuff. So you'll have to implement the inversion yourself. Google for "Gauss Jordan" to find one possible algorithm. If you can be absolutely sure, that O consists only of rotation and translation, i.e. no shearing or scaling, then you can shortcut by transposing the upper left 3x3 submatrix and negating the uppermost 3 elements of the rightmost column (this exploits the nature of orthogonal matrices, like rotation matrices, that the transpose is also the inverse, the upper left 3x3 is the rotational part, the inverse of a translation is negating the elements of it's vector which is the rightmost upper 3 elements).