Static objects using OpenGL VBOs and display lists
parent
39ac36efda
commit
4811defca2
|
@ -142,6 +142,8 @@ CApplication::CApplication()
|
||||||
|
|
||||||
m_lowCPU = true;
|
m_lowCPU = true;
|
||||||
|
|
||||||
|
m_useVbo = false;
|
||||||
|
|
||||||
for (int i = 0; i < DIR_MAX; ++i)
|
for (int i = 0; i < DIR_MAX; ++i)
|
||||||
m_dataDirs[i] = nullptr;
|
m_dataDirs[i] = nullptr;
|
||||||
|
|
||||||
|
@ -243,6 +245,10 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
SetDebugMode(true);
|
SetDebugMode(true);
|
||||||
}
|
}
|
||||||
|
else if (arg == "-vbo")
|
||||||
|
{
|
||||||
|
m_useVbo = true;
|
||||||
|
}
|
||||||
else if (arg == "-loglevel")
|
else if (arg == "-loglevel")
|
||||||
{
|
{
|
||||||
waitLogLevel = true;
|
waitLogLevel = true;
|
||||||
|
@ -262,6 +268,7 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
|
||||||
GetLogger()->Message("\n");
|
GetLogger()->Message("\n");
|
||||||
GetLogger()->Message("List of available options:\n");
|
GetLogger()->Message("List of available options:\n");
|
||||||
GetLogger()->Message(" -help this help\n");
|
GetLogger()->Message(" -help this help\n");
|
||||||
|
GetLogger()->Message(" -vbo enable OpenGL VBOs\n");
|
||||||
GetLogger()->Message(" -datadir path set custom data directory path\n");
|
GetLogger()->Message(" -datadir path set custom data directory path\n");
|
||||||
GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n");
|
GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n");
|
||||||
GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
|
GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
|
||||||
|
@ -425,6 +432,8 @@ bool CApplication::Create()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_cast<Gfx::CGLDevice*>(m_device)->SetUseVbo(m_useVbo);
|
||||||
|
|
||||||
// Create the 3D engine
|
// Create the 3D engine
|
||||||
m_engine = new Gfx::CEngine(m_iMan, this);
|
m_engine = new Gfx::CEngine(m_iMan, this);
|
||||||
|
|
||||||
|
|
|
@ -449,5 +449,7 @@ protected:
|
||||||
|
|
||||||
//! Low cpu mode
|
//! Low cpu mode
|
||||||
bool m_lowCPU;
|
bool m_lowCPU;
|
||||||
|
|
||||||
|
int m_useVbo; // TODO: temporary
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -313,9 +313,24 @@ public:
|
||||||
//! Renders primitive composed of vertices with multitexturing (2 textures)
|
//! Renders primitive composed of vertices with multitexturing (2 textures)
|
||||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) = 0;
|
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) = 0;
|
||||||
//! Renders primitive composed of vertices with color information
|
//! Renders primitive composed of vertices with solid color
|
||||||
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount) = 0;
|
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount) = 0;
|
||||||
|
|
||||||
|
//! Creates a static buffer composed of given primitives with single texture vertices
|
||||||
|
virtual unsigned int CreateStaticObject(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) = 0;
|
||||||
|
|
||||||
|
//! Creates a static buffer composed of given primitives with multitexturing (2 textures)
|
||||||
|
virtual unsigned int CreateStaticObject(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) = 0;
|
||||||
|
|
||||||
|
//! Creates a static buffer composed of given primitives with solid color
|
||||||
|
virtual unsigned int CreateStaticObject(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) = 0;
|
||||||
|
|
||||||
|
//! Draws a static buffer
|
||||||
|
virtual void DrawStaticObject(unsigned int objectId) = 0;
|
||||||
|
|
||||||
|
//! Deletes a static buffer
|
||||||
|
virtual void DestroyStaticObject(unsigned int objectId) = 0;
|
||||||
|
|
||||||
//! Tests whether a sphere is (partially) within the frustum volume
|
//! Tests whether a sphere is (partially) within the frustum volume
|
||||||
//! Returns a mask of frustum planes for which the test is positive
|
//! Returns a mask of frustum planes for which the test is positive
|
||||||
virtual int ComputeSphereVisibility(const Math::Vector ¢er, float radius) = 0;
|
virtual int ComputeSphereVisibility(const Math::Vector ¢er, float radius) = 0;
|
||||||
|
|
|
@ -44,23 +44,18 @@ namespace Gfx {
|
||||||
* - vertex coordinates (x,y,z) as Math::Vector,
|
* - vertex coordinates (x,y,z) as Math::Vector,
|
||||||
* - normal coordinates (nx,ny,nz) as Math::Vector
|
* - normal coordinates (nx,ny,nz) as Math::Vector
|
||||||
* - texture coordinates (u,v) as Math::Point.
|
* - texture coordinates (u,v) as Math::Point.
|
||||||
*
|
|
||||||
* Additional padding is provided to align to even multiplies of 4 floats for faster access.
|
|
||||||
*/
|
*/
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
Math::Vector coord;
|
Math::Vector coord;
|
||||||
float pad1;
|
|
||||||
Math::Vector normal;
|
Math::Vector normal;
|
||||||
float pad2;
|
|
||||||
Math::Point texCoord;
|
Math::Point texCoord;
|
||||||
float pad3, pad4;
|
|
||||||
|
|
||||||
explicit Vertex(Math::Vector aCoord = Math::Vector(),
|
explicit Vertex(Math::Vector aCoord = Math::Vector(),
|
||||||
Math::Vector aNormal = Math::Vector(),
|
Math::Vector aNormal = Math::Vector(),
|
||||||
Math::Point aTexCoord = Math::Point())
|
Math::Point aTexCoord = Math::Point())
|
||||||
: coord(aCoord), pad1(0.0f), normal(aNormal),
|
: coord(aCoord), normal(aNormal),
|
||||||
pad2(0.0f),texCoord(aTexCoord), pad3(0.0f), pad4(0.0f) {}
|
texCoord(aTexCoord) {}
|
||||||
|
|
||||||
|
|
||||||
//! Returns a string "(c: [...], n: [...], tc: [...])"
|
//! Returns a string "(c: [...], n: [...], tc: [...])"
|
||||||
|
@ -81,18 +76,15 @@ struct Vertex
|
||||||
* It contains:
|
* It contains:
|
||||||
* - vertex coordinates (x,y,z) as Math::Vector,
|
* - vertex coordinates (x,y,z) as Math::Vector,
|
||||||
* - RGBA color as Color
|
* - RGBA color as Color
|
||||||
*
|
|
||||||
* Additional padding is provided to align to even multiplies of 4 floats for faster access.
|
|
||||||
*/
|
*/
|
||||||
struct VertexCol
|
struct VertexCol
|
||||||
{
|
{
|
||||||
Math::Vector coord;
|
Math::Vector coord;
|
||||||
float pad;
|
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
explicit VertexCol(Math::Vector aCoord = Math::Vector(),
|
explicit VertexCol(Math::Vector aCoord = Math::Vector(),
|
||||||
Color aColor = Color())
|
Color aColor = Color())
|
||||||
: coord(aCoord), pad(0.0f), color(aColor) {}
|
: coord(aCoord), color(aColor) {}
|
||||||
|
|
||||||
//! Returns a string "(c: [...], col: [...])"
|
//! Returns a string "(c: [...], col: [...])"
|
||||||
inline std::string ToString() const
|
inline std::string ToString() const
|
||||||
|
@ -111,15 +103,11 @@ struct VertexCol
|
||||||
*
|
*
|
||||||
* In addition to fields from Vector, it contains
|
* In addition to fields from Vector, it contains
|
||||||
* secondary texture coordinates (u2, v2) as Math::Point
|
* secondary texture coordinates (u2, v2) as Math::Point
|
||||||
*
|
|
||||||
* Additional padding is provided to align to even multiplies of 4 floats for faster access.
|
|
||||||
*/
|
*/
|
||||||
struct VertexTex2
|
struct VertexTex2
|
||||||
{
|
{
|
||||||
Math::Vector coord;
|
Math::Vector coord;
|
||||||
float pad1;
|
|
||||||
Math::Vector normal;
|
Math::Vector normal;
|
||||||
float pad2;
|
|
||||||
Math::Point texCoord;
|
Math::Point texCoord;
|
||||||
Math::Point texCoord2;
|
Math::Point texCoord2;
|
||||||
|
|
||||||
|
@ -127,7 +115,7 @@ struct VertexTex2
|
||||||
Math::Vector aNormal = Math::Vector(),
|
Math::Vector aNormal = Math::Vector(),
|
||||||
Math::Point aTexCoord = Math::Point(),
|
Math::Point aTexCoord = Math::Point(),
|
||||||
Math::Point aTexCoord2 = Math::Point())
|
Math::Point aTexCoord2 = Math::Point())
|
||||||
: coord(aCoord), pad1(0.0f), normal(aNormal), pad2(0.0f),
|
: coord(aCoord), normal(aNormal),
|
||||||
texCoord(aTexCoord), texCoord2(aTexCoord2) {}
|
texCoord(aTexCoord), texCoord2(aTexCoord2) {}
|
||||||
|
|
||||||
//! Sets the fields from Vertex with texCoord2 = (0,0)
|
//! Sets the fields from Vertex with texCoord2 = (0,0)
|
||||||
|
|
|
@ -92,6 +92,7 @@ EngineObjLevel4::EngineObjLevel4(bool used, EngineTriangleType type, const Mater
|
||||||
this->type = type;
|
this->type = type;
|
||||||
this->material = material;
|
this->material = material;
|
||||||
this->state = state;
|
this->state = state;
|
||||||
|
this->staticBufferId = 0;
|
||||||
|
|
||||||
vertices.reserve(LEVEL4_VERTEX_PREALLOCATE_COUNT);
|
vertices.reserve(LEVEL4_VERTEX_PREALLOCATE_COUNT);
|
||||||
}
|
}
|
||||||
|
@ -182,6 +183,7 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
|
||||||
m_alphaMode = 1;
|
m_alphaMode = 1;
|
||||||
|
|
||||||
m_updateGeometry = false;
|
m_updateGeometry = false;
|
||||||
|
m_updateStaticObjects = false;
|
||||||
|
|
||||||
m_interfaceMode = false;
|
m_interfaceMode = false;
|
||||||
|
|
||||||
|
@ -385,6 +387,7 @@ void CEngine::FrameUpdate()
|
||||||
|
|
||||||
ComputeDistance();
|
ComputeDistance();
|
||||||
UpdateGeometry();
|
UpdateGeometry();
|
||||||
|
UpdateStaticObjects();
|
||||||
|
|
||||||
m_highlightTime = m_app->GetAbsTime();
|
m_highlightTime = m_app->GetAbsTime();
|
||||||
|
|
||||||
|
@ -570,11 +573,27 @@ bool CEngine::DeleteObject(int objRank)
|
||||||
EngineObjLevel2& p2 = p1.next[l2];
|
EngineObjLevel2& p2 = p1.next[l2];
|
||||||
if (! p2.used) continue;
|
if (! p2.used) continue;
|
||||||
|
|
||||||
if (p2.objRank == objRank)
|
if (p2.objRank != objRank) continue;
|
||||||
|
|
||||||
|
if (m_objects[objRank].staticBuffer)
|
||||||
{
|
{
|
||||||
p2.used = false;
|
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
|
||||||
p2.next.clear();
|
{
|
||||||
|
EngineObjLevel3& p3 = p2.next[l3];
|
||||||
|
if (! p3.used) continue;
|
||||||
|
|
||||||
|
for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
|
||||||
|
{
|
||||||
|
EngineObjLevel4& p4 = p3.next[l4];
|
||||||
|
|
||||||
|
m_device->DestroyStaticObject(p4.staticBufferId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p2.used = false;
|
||||||
|
p2.next.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +642,22 @@ bool CEngine::GetObjectTransform(int objRank, Math::Matrix& transform)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CEngine::SetObjectStatic(int objRank, bool staticBuffer)
|
||||||
|
{
|
||||||
|
if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_objects[objRank].staticBuffer = staticBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CEngine::GetObjectStatic(int objRank)
|
||||||
|
{
|
||||||
|
if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_objects[objRank].staticBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
bool CEngine::SetObjectDrawWorld(int objRank, bool draw)
|
bool CEngine::SetObjectDrawWorld(int objRank, bool draw)
|
||||||
{
|
{
|
||||||
if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
|
if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
|
||||||
|
@ -825,6 +860,17 @@ bool CEngine::AddTriangles(int objRank, const std::vector<VertexTex2>& vertices,
|
||||||
|
|
||||||
p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
|
p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
|
||||||
|
|
||||||
|
if (m_objects[objRank].staticBuffer)
|
||||||
|
{
|
||||||
|
if (p4.staticBufferId != 0)
|
||||||
|
{
|
||||||
|
m_device->DestroyStaticObject(p4.staticBufferId);
|
||||||
|
p4.staticBufferId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updateStaticObjects = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (globalUpdate)
|
if (globalUpdate)
|
||||||
{
|
{
|
||||||
m_updateGeometry = true;
|
m_updateGeometry = true;
|
||||||
|
@ -872,6 +918,17 @@ bool CEngine::AddSurface(int objRank, const std::vector<VertexTex2>& vertices,
|
||||||
|
|
||||||
p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
|
p4.vertices.insert(p4.vertices.end(), vertices.begin(), vertices.end());
|
||||||
|
|
||||||
|
if (m_objects[objRank].staticBuffer)
|
||||||
|
{
|
||||||
|
if (p4.staticBufferId != 0)
|
||||||
|
{
|
||||||
|
m_device->DestroyStaticObject(p4.staticBufferId);
|
||||||
|
p4.staticBufferId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updateStaticObjects = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (globalUpdate)
|
if (globalUpdate)
|
||||||
{
|
{
|
||||||
m_updateGeometry = true;
|
m_updateGeometry = true;
|
||||||
|
@ -898,8 +955,8 @@ bool CEngine::AddSurface(int objRank, const std::vector<VertexTex2>& vertices,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEngine::AddQuick(int objRank, const EngineObjLevel4& buffer,
|
bool CEngine::AddQuick(int objRank, const EngineObjLevel4& buffer,
|
||||||
std::string tex1Name, std::string tex2Name,
|
std::string tex1Name, std::string tex2Name,
|
||||||
float min, float max, bool globalUpdate)
|
float min, float max, bool globalUpdate)
|
||||||
{
|
{
|
||||||
if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
|
if ( objRank < 0 || objRank >= static_cast<int>( m_objects.size() ) )
|
||||||
{
|
{
|
||||||
|
@ -912,7 +969,26 @@ bool CEngine::AddQuick(int objRank, const EngineObjLevel4& buffer,
|
||||||
EngineObjLevel3& p3 = AddLevel3(p2, min, max);
|
EngineObjLevel3& p3 = AddLevel3(p2, min, max);
|
||||||
|
|
||||||
p3.next.push_back(buffer);
|
p3.next.push_back(buffer);
|
||||||
p3.next.back().used = true; // ensure that it is used
|
|
||||||
|
EngineObjLevel4& p4 = p3.next.back();
|
||||||
|
p4.used = true; // ensure that it is used
|
||||||
|
|
||||||
|
if (m_objects[objRank].staticBuffer)
|
||||||
|
{
|
||||||
|
if (p4.staticBufferId != 0)
|
||||||
|
{
|
||||||
|
m_device->DestroyStaticObject(p4.staticBufferId);
|
||||||
|
p4.staticBufferId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveType type;
|
||||||
|
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||||
|
type = PRIMITIVE_TRIANGLES;
|
||||||
|
else
|
||||||
|
type = PRIMITIVE_TRIANGLE_STRIP;
|
||||||
|
|
||||||
|
p4.staticBufferId = m_device->CreateStaticObject(type, &p4.vertices[0], p4.vertices.size());
|
||||||
|
}
|
||||||
|
|
||||||
if (globalUpdate)
|
if (globalUpdate)
|
||||||
{
|
{
|
||||||
|
@ -920,24 +996,24 @@ bool CEngine::AddQuick(int objRank, const EngineObjLevel4& buffer,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < static_cast<int>( buffer.vertices.size() ); i++)
|
for (int i = 0; i < static_cast<int>( p4.vertices.size() ); i++)
|
||||||
{
|
{
|
||||||
m_objects[objRank].bboxMin.x = Math::Min(buffer.vertices[i].coord.x, m_objects[objRank].bboxMin.x);
|
m_objects[objRank].bboxMin.x = Math::Min(p4.vertices[i].coord.x, m_objects[objRank].bboxMin.x);
|
||||||
m_objects[objRank].bboxMin.y = Math::Min(buffer.vertices[i].coord.y, m_objects[objRank].bboxMin.y);
|
m_objects[objRank].bboxMin.y = Math::Min(p4.vertices[i].coord.y, m_objects[objRank].bboxMin.y);
|
||||||
m_objects[objRank].bboxMin.z = Math::Min(buffer.vertices[i].coord.z, m_objects[objRank].bboxMin.z);
|
m_objects[objRank].bboxMin.z = Math::Min(p4.vertices[i].coord.z, m_objects[objRank].bboxMin.z);
|
||||||
m_objects[objRank].bboxMax.x = Math::Max(buffer.vertices[i].coord.x, m_objects[objRank].bboxMax.x);
|
m_objects[objRank].bboxMax.x = Math::Max(p4.vertices[i].coord.x, m_objects[objRank].bboxMax.x);
|
||||||
m_objects[objRank].bboxMax.y = Math::Max(buffer.vertices[i].coord.y, m_objects[objRank].bboxMax.y);
|
m_objects[objRank].bboxMax.y = Math::Max(p4.vertices[i].coord.y, m_objects[objRank].bboxMax.y);
|
||||||
m_objects[objRank].bboxMax.z = Math::Max(buffer.vertices[i].coord.z, m_objects[objRank].bboxMax.z);
|
m_objects[objRank].bboxMax.z = Math::Max(p4.vertices[i].coord.z, m_objects[objRank].bboxMax.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
|
m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
|
||||||
m_objects[objRank].bboxMax.Length());
|
m_objects[objRank].bboxMax.Length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||||
m_objects[objRank].totalTriangles += buffer.vertices.size() / 3;
|
m_objects[objRank].totalTriangles += p4.vertices.size() / 3;
|
||||||
else if (buffer.type == ENG_TRIANGLE_TYPE_SURFACE)
|
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||||
m_objects[objRank].totalTriangles += buffer.vertices.size() - 2;
|
m_objects[objRank].totalTriangles += p4.vertices.size() - 2;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1735,10 +1811,57 @@ void CEngine::UpdateGeometry()
|
||||||
m_updateGeometry = false;
|
m_updateGeometry = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CEngine::UpdateStaticObjects()
|
||||||
|
{
|
||||||
|
if (!m_updateStaticObjects)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
|
||||||
|
{
|
||||||
|
EngineObjLevel1& p1 = m_objectTree[l1];
|
||||||
|
if (! p1.used) continue;
|
||||||
|
|
||||||
|
for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
|
||||||
|
{
|
||||||
|
EngineObjLevel2& p2 = p1.next[l2];
|
||||||
|
if (! p2.used) continue;
|
||||||
|
|
||||||
|
int objRank = p2.objRank;
|
||||||
|
|
||||||
|
if (!m_objects[objRank].staticBuffer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
|
||||||
|
{
|
||||||
|
EngineObjLevel3& p3 = p2.next[l3];
|
||||||
|
if (! p3.used) continue;
|
||||||
|
|
||||||
|
for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
|
||||||
|
{
|
||||||
|
EngineObjLevel4& p4 = p3.next[l4];
|
||||||
|
if (! p4.used) continue;
|
||||||
|
|
||||||
|
if (p4.staticBufferId != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PrimitiveType type;
|
||||||
|
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||||
|
type = PRIMITIVE_TRIANGLES;
|
||||||
|
else
|
||||||
|
type = PRIMITIVE_TRIANGLE_STRIP;
|
||||||
|
|
||||||
|
p4.staticBufferId = m_device->CreateStaticObject(type, &p4.vertices[0], p4.vertices.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CEngine::Update()
|
void CEngine::Update()
|
||||||
{
|
{
|
||||||
ComputeDistance();
|
ComputeDistance();
|
||||||
UpdateGeometry();
|
UpdateGeometry();
|
||||||
|
UpdateStaticObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEngine::DetectBBox(int objRank, Math::Point mouse)
|
bool CEngine::DetectBBox(int objRank, Math::Point mouse)
|
||||||
|
@ -3106,20 +3229,7 @@ void CEngine::Draw3DScene()
|
||||||
SetMaterial(p4.material);
|
SetMaterial(p4.material);
|
||||||
SetState(p4.state);
|
SetState(p4.state);
|
||||||
|
|
||||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
m_statisticTriangle += p4.vertices.size() / 3;
|
|
||||||
}
|
|
||||||
if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
m_statisticTriangle += p4.vertices.size() - 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3188,22 +3298,7 @@ void CEngine::Draw3DScene()
|
||||||
SetMaterial(p4.material);
|
SetMaterial(p4.material);
|
||||||
SetState(p4.state);
|
SetState(p4.state);
|
||||||
|
|
||||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
|
|
||||||
m_statisticTriangle += p4.vertices.size() / 3;
|
|
||||||
}
|
|
||||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
|
|
||||||
m_statisticTriangle += p4.vertices.size() - 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3264,21 +3359,7 @@ void CEngine::Draw3DScene()
|
||||||
SetMaterial(p4.material);
|
SetMaterial(p4.material);
|
||||||
SetState(tState, tColor);
|
SetState(tState, tColor);
|
||||||
|
|
||||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
|
|
||||||
m_statisticTriangle += p4.vertices.size() / 3;
|
|
||||||
}
|
|
||||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
m_statisticTriangle += p4.vertices.size() - 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3307,6 +3388,32 @@ void CEngine::Draw3DScene()
|
||||||
if (! m_overFront) DrawOverColor(); // draws the foreground color
|
if (! m_overFront) DrawOverColor(); // draws the foreground color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CEngine::DrawObject(const EngineObjLevel4& obj, bool staticBuffer)
|
||||||
|
{
|
||||||
|
if (staticBuffer)
|
||||||
|
{
|
||||||
|
m_device->DrawStaticObject(obj.staticBufferId);
|
||||||
|
|
||||||
|
if (obj.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||||
|
m_statisticTriangle += obj.vertices.size() / 3;
|
||||||
|
else
|
||||||
|
m_statisticTriangle += obj.vertices.size() - 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (obj.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||||
|
{
|
||||||
|
m_device->DrawPrimitive(PRIMITIVE_TRIANGLES, &obj.vertices[0], obj.vertices.size());
|
||||||
|
m_statisticTriangle += obj.vertices.size() / 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, &obj.vertices[0], obj.vertices.size() );
|
||||||
|
m_statisticTriangle += obj.vertices.size() - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CEngine::DrawInterface()
|
void CEngine::DrawInterface()
|
||||||
{
|
{
|
||||||
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
|
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
|
||||||
|
@ -3397,21 +3504,7 @@ void CEngine::DrawInterface()
|
||||||
SetMaterial(p4.material);
|
SetMaterial(p4.material);
|
||||||
SetState(p4.state);
|
SetState(p4.state);
|
||||||
|
|
||||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
|
|
||||||
m_statisticTriangle += p4.vertices.size() / 3;
|
|
||||||
}
|
|
||||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
|
||||||
{
|
|
||||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
|
||||||
&p4.vertices[0],
|
|
||||||
p4.vertices.size() );
|
|
||||||
m_statisticTriangle += p4.vertices.size() - 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,9 @@ struct EngineObject
|
||||||
//! Number of triangles
|
//! Number of triangles
|
||||||
int totalTriangles;
|
int totalTriangles;
|
||||||
//! Type of object
|
//! Type of object
|
||||||
EngineObjectType type;
|
EngineObjectType type;
|
||||||
|
//! Whether the object is stored and rendered as static buffer
|
||||||
|
bool staticBuffer;
|
||||||
//! Transformation matrix
|
//! Transformation matrix
|
||||||
Math::Matrix transform;
|
Math::Matrix transform;
|
||||||
//! Distance to object from eye point
|
//! Distance to object from eye point
|
||||||
|
@ -225,6 +227,7 @@ struct EngineObject
|
||||||
drawWorld = false;
|
drawWorld = false;
|
||||||
drawFront = false;
|
drawFront = false;
|
||||||
totalTriangles = 0;
|
totalTriangles = 0;
|
||||||
|
staticBuffer = false;
|
||||||
type = ENG_OBJTYPE_NULL;
|
type = ENG_OBJTYPE_NULL;
|
||||||
transform.LoadIdentity();
|
transform.LoadIdentity();
|
||||||
bboxMax.LoadZero();
|
bboxMax.LoadZero();
|
||||||
|
@ -252,6 +255,7 @@ struct EngineObjLevel4
|
||||||
Material material;
|
Material material;
|
||||||
int state;
|
int state;
|
||||||
std::vector<VertexTex2> vertices;
|
std::vector<VertexTex2> vertices;
|
||||||
|
unsigned int staticBufferId;
|
||||||
|
|
||||||
EngineObjLevel4(bool used = false,
|
EngineObjLevel4(bool used = false,
|
||||||
EngineTriangleType type = ENG_TRIANGLE_TYPE_TRIANGLES,
|
EngineTriangleType type = ENG_TRIANGLE_TYPE_TRIANGLES,
|
||||||
|
@ -760,6 +764,12 @@ public:
|
||||||
bool GetObjectTransform(int objRank, Math::Matrix& transform);
|
bool GetObjectTransform(int objRank, Math::Matrix& transform);
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
//! Management of object static drawing flag
|
||||||
|
void SetObjectStatic(int objRank, bool staticBuffer);
|
||||||
|
bool GetObjectStatic(int objRank);
|
||||||
|
//@}
|
||||||
|
|
||||||
//! Sets drawWorld for given object
|
//! Sets drawWorld for given object
|
||||||
bool SetObjectDrawWorld(int objRank, bool draw);
|
bool SetObjectDrawWorld(int objRank, bool draw);
|
||||||
//! Sets drawFront for given object
|
//! Sets drawFront for given object
|
||||||
|
@ -1151,6 +1161,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
//! Prepares the interface for 3D scene
|
//! Prepares the interface for 3D scene
|
||||||
void Draw3DScene();
|
void Draw3DScene();
|
||||||
|
//! Draw 3D object
|
||||||
|
void DrawObject(const EngineObjLevel4& obj, bool staticBuffer);
|
||||||
//! Draws the user interface over the scene
|
//! Draws the user interface over the scene
|
||||||
void DrawInterface();
|
void DrawInterface();
|
||||||
|
|
||||||
|
@ -1215,6 +1227,9 @@ protected:
|
||||||
//! Updates geometric parameters of objects (bounding box and radius)
|
//! Updates geometric parameters of objects (bounding box and radius)
|
||||||
void UpdateGeometry();
|
void UpdateGeometry();
|
||||||
|
|
||||||
|
//! Updates static buffers of changed objects
|
||||||
|
void UpdateStaticObjects();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CInstanceManager* m_iMan;
|
CInstanceManager* m_iMan;
|
||||||
CApplication* m_app;
|
CApplication* m_app;
|
||||||
|
@ -1293,6 +1308,7 @@ protected:
|
||||||
Color m_waterAddColor;
|
Color m_waterAddColor;
|
||||||
int m_statisticTriangle;
|
int m_statisticTriangle;
|
||||||
bool m_updateGeometry;
|
bool m_updateGeometry;
|
||||||
|
bool m_updateStaticObjects;
|
||||||
int m_alphaMode;
|
int m_alphaMode;
|
||||||
bool m_groundSpotVisible;
|
bool m_groundSpotVisible;
|
||||||
bool m_shadowVisible;
|
bool m_shadowVisible;
|
||||||
|
|
|
@ -1157,18 +1157,24 @@ bool CModelFile::WriteBinaryModel(std::ostream& stream)
|
||||||
|
|
||||||
#ifndef MODELFILE_NO_ENGINE
|
#ifndef MODELFILE_NO_ENGINE
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: move the function to CEngine or new class (CModelManager?)
|
||||||
|
* and make models shared static objects.
|
||||||
|
*/
|
||||||
|
|
||||||
bool CModelFile::CreateEngineObject(int objRank)
|
bool CModelFile::CreateEngineObject(int objRank)
|
||||||
{
|
{
|
||||||
std::vector<VertexTex2> vs(3, VertexTex2());
|
std::vector<VertexTex2> vs(3, VertexTex2());
|
||||||
|
|
||||||
|
m_engine->SetObjectStatic(objRank, true); // TODO: make optional in the future
|
||||||
|
|
||||||
float limit[2];
|
float limit[2];
|
||||||
limit[0] = m_engine->GetLimitLOD(0); // frontier AB as config
|
limit[0] = m_engine->GetLimitLOD(0); // frontier AB as config
|
||||||
limit[1] = m_engine->GetLimitLOD(1); // frontier BC as config
|
limit[1] = m_engine->GetLimitLOD(1); // frontier BC as config
|
||||||
|
|
||||||
for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
|
for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
|
||||||
{
|
{
|
||||||
// TODO move this to CEngine
|
|
||||||
|
|
||||||
float min = m_triangles[i].min;
|
float min = m_triangles[i].min;
|
||||||
float max = m_triangles[i].max;
|
float max = m_triangles[i].max;
|
||||||
|
|
||||||
|
|
|
@ -363,6 +363,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force)
|
||||||
m_type == PT_EXPLOW )
|
m_type == PT_EXPLOW )
|
||||||
{
|
{
|
||||||
CreateTriangle(obj, oType, 0);
|
CreateTriangle(obj, oType, 0);
|
||||||
|
m_engine->SetObjectStatic(m_object->GetObjectRank(0), false);
|
||||||
m_engine->DeleteShadow(m_object->GetObjectRank(0));
|
m_engine->DeleteShadow(m_object->GetObjectRank(0));
|
||||||
ExploStart();
|
ExploStart();
|
||||||
}
|
}
|
||||||
|
@ -1397,6 +1398,8 @@ void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part)
|
||||||
int objRank = obj->GetObjectRank(part);
|
int objRank = obj->GetObjectRank(part);
|
||||||
if (objRank == -1) return;
|
if (objRank == -1) return;
|
||||||
|
|
||||||
|
m_engine->SetObjectStatic(objRank, false);
|
||||||
|
|
||||||
float min = 0.0f;
|
float min = 0.0f;
|
||||||
float max = m_engine->GetLimitLOD(0);
|
float max = m_engine->GetLimitLOD(0);
|
||||||
int total = m_engine->GetObjectTotalTriangles(objRank);
|
int total = m_engine->GetObjectTotalTriangles(objRank);
|
||||||
|
|
|
@ -478,6 +478,8 @@ VertexTex2 CTerrain::GetVertex(int x, int y, int step)
|
||||||
v.texCoord.x = (o.x-oo.x)*m_textureScale*m_textureSubdivCount;
|
v.texCoord.x = (o.x-oo.x)*m_textureScale*m_textureSubdivCount;
|
||||||
v.texCoord.y = 1.0f - (o.z-oo.z)*m_textureScale*m_textureSubdivCount;
|
v.texCoord.y = 1.0f - (o.z-oo.z)*m_textureScale*m_textureSubdivCount;
|
||||||
|
|
||||||
|
v.texCoord2 = v.texCoord;
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1166,6 +1168,10 @@ bool CTerrain::CreateSquare(int x, int y)
|
||||||
int objRank = m_engine->CreateObject();
|
int objRank = m_engine->CreateObject();
|
||||||
m_engine->SetObjectType(objRank, ENG_OBJTYPE_TERRAIN);
|
m_engine->SetObjectType(objRank, ENG_OBJTYPE_TERRAIN);
|
||||||
|
|
||||||
|
// TODO: create a static object, but not split into squares, but a single object for all terrain
|
||||||
|
// Squares should be sub-objects accessing parts of triangle list
|
||||||
|
// m_engine->SetObjectStatic(objRank, true);
|
||||||
|
|
||||||
m_objRanks[x+y*m_mosaicCount] = objRank;
|
m_objRanks[x+y*m_mosaicCount] = objRank;
|
||||||
|
|
||||||
float min = 0.0f;
|
float min = 0.0f;
|
||||||
|
|
|
@ -73,6 +73,8 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config)
|
||||||
{
|
{
|
||||||
m_config = config;
|
m_config = config;
|
||||||
m_lighting = false;
|
m_lighting = false;
|
||||||
|
m_lastVboId = 0;
|
||||||
|
m_useVbo = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,6 +111,16 @@ bool CGLDevice::Create()
|
||||||
GetLogger()->Error("GLEW reports required extensions not supported\n");
|
GetLogger()->Error("GLEW reports required extensions not supported\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GLEW_ARB_vertex_buffer_object)
|
||||||
|
{
|
||||||
|
GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n");
|
||||||
|
m_useVbo = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -174,6 +186,16 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig)
|
||||||
Create();
|
Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGLDevice::SetUseVbo(bool useVbo)
|
||||||
|
{
|
||||||
|
m_useVbo = useVbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGLDevice::GetUseVbo()
|
||||||
|
{
|
||||||
|
return m_useVbo;
|
||||||
|
}
|
||||||
|
|
||||||
void CGLDevice::BeginScene()
|
void CGLDevice::BeginScene()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
@ -927,6 +949,206 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount)
|
||||||
|
{
|
||||||
|
unsigned int id = 0;
|
||||||
|
if (m_useVbo)
|
||||||
|
{
|
||||||
|
id = ++m_lastVboId;
|
||||||
|
|
||||||
|
VboObjectInfo info;
|
||||||
|
info.primitiveType = primitiveType;
|
||||||
|
info.vertexType = VERTEX_TYPE_NORMAL;
|
||||||
|
info.vertexCount = vertexCount;
|
||||||
|
info.bufferId = 0;
|
||||||
|
|
||||||
|
glGenBuffers(1, &info.bufferId);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
m_vboObjects[id] = info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
id = glGenLists(1);
|
||||||
|
|
||||||
|
glNewList(id, GL_COMPILE);
|
||||||
|
|
||||||
|
DrawPrimitive(primitiveType, vertices, vertexCount);
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount)
|
||||||
|
{
|
||||||
|
unsigned int id = 0;
|
||||||
|
if (m_useVbo)
|
||||||
|
{
|
||||||
|
id = ++m_lastVboId;
|
||||||
|
|
||||||
|
VboObjectInfo info;
|
||||||
|
info.primitiveType = primitiveType;
|
||||||
|
info.vertexType = VERTEX_TYPE_TEX2;
|
||||||
|
info.vertexCount = vertexCount;
|
||||||
|
info.bufferId = 0;
|
||||||
|
|
||||||
|
glGenBuffers(1, &info.bufferId);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
m_vboObjects[id] = info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
id = glGenLists(1);
|
||||||
|
|
||||||
|
glNewList(id, GL_COMPILE);
|
||||||
|
|
||||||
|
DrawPrimitive(primitiveType, vertices, vertexCount);
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount)
|
||||||
|
{
|
||||||
|
unsigned int id = 0;
|
||||||
|
if (m_useVbo)
|
||||||
|
{
|
||||||
|
id = ++m_lastVboId;
|
||||||
|
|
||||||
|
VboObjectInfo info;
|
||||||
|
info.primitiveType = primitiveType;
|
||||||
|
info.vertexType = VERTEX_TYPE_COL;
|
||||||
|
info.vertexCount = vertexCount;
|
||||||
|
info.bufferId = 0;
|
||||||
|
|
||||||
|
glGenBuffers(1, &info.bufferId);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
m_vboObjects[id] = info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
id = glGenLists(1);
|
||||||
|
|
||||||
|
glNewList(id, GL_COMPILE);
|
||||||
|
|
||||||
|
DrawPrimitive(primitiveType, vertices, vertexCount);
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLDevice::DrawStaticObject(unsigned int objectId)
|
||||||
|
{
|
||||||
|
if (m_useVbo)
|
||||||
|
{
|
||||||
|
auto it = m_vboObjects.find(objectId);
|
||||||
|
if (it == m_vboObjects.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
glEnable(GL_VERTEX_ARRAY);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId);
|
||||||
|
|
||||||
|
if ((*it).second.vertexType == VERTEX_TYPE_NORMAL)
|
||||||
|
{
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, coord));
|
||||||
|
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, normal));
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, texCoord));
|
||||||
|
}
|
||||||
|
else if ((*it).second.vertexType == VERTEX_TYPE_TEX2)
|
||||||
|
{
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, coord));
|
||||||
|
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glNormalPointer(GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, normal));
|
||||||
|
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, texCoord));
|
||||||
|
|
||||||
|
glClientActiveTexture(GL_TEXTURE1);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, texCoord2));
|
||||||
|
}
|
||||||
|
else if ((*it).second.vertexType == VERTEX_TYPE_COL)
|
||||||
|
{
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glVertexPointer(3, GL_FLOAT, sizeof(VertexCol), static_cast<char*>(nullptr) + offsetof(VertexCol, coord));
|
||||||
|
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glColorPointer(4, GL_FLOAT, sizeof(VertexCol), static_cast<char*>(nullptr) + offsetof(VertexCol, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum mode = TranslateGfxPrimitive((*it).second.primitiveType);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, (*it).second.vertexCount);
|
||||||
|
|
||||||
|
if ((*it).second.vertexType == VERTEX_TYPE_NORMAL)
|
||||||
|
{
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE0
|
||||||
|
}
|
||||||
|
else if ((*it).second.vertexType == VERTEX_TYPE_TEX2)
|
||||||
|
{
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
else if ((*it).second.vertexType == VERTEX_TYPE_COL)
|
||||||
|
{
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glDisable(GL_VERTEX_ARRAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glCallList(objectId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLDevice::DestroyStaticObject(unsigned int objectId)
|
||||||
|
{
|
||||||
|
if (m_useVbo)
|
||||||
|
{
|
||||||
|
auto it = m_vboObjects.find(objectId);
|
||||||
|
if (it == m_vboObjects.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &(*it).second.bufferId);
|
||||||
|
|
||||||
|
m_vboObjects.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDeleteLists(objectId, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius)
|
bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius)
|
||||||
{
|
{
|
||||||
float distance = originPlane + Math::DotProduct(normal, center);
|
float distance = originPlane + Math::DotProduct(normal, center);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
// Graphics module namespace
|
// Graphics module namespace
|
||||||
|
@ -84,6 +85,9 @@ public:
|
||||||
|
|
||||||
void ConfigChanged(const GLDeviceConfig &newConfig);
|
void ConfigChanged(const GLDeviceConfig &newConfig);
|
||||||
|
|
||||||
|
void SetUseVbo(bool useVbo);
|
||||||
|
bool GetUseVbo();
|
||||||
|
|
||||||
virtual void BeginScene();
|
virtual void BeginScene();
|
||||||
virtual void EndScene();
|
virtual void EndScene();
|
||||||
|
|
||||||
|
@ -119,14 +123,18 @@ public:
|
||||||
|
|
||||||
virtual void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT);
|
virtual void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT);
|
||||||
|
|
||||||
//! Renders primitive composed of vertices with single texture
|
|
||||||
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
||||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
|
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
//! Renders primitive composed of vertices with multitexturing (2 textures)
|
|
||||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
|
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount);
|
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount);
|
||||||
|
|
||||||
|
virtual unsigned int CreateStaticObject(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount);
|
||||||
|
virtual unsigned int CreateStaticObject(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount);
|
||||||
|
virtual unsigned int CreateStaticObject(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount);
|
||||||
|
virtual void DrawStaticObject(unsigned int objectId);
|
||||||
|
virtual void DestroyStaticObject(unsigned int objectId);
|
||||||
|
|
||||||
virtual int ComputeSphereVisibility(const Math::Vector ¢er, float radius);
|
virtual int ComputeSphereVisibility(const Math::Vector ¢er, float radius);
|
||||||
|
|
||||||
virtual void SetRenderState(RenderState state, bool enabled);
|
virtual void SetRenderState(RenderState state, bool enabled);
|
||||||
|
@ -200,6 +208,30 @@ private:
|
||||||
|
|
||||||
//! Set of all created textures
|
//! Set of all created textures
|
||||||
std::set<Texture> m_allTextures;
|
std::set<Texture> m_allTextures;
|
||||||
|
|
||||||
|
//! Type of vertex structure
|
||||||
|
enum VertexType
|
||||||
|
{
|
||||||
|
VERTEX_TYPE_NORMAL,
|
||||||
|
VERTEX_TYPE_TEX2,
|
||||||
|
VERTEX_TYPE_COL,
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Info about static VBO buffers
|
||||||
|
struct VboObjectInfo
|
||||||
|
{
|
||||||
|
PrimitiveType primitiveType;
|
||||||
|
unsigned int bufferId;
|
||||||
|
VertexType vertexType;
|
||||||
|
int vertexCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Whether to use VBOs or display lists
|
||||||
|
bool m_useVbo;
|
||||||
|
//! Map of saved VBO objects
|
||||||
|
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
||||||
|
//! Last ID of VBO object
|
||||||
|
unsigned int m_lastVboId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue