www.pudn.com > tristripper-1.1.0-beta-5.zip > gl_mesh.cpp
#include "stdafx.h"
#include "gl_mesh.h"
#include "fileio.h"
#include "varrays_normalizer.h"
#include "tri_stripper.h"
#include "high_res_timer.h"
//#define USE_NVIDIA_STRIPPER
#ifdef USE_NVIDIA_STRIPPER
#include "NvTriStrip.h"
#endif
size_t gl_mesh::s_CacheSize = 10;
bool gl_mesh::s_ViewStrips = false;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
gl_mesh::~gl_mesh()
{
if (m_DisplayListID != 0)
glDeleteLists(m_DisplayListID, 1);
}
//////////////////////////////////////////////////////////////////////
// Members Functions
//////////////////////////////////////////////////////////////////////
void gl_mesh::Compile()
{
std::cout << "Compiling Mesh " << Name() << ": " << std::endl;
NormalizeVArrays(); // Remove duplicate or useless elements
TriangleStrip(); // Convert to triangle strips
InitDisplayList(); // Create a display list for future executions
}
void gl_mesh::Execute() const
{
// If there is no display list, simply draw the scene
if (m_DisplayListID == 0)
RawDraw();
// else call the display list
else
glCallList(m_DisplayListID);
}
void gl_mesh::LoadFromVxo(std::istream & File)
{
// float must be 32 bits
static_assert(sizeof(char) == sizeof(uint8_t));
static_assert(sizeof(float) == sizeof(uint32_t));
using io_facilities::readvar;
// Mesh Name
char String[256];
File.getline(String, 256, '\0');
m_Name = String;
// Mesh Info
size_t NbSubMeshes;
readvar(File, NbSubMeshes, 4);
readvar(File, m_NbVertices, 4);
readvar(File, m_NbTextures, 4);
m_SubMeshes.resize(NbSubMeshes);
m_VArrays[vertex].resize(3 * m_NbVertices);
m_VArrays[normal].resize(3 * m_NbVertices);
for (size_t i = 0; i < m_NbTextures; ++i)
m_VArrays[array_type(texture_coord0 + i)].resize(2 * m_NbVertices);
// Load Mesh Data
for (size_t i = 0; i < (m_NbVertices * 3); ++i)
readvar(File, reinterpret_cast(m_VArrays[vertex][i]), 4);
for (size_t i = 0; i < (m_NbVertices * 3); ++i)
readvar(File, reinterpret_cast(m_VArrays[normal][i]), 4);
for (size_t i = 0; i < m_NbTextures; ++i)
for (size_t j = 0; j < (m_NbVertices * 2); ++j)
readvar(File, reinterpret_cast(m_VArrays[array_type(texture_coord0 + i)][j]), 4);
// Load Each SubMesh
for (size_t i = 0; i < m_SubMeshes.size(); ++i)
m_SubMeshes[i].LoadFromVXO(File);
}
void gl_mesh::submesh::LoadFromVXO(std::istream & File)
{
using io_facilities::readvar;
// SubMesh Render Mode
readvar(File, m_glMode, 4);
// SubMesh Size
size_t NbIndices;
readvar(File, NbIndices, 4);
m_Indices.resize(NbIndices);
// Load Data Types And Acts As Needed
for (size_t i = 0; i < NbIndices; ++i) readvar(File, m_Indices[i], 4);
}
void gl_mesh::InitDisplayList()
{
if (m_DisplayListID != 0) {
glDeleteLists(m_DisplayListID, 1);
m_DisplayListID = 0;
}
m_DisplayListID = glGenLists(1);
if (m_DisplayListID == 0)
throw("Couldn't generate a display list");
glNewList(m_DisplayListID, GL_COMPILE);
RawDraw();
glEndList();
}
void gl_mesh::NormalizeVArrays()
{
using namespace std;
cout << "- Normalizing vertex arrays: " << endl;
high_res_timer Timer;
varrays_normalizer Normalizer(* this);
size_t NewSize = Normalizer.Normalize();
cout << " - went from " << static_cast(m_NbVertices) << " to " << static_cast(NewSize) << " vertices." << endl;
cout << " - took " << Timer.ElapsedTime() * 1000.0 << " msecs." << endl;
cout << endl;
}
void gl_mesh::TriangleStrip()
{
using namespace std;
// verify there is only one submesh containing only triangles
if ((m_SubMeshes.size() != 1) || (m_SubMeshes[0].GLMode() != GL_TRIANGLES))
throw ("trying to triangle strip a mesh that has more than one submesh or doesn't contain triangles");
cout << "- Stripping triangles: " << endl;
cout << " - number of triangles: " << static_cast(m_SubMeshes[0].Indices().size() / 3) << "." << endl;
#ifndef USE_NVIDIA_STRIPPER
// USING TRI STRIPPER
using namespace triangle_stripper;
high_res_timer Timer;
// convert 32 bits indices from the submesh into the type used by Tri Stripper
indices Indices(m_SubMeshes[0].Indices().begin(), m_SubMeshes[0].Indices().end());
primitive_vector PrimitivesVector;
{ // we want to time the tri_stripper object destruction as well
tri_stripper TriStripper(Indices);
TriStripper.SetMinStripSize(2);
TriStripper.SetCacheSize(s_CacheSize);
TriStripper.SetBackwardSearch(false);
TriStripper.Strip(&PrimitivesVector);
}
const float Time = Timer.ElapsedTime() * 1000.0;
// Replace the submeshes with the new one
m_SubMeshes.clear();
m_SubMeshes.reserve(PrimitivesVector.size());
for (size_t i = 0; i < PrimitivesVector.size(); ++i) {
// convert back from Tri Stripper indices type to 32 bits indices
const submesh::indices NewIndices(PrimitivesVector[i].Indices.begin(), PrimitivesVector[i].Indices.end());
m_SubMeshes.push_back(submesh(NewIndices, PrimitivesVector[i].Type));
}
// Display statistics
size_t NbStrips = 0;
size_t NbTriangles = 0;
size_t NbStrippedTri = 0;
for (size_t i = 0; i < PrimitivesVector.size(); ++i) {
if (PrimitivesVector[i].Type == TRIANGLE_STRIP) {
++NbStrips;
NbStrippedTri += (PrimitivesVector[i].Indices.size()) - 2;
} else
NbTriangles += (PrimitivesVector[i].Indices.size()) / 3;
}
cout << " - generated " << static_cast(NbStrips) << " triangle strips." << endl;
cout << " - stripped " << static_cast(NbStrippedTri) << " triangles." << endl;
cout << " - left " << static_cast(NbTriangles) << " triangles alone." << endl;
cout << " - created " << static_cast(PrimitivesVector.size()) << " primitive groups." << endl;
cout << " - took " << Time << " msecs." << endl;
cout << endl;
#else
// USING NVIDIA STRIPPER
unsigned short NbGroups;
PrimitiveGroup * pPrimitiveGroup = NULL;
std::vector Indices(m_SubMeshes[0].Indices().begin(), m_SubMeshes[0].Indices().end());
high_res_timer Timer;
SetCacheSize(s_CacheSize - 6);
SetStitchStrips(false);
SetMinStripSize(2);
GenerateStrips(&(Indices[0]), static_cast(Indices.size()), &pPrimitiveGroup, &NbGroups);
const float Time = Timer.ElapsedTime() * 1000.0;
// Replace the submeshes with the new one
m_SubMeshes.clear();
m_SubMeshes.reserve(NbGroups);
for (size_t i = 0; i < NbGroups; ++i) {
GLenum Type;
switch (pPrimitiveGroup[i].type) {
case PT_LIST:
Type = GL_TRIANGLES;
break;
case PT_STRIP:
Type = GL_TRIANGLE_STRIP;
break;
case PT_FAN:
Type = GL_TRIANGLE_FAN;
break;
}
m_SubMeshes.push_back(
submesh(
submesh::indices(
pPrimitiveGroup[i].indices + 0,
pPrimitiveGroup[i].indices + pPrimitiveGroup[i].numIndices
),
Type
)
);
}
// Display statistics
size_t NbStrips = 0;
size_t NbFans = 0;
size_t NbTriangles = 0;
size_t NbStrippedTri = 0;
for (size_t i = 0; i < NbGroups; ++i) {
GLenum Type;
switch (pPrimitiveGroup[i].type) {
case PT_LIST:
Type = GL_TRIANGLES;
break;
case PT_STRIP:
Type = GL_TRIANGLE_STRIP;
break;
case PT_FAN:
Type = GL_TRIANGLE_FAN;
break;
}
if (Type == GL_TRIANGLE_STRIP) {
++NbStrips;
NbStrippedTri += (pPrimitiveGroup[i].numIndices) - 2;
} else if (Type == GL_TRIANGLES)
NbTriangles += (pPrimitiveGroup[i].numIndices) / 3;
else if (Type == GL_TRIANGLE_FAN)
++NbFans;
}
cout << " - generated " << static_cast(NbFans) << " triangle fans." << endl;
cout << " - generated " << static_cast(NbStrips) << " triangle strips." << endl;
cout << " - stripped " << static_cast(NbStrippedTri) << " triangles." << endl;
cout << " - left " << static_cast(NbTriangles) << " triangles alone." << endl;
cout << " - created " << static_cast(NbGroups) << " primitive groups." << endl;
cout << " - took " << Time << " msecs." << endl;
cout << endl;
#endif
}
void gl_mesh::RawDraw() const
{
glVertexPointer(3, GL_FLOAT, 0, &(m_VArrays[vertex][0]));
glNormalPointer(GL_FLOAT, 0, &(m_VArrays[normal][0]));
glColor3f(0.4, 0.4, 0.4);
for (size_t i = 0; i < m_SubMeshes.size(); ++i) {
if (s_ViewStrips) {
// Switch colors to draw triangle strips
if (m_SubMeshes[i].GLMode() == GL_TRIANGLE_STRIP) {
switch(i % 19) {
case 0:
glColor3f(1.00, 0.00, 0.00);
break;
case 1:
glColor3f(0.75, 0.25, 0.00);
break;
case 2:
glColor3f(0.50, 0.50, 0.00);
break;
case 3:
glColor3f(0.25, 0.75, 0.00);
break;
case 4:
glColor3f(0.00, 1.00, 0.00);
break;
case 5:
glColor3f(0.00, 0.75, 0.25);
break;
case 6:
glColor3f(0.00, 0.50, 0.50);
break;
case 7:
glColor3f(0.00, 0.25, 0.75);
break;
case 8:
glColor3f(0.00, 0.00, 1.00);
break;
case 9:
glColor3f(0.25, 0.00, 0.75);
break;
case 10:
glColor3f(0.50, 0.00, 0.50);
break;
case 11:
glColor3f(0.75, 0.00, 0.25);
break;
case 12:
glColor3f(1.00, 0.00, 0.00);
break;
case 13:
glColor3f(1.00, 1.00, 0.00);
break;
case 14:
glColor3f(0.00, 1.00, 0.00);
break;
case 15:
glColor3f(0.00, 1.00, 1.00);
break;
case 16:
glColor3f(0.00, 0.00, 1.00);
break;
case 17:
glColor3f(1.00, 0.00, 1.00);
break;
case 18:
glColor3f(1.00, 1.00, 1.00);
break;
}
} else {
glColor3f(0.10, 0.10, 0.10);
}
}
glDrawElements(
m_SubMeshes[i].GLMode(),
(GLsizei) m_SubMeshes[i].Indices().size(),
GL_UNSIGNED_INT,
&((m_SubMeshes[i].Indices())[0]));
}
}