Static objects using OpenGL VBOs and display lists
parent
39ac36efda
commit
4811defca2
|
@ -142,6 +142,8 @@ CApplication::CApplication()
|
|||
|
||||
m_lowCPU = true;
|
||||
|
||||
m_useVbo = false;
|
||||
|
||||
for (int i = 0; i < DIR_MAX; ++i)
|
||||
m_dataDirs[i] = nullptr;
|
||||
|
||||
|
@ -243,6 +245,10 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
|
|||
{
|
||||
SetDebugMode(true);
|
||||
}
|
||||
else if (arg == "-vbo")
|
||||
{
|
||||
m_useVbo = true;
|
||||
}
|
||||
else if (arg == "-loglevel")
|
||||
{
|
||||
waitLogLevel = true;
|
||||
|
@ -262,6 +268,7 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
|
|||
GetLogger()->Message("\n");
|
||||
GetLogger()->Message("List of available options:\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(" -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");
|
||||
|
@ -425,6 +432,8 @@ bool CApplication::Create()
|
|||
return false;
|
||||
}
|
||||
|
||||
static_cast<Gfx::CGLDevice*>(m_device)->SetUseVbo(m_useVbo);
|
||||
|
||||
// Create the 3D engine
|
||||
m_engine = new Gfx::CEngine(m_iMan, this);
|
||||
|
||||
|
|
|
@ -449,5 +449,7 @@ protected:
|
|||
|
||||
//! Low cpu mode
|
||||
bool m_lowCPU;
|
||||
|
||||
int m_useVbo; // TODO: temporary
|
||||
};
|
||||
|
||||
|
|
|
@ -313,9 +313,24 @@ public:
|
|||
//! Renders primitive composed of vertices with multitexturing (2 textures)
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) = 0;
|
||||
//! Renders primitive composed of vertices with color information
|
||||
//! Renders primitive composed of vertices with solid color
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount) = 0;
|
||||
|
||||
//! 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
|
||||
//! Returns a mask of frustum planes for which the test is positive
|
||||
virtual int ComputeSphereVisibility(const Math::Vector ¢er, float radius) = 0;
|
||||
|
|
|
@ -44,23 +44,18 @@ namespace Gfx {
|
|||
* - vertex coordinates (x,y,z) as Math::Vector,
|
||||
* - normal coordinates (nx,ny,nz) as Math::Vector
|
||||
* - texture coordinates (u,v) as Math::Point.
|
||||
*
|
||||
* Additional padding is provided to align to even multiplies of 4 floats for faster access.
|
||||
*/
|
||||
struct Vertex
|
||||
{
|
||||
Math::Vector coord;
|
||||
float pad1;
|
||||
Math::Vector normal;
|
||||
float pad2;
|
||||
Math::Point texCoord;
|
||||
float pad3, pad4;
|
||||
|
||||
explicit Vertex(Math::Vector aCoord = Math::Vector(),
|
||||
Math::Vector aNormal = Math::Vector(),
|
||||
Math::Point aTexCoord = Math::Point())
|
||||
: coord(aCoord), pad1(0.0f), normal(aNormal),
|
||||
pad2(0.0f),texCoord(aTexCoord), pad3(0.0f), pad4(0.0f) {}
|
||||
: coord(aCoord), normal(aNormal),
|
||||
texCoord(aTexCoord) {}
|
||||
|
||||
|
||||
//! Returns a string "(c: [...], n: [...], tc: [...])"
|
||||
|
@ -81,18 +76,15 @@ struct Vertex
|
|||
* It contains:
|
||||
* - vertex coordinates (x,y,z) as Math::Vector,
|
||||
* - RGBA color as Color
|
||||
*
|
||||
* Additional padding is provided to align to even multiplies of 4 floats for faster access.
|
||||
*/
|
||||
struct VertexCol
|
||||
{
|
||||
Math::Vector coord;
|
||||
float pad;
|
||||
Color color;
|
||||
|
||||
explicit VertexCol(Math::Vector aCoord = Math::Vector(),
|
||||
Color aColor = Color())
|
||||
: coord(aCoord), pad(0.0f), color(aColor) {}
|
||||
: coord(aCoord), color(aColor) {}
|
||||
|
||||
//! Returns a string "(c: [...], col: [...])"
|
||||
inline std::string ToString() const
|
||||
|
@ -111,15 +103,11 @@ struct VertexCol
|
|||
*
|
||||
* In addition to fields from Vector, it contains
|
||||
* secondary texture coordinates (u2, v2) as Math::Point
|
||||
*
|
||||
* Additional padding is provided to align to even multiplies of 4 floats for faster access.
|
||||
*/
|
||||
struct VertexTex2
|
||||
{
|
||||
Math::Vector coord;
|
||||
float pad1;
|
||||
Math::Vector normal;
|
||||
float pad2;
|
||||
Math::Point texCoord;
|
||||
Math::Point texCoord2;
|
||||
|
||||
|
@ -127,7 +115,7 @@ struct VertexTex2
|
|||
Math::Vector aNormal = Math::Vector(),
|
||||
Math::Point aTexCoord = Math::Point(),
|
||||
Math::Point aTexCoord2 = Math::Point())
|
||||
: coord(aCoord), pad1(0.0f), normal(aNormal), pad2(0.0f),
|
||||
: coord(aCoord), normal(aNormal),
|
||||
texCoord(aTexCoord), texCoord2(aTexCoord2) {}
|
||||
|
||||
//! Sets the fields from Vertex with texCoord2 = (0,0)
|
||||
|
|
|
@ -92,6 +92,7 @@ EngineObjLevel4::EngineObjLevel4(bool used, EngineTriangleType type, const Mater
|
|||
this->type = type;
|
||||
this->material = material;
|
||||
this->state = state;
|
||||
this->staticBufferId = 0;
|
||||
|
||||
vertices.reserve(LEVEL4_VERTEX_PREALLOCATE_COUNT);
|
||||
}
|
||||
|
@ -182,6 +183,7 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
|
|||
m_alphaMode = 1;
|
||||
|
||||
m_updateGeometry = false;
|
||||
m_updateStaticObjects = false;
|
||||
|
||||
m_interfaceMode = false;
|
||||
|
||||
|
@ -385,6 +387,7 @@ void CEngine::FrameUpdate()
|
|||
|
||||
ComputeDistance();
|
||||
UpdateGeometry();
|
||||
UpdateStaticObjects();
|
||||
|
||||
m_highlightTime = m_app->GetAbsTime();
|
||||
|
||||
|
@ -570,11 +573,27 @@ bool CEngine::DeleteObject(int objRank)
|
|||
EngineObjLevel2& p2 = p1.next[l2];
|
||||
if (! p2.used) continue;
|
||||
|
||||
if (p2.objRank == objRank)
|
||||
if (p2.objRank != objRank) continue;
|
||||
|
||||
if (m_objects[objRank].staticBuffer)
|
||||
{
|
||||
p2.used = false;
|
||||
p2.next.clear();
|
||||
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];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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());
|
||||
|
||||
if (m_objects[objRank].staticBuffer)
|
||||
{
|
||||
if (p4.staticBufferId != 0)
|
||||
{
|
||||
m_device->DestroyStaticObject(p4.staticBufferId);
|
||||
p4.staticBufferId = 0;
|
||||
}
|
||||
|
||||
m_updateStaticObjects = true;
|
||||
}
|
||||
|
||||
if (globalUpdate)
|
||||
{
|
||||
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());
|
||||
|
||||
if (m_objects[objRank].staticBuffer)
|
||||
{
|
||||
if (p4.staticBufferId != 0)
|
||||
{
|
||||
m_device->DestroyStaticObject(p4.staticBufferId);
|
||||
p4.staticBufferId = 0;
|
||||
}
|
||||
|
||||
m_updateStaticObjects = true;
|
||||
}
|
||||
|
||||
if (globalUpdate)
|
||||
{
|
||||
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,
|
||||
std::string tex1Name, std::string tex2Name,
|
||||
float min, float max, bool globalUpdate)
|
||||
std::string tex1Name, std::string tex2Name,
|
||||
float min, float max, bool globalUpdate)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -920,24 +996,24 @@ bool CEngine::AddQuick(int objRank, const EngineObjLevel4& buffer,
|
|||
}
|
||||
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.y = Math::Min(buffer.vertices[i].coord.y, m_objects[objRank].bboxMin.y);
|
||||
m_objects[objRank].bboxMin.z = Math::Min(buffer.vertices[i].coord.z, m_objects[objRank].bboxMin.z);
|
||||
m_objects[objRank].bboxMax.x = Math::Max(buffer.vertices[i].coord.x, m_objects[objRank].bboxMax.x);
|
||||
m_objects[objRank].bboxMax.y = Math::Max(buffer.vertices[i].coord.y, m_objects[objRank].bboxMax.y);
|
||||
m_objects[objRank].bboxMax.z = Math::Max(buffer.vertices[i].coord.z, m_objects[objRank].bboxMax.z);
|
||||
m_objects[objRank].bboxMin.x = Math::Min(p4.vertices[i].coord.x, m_objects[objRank].bboxMin.x);
|
||||
m_objects[objRank].bboxMin.y = Math::Min(p4.vertices[i].coord.y, m_objects[objRank].bboxMin.y);
|
||||
m_objects[objRank].bboxMin.z = Math::Min(p4.vertices[i].coord.z, m_objects[objRank].bboxMin.z);
|
||||
m_objects[objRank].bboxMax.x = Math::Max(p4.vertices[i].coord.x, m_objects[objRank].bboxMax.x);
|
||||
m_objects[objRank].bboxMax.y = Math::Max(p4.vertices[i].coord.y, m_objects[objRank].bboxMax.y);
|
||||
m_objects[objRank].bboxMax.z = Math::Max(p4.vertices[i].coord.z, m_objects[objRank].bboxMax.z);
|
||||
}
|
||||
|
||||
m_objects[objRank].radius = Math::Max(m_objects[objRank].bboxMin.Length(),
|
||||
m_objects[objRank].bboxMax.Length());
|
||||
}
|
||||
|
||||
if (buffer.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||
m_objects[objRank].totalTriangles += buffer.vertices.size() / 3;
|
||||
else if (buffer.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||
m_objects[objRank].totalTriangles += buffer.vertices.size() - 2;
|
||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||
m_objects[objRank].totalTriangles += p4.vertices.size() / 3;
|
||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||
m_objects[objRank].totalTriangles += p4.vertices.size() - 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1735,10 +1811,57 @@ void CEngine::UpdateGeometry()
|
|||
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()
|
||||
{
|
||||
ComputeDistance();
|
||||
UpdateGeometry();
|
||||
UpdateStaticObjects();
|
||||
}
|
||||
|
||||
bool CEngine::DetectBBox(int objRank, Math::Point mouse)
|
||||
|
@ -3106,20 +3229,7 @@ void CEngine::Draw3DScene()
|
|||
SetMaterial(p4.material);
|
||||
SetState(p4.state);
|
||||
|
||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
m_statisticTriangle += p4.vertices.size() / 3;
|
||||
}
|
||||
if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
m_statisticTriangle += p4.vertices.size() - 2;
|
||||
}
|
||||
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3188,22 +3298,7 @@ void CEngine::Draw3DScene()
|
|||
SetMaterial(p4.material);
|
||||
SetState(p4.state);
|
||||
|
||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
|
||||
m_statisticTriangle += p4.vertices.size() / 3;
|
||||
}
|
||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
|
||||
m_statisticTriangle += p4.vertices.size() - 2;
|
||||
}
|
||||
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3264,21 +3359,7 @@ void CEngine::Draw3DScene()
|
|||
SetMaterial(p4.material);
|
||||
SetState(tState, tColor);
|
||||
|
||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
|
||||
m_statisticTriangle += p4.vertices.size() / 3;
|
||||
}
|
||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
m_statisticTriangle += p4.vertices.size() - 2;
|
||||
}
|
||||
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3307,6 +3388,32 @@ void CEngine::Draw3DScene()
|
|||
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()
|
||||
{
|
||||
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
|
||||
|
@ -3397,21 +3504,7 @@ void CEngine::DrawInterface()
|
|||
SetMaterial(p4.material);
|
||||
SetState(p4.state);
|
||||
|
||||
if (p4.type == ENG_TRIANGLE_TYPE_TRIANGLES)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLES,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
|
||||
m_statisticTriangle += p4.vertices.size() / 3;
|
||||
}
|
||||
else if (p4.type == ENG_TRIANGLE_TYPE_SURFACE)
|
||||
{
|
||||
m_device->DrawPrimitive( PRIMITIVE_TRIANGLE_STRIP,
|
||||
&p4.vertices[0],
|
||||
p4.vertices.size() );
|
||||
m_statisticTriangle += p4.vertices.size() - 2;
|
||||
}
|
||||
DrawObject(p4, m_objects[objRank].staticBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,9 @@ struct EngineObject
|
|||
//! Number of triangles
|
||||
int totalTriangles;
|
||||
//! Type of object
|
||||
EngineObjectType type;
|
||||
EngineObjectType type;
|
||||
//! Whether the object is stored and rendered as static buffer
|
||||
bool staticBuffer;
|
||||
//! Transformation matrix
|
||||
Math::Matrix transform;
|
||||
//! Distance to object from eye point
|
||||
|
@ -225,6 +227,7 @@ struct EngineObject
|
|||
drawWorld = false;
|
||||
drawFront = false;
|
||||
totalTriangles = 0;
|
||||
staticBuffer = false;
|
||||
type = ENG_OBJTYPE_NULL;
|
||||
transform.LoadIdentity();
|
||||
bboxMax.LoadZero();
|
||||
|
@ -252,6 +255,7 @@ struct EngineObjLevel4
|
|||
Material material;
|
||||
int state;
|
||||
std::vector<VertexTex2> vertices;
|
||||
unsigned int staticBufferId;
|
||||
|
||||
EngineObjLevel4(bool used = false,
|
||||
EngineTriangleType type = ENG_TRIANGLE_TYPE_TRIANGLES,
|
||||
|
@ -760,6 +764,12 @@ public:
|
|||
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
|
||||
bool SetObjectDrawWorld(int objRank, bool draw);
|
||||
//! Sets drawFront for given object
|
||||
|
@ -1151,6 +1161,8 @@ public:
|
|||
protected:
|
||||
//! Prepares the interface for 3D scene
|
||||
void Draw3DScene();
|
||||
//! Draw 3D object
|
||||
void DrawObject(const EngineObjLevel4& obj, bool staticBuffer);
|
||||
//! Draws the user interface over the scene
|
||||
void DrawInterface();
|
||||
|
||||
|
@ -1215,6 +1227,9 @@ protected:
|
|||
//! Updates geometric parameters of objects (bounding box and radius)
|
||||
void UpdateGeometry();
|
||||
|
||||
//! Updates static buffers of changed objects
|
||||
void UpdateStaticObjects();
|
||||
|
||||
protected:
|
||||
CInstanceManager* m_iMan;
|
||||
CApplication* m_app;
|
||||
|
@ -1293,6 +1308,7 @@ protected:
|
|||
Color m_waterAddColor;
|
||||
int m_statisticTriangle;
|
||||
bool m_updateGeometry;
|
||||
bool m_updateStaticObjects;
|
||||
int m_alphaMode;
|
||||
bool m_groundSpotVisible;
|
||||
bool m_shadowVisible;
|
||||
|
|
|
@ -1157,18 +1157,24 @@ bool CModelFile::WriteBinaryModel(std::ostream& stream)
|
|||
|
||||
#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)
|
||||
{
|
||||
std::vector<VertexTex2> vs(3, VertexTex2());
|
||||
|
||||
m_engine->SetObjectStatic(objRank, true); // TODO: make optional in the future
|
||||
|
||||
float limit[2];
|
||||
limit[0] = m_engine->GetLimitLOD(0); // frontier AB as config
|
||||
limit[1] = m_engine->GetLimitLOD(1); // frontier BC as config
|
||||
|
||||
for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
|
||||
{
|
||||
// TODO move this to CEngine
|
||||
|
||||
float min = m_triangles[i].min;
|
||||
float max = m_triangles[i].max;
|
||||
|
||||
|
|
|
@ -363,6 +363,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force)
|
|||
m_type == PT_EXPLOW )
|
||||
{
|
||||
CreateTriangle(obj, oType, 0);
|
||||
m_engine->SetObjectStatic(m_object->GetObjectRank(0), false);
|
||||
m_engine->DeleteShadow(m_object->GetObjectRank(0));
|
||||
ExploStart();
|
||||
}
|
||||
|
@ -1397,6 +1398,8 @@ void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part)
|
|||
int objRank = obj->GetObjectRank(part);
|
||||
if (objRank == -1) return;
|
||||
|
||||
m_engine->SetObjectStatic(objRank, false);
|
||||
|
||||
float min = 0.0f;
|
||||
float max = m_engine->GetLimitLOD(0);
|
||||
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.y = 1.0f - (o.z-oo.z)*m_textureScale*m_textureSubdivCount;
|
||||
|
||||
v.texCoord2 = v.texCoord;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -1166,6 +1168,10 @@ bool CTerrain::CreateSquare(int x, int y)
|
|||
int objRank = m_engine->CreateObject();
|
||||
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;
|
||||
|
||||
float min = 0.0f;
|
||||
|
|
|
@ -73,6 +73,8 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config)
|
|||
{
|
||||
m_config = config;
|
||||
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");
|
||||
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
|
||||
|
||||
|
@ -174,6 +186,16 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig)
|
|||
Create();
|
||||
}
|
||||
|
||||
void CGLDevice::SetUseVbo(bool useVbo)
|
||||
{
|
||||
m_useVbo = useVbo;
|
||||
}
|
||||
|
||||
bool CGLDevice::GetUseVbo()
|
||||
{
|
||||
return m_useVbo;
|
||||
}
|
||||
|
||||
void CGLDevice::BeginScene()
|
||||
{
|
||||
Clear();
|
||||
|
@ -927,6 +949,206 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int
|
|||
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)
|
||||
{
|
||||
float distance = originPlane + Math::DotProduct(normal, center);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
|
||||
// Graphics module namespace
|
||||
|
@ -84,6 +85,9 @@ public:
|
|||
|
||||
void ConfigChanged(const GLDeviceConfig &newConfig);
|
||||
|
||||
void SetUseVbo(bool useVbo);
|
||||
bool GetUseVbo();
|
||||
|
||||
virtual void BeginScene();
|
||||
virtual void EndScene();
|
||||
|
||||
|
@ -119,14 +123,18 @@ public:
|
|||
|
||||
virtual void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT);
|
||||
|
||||
//! Renders primitive composed of vertices with single texture
|
||||
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
//! Renders primitive composed of vertices with multitexturing (2 textures)
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount);
|
||||
|
||||
virtual unsigned int 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 void SetRenderState(RenderState state, bool enabled);
|
||||
|
@ -200,6 +208,30 @@ private:
|
|||
|
||||
//! Set of all created textures
|
||||
std::set<Texture> m_allTextures;
|
||||
|
||||
//! Type of vertex structure
|
||||
enum VertexType
|
||||
{
|
||||
VERTEX_TYPE_NORMAL,
|
||||
VERTEX_TYPE_TEX2,
|
||||
VERTEX_TYPE_COL,
|
||||
};
|
||||
|
||||
//! Info about static VBO buffers
|
||||
struct VboObjectInfo
|
||||
{
|
||||
PrimitiveType primitiveType;
|
||||
unsigned int bufferId;
|
||||
VertexType vertexType;
|
||||
int vertexCount;
|
||||
};
|
||||
|
||||
//! Whether to use 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