Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL: two bodies with two independent sources of light rotating around them

I am new to OpenGL. I want to write a program that displays two shapes of two different colors, a Torus and a Sphere and two independent light sources that rotate around them.

So far I have this code which makes a light source that rotates around the Torus nicely. However I am unable to figure out how to add a Sphere and a new light source that rotates around it.

EDIT:

Here is my whole code. The light rotates when you push the 's' or 'd' key on keyboard

#include "stdafx.h"
#include <windows.h>
#include <glut.h>

static int spin = 0;
bool updown = false;
bool leftright = false;

GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat direction[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat direction2[] = { 1.0, 0.0, 0.0, 0.0 };

void display() {
    GLfloat position[] = { 0.0, 0.0, 1.5, 1.0 };
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan);
    glMaterialfv(GL_FRONT, GL_SPECULAR, white);
    glMaterialf(GL_FRONT, GL_SHININESS, 30);
    glTranslatef(-2.0, 1.0, 0.0);
    glPushMatrix ();
    if(updown){
        glRotated ((GLdouble) spin, 1.0, 0.0, 0.0);
    }
    if(leftright){
       glRotated ((GLdouble) spin, 0.0, 1.0, 0.0);
    }
    glLightfv (GL_LIGHT0, GL_POSITION, position);

    glTranslated (0.0, 0.0, 1.5);
    glDisable (GL_LIGHTING);
    glColor3f (0.0, 1.0, 1.0);
    glEnable (GL_LIGHTING);
    glPopMatrix();
    glutSolidTorus(0.275, 0.85, 16, 40);
    glPopMatrix();
    glFlush();
}

void reshape(GLint w, GLint h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    GLfloat aspect = GLfloat(w) / GLfloat(h);
    glLoadIdentity();
    if (w <= h) {
        glOrtho(-2.5, 2.5, -2.5/aspect, 2.5/aspect, -10.0, 10.0);
    } else {
        glOrtho(-2.5*aspect, 2.5*aspect, -2.5, 2.5, -10.0, 10.0);
    }
}
void init() {
    glLightfv(GL_LIGHT0, GL_AMBIENT, black);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, yellow);
    glLightfv(GL_LIGHT0, GL_SPECULAR, white);

    glEnable(GL_LIGHTING);                
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);              
}

void keyboard(unsigned char button, int x, int y)
{
    switch (button) {
        case 's':
            updown = true;
            leftright = false;
            spin = (spin + 30) % 360;
            glutPostRedisplay();
            break;
        case 'd':
            updown = false;
            leftright = true;
            spin = (spin + 30) % 360;
            glutPostRedisplay();
            break;
        default:
            break;
   }
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(80, 80);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Shapes and light");
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutDisplayFunc(display);
    init();
    glutMainLoop();
}
like image 678
Helena Avatar asked Jan 22 '26 22:01

Helena


1 Answers

I believe the problem is more conceptual. OpenGL is stateful. What that means in practice is that you modify the state, draw something, modify the state again, draw something else. The state of OpenGL 1.x includes the matrix stack, materials, and the lights.

I believe in your mind, you want to add a new light object, then add a new object to draw, then have OpenGL render that. That is not how OpenGL works. There are no real objects in OpenGL.

What happens when you draw something, e.g. with glutSolidTorus, is that OpenGL puts pixels into buffers, including the screen. To determine the color of these pixels, it looks at the state you put it in before. So in order to draw two objects, you would first set up lighting, material, position for the first object, call glutSolidTorus, then set up the lighting, material, position for the second object, call glutSolidSphere. Note that you don't need to "add a new material", or "add a new light" for rendering the sphere. All you need to do is change the state before rendering, e.g. by moving GL_LIGHT0 to a different position.

like image 75
Andreas Haferburg Avatar answered Jan 25 '26 16:01

Andreas Haferburg