diff options
author | Zaba999 <qrwfw5rp> | 2012-09-29 23:53:57 +0200 |
---|---|---|
committer | Zaba999 <qrwfw5rp> | 2012-09-29 23:53:57 +0200 |
commit | 95e1d101c82e43396fd93abfaa522e3651613c4c (patch) | |
tree | 9d72f27e84a25c7a744b31eb7612698506ac5b68 /src/graphics/engine | |
parent | aa9df8b1f0fbbad4c7be0214a19a90b8495a2067 (diff) | |
parent | c8f39a4c96ab63f9e3edc96845e1b70c89b95d2b (diff) | |
download | colobot-95e1d101c82e43396fd93abfaa522e3651613c4c.tar.gz colobot-95e1d101c82e43396fd93abfaa522e3651613c4c.tar.bz2 colobot-95e1d101c82e43396fd93abfaa522e3651613c4c.zip |
Merge branch 'dev' of https://github.com/colobot/colobot into dev
Diffstat (limited to 'src/graphics/engine')
-rw-r--r-- | src/graphics/engine/README.txt | 4 | ||||
-rw-r--r-- | src/graphics/engine/engine.cpp | 107 | ||||
-rw-r--r-- | src/graphics/engine/engine.h | 11 | ||||
-rw-r--r-- | src/graphics/engine/lightman.cpp | 147 | ||||
-rw-r--r-- | src/graphics/engine/lightman.h | 58 | ||||
-rw-r--r-- | src/graphics/engine/planet.cpp | 5 | ||||
-rw-r--r-- | src/graphics/engine/planet.h | 3 | ||||
-rw-r--r-- | src/graphics/engine/terrain.cpp | 95 | ||||
-rw-r--r-- | src/graphics/engine/text.cpp | 46 | ||||
-rw-r--r-- | src/graphics/engine/text.h | 5 | ||||
-rw-r--r-- | src/graphics/engine/water.cpp | 23 | ||||
-rw-r--r-- | src/graphics/engine/water.h | 14 |
12 files changed, 297 insertions, 221 deletions
diff --git a/src/graphics/engine/README.txt b/src/graphics/engine/README.txt index f64d3dd..05d2d76 100644 --- a/src/graphics/engine/README.txt +++ b/src/graphics/engine/README.txt @@ -1,9 +1,9 @@ /** - * \dir graphics/engine + * \dir src/graphics/engine * \brief Graphics engine * * CEngine class and various other classes implementing the main features * of graphics engine from model loading to decorative particles * * Graphics operations are done on abstract interface from src/graphics/core - */
\ No newline at end of file + */ diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c170922..c094c63 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -186,6 +186,8 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_updateGeometry = false; + m_interfaceMode = false; + m_mice[ENG_MOUSE_NORM] = EngineMouse( 0, 1, 32, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 1.0f, 1.0f)); m_mice[ENG_MOUSE_WAIT] = EngineMouse( 2, 3, 33, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 8.0f, 12.0f)); m_mice[ENG_MOUSE_HAND] = EngineMouse( 4, 5, 34, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 7.0f, 2.0f)); @@ -215,6 +217,11 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_defaultTexParams.minFilter = TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR; m_defaultTexParams.magFilter = TEX_MAG_FILTER_LINEAR; + m_terrainTexParams.format = TEX_IMG_AUTO; + m_terrainTexParams.mipmap = false; + m_terrainTexParams.minFilter = TEX_MIN_FILTER_LINEAR; + m_terrainTexParams.magFilter = TEX_MAG_FILTER_LINEAR; + m_objectTree.reserve(LEVEL1_PREALLOCATE_COUNT); m_objects.reserve(OBJECT_PREALLOCATE_COUNT); m_shadows.reserve(SHADOW_PREALLOCATE_COUNT); @@ -1844,8 +1851,6 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(BLEND_ONE, BLEND_INV_SRC_COLOR); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); - m_device->SetTextureFactor(color); TextureStageParams params; @@ -1866,8 +1871,6 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(BLEND_DST_COLOR, BLEND_ZERO); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); - m_device->SetTextureFactor(color.Inverse()); TextureStageParams params; @@ -1884,20 +1887,22 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_FOG, false); m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(RENDER_STATE_TEXTURING, false); m_device->SetRenderState(RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(BLEND_ONE, BLEND_INV_SRC_COLOR); + + m_device->SetTextureEnabled(0, false); } else if (state & ENG_RSTATE_TCOLOR_WHITE) // transparent white color? { m_device->SetRenderState(RENDER_STATE_FOG, false); m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(RENDER_STATE_TEXTURING, false); m_device->SetRenderState(RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(BLEND_DST_COLOR, BLEND_ZERO); + + m_device->SetTextureEnabled(0, false); } else if (state & ENG_RSTATE_TDIFFUSE) // diffuse color as transparent? { @@ -1908,8 +1913,6 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(BLEND_SRC_ALPHA, BLEND_DST_ALPHA); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); - TextureStageParams params; params.colorOperation = TEX_MIX_OPER_REPLACE; params.colorArg1 = TEX_MIX_ARG_TEXTURE; @@ -1925,7 +1928,6 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false); m_device->SetRenderState(RENDER_STATE_BLENDING, false); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, TextureStageParams()); // default operation } @@ -1935,7 +1937,8 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false); m_device->SetRenderState(RENDER_STATE_BLENDING, false); - m_device->SetRenderState(RENDER_STATE_TEXTURING, false); + + m_device->SetTextureEnabled(0, false); } else if (state & ENG_RSTATE_TEXT) // font rendering? { @@ -1946,14 +1949,8 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_BLENDING, true); m_device->SetBlendFunc(BLEND_SRC_ALPHA, BLEND_INV_SRC_ALPHA); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); - - TextureStageParams params; - params.colorOperation = TEX_MIX_OPER_DEFAULT; // default modulate operation - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // default modulate operation - m_device->SetTextureEnabled(0, true); - m_device->SetTextureStageParams(0, params); + m_device->SetTextureStageParams(0, TextureStageParams()); // default operation } else if (state & ENG_RSTATE_ALPHA) // image with alpha channel? { @@ -1966,8 +1963,6 @@ void CEngine::SetState(int state, const Color& color) m_device->SetAlphaTestFunc(COMP_FUNC_GREATER, 0.5f); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); - m_device->SetTextureFactor(color); TextureStageParams params; @@ -1988,8 +1983,6 @@ void CEngine::SetState(int state, const Color& color) m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, true); m_device->SetRenderState(RENDER_STATE_FOG, true); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); - TextureStageParams params; params.colorOperation = TEX_MIX_OPER_DEFAULT; // default modulate params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? @@ -2014,7 +2007,7 @@ void CEngine::SetState(int state, const Color& color) params.colorArg1 = TEX_MIX_ARG_TEXTURE; params.colorArg2 = TEX_MIX_ARG_COMPUTED_COLOR; params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: ??? - m_device->SetTextureEnabled(0, true); + m_device->SetTextureEnabled(1, true); m_device->SetTextureStageParams(1, params); } else if ((state & ENG_RSTATE_DUAL_WHITE) && second) @@ -2024,7 +2017,7 @@ void CEngine::SetState(int state, const Color& color) params.colorArg1 = TEX_MIX_ARG_TEXTURE; params.colorArg2 = TEX_MIX_ARG_COMPUTED_COLOR; params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: ??? - m_device->SetTextureEnabled(0, true); + m_device->SetTextureEnabled(1, true); m_device->SetTextureStageParams(1, params); } else @@ -2034,25 +2027,13 @@ void CEngine::SetState(int state, const Color& color) if (state & ENG_RSTATE_WRAP) { - // TODO: separate function for setting wrap mode? - - TextureStageParams p1 = m_device->GetTextureStageParams(0); - p1.wrapS = p1.wrapT = TEX_WRAP_REPEAT; - m_device->SetTextureStageParams(0, p1); - - TextureStageParams p2 = m_device->GetTextureStageParams(1); - p2.wrapS = p2.wrapT = TEX_WRAP_REPEAT; - m_device->SetTextureStageParams(1, p2); + m_device->SetTextureStageWrap(0, TEX_WRAP_REPEAT, TEX_WRAP_REPEAT); + m_device->SetTextureStageWrap(1, TEX_WRAP_REPEAT, TEX_WRAP_REPEAT); } else // if (state & ENG_RSTATE_CLAMP) or otherwise { - TextureStageParams p1 = m_device->GetTextureStageParams(0); - p1.wrapS = p1.wrapT = TEX_WRAP_CLAMP; - m_device->SetTextureStageParams(0, p1); - - TextureStageParams p2 = m_device->GetTextureStageParams(1); - p2.wrapS = p2.wrapT = TEX_WRAP_CLAMP; - m_device->SetTextureStageParams(1, p2); + m_device->SetTextureStageWrap(0, TEX_WRAP_CLAMP, TEX_WRAP_CLAMP); + m_device->SetTextureStageWrap(1, TEX_WRAP_CLAMP, TEX_WRAP_CLAMP); } if (state & ENG_RSTATE_2FACE) @@ -2069,6 +2050,11 @@ void CEngine::SetState(int state, const Color& color) m_device->SetGlobalAmbient(Color(1.0f, 1.0f, 1.0f, 1.0f)); else m_device->SetGlobalAmbient(m_ambientColor[m_rankView]); + + + // In interface mode, disable lighting + if (m_interfaceMode) + m_device->SetRenderState(RENDER_STATE_LIGHTING, false); } void CEngine::SetMaterial(const Material& mat) @@ -2177,16 +2163,35 @@ bool CEngine::LoadAllTextures() EngineObjLevel1& p1 = m_objectTree[l1]; if (! p1.used) continue; + bool terrain = false; + + for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++) + { + EngineObjLevel2& p2 = p1.next[l2]; + if (! p2.used) continue; + + if (m_objects[p2.objRank].type == ENG_OBJTYPE_TERRAIN) + terrain = true; + } + if (! p1.tex1Name.empty()) { - p1.tex1 = LoadTexture(p1.tex1Name); + if (terrain) + p1.tex1 = LoadTexture(p1.tex1Name, m_terrainTexParams); + else + p1.tex1 = LoadTexture(p1.tex1Name); + if (! p1.tex1.Valid()) ok = false; } if (! p1.tex2Name.empty()) { - p1.tex2 = LoadTexture(p1.tex2Name); + if (terrain) + p1.tex2 = LoadTexture(p1.tex2Name, m_terrainTexParams); + else + p1.tex2 = LoadTexture(p1.tex2Name); + if (! p1.tex2.Valid()) ok = false; } @@ -2810,7 +2815,7 @@ void CEngine::Draw3DScene() if (m_shadowVisible) { - m_lightMan->UpdateLightsEnableState(ENG_OBJTYPE_TERRAIN); + m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN); // Draw the terrain @@ -2910,7 +2915,7 @@ void CEngine::Draw3DScene() if (! IsVisible(objRank)) continue; - m_lightMan->UpdateLightsEnableState(m_objects[objRank].type); + m_lightMan->UpdateDeviceLights(m_objects[objRank].type); for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++) { @@ -2999,7 +3004,7 @@ void CEngine::Draw3DScene() if (! IsVisible(objRank)) continue; - m_lightMan->UpdateLightsEnableState(m_objects[objRank].type); + m_lightMan->UpdateDeviceLights(m_objects[objRank].type); for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++) { @@ -3041,7 +3046,7 @@ void CEngine::Draw3DScene() } } - m_lightMan->UpdateLightsEnableState(ENG_OBJTYPE_TERRAIN); + m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN); if (m_waterMode) m_water->DrawSurf(); // draws water surface @@ -3064,11 +3069,20 @@ void CEngine::DrawInterface() m_device->SetTransform(TRANSFORM_PROJECTION, m_matProjInterface); m_device->SetTransform(TRANSFORM_WORLD, m_matWorldInterface); + // Force new state to disable lighting + m_interfaceMode = true; + m_lastState = -1; + SetState(Gfx::ENG_RSTATE_NORMAL); + // Draw the entire interface Ui::CInterface* interface = static_cast<Ui::CInterface*>( m_iMan->SearchInstance(CLASS_INTERFACE) ); if (interface != nullptr) interface->Draw(); + m_interfaceMode = false; + m_lastState = -1; + SetState(Gfx::ENG_RSTATE_NORMAL); + m_particle->DrawParticle(SH_INTERFACE); // draws the particles of the interface // 3D objects drawn in front of interface @@ -3117,7 +3131,7 @@ void CEngine::DrawInterface() if (! IsVisible(objRank)) continue; - m_lightMan->UpdateLightsEnableState(m_objects[objRank].type); + m_lightMan->UpdateDeviceLights(m_objects[objRank].type); for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++) { @@ -3559,7 +3573,6 @@ void CEngine::DrawOverColor() m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false); m_device->SetRenderState(RENDER_STATE_LIGHTING, false); m_device->SetRenderState(RENDER_STATE_FOG, false); - m_device->SetRenderState(RENDER_STATE_TEXTURING, false); m_device->SetTransform(TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(TRANSFORM_PROJECTION, m_matProjInterface); diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index e36865c..6363fd3 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -568,7 +568,7 @@ struct EngineMouse * * It uses a lower-level CDevice object which is implementation-independent core engine. * - * \section 3DScene 3D Scene + * \section Scene 3D Scene * * The 3D scene is drawn with view coordinates set from camera position in 3D space and * a perspective projection matrix. The world matrix depends on the object drawn. @@ -588,7 +588,7 @@ struct EngineMouse * - mouse cursor * - animated highlight box of the selected object(s) * - * \section 2DInterface 2D Interface + * \section Interface 2D Interface * * The 2D interface is drawn in fixed XY coordinates, independent from window size. * Lower-left corner of the screen is (0,0) and upper-right corner is (1,1). @@ -601,7 +601,7 @@ struct EngineMouse * are instances of CControl class. The source code for these classes is in * src/ui directory. * - * \section Objecs Engine Objects + * \section Objects Engine Objects * * The 3D scene is composed of objects which are basically collections of triangles forming * a surface or simply independent triangles in space. @@ -1348,6 +1348,8 @@ protected: //! Default texture create params TextureCreateParams m_defaultTexParams; + //! Create params for terrain textures + TextureCreateParams m_terrainTexParams; //! Map of loaded textures (by name) std::map<std::string, Texture> m_texNameMap; @@ -1375,6 +1377,9 @@ protected: std::string m_lastTexture[2]; //! Last material Material m_lastMaterial; + + //! True when drawing 2D UI + bool m_interfaceMode; }; diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp index 02719de..3055f08 100644 --- a/src/graphics/engine/lightman.cpp +++ b/src/graphics/engine/lightman.cpp @@ -18,6 +18,7 @@ #include "graphics/engine/lightman.h" +#include "common/logger.h" #include "common/iman.h" #include "graphics/core/device.h" @@ -28,6 +29,7 @@ #include <cmath> +// Graphics module namespace namespace Gfx { @@ -70,6 +72,7 @@ void LightProgression::SetTarget(float value) DynamicLight::DynamicLight() { used = enabled = false; + priority = LIGHT_PRI_LOW; includeType = excludeType = ENG_OBJTYPE_NULL; } @@ -80,7 +83,7 @@ CLightManager::CLightManager(CInstanceManager* iMan, CEngine* engine) m_iMan = iMan; m_iMan->AddInstance(CLASS_LIGHT, this); - m_device = NULL; + m_device = nullptr; m_engine = engine; m_time = 0.0f; @@ -90,56 +93,54 @@ CLightManager::~CLightManager() { m_iMan->DeleteInstance(CLASS_LIGHT, this); - m_iMan = NULL; - m_device = NULL; - m_engine = NULL; + m_iMan = nullptr; + m_device = nullptr; + m_engine = nullptr; } void CLightManager::SetDevice(CDevice* device) { m_device = device; - - m_dynLights = std::vector<DynamicLight>(m_device->GetMaxLightCount(), DynamicLight()); + m_lightMap = std::vector<int>(m_device->GetMaxLightCount(), -1); } void CLightManager::FlushLights() { - for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++) - { - m_dynLights[i].used = false; - m_device->SetLightEnabled(i, false); - } + m_dynLights.clear(); } -/** Returns the index of light created or -1 if all lights are used. */ -int CLightManager::CreateLight() +/** Returns the index of light created. */ +int CLightManager::CreateLight(LightPriority priority) { - for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++) + int index = 0; + for (; index < static_cast<int>( m_dynLights.size() ); index++) { - if (m_dynLights[i].used) continue; - - m_dynLights[i] = DynamicLight(); + if (! m_dynLights[index].used) + break; + } - m_dynLights[i].used = true; - m_dynLights[i].enabled = true; + if (index == static_cast<int>(m_dynLights.size())) + m_dynLights.push_back(DynamicLight()); - m_dynLights[i].includeType = ENG_OBJTYPE_NULL; - m_dynLights[i].excludeType = ENG_OBJTYPE_NULL; + m_dynLights[index] = DynamicLight(); + m_dynLights[index].used = true; + m_dynLights[index].enabled = true; + m_dynLights[index].priority = priority; - m_dynLights[i].light.type = LIGHT_DIRECTIONAL; - m_dynLights[i].light.diffuse = Color(0.5f, 0.5f, 0.5f); - m_dynLights[i].light.position = Math::Vector(-100.0f, 100.0f, -100.0f); - m_dynLights[i].light.direction = Math::Vector( 1.0f, -1.0f, 1.0f); + m_dynLights[index].includeType = ENG_OBJTYPE_NULL; + m_dynLights[index].excludeType = ENG_OBJTYPE_NULL; - m_dynLights[i].intensity.Init(1.0f); // maximum - m_dynLights[i].colorRed.Init(0.5f); - m_dynLights[i].colorGreen.Init(0.5f); - m_dynLights[i].colorBlue.Init(0.5f); // gray + m_dynLights[index].light.type = LIGHT_DIRECTIONAL; + m_dynLights[index].light.diffuse = Color(0.5f, 0.5f, 0.5f); + m_dynLights[index].light.position = Math::Vector(-100.0f, 100.0f, -100.0f); + m_dynLights[index].light.direction = Math::Vector( 1.0f, -1.0f, 1.0f); - return i; - } + m_dynLights[index].intensity.Init(1.0f); // maximum + m_dynLights[index].colorRed.Init(0.5f); + m_dynLights[index].colorGreen.Init(0.5f); + m_dynLights[index].colorBlue.Init(0.5f); // gray - return -1; + return index; } bool CLightManager::DeleteLight(int lightRank) @@ -148,8 +149,6 @@ bool CLightManager::DeleteLight(int lightRank) return false; m_dynLights[lightRank].used = false; - m_device->SetLightEnabled(lightRank, false); - return true; } @@ -357,7 +356,6 @@ void CLightManager::UpdateProgression(float rTime) } } - void CLightManager::UpdateLights() { for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++) @@ -366,7 +364,8 @@ void CLightManager::UpdateLights() continue; bool enabled = m_dynLights[i].enabled; - if (m_dynLights[i].intensity.current == 0.0f) + + if (Math::IsZero(m_dynLights[i].intensity.current)) enabled = false; if (enabled) @@ -379,42 +378,96 @@ void CLightManager::UpdateLights() value = m_dynLights[i].colorBlue.current * m_dynLights[i].intensity.current; m_dynLights[i].light.diffuse.b = value; - - m_device->SetLight(i, m_dynLights[i].light); - m_device->SetLightEnabled(i, enabled); } else { m_dynLights[i].light.diffuse.r = 0.0f; m_dynLights[i].light.diffuse.g = 0.0f; m_dynLights[i].light.diffuse.b = 0.0f; - - m_device->SetLightEnabled(i, enabled); } } } -void CLightManager::UpdateLightsEnableState(EngineObjectType type) +void CLightManager::UpdateDeviceLights(EngineObjectType type) { + for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i) + m_lightMap[i] = -1; + + // High priority for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++) { if (! m_dynLights[i].used) continue; if (! m_dynLights[i].enabled) continue; - if (m_dynLights[i].intensity.current == 0.0f) + if (Math::IsZero(m_dynLights[i].intensity.current)) + continue; + if (m_dynLights[i].priority == LIGHT_PRI_LOW) continue; + bool enabled = true; if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL) + enabled = (m_dynLights[i].includeType == type); + + if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL) + enabled = (m_dynLights[i].excludeType != type); + + if (enabled) { - bool enabled = (m_dynLights[i].includeType == type); - m_device->SetLightEnabled(i, enabled); + for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j) + { + if (m_lightMap[j] == -1) + { + m_lightMap[j] = i; + break; + } + } } + } + + // Low priority + for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++) + { + if (! m_dynLights[i].used) + continue; + if (! m_dynLights[i].enabled) + continue; + if (m_dynLights[i].intensity.current == 0.0f) + continue; + if (m_dynLights[i].priority == LIGHT_PRI_HIGH) + continue; + + bool enabled = true; + if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL) + enabled = (m_dynLights[i].includeType == type); if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL) + enabled = (m_dynLights[i].excludeType != type); + + if (enabled) + { + for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j) + { + if (m_lightMap[j] == -1) + { + m_lightMap[j] = i; + break; + } + } + } + } + + for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i) + { + int rank = m_lightMap[i]; + if (rank != -1) + { + m_device->SetLight(i, m_dynLights[rank].light); + m_device->SetLightEnabled(i, true); + } + else { - bool enabled = (m_dynLights[i].excludeType != type); - m_device->SetLightEnabled(i, enabled); + m_device->SetLightEnabled(i, false); } } } diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h index c50d176..d83dfb3 100644 --- a/src/graphics/engine/lightman.h +++ b/src/graphics/engine/lightman.h @@ -34,8 +34,9 @@ namespace Gfx { /** - \struct LightProgression - \brief Describes the progression of light parameters change */ + * \struct LightProgression + * \brief Describes the progression of light parameters change + */ struct LightProgression { //! Starting value @@ -65,11 +66,22 @@ struct LightProgression }; /** - \struct DynamicLight - \brief Dynamic light in 3D scene + * \enum LightPriority + * \brief Priority in light assignment + */ +enum LightPriority +{ + LIGHT_PRI_HIGH, + LIGHT_PRI_LOW +}; - It is an extension over standard light properties. Added are dynamic progressions for light - colors and intensity and types of objects included/excluded in lighting. */ +/** + * \struct DynamicLight + * \brief Dynamic light in 3D scene + * + * It is an extension over standard light properties. Added are dynamic progressions for light + * colors and intensity and types of objects included/excluded in lighting. + */ struct DynamicLight { //! Whether the light is used @@ -77,6 +89,9 @@ struct DynamicLight //! Whether the light is turned on bool enabled; + //! Priority in assignment + LightPriority priority; + //! Configuration of the light Light light; @@ -98,17 +113,18 @@ struct DynamicLight }; /** - \class CLightManager - \brief Manager for dynamic lights in 3D scene - - (Old CLight class) - - The class is responsible for managing dynamic lights (struct DynamicLight) used in 3D scene. - The dynamic lights are created, updated and deleted through the class' interface. - - Number of available lights depends on graphics device used. Class allocates vector - for the total number of lights, but only some are used. - */ + * \class CLightManager + * \brief Manager for dynamic lights in 3D scene + * + * The class is responsible for managing dynamic lights (struct DynamicLight) used in 3D scene. + * The dynamic lights are created, updated and deleted through the class' interface. + * + * Since there is a limit on total number of lights available in OpenGL (usually up to 8), the dynamic lights + * must be emulated by displaying only some of them. All functions normally operate only on DynamicLight structs, + * updating the models with new values, while only one function, UpdateDeviceLights(), performs the actual + * synchronization to the device. It allocates device's light slots as necessary, with two priority levels + * for lights. + */ class CLightManager { public: @@ -123,7 +139,7 @@ public: //! Clears and disables all lights void FlushLights(); //! Creates a new dynamic light and returns its index (lightRank) - int CreateLight(); + int CreateLight(LightPriority priority = LIGHT_PRI_LOW); //! Deletes and disables the given dynamic light bool DeleteLight(int lightRank); //! Sets the light parameters for dynamic light @@ -161,7 +177,7 @@ public: //! Sets the destination color for dynamic light's color progression bool SetLightColor(int lightRank, const Color &color); //! Returns current light color - Color GetLightColor(int lightRank); + Color GetLightColor(int lightRank); //! Sets the rate of change for dynamic light colors (RGB) bool SetLightColorSpeed(int lightRank, float speed); @@ -170,7 +186,7 @@ public: //! Updates (recalculates) all dynamic lights void UpdateLights(); //! Enables or disables dynamic lights affecting the given object type - void UpdateLightsEnableState(EngineObjectType type); + void UpdateDeviceLights(EngineObjectType type); protected: CInstanceManager* m_iMan; @@ -181,6 +197,8 @@ protected: float m_time; //! List of dynamic lights std::vector<DynamicLight> m_dynLights; + //! Map of current light allotment: graphics light -> dynamic light + std::vector<int> m_lightMap; }; }; // namespace Gfx diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp index 0ac2524..3b9aa6c 100644 --- a/src/graphics/engine/planet.cpp +++ b/src/graphics/engine/planet.cpp @@ -147,7 +147,8 @@ void CPlanet::Draw() } void CPlanet::Create(int mode, Math::Point start, float dim, float speed, - float dir, const std::string& name, Math::Point uv1, Math::Point uv2) + float dir, const std::string& name, Math::Point uv1, Math::Point uv2, + bool transparent) { if (mode < 0) mode = 0; if (mode > 1) mode = 1; @@ -164,7 +165,7 @@ void CPlanet::Create(int mode, Math::Point start, float dim, float speed, planet.uv1 = uv1; planet.uv2 = uv2; - planet.transparent = planet.name.find("planet") != std::string::npos; + planet.transparent = transparent; m_planet[mode].push_back(planet); diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 82c3aea..1b16da0 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -91,7 +91,8 @@ public: bool EventProcess(const Event &event); //! Creates a new planet void Create(int mode, Math::Point start, float dim, float speed, float dir, - const std::string& name, Math::Point uv1, Math::Point uv2); + const std::string& name, Math::Point uv1, Math::Point uv2, + bool transparent); //! Indicates if there is at least one planet bool PlanetExist(); //! Load all the textures for the planets diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index d2ddecc..4c22a32 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -74,7 +74,7 @@ CTerrain::~CTerrain() } bool CTerrain::Generate(int mosaicCount, int brickCountPow2, float brickSize, - float vision, int depth, float hardness) + float vision, int depth, float hardness) { m_mosaicCount = mosaicCount; m_brickCount = 1 << brickCountPow2; @@ -162,8 +162,8 @@ void CTerrain::FlushMaterials() } void CTerrain::AddMaterial(int id, const std::string& texName, const Math::Point &uv, - int up, int right, int down, int left, - float hardness) + int up, int right, int down, int left, + float hardness) { InitMaterialPoints(); @@ -207,25 +207,41 @@ bool CTerrain::LoadResources(const std::string& fileName) ImageData *data = img.GetData(); - int size = (m_mosaicCount*m_brickCount)+1; - - m_resources.clear(); + int size = (m_mosaicCount*m_brickCount)+1; - std::vector<unsigned char>(3*size*size).swap(m_resources); + std::vector<unsigned char>(size*size).swap(m_resources); - if ( (data->surface->w != size) || (data->surface->h != size) || - (data->surface->format->BytesPerPixel != 3) ) + if ( (data->surface->w != size) || (data->surface->h != size) ) { GetLogger()->Error("Invalid resource file\n"); return false; } - unsigned char* pixels = static_cast<unsigned char*>(data->surface->pixels); - int pitch = data->surface->pitch; - - for (int y = 0; y < size; y++) + for (int x = 0; x < size; ++x) { - memcpy(&m_resources[3*size*y], &pixels[pitch*y], 3*size); + for (int y = 0; y < size; ++y) + { + Gfx::IntColor pixel = img.GetPixelInt(Math::IntPoint(x, size - y - 1)); + TerrainRes res = TR_NULL; + + // values from original bitmap palette + if (pixel.r == 255 && pixel.g == 0 && pixel.b == 0) + res = TR_STONE; + else if (pixel.r == 255 && pixel.g == 255 && pixel.b == 0) + res = TR_URANIUM; + else if (pixel.r == 0 && pixel.g == 255 && pixel.b == 0) + res = TR_POWER; + else if (pixel.r == 0 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_A; + else if (pixel.r == 51 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_B; + else if (pixel.r == 102 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_C; + else if (pixel.r == 153 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_D; + + m_resources[x+size*y] = static_cast<unsigned char>(res); + } } return true; @@ -243,23 +259,9 @@ TerrainRes CTerrain::GetResource(const Math::Vector &p) y < 0 || y > m_mosaicCount*m_brickCount ) return TR_NULL; - int size = (m_mosaicCount*m_brickCount)+1; - - int resR = m_resources[3*x+3*size*(size-y-1)]; - int resG = m_resources[3*x+3*size*(size-y-1)+1]; - int resB = m_resources[3*x+3*size*(size-y-1)+2]; - - if (resR == 255 && resG == 0 && resB == 0) return TR_STONE; - if (resR == 255 && resG == 255 && resB == 0) return TR_URANIUM; - if (resR == 0 && resG == 255 && resB == 0) return TR_POWER; - - // TODO key res values - //if (ress == 24) return TR_KEY_A; // ~green? - //if (ress == 25) return TR_KEY_B; // ~green? - //if (ress == 26) return TR_KEY_C; // ~green? - //if (ress == 27) return TR_KEY_D; // ~green? + int size = (m_mosaicCount*m_brickCount)+1; - return TR_NULL; + return static_cast<TerrainRes>( m_resources[x+size*y] ); } void CTerrain::FlushRelief() @@ -287,22 +289,21 @@ bool CTerrain::LoadRelief(const std::string &fileName, float scaleRelief, int size = (m_mosaicCount*m_brickCount)+1; - if ( (data->surface->w != size) || (data->surface->h != size) || - (data->surface->format->BytesPerPixel != 3) ) + if ( (data->surface->w != size) || (data->surface->h != size) ) { GetLogger()->Error("Invalid relief file!\n"); return false; } - unsigned char* pixels = static_cast<unsigned char*>(data->surface->pixels); - int pitch = data->surface->pitch; - float limit = 0.9f; for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { - float level = (255 - pixels[3*x+pitch*(size-y-1)]) * scaleRelief; + Gfx::IntColor color = img.GetPixelInt(Math::IntPoint(x, size - y - 1)); + + float avg = (color.r + color.g + color.b) / 3.0f; // to be sure it is grayscale + float level = (255.0f - avg) * scaleRelief; float dist = Math::Max(fabs(static_cast<float>(x-size/2)), fabs(static_cast<float>(y-size/2))); @@ -492,8 +493,8 @@ VertexTex2 CTerrain::GetVertex(int x, int y, int step) +-------------------> x \endverbatim */ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, - const Material &mat, - float min, float max) + const Material &mat, + float min, float max) { std::string texName1; std::string texName2; @@ -1057,8 +1058,8 @@ bool CTerrain::InitMaterials(int id) } bool CTerrain::GenerateMaterials(int *id, float min, float max, - float slope, float freq, - Math::Vector center, float radius) + float slope, float freq, + Math::Vector center, float radius) { static char random[100] = { @@ -1454,13 +1455,14 @@ bool CTerrain::AdjustToFloor(Math::Vector &pos, bool brut, bool water) } /** - * @returns \c false if the initial coordinate was outside terrain area; \c true otherwise + * \param pos position to adjust + * \returns \c false if the initial coordinate was outside terrain area; \c true otherwise */ bool CTerrain::AdjustToStandardBounds(Math::Vector& pos) { bool ok = true; - // TODO: _TEEN ... * 0.98f; + // In _TEEN there used to be a limit of 0.98f float limit = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f*0.92f; if (pos.x < -limit) @@ -1491,8 +1493,9 @@ bool CTerrain::AdjustToStandardBounds(Math::Vector& pos) } /** - * @param margin margin to the terrain border - * @returns \c false if the initial coordinate was outside terrain area; \c true otherwise + * \param pos position to adjust + * \param margin margin to the terrain border + * \returns \c false if the initial coordinate was outside terrain area; \c true otherwise */ bool CTerrain::AdjustToBounds(Math::Vector& pos, float margin) { @@ -1718,14 +1721,14 @@ float CTerrain::GetFlatZoneRadius(Math::Vector center, float max) float ref = GetFloorLevel(center, true); Math::Point c(center.x, center.z); float radius = 1.0f; - + while (radius <= max) { angle = 0.0f; int nb = static_cast<int>(2.0f*Math::PI*radius); if (nb < 8) nb = 8; - Math::Point p (center.x+radius, center.z); + Math::Point p (center.x+radius, center.z); for (int i = 0; i < nb; i++) { Math::Point result = Math::RotatePoint(c, angle, p); diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index a77a6fd..9091905 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -279,18 +279,14 @@ float CText::GetHeight(FontType font, float size) float CText::GetStringWidth(const std::string &text, std::map<unsigned int, FontMetaChar> &format, float size) { - // TODO assert was commented as new code uses map not vector and if's size doesn't have to match text length - // this has to be tested if it's correct - //assert(StrUtils::Utf8StringLength(text) == format.size()); - float width = 0.0f; unsigned int index = 0; unsigned int fmtIndex = 0; while (index < text.length()) { FontType font = FONT_COLOBOT; - if (format.count(fmtIndex)) - font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); + if (format.count(fmtIndex)) + font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); UTF8Char ch; @@ -350,10 +346,6 @@ float CText::GetCharWidth(UTF8Char ch, FontType font, float size, float offset) int CText::Justify(const std::string &text, std::map<unsigned int, FontMetaChar> &format, float size, float width) { - // TODO assert was commented as new code uses map not vector and if's size doesn't have to match text length - // this has to be tested if it's correct - //assert(StrUtils::Utf8StringLength(text) == format.size()); - float pos = 0.0f; int cut = 0; unsigned int index = 0; @@ -361,8 +353,8 @@ int CText::Justify(const std::string &text, std::map<unsigned int, FontMetaChar> while (index < text.length()) { FontType font = FONT_COLOBOT; - if (format.count(fmtIndex)) - font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); + if (format.count(fmtIndex)) + font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); UTF8Char ch; @@ -437,18 +429,14 @@ int CText::Justify(const std::string &text, FontType font, float size, float wid int CText::Detect(const std::string &text, std::map<unsigned int, FontMetaChar> &format, float size, float offset) { - // TODO assert was commented as new code uses map not vector and if's size doesn't have to match text length - // this has to be tested if it's correct - //assert(StrUtils::Utf8StringLength(text) == format.size()); - float pos = 0.0f; unsigned int index = 0; unsigned int fmtIndex = 0; while (index < text.length()) { FontType font = FONT_COLOBOT; - if (format.count(fmtIndex)) - font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); + if (format.count(fmtIndex)) + font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); // TODO: if (font == FONT_BUTTON) if (font == FONT_BUTTON) continue; @@ -514,13 +502,8 @@ int CText::Detect(const std::string &text, FontType font, float size, float offs void CText::DrawString(const std::string &text, std::map<unsigned int, FontMetaChar> &format, float size, Math::Point pos, float width, int eol) { - // TODO assert was commented as new code uses map not vector and if's size doesn't have to match text length - // this has to be tested if it's correct - //assert(StrUtils::Utf8StringLength(text) == format.size()); - m_engine->SetState(ENG_RSTATE_TEXT); - FontType font = FONT_COLOBOT; float start = pos.x; unsigned int fmtIndex = 0; @@ -530,8 +513,8 @@ void CText::DrawString(const std::string &text, std::map<unsigned int, FontMetaC for (auto it = chars.begin(); it != chars.end(); ++it) { FontType font = FONT_COLOBOT; - if (format.count(fmtIndex)) - font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); + if (format.count(fmtIndex)) + font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT); // TODO: if (font == FONT_BUTTON) if (font == FONT_BUTTON) continue; @@ -566,17 +549,18 @@ void CText::DrawString(const std::string &text, std::map<unsigned int, FontMetaC void CText::StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars) { unsigned int index = 0; - while (index < text.length()) + unsigned int totalLength = text.length(); + while (index < totalLength) { UTF8Char ch; int len = StrUtils::Utf8CharSizeAt(text, index); if (len >= 1) - ch.c1 = text[index]; + ch.c1 = text[index]; if (len >= 2) - ch.c2 = text[index+1]; + ch.c2 = text[index+1]; if (len >= 3) - ch.c3 = text[index+2]; + ch.c3 = text[index+2]; index += len; @@ -663,7 +647,7 @@ void CText::DrawHighlight(FontHighlight hl, Math::Point pos, Math::Point size) p2.y = pos.y + size.y; } - m_device->SetRenderState(RENDER_STATE_TEXTURING, false); + m_device->SetTextureEnabled(0, false); VertexCol quad[] = { @@ -676,7 +660,7 @@ void CText::DrawHighlight(FontHighlight hl, Math::Point pos, Math::Point size) m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, quad, 4); m_engine->AddStatisticTriangle(2); - m_device->SetRenderState(RENDER_STATE_TEXTURING, true); + m_device->SetTextureEnabled(0, true); } void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::Point &pos) diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index cc18f55..7fa8768 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -149,9 +149,12 @@ enum FontMask struct UTF8Char { char c1, c2, c3; + // Padding for 4-byte alignment + // It also seems to fix some problems reported by valgrind + char pad; explicit UTF8Char(char ch1 = '\0', char ch2 = '\0', char ch3 = '\0') - : c1(ch1), c2(ch2), c3(ch3) {} + : c1(ch1), c2(ch2), c3(ch3), pad('\0') {} inline bool operator<(const UTF8Char &other) const { diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 81034a3..18811eb 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -279,11 +279,9 @@ void CWater::DrawBack() material.ambient = m_ambient; m_engine->SetMaterial(material); - m_engine->SetTexture("", 0); // TODO: disable texturing - CDevice* device = m_engine->GetDevice(); - m_engine->SetState(ENG_RSTATE_NORMAL); + m_engine->SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR); float deep = m_engine->GetDeepView(0); m_engine->SetDeepView(deep*2.0f, 0); @@ -310,17 +308,14 @@ void CWater::DrawBack() p1.y = -50.0f; p2.y = m_level; - Math::Vector n; - n.x = (lookat.x-eye.x)/dist; - n.z = (lookat.z-eye.z)/dist; - n.y = 0.0f; + Gfx::Color white = Gfx::Color(1.0f, 1.0f, 1.0f, 0.0f); - Vertex vertices[4] = + VertexCol vertices[4] = { - Vertex(Math::Vector(p1.x, p2.y, p1.z), n), - Vertex(Math::Vector(p1.x, p1.y, p1.z), n), - Vertex(Math::Vector(p2.x, p2.y, p2.z), n), - Vertex(Math::Vector(p2.x, p1.y, p2.z), n) + VertexCol(Math::Vector(p1.x, p2.y, p1.z), white), + VertexCol(Math::Vector(p1.x, p1.y, p1.z), white), + VertexCol(Math::Vector(p2.x, p2.y, p2.z), white), + VertexCol(Math::Vector(p2.x, p1.y, p2.z), white) }; device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertices, 4); @@ -480,8 +475,8 @@ void CWater::CreateLine(int x, int y, int len) } void CWater::Create(WaterType type1, WaterType type2, const std::string& fileName, - Color diffuse, Color ambient, - float level, float glint, Math::Vector eddy) + Color diffuse, Color ambient, + float level, float glint, Math::Vector eddy) { m_type[0] = type1; m_type[1] = type2; diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index a43c740..21d96d4 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -169,10 +169,10 @@ protected: protected: CInstanceManager* m_iMan; - CEngine* m_engine; - CDevice* m_device; - CTerrain* m_terrain; - CParticle* m_particule; + CEngine* m_engine; + CDevice* m_device; + CTerrain* m_terrain; + CParticle* m_particule; CSoundInterface* m_sound; WaterType m_type[2]; @@ -184,9 +184,9 @@ protected: //! Amplitude of swirls Math::Vector m_eddy; //! Diffuse color - Color m_diffuse; + Color m_diffuse; //! Ambient color - Color m_ambient; + Color m_ambient; float m_time; float m_lastLava; int m_subdiv; @@ -201,7 +201,7 @@ protected: bool m_draw; bool m_lava; - Color m_color; + Color m_color; }; |