3dObjectLight.cpp
资源名称:gloop.zip [点击查看]
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:24k
源码类别:
OpenGL
开发平台:
Visual C++
- /////////////////////////////////////////////////////////////////////////////
- // 3dObjectLight.cpp : implementation file
- //
- // glOOP (OpenGL Object Oriented Programming library)
- // Copyright (c) Craig Fahrnbach 1997, 1998
- //
- // OpenGL is a registered trademark of Silicon Graphics
- //
- //
- // This program is provided for educational and personal use only and
- // is provided without guarantee or warrantee expressed or implied.
- //
- // Commercial use is strickly prohibited without written permission
- // from ImageWare Development.
- //
- // This program is -not- in the public domain.
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "glOOP.h"
- #include "3dObjectDialog.h"
- #include <math.h>
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- //////////////////////////////////////////////////////////////////
- // C3dObjectLight local variables
- // To allow the user to modify certain characteristics of the light object,
- // such as moving the lights' direction and the spot lights direction points
- // we have defined the following local global variables to 'mimic' these
- // object features.
- static C3dPoint SpotRadius1;
- static C3dPoint SpotRadius2;
- static C3dPoint SpotRadius3;
- static C3dPoint SpotRadius4;
- static C3dPoint LightDirection;
- static GLfloat fSelectedRotation[3]; // User selected light rotation
- //////////////////////////////////////////////////////////////////
- // C3dObjectLight
- IMPLEMENT_SERIAL(C3dObjectLight, C3dObject, 0)
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectLight construction
- C3dObjectLight::C3dObjectLight()
- {
- // Set the member attributes to default values..
- m_iType = LIGHT_OBJECT;
- m_szName.Format("Light %u", nLights++);
- m_iLightType = LIGHT_POINT;
- m_iDisplayAs = DISPLAY_SPHERE;
- // If the w component of the position is 0.0, the light
- // is treated as a directional source. Diffuse and specular
- // lighting calculations take the lights direction, but
- // not its actual position, into account, and attenuation
- // is disabled. Otherwise, diffuse and specular lighting
- // calculations are based on the actual location of the
- // light in eye coordinates, and attenuation is enabled.
- // Note:
- // The W component is initialized at creation and is
- // NEVER modified again (this defines the type of light)
- m_fOrigin[0] = 5.0f; // X coordinate
- m_fOrigin[1] = -5.0f; // Y coordinate
- m_fOrigin[2] = 5.0f; // X coordinate
- m_fOrigin[3] = 1.0f; // W coordinate
- SetDirection(0.0f, 0.0f, 6.5f); // Light points along the Z-Axis
- SetRotation(225.0f, -35.0f, 0.0f); // Rotate so that Z-Axis looks at world origin
- m_ColorAmbient.SetColor4f(0.2f, 0.2f, 0.2f, 1.0f);
- m_ColorDiffuse.SetColor4f(0.7f, 0.7f, 0.7f, 1.0f);
- m_ColorSpecular.SetColor4f(0.9f, 0.9f, 0.9f, 1.0f);
- m_fRadius = 0.5f;
- m_fLength = 2.0f;
- m_fSpotAngle = 180.0f;
- m_fSpecHighlight = 0.0f;
- m_fConstantAttenuation = 1.0f;
- m_fLinearAttenuation = 0.0f;
- m_fQuadraticAttenuation = 0.0f;
- // Create a quadratic object so that we can display
- // the light source in the world
- m_pQuad = gluNewQuadric();
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectLight Destructor
- C3dObjectLight::~C3dObjectLight()
- {
- gluDeleteQuadric(m_pQuad);
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectLight Methods or virtual function implimentation
- void C3dObjectLight::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
- {
- C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
- ASSERT(pSheet);
- // Add the Directional Light attributes page to the property sheet
- pSheet->AddPage(&pSheet->m_LightPage);
- // Save the address of this light in the page
- pSheet->m_LightPage.m_pLight = this;
- pSheet->m_LightPage.m_pWorld = pWorld;
- // Add the Directional Light attributes page to the property sheet
- pSheet->AddPage(&pSheet->m_LightColorPage);
- // Save the address of this light in the page
- pSheet->m_LightColorPage.m_pLight = this;
- pSheet->m_LightColorPage.m_pWorld = pWorld;
- }
- void C3dObjectLight::GetShapeBounds(C3dBoundingBox* pBox)
- {
- // Calculate the bounds of the shape
- if(m_iDisplayAs == DISPLAY_NONE)
- {
- VecClear3f(pBox->m_fMax);
- VecClear3f(pBox->m_fMin);
- }
- else if(m_iDisplayAs == DISPLAY_SPHERE)
- {
- pBox->m_fMax[X] = m_fRadius;
- pBox->m_fMax[Y] = m_fRadius;
- pBox->m_fMax[Z] = m_fRadius;
- pBox->m_fMin[X] = -m_fRadius;
- pBox->m_fMin[Y] = -m_fRadius;
- pBox->m_fMin[Z] = -m_fRadius;
- }
- else if(m_iDisplayAs == DISPLAY_CYLINDER)
- {
- pBox->m_fMax[X] = m_fLength/2;
- pBox->m_fMax[Y] = m_fRadius;
- pBox->m_fMax[Z] = m_fRadius;
- pBox->m_fMin[X] = -m_fLength/2;
- pBox->m_fMin[Y] = -m_fRadius;
- pBox->m_fMin[Z] = -m_fRadius;
- }
- else if(m_iDisplayAs == DISPLAY_RECTANGLE)
- {
- pBox->m_fMax[X] = m_fRadius;
- pBox->m_fMax[Y] = m_fRadius;
- pBox->m_fMax[Z] = 0.0f;
- pBox->m_fMin[X] = -m_fRadius;
- pBox->m_fMin[Y] = -m_fRadius;
- pBox->m_fMin[Z] = 0.0f;
- }
- }
- int C3dObjectLight::LoadBitMapImage(CImageList* pList)
- {
- CBitmap bitmap;
- // If the image index has been stored in this object,
- // return the index.
- if(m_iBMImage > -1)
- return m_iBMImage;
- // If the image index for this object type has been
- // created, store the index for this object and
- // return the index.
- if( iObjectLightBMImage > -1) {
- m_iBMImage = iObjectLightBMImage;
- return m_iBMImage;
- }
- // The image index for this object type has not been
- // loaded and the object image index has not been
- // stored.
- //
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_LIGHT);
- m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- // Load the bitmap for the non-selected light
- bitmap.LoadBitmap(IDB_OBJECT_LIGHT_SELECTED);
- pList->Add(&bitmap, (COLORREF)0xFFFFFF);
- bitmap.DeleteObject();
- iObjectLightBMImage = m_iBMImage;
- return m_iBMImage;
- }
- void C3dObjectLight::Serialize(CArchive& ar, int iVersion)
- {
- CString szBuffer;
- if (ar.IsStoring())
- {
- // Save the Light Class header...
- szBuffer.Format("n%sC3dObjectLight {n", szIndent);
- ar.WriteString(szBuffer);
- // Save the this objects' specific data...
- szBuffer.Format("%stRadius < %f >n", szIndent, m_fRadius);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stDirection < %f %f %f >n", szIndent, m_fDirection[X], m_fDirection[Y], m_fDirection[Z]);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stLight Type < %i >n", szIndent, m_iLightType);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stDisplay As < %i >n", szIndent, m_iDisplayAs);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stAmbientColor < %f %f %f %f > //RGBAn", szIndent, m_ColorAmbient.m_fColor[0], m_ColorAmbient.m_fColor[1], m_ColorAmbient.m_fColor[2], m_ColorAmbient.m_fColor[3]);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stDiffuseColor < %f %f %f %f > //RGBAn", szIndent, m_ColorDiffuse.m_fColor[0], m_ColorDiffuse.m_fColor[1], m_ColorDiffuse.m_fColor[2], m_ColorDiffuse.m_fColor[3]);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stSpecularColor < %f %f %f %f > //RGBAn", szIndent, m_ColorSpecular.m_fColor[0], m_ColorSpecular.m_fColor[1], m_ColorSpecular.m_fColor[2], m_ColorSpecular.m_fColor[3]);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stSpot Exponent < %f >n", szIndent, m_fSpecHighlight);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stCutoff Angle < %f >n", szIndent, m_fSpotAngle);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stConstant Attenuation < %f >n", szIndent, m_fConstantAttenuation);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stLinear Attenuation < %f >n", szIndent, m_fLinearAttenuation);
- ar.WriteString(szBuffer);
- szBuffer.Format("%stQuadratic Atenuation < %f >n", szIndent, m_fQuadraticAttenuation);
- ar.WriteString(szBuffer);
- // Save the base class object data...
- C3dObject::Serialize(ar, iVersion);
- szBuffer.Format("%s}n", szIndent); // end of object def
- ar.WriteString(szBuffer);
- }
- else
- {
- if(iVersion < 102)
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- // Read the derived class data..
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft(); // Remove leading white spaces
- sscanf(szBuffer, "Radius < %f >n", &m_fRadius);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Direction < %f %f %f >n", &m_fDirection[X], &m_fDirection[Y], &m_fDirection[Z]);
- if(iVersion > 103)
- {
- // Set equal to our default direction vector
- SetDirection(0.0f, 0.0f, 6.5f); // Light points along the Z-Axis
- SetRotation(225.0f, -35.0f, 0.0f); // Rotate so that Z-Axis looks at world origin
- // Read new light type and display parameters
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Light Type < %i >n", &m_iLightType);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Display As < %i >n", &m_iDisplayAs);
- }
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "AmbientColor < %f %f %f %f >n", &m_ColorAmbient.m_fColor[0], &m_ColorAmbient.m_fColor[1], &m_ColorAmbient.m_fColor[2], &m_ColorAmbient.m_fColor[3]);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "DiffuseColor < %f %f %f %f >n", &m_ColorDiffuse.m_fColor[0], &m_ColorDiffuse.m_fColor[1], &m_ColorDiffuse.m_fColor[2], &m_ColorDiffuse.m_fColor[3]);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "SpecularColor < %f %f %f %f >n", &m_ColorSpecular.m_fColor[0], &m_ColorSpecular.m_fColor[1], &m_ColorSpecular.m_fColor[2], &m_ColorSpecular.m_fColor[3]);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Spot Exponent < %f >n", &m_fSpecHighlight);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Cutoff Angle < %f >n", &m_fSpotAngle);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Constant Attenuation < %f >n", &m_fConstantAttenuation);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Linear Attenuation < %f >n", &m_fQuadraticAttenuation);
- ar.ReadString(szBuffer);
- szBuffer.TrimLeft();
- sscanf(szBuffer, "Quadratic Attenuation < %f >n", &m_fQuadraticAttenuation);
- if(iVersion < 102)
- // Read all child objects...
- LoadChildObjects(ar, iVersion);
- else
- // Read the base class object data...
- C3dObject::Serialize(ar, iVersion);
- }
- }
- void C3dObjectLight::Build(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- if(m_iLightType == LIGHT_AMBIENT) {
- // Set the lights color component equal to the ambient component
- glColor4fv(m_ColorAmbient.m_fColor);
- // Copy this color to the default color
- m_Color.SetColor4fv(&m_ColorAmbient);
- }
- else {
- // Set the lights color component equal to the diffuse component
- glColor4fv(m_ColorDiffuse.m_fColor);
- m_Color.SetColor4fv(&m_ColorDiffuse);
- }
- // Compile and build the list
- glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
- // Disable lighting calculations..
- glDisable(GL_LIGHTING);
- if(m_iDisplayAs == DISPLAY_SPHERE)
- {
- gluSphere(m_pQuad,
- m_fRadius, // radius
- 10, // slices
- 10); // stacks
- }
- if(m_iDisplayAs == DISPLAY_CYLINDER)
- {
- // Orient along the X-Axis, centered about the XY-Axis
- glTranslatef(0.0f, 1.0f, 0.0f);
- glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
- gluCylinder(m_pQuad,
- m_fRadius, // Base Radius
- m_fRadius, // Top Radius
- m_fLength, // Length of the tube
- 10, // slices
- 10); // stacks
- // Put ends on our tube light
- // Translate to top of Cylinder
- glTranslated(0.0f, 0.0f, m_fLength);
- gluDisk(m_pQuad, 0.0f, m_fRadius, 10, 1);
- // Translate to back to bottom of Cylinder
- glTranslated(0.0f, 0.0f, -m_fLength);
- // Rotate 180 so that bottom is visible
- glRotated(180.0f, 1.0f, 0.0f, 0.0f);
- gluDisk(m_pQuad, 0.0f, m_fRadius, 10, 1);
- }
- if(m_iDisplayAs == DISPLAY_RECTANGLE)
- {
- // Place the Rectangle centered about the Z-Axis on the XY plane
- glBegin(GL_POLYGON); // CCW order...
- glVertex3f(-m_fRadius, m_fRadius, 0.0f);
- glVertex3f( m_fRadius, m_fRadius, 0.0f);
- glVertex3f( m_fRadius, -m_fRadius, 0.0f);
- glVertex3f(-m_fRadius, -m_fRadius, 0.0f);
- glEnd();
- }
- // Re-enable lighting calculations
- glEnable(GL_LIGHTING);
- glEndList();
- }
- void C3dObjectLight::DisplayPoints(C3dWorld* pWorld, C3dCamera* pCamera)
- {
- GLfloat fRadius = 0.12f;
- GLfloat fPointColor[4] = { 0.2f, 0.9f, 0.2f, 1.0f };
- GLfloat fSelectedColor[4] = { 0.9f, 0.0f, 0.2f, 1.0f };
- GLfloat fLineColor[4] = { 0.7f, 0.7f, 0.5f, 1.0f };
- // Disable lighting calculations
- glDisable(GL_LIGHTING);
- // Set new line width
- glLineWidth(2.0f);
- if(m_iLightType != LIGHT_AMBIENT && m_fOrigin[W] != 0.0f)
- {
- // Light is positional and not an ambient light, so display
- // our focal point.
- // Set our light object user selectable point value
- LightDirection.SetOrigin(m_fDirection[X], m_fDirection[Y], m_fDirection[Z]);
- if(pWorld->m_pSelectedPnt == &LightDirection)
- LightDirection.Display(fRadius, fSelectedColor, TRUE);
- else
- LightDirection.Display(fRadius, fPointColor, TRUE);
- // Draw a line from the center of the light to the end point of the
- // lights' focal direction
- glColor4fv(fLineColor);
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3fv(m_fDirection);
- glEnd();
- }
- if(m_iLightType == LIGHT_SPOT)
- {
- float fSpotRadius;
- fSpotRadius = m_fDirection[Z]*(sinf(Radiansf(m_fSpotAngle)));
- // Calculate four (4) spot light radial points around the focal point
- // of the light and set our user selectable point values
- SpotRadius1.SetOrigin(fSpotRadius, 0.0f, 0.0f);
- VecAddf(SpotRadius1.m_fOrigin, m_fDirection, SpotRadius1.m_fOrigin);
- SpotRadius2.SetOrigin(0.0f, fSpotRadius, 0.0f);
- VecAddf(SpotRadius2.m_fOrigin, m_fDirection, SpotRadius2.m_fOrigin);
- SpotRadius3.SetOrigin(-fSpotRadius, 0.0f, 0.0f);
- VecAddf(SpotRadius3.m_fOrigin, m_fDirection, SpotRadius3.m_fOrigin);
- SpotRadius4.SetOrigin(0.0f, -fSpotRadius, 0.0f);
- VecAddf(SpotRadius4.m_fOrigin, m_fDirection, SpotRadius4.m_fOrigin);
- if(pWorld->m_pSelectedPnt == &SpotRadius1)
- SpotRadius1.Display(fRadius, fSelectedColor, TRUE);
- else
- SpotRadius1.Display(fRadius, fPointColor, TRUE);
- if(pWorld->m_pSelectedPnt == &SpotRadius2)
- SpotRadius2.Display(fRadius, fSelectedColor, TRUE);
- else
- SpotRadius2.Display(fRadius, fPointColor, TRUE);
- if(pWorld->m_pSelectedPnt == &SpotRadius3)
- SpotRadius3.Display(fRadius, fSelectedColor, TRUE);
- else
- SpotRadius3.Display(fRadius, fPointColor, TRUE);
- if(pWorld->m_pSelectedPnt == &SpotRadius4)
- SpotRadius4.Display(fRadius, fSelectedColor, TRUE);
- else
- SpotRadius4.Display(fRadius, fPointColor, TRUE);
- // Draw a line from the center of the light around the radius of the
- // end point of the lights' focal direction
- glColor4fv(fLineColor);
- glBegin(GL_LINES);
- glVertex3fv(SpotRadius1.m_fOrigin);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3fv(SpotRadius2.m_fOrigin);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3fv(SpotRadius3.m_fOrigin);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3fv(SpotRadius4.m_fOrigin);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glEnd();
- // Draw a wireframe circle around the spot lights focal point
- float slices = 18.0f;
- for(float i=0.0f; i<=360-slices; i+=slices)
- {
- glBegin(GL_LINES);
- glVertex3f(fSpotRadius*cosf(Radiansf(i)),
- fSpotRadius*sinf(Radiansf(i)),
- m_fDirection[Z]);
- glVertex3f(fSpotRadius*cosf(Radiansf(i+slices)),
- fSpotRadius*sinf(Radiansf(i+slices)),
- m_fDirection[Z]);
- glEnd();
- }
- }
- // Enable lighting calculations and reset the line width
- glEnable(GL_LIGHTING);
- glLineWidth(1.0f);
- }
- C3dPoint* C3dObjectLight::FindPoint(C3dCamera* pCamera, float x, float y, float z)
- {
- Matx4x4 ObjXformMatrix;
- // Get the objects transformation matrix. We will use this to
- // transform each point to world coordinates.
- GetTransformMatrix(ObjXformMatrix);
- // Check to see if the coordinates are our light's 'Direction' end point
- if(LightDirection.IsPoint(pCamera, ObjXformMatrix, x, y, z))
- return &LightDirection;
- if(m_iLightType == LIGHT_SPOT)
- {
- // Check to see if the coordinates are our one of our spot lights'
- // radial points
- if(SpotRadius1.IsPoint(pCamera, ObjXformMatrix, x, y, z))
- return &SpotRadius1;
- if(SpotRadius2.IsPoint(pCamera, ObjXformMatrix, x, y, z))
- return &SpotRadius2;
- if(SpotRadius3.IsPoint(pCamera, ObjXformMatrix, x, y, z))
- return &SpotRadius3;
- if(SpotRadius4.IsPoint(pCamera, ObjXformMatrix, x, y, z))
- return &SpotRadius4;
- }
- // No user selectable light points found
- return NULL;
- }
- void C3dObjectLight::GetObjPointOrigin(C3dPoint* pPoint, float* x, float* y, float* z)
- {
- if(!pPoint)
- return; // No point given
- if(pPoint == &LightDirection)
- {
- // Get the xyz coordinates of our lights direction vector and
- // save the lights current rotation values. (We will use these values
- // in the SetObjPointOrigin() function below.)
- GetDirection(x, y, z);
- VecCopy3f(m_fRotation, fSelectedRotation);
- return;
- }
- // Return the xyz coordinates of the lights spot radius
- if(pPoint == &SpotRadius1)
- {
- *x = m_fDirection[X]+SpotRadius1.m_fOrigin[X];
- *y = m_fDirection[Y];
- *z = m_fDirection[Z];
- return;
- }
- if(pPoint == &SpotRadius2)
- {
- *x = m_fDirection[X];
- *y = m_fDirection[Y]+SpotRadius2.m_fOrigin[Y];
- *z = m_fDirection[Z];
- return;
- }
- if(pPoint == &SpotRadius3)
- {
- *x = m_fDirection[X]+SpotRadius3.m_fOrigin[X];
- *y = m_fDirection[Y];
- *z = m_fDirection[Z];
- return;
- }
- if(pPoint == &SpotRadius4)
- {
- *x = m_fDirection[X];
- *y = m_fDirection[Y]+SpotRadius4.m_fOrigin[Y];
- *z = m_fDirection[Z];
- return;
- }
- // The point is not a selected point of this light
- *x = *y = *z = 0.0f;
- }
- void C3dObjectLight::SetObjPointOrigin(C3dPoint* pPoint, float x, float y, float z)
- {
- if(!pPoint)
- return; // No point given
- if(pPoint == &LightDirection)
- {
- // User has moved the lights direction vector. We want the light vector
- // looking along the z-axis, so we must rotate about the xy-axis to
- // maintain this relationship.
- Matx4x4 InvZRotateMatrix;
- VECTORF LightRotation;
- float rx, ry;
- VecClear3f(LightRotation);
- // Calculate the rotation value of the light based on its
- // new direction vector
- rx = atan(y/m_fDirection[Z]);
- ry = atan(x/m_fDirection[Z]);
- if(rx)
- LightRotation[X] = Degreesf(rx);
- if(ry)
- LightRotation[Y] = Degreesf(ry);
- // Since our light may have a z-axis rotation, we must calcualte
- // the inverse z-axis transformation matrix, then multiply our
- // xy rotation values by the inverse matrix to ensure that our light
- // is rotated properly.
- Rotate3D(Z, -m_fRotation[Z], InvZRotateMatrix);
- VecTransformf(LightRotation, LightRotation, InvZRotateMatrix);
- // Now that we have the oriented xy rotations, add/subtract from
- // our saved values.
- m_fRotation[X] = fSelectedRotation[X] - LightRotation[X];
- m_fRotation[Y] = fSelectedRotation[Y] + LightRotation[Y];
- // We allow the user to move the lights focal point, (direction vector)
- // along the z-axis, so set its coordinate as (0, 0, z)
- m_fDirection[Z] = z;
- }
- // Has the user selected a spot light radial point?
- if(pPoint == &SpotRadius1)
- {
- // Set the spot light radial point coordinate and calculate
- // a new spot angle.
- SpotRadius1.m_fOrigin[X] = x;
- m_fSpotAngle = Degreesf(sin(x/m_fDirection[Z]));
- }
- if(pPoint == &SpotRadius2)
- {
- SpotRadius2.m_fOrigin[Y] = y;
- m_fSpotAngle = Degreesf(sin(y/m_fDirection[Z]));
- }
- if(pPoint == &SpotRadius3)
- {
- SpotRadius3.m_fOrigin[X] = x;
- m_fSpotAngle = Degreesf(sin(-x/m_fDirection[Z]));
- }
- if(pPoint == &SpotRadius4)
- {
- SpotRadius4.m_fOrigin[Y] = y;
- m_fSpotAngle = Degreesf(sin(-y/m_fDirection[Z]));
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // C3dObjectLight methods
- void C3dObjectLight::EnableLight(GLenum lightNum, C3dWorld* pWorld, C3dCamera* pCamera)
- {
- GLfloat colorBlack[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- Matx4x4 LightTransformMatrix;
- VECTORF fLightOrigin; // The center of our light
- VECTORF fLightDirection; // The direction our light is pointing to
- VECTORF fLightDirVec; // The direction vector of our light
- // To ensure that our 3d surfaces are lighted properly, we must enable all
- // lights in our scene before we display any surface. Lights should be enabled
- // AFTER positioning of our 'camera' to ensure that the light is properly
- // positioned.
- GetTransformMatrix(LightTransformMatrix);
- if(m_pParent)
- {
- // Since we allow lights to be child objects, we must calculate its'
- // position and direction vector in world coordinates.
- // Initialize our vectors
- VecClear4f(fLightOrigin); // Set to (0,0,0,0) or our World origin.
- // Calculate the light's position in World coordinates.
- VecTransformf(fLightOrigin, fLightOrigin, LightTransformMatrix);
- fLightOrigin[W] = m_fOrigin[W]; // copy the 'W' or light 'type' parameter
- }
- else
- VecCopy4f(m_fOrigin, fLightOrigin);
- // Calculate the lights' direction vector. Get the direction of the light
- // and multiply it by the lights Inverse Rotation transformation matrix.
- // Subtract this from the light's World coordinalte position then normalize.
- VecTransformf(m_fDirection, fLightDirection, LightTransformMatrix);
- VecSubf(fLightDirection, fLightOrigin, fLightDirVec);
- VecNormalizef(fLightDirVec);
- // Set the Lights Parameters and Enable...
- glLightfv(lightNum, GL_AMBIENT, m_ColorAmbient.m_fColor);
- if(m_iLightType == LIGHT_AMBIENT)
- {
- // Ambient light has no Diffuse or Specular color
- glLightfv(lightNum, GL_DIFFUSE, colorBlack);
- glLightfv(lightNum, GL_SPECULAR, colorBlack);
- }
- else
- {
- glLightfv(lightNum, GL_DIFFUSE, m_ColorDiffuse.m_fColor);
- glLightfv(lightNum, GL_SPECULAR, m_ColorSpecular.m_fColor);
- }
- glLightfv(lightNum, GL_POSITION, fLightOrigin);
- glLightfv(lightNum, GL_SPOT_DIRECTION, fLightDirVec);
- glLightf(lightNum, GL_SPOT_CUTOFF, m_fSpotAngle); // in Degrees
- glLightf(lightNum, GL_SPOT_EXPONENT, m_fSpecHighlight);
- glLightf(lightNum, GL_CONSTANT_ATTENUATION, m_fConstantAttenuation);
- glLightf(lightNum, GL_LINEAR_ATTENUATION, m_fLinearAttenuation);
- glLightf(lightNum, GL_QUADRATIC_ATTENUATION, m_fQuadraticAttenuation);
- glEnable(lightNum);
- }
- void C3dObjectLight::GetDirection(GLfloat *x, GLfloat *y, GLfloat *z)
- {
- // Get the light direction
- *x = m_fDirection[X];
- *y = m_fDirection[Y];
- *z = m_fDirection[Z];
- }
- void C3dObjectLight::GetAttenuation(GLfloat *k, GLfloat *l, GLfloat *q)
- {
- // Get the lights attenuation variables
- *k = m_fConstantAttenuation;
- *l = m_fLinearAttenuation;
- *q = m_fQuadraticAttenuation;
- }
- void C3dObjectLight::GetSpecularPwr(GLfloat *pwr)
- {
- // Get the lights specular power or spot exponent
- *pwr = m_fSpecHighlight;
- }
- void C3dObjectLight::GetSpotAngle(GLfloat *angle)
- {
- // Get the lights cutoff angle (degrees)
- *angle = m_fSpotAngle;
- }
- void C3dObjectLight::GetRadius(GLfloat *radius)
- {
- // Get the lights radius or size
- *radius = m_fRadius;
- }
- void C3dObjectLight::SetDirection(GLfloat x, GLfloat y, GLfloat z)
- {
- // Set the light objects direction to the supplied
- // values.
- m_fDirection[X] = x;
- m_fDirection[Y] = y;
- m_fDirection[Z] = z;
- }
- void C3dObjectLight::SetAttenuation(GLfloat k, GLfloat l, GLfloat q)
- {
- // Set the lights attenuation variables
- m_fConstantAttenuation = k;
- m_fLinearAttenuation = l;
- m_fQuadraticAttenuation = q;
- }
- void C3dObjectLight::SetSpecularPwr(GLfloat pwr)
- {
- // Set the lights specular power or spot exponent
- m_fSpecHighlight = pwr;
- }
- void C3dObjectLight::SetSpotAngle(GLfloat angle)
- {
- // Set the lights cutoff angle (degrees)
- m_fSpotAngle = angle;
- }
- void C3dObjectLight::SetRadius(GLfloat radius)
- {
- // Set the lights radius or size
- m_fRadius = radius;
- }