summaryrefslogtreecommitdiffstats
path: root/src/graphics/engine
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-08-13 00:14:42 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-08-13 00:14:42 +0200
commit712154bc4fcfb50c05c57a875e3b2affdc5e2b1b (patch)
tree9b13ef9f64cf272a8c67effdb62c2459306bd167 /src/graphics/engine
parent146ad47e4afbf1fe82763c94c2cd2209285f869f (diff)
downloadcolobot-712154bc4fcfb50c05c57a875e3b2affdc5e2b1b.tar.gz
colobot-712154bc4fcfb50c05c57a875e3b2affdc5e2b1b.tar.bz2
colobot-712154bc4fcfb50c05c57a875e3b2affdc5e2b1b.zip
Rendering functions, documentation
- rewrote the render functions for CEngine, CCloud and CWater - added documentation
Diffstat (limited to 'src/graphics/engine')
-rw-r--r--src/graphics/engine/cloud.cpp97
-rw-r--r--src/graphics/engine/cloud.h20
-rw-r--r--src/graphics/engine/engine.cpp452
-rw-r--r--src/graphics/engine/engine.h107
-rw-r--r--src/graphics/engine/lightning.h7
-rw-r--r--src/graphics/engine/modelfile.cpp44
-rw-r--r--src/graphics/engine/particle.h7
-rw-r--r--src/graphics/engine/planet.h13
-rw-r--r--src/graphics/engine/pyro.h7
-rw-r--r--src/graphics/engine/terrain.h43
-rw-r--r--src/graphics/engine/water.cpp197
-rw-r--r--src/graphics/engine/water.h33
12 files changed, 575 insertions, 452 deletions
diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp
index d7bac0f..6f6bc57 100644
--- a/src/graphics/engine/cloud.cpp
+++ b/src/graphics/engine/cloud.cpp
@@ -20,6 +20,7 @@
#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 "math/geometry.h"
@@ -94,112 +95,96 @@ void Gfx::CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep,
void Gfx::CCloud::Draw()
{
- /* TODO!
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2* vertex;
- Math::Matrix* matView;
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector n, pos, p, eye;
- Math::Point uv1, uv2;
- float iDeep, deep, size, fogStart, fogEnd;
- int i, j, u;
-
- if ( !m_enable ) return;
- if ( m_level == 0.0f ) return;
- if ( m_linesUsed == 0 ) return;
-
- vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
-
- iDeep = m_engine->GetDeepView();
- deep = (m_brick*m_size)/2.0f;
+ if (! m_enable) return;
+ if (m_level == 0.0f) return;
+ if (m_lines.empty()) return;
+
+ std::vector<Gfx::VertexTex2> vertices((m_brick+2)*2, Gfx::VertexTex2());
+
+ float iDeep = m_engine->GetDeepView();
+ float deep = (m_brick*m_size)/2.0f;
m_engine->SetDeepView(deep);
m_engine->SetFocus(m_engine->GetFocus());
m_engine->UpdateMatProj(); // increases the depth of view
- fogStart = deep*0.15f;
- fogEnd = deep*0.24f;
+ float fogStart = deep*0.15f;
+ float fogEnd = deep*0.24f;
- device = m_engine->GetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000);
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart));
- device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd));
+ Gfx::CDevice* device = m_engine->GetDevice();
- matView = m_engine->GetMatView();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(*matView);
- device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
+ // TODO: do this better?
+ device->SetFogParams(Gfx::FOG_LINEAR, m_engine->GetFogColor( m_engine->GetRankView() ),
+ fogStart, fogEnd, 1.0f);
+
+ device->SetTransform(Gfx::TRANSFORM_VIEW, m_engine->GetMatView());
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ Gfx::Material material;
material.diffuse = m_diffuse;
material.ambient = m_ambient;
m_engine->SetMaterial(material);
- m_engine->SetTexture(m_filename, 0);
- m_engine->SetTexture(m_filename, 1);
+ m_engine->SetTexture(m_fileName, 0);
+ m_engine->SetTexture(m_fileName, 1);
- m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP);
+ m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_BLACK | Gfx::ENG_RSTATE_FOG | Gfx::ENG_RSTATE_WRAP);
+ Math::Matrix matrix;
matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ device->SetTransform(Gfx::TRANSFORM_WORLD, matrix);
- size = m_size/2.0f;
- eye = m_engine->GetEyePt();
- n = Math::Vector(0.0f, -1.0f, 0.0f);
+ float size = m_size/2.0f;
+ Math::Vector eye = m_engine->GetEyePt();
+ Math::Vector n = Math::Vector(0.0f, -1.0f, 0.0f);
- // Draws all the lines.
- for ( i=0 ; i<m_linesUsed ; i++ )
+ // Draws all the lines
+ for (int i = 0; i < static_cast<int>( m_lines.size() ); i++)
{
+ Math::Vector pos;
pos.y = m_level;
pos.z = m_lines[i].pz;
pos.x = m_lines[i].px1;
- u = 0;
+ int vertexIndex = 0;
+
+ Math::Vector p;
+ Math::Point uv1, uv2;
+
p.x = pos.x-size;
p.z = pos.z+size;
p.y = pos.y;
AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
p.x = pos.x-size;
p.z = pos.z-size;
p.y = pos.y;
AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
- for ( j=0 ; j<m_lines[i].len ; j++ )
+ for (int j = 0; j < m_lines[i].len; j++)
{
p.x = pos.x+size;
p.z = pos.z+size;
p.y = pos.y;
AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
p.x = pos.x+size;
p.z = pos.z-size;
p.y = pos.y;
AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
pos.x += size*2.0f;
}
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
- m_engine->AddStatisticTriangle(u-2);
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, &vertices[0], vertexIndex);
+ m_engine->AddStatisticTriangle(vertexIndex - 2);
}
m_engine->SetDeepView(iDeep);
m_engine->SetFocus(m_engine->GetFocus());
m_engine->UpdateMatProj(); // gives depth to initial
-
- free(vertex); */
}
void Gfx::CCloud::CreateLine(int x, int y, int len)
diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h
index 079f77b..abfaf26 100644
--- a/src/graphics/engine/cloud.h
+++ b/src/graphics/engine/cloud.h
@@ -40,12 +40,19 @@ namespace Gfx {
class CEngine;
class CTerrain;
+/**
+ * \struct CloudLine
+ * \brief Cloud strip
+ */
struct CloudLine
{
- //! Beginning
+ //@{
+ //! Beginning (terrain coordinates)
short x, y;
- //! In length x
+ //@}
+ //! Length in X direction (terrain coordinates)
short len;
+ //! X (1, 2) and Z coordinates (world coordinates)
float px1, px2, pz;
CloudLine()
@@ -57,6 +64,15 @@ struct CloudLine
};
+/**
+ * \class CCloud
+ * \brief Cloud layer renderer
+ *
+ * Renders the cloud layer as fog. Cloud layer is similar to water layer
+ * - it occurs only at specified level of terrain. Cloud map is created
+ * the same way water is created. CloudLine structs are used to specify
+ * lines in X direction in XY terrain coordinates.
+ */
class CCloud
{
public:
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index ddc6b23..5988949 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -946,7 +946,7 @@ bool Gfx::CEngine::AddQuick(int objRank, const Gfx::EngineObjLevel4& buffer,
if (buffer.type == Gfx::ENG_TRIANGLE_TYPE_TRIANGLES)
m_objects[objRank].totalTriangles += buffer.vertices.size() / 3;
- else // surfaces
+ else if (buffer.type == Gfx::ENG_TRIANGLE_TYPE_SURFACE)
m_objects[objRank].totalTriangles += buffer.vertices.size() - 2;
return true;
@@ -2203,13 +2203,15 @@ bool Gfx::CEngine::LoadAllTextures()
if (! p1.tex1Name.empty())
{
- if (! LoadTexture(p1.tex1Name).Valid())
+ p1.tex1 = LoadTexture(p1.tex1Name);
+ if (! p1.tex1.Valid())
ok = false;
}
if (! p1.tex2Name.empty())
{
- if (! LoadTexture(p1.tex2Name).Valid())
+ p1.tex2 = LoadTexture(p1.tex2Name);
+ if (! p1.tex2.Valid())
ok = false;
}
}
@@ -2865,15 +2867,6 @@ void Gfx::CEngine::Render()
void Gfx::CEngine::Draw3DScene()
{
- /* TODO!
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, objRank;*/
-
if (m_groundSpotVisible)
UpdateGroundSpotTextures();
@@ -2899,144 +2892,144 @@ void Gfx::CEngine::Draw3DScene()
if (m_shadowVisible)
{
- // Draw the field
- // TODO!
- /*
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ // Draw the terrain
+
+ for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
{
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->tex1Name, 0);
- SetTexture(p2->tex2Name, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ Gfx::EngineObjLevel1& p1 = m_objectTree[l1];
+ if (! p1.used) continue;
+
+ // Should be loaded by now
+ SetTexture(p1.tex1, 0);
+ SetTexture(p1.tex2, 1);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_objects[objRank].type != TYPETERRAIN ) continue;
- if ( !m_objects[objRank].bDrawWorld ) continue;
+ Gfx::EngineObjLevel2& p2 = p1.next[l2];
+ if (! p2.used) continue;
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objects[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ int objRank = p2.objRank;
+ if (m_objects[objRank].type != Gfx::ENG_OBJTYPE_TERRAIN)
+ continue;
+ if (! m_objects[objRank].drawWorld)
+ continue;
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objects[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objects[objRank].distance < p4->min ||
- m_objects[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ Gfx::EngineObjLevel3& p3 = p2.next[l1];
+ if (! p3.used) continue;
+
+ if ( m_objects[objRank].distance < p3.min ||
+ m_objects[objRank].distance >= p3.max ) continue;
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ Gfx::EngineObjLevel4& p4 = p3.next[l4];
+ if (! p4.used) continue;
+
+ SetMaterial(p4.material);
+ SetState(p4.state);
+
+ if (p4.type == Gfx::ENG_TRIANGLE_TYPE_TRIANGLES)
{
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLES,
+ &p4.vertices[0],
+ p4.vertices.size() );
+ m_statisticTriangle += p4.vertices.size() / 3;
+ }
+ if (p4.type == Gfx::ENG_TRIANGLE_TYPE_SURFACE)
+ {
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLE_STRIP,
+ &p4.vertices[0],
+ p4.vertices.size() );
+ m_statisticTriangle += p4.vertices.size() - 2;
}
}
}
}
- }*/
+ }
// Draws the shadows
DrawShadow();
}
- // Draw objects
+ // Draw objects (non-terrain)
+
bool transparent = false;
- /* TODO!
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->tex1Name, 0);
- SetTexture(p2->tex2Name, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+
+ for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
+ {
+ Gfx::EngineObjLevel1& p1 = m_objectTree[l1];
+ if (! p1.used) continue;
+
+ // Should be loaded by now
+ SetTexture(p1.tex1, 0);
+ SetTexture(p1.tex2, 1);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_bShadow && m_objects[objRank].type == TYPETERRAIN ) continue;
- if ( !m_objects[objRank].bDrawWorld ) continue;
+ Gfx::EngineObjLevel2& p2 = p1.next[l2];
+ if (! p2.used) continue;
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objects[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ int objRank = p2.objRank;
+
+ if (m_shadowVisible && m_objects[objRank].type == Gfx::ENG_OBJTYPE_TERRAIN)
+ continue;
+
+ if (! m_objects[objRank].drawWorld)
+ continue;
+
+ m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_objects[objRank].transform);
+
+ if (! IsVisible(objRank))
+ continue;
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objects[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ m_lightMan->UpdateLightsEnableState(m_objects[objRank].type);
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objects[objRank].distance < p4->min ||
- m_objects[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ Gfx::EngineObjLevel3& p3 = p2.next[l1];
+ if (! p3.used) continue;
+
+ if ( m_objects[objRank].distance < p3.min ||
+ m_objects[objRank].distance >= p3.max ) continue;
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ Gfx::EngineObjLevel4& p4 = p3.next[l4];
+ if (! p4.used) continue;
+
+ if (m_objects[objRank].transparency != 0.0f) // transparent ?
{
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- if ( m_objects[objRank].transparency != 0.0f ) // transparent ?
- {
- transparent = true;
- continue;
- }
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
+ transparent = true;
+ continue;
+ }
+
+ SetMaterial(p4.material);
+ SetState(p4.state);
+
+ if (p4.type == Gfx::ENG_TRIANGLE_TYPE_TRIANGLES)
+ {
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLES,
+ &p4.vertices[0],
+ p4.vertices.size() );
+
+ m_statisticTriangle += p4.vertices.size() / 3;
+ }
+ else if (p4.type == Gfx::ENG_TRIANGLE_TYPE_SURFACE)
+ {
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLE_STRIP,
+ &p4.vertices[0],
+ p4.vertices.size() );
+
+ m_statisticTriangle += p4.vertices.size() - 2;
}
}
}
}
- }*/
+ }
+
+ // Draw transparent objects
if (transparent)
{
@@ -3053,70 +3046,73 @@ void Gfx::CEngine::Draw3DScene()
tColor = Gfx::Color(136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f);
}
- // Draw transparent objects.
- /* TODO!
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
{
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->tex1Name, 0);
- SetTexture(p2->tex2Name, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ Gfx::EngineObjLevel1& p1 = m_objectTree[l1];
+ if (! p1.used) continue;
+
+ // Should be loaded by now
+ SetTexture(p1.tex1, 0);
+ SetTexture(p1.tex2, 1);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_bShadow && m_objects[objRank].type == TYPETERRAIN ) continue;
- if ( !m_objects[objRank].bDrawWorld ) continue;
+ Gfx::EngineObjLevel2& p2 = p1.next[l2];
+ if (! p2.used) continue;
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objects[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ int objRank = p2.objRank;
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objects[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ if (m_shadowVisible && m_objects[objRank].type == Gfx::ENG_OBJTYPE_TERRAIN)
+ continue;
+
+ if (! m_objects[objRank].drawWorld)
+ continue;
+
+ m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_objects[objRank].transform);
+
+ if (! IsVisible(objRank))
+ continue;
+
+ m_lightMan->UpdateLightsEnableState(m_objects[objRank].type);
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objects[objRank].distance < p4->min ||
- m_objects[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ Gfx::EngineObjLevel3& p3 = p2.next[l1];
+ if (! p3.used) continue;
+
+ if ( m_objects[objRank].distance < p3.min ||
+ m_objects[objRank].distance >= p3.max ) continue;
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ Gfx::EngineObjLevel4& p4 = p3.next[l4];
+ if (! p4.used) continue;
+
+ if (m_objects[objRank].transparency == 0.0f)
+ continue;
+
+ SetMaterial(p4.material);
+ SetState(tState, tColor);
+
+ if (p4.type == Gfx::ENG_TRIANGLE_TYPE_TRIANGLES)
{
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- if ( m_objects[objRank].transparency == 0.0f ) continue;
- SetState(tState, tColor);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLES,
+ &p4.vertices[0],
+ p4.vertices.size() );
+
+ m_statisticTriangle += p4.vertices.size() / 3;
+ }
+ else if (p4.type == Gfx::ENG_TRIANGLE_TYPE_SURFACE)
+ {
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLE_STRIP,
+ &p4.vertices[0],
+ p4.vertices.size() );
+ m_statisticTriangle += p4.vertices.size() - 2;
}
}
}
}
- } */
+ }
}
m_lightMan->UpdateLightsEnableState(Gfx::ENG_OBJTYPE_TERRAIN);
@@ -3165,68 +3161,70 @@ void Gfx::CEngine::DrawInterface()
m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matView);
- // TODO!
- /*
- for (int l1 = 0; l1 < m_objectTree.size(); l1++)
+ for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
{
- Gfx::EngineObjLevel1* p1 = &m_objectTree[l1];
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->tex1Name, 0);
- SetTexture(p2->tex2Name, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ Gfx::EngineObjLevel1& p1 = m_objectTree[l1];
+ if (! p1.used) continue;
+
+ // Should be loaded by now
+ SetTexture(p1.tex1, 0);
+ SetTexture(p1.tex2, 1);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( !m_objects[objRank].bDrawFront ) continue;
+ Gfx::EngineObjLevel2& p2 = p1.next[l2];
+ if (! p2.used) continue;
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objects[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ int objRank = p2.objRank;
+
+ if (m_shadowVisible && m_objects[objRank].type == Gfx::ENG_OBJTYPE_TERRAIN)
+ continue;
+
+ if (! m_objects[objRank].drawFront)
+ continue;
+
+ m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_objects[objRank].transform);
+
+ if (! IsVisible(objRank))
+ continue;
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objects[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ m_lightMan->UpdateLightsEnableState(m_objects[objRank].type);
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objects[objRank].distance < p4->min ||
- m_objects[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ Gfx::EngineObjLevel3& p3 = p2.next[l1];
+ if (! p3.used) continue;
+
+ if ( m_objects[objRank].distance < p3.min ||
+ m_objects[objRank].distance >= p3.max ) continue;
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
{
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ Gfx::EngineObjLevel4& p4 = p3.next[l4];
+ if (! p4.used) continue;
+
+ SetMaterial(p4.material);
+ SetState(p4.state);
+
+ if (p4.type == Gfx::ENG_TRIANGLE_TYPE_TRIANGLES)
{
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLES,
+ &p4.vertices[0],
+ p4.vertices.size() );
+
+ m_statisticTriangle += p4.vertices.size() / 3;
+ }
+ else if (p4.type == Gfx::ENG_TRIANGLE_TYPE_SURFACE)
+ {
+ m_device->DrawPrimitive( Gfx::PRIMITIVE_TRIANGLE_STRIP,
+ &p4.vertices[0],
+ p4.vertices.size() );
+ m_statisticTriangle += p4.vertices.size() - 2;
}
}
}
}
- }*/
+ }
m_particle->DrawParticle(Gfx::SH_FRONT); // draws the particles of the 3D world
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 3f21e0d..b3a576a 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -539,24 +539,95 @@ struct EngineMouse
/**
- \class CEngine
- \brief The graphics engine
-
- This is the main class for graphics engine. It is responsible for drawing the 3D scene,
- setting various render states, and facilitating the drawing of 2D interface.
-
- It uses a lower-level CDevice object which is implementation-independent core engine.
-
- \section Objecs Engine objects
-
- The 3D scene is composed of objects which are basically collections of triangles forming
- a surface or simply independent triangles in space. Objects are stored in the engine
- as a tree structure which is composed of 4 tiers (EngineObjLevel1, EngineObjLevel2 and so on).
- Each tier stores some data about object triangle, like textures or materials used.
- Additional information on objects stored are in EngineObject structure.
- Each object is uniquely identified by its rank.
-
- ...
+ * \class CEngine
+ * \brief The graphics engine
+ *
+ * This is the main class for graphics engine. It is responsible for drawing the 3D scene,
+ * setting various render states, and facilitating the drawing of 2D interface.
+ *
+ * It uses a lower-level CDevice object which is implementation-independent core engine.
+ *
+ * \section 3DScene 3D Scene
+ *
+ * The 3D scene is drawn with view coordinates set from camera position in 3D space and
+ * a perspective projection matrix. The world matrix depends on the object drawn.
+ * The coordinate system is left-handed: X axis is to the right, Y axis to the top and Z axis
+ * is into the screen (Z = 0 is the sceen surface).
+ *
+ * In general, the 3D scene is composed of the following things:
+ * - sky background (gradient or texture image)
+ * - planets orbiting in the sky (drawn by CPlanet)
+ * - terrain - ground of the game level (part of engine objects)
+ * - main scene objects - robots, buildings, etc. (engine objects)
+ * - water/lava (drawn by CWater)
+ * - cloud layer (drawn by CCloud)
+ * - fire, lightning and particle effects (CPyro, CLightning and CParticle)
+ * - foreground image overlaid onto the scene at the end - for example, aiming crosshairs
+ * - 2D interface controls available in-game
+ * - mouse cursor
+ * - animated highlight box of the selected object(s)
+ *
+ * \section 2DInterface 2D Interface
+ *
+ * The 2D interface is drawn in fixed XY coordinates, independent from window size.
+ * Lower-left corner of the screen is (0,0) and upper-right corner is (1,1).
+ * Matrices for world, view and projection are therefore fixed and never change.
+ *
+ * The class tracks the change of window coordinates and conversion functions
+ * between the window and interface coordinates are provided.
+ *
+ * Interface drawing is delegated to CInterface class and particular controls
+ * are instances of CControl class. The source code for these classes is in
+ * src/ui directory.
+ *
+ * \section Objecs Engine Objects
+ *
+ * The 3D scene is composed of objects which are basically collections of triangles forming
+ * a surface or simply independent triangles in space.
+ *
+ * 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.
+ *
+ * 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
+ *
+ * NOTE: type of object in this context means only the internal type in 3D engine. It is not related
+ * to CObject types.
+ *
+ * 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).
+ *
+ * \section Shadows Shadows
+ *
+ * Each engine object can be associated with a shadow (EngineShadow). Like objects, shadows are
+ * identified by their rank obtained upon creation.
+ *
+ * ...
+ *
+ * \section RenderStates Render States
+ *
+ * Almost every primitive drawn on screen is drawn in state set through EngineRenderState enum.
+ * In some functions, custom modes are still set, using CDevice's SetRenderState. However, it
+ * will be subject to removal in the future. Generally, setting render states should be minimized
+ * to avoid unnecessary overhead.
+ *
+ * Some states are clearly the result of legacy drawing and texturing methods. For example, TTEXTURE
+ * states should really be removed and the textures changed to ones with alpha channel. In the future,
+ * the whole modesetting code will probably be refactored to something more maintainable.
+ *
+ * \section Textures Textures
+ *
+ * Textures are loaded from a texture subdir in data directory. In the old code, textures were identified
+ * by file name and loaded using some D3D util code. With new code and OpenGL backend, this approach is not
+ * efficient - name comparison, etc. takes a lot of time. In the future, textures should be loaded once
+ * at object creation time, and then referenced to as Gfx::Texture structs, or even as unsigned int ID's
+ * 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
{
diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h
index 3b4e2cf..e34eb3b 100644
--- a/src/graphics/engine/lightning.h
+++ b/src/graphics/engine/lightning.h
@@ -47,7 +47,12 @@ enum BlitzPhase
BPH_BLITZ,
};
-
+/**
+ * \class CLightning
+ * \brief Lightning effect renderer
+ *
+ * Functions are only stubs for now.
+ */
class CLightning
{
public:
diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp
index 844958f..9d7a389 100644
--- a/src/graphics/engine/modelfile.cpp
+++ b/src/graphics/engine/modelfile.cpp
@@ -723,25 +723,18 @@ bool Gfx::CModelFile::ReadDXF(std::istream &stream, float min, float max)
bool Gfx::CModelFile::CreateEngineObject(int objRank, int addState)
{
- /*char texName1[20];
- char texName2[20];
- int texNum, i, state;
-
- for (int i = 0; i < m_trianglesUsed; i++)
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
{
- if (! m_triangles[i].used) continue;
+ int state = m_triangles[i].state;
- state = m_triangles[i].state;
- strcpy(texName1, m_triangles[i].texName);
- texName2[0] = 0;
+ /* TODO ???
+ if (texName1 == "plant.png")
+ state |= Gfx::ENG_RSTATE_ALPHA;
- if ( strcmp(texName1, "plant.tga") == 0 ) // ???
+ if (m_triangles[i].tex2Name.empty())
{
- state |= D3DSTATEALPHA;
- }
+ int texNum = 0;
- if ( m_triangles[i].texNum2 != 0 )
- {
if ( m_triangles[i].texNum2 == 1 )
{
texNum = m_engine->RetSecondTexture();
@@ -760,15 +753,22 @@ bool Gfx::CModelFile::CreateEngineObject(int objRank, int addState)
state |= D3DSTATEDUALw;
}
sprintf(texName2, "dirty%.2d.tga", texNum); // ???
- }
+ }*/
+
+ std::vector<Gfx::VertexTex2> vs;
+ vs.push_back(m_triangles[i].p1);
+ vs.push_back(m_triangles[i].p2);
+ vs.push_back(m_triangles[i].p3);
+
+ m_engine->AddTriangles(objRank, vs,
+ m_triangles[i].material,
+ state + addState,
+ m_triangles[i].tex1Name,
+ m_triangles[i].tex2Name,
+ m_triangles[i].min,
+ m_triangles[i].max, false);
+ }
- m_engine->AddTriangle(objRank, &m_triangles[i].p1, 3,
- m_triangles[i].material,
- state + addState,
- texName1, texName2,
- m_triangles[i].min,
- m_triangles[i].max, false);
- }*/
return true;
}
diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h
index 45396d2..c53aea5 100644
--- a/src/graphics/engine/particle.h
+++ b/src/graphics/engine/particle.h
@@ -256,7 +256,12 @@ struct WheelTrace
};
-
+/**
+ * \class CParticle
+ * \brief Particle engine
+ *
+ * Functions are only stubs for now.
+ */
class CParticle
{
public:
diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h
index e859cd7..fd119f6 100644
--- a/src/graphics/engine/planet.h
+++ b/src/graphics/engine/planet.h
@@ -35,6 +35,10 @@ namespace Gfx {
class CEngine;
+/**
+ * \struct Planet
+ * \brief Planet texture definition
+ */
struct Planet
{
//! Initial position in degrees
@@ -63,6 +67,15 @@ struct Planet
}
};
+
+/**
+ * \class CPlanet
+ * \brief Planet manager
+ *
+ * Draws the planets orbiting in the sky.
+ *
+ * Planets are drawn in 2D mode, at coordinates calculated from camera position.
+ */
class CPlanet
{
public:
diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h
index 768abf8..5d2ca63 100644
--- a/src/graphics/engine/pyro.h
+++ b/src/graphics/engine/pyro.h
@@ -90,7 +90,12 @@ struct PyroLightOper
};
-
+/**
+ * \class CPyro
+ * \brief Fire effect renderer
+ *
+ * Functions are only stubs for now.
+ */
class CPyro
{
public:
diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h
index 0c7e3cf..24bd1f9 100644
--- a/src/graphics/engine/terrain.h
+++ b/src/graphics/engine/terrain.h
@@ -34,19 +34,31 @@ class CEngine;
class CWater;
+//! Limit of slope considered a flat piece of land
const short FLATLIMIT = (5.0f*Math::PI/180.0f);
+/**
+ * \enum TerrainRes
+ * \brief Underground resource type
+ */
enum TerrainRes
{
- TR_NULL = 0,
- TR_STONE = 1,
- TR_URANIUM = 2,
- TR_POWER = 3,
+ //! No resource
+ TR_NULL = 0,
+ //! Titanium
+ TR_STONE = 1,
+ //! Uranium
+ TR_URANIUM = 2,
+ //! Energy
+ TR_POWER = 3,
+ //! Vault keys
+ //@{
TR_KEY_A = 4,
TR_KEY_B = 5,
TR_KEY_C = 6,
- TR_KEY_D = 7,
+ TR_KEY_D = 7
+ //@}
};
struct BuildingLevel
@@ -98,6 +110,10 @@ struct DotLevel
}
};
+/**
+ * \struct FlyingLimit
+ * \brief Spherical limit of flight
+ */
struct FlyingLimit
{
Math::Vector center;
@@ -112,7 +128,22 @@ struct FlyingLimit
};
-
+/**
+ * \class CTerrain
+ * \brief Terrain loader/generator and manager
+ *
+ * Terrain is created from relief textures specifying a XY plane with height
+ * values which are then scaled and translated into XZ surface forming the
+ * terrain of game level.
+ *
+ * The class also facilitates creating and searching for flat space expanses
+ * for construction of buildings.
+ *
+ * The terrain also specifies underground resources loaded from texture
+ * and flying limits for the player.
+ *
+ * ...
+ */
class CTerrain
{
public:
diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp
index 2a7c6d2..bf2f64d 100644
--- a/src/graphics/engine/water.cpp
+++ b/src/graphics/engine/water.cpp
@@ -21,8 +21,10 @@
#include "common/iman.h"
#include "common/logger.h"
+#include "graphics/core/device.h"
#include "graphics/engine/engine.h"
#include "graphics/engine/terrain.h"
+#include "math/geometry.h"
#include "object/object.h"
#include "sound/sound.h"
@@ -258,53 +260,41 @@ void Gfx::CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm,
/** This surface prevents to see the sky (background) underwater! */
void Gfx::CWater::DrawBack()
{
- GetLogger()->Trace("CWater::DrawBack(): stub!\n");
- /* TODO!
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector eye, lookat, n, p, p1, p2;
- Math::Point uv1, uv2;
- float deep, dist;
-
- if ( !m_bDraw ) return;
- if ( m_type[0] == WATER_NULL ) return;
- if ( m_lineUsed == 0 ) return;
-
- eye = m_engine->GetEyePt();
- lookat = m_engine->GetLookatPt();
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ if (! m_draw) return;
+ if (m_type[0] == WATER_NULL) return;
+ if (m_lines.empty()) return;
+
+ Math::Vector eye = m_engine->GetEyePt();
+ Math::Vector lookat = m_engine->GetLookatPt();
+
+ Gfx::Material material;
material.diffuse = m_diffuse;
material.ambient = m_ambient;
m_engine->SetMaterial(material);
- m_engine->SetTexture("", 0);
+ m_engine->SetTexture("", 0); // TODO: disable texturing
+
+ Gfx::CDevice* device = m_engine->GetDevice();
- device = m_engine->GetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_engine->SetState(D3DSTATENORMAL);
+ m_engine->SetState(Gfx::ENG_RSTATE_NORMAL);
- deep = m_engine->GetDeepView(0);
+ float deep = m_engine->GetDeepView(0);
m_engine->SetDeepView(deep*2.0f, 0);
m_engine->SetFocus(m_engine->GetFocus());
m_engine->UpdateMatProj(); // twice the depth of view
+ Math::Matrix matrix;
matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ device->SetTransform(Gfx::TRANSFORM_WORLD, matrix);
+ Math::Vector p;
p.x = eye.x;
p.z = eye.z;
- dist = Math::DistanceProjected(eye, lookat);
+ float dist = Math::DistanceProjected(eye, lookat);
p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x;
p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z;
+ Math::Vector p1, p2;
p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x;
p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z;
p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x;
@@ -313,155 +303,132 @@ void Gfx::CWater::DrawBack()
p1.y = -50.0f;
p2.y = m_level;
+ Math::Vector n;
n.x = (lookat.x-eye.x)/dist;
n.z = (lookat.z-eye.z)/dist;
n.y = 0.0f;
- uv1.x = uv1.y = 0.0f;
- uv2.x = uv2.y = 0.0f;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y);
+ Gfx::Vertex vertices[4] =
+ {
+ Gfx::Vertex(Math::Vector(p1.x, p2.y, p1.z), n),
+ Gfx::Vertex(Math::Vector(p1.x, p1.y, p1.z), n),
+ Gfx::Vertex(Math::Vector(p2.x, p2.y, p2.z), n),
+ Gfx::Vertex(Math::Vector(p2.x, p1.y, p2.z), n)
+ };
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertices, 4);
m_engine->AddStatisticTriangle(2);
m_engine->SetDeepView(deep, 0);
m_engine->SetFocus(m_engine->GetFocus());
m_engine->UpdateMatProj(); // gives the initial depth of view
-
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);*/
}
void Gfx::CWater::DrawSurf()
{
- GetLogger()->Trace("CWater::DrawSurf(): stub!\n");
- /* TODO!
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2* vertex; // triangles
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector eye, lookat, n, pos, p;
- Math::Point uv1, uv2;
- bool bUnder;
- DWORD flags;
- float deep, size, sizez, radius;
- int rankview, i, j, u;
-
if (! m_draw) return;
if (m_type[0] == Gfx::WATER_NULL) return;
- if (m_line.empty()) return;
+ if (m_lines.empty()) return;
- vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
+ std::vector<Gfx::VertexTex2> vertices((m_brick+2)*2, Gfx::VertexTex2());
- eye = m_engine->GetEyePt();
- lookat = m_engine->GetLookatPt();
+ Math::Vector eye = m_engine->GetEyePt();
- rankview = m_engine->GetRankView();
- bUnder = ( rankview == 1);
+ int rankview = m_engine->GetRankView();
+ bool under = ( rankview == 1);
- device = m_engine->GetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ Gfx::CDevice* device = m_engine->GetDevice();
+ Math::Matrix matrix;
matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
+ device->SetTransform(Gfx::TRANSFORM_WORLD, matrix);
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ Gfx::Material material;
material.diffuse = m_diffuse;
material.ambient = m_ambient;
m_engine->SetMaterial(material);
- m_engine->SetTexture(m_filename, 0);
- m_engine->SetTexture(m_filename, 1);
+ m_engine->SetTexture(m_fileName, 0);
+ m_engine->SetTexture(m_fileName, 1);
- if ( m_type[rankview] == WATER_TT )
- {
- m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color);
- }
- if ( m_type[rankview] == WATER_TO )
- {
- m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP);
- }
- if ( m_type[rankview] == WATER_CT )
- {
- m_engine->SetState(D3DSTATETTb);
- }
- if ( m_type[rankview] == WATER_CO )
- {
- m_engine->SetState(D3DSTATENORMAL);
- }
- device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ if (m_type[rankview] == WATER_TT)
+ m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_BLACK | Gfx::ENG_RSTATE_DUAL_WHITE | Gfx::ENG_RSTATE_WRAP, m_color);
- size = m_size/2.0f;
- if ( bUnder ) sizez = -size;
- else sizez = size;
+ else if (m_type[rankview] == WATER_TO)
+ m_engine->SetState(Gfx::ENG_RSTATE_NORMAL | Gfx::ENG_RSTATE_DUAL_WHITE | Gfx::ENG_RSTATE_WRAP);
- // Draws all the lines.
- deep = m_engine->GetDeepView(0)*1.5f;
+ else if (m_type[rankview] == WATER_CT)
+ m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_BLACK);
- for ( i=0 ; i<m_lineUsed ; i++ )
+ else if (m_type[rankview] == WATER_CO)
+ m_engine->SetState(Gfx::ENG_RSTATE_NORMAL);
+
+ device->SetRenderState(Gfx::RENDER_STATE_FOG, true);
+
+ float size = m_size/2.0f;
+ float sizez = 0.0f;
+ if (under) sizez = -size;
+ else sizez = size;
+
+ // Draws all the lines
+ float deep = m_engine->GetDeepView(0)*1.5f;
+
+ for (int i = 0; i < static_cast<int>( m_lines.size() ); i++)
{
+ Math::Vector pos;
pos.y = m_level;
- pos.z = m_line[i].pz;
- pos.x = m_line[i].px1;
+ pos.z = m_lines[i].pz;
+ pos.x = m_lines[i].px1;
// Visible line?
- p = pos;
- p.x += size*(m_line[i].len-1);
- radius = sqrtf(powf(size, 2.0f)+powf(size*m_line[i].len, 2.0f));
+ 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;
- D3DVECTOR pD3D = VEC_TO_D3DVEC(p);
- device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags);
+ // TODO: ComputeSphereVisibility
+
+ int vertexIndex = 0;
- if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue;
+ Math::Point uv1, uv2;
+ Math::Vector n;
- u = 0;
p.x = pos.x-size;
p.z = pos.z-sizez;
p.y = pos.y;
AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ if (under) n.y = -n.y;
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
p.x = pos.x-size;
p.z = pos.z+sizez;
p.y = pos.y;
AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ if (under) n.y = -n.y;
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
- for ( j=0 ; j<m_line[i].len ; j++ )
+ for (int j = 0; j < m_lines[i].len; j++)
{
p.x = pos.x+size;
p.z = pos.z-sizez;
p.y = pos.y;
AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ if (under) n.y = -n.y;
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
p.x = pos.x+size;
p.z = pos.z+sizez;
p.y = pos.y;
AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+ if (under) n.y = -n.y;
+ vertices[vertexIndex++] = Gfx::VertexTex2(p, n, uv1, uv2);
pos.x += size*2.0f;
}
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
- m_engine->AddStatisticTriangle(u-2);
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, &vertices[0], vertexIndex);
+ m_engine->AddStatisticTriangle(vertexIndex - 2);
}
-
- free(vertex);*/
}
bool Gfx::CWater::GetWater(int x, int y)
diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h
index f20f992..371a91f 100644
--- a/src/graphics/engine/water.h
+++ b/src/graphics/engine/water.h
@@ -35,12 +35,19 @@ namespace Gfx {
class CEngine;
class CTerrain;
+/**
+ * \struct WaterLine
+ * \brief Water strip
+ */
struct WaterLine
{
- //! Beginning
+ //@{
+ //! Beginning of line (terrain coordinates)
short x, y;
- //! Length by x
+ //@}
+ //! Length in X direction (terrain coordinates)
short len;
+ //! X (1, 2) and Z coordinates (world coordinates)
float px1, px2, pz;
WaterLine()
@@ -51,6 +58,10 @@ struct WaterLine
}
};
+/**
+ * \struct WaterVapor
+ * \brief Water particle effect
+ */
struct WaterVapor
{
bool used;
@@ -68,6 +79,10 @@ struct WaterVapor
}
};
+/**
+ * \enum WaterType
+ * \brief Mode of water display
+ */
enum WaterType
{
//! No water
@@ -82,7 +97,19 @@ enum WaterType
WATER_CO = 4,
};
-
+/**
+ * \class CWater
+ * \brief Water manager/renderer
+ *
+ * Water is drawn where the terrain is below specified level. The mapping
+ * is based on terrain coordinates - for each "brick" coordinate, the level
+ * of terrain is tested. For every Y coordinate, many lines in X direction
+ * are created (WaterLines).
+ *
+ * There are two parts of drawing process: drawing the background image
+ * blocking the normal sky layer and drawing the surface of water.
+ * The surface is drawn with texture, so with proper texture it can be lava.
+ */
class CWater
{
public: