From d1fe0d2dcc30a76055d6423805f8e0108b4b64be Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 26 Jul 2012 19:05:09 +0200 Subject: Lighting - fixed problems with lighting - added light_test --- src/graphics/common/light.h | 94 +++++-- src/graphics/common/material.h | 3 + src/graphics/opengl/gldevice.cpp | 107 ++++++-- src/graphics/opengl/gldevice.h | 4 + src/graphics/opengl/test/CMakeLists.txt | 12 + src/graphics/opengl/test/light_test.cpp | 437 ++++++++++++++++++++++++++++++++ 6 files changed, 615 insertions(+), 42 deletions(-) create mode 100644 src/graphics/opengl/test/light_test.cpp (limited to 'src') diff --git a/src/graphics/common/light.h b/src/graphics/common/light.h index 46f1bfa..e1d51ab 100644 --- a/src/graphics/common/light.h +++ b/src/graphics/common/light.h @@ -41,8 +41,6 @@ enum LightType * \brief Light * * This structure was created as analog to DirectX's D3DLIGHT. - * - * It contains analogous fields as the D3DLIGHT struct. */ struct Light { @@ -54,29 +52,40 @@ struct Light Gfx::Color diffuse; //! Color of specular light Gfx::Color specular; - //! Position in world space + //! Position in world space (for point & spot lights) Math::Vector position; - //! Direction in world space + //! Direction in world space (for directional & spot lights) Math::Vector direction; - //! Cutoff range - float range; - //! Falloff - float falloff; - //! Inner angle of spotlight cone - float theta; - //! Outer angle of spotlight cone - float phi; - //! Constant attenuation + //! Constant attenuation factor float attenuation0; - //! Linear attenuation + //! Linear attenuation factor float attenuation1; - //! Quadratic attenuation + //! Quadratic attenuation factor 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() + { + LoadDefault(); + } + + //! Loads default values + void LoadDefault() { 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 * * TODO documentation */ -struct SceneLight +struct DynamicLight { //! true -> light exists bool used; @@ -128,6 +137,53 @@ struct SceneLight 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 m_dynLights; +}; }; // namespace Gfx diff --git a/src/graphics/common/material.h b/src/graphics/common/material.h index f71923f..c828d90 100644 --- a/src/graphics/common/material.h +++ b/src/graphics/common/material.h @@ -19,6 +19,9 @@ #pragma once +#include "graphics/common/color.h" + + namespace Gfx { /** diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index fc6e9b6..d31d007 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -52,6 +52,7 @@ void Gfx::GLDeviceConfig::LoadDefault() Gfx::CGLDevice::CGLDevice() { m_wasInit = false; + m_lighting = false; m_texturing = false; } @@ -86,6 +87,9 @@ bool Gfx::CGLDevice::Create() // To use separate specular color in drawing primitives 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 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glMatrixMode(GL_PROJECTION); @@ -100,9 +104,9 @@ bool Gfx::CGLDevice::Create() int maxTextures = 0; glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures); - m_currentTextures = std::vector (maxTextures, Gfx::Texture()); - m_texturesEnabled = std::vector (maxTextures, false); - m_textureStageParams = std::vector(maxTextures, Gfx::TextureStageParams()); + m_currentTextures = std::vector (maxTextures, Gfx::Texture()); + m_texturesEnabled = std::vector (maxTextures, false); + m_textureStageParams = std::vector(maxTextures, Gfx::TextureStageParams()); return true; } @@ -213,15 +217,21 @@ void Gfx::CGLDevice::UpdateModelviewMatrix() glLoadIdentity(); glScalef(1.0f, 1.0f, -1.0f); 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) { m_material = material; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_material.ambient.Array()); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_material.diffuse.Array()); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_material.specular.Array()); + glMaterialfv(GL_FRONT, GL_AMBIENT, m_material.ambient.Array()); + glMaterialfv(GL_FRONT, GL_DIFFUSE, m_material.diffuse.Array()); + glMaterialfv(GL_FRONT, GL_SPECULAR, m_material.specular.Array()); } 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(light.diffuse.Array())); glLightfv(GL_LIGHT0 + index, GL_SPECULAR, const_cast(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; + glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, light.attenuation0); + glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, light.attenuation1); + 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 - position[3] = 1.0f; - glLightfv(GL_LIGHT0 + index, GL_POSITION, position); + { + glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f); + } - GLfloat direction[4] = { light.direction.x, light.direction.y, light.direction.z, 0.0f }; - glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction); + UpdateLightPosition(index); +} - glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.range); +void Gfx::CGLDevice::UpdateLightPosition(int index) +{ + assert(index >= 0); + assert(index < (int)m_lights.size()); - // TODO: falloff?, phi?, theta? + if ((! m_lighting) || (! m_lightsEnabled[index])) + return; - glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, light.attenuation0); - glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, light.attenuation1); - glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, light.attenuation2); + 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) @@ -803,12 +846,29 @@ int Gfx::CGLDevice::ComputeSphereVisibility(const Math::Vector ¢er, float ra 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); 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; @@ -829,7 +889,6 @@ void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled) switch (state) { - case Gfx::RENDER_STATE_LIGHTING: flag = GL_LIGHTING; break; case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break; case Gfx::RENDER_STATE_FOG: flag = GL_FOG; 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) { - if (state == RENDER_STATE_TEXTURING) + if (state == Gfx::RENDER_STATE_LIGHTING) + return m_lighting; + + if (state == Gfx::RENDER_STATE_TEXTURING) return m_texturing; GLenum flag = 0; @@ -855,7 +917,6 @@ bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state) switch (state) { 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_FOG: flag = GL_FOG; break; case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break; diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 0f4d0c9..b779123 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -155,6 +155,8 @@ public: private: //! Updates internal modelview matrix void UpdateModelviewMatrix(); + //! Updates position for given light based on transformation matrices + void UpdateLightPosition(int index); private: //! Was initialized? @@ -174,6 +176,8 @@ private: //! The current material Gfx::Material m_material; + //! Whether lighting is enabled + bool m_lighting; //! Current lights std::vector m_lights; //! Current lights enable status diff --git a/src/graphics/opengl/test/CMakeLists.txt b/src/graphics/opengl/test/CMakeLists.txt index f49fbac..793e858 100644 --- a/src/graphics/opengl/test/CMakeLists.txt +++ b/src/graphics/opengl/test/CMakeLists.txt @@ -55,6 +55,15 @@ set(TRANSFORM_SOURCES 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}) set(LIBS @@ -73,3 +82,6 @@ target_link_libraries(model_test ${LIBS}) add_executable(transform_test ${TRANSFORM_SOURCES}) target_link_libraries(transform_test ${LIBS}) + +add_executable(light_test ${LIGHT_SOURCES}) +target_link_libraries(light_test ${LIBS}) \ No newline at end of file diff --git a/src/graphics/opengl/test/light_test.cpp b/src/graphics/opengl/test/light_test.cpp new file mode 100644 index 0000000..80fa911 --- /dev/null +++ b/src/graphics/opengl/test/light_test.cpp @@ -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 +#include +#include + +#include +#include + +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; +} -- cgit v1.2.3-1-g7c22