| 1 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
| 2 | // submesh.cpp | 
|---|
| 3 | // Author     : Francesco Giordana | 
|---|
| 4 | // Start Date : January 13, 2005 | 
|---|
| 5 | // Copyright  : (C) 2006 by Francesco Giordana | 
|---|
| 6 | // Email      : fra.giordana@tiscali.it | 
|---|
| 7 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
| 8 |  | 
|---|
| 9 | /********************************************************************************* | 
|---|
| 10 | *                                                                                * | 
|---|
| 11 | *   This program is free software; you can redistribute it and/or modify         * | 
|---|
| 12 | *   it under the terms of the GNU Lesser General Public License as published by  * | 
|---|
| 13 | *   the Free Software Foundation; either version 2 of the License, or            * | 
|---|
| 14 | *   (at your option) any later version.                                          * | 
|---|
| 15 | *                                                                                * | 
|---|
| 16 | **********************************************************************************/ | 
|---|
| 17 |  | 
|---|
| 18 | #include "submesh.h" | 
|---|
| 19 |  | 
|---|
| 20 | namespace OgreMayaExporter | 
|---|
| 21 | { | 
|---|
| 22 |         /***** Class Submesh *****/ | 
|---|
| 23 |         // constructor | 
|---|
| 24 |         Submesh::Submesh(const MString& name) | 
|---|
| 25 |         { | 
|---|
| 26 |                 m_pBlendShape = NULL; | 
|---|
| 27 |                 clear(); | 
|---|
| 28 |                 m_name = name; | 
|---|
| 29 |         } | 
|---|
| 30 |  | 
|---|
| 31 |         // destructor | 
|---|
| 32 |         Submesh::~Submesh() | 
|---|
| 33 |         { | 
|---|
| 34 |                 clear(); | 
|---|
| 35 |         } | 
|---|
| 36 |  | 
|---|
| 37 |         // clear data | 
|---|
| 38 |         void Submesh::clear() | 
|---|
| 39 |         { | 
|---|
| 40 |                 m_name = ""; | 
|---|
| 41 |                 m_numTriangles = 0; | 
|---|
| 42 |                 m_pMaterial = NULL; | 
|---|
| 43 |                 m_vertices.clear(); | 
|---|
| 44 |                 m_faces.clear(); | 
|---|
| 45 |                 m_uvsets.clear(); | 
|---|
| 46 |                 m_use32bitIndexes = false; | 
|---|
| 47 |                 if (m_pBlendShape) | 
|---|
| 48 |                         delete m_pBlendShape; | 
|---|
| 49 |                 m_pBlendShape = NULL; | 
|---|
| 50 |         } | 
|---|
| 51 |  | 
|---|
| 52 |         // return number of triangles composing the mesh | 
|---|
| 53 |         long Submesh::numTriangles() | 
|---|
| 54 |         { | 
|---|
| 55 |                 return m_numTriangles; | 
|---|
| 56 |         } | 
|---|
| 57 |  | 
|---|
| 58 |         // return number of vertices composing the mesh | 
|---|
| 59 |         long Submesh::numVertices() | 
|---|
| 60 |         { | 
|---|
| 61 |                 return m_numVertices; | 
|---|
| 62 |         } | 
|---|
| 63 |  | 
|---|
| 64 |         // return submesh name | 
|---|
| 65 |         MString& Submesh::name() | 
|---|
| 66 |         { | 
|---|
| 67 |                 return m_name; | 
|---|
| 68 |         } | 
|---|
| 69 |  | 
|---|
| 70 | /***** load data *****/ | 
|---|
| 71 |         MStatus Submesh::loadMaterial(MObject& shader,MStringArray& uvsets,ParamList& params) | 
|---|
| 72 |         { | 
|---|
| 73 |                 int i; | 
|---|
| 74 |                 MPlug plug; | 
|---|
| 75 |                 MPlugArray srcplugarray; | 
|---|
| 76 |                 bool foundShader = false; | 
|---|
| 77 |                 MStatus stat; | 
|---|
| 78 |                 MFnDependencyNode* pShader; | 
|---|
| 79 |                 //get shader from shading group | 
|---|
| 80 |                 MFnDependencyNode shadingGroup(shader); | 
|---|
| 81 |                 plug = shadingGroup.findPlug("surfaceShader"); | 
|---|
| 82 |                 plug.connectedTo(srcplugarray,true,false,&stat); | 
|---|
| 83 |                 for (i=0; i<srcplugarray.length() && !foundShader; i++) | 
|---|
| 84 |                 { | 
|---|
| 85 |                         if (srcplugarray[i].node().hasFn(MFn::kLambert) || srcplugarray[i].node().hasFn(MFn::kSurfaceShader) ||  | 
|---|
| 86 |                                 srcplugarray[i].node().hasFn(MFn::kPluginHwShaderNode) ) | 
|---|
| 87 |                         { | 
|---|
| 88 |                                 pShader = new MFnDependencyNode(srcplugarray[i].node()); | 
|---|
| 89 |                                 foundShader = true; | 
|---|
| 90 |                         } | 
|---|
| 91 |                 } | 
|---|
| 92 |                 if (foundShader) | 
|---|
| 93 |                 { | 
|---|
| 94 |                         std::cout << "Found material: " << pShader->name().asChar() << "\n"; | 
|---|
| 95 |                         std::cout.flush(); | 
|---|
| 96 |                         //check if this material has already been created | 
|---|
| 97 |                         //fix material name, adding the requested prefix | 
|---|
| 98 |                         MString tmpStr = params.matPrefix; | 
|---|
| 99 |                         if (tmpStr != "") | 
|---|
| 100 |                                 tmpStr += "/"; | 
|---|
| 101 |                         tmpStr += pShader->name(); | 
|---|
| 102 |                         MStringArray tmpStrArray; | 
|---|
| 103 |                         tmpStr.split(':',tmpStrArray); | 
|---|
| 104 |                         MString name = ""; | 
|---|
| 105 |                         for (i=0; i<tmpStrArray.length(); i++) | 
|---|
| 106 |                         { | 
|---|
| 107 |                                 name += tmpStrArray[i]; | 
|---|
| 108 |                                 if (i < tmpStrArray.length()-1) | 
|---|
| 109 |                                         name += "_"; | 
|---|
| 110 |                         } | 
|---|
| 111 |                         Material* pMaterial = MaterialSet::getSingleton().getMaterial(name); | 
|---|
| 112 |                         //if the material has already been created, update the pointer | 
|---|
| 113 |                         if (pMaterial) | 
|---|
| 114 |                                 m_pMaterial = pMaterial; | 
|---|
| 115 |                         //else create it and add it to the material set | 
|---|
| 116 |                         else | 
|---|
| 117 |                         { | 
|---|
| 118 |                                 pMaterial = new Material(); | 
|---|
| 119 |                                 pMaterial->load(pShader,uvsets,params); | 
|---|
| 120 |                                 m_pMaterial = pMaterial; | 
|---|
| 121 |                                 MaterialSet::getSingleton().addMaterial(pMaterial); | 
|---|
| 122 |                         } | 
|---|
| 123 |                         //delete temporary shader | 
|---|
| 124 |                         delete pShader; | 
|---|
| 125 |                 } | 
|---|
| 126 |                 else | 
|---|
| 127 |                 { | 
|---|
| 128 |                         std::cout << "Unsupported material, replacing with default lambert\n"; | 
|---|
| 129 |                         std::cout.flush(); | 
|---|
| 130 |                         m_pMaterial = MaterialSet::getSingleton().getDefaultMaterial(); | 
|---|
| 131 |                 } | 
|---|
| 132 |                  | 
|---|
| 133 |                 //loading complete | 
|---|
| 134 |                 return MS::kSuccess; | 
|---|
| 135 |         } | 
|---|
| 136 |  | 
|---|
| 137 |         MStatus Submesh::load(const MDagPath& dag,std::vector<face>& faces, std::vector<vertexInfo>& vertInfo, MPointArray& points,  | 
|---|
| 138 |                 MFloatVectorArray& normals, MStringArray& texcoordsets,ParamList& params,bool opposite) | 
|---|
| 139 |         { | 
|---|
| 140 |                 //save the dag path of the maya node from which this submesh will be created | 
|---|
| 141 |                 m_dagPath = dag; | 
|---|
| 142 |                 //create the mesh Fn | 
|---|
| 143 |                 MFnMesh mesh(dag); | 
|---|
| 144 |                 int i,j,k; | 
|---|
| 145 |                 std::cout << "Loading submesh associated to material: " << m_pMaterial->name().asChar() << "..."; | 
|---|
| 146 |                 std::cout.flush(); | 
|---|
| 147 |                 //save uvsets info | 
|---|
| 148 |                 for (i=m_uvsets.size(); i<texcoordsets.length(); i++) | 
|---|
| 149 |                 { | 
|---|
| 150 |                         uvset uv; | 
|---|
| 151 |                         uv.size = 2; | 
|---|
| 152 |                         m_uvsets.push_back(uv); | 
|---|
| 153 |                 } | 
|---|
| 154 |                 //iterate over faces array, to retrieve vertices info | 
|---|
| 155 |                 for (i=0; i<faces.size(); i++) | 
|---|
| 156 |                 { | 
|---|
| 157 |                         face newFace; | 
|---|
| 158 |                         // if we are using shared geometry, indexes refer to the vertex buffer of the whole mesh | 
|---|
| 159 |                         if (params.useSharedGeom) | 
|---|
| 160 |                         { | 
|---|
| 161 |                                 if(opposite) | 
|---|
| 162 |                                 {       // reverse order of face vertices for correct culling | 
|---|
| 163 |                                         newFace.v[0] = faces[i].v[2]; | 
|---|
| 164 |                                         newFace.v[1] = faces[i].v[1]; | 
|---|
| 165 |                                         newFace.v[2] = faces[i].v[0]; | 
|---|
| 166 |                                 } | 
|---|
| 167 |                                 else | 
|---|
| 168 |                                 { | 
|---|
| 169 |                                         newFace.v[0] = faces[i].v[0]; | 
|---|
| 170 |                                         newFace.v[1] = faces[i].v[1]; | 
|---|
| 171 |                                         newFace.v[2] = faces[i].v[2]; | 
|---|
| 172 |                                 } | 
|---|
| 173 |                         } | 
|---|
| 174 |                         // otherwise we create a vertex buffer for this submesh | 
|---|
| 175 |                         else | 
|---|
| 176 |                         {       // faces are triangles, so retrieve index of the three vertices | 
|---|
| 177 |                                 for (j=0; j<3; j++) | 
|---|
| 178 |                                 { | 
|---|
| 179 |                                         vertex v; | 
|---|
| 180 |                                         vertexInfo vInfo = vertInfo[faces[i].v[j]]; | 
|---|
| 181 |                                         // save vertex coordinates (rescale to desired length unit) | 
|---|
| 182 |                                         MPoint point = points[vInfo.pointIdx] * params.lum; | 
|---|
| 183 |                                         if (fabs(point.x) < PRECISION) | 
|---|
| 184 |                                                 point.x = 0; | 
|---|
| 185 |                                         if (fabs(point.y) < PRECISION) | 
|---|
| 186 |                                                 point.y = 0; | 
|---|
| 187 |                                         if (fabs(point.z) < PRECISION) | 
|---|
| 188 |                                                 point.z = 0; | 
|---|
| 189 |                                         v.x = point.x; | 
|---|
| 190 |                                         v.y = point.y; | 
|---|
| 191 |                                         v.z = point.z; | 
|---|
| 192 |                                         // save vertex normal | 
|---|
| 193 |                                         MFloatVector normal = normals[vInfo.normalIdx]; | 
|---|
| 194 |                                         if (fabs(normal.x) < PRECISION) | 
|---|
| 195 |                                                 normal.x = 0; | 
|---|
| 196 |                                         if (fabs(normal.y) < PRECISION) | 
|---|
| 197 |                                                 normal.y = 0; | 
|---|
| 198 |                                         if (fabs(normal.z) < PRECISION) | 
|---|
| 199 |                                                 normal.z = 0; | 
|---|
| 200 |                                         if (opposite) | 
|---|
| 201 |                                         { | 
|---|
| 202 |                                                 v.n.x = -normal.x; | 
|---|
| 203 |                                                 v.n.y = -normal.y; | 
|---|
| 204 |                                                 v.n.z = -normal.z; | 
|---|
| 205 |                                         } | 
|---|
| 206 |                                         else | 
|---|
| 207 |                                         { | 
|---|
| 208 |                                                 v.n.x = normal.x; | 
|---|
| 209 |                                                 v.n.y = normal.y; | 
|---|
| 210 |                                                 v.n.z = normal.z; | 
|---|
| 211 |                                         } | 
|---|
| 212 |                                         v.n.normalize(); | 
|---|
| 213 |                                         // save vertex color | 
|---|
| 214 |                                         v.r = vInfo.r; | 
|---|
| 215 |                                         v.g = vInfo.g; | 
|---|
| 216 |                                         v.b = vInfo.b; | 
|---|
| 217 |                                         v.a = vInfo.a; | 
|---|
| 218 |                                         // save vertex bone assignements | 
|---|
| 219 |                                         for (k=0; k<vInfo.vba.size(); k++) | 
|---|
| 220 |                                         { | 
|---|
| 221 |                                                 vba newVba; | 
|---|
| 222 |                                                 newVba.jointIdx = vInfo.jointIds[k]; | 
|---|
| 223 |                                                 newVba.weight = vInfo.vba[k]; | 
|---|
| 224 |                                                 v.vbas.push_back(newVba); | 
|---|
| 225 |                                         } | 
|---|
| 226 |                                         // save texture coordinates | 
|---|
| 227 |                                         for (k=0; k<vInfo.u.size(); k++) | 
|---|
| 228 |                                         { | 
|---|
| 229 |                                                 texcoords newTexCoords; | 
|---|
| 230 |                                                 newTexCoords.u = vInfo.u[k]; | 
|---|
| 231 |                                                 newTexCoords.v = vInfo.v[k]; | 
|---|
| 232 |                                                 newTexCoords.w = 0; | 
|---|
| 233 |                                                 v.texcoords.push_back(newTexCoords); | 
|---|
| 234 |                                         } | 
|---|
| 235 |                                         // save vertex index in maya mesh, to retrieve future positions of the same vertex | 
|---|
| 236 |                                         v.index = vInfo.pointIdx; | 
|---|
| 237 |                                         // add newly created vertex to vertex list | 
|---|
| 238 |                                         m_vertices.push_back(v); | 
|---|
| 239 |                                         if (opposite)   // reverse order of face vertices to get correct culling | 
|---|
| 240 |                                                 newFace.v[2-j] = m_vertices.size() - 1; | 
|---|
| 241 |                                         else | 
|---|
| 242 |                                                 newFace.v[j] = m_vertices.size() - 1; | 
|---|
| 243 |                                 } | 
|---|
| 244 |                         } | 
|---|
| 245 |                         m_faces.push_back(newFace); | 
|---|
| 246 |                 } | 
|---|
| 247 |                 // set use32bitIndexes flag | 
|---|
| 248 |                 if (params.useSharedGeom || (m_vertices.size() > 65535) || (m_faces.size() > 65535)) | 
|---|
| 249 |                         m_use32bitIndexes = true; | 
|---|
| 250 |                 else | 
|---|
| 251 |                         m_use32bitIndexes = false; | 
|---|
| 252 |                 // get submesh bounding box | 
|---|
| 253 |                 MPoint min = mesh.boundingBox().min(); | 
|---|
| 254 |                 MPoint max = mesh.boundingBox().max(); | 
|---|
| 255 |                 MBoundingBox bbox(min,max); | 
|---|
| 256 |                 if (params.exportWorldCoords) | 
|---|
| 257 |                         bbox.transformUsing(dag.inclusiveMatrix()); | 
|---|
| 258 |                 min = bbox.min() * params.lum; | 
|---|
| 259 |                 max = bbox.max() * params.lum; | 
|---|
| 260 |                 MBoundingBox newbbox(min,max); | 
|---|
| 261 |                 m_boundingBox = newbbox; | 
|---|
| 262 |                 // add submesh pointer to parameters list | 
|---|
| 263 |                 params.loadedSubmeshes.push_back(this); | 
|---|
| 264 |  | 
|---|
| 265 |                 std::cout << "DONE\n"; | 
|---|
| 266 |                 std::cout.flush(); | 
|---|
| 267 |                 return MS::kSuccess; | 
|---|
| 268 |         } | 
|---|
| 269 |  | 
|---|
| 270 |  | 
|---|
| 271 |         // Load a keyframe for this submesh | 
|---|
| 272 |         MStatus Submesh::loadKeyframe(Track& t,float time,ParamList& params) | 
|---|
| 273 |         { | 
|---|
| 274 |                 int i; | 
|---|
| 275 |                 // create a new keyframe | 
|---|
| 276 |                 vertexKeyframe k; | 
|---|
| 277 |                 // set keyframe time | 
|---|
| 278 |                 k.time = time; | 
|---|
| 279 |                 // get the mesh Fn | 
|---|
| 280 |                 MFnMesh mesh(m_dagPath); | 
|---|
| 281 |                 // get vertex positions | 
|---|
| 282 |                 MFloatPointArray points; | 
|---|
| 283 |                 if (params.exportWorldCoords) | 
|---|
| 284 |                         mesh.getPoints(points,MSpace::kWorld); | 
|---|
| 285 |                 else | 
|---|
| 286 |                         mesh.getPoints(points,MSpace::kObject); | 
|---|
| 287 |                 // calculate vertex offsets | 
|---|
| 288 |                 for (i=0; i<m_vertices.size(); i++) | 
|---|
| 289 |                 { | 
|---|
| 290 |                         vertexPosition pos; | 
|---|
| 291 |                         vertex v = m_vertices[i]; | 
|---|
| 292 |                         pos.x = points[v.index].x * params.lum; | 
|---|
| 293 |                         pos.y = points[v.index].y * params.lum; | 
|---|
| 294 |                         pos.z = points[v.index].z * params.lum; | 
|---|
| 295 |                         if (fabs(pos.x) < PRECISION) | 
|---|
| 296 |                                         pos.x = 0; | 
|---|
| 297 |                         if (fabs(pos.y) < PRECISION) | 
|---|
| 298 |                                 pos.y = 0; | 
|---|
| 299 |                         if (fabs(pos.z) < PRECISION) | 
|---|
| 300 |                                 pos.z = 0; | 
|---|
| 301 |                         k.positions.push_back(pos); | 
|---|
| 302 |                 } | 
|---|
| 303 |                 // add keyframe to given track | 
|---|
| 304 |                 t.addVertexKeyframe(k); | 
|---|
| 305 |                 if (params.vertBB) | 
|---|
| 306 |                 { | 
|---|
| 307 |                         // update bounding box | 
|---|
| 308 |                         MPoint min = mesh.boundingBox().min(); | 
|---|
| 309 |                         MPoint max = mesh.boundingBox().max(); | 
|---|
| 310 |                         MBoundingBox bbox(min,max); | 
|---|
| 311 |                         if (params.exportWorldCoords) | 
|---|
| 312 |                                 bbox.transformUsing(m_dagPath.inclusiveMatrix()); | 
|---|
| 313 |                         min = bbox.min() * params.lum; | 
|---|
| 314 |                         max = bbox.max() * params.lum; | 
|---|
| 315 |                         MBoundingBox newbbox(min,max); | 
|---|
| 316 |                         m_boundingBox.expand(newbbox); | 
|---|
| 317 |                 } | 
|---|
| 318 |                 // keyframe successfully loaded | 
|---|
| 319 |                 return MS::kSuccess; | 
|---|
| 320 |         } | 
|---|
| 321 |  | 
|---|
| 322 |  | 
|---|
| 323 |  | 
|---|
| 324 | /***** Export data *****/ | 
|---|
| 325 |         // Write submesh data to an Ogre compatible mesh | 
|---|
| 326 |         MStatus Submesh::createOgreSubmesh(Ogre::MeshPtr pMesh,const ParamList& params) | 
|---|
| 327 |         { | 
|---|
| 328 |                 int i,j; | 
|---|
| 329 |                 MStatus stat; | 
|---|
| 330 |                 // Create a new submesh | 
|---|
| 331 |                 Ogre::SubMesh* pSubmesh; | 
|---|
| 332 |                 if (m_name != "") | 
|---|
| 333 |                         pSubmesh = pMesh->createSubMesh(m_name.asChar()); | 
|---|
| 334 |                 else | 
|---|
| 335 |                         pSubmesh = pMesh->createSubMesh(); | 
|---|
| 336 |                 // Set material | 
|---|
| 337 |         pSubmesh->setMaterialName(m_pMaterial->name().asChar()); | 
|---|
| 338 |         // Set use shared geometry flag | 
|---|
| 339 |                 pSubmesh->useSharedVertices = params.useSharedGeom; | 
|---|
| 340 |                 // Create vertex data for current submesh | 
|---|
| 341 |                 pSubmesh->vertexData = new Ogre::VertexData(); | 
|---|
| 342 |         // Set number of indexes | 
|---|
| 343 |         pSubmesh->indexData->indexCount = 3*m_faces.size(); | 
|---|
| 344 |                 pSubmesh->vertexData->vertexCount = m_vertices.size(); | 
|---|
| 345 |                 // Check if we need to use 32 bit indexes | 
|---|
| 346 |                 bool use32BitIndexes = false; | 
|---|
| 347 |                 if (m_vertices.size() > 65536 || params.useSharedGeom) | 
|---|
| 348 |                 { | 
|---|
| 349 |                         use32BitIndexes = true; | 
|---|
| 350 |                 } | 
|---|
| 351 |                 // Create a new index buffer | 
|---|
| 352 |                 pSubmesh->indexData->indexBuffer =  | 
|---|
| 353 |                         Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( | 
|---|
| 354 |                                 use32BitIndexes ? Ogre::HardwareIndexBuffer::IT_32BIT : Ogre::HardwareIndexBuffer::IT_16BIT, | 
|---|
| 355 |                                 pSubmesh->indexData->indexCount, | 
|---|
| 356 |                                 Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); | 
|---|
| 357 |                 // Fill the index buffer with faces data | 
|---|
| 358 |                 if (use32BitIndexes) | 
|---|
| 359 |         { | 
|---|
| 360 |                         Ogre::uint32* pIdx = static_cast<Ogre::uint32*>( | 
|---|
| 361 |                                 pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); | 
|---|
| 362 |                         for (i=0; i<m_faces.size(); i++) | 
|---|
| 363 |                         { | 
|---|
| 364 |                                 *pIdx++ = static_cast<Ogre::uint32>(m_faces[i].v[0]); | 
|---|
| 365 |                                 *pIdx++ = static_cast<Ogre::uint32>(m_faces[i].v[1]); | 
|---|
| 366 |                                 *pIdx++ = static_cast<Ogre::uint32>(m_faces[i].v[2]); | 
|---|
| 367 |                         } | 
|---|
| 368 |                         pSubmesh->indexData->indexBuffer->unlock(); | 
|---|
| 369 |         } | 
|---|
| 370 |         else | 
|---|
| 371 |         { | 
|---|
| 372 |             Ogre::uint16* pIdx = static_cast<Ogre::uint16*>( | 
|---|
| 373 |                                 pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); | 
|---|
| 374 |             for (i=0; i<m_faces.size(); i++) | 
|---|
| 375 |                         { | 
|---|
| 376 |                                 *pIdx++ = static_cast<Ogre::uint16>(m_faces[i].v[0]); | 
|---|
| 377 |                                 *pIdx++ = static_cast<Ogre::uint16>(m_faces[i].v[1]); | 
|---|
| 378 |                                 *pIdx++ = static_cast<Ogre::uint16>(m_faces[i].v[2]); | 
|---|
| 379 |                         } | 
|---|
| 380 |                         pSubmesh->indexData->indexBuffer->unlock(); | 
|---|
| 381 |                 } | 
|---|
| 382 |                 // Define vertex declaration (only if we're not using shared geometry) | 
|---|
| 383 |                 if(!params.useSharedGeom) | 
|---|
| 384 |                 { | 
|---|
| 385 |                         Ogre::VertexDeclaration* pDecl = pSubmesh->vertexData->vertexDeclaration; | 
|---|
| 386 |                         unsigned buf = 0; | 
|---|
| 387 |                         size_t offset = 0; | 
|---|
| 388 |                         // Add vertex position | 
|---|
| 389 |                         pDecl->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); | 
|---|
| 390 |                         offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); | 
|---|
| 391 |                         // Add vertex normal | 
|---|
| 392 |                         if (params.exportVertNorm) | 
|---|
| 393 |                         { | 
|---|
| 394 |                                 pDecl->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); | 
|---|
| 395 |                                 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); | 
|---|
| 396 |                         } | 
|---|
| 397 |                         // Add vertex colour | 
|---|
| 398 |                         if(params.exportVertCol) | 
|---|
| 399 |                         { | 
|---|
| 400 |                                 pDecl->addElement(buf, offset, Ogre::VET_FLOAT4, Ogre::VES_DIFFUSE); | 
|---|
| 401 |                                 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT4); | 
|---|
| 402 |                         } | 
|---|
| 403 |                         // Add texture coordinates | 
|---|
| 404 |                         for (i=0; i<m_vertices[0].texcoords.size(); i++) | 
|---|
| 405 |                         { | 
|---|
| 406 |                                 Ogre::VertexElementType uvType = Ogre::VertexElement::multiplyTypeCount(Ogre::VET_FLOAT1, 2); | 
|---|
| 407 |                                 pDecl->addElement(buf, offset, uvType, Ogre::VES_TEXTURE_COORDINATES, i); | 
|---|
| 408 |                                 offset += Ogre::VertexElement::getTypeSize(uvType); | 
|---|
| 409 |                         } | 
|---|
| 410 |                         Ogre::VertexDeclaration* pOptimalDecl = pDecl->getAutoOrganisedDeclaration( | 
|---|
| 411 |                                 params.exportVBA,params.exportBlendShapes || params.exportVertAnims); | 
|---|
| 412 |                         // Fill the vertex buffer using the newly created vertex declaration | 
|---|
| 413 |                         stat = createOgreVertexBuffer(pSubmesh,pDecl,m_vertices); | 
|---|
| 414 |                         // Write vertex bone assignements list | 
|---|
| 415 |                         if (params.exportVBA) | 
|---|
| 416 |                         { | 
|---|
| 417 |                                 // Create a new vertex bone assignements list | 
|---|
| 418 |                                 Ogre::SubMesh::VertexBoneAssignmentList vbas; | 
|---|
| 419 |                                 // Scan list of shared geometry vertices | 
|---|
| 420 |                                 for (i=0; i<m_vertices.size(); i++) | 
|---|
| 421 |                                 { | 
|---|
| 422 |                                         vertex v = m_vertices[i]; | 
|---|
| 423 |                                         // Add all bone assignemnts for every vertex to the bone assignements list | 
|---|
| 424 |                                         for (j=0; j<v.vbas.size(); j++) | 
|---|
| 425 |                                         { | 
|---|
| 426 |                                                 Ogre::VertexBoneAssignment vba; | 
|---|
| 427 |                                                 vba.vertexIndex = i; | 
|---|
| 428 |                                                 vba.boneIndex = v.vbas[j].jointIdx; | 
|---|
| 429 |                                                 vba.weight = v.vbas[j].weight; | 
|---|
| 430 |                                                 vbas.insert(Ogre::SubMesh::VertexBoneAssignmentList::value_type(i, vba)); | 
|---|
| 431 |                                         } | 
|---|
| 432 |                                 } | 
|---|
| 433 |                                 // Rationalise the bone assignements list | 
|---|
| 434 |                                 pSubmesh->parent->_rationaliseBoneAssignments(pSubmesh->vertexData->vertexCount,vbas); | 
|---|
| 435 |                                 // Add bone assignements to the submesh | 
|---|
| 436 |                                 for (Ogre::SubMesh::VertexBoneAssignmentList::iterator bi = vbas.begin(); bi != vbas.end(); bi++) | 
|---|
| 437 |                                 { | 
|---|
| 438 |                                         pSubmesh->addBoneAssignment(bi->second); | 
|---|
| 439 |                                 } | 
|---|
| 440 |                                 pSubmesh->_compileBoneAssignments(); | 
|---|
| 441 |                         } | 
|---|
| 442 |                         pSubmesh->vertexData->reorganiseBuffers(pOptimalDecl); | 
|---|
| 443 |                 } | 
|---|
| 444 |                 return MS::kSuccess; | 
|---|
| 445 |         } | 
|---|
| 446 |  | 
|---|
| 447 |  | 
|---|
| 448 |         // Create an Ogre compatible vertex buffer | 
|---|
| 449 |         MStatus Submesh::createOgreVertexBuffer(Ogre::SubMesh* pSubmesh,Ogre::VertexDeclaration* pDecl,const std::vector<vertex>& vertices) | 
|---|
| 450 |         { | 
|---|
| 451 |                 Ogre::HardwareVertexBufferSharedPtr vbuf =  | 
|---|
| 452 |                         Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(pDecl->getVertexSize(0), | 
|---|
| 453 |                         pSubmesh->vertexData->vertexCount,  | 
|---|
| 454 |                         Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); | 
|---|
| 455 |                 pSubmesh->vertexData->vertexBufferBinding->setBinding(0, vbuf); | 
|---|
| 456 |                 size_t vertexSize = pDecl->getVertexSize(0); | 
|---|
| 457 |                 char* pBase = static_cast<char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); | 
|---|
| 458 |                 Ogre::VertexDeclaration::VertexElementList elems = pDecl->findElementsBySource(0); | 
|---|
| 459 |                 Ogre::VertexDeclaration::VertexElementList::iterator ei, eiend; | 
|---|
| 460 |                 eiend = elems.end(); | 
|---|
| 461 |                 float* pFloat; | 
|---|
| 462 |                 // Fill the vertex buffer with shared geometry data | 
|---|
| 463 |                 long vi; | 
|---|
| 464 |                 Ogre::ColourValue col; | 
|---|
| 465 |                 float ucoord, vcoord; | 
|---|
| 466 |                 for (vi=0; vi<vertices.size(); vi++) | 
|---|
| 467 |                 { | 
|---|
| 468 |                         int iTexCoord = 0; | 
|---|
| 469 |                         vertex v = vertices[vi]; | 
|---|
| 470 |                         for (ei = elems.begin(); ei != eiend; ++ei) | 
|---|
| 471 |                         { | 
|---|
| 472 |                                 Ogre::VertexElement& elem = *ei; | 
|---|
| 473 |                                 switch(elem.getSemantic()) | 
|---|
| 474 |                                 { | 
|---|
| 475 |                                 case Ogre::VES_POSITION: | 
|---|
| 476 |                                         elem.baseVertexPointerToElement(pBase, &pFloat); | 
|---|
| 477 |                                         *pFloat++ = v.x; | 
|---|
| 478 |                                         *pFloat++ = v.y; | 
|---|
| 479 |                                         *pFloat++ = v.z; | 
|---|
| 480 |                                         break; | 
|---|
| 481 |                                 case Ogre::VES_NORMAL: | 
|---|
| 482 |                                         elem.baseVertexPointerToElement(pBase, &pFloat); | 
|---|
| 483 |                                         *pFloat++ = v.n.x; | 
|---|
| 484 |                                         *pFloat++ = v.n.y; | 
|---|
| 485 |                                         *pFloat++ = v.n.z; | 
|---|
| 486 |                                         break; | 
|---|
| 487 |                                 case Ogre::VES_DIFFUSE: | 
|---|
| 488 |                                         elem.baseVertexPointerToElement(pBase, &pFloat); | 
|---|
| 489 |                                         *pFloat++ = v.r; | 
|---|
| 490 |                                         *pFloat++ = v.g; | 
|---|
| 491 |                                         *pFloat++ = v.b; | 
|---|
| 492 |                                         *pFloat++ = v.a; | 
|---|
| 493 |                                         break; | 
|---|
| 494 |                                 case Ogre::VES_TEXTURE_COORDINATES: | 
|---|
| 495 |                                         elem.baseVertexPointerToElement(pBase, &pFloat); | 
|---|
| 496 |                                         ucoord = v.texcoords[iTexCoord].u; | 
|---|
| 497 |                                         vcoord = v.texcoords[iTexCoord].v; | 
|---|
| 498 |                                         *pFloat++ = ucoord; | 
|---|
| 499 |                                         *pFloat++ = vcoord; | 
|---|
| 500 |                                         iTexCoord++; | 
|---|
| 501 |                                         break; | 
|---|
| 502 |                                 } | 
|---|
| 503 |                         } | 
|---|
| 504 |                         pBase += vertexSize; | 
|---|
| 505 |                 } | 
|---|
| 506 |                 vbuf->unlock(); | 
|---|
| 507 |                 return MS::kSuccess; | 
|---|
| 508 |         } | 
|---|
| 509 |  | 
|---|
| 510 | }; //end of namespace | 
|---|