I am having trouble rotating an ellipse in OpenGL. So, I have some code to draw an ellipse as follows:
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
glPushMatrix();
glTranslatef(0, 0, 0); // ellipse centre
glBegin(GL_LINE_LOOP);
float inc = (float) M_PI / 500.0;
for (GLfloat i = 0; i < M_PI * 2; i+=inc)
{
float x = cos(i) * 0.4;
float y = sin(i) * 0.4;
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glPopAttrib();
This produces a picture as so:
Now what I want to do is rotate this ellipse clockwise. So I added a glrotate in between but the result was not what I had expected.
So, I did something like:
glPushAttrib(GL_CURRENT_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glLineWidth(2.0);
glPushMatrix();
glTranslatef(0, 0, 0);
glRotatef(-90, 1, 1, 0);
glBegin(GL_LINE_LOOP);
float inc = (float) M_PI / 500.0;
for (GLfloat i = 0; i < M_PI * 2; i+=inc)
{
float x = cos(i) * 0.4;
float y = sin(i) * 0.4;
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glPopAttrib();
This produced an image which was simply collapsed. What I wanted to do was rotate the ellipse along its center by the specified degrees. Also, I tried playing around with the various parameters of glRotatef but could not get it do as I expected. The resulting image looks like:
You're working in the XY plane, so you can't really rotate around a vector in XY. Instead, you want to rotate along the unit Z axis (glRotate (angle, 0, 0, 1);). Imagine your screen being the XY coordinate system and the Z axis pointing inwards. What you want is to rotate around the Z axis, so your XY plane remains in the XY plane.
Related
I'm trying to draw these shaped bellow this this:
What I want
Tried this code:
glLoadIdentity();
glColor3f(0.98f, 0.83f, 0.73f);
glBegin(GL_POLYGON);
for (float i = 0; i <= (2 * p); i += 0.001) {
x = 100 * cos(i)-10;
y = 115 * sin(i)+270;
glVertex2f(x, y);
}
glEnd();
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) - 10;
y = 115 * sin(i) + 270;
glVertex2f(x, y);
}
But this is what I get:
What I get
If I want to only use the glLoadIdentity and glRotatef for rotation, do you have any idea about how to fix it?
Note:
I don't want to use push/pop or translation
You have to rotate the object around its center and move the rotated object to its position in the world. glRotatef rotates the vertices around (0, 0). Draw the object around (0, 0) and glTranslate to move the object to its position in the world:
glTranslate(-10.0f, 270.0f, 0.0f);
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i);
y = 115 * sin(i);
glVertex2f(x, y);
}
Note, the matrix operations like glRotate and glTranslate specify a new matrix and multiply the current matrix by the new matrix.
If you are not allowed to use glTranslate, you have to rotate the translation vector (-10, 270) in the opposite direction. Use the trigonometric functions sin an cos to rotate the vector (see Rotation matrix). You need to invert the angle and convert it to Radians since the unit of sin and cos is Radian.
float tx = -10.0f;
float ty = 270.0f;
float angle = -135.0f;
float inv_angle_rad = -angle * M_PI / 180.0f;
float tx_rot = tx * cos(inv_angle_rad) - ty * sin(inv_angle_rad);
float ty_rot = tx * sin(inv_angle_rad) + ty * cos(inv_angle_rad);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) + tx_rot;
y = 115 * sin(i) + ty_rot;
glVertex2f(x, y);
}
I am trying to draw an arrow using the style below but this arrow should be also rotated according to a condition (need to pass the degree for each condition). I can draw the rectangle and a triangle but I cannot draw the triangle as an arrowhead. Also, how can I include the rotation degree into the code? Is there any easier way to draw an arrow and rotate it?
int triangleRect=4, triangleTri=3, lineWidth=3;
double twicePi = 2.0f * M_PI, angle_offsetR =1.5* M_PI/2, radius = 0.05,
xR=m_start.x(), y=m_start.y(), xT=m_start.x()+ m_rect_width;
glColor3f(0,1,0);
glLineWidth(lineWidth);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_TRIANGLE_FAN);
//RECTANGLE
for(int i = 0; i <= triangleRect; i++) {
glVertex2f((xR + (radius * cos(i * twicePi / triangleRect + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleRect + angle_offsetR)))* m_parent_height_function());
}
// TRIANGLE
for(int i = 0; i <= triangleTri; i++) {
glVertex2f((xT + (radius * cos(i * twicePi / triangleTri + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleTri + angle_offsetR)))* m_parent_height_function());
}
glEnd();
You accidentally add angle_offsetR to the angle for the triangle vectors. Furthermore you've to restart a GL_TRIANGLE_FAN primitiv when you draw an new shape (see Triangle primitives).
If you want to rotate the model, then set the add a rotation around the z axis to the model view matrix by glRotatef.
Do not translate and scale the vertex coordinates. Use glScale and glTranslate. The matrix transformations are not commutative, the order matters:
float angle_of_roation = 30.0; // 30°
glPushMatrix();
// scale
glScalef( m_parent_width_function(), m_parent_height_function(), 1.0f);
// move triangle and rectangle to the position in the world
glTranslatef(xR, y, 0.0f);
// roatate triangle and rectangle
glRotatef(angle_of_roation, 0, 0, 1);
//RECTANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleRect; i++) {
float angle = i * twicePi / triangleRect + angle_offsetR;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPushMatrix();
// translate triangle relative to rectangle
glTranslatef(xT-xR, 0.0f, 0.0f);
// TRIANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleTri; i++) {
float angle = i * twicePi / triangleTri;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPopMatrix();
glPopMatrix();
i want to move an object along a path (sine wave), lets suppose object is a roller coaster.
it moves through translate but my problem is that i also want to rotate that object according to the path.
i tried this code before translate but its not working.
if (x = -4.8)
{
glRotatef(89, 1, 1, 0);
}
my code with only translation looks like this.
i want to add rotation here along sine waves
void object()
{ glPushMatrix();
glTranslatef(x, y, 0);
glColor3f(0.0f, 0.0f, 0.0f);//Set drawing color
glBegin(GL_QUADS);
glVertex2f(-0.3, 0.1);
glVertex2f(0.3, 0.1);
glVertex2f(0.3, -0.1);
glVertex2f(-0.3, -0.1);
glEnd();
glFlush();
glPopMatrix();
glFlush();
}
void drawsine()
{
glBegin(GL_LINE_STRIP);//Primitive
glColor3f(255, 0, 0);//Set drawing color
int i = 0;
float x = 0, y = 0;
for (x = -5; x < 6; x = x + 0.1)
{
y = (sin(3.142*x)) / 3.142*x;
glVertex2f(x, y);
//int j= 0;
sinex[i] = x;
siney[i] = y;
i++;
}
glEnd();
glFlush();
}
The angle of rotation depends on the direction vector along the sine wave.
The direction vector can be calculated by the subtraction of 2 positions. Subtract the position before the current position from the positions after the current position, to calcaulte the direction vector. In the following i is the current position of the object:
dx = sinex[i+1] - sinex[i-1];
dy = siney[i+1] - siney[i-1];
The angle of rotation can be calculated by the arcus tangent using atan2, which returns an angle in radians:
float ang_rad = atan2( dy, dx );
Since the angle has to be passed to glRotatef in degrees, the angle has to be converted from radians to degrees, before a rotation around the z axis can be performed.
A full circle in has 360 degrees or 2*Pi radians. So the scale from radians to degrees 180/Pi:
float ang_deg = ang_rad * 180.0f / M_PI;
glRotatef( ang_deg, 0, 0, 1 );
The following cde snippet show how to apply the code. Be aware that there is no bounds check. This means i has to be grater or equal 1 and less than the number of points - 1 (1 <= i < 110):
#define _USE_MATH_DEFINES
#include <math.h>
{
// [...]
drawsine();
x = sinex[i];
y = siney[i];
dx = sinex[i+1] - sinex[i-1];
dy = siney[i+1] - siney[i-1];
object();
// [...]
}
void object()
{
glPushMatrix();
glTranslatef(x, y, 0);
float ang_rad = atan2( dy, dx );
float ang_deg = ang_rad * 180.0f / M_PI;
glRotatef( ang_deg, 0, 0, 1 );
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(-0.3, 0.1);
glVertex2f(0.3, 0.1);
glVertex2f(0.3, -0.1);
glVertex2f(-0.3, -0.1);
glEnd();
glPopMatrix();
}
I'm writing a simple demo with the fixed pipeline mode in OpenGL
First I write some codes that will draw a rectangle, with top-left point (x1,y1), and buttom-right point (x2,y2)
// Drawing here
glPushMatrix();
// Perform rotation first
glTranslatef(x_cent, y_cent, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, 1.0f);
// Set origin back to the screen center with the rotation set above
glTranslatef(-x_cent, -y_cent, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_QUADS);
{
glVertex2f(x1, y2);
glVertex2f(x2, y2);
glVertex2f(x2, y1);
glVertex2f(x1, y1);
}
glEnd();
// End of drawing
glPopMatrix();
After I tweak the value of the angle with arrow keys, say 45 degrees counter-clockwise, and now the rectangle will rotate 45 degrees counter-clockwise. Then I translate it with arrow keys, it moves in the direction of up, down, left, and right. Everything works fine.
So I write anoter part of code that will draw a general polygon. It's similar to the code above. I simply draw lines between each pair of points
for (int i = 0; i < p_size; i++)
{
float x1 = point[i].x, x2 = point[(i + 1) % p_size].x;
float y1 = point[i].y, y2 = point[(i + 1) % p_size].y;
x1 = ((x1 + 0.5f) / winWidth) * 2.0f - 1.0f;
x2 = ((x2 + 0.5f) / winWidth) * 2.0f - 1.0f;
y1 = ((-y1 + 0.5f) / winHeight) * 2.0f + 1.0f;
y2 = ((-y2 + 0.5f) / winHeight) * 2.0f + 1.0f;
// Set the curent coord origin to this poly's center
float x_cent = (left + right) / 2.0, y_cent = (top + down) / 2.0;
float ratio = winWidth / winHeight;
if (ratio > 1)
{
x1 *= ratio;
x2 *= ratio;
}
else //if (ratio < 1)
{
y1 /= ratio;
y2 /= ratio;
}
// Drawing here
glPushMatrix();
// Perform rotation first
glTranslatef(x_cent, y_cent, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, 1.0f);
// Set origin back to the screen center with the rotation set above
glTranslatef(-x_cent, -y_cent, 0.0f);
glBegin(GL_LINES);
{
glVertex2f(x1, y1);
glVertex2f(x2, y2);
}
glEnd();
// End of drawing
glPopMatrix();
}
I rotate the polygon with arrow keys, that works fine, say also 45 degrees counter-clockwise. But after the rotation, when I translate it with up key, it moves not up but in the direction of 45 degrees.
Bbut why can the rectangle translate normally in the 4 directions after rotation? These two part of codes are almost the same, why is this happening...
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.