parent
bc1c9b5284
commit
d1fe0d2dcc
|
@ -41,8 +41,6 @@ enum LightType
|
||||||
* \brief Light
|
* \brief Light
|
||||||
*
|
*
|
||||||
* This structure was created as analog to DirectX's D3DLIGHT.
|
* This structure was created as analog to DirectX's D3DLIGHT.
|
||||||
*
|
|
||||||
* It contains analogous fields as the D3DLIGHT struct.
|
|
||||||
*/
|
*/
|
||||||
struct Light
|
struct Light
|
||||||
{
|
{
|
||||||
|
@ -54,29 +52,40 @@ struct Light
|
||||||
Gfx::Color diffuse;
|
Gfx::Color diffuse;
|
||||||
//! Color of specular light
|
//! Color of specular light
|
||||||
Gfx::Color specular;
|
Gfx::Color specular;
|
||||||
//! Position in world space
|
//! Position in world space (for point & spot lights)
|
||||||
Math::Vector position;
|
Math::Vector position;
|
||||||
//! Direction in world space
|
//! Direction in world space (for directional & spot lights)
|
||||||
Math::Vector direction;
|
Math::Vector direction;
|
||||||
//! Cutoff range
|
//! Constant attenuation factor
|
||||||
float range;
|
|
||||||
//! Falloff
|
|
||||||
float falloff;
|
|
||||||
//! Inner angle of spotlight cone
|
|
||||||
float theta;
|
|
||||||
//! Outer angle of spotlight cone
|
|
||||||
float phi;
|
|
||||||
//! Constant attenuation
|
|
||||||
float attenuation0;
|
float attenuation0;
|
||||||
//! Linear attenuation
|
//! Linear attenuation factor
|
||||||
float attenuation1;
|
float attenuation1;
|
||||||
//! Quadratic attenuation
|
//! Quadratic attenuation factor
|
||||||
float attenuation2;
|
float attenuation2;
|
||||||
|
//! Angle of spotlight cone (0-90 degrees)
|
||||||
|
float spotAngle;
|
||||||
|
//! Intensity of spotlight (0 = uniform; 128 = most intense)
|
||||||
|
float spotIntensity;
|
||||||
|
|
||||||
|
//! Constructor; calls LoadDefault()
|
||||||
Light()
|
Light()
|
||||||
|
{
|
||||||
|
LoadDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Loads default values
|
||||||
|
void LoadDefault()
|
||||||
{
|
{
|
||||||
type = LIGHT_POINT;
|
type = LIGHT_POINT;
|
||||||
range = falloff = theta = phi = attenuation0 = attenuation1 = attenuation2 = 0.0f;
|
ambient = Gfx::Color(0.4f, 0.4f, 0.4f);
|
||||||
|
diffuse = Gfx::Color(0.8f, 0.8f, 0.8f);
|
||||||
|
specular = Gfx::Color(1.0f, 1.0f, 1.0f);
|
||||||
|
position = Math::Vector(0.0f, 0.0f, 0.0f);
|
||||||
|
direction = Math::Vector(0.0f, 0.0f, 1.0f);
|
||||||
|
attenuation0 = 1.0f;
|
||||||
|
attenuation1 = attenuation2 = 0.0f;
|
||||||
|
spotAngle = 90.0f;
|
||||||
|
spotIntensity = 0.0f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,12 +110,12 @@ struct LightProgression
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \struct SceneLight
|
* \struct DynamicLight
|
||||||
* \brief Dynamic light in 3D scene
|
* \brief Dynamic light in 3D scene
|
||||||
*
|
*
|
||||||
* TODO documentation
|
* TODO documentation
|
||||||
*/
|
*/
|
||||||
struct SceneLight
|
struct DynamicLight
|
||||||
{
|
{
|
||||||
//! true -> light exists
|
//! true -> light exists
|
||||||
bool used;
|
bool used;
|
||||||
|
@ -128,6 +137,53 @@ struct SceneLight
|
||||||
Gfx::LightProgression colorBlue;
|
Gfx::LightProgression colorBlue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO CLight
|
/**
|
||||||
|
\class CLight
|
||||||
|
\brief Manager for dynamic lights in 3D scene
|
||||||
|
*/
|
||||||
|
class CLight
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CLight(CInstanceManager *iMan, Gfx::CEngine* engine);
|
||||||
|
virtual ~CLight();
|
||||||
|
|
||||||
|
void SetDevice(Gfx::CDevice* device);
|
||||||
|
|
||||||
|
void FlushLight();
|
||||||
|
int CreateLight();
|
||||||
|
bool DeleteLight(int lightRank);
|
||||||
|
bool SetLight(int lightRank, const Gfx::Light &light);
|
||||||
|
bool GetLight(int lightRank, Gfx::Light &light);
|
||||||
|
bool LightEnable(int lightRank, bool enable);
|
||||||
|
|
||||||
|
bool SetLightIncludeType(int lightRank, Gfx::EngineObjectType type);
|
||||||
|
bool SetLightExcludeType(int lightRank, Gfx::EngineObjectType type);
|
||||||
|
|
||||||
|
bool SetLightPos(int lightRank, const Math::Vector &pos);
|
||||||
|
Math::Vector GetLightPos(int lightRank);
|
||||||
|
|
||||||
|
bool SetLightDir(int lightRank, const Math::Vector &dir);
|
||||||
|
Math::Vector GetLightDir(int lightRank);
|
||||||
|
|
||||||
|
bool SetLightIntensitySpeed(int lightRank, float speed);
|
||||||
|
bool SetLightIntensity(int lightRank, float value);
|
||||||
|
float GetLightIntensity(int lightRank);
|
||||||
|
void AdaptLightColor(const Gfx::Color &color, float factor);
|
||||||
|
|
||||||
|
bool SetLightColorSpeed(int lightRank, float speed);
|
||||||
|
bool SetLightColor(int lightRank, const Gfx::Color &color);
|
||||||
|
Gfx::Color GetLightColor(int lightRank);
|
||||||
|
|
||||||
|
void FrameLight(float rTime);
|
||||||
|
void LightUpdate();
|
||||||
|
void LightUpdate(Gfx::EngineObjectType type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CInstanceManager* m_iMan;
|
||||||
|
CEngine* m_engine;
|
||||||
|
CDevice* m_device;
|
||||||
|
float m_time;
|
||||||
|
std::vector<Gfx::DynamicLight> m_dynLights;
|
||||||
|
};
|
||||||
|
|
||||||
}; // namespace Gfx
|
}; // namespace Gfx
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "graphics/common/color.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -52,6 +52,7 @@ void Gfx::GLDeviceConfig::LoadDefault()
|
||||||
Gfx::CGLDevice::CGLDevice()
|
Gfx::CGLDevice::CGLDevice()
|
||||||
{
|
{
|
||||||
m_wasInit = false;
|
m_wasInit = false;
|
||||||
|
m_lighting = false;
|
||||||
m_texturing = false;
|
m_texturing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +87,9 @@ bool Gfx::CGLDevice::Create()
|
||||||
// To use separate specular color in drawing primitives
|
// To use separate specular color in drawing primitives
|
||||||
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
||||||
|
|
||||||
|
// To avoid problems with scaling & lighting
|
||||||
|
glEnable(GL_RESCALE_NORMAL);
|
||||||
|
|
||||||
// Set just to be sure
|
// Set just to be sure
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
@ -100,9 +104,9 @@ bool Gfx::CGLDevice::Create()
|
||||||
int maxTextures = 0;
|
int maxTextures = 0;
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures);
|
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures);
|
||||||
|
|
||||||
m_currentTextures = std::vector<Gfx::Texture> (maxTextures, Gfx::Texture());
|
m_currentTextures = std::vector<Gfx::Texture> (maxTextures, Gfx::Texture());
|
||||||
m_texturesEnabled = std::vector<bool> (maxTextures, false);
|
m_texturesEnabled = std::vector<bool> (maxTextures, false);
|
||||||
m_textureStageParams = std::vector<Gfx::TextureStageParams>(maxTextures, Gfx::TextureStageParams());
|
m_textureStageParams = std::vector<Gfx::TextureStageParams>(maxTextures, Gfx::TextureStageParams());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -213,15 +217,21 @@ void Gfx::CGLDevice::UpdateModelviewMatrix()
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glScalef(1.0f, 1.0f, -1.0f);
|
glScalef(1.0f, 1.0f, -1.0f);
|
||||||
glMultMatrixf(m_modelviewMat.Array());
|
glMultMatrixf(m_modelviewMat.Array());
|
||||||
|
|
||||||
|
if (m_lighting)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < (int)m_lights.size(); ++index)
|
||||||
|
UpdateLightPosition(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx::CGLDevice::SetMaterial(const Gfx::Material &material)
|
void Gfx::CGLDevice::SetMaterial(const Gfx::Material &material)
|
||||||
{
|
{
|
||||||
m_material = material;
|
m_material = material;
|
||||||
|
|
||||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_material.ambient.Array());
|
glMaterialfv(GL_FRONT, GL_AMBIENT, m_material.ambient.Array());
|
||||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_material.diffuse.Array());
|
glMaterialfv(GL_FRONT, GL_DIFFUSE, m_material.diffuse.Array());
|
||||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_material.specular.Array());
|
glMaterialfv(GL_FRONT, GL_SPECULAR, m_material.specular.Array());
|
||||||
}
|
}
|
||||||
|
|
||||||
const Gfx::Material& Gfx::CGLDevice::GetMaterial()
|
const Gfx::Material& Gfx::CGLDevice::GetMaterial()
|
||||||
|
@ -246,23 +256,56 @@ void Gfx::CGLDevice::SetLight(int index, const Gfx::Light &light)
|
||||||
glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, const_cast<GLfloat*>(light.diffuse.Array()));
|
glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, const_cast<GLfloat*>(light.diffuse.Array()));
|
||||||
glLightfv(GL_LIGHT0 + index, GL_SPECULAR, const_cast<GLfloat*>(light.specular.Array()));
|
glLightfv(GL_LIGHT0 + index, GL_SPECULAR, const_cast<GLfloat*>(light.specular.Array()));
|
||||||
|
|
||||||
GLfloat position[4] = { light.position.x, light.position.y, light.position.z, 0.0f };
|
|
||||||
if (light.type == LIGHT_DIRECTIONAL)
|
|
||||||
position[3] = 0.0f;
|
|
||||||
else
|
|
||||||
position[3] = 1.0f;
|
|
||||||
glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
|
|
||||||
|
|
||||||
GLfloat direction[4] = { light.direction.x, light.direction.y, light.direction.z, 0.0f };
|
|
||||||
glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction);
|
|
||||||
|
|
||||||
glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.range);
|
|
||||||
|
|
||||||
// TODO: falloff?, phi?, theta?
|
|
||||||
|
|
||||||
glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, light.attenuation0);
|
glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, light.attenuation0);
|
||||||
glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, light.attenuation1);
|
glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, light.attenuation1);
|
||||||
glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, light.attenuation2);
|
glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, light.attenuation2);
|
||||||
|
|
||||||
|
if (light.type == Gfx::LIGHT_SPOT)
|
||||||
|
{
|
||||||
|
glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle);
|
||||||
|
glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, light.spotIntensity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateLightPosition(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gfx::CGLDevice::UpdateLightPosition(int index)
|
||||||
|
{
|
||||||
|
assert(index >= 0);
|
||||||
|
assert(index < (int)m_lights.size());
|
||||||
|
|
||||||
|
if ((! m_lighting) || (! m_lightsEnabled[index]))
|
||||||
|
return;
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glLoadIdentity();
|
||||||
|
glScalef(1.0f, 1.0f, -1.0f);
|
||||||
|
glMultMatrixf(m_viewMat.Array());
|
||||||
|
|
||||||
|
if (m_lights[index].type == LIGHT_DIRECTIONAL)
|
||||||
|
{
|
||||||
|
GLfloat position[4] = { m_lights[index].direction.x, m_lights[index].direction.y, m_lights[index].direction.z, 0.0f };
|
||||||
|
glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLfloat position[4] = { m_lights[index].position.x, m_lights[index].position.y, m_lights[index].position.z, 1.0f };
|
||||||
|
glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_lights[index].type == Gfx::LIGHT_SPOT)
|
||||||
|
{
|
||||||
|
GLfloat direction[4] = { m_lights[index].direction.x, m_lights[index].direction.y, m_lights[index].direction.z, 0.0f };
|
||||||
|
glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Gfx::Light& Gfx::CGLDevice::GetLight(int index)
|
const Gfx::Light& Gfx::CGLDevice::GetLight(int index)
|
||||||
|
@ -803,12 +846,29 @@ int Gfx::CGLDevice::ComputeSphereVisibility(const Math::Vector ¢er, float ra
|
||||||
|
|
||||||
void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
|
void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
|
||||||
{
|
{
|
||||||
if (state == RENDER_STATE_DEPTH_WRITE)
|
if (state == Gfx::RENDER_STATE_DEPTH_WRITE)
|
||||||
{
|
{
|
||||||
glDepthMask(enabled ? GL_TRUE : GL_FALSE);
|
glDepthMask(enabled ? GL_TRUE : GL_FALSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (state == RENDER_STATE_TEXTURING)
|
else if (state == Gfx::RENDER_STATE_LIGHTING)
|
||||||
|
{
|
||||||
|
m_lighting = enabled;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
else
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < (int)m_lights.size(); ++index)
|
||||||
|
UpdateLightPosition(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (state == Gfx::RENDER_STATE_TEXTURING)
|
||||||
{
|
{
|
||||||
m_texturing = enabled;
|
m_texturing = enabled;
|
||||||
|
|
||||||
|
@ -829,7 +889,6 @@ void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case Gfx::RENDER_STATE_LIGHTING: flag = GL_LIGHTING; break;
|
|
||||||
case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
|
case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
|
||||||
case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
|
case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
|
||||||
case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
|
case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
|
||||||
|
@ -847,7 +906,10 @@ void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
|
||||||
|
|
||||||
bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state)
|
bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state)
|
||||||
{
|
{
|
||||||
if (state == RENDER_STATE_TEXTURING)
|
if (state == Gfx::RENDER_STATE_LIGHTING)
|
||||||
|
return m_lighting;
|
||||||
|
|
||||||
|
if (state == Gfx::RENDER_STATE_TEXTURING)
|
||||||
return m_texturing;
|
return m_texturing;
|
||||||
|
|
||||||
GLenum flag = 0;
|
GLenum flag = 0;
|
||||||
|
@ -855,7 +917,6 @@ bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state)
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case Gfx::RENDER_STATE_DEPTH_WRITE: flag = GL_DEPTH_WRITEMASK; break;
|
case Gfx::RENDER_STATE_DEPTH_WRITE: flag = GL_DEPTH_WRITEMASK; break;
|
||||||
case Gfx::RENDER_STATE_LIGHTING: flag = GL_DEPTH_WRITEMASK; break;
|
|
||||||
case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
|
case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
|
||||||
case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
|
case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
|
||||||
case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
|
case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
|
||||||
|
|
|
@ -155,6 +155,8 @@ public:
|
||||||
private:
|
private:
|
||||||
//! Updates internal modelview matrix
|
//! Updates internal modelview matrix
|
||||||
void UpdateModelviewMatrix();
|
void UpdateModelviewMatrix();
|
||||||
|
//! Updates position for given light based on transformation matrices
|
||||||
|
void UpdateLightPosition(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Was initialized?
|
//! Was initialized?
|
||||||
|
@ -174,6 +176,8 @@ private:
|
||||||
//! The current material
|
//! The current material
|
||||||
Gfx::Material m_material;
|
Gfx::Material m_material;
|
||||||
|
|
||||||
|
//! Whether lighting is enabled
|
||||||
|
bool m_lighting;
|
||||||
//! Current lights
|
//! Current lights
|
||||||
std::vector<Gfx::Light> m_lights;
|
std::vector<Gfx::Light> m_lights;
|
||||||
//! Current lights enable status
|
//! Current lights enable status
|
||||||
|
|
|
@ -55,6 +55,15 @@ set(TRANSFORM_SOURCES
|
||||||
transform_test.cpp
|
transform_test.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(LIGHT_SOURCES
|
||||||
|
../gldevice.cpp
|
||||||
|
../../../common/logger.cpp
|
||||||
|
../../../common/image.cpp
|
||||||
|
../../../common/iman.cpp
|
||||||
|
../../../app/system.cpp
|
||||||
|
light_test.cpp
|
||||||
|
)
|
||||||
|
|
||||||
include_directories(../../../ ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(../../../ ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
set(LIBS
|
set(LIBS
|
||||||
|
@ -73,3 +82,6 @@ target_link_libraries(model_test ${LIBS})
|
||||||
|
|
||||||
add_executable(transform_test ${TRANSFORM_SOURCES})
|
add_executable(transform_test ${TRANSFORM_SOURCES})
|
||||||
target_link_libraries(transform_test ${LIBS})
|
target_link_libraries(transform_test ${LIBS})
|
||||||
|
|
||||||
|
add_executable(light_test ${LIGHT_SOURCES})
|
||||||
|
target_link_libraries(light_test ${LIBS})
|
|
@ -0,0 +1,437 @@
|
||||||
|
#include "app/system.h"
|
||||||
|
#include "common/logger.h"
|
||||||
|
#include "common/image.h"
|
||||||
|
#include "common/iman.h"
|
||||||
|
#include "graphics/opengl/gldevice.h"
|
||||||
|
#include "math/geometry.h"
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
#include <SDL/SDL_image.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
enum KeySlots
|
||||||
|
{
|
||||||
|
K_Forward,
|
||||||
|
K_Back,
|
||||||
|
K_Left,
|
||||||
|
K_Right,
|
||||||
|
K_Up,
|
||||||
|
K_Down,
|
||||||
|
K_Count
|
||||||
|
};
|
||||||
|
bool KEYMAP[K_Count] = { false };
|
||||||
|
|
||||||
|
Math::Point MOUSE_POS_BASE;
|
||||||
|
|
||||||
|
Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f);
|
||||||
|
Math::Vector ROTATION, ROTATION_BASE;
|
||||||
|
|
||||||
|
float CUBE_ORBIT = 0.0f;
|
||||||
|
|
||||||
|
const int FRAME_DELAY = 5000;
|
||||||
|
|
||||||
|
SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL;
|
||||||
|
|
||||||
|
void Init(Gfx::CGLDevice *device)
|
||||||
|
{
|
||||||
|
device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true);
|
||||||
|
device->SetShadeModel(Gfx::SHADE_SMOOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render(Gfx::CGLDevice *device)
|
||||||
|
{
|
||||||
|
device->BeginScene();
|
||||||
|
|
||||||
|
/* Unlit part of scene */
|
||||||
|
|
||||||
|
device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false);
|
||||||
|
device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); // Double-sided drawing
|
||||||
|
|
||||||
|
Math::Matrix persp;
|
||||||
|
Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f);
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);
|
||||||
|
|
||||||
|
|
||||||
|
Math::Matrix viewMat;
|
||||||
|
Math::Matrix mat;
|
||||||
|
|
||||||
|
viewMat.LoadIdentity();
|
||||||
|
|
||||||
|
Math::LoadRotationXMatrix(mat, -ROTATION.x);
|
||||||
|
viewMat = Math::MultiplyMatrices(viewMat, mat);
|
||||||
|
|
||||||
|
Math::LoadRotationYMatrix(mat, -ROTATION.y);
|
||||||
|
viewMat = Math::MultiplyMatrices(viewMat, mat);
|
||||||
|
|
||||||
|
Math::LoadTranslationMatrix(mat, -TRANSLATION);
|
||||||
|
viewMat = Math::MultiplyMatrices(viewMat, mat);
|
||||||
|
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);
|
||||||
|
|
||||||
|
Math::Matrix worldMat;
|
||||||
|
worldMat.LoadIdentity();
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
|
||||||
|
|
||||||
|
Gfx::VertexCol line[2] = { Gfx::VertexCol() };
|
||||||
|
|
||||||
|
for (int x = -40; x <= 40; ++x)
|
||||||
|
{
|
||||||
|
line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
|
||||||
|
line[0].coord.z = -40;
|
||||||
|
line[0].coord.x = x;
|
||||||
|
line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
|
||||||
|
line[1].coord.z = 40;
|
||||||
|
line[1].coord.x = x;
|
||||||
|
device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int z = -40; z <= 40; ++z)
|
||||||
|
{
|
||||||
|
line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
|
||||||
|
line[0].coord.z = z;
|
||||||
|
line[0].coord.x = -40;
|
||||||
|
line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
|
||||||
|
line[1].coord.z = z;
|
||||||
|
line[1].coord.x = 40;
|
||||||
|
device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Gfx::VertexCol quad[6] = { Gfx::VertexCol() };
|
||||||
|
|
||||||
|
quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f);
|
||||||
|
quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f);
|
||||||
|
quad[2].coord = Math::Vector(-1.0f, 1.0f, 0.0f);
|
||||||
|
quad[3].coord = Math::Vector( 1.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f));
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
|
||||||
|
|
||||||
|
device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f));
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
|
||||||
|
|
||||||
|
device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
Math::LoadTranslationMatrix(worldMat, Math::Vector(10.0f, 4.5f, 5.0f));
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
|
||||||
|
|
||||||
|
device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
|
||||||
|
|
||||||
|
/* Moving lit cube */
|
||||||
|
device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true);
|
||||||
|
device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); // Culling (CCW faces)
|
||||||
|
|
||||||
|
device->SetGlobalAmbient(Gfx::Color(0.4f, 0.4f, 0.4f));
|
||||||
|
|
||||||
|
Gfx::Light light1;
|
||||||
|
light1.type = Gfx::LIGHT_POINT;
|
||||||
|
light1.position = Math::Vector(10.0f, 4.5f, 5.0f);
|
||||||
|
light1.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
|
||||||
|
light1.diffuse = Gfx::Color(1.0f, 0.1f, 0.1f);
|
||||||
|
light1.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
|
||||||
|
device->SetLight(0, light1);
|
||||||
|
device->SetLightEnabled(0, true);
|
||||||
|
|
||||||
|
/*Gfx::Light light2;
|
||||||
|
device->SetLight(1, light2);
|
||||||
|
device->SetLightEnabled(1, true);*/
|
||||||
|
|
||||||
|
Gfx::Material material;
|
||||||
|
material.ambient = Gfx::Color(0.3f, 0.3f, 0.3f);
|
||||||
|
material.diffuse = Gfx::Color(0.8f, 0.7f, 0.6f);
|
||||||
|
material.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
|
||||||
|
device->SetMaterial(material);
|
||||||
|
|
||||||
|
const Gfx::Vertex cube[6][4] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// Front
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f))
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
// Back
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f))
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
// Top
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f))
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
// Bottom
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f))
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
// Left
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f))
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
// Right
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
|
||||||
|
Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Math::Matrix cubeTrans;
|
||||||
|
Math::LoadTranslationMatrix(cubeTrans, Math::Vector(10.0f, 2.0f, 5.0f));
|
||||||
|
Math::Matrix cubeRot;
|
||||||
|
Math::LoadRotationMatrix(cubeRot, Math::Vector(0.0f, 1.0f, 0.0f), CUBE_ORBIT);
|
||||||
|
Math::Matrix cubeRotInv;
|
||||||
|
Math::LoadRotationMatrix(cubeRotInv, Math::Vector(0.0f, 1.0f, 0.0f), -CUBE_ORBIT);
|
||||||
|
Math::Matrix cubeTransRad;
|
||||||
|
Math::LoadTranslationMatrix(cubeTransRad, Math::Vector(0.0f, 0.0f, 6.0f));
|
||||||
|
worldMat = Math::MultiplyMatrices(cubeTransRad, cubeRotInv);
|
||||||
|
worldMat = Math::MultiplyMatrices(cubeRot, worldMat);
|
||||||
|
worldMat = Math::MultiplyMatrices(cubeTrans, worldMat);
|
||||||
|
device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, cube[i], 4);
|
||||||
|
|
||||||
|
device->EndScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
const float TRANS_SPEED = 6.0f; // units / sec
|
||||||
|
|
||||||
|
GetCurrentTimeStamp(CURR_TIME);
|
||||||
|
float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC);
|
||||||
|
CopyTimeStamp(PREV_TIME, CURR_TIME);
|
||||||
|
|
||||||
|
CUBE_ORBIT += timeDiff * (Math::PI / 4.0f);
|
||||||
|
|
||||||
|
Math::Vector incTrans;
|
||||||
|
|
||||||
|
if (KEYMAP[K_Forward])
|
||||||
|
incTrans.z = +TRANS_SPEED * timeDiff;
|
||||||
|
if (KEYMAP[K_Back])
|
||||||
|
incTrans.z = -TRANS_SPEED * timeDiff;
|
||||||
|
if (KEYMAP[K_Right])
|
||||||
|
incTrans.x = +TRANS_SPEED * timeDiff;
|
||||||
|
if (KEYMAP[K_Left])
|
||||||
|
incTrans.x = -TRANS_SPEED * timeDiff;
|
||||||
|
if (KEYMAP[K_Up])
|
||||||
|
incTrans.y = +TRANS_SPEED * timeDiff;
|
||||||
|
if (KEYMAP[K_Down])
|
||||||
|
incTrans.y = -TRANS_SPEED * timeDiff;
|
||||||
|
|
||||||
|
Math::Point rotTrans = Math::RotatePoint(-ROTATION.y, Math::Point(incTrans.x, incTrans.z));
|
||||||
|
incTrans.x = rotTrans.x;
|
||||||
|
incTrans.z = rotTrans.y;
|
||||||
|
TRANSLATION += incTrans;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardDown(SDLKey key)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case SDLK_w:
|
||||||
|
KEYMAP[K_Forward] = true;
|
||||||
|
break;
|
||||||
|
case SDLK_s:
|
||||||
|
KEYMAP[K_Back] = true;
|
||||||
|
break;
|
||||||
|
case SDLK_d:
|
||||||
|
KEYMAP[K_Right] = true;
|
||||||
|
break;
|
||||||
|
case SDLK_a:
|
||||||
|
KEYMAP[K_Left] = true;
|
||||||
|
break;
|
||||||
|
case SDLK_z:
|
||||||
|
KEYMAP[K_Down] = true;
|
||||||
|
break;
|
||||||
|
case SDLK_x:
|
||||||
|
KEYMAP[K_Up] = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardUp(SDLKey key)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case SDLK_w:
|
||||||
|
KEYMAP[K_Forward] = false;
|
||||||
|
break;
|
||||||
|
case SDLK_s:
|
||||||
|
KEYMAP[K_Back] = false;
|
||||||
|
break;
|
||||||
|
case SDLK_d:
|
||||||
|
KEYMAP[K_Right] = false;
|
||||||
|
break;
|
||||||
|
case SDLK_a:
|
||||||
|
KEYMAP[K_Left] = false;
|
||||||
|
break;
|
||||||
|
case SDLK_z:
|
||||||
|
KEYMAP[K_Down] = false;
|
||||||
|
break;
|
||||||
|
case SDLK_x:
|
||||||
|
KEYMAP[K_Up] = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseMove(int x, int y)
|
||||||
|
{
|
||||||
|
Math::Point currentPos((float)x, (float)y);
|
||||||
|
|
||||||
|
static bool first = true;
|
||||||
|
if (first || (x < 10) || (y < 10) || (x > 790) || (y > 590))
|
||||||
|
{
|
||||||
|
SDL_WarpMouse(400, 300);
|
||||||
|
MOUSE_POS_BASE.x = 400;
|
||||||
|
MOUSE_POS_BASE.y = 300;
|
||||||
|
ROTATION_BASE = ROTATION;
|
||||||
|
first = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ROTATION.y = ROTATION_BASE.y + ((float) (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI;
|
||||||
|
ROTATION.x = ROTATION_BASE.x + ((float) (y - MOUSE_POS_BASE.y) / 600.0f) * Math::PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
CLogger logger;
|
||||||
|
|
||||||
|
PREV_TIME = CreateTimeStamp();
|
||||||
|
CURR_TIME = CreateTimeStamp();
|
||||||
|
|
||||||
|
GetCurrentTimeStamp(PREV_TIME);
|
||||||
|
GetCurrentTimeStamp(CURR_TIME);
|
||||||
|
|
||||||
|
CInstanceManager iMan;
|
||||||
|
|
||||||
|
// Without any error checking, for simplicity
|
||||||
|
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
|
||||||
|
IMG_Init(IMG_INIT_PNG);
|
||||||
|
|
||||||
|
const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
|
||||||
|
|
||||||
|
Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
|
||||||
|
|
||||||
|
if (videoInfo->hw_available)
|
||||||
|
videoFlags |= SDL_HWSURFACE;
|
||||||
|
else
|
||||||
|
videoFlags |= SDL_SWSURFACE;
|
||||||
|
|
||||||
|
if (videoInfo->blit_hw)
|
||||||
|
videoFlags |= SDL_HWACCEL;
|
||||||
|
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
|
||||||
|
SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags);
|
||||||
|
|
||||||
|
|
||||||
|
SDL_WM_SetCaption("Light Test", "Light Test");
|
||||||
|
|
||||||
|
//SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||||
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
|
||||||
|
Gfx::CGLDevice *device = new Gfx::CGLDevice();
|
||||||
|
device->Create();
|
||||||
|
|
||||||
|
Init(device);
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
while (! done)
|
||||||
|
{
|
||||||
|
Render(device);
|
||||||
|
Update();
|
||||||
|
|
||||||
|
SDL_GL_SwapBuffers();
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
if (event.type == SDL_QUIT)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_KEYDOWN)
|
||||||
|
{
|
||||||
|
if (event.key.keysym.sym == SDLK_q)
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
KeyboardDown(event.key.keysym.sym);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_KEYUP)
|
||||||
|
KeyboardUp(event.key.keysym.sym);
|
||||||
|
else if (event.type == SDL_MOUSEMOTION)
|
||||||
|
MouseMove(event.motion.x, event.motion.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(FRAME_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
//SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||||
|
SDL_ShowCursor(SDL_ENABLE);
|
||||||
|
|
||||||
|
device->Destroy();
|
||||||
|
delete device;
|
||||||
|
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
|
||||||
|
IMG_Quit();
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
DestroyTimeStamp(PREV_TIME);
|
||||||
|
DestroyTimeStamp(CURR_TIME);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue