Unable to glTranslate() light source

66 Views Asked by At

I am having a problem translating the light source.

I have coded a program that accepts up, down, left, and right keys to increase/decrease the x, y, and z values to reposition the light source. But the problem right now is the x, y, and z value does change but the light source remains in the same place. I believe the problem shall be somewhere inside the void lighting() function.

below is my code:

#include <Windows.h>
#include <gl/GL.h>
#include <math.h>
#include <gl/GLU.h>

#pragma comment (lib, "OpenGL32.lib") //link library
#pragma comment(lib, "Winmm.lib")

#define WINDOW_TITLE "Lighting"

bool isOrtho = true;
float ONear = -10.0, OFar = 10.0;   //Ortho Near & Far
float PNear = 1.0, PFar = 21.0;     //Perspective Near & Far
float exeDif[3] = { 1.0,0.0,0.0 };  //Red diffuse light
float x =6 , y=0, z=0;
float exePosD[3] = { 6,0,0 };
float exeDifM[3] = { 1.0,0.0,0.0 };
bool isLightOn = false;     //is light on?

LRESULT WINAPI WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);//quit application
        break;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE) PostQuitMessage(0);
        else if (wParam == VK_SPACE) {
            isLightOn = !isLightOn;
        }
        else if (wParam == VK_UP) {
            y = y + 1.0;
        }
        else if (wParam == VK_DOWN) {
            y = y - 1.0;
        }
        else if (wParam == VK_LEFT) {
            x = x - 1.0;
        }
        else if (wParam == VK_RIGHT) {
            x = x + 1.0;
        }
        else if (wParam == 'Q') {
            z = z - 1.0;
        }
        else if (wParam == 'E') {
            z = z + 1.0;
        }

        break;
    default:
        break;
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}

bool initPixelFormat(HDC hdc)
{
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));

    pfd.cAlphaBits = 8;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 0;

    pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;

    pfd.iLayerType = PFD_MAIN_PLANE;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;

    // choose pixel format returns the number most similar pixel format available
    int n = ChoosePixelFormat(hdc, &pfd);

    // set pixel format returns whether it sucessfully set the pixel format
    if (SetPixelFormat(hdc, n, &pfd))
    {
        return true;
    }
    else
    {
        return false;
    }
}

void lighting() {
    if (isLightOn) {
        glEnable(GL_LIGHTING);          //Turon on lighting for the whole scene
    }
    else {
        //Turn off lighting for the whole screen
        glDisable(GL_LIGHTING);
    }
    
    glPushMatrix();
    glTranslatef(x, y, z);
    glLightfv(GL_LIGHT0, GL_POSITION, exePosD);
    glPopMatrix();

    glLightfv(GL_LIGHT0, GL_DIFFUSE, exeDif);

    glEnable(GL_LIGHT0);
}

void projection() {
    glMatrixMode(GL_PROJECTION);    //refer to projection matrix
    glLoadIdentity();               //reset projection matrix
    if (isOrtho) {
        //Ortho View
        glOrtho(-10.0, 10.0, -10.0, 10.0, ONear, OFar); //Ortho view
    }
    else {
        //Perspective view
        gluPerspective(20, 1.0, -1.0, 1.0);
        glFrustum(-10.0, 10.0, -10.0, 10.0, PNear, PFar);
    }
}

void drawSphere(double r) {
    GLUquadricObj* sphere = NULL;
    sphere = gluNewQuadric();
    gluQuadricDrawStyle(sphere, GLU_FILL);
    gluSphere(sphere, r, 30, 30);
    gluDeleteQuadric(sphere);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);

    projection();                   //projection
    lighting();

    glMatrixMode(GL_MODELVIEW);     //refer to modelview matrix
    glLoadIdentity();               //reset
    drawSphere(3.0);

    //red color diffuse
    glMaterialfv(GL_FRONT, GL_DIFFUSE, exeDifM);

    glColor3f(0.0, 0.0, 1.0);       //blue
    drawSphere(3.0);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpfnWndProc = WindowProcedure;
    wc.lpszClassName = WINDOW_TITLE;
    wc.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClassEx(&wc)) return false;

    HWND hWnd = CreateWindow(WINDOW_TITLE, WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
        720, 10, 300, 300,
        NULL, NULL, wc.hInstance, NULL);

    //--------------------------------
    //  Initialize window for OpenGL
    //--------------------------------

    HDC hdc = GetDC(hWnd);

    //  initialize pixel format for the window
    initPixelFormat(hdc);

    //  get an openGL context
    HGLRC hglrc = wglCreateContext(hdc);

    //  make context current
    if (!wglMakeCurrent(hdc, hglrc)) return false;

    //--------------------------------
    //  End initialization
    //--------------------------------

    ShowWindow(hWnd, nCmdShow);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT) break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        display();

        SwapBuffers(hdc);
    }

    UnregisterClass(WINDOW_TITLE, wc.hInstance);

    return true;
}

This is the output screen:

1

There are 1 best solutions below

0
Rabbid76 On BEST ANSWER

The light position is transformed with the modelview matrix, but not with the projection matrix. Therefore you need to switch to the modelview matrix after projection() and before lighting():

projection();                   //projection

glMatrixMode(GL_MODELVIEW);     //refer to modelview matrix
glLoadIdentity();        

lighting();