Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
i've been creating a basic gui recently, and i'm trying to give the user the ability to rotate a shape/image/sprite. however, when i use glm::rotate to attempt to change the model matrix i get some unexpected results. the transformed shape changes dimensions, rotates way too far, and also rotates about a seemingly random point.
shader code:
#version 330 core
layout(location = 0) in vec2 pos;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
void main()
{
gl_Position = projection * view * model * vec4(pos.x, pos.y, 1.0f, 1.0f);
}
rotation code:
m_modelMatrix = glm::mat4(1.0f);
m_modelMatrix = glm::rotate(m_modelMatrix, 45.f, glm::vec3(0, 0, 1);
view and projection setup
glm::mat4 proj = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
proj = glm::perspective(glm::radians(53.f), 1.f, 0.1f, 100.f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
everything is in 2d.
Welcome to Stack Overflow! :)
I assume that you already have a setup with a projection and view matrix, like you pointed out in the comments. It should look like this,
#version 330 core
layout(location = 0) in vec2 pos;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
void main()
{
gl_Position = projection * view * model * vec4(pos.x, pos.y, 1.0f, 1.0f);
}
the projection matrix should have been created with
glm::ortho( ... );
or
glm::perspective( ... );
and the view matrix should have been created with
glm::lookAt( ... );
as described in https://glm.g-truc.net/0.9.2/api/a00245.html.
If further explanation is required, I advise you to look at https://learnopengl.com/Getting-started/Coordinate-Systems as a reference.
I also assume that the problem originates from previous transformations and how this rotation is used to modify an existing model matrix. E.g. the problem only occurs when you have specified a model matrix other than the identity matrix.
When you create the model matrix, you have to make sure that you use the correct order of multiplication:
glm::mat4 translation = ... ;
glm::mat4 rotation = ... ;
glm::mat4 scale = ... ;
glm::mat4 model = translation * rotation * scale;
Since you will multiply a vector from the right hand side to the model matrix, this order guarantees you that no distortions will occur. The vector will be scaled first, then rotated and finally translated.
When you try to rotate the model matrix with,
glm::rotate(model, angle, axis);
you essentially multiply the rotation matrix from the right hand side and break the multiplication order of the model matrix.
model * rotation_from_user_input
= translation * rotation * scale * rotation_from_user_input
You would have to change the rotation of the model matrix like this
rotation *= rotation_from_user_input;
and then update the model matrix itself to fix the distortions.
model = translation * rotation * scale;
Related
I have been getting unexpected behavior while trying to rotate a basic cube. It may be helpful to know that translating the cube works correctly in the y and z direction. However, translating along the x axis is backwards(I negate only x for proper results) which I haven't been able to figure out why.
Furthermore, rotating the cube has been a mess. Without any sort of transform the cube appears correctly. Once I add a rotation transformation the cube is not displayed until I change one of the x,y,z rotation values from 0(Putting all values back to 0 makes it disappear again). Once it appears the cube won't rotate around whichever x,y,z plane I first changed unless I change two or more of the coordinates. It also wobbles around its origin when rotating.
Below is a snippets of my code I believe has incorrect math.
/* Here's how I setup the matrices for a mvp matrix*/
proj = glm::perspective(glm::radians(90.0f), (960.0f / 540.0f), 0.1f, 400.0f);
view = glm::lookAt(glm::vec3(0, 0, -200), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
glm::mat4 model = glm::mat4(1.0f);
/* Here's how I transform the model matrix, note
translating works properly once the cube is visible*/
model = glm::translate(model, glm::vec3(-translation[0], translation[1], translation[2])); //negative x value
model = glm::rotate(model, 30.0f, rotation);
glm::mat4 mvp = proj * view * model;
shader->Bind();
shader->SetUniformMat4f("MVP", mvp);
renderer.Draw(*c_VAO, *c_EBO, *shader);
/* Here's how I use these values in my vertex shader */
layout(location = 0) in vec4 position;
...
uniform mat4 MVP;
...
void main()
{
gl_Position = u_MVP * position;
....
};
I've checked both the translation and rotation vectors values and they are as expected but I am still going mad trying to figure out this problem.
The unit of the angle of glm::rotate is radians. Use glm::radians to convert form degrees to radians:
model = glm::rotate(model, 30.0f, rotation);
model = glm::rotate(model, glm::radians(30.0f), rotation);
Let's say I have the following vertex shader code below:
attribute vec4 vPos;
uniform mat4 MVP;
uniform mat4 LookAt;
void main{
gl_Position = MVP * vPos;
}
How do I use the LookAt matrix in this shader to position the eye of the camera? I have tried LookAt * MVP * vPos but that didn't seem to work as my triangle just disappeared off screen!
I would suggest move the LookAt outside the shader to prevent un-necessary calculation per vertex. The shader still do
gl_Position = MVP * vPos;
and you manipulate MVP in the application with glm. For example:
projection = glm::perspective(fov, aspect, 0.1f, 10000.0f);
view = glm::lookAt(eye, center, up);
model = matrix of the model, with all the dynamic transforms.
MVP = projection * view * model;
A LookAt matrix is in general called a View matrix and is concatenated with a model-to-world transform matrix to form the WorldView matrix. This is then multiplied by the projection matrix which is often orthographic or perspective. Vertex positions in model space are multiplied with the resulting matrix in order to be transformed to clip space (kinda...I skipped a couple of steps here that you don't have to do and is performed by the hardware/driver).
In your case, make sure that you're using the correct 'handedness' for your transformations. Also you can try and multiply the position in the reverse order with the transpose of your transformation matrices like so vPos*T_MVP*T_LookAt.
I'm trying to port an old SDL game I wrote some time ago to 3.3+ OpenGL and I'm having a few issues getting a proper orthogonal matrix and it's corresponding view.
glm::mat4 proj = glm::ortho( 0.0f, static_cast<float>(win_W), static_cast<float>(win_H), 0.0f,-5.0f, 5.0f);
If I simply use this projection and try to render say a quad inside the boundaries of win_W and win_H, it works. However, if instead I try to simulate a camera using:
glm::mat4 view = glm::lookAt(
glm::vec3(0.0f, 0.0f, 1.0f),//cam pos
glm::vec3(0.0f, 0.0f, 0.0f),//looking at
glm::vec3(0.0f, 0.0f, 1.0f)//floored
);
I get nothing. Even when positioning the quad in the center, same if instead I center the view:
glm::mat4 view = glm::lookAt(
glm::vec3(static_cast<float>(win_W), static_cast<float>(winH), 1.0f),//cam pos
glm::vec3(static_cast<float>(win_W), static_cast<float>(winH), 0.0f),//looking at
glm::vec3(0.0f, 0.0f, 1.0f)//floored
);
Considering that SDL usually subtracts the camera values from the vertices in the game to simulate a view, is it simply better to replace my MVP operation in the shader like this:
#version 150
in vec2 position;
in vec3 color;
out vec3 Color;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 camera;
void main()
{
Color = color;
//faulty view
//gl_Position = projection *view * model * vec4(position, 0.0, 1.0);
//new SDL style camera
mat4 newPosition = projection * model * vec4(position, 0.0, 1.0);
gl_Position = newPosition - camera;
}
Unfortunately the source I'm learning from (ArcSynthesis Book) doesn't cover a view that involves a coordinate system other than the default NDC. And for some reason even today most discussion about opengl is about deprecated versions.
So in short, whats the best way of setting up the view to an orthogonal projection matrix for simple 2D rendering in modern opengl?
Your lookup call actually does not make sense at all, since your up vector (0,0,1) is colinear to the viewing direction (0,0,-1). This will not produce a useable matrix.
You probably want (0,1,0) as up vector. However, even if you change that, you might be surprised about the result. In combination with the projection matrix you set up, the point you specified as the lookat target will not appear in the center, but at the corner of the screen. Your projection does not map (0,0) to the center, which one typically assumes when using some LookAt function.
I agree to Colonel Thirty Two's comment: Don't use LookAt in this scenario, unless you have a very good reason to.
I've been learning OpenGL 3+ from various online resources and recently gotten confused with transformation (model) matrices. As far as I know the proper order of multiplication is translationMatrix * rotationMatrix * scaleMatrix. If I understand correctly the multiplication is backwards, so the scale is applied first, then the rotation and lastly the transformation.
I have a Transform class which stores the position, scale and origin as 2d vectors and rotation as a float. The method for calculating transformation matrix looks like this:
glm::mat4 Transform::getTransformationMatrix() const
{
glm::mat4 result = glm::mat4(1.0f);
result = glm::translate(result, glm::vec3(position, 0.0f));
result = glm::translate(result, glm::vec3(origin, 0.0f));
result = glm::rotate(result, rotation, glm::vec3(0, 0, 1));
result = glm::translate(result, glm::vec3(-origin, 0.0f));
result = glm::scale(result, glm::vec3(scale, 0.0f));
return result;
}
Here's the vertex shader code:
#version 330 core
layout(location = 0) in vec2 position;
uniform mat4 modelMatrix;
uniform mat4 projectionMatrix;
void main()
{
gl_Position = projectionMatrix * modelMatrix * vec4(position, 0.0, 1.0);
}
As you can see I first translate and then rotate and scale, which is the opposite of what I have learnt. At first I had it the proper way (scale, rotate and translate) but it rotated around the initial position with huge radius, not the translated position which is not what I want (I am making a 2d game with sprites). I don't understand why does it work this way, can someone explain, do I have to keep separate methods for transform matrix calculations? Also does it work the same in 3d space?
I currently have 5 models displayed in a screen and what I'm trying to do. The following is my vertex shader for translating the models individually so that I can get them to move in different directions:
#version 330
layout (location = 0) Position;
uniform mat4 MVP;
uniform vec3 Translation;
uniform mat4 Rotate;
void main()
{
gl_Position = MVP * * Rotate * vec4(Position + Translation, 1.0); // Correct?
}
And to position/move my models individually within the render loop:
//MODEL ONE
glUniform3f(loc, 0.0f, 4.0f, 0.0f); // loc is "Translate"
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(rotationMatrix)); // loc is "Rotate"
_model1.render();
Also I do have a glm::mat4 rotateMatrix() that returns a rotation. but when I multiply it with the other matrices within the render loop, the whole scene (minus the camera) rotates to the set angle.
UPDATE
How would I be able to apply my rotation to the models independently of the world on their own axis? The problem now is that the model rotates, but from 0,0,0 of the world and not it's own position.
There's are a couple of syntax error in your vertex shader:
No type for the Position variable. Looks from the context like it should be a vec3.
Two * signs after MVP.
I assume that was those were just an accident while copying the code, and you actually have a vertex shader that compiles.
To apply the rotation described by the Rotate matrix before the translation from the Translation vector, you should be able to simply change the order in the vertex shader:
vec4 rotatedVec = Rotate * vec4(Position, 1.0);
gl_Position = MVP * vec4(rotatedVec.xyz + Translation, 1.0);
The whole thing would looks simpler if you defined Rotate as a 3x3 matrix, which is sufficient for a rotation.