summaryrefslogtreecommitdiffstats
path: root/src/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/README.txt1
-rw-r--r--src/graphics/core/README.txt3
-rw-r--r--src/graphics/core/color.cpp1
-rw-r--r--src/graphics/core/color.h9
-rw-r--r--src/graphics/core/device.h6
-rw-r--r--src/graphics/core/light.h1
-rw-r--r--src/graphics/core/material.h1
-rw-r--r--src/graphics/core/texture.h6
-rw-r--r--src/graphics/core/vertex.h1
-rw-r--r--src/graphics/d3d/README.txt1
-rw-r--r--src/graphics/engine/README.txt1
-rw-r--r--src/graphics/engine/camera.cpp1
-rw-r--r--src/graphics/engine/camera.h4
-rw-r--r--src/graphics/engine/cloud.cpp1
-rw-r--r--src/graphics/engine/cloud.h1
-rw-r--r--src/graphics/engine/engine.cpp228
-rw-r--r--src/graphics/engine/engine.h67
-rw-r--r--src/graphics/engine/lightman.cpp77
-rw-r--r--src/graphics/engine/lightman.h14
-rw-r--r--src/graphics/engine/lightning.cpp1
-rw-r--r--src/graphics/engine/lightning.h1
-rw-r--r--src/graphics/engine/modelfile.cpp80
-rw-r--r--src/graphics/engine/modelfile.h5
-rw-r--r--src/graphics/engine/modelmanager.cpp18
-rw-r--r--src/graphics/engine/modelmanager.h11
-rw-r--r--src/graphics/engine/particle.cpp7
-rw-r--r--src/graphics/engine/particle.h1
-rw-r--r--src/graphics/engine/planet.cpp1
-rw-r--r--src/graphics/engine/planet.h1
-rw-r--r--src/graphics/engine/pyro.cpp32
-rw-r--r--src/graphics/engine/pyro.h1
-rw-r--r--src/graphics/engine/terrain.cpp1
-rw-r--r--src/graphics/engine/terrain.h1
-rw-r--r--src/graphics/engine/test/CMakeLists.txt27
-rw-r--r--src/graphics/engine/test/modelfile_test.cpp262
-rw-r--r--src/graphics/engine/text.cpp123
-rw-r--r--src/graphics/engine/text.h32
-rw-r--r--src/graphics/engine/water.cpp1
-rw-r--r--src/graphics/engine/water.h1
-rw-r--r--src/graphics/opengl/README.txt1
-rw-r--r--src/graphics/opengl/gldevice.cpp131
-rw-r--r--src/graphics/opengl/gldevice.h4
42 files changed, 735 insertions, 432 deletions
diff --git a/src/graphics/README.txt b/src/graphics/README.txt
index 1cb91ba..f9ec2ae 100644
--- a/src/graphics/README.txt
+++ b/src/graphics/README.txt
@@ -10,3 +10,4 @@
* This namespace was created to avoid clashing with old code, but now it still serves,
* defining a border between pure graphics engine and other parts of application.
*/
+
diff --git a/src/graphics/core/README.txt b/src/graphics/core/README.txt
index ca3768c..056441d 100644
--- a/src/graphics/core/README.txt
+++ b/src/graphics/core/README.txt
@@ -4,4 +4,5 @@
*
* Core types, enums, structs and CDevice abstract class that define
* the abstract graphics device used in graphics engine
- */ \ No newline at end of file
+ */
+
diff --git a/src/graphics/core/color.cpp b/src/graphics/core/color.cpp
index 1f9d7a5..f0b74f8 100644
--- a/src/graphics/core/color.cpp
+++ b/src/graphics/core/color.cpp
@@ -106,3 +106,4 @@ Color HSV2RGB(ColorHSV color)
} // namespace Gfx
+
diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h
index 5d059e5..87a50f4 100644
--- a/src/graphics/core/color.h
+++ b/src/graphics/core/color.h
@@ -139,10 +139,10 @@ struct ColorHSV
//! Returns a string "(h, s, v)"
inline std::string ToString() const
{
- std::stringstream s;
- s.precision(3);
- s << "(" << h << ", " << s << ", " << v << ")";
- return s.str();
+ std::stringstream str;
+ str.precision(3);
+ str << "(" << h << ", " << s << ", " << v << ")";
+ return str.str();
}
};
@@ -154,3 +154,4 @@ Color HSV2RGB(ColorHSV color);
} // namespace Gfx
+
diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
index 41d7796..4c1189c 100644
--- a/src/graphics/core/device.h
+++ b/src/graphics/core/device.h
@@ -72,7 +72,7 @@ struct DeviceConfig
size = Math::IntPoint(800, 600);
bpp = 32;
fullScreen = false;
- resizeable = false;
+ resizeable = true;
doubleBuf = true;
noFrame = false;
}
@@ -240,6 +240,9 @@ public:
//! Provides a hook to debug graphics code (implementation-specific)
virtual void DebugHook() = 0;
+ //! Displays light positions to aid in debuggings
+ virtual void DebugLights() = 0;
+
//! Initializes the device, setting the initial state
virtual bool Create() = 0;
//! Destroys the device, releasing every acquired resource
@@ -401,3 +404,4 @@ public:
} // namespace Gfx
+
diff --git a/src/graphics/core/light.h b/src/graphics/core/light.h
index 28733c1..923d0e9 100644
--- a/src/graphics/core/light.h
+++ b/src/graphics/core/light.h
@@ -98,3 +98,4 @@ struct Light
} // namespace Gfx
+
diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h
index 07782d5..e0bfaff 100644
--- a/src/graphics/core/material.h
+++ b/src/graphics/core/material.h
@@ -60,3 +60,4 @@ struct Material
} // namespace Gfx
+
diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h
index 49b29f8..0702428 100644
--- a/src/graphics/core/texture.h
+++ b/src/graphics/core/texture.h
@@ -136,6 +136,8 @@ struct TextureCreateParams
TexMinFilter minFilter;
//! Magnification filter
TexMagFilter magFilter;
+ //! Pad the image to nearest power of 2 dimensions
+ bool padToNearestPowerOfTwo;
//! Constructor; calls LoadDefault()
TextureCreateParams()
@@ -146,6 +148,7 @@ struct TextureCreateParams
{
format = TEX_IMG_RGB;
mipmap = false;
+ padToNearestPowerOfTwo = false;
minFilter = TEX_MIN_FILTER_NEAREST;
magFilter = TEX_MAG_FILTER_NEAREST;
@@ -212,6 +215,8 @@ struct Texture
unsigned int id;
//! Size of texture
Math::IntPoint size;
+ //! Original size of texture (as loaded from image)
+ Math::IntPoint originalSize;
//! Whether the texture has alpha channel
bool alpha;
@@ -264,3 +269,4 @@ struct Texture
} // namespace Gfx
+
diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h
index 66e1503..c3a657a 100644
--- a/src/graphics/core/vertex.h
+++ b/src/graphics/core/vertex.h
@@ -140,3 +140,4 @@ struct VertexTex2
} // namespace Gfx
+
diff --git a/src/graphics/d3d/README.txt b/src/graphics/d3d/README.txt
index 0fe7db6..4f96f27 100644
--- a/src/graphics/d3d/README.txt
+++ b/src/graphics/d3d/README.txt
@@ -1 +1,2 @@
Possible future DirectX implementation of graphics engine
+
diff --git a/src/graphics/engine/README.txt b/src/graphics/engine/README.txt
index 05d2d76..fbf45fd 100644
--- a/src/graphics/engine/README.txt
+++ b/src/graphics/engine/README.txt
@@ -7,3 +7,4 @@
*
* Graphics operations are done on abstract interface from src/graphics/core
*/
+
diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp
index f65a59a..f0c379c 100644
--- a/src/graphics/engine/camera.cpp
+++ b/src/graphics/engine/camera.cpp
@@ -1676,3 +1676,4 @@ Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
}
+
diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h
index 0ffc2c2..6d94dad 100644
--- a/src/graphics/engine/camera.h
+++ b/src/graphics/engine/camera.h
@@ -128,8 +128,7 @@ enum CameraOverEffect
... */
class CCamera {
-
- public:
+public:
CCamera();
~CCamera();
@@ -391,3 +390,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp
index d9ebf5a..74083af 100644
--- a/src/graphics/engine/cloud.cpp
+++ b/src/graphics/engine/cloud.cpp
@@ -270,3 +270,4 @@ bool CCloud::GetEnabled()
} // namespace Gfx
+
diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h
index 8f644f0..8e820c7 100644
--- a/src/graphics/engine/cloud.h
+++ b/src/graphics/engine/cloud.h
@@ -140,3 +140,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index e2ef569..669ea42 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -42,6 +42,8 @@
#include "ui/interface.h"
+#include <iomanip>
+
template<> Gfx::CEngine* CSingleton<Gfx::CEngine>::m_instance = nullptr;
// Graphics module namespace
@@ -94,7 +96,6 @@ CEngine::CEngine(CApplication *app)
m_backgroundCloudUp = Color();
m_backgroundCloudDown = Color();
m_backgroundFull = false;
- m_backgroundScale = Math::Point(1.0f, 1.0f);
m_overFront = true;
m_overColor = Color();
m_overMode = ENG_RSTATE_TCOLOR_BLACK;
@@ -127,6 +128,9 @@ CEngine::CEngine(CApplication *app)
m_interfaceMode = false;
+ m_debugLights = false;
+ m_debugDumpLights = false;
+
m_mice[ENG_MOUSE_NORM] = EngineMouse( 0, 1, 32, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 1.0f, 1.0f));
m_mice[ENG_MOUSE_WAIT] = EngineMouse( 2, 3, 33, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 8.0f, 12.0f));
m_mice[ENG_MOUSE_HAND] = EngineMouse( 4, 5, 34, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 7.0f, 2.0f));
@@ -237,7 +241,6 @@ void CEngine::SetTerrain(CTerrain* terrain)
m_terrain = terrain;
}
-
bool CEngine::Create()
{
m_size = m_app->GetVideoConfig().size;
@@ -317,7 +320,7 @@ void CEngine::ResetAfterDeviceChanged()
m_text->FlushCache();
- // TODO reload textures, reset device state, etc.
+ FlushTextureCache();
}
bool CEngine::ProcessEvent(const Event &event)
@@ -325,7 +328,22 @@ bool CEngine::ProcessEvent(const Event &event)
if (event.type == EVENT_KEY_DOWN)
{
if (event.key.key == KEY(F12))
+ {
m_showStats = !m_showStats;
+ return false;
+ }
+
+ if (event.key.key == KEY(F11))
+ {
+ m_debugLights = !m_debugLights;
+ return false;
+ }
+
+ if (event.key.key == KEY(F10))
+ {
+ m_debugDumpLights = true;
+ return false;
+ }
}
// By default, pass on all events
@@ -591,6 +609,27 @@ void CEngine::CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank)
assert(destBaseObjRank >= 0 && destBaseObjRank < static_cast<int>( m_baseObjects.size() ));
m_baseObjects[destBaseObjRank] = m_baseObjects[sourceBaseObjRank];
+
+ EngineBaseObject& p1 = m_baseObjects[destBaseObjRank];
+
+ if (! p1.used)
+ return;
+
+ 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];
+ p4.staticBufferId = 0;
+ }
+ }
+ }
}
void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>& vertices,
@@ -677,6 +716,82 @@ void CEngine::AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buff
p1.totalTriangles += p4.vertices.size() - 2;
}
+void CEngine::DebugObject(int objRank)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ CLogger* l = GetLogger();
+
+ l->Debug("Debug object: %d\n", objRank);
+ if (! m_objects[objRank].used)
+ {
+ l->Debug(" not used\n");
+ return;
+ }
+
+ l->Debug(" baseObjRank = %d\n", m_objects[objRank].baseObjRank);
+ l->Debug(" visible = %s\n", m_objects[objRank].visible ? "true" : "false");
+ l->Debug(" drawWorld = %s\n", m_objects[objRank].drawWorld ? "true" : "false");
+ l->Debug(" drawFront = %s\n", m_objects[objRank].drawFront ? "true" : "false");
+ l->Debug(" type = %d\n", m_objects[objRank].type);
+ l->Debug(" distance = %f\n", m_objects[objRank].distance);
+ l->Debug(" shadowRank = %d\n", m_objects[objRank].shadowRank);
+ l->Debug(" transparency = %f\n", m_objects[objRank].transparency);
+
+ l->Debug(" baseObj:\n");
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ {
+ l->Debug(" null\n");
+ return;
+ }
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (!p1.used)
+ {
+ l->Debug(" not used\n");
+ return;
+ }
+
+ std::string vecStr;
+
+ vecStr = p1.bboxMin.ToString();
+ l->Debug(" bboxMin: %s\n", vecStr.c_str());
+ vecStr = p1.bboxMax.ToString();
+ l->Debug(" bboxMax: %s\n", vecStr.c_str());
+ l->Debug(" totalTriangles: %d\n", p1.totalTriangles);
+ l->Debug(" radius: %f\n", p1.radius);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+ l->Debug(" l2:\n");
+
+ l->Debug(" tex1: %s (id: %u)\n", p2.tex1Name.c_str(), p2.tex1.id);
+ l->Debug(" tex2: %s (id: %u)\n", p2.tex2Name.c_str(), p2.tex2.id);
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
+ {
+ EngineBaseObjLODTier& p3 = p2.next[l3];
+
+ l->Debug(" l3:\n");
+ l->Debug(" lodLevel: %d\n", p3.lodLevel);
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
+ {
+ EngineBaseObjDataTier& p4 = p3.next[l4];
+
+ l->Debug(" l4:\n");
+ l->Debug(" type: %d\n", p4.type);
+ l->Debug(" state: %d\n", p4.state);
+ l->Debug(" staticBufferId: %u\n", p4.staticBufferId);
+ l->Debug(" updateStaticBuffer: %s\n", p4.updateStaticBuffer ? "true" : "false");
+ }
+ }
+ }
+}
int CEngine::CreateObject()
{
@@ -965,13 +1080,19 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name)
for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineBaseObjTexTier& p2 = p1.next[l2];
-
- if (p2.tex2Name == tex2Name)
+ if (p1.next[l2].tex2Name == tex2Name)
continue; // already new
- EngineBaseObjTexTier& newP2 = AddLevel2(p1, p2.tex1Name, tex2Name);
- newP2.next.swap(p2.next);
+ std::string tex1Name = p1.next[l2].tex1Name;
+ EngineBaseObjTexTier& newP2 = AddLevel2(p1, tex1Name, tex2Name);
+ newP2.next.insert(newP2.next.end(), p1.next[l2].next.begin(), p1.next[l2].next.end());
+ p1.next[l2].next.clear();
+
+ if (!newP2.tex1.Valid())
+ newP2.tex1 = LoadTexture(newP2.tex1Name);
+
+ if (!newP2.tex2.Valid())
+ newP2.tex2 = LoadTexture(newP2.tex2Name);
}
}
@@ -2098,25 +2219,44 @@ Texture CEngine::CreateTexture(const std::string& texName, const TextureCreatePa
return Texture(); // invalid texture
Texture tex;
+ CImage img;
if (image == nullptr)
{
- CImage img;
- if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ bool loadedFromTexPack = false;
+
+ std::string texPackName = m_app->GetTexPackFilePath(texName);
+ if (! texPackName.empty())
{
- std::string error = img.GetError();
- GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
- m_texBlacklist.insert(texName);
- return Texture(); // invalid texture
+ if (img.Load(texPackName))
+ {
+ loadedFromTexPack = true;
+ }
+ else
+ {
+ std::string error = img.GetError();
+ GetLogger()->Error("Couldn't load texture '%s' from texpack: %s, blacklisting the texpack path\n",
+ texName.c_str(), error.c_str());
+ m_texBlacklist.insert(texPackName);
+ }
}
- tex = m_device->CreateTexture(&img, params);
- }
- else
- {
- tex = m_device->CreateTexture(image, params);
+ if (!loadedFromTexPack)
+ {
+ if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ {
+ std::string error = img.GetError();
+ GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
+ m_texBlacklist.insert(texName);
+ return Texture(); // invalid texture
+ }
+ }
+
+ image = &img;
}
+ tex = m_device->CreateTexture(image, params);
+
if (! tex.Valid())
{
GetLogger()->Error("Couldn't load texture '%s', blacklisting\n", texName.c_str());
@@ -2150,8 +2290,7 @@ Texture CEngine::LoadTexture(const std::string& name, const TextureCreateParams&
if (it != m_texNameMap.end())
return (*it).second;
- Texture tex = CreateTexture(name, params);
- return tex;
+ return CreateTexture(name, params);
}
bool CEngine::LoadAllTextures()
@@ -2167,7 +2306,11 @@ bool CEngine::LoadAllTextures()
LoadTexture("map.png");
if (! m_backgroundName.empty())
- m_backgroundTex = LoadTexture(m_backgroundName);
+ {
+ TextureCreateParams params = m_defaultTexParams;
+ params.padToNearestPowerOfTwo = true;
+ m_backgroundTex = LoadTexture(m_backgroundName, params);
+ }
else
m_backgroundTex.SetInvalid();
@@ -2405,6 +2548,13 @@ void CEngine::DeleteTexture(const Texture& tex)
m_texNameMap.erase(it);
}
+void CEngine::FlushTextureCache()
+{
+ m_texNameMap.clear();
+ m_revTexNameMap.clear();
+ m_texBlacklist.clear();
+}
+
bool CEngine::SetTexture(const std::string& name, int stage)
{
auto it = m_texNameMap.find(name);
@@ -2588,8 +2738,7 @@ float CEngine::GetFogStart(int rank)
}
void CEngine::SetBackground(const std::string& name, Color up, Color down,
- Color cloudUp, Color cloudDown,
- bool full, Math::Point scale)
+ Color cloudUp, Color cloudDown, bool full)
{
if (m_backgroundTex.Valid())
{
@@ -2603,15 +2752,17 @@ void CEngine::SetBackground(const std::string& name, Color up, Color down,
m_backgroundCloudUp = cloudUp;
m_backgroundCloudDown = cloudDown;
m_backgroundFull = full;
- m_backgroundScale = scale;
if (! m_backgroundName.empty())
- m_backgroundTex = LoadTexture(m_backgroundName);
+ {
+ TextureCreateParams params = m_defaultTexParams;
+ params.padToNearestPowerOfTwo = true;
+ m_backgroundTex = LoadTexture(m_backgroundName, params);
+ }
}
void CEngine::GetBackground(std::string& name, Color& up, Color& down,
- Color& cloudUp, Color& cloudDown,
- bool &full, Math::Point& scale)
+ Color& cloudUp, Color& cloudDown, bool &full)
{
name = m_backgroundName;
up = m_backgroundColorUp;
@@ -2619,7 +2770,6 @@ void CEngine::GetBackground(std::string& name, Color& up, Color& down,
cloudUp = m_backgroundCloudUp;
cloudDown = m_backgroundCloudDown;
full = m_backgroundFull;
- scale = m_backgroundScale;
}
void CEngine::SetForegroundName(const std::string& name)
@@ -3161,6 +3311,15 @@ void CEngine::Draw3DScene()
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN);
+ if (m_debugLights)
+ m_device->DebugLights();
+
+ if (m_debugDumpLights)
+ {
+ m_debugDumpLights = false;
+ m_lightMan->DebugDumpLights();
+ }
+
if (m_waterMode)
{
m_app->StartPerformanceCounter(PCNT_RENDER_WATER);
@@ -3630,7 +3789,7 @@ void CEngine::DrawShadow()
float lastIntensity = -1.0f;
for (int i = 0; i < static_cast<int>( m_shadows.size() ); i++)
{
- if (m_shadows[i].hide)
+ if (m_shadows[i].hide || !m_shadows[i].used)
continue;
Math::Vector pos = m_shadows[i].pos; // pos = center of the shadow on the ground
@@ -3879,8 +4038,12 @@ void CEngine::DrawBackgroundImage()
v2 = v1+h;
}
- u2 *= m_backgroundScale.x;
- v2 *= m_backgroundScale.y;
+ Math::Point backgroundScale;
+ backgroundScale.x = static_cast<float>(m_backgroundTex.originalSize.x) / static_cast<float>(m_backgroundTex.size.x);
+ backgroundScale.y = static_cast<float>(m_backgroundTex.originalSize.y) / static_cast<float>(m_backgroundTex.size.y);
+
+ u2 *= backgroundScale.x;
+ v2 *= backgroundScale.y;
SetTexture(m_backgroundTex);
SetState(ENG_RSTATE_OPAQUE_TEXTURE | ENG_RSTATE_WRAP);
@@ -4279,3 +4442,4 @@ void CEngine::DrawStats()
} // namespace Gfx
+
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index f9dfd45..5ecde8f 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -118,7 +118,7 @@ enum EngineRenderState
//! Mode for rendering text
ENG_RSTATE_TEXT = (1<<18),
//! Only opaque texture, no blending, etc.
- ENG_RSTATE_OPAQUE_TEXTURE = (1<<19),
+ ENG_RSTATE_OPAQUE_TEXTURE = (1<<19),
//! Only opaque color, no texture, blending, etc.
ENG_RSTATE_OPAQUE_COLOR = (1<<20)
};
@@ -171,7 +171,7 @@ enum EngineObjectType
//! Fixed object
ENG_OBJTYPE_FIX = 2,
//! Moving object
- ENG_OBJTYPE_VEHICULE = 3,
+ ENG_OBJTYPE_VEHICLE = 3,
//! Part of a moving object
ENG_OBJTYPE_DESCENDANT = 4,
//! Fixed object type quartz
@@ -194,10 +194,15 @@ struct EngineBaseObjDataTier
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) {}
+ 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)
+ {}
};
/**
@@ -209,8 +214,9 @@ struct EngineBaseObjLODTier
LODLevel lodLevel;
std::vector<EngineBaseObjDataTier> next;
- inline EngineBaseObjLODTier(LODLevel lodLevel = LOD_Constant)
- : lodLevel(lodLevel) {}
+ inline EngineBaseObjLODTier(LODLevel _lodLevel = LOD_Constant)
+ : lodLevel(_lodLevel)
+ {}
};
/**
@@ -225,8 +231,10 @@ struct EngineBaseObjTexTier
Texture tex2;
std::vector<EngineBaseObjLODTier> next;
- inline EngineBaseObjTexTier(const std::string& tex1Name = "", const std::string& tex2Name = "")
- : tex1Name(tex1Name), tex2Name(tex2Name) {}
+ inline EngineBaseObjTexTier(const std::string& _tex1Name = "", const std::string& _tex2Name = "")
+ : tex1Name(_tex1Name)
+ , tex2Name(_tex2Name)
+ {}
};
/**
@@ -556,18 +564,17 @@ struct EngineMouse
//! Hot point
Math::Point hotPoint;
- 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;
- this->iconShadow = iconShadow;
- this->mode1 = mode1;
- this->mode2 = mode2;
- this->hotPoint = hotPoint;
- }
+ 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())
+ : icon1(_icon1)
+ , icon2(_icon2)
+ , iconShadow(_iconShadow)
+ , mode1(_mode1)
+ , mode2(_mode2)
+ , hotPoint(_hotPoint)
+ {}
};
@@ -726,6 +733,7 @@ public:
//! Writes a screenshot containing the current frame
bool WriteScreenShot(const std::string& fileName, int width, int height);
+
//@{
//! Management of game pause mode
void SetPause(bool pause);
@@ -799,6 +807,9 @@ public:
// Objects
+ //! Print debug info about an object
+ void DebugObject(int rank);
+
//! Creates a new object and returns its rank
int CreateObject();
//! Deletes all objects, shadows and ground spots
@@ -957,6 +968,9 @@ public:
//! Deletes the given texture, unloading it and removing from cache
void DeleteTexture(const Texture& tex);
+ //! Empties the texture cache
+ void FlushTextureCache();
+
//! Defines of the distance field of vision
void SetTerrainVision(float vision);
@@ -1050,10 +1064,10 @@ public:
//! Management of the background image to use
void SetBackground(const std::string& name, Color up = Color(), Color down = Color(),
Color cloudUp = Color(), Color cloudDown = Color(),
- bool full = false, Math::Point scale = Math::Point(1.0f, 1.0f));
+ bool full = false);
void GetBackground(std::string& name, Color& up, Color& down,
Color& cloudUp, Color& cloudDown,
- bool& full, Math::Point& scale);
+ bool& full);
//@}
//! Specifies the name of foreground texture
@@ -1346,7 +1360,6 @@ protected:
bool m_firstGroundSpot;
int m_secondTexNum;
bool m_backgroundFull;
- Math::Point m_backgroundScale;
std::string m_backgroundName;
Texture m_backgroundTex;
Color m_backgroundColorUp;
@@ -1424,7 +1437,11 @@ protected:
//! True when drawing 2D UI
bool m_interfaceMode;
+
+ bool m_debugLights;
+ bool m_debugDumpLights;
};
} // namespace Gfx
+
diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp
index 16c84ea..8694c7a 100644
--- a/src/graphics/engine/lightman.cpp
+++ b/src/graphics/engine/lightman.cpp
@@ -71,6 +71,7 @@ void LightProgression::SetTarget(float value)
DynamicLight::DynamicLight()
{
+ rank = 0;
used = enabled = false;
priority = LIGHT_PRI_LOW;
includeType = excludeType = ENG_OBJTYPE_NULL;
@@ -98,6 +99,61 @@ void CLightManager::SetDevice(CDevice* device)
m_lightMap = std::vector<int>(m_device->GetMaxLightCount(), -1);
}
+void CLightManager::DebugDumpLights()
+{
+ CLogger* l = GetLogger();
+
+ l->Debug("Dynamic lights:\n");
+
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); ++i)
+ {
+ const DynamicLight& dynLight = m_dynLights[i];
+ if (!dynLight.used)
+ continue;
+
+ int deviceLight = -1;
+ for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j)
+ {
+ if (m_lightMap[j] == i)
+ {
+ deviceLight = j;
+ break;
+ }
+ }
+
+ l->Debug(" light %d\n", i);
+ l->Debug(" enabled = %s\n", dynLight.enabled ? "true" : "false");
+ l->Debug(" priority = %d\n", dynLight.priority);
+ l->Debug(" device light = %d\n", deviceLight);
+ l->Debug(" light:\n");
+
+ const Light& light = dynLight.light;
+ std::string str;
+
+ l->Debug(" type = %d\n", light.type);
+ str = light.ambient.ToString();
+ l->Debug(" ambient = %s\n", str.c_str());
+ str = light.diffuse.ToString();
+ l->Debug(" diffuse = %s\n", str.c_str());
+ str = light.specular.ToString();
+ l->Debug(" specular = %s\n", str.c_str());
+ str = light.position.ToString();
+ l->Debug(" position = %s\n", str.c_str());
+ str = light.direction.ToString();
+ l->Debug(" direction = %s\n", str.c_str());
+ l->Debug(" attenuation0 = %f\n", light.attenuation0);
+ l->Debug(" attenuation1 = %f\n", light.attenuation1);
+ l->Debug(" attenuation2 = %f\n", light.attenuation2);
+ l->Debug(" spotAngle = %f\n", light.spotAngle);
+ l->Debug(" spotIntensity = %f\n", light.spotIntensity);
+
+ l->Debug(" intensity: %f\n", dynLight.intensity.current);
+ l->Debug(" color: %f %f %f\n", dynLight.colorRed.current, dynLight.colorGreen.current, dynLight.colorBlue.current);
+ l->Debug(" includeType: %d\n", dynLight.includeType);
+ l->Debug(" excludeType: %d\n", dynLight.excludeType);
+ }
+}
+
void CLightManager::FlushLights()
{
m_dynLights.clear();
@@ -117,6 +173,7 @@ int CLightManager::CreateLight(LightPriority priority)
m_dynLights.push_back(DynamicLight());
m_dynLights[index] = DynamicLight();
+ m_dynLights[index].rank = index;
m_dynLights[index].used = true;
m_dynLights[index].enabled = true;
m_dynLights[index].priority = priority;
@@ -179,6 +236,15 @@ bool CLightManager::SetLightEnabled(int lightRank, bool enabled)
return true;
}
+bool CLightManager::SetLightPriority(int lightRank, LightPriority priority)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].priority = priority;
+ return true;
+}
+
bool CLightManager::SetLightIncludeType(int lightRank, EngineObjectType type)
{
if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
@@ -411,7 +477,7 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
if (enabled)
{
- m_lightMap[lightMapIndex] = i;
+ m_lightMap[lightMapIndex] = sortedLights[i].rank;
++lightMapIndex;
}
@@ -424,8 +490,9 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
int rank = m_lightMap[i];
if (rank != -1)
{
- sortedLights[rank].light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
- m_device->SetLight(i, sortedLights[rank].light);
+ Light light = m_dynLights[rank].light;
+ light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
+ m_device->SetLight(i, light);
m_device->SetLightEnabled(i, true);
}
else
@@ -445,6 +512,9 @@ CLightManager::LightsComparator::LightsComparator(Math::Vector eyePos, EngineObj
float CLightManager::LightsComparator::GetLightWeight(const DynamicLight& dynLight)
{
+ if (dynLight.priority == LIGHT_PRI_HIGHEST)
+ return -1.0f;
+
bool enabled = true;
if (!dynLight.used || !dynLight.enabled || dynLight.intensity.current == 0.0f)
enabled = false;
@@ -465,3 +535,4 @@ bool CLightManager::LightsComparator::operator()(const DynamicLight& left, const
}
} // namespace Gfx
+
diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h
index ab66524..a2f6044 100644
--- a/src/graphics/engine/lightman.h
+++ b/src/graphics/engine/lightman.h
@@ -71,8 +71,9 @@ struct LightProgression
*/
enum LightPriority
{
- LIGHT_PRI_HIGH = 1,
- LIGHT_PRI_LOW = 2
+ LIGHT_PRI_HIGHEST = 0, //!< always highest weight (always picked)
+ LIGHT_PRI_HIGH = 1, //!< high weight
+ LIGHT_PRI_LOW = 2 //!< low weight
};
/**
@@ -84,6 +85,9 @@ enum LightPriority
*/
struct DynamicLight
{
+ //! Rank (index)
+ int rank;
+
//! Whether the light is used
bool used;
//! Whether the light is turned on
@@ -136,6 +140,9 @@ public:
//! Sets the device to be used
void SetDevice(CDevice* device);
+ //! Prints debug info
+ void DebugDumpLights();
+
//! Clears and disables all lights
void FlushLights();
//! Creates a new dynamic light and returns its index (lightRank)
@@ -148,6 +155,8 @@ public:
bool GetLight(int lightRank, Light &light);
//! Enables/disables the given dynamic light
bool SetLightEnabled(int lightRank, bool enable);
+ //! Changes the light priority
+ bool SetLightPriority(int lightRank, LightPriority priority);
//! Sets what objects are included in given dynamic light
bool SetLightIncludeType(int lightRank, EngineObjectType type);
@@ -216,3 +225,4 @@ protected:
};
}; // namespace Gfx
+
diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp
index 5fdae51..4395eec 100644
--- a/src/graphics/engine/lightning.cpp
+++ b/src/graphics/engine/lightning.cpp
@@ -418,3 +418,4 @@ CObject* CLightning::SearchObject(Math::Vector pos)
} // namespace Gfx
+
diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h
index 7809a6c..1b1d339 100644
--- a/src/graphics/engine/lightning.h
+++ b/src/graphics/engine/lightning.h
@@ -107,3 +107,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp
index f6d7a7b..99496aa 100644
--- a/src/graphics/engine/modelfile.cpp
+++ b/src/graphics/engine/modelfile.cpp
@@ -310,6 +310,7 @@ bool ReadLineString(std::istream& stream, const std::string& prefix, std::string
CModelFile::CModelFile()
+ : m_printDebugInfo(false)
{
}
@@ -615,23 +616,26 @@ bool CModelFile::ReadModel(std::istream& stream)
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());
- std::string s2 = m_triangles[i].p2.ToString();
- GetLogger()->Trace(" p2: %s\n", s2.c_str());
- std::string s3 = m_triangles[i].p3.ToString();
- GetLogger()->Trace(" p3: %s\n", s3.c_str());
-
- std::string d = m_triangles[i].material.diffuse.ToString();
- std::string a = m_triangles[i].material.ambient.ToString();
- std::string s = m_triangles[i].material.specular.ToString();
- 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].variableTex2 ? "(variable)" : m_triangles[i].tex2Name.c_str());
- GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel);
- GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ if (m_printDebugInfo)
+ {
+ GetLogger()->Trace("ModelTriangle %d\n", i+1);
+ std::string s1 = m_triangles[i].p1.ToString();
+ GetLogger()->Trace(" p1: %s\n", s1.c_str());
+ std::string s2 = m_triangles[i].p2.ToString();
+ GetLogger()->Trace(" p2: %s\n", s2.c_str());
+ std::string s3 = m_triangles[i].p3.ToString();
+ GetLogger()->Trace(" p3: %s\n", s3.c_str());
+
+ std::string d = m_triangles[i].material.diffuse.ToString();
+ std::string a = m_triangles[i].material.ambient.ToString();
+ std::string s = m_triangles[i].material.specular.ToString();
+ 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].variableTex2 ? "(variable)" : m_triangles[i].tex2Name.c_str());
+ GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel);
+ GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ }
}
return true;
@@ -1093,24 +1097,27 @@ bool CModelFile::ReadBinaryModel(std::istream& stream)
return false;
}
- for (int i = 0; i < static_cast<int>( m_triangles.size() ); ++i)
+ if (m_printDebugInfo)
{
- GetLogger()->Trace("ModelTriangle %d\n", i+1);
- std::string s1 = m_triangles[i].p1.ToString();
- GetLogger()->Trace(" p1: %s\n", s1.c_str());
- std::string s2 = m_triangles[i].p2.ToString();
- GetLogger()->Trace(" p2: %s\n", s2.c_str());
- std::string s3 = m_triangles[i].p3.ToString();
- GetLogger()->Trace(" p3: %s\n", s3.c_str());
-
- std::string d = m_triangles[i].material.diffuse.ToString();
- std::string a = m_triangles[i].material.ambient.ToString();
- std::string s = m_triangles[i].material.specular.ToString();
- 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(" lod level: %d\n", m_triangles[i].lodLevel);
- GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); ++i)
+ {
+ GetLogger()->Trace("ModelTriangle %d\n", i+1);
+ std::string s1 = m_triangles[i].p1.ToString();
+ GetLogger()->Trace(" p1: %s\n", s1.c_str());
+ std::string s2 = m_triangles[i].p2.ToString();
+ GetLogger()->Trace(" p2: %s\n", s2.c_str());
+ std::string s3 = m_triangles[i].p3.ToString();
+ GetLogger()->Trace(" p3: %s\n", s3.c_str());
+
+ std::string d = m_triangles[i].material.diffuse.ToString();
+ std::string a = m_triangles[i].material.ambient.ToString();
+ std::string s = m_triangles[i].material.specular.ToString();
+ 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(" lod level: %d\n", m_triangles[i].lodLevel);
+ GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ }
}
return true;
@@ -1197,5 +1204,10 @@ int CModelFile::GetTriangleCount()
return m_triangles.size();
}
+void CModelFile::SetPrintDebugInfo(bool printDebugInfo)
+{
+ m_printDebugInfo = printDebugInfo;
+}
} // namespace Gfx
+
diff --git a/src/graphics/engine/modelfile.h b/src/graphics/engine/modelfile.h
index 3a702cb..3b4019b 100644
--- a/src/graphics/engine/modelfile.h
+++ b/src/graphics/engine/modelfile.h
@@ -137,6 +137,9 @@ public:
//! Returns the triangle vector
const std::vector<ModelTriangle>& GetTriangles();
+ //! Controls printing of debug information
+ void SetPrintDebugInfo(bool printDebugInfo);
+
protected:
//@{
//! @deprecated min, max conversions
@@ -147,6 +150,8 @@ protected:
protected:
//! Model triangles
std::vector<ModelTriangle> m_triangles;
+ bool m_printDebugInfo;
};
}; // namespace Gfx
+
diff --git a/src/graphics/engine/modelmanager.cpp b/src/graphics/engine/modelmanager.cpp
index c23b79d..abc8c6c 100644
--- a/src/graphics/engine/modelmanager.cpp
+++ b/src/graphics/engine/modelmanager.cpp
@@ -23,10 +23,13 @@ CModelManager::~CModelManager()
bool CModelManager::LoadModel(const std::string& fileName, bool mirrored)
{
- GetLogger()->Info("Loading model '%s'\n", fileName.c_str());
+ GetLogger()->Debug("Loading model '%s'\n", fileName.c_str());
CModelFile modelFile;
+ if (CApplication::GetInstance().IsDebugModeActive(DEBUG_MODELS))
+ modelFile.SetPrintDebugInfo(true);
+
std::string filePath = CApplication::GetInstance().GetDataFilePath(DIR_MODEL, fileName);
if (!modelFile.ReadModel(filePath))
@@ -111,6 +114,8 @@ bool CModelManager::AddModelCopy(const std::string& fileName, bool mirrored, int
m_engine->CopyBaseObject((*it).second.baseObjRank, copyBaseObjRank);
m_engine->SetObjectBaseRank(objRank, copyBaseObjRank);
+ m_copiesBaseRanks.push_back(copyBaseObjRank);
+
return true;
}
@@ -128,6 +133,16 @@ int CModelManager::GetModelBaseObjRank(const std::string& fileName, bool mirrore
return (*it).second.baseObjRank;
}
+void CModelManager::DeleteAllModelCopies()
+{
+ for (int baseObjRank : m_copiesBaseRanks)
+ {
+ m_engine->DeleteBaseObject(baseObjRank);
+ }
+
+ m_copiesBaseRanks.clear();
+}
+
void CModelManager::UnloadModel(const std::string& fileName, bool mirrored)
{
auto it = m_models.find(FileInfo(fileName, mirrored));
@@ -189,3 +204,4 @@ float CModelManager::GetHeight(std::vector<ModelTriangle>& triangles, Math::Vect
}
+
diff --git a/src/graphics/engine/modelmanager.h b/src/graphics/engine/modelmanager.h
index 601d636..9d50b97 100644
--- a/src/graphics/engine/modelmanager.h
+++ b/src/graphics/engine/modelmanager.h
@@ -53,6 +53,9 @@ public:
//! Returns the rank of base engine object of given loaded model
int GetModelBaseObjRank(const std::string& fileName, bool mirrored);
+ //! Deletes all copied objects
+ void DeleteAllModelCopies();
+
//! Unloads the given model
void UnloadModel(const std::string& fileName, bool mirrored);
//! Unloads all models
@@ -76,8 +79,10 @@ private:
std::string fileName;
bool mirrored;
- inline FileInfo(const std::string& fileName, bool mirrored)
- : fileName(fileName), mirrored(mirrored) {}
+ inline FileInfo(const std::string& _fileName, bool _mirrored)
+ : fileName(_fileName)
+ , mirrored(_mirrored)
+ {}
inline bool operator<(const FileInfo& other) const
{
@@ -91,7 +96,9 @@ private:
}
};
std::map<FileInfo, ModelInfo> m_models;
+ std::vector<int> m_copiesBaseRanks;
CEngine* m_engine;
};
} // namespace Gfx
+
diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp
index d15ee3b..abee2e2 100644
--- a/src/graphics/engine/particle.cpp
+++ b/src/graphics/engine/particle.cpp
@@ -3553,9 +3553,9 @@ void CParticle::DrawParticle(int sheet)
{
m_engine->SetTexture("text.png");
m_engine->SetState(ENG_RSTATE_TTEXTURE_WHITE);
- Math::Matrix mat;
- mat.LoadIdentity();
- m_device->SetTransform(TRANSFORM_WORLD, mat);
+ Math::Matrix matrix;
+ matrix.LoadIdentity();
+ m_device->SetTransform(TRANSFORM_WORLD, matrix);
for (int i = 0; i < m_wheelTraceTotal; i++)
DrawParticleWheel(i);
@@ -3917,3 +3917,4 @@ bool CParticle::WriteWheelTrace(const char *filename, int width, int height,
}
} // namespace Gfx
+
diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h
index 708a04d..7fb24a1 100644
--- a/src/graphics/engine/particle.h
+++ b/src/graphics/engine/particle.h
@@ -395,3 +395,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp
index 49bcb4c..0c96f63 100644
--- a/src/graphics/engine/planet.cpp
+++ b/src/graphics/engine/planet.cpp
@@ -185,3 +185,4 @@ int CPlanet::GetMode()
} // namespace Gfx
+
diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h
index 3762e1d..58d3aeb 100644
--- a/src/graphics/engine/planet.h
+++ b/src/graphics/engine/planet.h
@@ -118,3 +118,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp
index cab28b6..7c51829 100644
--- a/src/graphics/engine/pyro.cpp
+++ b/src/graphics/engine/pyro.cpp
@@ -89,13 +89,15 @@ bool CPyro::Create(PyroType type, CObject* obj, float force)
DisplayError(type, obj); // displays eventual messages
- int i = 0;
- // Copies all spheres of the object.
- for (; i < 50; i++)
{
- if ( !obj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
+ int i = 0;
+ // Copies all spheres of the object.
+ for (; i < 50; i++)
+ {
+ if ( !obj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
+ }
+ m_crashSphereUsed = i;
}
- m_crashSphereUsed = i;
// Calculates the size of the effect.
if ( oType == OBJECT_ANT ||
@@ -1554,8 +1556,15 @@ void CPyro::ExploStart()
for (int i = 0; i < OBJECTMAXPART; i++)
{
int objRank = m_object->GetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+ if (objRank == -1) continue;
+
+ // TODO: refactor later to material change
+ int oldBaseObjRank = m_engine->GetObjectBaseRank(objRank);
+ int newBaseObjRank = m_engine->CreateBaseObject();
+ m_engine->CopyBaseObject(oldBaseObjRank, newBaseObjRank);
+ m_engine->SetObjectBaseRank(objRank, newBaseObjRank);
+
+ m_engine->ChangeSecondTexture(objRank, "dirty04.png");
Math::Vector pos = m_object->GetPosition(i);
@@ -1616,6 +1625,13 @@ void CPyro::BurnStart()
{
int objRank = m_object->GetObjectRank(i);
if (objRank == -1) continue;
+
+ // TODO: refactor later to material change
+ int oldBaseObjRank = m_engine->GetObjectBaseRank(objRank);
+ int newBaseObjRank = m_engine->CreateBaseObject();
+ m_engine->CopyBaseObject(oldBaseObjRank, newBaseObjRank);
+ m_engine->SetObjectBaseRank(objRank, newBaseObjRank);
+
m_engine->ChangeSecondTexture(objRank, "dirty04.png");
}
m_engine->LoadTexture("dirty04.png");
@@ -2382,6 +2398,7 @@ void CPyro::LightOperFrame(float rTime)
{
if ( m_progress < m_lightOper[i].progress )
{
+ assert(i > 0); // TODO: if assert fails, fix the code
float progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
float intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
@@ -2399,3 +2416,4 @@ void CPyro::LightOperFrame(float rTime)
} // namespace Gfx
+
diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h
index 9548a07..98b9a1b 100644
--- a/src/graphics/engine/pyro.h
+++ b/src/graphics/engine/pyro.h
@@ -219,3 +219,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp
index c2a7855..4fe3057 100644
--- a/src/graphics/engine/terrain.cpp
+++ b/src/graphics/engine/terrain.cpp
@@ -1801,3 +1801,4 @@ float CTerrain::GetFlyingLimit(Math::Vector pos, bool noLimit)
} // namespace Gfx
+
diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h
index 1fa8dec..e2317c4 100644
--- a/src/graphics/engine/terrain.h
+++ b/src/graphics/engine/terrain.h
@@ -418,3 +418,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/test/CMakeLists.txt b/src/graphics/engine/test/CMakeLists.txt
deleted file mode 100644
index afaa86a..0000000
--- a/src/graphics/engine/test/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE debug)
-endif(NOT CMAKE_BUILD_TYPE)
-set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
-
-set(MODELFILE_TEST_SOURCES
-modelfile_test.cpp
-../modelfile.cpp
-../../../common/logger.cpp
-../../../common/stringutils.cpp
-)
-
-add_definitions(-DMODELFILE_NO_ENGINE)
-
-include_directories(
-.
-../../..
-${GTEST_INCLUDE_DIR}
-)
-
-add_executable(modelfile_test ${MODELFILE_TEST_SOURCES})
-
-target_link_libraries(modelfile_test gtest)
-
-add_test(modelfile_test modelfile_test)
diff --git a/src/graphics/engine/test/modelfile_test.cpp b/src/graphics/engine/test/modelfile_test.cpp
deleted file mode 100644
index e7078a9..0000000
--- a/src/graphics/engine/test/modelfile_test.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include "common/logger.h"
-#include "graphics/engine/modelfile.h"
-#include "math/func.h"
-
-#include <gtest/gtest.h>
-
-#include <cassert>
-#include <sstream>
-
-/* Test model file (new text format) */
-const char* const TEXT_MODEL =
-"# Colobot text model\n"
-"\n"
-"### HEAD\n"
-"version 1\n"
-"total_triangles 2\n"
-"\n"
-"### TRIANGLES\n"
-"p1 c -12.4099 10.0016 -2.54558 n 1 -0 1.87319e-07 t1 0.970703 0.751953 t2 0 0\n"
-"p2 c -12.4099 10.0016 2.54558 n 1 -0 1.87319e-07 t1 0.998047 0.751953 t2 0 0\n"
-"p3 c -12.4099 4.00165 -2.54558 n 1 -0 1.87319e-07 t1 0.970703 0.998047 t2 0 0\n"
-"mat dif 1 1 1 0 amb 0.5 0.5 0.5 0 spc 0 0 0 0\n"
-"tex1 lemt.png\n"
-"tex2\n"
-"var_tex2 N\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"
-"p2 c -19 4 4 n -1 0 0 t1 0.248047 0.00195312 t2 0.905224 0.614223\n"
-"p3 c -19 4 -4 n -1 0 0 t1 0.00195312 0.00195312 t2 0.0947756 0.614223\n"
-"mat dif 1 1 1 0 amb 0.5 0.5 0.5 0 spc 0 0 0 0\n"
-"tex1 derrick.png\n"
-"tex2\n"
-"var_tex2 Y\n"
-"lod_level 1\n"
-"state 0\n"
-"";
-
-// Triangles as defined in model file
-Gfx::ModelTriangle TRIANGLE_1;
-Gfx::ModelTriangle TRIANGLE_2;
-
-// Sets triangle data
-void Init()
-{
-
- TRIANGLE_1.p1 = Gfx::VertexTex2(Math::Vector(-12.4099, 10.0016, -2.54558),
- Math::Vector(1, 0, 1.87319e-07),
- Math::Point(0.970703, 0.751953),
- Math::Point(0, 0));
- TRIANGLE_1.p2 = Gfx::VertexTex2(Math::Vector(-12.4099, 10.0016, 2.54558),
- Math::Vector(1, 0, 1.87319e-07),
- Math::Point(0.998047, 0.751953),
- Math::Point(0, 0));
- TRIANGLE_1.p3 = Gfx::VertexTex2(Math::Vector(-12.4099, 4.00165, -2.54558),
- Math::Vector(1, 0, 1.87319e-07),
- Math::Point(0.970703, 0.998047),
- Math::Point(0, 0));
- TRIANGLE_1.material.diffuse = Gfx::Color(1, 1, 1, 0);
- TRIANGLE_1.material.ambient = Gfx::Color(0.5, 0.5, 0.5, 0);
- TRIANGLE_1.material.specular = Gfx::Color(0, 0, 0, 0);
- TRIANGLE_1.tex1Name = "lemt.png";
- TRIANGLE_1.variableTex2 = false;
- TRIANGLE_1.lodLevel = Gfx::LOD_Constant;
- TRIANGLE_1.state = 1024;
-
- TRIANGLE_2.p1 = Gfx::VertexTex2(Math::Vector(-19, -1, 4),
- Math::Vector(-1, 0, 0),
- Math::Point(0.248047, 0.123047),
- Math::Point(0.905224, 0.52067));
- TRIANGLE_2.p2 = Gfx::VertexTex2(Math::Vector(-19, 4, 4),
- Math::Vector(-1, 0, 0),
- Math::Point(0.248047, 0.00195312),
- Math::Point(0.905224, 0.614223));
- TRIANGLE_2.p3 = Gfx::VertexTex2(Math::Vector(-19, 4, -4),
- Math::Vector(-1, 0, 0),
- Math::Point(0.00195312, 0.00195312),
- Math::Point(0.0947756, 0.614223));
- TRIANGLE_2.material.diffuse = Gfx::Color(1, 1, 1, 0);
- TRIANGLE_2.material.ambient = Gfx::Color(0.5, 0.5, 0.5, 0);
- TRIANGLE_2.material.specular = Gfx::Color(0, 0, 0, 0);
- TRIANGLE_2.tex1Name = "derrick.png";
- TRIANGLE_2.variableTex2 = true;
- TRIANGLE_2.lodLevel = Gfx::LOD_Low;
- TRIANGLE_2.state = 0;
-}
-
-
-// Compares vertices (within Math::TOLERANCE)
-bool CompareVertices(const Gfx::VertexTex2& v1, const Gfx::VertexTex2& v2)
-{
- if ( !( Math::IsEqual(v1.coord.x, v2.coord.x) &&
- Math::IsEqual(v1.coord.y, v2.coord.y) &&
- Math::IsEqual(v1.coord.z, v2.coord.z) ) )
- return false;
-
- if ( !( Math::IsEqual(v1.normal.x, v2.normal.x) &&
- Math::IsEqual(v1.normal.y, v2.normal.y) &&
- Math::IsEqual(v1.normal.z, v2.normal.z) ) )
- return false;
-
- if ( !( Math::IsEqual(v1.texCoord.x, v2.texCoord.x) &&
- Math::IsEqual(v1.texCoord.y, v2.texCoord.y) ) )
- return false;
-
- if ( !( Math::IsEqual(v1.texCoord2.x, v2.texCoord2.x) &&
- Math::IsEqual(v1.texCoord2.y, v2.texCoord2.y) ) )
- return false;
-
- return true;
-}
-
-// Compares colors (within Math::TOLERANCE)
-bool CompareColors(const Gfx::Color& c1, const Gfx::Color& c2)
-{
- return Math::IsEqual(c1.r, c2.r) &&
- Math::IsEqual(c1.g, c2.g) &&
- Math::IsEqual(c1.b, c2.b) &&
- Math::IsEqual(c1.a, c2.a);
-}
-
-// Compares model triangles (within Math::TOLERANCE)
-bool CompareTriangles(const Gfx::ModelTriangle& t1, const Gfx::ModelTriangle& t2)
-{
- if (! CompareVertices(t1.p1, t2.p1))
- return false;
-
- if (! CompareVertices(t1.p2, t2.p2))
- return false;
-
- if (! CompareVertices(t1.p3, t2.p3))
- return false;
-
- if (! CompareColors(t1.material.diffuse, t2.material.diffuse))
- return false;
-
- if (! CompareColors(t1.material.ambient, t2.material.ambient))
- return false;
-
- if (! CompareColors(t1.material.specular, t2.material.specular))
- return false;
-
- if (t1.tex1Name != t2.tex1Name)
- return false;
-
- if (t1.tex2Name != t2.tex2Name)
- return false;
-
- if (t1.variableTex2 != t2.variableTex2)
- return false;
-
- if (t1.lodLevel != t2.lodLevel)
- return false;
-
- if (t1.state != t2.state)
- return false;
-
- return true;
-}
-
-// Tests reading/writing new text model file
-TEST(ModelFileTest, RWTxtModel)
-{
- std::stringstream str;
- str.str(TEXT_MODEL);
-
- Gfx::CModelFile modelFile;
-
- EXPECT_TRUE(modelFile.ReadTextModel(str));
-
- EXPECT_EQ(modelFile.GetTriangleCount(), 2);
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
-
- str.str("");
-
- EXPECT_TRUE(modelFile.WriteTextModel(str));
- str.seekg(0);
- EXPECT_TRUE(modelFile.ReadTextModel(str));
-
- EXPECT_EQ(modelFile.GetTriangleCount(), 2);
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
-}
-
-// Tests reading/writing new binary model
-TEST(ModelFileTest, RWBinModel)
-{
- std::stringstream str;
- str.str(TEXT_MODEL);
-
- Gfx::CModelFile modelFile;
-
- EXPECT_TRUE(modelFile.ReadTextModel(str));
-
- EXPECT_EQ(modelFile.GetTriangleCount(), 2);
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
-
- str.str("");
-
- EXPECT_TRUE(modelFile.WriteBinaryModel(str));
- str.seekg(0);
- EXPECT_TRUE(modelFile.ReadBinaryModel(str));
-
- EXPECT_EQ(modelFile.GetTriangleCount(), 2);
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
-}
-
-// Tests reading/writing old model file
-TEST(ModelFileTest, RWOldModel)
-{
- std::stringstream str;
- str.str(TEXT_MODEL);
-
- Gfx::CModelFile modelFile;
-
- EXPECT_TRUE(modelFile.ReadTextModel(str));
-
- EXPECT_EQ(modelFile.GetTriangleCount(), 2);
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
-
- str.str("");
-
- EXPECT_TRUE(modelFile.WriteModel(str));
- str.seekg(0);
- EXPECT_TRUE(modelFile.ReadModel(str));
-
- EXPECT_EQ(modelFile.GetTriangleCount(), 2);
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
- EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
-}
-
-int main(int argc, char **argv)
-{
- CLogger logger;
-
- Init();
-
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp
index 308c813..610bfcf 100644
--- a/src/graphics/engine/text.cpp
+++ b/src/graphics/engine/text.cpp
@@ -56,6 +56,7 @@ CText::CText(CEngine* engine)
m_engine = engine;
m_defaultSize = 12.0f;
+ m_tabSize = 4;
m_lastFontType = FONT_COLOBOT;
m_lastFontSize = 0;
@@ -148,6 +149,16 @@ void CText::FlushCache()
m_lastCachedFont = nullptr;
}
+int CText::GetTabSize()
+{
+ return m_tabSize;
+}
+
+void CText::SetTabSize(int tabSize)
+{
+ m_tabSize = tabSize;
+}
+
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,
@@ -309,11 +320,16 @@ float CText::GetStringWidth(const std::string &text,
return width;
}
-float CText::GetStringWidth(const std::string &text, FontType font, float size)
+float CText::GetStringWidth(std::string text, FontType font, float size)
{
assert(font != FONT_BUTTON);
- // TODO: special chars?
+ // Skip special chars
+ for (char& c : text)
+ {
+ if (c < 32)
+ c = ':';
+ }
CachedFont* cf = GetOrOpenFont(font, size);
assert(cf != nullptr);
@@ -328,8 +344,16 @@ float CText::GetCharWidth(UTF8Char ch, FontType font, float size, float offset)
// TODO: if (font == FONT_BUTTON)
if (font == FONT_BUTTON) return 0.0f;
- // TODO: special chars?
- // TODO: tab sizing
+ int width = 1;
+ if (ch.c1 < 32)
+ {
+ if (ch.c1 == '\t')
+ width = m_tabSize;
+
+ // TODO: tab sizing at intervals?
+
+ ch.c1 = ':';
+ }
CachedFont* cf = GetOrOpenFont(font, size);
assert(cf != nullptr);
@@ -341,7 +365,7 @@ float CText::GetCharWidth(UTF8Char ch, FontType font, float size, float offset)
else
tex = CreateCharTexture(ch, cf);
- return tex.charSize.x;
+ return tex.charSize.x * width;
}
@@ -505,6 +529,63 @@ int CText::Detect(const std::string &text, FontType font, float size, float offs
return index;
}
+UTF8Char CText::TranslateSpecialChar(int specialChar)
+{
+ UTF8Char ch;
+
+ switch (specialChar)
+ {
+ case CHAR_TAB:
+ ch.c1 = ':';
+ ch.c2 = 0;
+ ch.c3 = 0;
+ break;
+
+ case CHAR_NEWLINE:
+ // Unicode: U+21B2
+ ch.c1 = 0xE2;
+ ch.c2 = 0x86;
+ ch.c3 = 0xB2;
+ break;
+
+ case CHAR_DOT:
+ // Unicode: U+23C5
+ ch.c1 = 0xE2;
+ ch.c2 = 0x8F;
+ ch.c3 = 0x85;
+ break;
+
+ case CHAR_SQUARE:
+ // Unicode: U+25FD
+ ch.c1 = 0xE2;
+ ch.c2 = 0x97;
+ ch.c3 = 0xBD;
+ break;
+
+ case CHAR_SKIP_RIGHT:
+ // Unicode: U+25B6
+ ch.c1 = 0xE2;
+ ch.c2 = 0x96;
+ ch.c3 = 0xB6;
+ break;
+
+ case CHAR_SKIP_LEFT:
+ // Unicode: U+25C0
+ ch.c1 = 0xE2;
+ ch.c2 = 0x97;
+ ch.c3 = 0x80;
+ break;
+
+ default:
+ ch.c1 = '?';
+ ch.c2 = 0;
+ ch.c3 = 0;
+ break;
+ }
+
+ return ch;
+}
+
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)
@@ -532,7 +613,11 @@ void CText::DrawString(const std::string &text, std::vector<FontMetaChar>::itera
float cw = GetCharWidth(ch, font, size, offset);
if (offset + cw > width) // exceeds the maximum width?
{
- // TODO: special end-of-line char
+ ch = TranslateSpecialChar(CHAR_SKIP_RIGHT);
+ cw = GetCharWidth(ch, font, size, offset);
+ pos.x = start + width - cw;
+ color = Color(1.0f, 0.0f, 0.0f);
+ DrawCharAndAdjustPos(ch, font, size, pos, color);
break;
}
@@ -550,7 +635,13 @@ void CText::DrawString(const std::string &text, std::vector<FontMetaChar>::itera
fmtIndex++;
}
- // TODO: eol
+ if (eol != 0)
+ {
+ FontType font = FONT_COLOBOT;
+ UTF8Char ch = TranslateSpecialChar(eol);
+ color = Color(1.0f, 0.0f, 0.0f);
+ DrawCharAndAdjustPos(ch, font, size, pos, color);
+ }
}
void CText::StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars)
@@ -675,23 +766,18 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::P
// TODO: if (font == FONT_BUTTON)
if (font == FONT_BUTTON) return;
- // TODO: special chars?
-
CachedFont* cf = GetOrOpenFont(font, size);
if (cf == nullptr)
return;
int width = 1;
- if (ch.c1 > 0 && ch.c1 < 32) { // FIXME add support for chars with code 9 10 23
- if (ch.c1 == '\t') {
- ch.c1 = ':';
- width = 4;
- } else {
- ch.c1 = ' ';
- }
- ch.c2 = 0;
- ch.c3 = 0;
+ if (ch.c1 > 0 && ch.c1 < 32)
+ {
+ if (ch.c1 == '\t')
+ width = m_tabSize;
+
+ ch = TranslateSpecialChar(ch.c1);
}
auto it = cf->cache.find(ch);
@@ -827,3 +913,4 @@ CharTexture CText::CreateCharTexture(UTF8Char ch, CachedFont* font)
} // namespace Gfx
+
diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h
index 6bcc59b..3abb8b7 100644
--- a/src/graphics/engine/text.h
+++ b/src/graphics/engine/text.h
@@ -206,6 +206,20 @@ struct MultisizeFont
};
/**
+ * \enum SpecialChar
+ * \brief Special codes for certain characters
+ */
+enum SpecialChar
+{
+ CHAR_TAB = '\t', //! Tab character - :
+ CHAR_NEWLINE = '\n', //! Newline character - arrow pointing down and left
+ CHAR_DOT = 1, //! Single dot in the middle
+ CHAR_SQUARE = 2, //! Square
+ CHAR_SKIP_RIGHT = 5, //! Filled triangle pointing right
+ CHAR_SKIP_LEFT = 6 //! Filled triangle pointing left
+};
+
+/**
* \class CText
* \brief Text rendering engine
*
@@ -240,6 +254,12 @@ public:
//! Flushes cached textures
void FlushCache();
+ //@{
+ //! Tab size management
+ void SetTabSize(int tabSize);
+ int GetTabSize();
+ //@}
+
//! Draws text (multi-format)
void DrawText(const std::string &text, std::vector<FontMetaChar>::iterator format,
std::vector<FontMetaChar>::iterator end,
@@ -268,11 +288,11 @@ public:
float GetHeight(FontType font, float size);
//! Returns width of string (multi-format)
- TEST_VIRTUAL float GetStringWidth(const std::string &text,
- std::vector<FontMetaChar>::iterator format,
- std::vector<FontMetaChar>::iterator end, float size);
+ TEST_VIRTUAL float GetStringWidth(const std::string& text,
+ 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);
+ TEST_VIRTUAL float GetStringWidth(std::string text, FontType font, float size);
//! Returns width of single character
TEST_VIRTUAL float GetCharWidth(UTF8Char ch, FontType font, float size, float offset);
@@ -290,6 +310,8 @@ public:
//! Returns the most suitable position to a given offset (one font)
int Detect(const std::string &text, FontType font, float size, float offset);
+ UTF8Char TranslateSpecialChar(int specialChar);
+
protected:
CachedFont* GetOrOpenFont(FontType type, float size);
CharTexture CreateCharTexture(UTF8Char ch, CachedFont* font);
@@ -309,6 +331,7 @@ protected:
std::string m_error;
float m_defaultSize;
+ int m_tabSize;
std::map<FontType, MultisizeFont*> m_fonts;
@@ -319,3 +342,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp
index d90652b..d1f8d29 100644
--- a/src/graphics/engine/water.cpp
+++ b/src/graphics/engine/water.cpp
@@ -628,3 +628,4 @@ void CWater::AdjustEye(Math::Vector &eye)
} // namespace Gfx
+
diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h
index bb113e0..5e9f4b2 100644
--- a/src/graphics/engine/water.h
+++ b/src/graphics/engine/water.h
@@ -204,3 +204,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/opengl/README.txt b/src/graphics/opengl/README.txt
index c62166b..1a6bedd 100644
--- a/src/graphics/opengl/README.txt
+++ b/src/graphics/opengl/README.txt
@@ -5,3 +5,4 @@
* Contains the concrete implementation using OpenGL of abstract CDevice class
* from src/graphics/core
*/
+
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index df64e34..bbabdd6 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -79,6 +79,106 @@ void CGLDevice::DebugHook()
glColor3i(0, 0, 0);
}
+void CGLDevice::DebugLights()
+{
+ Gfx::ColorHSV color(0.0, 1.0, 1.0);
+
+ glLineWidth(3.0f);
+ glDisable(GL_LIGHTING);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_BLEND);
+
+ Math::Matrix saveWorldMat = m_worldMat;
+ m_worldMat.LoadIdentity();
+ UpdateModelviewMatrix();
+
+ for (int i = 0; i < static_cast<int>( m_lights.size() ); ++i)
+ {
+ color.h = static_cast<float>(i) / static_cast<float>(m_lights.size());
+ if (m_lightsEnabled[i])
+ {
+ const Light& l = m_lights[i];
+ if (l.type == LIGHT_DIRECTIONAL)
+ {
+ Gfx::VertexCol v[2];
+ v[0].coord = -Math::Normalize(l.direction) * 100.0f + Math::Vector(0.0f, 0.0f, 1.0f) * i;
+ v[0].color = HSV2RGB(color);
+ v[1].coord = Math::Normalize(l.direction) * 100.0f + Math::Vector(0.0f, 0.0f, 1.0f) * i;
+ v[1].color = HSV2RGB(color);
+ while (v[0].coord.y < 60.0f && v[0].coord.y < 60.0f)
+ {
+ v[0].coord.y += 10.0f;
+ v[1].coord.y += 10.0f;
+ }
+ DrawPrimitive(PRIMITIVE_LINES, v, 2);
+
+ v[0].coord = v[1].coord + Math::Normalize(v[0].coord - v[1].coord) * 50.0f;
+
+ glLineWidth(10.0f);
+ DrawPrimitive(PRIMITIVE_LINES, v, 2);
+ glLineWidth(3.0f);
+ }
+ else if (l.type == LIGHT_POINT)
+ {
+ Gfx::VertexCol v[8];
+ for (int i = 0; i < 8; ++i)
+ v[i].color = HSV2RGB(color);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector( 1.0f, -1.0f, -1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, 1.0f, -1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector(-1.0f, 1.0f, -1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector( 1.0f, -1.0f, 1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, 1.0f, 1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector(-1.0f, 1.0f, 1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, -1.0f, -1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector( 1.0f, -1.0f, 1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector( 1.0f, 1.0f, -1.0f) * 4.0f;
+ v[5].coord = l.position + Math::Vector( 1.0f, 1.0f, 1.0f) * 4.0f;
+ v[6].coord = l.position + Math::Vector(-1.0f, 1.0f, -1.0f) * 4.0f;
+ v[7].coord = l.position + Math::Vector(-1.0f, 1.0f, 1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINES, v, 8);
+ }
+ else if (l.type == LIGHT_SPOT)
+ {
+ Gfx::VertexCol v[5];
+ for (int i = 0; i < 5; ++i)
+ v[i].color = HSV2RGB(color);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, 0.0f, -1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector( 1.0f, 0.0f, -1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, 0.0f, 1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector(-1.0f, 0.0f, 1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector(-1.0f, 0.0f, -1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5);
+
+ v[0].coord = l.position;
+ v[1].coord = l.position + Math::Normalize(l.direction) * 100.0f;
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(3.0, 0xFF);
+ DrawPrimitive(PRIMITIVE_LINES, v, 2);
+ glDisable(GL_LINE_STIPPLE);
+ }
+ }
+ }
+
+ glLineWidth(1.0f);
+ glEnable(GL_LIGHTING);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_BLEND);
+ m_worldMat = saveWorldMat;
+ UpdateModelviewMatrix();
+}
+
bool CGLDevice::Create()
{
GetLogger()->Info("Creating CDevice\n");
@@ -417,13 +517,21 @@ bool CGLDevice::GetLightEnabled(int index)
Texture CGLDevice::CreateTexture(CImage *image, const TextureCreateParams &params)
{
ImageData *data = image->GetData();
- if (data == NULL)
+ if (data == nullptr)
{
GetLogger()->Error("Invalid texture data\n");
return Texture(); // invalid texture
}
- return CreateTexture(data, params);
+ Math::IntPoint originalSize = image->GetSize();
+
+ if (params.padToNearestPowerOfTwo)
+ image->PadToNearestPowerOfTwo();
+
+ Texture tex = CreateTexture(data, params);
+ tex.originalSize = originalSize;
+
+ return tex;
}
Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &params)
@@ -433,6 +541,11 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
result.size.x = data->surface->w;
result.size.y = data->surface->h;
+ if (!Math::IsPowerOfTwo(result.size.x) || !Math::IsPowerOfTwo(result.size.y))
+ GetLogger()->Warn("Creating non-power-of-2 texture (%dx%d)!\n", result.size.x, result.size.y);
+
+ result.originalSize = result.size;
+
// Use & enable 1st texture stage
if (m_multitextureAvailable)
glActiveTexture(GL_TEXTURE0);
@@ -640,7 +753,7 @@ void CGLDevice::SetTexture(int index, const Texture &texture)
glBindTexture(GL_TEXTURE_2D, texture.id);
// Params need to be updated for the new bound texture
- SetTextureStageParams(index, m_textureStageParams[index]);
+ UpdateTextureParams(index);
}
void CGLDevice::SetTexture(int index, unsigned int textureId)
@@ -661,7 +774,7 @@ void CGLDevice::SetTexture(int index, unsigned int textureId)
glBindTexture(GL_TEXTURE_2D, textureId);
// Params need to be updated for the new bound texture
- SetTextureStageParams(index, m_textureStageParams[index]);
+ UpdateTextureParams(index);
}
/**
@@ -714,6 +827,13 @@ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams &param
// Remember the settings
m_textureStageParams[index] = params;
+ UpdateTextureParams(index);
+}
+
+void CGLDevice::UpdateTextureParams(int index)
+{
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
+
if (!m_multitextureAvailable && index != 0)
return;
@@ -721,6 +841,8 @@ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams &param
if (! m_currentTextures[index].Valid())
return;
+ const TextureStageParams &params = m_textureStageParams[index];
+
if (m_multitextureAvailable)
glActiveTexture(GL_TEXTURE0 + index);
@@ -1667,3 +1789,4 @@ FillMode CGLDevice::GetFillMode()
} // namespace Gfx
+
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index fe3f2a1..c648161 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -93,6 +93,7 @@ public:
virtual ~CGLDevice();
virtual void DebugHook();
+ virtual void DebugLights();
virtual bool Create();
virtual void Destroy();
@@ -192,6 +193,8 @@ private:
void UpdateModelviewMatrix();
//! Updates position for given light based on transformation matrices
void UpdateLightPosition(int index);
+ //! Updates the texture params for given texture stage
+ void UpdateTextureParams(int index);
private:
//! Current config
@@ -255,3 +258,4 @@ private:
} // namespace Gfx
+