Transformation matrix issues - c++

I'm learning about computer graphics through modern OpenGL tutorials, and I'm having issues refactoring my code from GLM to a custom matrix math class. Using GLM I can achieve the desired effect (which is a pyramid-like shape rotating across the screen); however, using my math class I cannot get the correct transformation. For reference, this is what the transformation looks like with my math class. Using GLM the shape will translate along the x-axis (horizontally) which is what I want. I assume the GLSL code is correct since it works with the GLM code.
In my Transform class, I have a function that returns a model matrix and which maps to the corresponding uniform variable in my shader class.
Matrix4f Transform::getModel() const // my math class - not working
{
Matrix4f transMat, rotMat, scaleMat;
transMat.initTranslation(trans.x, trans.y, trans.z);
rotMat.initRotation(rot.x, rot.y, rot.z);
scaleMat.initScale(scale.x, scale.y, scale.z);
return transMat * rotMat * scaleMat;
}
glm::mat4 Transform::getModel() const // glm - works fine
{
glm::mat4 transMat = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
glm::mat4 scaleMat = glm::scale(glm::vec3(scale.x, scale.y, scale.z));
glm::mat4 rotX = glm::rotate(rot.x, glm::vec3(1.0, 0.0, 0.0));
glm::mat4 rotY = glm::rotate(rot.y, glm::vec3(0.0, 1.0, 0.0));
glm::mat4 rotZ = glm::rotate(rot.z, glm::vec3(0.0, 0.0, 1.0));
glm::mat4 rotMat = rotX * rotY * rotZ;
return transMat * rotMat * scaleMat;
}
I think the problem lies in my Matrix4<T> class, but there's quite a bit of code to show so I will link. The Matrix class is based on the tutorials I linked above.
P.S. If you're wondering why I'm using a custom math class instead of GLM it is for learning purposes (I realize GLM is much more suited for this than my untested library).

Thanks for the helpful comments, all I needed to do was change the 3rd parameter in glUniformMatrix* which performed a transpose on the transformation matrix.

Related

Am I correctly rotating my model using matrices?

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

Opengl Camera rotation around X

Working on an opengl project in visual studio.Im trying to rotate the camera around the X and Y axis.
Thats the math i should use
Im having trouble because im using glm::lookAt for camera position and it takes glm::vec3 as arguments.
Can someone explain how can i implement this in opengl?
PS:i cant use quaternions
The lookAt function should take three inputs:
vec3 cameraPosition
vec3 cameraLookAt
vec3 cameraUp
For my past experience, if you want to move the camera, first find the transform matrix of the movement, then apply the matrix onto these three vectors, and the result will be three new vec3, which are your new input into the lookAt function.
vec3 newCameraPosition = movementMat4 * cameraPosition
//Same for other two
Another approach could be finding the inverse movement of the one you want the camera to do and applying it to the whole scene. Since moving the camera is kind of equals to move the object onto inverse movement while keep the camera not move :)
Below the camera is rotated around the z-axis.
const float radius = 10.0f;
float camX = sin(time) * radius;
float camZ = cos(time) * radius;
glm::vec3 cameraPos = glm::vec3(camX, 0.0, camZ);
glm::vec3 objectPos = glm::vec3(0.0, 0.0, 0.0);
glm::vec3 up = glm::vec3(0.0, 1.0, 0.0);
glm::mat4 view = glm::lookAt(cameraPos, objectPos, up);
Check out https://learnopengl.com/, its a great site to learn!

Z coordinates are flipped when using glm

I am trying to render a 3D model using OpenGL. And for the projection and transformation matrices, I am using glm. I've got my model on the screen and it works just like I intended it to; except one small problem.
I am setting the model's translation matrix as
glm::translate(glm::vec3(0, 0, 4)
to move the model a little bit forward so that I can see it. Since in OpenGL, by default, negative z is out towards the 'camera' and positive z is forward, I expected this to work but it doesn't. It only works if I set it to
glm::translate(glm::vec3(0, 0, -4)
But this seems weird to me, as I am setting my zNear to 0.01 and zFar to 1000. Is glm's z values flipped or am I doing something wrong here?
Here is my code:
glm::mat4 rotation = glm::mat4(1.0f);
glm::mat4 translation = glm::translate(glm::vec3(0, 0, -4));
glm::mat4 scale = glm::mat4(1.0f);
glm::mat4 modelMatrix = translation * rotation * scale;
glm::mat4 projectionMatrix = glm::perspective(70.0f, aspectRatio, 0.01f, 1000.0f);
glm::mat4 transformationMatrix = projectionMatrix * modelMatrix;
When you call perspective() with near = 0.01 and far = 1000.0 planes, its actual meaning is that you are cutting it as -0.01 to -1000.0 so you should put the object's z-value into the range [-0.01, -1000.0].
Imagine the right handed Coordinate and assume your eye's z-value is 0.0 in default.

OpenGl local coordinate rotation

I have been attempting to rotate an object around its local coordinates and then move it based off based of the rotated coordinates but i have not been able to achieve the desired results,
to explain the problem in a more in depth way i have an object at a certain point in space and i need to rotate it around its own origin(not the global origin) and then translate the object based off of the newly rotated axis's, after much experimenting i have discovered that i can either rotate the object around is origin but the coordinates will not be rotated with it or i can have the objects local coordinates be transformed with it but it will then rotate around the global origin.
currently my rotation/translation/scaling code looks like this
glm::mat4 myMatrix = glm::translate(glm::mat4(1.0f),trans);
glm::mat4 Model = glm::mat4(1.f);
glm::mat4 myScalingMatrix = glm::scale(sx, sy ,sz);
glm::vec3 myRotationAxis( 0, 1, 0);
glm::mat4 myRotationMatrix =glm::rotate(glm::mat4(1.0f),rot, myRotationAxis);
Model= myScalingMatrix* myRotationMatrix*myMatrix;
glm::mat4 MVP = Projection* View * Model;
I believe this is the problem code specifically the second line from the bottom but i could be wrong and will be post more code if its needed.
i have also attempted to create an inverse matrix and use that at the start of the calculation but that appears to do nothing(i can add the code that i attempted to do this with if needed)
If any kind of elaboration is needed regarding this issue feel free to ask and i will expand on the question
Thanks.
EDIT 1:
Slightly modified code that was suggested in the answers section, still giving the same bug though.
glm::mat4 Model = glm::mat4(1.f);
glm::mat4 myScalingMatrix = glm::scale(sx, sy ,sz);
glm::vec3 myRotationAxis( 0, 1, 0);
glm::mat4 myRotationMatrix =glm::rotate(glm::mat4(1.0f),rot, myRotationAxis);
glm::vec4 trans(x,y,z,1);
glm::vec4 vTrans = myRotationMatrix* trans ;
glm::mat4 myMatrix = glm::translate(glm::mat4(1.0f),vTrans.x,vTrans.y,vTrans.z);
Model= myScalingMatrix* myRotationMatrix*myMatrix;
You need to apply your rotation matrix to the translation vector (trans).
So, assuming trans is a vec4, your code will be:
glm::mat4 Model = glm::mat4(1.f);
glm::mat4 myScalingMatrix = glm::scale(sx, sy ,sz);
glm::vec3 myRotationAxis( 0, 1, 0);
glm::mat4 myRotationMatrix =glm::rotate(glm::mat4(1.0f),rot, myRotationAxis);
glm::vec4 vTrans = myRotationMatrix * trans;
glm::mat4 myMatrix = glm::translate(glm::mat4(1.0f), vTrans.xyz);
Model= myScalingMatrix* myRotationMatrix*myMatrix;
glm::mat4 MVP = Projection* View * Model;
convert vec4 to vec3
So to complete the answer, if the model center is not (0,0,0) , you will have to compute
bounds of your model and translate it by half of it less model bottom left vertex.
It's well explicated here:
model local origin
According to supplied code, the answer is the best available... if you wants more details, supply some screenshots and details on your Projection and view matrix calculations

Applying Camera Transformations to OpenGL

I'm attempting to create a Camera class for a 3D OpenGL project. However I cannot figure out how to actually apply the camera to my scene. I have these Camera functions (amongst others):
void Camera::update(){
glm::vec3 direction(cos(_verticalAngle) * sin(_horizontalAngle), sin(_verticalAngle), cos(_verticalAngle) * cos(_horizontalAngle));
glm::vec3 right = glm::vec3(sin(_horizontalAngle - 3.14f/2.0f), 0, cos(_horizontalAngle - 3.14f/2.0f));
glm::vec3 up = glm::cross(right, direction);
_projectionMatrix = glm::perspective(_FoV, float(VIEWPORT_X) / float(VIEWPORT_Y), 0.1f, 250.0f);
_viewMatrix = glm::lookAt(_position, _position + direction, up);
}
glm::mat4 Camera::getProjectionMatrix(){
return _projectionMatrix;
}
glm::mat4 Camera::getViewMatrix(){
return _viewMatrix;
}
They were created from a tutorial, I'm not sure if they work though since I can't test them. What I want to do is get OpenGL to use the view and projection matrices to simulate a camera. How exactly do I tell OpenGL to use those projection and view matrices, so that it properly simulates a camera separate from model's transformations? I'm aware OpenGL will not accept glm matrices by default, but I have seen this type of thing in a few tutorials:
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
but glUniformMatrix4fv (which I think applies the camera transforms?) makes no sense to me. It always has something to do with shaders, which I have none of. I simply have a wireframe test mesh currently. Could someone provide me a code snippet for this problem?
use glLoadMatrixf() if you are not using shaders, if you want just multiply current matrix use glMultMatrixf(), current matrix mode can switch use glMatrixMode(GL_PROJECTION or GL_MODELVIEW); for example(this is your code):
lm::mat4 ProjectionMatrix = getProjectionMatrix();
//setup projection matrix for opengl
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf(glm::value_ptr(ProjectionMatrix));
or:
glMultMatrixf(&ProjectionMatrix[0][0]);
EDIT:
if you want to apply transform to your model:(model_view are combined in fixed function)
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&viewMatrix[0][0]);
glMultMatrixf(&modelTransform[0][0]); //model * view
Draw_your_model();
you might need to set your transform like this :
glm::translate(modelTransform,-10,-10,-10); so your model will be at (10,10,10)
I don't know about using GLM, but I can help with the regular OpenGL part.
glUniformMatrix4fv updates a 4x4 uniform matrix at the location specified by MatrixID in a particular shader program.
I recommend working through Learning Modern 3D Graphics Programming, which is excellent as both a reference and guide.
For a discussion of how these uniforms are used within the GLSL shader program see:
Learning Modern 3D Graphics Programming - Chapter 3
Based at your code you should do the following :
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = inverse(getViewMatrix());//view(camera) must be inverse(if you don't already do it)
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, value_ptr(MVP));//use value_ptr method to pass matrix pointer
Also to set proper camera matrix I would suggest using lookAt() GLM build in method to calculate eye, dir ,up and compose those into final matrix for you.