From a937a7b6ec081ab546505e5ab1fcd9b3723a6f4b Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 27 Jan 2013 11:43:53 +0100 Subject: Changed model min/max to LOD levels --- src/graphics/engine/engine.cpp | 199 +++++++++------------------- src/graphics/engine/engine.h | 41 +++--- src/graphics/engine/modelfile.cpp | 146 ++++++++++++-------- src/graphics/engine/modelfile.h | 35 +++-- src/graphics/engine/modelmanager.cpp | 24 +--- src/graphics/engine/pyro.cpp | 38 ++++-- src/graphics/engine/terrain.cpp | 13 +- src/graphics/engine/terrain.h | 2 +- src/graphics/engine/test/modelfile_test.cpp | 17 +-- 9 files changed, 226 insertions(+), 289 deletions(-) (limited to 'src/graphics/engine') diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 7c90a8d..71b5e7d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -109,13 +109,9 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f); m_drawWorld = true; m_drawFront = false; - m_limitLOD[0] = 100.0f; - m_limitLOD[1] = 200.0f; m_particleDensity = 1.0f; - m_clippingDistance = 1.0f; m_lastClippingDistance = m_clippingDistance = 1.0f; m_objectDetail = 1.0f; - m_lastObjectDetail = m_objectDetail; m_terrainVision = 1000.0f; m_gadgetQuantity = 1.0f; m_textureQuality = 1; @@ -130,7 +126,6 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app) m_editIndentValue = 4; m_tracePrecision = 1.0f; - m_alphaMode = 1; m_updateGeometry = false; m_updateStaticBuffers = false; @@ -208,7 +203,7 @@ CText* CEngine::GetText() bool CEngine::Create() { - m_size = m_lastSize = m_app->GetVideoConfig().size; + m_size = m_app->GetVideoConfig().size; m_lightMan = new CLightManager(m_iMan, this); m_text = new CText(m_iMan, this); @@ -416,11 +411,6 @@ Math::IntPoint CEngine::GetWindowSize() return m_size; } -Math::IntPoint CEngine::GetLastWindowSize() -{ - return m_lastSize; -} - Math::Point CEngine::WindowToInterfaceCoords(Math::IntPoint pos) { return Math::Point( static_cast(pos.x) / static_cast(m_size.x), @@ -473,15 +463,15 @@ EngineBaseObjTexTier& CEngine::AddLevel2(EngineBaseObject& p1, const std::string return p1.next.back(); } -EngineBaseObjLODTier& CEngine::AddLevel3(EngineBaseObjTexTier& p2, float min, float max) +EngineBaseObjLODTier& CEngine::AddLevel3(EngineBaseObjTexTier& p2, LODLevel lodLevel) { for (int i = 0; i < static_cast( p2.next.size() ); i++) { - if ( (p2.next[i].min == min) && (p2.next[i].max == max) ) + if (p2.next[i].lodLevel == lodLevel) return p2.next[i]; } - p2.next.push_back(EngineBaseObjLODTier(min, max)); + p2.next.push_back(EngineBaseObjLODTier(lodLevel)); return p2.next.back(); } @@ -570,17 +560,13 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector EngineTriangleType triangleType, const Material& material, int state, std::string tex1Name, std::string tex2Name, - float min, float max, bool globalUpdate) + LODLevel lodLevel, bool globalUpdate) { assert(baseObjRank >= 0 && baseObjRank < static_cast( m_baseObjects.size() )); - m_lastSize = m_size; - m_lastObjectDetail = m_objectDetail; - m_lastClippingDistance = m_clippingDistance; - EngineBaseObject& p1 = m_baseObjects[baseObjRank]; EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name); - EngineBaseObjLODTier& p3 = AddLevel3(p2, min, max); + EngineBaseObjLODTier& p3 = AddLevel3(p2, lodLevel); EngineBaseObjDataTier& p4 = AddLevel4(p3, triangleType, material, state); p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end()); @@ -615,13 +601,13 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector void CEngine::AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buffer, std::string tex1Name, std::string tex2Name, - float min, float max, bool globalUpdate) + LODLevel lodLevel, bool globalUpdate) { assert(baseObjRank >= 0 && baseObjRank < static_cast( m_baseObjects.size() )); EngineBaseObject& p1 = m_baseObjects[baseObjRank]; EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name); - EngineBaseObjLODTier& p3 = AddLevel3(p2, min, max); + EngineBaseObjLODTier& p3 = AddLevel3(p2, lodLevel); p3.next.push_back(buffer); @@ -797,7 +783,7 @@ int CEngine::GetObjectTotalTriangles(int objRank) EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, const Material& material, int state, std::string tex1Name, - std::string tex2Name, float min, float max) + std::string tex2Name, int lodLevelMask) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); @@ -820,7 +806,7 @@ EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, const Material& mater { EngineBaseObjLODTier& p3 = p2.next[l3]; - if (p3.min != min || p3.max != max) + if ((p3.lodLevel & lodLevelMask) == 0) continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) @@ -839,7 +825,7 @@ EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, const Material& mater return nullptr; } -int CEngine::GetPartialTriangles(int objRank, float min, float max, float percent, int maxCount, +int CEngine::GetPartialTriangles(int objRank, int lodLevelMask, float percent, int maxCount, std::vector& triangles) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); @@ -866,7 +852,7 @@ int CEngine::GetPartialTriangles(int objRank, float min, float max, float percen { EngineBaseObjLODTier& p3 = p2.next[l3]; - if (p3.min != min || p3.max != max) + if ((p3.lodLevel & lodLevelMask) == 0) continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) @@ -928,68 +914,6 @@ int CEngine::GetPartialTriangles(int objRank, float min, float max, float percen return actualCount; } -void CEngine::ChangeLOD() -{ - float oldLimit[2] = - { - GetLimitLOD(0, true), - GetLimitLOD(1, true) - }; - - float newLimit[2] = - { - GetLimitLOD(0, false), - GetLimitLOD(1, false) - }; - - float oldTerrain = m_terrainVision * m_lastClippingDistance; - float newTerrain = m_terrainVision * m_clippingDistance; - - for (int baseObjRank = 0; baseObjRank < static_cast( m_baseObjects.size() ); baseObjRank++) - { - EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - - if (! p1.used) - continue; - - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) - { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjLODTier& p3 = p2.next[l3]; - - if ( Math::IsEqual(p3.min, 0.0f ) && - Math::IsEqual(p3.max, oldLimit[0]) ) - { - p3.max = newLimit[0]; - } - else if ( Math::IsEqual(p3.min, oldLimit[0]) && - Math::IsEqual(p3.max, oldLimit[1]) ) - { - p3.min = newLimit[0]; - p3.max = newLimit[1]; - } - else if ( Math::IsEqual(p3.min, oldLimit[1]) && - Math::IsEqual(p3.max, 1000000.0f ) ) - { - p3.min = newLimit[1]; - } - else if ( Math::IsEqual(p3.min, 0.0f ) && - Math::IsEqual(p3.max, oldTerrain) ) - { - p3.max = newTerrain; - } - } - } - } - - m_lastSize = m_size; - m_lastObjectDetail = m_objectDetail; - m_lastClippingDistance = m_clippingDistance; -} - void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); @@ -1016,12 +940,12 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name) void CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state, const std::string& tex1Name, const std::string& tex2Name, - float min, float max, EngineTextureMapping mode, + int lodLevelMask, EngineTextureMapping mode, float au, float bu, float av, float bv) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); - EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, min, max); + EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, lodLevelMask); if (p4 == nullptr) return; @@ -1078,12 +1002,12 @@ void CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state, void CEngine::TrackTextureMapping(int objRank, const Material& mat, int state, const std::string& tex1Name, const std::string& tex2Name, - float min, float max, EngineTextureMapping mode, + int lodLevelMask, EngineTextureMapping mode, float pos, float factor, float tl, float ts, float tt) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); - EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, min, max); + EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, lodLevelMask); if (p4 == nullptr) return; @@ -1707,8 +1631,8 @@ int CEngine::DetectObject(Math::Point mouse) { EngineBaseObjLODTier& p3 = p2.next[l3]; - if (p3.min != 0.0f) - continue; // LOD B or C? + if (p3.lodLevel != LOD_Constant && p3.lodLevel != LOD_High) + continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) { @@ -1820,6 +1744,43 @@ bool CEngine::IsVisible(int objRank) return false; } +bool CEngine::IsWithinLODLimit(float distance, LODLevel lodLevel) +{ + float min = 0.0f, max = 0.0f; + + if (lodLevel == LOD_Constant) + { + min = 0.0f; + max = m_terrainVision * m_clippingDistance; + } + else + { + if (lodLevel == LOD_High) + { + min = 0.0f; + max = 100.0f; + } + else if (lodLevel == LOD_Medium) + { + min = 100.0f; + max = 200.0f; + } + else if (lodLevel == LOD_Low) + { + min = 100.0f; + max = 1000000.0f; + } + + min *= m_size.x / 640.0f; + min *= m_objectDetail*2.0f; + + max *= m_size.x / 640.0f; + max *= m_objectDetail*2.0f; + } + + return distance >= min && distance < max; +} + bool CEngine::TransformPoint(Math::Vector& p2D, int objRank, Math::Vector p3D) { assert(objRank >= 0 && objRank < static_cast(m_objects.size())); @@ -1856,15 +1817,6 @@ void CEngine::SetState(int state, const Color& color) m_lastState = state; m_lastColor = color; - if (m_alphaMode != 1 && (state & ENG_RSTATE_ALPHA)) - { - state &= ~ENG_RSTATE_ALPHA; - - if (m_alphaMode == 2) - state |= ENG_RSTATE_TTEXTURE_BLACK; - } - - if (state & ENG_RSTATE_TTEXTURE_BLACK) // transparent black texture? { m_device->SetRenderState(RENDER_STATE_FOG, false); @@ -2447,33 +2399,6 @@ void CEngine::SetTexture(const Texture& tex, int stage) m_device->SetTexture(stage, tex); } -void CEngine::SetLimitLOD(int rank, float limit) -{ - m_limitLOD[rank] = limit; -} - -float CEngine::GetLimitLOD(int rank, bool last) -{ - float limit = 0.0f; - - if (last) - { - limit = m_limitLOD[rank]; - limit *= m_lastSize.x/640.0f; // limit further if large window! - limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f); - } - else - { - limit = m_limitLOD[rank]; - limit *= m_size.x/640.0f; // limit further if large window! - limit += m_limitLOD[0]*(m_objectDetail*2.0f); - } - - if (limit < 0.0f) limit = 0.0f; - - return limit; -} - void CEngine::SetTerrainVision(float vision) { m_terrainVision = vision; @@ -2709,6 +2634,7 @@ void CEngine::SetClippingDistance(float value) { if (value < 0.5f) value = 0.5f; if (value > 2.0f) value = 2.0f; + m_lastClippingDistance = m_clippingDistance; m_clippingDistance = value; } @@ -2920,7 +2846,6 @@ void CEngine::ApplyChange() m_deepView[1] /= m_lastClippingDistance; SetFocus(m_focus); - ChangeLOD(); m_deepView[0] *= m_clippingDistance; m_deepView[1] *= m_clippingDistance; @@ -3040,8 +2965,7 @@ void CEngine::Draw3DScene() { EngineBaseObjLODTier& p3 = p2.next[l3]; - if ( m_objects[objRank].distance < p3.min || - m_objects[objRank].distance >= p3.max ) + if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel)) continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) @@ -3108,8 +3032,7 @@ void CEngine::Draw3DScene() { EngineBaseObjLODTier& p3 = p2.next[l3]; - if ( m_objects[objRank].distance < p3.min || - m_objects[objRank].distance >= p3.max ) + if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel)) continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) @@ -3177,8 +3100,7 @@ void CEngine::Draw3DScene() { EngineBaseObjLODTier& p3 = p2.next[l3]; - if (m_objects[objRank].distance < p3.min || - m_objects[objRank].distance >= p3.max) + if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel)) continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) @@ -3330,8 +3252,7 @@ void CEngine::DrawInterface() { EngineBaseObjLODTier& p3 = p2.next[l3]; - if (m_objects[objRank].distance < p3.min || - m_objects[objRank].distance >= p3.max) + if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel)) continue; for (int l4 = 0; l4 < static_cast( p3.next.size() ); l4++) diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index c9391db..e5c75bc 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -32,6 +32,8 @@ #include "graphics/core/texture.h" #include "graphics/core/vertex.h" +#include "graphics/engine/modelfile.h" + #include "math/intpoint.h" #include "math/matrix.h" #include "math/point.h" @@ -204,12 +206,11 @@ struct EngineBaseObjDataTier */ struct EngineBaseObjLODTier { - float min; - float max; + LODLevel lodLevel; std::vector next; - inline EngineBaseObjLODTier(float min = 0.0f, float max = 0.0f) - : min(min), max(max) {} + inline EngineBaseObjLODTier(LODLevel lodLevel = LOD_Constant) + : lodLevel(lodLevel) {} }; /** @@ -777,12 +778,12 @@ public: EngineTriangleType triangleType, const Material& material, int state, std::string tex1Name, std::string tex2Name, - float min, float max, bool globalUpdate); + LODLevel lodLevel, bool globalUpdate); //! Adds a tier 4 engine object directly void AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buffer, std::string tex1Name, std::string tex2Name, - float min, float max, bool globalUpdate); + LODLevel lodLevel, bool globalUpdate); // Objects @@ -827,29 +828,26 @@ public: //! Returns the first found tier 4 engine object for the given params or nullptr if not found EngineBaseObjDataTier* FindTriangles(int objRank, const Material& material, - int state, std::string tex1Name, std::string tex2Name, - float min, float max); + int state, std::string tex1Name, std::string tex2Name, + int lodLevelMask); //! Returns a partial list of triangles for given object - int GetPartialTriangles(int objRank, float min, float max, float percent, int maxCount, + int GetPartialTriangles(int objRank, int lodLevelMask, float percent, int maxCount, std::vector& triangles); - //! Updates LOD after parameter or resolution change - void ChangeLOD(); - //! Changes the 2nd texure for given object void ChangeSecondTexture(int objRank, const std::string& tex2Name); //! Changes (recalculates) texture mapping for given object void ChangeTextureMapping(int objRank, const Material& mat, int state, const std::string& tex1Name, const std::string& tex2Name, - float min, float max, EngineTextureMapping mode, + int lodLevelMask, EngineTextureMapping mode, float au, float bu, float av, float bv); //! Changes texture mapping for robot tracks void TrackTextureMapping(int objRank, const Material& mat, int state, const std::string& tex1Name, const std::string& tex2Name, - float min, float max, EngineTextureMapping mode, + int lodLevelMask, EngineTextureMapping mode, float pos, float factor, float tl, float ts, float tt); //! Detects the target object that is selected with the mouse @@ -947,12 +945,6 @@ public: //! Deletes the given texture, unloading it and removing from cache void DeleteTexture(const Texture& tex); - //@{ - //! Border management (distance limits) depends of the resolution (LOD = level-of-detail) - void SetLimitLOD(int rank, float limit); - float GetLimitLOD(int rank, bool last=false); - //@} - //! Defines of the distance field of vision void SetTerrainVision(float vision); @@ -1219,7 +1211,7 @@ protected: //! Creates a new tier 2 object (texture) EngineBaseObjTexTier& AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name); //! Creates a new tier 3 object (LOD) - EngineBaseObjLODTier& AddLevel3(EngineBaseObjTexTier &p2, float min, float max); + EngineBaseObjLODTier& AddLevel3(EngineBaseObjTexTier &p2, LODLevel lodLevel); //! Creates a new tier 4 object (data) EngineBaseObjDataTier& AddLevel4(EngineBaseObjLODTier &p3, EngineTriangleType type, const Material& mat, int state); @@ -1230,6 +1222,9 @@ protected: //! Tests whether the given object is visible bool IsVisible(int objRank); + //! Checks whether the given distance is within LOD min & max limit + bool IsWithinLODLimit(float distance, LODLevel lodLevel); + //! Detects whether an object is affected by the mouse bool DetectBBox(int objRank, Math::Point mouse); @@ -1304,8 +1299,6 @@ protected: //! Current size of viewport window Math::IntPoint m_size; - //! Previous size of viewport window - Math::IntPoint m_lastSize; //! Base objects (also level 1 tier list) std::vector m_baseObjects; @@ -1356,12 +1349,10 @@ protected: Texture m_foregroundTex; bool m_drawWorld; bool m_drawFront; - float m_limitLOD[2]; float m_particleDensity; float m_clippingDistance; float m_lastClippingDistance; float m_objectDetail; - float m_lastObjectDetail; float m_terrainVision; float m_gadgetQuantity; int m_textureQuality; diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp index a942b08..c9d41f3 100644 --- a/src/graphics/engine/modelfile.cpp +++ b/src/graphics/engine/modelfile.cpp @@ -495,8 +495,7 @@ bool CModelFile::ReadModel(std::istream& stream) triangle.material = t.material; triangle.tex1Name = std::string(t.texName); - triangle.min = t.min; - triangle.max = t.max; + triangle.lodLevel = MinMaxToLodLevel(t.min, t.max); m_triangles.push_back(triangle); } @@ -539,8 +538,7 @@ bool CModelFile::ReadModel(std::istream& stream) triangle.material = t.material; triangle.tex1Name = std::string(t.texName); - triangle.min = t.min; - triangle.max = t.max; + triangle.lodLevel = MinMaxToLodLevel(t.min, t.max); triangle.state = t.state; m_triangles.push_back(triangle); @@ -584,8 +582,7 @@ bool CModelFile::ReadModel(std::istream& stream) triangle.material = t.material; triangle.tex1Name = std::string(t.texName); - triangle.min = t.min; - triangle.max = t.max; + triangle.lodLevel = MinMaxToLodLevel(t.min, t.max); triangle.state = t.state; triangle.variableTex2 = t.texNum2 == 1; @@ -634,7 +631,7 @@ bool CModelFile::ReadModel(std::istream& stream) GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(), m_triangles[i].variableTex2 ? "(variable)" : m_triangles[i].tex2Name.c_str()); - GetLogger()->Trace(" min: %.2f max: %.2f\n", m_triangles[i].min, m_triangles[i].max); + GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel); GetLogger()->Trace(" state: %ld\n", m_triangles[i].state); } @@ -685,8 +682,7 @@ bool CModelFile::WriteModel(std::ostream& stream) t.material = m_triangles[i].material; strncpy(t.texName, m_triangles[i].tex1Name.c_str(), 20); - t.min = m_triangles[i].min; - t.max = m_triangles[i].max; + LODLevelToMinMax(m_triangles[i].lodLevel, t.min, t.max); t.state = m_triangles[i].state; int no = 0; @@ -722,6 +718,46 @@ bool CModelFile::WriteModel(std::ostream& stream) return true; } +LODLevel CModelFile::MinMaxToLodLevel(float min, float max) +{ + if (min == 0.0f && max == 100.0f) + return LOD_High; + else if (min == 100.0f && max == 200.0f) + return LOD_Medium; + else if (min == 200.0f && max == 1000000.0f) + return LOD_Low; + else if (min == 0.0f && max == 1000000.0f) + return LOD_Constant; + + return LOD_Constant; +} + +void CModelFile::LODLevelToMinMax(LODLevel lodLevel, float& min, float& max) +{ + switch (lodLevel) + { + case LOD_High: + min = 0.0f; + max = 100.0f; + break; + + case LOD_Medium: + min = 100.0f; + max = 200.0f; + break; + + case LOD_Low: + min = 200.0f; + max = 1000000.0f; + break; + + case LOD_Constant: + min = 0.0f; + max = 1000000.0f; + break; + } +} + /******************************************************* New formats @@ -768,17 +804,15 @@ struct NewModelTriangle1 std::string tex2Name; //! If true, 2nd texture will be taken from current engine setting bool variableTex2; - //! Min LOD threshold - float min; - //! Max LOD threshold - float max; + //! LOD level + int lodLevel; //! Rendering state to be set int state; NewModelTriangle1() { variableTex2 = true; - min = max = 0.0f; + lodLevel = 0; state = 0; } }; @@ -834,8 +868,7 @@ bool CModelFile::ReadTextModel(std::istream& stream) ReadLineValue(stream, "tex1", t.tex1Name) && ReadLineValue(stream, "tex2", t.tex2Name) && ReadLineValue(stream, "var_tex2", varTex2Ch) && - ReadLineValue(stream, "min", t.min) && - ReadLineValue(stream, "max", t.max) && + ReadLineValue(stream, "lod_level", t.lodLevel) && ReadLineValue(stream, "state", t.state); if (!triOk || stream.fail()) @@ -855,10 +888,17 @@ bool CModelFile::ReadTextModel(std::istream& stream) triangle.tex1Name = t.tex1Name; triangle.tex2Name = t.tex2Name; triangle.variableTex2 = t.variableTex2; - triangle.min = t.min; - triangle.max = t.max; triangle.state = t.state; + switch (t.lodLevel) + { + case 0: triangle.lodLevel = LOD_Constant; break; + case 1: triangle.lodLevel = LOD_Low; break; + case 2: triangle.lodLevel = LOD_Medium; break; + case 3: triangle.lodLevel = LOD_High; break; + default: break; + } + m_triangles.push_back(triangle); continue; @@ -886,7 +926,7 @@ bool CModelFile::ReadTextModel(std::istream& stream) GetLogger()->Trace(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str()); GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(), m_triangles[i].tex2Name.c_str()); - GetLogger()->Trace(" min: %.2f max: %.2f\n", m_triangles[i].min, m_triangles[i].max); + GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel); GetLogger()->Trace(" state: %ld\n", m_triangles[i].state); } @@ -938,10 +978,16 @@ bool CModelFile::WriteTextModel(std::ostream& stream) t.tex1Name = m_triangles[i].tex1Name; t.tex2Name = m_triangles[i].tex2Name; t.variableTex2 = m_triangles[i].variableTex2; - t.min = m_triangles[i].min; - t.max = m_triangles[i].max; t.state = m_triangles[i].state; + switch (m_triangles[i].lodLevel) + { + case LOD_Constant: t.lodLevel = 0; break; + case LOD_Low: t.lodLevel = 1; break; + case LOD_Medium: t.lodLevel = 2; break; + case LOD_High: t.lodLevel = 3; break; + } + stream << "p1 "; WriteTextVertexTex2(t.p1, stream); stream << "p2 "; @@ -954,8 +1000,7 @@ bool CModelFile::WriteTextModel(std::ostream& stream) stream << "tex1 " << t.tex1Name << std::endl; stream << "tex2 " << t.tex2Name << std::endl; stream << "var_tex2 " << (t.variableTex2 ? 'Y' : 'N') << std::endl; - stream << "min " << t.min << std::endl; - stream << "max " << t.max << std::endl; + stream << "lod_level " << t.lodLevel << std::endl; stream << "state " << t.state << std::endl; stream << std::endl; @@ -1012,9 +1057,8 @@ bool CModelFile::ReadBinaryModel(std::istream& stream) t.tex1Name = IOUtils::ReadBinaryString<1>(stream); t.tex2Name = IOUtils::ReadBinaryString<1>(stream); t.variableTex2 = IOUtils::ReadBinaryBool(stream); - t.min = IOUtils::ReadBinaryFloat(stream); - t.max = IOUtils::ReadBinaryFloat(stream); - t.state = IOUtils::ReadBinary<4, unsigned int>(stream); + t.lodLevel = IOUtils::ReadBinary<4, int>(stream); + t.state = IOUtils::ReadBinary<4, int>(stream); if (stream.fail()) { @@ -1030,10 +1074,17 @@ bool CModelFile::ReadBinaryModel(std::istream& stream) triangle.tex1Name = t.tex1Name; triangle.tex2Name = t.tex2Name; triangle.variableTex2 = t.variableTex2; - triangle.min = t.min; - triangle.max = t.max; triangle.state = t.state; + switch (t.lodLevel) + { + case 0: triangle.lodLevel = LOD_Constant; break; + case 1: triangle.lodLevel = LOD_Low; break; + case 2: triangle.lodLevel = LOD_Medium; break; + case 3: triangle.lodLevel = LOD_High; break; + default: break; + } + m_triangles.push_back(triangle); } } @@ -1059,7 +1110,7 @@ bool CModelFile::ReadBinaryModel(std::istream& stream) GetLogger()->Trace(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str()); GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(), m_triangles[i].tex2Name.c_str()); - GetLogger()->Trace(" min: %.2f max: %.2f\n", m_triangles[i].min, m_triangles[i].max); + GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel); GetLogger()->Trace(" state: %ld\n", m_triangles[i].state); } @@ -1106,10 +1157,16 @@ bool CModelFile::WriteBinaryModel(std::ostream& stream) t.tex1Name = m_triangles[i].tex1Name; t.tex2Name = m_triangles[i].tex2Name; t.variableTex2 = m_triangles[i].variableTex2; - t.min = m_triangles[i].min; - t.max = m_triangles[i].max; t.state = m_triangles[i].state; + switch (m_triangles[i].lodLevel) + { + case LOD_Constant: t.lodLevel = 0; break; + case LOD_Low: t.lodLevel = 1; break; + case LOD_Medium: t.lodLevel = 2; break; + case LOD_High: t.lodLevel = 3; break; + } + WriteBinaryVertexTex2(t.p1, stream); WriteBinaryVertexTex2(t.p2, stream); WriteBinaryVertexTex2(t.p3, stream); @@ -1117,9 +1174,8 @@ bool CModelFile::WriteBinaryModel(std::ostream& stream) IOUtils::WriteBinaryString<1>(t.tex1Name, stream); IOUtils::WriteBinaryString<1>(t.tex2Name, stream); IOUtils::WriteBinaryBool(t.variableTex2, stream); - IOUtils::WriteBinaryFloat(t.min, stream); - IOUtils::WriteBinaryFloat(t.max, stream); - IOUtils::WriteBinary<4, unsigned int>(t.state, stream); + IOUtils::WriteBinary<4, int>(t.lodLevel, stream); + IOUtils::WriteBinary<4, int>(t.state, stream); if (stream.fail()) { @@ -1132,10 +1188,6 @@ bool CModelFile::WriteBinaryModel(std::ostream& stream) } -/******************************************************* - Other stuff - *******************************************************/ - const std::vector& CModelFile::GetTriangles() { return m_triangles; @@ -1146,23 +1198,5 @@ int CModelFile::GetTriangleCount() return m_triangles.size(); } -void CModelFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max) -{ - ModelTriangle triangle; - - Math::Vector n = Math::NormalToPlane(p3, p2, p1); - triangle.p1 = VertexTex2(p1, n); - triangle.p2 = VertexTex2(p2, n); - triangle.p3 = VertexTex2(p3, n); - - triangle.material.diffuse = Color(1.0f, 1.0f, 1.0f, 0.0f); - triangle.material.ambient = Color(0.5f, 0.5f, 0.5f, 0.0f); - - triangle.min = min; - triangle.max = max; - - m_triangles.push_back(triangle); -} - } // namespace Gfx diff --git a/src/graphics/engine/modelfile.h b/src/graphics/engine/modelfile.h index b2b5d87..3a702cb 100644 --- a/src/graphics/engine/modelfile.h +++ b/src/graphics/engine/modelfile.h @@ -39,9 +39,23 @@ namespace Gfx { /** - \struct ModelTriangle - \brief Triangle of a 3D model - */ + * \enum LODLevel + * \brief Level-of-detail + * + * A quantified replacement for older values of min/max. + */ +enum LODLevel +{ + LOD_Constant = -1, //!< triangle is always visible, no matter at what distance + LOD_Low = 1, //!< triangle is visible at farthest distance (lowest quality) + LOD_Medium = 2, //!< triangle is visible at medium distance (medium quality) + LOD_High = 4 //!< triangle is visible at closest distance (highest quality) +}; + +/** + * \struct ModelTriangle + * \brief Triangle of a 3D model + */ struct ModelTriangle { //! 1st vertex @@ -58,17 +72,15 @@ struct ModelTriangle std::string tex2Name; //! If true, 2nd texture will be taken from current engine setting bool variableTex2; - //! Min LOD threshold - float min; - //! Max LOD threshold - float max; + //! LOD level + LODLevel lodLevel; //! Rendering state to be set int state; ModelTriangle() { variableTex2 = true; - min = max = 0.0f; + lodLevel = LOD_Constant; state = 0; } }; @@ -126,8 +138,11 @@ public: const std::vector& GetTriangles(); protected: - //! Adds a triangle to the list - void CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max); + //@{ + //! @deprecated min, max conversions + LODLevel MinMaxToLodLevel(float min, float max); + void LODLevelToMinMax(LODLevel lodLevel, float& min, float& max); + //@} protected: //! Model triangles diff --git a/src/graphics/engine/modelmanager.cpp b/src/graphics/engine/modelmanager.cpp index 5b17769..051922f 100644 --- a/src/graphics/engine/modelmanager.cpp +++ b/src/graphics/engine/modelmanager.cpp @@ -47,30 +47,8 @@ bool CModelManager::LoadModel(const std::string& fileName, bool mirrored) std::vector vs(3, VertexTex2()); - float limit[2]; - limit[0] = m_engine->GetLimitLOD(0); // frontier AB as config - limit[1] = m_engine->GetLimitLOD(1); // frontier BC as config - for (int i = 0; i < static_cast( modelInfo.triangles.size() ); i++) { - float min = modelInfo.triangles[i].min; - float max = modelInfo.triangles[i].max; - - // Standard frontiers -> config - if (min == 0.0f && max == 100.0f) // resolution A ? - { - max = limit[0]; - } - else if (min == 100.0f && max == 200.0f) // resolution B ? - { - min = limit[0]; - max = limit[1]; - } - else if (min == 200.0f && max == 1000000.0f) // resolution C ? - { - min = limit[1]; - } - int state = modelInfo.triangles[i].state; std::string tex2Name = modelInfo.triangles[i].tex2Name; @@ -96,7 +74,7 @@ bool CModelManager::LoadModel(const std::string& fileName, bool mirrored) m_engine->AddBaseObjTriangles(modelInfo.baseObjRank, vs, ENG_TRIANGLE_TYPE_TRIANGLES, modelInfo.triangles[i].material, state, modelInfo.triangles[i].tex1Name, tex2Name, - min, max, false); + modelInfo.triangles[i].lodLevel, false); } return true; diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp index 978471b..e374d6c 100644 --- a/src/graphics/engine/pyro.cpp +++ b/src/graphics/engine/pyro.cpp @@ -1397,27 +1397,39 @@ void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part) int objRank = obj->GetObjectRank(part); if (objRank == -1) return; - float min = 0.0f; - float max = m_engine->GetLimitLOD(0); + int total = m_engine->GetObjectTotalTriangles(objRank); + float percent = 0.10f; if (total < 50) percent = 0.25f; if (total < 20) percent = 0.50f; if (m_type == PT_EGG) percent = 0.30f; - if ( oType == OBJECT_POWER || - oType == OBJECT_ATOMIC || - oType == OBJECT_URANIUM || - oType == OBJECT_TNT || - oType == OBJECT_BOMB ) percent = 0.75f; - if ( oType == OBJECT_MOBILEtg ) percent = 0.50f; - if ( oType == OBJECT_TEEN28 ) percent = 0.75f; - if ( oType == OBJECT_MOTHER ) max = 1000000.0f; - if ( oType == OBJECT_TEEN28 ) max = 1000000.0f; - if ( oType == OBJECT_TEEN31 ) max = 1000000.0f; + if (oType == OBJECT_POWER || + oType == OBJECT_ATOMIC || + oType == OBJECT_URANIUM || + oType == OBJECT_TNT || + oType == OBJECT_BOMB || + oType == OBJECT_TEEN28) + { + percent = 0.75f; + } + else if (oType == OBJECT_MOBILEtg) + { + percent = 0.50f; + } + + LODLevel lodLevel = LOD_High; + + if (oType == OBJECT_MOTHER || + oType == OBJECT_TEEN28 || + oType == OBJECT_TEEN31) + { + lodLevel = LOD_Constant; + } std::vector buffer; - total = m_engine->GetPartialTriangles(objRank, min, max, percent, 100, buffer); + total = m_engine->GetPartialTriangles(objRank, lodLevel, percent, 100, buffer); for (int i = 0; i < total; i++) { diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index a66b4b0..0be75bc 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -487,8 +487,7 @@ 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) { int baseObjRank = m_engine->GetObjectBaseRank(objRank); if (baseObjRank == -1) @@ -640,7 +639,7 @@ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, buffer.vertices.push_back(p2); } - m_engine->AddBaseObjQuick(baseObjRank, buffer, texName1, texName2, min, max, true); + m_engine->AddBaseObjQuick(baseObjRank, buffer, texName1, texName2, LOD_Constant, true); } } } @@ -1170,15 +1169,9 @@ bool CTerrain::CreateSquare(int x, int y) m_objRanks[x+y*m_mosaicCount] = objRank; - float min = 0.0f; - float max = m_vision; - max *= m_engine->GetClippingDistance(); for (int step = 0; step < m_depth; step++) { - CreateMosaic(x, y, 1 << step, objRank, mat, min, max); - min = max; - max *= 2; - if (step == m_depth-1) max = Math::HUGE_NUM; + CreateMosaic(x, y, 1 << step, objRank, mat); } return true; diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index e17144e..91ddc76 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -330,7 +330,7 @@ protected: //! Calculates a vertex of the terrain VertexTex2 GetVertex(int x, int y, int step); //! Creates all objects of a mosaic - bool CreateMosaic(int ox, int oy, int step, int objRank, const Material& mat, float min, float max); + bool CreateMosaic(int ox, int oy, int step, int objRank, const Material& mat); //! Creates all objects in a mesh square ground bool CreateSquare(int x, int y); diff --git a/src/graphics/engine/test/modelfile_test.cpp b/src/graphics/engine/test/modelfile_test.cpp index 43cd43b..e7078a9 100644 --- a/src/graphics/engine/test/modelfile_test.cpp +++ b/src/graphics/engine/test/modelfile_test.cpp @@ -40,8 +40,7 @@ const char* const TEXT_MODEL = "tex1 lemt.png\n" "tex2\n" "var_tex2 N\n" -"min 200\n" -"max 1e+06\n" +"lod_level 0\n" "state 1024\n" "\n" "p1 c -19 -1 4 n -1 0 0 t1 0.248047 0.123047 t2 0.905224 0.52067\n" @@ -51,8 +50,7 @@ const char* const TEXT_MODEL = "tex1 derrick.png\n" "tex2\n" "var_tex2 Y\n" -"min 200\n" -"max 1e+06\n" +"lod_level 1\n" "state 0\n" ""; @@ -81,8 +79,7 @@ void Init() TRIANGLE_1.material.specular = Gfx::Color(0, 0, 0, 0); TRIANGLE_1.tex1Name = "lemt.png"; TRIANGLE_1.variableTex2 = false; - TRIANGLE_1.min = 200.0f; - TRIANGLE_1.max = 1e+06f; + TRIANGLE_1.lodLevel = Gfx::LOD_Constant; TRIANGLE_1.state = 1024; TRIANGLE_2.p1 = Gfx::VertexTex2(Math::Vector(-19, -1, 4), @@ -102,8 +99,7 @@ void Init() TRIANGLE_2.material.specular = Gfx::Color(0, 0, 0, 0); TRIANGLE_2.tex1Name = "derrick.png"; TRIANGLE_2.variableTex2 = true; - TRIANGLE_2.min = 200.0f; - TRIANGLE_2.max = 1e+06f; + TRIANGLE_2.lodLevel = Gfx::LOD_Low; TRIANGLE_2.state = 0; } @@ -171,10 +167,7 @@ bool CompareTriangles(const Gfx::ModelTriangle& t1, const Gfx::ModelTriangle& t2 if (t1.variableTex2 != t2.variableTex2) return false; - if (!Math::IsEqual(t1.min, t2.min)) - return false; - - if (!Math::IsEqual(t1.max, t2.max)) + if (t1.lodLevel != t2.lodLevel) return false; if (t1.state != t2.state) -- cgit v1.2.3-1-g7c22