Hi,
I am trying to create a prototype program that allows for a spotlight to be moved (and rotated) around a scene depending on user mouse input.
Unfortunately I am a complete noob at OpenGL and don't seem to be able to make it move as intended. It is behaving as a directional light and not positional. No matter what I do I cannot seem to make the light rotate and move around the scene. Rather, it has always the same origin and *doesn't* rotate. All I /can/ do is move what seems to be the "spotlight direction" - from the origin to some end point, which gives the impression that the light is spreading.
You can see a couple of screenshots at this link:
http://picasaweb.google.co.uk/0v3rloader/UntitledAlbum
The leftmost picture shows the light at its initial position - no translations/rotations performed. The rightmost one shows the light *after* having been translated along the (negative) z-axis. There is also a green vector showing what *should be* the light's current direction and position.
As you can see it is not working as it should. Below you can find some code snippets that should help you understand what I am doing wrong :)
- Initializations are done like so:
void CScene::Init()
{
GLfloat afAmbientLight[] = {0.4f, 0.4f, 0.4f, 1.0f};
GLfloat no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_FOG_HINT, GL_NICEST);
glEnable(GL_LIGHTING);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_mat);
}
- The method that sets up the light and draws the vector:
void CLight::Draw()
{
glPushMatrix();
GLfloat glfPosition[4];
GLfloat samplelight[]={1.,1.,1.,1.};
// the position of the light
glfPosition[0] = 0;
glfPosition[1] = 0;
glfPosition[2] = 0;
glfPosition[3] = 1.0f;
// transform light position/rotation accordingly
glTranslatef(m_fX, m_fY, m_fZ);
glRotatef(m_fAX, 1.0f, 0.0f, 0.0f);
glRotatef(m_fAY, 0.0f, 1.0f, 0.0f);
glRotatef(m_fAZ, 0.0f, 0.0f, 1.0f);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, samplelight);
glLightfv(GL_LIGHT0, GL_SPECULAR, samplelight);
glLightfv(GL_LIGHT0, GL_POSITION, glfPosition);
// draw the vector
glMaterialfv(GL_FRONT, GL_EMISSION, mat_diffuse);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
{
glColor3f(0,1,0);
glVertex3f(0, 10, 0);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, 0);
glVertex3f(-0.4f, 0.6f, 0);
glVertex3f(0, 0, 0);
glVertex3f(0.4f, 0.6f, 0);
}
glEnd();
glEnable(GL_LIGHTING);
glPopMatrix();
}
- Method that handles drawing of the scene:
void CMainScene::Draw(DWORD dwMsElapsed)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// this is here temporarily until I get this sorted out
static GLfloat fX = 0, fY = -15, fZ = -55;
static GLfloat fRX = 20, fRY = 0, fRZ = 0;
// transform camera or light
if(::GetGLMainWnd()->IsKeyDown(VK_CONTROL))
{
fX -= m_pMiceInfo[0].pos.x;
fY += m_pMiceInfo[0].pos.y;
fZ -= m_pMiceInfo[1].pos.y;
fRX += m_pMiceInfo[2].pos.y * m_fRotScalingFactor;
fRY += m_pMiceInfo[1].pos.x * m_fRotScalingFactor;
fRZ += m_pMiceInfo[2].pos.x * m_fRotScalingFactor;
}
else
{
m_Light.AddXBy(m_pMiceInfo[0].pos.x * m_fXYScalingFactor);
m_Light.AddYBy((-m_pMiceInfo[0].pos.y) * m_fXYScalingFactor);
m_Light.AddZBy(m_pMiceInfo[1].pos.y * m_fRotScalingFactor);
m_Light.AddYAngleBy((-m_pMiceInfo[1].pos.x) * m_fRotScalingFactor);
m_Light.AddZAngleBy((-m_pMiceInfo[2].pos.x) * m_fRotScalingFactor);
m_Light.AddXAngleBy(m_pMiceInfo[2].pos.y * m_fRotScalingFactor);
}
// similar to gluLookAt, only not
glTranslatef(fX, fY, fZ);
glRotatef(fRX, 1,0,0);
glRotatef(fRY, 0,1,0);
glRotatef(fRZ, 0,0,1);
// let's start drawing
m_Light.Draw();
glCallList(O3D_FLOOR);
glCallList(O3D_WALLS);
// flush, swap and all done!
glFlush();
::SwapBuffers(m_poWndParent->GetDC());
}
I really am in need of some expert help. I welcome any comments/suggestions you may have.
[EDIT]Added link to pics.[/EDIT