C++ and GLUT smooth movement - c++

I am new at using graphics with C++ and I have the following code from this
tutorial
here is the code
#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdlib.h>
#include <math.h>
float angle = 0.0f;
float lx = 0.0f, lz = -1.0f;
float x = 0.0f, z = 5.0f;
float deltaAngle = 0.0f;
float deltaMove = 0;
void drawSnowMan(){
glColor3f(1.0f, 1.0f, 1.0f);
glTranslatef(0.0f, 0.75f, 0.0f);
glutSolidSphere(0.75f, 20, 20);
glTranslatef(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.25f, 20, 20);
glPushMatrix();
glColor3f(0.0f, 0.0f, 0.0f);
glTranslatef(0.5f, 0.10f, 0.18f);
glutSolidSphere(0.05f, 10, 10);
glTranslatef(-0.1f, 0.0f, 0.0f);
glutSolidSphere(0.05f, 10, 10);
glPopMatrix();
glColor3f(1.0f, 0.5f, 0.5f);
glutSolidCone(0.8f, 0.5f, 10, 2);
}
void changeSize(int w, int h){
if(h == 0)
h = 1;
float ratio = 1.0*w/h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,w,h);
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
void computePos(float deltaMove){
x += deltaMove * lx * 0.1f;
z += deltaMove * lz * 0.1f;
}
void computeDir(float deltaAngle){
angle += deltaAngle;
lx = sin(angle/75.0);
lz = -cos(angle/75.0);
}
void pressKey(int key, int xx, int yy){
switch(key){
case GLUT_KEY_LEFT: deltaAngle = -0.5f; break;
case GLUT_KEY_RIGHT: deltaAngle = 0.5; break;
case GLUT_KEY_UP: deltaMove = 0.5f; break;
case GLUT_KEY_DOWN: deltaMove = -0.5f; break;
}
}
void relaseKey(int key, int x, int y){
switch(key){
case GLUT_KEY_LEFT:
case GLUT_KEY_RIGHT: deltaAngle = 0.0f; break;
case GLUT_KEY_UP:
case GLUT_KEY_DOWN: deltaMove = 0; break;
}
}
void renderScene(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
if(deltaMove)
computePos(deltaMove);
if(deltaAngle)
computeDir(deltaAngle);
gluLookAt( x, 1.0f, z,
x+lx, 1.0f, z+lz,
0.0f, 1.0f, 0.0f
);
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
angle += 0.1f;
for(int i = -3; i < 3; i++){
for(int j = -3; j < 3; j++){
glPushMatrix();
glTranslatef(i*10.0,0, j*10.0);
drawSnowMan();
glPopMatrix();
}
}
glutSwapBuffers();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(320,320);
glutInitWindowPosition(100,100);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Lighthouse 3D");
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glutSpecialFunc(pressKey);
glutIgnoreKeyRepeat(1);
glutSpecialUpFunc(relaseKey);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 1;
}
My problem is the following, when i try to turn to the left and i keep the left key pressed everything works perfectly fine. When i try to hit the left once the action is not smooth at all. In some cases if the button stroke is too fast it even turns to the opposite direction!

I assume you mean keyboard instead of mouse, in which case to have a "smoother" and "slower" feel you need to adjust your deltaAngle values, which might be too high.
This is only a temporary fix, since those values may affect other machines in different ways - some may be faster, some may be slower. You need to calculate the host machine's FPS in your render loop and multiply your delta values with it, to have the same performance on every computer. This is called time-based movement and is an essential feature of every modern graphics application.
This is exactly what is happening in the following tutorial, when a dot is moving too fast on the screen.
http://lazyfoo.net/SDL_tutorials/lesson32/index.php

A glutIdleFunc() will eat all your battery/CPU/GPU, use a glutTimerFunc() instead to redraw on a predictable, sane schedule.
Accumulate your input state between frames and apply it in your glutTimerFunc() instead of trying to do it right in your keyup/keydown callbacks.
No need for a glutResizeFunc(), do all that just before your draw.
You're using C++ so you should use the C++ versions of C headers, like <cmath> instead of <math.h>.
All together:
#include <GL/glut.h>
#include <cmath>
#include <map>
std::map< int, bool > keys;
void pressKey(int key, int xx, int yy)
{
keys[ key ] = true;
}
void relaseKey(int key, int x, int y)
{
keys[ key ] = false;
}
float angle = 0.0f;
float lx = 0.0f, lz = -1.0f;
float x = 0.0f, z = 5.0f;
void update()
{
const float angleStep = 0.5f;
if( keys[ GLUT_KEY_LEFT ] ) angle -= angleStep;
if( keys[ GLUT_KEY_RIGHT ] ) angle += angleStep;
const float moveStep = 0.5f;
float move = 0.0f;
if( keys[ GLUT_KEY_DOWN ] ) move -= moveStep;
if( keys[ GLUT_KEY_UP ] ) move += moveStep;
x += move * lx * 0.1f;
z += move * lz * 0.1f;
lx = sin(angle/75.0);
lz = -cos(angle/75.0);
}
void drawSnowMan()
{
glColor3f(1.0f, 1.0f, 1.0f);
glTranslatef(0.0f, 0.75f, 0.0f);
glutSolidSphere(0.75f, 20, 20);
glTranslatef(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.25f, 20, 20);
glPushMatrix();
glColor3f(0.0f, 0.0f, 0.0f);
glTranslatef(0.5f, 0.10f, 0.18f);
glutSolidSphere(0.05f, 10, 10);
glTranslatef(-0.1f, 0.0f, 0.0f);
glutSolidSphere(0.05f, 10, 10);
glPopMatrix();
glColor3f(1.0f, 0.5f, 0.5f);
glutSolidCone(0.8f, 0.5f, 10, 2);
}
void renderScene(void)
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(45.0f, w / h, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt
(
x, 1.0f, z,
x+lx, 1.0f, z+lz,
0.0f, 1.0f, 0.0f
);
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
for(int i = -3; i < 3; i++)
{
for(int j = -3; j < 3; j++)
{
glPushMatrix();
glTranslatef(i*10.0,0, j*10.0);
drawSnowMan();
glPopMatrix();
}
}
glutSwapBuffers();
}
void timer( int value )
{
update();
glutTimerFunc( 16, timer, 0 );
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(320,320);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Lighthouse 3D");
glutDisplayFunc(renderScene);
glutSpecialFunc(pressKey);
glutSpecialUpFunc(relaseKey);
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 1;
}

Related

Is there a way to cycle options in C++/GLUT

I am making a program that will cycle the color of a triangle with the up and down arrows. I am pretty new to GLUT and C++, so I can't figure out a way to "cycle" colors.
Here is the triangle code:
void render(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt( 0.0f, 0.0f, 10.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glColor3f(red, green, blue);
glBegin(GL_TRIANGLES);
glVertex3f(-2, 0, 0.0);
glVertex3f(2, 0, 0.0);
glVertex3f(2, 2, 0.0);
glEnd();
angle+=0.1f;
glutSwapBuffers();
}
and the input code:
void processSpecialKey(int key, int x, int y) {
switch(key) {
case GLUT_KEY_UP :
red += 1.0;
green += 0.0;
blue += 0.0; break;
case GLUT_KEY_DOWN :
red += 0.0;
green += 1.0;
blue += 0.0; break;
}
}

OpenGL/Glut: Making the camera rotate around X axis with arrow keys?

I'm trying to make the gluLookAt() function so that when I press the up & down key the camera moves around the X axis
I'm trying a method I saw at: http://www.lighthouse3d.com/tutorials/glut-tutorial/keyboard-example-moving-around-the-world/
but it's not working for me. Anyone knows an easier way? and where should I put the gluLookAt() so on myDisplay() func?
#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
// actual vector representing the camera's direction
float lx = 0.0f, lz = -1.0f;
// XZ position of the camera
float x = 0.0f, z = 5.0f;
GLfloat angle = 0.0f;
int refreshmill = 1;
void timer(int value) { //to control the rotation of the object
glutPostRedisplay();
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
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;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
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);
}
glutSwapBuffers();
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
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();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Set the camera
gluLookAt(x, 1.0f, z,
x + lx, 1.0f, z + lz,
0.0f, 1.0f, 0.0f);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
myDisplay();
glutSwapBuffers();
}
//Move to left or right
void keyboard(int key, int x, int y) {
float fraction = 0.1f;
switch (key) {
case GLUT_KEY_RIGHT:
xr++;
cout << x << endl;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
xr--;
cout << x << endl;
glutPostRedisplay();
break;
case GLUT_KEY_UP:
angle -= 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_DOWN:
angle += 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
}
}
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-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(myDisplay);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutTimerFunc(0,timer,0);
glutSpecialFunc(keyboard);
// OpenGL init
init();
// enter GLUT event processing cycle
glutMainLoop();
}
First of all there should be only 1 display call back function:
int main(int argc, char** argv) {
// [...]
// glutDisplayFunc(myDisplay); <----- DELETE!!!
glutDisplayFunc(renderScene);
// glutIdleFunc(renderScene); <----- DELETE!!!
// [...]
}
Setup an an orthographic projection with an extended near and far plane. If the object is rotated around the X axis, it takes space in the 3 dimensions:
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-250, 250, -250, 250, -250, 250); // <----
glMatrixMode(GL_MODELVIEW);
}
Add a variable anglaX which is changed in the keyboard event:
float angleX = 0.0f;
void keyboard(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT: xr++; break;
case GLUT_KEY_LEFT: xr--; break;
case GLUT_KEY_UP: angleX -= 1.0f; break;
case GLUT_KEY_DOWN: angleX += 1.0f; break;
}
}
Rotate the model, after the view was set:
gluLookAt(x, 0.0f, z, x, 0.0f, z-1.0f, 0.0f, 1.0f, 0.0f);
glRotatef(angleX, 1, 0, 0);
Don't do any calls to glutSwapBuffers(), glFlush() and glutPostRedisplay(), except at the end of renderScene:
void timer(int value) { //to control the rotation of the object
// glutPostRedisplay(); <--- DELETE
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();
}
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set the camera
gluLookAt(x, 0.0f, z, x, 0.0f, z-1.0f, 0.0f, 1.0f, 0.0f);
glRotatef(angleX, 1, 0, 0);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
myDisplay();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
Further I recommend to use double buffering:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
You can init your camera with gluLookAt at init(), then rotate it when arrow keys pressed. If you want to rotate camera around it's local x axis, assume your initial modelview matrix is V, newly happened rotation around x axis is R, you need to set modelview matrix to R*V, not V*R.
case GLUT_KEY_UP:
GLfloat temp[16];
glGetFloatv(GL_MODELVIEW_MATRIX, temp);
glLoadIdentity();
glRotate(stepAngle, 1, 0, 0); // calculate stepAngle by your self
glMultMatrixf(temp);
break;
You don need to reset modelview matrix during rendering, view part is already done, make sure you restore it after rendering the whole scene:
glPushMatrix(GL_MODELVIEW_MATRIX)
// don't call glLoadIdentity() here, you don't need to reset view part.
...
...
glPopMatrix()

How do I get color to change using glut and openGL?

I am trying to teach myself to animate an object without user input, so far I have figured out how to make a scene rotate. How do I get an object to change color though? I thought the code I have would do it, but it remains a white triangle (not even a different color).
How do I get it to change color at the same time that the triangle or perspective rotates?
Here is my current code:
#include <GL/glut.h>
float color1;
float color2;
float color3;
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if (h == 0)
h = 1;
float ratio = w * 1.0 / h;
// Use the Projection Matrix
glMatrixMode(GL_PROJECTION);
// Reset Matrix
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
//changeColor?
color1 += 0.1f;
color2 += 0.3;
color3 += color2;
if (color1 > 1.0)
color1 = 0;
if (color2 > 1.0)
color2 = 0;
if (color3 > 1.0)
color3 = 0;
// Get Back to the Modelview
glMatrixMode(GL_MODELVIEW);
}
float angle = 0.0f;
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Set the camera
gluLookAt(0.0f, 0.0f, 10.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(color1, color2, color3);
glVertex3f(2.0f, -2.0f, 0.0f);
glVertex3f(2.0f, 0.0f, 0.0);
glVertex3f(0.0f, 2.0f, 0.0);
glEnd();
angle += 0.1f;
color1 += 0.1f;
color2 += 0.3;
color3 += color2;
glutSwapBuffers();
}
int main(int argc, char **argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(320, 320);
glutCreateWindow("tutorial example");
// register callbacks
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
// enter GLUT event processing cycle
glutMainLoop();
return 1;
}
Float colors have to be in range of [0,1] and you only add something to your values and never reset it to zero, so it becomes greater than 1 in first 10 frames (=very fast), OpenGL clamps it to 1, so you see it white.
I.e. that bunch of ifs in changeSize should actually be in renderScene.
For something simple like this use a glutTimerFunc() callback with a reasonable timeout
Update the angle/color in the timer callback & kick off a repaint
Re-set the projection/modelview matrices each time through the glutDisplayFunc() callback, helps prevent weird matrix problems
All together:
#include <GL/glut.h>
float angle = 0.0f;
float color1 = 0.0f;
float color2 = 0.0f;
float color3 = 0.0f;
void timer( int value )
{
angle += 3.0f;
//changeColor?
color1 += 0.001f;
color2 += 0.003f;
color3 += color2;
if (color1 > 1.0)
color1 = 0;
if (color2 > 1.0)
color2 = 0;
if (color3 > 1.0)
color3 = 0;
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(45.0f, w / h, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt
(
0.0f, 0.0f, 10.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(color1, color2, color3);
glVertex3f(2.0f, -2.0f, 0.0f);
glVertex3f(2.0f, 0.0f, 0.0);
glVertex3f(0.0f, 2.0f, 0.0);
glEnd();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(320, 320);
glutCreateWindow("tutorial example");
glutDisplayFunc(renderScene);
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 1;
}

gluLookAt() doesn't work as expected

I have created a bowling game in OpenGL using Eclipse.
Now I want to change the view of camera upon key-pressed.
But When I press x button, everything disappears.
Here us the code: -
#include <GL/glut.h>
#include <stdlib.h>
int refreshMillis = 30; // Refresh period in milliseconds
int windowWidth = 640; // Windowed mode's width
int windowHeight = 480; // Windowed mode's height
int windowPosX = 50; // Windowed mode's top-left corner x
int windowPosY = 50; // Windowed mode's top-left corner y
bool fullScreenMode = false; // Full-screen or windowed mode?
GLfloat ballTSpeed = 0.15f; // Ball's speed in y directions
GLfloat x = 1.0f, y = 10.0f, z = 10.0f, i = 0.0f, j = 0.0f, k = 0.0f, a = 0.0f,
b = 0.0f, c = -1.0f;
bool moveBallUp = false, moveBallDown = false, isCollision = false, resetCall =
false;
//
GLfloat cone1[] = { 0.0f, 2.5f, -11.0f, /*rotated*/30.0f, -1.5, 0.0, 0.0 };
GLfloat cone2[] = { 2.0f, 2.5f, -11.0f, /*rotated*/30.0f, -1.5, 0.0, 0.0 };
GLfloat cone3[] = { -2.0f, 2.5f, -11.0f, /*rotated*/30.0f, -1.5, 0.0, 0.0 };
GLfloat ball[] = {/* X */0.0f, /* Y */-2.0f, /* Z */-6.0f, /*sphere*/1.0f, 50.0,
50.0 };
//
void resetGame() {
resetCall = true;
cone1[0] = 0.0f;
cone1[1] = 2.5f;
cone1[2] = -11.0f;
/*rotated*/
cone1[3] = 30.0f;
cone1[4] = -1.5;
cone1[5] = 0.0;
cone1[6] = 0.0;
cone2[0] = 2.0f;
cone2[1] = 2.5f;
cone2[2] = -11.0f;
/*rotated*/
cone2[3] = 30.0f;
cone2[4] = -1.5;
cone2[5] = 0.0;
cone2[6] = 0.0;
cone3[0] = -2.0f;
cone3[1] = 2.5f;
cone3[2] = -11.0f;
/*rotated*/
cone3[3] = 30.0f;
cone3[4] = -1.5;
cone3[5] = 0.0;
cone3[6] = 0.0;
}
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
static void resize(int width, int height) {
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(x, y, z, i, j, k, a, b, c);
// eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz
}
/* Called back when the timer expired */
void Timer(int value) {
glutPostRedisplay(); // Post a paint request to activate display()
glutTimerFunc(refreshMillis, Timer, 0); // subsequent timer call at milliseconds
}
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 27: // ESC key
exit(0);
break;
case 'r':
resetGame();
break;
case 'i':
x += 0.5;
gluLookAt(x, y, z, i, j, k, a, b, c);
// eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz
}
}
void specialKeys(int key, int x, int y) {
switch (key) {
case GLUT_KEY_F1: // F1: Toggle between full-screen and windowed mode
fullScreenMode = !fullScreenMode; // Toggle state
if (fullScreenMode) { // Full-screen mode
windowPosX = glutGet(GLUT_WINDOW_X ); // Save parameters for restoring later
windowPosY = glutGet(GLUT_WINDOW_Y );
windowWidth = glutGet(GLUT_WINDOW_WIDTH );
windowHeight = glutGet(GLUT_WINDOW_HEIGHT );
glutFullScreen(); // Switch into full screen
} else { // Windowed mode
glutReshapeWindow(windowWidth, windowHeight); // Switch into windowed mode
glutPositionWindow(windowPosX, windowPosX); // Position top-left corner
}
break;
case GLUT_KEY_UP:
if (!isCollision)
moveBallUp = true;
break;
case GLUT_KEY_PAGE_UP:
ballTSpeed *= 1.2f;
break;
}
}
static void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (moveBallUp) {
ball[1] += ballTSpeed;
ball[2] -= 0.02 + ballTSpeed;
}
if (ball[1] >= (cone1[1] - 0.4) && ball[1] <= cone1[1]) {
if (!isCollision)
{
cone1[0] -= 0.5;
cone1[4] -= 10.0;
cone1[5] += 10.0;
cone1[2] += -0.3;
cone2[0] += 0.5;
cone2[4] -= 10.0;
cone2[5] -= 10.0;
cone2[2] += -0.4;
cone3[0] += 0.5;
cone3[4] -= 10.0;
cone3[5] -= 10.0;
cone3[2] += -0.4;
}
isCollision = true;
moveBallUp = false; // stop moving the ball
}
if (resetCall) {
if ((ball[1] >= -2.0f && ball[1] <= -1.6f)
&& (ball[2] >= -6.0f && ball[2] <= -5.6f)) {
resetCall = false;
isCollision = false;
}
else {
ball[1] -= ballTSpeed;
ball[2] += 0.02 + ballTSpeed;
}
}
glColor3d(1, 1, 0);
glPushMatrix();
glTranslated(cone1[0], cone1[1], cone1[2]);
glRotated(cone1[3], cone1[4], cone1[5], cone1[6]);
glutSolidCone(1, 2, 50, 50);
glPopMatrix();
glColor3d(1, 0, 1);
glPushMatrix();
glTranslated(cone2[0], cone2[1], cone2[2]);
glRotated(cone2[3], cone2[4], cone2[5], cone2[6]);
glutSolidCone(1, 2, 50, 50);
glPopMatrix();
glColor3d(0, 0, 1);
glPushMatrix();
glTranslated(cone3[0], cone3[1], cone3[2]);
glRotated(cone3[3], cone3[4], cone3[5], cone3[6]);
glutSolidCone(1, 2, 50, 50);
glPopMatrix();
glColor3d(1, 0, 0);
glPushMatrix();
glTranslated(ball[0], ball[1], ball[2]);
glutSolidSphere(ball[3], ball[4], ball[5]);
glPopMatrix();
glPushMatrix();
glColor3d(0.6, 1, 0.20);
glBegin(GL_QUADS);
glVertex3f(16.0, 5.0, -25.0);
glVertex3f(-16.0, 5.0, -25.0);
glVertex3f(-6.0, -4.0, -5.0);
glVertex3f(6.0, -4.0, -5.0);
glEnd();
glColor3d(1, 1, 0);
glBegin(GL_QUADS);
glVertex3f(16.0, 15.0, -25.0);
glVertex3f(-16.0, 15.0, -25.0);
glVertex3f(-16.0, -4.0, -25.0);
glVertex3f(16.0, -4.0, -25.0);
glEnd();
glutSwapBuffers();
}
/* Program entry point */
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitWindowSize(windowWidth, windowHeight); // Initial window width and height
glutInitWindowPosition(windowPosX, windowPosY); // Initial window top-left corner (x, y)
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Balling Game 3d");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glClearColor(1, 1, 1, 1);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
glutTimerFunc(0, Timer, 0); // First timer call immediately
glutSpecialFunc(specialKeys); // Register callback handler for special-key event
glutKeyboardFunc(keyboard); // Register callback handler for special-key event
glutMainLoop();
return EXIT_SUCCESS;
}
In the code case 'i':
x += 0.5;
gluLookAt(x, y, z, i, j, k, a, b, c);
// eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz
Camera view should be changed as I guess but I know that I am doing wrong. Please tell me how to do this?
Never call OpenGL functions from input event handlers. Only misery and dispair comes out of this.
In your input event handlers set variables from the user input data and trigger a redraw. In the drawing function parameterize the rendering process from those variables.
You can remove the resize handler entirely. Setup viewport and projection in the display function
static void display(void) {
int const width = glutGet(GLUT_WINDOW_WIDTH);
int const height = glutGet(GLUT_WINDOW_HEIGHT);
float const ar = (float) width / (float) height;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(view_x, view_y, view_z, target_x, target_y, target_z, up_x, up_y, up_z);
// eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz
/* ... */
In the keyboard handler just set variables and trigger a redisplay
void keyboard(unsigned char key, int mouse_x, int mouse_y) {
switch (key) {
case 27: // ESC key
exit(0);
break;
case 'r':
resetGame();
break;
case 'i':
view_x += 0.5;
/* don't call gluLookAt here! */
}
glutPostRedisplay();
}

Opengl translation with glMultMatrixf

Im trying to translate an object without using glTranslate(). I have searched through web and found a function glMultMatrixf(). I wanted to multiply my translation matrix using this function but I couldn't accomplished it. I feel like I'm on the correct path logically but is translating an object this way even possible?
I have written the code using opengl and c++. Here is the code:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
using namespace std;
float _angle = 0;
typedef GLfloat Matrix4x4 [4][4];
Matrix4x4 matTransl3D;
/* Construct the 4 x 4 identity matrix. */
void matrix4x4SetIdentity (Matrix4x4 matIdent4x4)
{
GLint row, col;
for (row = 0; row < 4; row++)
for (col = 0; col < 4 ; col++)
matIdent4x4 [row][col] = (row == col);
}
void translate3D (GLfloat tx, GLfloat ty, GLfloat tz)
{
/* Initialize translation matrix to identity. */
matrix4x4SetIdentity (matTransl3D);
matTransl3D [0][3] = tx;
matTransl3D [1][3] = ty;
matTransl3D [2][3] = tz;
}
void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 27: //Escape key
exit(0);
}
}
void initRendering()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
}
void handleResize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float)w / (float)h, 1.0, 200.0);
}
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
translate3D(0.0f, 0.0f, -50.0f);
glMultMatrixf(*matTransl3D);
glBegin(GL_TRIANGLE_FAN); // draw triangle
glColor3f(1.0f,0.0f,0.0f); // set color to red
glVertex3f( 0.0f, 3.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f); // set color to green
glVertex3f(-5.0f, -5.0f, 5.0f);
glColor3f(1.0f,1.0f,0.0f); // set color to yellow
glVertex3f( 5.0f, -5.0f, 5.0f);
glColor3f(0.0f,0.0f,1.0f); // set color to blue
glVertex3f( 5.0f, -5.0f, -5.0f);
glColor3f(1.0f,1.0f,1.0f); // set color to white
glVertex3f( -5.0f, -5.0f, -5.0f);
glColor3f(0.0f,1.0f,0.0f); // set color to green
glVertex3f(-5.0f, -5.0f, 5.0f);
glEnd();
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f); // set color to green
glVertex3f(-5.0f, -5.0f, 5.0f);
glColor3f(1.0f,1.0f,1.0f); // set color to white
glVertex3f( -5.0f, -5.0f, -5.0f);
glColor3f(0.0f,0.0f,1.0f); // set color to blue
glVertex3f( 5.0f, -5.0f, -5.0f);
glColor3f(1.0f,1.0f,0.0f); // set color to yellow
glVertex3f( 5.0f, -5.0f, 5.0f);
glEnd();
glutSwapBuffers();
}
//Called every 25 milliseconds
void update(int value) {
_angle += 1.0f;
if (_angle > 360) {
_angle -= 360;
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("Translation 3d");
initRendering();
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0);
glutMainLoop();
return 0;
}
OpenGL takes matrices as column major, i.e. the indexing is
0 4 8 c
1 5 9 d
2 6 a e
3 7 b f
However you're indexing your translation matrix in the order
0 1 2 3
4 5 6 7
8 9 a b
c d e f