summaryrefslogtreecommitdiffstats
path: root/src/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/core/color.h10
-rw-r--r--src/graphics/core/device.h60
-rw-r--r--src/graphics/core/vertex.h20
-rw-r--r--src/graphics/engine/camera.cpp31
-rw-r--r--src/graphics/engine/camera.h6
-rw-r--r--src/graphics/engine/cloud.cpp19
-rw-r--r--src/graphics/engine/cloud.h11
-rw-r--r--src/graphics/engine/engine.cpp2515
-rw-r--r--src/graphics/engine/engine.h425
-rw-r--r--src/graphics/engine/lightman.cpp109
-rw-r--r--src/graphics/engine/lightman.h24
-rw-r--r--src/graphics/engine/lightning.cpp22
-rw-r--r--src/graphics/engine/lightning.h4
-rw-r--r--src/graphics/engine/modelfile.cpp284
-rw-r--r--src/graphics/engine/modelfile.h60
-rw-r--r--src/graphics/engine/modelmanager.cpp191
-rw-r--r--src/graphics/engine/modelmanager.h97
-rw-r--r--src/graphics/engine/particle.cpp31
-rw-r--r--src/graphics/engine/particle.h4
-rw-r--r--src/graphics/engine/planet.cpp8
-rw-r--r--src/graphics/engine/planet.h5
-rw-r--r--src/graphics/engine/pyro.cpp81
-rw-r--r--src/graphics/engine/pyro.h4
-rw-r--r--src/graphics/engine/terrain.cpp53
-rw-r--r--src/graphics/engine/terrain.h10
-rw-r--r--src/graphics/engine/test/CMakeLists.txt1
-rw-r--r--src/graphics/engine/test/modelfile_test.cpp29
-rw-r--r--src/graphics/engine/text.cpp81
-rw-r--r--src/graphics/engine/text.h24
-rw-r--r--src/graphics/engine/water.cpp34
-rw-r--r--src/graphics/engine/water.h8
-rw-r--r--src/graphics/opengl/gldevice.cpp558
-rw-r--r--src/graphics/opengl/gldevice.h57
-rw-r--r--src/graphics/opengl/test/CMakeLists.txt90
-rw-r--r--src/graphics/opengl/test/README.txt9
-rw-r--r--src/graphics/opengl/test/light_test.cpp437
-rw-r--r--src/graphics/opengl/test/model_test.cpp377
-rw-r--r--src/graphics/opengl/test/tex1.pngbin151263 -> 0 bytes
-rw-r--r--src/graphics/opengl/test/tex2.pngbin57503 -> 0 bytes
-rw-r--r--src/graphics/opengl/test/texture_test.cpp193
-rw-r--r--src/graphics/opengl/test/transform_test.cpp339
41 files changed, 2941 insertions, 3380 deletions
diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h
index 7cbd175..5d059e5 100644
--- a/src/graphics/core/color.h
+++ b/src/graphics/core/color.h
@@ -76,6 +76,16 @@ struct Color
{
return ! this->operator==(other);
}
+
+ inline Color operator*(float scale) const
+ {
+ Color c = *this;
+ c.r *= scale;
+ c.g *= scale;
+ c.b *= scale;
+ c.a *= scale;
+ return c;
+ }
};
/**
diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
index b6dd138..41d7796 100644
--- a/src/graphics/core/device.h
+++ b/src/graphics/core/device.h
@@ -104,8 +104,7 @@ enum RenderState
RENDER_STATE_DEPTH_TEST,
RENDER_STATE_DEPTH_WRITE,
RENDER_STATE_ALPHA_TEST,
- RENDER_STATE_CULLING,
- RENDER_STATE_DITHERING
+ RENDER_STATE_CULLING
};
/**
@@ -204,22 +203,22 @@ enum PrimitiveType
};
/**
- * \enum IntersectPlane
- * \brief Intersection plane of projection volume
+ * \enum FrustumPlane
+ * \brief Planes of frustum space
*
- * These flags can be OR'd together.
+ * Bitset of flags - can be OR'd together.
*/
-enum IntersectPlane
+enum FrustumPlane
{
- INTERSECT_PLANE_LEFT = 0x01,
- INTERSECT_PLANE_RIGHT = 0x02,
- INTERSECT_PLANE_TOP = 0x04,
- INTERSECT_PLANE_BOTTOM = 0x08,
- INTERSECT_PLANE_FRONT = 0x10,
- INTERSECT_PLANE_BACK = 0x20,
- INTERSECT_PLANE_ALL = INTERSECT_PLANE_LEFT | INTERSECT_PLANE_RIGHT |
- INTERSECT_PLANE_TOP | INTERSECT_PLANE_BOTTOM |
- INTERSECT_PLANE_FRONT | INTERSECT_PLANE_BACK
+ FRUSTUM_PLANE_LEFT = 0x01,
+ FRUSTUM_PLANE_RIGHT = 0x02,
+ FRUSTUM_PLANE_TOP = 0x04,
+ FRUSTUM_PLANE_BOTTOM = 0x08,
+ FRUSTUM_PLANE_FRONT = 0x10,
+ FRUSTUM_PLANE_BACK = 0x20,
+ FRUSTUM_PLANE_ALL = FRUSTUM_PLANE_LEFT | FRUSTUM_PLANE_RIGHT |
+ FRUSTUM_PLANE_TOP | FRUSTUM_PLANE_BOTTOM |
+ FRUSTUM_PLANE_FRONT | FRUSTUM_PLANE_BACK
};
/**
@@ -287,7 +286,7 @@ public:
virtual void DestroyAllTextures() = 0;
//! Returns the maximum number of multitexture stages
- virtual int GetMaxTextureCount() = 0;
+ virtual int GetMaxTextureStageCount() = 0;
//! Sets the texture at given texture stage
virtual void SetTexture(int index, const Texture &texture) = 0;
//! Sets the texture image by ID at given texture stage
@@ -313,10 +312,35 @@ public:
//! Renders primitive composed of vertices with multitexturing (2 textures)
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) = 0;
- //! Renders primitive composed of vertices with color information
+ //! Renders primitive composed of vertices with solid color
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount) = 0;
- //! Tests whether a sphere intersects the 6 clipping planes of projection volume
+ //! Creates a static buffer composed of given primitives with single texture vertices
+ virtual unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) = 0;
+
+ //! Creates a static buffer composed of given primitives with multitexturing
+ virtual unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) = 0;
+
+ //! Creates a static buffer composed of given primitives with solid color
+ virtual unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) = 0;
+
+ //! Updates the static buffer composed of given primitives with single texture vertices
+ virtual void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) = 0;
+
+ //! Updates the static buffer composed of given primitives with multitexturing
+ virtual void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) = 0;
+
+ //! Updates the static buffer composed of given primitives with solid color
+ virtual void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) = 0;
+
+ //! Draws a static buffer
+ virtual void DrawStaticBuffer(unsigned int bufferId) = 0;
+
+ //! Deletes a static buffer
+ virtual void DestroyStaticBuffer(unsigned int bufferId) = 0;
+
+ //! Tests whether a sphere is (partially) within the frustum volume
+ //! Returns a mask of frustum planes for which the test is positive
virtual int ComputeSphereVisibility(const Math::Vector &center, float radius) = 0;
//! Enables/disables the given render state
diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h
index 2ee6be4..66e1503 100644
--- a/src/graphics/core/vertex.h
+++ b/src/graphics/core/vertex.h
@@ -44,23 +44,18 @@ namespace Gfx {
* - vertex coordinates (x,y,z) as Math::Vector,
* - normal coordinates (nx,ny,nz) as Math::Vector
* - texture coordinates (u,v) as Math::Point.
- *
- * Additional padding is provided to align to even multiplies of 4 floats for faster access.
*/
struct Vertex
{
Math::Vector coord;
- float pad1;
Math::Vector normal;
- float pad2;
Math::Point texCoord;
- float pad3, pad4;
explicit Vertex(Math::Vector aCoord = Math::Vector(),
Math::Vector aNormal = Math::Vector(),
Math::Point aTexCoord = Math::Point())
- : coord(aCoord), pad1(0.0f), normal(aNormal),
- pad2(0.0f),texCoord(aTexCoord), pad3(0.0f), pad4(0.0f) {}
+ : coord(aCoord), normal(aNormal),
+ texCoord(aTexCoord) {}
//! Returns a string "(c: [...], n: [...], tc: [...])"
@@ -81,18 +76,15 @@ struct Vertex
* It contains:
* - vertex coordinates (x,y,z) as Math::Vector,
* - RGBA color as Color
- *
- * Additional padding is provided to align to even multiplies of 4 floats for faster access.
*/
struct VertexCol
{
Math::Vector coord;
- float pad;
Color color;
explicit VertexCol(Math::Vector aCoord = Math::Vector(),
Color aColor = Color())
- : coord(aCoord), pad(0.0f), color(aColor) {}
+ : coord(aCoord), color(aColor) {}
//! Returns a string "(c: [...], col: [...])"
inline std::string ToString() const
@@ -111,15 +103,11 @@ struct VertexCol
*
* In addition to fields from Vector, it contains
* secondary texture coordinates (u2, v2) as Math::Point
- *
- * Additional padding is provided to align to even multiplies of 4 floats for faster access.
*/
struct VertexTex2
{
Math::Vector coord;
- float pad1;
Math::Vector normal;
- float pad2;
Math::Point texCoord;
Math::Point texCoord2;
@@ -127,7 +115,7 @@ struct VertexTex2
Math::Vector aNormal = Math::Vector(),
Math::Point aTexCoord = Math::Point(),
Math::Point aTexCoord2 = Math::Point())
- : coord(aCoord), pad1(0.0f), normal(aNormal), pad2(0.0f),
+ : coord(aCoord), normal(aNormal),
texCoord(aTexCoord), texCoord2(aTexCoord2) {}
//! Sets the fields from Vertex with texCoord2 = (0,0)
diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp
index d85194e..f65a59a 100644
--- a/src/graphics/engine/camera.cpp
+++ b/src/graphics/engine/camera.cpp
@@ -30,6 +30,7 @@
#include "math/geometry.h"
#include "object/object.h"
+#include "object/robotmain.h"
#include "physics/physics.h"
@@ -54,14 +55,13 @@ void SetTransparency(CObject* obj, float value)
-CCamera::CCamera(CInstanceManager* iMan)
+CCamera::CCamera()
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_CAMERA, this);
+ m_engine = CEngine::GetInstancePointer();
+ m_water = m_engine->GetWater();
- m_engine = static_cast<CEngine*> ( m_iMan->SearchInstance(CLASS_ENGINE) );
- m_terrain = static_cast<CTerrain*>( m_iMan->SearchInstance(CLASS_TERRAIN) );
- m_water = static_cast<CWater*> ( m_iMan->SearchInstance(CLASS_WATER) );
+ m_main = CRobotMain::GetInstancePointer();
+ m_terrain = m_main->GetTerrain();
m_type = CAM_TYPE_FREE;
m_smooth = CAM_SMOOTH_NORM;
@@ -227,11 +227,13 @@ void CCamera::SetType(CameraType type)
m_remotePan = 0.0f;
m_remoteZoom = 0.0f;
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
if ( (m_type == CAM_TYPE_BACK) && m_transparency )
{
for (int i = 0; i < 1000000; i++)
{
- CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ CObject* obj = static_cast<CObject*>( iMan->SearchInstance(CLASS_OBJECT, i) );
if (obj == NULL)
break;
@@ -315,6 +317,7 @@ void CCamera::SetType(CameraType type)
if ( oType == OBJECT_PARA ) m_backDist = 180.0f;
if ( oType == OBJECT_SAFE ) m_backDist = 50.0f;
if ( oType == OBJECT_HUSTON ) m_backDist = 120.0f;
+ if ( oType == OBJECT_MOTHER ) m_backDist = 55.0f;
m_backMin = m_backDist/3.0f;
if ( oType == OBJECT_HUMAN ) m_backMin = 10.0f;
@@ -327,8 +330,8 @@ void CCamera::SetType(CameraType type)
if ( oType == OBJECT_HUSTON ) m_backMin = 80.0f;
}
- if ( type != CAM_TYPE_ONBOARD && m_cameraObj != 0 )
- m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
+ //if ( type != CAM_TYPE_ONBOARD && m_cameraObj != 0 )
+ // m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
if ( type == CAM_TYPE_ONBOARD )
m_focus = 1.50f; // Wide
@@ -880,9 +883,11 @@ bool CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
m_transparency = false;
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
for (int i = 0 ;i < 1000000; i++)
{
- CObject *obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ CObject *obj = static_cast<CObject*>( iMan->SearchInstance(CLASS_OBJECT, i) );
if (obj == NULL) break;
if (obj->GetTruck()) continue; // battery or cargo?
@@ -957,9 +962,11 @@ bool CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
bool CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
{
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
for (int i = 0; i < 1000000; i++)
{
- CObject *obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ CObject *obj = static_cast<CObject*>( iMan->SearchInstance(CLASS_OBJECT, i) );
if (obj == NULL) break;
if (obj == m_cameraObj) continue;
@@ -1649,7 +1656,7 @@ Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
/*
for (int i = 0; i < 1000000; i++)
{
- CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ CObject* obj = static_cast<CObject*>( iMan->SearchInstance(CLASS_OBJECT, i) );
if (obj == NULL)
break;
diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h
index 20d252d..0ffc2c2 100644
--- a/src/graphics/engine/camera.h
+++ b/src/graphics/engine/camera.h
@@ -28,8 +28,8 @@
#include "graphics/engine/engine.h"
-class CInstanceManager;
class CObject;
+class CRobotMain;
// Graphics module namespace
@@ -130,7 +130,7 @@ enum CameraOverEffect
class CCamera {
public:
- CCamera(CInstanceManager* iMan);
+ CCamera();
~CCamera();
//! Management of an event
@@ -258,8 +258,8 @@ protected:
void OverFrame(const Event &event);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
+ CRobotMain* m_main;
CTerrain* m_terrain;
CWater* m_water;
diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp
index 0df0d12..d9ebf5a 100644
--- a/src/graphics/engine/cloud.cpp
+++ b/src/graphics/engine/cloud.cpp
@@ -18,12 +18,12 @@
#include "graphics/engine/cloud.h"
-#include "common/iman.h"
-
#include "graphics/core/device.h"
#include "graphics/engine/engine.h"
#include "graphics/engine/terrain.h"
+#include "object/robotmain.h"
+
#include "math/geometry.h"
@@ -37,11 +37,8 @@ const int CLOUD_LINE_PREALLOCATE_COUNT = 100;
const int CLOUD_SIZE_EXPAND = 4;
-CCloud::CCloud(CInstanceManager* iMan, CEngine* engine)
+CCloud::CCloud(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_CLOUD, this);
-
m_engine = engine;
m_terrain = nullptr;
@@ -55,7 +52,6 @@ CCloud::CCloud(CInstanceManager* iMan, CEngine* engine)
CCloud::~CCloud()
{
- m_iMan = nullptr;
m_engine = nullptr;
m_terrain = nullptr;
}
@@ -84,7 +80,7 @@ bool CCloud::EventFrame(const Event &event)
}
void CCloud::AdjustLevel(Math::Vector& pos, Math::Vector& eye, float deep,
- Math::Point& uv1, Math::Point& uv2)
+ Math::Point& uv1, Math::Point& uv2)
{
uv1.x = (pos.x+20000.0f)/1280.0f;
uv1.y = (pos.z+20000.0f)/1280.0f;
@@ -211,8 +207,8 @@ void CCloud::CreateLine(int x, int y, int len)
}
void CCloud::Create(const std::string& fileName,
- const Color& diffuse, const Color& ambient,
- float level)
+ const Color& diffuse, const Color& ambient,
+ float level)
{
m_diffuse = diffuse;
m_ambient = ambient;
@@ -225,7 +221,7 @@ void CCloud::Create(const std::string& fileName,
m_engine->LoadTexture(m_fileName);
if (m_terrain == nullptr)
- m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+ m_terrain = CRobotMain::GetInstancePointer()->GetTerrain();
m_wind = m_terrain->GetWind();
@@ -250,7 +246,6 @@ void CCloud::Flush()
m_level = 0.0f;
}
-
void CCloud::SetLevel(float level)
{
m_level = level;
diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h
index 6f6985f..8f644f0 100644
--- a/src/graphics/engine/cloud.h
+++ b/src/graphics/engine/cloud.h
@@ -34,9 +34,6 @@
#include <string>
-class CInstanceManager;
-
-
// Graphics module namespace
namespace Gfx {
@@ -79,12 +76,13 @@ struct CloudLine
class CCloud
{
public:
- CCloud(CInstanceManager* iMan, CEngine* engine);
+ CCloud(CEngine* engine);
~CCloud();
bool EventProcess(const Event& event);
//! Removes all the clouds
void Flush();
+
//! Creates all areas of cloud
void Create(const std::string& fileName, const Color& diffuse, const Color& ambient, float level);
//! Draw the clouds
@@ -112,9 +110,8 @@ protected:
void CreateLine(int x, int y, int len);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CTerrain* m_terrain;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
bool m_enabled;
//! Overall level
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index 3365b24..e2ef569 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -20,7 +20,6 @@
#include "app/app.h"
-#include "common/iman.h"
#include "common/image.h"
#include "common/key.h"
#include "common/logger.h"
@@ -43,69 +42,16 @@
#include "ui/interface.h"
+template<> Gfx::CEngine* CSingleton<Gfx::CEngine>::m_instance = nullptr;
// Graphics module namespace
namespace Gfx {
-
-// Initial size of various vectors
-const int OBJECT_PREALLOCATE_COUNT = 1200;
-const int SHADOW_PREALLOCATE_COUNT = 500;
-const int GROUNDSPOT_PREALLOCATE_COUNT = 100;
-
-const int LEVEL1_PREALLOCATE_COUNT = 50;
-const int LEVEL2_PREALLOCATE_COUNT = 100;
-const int LEVEL3_PREALLOCATE_COUNT = 5;
-const int LEVEL4_PREALLOCATE_COUNT = 100;
-const int LEVEL4_VERTEX_PREALLOCATE_COUNT = 200;
-
-
-EngineObjLevel1::EngineObjLevel1(bool used, const std::string& tex1Name, const std::string& tex2Name)
-{
- this->used = used;
- this->tex1Name = tex1Name;
- this->tex2Name = tex2Name;
-
- next.reserve(LEVEL2_PREALLOCATE_COUNT);
-}
-
-EngineObjLevel2::EngineObjLevel2(bool used, int objRank)
-{
- this->used = used;
- this->objRank = objRank;
-
- next.reserve(LEVEL3_PREALLOCATE_COUNT);
-}
-
-EngineObjLevel3::EngineObjLevel3(bool used, float min, float max)
-{
- this->used = used;
- this->min = min;
- this->max = max;
-
- next.reserve(LEVEL4_PREALLOCATE_COUNT);
-}
-
-EngineObjLevel4::EngineObjLevel4(bool used, EngineTriangleType type, const Material& material, int state)
-{
- this->used = used;
- this->type = type;
- this->material = material;
- this->state = state;
-
- vertices.reserve(LEVEL4_VERTEX_PREALLOCATE_COUNT);
-}
-
-CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
+CEngine::CEngine(CApplication *app)
{
- m_iMan = iMan;
m_app = app;
m_device = nullptr;
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_ENGINE, this);
- m_app = app;
-
m_lightMan = nullptr;
m_text = nullptr;
m_particle = nullptr;
@@ -158,13 +104,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;
@@ -179,9 +121,9 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
m_editIndentValue = 4;
m_tracePrecision = 1.0f;
- m_alphaMode = 1;
m_updateGeometry = false;
+ m_updateStaticBuffers = false;
m_interfaceMode = false;
@@ -206,8 +148,8 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
m_mouseType = ENG_MOUSE_NORM;
m_fpsCounter = 0;
- m_lastFrameTime = CreateTimeStamp();
- m_currentFrameTime = CreateTimeStamp();
+ m_lastFrameTime = GetSystemUtils()->CreateTimeStamp();
+ m_currentFrameTime = GetSystemUtils()->CreateTimeStamp();
m_defaultTexParams.format = TEX_IMG_AUTO;
m_defaultTexParams.mipmap = true;
@@ -218,24 +160,25 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
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);
- m_groundSpots.reserve(GROUNDSPOT_PREALLOCATE_COUNT);
}
CEngine::~CEngine()
{
- m_iMan = nullptr;
- m_app = nullptr;
- m_device = nullptr;
- m_sound = nullptr;
- m_terrain = nullptr;
+ m_app = nullptr;
+ m_sound = nullptr;
+ m_device = nullptr;
+ m_text = nullptr;
+ m_lightMan = nullptr;
+ m_particle = nullptr;
+ m_water = nullptr;
+ m_cloud = nullptr;
+ m_lightning = nullptr;
+ m_planet = nullptr;
+ m_terrain = nullptr;
- DestroyTimeStamp(m_lastFrameTime);
+ GetSystemUtils()->DestroyTimeStamp(m_lastFrameTime);
m_lastFrameTime = nullptr;
- DestroyTimeStamp(m_currentFrameTime);
+ GetSystemUtils()->DestroyTimeStamp(m_currentFrameTime);
m_currentFrameTime = nullptr;
}
@@ -249,27 +192,63 @@ CDevice* CEngine::GetDevice()
return m_device;
}
-void CEngine::SetTerrain(CTerrain* terrain)
+CText* CEngine::GetText()
{
- m_terrain = terrain;
+ return m_text;
}
-CText* CEngine::GetText()
+CLightManager* CEngine::GetLightManager()
{
- return m_text;
+ return m_lightMan;
}
+CParticle* CEngine::GetParticle()
+{
+ return m_particle;
+}
+
+CTerrain* CEngine::GetTerrain()
+{
+ return m_terrain;
+}
+
+CWater* CEngine::GetWater()
+{
+ return m_water;
+}
+
+CLightning* CEngine::GetLightning()
+{
+ return m_lightning;
+}
+
+CPlanet* CEngine::GetPlanet()
+{
+ return m_planet;
+}
+
+CCloud* CEngine::GetCloud()
+{
+ return m_cloud;
+}
+
+void CEngine::SetTerrain(CTerrain* terrain)
+{
+ m_terrain = terrain;
+}
+
+
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);
- m_particle = new CParticle(m_iMan, this);
- m_water = new CWater(m_iMan, this);
- m_cloud = new CCloud(m_iMan, this);
- m_lightning = new CLightning(m_iMan, this);
- m_planet = new CPlanet(m_iMan, this);
+ m_lightMan = new CLightManager(this);
+ m_text = new CText(this);
+ m_particle = new CParticle(this);
+ m_water = new CWater(this);
+ m_cloud = new CCloud(this);
+ m_lightning = new CLightning(this);
+ m_planet = new CPlanet(this);
m_lightMan->SetDevice(m_device);
m_particle->SetDevice(m_device);
@@ -300,8 +279,8 @@ bool CEngine::Create()
params.mipmap = false;
m_miceTexture = LoadTexture("mouse.png", params);
- GetCurrentTimeStamp(m_currentFrameTime);
- GetCurrentTimeStamp(m_lastFrameTime);
+ GetSystemUtils()->GetCurrentTimeStamp(m_currentFrameTime);
+ GetSystemUtils()->GetCurrentTimeStamp(m_lastFrameTime);
return true;
}
@@ -334,6 +313,8 @@ void CEngine::Destroy()
void CEngine::ResetAfterDeviceChanged()
{
+ m_size = m_app->GetVideoConfig().size;;
+
m_text->FlushCache();
// TODO reload textures, reset device state, etc.
@@ -355,11 +336,11 @@ void CEngine::FrameUpdate()
{
m_fpsCounter++;
- GetCurrentTimeStamp(m_currentFrameTime);
- float diff = TimeStampDiff(m_lastFrameTime, m_currentFrameTime, STU_SEC);
+ GetSystemUtils()->GetCurrentTimeStamp(m_currentFrameTime);
+ float diff = GetSystemUtils()->TimeStampDiff(m_lastFrameTime, m_currentFrameTime, STU_SEC);
if (diff > 1.0f)
{
- CopyTimeStamp(m_lastFrameTime, m_currentFrameTime);
+ GetSystemUtils()->CopyTimeStamp(m_lastFrameTime, m_currentFrameTime);
m_fps = m_fpsCounter / diff;
m_fpsCounter = 0;
@@ -378,9 +359,14 @@ void CEngine::FrameUpdate()
float rTime = m_app->GetRelTime();
m_lightMan->UpdateProgression(rTime);
+
+ m_app->StartPerformanceCounter(PCNT_UPDATE_PARTICLE);
m_particle->FrameParticle(rTime);
+ m_app->StopPerformanceCounter(PCNT_UPDATE_PARTICLE);
+
ComputeDistance();
UpdateGeometry();
+ UpdateStaticBuffers();
m_highlightTime = m_app->GetAbsTime();
@@ -409,7 +395,7 @@ void CEngine::FrameUpdate()
{
m_groundMark.intensity = 0.0f;
m_groundMark.phase = ENG_GR_MARK_PHASE_NULL;
- m_groundMark.draw = false;
+ m_groundMark.draw = false;
}
}
}
@@ -422,18 +408,6 @@ bool CEngine::WriteScreenShot(const std::string& fileName, int width, int height
return true;
}
-bool CEngine::ReadSettings()
-{
- // TODO: when INI reading is completed
- return true;
-}
-
-bool CEngine::WriteSettings()
-{
- // TODO: when INI writing is completed
- return true;
-}
-
void CEngine::SetPause(bool pause)
{
m_pause = pause;
@@ -474,11 +448,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<float>(pos.x) / static_cast<float>(m_size.x),
@@ -500,7 +469,7 @@ Math::Point CEngine::WindowToInterfaceSize(Math::IntPoint size)
Math::IntPoint CEngine::InterfaceToWindowSize(Math::Point size)
{
return Math::IntPoint(static_cast<int>(size.x * m_size.x),
- static_cast<int>(size.y * m_size.y));
+ static_cast<int>(size.y * m_size.y));
}
void CEngine::AddStatisticTriangle(int count)
@@ -519,480 +488,373 @@ int CEngine::GetStatisticTriangle()
Object management
*******************************************************/
+EngineBaseObjTexTier& CEngine::AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name)
+{
+ for (int i = 0; i < static_cast<int>( p1.next.size() ); i++)
+ {
+ if (p1.next[i].tex1Name == tex1Name && p1.next[i].tex2Name == tex2Name)
+ return p1.next[i];
+ }
+
+ p1.next.push_back(EngineBaseObjTexTier(tex1Name, tex2Name));
+ return p1.next.back();
+}
+EngineBaseObjLODTier& CEngine::AddLevel3(EngineBaseObjTexTier& p2, LODLevel lodLevel)
+{
+ for (int i = 0; i < static_cast<int>( p2.next.size() ); i++)
+ {
+ if (p2.next[i].lodLevel == lodLevel)
+ return p2.next[i];
+ }
-int CEngine::CreateObject()
+ p2.next.push_back(EngineBaseObjLODTier(lodLevel));
+ return p2.next.back();
+}
+
+EngineBaseObjDataTier& CEngine::AddLevel4(EngineBaseObjLODTier& p3, EngineTriangleType type,
+ const Material& material, int state)
{
- int i = 0;
- for ( ; i < static_cast<int>( m_objects.size() ); i++)
+ for (int i = 0; i < static_cast<int>( p3.next.size() ); i++)
{
- if (! m_objects[i].used)
+ if ( (p3.next[i].type == type) && (p3.next[i].material == material) && (p3.next[i].state == state) )
+ return p3.next[i];
+ }
+
+ p3.next.push_back(EngineBaseObjDataTier(type, material, state));
+ return p3.next.back();
+}
+
+int CEngine::CreateBaseObject()
+{
+ int baseObjRank = 0;
+ for ( ; baseObjRank < static_cast<int>( m_baseObjects.size() ); baseObjRank++)
+ {
+ if (! m_baseObjects[baseObjRank].used)
{
- m_objects[i].LoadDefault();
+ m_baseObjects[baseObjRank].LoadDefault();
break;
}
}
- if (i == static_cast<int>( m_objects.size() ))
- m_objects.push_back(EngineObject());
+ if (baseObjRank == static_cast<int>( m_baseObjects.size() ))
+ m_baseObjects.push_back(EngineBaseObject());
+ else
+ m_baseObjects[baseObjRank].LoadDefault();
- m_objects[i].used = true;
+ m_baseObjects[baseObjRank].used = true;
- Math::Matrix mat;
- mat.LoadIdentity();
- SetObjectTransform(i, mat);
-
- m_objects[i].drawWorld = true;
- m_objects[i].distance = 0.0f;
- m_objects[i].bboxMin = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objects[i].bboxMax = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objects[i].shadowRank = -1;
-
- return i;
+ return baseObjRank;
}
-void CEngine::FlushObject()
+void CEngine::DeleteBaseObject(int baseObjRank)
{
- m_objectTree.clear();
- m_objects.clear();
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- m_shadows.clear();
-
- FlushGroundSpot();
-}
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
-bool CEngine::DeleteObject(int objRank)
-{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ if (! p1.used)
+ return;
- // Delete object's triangles
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ EngineBaseObjTexTier& p2 = p1.next[l2];
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
- if (p2.objRank == objRank)
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- p2.used = false;
- p2.next.clear();
+ EngineBaseObjDataTier& p4 = p3.next[l4];
+
+ m_device->DestroyStaticBuffer(p4.staticBufferId);
+ p4.staticBufferId = 0;
}
}
}
- // Mark object as deleted
- m_objects[objRank].used = false;
+ p1.next.clear();
- // Delete associated shadows
- DeleteShadow(objRank);
-
- return true;
+ p1.used = false;
}
-bool CEngine::SetObjectType(int objRank, EngineObjectType type)
+void CEngine::DeleteAllBaseObjects()
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
-
- m_objects[objRank].type = type;
- return true;
+ m_baseObjects.clear();
}
-EngineObjectType CEngine::GetObjectType(int objRank)
+void CEngine::CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return ENG_OBJTYPE_NULL;
+ assert(sourceBaseObjRank >= 0 && sourceBaseObjRank < static_cast<int>( m_baseObjects.size() ));
+ assert(destBaseObjRank >= 0 && destBaseObjRank < static_cast<int>( m_baseObjects.size() ));
- return m_objects[objRank].type;
+ m_baseObjects[destBaseObjRank] = m_baseObjects[sourceBaseObjRank];
}
-
-bool CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform)
+void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>& vertices,
+ EngineTriangleType triangleType,
+ const Material& material, int state,
+ std::string tex1Name, std::string tex2Name,
+ LODLevel lodLevel, bool globalUpdate)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
-
- m_objects[objRank].transform = transform;
- return true;
-}
-
-bool CEngine::GetObjectTransform(int objRank, Math::Matrix& transform)
-{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- transform = m_objects[objRank].transform;
- return true;
-}
-
-bool CEngine::SetObjectDrawWorld(int objRank, bool draw)
-{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name);
+ EngineBaseObjLODTier& p3 = AddLevel3(p2, lodLevel);
+ EngineBaseObjDataTier& p4 = AddLevel4(p3, triangleType, material, state);
- m_objects[objRank].drawWorld = draw;
- return true;
-}
+ p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
-bool CEngine::SetObjectDrawFront(int objRank, bool draw)
-{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ p4.updateStaticBuffer = true;
+ m_updateStaticBuffers = true;
- m_objects[objRank].drawFront = draw;
- return true;
-}
+ if (globalUpdate)
+ {
+ m_updateGeometry = true;
+ }
+ else
+ {
+ for (int i = 0; i < static_cast<int>( vertices.size() ); i++)
+ {
+ p1.bboxMin.x = Math::Min(vertices[i].coord.x, p1.bboxMin.x);
+ p1.bboxMin.y = Math::Min(vertices[i].coord.y, p1.bboxMin.y);
+ p1.bboxMin.z = Math::Min(vertices[i].coord.z, p1.bboxMin.z);
+ p1.bboxMax.x = Math::Max(vertices[i].coord.x, p1.bboxMax.x);
+ p1.bboxMax.y = Math::Max(vertices[i].coord.y, p1.bboxMax.y);
+ p1.bboxMax.z = Math::Max(vertices[i].coord.z, p1.bboxMax.z);
+ }
-bool CEngine::SetObjectTransparency(int objRank, float value)
-{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ p1.radius = Math::Max(p1.bboxMin.Length(), p1.bboxMax.Length());
+ }
- m_objects[objRank].transparency = value;
- return true;
+ if (triangleType == ENG_TRIANGLE_TYPE_TRIANGLES)
+ p1.totalTriangles += vertices.size() / 3;
+ else
+ p1.totalTriangles += vertices.size() - 2;
}
-bool CEngine::GetObjectBBox(int objRank, Math::Vector& min, Math::Vector& max)
+void CEngine::AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buffer,
+ std::string tex1Name, std::string tex2Name,
+ LODLevel lodLevel, bool globalUpdate)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return 0;
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- min = m_objects[objRank].bboxMin;
- max = m_objects[objRank].bboxMax;
- return true;
-}
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name);
+ EngineBaseObjLODTier& p3 = AddLevel3(p2, lodLevel);
+ p3.next.push_back(buffer);
-int CEngine::GetObjectTotalTriangles(int objRank)
-{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return 0;
-
- return m_objects[objRank].totalTriangles;
-}
+ EngineBaseObjDataTier& p4 = p3.next.back();
+ UpdateStaticBuffer(p4);
-EngineObjLevel1& CEngine::AddLevel1(const std::string& tex1Name, const std::string& tex2Name)
-{
- bool unusedPresent = false;
- for (int i = 0; i < static_cast<int>( m_objectTree.size() ); i++)
+ if (globalUpdate)
{
- if (! m_objectTree[i].used)
- {
- unusedPresent = true;
- continue;
- }
-
- if (m_objectTree[i].tex1Name == tex1Name && m_objectTree[i].tex2Name == tex2Name)
- return m_objectTree[i];
+ m_updateGeometry = true;
}
-
- if (unusedPresent)
+ else
{
- for (int i = 0; i < static_cast<int>( m_objectTree.size() ); i++)
+ for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i++)
{
- if (! m_objectTree[i].used)
- {
- m_objectTree[i].used = true;
- m_objectTree[i].tex1Name = tex1Name;
- m_objectTree[i].tex2Name = tex2Name;
- return m_objectTree[i];
- }
+ p1.bboxMin.x = Math::Min(p4.vertices[i].coord.x, p1.bboxMin.x);
+ p1.bboxMin.y = Math::Min(p4.vertices[i].coord.y, p1.bboxMin.y);
+ p1.bboxMin.z = Math::Min(p4.vertices[i].coord.z, p1.bboxMin.z);
+ p1.bboxMax.x = Math::Max(p4.vertices[i].coord.x, p1.bboxMax.x);
+ p1.bboxMax.y = Math::Max(p4.vertices[i].coord.y, p1.bboxMax.y);
+ p1.bboxMax.z = Math::Max(p4.vertices[i].coord.z, p1.bboxMax.z);
}
+
+ p1.radius = Math::Max(p1.bboxMin.Length(), p1.bboxMax.Length());
}
- m_objectTree.push_back(EngineObjLevel1(true, tex1Name, tex2Name));
- return m_objectTree.back();
+ if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
+ p1.totalTriangles += p4.vertices.size() / 3;
+ else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
+ p1.totalTriangles += p4.vertices.size() - 2;
}
-EngineObjLevel2& CEngine::AddLevel2(EngineObjLevel1& p1, int objRank)
+
+int CEngine::CreateObject()
{
- bool unusedPresent = false;
- for (int i = 0; i < static_cast<int>( p1.next.size() ); i++)
+ int objRank = 0;
+ for ( ; objRank < static_cast<int>( m_objects.size() ); objRank++)
{
- if (! p1.next[i].used)
+ if (! m_objects[objRank].used)
{
- unusedPresent = true;
- continue;
+ m_objects[objRank].LoadDefault();
+ break;
}
-
- if (p1.next[i].objRank == objRank)
- return p1.next[i];
}
- if (unusedPresent)
- {
- for (int i = 0; i < static_cast<int>( p1.next.size() ); i++)
- {
- if (! p1.next[i].used)
- {
- p1.next[i].used = true;
- p1.next[i].objRank = objRank;
- return p1.next[i];
- }
- }
- }
+ if (objRank == static_cast<int>( m_objects.size() ))
+ m_objects.push_back(EngineObject());
- p1.next.push_back(EngineObjLevel2(true, objRank));
- return p1.next.back();
+
+ m_objects[objRank].used = true;
+
+ Math::Matrix mat;
+ mat.LoadIdentity();
+ SetObjectTransform(objRank, mat);
+
+ m_objects[objRank].drawWorld = true;
+ m_objects[objRank].distance = 0.0f;
+ m_objects[objRank].shadowRank = -1;
+
+ return objRank;
}
-EngineObjLevel3& CEngine::AddLevel3(EngineObjLevel2& p2, float min, float max)
+void CEngine::DeleteAllObjects()
{
- bool unusedPresent = false;
- for (int i = 0; i < static_cast<int>( p2.next.size() ); i++)
- {
- if (! p2.next[i].used)
- {
- unusedPresent = true;
- continue;
- }
+ m_objects.clear();
+ m_shadows.clear();
- if ( (p2.next[i].min == min) && (p2.next[i].max == max) )
- return p2.next[i];
- }
+ DeleteAllGroundSpots();
+}
- if (unusedPresent)
- {
- for (int i = 0; i < static_cast<int>( p2.next.size() ); i++)
- {
- if (! p2.next[i].used)
- {
- p2.next[i].used = true;
- p2.next[i].min = min;
- p2.next[i].max = max;
- return p2.next[i];
- }
- }
- }
+void CEngine::DeleteObject(int objRank)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- p2.next.push_back(EngineObjLevel3(true, min, max));
- return p2.next.back();
+ // Mark object as deleted
+ m_objects[objRank].used = false;
+
+ // Delete associated shadows
+ DeleteShadow(objRank);
}
-EngineObjLevel4& CEngine::AddLevel4(EngineObjLevel3& p3, EngineTriangleType type,
- const Material& material, int state)
+void CEngine::SetObjectBaseRank(int objRank, int baseObjRank)
{
- bool unusedPresent = false;
- for (int i = 0; i < static_cast<int>( p3.next.size() ); i++)
- {
- if (! p3.next[i].used)
- {
- unusedPresent = true;
- continue;
- }
+ assert(objRank == -1 || (objRank >= 0 && objRank < static_cast<int>( m_objects.size() )));
- if ( (p3.next[i].type == type) && (p3.next[i].material == material) && (p3.next[i].state == state) )
- return p3.next[i];
- }
+ m_objects[objRank].baseObjRank = baseObjRank;
+}
- if (unusedPresent)
- {
- for (int i = 0; i < static_cast<int>( p3.next.size() ); i++)
- {
- if (! p3.next[i].used)
- {
- p3.next[i].used = true;
- p3.next[i].type = type;
- p3.next[i].material = material;
- p3.next[i].state = state;
- return p3.next[i];
- }
- }
- }
+int CEngine::GetObjectBaseRank(int objRank)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- p3.next.push_back(EngineObjLevel4(true, type, material, state));
- return p3.next.back();
+ return m_objects[objRank].baseObjRank;
}
-bool CEngine::AddTriangles(int objRank, const std::vector<VertexTex2>& vertices,
- const Material& material, int state,
- std::string tex1Name, std::string tex2Name,
- float min, float max, bool globalUpdate)
+void CEngine::SetObjectType(int objRank, EngineObjectType type)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- {
- GetLogger()->Error("AddTriangle(): invalid object rank %d\n", objRank);
- return false;
- }
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- m_lastSize = m_size;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
-
- EngineObjLevel1& p1 = AddLevel1(tex1Name, tex2Name);
- EngineObjLevel2& p2 = AddLevel2(p1, objRank);
- EngineObjLevel3& p3 = AddLevel3(p2, min, max);
- EngineObjLevel4& p4 = AddLevel4(p3, ENG_TRIANGLE_TYPE_TRIANGLES, material, state);
+ m_objects[objRank].type = type;
+}
- p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
+EngineObjectType CEngine::GetObjectType(int objRank)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- if (globalUpdate)
- {
- m_updateGeometry = true;
- }
- else
- {
- for (int i = 0; i < static_cast<int>( vertices.size() ); i++)
- {
- m_objects[objRank].bboxMin.x = Math::Min(vertices[i].coord.x, m_objects[objRank].bboxMin.x);
- m_objects[objRank].bboxMin.y = Math::Min(vertices[i].coord.y, m_objects[objRank].bboxMin.y);
- m_objects[objRank].bboxMin.z = Math::Min(vertices[i].coord.z, m_objects[objRank].bboxMin.z);
- m_objects[objRank].bboxMax.x = Math::Max(vertices[i].coord.x, m_objects[objRank].bboxMax.x);
- m_objects[objRank].bboxMax.y = Math::Max(vertices[i].coord.y, m_objects[objRank].bboxMax.y);
- m_objects[objRank].bboxMax.z = Math::Max(vertices[i].coord.z, m_objects[objRank].bboxMax.z);
- }
+ return m_objects[objRank].type;
+}
- m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
- m_objects[objRank].bboxMax.Length());
- }
- m_objects[objRank].totalTriangles += vertices.size() / 3;
+void CEngine::SetObjectTransform(int objRank, const Math::Matrix& transform)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- return true;
+ m_objects[objRank].transform = transform;
}
-bool CEngine::AddSurface(int objRank, const std::vector<VertexTex2>& vertices,
- const Material& material, int state,
- std::string tex1Name, std::string tex2Name,
- float min, float max, bool globalUpdate)
+void CEngine::GetObjectTransform(int objRank, Math::Matrix& transform)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- {
- GetLogger()->Error("AddSurface(): invalid object rank %d\n", objRank);
- return false;
- }
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- m_lastSize = m_size;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
+ transform = m_objects[objRank].transform;
+}
- EngineObjLevel1& p1 = AddLevel1(tex1Name, tex2Name);
- EngineObjLevel2& p2 = AddLevel2(p1, objRank);
- EngineObjLevel3& p3 = AddLevel3(p2, min, max);
- EngineObjLevel4& p4 = AddLevel4(p3, ENG_TRIANGLE_TYPE_SURFACE, material, state);
+void CEngine::SetObjectDrawWorld(int objRank, bool draw)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
+ m_objects[objRank].drawWorld = draw;
+}
- if (globalUpdate)
- {
- m_updateGeometry = true;
- }
- else
- {
- for (int i = 0; i < static_cast<int>( vertices.size() ); i++)
- {
- m_objects[objRank].bboxMin.x = Math::Min(vertices[i].coord.x, m_objects[objRank].bboxMin.x);
- m_objects[objRank].bboxMin.y = Math::Min(vertices[i].coord.y, m_objects[objRank].bboxMin.y);
- m_objects[objRank].bboxMin.z = Math::Min(vertices[i].coord.z, m_objects[objRank].bboxMin.z);
- m_objects[objRank].bboxMax.x = Math::Max(vertices[i].coord.x, m_objects[objRank].bboxMax.x);
- m_objects[objRank].bboxMax.y = Math::Max(vertices[i].coord.y, m_objects[objRank].bboxMax.y);
- m_objects[objRank].bboxMax.z = Math::Max(vertices[i].coord.z, m_objects[objRank].bboxMax.z);
- }
+void CEngine::SetObjectDrawFront(int objRank, bool draw)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
- m_objects[objRank].bboxMax.Length());
- }
+ m_objects[objRank].drawFront = draw;
+}
- m_objects[objRank].totalTriangles += vertices.size() - 2;
+void CEngine::SetObjectTransparency(int objRank, float value)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- return true;
+ m_objects[objRank].transparency = value;
}
-bool CEngine::AddQuick(int objRank, const EngineObjLevel4& buffer,
- std::string tex1Name, std::string tex2Name,
- float min, float max, bool globalUpdate)
+void CEngine::GetObjectBBox(int objRank, Math::Vector& min, Math::Vector& max)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- {
- GetLogger()->Error("AddQuick(): invalid object rank %d\n", objRank);
- return false;
- }
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- EngineObjLevel1& p1 = AddLevel1(tex1Name, tex2Name);
- EngineObjLevel2& p2 = AddLevel2(p1, objRank);
- EngineObjLevel3& p3 = AddLevel3(p2, min, max);
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ return;
- p3.next.push_back(buffer);
- p3.next.back().used = true; // ensure that it is used
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>(m_baseObjects.size()));
- if (globalUpdate)
- {
- m_updateGeometry = true;
- }
- else
- {
- for (int i = 0; i < static_cast<int>( buffer.vertices.size() ); i++)
- {
- m_objects[objRank].bboxMin.x = Math::Min(buffer.vertices[i].coord.x, m_objects[objRank].bboxMin.x);
- m_objects[objRank].bboxMin.y = Math::Min(buffer.vertices[i].coord.y, m_objects[objRank].bboxMin.y);
- m_objects[objRank].bboxMin.z = Math::Min(buffer.vertices[i].coord.z, m_objects[objRank].bboxMin.z);
- m_objects[objRank].bboxMax.x = Math::Max(buffer.vertices[i].coord.x, m_objects[objRank].bboxMax.x);
- m_objects[objRank].bboxMax.y = Math::Max(buffer.vertices[i].coord.y, m_objects[objRank].bboxMax.y);
- m_objects[objRank].bboxMax.z = Math::Max(buffer.vertices[i].coord.z, m_objects[objRank].bboxMax.z);
- }
+ min = m_baseObjects[baseObjRank].bboxMin;
+ max = m_baseObjects[baseObjRank].bboxMax;
+}
- m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
- m_objects[objRank].bboxMax.Length());
- }
- if (buffer.type == ENG_TRIANGLE_TYPE_TRIANGLES)
- m_objects[objRank].totalTriangles += buffer.vertices.size() / 3;
- else if (buffer.type == ENG_TRIANGLE_TYPE_SURFACE)
- m_objects[objRank].totalTriangles += buffer.vertices.size() - 2;
+int CEngine::GetObjectTotalTriangles(int objRank)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ return 0;
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- return true;
+ return m_baseObjects[baseObjRank].totalTriangles;
}
-EngineObjLevel4* CEngine::FindTriangles(int objRank, const Material& material,
- int state, std::string tex1Name,
- std::string tex2Name, float min, float max)
+EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, const Material& material,
+ int state, std::string tex1Name,
+ std::string tex2Name, int lodLevelMask)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- {
- GetLogger()->Error("FindTriangles(): invalid object rank %d\n", objRank);
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
return nullptr;
- }
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ EngineBaseObjTexTier& p2 = p1.next[l2];
- if (p1.tex1Name != tex1Name) continue;
- // TODO: tex2Name compare?
+ if (p2.tex1Name != tex1Name)
+ continue;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
- if (p2.objRank != objRank) continue;
+ if ((p3.lodLevel & lodLevelMask) == 0)
+ continue;
- for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
- if (p3.min != min || p3.max != max) continue;
-
- for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
- {
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
-
- if ( (p4.state & (~(ENG_RSTATE_DUAL_BLACK|ENG_RSTATE_DUAL_WHITE))) != state ||
- p4.material != material )
- continue;
+ if ( (p4.state & (~(ENG_RSTATE_DUAL_BLACK|ENG_RSTATE_DUAL_WHITE))) != state ||
+ p4.material != material )
+ continue;
- return &p4;
- }
+ return &p4;
}
}
}
@@ -1000,92 +862,86 @@ EngineObjLevel4* CEngine::FindTriangles(int objRank, const Material& material,
return nullptr;
}
-int CEngine::GetPartialTriangles(int objRank, float min, float max, float percent, int maxCount,
- std::vector<EngineTriangle>& triangles)
+int CEngine::GetPartialTriangles(int objRank, int lodLevelMask, float percent, int maxCount,
+ std::vector<EngineTriangle>& triangles)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- {
- GetLogger()->Error("GetPartialTriangles(): invalid object rank %d\n", objRank);
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
return 0;
- }
- int total = m_objects[objRank].totalTriangles;
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+
+ int total = p1.totalTriangles;
int expectedCount = static_cast<int>(percent * total);
triangles.reserve(Math::Min(maxCount, expectedCount));
int actualCount = 0;
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ EngineBaseObjTexTier& p2 = p1.next[l2];
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
- if (p2.objRank != objRank) continue;
+ if ((p3.lodLevel & lodLevelMask) == 0)
+ continue;
- for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
-
- if (p3.min != min || p3.max != max) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
- for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
+ if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
-
- if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
+ for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i += 3)
{
- for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i += 3)
- {
- if (static_cast<float>(actualCount) / total >= percent)
- break;
+ if (static_cast<float>(actualCount) / total >= percent)
+ break;
- if (actualCount >= maxCount)
- break;
+ if (actualCount >= maxCount)
+ break;
- EngineTriangle t;
- t.triangle[0] = p4.vertices[i];
- t.triangle[1] = p4.vertices[i+1];
- t.triangle[2] = p4.vertices[i+2];
- t.material = p4.material;
- t.state = p4.state;
- t.tex1Name = p1.tex1Name;
- t.tex2Name = p1.tex2Name;
+ EngineTriangle t;
+ t.triangle[0] = p4.vertices[i];
+ t.triangle[1] = p4.vertices[i+1];
+ t.triangle[2] = p4.vertices[i+2];
+ t.material = p4.material;
+ t.state = p4.state;
+ t.tex1Name = p2.tex1Name;
+ t.tex2Name = p2.tex2Name;
- triangles.push_back(t);
+ triangles.push_back(t);
- ++actualCount;
- }
+ ++actualCount;
}
- else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
+ }
+ else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
+ {
+ for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i += 1)
{
- for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i += 1)
- {
- if (static_cast<float>(actualCount) / total >= percent)
- break;
+ if (static_cast<float>(actualCount) / total >= percent)
+ break;
- if (actualCount >= maxCount)
- break;
+ if (actualCount >= maxCount)
+ break;
- EngineTriangle t;
- t.triangle[0] = p4.vertices[i];
- t.triangle[1] = p4.vertices[i+1];
- t.triangle[2] = p4.vertices[i+2];
- t.material = p4.material;
- t.state = p4.state;
- t.tex1Name = p1.tex1Name;
- t.tex2Name = p1.tex2Name;
+ EngineTriangle t;
+ t.triangle[0] = p4.vertices[i];
+ t.triangle[1] = p4.vertices[i+1];
+ t.triangle[2] = p4.vertices[i+2];
+ t.material = p4.material;
+ t.state = p4.state;
+ t.tex1Name = p2.tex1Name;
+ t.tex2Name = p2.tex2Name;
- triangles.push_back(t);
+ triangles.push_back(t);
- ++actualCount;
- }
+ ++actualCount;
}
}
}
@@ -1095,105 +951,40 @@ int CEngine::GetPartialTriangles(int objRank, float min, float max, float percen
return actualCount;
}
-void CEngine::ChangeLOD()
+void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name)
{
- float oldLimit[2] =
- {
- GetLimitLOD(0, true),
- GetLimitLOD(1, true)
- };
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- float newLimit[2] =
- {
- GetLimitLOD(0, false),
- GetLimitLOD(1, false)
- };
-
- float oldTerrain = m_terrainVision * m_lastClippingDistance;
- float newTerrain = m_terrainVision * m_clippingDistance;
-
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
- {
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
-
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ return;
- for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
- {
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- 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;
- }
- }
- }
- }
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
- m_lastSize = m_size;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
-}
-
-bool CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name)
-{
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
-
- if (p1.tex2Name == tex2Name) continue; // already new
-
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
-
- if (p2.objRank != objRank) continue;
-
- EngineObjLevel1& newP1 = AddLevel1(p1.tex1Name, tex2Name);
+ EngineBaseObjTexTier& p2 = p1.next[l2];
- newP1.next.push_back(EngineObjLevel2(true, objRank));
+ if (p2.tex2Name == tex2Name)
+ continue; // already new
- EngineObjLevel2& newP2 = newP1.next.back();
- newP2.next.swap(p2.next);
-
- p2.used = false;
- }
+ EngineBaseObjTexTier& newP2 = AddLevel2(p1, p2.tex1Name, tex2Name);
+ newP2.next.swap(p2.next);
}
- return true;
}
-bool CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state,
- const std::string& tex1Name, const std::string& tex2Name,
- float min, float max, EngineTextureMapping mode,
- float au, float bu, float av, float bv)
+void CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state,
+ const std::string& tex1Name, const std::string& tex2Name,
+ int lodLevelMask, EngineTextureMapping mode,
+ float au, float bu, float av, float bv)
{
- EngineObjLevel4* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, min, max);
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, lodLevelMask);
if (p4 == nullptr)
- return false;
+ return;
int nb = p4->vertices.size();
@@ -1243,27 +1034,113 @@ bool CEngine::ChangeTextureMapping(int objRank, const Material& mat, int state,
}
}
- return true;
+ UpdateStaticBuffer(*p4);
}
-bool CEngine::TrackTextureMapping(int objRank, const Material& mat, int state,
- const std::string& tex1Name, const std::string& tex2Name,
- float min, float max, EngineTextureMapping mode,
- float pos, float factor, float tl, float ts, float tt)
+void CEngine::TrackTextureMapping(int objRank, const Material& mat, int state,
+ const std::string& tex1Name, const std::string& tex2Name,
+ int lodLevelMask, EngineTextureMapping mode,
+ float pos, float factor, float tl, float ts, float tt)
{
- // TODO track texture mapping: pretty complex code, so leaving it for now
- GetLogger()->Trace("CEngine::TrackTextureMapping(): stub!\n");
- return true;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ EngineBaseObjDataTier* p4 = FindTriangles(objRank, mat, state, tex1Name, tex2Name, lodLevelMask);
+ if (p4 == nullptr)
+ return;
+
+ int tNum = p4->vertices.size();
+ if (tNum < 12 || tNum % 6 != 0)
+ return;
+
+ std::vector<Gfx::VertexTex2>& vs = p4->vertices;
+
+ while (pos < 0.0f)
+ pos += 1.0f; // never negative!
+
+ Math::Vector current;
+
+ for (int i = 0; i < 6; i++)
+ {
+ for (int j = 0; j < 6; j++)
+ {
+ if (Math::IsEqual(vs[i].coord.x, vs[j+6].coord.x) &&
+ Math::IsEqual(vs[i].coord.y, vs[j+6].coord.y))
+ {
+ current.x = vs[i].coord.x; // position end link
+ current.y = vs[i].coord.y;
+ break;
+ }
+ }
+ }
+
+ float ps = 0.0f; // start position on the periphery
+ float pe = 0.0f;
+ int is[6] = { 0 }, ie[6] = { 0 };
+
+ int tBase = 0;
+ for (int ti = 0; ti < tNum / 6; ti++)
+ {
+ int s = 0;
+ int e = 0;
+
+ for (int i = 0; i < 6; i++)
+ {
+ if (Math::IsEqual(vs[tBase + i].coord.x, current.x, 0.0001f) &&
+ Math::IsEqual(vs[tBase + i].coord.y, current.y, 0.0001f))
+ {
+ ie[e++] = i;
+ }
+ else
+ {
+ is[s++] = i;
+ }
+ }
+ if (s == 3 && e == 3)
+ {
+ pe = ps + Math::Point(vs[tBase + is[0]].coord.x - vs[tBase + ie[0]].coord.x,
+ vs[tBase + is[0]].coord.y - vs[tBase + ie[0]].coord.y).Length() / factor; // end position on the periphery
+
+ float pps = ps + pos;
+ float ppe = pe + pos;
+ int offset = static_cast<int>(pps);
+ ppe -= offset;
+ pps -= offset;
+
+ for (int i = 0; i < 3; i++)
+ {
+ vs[tBase + is[i]].texCoord.x = ((pps * tl) + ts) / tt;
+ vs[tBase + ie[i]].texCoord.x = ((ppe * tl) + ts) / tt;
+ }
+ }
+
+ if (ti >= (tNum / 6) - 1)
+ break;
+
+ for (int i = 0; i < 6; i++)
+ {
+ if (!Math::IsEqual(vs[tBase + i+6].coord.x, current.x, 0.0001f) ||
+ !Math::IsEqual(vs[tBase + i+6].coord.y, current.y, 0.0001f))
+ {
+ current.x = vs[tBase + i+6].coord.x; // end next link
+ current.y = vs[tBase + i+6].coord.y;
+ break;
+ }
+ }
+ ps = pe; // following start position on the periphery
+ tBase += 6;
+ }
+
+ UpdateStaticBuffer(*p4);
}
-bool CEngine::CreateShadow(int objRank)
+void CEngine::CreateShadow(int objRank)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
// Already allocated?
- if (m_objects[objRank].shadowRank != -1) return true;
+ if (m_objects[objRank].shadowRank != -1)
+ return;
int index = 0;
for ( ; index < static_cast<int>( m_shadows.size() ); index++)
@@ -1275,146 +1152,147 @@ bool CEngine::CreateShadow(int objRank)
}
}
- m_shadows.push_back(EngineShadow());
+ if (index == static_cast<int>( m_shadows.size() ))
+ m_shadows.push_back(EngineShadow());
m_shadows[index].used = true;
m_shadows[index].objRank = objRank;
m_shadows[index].height = 0.0f;
m_objects[objRank].shadowRank = index;
-
- return true;
}
void CEngine::DeleteShadow(int objRank)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
return;
- m_shadows[i].used = false;
- m_shadows[i].objRank = -1;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].used = false;
+ m_shadows[shadowRank].objRank = -1;
m_objects[objRank].shadowRank = -1;
}
-bool CEngine::SetObjectShadowHide(int objRank, bool hide)
+void CEngine::SetObjectShadowHide(int objRank, bool hide)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].hide = hide;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].hide = hide;
}
-bool CEngine::SetObjectShadowType(int objRank, EngineShadowType type)
+void CEngine::SetObjectShadowType(int objRank, EngineShadowType type)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].type = type;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].type = type;
}
-bool CEngine::SetObjectShadowPos(int objRank, const Math::Vector& pos)
+void CEngine::SetObjectShadowPos(int objRank, const Math::Vector& pos)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].pos = pos;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].pos = pos;
}
-bool CEngine::SetObjectShadowNormal(int objRank, const Math::Vector& normal)
+void CEngine::SetObjectShadowNormal(int objRank, const Math::Vector& normal)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].normal = normal;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].normal = normal;
}
-bool CEngine::SetObjectShadowAngle(int objRank, float angle)
+void CEngine::SetObjectShadowAngle(int objRank, float angle)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].angle = angle;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].angle = angle;
}
-bool CEngine::SetObjectShadowRadius(int objRank, float radius)
+void CEngine::SetObjectShadowRadius(int objRank, float radius)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].radius = radius;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].radius = radius;
}
-bool CEngine::SetObjectShadowIntensity(int objRank, float intensity)
+void CEngine::SetObjectShadowIntensity(int objRank, float intensity)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].intensity = intensity;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].intensity = intensity;
}
-bool CEngine::SetObjectShadowHeight(int objRank, float height)
+void CEngine::SetObjectShadowHeight(int objRank, float height)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return false;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
- return false;
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
+ return;
- m_shadows[i].height = height;
- return true;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ m_shadows[shadowRank].height = height;
}
float CEngine::GetObjectShadowRadius(int objRank)
{
- if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
- return 0.0f;
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
- int i = m_objects[objRank].shadowRank;
- if (i == -1)
+ int shadowRank = m_objects[objRank].shadowRank;
+ if (shadowRank == -1)
return 0.0f;
- return m_shadows[i].radius;
+ assert(shadowRank >= 0 && shadowRank < static_cast<int>( m_shadows.size() ));
+
+ return m_shadows[shadowRank].radius;
}
bool CEngine::GetHighlight(Math::Point &p1, Math::Point &p2)
@@ -1436,21 +1314,31 @@ void CEngine::SetHighlightRank(int *rankList)
bool CEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max)
{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
min.x = 1000000.0f;
min.y = 1000000.0f;
max.x = -1000000.0f;
max.y = -1000000.0f;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ return false;
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+
for (int i = 0; i < 8; i++)
{
Math::Vector p;
- if ( i & (1<<0) ) p.x = m_objects[objRank].bboxMin.x;
- else p.x = m_objects[objRank].bboxMax.x;
- if ( i & (1<<1) ) p.y = m_objects[objRank].bboxMin.y;
- else p.y = m_objects[objRank].bboxMax.y;
- if ( i & (1<<2) ) p.z = m_objects[objRank].bboxMin.z;
- else p.z = m_objects[objRank].bboxMax.z;
+ if ( i & (1<<0) ) p.x = p1.bboxMin.x;
+ else p.x = p1.bboxMax.x;
+ if ( i & (1<<1) ) p.y = p1.bboxMin.y;
+ else p.y = p1.bboxMax.y;
+ if ( i & (1<<2) ) p.z = p1.bboxMin.z;
+ else p.z = p1.bboxMax.z;
Math::Vector pp;
if (TransformPoint(pp, objRank, p))
@@ -1462,20 +1350,36 @@ bool CEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max)
}
}
- if ( min.x == 1000000.0f ||
- min.y == 1000000.0f ||
- max.x == -1000000.0f ||
- max.y == -1000000.0f ) return false;
+ if (min.x == 1000000.0f ||
+ min.y == 1000000.0f ||
+ max.x == -1000000.0f ||
+ max.y == -1000000.0f)
+ return false;
return true;
}
-void CEngine::FlushGroundSpot()
+void CEngine::DeleteAllGroundSpots()
{
m_groundSpots.clear();
m_firstGroundSpot = true;
- // TODO: blank all shadow textures
+ for (int s = 0; s < 16; s++)
+ {
+ CImage shadowImg(Math::IntPoint(256, 256));
+ shadowImg.Fill(Gfx::IntColor(255, 255, 255, 255));
+
+ std::stringstream str;
+ str << "shadow" << std::setfill('0') << std::setw(2) << s << ".png";
+ std::string texName = str.str();
+
+ DeleteTexture(texName);
+
+ Gfx::Texture tex = m_device->CreateTexture(&shadowImg, m_defaultTexParams);
+
+ m_texNameMap[texName] = tex;
+ m_revTexNameMap[tex] = texName;
+ }
}
int CEngine::CreateGroundSpot()
@@ -1500,54 +1404,46 @@ int CEngine::CreateGroundSpot()
void CEngine::DeleteGroundSpot(int rank)
{
+ assert(rank >= 0 && rank < static_cast<int>( m_groundSpots.size() ));
+
m_groundSpots[rank].used = false;
m_groundSpots[rank].pos = Math::Vector(0.0f, 0.0f, 0.0f);
}
-bool CEngine::SetObjectGroundSpotPos(int rank, const Math::Vector& pos)
+void CEngine::SetObjectGroundSpotPos(int rank, const Math::Vector& pos)
{
- if ( rank < 0 || rank >= static_cast<int>( m_groundSpots.size() ) )
- return 0.0f;
+ assert(rank >= 0 && rank < static_cast<int>( m_groundSpots.size() ));
m_groundSpots[rank].pos = pos;
- return true;
}
-bool CEngine::SetObjectGroundSpotRadius(int rank, float radius)
+void CEngine::SetObjectGroundSpotRadius(int rank, float radius)
{
- if ( rank < 0 || rank >= static_cast<int>( m_groundSpots.size() ) )
- return 0.0f;
+ assert(rank >= 0 && rank < static_cast<int>( m_groundSpots.size() ));
m_groundSpots[rank].radius = radius;
- return true;
}
-bool CEngine::SetObjectGroundSpotColor(int rank, const Color& color)
+void CEngine::SetObjectGroundSpotColor(int rank, const Color& color)
{
- if ( rank < 0 || rank >= static_cast<int>( m_groundSpots.size() ) )
- return 0.0f;
+ assert(rank >= 0 && rank < static_cast<int>( m_groundSpots.size() ));
m_groundSpots[rank].color = color;
- return true;
}
-bool CEngine::SetObjectGroundSpotMinMax(int rank, float min, float max)
+void CEngine::SetObjectGroundSpotMinMax(int rank, float min, float max)
{
- if ( rank < 0 || rank >= static_cast<int>( m_groundSpots.size() ) )
- return 0.0f;
+ assert(rank >= 0 && rank < static_cast<int>( m_groundSpots.size() ));
m_groundSpots[rank].min = min;
m_groundSpots[rank].max = max;
- return true;
}
-bool CEngine::SetObjectGroundSpotSmooth(int rank, float smooth)
+void CEngine::SetObjectGroundSpotSmooth(int rank, float smooth)
{
- if ( rank < 0 || rank >= static_cast<int>( m_groundSpots.size() ) )
- return 0.0f;
+ assert(rank >= 0 && rank < static_cast<int>( m_groundSpots.size() ));
m_groundSpots[rank].smooth = smooth;
- return true;
}
void CEngine::CreateGroundMark(Math::Vector pos, float radius,
@@ -1556,6 +1452,7 @@ void CEngine::CreateGroundMark(Math::Vector pos, float radius,
{
m_groundMark.LoadDefault();
+ m_groundMark.draw = true;
m_groundMark.phase = ENG_GR_MARK_PHASE_INC;
m_groundMark.delay[0] = delay1;
m_groundMark.delay[1] = delay2;
@@ -1575,8 +1472,6 @@ void CEngine::DeleteGroundMark(int rank)
void CEngine::ComputeDistance()
{
- // TODO: s_resol???
-
for (int i = 0; i < static_cast<int>( m_objects.size() ); i++)
{
if (! m_objects[i].used)
@@ -1595,51 +1490,39 @@ void CEngine::UpdateGeometry()
if (! m_updateGeometry)
return;
- for (int i = 0; i < static_cast<int>( m_objects.size() ); i++)
+ for (int baseObjRank = 0; baseObjRank < static_cast<int>( m_baseObjects.size() ); baseObjRank++)
{
- m_objects[i].bboxMin.x = 0;
- m_objects[i].bboxMin.y = 0;
- m_objects[i].bboxMin.z = 0;
- m_objects[i].bboxMax.x = 0;
- m_objects[i].bboxMax.y = 0;
- m_objects[i].bboxMax.z = 0;
- m_objects[i].radius = 0;
- }
+ EngineBaseObject &p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
- {
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ p1.bboxMin.LoadZero();
+ p1.bboxMax.LoadZero();
+ p1.radius = 0;
for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
-
- int objRank = p2.objRank;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i++)
{
- m_objects[objRank].bboxMin.x = Math::Min(p4.vertices[i].coord.x, m_objects[objRank].bboxMin.x);
- m_objects[objRank].bboxMin.y = Math::Min(p4.vertices[i].coord.y, m_objects[objRank].bboxMin.y);
- m_objects[objRank].bboxMin.z = Math::Min(p4.vertices[i].coord.z, m_objects[objRank].bboxMin.z);
- m_objects[objRank].bboxMax.x = Math::Max(p4.vertices[i].coord.x, m_objects[objRank].bboxMax.x);
- m_objects[objRank].bboxMax.y = Math::Max(p4.vertices[i].coord.y, m_objects[objRank].bboxMax.y);
- m_objects[objRank].bboxMax.z = Math::Max(p4.vertices[i].coord.z, m_objects[objRank].bboxMax.z);
+ p1.bboxMin.x = Math::Min(p4.vertices[i].coord.x, p1.bboxMin.x);
+ p1.bboxMin.y = Math::Min(p4.vertices[i].coord.y, p1.bboxMin.y);
+ p1.bboxMin.z = Math::Min(p4.vertices[i].coord.z, p1.bboxMin.z);
+ p1.bboxMax.x = Math::Max(p4.vertices[i].coord.x, p1.bboxMax.x);
+ p1.bboxMax.y = Math::Max(p4.vertices[i].coord.y, p1.bboxMax.y);
+ p1.bboxMax.z = Math::Max(p4.vertices[i].coord.z, p1.bboxMax.z);
}
- m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
- m_objects[objRank].bboxMax.Length());
+ p1.radius = Math::Max(p1.bboxMin.Length(), p1.bboxMax.Length());
}
}
}
@@ -1648,14 +1531,76 @@ void CEngine::UpdateGeometry()
m_updateGeometry = false;
}
+void CEngine::UpdateStaticBuffer(EngineBaseObjDataTier& p4)
+{
+ PrimitiveType type;
+ if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
+ type = PRIMITIVE_TRIANGLES;
+ else
+ type = PRIMITIVE_TRIANGLE_STRIP;
+
+ if (p4.staticBufferId == 0)
+ p4.staticBufferId = m_device->CreateStaticBuffer(type, &p4.vertices[0], p4.vertices.size());
+ else
+ m_device->UpdateStaticBuffer(p4.staticBufferId, type, &p4.vertices[0], p4.vertices.size());
+
+ p4.updateStaticBuffer = false;
+}
+
+void CEngine::UpdateStaticBuffers()
+{
+ if (!m_updateStaticBuffers)
+ return;
+
+ m_updateStaticBuffers = false;
+
+ for (int baseObjRank = 0; baseObjRank < static_cast<int>( m_baseObjects.size() ); baseObjRank++)
+ {
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
+ {
+ EngineBaseObjLODTier& p3 = p2.next[l3];
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
+ {
+ EngineBaseObjDataTier& p4 = p3.next[l4];
+
+ if (! p4.updateStaticBuffer)
+ continue;
+
+ UpdateStaticBuffer(p4);
+ }
+ }
+ }
+ }
+}
+
void CEngine::Update()
{
ComputeDistance();
UpdateGeometry();
+ UpdateStaticBuffers();
}
bool CEngine::DetectBBox(int objRank, Math::Point mouse)
{
+ assert(objRank >= 0 && objRank < static_cast<int>(m_objects.size()));
+
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ return false;
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>(m_baseObjects.size()));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+
Math::Point min, max;
min.x = 1000000.0f;
min.y = 1000000.0f;
@@ -1666,12 +1611,12 @@ bool CEngine::DetectBBox(int objRank, Math::Point mouse)
{
Math::Vector p;
- if ( i & (1<<0) ) p.x = m_objects[objRank].bboxMin.x;
- else p.x = m_objects[objRank].bboxMax.x;
- if ( i & (1<<1) ) p.y = m_objects[objRank].bboxMin.y;
- else p.y = m_objects[objRank].bboxMax.y;
- if ( i & (1<<2) ) p.z = m_objects[objRank].bboxMin.z;
- else p.z = m_objects[objRank].bboxMax.z;
+ if ( i & (1<<0) ) p.x = p1.bboxMin.x;
+ else p.x = p1.bboxMax.x;
+ if ( i & (1<<1) ) p.y = p1.bboxMin.y;
+ else p.y = p1.bboxMax.y;
+ if ( i & (1<<2) ) p.z = p1.bboxMin.z;
+ else p.z = p1.bboxMax.z;
Math::Vector pp;
if ( TransformPoint(pp, objRank, p) )
@@ -1694,41 +1639,51 @@ int CEngine::DetectObject(Math::Point mouse)
float min = 1000000.0f;
int nearest = -1;
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int objRank = 0; objRank < static_cast<int>( m_objects.size() ); objRank++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ if (! m_objects[objRank].used)
+ continue;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
+ continue;
+
+ if (! DetectBBox(objRank, mouse))
+ continue;
- if (m_objects[p2.objRank].type == ENG_OBJTYPE_TERRAIN) continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ continue;
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>(m_baseObjects.size()));
- if (! DetectBBox(p2.objRank, mouse)) continue;
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ 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<int>( p3.next.size() ); l4++)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
{
for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i += 3)
{
float dist = 0.0f;
- if (DetectTriangle(mouse, &p4.vertices[i], p2.objRank, dist) && dist < min)
+ if (DetectTriangle(mouse, &p4.vertices[i], objRank, dist) && dist < min)
{
min = dist;
- nearest = p2.objRank;
+ nearest = objRank;
}
}
}
@@ -1737,10 +1692,10 @@ int CEngine::DetectObject(Math::Point mouse)
for (int i = 0; i < static_cast<int>( p4.vertices.size() ) - 2; i += 1)
{
float dist = 0.0f;
- if (DetectTriangle(mouse, &p4.vertices[i], p2.objRank, dist) && dist < min)
+ if (DetectTriangle(mouse, &p4.vertices[i], objRank, dist) && dist < min)
{
min = dist;
- nearest = p2.objRank;
+ nearest = objRank;
}
}
}
@@ -1754,6 +1709,8 @@ int CEngine::DetectObject(Math::Point mouse)
bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRank, float& dist)
{
+ assert(objRank >= 0 && objRank < static_cast<int>(m_objects.size()));
+
Math::Vector p2D[3], p3D;
for (int i = 0; i < 3; i++)
@@ -1766,18 +1723,25 @@ bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRan
return false;
}
- if ( mouse.x < p2D[0].x &&
- mouse.x < p2D[1].x &&
- mouse.x < p2D[2].x ) return false;
- if ( mouse.x > p2D[0].x &&
- mouse.x > p2D[1].x &&
- mouse.x > p2D[2].x ) return false;
- if ( mouse.y < p2D[0].y &&
- mouse.y < p2D[1].y &&
- mouse.y < p2D[2].y ) return false;
- if ( mouse.y > p2D[0].y &&
- mouse.y > p2D[1].y &&
- mouse.y > p2D[2].y ) return false;
+ if (mouse.x < p2D[0].x &&
+ mouse.x < p2D[1].x &&
+ mouse.x < p2D[2].x)
+ return false;
+
+ if (mouse.x > p2D[0].x &&
+ mouse.x > p2D[1].x &&
+ mouse.x > p2D[2].x)
+ return false;
+
+ if (mouse.y < p2D[0].y &&
+ mouse.y < p2D[1].y &&
+ mouse.y < p2D[2].y)
+ return false;
+
+ if (mouse.y > p2D[0].y &&
+ mouse.y > p2D[1].y &&
+ mouse.y > p2D[2].y)
+ return false;
Math::Point a, b, c;
a.x = p2D[0].x;
@@ -1794,18 +1758,75 @@ bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRan
return true;
}
+//! Use only after world transform already set
bool CEngine::IsVisible(int objRank)
{
- // TODO: use ComputeSphereVisiblity() after tested OK
- return true;
+ assert(objRank >= 0 && objRank < static_cast<int>(m_objects.size()));
+
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ return false;
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>(m_baseObjects.size()));
+
+ float radius = m_baseObjects[baseObjRank].radius;
+ Math::Vector center(0.0f, 0.0f, 0.0f);
+ if (m_device->ComputeSphereVisibility(center, radius) == Gfx::FRUSTUM_PLANE_ALL)
+ {
+ m_objects[objRank].visible = true;
+ return true;
+ }
+
+ m_objects[objRank].visible = false;
+ 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<int>(m_objects.size()));
+
p3D = Math::Transform(m_objects[objRank].transform, p3D);
p3D = Math::Transform(m_matView, p3D);
- if (p3D.z < 2.0f) return false; // behind?
+ if (p3D.z < 2.0f)
+ return false; // behind?
p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1);
p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2);
@@ -1833,15 +1854,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);
@@ -1855,7 +1867,7 @@ void CEngine::SetState(int state, const Color& color)
params.colorOperation = TEX_MIX_OPER_MODULATE;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_FACTOR;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ?
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
params.factor = color;
m_device->SetTextureEnabled(0, true);
@@ -1874,7 +1886,7 @@ void CEngine::SetState(int state, const Color& color)
params.colorOperation = TEX_MIX_OPER_ADD;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_FACTOR;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ?
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
params.factor = color.Inverse();
m_device->SetTextureEnabled(0, true);
@@ -1914,7 +1926,7 @@ void CEngine::SetState(int state, const Color& color)
TextureStageParams params;
params.colorOperation = TEX_MIX_OPER_REPLACE;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ?
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
m_device->SetTextureEnabled(0, true);
m_device->SetTextureStageParams(0, params);
@@ -1982,7 +1994,7 @@ void CEngine::SetState(int state, const Color& color)
TextureStageParams params;
params.colorOperation = TEX_MIX_OPER_DEFAULT; // default modulate
- params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ?
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
m_device->SetTextureEnabled(0, true);
m_device->SetTextureStageParams(0, params);
@@ -2003,7 +2015,7 @@ void CEngine::SetState(int state, const Color& color)
params.colorOperation = TEX_MIX_OPER_MODULATE;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_COMPUTED_COLOR;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: ???
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
m_device->SetTextureEnabled(1, true);
m_device->SetTextureStageParams(1, params);
}
@@ -2013,7 +2025,7 @@ void CEngine::SetState(int state, const Color& color)
params.colorOperation = TEX_MIX_OPER_ADD;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_COMPUTED_COLOR;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: ???
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
m_device->SetTextureEnabled(1, true);
m_device->SetTextureStageParams(1, params);
}
@@ -2071,7 +2083,7 @@ void CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& looka
Math::LoadViewMatrix(m_matView, eyePt, lookatPt, upVec);
if (m_sound == nullptr)
- m_sound = static_cast<CSoundInterface*>( m_iMan->SearchInstance(CLASS_SOUND) );
+ m_sound = m_app->GetSound();
if (m_sound != nullptr)
m_sound->SetListener(eyePt, lookatPt);
@@ -2168,42 +2180,50 @@ bool CEngine::LoadAllTextures()
bool ok = true;
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int objRank = 0; objRank < static_cast<int>( m_objects.size() ); objRank++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ if (! m_objects[objRank].used)
+ continue;
bool terrain = false;
+ if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
+ terrain = true;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ continue;
- if (m_objects[p2.objRank].type == ENG_OBJTYPE_TERRAIN)
- terrain = true;
- }
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
- if (! p1.tex1Name.empty())
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- if (terrain)
- p1.tex1 = LoadTexture(p1.tex1Name, m_terrainTexParams);
- else
- p1.tex1 = LoadTexture(p1.tex1Name);
+ EngineBaseObjTexTier& p2 = p1.next[l2];
- if (! p1.tex1.Valid())
- ok = false;
- }
+ if (! p2.tex1Name.empty())
+ {
+ if (terrain)
+ p2.tex1 = LoadTexture(p2.tex1Name, m_terrainTexParams);
+ else
+ p2.tex1 = LoadTexture(p2.tex1Name);
- if (! p1.tex2Name.empty())
- {
- if (terrain)
- p1.tex2 = LoadTexture(p1.tex2Name, m_terrainTexParams);
- else
- p1.tex2 = LoadTexture(p1.tex2Name);
+ if (! p2.tex1.Valid())
+ ok = false;
+ }
- if (! p1.tex2.Valid())
- ok = false;
+ if (! p2.tex2Name.empty())
+ {
+ if (terrain)
+ p2.tex2 = LoadTexture(p2.tex2Name, m_terrainTexParams);
+ else
+ p2.tex2 = LoadTexture(p2.tex2Name);
+
+ if (! p2.tex2.Valid())
+ ok = false;
+ }
}
}
@@ -2219,7 +2239,8 @@ bool IsExcludeColor(Math::Point *exclude, int x, int y)
if ( x >= static_cast<int>(exclude[i+0].x*256.0f) &&
x < static_cast<int>(exclude[i+1].x*256.0f) &&
y >= static_cast<int>(exclude[i+0].y*256.0f) &&
- y < static_cast<int>(exclude[i+1].y*256.0f) ) return true; // exclude
+ y < static_cast<int>(exclude[i+1].y*256.0f) )
+ return true; // exclude
i += 2;
}
@@ -2235,12 +2256,13 @@ bool CEngine::ChangeTextureColor(const std::string& texName,
Math::Point ts, Math::Point ti,
Math::Point *exclude, float shift, bool hsv)
{
- if ( colorRef1.r == colorNew1.r &&
- colorRef1.g == colorNew1.g &&
- colorRef1.b == colorNew1.b &&
- colorRef2.r == colorNew2.r &&
- colorRef2.g == colorNew2.g &&
- colorRef2.b == colorNew2.b ) return true;
+ if (colorRef1.r == colorNew1.r &&
+ colorRef1.g == colorNew1.g &&
+ colorRef1.b == colorNew1.b &&
+ colorRef2.r == colorNew2.r &&
+ colorRef2.g == colorNew2.g &&
+ colorRef2.b == colorNew2.b)
+ return true;
DeleteTexture(texName);
@@ -2275,7 +2297,8 @@ bool CEngine::ChangeTextureColor(const std::string& texName,
{
for (int x = sx; x < ex; x++)
{
- if (exclude != nullptr && IsExcludeColor(exclude, x,y) ) continue;
+ if (exclude != nullptr && IsExcludeColor(exclude, x,y) )
+ continue;
Color color = img.GetPixel(Math::IntPoint(x, y));
@@ -2413,33 +2436,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;
@@ -2675,6 +2671,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;
}
@@ -2886,7 +2883,6 @@ void CEngine::ApplyChange()
m_deepView[1] /= m_lastClippingDistance;
SetFocus(m_focus);
- ChangeLOD();
m_deepView[0] *= m_clippingDistance;
m_deepView[1] *= m_clippingDistance;
@@ -2905,7 +2901,8 @@ void CEngine::ApplyChange()
viewport, and renders the scene. */
void CEngine::Render()
{
- if (! m_render) return;
+ if (! m_render)
+ return;
m_statisticTriangle = 0;
m_lastState = -1;
@@ -2928,7 +2925,9 @@ void CEngine::Render()
if (m_drawWorld)
Draw3DScene();
+ m_app->StartPerformanceCounter(PCNT_RENDER_INTERFACE);
DrawInterface();
+ m_app->StopPerformanceCounter(PCNT_RENDER_INTERFACE);
// End the scene
m_device->EndScene();
@@ -2959,68 +2958,61 @@ void CEngine::Draw3DScene()
if (m_waterMode) m_water->DrawBack(); // draws water background
+ m_app->StartPerformanceCounter(PCNT_RENDER_TERRAIN);
+
+ // Draw terrain with shadows, if shadows enabled
if (m_shadowVisible)
{
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN);
- // Draw the terrain
-
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ if (! m_objects[objRank].used)
+ continue;
- // Should be loaded by now
- SetTexture(p1.tex1, 0);
- SetTexture(p1.tex2, 1);
+ if (m_objects[objRank].type != ENG_OBJTYPE_TERRAIN)
+ continue;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ if (! m_objects[objRank].drawWorld)
+ continue;
- int objRank = p2.objRank;
- if (m_objects[objRank].type != ENG_OBJTYPE_TERRAIN)
- continue;
- if (! m_objects[objRank].drawWorld)
- continue;
+ m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
- m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
+ if (! IsVisible(objRank))
+ continue;
- if (! IsVisible(objRank))
- continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ continue;
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+
+ SetTexture(p2.tex1, 0);
+ SetTexture(p2.tex2, 1);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ 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<int>( p3.next.size() ); l4++)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
SetMaterial(p4.material);
SetState(p4.state);
- if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
- &p4.vertices[0],
- p4.vertices.size() );
- m_statisticTriangle += p4.vertices.size() / 3;
- }
- if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
- &p4.vertices[0],
- p4.vertices.size() );
- m_statisticTriangle += p4.vertices.size() - 2;
- }
+ DrawObject(p4);
}
}
}
@@ -3030,51 +3022,59 @@ void CEngine::Draw3DScene()
DrawShadow();
}
- // Draw objects (non-terrain)
+ m_app->StopPerformanceCounter(PCNT_RENDER_TERRAIN);
+
+ // Draw other objects (and if shadows disabled, also terrain)
+
+ m_app->StartPerformanceCounter(PCNT_RENDER_OBJECTS);
bool transparent = false;
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ if (! m_objects[objRank].used)
+ continue;
+
+ if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
+ continue;
- // Should be loaded by now
- SetTexture(p1.tex1, 0);
- SetTexture(p1.tex2, 1);
+ if (! m_objects[objRank].drawWorld)
+ continue;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
- int objRank = p2.objRank;
+ if (! IsVisible(objRank))
+ continue;
- if (m_shadowVisible && m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
- continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ continue;
- if (! m_objects[objRank].drawWorld)
- continue;
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
- if (! IsVisible(objRank))
- continue;
+ m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
- m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+
+ SetTexture(p2.tex1, 0);
+ SetTexture(p2.tex2, 1);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
- if ( m_objects[objRank].distance < p3.min ||
- m_objects[objRank].distance >= p3.max ) continue;
+ if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel))
+ continue;
for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
if (m_objects[objRank].transparency != 0.0f) // transparent ?
{
@@ -3085,22 +3085,7 @@ void CEngine::Draw3DScene()
SetMaterial(p4.material);
SetState(p4.state);
- if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
- &p4.vertices[0],
- p4.vertices.size() );
-
- m_statisticTriangle += p4.vertices.size() / 3;
- }
- else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
- &p4.vertices[0],
- p4.vertices.size() );
-
- m_statisticTriangle += p4.vertices.size() - 2;
- }
+ DrawObject(p4);
}
}
}
@@ -3113,47 +3098,51 @@ void CEngine::Draw3DScene()
int tState = ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE;
Color tColor = Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f);
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ if (! m_objects[objRank].used)
+ continue;
+
+ if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
+ continue;
- // Should be loaded by now
- SetTexture(p1.tex1, 0);
- SetTexture(p1.tex2, 1);
+ if (! m_objects[objRank].drawWorld)
+ continue;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
- int objRank = p2.objRank;
+ if (! IsVisible(objRank))
+ continue;
- if (m_shadowVisible && m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
- continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ continue;
- if (! m_objects[objRank].drawWorld)
- continue;
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
- if (! IsVisible(objRank))
- continue;
+ m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
- m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
+ SetTexture(p2.tex1, 0);
+ SetTexture(p2.tex2, 1);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
- if ( m_objects[objRank].distance < p3.min ||
- m_objects[objRank].distance >= p3.max ) continue;
+ if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel))
+ continue;
for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
if (m_objects[objRank].transparency == 0.0f)
continue;
@@ -3161,40 +3150,61 @@ void CEngine::Draw3DScene()
SetMaterial(p4.material);
SetState(tState, tColor);
- if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
- &p4.vertices[0],
- p4.vertices.size() );
-
- m_statisticTriangle += p4.vertices.size() / 3;
- }
- else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
- &p4.vertices[0],
- p4.vertices.size() );
- m_statisticTriangle += p4.vertices.size() - 2;
- }
+ DrawObject(p4);
}
}
}
}
}
+ m_app->StopPerformanceCounter(PCNT_RENDER_OBJECTS);
+
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN);
- if (m_waterMode) m_water->DrawSurf(); // draws water surface
+ if (m_waterMode)
+ {
+ m_app->StartPerformanceCounter(PCNT_RENDER_WATER);
+ m_water->DrawSurf(); // draws water surface
+ m_app->StopPerformanceCounter(PCNT_RENDER_WATER);
+ }
+ m_app->StartPerformanceCounter(PCNT_RENDER_PARTICLE);
m_particle->DrawParticle(SH_WORLD); // draws the particles of the 3D world
+ m_app->StopPerformanceCounter(PCNT_RENDER_PARTICLE);
+
m_lightning->Draw(); // draws lightning
- // TODO: fix white screen error; commenting out temporarily
- // if (m_lensMode) DrawForegroundImage(); // draws the foreground
+ if (m_lensMode) DrawForegroundImage(); // draws the foreground
if (! m_overFront) DrawOverColor(); // draws the foreground color
}
+void CEngine::DrawObject(const EngineBaseObjDataTier& p4)
+{
+ if (p4.staticBufferId != 0)
+ {
+ m_device->DrawStaticBuffer(p4.staticBufferId);
+
+ if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
+ m_statisticTriangle += p4.vertices.size() / 3;
+ else
+ m_statisticTriangle += p4.vertices.size() - 2;
+ }
+ else
+ {
+ if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
+ {
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLES, &p4.vertices[0], p4.vertices.size());
+ m_statisticTriangle += p4.vertices.size() / 3;
+ }
+ else
+ {
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, &p4.vertices[0], p4.vertices.size() );
+ m_statisticTriangle += p4.vertices.size() - 2;
+ }
+ }
+}
+
void CEngine::DrawInterface()
{
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
@@ -3211,9 +3221,11 @@ void CEngine::DrawInterface()
SetState(Gfx::ENG_RSTATE_NORMAL);
// Draw the entire interface
- Ui::CInterface* interface = static_cast<Ui::CInterface*>( m_iMan->SearchInstance(CLASS_INTERFACE) );
+ Ui::CInterface* interface = CRobotMain::GetInstancePointer()->GetInterface();
if (interface != nullptr)
+ {
interface->Draw();
+ }
m_interfaceMode = false;
m_lastState = -1;
@@ -3240,66 +3252,56 @@ void CEngine::DrawInterface()
m_device->SetTransform(TRANSFORM_VIEW, m_matView);
- for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
- EngineObjLevel1& p1 = m_objectTree[l1];
- if (! p1.used) continue;
+ if (! m_objects[objRank].used)
+ continue;
- // Should be loaded by now
- SetTexture(p1.tex1, 0);
- SetTexture(p1.tex2, 1);
+ if (m_shadowVisible && m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
+ continue;
- for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
- {
- EngineObjLevel2& p2 = p1.next[l2];
- if (! p2.used) continue;
+ if (! m_objects[objRank].drawFront)
+ continue;
- int objRank = p2.objRank;
+ m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
- if (m_shadowVisible && m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
- continue;
+ if (! IsVisible(objRank))
+ continue;
- if (! m_objects[objRank].drawFront)
- continue;
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ continue;
- m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
- if (! IsVisible(objRank))
- continue;
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (! p1.used)
+ continue;
- m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
+ m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+
+ SetTexture(p2.tex1, 0);
+ SetTexture(p2.tex2, 1);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- EngineObjLevel3& p3 = p2.next[l3];
- if (! p3.used) continue;
+ EngineBaseObjLODTier& p3 = p2.next[l3];
- if ( m_objects[objRank].distance < p3.min ||
- m_objects[objRank].distance >= p3.max ) continue;
+ if (! IsWithinLODLimit(m_objects[objRank].distance, p3.lodLevel))
+ continue;
for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- EngineObjLevel4& p4 = p3.next[l4];
- if (! p4.used) continue;
+ EngineBaseObjDataTier& p4 = p3.next[l4];
SetMaterial(p4.material);
SetState(p4.state);
- if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
- &p4.vertices[0],
- p4.vertices.size() );
-
- m_statisticTriangle += p4.vertices.size() / 3;
- }
- else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
- {
- m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
- &p4.vertices[0],
- p4.vertices.size() );
- m_statisticTriangle += p4.vertices.size() - 2;
- }
+ DrawObject(p4);
}
}
}
@@ -3328,8 +3330,270 @@ void CEngine::DrawInterface()
void CEngine::UpdateGroundSpotTextures()
{
- // TODO the original code modifying the textures is very complex, so stub for now
- GetLogger()->Trace("CEngine::UpdateGroundSpotTextures(): stub!\n");
+ if (!m_firstGroundSpot &&
+ m_groundMark.drawPos.x == m_groundMark.pos.x &&
+ m_groundMark.drawPos.z == m_groundMark.pos.z &&
+ m_groundMark.drawRadius == m_groundMark.radius &&
+ m_groundMark.drawIntensity == m_groundMark.intensity)
+ return;
+
+ for (int s = 0; s < 16; s++)
+ {
+ Math::Point min, max;
+ min.x = (s%4) * 254.0f - 1.0f; // 1 pixel cover
+ min.y = (s/4) * 254.0f - 1.0f;
+ max.x = min.x + 254.0f + 2.0f;
+ max.y = min.y + 254.0f + 2.0f;
+
+ bool clear = false;
+ bool set = false;
+
+ // Calculate the area to be erased.
+ int dot = static_cast<int>(m_groundMark.drawRadius/2.0f);
+
+ float tu, tv;
+ float cx, cy;
+
+ tu = (m_groundMark.drawPos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.drawPos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if (dot == 0)
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ float px = cx-Math::Mod(cx, 1.0f);
+ float py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if (m_firstGroundSpot ||
+ (m_groundMark.drawRadius != 0.0f &&
+ px+dot >= min.x && py+dot >= min.y &&
+ px-dot <= max.x && py-dot <= max.y))
+ {
+ clear = true;
+ }
+
+ // Calculate the area to draw.
+ dot = static_cast<int>(m_groundMark.radius/2.0f);
+
+ tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx - Math::Mod(cx, 1.0f);
+ py = cy - Math::Mod(cy, 1.0f); // multiple of 1
+
+ if (m_groundMark.draw &&
+ px+dot >= min.x && py+dot >= min.y &&
+ px-dot <= max.x && py-dot <= max.y)
+ {
+ set = true;
+ }
+
+ if (clear || set)
+ {
+ CImage shadowImg(Math::IntPoint(256, 256));
+ shadowImg.Fill(Gfx::IntColor(255, 255, 255, 255));
+
+ // Draw the new shadows.
+ for (int i = 0; i < static_cast<int>( m_groundSpots.size() ); i++)
+ {
+ if (m_groundSpots[i].used == false ||
+ m_groundSpots[i].radius == 0.0f)
+ continue;
+
+ if (m_groundSpots[i].min == 0.0f &&
+ m_groundSpots[i].max == 0.0f)
+ {
+ dot = static_cast<int>(m_groundSpots[i].radius/2.0f);
+
+ tu = (m_groundSpots[i].pos.x+1600.0f)/3200.0f;
+ tv = (m_groundSpots[i].pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f) - 0.5f;
+ cy = (tv*254.0f*4.0f) - 0.5f;
+
+ if (dot == 0)
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if (px+dot < min.x || py+dot < min.y ||
+ px-dot > max.x || py-dot > max.y)
+ continue;
+
+ for (int iy = -dot; iy <= dot; iy++)
+ {
+ for (int ix =- dot; ix <= dot; ix++)
+ {
+ float ppx = px+ix;
+ float ppy = py+iy;
+
+ if (ppx < min.x || ppy < min.y ||
+ ppx >= max.x || ppy >= max.y)
+ continue;
+
+ float intensity;
+ if (dot == 0)
+ intensity = 0.0f;
+ else
+ intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
+
+ Gfx::Color color;
+ color.r = Math::Norm(m_groundSpots[i].color.r+intensity);
+ color.g = Math::Norm(m_groundSpots[i].color.g+intensity);
+ color.b = Math::Norm(m_groundSpots[i].color.b+intensity);
+
+ ppx -= min.x; // on the texture
+ ppy -= min.y;
+
+ shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
+ }
+ }
+ }
+ else
+ {
+ for (int iy = 0; iy < 256; iy++)
+ {
+ for (int ix = 0; ix < 256; ix++)
+ {
+ Math::Vector pos;
+ pos.x = (256.0f * (s%4) + ix) * 3200.0f/1024.0f - 1600.0f;
+ pos.z = (256.0f * (s/4) + iy) * 3200.0f/1024.0f - 1600.0f;
+ pos.y = 0.0f;
+
+ float level = m_terrain->GetFloorLevel(pos, true);
+ if (level < m_groundSpots[i].min ||
+ level > m_groundSpots[i].max)
+ continue;
+
+ float intensity;
+ if (level > (m_groundSpots[i].max+m_groundSpots[i].min)/2.0f)
+ intensity = 1.0f - (m_groundSpots[i].max-level) / m_groundSpots[i].smooth;
+ else
+ intensity = 1.0f - (level-m_groundSpots[i].min) / m_groundSpots[i].smooth;
+
+ if (intensity < 0.0f) intensity = 0.0f;
+
+ Gfx::Color color;
+ color.r = Math::Norm(m_groundSpots[i].color.r+intensity);
+ color.g = Math::Norm(m_groundSpots[i].color.g+intensity);
+ color.b = Math::Norm(m_groundSpots[i].color.b+intensity);
+
+ shadowImg.SetPixel(Math::IntPoint(ix, iy), color);
+ }
+ }
+ }
+ }
+
+ if (set)
+ {
+ dot = static_cast<int>(m_groundMark.radius/2.0f);
+
+ tu = (m_groundMark.pos.x + 1600.0f) / 3200.0f;
+ tv = (m_groundMark.pos.z + 1600.0f) / 3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if (dot == 0)
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ for (int iy = -dot; iy <= dot; iy++)
+ {
+ for (int ix = -dot; ix <= dot; ix++)
+ {
+ float ppx = px+ix;
+ float ppy = py+iy;
+
+ if (ppx < min.x || ppy < min.y ||
+ ppx >= max.x || ppy >= max.y)
+ continue;
+
+ ppx -= min.x; // on the texture
+ ppy -= min.y;
+
+ float intensity = 1.0f - Math::Point(ix, iy).Length() / dot;
+ if (intensity <= 0.0f)
+ continue;
+
+ intensity *= m_groundMark.intensity;
+
+ int j = (ix+dot) + (iy+dot) * m_groundMark.dx;
+ if (m_groundMark.table[j] == 1) // green ?
+ {
+ Gfx::Color color;
+ color.r = Math::Norm(1.0f-intensity);
+ color.g = 1.0f;
+ color.b = Math::Norm(1.0f-intensity);
+ shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
+ }
+ if (m_groundMark.table[j] == 2) // red ?
+ {
+ Gfx::Color color;
+ color.r = 1.0f;
+ color.g = Math::Norm(1.0f-intensity);
+ color.b = Math::Norm(1.0f-intensity);
+ shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
+ }
+ }
+ }
+ }
+
+ std::stringstream str;
+ str << "shadow" << std::setfill('0') << std::setw(2) << s << ".png";
+ std::string texName = str.str();
+
+ DeleteTexture(texName);
+
+ Gfx::Texture tex = m_device->CreateTexture(&shadowImg, m_defaultTexParams);
+
+ m_texNameMap[texName] = tex;
+ m_revTexNameMap[tex] = texName;
+ }
+ }
+
+ for (int i = 0; i < static_cast<int>( m_groundSpots.size() ); i++)
+ {
+ if (m_groundSpots[i].used == false ||
+ m_groundSpots[i].radius == 0.0f)
+ {
+ m_groundSpots[i].drawRadius = 0.0f;
+ }
+ else
+ {
+ m_groundSpots[i].drawPos = m_groundSpots[i].pos;
+ m_groundSpots[i].drawRadius = m_groundSpots[i].radius;
+ }
+ }
+
+ m_groundMark.drawPos = m_groundMark.pos;
+ m_groundMark.drawRadius = m_groundMark.radius;
+ m_groundMark.drawIntensity = m_groundMark.intensity;
+
+ m_firstGroundSpot = false;
}
void CEngine::DrawShadow()
@@ -3366,11 +3630,13 @@ void CEngine::DrawShadow()
float lastIntensity = -1.0f;
for (int i = 0; i < static_cast<int>( m_shadows.size() ); i++)
{
- if (m_shadows[i].hide) continue;
+ if (m_shadows[i].hide)
+ continue;
Math::Vector pos = m_shadows[i].pos; // pos = center of the shadow on the ground
- if (m_eyePt.y == pos.y) continue; // camera at the same level?
+ if (m_eyePt.y == pos.y)
+ continue; // camera at the same level?
float d = 0.0f;
float D = 0.0f;
@@ -3386,7 +3652,9 @@ void CEngine::DrawShadow()
if ( h > 4.0f ) h = 4.0f;
D = Math::Distance(m_eyePt, pos);
- if ( D >= endDeepView ) continue;
+ if (D >= endDeepView)
+ continue;
+
d = D*h/height;
pos.x += (m_eyePt.x-pos.x)*d/D;
@@ -3402,7 +3670,9 @@ void CEngine::DrawShadow()
if ( h > 4.0f ) h = 4.0f;
D = Math::Distance(m_eyePt, pos);
- if ( D >= endDeepView ) continue;
+ if (D >= endDeepView)
+ continue;
+
d = D*h/height;
pos.x += (m_eyePt.x-pos.x)*d/D;
@@ -3510,7 +3780,8 @@ void CEngine::DrawShadow()
if ( D > startDeepView )
intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView);
- if (intensity == 0.0f) continue;
+ if (intensity == 0.0f)
+ continue;
if (lastIntensity != intensity) // intensity changed?
{
@@ -3526,7 +3797,6 @@ void CEngine::DrawShadow()
m_device->SetRenderState(RENDER_STATE_LIGHTING, true);
}
-// STATUS: TESTED, VERIFIED
void CEngine::DrawBackground()
{
if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ?
@@ -3546,7 +3816,6 @@ void CEngine::DrawBackground()
}
}
-// STATUS: TESTED
void CEngine::DrawBackgroundGradient(const Color& up, const Color& down)
{
Math::Point p1(0.0f, 0.5f);
@@ -3577,7 +3846,6 @@ void CEngine::DrawBackgroundGradient(const Color& up, const Color& down)
AddStatisticTriangle(2);
}
-// Status: TESTED, VERIFIED
void CEngine::DrawBackgroundImage()
{
Math::Point p1, p2;
@@ -3586,7 +3854,7 @@ void CEngine::DrawBackgroundImage()
p2.x = 1.0f;
p2.y = 1.0f;
-Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+ Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
float u1, u2, v1, v2;
if (m_backgroundFull)
@@ -3635,7 +3903,8 @@ Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
void CEngine::DrawPlanet()
{
- if (! m_planet->PlanetExist()) return;
+ if (! m_planet->PlanetExist())
+ return;
m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false);
m_device->SetRenderState(RENDER_STATE_LIGHTING, false);
@@ -3648,10 +3917,10 @@ void CEngine::DrawPlanet()
m_planet->Draw(); // draws the planets
}
-// Status: PART_TESTED
void CEngine::DrawForegroundImage()
{
- if (m_foregroundName.empty()) return;
+ if (m_foregroundName.empty())
+ return;
Math::Vector n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
@@ -3684,12 +3953,11 @@ void CEngine::DrawForegroundImage()
AddStatisticTriangle(2);
}
-// Status: PART_TESTED
void CEngine::DrawOverColor()
{
- // TODO: fuzzy compare?
- if ( (m_overColor == Color(0.0f, 0.0f, 0.0f, 0.0f) && m_overMode == ENG_RSTATE_TCOLOR_BLACK) ||
- (m_overColor == Color(1.0f, 1.0f, 1.0f, 1.0f) && m_overMode == ENG_RSTATE_TCOLOR_WHITE) ) return;
+ if ((m_overColor == Color(0.0f, 0.0f, 0.0f, 0.0f) && m_overMode == ENG_RSTATE_TCOLOR_BLACK) ||
+ (m_overColor == Color(1.0f, 1.0f, 1.0f, 1.0f) && m_overMode == ENG_RSTATE_TCOLOR_WHITE))
+ return;
Math::Point p1(0.0f, 0.0f);
Math::Point p2(1.0f, 1.0f);
@@ -3703,11 +3971,6 @@ void CEngine::DrawOverColor()
SetState(m_overMode);
- // TODO: set also with m_overMode ?
- m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false);
- m_device->SetRenderState(RENDER_STATE_LIGHTING, false);
- m_device->SetRenderState(RENDER_STATE_FOG, false);
-
m_device->SetTransform(TRANSFORM_VIEW, m_matViewInterface);
m_device->SetTransform(TRANSFORM_PROJECTION, m_matProjInterface);
m_device->SetTransform(TRANSFORM_WORLD, m_matWorldInterface);
@@ -3724,7 +3987,6 @@ void CEngine::DrawOverColor()
AddStatisticTriangle(2);
}
-// Status: TESTED, VERIFIED
void CEngine::DrawHighlight()
{
Math::Point min, max;
@@ -3816,7 +4078,6 @@ void CEngine::DrawHighlight()
m_device->DrawPrimitive(PRIMITIVE_LINE_STRIP, line, 3);
}
-// Status: TESTED, VERIFIED
void CEngine::DrawMouse()
{
MouseMode mode = m_app->GetMouseMode();
@@ -3850,7 +4111,6 @@ void CEngine::DrawMouse()
DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2);
}
-// Status: TESTED, VERIFIED
void CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon)
{
if (icon == -1)
@@ -3889,15 +4149,10 @@ void CEngine::DrawStats()
if (!m_showStats)
return;
- std::stringstream str;
- str << "Triangles: ";
- str << m_statisticTriangle;
- std::string triangleText = str.str();
-
float height = m_text->GetAscent(FONT_COLOBOT, 12.0f);
float width = 0.2f;
- Math::Point pos(0.04f, 0.04f + height);
+ Math::Point pos(0.04f, 0.04f + 17 * height);
SetState(ENG_RSTATE_OPAQUE_COLOR);
@@ -3905,9 +4160,9 @@ void CEngine::DrawStats()
VertexCol vertex[4] =
{
- VertexCol(Math::Vector(pos.x , pos.y - height, 0.0f), black),
+ VertexCol(Math::Vector(pos.x , pos.y - 17 * height, 0.0f), black),
VertexCol(Math::Vector(pos.x , pos.y + height, 0.0f), black),
- VertexCol(Math::Vector(pos.x + width, pos.y - height, 0.0f), black),
+ VertexCol(Math::Vector(pos.x + width, pos.y - 17 * height, 0.0f), black),
VertexCol(Math::Vector(pos.x + width, pos.y + height, 0.0f), black)
};
@@ -3915,7 +4170,107 @@ void CEngine::DrawStats()
SetState(ENG_RSTATE_TEXT);
- m_text->DrawText(triangleText, FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+ std::stringstream str;
+
+ str.str("");
+ str << "Event processing: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_EVENT_PROCESSING);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+ pos.y -= height;
+
+
+ str.str("");
+ str << "Frame update: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_UPDATE_ALL);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Engine update: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_UPDATE_ENGINE);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Particle update: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_UPDATE_PARTICLE);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Game update: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_UPDATE_GAME);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ float otherUpdate = Math::Max(0.0f, m_app->GetPerformanceCounterData(PCNT_UPDATE_ALL) -
+ m_app->GetPerformanceCounterData(PCNT_UPDATE_ENGINE) -
+ m_app->GetPerformanceCounterData(PCNT_UPDATE_PARTICLE) -
+ m_app->GetPerformanceCounterData(PCNT_UPDATE_GAME));
+
+ str.str("");
+ str << "Other update: " << std::fixed << std::setprecision(2) << otherUpdate;
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+ pos.y -= height;
+
+
+ str.str("");
+ str << "Frame render: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_RENDER_ALL);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Particle render: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_RENDER_PARTICLE);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Water render: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_RENDER_WATER);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Terrain render: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_RENDER_TERRAIN);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "Objects render: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_RENDER_OBJECTS);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ str.str("");
+ str << "UI render: " << std::fixed << std::setprecision(2) << m_app->GetPerformanceCounterData(PCNT_RENDER_INTERFACE);
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+
+ float otherRender = m_app->GetPerformanceCounterData(PCNT_RENDER_ALL) -
+ m_app->GetPerformanceCounterData(PCNT_RENDER_PARTICLE) -
+ m_app->GetPerformanceCounterData(PCNT_RENDER_WATER) -
+ m_app->GetPerformanceCounterData(PCNT_RENDER_TERRAIN) -
+ m_app->GetPerformanceCounterData(PCNT_RENDER_OBJECTS) -
+ m_app->GetPerformanceCounterData(PCNT_RENDER_INTERFACE);
+
+ str.str("");
+ str << "Other render: " << std::fixed << std::setprecision(2) << otherRender;
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+ pos.y -= height;
+ pos.y -= height;
+
+
+ str.str("");
+ str << "Triangles: " << m_statisticTriangle;
+ m_text->DrawText(str.str(), FONT_COLOBOT, 12.0f, pos, 1.0f, TEXT_ALIGN_LEFT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f));
pos.y -= height;
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 27f0173..f9dfd45 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -26,12 +26,15 @@
#include "app/system.h"
#include "common/event.h"
+#include "common/singleton.h"
#include "graphics/core/color.h"
#include "graphics/core/material.h"
#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"
@@ -45,7 +48,6 @@
class CApplication;
-class CInstanceManager;
class CObject;
class CSoundInterface;
class CImage;
@@ -151,7 +153,7 @@ struct EngineTriangle
//! 2nd texture
std::string tex2Name;
- EngineTriangle()
+ inline EngineTriangle()
{
state = ENG_RSTATE_NORMAL;
}
@@ -178,6 +180,91 @@ enum EngineObjectType
ENG_OBJTYPE_METAL = 6
};
+
+/**
+ * \struct EngineBaseObjDataTier
+ * \brief Tier 4 of object tree (data)
+ */
+struct EngineBaseObjDataTier
+{
+ EngineTriangleType type;
+ Material material;
+ int state;
+ std::vector<VertexTex2> vertices;
+ unsigned int staticBufferId;
+ bool updateStaticBuffer;
+
+ inline EngineBaseObjDataTier(EngineTriangleType type = ENG_TRIANGLE_TYPE_TRIANGLES,
+ const Material& material = Material(),
+ int state = ENG_RSTATE_NORMAL)
+ : type(type), material(material), state(state), staticBufferId(0), updateStaticBuffer(false) {}
+};
+
+/**
+ * \struct EngineBaseObjLODTier
+ * \brief Tier 3 of base object tree (LOD)
+ */
+struct EngineBaseObjLODTier
+{
+ LODLevel lodLevel;
+ std::vector<EngineBaseObjDataTier> next;
+
+ inline EngineBaseObjLODTier(LODLevel lodLevel = LOD_Constant)
+ : lodLevel(lodLevel) {}
+};
+
+/**
+ * \struct EngineBaseObjTexTier
+ * \brief Tier 2 of base object tree (textures)
+ */
+struct EngineBaseObjTexTier
+{
+ std::string tex1Name;
+ Texture tex1;
+ std::string tex2Name;
+ Texture tex2;
+ std::vector<EngineBaseObjLODTier> next;
+
+ inline EngineBaseObjTexTier(const std::string& tex1Name = "", const std::string& tex2Name = "")
+ : tex1Name(tex1Name), tex2Name(tex2Name) {}
+};
+
+/**
+ * \struct BaseEngineObject
+ * \brief Base (template) object - geometry for engine objects
+ *
+ * This is also the tier 1 of base object tree.
+ */
+struct EngineBaseObject
+{
+ //! If true, base object is valid in objects vector
+ bool used;
+ //! Number of triangles
+ int totalTriangles;
+ //! Bounding box min (origin 0,0,0 always included)
+ Math::Vector bboxMin;
+ //! bounding box max (origin 0,0,0 always included)
+ Math::Vector bboxMax;
+ //! Radius of the sphere at the origin
+ float radius;
+ //! Next tier (LOD)
+ std::vector<EngineBaseObjTexTier> next;
+
+ inline EngineBaseObject()
+ {
+ LoadDefault();
+ }
+
+ inline void LoadDefault()
+ {
+ used = false;
+ totalTriangles = 0;
+ bboxMax.LoadZero();
+ bboxMin.LoadZero();
+ radius = 0.0f;
+ }
+};
+
/**
* \struct EngineObject
* \brief Object drawn by the graphics engine
@@ -186,33 +273,27 @@ struct EngineObject
{
//! If true, object is valid in objects vector
bool used;
+ //! Rank of associated base engine object
+ int baseObjRank;
//! If true, the object is drawn
bool visible;
//! If true, object is behind the 2D interface
bool drawWorld;
//! If true, the shape is before the 2D interface
bool drawFront;
- //! Number of triangles
- int totalTriangles;
//! Type of object
- EngineObjectType type;
+ EngineObjectType type;
//! Transformation matrix
Math::Matrix transform;
//! Distance to object from eye point
float distance;
- //! Bounding box min (origin 0,0,0 always included)
- Math::Vector bboxMin;
- //! bounding box max (origin 0,0,0 always included)
- Math::Vector bboxMax;
- //! Radius of the sphere at the origin
- float radius;
//! Rank of the associated shadow
int shadowRank;
//! Transparency of the object [0, 1]
float transparency;
//! Calls LoadDefault()
- EngineObject()
+ inline EngineObject()
{
LoadDefault();
}
@@ -221,88 +302,18 @@ struct EngineObject
inline void LoadDefault()
{
used = false;
+ baseObjRank = -1;
visible = false;
drawWorld = false;
drawFront = false;
- totalTriangles = 0;
type = ENG_OBJTYPE_NULL;
transform.LoadIdentity();
- bboxMax.LoadZero();
- bboxMin.LoadZero();
distance = 0.0f;
- radius = 0.0f;
shadowRank = -1;
transparency = 0.0f;
}
};
-struct EngineObjLevel1;
-struct EngineObjLevel2;
-struct EngineObjLevel3;
-struct EngineObjLevel4;
-
-/**
- * \struct EngineObjLevel4
- * \brief Tier 4 of object tree
- */
-struct EngineObjLevel4
-{
- bool used;
- EngineTriangleType type;
- Material material;
- int state;
- std::vector<VertexTex2> vertices;
-
- EngineObjLevel4(bool used = false,
- EngineTriangleType type = ENG_TRIANGLE_TYPE_TRIANGLES,
- const Material& material = Material(),
- int state = ENG_RSTATE_NORMAL);
-};
-
-/**
- * \struct EngineObjLevel3
- * \brief Tier 3 of object tree
- */
-struct EngineObjLevel3
-{
- bool used;
- float min;
- float max;
- std::vector<EngineObjLevel4> next;
-
- EngineObjLevel3(bool used = false, float min = 0.0f, float max = 0.0f);
-};
-
-/**
- * \struct EngineObjLevel2
- * \brief Tier 2 of object tree
- */
-struct EngineObjLevel2
-{
- bool used;
- int objRank;
- std::vector<EngineObjLevel3> next;
-
- EngineObjLevel2(bool used = false, int objRank = -1);
-};
-
-/**
- * \struct EngineObjLevel1
- * \brief Tier 1 of object tree
- */
-struct EngineObjLevel1
-{
- bool used;
- std::string tex1Name;
- Texture tex1;
- std::string tex2Name;
- Texture tex2;
- std::vector<EngineObjLevel2> next;
-
- EngineObjLevel1(bool used = false, const std::string& tex1Name = "",
- const std::string& tex2Name = "");
-};
-
/**
* \struct EngineShadowType
* \brief Type of shadow drawn by the graphics engine
@@ -342,12 +353,12 @@ struct EngineShadow
//! Height from the ground
float height;
- EngineShadow()
+ inline EngineShadow()
{
LoadDefault();
}
- void LoadDefault()
+ inline void LoadDefault()
{
used = false;
hide = false;
@@ -384,12 +395,12 @@ struct EngineGroundSpot
//! Radius of the shadow drawn
float drawRadius;
- EngineGroundSpot()
+ inline EngineGroundSpot()
{
LoadDefault();
}
- void LoadDefault()
+ inline void LoadDefault()
{
used = false;
color = Color();
@@ -448,12 +459,12 @@ struct EngineGroundMark
//! Pointer to the table
char* table;
- EngineGroundMark()
+ inline EngineGroundMark()
{
LoadDefault();
}
- void LoadDefault()
+ inline void LoadDefault()
{
draw = false;
phase = ENG_GR_MARK_PHASE_NULL;
@@ -545,10 +556,10 @@ struct EngineMouse
//! Hot point
Math::Point hotPoint;
- EngineMouse(int icon1 = -1, int icon2 = -1, int iconShadow = -1,
- EngineRenderState mode1 = ENG_RSTATE_NORMAL,
- EngineRenderState mode2 = ENG_RSTATE_NORMAL,
- Math::Point hotPoint = Math::Point())
+ inline EngineMouse(int icon1 = -1, int icon2 = -1, int iconShadow = -1,
+ EngineRenderState mode1 = ENG_RSTATE_NORMAL,
+ EngineRenderState mode2 = ENG_RSTATE_NORMAL,
+ Math::Point hotPoint = Math::Point())
{
this->icon1 = icon1;
this->icon2 = icon2;
@@ -609,27 +620,36 @@ struct EngineMouse
*
* Objects are uniquely identified by object rank obtained at object creation. Creating an
* object equals to allocating space for EngineObject structure which holds object parameters.
- * Object's geometric data is stored in a separate structure - a 4-tier tree which splits
- * the information of each geometric triangle.
+ *
+ * Object's geometric data is stored as a separate object -- base engine object. Each object
+ * must reference a valid base engine object or an empty base engine object (with rank = -1).
+ * This many-to-one association allows to share same geometric data (e.g. from same model)
+ * across objects.
+ *
+ * Base engine object data is stored in a 4-tier tree which splits the data describing triangles.
*
* The 4 tiers contain the following information:
- * - level 1 (EngineObjLevel1) - two textures (names and structs) applied to triangles,
- * - level 2 (EngineObjLevel2) - object rank
- * - level 3 (EngineObjLevel3) - minumum and maximum LOD (=level of detail)
- * - level 4 (EngineObjLevel4) - type of object*, material, render state and the actual triangle data
+ * - level 1 (EngineBaseObject) - geometric statistics
+ * - level 2 (EngineBaseObjTexTier) - two textures (names and structs) applied to triangles,
+ * - level 3 (EngineBaseObjLODTier) - minumum and maximum LOD (=level of detail)
+ * - level 4 (EngineBaseObjDataTier) - type of object*, material, render state and the actual vertex data
*
- * NOTE: type of object in this context means only the internal type in 3D engine. It is not related
+ * *NOTE: type of object in this context means only the internal type in 3D engine. It is not related
* to CObject types.
*
+ * Last tier containing vertex data contains also an ID of static buffer holding the data.
+ * The static buffer is created and updated with new data as needed.
+ *
* Such tiered structure complicates loops over all object data, but saves a lot of memory and
- * optimizes the rendering process (for instance, switching of textures is an expensive operation).
+ * optimizes the rendering process.
*
* \section Shadows Shadows
*
* Each engine object can be associated with a shadow (EngineShadow). Like objects, shadows are
* identified by their rank obtained upon creation.
*
- * ...
+ * Shadows are drawn as circular spots on the ground, except for shadows for worms, which have
+ * special mode for them.
*
* \section RenderStates Render States
*
@@ -651,22 +671,36 @@ struct EngineMouse
* which is what OpenGL actually wants. The old method is kept for now, with mapping between texture names
* and texture structs but it will also be subject to refactoring in the future.
*/
-class CEngine
+class CEngine : public CSingleton<CEngine>
{
public:
- CEngine(CInstanceManager* iMan, CApplication* app);
+ CEngine(CApplication* app);
~CEngine();
//! Sets the device to be used
void SetDevice(CDevice* device);
//! Returns the current device
- CDevice* GetDevice();
-
- //! Sets the terrain object
- void SetTerrain(CTerrain* terrain);
+ CDevice* GetDevice();
//! Returns the text rendering engine
CText* GetText();
+ //! Returns the light manager
+ CLightManager* GetLightManager();
+ //! Returns the particle manager
+ CParticle* GetParticle();
+ //! Returns the terrain manager
+ CTerrain* GetTerrain();
+ //! Returns the water manager
+ CWater* GetWater();
+ //! Returns the lighting manager
+ CLightning* GetLightning();
+ //! Returns the planet manager
+ CPlanet* GetPlanet();
+ //! Returns the fog manager
+ CCloud* GetCloud();
+
+ //! Sets the terrain object
+ void SetTerrain(CTerrain* terrain);
//! Performs the initialization; must be called after device was set
@@ -692,16 +726,10 @@ public:
//! Writes a screenshot containing the current frame
bool WriteScreenShot(const std::string& fileName, int width, int height);
-
- //! Reads settings from INI
- bool ReadSettings();
- //! Writes settings to INI
- bool WriteSettings();
-
//@{
//! Management of game pause mode
void SetPause(bool pause);
- bool GetPause();
+ TEST_VIRTUAL bool GetPause();
//@}
//@{
@@ -721,8 +749,6 @@ public:
//! Returns current size of viewport window
Math::IntPoint GetWindowSize();
- //! Returns the last size of viewport window
- Math::IntPoint GetLastWindowSize();
//@{
//! Conversion functions between window and interface coordinates
@@ -747,81 +773,93 @@ public:
/* *************** Object management *************** */
+ // Base objects
+
+ //! Creates a base object and returns its rank
+ int CreateBaseObject();
+ //! Deletes a base object
+ void DeleteBaseObject(int baseObjRank);
+ //! Deletes all base objects
+ void DeleteAllBaseObjects();
+
+ //! Copies geometry between two base objects
+ void CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank);
+
+ //! Adds triangles to given object with the specified params
+ void AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>& vertices,
+ EngineTriangleType triangleType,
+ const Material& material, int state,
+ std::string tex1Name, std::string tex2Name,
+ LODLevel lodLevel, bool globalUpdate);
+
+ //! Adds a tier 4 engine object directly
+ void AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buffer,
+ std::string tex1Name, std::string tex2Name,
+ LODLevel lodLevel, bool globalUpdate);
+
+ // Objects
+
//! Creates a new object and returns its rank
int CreateObject();
//! Deletes all objects, shadows and ground spots
- void FlushObject();
+ void DeleteAllObjects();
//! Deletes the given object
- bool DeleteObject(int objRank);
+ void DeleteObject(int objRank);
+
+ //@{
+ //! Management of the base object rank for engine object
+ void SetObjectBaseRank(int objRank, int baseObjRank);
+ int GetObjectBaseRank(int objRank);
+ //@}
//@{
//! Management of engine object type
- bool SetObjectType(int objRank, EngineObjectType type);
+ void SetObjectType(int objRank, EngineObjectType type);
EngineObjectType GetObjectType(int objRank);
//@}
//@{
//! Management of object transform
- bool SetObjectTransform(int objRank, const Math::Matrix& transform);
- bool GetObjectTransform(int objRank, Math::Matrix& transform);
+ void SetObjectTransform(int objRank, const Math::Matrix& transform);
+ void GetObjectTransform(int objRank, Math::Matrix& transform);
//@}
//! Sets drawWorld for given object
- bool SetObjectDrawWorld(int objRank, bool draw);
+ void SetObjectDrawWorld(int objRank, bool draw);
//! Sets drawFront for given object
- bool SetObjectDrawFront(int objRank, bool draw);
+ void SetObjectDrawFront(int objRank, bool draw);
//! Sets the transparency level for given object
- bool SetObjectTransparency(int objRank, float value);
+ void SetObjectTransparency(int objRank, float value);
//! Returns the bounding box for an object
- bool GetObjectBBox(int objRank, Math::Vector& min, Math::Vector& max);
+ void GetObjectBBox(int objRank, Math::Vector& min, Math::Vector& max);
//! Returns the total number of triangles of given object
int GetObjectTotalTriangles(int objRank);
- //! Adds triangles to given object with the specified params
- bool AddTriangles(int objRank, const std::vector<VertexTex2>& vertices,
- const Material& material, int state,
- std::string tex1Name, std::string tex2Name,
- float min, float max, bool globalUpdate);
-
- //! Adds a surface to given object with the specified params
- bool AddSurface(int objRank, const std::vector<VertexTex2>& vertices,
- const Material& material, int state,
- std::string tex1Name, std::string tex2Name,
- float min, float max, bool globalUpdate);
-
- //! Adds a tier 4 engine object directly
- bool AddQuick(int objRank, const EngineObjLevel4& buffer,
- std::string tex1Name, std::string tex2Name,
- float min, float max, bool globalUpdate);
-
//! Returns the first found tier 4 engine object for the given params or nullptr if not found
- EngineObjLevel4* FindTriangles(int objRank, const Material& material,
- int state, std::string tex1Name, std::string tex2Name,
- float min, float max);
+ EngineBaseObjDataTier* FindTriangles(int objRank, const Material& material,
+ 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<EngineTriangle>& triangles);
- //! Updates LOD after parameter or resolution change
- void ChangeLOD();
-
//! Changes the 2nd texure for given object
- bool ChangeSecondTexture(int objRank, const std::string& tex2Name);
+ void ChangeSecondTexture(int objRank, const std::string& tex2Name);
//! Changes (recalculates) texture mapping for given object
- bool ChangeTextureMapping(int objRank, const Material& mat, int state,
+ 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
- bool TrackTextureMapping(int objRank, const Material& mat, int state,
+ 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
@@ -829,20 +867,20 @@ public:
int DetectObject(Math::Point mouse);
//! Creates a shadow for the given object
- bool CreateShadow(int objRank);
+ void CreateShadow(int objRank);
//! Deletes the shadow for given object
void DeleteShadow(int objRank);
//@{
//! Management of different shadow params
- bool SetObjectShadowHide(int objRank, bool hide);
- bool SetObjectShadowType(int objRank, EngineShadowType type);
- bool SetObjectShadowPos(int objRank, const Math::Vector& pos);
- bool SetObjectShadowNormal(int objRank, const Math::Vector& normal);
- bool SetObjectShadowAngle(int objRank, float angle);
- bool SetObjectShadowRadius(int objRank, float radius);
- bool SetObjectShadowIntensity(int objRank, float intensity);
- bool SetObjectShadowHeight(int objRank, float height);
+ void SetObjectShadowHide(int objRank, bool hide);
+ void SetObjectShadowType(int objRank, EngineShadowType type);
+ void SetObjectShadowPos(int objRank, const Math::Vector& pos);
+ void SetObjectShadowNormal(int objRank, const Math::Vector& normal);
+ void SetObjectShadowAngle(int objRank, float angle);
+ void SetObjectShadowRadius(int objRank, float radius);
+ void SetObjectShadowIntensity(int objRank, float intensity);
+ void SetObjectShadowHeight(int objRank, float height);
float GetObjectShadowRadius(int objRank);
//@}
@@ -852,7 +890,7 @@ public:
bool GetHighlight(Math::Point& p1, Math::Point& p2);
//! Deletes all ground spots
- void FlushGroundSpot();
+ void DeleteAllGroundSpots();
//! Creates a new ground spot and returns its rank
int CreateGroundSpot();
//! Deletes the given ground spot
@@ -860,11 +898,11 @@ public:
//@{
//! Management of different ground spot params
- bool SetObjectGroundSpotPos(int rank, const Math::Vector& pos);
- bool SetObjectGroundSpotRadius(int rank, float radius);
- bool SetObjectGroundSpotColor(int rank, const Color& color);
- bool SetObjectGroundSpotMinMax(int rank, float min, float max);
- bool SetObjectGroundSpotSmooth(int rank, float smooth);
+ void SetObjectGroundSpotPos(int rank, const Math::Vector& pos);
+ void SetObjectGroundSpotRadius(int rank, float radius);
+ void SetObjectGroundSpotColor(int rank, const Color& color);
+ void SetObjectGroundSpotMinMax(int rank, float min, float max);
+ void SetObjectGroundSpotSmooth(int rank, float smooth);
//@}
//! Creates the ground mark with the given params
@@ -919,12 +957,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);
@@ -1138,9 +1170,9 @@ public:
//! Returns the view matrix
const Math::Matrix& GetMatView();
//! Returns the camera center point
- Math::Vector GetEyePt();
+ TEST_VIRTUAL Math::Vector GetEyePt();
//! Returns the camera target point
- Math::Vector GetLookatPt();
+ TEST_VIRTUAL Math::Vector GetLookatPt();
//! Returns the horizontal direction angle of view
float GetEyeDirH();
//! Returns the vertical direction angle of view
@@ -1157,6 +1189,8 @@ public:
protected:
//! Prepares the interface for 3D scene
void Draw3DScene();
+ //! Draw 3D object
+ void DrawObject(const EngineBaseObjDataTier& p4);
//! Draws the user interface over the scene
void DrawInterface();
@@ -1186,15 +1220,13 @@ protected:
//! Draw statistic texts
void DrawStats();
- //! Creates new tier 1 object
- EngineObjLevel1& AddLevel1(const std::string& tex1Name, const std::string& tex2Name);
- //! Creates a new tier 2 object
- EngineObjLevel2& AddLevel2(EngineObjLevel1 &p1, int objRank);
- //! Creates a new tier 3 object
- EngineObjLevel3& AddLevel3(EngineObjLevel2 &p2, float min, float max);
- //! Creates a new tier 4 object
- EngineObjLevel4& AddLevel4(EngineObjLevel3 &p3, EngineTriangleType type,
- const Material& mat, int state);
+ //! 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, LODLevel lodLevel);
+ //! Creates a new tier 4 object (data)
+ EngineBaseObjDataTier& AddLevel4(EngineBaseObjLODTier &p3, EngineTriangleType type,
+ const Material& mat, int state);
//! Create texture and add it to cache
Texture CreateTexture(const std::string &texName, const TextureCreateParams &params, CImage* image = nullptr);
@@ -1202,6 +1234,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);
@@ -1221,8 +1256,13 @@ protected:
//! Updates geometric parameters of objects (bounding box and radius)
void UpdateGeometry();
+ //! Updates a given static buffer
+ void UpdateStaticBuffer(EngineBaseObjDataTier& p4);
+
+ //! Updates static buffers of changed objects
+ void UpdateStaticBuffers();
+
protected:
- CInstanceManager* m_iMan;
CApplication* m_app;
CSoundInterface* m_sound;
CDevice* m_device;
@@ -1270,11 +1310,9 @@ protected:
//! Current size of viewport window
Math::IntPoint m_size;
- //! Previous size of viewport window
- Math::IntPoint m_lastSize;
- //! Root of tree object structure (level 1 list)
- std::vector<EngineObjLevel1> m_objectTree;
+ //! Base objects (also level 1 tier list)
+ std::vector<EngineBaseObject> m_baseObjects;
//! Object parameters
std::vector<EngineObject> m_objects;
//! Shadow list
@@ -1299,6 +1337,7 @@ protected:
Color m_waterAddColor;
int m_statisticTriangle;
bool m_updateGeometry;
+ bool m_updateStaticBuffers;
int m_alphaMode;
bool m_groundSpotVisible;
bool m_shadowVisible;
@@ -1321,12 +1360,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/lightman.cpp b/src/graphics/engine/lightman.cpp
index 3055f08..16c84ea 100644
--- a/src/graphics/engine/lightman.cpp
+++ b/src/graphics/engine/lightman.cpp
@@ -19,7 +19,6 @@
#include "graphics/engine/lightman.h"
#include "common/logger.h"
-#include "common/iman.h"
#include "graphics/core/device.h"
@@ -27,6 +26,7 @@
#include <cmath>
+#include <algorithm>
// Graphics module namespace
@@ -78,11 +78,8 @@ DynamicLight::DynamicLight()
-CLightManager::CLightManager(CInstanceManager* iMan, CEngine* engine)
+CLightManager::CLightManager(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_LIGHT, this);
-
m_device = nullptr;
m_engine = engine;
@@ -91,9 +88,6 @@ CLightManager::CLightManager(CInstanceManager* iMan, CEngine* engine)
CLightManager::~CLightManager()
{
- m_iMan->DeleteInstance(CLASS_LIGHT, this);
-
- m_iMan = nullptr;
m_device = nullptr;
m_engine = nullptr;
}
@@ -132,6 +126,7 @@ int CLightManager::CreateLight(LightPriority priority)
m_dynLights[index].light.type = LIGHT_DIRECTIONAL;
m_dynLights[index].light.diffuse = Color(0.5f, 0.5f, 0.5f);
+ m_dynLights[index].light.ambient = Color(0.0f, 0.0f, 0.0f);
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);
@@ -393,68 +388,35 @@ 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 (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);
+ std::vector<DynamicLight> sortedLights = m_dynLights;
+ LightsComparator lightsComparator(m_engine->GetEyePt(), type);
+ std::sort(sortedLights.begin(), sortedLights.end(), lightsComparator);
- if (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++)
+ int lightMapIndex = 0;
+ for (int i = 0; i < static_cast<int>( sortedLights.size() ); i++)
{
- if (! m_dynLights[i].used)
- continue;
- if (! m_dynLights[i].enabled)
+ if (! sortedLights[i].used)
continue;
- if (m_dynLights[i].intensity.current == 0.0f)
+ if (! sortedLights[i].enabled)
continue;
- if (m_dynLights[i].priority == LIGHT_PRI_HIGH)
+ if (sortedLights[i].intensity.current == 0.0f)
continue;
bool enabled = true;
- if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL)
- enabled = (m_dynLights[i].includeType == type);
+ if (sortedLights[i].includeType != ENG_OBJTYPE_NULL)
+ enabled = (sortedLights[i].includeType == type);
- if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL)
- enabled = (m_dynLights[i].excludeType != type);
+ if (sortedLights[i].excludeType != ENG_OBJTYPE_NULL)
+ enabled = (sortedLights[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;
- }
- }
+ m_lightMap[lightMapIndex] = i;
+ ++lightMapIndex;
}
+
+ if (lightMapIndex >= static_cast<int>( m_lightMap.size() ))
+ break;
}
for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i)
@@ -462,7 +424,8 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
int rank = m_lightMap[i];
if (rank != -1)
{
- m_device->SetLight(i, m_dynLights[rank].light);
+ sortedLights[rank].light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
+ m_device->SetLight(i, sortedLights[rank].light);
m_device->SetLightEnabled(i, true);
}
else
@@ -472,5 +435,33 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
}
}
+// -----------
+
+CLightManager::LightsComparator::LightsComparator(Math::Vector eyePos, EngineObjectType objectType)
+{
+ m_eyePos = eyePos;
+ m_objectType = objectType;
+}
+
+float CLightManager::LightsComparator::GetLightWeight(const DynamicLight& dynLight)
+{
+ bool enabled = true;
+ if (!dynLight.used || !dynLight.enabled || dynLight.intensity.current == 0.0f)
+ enabled = false;
+ else if (dynLight.includeType != ENG_OBJTYPE_NULL)
+ enabled = dynLight.includeType == m_objectType;
+ else if (dynLight.excludeType != ENG_OBJTYPE_NULL)
+ enabled = dynLight.excludeType != m_objectType;
+
+ return enabled ? ( (dynLight.light.position - m_eyePos).Length() * dynLight.priority ) : 10000.0f;
+}
+
+bool CLightManager::LightsComparator::operator()(const DynamicLight& left, const DynamicLight& right)
+{
+ float leftWeight = GetLightWeight(left);
+ float rightWeight = GetLightWeight(right);
+
+ return leftWeight < rightWeight;
+}
} // namespace Gfx
diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h
index d83dfb3..ab66524 100644
--- a/src/graphics/engine/lightman.h
+++ b/src/graphics/engine/lightman.h
@@ -71,8 +71,8 @@ struct LightProgression
*/
enum LightPriority
{
- LIGHT_PRI_HIGH,
- LIGHT_PRI_LOW
+ LIGHT_PRI_HIGH = 1,
+ LIGHT_PRI_LOW = 2
};
/**
@@ -129,7 +129,7 @@ class CLightManager
{
public:
//! Constructor
- CLightManager(CInstanceManager *iMan, CEngine* engine);
+ CLightManager(CEngine* engine);
//! Destructor
virtual ~CLightManager();
@@ -189,7 +189,21 @@ public:
void UpdateDeviceLights(EngineObjectType type);
protected:
- CInstanceManager* m_iMan;
+ class LightsComparator
+ {
+ public:
+ LightsComparator(Math::Vector eyePos, EngineObjectType objectType);
+
+ bool operator()(const DynamicLight& left, const DynamicLight& right);
+
+ private:
+ float GetLightWeight(const DynamicLight& dynLight);
+
+ Math::Vector m_eyePos;
+ EngineObjectType m_objectType;
+ };
+
+protected:
CEngine* m_engine;
CDevice* m_device;
@@ -197,7 +211,7 @@ protected:
float m_time;
//! List of dynamic lights
std::vector<DynamicLight> m_dynLights;
- //! Map of current light allotment: graphics light -> dynamic light
+ //! Map of current light allocation: graphics light -> dynamic light
std::vector<int> m_lightMap;
};
diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp
index d256599..5fdae51 100644
--- a/src/graphics/engine/lightning.cpp
+++ b/src/graphics/engine/lightning.cpp
@@ -18,6 +18,8 @@
#include "graphics/engine/lightning.h"
+#include "app/app.h"
+
#include "common/logger.h"
#include "common/iman.h"
@@ -25,22 +27,20 @@
#include "graphics/engine/camera.h"
#include "graphics/engine/terrain.h"
+#include "math/geometry.h"
+
#include "object/object.h"
+#include "object/robotmain.h"
#include "object/auto/autopara.h"
-#include "math/geometry.h"
-
// Graphics module namespace
namespace Gfx {
-CLightning::CLightning(CInstanceManager* iMan, CEngine* engine)
+CLightning::CLightning(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_BLITZ, this);
-
m_engine = engine;
m_terrain = nullptr;
m_camera = nullptr;
@@ -187,13 +187,13 @@ bool CLightning::Create(float sleep, float delay, float magnetic)
m_speed = 1.0f / m_sleep;
if (m_terrain == nullptr)
- m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+ m_terrain = CRobotMain::GetInstancePointer()->GetTerrain();
if (m_camera == nullptr)
- m_camera = static_cast<CCamera*>(m_iMan->SearchInstance(CLASS_CAMERA));
+ m_camera = CRobotMain::GetInstancePointer()->GetCamera();
if (m_sound == nullptr)
- m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+ m_sound = CApplication::GetInstancePointer()->GetSound();
return false;
}
@@ -312,12 +312,14 @@ CObject* CLightning::SearchObject(Math::Vector pos)
std::vector<Math::Vector> paraObjPos;
paraObjPos.reserve(100);
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
// Seeking the object closest to the point of impact of lightning.
CObject* bestObj = 0;
float min = 100000.0f;
for (int i = 0; i < 1000000; i++)
{
- CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ CObject* obj = static_cast<CObject*>( iMan->SearchInstance(CLASS_OBJECT, i) );
if (obj == nullptr) break;
if (!obj->GetActif()) continue; // inactive object?
diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h
index b21f681..7809a6c 100644
--- a/src/graphics/engine/lightning.h
+++ b/src/graphics/engine/lightning.h
@@ -28,7 +28,6 @@
#include "math/vector.h"
-class CInstanceManager;
class CObject;
class CSoundInterface;
@@ -53,7 +52,7 @@ const float LTNG_PROTECTION_RADIUS = 200.0f;
class CLightning
{
public:
- CLightning(CInstanceManager* iMan, CEngine* engine);
+ CLightning(CEngine* engine);
~CLightning();
//! Triggers lightning
@@ -80,7 +79,6 @@ protected:
CObject* SearchObject(Math::Vector pos);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
CTerrain* m_terrain;
CCamera* m_camera;
diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp
index c0d04a0..f6d7a7b 100644
--- a/src/graphics/engine/modelfile.cpp
+++ b/src/graphics/engine/modelfile.cpp
@@ -18,7 +18,6 @@
#include "graphics/engine/modelfile.h"
-#include "common/iman.h"
#include "common/ioutils.h"
#include "common/logger.h"
#include "common/stringutils.h"
@@ -34,22 +33,10 @@
#include <sstream>
-/*
- * NOTE: #ifndef checking for MODELFILE_NO_ENGINE
- * is provided in this module to conditionally
- * disable dependence on CEngine.
- */
-
-
// Graphics module namespace
namespace Gfx {
-//! How big the triangle vector is by default
-const int TRIANGLE_PREALLOCATE_COUNT = 2000;
-
-
-
bool ReadBinaryVertex(std::istream& stream, Vertex& vertex)
{
vertex.coord.x = IOUtils::ReadBinaryFloat(stream);
@@ -322,15 +309,8 @@ bool ReadLineString(std::istream& stream, const std::string& prefix, std::string
}
-CModelFile::CModelFile(CInstanceManager* iMan)
+CModelFile::CModelFile()
{
- m_iMan = iMan;
-
-#ifndef MODELFILE_NO_ENGINE
- m_engine = static_cast<CEngine*>(m_iMan->SearchInstance(CLASS_ENGINE));
-#endif
-
- m_triangles.reserve(TRIANGLE_PREALLOCATE_COUNT);
}
CModelFile::~CModelFile()
@@ -514,8 +494,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);
}
@@ -558,8 +537,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);
@@ -603,14 +581,10 @@ 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;
- if (triangle.tex1Name == "plant.png")
- triangle.state |= ENG_RSTATE_ALPHA;
-
if (!triangle.variableTex2 && t.texNum2 != 0)
{
if (t.texNum2 >= 1 && t.texNum2 <= 10)
@@ -637,6 +611,10 @@ bool CModelFile::ReadModel(std::istream& stream)
m_triangles[i].tex2Name = StrUtils::Replace(m_triangles[i].tex2Name, "bmp", "png");
m_triangles[i].tex2Name = StrUtils::Replace(m_triangles[i].tex2Name, "tga", "png");
+ // TODO: fix this in model files
+ if (m_triangles[i].tex1Name == "plant.png")
+ m_triangles[i].state |= ENG_RSTATE_ALPHA;
+
GetLogger()->Trace("ModelTriangle %d\n", i+1);
std::string s1 = m_triangles[i].p1.ToString();
GetLogger()->Trace(" p1: %s\n", s1.c_str());
@@ -652,7 +630,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);
}
@@ -703,8 +681,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;
@@ -740,6 +717,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
@@ -786,17 +803,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;
}
};
@@ -852,8 +867,7 @@ bool CModelFile::ReadTextModel(std::istream& stream)
ReadLineValue<std::string>(stream, "tex1", t.tex1Name) &&
ReadLineValue<std::string>(stream, "tex2", t.tex2Name) &&
ReadLineValue<char>(stream, "var_tex2", varTex2Ch) &&
- ReadLineValue<float>(stream, "min", t.min) &&
- ReadLineValue<float>(stream, "max", t.max) &&
+ ReadLineValue<int>(stream, "lod_level", t.lodLevel) &&
ReadLineValue<int>(stream, "state", t.state);
if (!triOk || stream.fail())
@@ -873,10 +887,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;
@@ -904,7 +925,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);
}
@@ -956,10 +977,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 ";
@@ -972,8 +999,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;
@@ -1030,9 +1056,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())
{
@@ -1048,10 +1073,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);
}
}
@@ -1077,7 +1109,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);
}
@@ -1124,10 +1156,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);
@@ -1135,9 +1173,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())
{
@@ -1150,97 +1187,6 @@ bool CModelFile::WriteBinaryModel(std::ostream& stream)
}
-/*******************************************************
- Other stuff
- *******************************************************/
-
-#ifndef MODELFILE_NO_ENGINE
-
-bool CModelFile::CreateEngineObject(int objRank)
-{
- std::vector<VertexTex2> 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<int>( m_triangles.size() ); i++)
- {
- // TODO move this to CEngine
-
- float min = m_triangles[i].min;
- float max = m_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 = m_triangles[i].state;
- std::string tex2Name = m_triangles[i].tex2Name;
-
- if (m_triangles[i].variableTex2)
- {
- int texNum = m_engine->GetSecondTexture();
-
- if (texNum >= 1 && texNum <= 10)
- state |= ENG_RSTATE_DUAL_BLACK;
-
- if (texNum >= 11 && texNum <= 20)
- state |= ENG_RSTATE_DUAL_WHITE;
-
- char name[20] = { 0 };
- sprintf(name, "dirty%.2d.png", texNum);
- tex2Name = name;
- }
-
- vs[0] = m_triangles[i].p1;
- vs[1] = m_triangles[i].p2;
- vs[2] = m_triangles[i].p3;
-
- bool ok = m_engine->AddTriangles(objRank, vs,
- m_triangles[i].material,
- state,
- m_triangles[i].tex1Name,
- tex2Name,
- min, max, false);
- if (!ok)
- return false;
- }
-
- return true;
-}
-
-#endif
-
-void CModelFile::Mirror()
-{
- for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
- {
- VertexTex2 t = m_triangles[i].p1;
- m_triangles[i].p1 = m_triangles[i].p2;
- m_triangles[i].p2 = t;
-
- m_triangles[i].p1.coord.z = -m_triangles[i].p1.coord.z;
- m_triangles[i].p2.coord.z = -m_triangles[i].p2.coord.z;
- m_triangles[i].p3.coord.z = -m_triangles[i].p3.coord.z;
-
- m_triangles[i].p1.normal.z = -m_triangles[i].p1.normal.z;
- m_triangles[i].p2.normal.z = -m_triangles[i].p2.normal.z;
- m_triangles[i].p3.normal.z = -m_triangles[i].p3.normal.z;
- }
-}
-
const std::vector<ModelTriangle>& CModelFile::GetTriangles()
{
return m_triangles;
@@ -1251,45 +1197,5 @@ int CModelFile::GetTriangleCount()
return m_triangles.size();
}
-float CModelFile::GetHeight(Math::Vector pos)
-{
- float limit = 5.0f;
-
- for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
- {
- if ( fabs(pos.x - m_triangles[i].p1.coord.x) < limit &&
- fabs(pos.z - m_triangles[i].p1.coord.z) < limit )
- return m_triangles[i].p1.coord.y;
-
- if ( fabs(pos.x - m_triangles[i].p2.coord.x) < limit &&
- fabs(pos.z - m_triangles[i].p2.coord.z) < limit )
- return m_triangles[i].p2.coord.y;
-
- if ( fabs(pos.x - m_triangles[i].p3.coord.x) < limit &&
- fabs(pos.z - m_triangles[i].p3.coord.z) < limit )
- return m_triangles[i].p3.coord.y;
- }
-
- return 0.0f;
-}
-
-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 6c573b8..3a702cb 100644
--- a/src/graphics/engine/modelfile.h
+++ b/src/graphics/engine/modelfile.h
@@ -33,19 +33,29 @@
#include <iostream>
-class CInstanceManager;
-
// Graphics module namespace
namespace Gfx {
-class CEngine;
+/**
+ * \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
+ * \brief Triangle of a 3D model
+ */
struct ModelTriangle
{
//! 1st vertex
@@ -62,31 +72,30 @@ 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;
}
};
/**
- \class CModelFile
- \brief Model file reader/writer
-
- Allows reading and writing model objects. Models are collections of ModelTriangle structs. */
+ * \class CModelFile
+ * \brief Model file reader/writer
+ *
+ * Allows reading and writing model objects. Models are collections of ModelTriangle structs.
+ */
class CModelFile
{
public:
- CModelFile(CInstanceManager* iMan);
+ CModelFile();
~CModelFile();
//! Reads a model in text format from file
@@ -128,23 +137,14 @@ public:
//! Returns the triangle vector
const std::vector<ModelTriangle>& GetTriangles();
- //! Returns the height of model -- closest point to X and Z coords of \a pos
- float GetHeight(Math::Vector pos);
-
- //! Mirrors the model along the Z axis
- void Mirror();
-
- //! Creates an object in the graphics engine from the model
- bool CreateEngineObject(int objRank);
-
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:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
-
//! Model triangles
std::vector<ModelTriangle> m_triangles;
};
diff --git a/src/graphics/engine/modelmanager.cpp b/src/graphics/engine/modelmanager.cpp
new file mode 100644
index 0000000..c23b79d
--- /dev/null
+++ b/src/graphics/engine/modelmanager.cpp
@@ -0,0 +1,191 @@
+#include "graphics/engine/modelmanager.h"
+
+#include "app/app.h"
+
+#include "common/logger.h"
+
+#include "graphics/engine/engine.h"
+
+#include <cstdio>
+
+template<> Gfx::CModelManager* CSingleton<Gfx::CModelManager>::m_instance = nullptr;
+
+namespace Gfx {
+
+CModelManager::CModelManager(CEngine* engine)
+{
+ m_engine = engine;
+}
+
+CModelManager::~CModelManager()
+{
+}
+
+bool CModelManager::LoadModel(const std::string& fileName, bool mirrored)
+{
+ GetLogger()->Info("Loading model '%s'\n", fileName.c_str());
+
+ CModelFile modelFile;
+
+ std::string filePath = CApplication::GetInstance().GetDataFilePath(DIR_MODEL, fileName);
+
+ if (!modelFile.ReadModel(filePath))
+ {
+ GetLogger()->Error("Loading model '%s' failed\n", filePath.c_str());
+ return false;
+ }
+
+ ModelInfo modelInfo;
+ modelInfo.baseObjRank = m_engine->CreateBaseObject();
+ modelInfo.triangles = modelFile.GetTriangles();
+
+ if (mirrored)
+ Mirror(modelInfo.triangles);
+
+ FileInfo fileInfo(fileName, mirrored);
+ m_models[fileInfo] = modelInfo;
+
+ std::vector<VertexTex2> vs(3, VertexTex2());
+
+ for (int i = 0; i < static_cast<int>( modelInfo.triangles.size() ); i++)
+ {
+ int state = modelInfo.triangles[i].state;
+ std::string tex2Name = modelInfo.triangles[i].tex2Name;
+
+ if (modelInfo.triangles[i].variableTex2)
+ {
+ int texNum = m_engine->GetSecondTexture();
+
+ if (texNum >= 1 && texNum <= 10)
+ state |= ENG_RSTATE_DUAL_BLACK;
+
+ if (texNum >= 11 && texNum <= 20)
+ state |= ENG_RSTATE_DUAL_WHITE;
+
+ char name[20] = { 0 };
+ sprintf(name, "dirty%.2d.png", texNum);
+ tex2Name = name;
+ }
+
+ vs[0] = modelInfo.triangles[i].p1;
+ vs[1] = modelInfo.triangles[i].p2;
+ vs[2] = modelInfo.triangles[i].p3;
+
+ m_engine->AddBaseObjTriangles(modelInfo.baseObjRank, vs, ENG_TRIANGLE_TYPE_TRIANGLES,
+ modelInfo.triangles[i].material, state,
+ modelInfo.triangles[i].tex1Name, tex2Name,
+ modelInfo.triangles[i].lodLevel, false);
+ }
+
+ return true;
+}
+
+bool CModelManager::AddModelReference(const std::string& fileName, bool mirrored, int objRank)
+{
+ auto it = m_models.find(FileInfo(fileName, mirrored));
+ if (it == m_models.end())
+ {
+ if (!LoadModel(fileName, mirrored))
+ return false;
+
+ it = m_models.find(FileInfo(fileName, mirrored));
+ }
+
+ m_engine->SetObjectBaseRank(objRank, (*it).second.baseObjRank);
+
+ return true;
+}
+
+bool CModelManager::AddModelCopy(const std::string& fileName, bool mirrored, int objRank)
+{
+ auto it = m_models.find(FileInfo(fileName, mirrored));
+ if (it == m_models.end())
+ {
+ if (!LoadModel(fileName, mirrored))
+ return false;
+
+ it = m_models.find(FileInfo(fileName, mirrored));
+ }
+
+ int copyBaseObjRank = m_engine->CreateBaseObject();
+ m_engine->CopyBaseObject((*it).second.baseObjRank, copyBaseObjRank);
+ m_engine->SetObjectBaseRank(objRank, copyBaseObjRank);
+
+ return true;
+}
+
+bool CModelManager::IsModelLoaded(const std::string& fileName, bool mirrored)
+{
+ return m_models.count(FileInfo(fileName, mirrored)) > 0;
+}
+
+int CModelManager::GetModelBaseObjRank(const std::string& fileName, bool mirrored)
+{
+ auto it = m_models.find(FileInfo(fileName, mirrored));
+ if (it == m_models.end())
+ return -1;
+
+ return (*it).second.baseObjRank;
+}
+
+void CModelManager::UnloadModel(const std::string& fileName, bool mirrored)
+{
+ auto it = m_models.find(FileInfo(fileName, mirrored));
+ if (it == m_models.end())
+ return;
+
+ m_engine->DeleteBaseObject((*it).second.baseObjRank);
+
+ m_models.erase(it);
+}
+
+void CModelManager::UnloadAllModels()
+{
+ for (auto& mf : m_models)
+ m_engine->DeleteBaseObject(mf.second.baseObjRank);
+
+ m_models.clear();
+}
+
+void CModelManager::Mirror(std::vector<ModelTriangle>& triangles)
+{
+ for (int i = 0; i < static_cast<int>( triangles.size() ); i++)
+ {
+ VertexTex2 t = triangles[i].p1;
+ triangles[i].p1 = triangles[i].p2;
+ triangles[i].p2 = t;
+
+ triangles[i].p1.coord.z = -triangles[i].p1.coord.z;
+ triangles[i].p2.coord.z = -triangles[i].p2.coord.z;
+ triangles[i].p3.coord.z = -triangles[i].p3.coord.z;
+
+ triangles[i].p1.normal.z = -triangles[i].p1.normal.z;
+ triangles[i].p2.normal.z = -triangles[i].p2.normal.z;
+ triangles[i].p3.normal.z = -triangles[i].p3.normal.z;
+ }
+}
+
+float CModelManager::GetHeight(std::vector<ModelTriangle>& triangles, Math::Vector pos)
+{
+ const float limit = 5.0f;
+
+ for (int i = 0; i < static_cast<int>( triangles.size() ); i++)
+ {
+ if ( fabs(pos.x - triangles[i].p1.coord.x) < limit &&
+ fabs(pos.z - triangles[i].p1.coord.z) < limit )
+ return triangles[i].p1.coord.y;
+
+ if ( fabs(pos.x - triangles[i].p2.coord.x) < limit &&
+ fabs(pos.z - triangles[i].p2.coord.z) < limit )
+ return triangles[i].p2.coord.y;
+
+ if ( fabs(pos.x - triangles[i].p3.coord.x) < limit &&
+ fabs(pos.z - triangles[i].p3.coord.z) < limit )
+ return triangles[i].p3.coord.y;
+ }
+
+ return 0.0f;
+}
+
+
+}
diff --git a/src/graphics/engine/modelmanager.h b/src/graphics/engine/modelmanager.h
new file mode 100644
index 0000000..601d636
--- /dev/null
+++ b/src/graphics/engine/modelmanager.h
@@ -0,0 +1,97 @@
+#pragma once
+
+#include "common/singleton.h"
+
+#include "graphics/engine/modelfile.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Gfx {
+
+class CEngine;
+class CModelFile;
+
+/**
+ * \class CModelManager
+ * \brief Manager for static models
+ *
+ * The manager allows for loading models as static objects and adding
+ * new instances of models to the engine.
+ *
+ * The models are loaded from stanard application model directory and
+ * they are identified by unique file names.
+ *
+ * The models are loaded by creating (if it doesn't exist yet)
+ * a base engine object from the model geometry. This base object
+ * is then shared among all instances of this model with the instances
+ * being engine objects linked to the shared base object.
+ *
+ * There is also a possibility of creating a copy of model so it has
+ * its own and unique base engine object. This is especially useful
+ * for models where the geometry must be altered.
+ */
+class CModelManager : public CSingleton<CModelManager>
+{
+public:
+ CModelManager(CEngine* engine);
+ ~CModelManager();
+
+ //! Loads a model from given file
+ bool LoadModel(const std::string& fileName, bool mirrored);
+
+ //! Adds an instance of model to the given object rank as a reference to base object
+ bool AddModelReference(const std::string& fileName, bool mirrored, int objRank);
+
+ //! Adds an instance of model to the given object rank as a copy (copied base object)
+ bool AddModelCopy(const std::string& fileName, bool mirrored, int objRank);
+
+ //! Returns true if given model is loaded
+ bool IsModelLoaded(const std::string& fileName, bool mirrored);
+
+ //! Returns the rank of base engine object of given loaded model
+ int GetModelBaseObjRank(const std::string& fileName, bool mirrored);
+
+ //! Unloads the given model
+ void UnloadModel(const std::string& fileName, bool mirrored);
+ //! Unloads all models
+ void UnloadAllModels();
+
+protected:
+ //! Returns the height of model -- closest point to X and Z coords of \a pos
+ float GetHeight(std::vector<ModelTriangle>& triangles, Math::Vector pos);
+
+ //! Mirrors the model along the Z axis
+ void Mirror(std::vector<ModelTriangle>& triangles);
+
+private:
+ struct ModelInfo
+ {
+ std::vector<ModelTriangle> triangles;
+ int baseObjRank;
+ };
+ struct FileInfo
+ {
+ std::string fileName;
+ bool mirrored;
+
+ inline FileInfo(const std::string& fileName, bool mirrored)
+ : fileName(fileName), mirrored(mirrored) {}
+
+ inline bool operator<(const FileInfo& other) const
+ {
+ int compare = fileName.compare(other.fileName);
+ if (compare < 0)
+ return true;
+ if (compare > 0)
+ return false;
+
+ return !mirrored && mirrored != other.mirrored;
+ }
+ };
+ std::map<FileInfo, ModelInfo> m_models;
+ CEngine* m_engine;
+};
+
+} // namespace Gfx
diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp
index acc40df..d15ee3b 100644
--- a/src/graphics/engine/particle.cpp
+++ b/src/graphics/engine/particle.cpp
@@ -18,6 +18,9 @@
#include "graphics/engine/particle.h"
+#include "app/app.h"
+
+#include "common/iman.h"
#include "common/logger.h"
#include "graphics/core/device.h"
@@ -117,11 +120,8 @@ float GetDecay(ObjectType type)
-CParticle::CParticle(CInstanceManager *iMan, CEngine* engine)
+CParticle::CParticle(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PARTICULE, this);
-
m_device = nullptr;
m_engine = engine;
m_main = nullptr;
@@ -138,7 +138,6 @@ CParticle::CParticle(CInstanceManager *iMan, CEngine* engine)
CParticle::~CParticle()
{
- m_iMan->DeleteInstance(CLASS_PARTICULE, this);
}
void CParticle::SetDevice(CDevice* device)
@@ -213,7 +212,7 @@ int CParticle::CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point
float windSensitivity, int sheet)
{
if (m_main == nullptr)
- m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
+ m_main = CRobotMain::GetInstancePointer();
int t = -1;
if ( type == PARTIEXPLOT ||
@@ -649,7 +648,7 @@ void CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2,
m_wheelTrace[i].startTime = m_absTime;
if (m_terrain == nullptr)
- m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+ m_terrain = m_main->GetTerrain();
m_terrain->AdjustToFloor(m_wheelTrace[i].pos[0]);
m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground
@@ -808,15 +807,15 @@ void CParticle::SetFrameUpdate(int sheet, bool update)
void CParticle::FrameParticle(float rTime)
{
if (m_main == nullptr)
- m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
+ m_main = CRobotMain::GetInstancePointer();
bool pause = (m_engine->GetPause() && !m_main->GetInfoLock());
if (m_terrain == nullptr)
- m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+ m_terrain = m_main->GetTerrain();
if (m_water == nullptr)
- m_water = static_cast<CWater*>(m_iMan->SearchInstance(CLASS_WATER));
+ m_water = m_engine->GetWater();
if (!pause)
{
@@ -3214,7 +3213,7 @@ void CParticle::DrawParticleSphere(int i)
angle.z = m_particle[i].angle*0.7f;
Math::Matrix rot;
Math::LoadRotationZXYMatrix(rot, angle);
- mat = Math::MultiplyMatrices(rot, mat);
+ mat = Math::MultiplyMatrices(mat, rot);
}
m_device->SetTransform(TRANSFORM_WORLD, mat);
@@ -3654,11 +3653,13 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
box2.y += min;
box2.z += min;
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
CObject* best = 0;
bool shield = false;
for (int i = 0; i < 1000000; i++)
{
- CObject* obj = static_cast<CObject*>(m_iMan->SearchInstance(CLASS_OBJECT, i));
+ CObject* obj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
if (obj == 0) break;
if (!obj->GetActif()) continue; // inactive?
@@ -3782,9 +3783,11 @@ CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal,
box2.y += min;
box2.z += min;
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
for (int i = 0; i < 1000000; i++)
{
- CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ CObject* obj = static_cast<CObject*>( iMan->SearchInstance(CLASS_OBJECT, i) );
if (obj == nullptr) break;
if (!obj->GetActif()) continue; // inactive?
@@ -3822,7 +3825,7 @@ CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal,
void CParticle::Play(Sound sound, Math::Vector pos, float amplitude)
{
if (m_sound == nullptr)
- m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+ m_sound = CApplication::GetInstancePointer()->GetSound();
m_sound->Play(sound, pos, amplitude);
}
diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h
index 90aec55..708a04d 100644
--- a/src/graphics/engine/particle.h
+++ b/src/graphics/engine/particle.h
@@ -28,7 +28,6 @@
#include "sound/sound.h"
-class CInstanceManager;
class CRobotMain;
class CObject;
class CSoundInterface;
@@ -267,7 +266,7 @@ struct WheelTrace
class CParticle
{
public:
- CParticle(CInstanceManager* iMan, CEngine* engine);
+ CParticle(CEngine* engine);
~CParticle();
//! Sets the device to use
@@ -371,7 +370,6 @@ protected:
void TrackDraw(int i, ParticleType type);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
CDevice* m_device;
CTerrain* m_terrain;
diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp
index 3b9aa6c..49bcb4c 100644
--- a/src/graphics/engine/planet.cpp
+++ b/src/graphics/engine/planet.cpp
@@ -18,8 +18,6 @@
#include "graphics/engine/planet.h"
-#include "common/iman.h"
-
#include "graphics/core/device.h"
#include "graphics/engine/engine.h"
@@ -31,11 +29,8 @@ namespace Gfx {
const int PLANET_PREALLOCATE_COUNT = 10;
-CPlanet::CPlanet(CInstanceManager* iMan, CEngine* engine)
+CPlanet::CPlanet(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PLANET, this);
-
m_planet[0].reserve(PLANET_PREALLOCATE_COUNT);
m_planet[1].reserve(PLANET_PREALLOCATE_COUNT);
@@ -46,7 +41,6 @@ CPlanet::CPlanet(CInstanceManager* iMan, CEngine* engine)
CPlanet::~CPlanet()
{
- m_iMan = nullptr;
}
void CPlanet::Flush()
diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h
index 1b16da0..3762e1d 100644
--- a/src/graphics/engine/planet.h
+++ b/src/graphics/engine/planet.h
@@ -30,8 +30,6 @@
#include <vector>
-class CInstanceManager;
-
// Graphics module namespace
namespace Gfx {
@@ -82,7 +80,7 @@ struct Planet
class CPlanet
{
public:
- CPlanet(CInstanceManager* iMan, CEngine* engine);
+ CPlanet(CEngine* engine);
~CPlanet();
//! Removes all the planets
@@ -110,7 +108,6 @@ protected:
bool EventFrame(const Event &event);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
float m_time;
diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp
index 978471b..cab28b6 100644
--- a/src/graphics/engine/pyro.cpp
+++ b/src/graphics/engine/pyro.cpp
@@ -18,6 +18,9 @@
#include "graphics/engine/pyro.h"
+#include "app/app.h"
+
+#include "common/iman.h"
#include "common/logger.h"
#include "graphics/engine/lightman.h"
@@ -36,20 +39,19 @@
namespace Gfx {
-CPyro::CPyro(CInstanceManager* iMan)
+CPyro::CPyro()
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PYRO, this, 100);
-
- m_engine = static_cast<CEngine*>(m_iMan->SearchInstance(CLASS_ENGINE));
- m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
- m_camera = static_cast<CCamera*>(m_iMan->SearchInstance(CLASS_CAMERA));
- m_particle = static_cast<CParticle*>(m_iMan->SearchInstance(CLASS_PARTICULE));
- m_lightMan = static_cast<CLightManager*>(m_iMan->SearchInstance(CLASS_LIGHT));
- m_displayText = static_cast<Ui::CDisplayText*>(m_iMan->SearchInstance(CLASS_DISPLAYTEXT));
- m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
- m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
- m_object = 0;
+ CInstanceManager::GetInstancePointer()->AddInstance(CLASS_PYRO, this, 100);
+
+ m_engine = CEngine::GetInstancePointer();
+ m_main = CRobotMain::GetInstancePointer();
+ m_terrain = m_main->GetTerrain();
+ m_camera = m_main->GetCamera();
+ m_particle = m_engine->GetParticle();
+ m_lightMan = m_engine->GetLightManager();
+ m_displayText = m_main->GetDisplayText();
+ m_sound = CApplication::GetInstancePointer()->GetSound();
+ m_object = nullptr;
m_progress = 0.0f;
m_speed = 0.0f;
@@ -60,7 +62,7 @@ CPyro::CPyro(CInstanceManager* iMan)
CPyro::~CPyro()
{
- m_iMan->DeleteInstance(CLASS_PYRO, this);
+ CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_PYRO, this);
}
void CPyro::DeleteObject()
@@ -1316,12 +1318,9 @@ void CPyro::CreateLight(Math::Vector pos, float height)
Gfx::Light light;
light.type = LIGHT_SPOT;
- light.position.x = pos.x;
- light.position.y = pos.y+height;
- light.position.z = pos.z;
- light.direction.x = 0.0f;
- light.direction.y = -1.0f; // against the bottom
- light.direction.z = 0.0f;
+ light.ambient = Gfx::Color(0.0f, 0.0f, 0.0f);
+ light.position = Math::Vector(pos.x, pos.y+height, pos.z);
+ light.direction = Math::Vector(0.0f, -1.0f, 0.0f); // against the bottom
light.spotIntensity = 1.0f;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
@@ -1397,27 +1396,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<EngineTriangle> 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++)
{
@@ -2171,9 +2182,11 @@ CObject* CPyro::FallSearchBeeExplo()
float iRadius;
m_object->GetCrashSphere(0, iPos, iRadius);
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
for (int i = 0; i < 1000000; i++)
{
- CObject* pObj = static_cast<CObject*>(m_iMan->SearchInstance(CLASS_OBJECT, i));
+ CObject* pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
if ( pObj == 0 ) break;
ObjectType oType = pObj->GetType();
diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h
index 0204070..9548a07 100644
--- a/src/graphics/engine/pyro.h
+++ b/src/graphics/engine/pyro.h
@@ -31,7 +31,6 @@
#include "object/object.h"
-class CInstanceManager;
class CObject;
class CRobotMain;
class CSoundInterface;
@@ -111,7 +110,7 @@ struct PyroLightOper
class CPyro
{
public:
- CPyro(CInstanceManager* iMan);
+ CPyro();
~CPyro();
//! Creates pyrotechnic effect
@@ -174,7 +173,6 @@ protected:
void LightOperFrame(float rTime);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
CTerrain* m_terrain;
CCamera* m_camera;
diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp
index 4c22a32..c2a7855 100644
--- a/src/graphics/engine/terrain.cpp
+++ b/src/graphics/engine/terrain.cpp
@@ -19,33 +19,28 @@
#include "graphics/engine/terrain.h"
#include "app/app.h"
-#include "common/iman.h"
+
#include "common/image.h"
#include "common/logger.h"
+
#include "graphics/engine/engine.h"
#include "graphics/engine/water.h"
+
#include "math/geometry.h"
#include <sstream>
-#include <SDL/SDL.h>
+#include <SDL.h>
// Graphics module namespace
namespace Gfx {
-const int LEVEL_MAT_PREALLOCATE_COUNT = 101;
-const int FLYING_LIMIT_PREALLOCATE_COUNT = 10;
-const int BUILDING_LEVEL_PREALLOCATE_COUNT = 101;
-
-CTerrain::CTerrain(CInstanceManager* iMan)
+CTerrain::CTerrain()
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TERRAIN, this);
-
- m_engine = static_cast<CEngine*>( m_iMan->SearchInstance(CLASS_ENGINE) );
- m_water = static_cast<CWater*>( m_iMan->SearchInstance(CLASS_WATER) );
+ m_engine = CEngine::GetInstancePointer();
+ m_water = m_engine->GetWater();
m_mosaicCount = 20;
m_brickCount = 1 << 4;
@@ -60,10 +55,6 @@ CTerrain::CTerrain(CInstanceManager* iMan)
m_defaultHardness = 0.5f;
m_useMaterials = false;
- m_materials.reserve(LEVEL_MAT_PREALLOCATE_COUNT);
- m_flyingLimits.reserve(FLYING_LIMIT_PREALLOCATE_COUNT);
- m_buildingLevels.reserve(BUILDING_LEVEL_PREALLOCATE_COUNT);
-
FlushBuildingLevel();
FlushFlyingLimit();
FlushMaterials();
@@ -478,6 +469,8 @@ VertexTex2 CTerrain::GetVertex(int x, int y, int step)
v.texCoord.x = (o.x-oo.x)*m_textureScale*m_textureSubdivCount;
v.texCoord.y = 1.0f - (o.z-oo.z)*m_textureScale*m_textureSubdivCount;
+ v.texCoord2 = v.texCoord;
+
return v;
}
@@ -493,9 +486,15 @@ 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)
+ {
+ baseObjRank = m_engine->CreateBaseObject();
+ m_engine->SetObjectBaseRank(objRank, baseObjRank);
+ }
+
std::string texName1;
std::string texName2;
@@ -545,7 +544,7 @@ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
for (int y = 0; y < brick; y += step)
{
- EngineObjLevel4 buffer;
+ EngineBaseObjDataTier buffer;
buffer.vertices.reserve(total);
buffer.type = ENG_TRIANGLE_TYPE_SURFACE;
@@ -638,7 +637,8 @@ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
buffer.vertices.push_back(p1);
buffer.vertices.push_back(p2);
}
- m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true);
+
+ m_engine->AddBaseObjQuick(baseObjRank, buffer, texName1, texName2, LOD_Constant, true);
}
}
}
@@ -1168,15 +1168,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;
@@ -1272,7 +1266,10 @@ bool CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float h
{
for (int x = pp1.x; x <= pp2.x; x++)
{
- m_engine->DeleteObject(m_objRanks[x+y*m_mosaicCount]);
+ int objRank = m_objRanks[x+y*m_mosaicCount];
+ int baseObjRank = m_engine->GetObjectBaseRank(objRank);
+ m_engine->DeleteBaseObject(baseObjRank);
+ m_engine->DeleteObject(objRank);
CreateSquare(x, y); // recreates the square
}
}
diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h
index 3012e62..1fa8dec 100644
--- a/src/graphics/engine/terrain.h
+++ b/src/graphics/engine/terrain.h
@@ -26,9 +26,6 @@
#include "graphics/engine/engine.h"
-class CInstanceManager;
-
-
// Graphics module namespace
namespace Gfx {
@@ -223,7 +220,7 @@ struct FlyingLimit
class CTerrain
{
public:
- CTerrain(CInstanceManager* iMan);
+ CTerrain();
~CTerrain();
//! Generates a new flat terrain
@@ -328,9 +325,9 @@ protected:
//! Calculates a vector of the terrain
Math::Vector GetVector(int x, int y);
//! Calculates a vertex of the terrain
- VertexTex2 GetVertex(int x, int y, int step);
+ 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);
@@ -359,7 +356,6 @@ protected:
void AdjustBuildingLevel(Math::Vector &p);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
CWater* m_water;
diff --git a/src/graphics/engine/test/CMakeLists.txt b/src/graphics/engine/test/CMakeLists.txt
index c837ae5..afaa86a 100644
--- a/src/graphics/engine/test/CMakeLists.txt
+++ b/src/graphics/engine/test/CMakeLists.txt
@@ -10,7 +10,6 @@ modelfile_test.cpp
../modelfile.cpp
../../../common/logger.cpp
../../../common/stringutils.cpp
-../../../common/iman.cpp
)
add_definitions(-DMODELFILE_NO_ENGINE)
diff --git a/src/graphics/engine/test/modelfile_test.cpp b/src/graphics/engine/test/modelfile_test.cpp
index 6879a1b..e7078a9 100644
--- a/src/graphics/engine/test/modelfile_test.cpp
+++ b/src/graphics/engine/test/modelfile_test.cpp
@@ -15,12 +15,11 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
-#include "common/iman.h"
#include "common/logger.h"
#include "graphics/engine/modelfile.h"
#include "math/func.h"
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
#include <cassert>
#include <sstream>
@@ -41,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"
@@ -52,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"
"";
@@ -82,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),
@@ -103,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;
}
@@ -172,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)
@@ -190,8 +182,7 @@ TEST(ModelFileTest, RWTxtModel)
std::stringstream str;
str.str(TEXT_MODEL);
- CInstanceManager iMan;
- Gfx::CModelFile modelFile(&iMan);
+ Gfx::CModelFile modelFile;
EXPECT_TRUE(modelFile.ReadTextModel(str));
@@ -216,8 +207,7 @@ TEST(ModelFileTest, RWBinModel)
std::stringstream str;
str.str(TEXT_MODEL);
- CInstanceManager iMan;
- Gfx::CModelFile modelFile(&iMan);
+ Gfx::CModelFile modelFile;
EXPECT_TRUE(modelFile.ReadTextModel(str));
@@ -242,8 +232,7 @@ TEST(ModelFileTest, RWOldModel)
std::stringstream str;
str.str(TEXT_MODEL);
- CInstanceManager iMan;
- Gfx::CModelFile modelFile(&iMan);
+ Gfx::CModelFile modelFile;
EXPECT_TRUE(modelFile.ReadTextModel(str));
diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp
index 101e01a..308c813 100644
--- a/src/graphics/engine/text.cpp
+++ b/src/graphics/engine/text.cpp
@@ -19,14 +19,15 @@
#include "graphics/engine/text.h"
#include "app/app.h"
+
#include "common/image.h"
-#include "common/iman.h"
#include "common/logger.h"
#include "common/stringutils.h"
+
#include "math/func.h"
-#include <SDL/SDL.h>
-#include <SDL/SDL_ttf.h>
+#include <SDL.h>
+#include <SDL_ttf.h>
// Graphics module namespace
@@ -46,14 +47,11 @@ struct CachedFont
};
+const Math::IntPoint REFERENCE_SIZE(800, 600);
-
-CText::CText(CInstanceManager *iMan, CEngine* engine)
+CText::CText(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TEXT, this);
-
m_device = nullptr;
m_engine = engine;
@@ -66,9 +64,6 @@ CText::CText(CInstanceManager *iMan, CEngine* engine)
CText::~CText()
{
- m_iMan->DeleteInstance(CLASS_TEXT, this);
-
- m_iMan = nullptr;
m_device = nullptr;
m_engine = nullptr;
}
@@ -147,9 +142,14 @@ void CText::FlushCache()
f->cache.clear();
}
}
+
+ m_lastFontType = FONT_COLOBOT;
+ m_lastFontSize = 0;
+ m_lastCachedFont = nullptr;
}
-void CText::DrawText(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+void CText::DrawText(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, Math::Point pos, float width, TextAlign align,
int eol, Color color)
{
@@ -157,18 +157,18 @@ void CText::DrawText(const std::string &text, std::map<unsigned int, FontMetaCha
if (align == TEXT_ALIGN_CENTER)
{
- sw = GetStringWidth(text, format, size);
+ sw = GetStringWidth(text, format, end, size);
if (sw > width) sw = width;
pos.x -= sw / 2.0f;
}
else if (align == TEXT_ALIGN_RIGHT)
{
- sw = GetStringWidth(text, format, size);
+ sw = GetStringWidth(text, format, end, size);
if (sw > width) sw = width;
pos.x -= sw;
}
- DrawString(text, format, size, pos, width, eol, color);
+ DrawString(text, format, end, size, pos, width, eol, color);
}
void CText::DrawText(const std::string &text, FontType font,
@@ -193,13 +193,14 @@ void CText::DrawText(const std::string &text, FontType font,
DrawString(text, font, size, pos, width, eol, color);
}
-void CText::SizeText(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+void CText::SizeText(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator endFormat,
float size, Math::Point pos, TextAlign align,
Math::Point &start, Math::Point &end)
{
start = end = pos;
- float sw = GetStringWidth(text, format, size);
+ float sw = GetStringWidth(text, format, endFormat, size);
end.x += sw;
if (align == TEXT_ALIGN_CENTER)
{
@@ -277,7 +278,8 @@ float CText::GetHeight(FontType font, float size)
float CText::GetStringWidth(const std::string &text,
- std::map<unsigned int, FontMetaChar> &format, float size)
+ std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end, float size)
{
float width = 0.0f;
unsigned int index = 0;
@@ -285,8 +287,8 @@ float CText::GetStringWidth(const std::string &text,
while (index < text.length())
{
FontType font = FONT_COLOBOT;
- if (format.count(fmtIndex))
- font = static_cast<FontType>(format[fmtIndex] & FONT_MASK_FONT);
+ if (format + fmtIndex != end)
+ font = static_cast<FontType>(*(format + fmtIndex) & FONT_MASK_FONT);
UTF8Char ch;
@@ -343,7 +345,8 @@ float CText::GetCharWidth(UTF8Char ch, FontType font, float size, float offset)
}
-int CText::Justify(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+int CText::Justify(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, float width)
{
float pos = 0.0f;
@@ -353,8 +356,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 + fmtIndex != end)
+ font = static_cast<FontType>(*(format + fmtIndex) & FONT_MASK_FONT);
UTF8Char ch;
@@ -427,7 +430,8 @@ int CText::Justify(const std::string &text, FontType font, float size, float wid
return index;
}
-int CText::Detect(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+int CText::Detect(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, float offset)
{
float pos = 0.0f;
@@ -436,11 +440,12 @@ int CText::Detect(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 + fmtIndex != end)
+ font = static_cast<FontType>(*(format + fmtIndex) & FONT_MASK_FONT);
// TODO: if (font == FONT_BUTTON)
- if (font == FONT_BUTTON) continue;
+ //if (font == FONT_BUTTON) continue;
UTF8Char ch;
@@ -500,7 +505,8 @@ int CText::Detect(const std::string &text, FontType font, float size, float offs
return index;
}
-void CText::DrawString(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+void CText::DrawString(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, Math::Point pos, float width, int eol, Color color)
{
m_engine->SetState(ENG_RSTATE_TEXT);
@@ -514,8 +520,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 + fmtIndex != end)
+ font = static_cast<FontType>(*(format + fmtIndex) & FONT_MASK_FONT);
// TODO: if (font == FONT_BUTTON)
if (font == FONT_BUTTON) continue;
@@ -678,11 +684,14 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::P
int width = 1;
if (ch.c1 > 0 && ch.c1 < 32) { // FIXME add support for chars with code 9 10 23
- ch.c1 = ' ';
+ if (ch.c1 == '\t') {
+ ch.c1 = ':';
+ width = 4;
+ } else {
+ ch.c1 = ' ';
+ }
ch.c2 = 0;
ch.c3 = 0;
- if (ch.c1 == '\t')
- width = 4;
}
auto it = cf->cache.find(ch);
@@ -702,7 +711,7 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::P
}
Math::Point p1(pos.x, pos.y + tex.charSize.y - tex.texSize.y);
- Math::Point p2(pos.x + tex.texSize.x * width, pos.y + tex.charSize.y);
+ Math::Point p2(pos.x + tex.texSize.x, pos.y + tex.charSize.y);
Math::Vector n(0.0f, 0.0f, -1.0f); // normal
@@ -723,8 +732,8 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::P
CachedFont* CText::GetOrOpenFont(FontType font, float size)
{
- // TODO: sizing
- int pointSize = static_cast<int>(size);
+ Math::IntPoint windowSize = m_engine->GetWindowSize();
+ int pointSize = static_cast<int>(size * (windowSize.Length() / REFERENCE_SIZE.Length()));
if (m_lastCachedFont != nullptr)
{
diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h
index 57fad43..6bcc59b 100644
--- a/src/graphics/engine/text.h
+++ b/src/graphics/engine/text.h
@@ -31,9 +31,6 @@
#include <map>
-class CInstanceManager;
-
-
// Graphics module namespace
namespace Gfx {
@@ -226,7 +223,7 @@ struct MultisizeFont
class CText
{
public:
- CText(CInstanceManager *iMan, CEngine* engine);
+ CText(CEngine* engine);
virtual ~CText();
//! Sets the device to be used
@@ -244,7 +241,8 @@ public:
void FlushCache();
//! Draws text (multi-format)
- void DrawText(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+ void DrawText(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, Math::Point pos, float width, TextAlign align,
int eol, Color color = Color(0.0f, 0.0f, 0.0f, 1.0f));
//! Draws text (one font)
@@ -253,7 +251,8 @@ public:
int eol, Color color = Color(0.0f, 0.0f, 0.0f, 1.0f));
//! Calculates dimensions for text (multi-format)
- void SizeText(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+ void SizeText(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator endFormat,
float size, Math::Point pos, TextAlign align,
Math::Point &start, Math::Point &end);
//! Calculates dimensions for text (one font)
@@ -270,20 +269,23 @@ public:
//! Returns width of string (multi-format)
TEST_VIRTUAL float GetStringWidth(const std::string &text,
- std::map<unsigned int, FontMetaChar> &format, float size);
+ std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end, float size);
//! Returns width of string (single font)
TEST_VIRTUAL float GetStringWidth(const std::string &text, FontType font, float size);
//! Returns width of single character
TEST_VIRTUAL float GetCharWidth(UTF8Char ch, FontType font, float size, float offset);
//! Justifies a line of text (multi-format)
- int Justify(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+ int Justify(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, float width);
//! Justifies a line of text (one font)
int Justify(const std::string &text, FontType font, float size, float width);
//! Returns the most suitable position to a given offset (multi-format)
- int Detect(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+ int Detect(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, float offset);
//! Returns the most suitable position to a given offset (one font)
int Detect(const std::string &text, FontType font, float size, float offset);
@@ -292,7 +294,8 @@ protected:
CachedFont* GetOrOpenFont(FontType type, float size);
CharTexture CreateCharTexture(UTF8Char ch, CachedFont* font);
- void DrawString(const std::string &text, std::map<unsigned int, FontMetaChar> &format,
+ void DrawString(const std::string &text, std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end,
float size, Math::Point pos, float width, int eol, Color color);
void DrawString(const std::string &text, FontType font,
float size, Math::Point pos, float width, int eol, Color color);
@@ -301,7 +304,6 @@ protected:
void StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
CDevice* m_device;
diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp
index 18811eb..d90652b 100644
--- a/src/graphics/engine/water.cpp
+++ b/src/graphics/engine/water.cpp
@@ -18,7 +18,8 @@
#include "graphics/engine/water.h"
-#include "common/iman.h"
+#include "app/app.h"
+
#include "common/logger.h"
#include "graphics/core/device.h"
@@ -28,6 +29,7 @@
#include "math/geometry.h"
#include "object/object.h"
+#include "object/robotmain.h"
#include "sound/sound.h"
@@ -42,14 +44,11 @@ const int WATERLINE_PREALLOCATE_COUNT = 500;
const int VAPOR_SIZE = 10;
-CWater::CWater(CInstanceManager* iMan, CEngine* engine)
+CWater::CWater(CEngine* engine)
{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_WATER, this);
-
m_engine = engine;
m_terrain = nullptr;
- m_particule = nullptr;
+ m_particle = nullptr;
m_sound = nullptr;
m_type[0] = WATER_NULL;
@@ -67,10 +66,9 @@ CWater::CWater(CInstanceManager* iMan, CEngine* engine)
CWater::~CWater()
{
- m_iMan = nullptr;
m_engine = nullptr;
m_terrain = nullptr;
- m_particule = nullptr;
+ m_particle = nullptr;
m_sound = nullptr;
}
@@ -99,8 +97,8 @@ bool CWater::EventFrame(const Event &event)
void CWater::LavaFrame(float rTime)
{
- if (m_particule == nullptr)
- m_particule = static_cast<CParticle*>( m_iMan->SearchInstance(CLASS_PARTICULE) );
+ if (m_particle == nullptr)
+ m_particle = m_engine->GetParticle();
for (int i = 0; i < static_cast<int>( m_vapors.size() ); i++)
VaporFrame(i, rTime);
@@ -183,7 +181,7 @@ void CWater::VaporFrame(int i, float rTime)
m_vapors[i].time += rTime;
if (m_sound == nullptr)
- m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+ m_sound = CApplication::GetInstancePointer()->GetSound();
if (m_vapors[i].time <= m_vapors[i].delay)
{
@@ -206,7 +204,7 @@ void CWater::VaporFrame(int i, float rTime)
Math::Point dim;
dim.x = Math::Rand()*1.5f+1.5f;
dim.y = dim.x;
- m_particule->CreateParticle(pos, speed, dim, PARTIERROR, 2.0f, 10.0f);
+ m_particle->CreateParticle(pos, speed, dim, PARTIERROR, 2.0f, 10.0f);
}
}
else if (m_vapors[i].type == PARTIFLAME)
@@ -222,7 +220,7 @@ void CWater::VaporFrame(int i, float rTime)
Math::Point dim;
dim.x = Math::Rand()*2.0f+2.0f;
dim.y = dim.x;
- m_particule->CreateParticle(pos, speed, dim, PARTIFLAME);
+ m_particle->CreateParticle(pos, speed, dim, PARTIFLAME);
}
else
{
@@ -237,7 +235,7 @@ void CWater::VaporFrame(int i, float rTime)
Math::Point dim;
dim.x = Math::Rand()*1.0f+1.0f;
dim.y = dim.x;
- m_particule->CreateParticle(pos, speed, dim, PARTIVAPOR);
+ m_particle->CreateParticle(pos, speed, dim, PARTIVAPOR);
}
}
}
@@ -386,9 +384,11 @@ void CWater::DrawSurf()
Math::Vector p = pos;
p.x += size*(m_lines[i].len-1);
float radius = sqrtf(powf(size, 2.0f)+powf(size*m_lines[i].len, 2.0f));
- if ( Math::Distance(p, eye) > deep+radius ) continue;
+ if (Math::Distance(p, eye) > deep + radius)
+ continue;
- // TODO: ComputeSphereVisibility
+ if (device->ComputeSphereVisibility(p, radius) != Gfx::FRUSTUM_PLANE_ALL)
+ continue;
int vertexIndex = 0;
@@ -495,7 +495,7 @@ void CWater::Create(WaterType type1, WaterType type2, const std::string& fileNam
m_engine->LoadTexture(m_fileName);
if (m_terrain == nullptr)
- m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+ m_terrain = CRobotMain::GetInstancePointer()->GetTerrain();
m_brickCount = m_terrain->GetBrickCount()*m_terrain->GetMosaicCount();
m_brickSize = m_terrain->GetBrickSize();
diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h
index 21d96d4..bb113e0 100644
--- a/src/graphics/engine/water.h
+++ b/src/graphics/engine/water.h
@@ -28,7 +28,6 @@
#include "graphics/engine/particle.h"
-class CInstanceManager;
class CSoundInterface;
@@ -117,8 +116,8 @@ enum WaterType
class CWater
{
public:
- CWater(CInstanceManager* iMan, CEngine* engine);
- ~CWater();
+ CWater(CEngine* engine);
+ virtual ~CWater();
void SetDevice(CDevice* device);
bool EventProcess(const Event &event);
@@ -168,11 +167,10 @@ protected:
void VaporFrame(int i, float rTime);
protected:
- CInstanceManager* m_iMan;
CEngine* m_engine;
CDevice* m_device;
CTerrain* m_terrain;
- CParticle* m_particule;
+ CParticle* m_particle;
CSoundInterface* m_sound;
WaterType m_type[2];
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index 94b0dbc..df64e34 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -24,23 +24,10 @@
#include "math/geometry.h"
-#if defined(USE_GLEW)
-
-// When using GLEW, only glew.h is needed
+// Using GLEW so only glew.h is needed
#include <GL/glew.h>
-#else
-
-// Should define prototypes of used extensions as OpenGL functions
-#define GL_GLEXT_PROTOTYPES
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include <GL/glext.h>
-
-#endif // if defined(GLEW)
-
-#include <SDL/SDL.h>
+#include <SDL.h>
#include <cassert>
@@ -64,6 +51,8 @@ void GLDeviceConfig::LoadDefault()
greenSize = 8;
alphaSize = 8;
depthSize = 24;
+
+ vboMode = VBO_MODE_AUTO;
}
@@ -73,6 +62,9 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config)
{
m_config = config;
m_lighting = false;
+ m_lastVboId = 0;
+ m_multitextureAvailable = false;
+ m_vboAvailable = false;
}
@@ -91,29 +83,45 @@ bool CGLDevice::Create()
{
GetLogger()->Info("Creating CDevice\n");
-#if defined(USE_GLEW)
static bool glewInited = false;
if (!glewInited)
{
glewInited = true;
+ glewExperimental = GL_TRUE;
+
if (glewInit() != GLEW_OK)
{
GetLogger()->Error("GLEW initialization failed\n");
return false;
}
- if ( (! GLEW_ARB_multitexture) || (! GLEW_EXT_texture_env_combine) )
+ m_multitextureAvailable = glewIsSupported("GL_ARB_multitexture GL_ARB_texture_env_combine");
+ if (!m_multitextureAvailable)
+ GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
+
+ if (m_config.vboMode == VBO_MODE_ENABLE)
{
- GetLogger()->Error("GLEW reports required extensions not supported\n");
- return false;
+ GetLogger()->Info("VBO enabled by override - using VBOs\n");
+ m_vboAvailable = true;
}
- }
-#endif
+ else if (m_config.vboMode == VBO_MODE_DISABLE)
+ {
+ GetLogger()->Info("VBO disabled by override - using display lists\n");
+ m_vboAvailable = false;
+ }
+ else
+ {
+ GetLogger()->Info("Auto-detecting VBO support\n");
+ m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object");
- /* NOTE: when not using GLEW, extension testing is not performed, as it is assumed that
- glext.h is up-to-date and the OpenGL shared library has the required functions present. */
+ if (m_vboAvailable)
+ GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n");
+ else
+ GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n");
+ }
+ }
// This is mostly done in all modern hardware by default
// DirectX doesn't even allow the option to turn off perspective correction anymore
@@ -123,6 +131,9 @@ bool CGLDevice::Create()
// To avoid problems with scaling & lighting
glEnable(GL_RESCALE_NORMAL);
+ // Minimal depth bias to avoid Z-fighting
+ SetDepthBias(0.001f);
+
// Set just to be sure
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glMatrixMode(GL_PROJECTION);
@@ -174,6 +185,16 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig)
Create();
}
+void CGLDevice::SetUseVbo(bool vboAvailable)
+{
+ m_vboAvailable = vboAvailable;
+}
+
+bool CGLDevice::GetUseVbo()
+{
+ return m_vboAvailable;
+}
+
void CGLDevice::BeginScene()
{
Clear();
@@ -413,7 +434,9 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
result.size.y = data->surface->h;
// Use & enable 1st texture stage
- glActiveTexture(GL_TEXTURE0);
+ if (m_multitextureAvailable)
+ glActiveTexture(GL_TEXTURE0);
+
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &result.id);
@@ -588,7 +611,7 @@ void CGLDevice::DestroyAllTextures()
m_allTextures.clear();
}
-int CGLDevice::GetMaxTextureCount()
+int CGLDevice::GetMaxTextureStageCount()
{
return m_currentTextures.size();
}
@@ -599,17 +622,21 @@ int CGLDevice::GetMaxTextureCount()
The setting is remembered, even if texturing is disabled at the moment. */
void CGLDevice::SetTexture(int index, const Texture &texture)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
bool same = m_currentTextures[index].id == texture.id;
m_currentTextures[index] = texture; // remember the new value
+ if (!m_multitextureAvailable && index != 0)
+ return;
+
if (same)
return; // nothing to do
- glActiveTexture(GL_TEXTURE0 + index);
+ if (m_multitextureAvailable)
+ glActiveTexture(GL_TEXTURE0 + index);
+
glBindTexture(GL_TEXTURE_2D, texture.id);
// Params need to be updated for the new bound texture
@@ -618,15 +645,19 @@ void CGLDevice::SetTexture(int index, const Texture &texture)
void CGLDevice::SetTexture(int index, unsigned int textureId)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
if (m_currentTextures[index].id == textureId)
return; // nothing to do
m_currentTextures[index].id = textureId;
- glActiveTexture(GL_TEXTURE0 + index);
+ if (!m_multitextureAvailable && index != 0)
+ return;
+
+ if (m_multitextureAvailable)
+ glActiveTexture(GL_TEXTURE0 + index);
+
glBindTexture(GL_TEXTURE_2D, textureId);
// Params need to be updated for the new bound texture
@@ -637,16 +668,14 @@ void CGLDevice::SetTexture(int index, unsigned int textureId)
Returns the previously assigned texture or invalid texture if the given stage is not enabled. */
Texture CGLDevice::GetTexture(int index)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
return m_currentTextures[index];
}
void CGLDevice::SetTextureEnabled(int index, bool enabled)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
bool same = m_texturesEnabled[index] == enabled;
@@ -655,7 +684,12 @@ void CGLDevice::SetTextureEnabled(int index, bool enabled)
if (same)
return; // nothing to do
- glActiveTexture(GL_TEXTURE0 + index);
+ if (!m_multitextureAvailable && index != 0)
+ return;
+
+ if (m_multitextureAvailable)
+ glActiveTexture(GL_TEXTURE0 + index);
+
if (enabled)
glEnable(GL_TEXTURE_2D);
else
@@ -664,8 +698,7 @@ void CGLDevice::SetTextureEnabled(int index, bool enabled)
bool CGLDevice::GetTextureEnabled(int index)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
return m_texturesEnabled[index];
}
@@ -676,17 +709,36 @@ bool CGLDevice::GetTextureEnabled(int index)
The settings are remembered, even if texturing is disabled at the moment. */
void CGLDevice::SetTextureStageParams(int index, const TextureStageParams &params)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
// Remember the settings
m_textureStageParams[index] = params;
+ if (!m_multitextureAvailable && index != 0)
+ return;
+
// Don't actually do anything if texture not set
if (! m_currentTextures[index].Valid())
return;
- glActiveTexture(GL_TEXTURE0 + index);
+ if (m_multitextureAvailable)
+ glActiveTexture(GL_TEXTURE0 + index);
+
+ if (params.wrapS == TEX_WRAP_CLAMP)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ else if (params.wrapS == TEX_WRAP_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ else assert(false);
+
+ if (params.wrapT == TEX_WRAP_CLAMP)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ else if (params.wrapT == TEX_WRAP_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ else assert(false);
+
+ // Texture env setting is silly without multitexturing
+ if (!m_multitextureAvailable)
+ return;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, params.factor.Array());
@@ -790,26 +842,12 @@ after_tex_color:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
else assert(false);
-
-after_tex_operations:
-
- if (params.wrapS == TEX_WRAP_CLAMP)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- else if (params.wrapS == TEX_WRAP_REPEAT)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- else assert(false);
-
- if (params.wrapT == TEX_WRAP_CLAMP)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- else if (params.wrapT == TEX_WRAP_REPEAT)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- else assert(false);
+after_tex_operations: ;
}
void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wrapT)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
// Remember the settings
m_textureStageParams[index].wrapS = wrapS;
@@ -819,7 +857,11 @@ void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wr
if (! m_currentTextures[index].Valid())
return;
- glActiveTexture(GL_TEXTURE0 + index);
+ if (!m_multitextureAvailable && index != 0)
+ return;
+
+ if (m_multitextureAvailable)
+ glActiveTexture(GL_TEXTURE0 + index);
if (wrapS == TEX_WRAP_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
@@ -836,8 +878,7 @@ void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wr
TextureStageParams CGLDevice::GetTextureStageParams(int index)
{
- assert(index >= 0);
- assert(index < static_cast<int>( m_currentTextures.size() ));
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
return m_textureStageParams[index];
}
@@ -868,7 +909,9 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int ve
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(Vertex), reinterpret_cast<GLfloat*>(&vs[0].normal));
- glClientActiveTexture(GL_TEXTURE0);
+ if (m_multitextureAvailable)
+ glClientActiveTexture(GL_TEXTURE0);
+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<GLfloat*>(&vs[0].texCoord));
@@ -892,13 +935,18 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, in
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].normal));
- glClientActiveTexture(GL_TEXTURE0);
+ if (m_multitextureAvailable)
+ glClientActiveTexture(GL_TEXTURE0);
+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord));
- glClientActiveTexture(GL_TEXTURE1);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord2));
+ if (m_multitextureAvailable)
+ {
+ glClientActiveTexture(GL_TEXTURE1);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord2));
+ }
glColor4fv(color.Array());
@@ -907,8 +955,11 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, in
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1
- glClientActiveTexture(GL_TEXTURE0);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ if (m_multitextureAvailable)
+ {
+ glClientActiveTexture(GL_TEXTURE0);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
}
void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount)
@@ -927,29 +978,318 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int
glDisableClientState(GL_COLOR_ARRAY);
}
+unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount)
+{
+ unsigned int id = 0;
+ if (m_vboAvailable)
+ {
+ id = ++m_lastVboId;
+
+ VboObjectInfo info;
+ info.primitiveType = primitiveType;
+ info.vertexType = VERTEX_TYPE_NORMAL;
+ info.vertexCount = vertexCount;
+ info.bufferId = 0;
+
+ glGenBuffers(1, &info.bufferId);
+ glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_vboObjects[id] = info;
+ }
+ else
+ {
+ id = glGenLists(1);
+
+ glNewList(id, GL_COMPILE);
+
+ DrawPrimitive(primitiveType, vertices, vertexCount);
+
+ glEndList();
+ }
+
+ return id;
+}
+
+unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount)
+{
+ unsigned int id = 0;
+ if (m_vboAvailable)
+ {
+ id = ++m_lastVboId;
+
+ VboObjectInfo info;
+ info.primitiveType = primitiveType;
+ info.vertexType = VERTEX_TYPE_TEX2;
+ info.vertexCount = vertexCount;
+ info.bufferId = 0;
+
+ glGenBuffers(1, &info.bufferId);
+ glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_vboObjects[id] = info;
+ }
+ else
+ {
+ id = glGenLists(1);
+
+ glNewList(id, GL_COMPILE);
+
+ DrawPrimitive(primitiveType, vertices, vertexCount);
+
+ glEndList();
+ }
+
+ return id;
+}
+
+unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount)
+{
+ unsigned int id = 0;
+ if (m_vboAvailable)
+ {
+ id = ++m_lastVboId;
+
+ VboObjectInfo info;
+ info.primitiveType = primitiveType;
+ info.vertexType = VERTEX_TYPE_COL;
+ info.vertexCount = vertexCount;
+ info.bufferId = 0;
+
+ glGenBuffers(1, &info.bufferId);
+ glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_vboObjects[id] = info;
+ }
+ else
+ {
+ id = glGenLists(1);
+
+ glNewList(id, GL_COMPILE);
+
+ DrawPrimitive(primitiveType, vertices, vertexCount);
+
+ glEndList();
+ }
+
+ return id;
+}
+
+void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount)
+{
+ if (m_vboAvailable)
+ {
+ auto it = m_vboObjects.find(bufferId);
+ if (it == m_vboObjects.end())
+ return;
+
+ VboObjectInfo& info = (*it).second;
+ info.primitiveType = primitiveType;
+ info.vertexType = VERTEX_TYPE_NORMAL;
+ info.vertexCount = vertexCount;
+
+ glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ else
+ {
+ glNewList(bufferId, GL_COMPILE);
+
+ DrawPrimitive(primitiveType, vertices, vertexCount);
+
+ glEndList();
+ }
+}
+
+void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount)
+{
+ if (m_vboAvailable)
+ {
+ auto it = m_vboObjects.find(bufferId);
+ if (it == m_vboObjects.end())
+ return;
+
+ VboObjectInfo& info = (*it).second;
+ info.primitiveType = primitiveType;
+ info.vertexType = VERTEX_TYPE_TEX2;
+ info.vertexCount = vertexCount;
+
+ glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ else
+ {
+ glNewList(bufferId, GL_COMPILE);
+
+ DrawPrimitive(primitiveType, vertices, vertexCount);
+
+ glEndList();
+ }
+}
+
+void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount)
+{
+ if (m_vboAvailable)
+ {
+ auto it = m_vboObjects.find(bufferId);
+ if (it == m_vboObjects.end())
+ return;
+
+ VboObjectInfo& info = (*it).second;
+ info.primitiveType = primitiveType;
+ info.vertexType = VERTEX_TYPE_COL;
+ info.vertexCount = vertexCount;
+
+ glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
+ glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ else
+ {
+ glNewList(bufferId, GL_COMPILE);
+
+ DrawPrimitive(primitiveType, vertices, vertexCount);
+
+ glEndList();
+ }
+}
+
+void CGLDevice::DrawStaticBuffer(unsigned int bufferId)
+{
+ if (m_vboAvailable)
+ {
+ auto it = m_vboObjects.find(bufferId);
+ if (it == m_vboObjects.end())
+ return;
+
+ glEnable(GL_VERTEX_ARRAY);
+ glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId);
+
+ if ((*it).second.vertexType == VERTEX_TYPE_NORMAL)
+ {
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, coord));
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, normal));
+
+ if (m_multitextureAvailable)
+ glClientActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, texCoord));
+ }
+ else if ((*it).second.vertexType == VERTEX_TYPE_TEX2)
+ {
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, coord));
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, normal));
+
+ if (m_multitextureAvailable)
+ glClientActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, texCoord));
+
+ if (m_multitextureAvailable)
+ {
+ glClientActiveTexture(GL_TEXTURE1);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, texCoord2));
+ }
+ }
+ else if ((*it).second.vertexType == VERTEX_TYPE_COL)
+ {
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(VertexCol), static_cast<char*>(nullptr) + offsetof(VertexCol, coord));
+
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(4, GL_FLOAT, sizeof(VertexCol), static_cast<char*>(nullptr) + offsetof(VertexCol, color));
+ }
+
+ GLenum mode = TranslateGfxPrimitive((*it).second.primitiveType);
+ glDrawArrays(mode, 0, (*it).second.vertexCount);
+
+ if ((*it).second.vertexType == VERTEX_TYPE_NORMAL)
+ {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE0
+ }
+ else if ((*it).second.vertexType == VERTEX_TYPE_TEX2)
+ {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1
+ if (m_multitextureAvailable)
+ {
+ glClientActiveTexture(GL_TEXTURE0);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+ else if ((*it).second.vertexType == VERTEX_TYPE_COL)
+ {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glDisable(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ glCallList(bufferId);
+ }
+}
+
+void CGLDevice::DestroyStaticBuffer(unsigned int bufferId)
+{
+ if (m_vboAvailable)
+ {
+ auto it = m_vboObjects.find(bufferId);
+ if (it == m_vboObjects.end())
+ return;
+
+ glDeleteBuffers(1, &(*it).second.bufferId);
+
+ m_vboObjects.erase(it);
+ }
+ else
+ {
+ glDeleteLists(bufferId, 1);
+ }
+}
+
bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius)
{
- float distance = (originPlane + Math::DotProduct(normal, center)) / normal.Length();
+ float distance = originPlane + Math::DotProduct(normal, center);
if (distance < -radius)
- return true;
+ return false;
- return false;
+ return true;
}
-/*
- The implementation of ComputeSphereVisibility is taken from libwine's device.c
- Copyright of the WINE team, licensed under GNU LGPL v 2.1
- */
+/* Based on libwine's implementation */
-// TODO: testing
int CGLDevice::ComputeSphereVisibility(const Math::Vector &center, float radius)
{
Math::Matrix m;
- m.LoadIdentity();
- m = Math::MultiplyMatrices(m, m_worldMat);
- m = Math::MultiplyMatrices(m, m_viewMat);
- m = Math::MultiplyMatrices(m, m_projectionMat);
+ m = Math::MultiplyMatrices(m_worldMat, m);
+ m = Math::MultiplyMatrices(m_viewMat, m);
+ Math::Matrix sc;
+ Math::LoadScaleMatrix(sc, Math::Vector(1.0f, 1.0f, -1.0f));
+ m = Math::MultiplyMatrices(sc, m);
+ m = Math::MultiplyMatrices(m_projectionMat, m);
Math::Vector vec[6];
float originPlane[6];
@@ -958,52 +1298,64 @@ int CGLDevice::ComputeSphereVisibility(const Math::Vector &center, float radius)
vec[0].x = m.Get(4, 1) + m.Get(1, 1);
vec[0].y = m.Get(4, 2) + m.Get(1, 2);
vec[0].z = m.Get(4, 3) + m.Get(1, 3);
- originPlane[0] = m.Get(4, 4) + m.Get(1, 4);
+ float l1 = vec[0].Length();
+ vec[0].Normalize();
+ originPlane[0] = (m.Get(4, 4) + m.Get(1, 4)) / l1;
// Right plane
vec[1].x = m.Get(4, 1) - m.Get(1, 1);
vec[1].y = m.Get(4, 2) - m.Get(1, 2);
vec[1].z = m.Get(4, 3) - m.Get(1, 3);
- originPlane[1] = m.Get(4, 4) - m.Get(1, 4);
-
- // Top plane
- vec[2].x = m.Get(4, 1) - m.Get(2, 1);
- vec[2].y = m.Get(4, 2) - m.Get(2, 2);
- vec[2].z = m.Get(4, 3) - m.Get(2, 3);
- originPlane[2] = m.Get(4, 4) - m.Get(2, 4);
+ float l2 = vec[1].Length();
+ vec[1].Normalize();
+ originPlane[1] = (m.Get(4, 4) - m.Get(1, 4)) / l2;
// Bottom plane
- vec[3].x = m.Get(4, 1) + m.Get(2, 1);
- vec[3].y = m.Get(4, 2) + m.Get(2, 2);
- vec[3].z = m.Get(4, 3) + m.Get(2, 3);
- originPlane[3] = m.Get(4, 4) + m.Get(2, 4);
+ vec[2].x = m.Get(4, 1) + m.Get(2, 1);
+ vec[2].y = m.Get(4, 2) + m.Get(2, 2);
+ vec[2].z = m.Get(4, 3) + m.Get(2, 3);
+ float l3 = vec[2].Length();
+ vec[2].Normalize();
+ originPlane[2] = (m.Get(4, 4) + m.Get(2, 4)) / l3;
+
+ // Top plane
+ vec[3].x = m.Get(4, 1) - m.Get(2, 1);
+ vec[3].y = m.Get(4, 2) - m.Get(2, 2);
+ vec[3].z = m.Get(4, 3) - m.Get(2, 3);
+ float l4 = vec[3].Length();
+ vec[3].Normalize();
+ originPlane[3] = (m.Get(4, 4) - m.Get(2, 4)) / l4;
// Front plane
- vec[4].x = m.Get(3, 1);
- vec[4].y = m.Get(3, 2);
- vec[4].z = m.Get(3, 3);
- originPlane[4] = m.Get(3, 4);
+ vec[4].x = m.Get(4, 1) + m.Get(3, 1);
+ vec[4].y = m.Get(4, 2) + m.Get(3, 2);
+ vec[4].z = m.Get(4, 3) + m.Get(3, 3);
+ float l5 = vec[4].Length();
+ vec[4].Normalize();
+ originPlane[4] = (m.Get(4, 4) + m.Get(3, 4)) / l5;
// Back plane
vec[5].x = m.Get(4, 1) - m.Get(3, 1);
vec[5].y = m.Get(4, 2) - m.Get(3, 2);
vec[5].z = m.Get(4, 3) - m.Get(3, 3);
- originPlane[5] = m.Get(4, 4) - m.Get(3, 4);
+ float l6 = vec[5].Length();
+ vec[5].Normalize();
+ originPlane[5] = (m.Get(4, 4) - m.Get(3, 4)) / l6;
int result = 0;
if (InPlane(vec[0], originPlane[0], center, radius))
- result |= INTERSECT_PLANE_LEFT;
+ result |= FRUSTUM_PLANE_LEFT;
if (InPlane(vec[1], originPlane[1], center, radius))
- result |= INTERSECT_PLANE_RIGHT;
+ result |= FRUSTUM_PLANE_RIGHT;
if (InPlane(vec[2], originPlane[2], center, radius))
- result |= INTERSECT_PLANE_TOP;
+ result |= FRUSTUM_PLANE_BOTTOM;
if (InPlane(vec[3], originPlane[3], center, radius))
- result |= INTERSECT_PLANE_BOTTOM;
+ result |= FRUSTUM_PLANE_TOP;
if (InPlane(vec[4], originPlane[4], center, radius))
- result |= INTERSECT_PLANE_FRONT;
+ result |= FRUSTUM_PLANE_FRONT;
if (InPlane(vec[5], originPlane[5], center, radius))
- result |= INTERSECT_PLANE_BACK;
+ result |= FRUSTUM_PLANE_BACK;
return result;
}
@@ -1042,7 +1394,6 @@ void CGLDevice::SetRenderState(RenderState state, bool enabled)
case RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
case RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break;
case RENDER_STATE_CULLING: flag = GL_CULL_FACE; break;
- case RENDER_STATE_DITHERING: flag = GL_DITHER; break;
default: assert(false); break;
}
@@ -1067,7 +1418,6 @@ bool CGLDevice::GetRenderState(RenderState state)
case RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
case RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break;
case RENDER_STATE_CULLING: flag = GL_CULL_FACE; break;
- case RENDER_STATE_DITHERING: flag = GL_DITHER; break;
default: assert(false); break;
}
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index 87c1247..fe3f2a1 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -27,12 +27,24 @@
#include <string>
#include <vector>
#include <set>
+#include <map>
// Graphics module namespace
namespace Gfx {
/**
+ \enum VBOMode
+ \brief VBO autodetect/override
+ */
+enum VBOMode
+{
+ VBO_MODE_ENABLE, //! < override: enable
+ VBO_MODE_DISABLE, //! < override: disable
+ VBO_MODE_AUTO //! < autodetect
+};
+
+/**
\struct GLDeviceConfig
\brief Additional config with OpenGL-specific settings */
struct GLDeviceConfig : public DeviceConfig
@@ -51,6 +63,9 @@ struct GLDeviceConfig : public DeviceConfig
//! Force hardware acceleration (video mode set will fail on lack of hw accel)
bool hardwareAccel;
+ //! VBO override/autodetect
+ VBOMode vboMode;
+
//! Constructor calls LoadDefaults()
GLDeviceConfig();
@@ -84,6 +99,9 @@ public:
void ConfigChanged(const GLDeviceConfig &newConfig);
+ void SetUseVbo(bool useVbo);
+ bool GetUseVbo();
+
virtual void BeginScene();
virtual void EndScene();
@@ -107,7 +125,7 @@ public:
virtual void DestroyTexture(const Texture &texture);
virtual void DestroyAllTextures();
- virtual int GetMaxTextureCount();
+ virtual int GetMaxTextureStageCount();
virtual void SetTexture(int index, const Texture &texture);
virtual void SetTexture(int index, unsigned int textureId);
virtual Texture GetTexture(int index);
@@ -119,14 +137,21 @@ public:
virtual void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT);
- //! Renders primitive composed of vertices with single texture
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
- //! Renders primitive composed of vertices with multitexturing (2 textures)
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount);
+ virtual unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount);
+ virtual unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount);
+ virtual unsigned int CreateStaticBuffer(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount);
+ virtual void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount);
+ virtual void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount);
+ virtual void UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount);
+ virtual void DrawStaticBuffer(unsigned int bufferId);
+ virtual void DestroyStaticBuffer(unsigned int bufferId);
+
virtual int ComputeSphereVisibility(const Math::Vector &center, float radius);
virtual void SetRenderState(RenderState state, bool enabled);
@@ -200,6 +225,32 @@ private:
//! Set of all created textures
std::set<Texture> m_allTextures;
+
+ //! Type of vertex structure
+ enum VertexType
+ {
+ VERTEX_TYPE_NORMAL,
+ VERTEX_TYPE_TEX2,
+ VERTEX_TYPE_COL,
+ };
+
+ //! Info about static VBO buffers
+ struct VboObjectInfo
+ {
+ PrimitiveType primitiveType;
+ unsigned int bufferId;
+ VertexType vertexType;
+ int vertexCount;
+ };
+
+ //! Whether to use multitexturing
+ bool m_multitextureAvailable;
+ //! Whether to use VBOs or display lists
+ bool m_vboAvailable;
+ //! Map of saved VBO objects
+ std::map<unsigned int, VboObjectInfo> m_vboObjects;
+ //! Last ID of VBO object
+ unsigned int m_lastVboId;
};
diff --git a/src/graphics/opengl/test/CMakeLists.txt b/src/graphics/opengl/test/CMakeLists.txt
deleted file mode 100644
index 79e0ba5..0000000
--- a/src/graphics/opengl/test/CMakeLists.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-find_package(OpenGL REQUIRED)
-find_package(SDL REQUIRED)
-find_package(SDL_image REQUIRED)
-find_package(PNG REQUIRED)
-
-if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE debug)
-endif(NOT CMAKE_BUILD_TYPE)
-set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
-
-set(ADD_LIBS "")
-
-if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
- set(PLATFORM_WINDOWS 1)
- set(PLATFORM_LINUX 0)
- set(PLATFORM_OTHER 0)
-elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- set(PLATFORM_WINDOWS 0)
- set(PLATFORM_LINUX 1)
- set(PLATFORM_OTHER 0)
- set(ADD_LIBS "-lrt")
-else()
- set(PLATFORM_WINDOWS 0)
- set(PLATFORM_LINUX 0)
- set(PLATFORM_OTHER 1)
-endif()
-
-configure_file(../../../common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h)
-
-
-set(TEXTURE_SOURCES
-../gldevice.cpp
-../../../common/logger.cpp
-../../../common/image.cpp
-texture_test.cpp
-)
-
-set(MODEL_SOURCES
-../gldevice.cpp
-../../engine/modelfile.cpp
-../../../common/logger.cpp
-../../../common/image.cpp
-../../../common/iman.cpp
-../../../common/stringutils.cpp
-../../../app/system.cpp
-model_test.cpp
-)
-
-set(TRANSFORM_SOURCES
-../gldevice.cpp
-../../../common/logger.cpp
-../../../common/image.cpp
-../../../common/iman.cpp
-../../../app/system.cpp
-transform_test.cpp
-)
-
-set(LIGHT_SOURCES
-../gldevice.cpp
-../../../common/logger.cpp
-../../../common/image.cpp
-../../../common/iman.cpp
-../../../app/system.cpp
-light_test.cpp
-)
-
-include_directories(../../../ ${CMAKE_CURRENT_BINARY_DIR})
-
-set(LIBS
-${SDL_LIBRARY}
-${SDLIMAGE_LIBRARY}
-${OPENGL_LIBRARY}
-${PNG_LIBRARIES}
-${ADD_LIBS}
-)
-
-add_executable(texture_test ${TEXTURE_SOURCES})
-target_link_libraries(texture_test ${LIBS})
-
-# Temporarily disabling because of dependencies on CEngine et al.
-#add_executable(model_test ${MODEL_SOURCES})
-#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})
diff --git a/src/graphics/opengl/test/README.txt b/src/graphics/opengl/test/README.txt
deleted file mode 100644
index c618415..0000000
--- a/src/graphics/opengl/test/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Test programs for OpenGL engine:
- - texture_test -> multitexturing test with 2 textures (included as files: ./tex1.png, ./tex2.png)
- - model_test -> simple model viewer to test model loading
- usage: ./model_test {dxf|mod} model_file
- second argument is the loaded format (DXF or Colobot .mod files)
- requires ./tex folder (or symlink) with Colobot textures
- viewer is controlled from keyboard - the bindings can be found in code
- - transform_test -> simple "walk around" test for world & view transformations
- - light test -> test for lighting
diff --git a/src/graphics/opengl/test/light_test.cpp b/src/graphics/opengl/test/light_test.cpp
deleted file mode 100644
index 6ff3b1c..0000000
--- a/src/graphics/opengl/test/light_test.cpp
+++ /dev/null
@@ -1,437 +0,0 @@
-#include "app/system.h"
-#include "common/logger.h"
-#include "common/image.h"
-#include "common/iman.h"
-#include "graphics/opengl/gldevice.h"
-#include "math/geometry.h"
-
-#include <SDL/SDL.h>
-#include <SDL/SDL_image.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <map>
-
-enum KeySlots
-{
- K_Forward,
- K_Back,
- K_Left,
- K_Right,
- K_Up,
- K_Down,
- K_Count
-};
-bool KEYMAP[K_Count] = { false };
-
-Math::Point MOUSE_POS_BASE;
-
-Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f);
-Math::Vector ROTATION, ROTATION_BASE;
-
-float CUBE_ORBIT = 0.0f;
-
-const int FRAME_DELAY = 5000;
-
-SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL;
-
-void Init(Gfx::CGLDevice *device)
-{
- device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true);
- device->SetShadeModel(Gfx::SHADE_SMOOTH);
-}
-
-void Render(Gfx::CGLDevice *device)
-{
- device->BeginScene();
-
- /* Unlit part of scene */
-
- device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false);
- device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); // Double-sided drawing
-
- Math::Matrix persp;
- Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f);
- device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);
-
-
- Math::Matrix viewMat;
- Math::Matrix mat;
-
- viewMat.LoadIdentity();
-
- Math::LoadRotationXMatrix(mat, -ROTATION.x);
- viewMat = Math::MultiplyMatrices(viewMat, mat);
-
- Math::LoadRotationYMatrix(mat, -ROTATION.y);
- viewMat = Math::MultiplyMatrices(viewMat, mat);
-
- Math::LoadTranslationMatrix(mat, -TRANSLATION);
- viewMat = Math::MultiplyMatrices(viewMat, mat);
-
- device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);
-
- Math::Matrix worldMat;
- worldMat.LoadIdentity();
- device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
-
- Gfx::VertexCol line[2] = { Gfx::VertexCol() };
-
- for (int x = -40; x <= 40; ++x)
- {
- line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
- line[0].coord.z = -40;
- line[0].coord.x = x;
- line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
- line[1].coord.z = 40;
- line[1].coord.x = x;
- device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
- }
-
- for (int z = -40; z <= 40; ++z)
- {
- line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
- line[0].coord.z = z;
- line[0].coord.x = -40;
- line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
- line[1].coord.z = z;
- line[1].coord.x = 40;
- device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
- }
-
-
- Gfx::VertexCol quad[6] = { Gfx::VertexCol() };
-
- quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f);
- quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f);
- quad[2].coord = Math::Vector(-1.0f, 1.0f, 0.0f);
- quad[3].coord = Math::Vector( 1.0f, 1.0f, 0.0f);
-
- for (int i = 0; i < 6; ++i)
- quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f);
-
- Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f));
- device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
-
- for (int i = 0; i < 6; ++i)
- quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f);
-
- Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f));
- device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
-
- for (int i = 0; i < 6; ++i)
- quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f);
-
- Math::LoadTranslationMatrix(worldMat, Math::Vector(10.0f, 4.5f, 5.0f));
- device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
-
- /* Moving lit cube */
- device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true);
- device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); // Culling (CCW faces)
-
- device->SetGlobalAmbient(Gfx::Color(0.4f, 0.4f, 0.4f));
-
- Gfx::Light light1;
- light1.type = Gfx::LIGHT_POINT;
- light1.position = Math::Vector(10.0f, 4.5f, 5.0f);
- light1.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
- light1.diffuse = Gfx::Color(1.0f, 0.1f, 0.1f);
- light1.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
- device->SetLight(0, light1);
- device->SetLightEnabled(0, true);
-
- /*Gfx::Light light2;
- device->SetLight(1, light2);
- device->SetLightEnabled(1, true);*/
-
- Gfx::Material material;
- material.ambient = Gfx::Color(0.3f, 0.3f, 0.3f);
- material.diffuse = Gfx::Color(0.8f, 0.7f, 0.6f);
- material.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
- device->SetMaterial(material);
-
- const Gfx::Vertex cube[6][4] =
- {
- {
- // Front
- Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f))
- },
-
- {
- // Back
- Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f))
- },
-
- {
- // Top
- Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f))
- },
-
- {
- // Bottom
- Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f))
- },
-
- {
- // Left
- Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
- Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f))
- },
-
- {
- // Right
- Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
- Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f))
- }
- };
-
- Math::Matrix cubeTrans;
- Math::LoadTranslationMatrix(cubeTrans, Math::Vector(10.0f, 2.0f, 5.0f));
- Math::Matrix cubeRot;
- Math::LoadRotationMatrix(cubeRot, Math::Vector(0.0f, 1.0f, 0.0f), CUBE_ORBIT);
- Math::Matrix cubeRotInv;
- Math::LoadRotationMatrix(cubeRotInv, Math::Vector(0.0f, 1.0f, 0.0f), -CUBE_ORBIT);
- Math::Matrix cubeTransRad;
- Math::LoadTranslationMatrix(cubeTransRad, Math::Vector(0.0f, 0.0f, 6.0f));
- worldMat = Math::MultiplyMatrices(cubeTransRad, cubeRotInv);
- worldMat = Math::MultiplyMatrices(cubeRot, worldMat);
- worldMat = Math::MultiplyMatrices(cubeTrans, worldMat);
- device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
-
- for (int i = 0; i < 6; ++i)
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, cube[i], 4);
-
- device->EndScene();
-}
-
-void Update()
-{
- const float TRANS_SPEED = 6.0f; // units / sec
-
- GetCurrentTimeStamp(CURR_TIME);
- float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC);
- CopyTimeStamp(PREV_TIME, CURR_TIME);
-
- CUBE_ORBIT += timeDiff * (Math::PI / 4.0f);
-
- Math::Vector incTrans;
-
- if (KEYMAP[K_Forward])
- incTrans.z = +TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Back])
- incTrans.z = -TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Right])
- incTrans.x = +TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Left])
- incTrans.x = -TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Up])
- incTrans.y = +TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Down])
- incTrans.y = -TRANS_SPEED * timeDiff;
-
- Math::Point rotTrans = Math::RotatePoint(-ROTATION.y, Math::Point(incTrans.x, incTrans.z));
- incTrans.x = rotTrans.x;
- incTrans.z = rotTrans.y;
- TRANSLATION += incTrans;
-}
-
-void KeyboardDown(SDLKey key)
-{
- switch (key)
- {
- case SDLK_w:
- KEYMAP[K_Forward] = true;
- break;
- case SDLK_s:
- KEYMAP[K_Back] = true;
- break;
- case SDLK_d:
- KEYMAP[K_Right] = true;
- break;
- case SDLK_a:
- KEYMAP[K_Left] = true;
- break;
- case SDLK_z:
- KEYMAP[K_Down] = true;
- break;
- case SDLK_x:
- KEYMAP[K_Up] = true;
- break;
- default:
- break;
- }
-}
-
-void KeyboardUp(SDLKey key)
-{
- switch (key)
- {
- case SDLK_w:
- KEYMAP[K_Forward] = false;
- break;
- case SDLK_s:
- KEYMAP[K_Back] = false;
- break;
- case SDLK_d:
- KEYMAP[K_Right] = false;
- break;
- case SDLK_a:
- KEYMAP[K_Left] = false;
- break;
- case SDLK_z:
- KEYMAP[K_Down] = false;
- break;
- case SDLK_x:
- KEYMAP[K_Up] = false;
- break;
- default:
- break;
- }
-}
-
-void MouseMove(int x, int y)
-{
- Math::Point currentPos(static_cast<float>(x), static_cast<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 + (static_cast<float> (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI;
- ROTATION.x = ROTATION_BASE.x + (static_cast<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(Gfx::GLDeviceConfig());
- 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;
-}
diff --git a/src/graphics/opengl/test/model_test.cpp b/src/graphics/opengl/test/model_test.cpp
deleted file mode 100644
index e951e6e..0000000
--- a/src/graphics/opengl/test/model_test.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-#include "app/system.h"
-#include "common/logger.h"
-#include "common/image.h"
-#include "common/iman.h"
-#include "graphics/engine/modelfile.h"
-#include "graphics/opengl/gldevice.h"
-#include "math/geometry.h"
-
-#include <SDL/SDL.h>
-#include <SDL/SDL_image.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <map>
-
-enum KeySlots
-{
- K_RotXUp,
- K_RotXDown,
- K_RotYLeft,
- K_RotYRight,
- K_Forward,
- K_Back,
- K_Left,
- K_Right,
- K_Up,
- K_Down,
- K_Count
-};
-bool KEYMAP[K_Count] = { false };
-
-Math::Vector TRANSLATION(0.0f, 0.0f, 30.0f);
-Math::Vector ROTATION;
-
-const int FRAME_DELAY = 5000;
-
-std::map<std::string, Gfx::Texture> TEXS;
-
-SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL;
-
-Gfx::Texture GetTexture(const std::string &name)
-{
- std::map<std::string, Gfx::Texture>::iterator it = TEXS.find(name);
- if (it == TEXS.end())
- return Gfx::Texture();
-
- return (*it).second;
-}
-
-void LoadTexture(Gfx::CGLDevice *device, const std::string &name)
-{
- if (name.empty())
- return;
-
- Gfx::Texture tex = GetTexture(name);
-
- if (tex.Valid())
- return;
-
- CImage img;
- if (! img.Load(std::string("tex/") + name))
- {
- std::string err = img.GetError();
- GetLogger()->Error("Texture not loaded, error: %s!\n", err.c_str());
- }
- else
- {
- Gfx::TextureCreateParams texCreateParams;
- texCreateParams.mipmap = true;
- if (img.GetData()->surface->format->Amask == 0)
- texCreateParams.format = Gfx::TEX_IMG_BGR;
- else
- texCreateParams.format = Gfx::TEX_IMG_BGRA;
- texCreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
- texCreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
-
- tex = device->CreateTexture(&img, texCreateParams);
- }
-
- TEXS[name] = tex;
-}
-
-void Init(Gfx::CGLDevice *device, Gfx::CModelFile *model)
-{
- std::vector<Gfx::ModelTriangle> &triangles = model->GetTriangles();
-
- for (int i = 0; i < static_cast<int>( triangles.size() ); ++i)
- {
- LoadTexture(device, triangles[i].tex1Name);
- LoadTexture(device, triangles[i].tex2Name);
- }
-
- device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
- device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true);
- device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true);
- device->SetShadeModel(Gfx::SHADE_SMOOTH);
-
- Gfx::Light light;
- light.type = Gfx::LIGHT_DIRECTIONAL;
- light.ambient = Gfx::Color(0.4f, 0.4f, 0.4f, 0.0f);
- light.diffuse = Gfx::Color(0.8f, 0.8f, 0.8f, 0.0f);
- light.specular = Gfx::Color(0.2f, 0.2f, 0.2f, 0.0f);
- light.position = Math::Vector(0.0f, 0.0f, -1.0f);
- light.direction = Math::Vector(0.0f, 0.0f, 1.0f);
-
- device->SetGlobalAmbient(Gfx::Color(0.5f, 0.5f, 0.5f, 0.0f));
- device->SetLight(0, light);
- device->SetLightEnabled(0, true);
-}
-
-void Render(Gfx::CGLDevice *device, Gfx::CModelFile *modelFile)
-{
- device->BeginScene();
-
- 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 id;
- id.LoadIdentity();
- device->SetTransform(Gfx::TRANSFORM_WORLD, id);
-
- Math::Matrix viewMat;
- Math::LoadTranslationMatrix(viewMat, TRANSLATION);
- Math::Matrix rot;
- Math::LoadRotationXZYMatrix(rot, ROTATION);
- viewMat = Math::MultiplyMatrices(viewMat, rot);
- device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);
-
- std::vector<Gfx::ModelTriangle> &triangles = modelFile->GetTriangles();
-
- Gfx::VertexTex2 tri[3];
-
- for (int i = 0; i < static_cast<int>( triangles.size() ); ++i)
- {
- device->SetTexture(0, GetTexture(triangles[i].tex1Name));
- device->SetTexture(1, GetTexture(triangles[i].tex2Name));
- device->SetTextureEnabled(0, true);
- device->SetTextureEnabled(1, true);
-
- device->SetMaterial(triangles[i].material);
-
- tri[0] = triangles[i].p1;
- tri[1] = triangles[i].p2;
- tri[2] = triangles[i].p3;
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, tri, 3);
- }
-
- device->EndScene();
-}
-
-void Update()
-{
- const float ROT_SPEED = 80.0f * Math::DEG_TO_RAD; // rad / sec
- const float TRANS_SPEED = 3.0f; // units / sec
-
- GetCurrentTimeStamp(CURR_TIME);
- float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC);
- CopyTimeStamp(PREV_TIME, CURR_TIME);
-
- if (KEYMAP[K_RotYLeft])
- ROTATION.y -= ROT_SPEED * timeDiff;
- if (KEYMAP[K_RotYRight])
- ROTATION.y += ROT_SPEED * timeDiff;
- if (KEYMAP[K_RotXDown])
- ROTATION.x -= ROT_SPEED * timeDiff;
- if (KEYMAP[K_RotXUp])
- ROTATION.x += ROT_SPEED * timeDiff;
-
- if (KEYMAP[K_Forward])
- TRANSLATION.z -= TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Back])
- TRANSLATION.z += TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Left])
- TRANSLATION.x += TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Right])
- TRANSLATION.x -= TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Up])
- TRANSLATION.y += TRANS_SPEED * timeDiff;
- if (KEYMAP[K_Down])
- TRANSLATION.y -= TRANS_SPEED * timeDiff;
-}
-
-void KeyboardDown(SDLKey key)
-{
- switch (key)
- {
- case SDLK_LEFT:
- KEYMAP[K_RotYLeft] = true;
- break;
- case SDLK_RIGHT:
- KEYMAP[K_RotYRight] = true;
- break;
- case SDLK_UP:
- KEYMAP[K_RotXUp] = true;
- break;
- case SDLK_DOWN:
- KEYMAP[K_RotXDown] = true;
- break;
- case SDLK_w:
- KEYMAP[K_Forward] = true;
- break;
- case SDLK_s:
- KEYMAP[K_Back] = true;
- break;
- case SDLK_a:
- KEYMAP[K_Left] = true;
- break;
- case SDLK_d:
- KEYMAP[K_Right] = 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_LEFT:
- KEYMAP[K_RotYLeft] = false;
- break;
- case SDLK_RIGHT:
- KEYMAP[K_RotYRight] = false;
- break;
- case SDLK_UP:
- KEYMAP[K_RotXUp] = false;
- break;
- case SDLK_DOWN:
- KEYMAP[K_RotXDown] = false;
- break;
- case SDLK_w:
- KEYMAP[K_Forward] = false;
- break;
- case SDLK_s:
- KEYMAP[K_Back] = false;
- break;
- case SDLK_a:
- KEYMAP[K_Left] = false;
- break;
- case SDLK_d:
- KEYMAP[K_Right] = false;
- break;
- case SDLK_z:
- KEYMAP[K_Down] = false;
- break;
- case SDLK_x:
- KEYMAP[K_Up] = false;
- break;
- default:
- break;
- }
-}
-
-int main(int argc, char *argv[])
-{
- CLogger logger;
-
- PREV_TIME = CreateTimeStamp();
- CURR_TIME = CreateTimeStamp();
-
- GetCurrentTimeStamp(PREV_TIME);
- GetCurrentTimeStamp(CURR_TIME);
-
- if (argc != 3)
- {
- std::cerr << "Usage: " << argv[0] << "{mod|dxf} model_file" << std::endl;
- return 1;
- }
-
- CInstanceManager iMan;
-
- Gfx::CModelFile *modelFile = new Gfx::CModelFile(&iMan);
- if (std::string(argv[1]) == "mod")
- {
- if (! modelFile->ReadModel(argv[2], false, false))
- {
- std::cerr << "Error reading MOD: " << modelFile->GetError() << std::endl;
- return 1;
- }
- }
- else if (std::string(argv[1]) == "dxf")
- {
- if (! modelFile->ReadDXF(argv[2], 0.0f, 0.0f))
- {
- std::cerr << "Error reading DXF: " << modelFile->GetError() << std::endl;
- return 1;
- }
- }
- else
- {
- std::cerr << "Usage: " << argv[0] << "{mod|dxf} model_file" << std::endl;
- return 1;
- }
-
- // 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("Model Test", "Model Test");
-
- Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig());
- device->Create();
-
- Init(device, modelFile);
-
- bool done = false;
- while (! done)
- {
- Render(device, modelFile);
- Update();
-
- SDL_GL_SwapBuffers();
-
- SDL_Event event;
- SDL_PollEvent(&event);
- if (event.type == SDL_QUIT)
- done = true;
- else if (event.type == SDL_KEYDOWN)
- KeyboardDown(event.key.keysym.sym);
- else if (event.type == SDL_KEYUP)
- KeyboardUp(event.key.keysym.sym);
-
- usleep(FRAME_DELAY);
- }
-
- delete modelFile;
-
- device->Destroy();
- delete device;
-
- SDL_FreeSurface(surface);
-
- IMG_Quit();
-
- SDL_Quit();
-
- DestroyTimeStamp(PREV_TIME);
- DestroyTimeStamp(CURR_TIME);
-
- return 0;
-}
diff --git a/src/graphics/opengl/test/tex1.png b/src/graphics/opengl/test/tex1.png
deleted file mode 100644
index 46c68a0..0000000
--- a/src/graphics/opengl/test/tex1.png
+++ /dev/null
Binary files differ
diff --git a/src/graphics/opengl/test/tex2.png b/src/graphics/opengl/test/tex2.png
deleted file mode 100644
index ebdae0d..0000000
--- a/src/graphics/opengl/test/tex2.png
+++ /dev/null
Binary files differ
diff --git a/src/graphics/opengl/test/texture_test.cpp b/src/graphics/opengl/test/texture_test.cpp
deleted file mode 100644
index 534a5c0..0000000
--- a/src/graphics/opengl/test/texture_test.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-#include "common/logger.h"
-#include "common/image.h"
-#include "graphics/opengl/gldevice.h"
-#include "math/geometry.h"
-
-#include <SDL/SDL.h>
-#include <SDL/SDL_image.h>
-#include <unistd.h>
-
-
-void Init(Gfx::CGLDevice *device)
-{
- device->SetShadeModel(Gfx::SHADE_SMOOTH);
-
- device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false);
- device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
-
- device->SetTextureEnabled(0, true);
- device->SetTextureEnabled(1, true);
-
- CImage img1;
- if (! img1.Load("tex1.png"))
- {
- std::string err = img1.GetError();
- GetLogger()->Error("texture 1 not loaded, error: %d!\n", err.c_str());
- }
- CImage img2;
- if (! img2.Load("tex2.png"))
- {
- std::string err = img2.GetError();
- GetLogger()->Error("texture 2 not loaded, error: %d!\n", err.c_str());
- }
-
- Gfx::TextureCreateParams tex1CreateParams;
- tex1CreateParams.mipmap = true;
- tex1CreateParams.format = Gfx::TEX_IMG_RGBA;
- tex1CreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
- tex1CreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
-
- Gfx::TextureCreateParams tex2CreateParams;
- tex2CreateParams.mipmap = true;
- tex2CreateParams.format = Gfx::TEX_IMG_RGBA;
- tex2CreateParams.minFilter = Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST;
- tex2CreateParams.magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
-
- Gfx::Texture tex1 = device->CreateTexture(&img1, tex1CreateParams);
- Gfx::Texture tex2 = device->CreateTexture(&img2, tex2CreateParams);
-
- device->SetTexture(0, tex1);
- device->SetTexture(1, tex2);
-}
-
-void Render(Gfx::CGLDevice *device)
-{
- device->BeginScene();
-
- Math::Matrix ortho;
- Math::LoadOrthoProjectionMatrix(ortho, -10, 10, -10, 10);
- device->SetTransform(Gfx::TRANSFORM_PROJECTION, ortho);
-
- Math::Matrix id;
- id.LoadIdentity();
-
- device->SetTransform(Gfx::TRANSFORM_WORLD, id);
- device->SetTransform(Gfx::TRANSFORM_VIEW, id);
-
- static Gfx::VertexTex2 quad[] =
- {
- Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)),
- Gfx::VertexTex2(Math::Vector( 2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 0.0f), Math::Point(1.0f, 0.0f)),
- Gfx::VertexTex2(Math::Vector( 2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 1.0f), Math::Point(1.0f, 1.0f)),
-
- Gfx::VertexTex2(Math::Vector( 2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 1.0f), Math::Point(1.0f, 1.0f)),
- Gfx::VertexTex2(Math::Vector(-2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 1.0f), Math::Point(0.0f, 1.0f)),
- Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)),
- };
-
- Gfx::TextureStageParams tex1StageParams;
- tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- device->SetTextureStageParams(0, tex1StageParams);
-
- Gfx::TextureStageParams tex2StageParams;
- tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- device->SetTextureStageParams(1, tex2StageParams);
-
- Math::Matrix t;
- Math::LoadTranslationMatrix(t, Math::Vector(-4.0f, 4.0f, 0.0f));
- device->SetTransform(Gfx::TRANSFORM_VIEW, t);
-
- device->SetTextureEnabled(0, true);
- device->SetTextureEnabled(1, false);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
-
- Math::LoadTranslationMatrix(t, Math::Vector( 4.0f, 4.0f, 0.0f));
- device->SetTransform(Gfx::TRANSFORM_VIEW, t);
-
- device->SetTextureEnabled(0, false);
- device->SetTextureEnabled(1, true);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
-
- Math::LoadTranslationMatrix(t, Math::Vector( 0.0f, -4.0f, 0.0f));
- device->SetTransform(Gfx::TRANSFORM_VIEW, t);
-
- device->SetTextureEnabled(0, true);
- device->SetTextureEnabled(1, true);
-
- tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- device->SetTextureStageParams(0, tex1StageParams);
-
- tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_ADD;
- tex2StageParams.colorArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR;
- tex2StageParams.colorArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
- tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
- device->SetTextureStageParams(1, tex2StageParams);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
-
- device->EndScene();
-}
-
-int main()
-{
- CLogger();
-
- // 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("Texture Test", "Texture Test");
-
- Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig());
- device->Create();
-
- Init(device);
-
- bool done = false;
- while (! done)
- {
- Render(device);
-
- SDL_GL_SwapBuffers();
-
- SDL_Event event;
- SDL_PollEvent(&event);
- if (event.type == SDL_QUIT)
- done = true;
-
- usleep(10000);
- }
-
- device->Destroy();
- delete device;
-
- SDL_FreeSurface(surface);
-
- IMG_Quit();
-
- SDL_Quit();
-
- return 0;
-}
diff --git a/src/graphics/opengl/test/transform_test.cpp b/src/graphics/opengl/test/transform_test.cpp
deleted file mode 100644
index cddd1b8..0000000
--- a/src/graphics/opengl/test/transform_test.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-#include "app/system.h"
-#include "common/logger.h"
-#include "common/image.h"
-#include "common/iman.h"
-#include "graphics/opengl/gldevice.h"
-#include "math/geometry.h"
-
-#include <SDL/SDL.h>
-#include <SDL/SDL_image.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <map>
-
-enum KeySlots
-{
- K_Forward,
- K_Back,
- K_Left,
- K_Right,
- K_Up,
- K_Down,
- K_Count
-};
-bool KEYMAP[K_Count] = { false };
-
-Math::Point MOUSE_POS_BASE;
-
-Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f);
-Math::Vector ROTATION, ROTATION_BASE;
-
-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();
-
- 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() };
-
- for (int i = 0; i < 6; ++i)
- quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f);
-
- 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);
- quad[4].coord = Math::Vector(-1.0f, 1.0f, 0.0f);
- quad[5].coord = Math::Vector(-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_TRIANGLES, quad, 6);
-
- 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_TRIANGLES, quad, 6);
-
- for (int i = 0; i < 6; ++i)
- quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f);
-
- Math::LoadTranslationMatrix(worldMat, Math::Vector(0.0f, 10.0f, 0.0f));
- device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
-
- device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
-
- 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);
-
- 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(static_cast<float>(x), static_cast<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 + (static_cast<float> (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI;
- ROTATION.x = ROTATION_BASE.x + (static_cast<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("Transform Test", "Transform Test");
-
- //SDL_WM_GrabInput(SDL_GRAB_ON);
- SDL_ShowCursor(SDL_DISABLE);
-
- Gfx::CGLDevice *device = new Gfx::CGLDevice(Gfx::GLDeviceConfig());
- 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;
-}