Related
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 have this weird problem in which the object that I'm trying to rotate just suddenly disappears. The way I am looking to rotate the object is with a keypress, which turns a global variable rotateAnimation to true. When the variable rotateAnimation is false, the object is visible, but once it's true the object disappears.
Here is the code:
bool rotateAnimation = false;
bool moveAnimation = false;
int moveDirX = 1, moveDirY = 1;
void DrawSpiral(int x, int y)
{
float tx, ty;
float i;
float a = 0, b = 0;
glPointSize(3);
glBegin(GL_LINE_STRIP);
for (i = 0; i < 20; i = i + 0.025)
{
a = a + .05;
b = b + .05;
tx = x + b * cos(i);
ty = y + a * sin(i);
glVertex2f(tx, ty);
}
glEnd();
}
void DrawSquare(int x, int y, int size)
{
glBegin(GL_POLYGON);
glVertex2f(x, y);
glVertex2f(x - size, y);
glVertex2f(x - size, y - size);
glVertex2f(x, y - size);
glEnd();
}
void DrawPolygon(int x, int y)
{
glBegin(GL_POLYGON);
glVertex2f(x, y);
glVertex2f(x - 25, y - 25);
glVertex2f(x - 15, y - 53);
glVertex2f(x + 15, y - 53);
glVertex2f(x + 25, y - 25);
glEnd();
}
void init()
{
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION); // Since I want to do rotation in 2D
glLoadIdentity();
glClearColor(1.0, 1.0, 1.0, 0);
glColor3f(0.0f, 0.0f, 0.0f);
gluOrtho2D(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT);
}
void Keypress(int key, int x, int y)
{
switch (key)
{
case 'm':
moveAnimation = !moveAnimation;
break;
case 'o':
rotateAnimation = !rotateAnimation;
break;
}
}
void Display()
{
glClear(GL_COLOR_BUFFER_BIT);
staticScene(); // Some other drawings that should always be there on the screen
glPushMatrix();
if (rotateAnimation)
{
glRotatef(60, 1.0, 0.0, 0.0);
}
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(2);
if (shape == "square")
DrawSquare(X, Y, 40);
else if (shape == "polygon")
DrawPolygon(X, Y);
else if (shape == "spiral")
DrawSpiral(X, Y);
glPopMatrix();
glutSwapBuffers();
}
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(1000 / 60, timer, 0);
if (moveAnimation)
{
int dx = 2, dy = 2;
if (X - dx < 0) // Add from X
X += dx, moveDirX = 1;
else if (X + dx > drawingWindow[0].first) // Subtract to X
X -= dx, moveDirX = -1;
else
X += (dx * moveDirX);
if (Y - dy < drawingWindow[2].second) // Add from Y
Y += dy, moveDirY = 1;
else if (Y + dy > drawingWindow[0].second) // Subtract to Y
Y -= dy, moveDirY = -1;
else
Y += (dy * moveDirY);
}
}
When rotateAnimation is false:
When rotateAnimation is true:
EDIT: I tried to scale the object too, but the same thing happens, when the toggle is on the object disappears, and when off it appears. One thing I noted is that when I comment out the TimerFunc then nothing happens. Neither does the object scale or rotate depending on what is toggled on.
Edited: You didn't switch the matrix mode to GL_MODELVIEW.
void init()
{
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION); // Since I want to do rotation in 2D
glLoadIdentity();
glClearColor(1.0, 1.0, 1.0, 0);
glColor3f(0.0f, 0.0f, 0.0f);
gluOrtho2D(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT);
glMatrixMode(GL_MODELVIEW); //<--here
}
NOTE I know that my plane and the cylinder are badly built but their purpose is just to have something to see on the screen. Considering (px,py,pz), the camera position, and (dx, dy, dz), the view direction.
Important: My camera should follow a structure similar to the one I implemented here, so I can't use glRotate, glTranslate everything has to be done manually, the imposition of my teacher sadly, And also I am using Visual Studio.
FIX: My translations are all ok now I fixed a thing in the case GLUT_KEY_LEFT and GLUT_KEY_RIGTH.
Problem: Now the remaning problem is in the mouse_motion, when I click with left mouse button and drag the mouse around the screen my camera changes it direction really fast and sometimes when I go up it faces down its strange and hard to describe XD.
Warning: Warning C26451 Arithmetic overflow: Using operator '+' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '+' to avoid overflow (io.2). class2 main.cpp 199 .
This is my the line that says gluLookAt(px, py, pz, px+dx, py+dy, pz+dz, 0.0f, 1.0f, 0.0f); How can I fix it?
Camera: I just want the motion of the mouse to allow me to define the direction I want to go and use the up, down, left, right keys to move.
#include <math.h>
#include <ctime>
#include <iostream>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#define PI 3.1415926535897932384626433832795
//For Camera
#define GlUT_KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
// angle of rotation for the camera direction
float angle = 0.0f; //alpha
float angle1 = 0.0f; //beta
// actual vector representing the camera's direction
float dx = 0.0f;
float dy = 0.0f;
float dz = 1.0f;
// XZ position of the camera
float px = 0.0f;
float py = 0.0f;
float pz = 10.0f;
float speed = 1.0f;
float rotateSpeed = 0.0008f;
//For FPS
int timebase;
float frame;
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window with zero width).
if(h == 0)
h = 1;
// compute window's aspect ratio
float ratio = w * 1.0 / h;
// Set the projection matrix as current
glMatrixMode(GL_PROJECTION);
// Load Identity Matrix
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set perspective
gluPerspective(45.0f ,ratio, 1.0f ,1000.0f);
// return to the model view matrix mode
glMatrixMode(GL_MODELVIEW);
}
// Draw Figures
void drawAxis() {
glBegin(GL_LINES);
// X axis in Red
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(100.0f, 0.0f, 0.0f);
glVertex3f(-100.0f, 0.0f, 0.0f);
// Y Axis in Green
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 100.0f, 0.0f);
glVertex3f(0.0f, -100.0f, 0.0f);
// Z Axis in Blue
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 100.0f);
glVertex3f(0.0f, 0.0f, -100.0f);
glEnd();
}
void drawPlane(float width) {
width/=2;
glBegin(GL_TRIANGLE_FAN);
glColor3f(4.0f, 1.0f, 1.0f);
glVertex3d(width, 0,width);
glVertex3d(width, 0, -width);
glVertex3d(-width, 0,-width);
glColor3f(3.0f, 1.0f, 0.0f);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, -width);
glVertex3d(-width, 0, width);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3d(width, 0, -width);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, -width);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3d(-width, 0, -width);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, width);
glEnd();
}
void drawCylinder(float radius, float height, int slices) {
float interval = 2 * PI / slices;
float next_a, next_h;
for (float a = 0; a < 2 * PI; a += interval) {
next_a = a + interval;
if (next_a > 2 * PI) {
next_a = 2 * PI;
}
glBegin(GL_TRIANGLES);
//Top
glColor3f(0.698f, 0.133f, 0.133f);
glVertex3f(0.0f, height / 2, 0.0f);
glVertex3f(radius * sin(a), height / 2, radius * cos(a));
glVertex3f(radius * sin(next_a), height / 2, radius * cos(next_a));
//Bottom
glColor3f(0.698f, 0.133f, 0.133f);
glVertex3f(0.0f, -height / 2, 0.0f);
glVertex3f(radius * sin(next_a), -height / 2, radius * cos(next_a));
glVertex3f(radius * sin(a), -height / 2, radius * cos(a));
for (float h = -height / 2; h < height / 2; h += height) {
next_h = h + height;
if (next_h > height / 2) {
next_h = height / 2;
}
//Walls
glColor3f(1.0f, 0.271f, 0.0f);
glVertex3f(radius * sin(next_a), next_h, radius * cos(next_a));
glVertex3f(radius * sin(a), next_h, radius * cos(a));
glVertex3f(radius * sin(next_a), h, radius * cos(next_a));
glColor3f((a + 0.05) / (2 * PI), (a + 0.3) / (2 * PI), (h + height / 2) / height);
glVertex3f(radius * sin(a), next_h, radius * cos(a));
glVertex3f(radius * sin(a), h, radius * cos(a));
glVertex3f(radius * sin(next_a), h, radius * cos(next_a));
}
glEnd();
}
}
void renderScene(void) {
// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// set the camera
glLoadIdentity();
//FPS Camera
gluLookAt(px, py, pz, px+dx, py+dy, pz+dz, 0.0f, 1.0f, 0.0f);
// put the geometric transformations here
// put drawing instructions here
drawAxis();
drawPlane(4);
drawCylinder(1,3,30);
//FPS counter
frame++;
int final_time = glutGet(GLUT_ELAPSED_TIME);
if (final_time - timebase > 1000) {
int fps = frame * 1000.0f / (final_time - timebase);
char title[(((sizeof fps) * CHAR_BIT) + 2) / 3 + 2];
sprintf(title,"FPS: %d", fps);
glutSetWindowTitle(title);
timebase = final_time;
frame = 0;
}
// End of frame
glutSwapBuffers();
}
//FPS Camera
void move(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT: {
px -= (dz * speed);
pz += (dx * speed);
break;
}
case GLUT_KEY_LEFT: {
px += (dz * speed);
pz -= (dx * speed);
break;
}
case GLUT_KEY_UP: {
px += (dx * speed);
pz += (dz * speed);
break;
}
case GLUT_KEY_DOWN: {
px -= (dx * speed);
pz -= (dz * speed);
break;
}
default: {
break;
}
}
glutPostRedisplay();
}
void mouse_motion(int x, int y) {
float lx = x - 800;
float ly = y - 800;
angle = angle + lx * rotateSpeed;
angle1 = angle1 + ly * rotateSpeed;
dx = cos(angle1) * sin(angle);
dy = sin(angle1);
dz = cos(angle1) * cos(angle);
}
int main(int argc, char **argv) {
// init GLUT and the window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("CG");
// Required callback registry
glutIdleFunc(renderScene);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
//FPS
timebase = glutGet(GLUT_ELAPSED_TIME);
// put here the registration of the keyboard callbacks
glutSpecialFunc(move);
glutMotionFunc(mouse_motion);
//glutPassiveMotionFunc(mouse_motion);
// OpenGL settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
// enter GLUT's main cycle
glutMainLoop();
return 1;
}
I'm trying to make a program where I'm able to zoom in & out on the figures I've drawn, but is not doing it; it's switching the orientation of the figures and if I keep scrolling, it just disappears. The function that are suppose to be executed for this to work are the MouseFunc() along with the renderScene(). Any explanation for the problem or help is welcomed.
#include"glut.h"
#include<cmath>
#include<iostream>
using namespace std;
float xr = 0, yr = 0; //to control the object's movement from left to right
// XZ position of the camera
float x = 0.0f, z = 5.0f; //Module 4
float angleX = 0.0f; //Module 4
//Shift + ArrowKey rotation
float transX = 0.0f;
float transY = 0.0f;
float rotY = 0.0f;
//end
//Mouse Commands
//float ZoomFactor = 0.5;
GLfloat theta3 = 0;
GLfloat phi = 0;
GLfloat rho = 5;
GLfloat camX = 0;
GLfloat camY = 0;
GLfloat camZ = 0;
GLfloat upX = 0;
GLfloat upY = 0;
GLfloat upZ = 0;
//end
GLfloat angle = 0.0f;
int refreshmill = 1;
void timer(int value) { //to control the rotation of the object
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta) + xr, 150 * sin(theta) + yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15 + xr, 60 + yr);
glVertex2d(75 + xr, 75 + yr); //right peak
glVertex2d(15 + xr, 90 + yr);
glVertex2d(0 + xr, 150 + yr); //Up-peak Changed
glVertex2d(-15 + xr, 90 + yr);
glVertex2d(-75 + xr, 75 + yr);
glVertex2d(-15 + xr, 60 + yr);
glVertex2d(0 + xr, 0 + yr);
glEnd();
glPopMatrix();
}
//Close code
void handleKeypress(unsigned char key, int x, int y){
switch (key){
case 27: //when the escape key is pressed the program will exit.
exit(0);
}
}
//Movement of drawing
void keyboard(int key, int x, int y) {
float fraction = 0.1f;
bool shift = false;
int mod = glutGetModifiers();
if (mod == GLUT_ACTIVE_SHIFT) {
shift = true;
}
if (!shift) {
switch (key) {
case GLUT_KEY_RIGHT: xr++; break;
case GLUT_KEY_LEFT: xr--; break;
case GLUT_KEY_UP: angleX -= 1.0f; break; //Module 4
case GLUT_KEY_DOWN: angleX += 1.0f; break; //Module 4
}
}
else {
switch (key) {
case GLUT_KEY_LEFT:// RotaciĆ³n del dibujo hacia la izquierda en el eje de Y
rotY -= 1.0f;
break;
case GLUT_KEY_RIGHT:// RotaciĆ³n del dibujo hacia la derecha en el eje de Y
rotY += 1.0f;
break;
}
}
}
//Mouse Function
void MouseFunc(int button, int state, int x, int y){
if (button > 4){
rho = rho + 3.0;
}
else (button < 3);{
rho = rho - 3.0;
}
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
glRotatef(rotY, 0.0, 1.0, 0.0); //Rotation with Shift + ArrowKey
GLfloat camX = rho * cos(theta3*3.1415926f / 180)*sin(phi*3.1415926f / 180);
GLfloat camY = rho * sin(theta3*3.1415926f / 180);
GLfloat camZ = rho * cos(theta3*3.1415926f / 180)*cos(phi*3.1415926f / 180);
// Reduce theta slightly to obtain another point on the same longitude line on the sphere.
GLfloat dt = 1;
GLfloat eyeXtemp = -rho * cos((theta3 - dt)*3.1415926f / 180)*sin(phi*3.1415926f / 180);
GLfloat eyeYtemp = -rho * sin((theta3 - dt)*3.1415926f / 180);
GLfloat eyeZtemp = -rho * cos((theta3 - dt)*3.1415926f / 180)*cos(phi*3.1415926f / 180);
// Connect these two points to obtain the camera's up vector.
GLfloat upX = eyeXtemp - camX;
GLfloat upY = eyeYtemp - camY;
GLfloat upZ = eyeZtemp - camZ;
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set the camera
gluLookAt(camX, camY, camZ, 0, 0, 0, upX, upY, upZ);
gluLookAt(x, 0.0f, z, x, 0.0f, z - 1.0f, 0.0f, 1.0f, 0.0f); //Module 4
glRotatef(angleX, 1, 0, 0); //Module 4
myDisplay();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(0.0f, 0.1f, 0.1f, 0.0f);
glOrtho(-250, 250, -250, 250, -250, 250); //IMPORTANT- Define from negative to positive
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Homework: Circle");
// register callbacks
glutDisplayFunc(renderScene);
glutTimerFunc(0,timer,0);
glutKeyboardFunc(handleKeypress);
glutSpecialFunc(keyboard);
glutMouseFunc(MouseFunc);
// OpenGL init
init();
// enter GLUT event processing cycle
glutMainLoop();
}
Is wired to set a perspective and an orthographic projection. Delete the perspective projection gluPerspective:
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(0.0f, 0.1f, 0.1f, 0.0f); <---- delete
glOrtho(-250, 250, -250, 250, -250, 250);
glMatrixMode(GL_MODELVIEW);
}
If you want to zoom, the the orthographic projection has to be changed (glOrtho). The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport.
Implement a mouse wheel event, which changes the zoom, in a restricted range:
e.g.
GLdouble zoom = 0.0f;
void MouseFunc(int button, int state, int x, int y){
GLdouble min_z = -100.0;
GLdouble max_z = 100.0;
if (button == 4 && zoom < max_z) {
zoom += 3.0;
}
else if (button == 3 && zoom > min_z) {
zoom -= 3.0;
}
}
Modify the orthographic projection, dependent on the zoom in the display loop renderScene:
void renderScene(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble ortho = 250 + zoom;
glOrtho(-ortho, ortho, -ortho, ortho, -250, 250);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// [...]
}
I'm trying to play around with OpenGL and this is my very first code. How can I change to different view to 2 object drawn on the screen?
Is there anyway to do this manually, in stead of using function gluPerspective()?
I tried glRotatef(60, 0.0, 0.0, 5.0) but there is nothing happen. Cos I want to see other faces of the Pyramid and also different view of the rotating sphere.
Also I want to set different colours to different objects that I draw on the screen, how can I do that?
The code to set colour for each object, which is glColor3f, I put it in between glPushMatrix() and glPopMatrix(), also I always include the line glLoadIdentity() before starting draw objects on screen. As far as I know, this line will reset the settings of the previous objects and allows me to set new properties for new object.
Then why when I press button D, the sphere is blue when it supposes to be in white?
Here is my full code:
#include <windows.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <math.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define X .525731112119133606
#define Z .850650808352039932
#define Y 0.0
#define PI 3.1415926535898
#define CIRCLE_STEP 5000
using namespace std;
// Open an OpenGL window
GLFWwindow* window;
int keyboard = 0, itr;
bool big_Sphere = true, sphereWithNormalV = false, animation = false;
GLdouble angle = 0;
/****Step 1: define vertices in (x, y, z) form****/
// Coordinates to draw a Icosahedron
GLfloat icoVertices[12][3] = {
{-X, Y, Z}, {X, Y, Z}, {-X, Y, -Z}, {X, Y, -Z},
{Y, Z, X}, {Y, Z, -X}, {Y, -Z, X}, {Y, -Z, -X},
{Z, X, Y}, {-Z, X, Y}, {Z, -X, Y}, {-Z, -X, Y}
};
// Coordinates to draw a Pyramid
GLfloat pyVertices[4][3] = {
{0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f}
};
static GLuint icoIndices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
static GLuint pyIndices[4][3] = {
{0,1,2}, {0,1,3}, {0,2,3}, {1,2,3}
};
/************************/
void normalize3f(float v[3]) {
GLfloat d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (d == 0.0) {
fprintf(stderr, "zero length vector");
return;
}
v[0] /= d; v[1] /= d; v[2] /= d;
}
void sphereNormalV(GLfloat p1[3], GLfloat p2[3], GLfloat p3[3])
{
glBegin(GL_LINES);
glVertex3f(p1[0] *1.5,p1[1] *1.5, p1[2] *1.5);
glVertex3fv(p1);
glEnd();
glBegin(GL_LINES);
glVertex3f(p2[0] *1.1,p2[1] *1.1, p2[2] *1.1);
glVertex3fv(p2);
glEnd();
glBegin(GL_LINES);
glVertex3f(p3[0] *1.1,p3[1] *1.1, p3[2] *1.1);
glVertex3fv(p3);
glEnd();
}
void drawtriangle(float *v1, float *v2, float *v3)
{
glBegin(GL_LINE_LOOP);
//glNormal3fv(v1);
glVertex3fv(v1);
//glNormal3fv(v2);
glVertex3fv(v2);
//glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}
void subdivide(GLfloat *v1, GLfloat *v2, GLfloat *v3, long depth)
{
GLfloat v12[3], v23[3], v31[3];
GLint i;
if (depth == 0){
drawtriangle(v1, v2, v3);
if (sphereWithNormalV == true){
sphereNormalV(v1, v2, v3);
}
return;
}
for (i = 0; i < 3; i++) {
v12[i] = v1[i]+v2[i];
v23[i] = v2[i]+v3[i];
v31[i] = v3[i]+v1[i];
}
normalize3f(v12);
normalize3f(v23);
normalize3f(v31);
subdivide(v1, v12, v31, depth-1);
subdivide(v2, v23, v12, depth-1);
subdivide(v3, v31, v23, depth-1);
subdivide(v12, v23, v31, depth-1);
}
void drawSphere(GLfloat x, GLfloat y, GLfloat z){
glLoadIdentity();
glPushMatrix();
if (big_Sphere == true){
glScaled(0.4, 0.55, 0.4);
}else{
glScaled(0.13, 0.18, 0.13);
}
if (animation){
glTranslatef(x, y, z);
}
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 20; i++) {
subdivide(&icoVertices[icoIndices[i][0]][0], &icoVertices[icoIndices[i][1]][0], &icoVertices[icoIndices[i][2]][0], 3);
}
glEnd();
glPopMatrix();
}
void drawPyramid(){//(GLfloat x, GLfloat y, GLfloat z){
glLoadIdentity();
glPushMatrix();
glScaled(0.13, 0.18, 0.13);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 4; i++){
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3fv(pyVertices[pyIndices[i][0]]);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3fv(pyVertices[pyIndices[i][1]]);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3fv(pyVertices[pyIndices[i][2]]);
}
glEnd();
glPopMatrix();
}
int getKeyPressed(){
if (glfwGetKey(window, GLFW_KEY_A)){
keyboard = GLFW_KEY_A;
}
if (glfwGetKey(window, GLFW_KEY_B)){
keyboard = GLFW_KEY_B;
}
if (glfwGetKey(window, GLFW_KEY_C)){
keyboard = GLFW_KEY_A;
}
if (glfwGetKey(window, GLFW_KEY_D)){
keyboard = GLFW_KEY_D;
}
if (glfwGetKey(window, GLFW_KEY_E)){
keyboard = GLFW_KEY_E;
}
return keyboard;
}
void controlSphere(bool _big_Sphere, bool _sphereNormalV, bool _animation){
big_Sphere = _big_Sphere;
sphereWithNormalV = _sphereNormalV;
animation = _animation;
}
void gluPerspective(double fovy,double aspect, double zNear, double zFar)
{
// Start in projection mode.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
int main( void ) {
if (!glfwInit()){
fprintf(stderr, "Failed to initialize GLFW.\n");
return -1;
}
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(1100, 800, "Hello World", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "glfw failed to create window.\n");
//glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
glewInit();
if (glewInit() != GLEW_OK){
fprintf(stderr, "Failed to initialize GLEW: %s.\n", glewGetErrorString(glewInit()));
return -1;
}
// 4x anti aliasing
glfwWindowHint(GLFW_SAMPLES, 4);
/**Step 3: Main loop for OpenGL draw the shape**
/* Main loop */
int i = 0;
GLfloat pos_X, pos_Y;
glRotatef(60, 0.0f, 0.3f, 0.4f);
do{
//glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
switch(getKeyPressed()){
case 65:
controlSphere(true, false, false);
drawSphere(0, 0, 0);
break;
case 66:
controlSphere(true, true, false);
drawSphere(0, 0, 0);
break;
case 67:
// drawPyramid();
break;
case 68:
// drawing a Sphere moving in a circular path
controlSphere(false, false, true);
angle = 2*PI*i/CIRCLE_STEP;
pos_X = cos(angle) * 4.5;
pos_Y = sin(angle) * 4.5;
drawSphere(pos_X, pos_Y, 0);
i += 1;
angle += 1;
if (angle >= 360){
angle = 0;
}
// drawing a Pyramid rotate around its y axis
drawPyramid();
break;
default:
controlSphere(true, false, false);
drawSphere(0, 0, 0);
break;
}
Sleep(1);
// Swap front and back rendering buffers
glfwSwapBuffers(window);
//Poll for and process events
glfwPollEvents();
} // check if the ESC key was pressed or the window was closed
while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
/***********************************************/
// Close window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
// Exit program
exit( EXIT_SUCCESS );
}
Is there anyway to do this manually, in stead of using function gluPerspective()?
I don't really understand this question. But if you want to set multiples objects (that have the same parameters) with different transformations, scale, rotation and/or translation, you need to push this to the stack and then draw the desired object. A good starting point can be found here: http://www.songho.ca/opengl/gl_transform.html
Also I want to set different colours to different objects that I draw on the screen, how can I do that?
Your sphere is blue because the last call for glColor3f() was in drawPyramid().
You can change the color of your ball by just calling glColor3f (1.0f, 1.0f, 1.0f); in the beginning of its draw function:
void drawSphere (GLfloat x, GLfloat y, GLfloat z)
{
glColor3f (1.0f, 1.0f, 1.0f);
...
}
A really great site to learn OpenGL from the old pipeline (what you just implemented) to the new (GLSL) is http://www.lighthouse3d.com/tutorials/.
You are looking for Multiple viewports which allows the to split the screen. In your case two different viewports two different cameras(one for each) will be enough.
Check this post.