I'm having difficulty figuring out how to translate an object across the screen given arrow key inputs. Currently I have no issue moving the camera around, but I can't seem to wrap my head around making the object move instead of the camera.
Here's what I'm doing to compute the View Matrix
ViewMatrix = glm::lookAt(
position, //camera position
position+direction, //look at origin
up //head up
);
where position and direction are glm::vec3
So to instead change the position of the object, would I modify the Model Matrix? or would I do something with mvp?
The model matrix currently remains at glm::mat4(1.0)
computeMatricesFromInputs(window,time); //function that handles input and computes viewMatrix
glm::mat4 projectionMatrix = glm::perspective(45.0f, 4.0f/3.0f, 0.1f, 100.0f);
glm::mat4 viewMatrix = getViewMatrix();
glm::mat4 modelMatrix = glm::mat4(1.0);
glm::mat4 MVP = projectionMatrix * viewMatrix * modelMatrix;
So I ended up figuring the problem with with help from #j-p. What I wanted to do was move the object, so I applied the glm function translate() to the model matrix. To do this I went over to my controls file and created a function called
glm::mat4 getModelMatrix();
which returned the variable glm::mat4 ModelMatrix that I had also declared in the header file. The actual portion of code and moved the object was like so:
//If the the corresponding key is pressed...
ModelMatrix = glm::translate(ModelMatrix, glm::vec3(0.0f, 1.0f, 0.0f); //move y 1.0f
//else If..etc..
Then passing back towards my main loop the final code would look like:
computeMatricesFromInputs(window,time); //function that handles input and computes viewMatrix
glm::mat4 projectionMatrix = glm::perspective(45.0f, 4.0f/3.0f, 0.1f, 100.0f);
glm::mat4 viewMatrix = getViewMatrix();
glm::mat4 modelMatrix = getModelMatrix();
glm::mat4 MVP = projectionMatrix * viewMatrix * modelMatrix;
Related
I want to rotate a 2D object in OpenGL with this code:
mView = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f));
mModel = glm::translate(glm::mat4(1.0f), mLocation);
mModel = glm::rotate(mModel, mRotation, glm::vec3(0.0f, 0.f, 1.f));
mModel = glm::scale(mModel, mScale);
mMVP = mProj * mView * mModel;
With this code, the object rotates around the global axis and not it's local axis.
If I don't include the view matrix(mMVP = mProj * mModel;) It works fine, but then I don't have a view projection. How is it possible for an object to rotate around it's own axis?
I have a mat4 called model. I want my cube to orbit around a position. I am able to call the glm::rotate(mat4, angle, vec3) just fine and have it rotate at its origin.
void Object::Update(unsigned int dt)
{
angle += dt * M_PI/1000;
model = glm::rotate(glm::mat4(1.0f), (angle), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, -0.5f, 0.0f));
}
Unfortunately my cube is frozen in place when I add the glm::translate call after the rotation. Is there something basic I'm missing?
You must pass it the result of the rotation as the initial matrix: model = glm::translate(model, glm::vec3(0.5f, -0.5f, 0.0f));. Otherwise you are resetting and translating the Identity matrix, which will completely overwrite your rotation.
glm::mat4 Model = glm::mat4(1.0f);
float dir_x = 0.0f, dir_y = 1.0f, dir_z = 0.0f;
do {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);
//glm::mat4 Projection = glm::ortho(-1.0f,1.0f,-1.0f,1.0f,0.0f,100.0f); // In world coordinates
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(0.5, 0.5, 3), // Camera is at (4,3,3), in World Space
glm::vec3(0.5, 0.5, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
float rot_angle = 0.0f;
const float speed = 0.01f;
glm::vec3 dir = glm::vec3(dir_x, dir_y, dir-z);
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
{
rot_angle = -1.0f;
Model = glm::translate(tri_center)* glm::rotate(glm::mat4(), glm::radians(rot_angle), glm::vec3(0, 0, -1))*glm::translate(-tri_center)*Model;
//dir left
...
If I rotate the object(car), I want to move it to the head of the car. Now, regardless of the head of car, the car only moves upward.
How do codes make dir rotate?
Changing the center of rotation can be achieved with the following:
Remember, multiply matrices RIGHT TO LEFT, the first transform on the rightmost side, the last on the left
First, create a translation that brings the center of rotation to the origin of the scene (0, 0, 0), this is basically reversing each x,y, and z. So the translation for the example center vec3(1.0, 2.3, -5.2) is glm::mat4 origin = glm::translate(origin, glm::vec3(-1.0, -2.3, 5.2);
Store this vector, we are going to use this for ALL points in the mesh
Now apply the desired rotation(s) to this translate matrix and store them in a new mat4, so do:
glm::mat4 final = glm::rotate(..) * origin
Finally, bring the center (and the rest of the model) back to the original position by creating a translation identical to the vector3 with the following:
glm::mat4 relocate = glm::translate(relocate, center) and then
glm::mat4 final = relocate * glm::rotate(..) * origin
Essentially what we are doing here is bringing the center of the model to the origin, translating all points relative to that, then rotating them around the center (which is now the origin), then bringing them back the same distance they came.
Now apply this translation to ALL of the models points, do this in the vertex shader, obviously. If the model is really small, you could do it in your code but that will gobble memory for most meshes. This mat4 could be applied to the model matrix if you don't want to add another matrix. model = model * final //note, first do transformations, then scale for the model
Full code looks something like this: (you could also multiply the matricies manually, but GLM lets you pass a matrix into the args of translate() function, it then just applies the translation to the matrix in its current form)
glm::vec3 center = vec3(1.0, 2.3, -5.2);
glm::mat4 finalTransform = glm::translate(finalTransform, glm::vec3(-1.0, -2.3, 5.2)); //first bring everything to origin, notice this is a mat4
finalTransform = glm::rotate(finalTransform, ...); //rotate how you want
finalTransform = glm::translate(finalTransform, center); //return to center
model = model * finalTransform; //apply this transformation to be calculated by the vertex shader for the object
glUniformMatrix4fv(glGetUniformLocation(sp, "model"), 1, GL_FALSE, glm::value_ptr(model)); //pass model matrix into shader program
Also, in your current code it appears that you have the right idea, but you are using the translate function incorrectly. It should be called like this: glm::translate(mat4, vec3). At the very least, construct an empty mat4 to translate with the glm::mat4() constructor.
How can I rotate a camera in a axis? What matrix I have to multiply?
I am using glm::lookAt to construct the viewMatrix, but I tried to multiply it by a rotation matrix and nothing happened.
glm::mat4 GetViewMatrix()
{
return glm::lookAt(this->Position, this->Position + this->Front, glm::vec3(0.0f, 5.0f, 0.0f));
}
glm::mat4 ProjectionMatrix = glm::perspective(actual_camera->Zoom, (float)g_nWidth / (float)g_nHeight, 0.1f, 1000.0f);
glm::mat4 ViewMatrix = actual_camera->GetViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
Rotate the front and up vectors of your camera using glm::rotate:
glm::mat4 GetViewMatrix()
{
auto front = glm::rotate(this->Front, angle, axis);
auto up = glm::rotate(glm::vec3(0, 1, 0), angle, axis);
return glm::lookAt(this->Position, this->Position + front, up);
}
Alternatively, you can add a multiplication with your rotation matrix to your MVP construction:
glm::mat4 MVP = ProjectionMatrix * glm::transpose(Rotation) * ViewMatrix * ModelMatrix;
It is important that the rotation happens after the view matrix, so all objects will be rotated relative to the camera's position. Furthermore, you have to use transpose(Rotation) (the inverse of a rotation matrix is its transpose), since rotating the camera clockwise for example, is equivalent to rotating all objects counter-clockwise.
How do I apply the drawing position in the world via shaders?
My vertex shader looks like this:
in vec2 position;
uniform mat4x4 model;
uniform mat4x4 view;
uniform mat4x4 projection;
void main() {
gl_Position = projection * view * model * vec4(position, 0.0, 1.0);
}
Where position is the positions of the vertexes of the triangles.
I'm binding the matrices as follows.
view:
glm::mat4x4 view = glm::lookAt(
glm::vec3(0.0f, 1.2f, 1.2f), // camera position
glm::vec3(0.0f, 0.0f, 0.0f), // camera target
glm::vec3(0.0f, 0.0f, 1.0f)); // camera up axis
GLint view_uniform = glGetUniformLocation(shader, "view");
glUniformMatrix4fv(view_uniform, 1, GL_FALSE, glm::value_ptr(view));
projection:
glm::mat4x4 projection = glm::perspective(80.0f, 640.0f/480.0f, 0.1f, 100.0f);
GLint projection_uniform = glGetUniformLocation(shader, "projection");
glUniformMatrix4fv(projection_uniform, 1, GL_FALSE, glm::value_ptr(projection));
model transformation:
glm::mat4x4 model;
model = glm::translate(model, glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::rotate(model, static_cast<float>((glm::sin(currenttime)) * 360.0), glm::vec3(0.0, 0.0, 1.0));
GLint trans_uniform = glGetUniformLocation(shader, "model");
glUniformMatrix4fv(trans_uniform, 1, GL_FALSE, glm::value_ptr(model));
So this way I have to compute the position transformation each frame on the CPU. Is this the recommended way or is there a better one?
So this way I have to compute the position transformation each frame on the CPU. Is this the recommended way or is there a better one?
Yes. Calculating a new transform once for a mesh on the CPU and then applying it to all vertices inside the mesh inside the vertex shader is not going to be a very slow operation and needs to be done every frame.
In the render() method you usually do the following things
create matrix for camera (once per frame usually)
for each object in the scene:
create transformation (position) matrix
draw object
projection matrix can be created once per windowResize, or when creating matrix for camera.
Answer: Your code is good, it is a basic way to draw/update objects.
You could go into some framework/system that manages it automatically. You should not care (right now) about the performance of those matrix creation procedures... it is very fast. Drawing is more problematic.
as jozxyqk wrote in one comment, you can create ModelViewProjMatrix and send one combined matrix instead of three different one.