attempt to implement will's mesh merging for better render performance
This commit is contained in:
parent
00eb9a9561
commit
dde601e416
|
@ -92,6 +92,8 @@ public:
|
|||
void init();
|
||||
void end();
|
||||
|
||||
void copyInto(Mesh *dest, bool ignoreInterpolationData, bool destinationOwnsTextures);
|
||||
|
||||
//maps
|
||||
const Texture2D *getTexture(int i) const {return textures[i];}
|
||||
|
||||
|
@ -116,6 +118,11 @@ public:
|
|||
const Vec3f *getTangents() const {return tangents;}
|
||||
const uint32 *getIndices() const {return indices;}
|
||||
|
||||
void setVertices(Vec3f *data, uint32 count);
|
||||
void setNormals(Vec3f *data, uint32 count);
|
||||
void setTexCoords(Vec2f *data, uint32 count);
|
||||
void setIndices(uint32 *data, uint32 count);
|
||||
|
||||
//material
|
||||
const Vec3f &getDiffuseColor() const {return diffuseColor;}
|
||||
const Vec3f &getSpecularColor() const {return specularColor;}
|
||||
|
@ -127,11 +134,15 @@ public:
|
|||
bool getCustomTexture() const {return customColor;}
|
||||
bool getNoSelect() const {return noSelect;}
|
||||
|
||||
uint32 getTextureFlags() const { return textureFlags; }
|
||||
|
||||
//external data
|
||||
const InterpolationData *getInterpolationData() const {return interpolationData;}
|
||||
|
||||
//interpolation
|
||||
void buildInterpolationData();
|
||||
void cleanupInterpolationData();
|
||||
|
||||
void updateInterpolationData(float t, bool cycle);
|
||||
void updateInterpolationVertices(float t, bool cycle);
|
||||
|
||||
|
@ -225,6 +236,7 @@ public:
|
|||
|
||||
private:
|
||||
void buildInterpolationData() const;
|
||||
void autoJoinMeshFrames();
|
||||
};
|
||||
|
||||
class PixelBufferWrapper {
|
||||
|
|
|
@ -237,6 +237,8 @@ void ModelRendererGl::renderMesh(Mesh *mesh,int renderMode) {
|
|||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
assertGl();
|
||||
|
||||
//tex coords
|
||||
if(renderTextures && mesh->getTexture(mtDiffuse) != NULL ) {
|
||||
if(duplicateTexCoords) {
|
||||
|
@ -279,6 +281,8 @@ void ModelRendererGl::renderMesh(Mesh *mesh,int renderMode) {
|
|||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
assertGl();
|
||||
|
||||
//tex coords
|
||||
if(renderTextures && mesh->getTexture(mtDiffuse)!=NULL ) {
|
||||
if(duplicateTexCoords) {
|
||||
|
@ -302,15 +306,21 @@ void ModelRendererGl::renderMesh(Mesh *mesh,int renderMode) {
|
|||
}
|
||||
|
||||
if(getVBOSupported() == true && mesh->getFrameCount() == 1) {
|
||||
assertGl();
|
||||
|
||||
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->getVBOIndexes() );
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, (char *)NULL);
|
||||
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
|
||||
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
||||
|
||||
//glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
|
||||
|
||||
assertGl();
|
||||
}
|
||||
else {
|
||||
//draw model
|
||||
assertGl();
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "opengl.h"
|
||||
#include "platform_util.h"
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
|
@ -287,8 +289,7 @@ void Mesh::end() {
|
|||
delete [] indices;
|
||||
indices=NULL;
|
||||
|
||||
delete interpolationData;
|
||||
interpolationData=NULL;
|
||||
cleanupInterpolationData();
|
||||
|
||||
if(textureManager != NULL) {
|
||||
for(int i = 0; i < meshTextureCount; ++i) {
|
||||
|
@ -311,6 +312,11 @@ void Mesh::buildInterpolationData(){
|
|||
interpolationData= new InterpolationData(this);
|
||||
}
|
||||
|
||||
void Mesh::cleanupInterpolationData() {
|
||||
delete interpolationData;
|
||||
interpolationData=NULL;
|
||||
}
|
||||
|
||||
void Mesh::updateInterpolationData(float t, bool cycle) {
|
||||
if(interpolationData != NULL) {
|
||||
interpolationData->update(t, cycle);
|
||||
|
@ -1292,6 +1298,8 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad,
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
autoJoinMeshFrames();
|
||||
}
|
||||
catch(megaglest_runtime_error& ex) {
|
||||
//printf("1111111 ex.wantStackTrace() = %d\n",ex.wantStackTrace());
|
||||
|
@ -1369,6 +1377,338 @@ void Model::deletePixels() {
|
|||
}
|
||||
}
|
||||
|
||||
class MeshContainer {
|
||||
protected:
|
||||
int indexValue;
|
||||
std::vector<Mesh *> meshes;
|
||||
|
||||
public:
|
||||
|
||||
MeshContainer() {
|
||||
this->indexValue = -1;
|
||||
}
|
||||
void add(int index, Mesh *mesh) {
|
||||
if(this->indexValue < 0) {
|
||||
this->indexValue = index;
|
||||
}
|
||||
meshes.push_back(mesh);
|
||||
}
|
||||
int index() {
|
||||
return indexValue;
|
||||
}
|
||||
int size() {
|
||||
return meshes.size();
|
||||
}
|
||||
std::vector<Mesh *> get() {
|
||||
return meshes;
|
||||
}
|
||||
};
|
||||
|
||||
void Mesh::setVertices(Vec3f *data, uint32 count) {
|
||||
delete [] this->vertices;
|
||||
this->vertices = data;
|
||||
|
||||
this->vertexCount = count;
|
||||
}
|
||||
void Mesh::setNormals(Vec3f *data, uint32 count) {
|
||||
delete [] this->normals;
|
||||
this->normals = data;
|
||||
|
||||
this->vertexCount = count;
|
||||
}
|
||||
|
||||
void Mesh::setTexCoords(Vec2f *data, uint32 count) {
|
||||
delete [] this->texCoords;
|
||||
this->texCoords = data;
|
||||
|
||||
this->vertexCount = count;
|
||||
}
|
||||
|
||||
void Mesh::setIndices(uint32 *data, uint32 count) {
|
||||
delete [] this->indices;
|
||||
this->indices = data;
|
||||
|
||||
this->indexCount = count;
|
||||
}
|
||||
|
||||
void Mesh::copyInto(Mesh *dest, bool ignoreInterpolationData,
|
||||
bool destinationOwnsTextures) {
|
||||
|
||||
for(int index = 0; index < meshTextureCount; ++index){
|
||||
dest->textures[index] = this->textures[index];
|
||||
dest->texturesOwned[index] = this->texturesOwned[index];
|
||||
dest->texturePaths[index] = this->texturePaths[index];
|
||||
|
||||
if(destinationOwnsTextures == true) {
|
||||
this->texturesOwned[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
dest->name = this->name;
|
||||
//vertex data counts
|
||||
dest->frameCount = this->frameCount;
|
||||
dest->vertexCount = this->vertexCount;
|
||||
dest->indexCount = this->indexCount;
|
||||
dest->texCoordFrameCount = this->texCoordFrameCount;
|
||||
|
||||
//vertex data
|
||||
if(dest->vertices != NULL) {
|
||||
delete [] dest->vertices;
|
||||
dest->vertices = NULL;
|
||||
}
|
||||
if(this->vertices != NULL) {
|
||||
dest->vertices = new Vec3f[this->frameCount * this->vertexCount];
|
||||
memcpy(&dest->vertices[0],&this->vertices[0],this->frameCount * this->vertexCount * sizeof(Vec3f));
|
||||
}
|
||||
|
||||
if(dest->normals != NULL) {
|
||||
delete [] dest->normals;
|
||||
dest->normals = NULL;
|
||||
}
|
||||
if(this->normals != NULL) {
|
||||
dest->normals = new Vec3f[this->frameCount * this->vertexCount];
|
||||
memcpy(&dest->normals[0],&this->normals[0],this->frameCount * this->vertexCount * sizeof(Vec3f));
|
||||
}
|
||||
|
||||
if(dest->texCoords != NULL) {
|
||||
delete [] dest->texCoords;
|
||||
dest->texCoords = NULL;
|
||||
}
|
||||
if(this->texCoords != NULL) {
|
||||
dest->texCoords = new Vec2f[this->vertexCount];
|
||||
memcpy(&dest->texCoords[0],&this->texCoords[0],this->vertexCount * sizeof(Vec2f));
|
||||
}
|
||||
|
||||
if(dest->tangents != NULL) {
|
||||
delete [] dest->tangents;
|
||||
dest->tangents = NULL;
|
||||
}
|
||||
if(this->tangents != NULL) {
|
||||
dest->tangents = new Vec3f[this->vertexCount];
|
||||
memcpy(&dest->tangents[0],&this->tangents[0],this->vertexCount * sizeof(Vec3f));
|
||||
}
|
||||
|
||||
if(dest->indices != NULL) {
|
||||
delete [] dest->indices;
|
||||
dest->indices = NULL;
|
||||
}
|
||||
if(this->indices != NULL) {
|
||||
dest->indices = new uint32[this->indexCount];
|
||||
memcpy(&dest->indices[0],&this->indices[0],this->indexCount * sizeof(uint32));
|
||||
}
|
||||
|
||||
//material data
|
||||
dest->diffuseColor = this->diffuseColor;
|
||||
dest->specularColor = this->specularColor;
|
||||
dest->specularPower = this->specularPower;
|
||||
dest->opacity = this->opacity;
|
||||
|
||||
//properties
|
||||
dest->twoSided = this->twoSided;
|
||||
dest->customColor = this->customColor;
|
||||
dest->noSelect = this->noSelect;
|
||||
|
||||
dest->textureFlags = this->textureFlags;
|
||||
|
||||
if(ignoreInterpolationData == false) {
|
||||
dest->interpolationData = this->interpolationData;
|
||||
}
|
||||
dest->textureManager = this->textureManager;
|
||||
|
||||
// Vertex Buffer Object Names
|
||||
dest->hasBuiltVBOs = this->hasBuiltVBOs;
|
||||
dest->m_nVBOVertices = this-> m_nVBOVertices;
|
||||
dest->m_nVBOTexCoords = this->m_nVBOTexCoords;
|
||||
dest->m_nVBONormals = this->m_nVBONormals;
|
||||
dest->m_nVBOIndexes = this->m_nVBOIndexes;
|
||||
}
|
||||
|
||||
void Model::autoJoinMeshFrames() {
|
||||
|
||||
/*
|
||||
print "auto-joining compatible meshes..."
|
||||
meshes = {}
|
||||
for mesh in self.meshes:
|
||||
key = (mesh.texture,mesh.frame_count,mesh.twoSided|mesh.customColour)
|
||||
if key in meshes:
|
||||
meshes[key].append(mesh)
|
||||
else:
|
||||
meshes[key] = [mesh]
|
||||
for joinable in meshes.values():
|
||||
if len(joinable) < 2: continue
|
||||
base = joinable[0]
|
||||
print "\tjoining to",base
|
||||
for mesh in joinable[1:]:
|
||||
if base.index_count+mesh.index_count > 0xffff:
|
||||
base = mesh
|
||||
print "\tjoining to",base
|
||||
continue
|
||||
print "\t\t",mesh
|
||||
for a,b in zip(base.frames,mesh.frames):
|
||||
a.vertices.extend(b.vertices)
|
||||
a.normals.extend(b.normals)
|
||||
if base.texture:
|
||||
base.textures.extend(mesh.textures)
|
||||
base.indices.extend(index+base.vertex_count for index in mesh.indices)
|
||||
base.vertex_count += mesh.vertex_count
|
||||
base.index_count += mesh.index_count
|
||||
self.meshes.remove(mesh)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
bool haveJoinedMeshes = false;
|
||||
|
||||
// First looks for meshes with same texture in the same frame
|
||||
std::map<std::string,MeshContainer> joinedMeshes;
|
||||
for(uint32 index = 0; index < meshCount; ++index) {
|
||||
Mesh &mesh = meshes[index];
|
||||
|
||||
// Duplicate mesh vertices are considered to be those with the same
|
||||
// 1. texture 2. framecount 3. twosided flag value 4. same custom texture color
|
||||
string mesh_key = (mesh.getTextureFlags() & 1 ? mesh.getTexture(0)->getPath() : "none");
|
||||
mesh_key += string("_") + intToStr(mesh.getFrameCount()) +
|
||||
string("_") + intToStr(mesh.getTwoSided()) +
|
||||
string("_") + intToStr(mesh.getCustomTexture());
|
||||
|
||||
joinedMeshes[mesh_key].add(index,&mesh);
|
||||
if(haveJoinedMeshes == false && joinedMeshes[mesh_key].size() > 1) {
|
||||
haveJoinedMeshes = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(haveJoinedMeshes == true) {
|
||||
//printf("*** Detected Joined meshes for model [%s]\n",fileName.c_str());
|
||||
|
||||
// We have mesh data to join we now create a list in the same order
|
||||
// as the original meshes but each index will have 1 or more meshes
|
||||
// This is done to maintain original mesh ordering
|
||||
std::map<int, std::vector<Mesh *> > orderedMeshes;
|
||||
for(std::map<std::string,MeshContainer >::iterator iterMap = joinedMeshes.begin();
|
||||
iterMap != joinedMeshes.end(); ++iterMap) {
|
||||
orderedMeshes[iterMap->second.index()] = iterMap->second.get();
|
||||
|
||||
//if(iterMap->second.size() > 1) {
|
||||
// printf("Key [%s] joined meshes: %d\n",iterMap->first.c_str(),iterMap->second.size());
|
||||
//}
|
||||
}
|
||||
|
||||
// Now the real work of creating a new list of joined mesh data
|
||||
Mesh *joinedMeshList = new Mesh[joinedMeshes.size()];
|
||||
|
||||
int index = 0;
|
||||
for(std::map<int, std::vector<Mesh *> >::iterator iterMap = orderedMeshes.begin();
|
||||
iterMap != orderedMeshes.end(); ++iterMap) {
|
||||
//printf("Join index: %d joincount: %d\n",index,iterMap->second.size());
|
||||
|
||||
Mesh *base = &joinedMeshList[index];
|
||||
|
||||
// Deep copy mesh data
|
||||
iterMap->second[0]->copyInto(base, true, true);
|
||||
|
||||
if(iterMap->second.size() > 1) {
|
||||
// Time to join mesh data for this mesh
|
||||
for(int joinIndex = 1;
|
||||
joinIndex < iterMap->second.size(); ++joinIndex) {
|
||||
Mesh *mesh = iterMap->second[joinIndex];
|
||||
if(base->getIndexCount() + mesh->getIndexCount() > 0xffff) {
|
||||
printf("Not exactly sure what this IF statement is for?\n");
|
||||
mesh->copyInto(base, true, true);
|
||||
}
|
||||
else {
|
||||
// Need to add verticies for each from from mesh to base
|
||||
uint32 originalBaseVertexCount = base->getVertexCount();
|
||||
|
||||
uint32 newVertexCount =
|
||||
base->getVertexCount() + mesh->getVertexCount();
|
||||
|
||||
uint32 newVertexFrameCount =
|
||||
(base->getFrameCount() * newVertexCount);
|
||||
|
||||
Vec3f *joined_vertices = new Vec3f[newVertexFrameCount];
|
||||
Vec3f *joined_normals = new Vec3f[newVertexFrameCount];
|
||||
uint32 join_index = 0;
|
||||
|
||||
// Join mesh vertices and normals
|
||||
for(int frameIndex = 0;
|
||||
frameIndex < base->getFrameCount(); ++frameIndex) {
|
||||
uint32 baseIndex = frameIndex * originalBaseVertexCount;
|
||||
uint32 meshIndex = frameIndex * mesh->getVertexCount();
|
||||
//uint32 appendBaseJoinIndex = frameIndex * newVertexCount;
|
||||
|
||||
// first original mesh values get copied
|
||||
memcpy(&joined_vertices[join_index],
|
||||
&base->getVertices()[baseIndex],
|
||||
originalBaseVertexCount * sizeof(Vec3f));
|
||||
memcpy(&joined_normals[join_index],
|
||||
&base->getNormals()[baseIndex],
|
||||
originalBaseVertexCount * sizeof(Vec3f));
|
||||
join_index += originalBaseVertexCount;
|
||||
|
||||
// second joined mesh values get copied
|
||||
memcpy(&joined_vertices[join_index],
|
||||
&mesh->getVertices()[meshIndex],
|
||||
mesh->getVertexCount() * sizeof(Vec3f));
|
||||
memcpy(&joined_normals[join_index],
|
||||
&mesh->getNormals()[meshIndex],
|
||||
mesh->getVertexCount() * sizeof(Vec3f));
|
||||
join_index += mesh->getVertexCount();
|
||||
}
|
||||
|
||||
// update vertex and normal buffers with joined mesh data
|
||||
base->setVertices(joined_vertices, newVertexCount);
|
||||
base->setNormals(joined_normals, newVertexCount);
|
||||
|
||||
// If we have texture coords join them
|
||||
if(base->getTextureFlags() & 1) {
|
||||
Vec2f *joined_texCoords = new Vec2f[newVertexCount];
|
||||
|
||||
// update texture coord buffers with joined mesh data
|
||||
memcpy(&joined_texCoords[0],
|
||||
&base->getTexCoords()[0],
|
||||
originalBaseVertexCount * sizeof(Vec2f));
|
||||
memcpy(&joined_texCoords[originalBaseVertexCount],
|
||||
&mesh->getTexCoords()[0],
|
||||
mesh->getVertexCount() * sizeof(Vec2f));
|
||||
|
||||
base->setTexCoords(joined_texCoords, newVertexCount);
|
||||
}
|
||||
|
||||
// update index buffers with joined mesh data
|
||||
uint32 newindexCount = base->getIndexCount() + mesh->getIndexCount();
|
||||
uint32 *joined_indexes = new uint32[newindexCount];
|
||||
|
||||
uint32 join_index_index = 0;
|
||||
memcpy(&joined_indexes[join_index_index],
|
||||
&base->getIndices()[0],
|
||||
base->getIndexCount() * sizeof(uint32));
|
||||
join_index_index += base->getIndexCount();
|
||||
|
||||
for(int meshIndex = 0;
|
||||
meshIndex < mesh->getIndexCount(); ++meshIndex) {
|
||||
uint32 index_value = mesh->getIndices()[meshIndex];
|
||||
|
||||
// join index values
|
||||
joined_indexes[join_index_index] = index_value + originalBaseVertexCount;
|
||||
join_index_index++;
|
||||
}
|
||||
base->setIndices(joined_indexes, newindexCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
base->buildInterpolationData();
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
delete [] meshes;
|
||||
meshes = joinedMeshList;
|
||||
meshCount = joinedMeshes.size();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool PixelBufferWrapper::isPBOEnabled = false;
|
||||
int PixelBufferWrapper::index = 0;
|
||||
vector<unsigned int> PixelBufferWrapper::pboIds;
|
||||
|
|
Loading…
Reference in New Issue
Block a user