//////////////////////////////////////////////////////////////////////////////// // submesh.cpp // Author : Francesco Giordana // Start Date : January 13, 2005 // Copyright : (C) 2006 by Francesco Giordana // Email : fra.giordana@tiscali.it //////////////////////////////////////////////////////////////////////////////// /********************************************************************************* * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * **********************************************************************************/ #include "submesh.h" namespace OgreMayaExporter { /***** Class Submesh *****/ // constructor Submesh::Submesh(const MString& name) { m_pBlendShape = NULL; clear(); m_name = name; } // destructor Submesh::~Submesh() { clear(); } // clear data void Submesh::clear() { m_name = ""; m_numTriangles = 0; m_pMaterial = NULL; m_vertices.clear(); m_faces.clear(); m_uvsets.clear(); m_use32bitIndexes = false; if (m_pBlendShape) delete m_pBlendShape; m_pBlendShape = NULL; } // return number of triangles composing the mesh long Submesh::numTriangles() { return m_numTriangles; } // return number of vertices composing the mesh long Submesh::numVertices() { return m_numVertices; } // return submesh name MString& Submesh::name() { return m_name; } /***** load data *****/ MStatus Submesh::loadMaterial(MObject& shader,MStringArray& uvsets,ParamList& params) { int i; MPlug plug; MPlugArray srcplugarray; bool foundShader = false; MStatus stat; MFnDependencyNode* pShader; //get shader from shading group MFnDependencyNode shadingGroup(shader); plug = shadingGroup.findPlug("surfaceShader"); plug.connectedTo(srcplugarray,true,false,&stat); for (i=0; iname().asChar() << "\n"; std::cout.flush(); //check if this material has already been created //fix material name, adding the requested prefix MString tmpStr = params.matPrefix; if (tmpStr != "") tmpStr += "/"; tmpStr += pShader->name(); MStringArray tmpStrArray; tmpStr.split(':',tmpStrArray); MString name = ""; for (i=0; iload(pShader,uvsets,params); m_pMaterial = pMaterial; MaterialSet::getSingleton().addMaterial(pMaterial); } //delete temporary shader delete pShader; } else { std::cout << "Unsupported material, replacing with default lambert\n"; std::cout.flush(); m_pMaterial = MaterialSet::getSingleton().getDefaultMaterial(); } //loading complete return MS::kSuccess; } MStatus Submesh::load(const MDagPath& dag,std::vector& faces, std::vector& vertInfo, MPointArray& points, MFloatVectorArray& normals, MStringArray& texcoordsets,ParamList& params,bool opposite) { //save the dag path of the maya node from which this submesh will be created m_dagPath = dag; //create the mesh Fn MFnMesh mesh(dag); int i,j,k; std::cout << "Loading submesh associated to material: " << m_pMaterial->name().asChar() << "..."; std::cout.flush(); //save uvsets info for (i=m_uvsets.size(); i 65535) || (m_faces.size() > 65535)) m_use32bitIndexes = true; else m_use32bitIndexes = false; // get submesh bounding box MPoint min = mesh.boundingBox().min(); MPoint max = mesh.boundingBox().max(); MBoundingBox bbox(min,max); if (params.exportWorldCoords) bbox.transformUsing(dag.inclusiveMatrix()); min = bbox.min() * params.lum; max = bbox.max() * params.lum; MBoundingBox newbbox(min,max); m_boundingBox = newbbox; // add submesh pointer to parameters list params.loadedSubmeshes.push_back(this); std::cout << "DONE\n"; std::cout.flush(); return MS::kSuccess; } // Load a keyframe for this submesh MStatus Submesh::loadKeyframe(Track& t,float time,ParamList& params) { int i; // create a new keyframe vertexKeyframe k; // set keyframe time k.time = time; // get the mesh Fn MFnMesh mesh(m_dagPath); // get vertex positions MFloatPointArray points; if (params.exportWorldCoords) mesh.getPoints(points,MSpace::kWorld); else mesh.getPoints(points,MSpace::kObject); // calculate vertex offsets for (i=0; icreateSubMesh(m_name.asChar()); else pSubmesh = pMesh->createSubMesh(); // Set material pSubmesh->setMaterialName(m_pMaterial->name().asChar()); // Set use shared geometry flag pSubmesh->useSharedVertices = params.useSharedGeom; // Create vertex data for current submesh pSubmesh->vertexData = new Ogre::VertexData(); // Set number of indexes pSubmesh->indexData->indexCount = 3*m_faces.size(); pSubmesh->vertexData->vertexCount = m_vertices.size(); // Check if we need to use 32 bit indexes bool use32BitIndexes = false; if (m_vertices.size() > 65536 || params.useSharedGeom) { use32BitIndexes = true; } // Create a new index buffer pSubmesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( use32BitIndexes ? Ogre::HardwareIndexBuffer::IT_32BIT : Ogre::HardwareIndexBuffer::IT_16BIT, pSubmesh->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Fill the index buffer with faces data if (use32BitIndexes) { Ogre::uint32* pIdx = static_cast( pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (i=0; i(m_faces[i].v[0]); *pIdx++ = static_cast(m_faces[i].v[1]); *pIdx++ = static_cast(m_faces[i].v[2]); } pSubmesh->indexData->indexBuffer->unlock(); } else { Ogre::uint16* pIdx = static_cast( pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (i=0; i(m_faces[i].v[0]); *pIdx++ = static_cast(m_faces[i].v[1]); *pIdx++ = static_cast(m_faces[i].v[2]); } pSubmesh->indexData->indexBuffer->unlock(); } // Define vertex declaration (only if we're not using shared geometry) if(!params.useSharedGeom) { Ogre::VertexDeclaration* pDecl = pSubmesh->vertexData->vertexDeclaration; unsigned buf = 0; size_t offset = 0; // Add vertex position pDecl->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // Add vertex normal if (params.exportVertNorm) { pDecl->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); } // Add vertex colour if(params.exportVertCol) { pDecl->addElement(buf, offset, Ogre::VET_FLOAT4, Ogre::VES_DIFFUSE); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT4); } // Add texture coordinates for (i=0; iaddElement(buf, offset, uvType, Ogre::VES_TEXTURE_COORDINATES, i); offset += Ogre::VertexElement::getTypeSize(uvType); } Ogre::VertexDeclaration* pOptimalDecl = pDecl->getAutoOrganisedDeclaration( params.exportVBA,params.exportBlendShapes || params.exportVertAnims); // Fill the vertex buffer using the newly created vertex declaration stat = createOgreVertexBuffer(pSubmesh,pDecl,m_vertices); // Write vertex bone assignements list if (params.exportVBA) { // Create a new vertex bone assignements list Ogre::SubMesh::VertexBoneAssignmentList vbas; // Scan list of shared geometry vertices for (i=0; iparent->_rationaliseBoneAssignments(pSubmesh->vertexData->vertexCount,vbas); // Add bone assignements to the submesh for (Ogre::SubMesh::VertexBoneAssignmentList::iterator bi = vbas.begin(); bi != vbas.end(); bi++) { pSubmesh->addBoneAssignment(bi->second); } pSubmesh->_compileBoneAssignments(); } pSubmesh->vertexData->reorganiseBuffers(pOptimalDecl); } return MS::kSuccess; } // Create an Ogre compatible vertex buffer MStatus Submesh::createOgreVertexBuffer(Ogre::SubMesh* pSubmesh,Ogre::VertexDeclaration* pDecl,const std::vector& vertices) { Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(pDecl->getVertexSize(0), pSubmesh->vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); pSubmesh->vertexData->vertexBufferBinding->setBinding(0, vbuf); size_t vertexSize = pDecl->getVertexSize(0); char* pBase = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); Ogre::VertexDeclaration::VertexElementList elems = pDecl->findElementsBySource(0); Ogre::VertexDeclaration::VertexElementList::iterator ei, eiend; eiend = elems.end(); float* pFloat; // Fill the vertex buffer with shared geometry data long vi; Ogre::ColourValue col; float ucoord, vcoord; for (vi=0; viunlock(); return MS::kSuccess; } }; //end of namespace