glm rotation in ortho space - c++

I set up my ortho projection like this :
transform = glm::ortho(0.0f, width, height, 0.0f);
this works pretty well, but when I want to use the glm::rotate function like this:
transform = glm::rotate(transform, glm::radians(45.0f), glm::vec3(0, 0, 1));
my object rotates around 0 : 0 : 0.
my vertices look like this:
GLfloat vertices[] = {
600, 100, 0,
612, 100, 0,
612, 130, 0,
600, 130, 0
};
how can I make my object rotate around its center ?

If you want to rotate around its center you have to:
Translate the object so that the center of the object is moved to (0, 0).
Rotate the object.
Move the object so that the center point moves in its original position.
GLfloat center_x = 606.0f;
GLfloat center_y = 115.0f;
transform = glm::translate(transform, glm::vec3(center_x, center_y, 0));
transform = glm::rotate(transform, glm::radians(45.0f), glm::vec3(0, 0, 1));
transform = glm::translate(transform, glm::vec3(-center_x, -center_y, 0));
See also How to use Pivot Point in Transformations

Related

Rotation in OpenGL has different effect each time

I am trying to learn OpenGL by coding some stuff, but am still not able to understand the concept of rotation.
Here is my code:
glm::mat4 projection1 = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view1 =camera.GetViewMatrix();//// //
ourShader.setMat4("projection", projection1);
ourShader.setMat4("view", view1);
ourShader.setInt ("pass1",1);
glm::mat4 model1 = glm::mat4(1.0f);
vangle+=0.1;
float cvangle = (vangle-90)*PI /180;
model1=glm::translate (model1 ,glm::vec3(cos(cvangle )*50,0,sin(cvangle )*50));
model1 = glm::scale(model1, glm::vec3(1,1, 1));
model1 = glm::rotate(model1,3.0f , glm::vec3(1, 0, 0));
model1 = glm::rotate(model1,2.0f, glm::vec3(0, 1, 0));
ourShader.setMat4("model", model1);
ourModel.Draw(ourShader);
The helicopter should rotate around the camera, but my problem is that the rotation has a different effect in each angle, i.e. at angle 0, it looks like this:
while at angle 90, it looks like this:
My goal is to rotate the helicopter around the camera showing always the same side.
Any help is appreciated.
If you want to rotate an object in place, then you've to dot the rotation before the translation:
model = translate * rotate;
If you want to rotate around a point, then you've to translate the object (by the rotation radius) and then rotate the translated object:
model = rotate * translate
Note, the operations like rotate, scale and translate, define a new matrix and multiply the input matrix by the new matrix.
So In your case the translate has to be done after a rotation (rotate) around the z axis:
vangle+=0.1;
glm::mat4 model1 = glm::mat4(1.0f);
model1 = glm::rotate(model1, glm::radians(vangle), glm::vec3(0, 0, 1));
model1 = glm::translate(model1, glm::vec3(50.0f, 0.0f, 0.0f);
model1 = glm::scale(model1, glm::vec3(1, 1, 1));

How to rotate camera view with glm?

I'm trying to rotate my camera with the purpose of see an object rotating around my cam with a rotation Matrix that I develop the problem is that it doesn't works.
So I try with the glm::rotation matrix and put the values
m_View = glm::rotate(m_View, a * glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f))
but it does not works either:
void CCam::setView()
{
Front = glm::normalize(Eye - At);
Right = glm::normalize(glm::cross(Up, Front));
up = glm::cross(Front, Right); // Up Verdadero
m_View = glm::lookAt(
Eye, // Camera Position
(Eye + Front), // Where the camera looks
up // This is another way to say camera is not rotated
);
newAt = glm::vec4(At, 1.0f);
//m_View = m_View * GLMatrixRotationY(a);
m_View = glm::rotate(m_View, a * glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
glm::mat4 CCam::GLMatrixRotationX(float Angle)
{
matrizRotacionX = glm::mat4(
1, 0, 0, 0,
0, cos(Angle), -sin(Angle), 0,
0, sin(Angle), cos(Angle), 0,
0, 0, 0, 1
);
return matrizRotacionX;
}
I expect to see my mesh rotating around the camera but I only got the cam rotating around the mesh.

How to decrease first person shooting camera object in OpenGL

I am making 3d open gl project which contain camera object as a shooting bullet but it is render with very big size and contain whole screen in white lines like this
i want to display object as a center of camera with small size how to do this
code is here
static GLdouble ort1[] = { -200, 200, -33, 140 };
static GLdouble viewer[] = { 525, 25, -180 };
static GLdouble up[] = { 0, 1, 0 };
static GLdouble objec[] = { 525.0, 25, -350 };
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(viewer[0], viewer[1], viewer[2], objec[0], objec[1], objec[2], 0, 1, 0);
glMatrixMode(GL_PROJECTION);
//glOrtho(-1, 1, -1, 1, -1, 100);
glLoadIdentity();
//gluPerspective(fov, 1.333, n, f);
gluPerspective(fov, 1, 0.001, 1000);
//gluPerspective(50, screenWidth / screenHeight, 0.000001, 2000);
glPointSize(2.0);
glMatrixMode(GL_MODELVIEW);
//cube.drawFace(10, 20, 10, 22);
drawFlorr();
glPushMatrix();
glTranslatef(viewer[0], viewer[1], viewer[2]); // Translation to the camera center
glRotatef(camAngle * 57.2957795, 0, 1, 0); // Rotate to correspond to the camera
//glTranslatef(0.016, 0, -0.05); // Offset to draw the object
glutWireCone(0.005, 1, 20, 20);
glPopMatrix();
i am new in game prgramming and stuck in this problem ?
You're not setting up the projection matrix correctly.
You need to set the mode to GL_PROJECTION, then set the projection matrix to look at the target (shooter's object of attention) and have a perspective correct with right field of view.
Then set the modelview matrix, mode GL_MODELVIEW.
The gun sight needs to be placed so that it is looking at the camera, and the camera is looking at it. So on the line between the shooter's eyes and his object of attention, perpendicular to it. Do this in the modelview matrix, and call gluLookAt again, on the model.
(Ultimately projection and modelview get multiplied, but Open GL handles that for you).

How to rotate an object using glm::lookAt()?

I'm working on a scenario that involves some cone meshes that are to be used as spot lights in a deferred renderer. I need to scale, rotate and translate these cone meshes so that they point in the correct direction. According to one of my lecturers I can rotate the cones to align with a direction vector and move them to the correct position by multiplying its model matrix with the matrix returned by this,
glm::inverse(glm::lookAt(spot_light_direction, spot_light_position, up));
however this doesn't seem to work, doing this causes all of the cones to be placed on the world origin. If I then translate the cones manually using another matrix it seems that the cones aren't even facing the right direction.
Is there a better way to rotate objects so that they face a specific direction?
Here is my current code that gets executed for each cone,
//Move the cone to the correct place
glm::mat4 model = glm::mat4(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
spot_light_position.x, spot_light_position.y, spot_light_position.z, 1);
// Calculate rotation matrix
model *= glm::inverse(glm::lookAt(spot_light_direction, spot_light_position, up));
float missing_angle = 180 - (spot_light_angle / 2 + 90);
float scale = (spot_light_range * sin(missing_angle)) / sin(spot_light_angle / 2);
// Scale the cone to the correct dimensions
model *= glm::mat4(scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, spot_light_range, 0,
0, 0, 0, 1);
// The origin of the cones is at the flat end, offset their position so that they rotate around the point.
model *= glm::mat4(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, -1, 1);
I've noted this in the comments but I'll mention again that the cones origin is at center of the flat end of the cone, I don't know if this makes a difference or not, I just thought I'd bring it up.
Your order of the matrices seems correct, but the lookAt function expects:
glm::mat4 lookAt ( glm::vec3 eye, glm::vec3 center, glm::vec3 up )
Here eye is the location of the camera, center is the location of the object you are looking at (in your case if you dont have that location, you can use
spot_light_direction + spot_light_position ).
so just change
glm::lookAt(spot_light_direction, spot_light_position, up)
to
glm::lookAt(spot_light_position, spot_light_direction + spot_light_position, up)

Apply transformations to Bounding Box

I am trying to make a tank game. I have successfully loaded an OBJ model, and calculated its bounding box for the model at the origin.
I am now trying to apply the transformations done to my model in the game logic to the original coordinates for the bounding box. For this, I grab the modelview matrix right before drawing my model, then multiply this matrix for the two vectors that define the BBox.
Here is the code that draws my tank:
void drawTank()
{
bBox = calcBBox(modelo, 1);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texTank);
glScalef(0.2, 0.2, 0.2);
glTranslatef(posTank.x,posTank.y,posTank.z);
glRotatef(anguloTanque, 0, 1, 0); // rotate around Y (horizontal)
glRotatef(90, 0, 1, 0);
glRotatef(-90, 1, 0, 0);
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
glmDraw(modelo, GLM_TEXTURE | GLM_MATERIAL);
glColor3f(1,0,0);
drawBBox(bBox);
glPopMatrix();
}
With this snippet, my bbox is properly drawn over the tank model (transformations are applied in rendering by the glTranslate & glRotate functions). As you can see I also grab here my ModelView matrix.
Then I apply this matrix as follows (this is my entire display function):
void Display(void) {
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
camera();
glEnable(GL_TEXTURE_2D);
//glTranslatef(0,-40,150);
//PLANE
glBindTexture(GL_TEXTURE_2D, texArena);
glBegin(GL_POLYGON);
glTexCoord2f( 0.0f, 0.0f );
glVertex3f(-500, 0, -500);
glTexCoord2f( 5.0f, 5.0f );
glVertex3f(500, 0, -500);
glTexCoord2f(5.0f, 0.0f );
glVertex3f(500, 0, 500);
glTexCoord2f( 0.0f, 5.0f );
glVertex3f(-500, 0, 500);
glEnd();
drawTank();
glPopMatrix();
point3D max = bBox.max;
point3D min = bBox.min;
point3D resultMax;
point3D resultMin;
//Transformacion
multVectorByMatrix(matrix, max, resultMax);
multVectorByMatrix(matrix, min, resultMin);
bBox.max.x = resultMax.x; bBox.max.y = resultMax.y; bBox.max.z = resultMax.z;
bBox.min.x = resultMin.x; bBox.min.y = resultMin.y; bBox.min.z = resultMin.z;
glPushMatrix();
glColor3f(1,1,1);
drawBBox(bBox);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
The function that multiplies a vector by a matrix:
void multVectorByMatrix(float* matrix, point3D vector, point3D &result)
{
result.x = (matrix[0] * vector.x) +
(matrix[4] * vector.y) +
(matrix[8] * vector.z) +
matrix[12];
result.y = (matrix[1] * vector.x) +
(matrix[5] * vector.y) +
(matrix[9] * vector.z) +
matrix[13];
result.z = (matrix[2] * vector.x) +
(matrix[6] * vector.y) +
(matrix[10] * vector.z) +
matrix[14];
}
If I draw the bounding box with this render loop, then my bounding box gets drawn but transformations are not applied properly. I can see the bounding box moving correctly with translations, but rotations are not done right.
What might be the problem here?
edit: some screenshots
Your problem is in this code.
point3D max = bBox.max;
point3D min = bBox.min;
point3D resultMax;
point3D resultMin;
//Transformacion
multVectorByMatrix(matrix, max, resultMax);
multVectorByMatrix(matrix, min, resultMin);
bBox.max.x = resultMax.x; bBox.max.y = resultMax.y; bBox.max.z = resultMax.z;
bBox.min.x = resultMin.x; bBox.min.y = resultMin.y; bBox.min.z = resultMin.z;
glPushMatrix();
glColor3f(1,1,1);
drawBBox(bBox);
glPopMatrix();
You take two vertices from your box and then apply transformations to them, then you use this transformed vertices to display a box, which of course will be axis aligned, because that's the only box you can get from just two opposite vertices. And you can see on your screenshot, that you bbox and the correct bbox have common vertices - these are exactly the vertices you applied your transformations to. So, in order to get a correct bbox, you need to get all vertices of the bbox and apply these transformations to all of them. Then you'll get exactly what you want.