openvr: move in view direction - c++

I am programming an application with openvr and opengl and I want the camera to move in the direction it is looking at. So when you put on the hmd and look in a certain direction the virtual camera should fly in that direction so you can move around.
So the position of the hmd is provided by openvr with a call to VRCompositor()->WaitGetPoses and this should be analogous to the inverse of the view matrix, so if I extract the third coulmn of the matrix I should get the view direction and then I can translate my model matrix along that direction to move the scene.
m_mat4HMDPose = VRCompositor()->WaitGetPoses;
m_mat4HMDPose = inverse(m_mat4HMDPose);
vec4 direction = m_mat4HMDPose * vec4(0.0, 0.0, -1.0, 0.0);
model = translate(model, vec3(direction.x, direction.y, direction.z));
This seems to be not completly wrong, but this does not work for all directions. Sometimes I look to the left but I am translated to the right, and vice versa. This also happens with up/down, and the translation will change when Im rotating the hmd around the z-axis.
I also tried to follow this tutorial https://www.youtube.com/watch?v=QREKO1sf8b8 for unity, and I got the movement working with unity, but I cannot convert the code back to run with my opengl application. I tried to implement the euler and quaternion conversion, but with no success.
I am feeling that I need to transform my direction vector with an additional matrix, so it will point in the right direction all the time, but I cannot figure out how o_o
Does anyone know what the mistake is, or knows a way how to implement this movement?

okay I found the mistake I need to multiply the direction with the inverse of the hmd pose, so vec4 direction = inverse(m_mat4HMDPose) * vec4(0.0, 0.0, 1.0, 0.0);

Related

Correct camera transformation for first person camera

I am making a camera in openGl and I am having troubles with first person camera. So I had a few versions of camera transformation and all of them had their own problems. So at first, I was doing transformations in this order: I would first translate the object in the positive direction when trying to move away from it and I would translate it in the negative direction when trying to move towards it. After this translation, I would perform rotations arround X and Y axis. Now, when I try to use this camera, I found out that when I have objects in my scene, lets say a few cubes, and when I rotate, everything is fine, but when after this rotation I try translation, all of the objects converge to me or better to say, towards the "player". So after I gave this some thought I realized that because I am doing translations first, in the next frame when I try to translate the player in the direction in which the camera is looking at that moment, what happens is, objects get translated first and then rotated so I get, as a result of this, movement of the objects towards or away from the player. Code for this is here (and dont mind camUp and camRight vectors, these are just y and x axis vectors and are not transformed at all):
m_ViewMatrix = inverse(glm::rotate(glm::mat4(1.0f), m_Rotation, camUp))* inverse(glm::rotate(glm::mat4(1.0f), m_TiltRotation, camRight)) * glm::translate(glm::mat4(1.0f), m_Position);
But option to rotate and then translate is not good because then I get editor sort of camera which is actually fine but that is not what I want.
So I thought about it some more and tried to make small transformations and then reset the parameters, acumulating all the transformations in this way:
m_ViewMatrix = inverse(glm::rotate(glm::mat4(1.0f), m_Rotation, camUp)) * glm::translate(glm::mat4(1.0f), m_Position)* inverse(glm::rotate(glm::mat4(1.0f), m_TiltRotation, camRight))*m_ViewMatrix;
m_Position = { 0.0f, 0.0f, 0.0f };
m_Rotation = 0.0f;
m_TiltRotation = 0.0f;
But now I have a problem with rotations arround z axis which I don't want. This problem was not there before. So now I have no idea what to do, I read some answers here but couldn't apply them I don't know why. So if anyone could help me in the context of the code I just copied here, that would be great.

Rotating 'camera' in OpenGL around object not object around camera

In my app I have a set of object lying around the scene. They are all grouped inside box. When user zoom out to see whole box and starts rotate it then the pivot point is in the middle of box,. When you zoom in to see specific object inside then rotating camera so that the object that you are looking at (or space in front of you) then they are still rotating around this previous pivot point.
What I would like to achieve is to have pivot point always in front of camera. In other words, when you zoom out and see box it rotates as it is doing now. When you zoom in to specific object/space then camera rotate around it.
I've created simple images to show what I mean - triangle is camera, red box is some object/space and orange circle is a path on which element is going on while rotating. The first one is what I have now, the second what I'd like to have.
I know that in OpenGL there isn't something like camera, so in fact it is whole world moving and not one point. So far I've created something like that:
glPushMatrix();
glTranslatef(translate[0], translate[1], translate[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
DrawObject();
glPopMatrix();
translate is an array of values simulating camera movement.
EDIT:
After Ike answer I modified a little my code so now it looks like this:
glPushMatrix();
glTranslatef(pivot[0], pivot[1], pivot[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(translate[0], translate[1], translate[2]);
glPopMatrix();
So if I'm getting Iko's solution correctly now my biggest concern is calculating correctly pivot point according to place that I'm looking at. Is it correct thinking?
One way to get this kind of representation is to kind of translate the pivot to the origin, then rotate, and then step backwards, away from the pivot.
Effectively you translate in the opposite direction of the pivot (negative pivot, effectively moving it to the origin). Then rotate to the desired viewing angle. And then "step back" (translate along -Z in a right-handed coordinate system).
Something like this:
mat4 modelview_matrix(float distance, const vec3& pivot, const vec3& rotation_xyz)
{
mat4 distance_mat = tmat(0.0, 0.0, -distance);
mat4 rot_mat = rmat(rotation_xyz[0], rotation_xyz[1], rotation_xyz[2]);
mat4 pivot_mat = tmat(-pivot[0], -pivot[1], -pivot[2]);
return distance_mat * rot_mat * pivot_mat;
}
tmat and rmat above are basically just constructing translation and rotation matrices.
That allows you to orbit the camera around a pivot of your choice. Panning can be achieved by actually moving the pivot around, giving you those CAD-style viewport navigation controls.
So if I'm getting Iko's solution correctly now my biggest concern is
calculating correctly pivot point according to place that I'm looking
at. Is it correct thinking?
Pretty much -- maybe with a slight tweak. That pivot point will always be what you look at -- it's going to be your center of interest. You can, for example, put it at the center of the bounding box of your scene, e.g. (some 3D software does this to fit/frame the view around the scene). After that, it's up to you to place the pivot point where you like based on the kind of software design you're after. The camera will always be looking at it.
Edit
glPushMatrix();
glTranslatef(pivot[0], pivot[1], pivot[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(translate[0], translate[1], translate[2]);
glPopMatrix();
For this kind of thing, you probably want something more like this:
glTranslatef(-pivot[0], -pivot[1], -pivot[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(0, 0, -distance);
... and outside of pushing to the transformation stack and rendering individual objects (do this at the top of the call stack). That's what gives you something akin to "camera control".
Then when you render each object, push the current transformation and do the necessary local transformations for each object and child. That gives you something akin to objects moving around and being oriented in the world independently of the camera, and a motion hierarchy with parent-child relationships.

GL_MODELVIEW and GL_PROJECTION

My code Currently looks like this :
glViewport (0, 0, this->w(), this->h());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//glTranslated (m_fXmovement, 0.0, m_fZmovement - 5);
//glRotated (m_fYangleView, 1.0, 0.0, 0.0);
//glRotated (m_fXangleView, 0.0, 1.0, 0.0);
///// Model View \\\\\
glMatrixMode(GL_MODELVIEW);
glTranslated (m_fXmovement, 0.0, m_fZmovement - 5 );
glRotated (m_fYangleView, 1.0, 0.0, 0.0);
glRotated (m_fXangleView, 0.0, 1.0, 0.0);
DrawWaveFrontObject (m_pDataObjectMedia);
glPushMatrix();
glTranslated (0.0, -3.0, 0.0);
DrawArea();
glPopMatrix();
DrawClickAnimation();
glLoadIdentity();
First I had the movement part in GL_PROJECTION and all was running fine until I was working with fog.... It felt like the Camera isn't moving, it felt more like an additional camera pointing to that camera....
Then I accidentally copied the movement parts to the GL_MODELVIEW and the fog was acting as I wanted it to act..... all was fine accepting the click animation wasn't in relation to the area anymore, now the animation moved with my ego perspective.... and I don't really get it what kind of drawing I have to put in which of these two VIEW's. Could anyone give me examples or explanations according to my code or a hint what I could improve in my styl?
Quote from opengl.org forum:
The projection matrix is used to create your viewing volume. Imagine a
scene in the real world. You don't really see everything around you,
only what your eyes allow you to see. If you're a fish for example you
see things a bit broader. So when we say that we set up the projection
matrix we mean that we set up what we want to see from the scene that
we create. I mean you can draw objects anywhere in your world. If they
are not inside the view volume you won't see anything. When you create
the view volume imagine that you create 6 clipping planes that define
your field of view.
As for the modelview matrix, it is used to make various
transformations to the models (objects) in your world. Like this you
only have to define your object once and then translate it or rotate
it or scale it.
You would use the projection matrix before drawing the objects in your
scene to set the view volume. Then you draw your object and change the
modelview matrix accordingly. Of course you can change your matrix
midway of drawing your models if for example you want to draw a scene
and then draw some text (which with some methods you can work easier
in orthographic projection) then change back to modelview matrix.
As for the name modelview it has to do with the duality of modeling
and viewing transformations. If you draw the camera 5 units back, or
move the object 5 units forwards it is essentially the same.
First of all, I suggest that you try to abandon the fixed-function pipeline (glTranslate etc) since it's been deprecated for like 10 years now. Look here for a more modern tutorial if you're interested.
As for your problem, you can imagine the meaning of the two matrices like this: The projection matrix essentially captures properties intrinsic to the camera itself, like how its field of view is shaped.
On the other hand, the modelview matrix is composed of two parts, the model matrix and the view matrix. The model part is for transforming from object space (relative to an object itself) to world space. Then, the view part translates from there to the eye space, in which the camera sits at the origin and points down the (negative?) z axis. Together, the modelview matrix essentially states how objects are to be positioned relative to the camera.
For further information, this resource gives a detailed description of graphics transformations in the context of OpenGL.
[Jan, 2017] Edit: Pages from the first link seem to be unable to access these days, so there is another link to the same content from their archive.

OpenGL: scale then translate? and how?

I've got some 2D geometry. I want to take some bounding rect around my geometry, and then render a smaller version of it somewhere else on the plane. Here's more or less the code I have to do scaling and translation:
// source and dest are arbitrary rectangles.
float scaleX = dest.width / source.width;
float scaleY = dest.height / source.height;
float translateX = dest.x - source.x;
float translateY = dest.y - source.y;
glScalef(scaleX, scaleY, 0.0);
glTranslatef(translateX, translateY, 0.0);
// Draw geometry in question with its normal verts.
This works exactly as expected for a given dimension when the dest origin is 0. But if the origin for, say, x, is nonzero, the result is still scaled correctly but looks like (?) it's translated to something near zero on that axis anyways-- turns out it's not exactly the same as if dest.x were zero.
Can someone point out something obvious I'm missing?
Thanks!
FINAL UPDATE Per Bahbar's and Marcus's answers below, I did some more experimentation and solved this. Adam Bowen's comment was the tip off. I was missing two critical facts:
I needed to be scaling around the center of the geometry I cared about.
I needed to apply the transforms in the opposite order of the intuition (for me).
The first is kind of obvious in retrospect. But for the latter, for other good programmers/bad mathematicians like me: Turns out my intuition was operating in what the Red Book calls a "Grand, Fixed Coordinate System", in which there is an absolute plane, and your geometry moves around on that plane using transforms. This is OK, but given the nature of the math behind stacking multiple transforms into one matrix, it's the opposite of how things really work (see answers below or Red Book for more). Basically, the transforms are "applied" in "reverse order" to how they appear in code. Here's the final working solution:
// source and dest are arbitrary rectangles.
float scaleX = dest.width / source.width;
float scaleY = dest.height / source.height;
Point sourceCenter = centerPointOfRect(source);
Point destCenter = centerPointOfRect(dest);
glTranslatef(destCenter.x, destCenter.y, 0.0);
glScalef(scaleX, scaleY, 0.0);
glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0);
// Draw geometry in question with its normal verts.
In OpenGL, matrices you specify are multiplied to the right of the existing matrix, and the vertex is on the far right of the expression.
Thus, the last operation you specify are in the coordinate system of the geometry itself.
(The first is usually the view transform, i.e. inverse of your camera's to-world transform.)
Bahbar makes a good point that you need to consider the center point for scaling. (or the pivot point for rotations.) Usually you translate there, rotate/scale, then translate back. (or in general, apply basis transform, the operation, then the inverse). This is called Change of Basis, which you might want to read up on.
Anyway, to get some intuition about how it works, try with some simple values (zero, etc) then alter them slightly (perhaps an animation) and see what happens with the output. Then it's much easier to see what your transforms are actually doing to your geometry.
Update
That the order is "reversed" w.r.t. intuition is rather common among beginner OpenGL-coders. I've been tutoring a computer graphics course and many react in a similar manner. It becomes easier to think about how OpenGL does it if you consider the use of pushmatrix/popmatrix while rendering a tree (scene-graph) of transforms and geometries. Then the current order-of-things becomes rather natural, and the opposite would make it rather difficult to get anything useful done.
Scale, just like Rotate, operates from the origin. so if you scale by half an object that spans the segment [10:20] (on axis X, e.g.), you get [5:10]. The object therefore was scaled, and moved closer to the origin. Exactly what you observed.
This is why you apply Scale first in general (because objects tend to be defined around 0).
So if you want to scale an object around point Center, you can translate the object from Center to the origin, scale there, and translate back.
Side note, if you translate first, and then scale, then your scale is applied to the previous translation, which is why you probably had issues with this method.
I haven't played with OpenGL ES, just a bit with OpenGL.
It sounds like you want to transform from a different position as opposed to the origin, not sure, but can you try to do the transforms and draws that bit within glPushMatrix() and glPopMatrix() ?
e.g.
// source and dest are arbitrary rectangles.
float scaleX = dest.width / source.width;
float scaleY = dest.height / source.height;
float translateX = dest.x - source.x;
float translateY = dest.y - source.y;
glPushMatrix();
glScalef(scaleX, scaleY, 0.0);
glTranslatef(translateX, translateY, 0.0);
// Draw geometry in question with its normal verts.
//as if it were drawn from 0,0
glPopMatrix();
Here's a simple Processing sketch I wrote to illustrate the point:
import processing.opengl.*;
import javax.media.opengl.*;
void setup() {
size(500, 400, OPENGL);
}
void draw() {
background(255);
PGraphicsOpenGL pgl = (PGraphicsOpenGL) g;
GL gl = pgl.beginGL();
gl.glPushMatrix();
//transform the 'pivot'
gl.glTranslatef(100,100,0);
gl.glScalef(10,10,10);
//draw something from the 'pivot'
gl.glColor3f(0, 0.77, 0);
drawTriangle(gl);
gl.glPopMatrix();
//matrix poped, we're back to orginin(0,0,0), continue as normal
gl.glColor3f(0.77, 0, 0);
drawTriangle(gl);
pgl.endGL();
}
void drawTriangle(GL gl){
gl.glBegin(GL.GL_TRIANGLES);
gl.glVertex2i(10, 0);
gl.glVertex2i(0, 20);
gl.glVertex2i(20, 20);
gl.glEnd();
}
Here is an image of the sketch running, the same green triangle is drawn, with translation and scale applied, then the red one, outsie the push/pop 'block', so it is not affected by the transform:
HTH,
George

OpenGL Rotation

I'm trying to do a simple rotation in OpenGL but must be missing the point.
I'm not looking for a specific fix so much as a quick explanation or link that explains OpenGL rotation more generally.
At the moment I have code like this:
glPushMatrix();
glRotatef(90.0, 0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 3.0, 2.0, 0.0 );
glVertex3f( 3.0, 1.0, 0.0 );
glEnd();
glPopMatrix();
But the result is not a triangle rotated 90 degrees.
Edit
Hmm thanks to Mike Haboustak - it appeared my code was calling a SetCamera function that use glOrtho. I'm too new to OpenGL to have any idea of what this meant but disabling this and rotating in the Z-axis produced the desired result.
Ensure that you're modifying the modelview matrix by putting the following before the glRotatef call:
glMatrixMode(GL_MODELVIEW);
Otherwise, you may be modifying either the projection or a texture matrix instead.
Do you get a 1 unit straight line? It seems that 90deg rot. around Y is going to have you looking at the side of a triangle with no depth.
You should try rotating around the Z axis instead and see if you get something that makes more sense.
OpenGL has two matrices related to the display of geometry, the ModelView and the Projection. Both are applied to coordinates before the data becomes visible on the screen. First the ModelView matrix is applied, transforming the data from model space into view space. Then the Projection matrix is applied with transforms the data from view space for "projection" on your 2D monitor.
ModelView is used to position multiple objects to their locations in the "world", Projection is used to position the objects onto the screen.
Your code seems fine, so I assume from reading the documentation you know what the nature of functions like glPushMatrix() is. If rotating around Z still doesn't make sense, verify that you're editing the ModelView matrix by calling glMatrixMode.
The "accepted answer" is not fully correct - rotating around the Z will not help you see this triangle unless you've done some strange things prior to this code. Removing a glOrtho(...) call might have corrected the problem in this case, but you still have a couple of other issues.
Two major problems with the code as written:
Have you positioned the camera previously? In OpenGL, the camera is located at the origin, looking down the Z axis, with positive Y as up. In this case, the triangle is being drawn in the same plane as your eye, but up and to the right. Unless you have a very strange projection matrix, you won't see it. gluLookat() is the easiest command to do this, but any command that moves the current matrix (which should be MODELVIEW) can be made to work.
You are drawing the triangle in a left handed, or clockwise method, whereas the default for OpenGL is a right handed, or counterclockwise coordinate system. This means that, if you are culling backfaces (which you are probably not, but will likely move onto as you get more advanced), you would not see the triangle as expected. To see the problem, put your right hand in front of your face and, imagining it is in the X-Y plane, move your fingers in the order you draw the vertices (1,1) to (3,2) to (3,1). When you do this, your thumb is facing away from your face, meaning you are looking at the back side of the triangle. You need to get into the habit of drawing faces in a right handed method, since that is the common way it is done in OpenGL.
The best thing I can recommend is to use the NeHe tutorials - http://nehe.gamedev.net/. They begin by showing you how to set up OpenGL in several systems, move onto drawing triangles, and continue slowly and surely to more advanced topics. They are very easy to follow.
Regarding Projection matrix, you can find a good source to start with here:
http://msdn.microsoft.com/en-us/library/bb147302(VS.85).aspx
It explains a bit about how to construct one type of projection matrix. Orthographic projection is the very basic/primitive form of such a matrix and basically what is does is taking 2 of the 3 axes coordinates and project them to the screen (you can still flip axes and scale them but there is no warp or perspective effect).
transformation of matrices is most likely one of the most important things when rendering in 3D and basically involves 3 matrix stages:
Transform1 = Object coordinates system to World (for example - object rotation and scale)
Transform2 = World coordinates system to Camera (placing the object in the right place)
Transform3 = Camera coordinates system to Screen space (projecting to screen)
Usually the 3 matrix multiplication result is referred to as the WorldViewProjection matrix (if you ever bump into this term), since it transforms the coordinates from Model space through World, then to Camera and finally to the screen representation.
Have fun