开发者

How to keep trace of the change of light position?

I am trying to make a very simple MFC OpenGL tutorial.

There is a sphere. And the spere is the source of light(like sun). And there is two triangle. According to movement of the spere, I want to have the triangles lightend.

But When I move the sphere, the surface of the triangle changed only for the first time.

Next movement of the sphere don't change the surface the the triangle.

How to keep trace of the light position?

This is the keyborad handler function.

void CView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_UP)
    {
        m.x += 0.1f;
    }
    else if (nChar == VK_DOWN)
    {
        m.y -= 0.1f;
    }
    else if (nChar == VK_LEFT)
    {
        m.x -= 0.1f;
    }
    else if (nChar == VK_RIGHT)
    {
        m.x += 0.1f;
    }
    setGL();
    DrawGL();
    CView::OnKeyDown(nChar, nRepCnt, nFlags);
}  

And these are the functions which called by keyboard function.

void CView::setGL(GLvoid)           
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);       
    glClearDepth(1.0f); 
    glEnable(GL_DEPTH_TEST);    
    glDepthFunc(GL_LEQUAL);             
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    // light source configuration ##################
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.f,0.f,1.f, 0.f,0.f,0.f, 0.f,1.f,0.f);

    GLfloat light0_diffuse[] = {0.5, 0.5, 1.0};
    GLfloat light0_specular[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat light0_spot_direction[] = {1,1,1,0};

    GLfloat light1_diffuse[] = {1.0f, 0.3f, 0.3f};
    GLfloat light1_specular[] = {1.0f, 0.8f, 0.8f, 1.0f};
    GLfloat light1_shiniess[] = {50.0};
    GLfloat light1_pos[] = {m.x, m.y, m.z};

    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightfv(GL_LIGHT0, GL_SPOT_开发者_运维技巧DIRECTION, light0_spot_direction);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
    glLightfv(GL_LIGHT1, GL_SHININESS, light1_shiniess);
    glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
}

void CView::DrawGL(void)                
{
    // clear screen and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity();
    // camera view configuration 
    gluLookAt(0.0f,0.0f,1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);

    // draw 
    //glColor3f(1.f, 1.f, 1.f);
    glPushMatrix();
    glTranslatef(m.x, m.y, m.z);
    glutSolidSphere(0.25f, 120, 120);

    glPopMatrix();
    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5f, 0.5f, -0.5f);
    glVertex3f(0.0f, 0.0f, -0.5f);
    glVertex3f(-1.0f, 0.0f, -0.5f);

    m.calculateNormal(-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -1.0f, 0.0f, -0.5f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);

    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, -1.0f);
    glVertex3f(0.0f, 0.0f, -1.0f);
    glVertex3f(1.0f, 0.0f, -1.0f);

    m.calculateNormal(0.5f, 0.5f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);

    glEnd();

    // swap buffer
    SwapBuffers(m_hDC);
}


You should never place drawing calls in a input event handler. That's your main problem. The other problem is – so it seems – that you confuse OpenGL for a scene graph.

OpenGL is a drawing API with no recollection of a scene, whatsoever. In your input handler you set some variables, issue a redraw event and then in the drawing event handler render from those variables. OpenGL being a state machine drawing API also means, that there is no explicit initialization phase. A function like setGL makes no sense whatsoever. What you do in setGL actually belongs into the drawing function. This includes setting the viewport and the projection matrix!

void CView::drawGL(GLvoid)           
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);       
    glClearDepth(1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glViewport(…);
    glMatrixMode(GL_PROJECTION);
        set_projection_matrix(…);    

    // light source configuration ##################
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); // gluLookAt expects to work from a identity matrix.
    gluLookAt(0.f,0.f,1.f, 0.f,0.f,0.f, 0.f,1.f,0.f);

    GLfloat light0_diffuse[] = {0.5, 0.5, 1.0};
    GLfloat light0_specular[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat light0_spot_direction[] = {1,1,1,0};

    GLfloat light1_diffuse[] = {1.0f, 0.3f, 0.3f};
    GLfloat light1_specular[] = {1.0f, 0.8f, 0.8f, 1.0f};
    GLfloat light1_shiniess[] = {50.0};
    GLfloat light1_pos[] = {m.x, m.y, m.z};

    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_spot_direction);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
    glLightfv(GL_LIGHT1, GL_SHININESS, light1_shiniess);
    glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // draw 
    glColor3f(1.f, 1.f, 1.f);
    glPushMatrix();
    glTranslatef(m.x, m.y, m.z);
    glutSolidSphere(0.25f, 120, 120);
    glPopMatrix();

    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5f, 0.5f, -0.5f);
    glVertex3f(0.0f, 0.0f, -0.5f);
    glVertex3f(-1.0f, 0.0f, -0.5f);

    m.calculateNormal(-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -1.0f, 0.0f, -0.5f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);

    glBegin(GL_TRIANGLES);
    glVertex3f(0.5f, 0.5f, -1.0f);
    glVertex3f(0.0f, 0.0f, -1.0f);
    glVertex3f(1.0f, 0.0f, -1.0f);

    m.calculateNormal(0.5f, 0.5f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f);
    glNormal3f(m.normalX, m.normalY, m.normalZ);
    glEnd();

    // swap buffer
    SwapBuffers(m_hDC);
}

The calls to glLight… happen in the context of the currently set state (most importantly for the lights is the modelview matrix). The light positions are multiplied by the modelview matrix. If using gluLookAt, which you do, the calls to glLightfv(GL_LIGHT<n>, GL_POSITION, …) must happen after gluLookAt and before drawing the illuminated geometry.


void CView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    ...
    CView::OnKeyDown(nChar, nRepCnt, nFlags);
}  

How isn't that an infinite recursive call? Doesn't your compiler warn you about this?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜