I am working on an nbody simulator and I want to display it with OpenGL. I want to always be looking at the centre of mass reference frame. I have the following code. I calculate the COM and I set the center coordinate in the gluLookAt function to be the center of mass. I then subtract the "zoom" from the z coordinate to get the eye position. By logic this should ensure that I am always looking at whatever value the center of mass is. The only issue is that I marked where the center of mass should be on the screen with a red dot and it is moving. Shouldn't it never move if I am always looking at it from the same relative position? Here is my code. Focus on the display function since I assume that is where the error will be. I had similar code working in another project and I can't really find any differences.
#include "Universe.cuh"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "timer.hpp"
#include <GL/glut.h>
Universe u;
float* vbuf;
double angle = 0.0, zoom = 1000;
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
float3 c = u.getCenterOfMass();
gluLookAt(c.x, c.y, c.z - zoom, c.x, c.y, c.z, 0, 1, 0);
glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
glColor4f(1, 1, 1, 0.25);
glBegin(GL_POINTS);
{
glColor3f(1.0, 0.0, 0.0);
glVertex3d(c.x, c.y, c.z);
}
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (double)w / (double)h, 1.0, zoom * 1e9);
glMatrixMode(GL_MODELVIEW);
}
void copy_to_vbuf()
{
for(int i = 0; i < u.size(); i++)
{
vbuf[3 * i + 0] = u.getObjects()[i].p.x;
vbuf[3 * i + 1] = u.getObjects()[i].p.y;
vbuf[3 * i + 2] = u.getObjects()[i].p.z;
}
}
void keyboard(unsigned char c, int x, int y)
{
if(c == 'w')
angle += 1;
else if(c == 's')
angle -= 1;
else if(c == '=')
zoom /= 1.2;
else if(c == '-')
zoom *= 1.2;
glutPostRedisplay();
}
void idle()
{
u.timeStep();
copy_to_vbuf();
glutPostRedisplay();
}
int main(int argc, char** argv)
{
cudaSetDevice(0);
srand(time(0));
u.getConfiguration().max_velocity = 10;
u.getConfiguration().softening_factor = 0.01;
u.getConfiguration().threshold_angle = 35;
u.getConfiguration().time_step = 0.1;
const int N = 5;
vbuf = new float[3 * N];
for(int i = 0; i < N; i++)
{
Object o;
o.m = rand() % 100 + 1;
o.p.x = 500.0 * rand() / RAND_MAX - 250.0;
o.p.y = 500.0 * rand() / RAND_MAX - 250.0;
o.p.z = 500.0 * rand() / RAND_MAX - 250.0;
u.addObject(o);
}
copy_to_vbuf();
glutInit(&argc, argv);
glutInitDisplayMode(GL_DOUBLE);
glutInitWindowSize(1000, 1000);
glutCreateWindow("N-Body");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPointSize(1.0);
glutMainLoop();
return 0;
}
Two points regarding:
glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
Since your axis is not centered on the 'COM', when you apply rotation the COM point will not stay in place and logically would move around the screen.
AFIK the normal order is scale,rotate,translate for transformations. This will apply the rotation and then scale.
EDIT:
To expand on that: Currently you take an arbitrary point rotate it, scale it and then focus on the point where it used to be. If you want to rotate your model (e.g. point marking the 'COM') around itself, it needs to be centered at (0,0,0).
Related
I have program in which the object (a triangle) follows the mouse as it moves around and rotates to the direction its moving. What do I have to do to make it so the object stays still, until I click it, drag it to a position and once I release the mouse, it starts to move to that position?
#include <GL/glut.h>
#include <math.h>
# define ANIMATION_STEP (1000/300)
# define PI 3.1415926535897932
struct Globals {
centre_x, centre_y, rotate;
float length;
float mouse_x, mouse_y, speed;
int animating;
} globals;
void init(void){
// Starting position of the triangle
globals.centre_x = 100;
globals.centre_y = 100;
globals.rotate = 0.0;
globals.mouse_x = 300.0;
globals.mouse_y = 300.0;
// Animation speed in pixels per second
globals.speed = 300.0;
// size of the triangle
globals.length = 27;
globals.animating = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1000.0, 0.0, 700.0);
}
void triangle(void){
glBegin(GL_POLYGON);
glVertex2f(0.5, 0.0);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glEnd();
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(globals.mouse_x, globals.mouse_y, 0.0);
glRotatef(globals.rotate, 0.0, 0.0, 1.0);
glScalef(globals.length, globals.length, 1.0);
triangle();
glFlush();
glutSwapBuffers();
}
float limit(float x, float min, float max){
if (x < min) {
x = min;
}
if (x > max) {
x = max;
}
return x;
}
void timer(int v){
// Computing elapsed time for smooth animation.
int time = glutGet(GLUT_ELAPSED_TIME);
float angle;
glutTimerFunc(ANIMATION_STEP, timer, time);
if (globals.animating) {
int delta_t = time - v;
float delta_x, delta_y, length, step_size;
// Compute vector from current location to mouse
delta_x = globals.mouse_x - globals.centre_x;
delta_y = globals.mouse_y - globals.centre_y;
// Compute length of the vector
length = sqrt (delta_x*delta_x + delta_y*delta_y);
// If the triangle is close to the mouse, then no motion is required.
step_size = globals.speed * delta_t / 1000.0;
if (length > step_size * 0.55) {
delta_x = delta_x / length;
delta_y = delta_y / length;
globals.centre_x += delta_x * step_size;
globals.centre_y += delta_y * step_size;
angle = atan2(delta_y, delta_x);
globals.rotate = angle * 180.0 / PI;
// Keep the triangle inside the world window.
globals.centre_x = limit(globals.centre_x, 0.0 + globals.length/2, 1000.0 - globals.length/2);
globals.centre_y = limit(globals.centre_y, 0.0 + globals.length/2, 700.0 - globals.length/2);
}
glutPostRedisplay();
}
}
void mousemotion(int x, int yc){
globals.mouse_x = x;
globals.mouse_y = 700 - yc;
glutPostRedisplay();
}
main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1000, 700);
glutInitWindowPosition(10, 10);
glutDisplayFunc(display);
glutTimerFunc(ANIMATION_STEP, timer, 0);
glutPassiveMotionFunc(mousemotion);
init();
glutMainLoop();
return 0;
}
I have investigated processMouse() where if state == GLUT_DOWN then it records the current position and mouse press cordinates, but the best ive been able to get is that it immediately teleports to the mouse click. Can someone please explain what I would need to do to click on it, drag, release, then move to position?
in opengl, how to change mouse...
You don't. Mouse does not exist in OpenGL. Maybe you should change the question to "How to process mouse events in windows/GLUT/SDL/whatever-framework?" for which there are dozens of duplicates.
I am attempting to translate one circle independent of a separate, stationary circle, utilizing glTranslatef();. However, with my current, full code, each of my circles remains immobile. To investigate why this may be so, I have researched several answers, each comparable to those found here and here. Additionally, I read up on glLoadIdentity as well as the differences between GL_MODELVIEW and GL_PROJECTION, just to see if their details would offer any further clarification. I've also consulted the OpenGL API for the proper definitions of each of the above.
In the style of these solutions, I produced the following do...while loop:
do{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, fb_width, fb_height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(0,1,0);
drawCircle(1280 * 0.50, 720 * 0.25,e[2]);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,0);
drawTarget(1280 * 0.50, 720 * 0.75,50);
glPopMatrix();
glfwSwapBuffers(w);
glfwPollEvents();
}
while (!glfwWindowShouldClose(w));
In this snippet, the drawCircle drawing remains stationary, but I would like for it to follow the written glTranslatef(0,1,0) instead. Is the stationary nature of the circle due to misplaced a glMatrixMode or glLoadIdentity, or perhaps due to the fact that they are being called within the do...while loop and the proper matrix is never really being utilized? I would appreciate any guidance you may have as to why the aforementioned and accepted answers are not functioning quite as well within my program.
For the sake of full transparency, here is the entirety of my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <stddef.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLFWwindow *w;
int fb_width, fb_height;
static void error(int error, const char *desc)
{
fputs(desc, stderr);
}
static void key_callback(GLFWwindow *w, int key, int scancode, int action, int mods)
{
if ((key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) && action == GLFW_PRESS)
glfwSetWindowShouldClose(w, GL_TRUE);
}
void drawCircle(float cx, float cy, float radius)
{
float num_segments = 360;
float theta = 2 * 3.1415926 / num_segments;
float c = cosf(theta);//precalculate the sine and cosine
float s = sinf(theta);
float t;
float x = radius;//we start at angle = 0
float y = 0;
glBegin(GL_TRIANGLE_FAN);
glColor3f(1, 0, 1);
for(int ii = 0; ii < num_segments; ii++)
{
glVertex2f(x + cx, y + cy);//output vertex
//apply the rotation matrix
t = x;
x = c * x - s * y;
y = s * t + c * y;
}
glEnd();
}
void drawTarget(float cx, float cy, float radius)
{
float num_segments = 360;
float theta = 2 * 3.1415926 / num_segments;
float c = cosf(theta);//precalculate the sine and cosine
float s = sinf(theta);
float t;
float x = radius;//we start at angle = 0
float y = 0;
glBegin(GL_LINE_LOOP);
glColor3f(1, 1, 1);
for(int ii = 0; ii < num_segments; ii++)
{
glVertex2f(x + cx, y + cy);//output vertex
//apply the rotation matrix
t = x;
x = c * x - s * y;
y = s * t + c * y;
}
glEnd();
}
int main(void)
{
int i;
float e[3] = {140,120,100};
float m[3] = {90,80,70};
float h[3] = {60,50,40};
glfwSetErrorCallback(error);
if (!glfwInit())
exit(EXIT_FAILURE);
w = glfwCreateWindow(1280, 720, "AxTest", NULL, NULL);
if (!w)
{
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(w);
glfwSetKeyCallback(w, key_callback);
glfwGetFramebufferSize(w, &fb_width, &fb_height);
do{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, fb_width, fb_height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(0,1,0);
drawCircle(1280 * 0.50, 720 * 0.25,e[2]);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,0);
drawTarget(1280 * 0.50, 720 * 0.75,50);
glPopMatrix();
glfwSwapBuffers(w);
glfwPollEvents();
}
while (!glfwWindowShouldClose(w));
glfwDestroyWindow(w);
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
The values for the vertex positions with which you draw your circles are in the order of hundreds (likely, because you want to address pixels as indicated by the values for the projection matrix). But glTranslates sees only a small number, so the shift is miniscule (one pixel) and hence you think nothing did happen. If you rewrite your code so that you don't specify the circle/target center by explicit modification of the vertex position offset it'd be clearer.
void drawCircle(float radius)
{
/* ... */
for(int ii = 0; ii < num_segments; ii++)
{
glVertex2f(x, y); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/* ... */
}
void drawTarget(float radius)
{
/* ... */
for(int ii = 0; ii < num_segments; ii++)
{
glVertex2f(x, y); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/* ... */
}
int main(void)
{
/* ... */
glPushMatrix();
glTranslatef(1280*0.50, 720*0.25, 0);
drawCircle(e[2]);
glPopMatrix();
glPushMatrix();
glTranslatef(1280 * 0.50, 720 * 0.25, 0);
drawTarget(50);
glPopMatrix();
/* ... */
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, fb_width, fb_height, 0, 0, 1);
You don't have to make the projection matrix at every loop, put it before the loop.
Then the error you have is surely due to :
glMatrixMode(GL_MODELVIEW);
// it miss glLoadIdentity() here
glPushMatrix();
glTranslatef(0,1,0);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
So I have this code that produces fireworks using what appears to be a particle effect, but I don't understand what is going on in the code. Could someone explain it to me, particularly the initialize function and the draw blast blast function. If you could annotate it with notes that would be super.
/* fireworks.c - simulate fireworks with particle systems */
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
//to correct ASCI deviations in Microsoft VC++ 6.0
#define M_PI (3.1415926535897932384626433832795)
double drand48()
{ return (rand()%10000)/10000.0; }
//end of corrections
#endif
#define MAX_POINTS 5000
int numPoints;
GLfloat curx, cury;
GLfloat x[MAX_POINTS], y[MAX_POINTS];
GLfloat xacc[MAX_POINTS], yacc[MAX_POINTS];
GLfloat red, green, blue;
int step; int length;
void initialize()
{ int j; double temp, temp2;
numPoints = drand48()*(MAX_POINTS-1);
curx = -0.5 + drand48();
cury = 0.0 + drand48();
red = 0.5 + 0.5*drand48();
green = 0.5 + 0.5*drand48();
blue = 0.5 + 0.5*drand48();
glPointSize(1.5);
step = 0;
length = 700 + 300*drand48();
/* initialize the blast */
for (j=0 ; j<numPoints ; j++ ) {
x[j] = curx;
y[j] = cury;
temp = drand48();
temp2 = drand48()*2.0*M_PI;
xacc[j] = (cos(temp2) * temp)/length;
yacc[j] = (sin(temp2) * temp)/length;
}
}
void draw_blast(void)
{ int i;
double glow = (length - step) / (double)length;
glColor3f(red*glow, green*glow, blue*glow);
glBegin(GL_POINTS);
for (i=0;i<numPoints;i++) {
x[i] += xacc[i];
y[i] += yacc[i];
glVertex2f(x[i], y[i]);
}
glEnd();
glFlush();
glutSwapBuffers();
}
void display(void)
{ int i;
glClear(GL_COLOR_BUFFER_BIT);
if (step < 0.9*length) {
for (i=0; i<numPoints; i++)
yacc[i] -= 0.02 / length; // gravity
draw_blast();
}
step ++;
if (step > length) initialize();
}
void idle(void)
{
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27: exit(0); break;
}
}
void reshape (int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.0, 1.0,
-1.0*(GLfloat)h/(GLfloat)w, 1.0*(GLfloat)h/(GLfloat)w,
-1.0, 1.0);
else
glOrtho(-1.0*(GLfloat)w/(GLfloat)h, 1.0*(GLfloat)w/(GLfloat)h,
-1.0, 1.0,
-1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (800, 800);
glutInitWindowPosition(0, 0);
glutCreateWindow ("Fireworks");
glClearColor (0.0, 0.0, 0.0, 0.0);
initialize();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Yes, it is a particle system. However - not a particularly efficient one.
Let's go through it step by step:
GLfloat x[MAX_POINTS], y[MAX_POINTS];
GLfloat xacc[MAX_POINTS], yacc[MAX_POINTS];
x and y hold the particles' positions. xacc and yacc hold their velocities.
In initialize:
numPoints = drand48()*(MAX_POINTS-1);
This sets a random number of particles...
curx = -0.5 + drand48();
cury = 0.0 + drand48();
red = 0.5 + 0.5*drand48();
green = 0.5 + 0.5*drand48();
blue = 0.5 + 0.5*drand48();
glPointSize(1.5);
step = 0;
length = 700 + 300*drand48();
... with a random center position, color, and radius (length).
for (j=0 ; j<numPoints ; j++ ) {
This starts the initialization for every particle.
x[j] = curx;
y[j] = cury;
Sets the particle's position the the center position.
temp = drand48();
temp2 = drand48()*2.0*M_PI;
xacc[j] = (cos(temp2) * temp)/length;
yacc[j] = (sin(temp2) * temp)/length;
Sets a random direction of the particle (temp2) and a random velocity based on the system's radius (temp / length).
In drawBlast():
double glow = (length - step) / (double)length;
glColor3f(red*glow, green*glow, blue*glow);
Slowly fades the particles' color to black.
x[i] += xacc[i];
y[i] += yacc[i];
Advance the particle by their velocity. This assumes a constant frame rate.
glVertex2f(x[i], y[i]);
Draw the particle as a point.
In display():
yacc[i] -= 0.02 / length; // gravity
Accelerate every particle downwards. I.e. simulate that the particles fall.
I'm trying to code a camera with glTranslate/glRotate. To implement the look-up / look-down functions I need all the objects in my rendering space to rotate around a point (that is, where the "camera" is at), point which usually differs from the origin. Still, things keep rotating around the origin. Is there a way to specify a different point?
EDIT: Added code
Thanks for your fast reply. It seems that I can't get it working right no matter what, so I've decided to add my code; I'd much appreciate if someone could take a look at it and tell me what changes are needed in order to translate/rotate/translate back.
#include <iostream>
#include <cmath>
#include <GLUT/GLUT.h>
const double roaming_step = .13;
double z_offset = .0;
double y_offset = .0;
double x_offset = .0;
const double angle_step = 1.5;
double angle_xz = .0;
double angle_yz = .0;
bool keyStates[256] = { false };
void drawFloor()
{
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3f(-3.0, -1.0, 3.0);
glVertex3f(-3.0, -1.0, -3.0);
glVertex3f(3.0, -1.0, -3.0);
glVertex3f(3.0, -1.0, 3.0);
glEnd();
}
void drawBalls()
{
glTranslatef(-3.0, -.5, -3.0);
glColor3f(.8, .1, .1);
for(int i = 0; i < 3; i++)
{
glPushMatrix();
glTranslatef(.0, -.5, i * 3);
for(int j = 0; j < 3; j++)
{
glPushMatrix();
glTranslatef(j * 3, .0, .0);
glutSolidSphere(.5, 20, 20);
glPopMatrix();
}
glPopMatrix();
}
}
void keyPressed(unsigned char key, int x, int y)
{
keyStates[key] = true;
}
void keyReleased(unsigned char key, int x, int y)
{
keyStates[key] = false;
}
void keyboardOperations()
{
if(keyStates['w'])
z_offset += roaming_step;
if(keyStates['s'])
z_offset -= roaming_step;
if(keyStates['a'])
x_offset += roaming_step;
if(keyStates['d'])
x_offset -= roaming_step;
if(keyStates['i'])
{
angle_xz -= angle_step;
if(angle_xz < .0)
angle_xz += 360.0;
}
if(keyStates['o'])
{
angle_xz += angle_step;
if(angle_xz >= 360.0)
angle_xz -= 360.0;
}
if(keyStates['u'])
{
angle_yz -= angle_step;
if(angle_yz < .0)
angle_yz += 360.0;
}
if(keyStates['j'])
{
angle_yz += angle_step;
if(angle_yz >= 360.0)
angle_yz -= 360.0;
}
if(keyStates['q'])
exit(0);
}
// I guess it has to be done in this function
// but didn't get how
void camera()
{
glLoadIdentity();
// Forward / Backward
glTranslated(.0, .0, z_offset);
// Left / Right
glTranslated(x_offset, .0, .0);
// XZ Rotation
glRotated(angle_xz, .0, 1.0, .0);
// YZ Rotation
glRotated(angle_yz, 1.0, .0, .0);
}
void display(void)
{
keyboardOperations();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera();
drawFloor();
drawBalls();
glutSwapBuffers();
}
void reshape(int width, int height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
GLdouble aspect = (GLdouble) width / (GLdouble) height;
gluPerspective(60, aspect, 1, 100);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("openGLtest3");
glClearColor(.0, .0, .0, .0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(display);
glutIgnoreKeyRepeat(true);
glutKeyboardFunc(keyPressed);
glutKeyboardUpFunc(keyReleased);
glutMainLoop();
return 0;
}
In openGL, glRotation fuction takes origin as a reference. In order to rotate around a point (your camera coordinate in this case) you should translate your camera position to the origin (Translate all your objects accordingly) and then apply rotation function.And then you can translate your camera back (with all your objects)
lets say your camera position is (a,b,c) so your code should be something like :
foreach object
{
glPushMatrix();
glTranslate(a,b,c);
glRotate(...);
glTranslate(-a,-b,-c);
//render
glPopMatrix();
}
I'm trying to create an effect of zooming on a rotating hexagon. I'm accomplishing this by changing the window. Once it "zooms in" it supposed to "zoom out", and then repeat continuously. I've managed to zoom in just fine, and by the looks of my code, it should zoom out as well, but once it zooms in, nothing else is drawn. I've debugged my code, and i can tell that the variables are indeed being incremented on this line:
gluOrtho2D(cx - w, cx + w, cy -h, cy +h);
But yet i still fail to see my hexagon "zoom out". Any help would be appreciated. I'm pretty sure its something simple i'm forgetting. But it keeps eluding me. My code follows:
#include <cstdlib>
#include <GL/glut.h>
#include <cmath>
#define PI 3.14159265
#define ZOOM_IN 1
#define ZOOM_OUT -1
using namespace std;
const int screenWidth = 500;
const int screenHeight = 500;
float cx = 0.0, cy = 0.0; //center of viewport (cx, cy)
float h=1.2, w = 1.2; //window size
int NumFrames = 10; //frames
int frame = 0;
int direction = ZOOM_IN;
//<<<<<<<<<<<<<<<<<<<<<<< myInit >>>>>>>>>>>>>>>>>>>>
void myinit() {
glClearColor (1.0, 1.0, 1.0, 1.0); //set the background color to white
glColor3f (0.0, 0.0, 0.0); //set the foreground color to black
glPointSize (3.0); //set the point size to 3 X 3 pixels
glViewport (0.0, 0.0, 500.0, 500.0); //set the viewport to be the entire window
//set up a world window to screen transformation
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-5.0, 5.0, -5.0, 5.0);
// glMatrixMode (GL_MODELVIEW);
}
//<<<<<<<<<<<<<<<<<<<<<<< hexswirl >>>>>>>>>>>>>>>>>>>>
void hexswirl() {
double angle; //the angle of rotation
double angleInc = 2*PI/6.0; //the angle increment
double inc = 5.0/50; //the radius increment
double radius = 5.0/50.0; //the radius to be used
//clear the background
glClear (GL_COLOR_BUFFER_BIT);
//draw the hexagon swirl
for (int j = 0; j <= 50; j++) {
//the angle of rotation depends on which hexagon is
//being drawn.
angle = j* (PI/180.0);
//draw one hexagon
glBegin (GL_LINE_STRIP);
for (int k=0; k <= 6; k++) {
angle += angleInc;
glVertex2d(radius * cos(angle), radius *sin(angle));
}
glEnd();
//determine the radius of the next hexagon
radius += inc;
}
//swap buffers for a smooth change from one
//frame to another
glutSwapBuffers();
glutPostRedisplay();
glFlush();
}
//<<<<<<<<<<<<<<<<<<<<<<< viewZoom >>>>>>>>>>>>>>>>>>>>
void viewZoom(int i) {
if(direction == ZOOM_IN) {
//change the width and height of the window each time
w *= 0.9;
h *= 0.9;
}
if(direction == ZOOM_OUT) {
w /= 0.9;
h /= 0.9;
}
if(i%10 == 0) {
direction = -direction;
}
//change the window and draw the hexagon swirl
gluOrtho2D (cx - w, cx + w, cy - h, cy + h);
hexswirl();
glutPostRedisplay();
glutTimerFunc(200, viewZoom,i+1);
}
//<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(100,100);
glutCreateWindow("hexanim");
glutDisplayFunc(hexswirl);
viewZoom(1);
myinit();
glutMainLoop();
return 1;
}
I figured out a way around my problem. I still don't know why my window wasn't redrawing after "zooming in", but i decided to implement it through changing my viewport instead. I ended up switching out:
gluOrtho2D (cx - w, cx + w, cy - h, cy + h);
for
cx = screenWidth / w;
cy = screenHeight / h;
glViewport((screenWidth-cx)/2, (screenHeight-cy)/2, cx, cy);
(and made all the corresponding changes associated with it).