user6842178 user6842178 - 5 days ago 5
C++ Question

How to rotate rotation axis in OpenGL C++?

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?

Answer

Changing the center of rotation can be achieved with the following:

  1. Remember, multiply matrices RIGHT TO LEFT, the first transform on the rightmost side, the last on the left

  2. 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);

  3. Store this vector, we are going to use this for ALL points in the mesh
  4. 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
  5. 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
  6. 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.
  7. 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.

Comments