I'm trying to draw in OpenGL 2 vectors with a given angle (in radians) between them, something like this:
I managed to draw the vectors but I'm not sure how to place them at the specific angle:
glBegin(GL_LINES); // Vx
glColor4f(1, .5, 0, 1);
glVertex3f(0, 0, 0);
glVertex3f(0, vectorYRScalingValue, 0); // vectorYRScalingValue is 5.0
glEnd();
glBegin(GL_LINES); // Vy
glColor4f(1, .5, 0, 1);
glVertex3f(0, 0, 0);
glVertex3f(0, vectorYRScalingValue, 0);
glEnd();
If β is the angle to be rotated in radians.
We rotate this vector anticlockwise around the origin.
float c = cos(β);
float s = sin(β);
NewX = x * c - y * s;
NewY = x * s + y * c;
I have a 2D transformation problem in OpenGL. My program draws two letters on screen and, by pressing assigned keys, letters have to move up (GLUT_KEY_UP) down (GLUT_KEY_DOWN) left (GLUT_KEY_LEFT) right (GLUT_KEY_RIGHT) and rotate CW (GLUT_KEY_HOME) and CCW (GLUT_KEY_END). (On keys GLUT_KEY_PAGE_UP and GLUT_KEY_PAGE_DOWN both letters rotate around their own centers simultaniously in oposite directions, pressing e.g. GLUT_KEY_UP after GLUT_KEY_PAGE_UP moves both letters in a correct direction).
I can't make the letters do the correct movement (up, down, left or right) after the objects had been rotated with GLUT_KEY_HOME or GLUT_KEY_END:
case GLUT_KEY_HOME: //rotate clockwise around the center of the model
glMatrixMode(GL_MODELVIEW);
setRotationMatrix(-angle, modelSizeX, modelSizeY);
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
display();
break;
Function that 'sets' the rotation matrix inserts angle and rotation point into Identity matrix [4x4]:
void setRotationMatrix(float theta, float x0, float y0)
{
theta = theta * (2 * acos(0.0)) / 180; // convert theta from degrees to radian
rotationMatrix[0] = cos(theta);
rotationMatrix[1] = sin(theta);
rotationMatrix[4] = -sin(theta);
rotationMatrix[5] = cos(theta);
rotationMatrix[12] = ((x0 * 0.5f) * (1 - cos(theta)) + (y0 * 0.5f) * sin(theta));
rotationMatrix[13] = ((y0 * 0.5f) * (1 - cos(theta)) - (x0 * 0.5f) * sin(theta));
}
After the objects have been rotated, if I press KEY_UP, they move not 'up' (in normal direction against x axis ) but in the direction normal to the horizontal plane of the object after rotation (slightly sideways).
case GLUT_KEY_UP:
glMatrixMode(GL_MODELVIEW);
glTranslated(0, delta, 0);
display();
break;
how do I make it move straightly to the 'north', meaning, not the 'north' of the object but the 'north' of my coordinate system?
#include <Windows.h>
#include <GL/glut.h>
#include <vector>
#include <fstream>
#include <cmath>
using namespace std;
#define EscKey 27
#define PlusKey 43
#define MinusKey 45
struct Point
{
int x, y;
};
double pi = 2 * acos(0.0);
void reshape(int w, int h);
void display();
void drawInitials();
void processNormalKeys(unsigned char key, int x, int y);
void processSpecialKeys(int key, int x, int y);
void setRotationMatrix(float theta, float x0, float y0);
void readFromFile();
void lineto(Point p);
void moveto(Point p);
void drawM();
void drawJ();
vector <Point> point;
vector <int> code;
Point currentPoint;
int modelSizeX = 202; int modelSizeY = 89;
int letterMSizeX = 107; int letterJSizeX = 78;
int delta = 5; // movement size
float zoomRate = 0.1; // scale-and-translate rate: 0.1 = resize by 10%
float angle = 1, rotaterR = 1 * pi / 180, rotater, angleCount = 0.0; // saved rotation angle
GLfloat modelviewStateMatrix[16];
int windowSizeX, windowSizeY;
boolean separate = false;
float rotationMatrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
float plusKeyMatrix[16] = { 1.0f + zoomRate, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f + zoomRate, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-(modelSizeX * zoomRate * 0.5f), -(modelSizeY * zoomRate * 0.5f), 0.0f, 1.0f };
float minusKeyMatrix[16] = { 1.0f - zoomRate, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f - zoomRate, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
modelSizeX * zoomRate * 0.5f, modelSizeY * zoomRate * 0.5f, 0.0f, 1.0f };
void readFromFile()
{
fstream f("initials_points_2.txt", ios::in);
int pointNumber;
Point p;
f >> pointNumber;
for (int i = 0; i < pointNumber;i++)
{
f >> p.x >> p.y;
point.push_back(p);
}
int movesNumber, m;
f >> movesNumber;
for (int i = 0; i < movesNumber; i++)
{
f >> m; code.push_back(m);
}
f.close();
}
void moveto(Point p)
{
currentPoint.x = p.x; currentPoint.y = p.y;
}
void lineto(Point p)
{
glBegin(GL_LINES);
glVertex2i(currentPoint.x, currentPoint.y);
glVertex2i(p.x, p.y);
glEnd();
currentPoint.x = p.x; currentPoint.y = p.y;
}
void setRotationMatrix(float theta, float x0, float y0)
{
theta = theta * (2 * acos(0.0)) / 180; // convert theta from degrees to radian
rotationMatrix[0] = cos(theta);
rotationMatrix[1] = sin(theta);
rotationMatrix[4] = -sin(theta);
rotationMatrix[5] = cos(theta);
rotationMatrix[12] = ((x0 * 0.5f) * (1 - cos(theta)) + (y0 * 0.5f) * sin(theta));
rotationMatrix[13] = ((y0 * 0.5f) * (1 - cos(theta)) - (x0 * 0.5f) * sin(theta));
}
void drawM()
{
int i = 1;
moveto(point[0]);
while (code[i] > 0 && i < code.size())
{
lineto(point[code[i] - 1]);
i++;
}
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(letterMSizeX, 0.0, 0.0);
glVertex3f(letterMSizeX, 0.0, 0.0);
glVertex3f(letterMSizeX, modelSizeY, 0.0);
glVertex3f(letterMSizeX, modelSizeY, 0.0);
glVertex3f(0.0, modelSizeY, 0.0);
glVertex3f(0.0, modelSizeY, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINES);
glVertex2i(0, 0); glVertex2i(letterMSizeX, modelSizeY);
glVertex2i(letterMSizeX, 0); glVertex2i(0, modelSizeY);
glEnd();
}
void drawJ()
{
glColor3f(1.0, 0.0, 0.0);
int i = 14;
moveto(point[-1 * (code[i]) - 1]);
i++;
while (i < code.size())
{
lineto(point[code[i] - 1]);
i++;
}
glBegin(GL_LINES);
glVertex3f((modelSizeX - letterJSizeX), 0.0, 0.0);
glVertex3f((modelSizeX - letterJSizeX), modelSizeY, 0.0);
glVertex3f((modelSizeX - letterJSizeX), modelSizeY, 0.0);
glVertex3f(modelSizeX, modelSizeY, 0.0);
glVertex3f(modelSizeX, modelSizeY, 0.0);
glVertex3f(modelSizeX, 0.0, 0.0);
glVertex3f(modelSizeX, 0.0, 0.0);
glVertex3f((modelSizeX - letterJSizeX), 0.0, 0.0);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINES);
glVertex2i(letterMSizeX + 17, 0); glVertex2i(modelSizeX, modelSizeY);
glVertex2i(letterMSizeX + 17, modelSizeY); glVertex2i(modelSizeX, 0);
glEnd();
}
void drawInitials()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
setRotationMatrix(-rotater, letterMSizeX, modelSizeY);
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
drawM();
glTranslatef(-letterMSizeX * 0.5, -modelSizeY * 0.5, 0);
glPopMatrix();
glPushMatrix();
glTranslatef((modelSizeX - letterJSizeX), 0, 0);
setRotationMatrix(rotater, letterJSizeX, modelSizeY);
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
glTranslatef(-(modelSizeX - letterJSizeX), 0, 0);
drawJ();
glPopMatrix();
}
void processNormalKeys(unsigned char key, int x, int y)
{
switch (key)
{
case EscKey:
exit(0);
break;
case PlusKey: // "zoom in"
glMatrixMode(GL_MODELVIEW);
glMultMatrixf(plusKeyMatrix); // multiply current Modelview Matrix by scale-and-translate matrix
display();
break;
case MinusKey: // "zoom out"
glMatrixMode(GL_MODELVIEW);
glMultMatrixf(minusKeyMatrix); // multiply current Modelview Matrix by scale-and-translate matrix
display();
break;
}
}
void processSpecialKeys(int key, int x, int y) {
switch (key) {
case GLUT_KEY_UP:
glMatrixMode(GL_MODELVIEW);
glTranslated(0, delta, 0);
display();
break;
case GLUT_KEY_DOWN:
glMatrixMode(GL_MODELVIEW);
glTranslated(0, -delta, 0);
display();
break;
case GLUT_KEY_LEFT:
glMatrixMode(GL_MODELVIEW);
glTranslated(-delta, 0, 0);
display();
break;
case GLUT_KEY_RIGHT:
glMatrixMode(GL_MODELVIEW);
glTranslated(delta, 0, 0);
display();
break;
case GLUT_KEY_HOME: //rotate clockwise around the center of the model
glMatrixMode(GL_MODELVIEW);
setRotationMatrix(-angle, modelSizeX, modelSizeY);
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
display();
break;
case GLUT_KEY_END: //rotate counterclockwise around the center of the model
glMatrixMode(GL_MODELVIEW);
setRotationMatrix(angle, modelSizeX, modelSizeY);
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
display();
break;
case GLUT_KEY_PAGE_UP:
rotater -= rotaterR;
if (rotater <= -2 * pi)
rotater += 2 * pi;
display();
break;
case GLUT_KEY_PAGE_DOWN:
rotater += rotaterR;
if (rotater >= 2 * pi)
rotater -= 2 * pi;
display();
break;
}
}
int main(int argc, char* argv[])
{
currentPoint.x = 0; currentPoint.y = 0;
readFromFile();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutInitWindowPosition(100, 150);
glutCreateWindow("OpenGL lab");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(processSpecialKeys);
glutMainLoop();
return 0;
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
windowSizeX = w;
windowSizeY = h;
gluOrtho2D(-modelSizeX, modelSizeX * 2, -modelSizeY, modelSizeY * 2); // World size
}
void display()
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINES);
glVertex2i(-windowSizeX, 0); glVertex2i(windowSizeX, 0);
glVertex2i(0, -windowSizeY); glVertex2i(0, windowSizeY);
glEnd();
glPopMatrix();
glColor3d(1, 0, 0);
drawInitials();
glPointSize(5);
glBegin(GL_POINTS);
glVertex3f(modelSizeX * 0.5, modelSizeY * 0.5, 0.0);
glVertex3f(letterMSizeX * 0.5, modelSizeY * 0.5, 0.0);
glVertex3f(letterJSizeX * 0.5 + letterMSizeX + 17, modelSizeY * 0.5, 0.0);
glEnd();
glFlush();
}
vertices file: initials_points_2.txt
I was trying to:
encapsulate _HOME/_END rotation with glPushMatrix()/glPopMatrix()
revert the rotation after the drawal of the object by multiplying MODELVIEW matrix with (-angle, same point)
was trying to drop glMultMatrix() and use glTranslate(), glRotate()
none of them had worked as I intended
Consider the following steps:
At first, rotate the object on the object coordinate system.
Next, place the object into the space (coordinate system) that you are considering the directions {up, down, left, and right} in.
i.e. for first rotation, the center must be the value in the object coordinate system. For example, object coordinate system is often defined as the origin equals to the center of object. In this case, rotation center is (0,0,0).
glPushMatrix();
//2nd step : Place the object
glTranslatef( ... );
//1st step : rotate the object
glRotatef( ... );
//object draw code
//(all vertex value is in the object coordinate system)
glPopMatrix();
I found out what I was doing wrong: buttons GLUT_KEY_HOME/GLUT_KEY_END should be performing rotations similar to those of GLUT_KEY_PAGE_UP/GLUT_KEY_PAGE_DOWN:
increase current rotation angle for the whole model (new variable to save rotation angle around the middle of the model);
call display method();
Then, inside display() method:
push current matrix into stack;
rotate model by the angle;
another push matrix into stack
rotate letters by the rotater variable changed in PAGE_UP/PAGE_DOWN
draw letters
pop matrix
pop matrix;
Code on keys:
case GLUT_KEY_HOME: //rotate clockwise around the center of the model
glMatrixMode(GL_MODELVIEW);
angle -= rotationRate;
if (angle <= -2 * pi)
angle += 2 * pi;
display();
break;
case GLUT_KEY_END: //rotate counterclockwise around the center of the model
glMatrixMode(GL_MODELVIEW);
angle += rotationRate;
if (angle >= 2 * pi)
angle -= 2 * pi;
display();
break;
edited drawInitials() method (called from display() method):
void drawInitials()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
setRotationMatrix(angle, modelSizeX, modelSizeY); //set rotation matrix to rotate around the center of the model by current angle
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
glPushMatrix();
setRotationMatrix(-rotater, letterMSizeX, modelSizeY); //set to rotate around the center of the letter M by current rotater Clockwise
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
drawM();
glPopMatrix();
glPushMatrix();
glTranslatef((modelSizeX - letterJSizeX), 0, 0); // move OX axis by the size of letter M + space between the letters
setRotationMatrix(rotater, letterJSizeX, modelSizeY);//set to rotate around the center of the letter J by current rotater Counter Clockwise
glMultMatrixf(rotationMatrix); // multiply current Modelview Matrix by rotate-and-translate matrix
glTranslatef(-(modelSizeX - letterJSizeX), 0, 0); // return OX axis to its previous place
drawJ();
glPopMatrix();
glPopMatrix();
}
In setRotationMatrix() remove conversion into radian;
Add new variable rotationRate to use it as an incriment for both rotations:
float angle;
// saved rotation angle around center of the model (radian)
float rotater;
// rotater - saved rotation angle around center of the letter (radian)
float rotationRate = 1 * pi / 180; // rotation rate (radian), ex rotaterR
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'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 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.