#include "GeoMesh.h" using namespace Geometry; using namespace std; //------------------------------------------------------------------------- // Cosntructor. //------------------------------------------------------------------------- Mesh::Mesh(): mVertexBuffer(0), mSubMeshCount(0), mSubMesh(0), hasSkeleton(false) { mMeshBounds.maxX = 0.0; mMeshBounds.maxY = 0.0; mMeshBounds.maxZ = 0.0; mMeshBounds.minX = 0.0; mMeshBounds.minY = 0.0; mMeshBounds.minZ = 0.0; mMeshBounds.scaleFactor = 0.0; } //------------------------------------------------------------------------- // Destroyer. //------------------------------------------------------------------------- Mesh::~Mesh() { delete [] mSubMesh; delete mVertexBuffer; } //------------------------------------------------------------------------- // Copy constructor. //------------------------------------------------------------------------- Mesh::Mesh(const Mesh &mesh) { mVertexBuffer = new VertexBuffer(); mSubMeshCount = mesh.mSubMeshCount; mSubMesh = new SubMesh[mesh.mSubMeshCount]; // Fill up bounding box settings. mMeshBounds.maxX = mesh.mMeshBounds.maxX; mMeshBounds.maxY = mesh.mMeshBounds.maxY; mMeshBounds.maxZ = mesh.mMeshBounds.maxZ; mMeshBounds.minX = mesh.mMeshBounds.minX; mMeshBounds.minY = mesh.mMeshBounds.minY; mMeshBounds.minZ = mesh.mMeshBounds.minZ; mMeshBounds.radius = mesh.mMeshBounds.radius; mMeshBounds.scaleFactor = mesh.mMeshBounds.scaleFactor; // For each submesh. for (size_t i = 0; i < mesh.mSubMeshCount; i++) { mSubMesh[i].mSharedVertexBuffer = false; mSubMesh[i].mVertexBuffer = new VertexBuffer(); mSubMesh[i].mVertexBuffer->mPosition = new Vector3[mesh.mSubMesh[i].mVertexBuffer->mVertexCount]; mSubMesh[i].mVertexBuffer->mNormal = new Vector3[mesh.mSubMesh[i].mVertexBuffer->mVertexCount]; mSubMesh[i].mVertexBuffer->mTexCoords = new Vector2[mesh.mSubMesh[i].mVertexBuffer->mVertexCount]; mSubMesh[i].mVertexBuffer->mVertexCount = mesh.mSubMesh[i].mVertexBuffer->mVertexCount; mSubMesh[i].mVertexBuffer->mVertexInfo = mesh.mSubMesh[i].mVertexBuffer->mVertexInfo; mSubMesh[i].mType = mesh.mSubMesh[i].mType; strcpy(mSubMesh[i].mName,mesh.mSubMesh[i].mName); strcpy(mSubMesh[i].mMaterialName,mesh.mSubMesh[i].mMaterialName); if (mesh.mSubMesh[i].mSharedVertexBuffer) { for (size_t s = 0; s < mesh.mSubMesh[i].mVertexBuffer->mVertexCount; s++) { if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_POSITION) { mSubMesh[i].mVertexBuffer->mPosition[s].x = mesh.mVertexBuffer->mPosition[s].x; mSubMesh[i].mVertexBuffer->mPosition[s].y = mesh.mVertexBuffer->mPosition[s].y; mSubMesh[i].mVertexBuffer->mPosition[s].z = mesh.mVertexBuffer->mPosition[s].z; } if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_NORMAL) { mSubMesh[i].mVertexBuffer->mNormal[s].x = mesh.mVertexBuffer->mNormal[s].x; mSubMesh[i].mVertexBuffer->mNormal[s].y = mesh.mVertexBuffer->mNormal[s].y; mSubMesh[i].mVertexBuffer->mNormal[s].z = mesh.mVertexBuffer->mNormal[s].z; } if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_TEXCOORDS) { mSubMesh[i].mVertexBuffer->mTexCoords[s].x = mesh.mVertexBuffer->mTexCoords[s].x; mSubMesh[i].mVertexBuffer->mTexCoords[s].y = mesh.mVertexBuffer->mTexCoords[s].y; } } mesh.mSubMesh[i].mSharedVertexBuffer = false; } else { for (size_t s = 0; s < mesh.mSubMesh[i].mVertexBuffer->mVertexCount; s++) { if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_POSITION) { mSubMesh[i].mVertexBuffer->mPosition[s].x = mesh.mSubMesh[i].mVertexBuffer->mPosition[s].x; mSubMesh[i].mVertexBuffer->mPosition[s].y = mesh.mSubMesh[i].mVertexBuffer->mPosition[s].y; mSubMesh[i].mVertexBuffer->mPosition[s].z = mesh.mSubMesh[i].mVertexBuffer->mPosition[s].z; } if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_NORMAL) { mSubMesh[i].mVertexBuffer->mNormal[s].x = mesh.mSubMesh[i].mVertexBuffer->mNormal[s].x; mSubMesh[i].mVertexBuffer->mNormal[s].y = mesh.mSubMesh[i].mVertexBuffer->mNormal[s].y; mSubMesh[i].mVertexBuffer->mNormal[s].z = mesh.mSubMesh[i].mVertexBuffer->mNormal[s].z; } if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_TEXCOORDS) { mSubMesh[i].mVertexBuffer->mTexCoords[s].x = mesh.mSubMesh[i].mVertexBuffer->mTexCoords[s].x; mSubMesh[i].mVertexBuffer->mTexCoords[s].y = mesh.mSubMesh[i].mVertexBuffer->mTexCoords[s].y; } } } // Copy indices. mSubMesh[i].mIndexCount = mesh.mSubMesh[i].mIndexCount; mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; memcpy( mSubMesh[i].mIndex, mesh.mSubMesh[i].mIndex, mesh.mSubMesh[i].mIndexCount * sizeof(Index)); // Copy strips. // offset between memory positions. __w64 int offset = 0; mSubMesh[i].mStripCount = mesh.mSubMesh[i].mStripCount; if (mesh.mSubMesh[i].mStripCount > 0) { mSubMesh[i].mStrip = new Index*[mesh.mSubMesh[i].mStripCount]; offset = &(mSubMesh[i].mIndex[0]) - &(mesh.mSubMesh[i].mIndex[0]); for (size_t j = 0; j < mesh.mSubMesh[i].mStripCount; j++) { mSubMesh[i].mStrip[j] = mesh.mSubMesh[i].mStrip[j] + offset; } } // Copy submesh bones. if (!mesh.mSubMesh[i].mBones.empty()) { for (unsigned int j = 0; j < mesh.mSubMesh[i].mBones.size(); j++) { mSubMesh[i].mBones.push_back(mesh.mSubMesh[i].mBones[j]); } } } // Copy skeleton name. if (mesh.hasSkeleton) { hasSkeleton = true; strcpy(mSkeletonName, mesh.mSkeletonName); } // Copy mesh bones. if (!mesh.mBones.empty()) { for (unsigned int j = 0; j < mesh.mBones.size(); j++) { mBones.push_back(mesh.mBones[j]); } } } //------------------------------------------------------------------------- // Assignment operator. //------------------------------------------------------------------------- Mesh &Mesh::operator =(const Mesh &mesh) { bool copied = false; mVertexBuffer = new VertexBuffer(); mSubMeshCount = mesh.mSubMeshCount; mSubMesh = new Geometry::SubMesh[mesh.mSubMeshCount]; // Fill up bounding box settings. mMeshBounds.maxX = mesh.mMeshBounds.maxX; mMeshBounds.maxY = mesh.mMeshBounds.maxY; mMeshBounds.maxZ = mesh.mMeshBounds.maxZ; mMeshBounds.minX = mesh.mMeshBounds.minX; mMeshBounds.minY = mesh.mMeshBounds.minY; mMeshBounds.minZ = mesh.mMeshBounds.minZ; mMeshBounds.radius = mesh.mMeshBounds.radius; mMeshBounds.scaleFactor = mesh.mMeshBounds.scaleFactor; // For each submesh. for (size_t i = 0; i < mesh.mSubMeshCount; i++) { mSubMesh[i].mSharedVertexBuffer = mesh.mSubMesh[i].mSharedVertexBuffer; //.false; mSubMesh[i].mVertexBuffer = new Geometry::VertexBuffer(); mSubMesh[i].mVertexBuffer->mPosition = new Geometry::Vector3[mesh.mSubMesh[i].mVertexBuffer->mVertexCount]; mSubMesh[i].mVertexBuffer->mNormal = new Geometry::Vector3[mesh.mSubMesh[i].mVertexBuffer->mVertexCount]; mSubMesh[i].mVertexBuffer->mTexCoords = new Geometry::Vector2[mesh.mSubMesh[i].mVertexBuffer->mVertexCount]; mSubMesh[i].mVertexBuffer->mVertexCount = mesh.mSubMesh[i].mVertexBuffer->mVertexCount; mSubMesh[i].mVertexBuffer->mVertexInfo = mesh.mSubMesh[i].mVertexBuffer->mVertexInfo; mSubMesh[i].mType = mesh.mSubMesh[i].mType; strcpy(mSubMesh[i].mName,mesh.mSubMesh[i].mName); strcpy(mSubMesh[i].mMaterialName,mesh.mSubMesh[i].mMaterialName); if (mesh.mSubMesh[i].mSharedVertexBuffer && !copied) { mVertexBuffer = mSubMesh[i].mVertexBuffer; copied = true; } for ( size_t s = 0; s < mesh.mSubMesh[i].mVertexBuffer->mVertexCount; s++) { mSubMesh[i].mVertexBuffer->mPosition[s].x = mesh.mSubMesh[i].mVertexBuffer->mPosition[s].x; mSubMesh[i].mVertexBuffer->mPosition[s].y = mesh.mSubMesh[i].mVertexBuffer->mPosition[s].y; mSubMesh[i].mVertexBuffer->mPosition[s].z = mesh.mSubMesh[i].mVertexBuffer->mPosition[s].z; if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_NORMAL) { mSubMesh[i].mVertexBuffer->mNormal[s].x = mesh.mSubMesh[i].mVertexBuffer->mNormal[s].x; mSubMesh[i].mVertexBuffer->mNormal[s].y = mesh.mSubMesh[i].mVertexBuffer->mNormal[s].y; mSubMesh[i].mVertexBuffer->mNormal[s].z = mesh.mSubMesh[i].mVertexBuffer->mNormal[s].z; } if (mesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_TEXCOORDS) { mSubMesh[i].mVertexBuffer->mTexCoords[s].x = mesh.mSubMesh[i].mVertexBuffer->mTexCoords[s].x; mSubMesh[i].mVertexBuffer->mTexCoords[s].y = mesh.mSubMesh[i].mVertexBuffer->mTexCoords[s].y; } } // Copy indices. mSubMesh[i].mIndexCount = mesh.mSubMesh[i].mIndexCount; mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; memcpy( mSubMesh[i].mIndex, mesh.mSubMesh[i].mIndex, mesh.mSubMesh[i].mIndexCount*sizeof(Geometry::Index)); // Copy strips. __w64 offset = 0; mSubMesh[i].mStripCount = mesh.mSubMesh[i].mStripCount; if (mesh.mSubMesh[i].mStripCount > 0) { mSubMesh[i].mStrip = new Index*[mesh.mSubMesh[i].mStripCount]; offset = &(mSubMesh[i].mIndex[0]) - &(mesh.mSubMesh[i].mIndex[0]); for (size_t j = 0; j < mesh.mSubMesh[i].mStripCount; j++) { mSubMesh[i].mStrip[j] = mesh.mSubMesh[i].mStrip[j] + offset; } } // Copy submesh bones. if (!mesh.mSubMesh[i].mBones.empty()) { for (unsigned int j = 0; j < mesh.mSubMesh[i].mBones.size(); j++) { mSubMesh[i].mBones.push_back(mesh.mSubMesh[i].mBones[j]); } } } // Copy skeleton name. if (mesh.hasSkeleton) { hasSkeleton = true; strcpy(mSkeletonName, mesh.mSkeletonName); } // Copy mesh bones. if (!mesh.mBones.empty()) { for (unsigned int j = 0; j < mesh.mBones.size(); j++) { mBones.push_back(mesh.mBones[j]); } } return *this; } //------------------------------------------------------------------------- // Load mesh. //------------------------------------------------------------------------- void Mesh::Load(Serializer &s) { bool sharedVertexBuffer = false; // Clear Data. delete [] mSubMesh; mSubMesh = 0; delete mVertexBuffer; mVertexBuffer = 0; mSubMeshCount = 0; s.ReadArray(&sharedVertexBuffer,1); if (sharedVertexBuffer) { mVertexBuffer = new VertexBuffer; mVertexBuffer->Load(s); } s.ReadArray(&mSubMeshCount, 1); mSubMesh = new SubMesh[mSubMeshCount]; for(size_t i = 0; i < mSubMeshCount; i++) { mSubMesh[i].Load(s); if (mSubMesh[i].mSharedVertexBuffer && sharedVertexBuffer) { mSubMesh[i].mVertexBuffer = mVertexBuffer; } } } //------------------------------------------------------------------------- // Save mesh. //------------------------------------------------------------------------- void Mesh::Save(Serializer &s) { bool sharedVertexBuffer = (mVertexBuffer != 0); s.WriteArray(&sharedVertexBuffer, 1); if (sharedVertexBuffer) { mVertexBuffer->Save(s); } s.WriteArray(&mSubMeshCount,1); for(size_t i = 0; i < mSubMeshCount; i++) { mSubMesh[i].Save(s); } } //------------------------------------------------------------------------- // Export to obj mesh. //------------------------------------------------------------------------- void Mesh::exportToOBJ(char *fileName) { size_t vertex_count; vertex_count = 0; std::ofstream obj(fileName); obj << "begin" << std::endl; for (size_t j = 0; j < mVertexBuffer->mVertexCount; j++) { obj << "v " << mVertexBuffer->mPosition[j].x << " " << mVertexBuffer->mPosition[j].y << " " << mVertexBuffer->mPosition[j].z << " " << std::endl; } // Vertices. for (size_t i = 0; i < mSubMeshCount; i++) { if (!mSubMesh[i].mSharedVertexBuffer) { for (size_t j = 0; j < mSubMesh[i].mVertexBuffer->mVertexCount; j++) { obj << "v " << mSubMesh[i].mVertexBuffer->mPosition[j].x << " " << mSubMesh[i].mVertexBuffer->mPosition[j].y << " " << mSubMesh[i].mVertexBuffer->mPosition[j].z << " " << std::endl; } } } // Normals. for (size_t j = 0; j < mVertexBuffer->mVertexCount; j++) { obj << "vn " << mVertexBuffer->mNormal[j].x << " " << mVertexBuffer->mNormal[j].y << " " << mVertexBuffer->mNormal[j].z << " " << std::endl; } for (size_t i = 0; i < mSubMeshCount; i++) { if (!mSubMesh[i].mSharedVertexBuffer) { for (size_t j = 0; j < mSubMesh[i].mVertexBuffer->mVertexCount; j++) { obj << "vn " << mSubMesh[i].mVertexBuffer->mNormal[j].x << " " << mSubMesh[i].mVertexBuffer->mNormal[j].y << " " << mSubMesh[i].mVertexBuffer->mNormal[j].z << " " << std::endl; } } } // tex coords. for (size_t j = 0; j < mVertexBuffer->mVertexCount; j++) { obj << "vt " << mVertexBuffer->mTexCoords[j].x << " " << mVertexBuffer->mTexCoords[j].y << " " << std::endl; } for (size_t i = 0; i < mSubMeshCount; i++) { if (!mSubMesh[i].mSharedVertexBuffer) { for (size_t j = 0; j < mSubMesh[i].mVertexBuffer->mVertexCount; j++) { obj << "vt " << mSubMesh[i].mVertexBuffer->mTexCoords[j].x << " " << mSubMesh[i].mVertexBuffer->mTexCoords[j].y << " " << std::endl; } } } // Faces. for (size_t i = 0; i < mSubMeshCount; i++) { for (size_t j = 0; j < mSubMesh[i].mIndexCount; j = j + 3) { int a = mSubMesh[i].mIndex[j] + 1 + vertex_count; int b = mSubMesh[i].mIndex[j+1] + 1 + vertex_count; int c = mSubMesh[i].mIndex[j+2] + 1 + vertex_count; obj << "f " << a << "/" << a << "/" << a << " " << b << "/" << b << "/" << b << " " << c << "/" << c << "/" << c << " " << std::endl; } vertex_count += mSubMesh[i].mVertexBuffer->mVertexCount; } obj << "end" << std::endl; obj.close(); } //------------------------------------------------------------------------- // Transform to shared vertex mesh. //------------------------------------------------------------------------- Mesh *Mesh::toSharedVertex() { // Move all vertex to the shared vertex buffer. Mesh *mesh = new Mesh(); if (mSubMesh[0].mSharedVertexBuffer) { *mesh = *this; return mesh; } mesh->mVertexBuffer = new VertexBuffer(); mesh->mSubMeshCount = mSubMeshCount; mesh->mSubMesh = new SubMesh[mSubMeshCount]; // Fill up bounding box settings. mesh->mMeshBounds.maxX = mMeshBounds.maxX; mesh->mMeshBounds.maxY = mMeshBounds.maxY; mesh->mMeshBounds.maxZ = mMeshBounds.maxZ; mesh->mMeshBounds.minX = mMeshBounds.minX; mesh->mMeshBounds.minY = mMeshBounds.minY; mesh->mMeshBounds.minZ = mMeshBounds.minZ; mesh->mMeshBounds.radius = mMeshBounds.radius; mesh->mMeshBounds.scaleFactor = mMeshBounds.scaleFactor; // construcción de los submeshes long int acumVerts = 0; for (size_t i = 0; i < mesh->mSubMeshCount; i++) { mesh->mSubMesh[i].mSharedVertexBuffer = true; mesh->mSubMesh[i].mVertexBuffer = mesh->mVertexBuffer; mesh->mSubMesh[i].mStripCount = 0; mesh->mSubMesh[i].mStrip = NULL; mesh->mSubMesh[i].mType = mSubMesh[i].mType; strcpy(mesh->mSubMesh[i].mName,mSubMesh[i].mName); strcpy(mesh->mSubMesh[i].mMaterialName,mSubMesh[i].mMaterialName); // Copy indices. mesh->mSubMesh[i].mIndexCount = mSubMesh[i].mIndexCount; mesh->mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; for (size_t j = 0; j < mSubMesh[i].mIndexCount; j++) { mesh->mSubMesh[i].mIndex[j] = mSubMesh[i].mIndex[j]+acumVerts; } acumVerts += long(mSubMesh[i].mVertexBuffer->mVertexCount); // Copy strips. int offset = 0; mesh->mSubMesh[i].mStripCount = mSubMesh[i].mStripCount; if (mSubMesh[i].mStripCount > 0) { mesh->mSubMesh[i].mStrip = new Index*[mSubMesh[i].mStripCount]; offset = int(&(mesh->mSubMesh[i].mIndex[0]) - &(mSubMesh[i].mIndex[0])); for (size_t j = 0; j < mSubMesh[i].mStripCount; j++) { mesh->mSubMesh[i].mStrip[j] = mSubMesh[i].mStrip[j] + offset; } } } mesh->mVertexBuffer->mVertexCount = acumVerts; mesh->mVertexBuffer->mVertexInfo = mSubMesh[0].mVertexBuffer->mVertexInfo; mesh->mVertexBuffer->mPosition = new Vector3[mesh->mVertexBuffer->mVertexCount]; mesh->mVertexBuffer->mNormal = new Vector3[mesh->mVertexBuffer->mVertexCount]; mesh->mVertexBuffer->mTexCoords = new Vector2[mesh->mVertexBuffer->mVertexCount]; acumVerts = 0; size_t newIndex; for (size_t i = 0; i < mSubMeshCount; i++) { for (size_t j = 0; j < mSubMesh[i].mVertexBuffer->mVertexCount; j++) { newIndex = acumVerts + j; mesh->mVertexBuffer-> mPosition[newIndex].x = mSubMesh[i].mVertexBuffer-> mPosition[j].x; mesh->mVertexBuffer-> mPosition[newIndex].y = mSubMesh[i].mVertexBuffer-> mPosition[j].y; mesh->mVertexBuffer-> mPosition[newIndex].z = mSubMesh[i].mVertexBuffer-> mPosition[j].z; mesh->mVertexBuffer-> mNormal[newIndex].x = mSubMesh[i].mVertexBuffer-> mNormal[j].x; mesh->mVertexBuffer-> mNormal[newIndex].y = mSubMesh[i].mVertexBuffer-> mNormal[j].y; mesh->mVertexBuffer-> mNormal[newIndex].z = mSubMesh[i].mVertexBuffer-> mNormal[j].z; mesh->mVertexBuffer-> mTexCoords[newIndex].x = mSubMesh[i].mVertexBuffer-> mTexCoords[j].x; mesh->mVertexBuffer-> mTexCoords[newIndex].y = mSubMesh[i].mVertexBuffer-> mTexCoords[j].y; } // Shared bones. if (!mSubMesh[i].mBones.empty()) { for (unsigned int j = 0; j < mSubMesh[i].mBones.size(); j++) { mesh->mBones.push_back(mSubMesh[i].mBones[j]); mesh->mBones.back().vertexIndex += acumVerts; } } acumVerts += long(mSubMesh[i].mVertexBuffer->mVertexCount); } // Copy skeleton name. if (hasSkeleton) { mesh->hasSkeleton = true; strcpy(mesh->mSkeletonName,mSkeletonName); } // Copy mesh bones. if (!mBones.empty()) { for (unsigned int j = 0; j < mBones.size(); j++) { mesh->mBones.push_back(mBones[j]); } } return mesh; }