OpenGL Make Object Stick to Camera - c++

In my adventures to better understand what exactly is going on with matrices and vertex math with OpenGL, I wanted to see if I could get an object to "stick" in front of my "camera". I have been playing with this for a couple of days now and feel like I'm getting close.
So far I have managed to get the object to follow the camera's movement, except for it's rotation (I just can't seem to figure out this front vector). To create the new position of the object I have the following code:
glm::mat4 mtx_trans = glm::mat4(1.0f);
mtx_trans = glm::translate(mtx_trans, camera->getPosition() + camera->getFront());
glm::vec4 cubePosVec4 = glm::vec4(0.0f, 0.0f, -3.0f, 1.0);
cubePosVec4 = mtx_trans * cubePosVec4;
cubePositions[9] = glm::vec3(cubePosVec4.x, cubePosVec4.y, cubePosVec4.z);
Where camera->getPosition() obtains the camera's current position vector and camera->getFront() obtains the camera's current front vector.
As mentioned I'm in the process of learning what all is going on here, so it's possible I'm going about this all wrong...In which case how should I go about "locking" an object a certain distance away from the camera?

If the object should always be at the same position in relation to the camera, then you've to skip the transformation by the view matrix.
Note, the view matrix transforms from world space to view space. If the object should always be placed in front of the camera, then the object has not to be placed in the world, it has to be placed in the view. Therefore, the "view" matrix for the object is the identity matrix.
So the common model view transformation for the object in your case is a translation of the object in along the z axis in negative direction. The translation has to be negative, because the z axis points out of the view (in view space):
glm::mat4 mtx_trans = glm::mat4(1.0f);
mtx_trans = glm::translate(mtx_trans, glm::vec3(0.0f, 0.0f, -3.0f));

Related

Rotating a polygon about origin

I'm trying to rotate an object (set of vertices) about the origin in opengl.
The object being a Carriage in a Ferris wheel which must not must stay upright during the rotation. So far all I've got is the following transformation which rotates the carriage but does not stay upright. This uses basic rotation transformation about the origin at a 72 degree angle. The model martix looks something like this:
g_modelMatrix[i] = glm::mat4(1.0f) * glm::rotate(glm::radians(-72.0f), glm::vec3(0.0f, 0.0f, 1.0f));
where glm::mat4(1.0f)is an identity matrix
The end result transforms the carriage but does not make it upright.
What transformation would be appropriate for this kind of problem?
This is the approach I used to solve the problem.
rotate(i * 72°) * translate(r, 0, 0) * rotate(-i * 72°)

OpenGL glm rotate model around a point issue

I have a model and some helper cubes which are located on its axes, three on each axis for transformations, I used them for rotate the model around its local axes.
I want to make those cubes rotate around the model center with its rotation so I translate them to the model center, rotate them by the same angle on the same axis the translate them back.
This is the code:
//Rotation around X axis
GLfloat theta=glm::radians(xoffset);
glm::quat Qx(glm::angleAxis(theta, glm::vec3(1.0f, 0.0f, 0.0f)));
glm::mat4 rotX = glm::mat4_cast(Qx);
pickedObject->Transform(rotX);//Multiply the model matrix by the transformation matrix
glm::vec3 op(pickedObject->getMatrix()[3]);//model position
for(TransformationHelper* h:pickedObject->GetTransformationHelpers()){//the small cubes
glm::mat4 m,it,t;
glm::vec3 hp(h->getMatrix()[3]);//the cube position
t=glm::translate(m,op);//m is a unit matrix
it=glm::translate(m,-op);
m=t*rotX*it;
h->Transform(m);
}
The result is unexpected
Update:
after updating the translation matrix I got this result:
The translation is in the wrong direction; the correct offset should be hp-op, i.e. the matrix t should restore the cube's position after rotating.
t=glm::translate(glm::mat(1.f),hp-op);
Also there is no need to use inverse since it is costly (and numerically less stable):
it=glm::translate(glm::mat(1.f),op-hp);
(Note: here translate was called with an explicitly constructed identity matrix. See this post for a similar problem. See here for why this is necessary.)

Multiple modelview matrices

I'm following the OpenGL tutorials on opengl-tutorial.org, and in tutorial 4 the author proposed, as a side "project", to send two "objects" to OpenGL and we have only ever rendered one object before. Specifically, he asks this:
Draw the cube AND the triangle, at different locations. You will need to generate 2 MVP matrices, to make 2 draw calls in the main loop, but only 1 shader is required.
We define the MVP matrix like this:
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(0,0,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
Now I understand that only one MVP matrix is used per object. But I have a few questions.
How do I create a MVP matrix for each object? Do I have to re-create the View and Model matrices for every object (IE specify a new one for each object)?
I thought glm::lookAt was used as the "camera" of sorts, so I shouldn't have to create a new "Camera" for each object, should I?
What does the Model matrix do? The author says it is a identity matrix right now, but if I change that to say 100, nothing happens! I thought that the Model matrix was the matrix that defined where the model was rendered, but I can't seem to change where the model is rendered without modifying the View matrix (which makes sense).
Typically, one uses one projection and one view matrix per "camera". The view matrix basically represents the position and orientation of the camera, and the projection matrix represents the properties of the camera (field of view, aspect, etc. in some way like a "lens" of a real camera, but don't stretch that analogy too far).
A model matrix typically is used to place the model in some global "world cooridnate system". So, you need a model matrix per object, so each object can be placed independently.
The world coordiante system is not strictly needed at all. What matters to the resulting picture is how the objects are placed relative to the camera - that is there ModelView enters the picture - as the composition of the model and the view transform, directly going from object space to some camera-relative eye space, bypassing any "world space" completely.
In your case, you even further combine this with the projection matrix, so you go directly from object space to clip space.
As you can see, the MVP matrix needs to change if any of the distinct matrices it is composed of does change. You could in theory precalculate an MVP per object - but that is typically not done, since the camera is moveable and all those MVP matrices would have to be recalculated anyways - there is not much to save here. So one typically keeps these matrices separate and multiplies them together directly before the draw call.
What does the Model matrix do? The author says it is a identity matrix right now, but if I change that to say 100, nothing happens!
What does this even mean, "changing a matrix to 100"? From the above code snippets it can be seen that your model matrix is indeed used and affects the MVP matrix. So changing it should have an effect - depending on what you change, of course. If you just changed the line
glm::mat4 Model = glm::mat4(1.0f);
to
glm::mat4 Model = glm::mat4(100.0f);
then it would actually not lead to any observeable change. You would get different clip space coords, but the differences would cancel each other out and the produced image would have been the same. That would be due to how homogenous coordinates work, and is a different matter entirely.

Perspective Issue with 3D coordinate system in OpenGL

I'm currently facing some perspective issues when trying to render the axes of a coordinate system into my scene. For these axes I draw three orthogonal lines that go through the center of my 3D cube.
It's pretty tough to explain what the problem is, so I guess the most demonstrative way of presenting it is to post some pictures.
1) view on the whole scene: click here
2) zoomed in view on the origin of the coordinate system: click here
3) When I zoom in a tiny little bit further, two of the axes disappear and the other one seems to be displaced for some reason: click here
Why does this happen and how can I prevent it?
My modelview and projection matrices look the following:
// Set ProjectionMatrix
projectionMatrix = glm::perspective(90.0f, (GLfloat)width / (GLfloat) height, 0.0001f, 1000.f);
glBindBuffer(GL_UNIFORM_BUFFER, globalMatricesUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projectionMatrix));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
// Set ModelViewMatrix
glm::mat4 identity = glm::mat4(1.0); // Start with the identity as the transformation matrix
glm::mat4 pointTranslateZ = glm::translate(identity, glm::vec3(0.0f, 0.0f, -translate_z)); // Zoom in or out by translating in z-direction based on user input
glm::mat4 viewRotateX = glm::rotate(pointTranslateZ, rotate_x, glm::vec3(1.0f, 0.0f, 0.0f)); // Rotate the whole szene in x-direction based on user input
glm::mat4 viewRotateY = glm::rotate(viewRotateX, rotate_y, glm::vec3(0.0f, 1.0f, 0.0f)); // Rotate the whole szene in y-direction based on user input
glm::mat4 pointRotateX = glm::rotate(viewRotateY, -90.0f, glm::vec3(1.0f, 0.0f, 0.0f)); // Rotate the camera by 90 degrees in negative x-direction to get a frontal look on the szene
glm::mat4 viewTranslate = glm::translate(pointRotateX, glm::vec3(-dimensionX/2.0f, -dimensionY/2.0f, -dimensionZ/2.0f)); // Translate the origin to be the center of the cube
That's called "clipping". The axis is hitting the near-clip plane and thus is being clipped. The third axis is not "displaced"; it is simply partially clipped. Take your second image and cover up most of it, so that you only see part of the diagonal axis; that's what you're getting.
There are a few general solutions to this. First, you could just not allow the user to zoom in that far. Or you could adjust the near clip plane inward as the camera is moved closer to the target object. This will also cause precision problems for far away objects, so you'll probably want to adjust your far clip plane inward too.
Alternatively, you can just turn on depth clamping (assuming you have GL 3.x+, or access to ARB_depth_clamp or NV_depth_clamp). This isn't a perfect solution, as things will still be clipped when they get behind the camera. And things that intersect the near clip plane will no longer have proper depth buffering if two such objects overlap. But it's generally good enough.

OpenGL/GLSL/GLM - Skybox rotates as if in 3rd person

I have just gotten into implementing skyboxes and am doing so with OpenGL/GLSL and GLM as my math library. I assume the problem is matrix related and I haven't been able to find an implementation that utilizes the GLM library:
The model for the skybox loads just fine, the camera however circles it as if it is rotating around it in 3d third person camera.
For my skybox matrix, I am updating it every time my camera updates. Because I use glm::lookAt, it is essentially created the same way as my view matrix except I use 0, 0, 0 for the direction.
Here is my view matrix creation. It works fine in rendering of objects and geometry:
direction = glm::vec3(cos(anglePitch) * sin(angleYaw), sin(anglePitch), cos(anglePitch) * cos(angleYaw));
right = glm::vec3(sin(angleYaw - 3.14f/2.0f), 0, cos(angleYaw - 3.14f/2.0f));
up = glm::cross(right, direction);
glm::mat4 viewMatrix = glm::lookAt(position, position+direction, up);
Similarly, my sky matrix is created in the same way with only one change:
glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
glm::mat4 skyView = glm::lookAt(position, position + direction, up);
I know a skybox does not apply translation and only considers rotations so I am not sure what the issue is. Is there an easier way to do this?
Visual aids:
Straight on without any movement yet
When I rotate the camera:
My question is this: how do I set up the correct matrix for rendering a skybox using glm:lookAt?
Aesthete is right skybox/skydome is only object that means you do not change projection matrix !!!
your render should be something like this:
clear screen/buffers
set camera
set modelview to identity and then translate it to position of camera you can get the position directly from projection matrix (if my memory serves at array positions 12,13,14) to obtain the matrix see this https://stackoverflow.com/a/18039707/2521214
draw skybox/skydome (do not cross your z_far plane,or disable Depth Test)
optionaly clear Z-buffer or re-enable Depth Test
draw your scene stuf .... ( do not forget to set modelview matrix for each of your drawed model)
of course you can temporary set your camera position (projection matrix) to (0,0,0) and leave modelview matrix with identity, it is sometimes more precise approach but do not forget to set the camera position back after skybox draw.
hope it helps.