Help end child hunger

The Code So Far II

 
Prev: Moving the Camera III Next: Popup Menus
 
#include <stdlib.h>
#include <math.h>

#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

// angle of rotation for the camera direction
float angle = 0.0f;

// 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;

// the key states. These variables will be zero
//when no key is being presses
float deltaAngle = 0.0f;
float deltaMove = 0;
int xOrigin = -1;

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);

	// Get Back to the Modelview
	glMatrixMode(GL_MODELVIEW);
}

void drawSnowMan() {

	glColor3f(1.0f, 1.0f, 1.0f);

// Draw Body
	glTranslatef(0.0f ,0.75f, 0.0f);
	glutSolidSphere(0.75f,20,20);

// Draw Head
	glTranslatef(0.0f, 1.0f, 0.0f);
	glutSolidSphere(0.25f,20,20);

// Draw Eyes
	glPushMatrix();
	glColor3f(0.0f,0.0f,0.0f);
	glTranslatef(0.05f, 0.10f, 0.18f);
	glutSolidSphere(0.05f,10,10);
	glTranslatef(-0.1f, 0.0f, 0.0f);
	glutSolidSphere(0.05f,10,10);
	glPopMatrix();

// Draw Nose
	glColor3f(1.0f, 0.5f , 0.5f);
	glRotatef(0.0f,1.0f, 0.0f, 0.0f);
	glutSolidCone(0.08f,0.5f,10,2);
}

void computePos(float deltaMove) {

	x += deltaMove * lx * 0.1f;
	z += deltaMove * lz * 0.1f;
}

void renderScene(void) {

	if (deltaMove)
		computePos(deltaMove);

	// 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();

// Draw 36 SnowMen

	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 processNormalKeys(unsigned char key, int xx, int yy) { 	

        if (key == 27)
              exit(0);
} 

void pressKey(int key, int xx, int yy) {

       switch (key) {
             case GLUT_KEY_UP : deltaMove = 0.5f; break;
             case GLUT_KEY_DOWN : deltaMove = -0.5f; break;
       }
} 

void releaseKey(int key, int x, int y) { 	

        switch (key) {
             case GLUT_KEY_UP :
             case GLUT_KEY_DOWN : deltaMove = 0;break;
        }
} 

void mouseMove(int x, int y) { 	

         // this will only be true when the left button is down
         if (xOrigin >= 0) {

		// update deltaAngle
		deltaAngle = (x - xOrigin) * 0.001f;

		// update camera's direction
		lx = sin(angle + deltaAngle);
		lz = -cos(angle + deltaAngle);
	}
}

void mouseButton(int button, int state, int x, int y) {

	// only start motion if the left button is pressed
	if (button == GLUT_LEFT_BUTTON) {

		// when the button is released
		if (state == GLUT_UP) {
			angle += deltaAngle;
			xOrigin = -1;
		}
		else  {// state = GLUT_DOWN
			xOrigin = x;
		}
	}
}

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("Lighthouse3D - GLUT Tutorial");

	// register callbacks
	glutDisplayFunc(renderScene);
	glutReshapeFunc(changeSize);
	glutIdleFunc(renderScene);

	glutIgnoreKeyRepeat(1);
	glutKeyboardFunc(processNormalKeys);
	glutSpecialFunc(pressKey);
	glutSpecialUpFunc(releaseKey);

	// here are the two new functions
	glutMouseFunc(mouseButton);
	glutMotionFunc(mouseMove);

	// OpenGL init
	glEnable(GL_DEPTH_TEST);

	// enter GLUT event processing cycle
	glutMainLoop();

	return 1;
}

Check out the source code at GitHub.

 

Prev: Moving the Camera III Next: Popup Menus
 

  16 Responses to “The Code So Far II”

  1. Why is the code:

    //if (deltaAngle)
    // computeDir(deltaAngle);

    removed from this example?

  2. Here is my code. Just some differences. And one problem: I can’t reply on your page by Firefox.

    #include
    #include
    #include

    float angle = 0;
    float xView = 0, yView = 2, zView = 7;
    float lx = 0, ly = 0, lz = -1;

    int xOrigin = -1, yOrigin = -1, zOrigin = -1;

    float deltaAngle = 0;
    //float deltaMove = 0;

    void changeSize(int width, int height);
    void drawSnowMan();
    void display(void);
    void processNormalKeys(unsigned char key, int x, int y);
    void processSpecialKeys(int key, int x, int y);

    void mouseMove(int x, int y);
    void mouseButton(int button, int state, int x, int y);

    void changeSize(int width, int height)
    {
    if (height == 0)
    {
    height = 1;
    }

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0, 0, width, height);
    float aspect = width / height;
    gluPerspective(45, aspect, 0.1, 100);
    glMatrixMode(GL_MODELVIEW);
    }

    void drawSnowMan()
    {
    glColor3f(1, 1, 1);
    glTranslatef(0, 0.75, 0);
    glutWireSphere(0.75, 10, 10);
    glTranslatef(0, 1, 0);
    glutSolidSphere(0.25, 10, 10);
    glPushMatrix();

    //Draw eyes
    glTranslatef(0.1, 0, 0.23);
    glColor3f(0, 0, 1);
    glutSolidSphere(0.03, 10, 10);
    glTranslatef(-0.2, 0, 0);
    glutSolidSphere(0.03, 10, 10);

    glPopMatrix();
    glTranslatef(0, -0.05, 0.25);
    glColor3f(1, 0, 0);
    glutSolidCone(0.025, 0.25, 4, 4);

    }

    void display(void)
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluLookAt(xView, yView, zView,
    xView + lx, yView + ly, zView + lz,
    0, 1, 0);
    glRotatef(angle, 0, 1, 0);

    glColor3f(1, 0, 0);
    glLineWidth(3);
    glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(1.5, 0, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 3, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, 1.5);
    glEnd();

    glColor3f(0.5, 0.5, 0.5);
    glBegin(GL_QUADS);
    glVertex3f(-100, 0, -100);
    glVertex3f(-100, 0, 100);
    glVertex3f(100, 0, 100);
    glVertex3f(100, 0, -100);
    glEnd();

    drawSnowMan();

    glutSwapBuffers();

    }

    void processNormalKeys(unsigned char key, int x, int y)
    {
    switch (key)
    {
    case 27:
    exit(0);
    break;
    }
    }

    void processSpecialKeys(int key, int x, int y)
    {
    switch (key)
    {
    case GLUT_KEY_LEFT:
    angle -= 0.5;
    break;

    case GLUT_KEY_RIGHT:
    angle += 0.5;
    break;

    case GLUT_KEY_UP:
    zView -= 0.5;
    break;

    case GLUT_KEY_DOWN:
    zView += 0.5;
    break;
    }
    }

    void mouseMove(int x, int y)
    {
    if (xOrigin >= 0 || zOrigin >= 0)
    {
    deltaAngle = acos(((float)xOrigin * x + yOrigin * y) / (sqrt((float)xOrigin * xOrigin + yOrigin * yOrigin) * sqrt((float)x * x + y * y)));
    if (x <= xOrigin)
    {
    angle -= deltaAngle * 100;
    xOrigin = x;
    yOrigin = y;
    }
    else
    {
    angle += deltaAngle * 100;
    xOrigin = x;
    yOrigin = y;
    }
    }
    }

    void mouseButton(int button, int state, int x, int y)
    {
    if (button == GLUT_LEFT_BUTTON)
    {
    if (state == GLUT_DOWN)
    {
    xOrigin = x;
    yOrigin = y;
    }
    else
    {
    xOrigin = -1;
    yOrigin = -1;
    }
    }
    }

    int main(int argc, char** argv)
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(680, 680);
    glutCreateWindow("Example 2.4 – Mouse");

    glutDisplayFunc(display);
    glutReshapeFunc(changeSize);
    glutIdleFunc(display);
    glutKeyboardFunc(processNormalKeys);
    glutSpecialFunc(processSpecialKeys);
    //glutIgnoreKeyRepeat(1);
    glutMouseFunc(mouseButton);
    glutMotionFunc(mouseMove);

    glEnable(GL_DEPTH_TEST);

    glutMainLoop();

    return 0;

    }

  3. You have to be careful when you name your variables. I spent like one hour until i figure out that x from expresion (x – xOrigin) is the local x from the function and the same thing at xOrigin = x. Very good tutorial !! I also want to make the camera to move up and down and, as you said, I need another angle variable to move horizontaly

  4. …has been removed from renderScene().

    Sorry about that :/

  5. Note that
    :
    if (deltaAngle)
    computeDir(deltaAngle);

  6. I would also like to thank for for this awesome guide. It has helped me immensely. By adopting the same techniques and functions I have been able to create a decent fractal generator. 😀

  7. It seems to me that, in the function mouseButton the line “angle += deltaAngle” is redundant, since nothing happens if I remove it. Is there another not-obvious reason for this?

    Also, as it is written in the example the camera continues to rotate when I release the left mouse button at the same “speed” as before I released it. If I change the code under the second if, then I can make it stop rotating when I release the left mouse button:

    void mouseButton(int button, int state, int x, int y) {

    // only start motion if the left button is pressed
    if (button == GLUT_LEFT_BUTTON) {

    // when the button is released
    if (state == GLUT_UP) {
    //angle += deltaAngle;
    deltaAngle = 0; // Stops the camera.
    xOrigin = -1;
    }
    else {// state = GLUT_DOWN
    xOrigin = x;
    }
    }
    }

    • Additionally, if you want the camera to only “follow the mouse” (in lack of better expression) instead of letting the difference (x – xOrigin) decide the speed of rotation, you can add one line in the function moveMouse:

      void mouseMove(int x, int y) {

      // this will only be true when the left button is down
      if (xOrigin >= 0) {

      // update deltaAngle
      deltaAngle = (x – xOrigin) * 0.001f;
      xOrigin = x;
      // update camera’s direction
      lx = sin(angle + deltaAngle);
      lz = -cos(angle + deltaAngle);
      }
      }

      • Hi Morten,

        Let me see if I reply properly to your comment.

        1. The speed of rotation is determined only by the multiplication factor 0.001f. Changing this number changes the speed of rotation.
        2. The code in the page is almost equivalent to yours if instead of deltaAngle = (x – xOrigin) * 0.001f; you write angle += (x – xOrigin) * 0.001f;. However it is not strictly equivalent due to resolution issues. What i mean is that if you move the mouse 10 pixels to the right you’re going to sum 10 times the step, whereas the site’s solution sums only once (ten times the step). This is not equivalent due to floating point resolution issues, i.e. step+step+…+step (n times) is different from n * step. Although you get almost the same result, it is not exactly the same. So in short, the code in the tutorial is a tiny bit more accurate than yours, although in most examples the difference is irrelevant.

        Actually it is not quite the same due to resolution issues. I

        • What I wanted to say by “speed” was actually “how far it moves”. Without xOrigin = x it will continue to rotate until you release the button or somehow change the direction by other means (If I recall correctly).

          I extended the code so that you can look up-down in addition to left-right. It is far from perfect, but may be able to help others who want to try something similar. The camera still moves if you hold down the right mouse button, but only slighty (I swear it didn’t happen last time I tried! :S)

          Here: http://folk.ntnu.no/mortevas/fractal/GLUT/main.cpp

    • Hi,

      If you remove the line “angle += deltaAngle” you could see a jump next time you press the mouse. Notice that in the function mouseMove only deltaAngle is being updated, not the angle itself.

      As for the camera rotation I have not been able to reproduce your situation, but adding “deltaAngle = 0” should be a good safeguard against those situations.

      • In my code (the one linked in the comment above) there is no noticable difference if I remove the line “angle += deltaAngle” or not. On the other hand. If I keep the three lines below “// update camera’s direction” in the function mouseMove, it jumps each time I press the right button, so I’ve commented them out. I may have changed the code too much for it to act like in the example, I guess.

  8. oh… sry that was from the code with the keyboard… ich copied the mouse code into that one…
    gotta leave my appreciation here as well: thx for supplying a tutorial for glut/opengl that would have taken me weeks to learn otherwise!

  9. Hi,
    why do u update the lx and lz vars, 2 times ?
    once in the mouseMove func and once in the computeDir func
    seems unnecessary

  10. Wow, the first actually understandable tutorial on the internet to starting OpenGL with GLUT ( I haven’t done pure OGL yet, I figured starting managed and then moving to the native is easier.).
    Thank you.
    BTW, the interface now looks like the FPS games’ interface, with constant forward movement and mouse direction changing.
    You rock!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: