| 1 | /* | 
|---|
| 2 | ----------------------------------------------------------------------------- | 
|---|
| 3 | This source file is part of OGRE | 
|---|
| 4 |     (Object-oriented Graphics Rendering Engine) | 
|---|
| 5 | For the latest info, see http://www.ogre3d.org/ | 
|---|
| 6 |  | 
|---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd | 
|---|
| 8 | Also see acknowledgements in Readme.html | 
|---|
| 9 |  | 
|---|
| 10 | This program is free software; you can redistribute it and/or modify it under | 
|---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software | 
|---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later | 
|---|
| 13 | version. | 
|---|
| 14 |  | 
|---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | 
|---|
| 18 |  | 
|---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with | 
|---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 
|---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to | 
|---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. | 
|---|
| 23 |  | 
|---|
| 24 | You may alternatively use this source under the terms of a specific version of | 
|---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from | 
|---|
| 26 | Torus Knot Software Ltd. | 
|---|
| 27 | ----------------------------------------------------------------------------- | 
|---|
| 28 | */ | 
|---|
| 29 |  | 
|---|
| 30 |  | 
|---|
| 31 | #include "OgreXMLMeshSerializer.h" | 
|---|
| 32 | #include "OgreSubMesh.h" | 
|---|
| 33 | #include "OgreLogManager.h" | 
|---|
| 34 | #include "OgreSkeleton.h" | 
|---|
| 35 | #include "OgreStringConverter.h" | 
|---|
| 36 | #include "OgreHardwareBufferManager.h" | 
|---|
| 37 | #include "OgreException.h" | 
|---|
| 38 | #include "OgreAnimation.h" | 
|---|
| 39 | #include "OgreAnimationTrack.h" | 
|---|
| 40 | #include "OgreKeyFrame.h" | 
|---|
| 41 |  | 
|---|
| 42 | namespace Ogre { | 
|---|
| 43 |  | 
|---|
| 44 |     //--------------------------------------------------------------------- | 
|---|
| 45 |     XMLMeshSerializer::XMLMeshSerializer() | 
|---|
| 46 |     { | 
|---|
| 47 |     } | 
|---|
| 48 |     //--------------------------------------------------------------------- | 
|---|
| 49 |     XMLMeshSerializer::~XMLMeshSerializer() | 
|---|
| 50 |     { | 
|---|
| 51 |     } | 
|---|
| 52 |     //--------------------------------------------------------------------- | 
|---|
| 53 |     void XMLMeshSerializer::importMesh(const String& filename,  | 
|---|
| 54 |                 VertexElementType colourElementType, Mesh* pMesh) | 
|---|
| 55 |     { | 
|---|
| 56 |         LogManager::getSingleton().logMessage("XMLMeshSerializer reading mesh data from " + filename + "..."); | 
|---|
| 57 |         mpMesh = pMesh; | 
|---|
| 58 |                 mColourElementType = colourElementType; | 
|---|
| 59 |         mXMLDoc = new TiXmlDocument(filename); | 
|---|
| 60 |         mXMLDoc->LoadFile(); | 
|---|
| 61 |  | 
|---|
| 62 |         TiXmlElement* elem; | 
|---|
| 63 |  | 
|---|
| 64 |         TiXmlElement* rootElem = mXMLDoc->RootElement(); | 
|---|
| 65 |  | 
|---|
| 66 |         // shared geometry | 
|---|
| 67 |         elem = rootElem->FirstChildElement("sharedgeometry"); | 
|---|
| 68 |         if (elem) | 
|---|
| 69 |         { | 
|---|
| 70 |             const char *claimedVertexCount_ = elem->Attribute("vertexcount"); | 
|---|
| 71 |             if(!claimedVertexCount_ || StringConverter::parseInt(claimedVertexCount_) > 0) | 
|---|
| 72 |             { | 
|---|
| 73 |                 mpMesh->sharedVertexData = new VertexData(); | 
|---|
| 74 |                 readGeometry(elem, mpMesh->sharedVertexData); | 
|---|
| 75 |             } | 
|---|
| 76 |         } | 
|---|
| 77 |  | 
|---|
| 78 |         // submeshes | 
|---|
| 79 |         elem = rootElem->FirstChildElement("submeshes"); | 
|---|
| 80 |         if (elem) | 
|---|
| 81 |             readSubMeshes(elem); | 
|---|
| 82 |  | 
|---|
| 83 |         // skeleton link | 
|---|
| 84 |         elem = rootElem->FirstChildElement("skeletonlink"); | 
|---|
| 85 |         if (elem) | 
|---|
| 86 |             readSkeletonLink(elem); | 
|---|
| 87 |  | 
|---|
| 88 |         // bone assignments | 
|---|
| 89 |         elem = rootElem->FirstChildElement("boneassignments"); | 
|---|
| 90 |         if (elem) | 
|---|
| 91 |             readBoneAssignments(elem); | 
|---|
| 92 |  | 
|---|
| 93 |                 //Lod | 
|---|
| 94 |                 elem = rootElem->FirstChildElement("levelofdetail"); | 
|---|
| 95 |                 if (elem) | 
|---|
| 96 |                         readLodInfo(elem); | 
|---|
| 97 |  | 
|---|
| 98 |                 // submesh names | 
|---|
| 99 |                 elem = rootElem->FirstChildElement("submeshnames"); | 
|---|
| 100 |                 if (elem) | 
|---|
| 101 |                         readSubMeshNames(elem, mpMesh); | 
|---|
| 102 |  | 
|---|
| 103 |                 // submesh extremes | 
|---|
| 104 |                 elem = rootElem->FirstChildElement("extremes"); | 
|---|
| 105 |                 if (elem) | 
|---|
| 106 |                         readExtremes(elem, mpMesh); | 
|---|
| 107 |  | 
|---|
| 108 |                 // poses | 
|---|
| 109 |                 elem = rootElem->FirstChildElement("poses"); | 
|---|
| 110 |                 if (elem) | 
|---|
| 111 |                         readPoses(elem, mpMesh); | 
|---|
| 112 |  | 
|---|
| 113 |                 // animations | 
|---|
| 114 |                 elem = rootElem->FirstChildElement("animations"); | 
|---|
| 115 |                 if (elem) | 
|---|
| 116 |                         readAnimations(elem, mpMesh); | 
|---|
| 117 |  | 
|---|
| 118 |                 delete mXMLDoc; | 
|---|
| 119 |  | 
|---|
| 120 |         LogManager::getSingleton().logMessage("XMLMeshSerializer import successful."); | 
|---|
| 121 |          | 
|---|
| 122 |     } | 
|---|
| 123 |     //--------------------------------------------------------------------- | 
|---|
| 124 |     void XMLMeshSerializer::exportMesh(const Mesh* pMesh, const String& filename) | 
|---|
| 125 |     { | 
|---|
| 126 |         LogManager::getSingleton().logMessage("XMLMeshSerializer writing mesh data to " + filename + "..."); | 
|---|
| 127 |          | 
|---|
| 128 |         mpMesh = const_cast<Mesh*>(pMesh); | 
|---|
| 129 |  | 
|---|
| 130 |         mXMLDoc = new TiXmlDocument(); | 
|---|
| 131 |         mXMLDoc->InsertEndChild(TiXmlElement("mesh")); | 
|---|
| 132 |  | 
|---|
| 133 |         LogManager::getSingleton().logMessage("Populating DOM..."); | 
|---|
| 134 |  | 
|---|
| 135 |              | 
|---|
| 136 |             | 
|---|
| 137 |         // Write to DOM | 
|---|
| 138 |         writeMesh(pMesh); | 
|---|
| 139 |         LogManager::getSingleton().logMessage("DOM populated, writing XML file.."); | 
|---|
| 140 |  | 
|---|
| 141 |         // Write out to a file | 
|---|
| 142 |         mXMLDoc->SaveFile(filename); | 
|---|
| 143 |  | 
|---|
| 144 |      | 
|---|
| 145 |         delete mXMLDoc; | 
|---|
| 146 |  | 
|---|
| 147 |         LogManager::getSingleton().logMessage("XMLMeshSerializer export successful."); | 
|---|
| 148 |  | 
|---|
| 149 |     } | 
|---|
| 150 |     //--------------------------------------------------------------------- | 
|---|
| 151 |     void XMLMeshSerializer::writeMesh(const Mesh* pMesh) | 
|---|
| 152 |     { | 
|---|
| 153 |         TiXmlElement* rootNode = mXMLDoc->RootElement(); | 
|---|
| 154 |         // Write geometry | 
|---|
| 155 |                 if (pMesh->sharedVertexData) | 
|---|
| 156 |                 { | 
|---|
| 157 |                         TiXmlElement* geomNode =  | 
|---|
| 158 |                                 rootNode->InsertEndChild(TiXmlElement("sharedgeometry"))->ToElement(); | 
|---|
| 159 |                         writeGeometry(geomNode, pMesh->sharedVertexData); | 
|---|
| 160 |                 } | 
|---|
| 161 |  | 
|---|
| 162 |         // Write Submeshes | 
|---|
| 163 |         TiXmlElement* subMeshesNode =  | 
|---|
| 164 |             rootNode->InsertEndChild(TiXmlElement("submeshes"))->ToElement(); | 
|---|
| 165 |         for (int i = 0; i < pMesh->getNumSubMeshes(); ++i) | 
|---|
| 166 |         { | 
|---|
| 167 |             LogManager::getSingleton().logMessage("Writing submesh..."); | 
|---|
| 168 |             writeSubMesh(subMeshesNode, pMesh->getSubMesh(i)); | 
|---|
| 169 |             LogManager::getSingleton().logMessage("Submesh exported."); | 
|---|
| 170 |         } | 
|---|
| 171 |  | 
|---|
| 172 |         // Write skeleton info if required | 
|---|
| 173 |         if (pMesh->hasSkeleton()) | 
|---|
| 174 |         { | 
|---|
| 175 |             LogManager::getSingleton().logMessage("Exporting skeleton link..."); | 
|---|
| 176 |             // Write skeleton link | 
|---|
| 177 |             writeSkeletonLink(rootNode, pMesh->getSkeletonName()); | 
|---|
| 178 |             LogManager::getSingleton().logMessage("Skeleton link exported."); | 
|---|
| 179 |  | 
|---|
| 180 |             // Write bone assignments | 
|---|
| 181 |             Mesh::BoneAssignmentIterator bi = const_cast<Mesh*>(pMesh)->getBoneAssignmentIterator(); | 
|---|
| 182 |             if (bi.hasMoreElements()) | 
|---|
| 183 |             { | 
|---|
| 184 |                 LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments..."); | 
|---|
| 185 |                 TiXmlElement* boneAssignNode =  | 
|---|
| 186 |                     rootNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement(); | 
|---|
| 187 |  | 
|---|
| 188 |                 while (bi.hasMoreElements()) | 
|---|
| 189 |                 { | 
|---|
| 190 |                                         const VertexBoneAssignment& assign = bi.getNext(); | 
|---|
| 191 |                     writeBoneAssignment(boneAssignNode, &assign); | 
|---|
| 192 |                 } | 
|---|
| 193 |  | 
|---|
| 194 |                 LogManager::getSingleton().logMessage("Shared geometry bone assignments exported."); | 
|---|
| 195 |             } | 
|---|
| 196 |         } | 
|---|
| 197 |                 if (pMesh->getNumLodLevels() > 1) | 
|---|
| 198 |                 { | 
|---|
| 199 |             LogManager::getSingleton().logMessage("Exporting LOD information..."); | 
|---|
| 200 |                         writeLodInfo(rootNode, pMesh); | 
|---|
| 201 |             LogManager::getSingleton().logMessage("LOD information exported."); | 
|---|
| 202 |                 } | 
|---|
| 203 |         // Write submesh names | 
|---|
| 204 |         writeSubMeshNames(rootNode, pMesh); | 
|---|
| 205 |                 // Write poses | 
|---|
| 206 |                 writePoses(rootNode, pMesh); | 
|---|
| 207 |                 // Write animations | 
|---|
| 208 |                 writeAnimations(rootNode, pMesh); | 
|---|
| 209 |         // Write extremes | 
|---|
| 210 |         writeExtremes(rootNode, pMesh); | 
|---|
| 211 |     } | 
|---|
| 212 |     //--------------------------------------------------------------------- | 
|---|
| 213 |     void XMLMeshSerializer::writeSubMesh(TiXmlElement* mSubMeshesNode, const SubMesh* s) | 
|---|
| 214 |     { | 
|---|
| 215 |         TiXmlElement* subMeshNode =  | 
|---|
| 216 |             mSubMeshesNode->InsertEndChild(TiXmlElement("submesh"))->ToElement(); | 
|---|
| 217 |  | 
|---|
| 218 |         size_t numFaces; | 
|---|
| 219 |  | 
|---|
| 220 |         // Material name | 
|---|
| 221 |         subMeshNode->SetAttribute("material", s->getMaterialName()); | 
|---|
| 222 |         // bool useSharedVertices | 
|---|
| 223 |         subMeshNode->SetAttribute("usesharedvertices",  | 
|---|
| 224 |             StringConverter::toString(s->useSharedVertices) ); | 
|---|
| 225 |         // bool use32BitIndexes | 
|---|
| 226 |                 bool use32BitIndexes = (s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT); | 
|---|
| 227 |         subMeshNode->SetAttribute("use32bitindexes",  | 
|---|
| 228 |             StringConverter::toString( use32BitIndexes )); | 
|---|
| 229 |  | 
|---|
| 230 |         // Operation type | 
|---|
| 231 |         switch(s->operationType) | 
|---|
| 232 |         { | 
|---|
| 233 |         case RenderOperation::OT_LINE_LIST: | 
|---|
| 234 |         case RenderOperation::OT_LINE_STRIP: | 
|---|
| 235 |         case RenderOperation::OT_POINT_LIST: | 
|---|
| 236 |             OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Unsupported operation type, only " | 
|---|
| 237 |                 "triangle types are allowed.", "XMLMeshSerializer::writeSubMesh"); | 
|---|
| 238 |             break; | 
|---|
| 239 |         case RenderOperation::OT_TRIANGLE_FAN: | 
|---|
| 240 |             subMeshNode->SetAttribute("operationtype", "triangle_fan"); | 
|---|
| 241 |             break; | 
|---|
| 242 |         case RenderOperation::OT_TRIANGLE_LIST: | 
|---|
| 243 |             subMeshNode->SetAttribute("operationtype", "triangle_list"); | 
|---|
| 244 |             break; | 
|---|
| 245 |         case RenderOperation::OT_TRIANGLE_STRIP: | 
|---|
| 246 |             subMeshNode->SetAttribute("operationtype", "triangle_strip"); | 
|---|
| 247 |             break; | 
|---|
| 248 |         } | 
|---|
| 249 |  | 
|---|
| 250 |         // Faces | 
|---|
| 251 |         TiXmlElement* facesNode =  | 
|---|
| 252 |             subMeshNode->InsertEndChild(TiXmlElement("faces"))->ToElement(); | 
|---|
| 253 |         if (s->operationType == RenderOperation::OT_TRIANGLE_LIST) | 
|---|
| 254 |         { | 
|---|
| 255 |             // tri list | 
|---|
| 256 |             numFaces = s->indexData->indexCount / 3; | 
|---|
| 257 |         } | 
|---|
| 258 |         else | 
|---|
| 259 |         { | 
|---|
| 260 |             // triangle fan or triangle strip | 
|---|
| 261 |             numFaces = s->indexData->indexCount - 2; | 
|---|
| 262 |         } | 
|---|
| 263 |         facesNode->SetAttribute("count",  | 
|---|
| 264 |             StringConverter::toString(numFaces)); | 
|---|
| 265 |         // Write each face in turn | 
|---|
| 266 |         size_t i; | 
|---|
| 267 |                 unsigned int* pInt; | 
|---|
| 268 |                 unsigned short* pShort; | 
|---|
| 269 |                 HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer; | 
|---|
| 270 |                 if (use32BitIndexes) | 
|---|
| 271 |                 { | 
|---|
| 272 |                         pInt = static_cast<unsigned int*>( | 
|---|
| 273 |                                 ibuf->lock(HardwareBuffer::HBL_READ_ONLY));  | 
|---|
| 274 |                 } | 
|---|
| 275 |                 else | 
|---|
| 276 |                 { | 
|---|
| 277 |                         pShort = static_cast<unsigned short*>( | 
|---|
| 278 |                                 ibuf->lock(HardwareBuffer::HBL_READ_ONLY));  | 
|---|
| 279 |                 } | 
|---|
| 280 |         for (i = 0; i < numFaces; ++i) | 
|---|
| 281 |         { | 
|---|
| 282 |             TiXmlElement* faceNode =  | 
|---|
| 283 |                 facesNode->InsertEndChild(TiXmlElement("face"))->ToElement(); | 
|---|
| 284 |                         if (use32BitIndexes) | 
|---|
| 285 |                         { | 
|---|
| 286 |                                 faceNode->SetAttribute("v1", StringConverter::toString(*pInt++)); | 
|---|
| 287 |                 /// Only need all 3 vertex indices if trilist or first face | 
|---|
| 288 |                 if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0) | 
|---|
| 289 |                 { | 
|---|
| 290 |                                     faceNode->SetAttribute("v2", StringConverter::toString(*pInt++)); | 
|---|
| 291 |                                     faceNode->SetAttribute("v3", StringConverter::toString(*pInt++)); | 
|---|
| 292 |                 } | 
|---|
| 293 |                         } | 
|---|
| 294 |                         else | 
|---|
| 295 |                         { | 
|---|
| 296 |                                 faceNode->SetAttribute("v1", StringConverter::toString(*pShort++)); | 
|---|
| 297 |                 /// Only need all 3 vertex indices if trilist or first face | 
|---|
| 298 |                 if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0) | 
|---|
| 299 |                 { | 
|---|
| 300 |                                     faceNode->SetAttribute("v2", StringConverter::toString(*pShort++)); | 
|---|
| 301 |                                     faceNode->SetAttribute("v3", StringConverter::toString(*pShort++)); | 
|---|
| 302 |                 } | 
|---|
| 303 |                         } | 
|---|
| 304 |         } | 
|---|
| 305 |  | 
|---|
| 306 |         // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false) | 
|---|
| 307 |         if (!s->useSharedVertices) | 
|---|
| 308 |         { | 
|---|
| 309 |             TiXmlElement* geomNode =  | 
|---|
| 310 |                 subMeshNode->InsertEndChild(TiXmlElement("geometry"))->ToElement(); | 
|---|
| 311 |             writeGeometry(geomNode, s->vertexData); | 
|---|
| 312 |         } | 
|---|
| 313 |  | 
|---|
| 314 |         // texture aliases | 
|---|
| 315 |         writeTextureAliases(subMeshNode, s); | 
|---|
| 316 |  | 
|---|
| 317 |         // Bone assignments | 
|---|
| 318 |         if (mpMesh->hasSkeleton()) | 
|---|
| 319 |         { | 
|---|
| 320 |             SubMesh::BoneAssignmentIterator bi = const_cast<SubMesh*>(s)->getBoneAssignmentIterator(); | 
|---|
| 321 |             LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments..."); | 
|---|
| 322 |  | 
|---|
| 323 |             TiXmlElement* boneAssignNode =  | 
|---|
| 324 |                 subMeshNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement(); | 
|---|
| 325 |             while (bi.hasMoreElements()) | 
|---|
| 326 |             { | 
|---|
| 327 |                                 const VertexBoneAssignment& assign = bi.getNext(); | 
|---|
| 328 |                 writeBoneAssignment(boneAssignNode, &assign); | 
|---|
| 329 |             } | 
|---|
| 330 |         } | 
|---|
| 331 |         LogManager::getSingleton().logMessage("Dedicated geometry bone assignments exported."); | 
|---|
| 332 |  | 
|---|
| 333 |     } | 
|---|
| 334 |     //--------------------------------------------------------------------- | 
|---|
| 335 |     void XMLMeshSerializer::writeGeometry(TiXmlElement* mParentNode, const VertexData* vertexData) | 
|---|
| 336 |     { | 
|---|
| 337 |         // Write a vertex buffer per element | 
|---|
| 338 |  | 
|---|
| 339 |         TiXmlElement *vbNode, *vertexNode, *dataNode; | 
|---|
| 340 |  | 
|---|
| 341 |         // Set num verts on parent | 
|---|
| 342 |         mParentNode->SetAttribute("vertexcount", StringConverter::toString(vertexData->vertexCount)); | 
|---|
| 343 |  | 
|---|
| 344 |                 VertexDeclaration* decl = vertexData->vertexDeclaration; | 
|---|
| 345 |                 VertexBufferBinding* bind = vertexData->vertexBufferBinding; | 
|---|
| 346 |  | 
|---|
| 347 |                 VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend; | 
|---|
| 348 |                 bend = bind->getBindings().end(); | 
|---|
| 349 |                 // Iterate over buffers | 
|---|
| 350 |                 for(b = bind->getBindings().begin(); b != bend; ++b) | 
|---|
| 351 |                 { | 
|---|
| 352 |                         vbNode = mParentNode->InsertEndChild(TiXmlElement("vertexbuffer"))->ToElement(); | 
|---|
| 353 |                         const HardwareVertexBufferSharedPtr vbuf = b->second; | 
|---|
| 354 |                         unsigned short bufferIdx = b->first; | 
|---|
| 355 |                         // Get all the elements that relate to this buffer                       | 
|---|
| 356 |                         VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx); | 
|---|
| 357 |                         VertexDeclaration::VertexElementList::iterator i, iend; | 
|---|
| 358 |                         iend = elems.end(); | 
|---|
| 359 |  | 
|---|
| 360 |                         // Set up the data access for this buffer (lock read-only) | 
|---|
| 361 |                         unsigned char* pVert; | 
|---|
| 362 |                         float* pFloat; | 
|---|
| 363 |                         ARGB* pColour; | 
|---|
| 364 |  | 
|---|
| 365 |                         pVert = static_cast<unsigned char*>( | 
|---|
| 366 |                                 vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); | 
|---|
| 367 |  | 
|---|
| 368 |             // Skim over the elements to set up the general data | 
|---|
| 369 |             unsigned short numTextureCoords = 0; | 
|---|
| 370 |                         for (i = elems.begin(); i != iend; ++i) | 
|---|
| 371 |                         { | 
|---|
| 372 |                                 VertexElement& elem = *i; | 
|---|
| 373 |                                 switch(elem.getSemantic()) | 
|---|
| 374 |                                 { | 
|---|
| 375 |                                 case VES_POSITION: | 
|---|
| 376 |                                         vbNode->SetAttribute("positions","true"); | 
|---|
| 377 |                     break; | 
|---|
| 378 |                                 case VES_NORMAL: | 
|---|
| 379 |                                         vbNode->SetAttribute("normals","true"); | 
|---|
| 380 |                     break; | 
|---|
| 381 |                                 case VES_TANGENT: | 
|---|
| 382 |                                         vbNode->SetAttribute("tangents","true"); | 
|---|
| 383 |                                         break; | 
|---|
| 384 |                                 case VES_BINORMAL: | 
|---|
| 385 |                                         vbNode->SetAttribute("binormals","true"); | 
|---|
| 386 |                                         break; | 
|---|
| 387 |                                 case VES_DIFFUSE: | 
|---|
| 388 |                                         vbNode->SetAttribute("colours_diffuse","true"); | 
|---|
| 389 |                     break; | 
|---|
| 390 |                                 case VES_SPECULAR: | 
|---|
| 391 |                                         vbNode->SetAttribute("colours_specular","true"); | 
|---|
| 392 |                     break; | 
|---|
| 393 |                 case VES_TEXTURE_COORDINATES: | 
|---|
| 394 |                     vbNode->SetAttribute( | 
|---|
| 395 |                         "texture_coord_dimensions_" + StringConverter::toString(numTextureCoords),  | 
|---|
| 396 |                         StringConverter::toString(VertexElement::getTypeCount(elem.getType()))); | 
|---|
| 397 |                     ++numTextureCoords; | 
|---|
| 398 |                     break; | 
|---|
| 399 |  | 
|---|
| 400 |                 default: | 
|---|
| 401 |                     break; | 
|---|
| 402 |                 } | 
|---|
| 403 |             } | 
|---|
| 404 |             if (numTextureCoords > 0) | 
|---|
| 405 |             { | 
|---|
| 406 |                 vbNode->SetAttribute("texture_coords",  | 
|---|
| 407 |                     StringConverter::toString(numTextureCoords)); | 
|---|
| 408 |             } | 
|---|
| 409 |  | 
|---|
| 410 |                         // For each vertex | 
|---|
| 411 |                         for (size_t v = 0; v < vertexData->vertexCount; ++v) | 
|---|
| 412 |                         { | 
|---|
| 413 |                 vertexNode =  | 
|---|
| 414 |                     vbNode->InsertEndChild(TiXmlElement("vertex"))->ToElement(); | 
|---|
| 415 |                                 // Iterate over the elements | 
|---|
| 416 |                                 for (i = elems.begin(); i != iend; ++i) | 
|---|
| 417 |                                 { | 
|---|
| 418 |                                         VertexElement& elem = *i; | 
|---|
| 419 |                                         switch(elem.getSemantic()) | 
|---|
| 420 |                                         { | 
|---|
| 421 |                                         case VES_POSITION: | 
|---|
| 422 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 423 |                                                 dataNode =  | 
|---|
| 424 |                                                         vertexNode->InsertEndChild(TiXmlElement("position"))->ToElement(); | 
|---|
| 425 |                                                 dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); | 
|---|
| 426 |                                                 dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); | 
|---|
| 427 |                                                 dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); | 
|---|
| 428 |                                                 break; | 
|---|
| 429 |                                         case VES_NORMAL: | 
|---|
| 430 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 431 |                                                 dataNode =  | 
|---|
| 432 |                                                         vertexNode->InsertEndChild(TiXmlElement("normal"))->ToElement(); | 
|---|
| 433 |                                                 dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); | 
|---|
| 434 |                                                 dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); | 
|---|
| 435 |                                                 dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); | 
|---|
| 436 |                                                 break; | 
|---|
| 437 |                                         case VES_TANGENT: | 
|---|
| 438 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 439 |                                                 dataNode =  | 
|---|
| 440 |                                                         vertexNode->InsertEndChild(TiXmlElement("tangent"))->ToElement(); | 
|---|
| 441 |                                                 dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); | 
|---|
| 442 |                                                 dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); | 
|---|
| 443 |                                                 dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); | 
|---|
| 444 |                                                 break; | 
|---|
| 445 |                                         case VES_BINORMAL: | 
|---|
| 446 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 447 |                                                 dataNode =  | 
|---|
| 448 |                                                         vertexNode->InsertEndChild(TiXmlElement("binormal"))->ToElement(); | 
|---|
| 449 |                                                 dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); | 
|---|
| 450 |                                                 dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); | 
|---|
| 451 |                                                 dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); | 
|---|
| 452 |                                                 break; | 
|---|
| 453 |                                         case VES_DIFFUSE: | 
|---|
| 454 |                                                 elem.baseVertexPointerToElement(pVert, &pColour); | 
|---|
| 455 |                                                 dataNode =  | 
|---|
| 456 |                                                         vertexNode->InsertEndChild(TiXmlElement("colour_diffuse"))->ToElement(); | 
|---|
| 457 |                                                 { | 
|---|
| 458 |                                                         ARGB rc = *pColour++; | 
|---|
| 459 |                                                         ColourValue cv; | 
|---|
| 460 |                                                         cv.b = (rc & 0xFF) / 255.0f;            rc >>= 8; | 
|---|
| 461 |                                                         cv.g = (rc & 0xFF) / 255.0f;            rc >>= 8; | 
|---|
| 462 |                                                         cv.r = (rc & 0xFF) / 255.0f;            rc >>= 8; | 
|---|
| 463 |                                                         cv.a = (rc & 0xFF) / 255.0f; | 
|---|
| 464 |                             dataNode->SetAttribute("value", StringConverter::toString(cv)); | 
|---|
| 465 |                                                 } | 
|---|
| 466 |                                                 break; | 
|---|
| 467 |                                         case VES_SPECULAR: | 
|---|
| 468 |                                                 elem.baseVertexPointerToElement(pVert, &pColour); | 
|---|
| 469 |                                                 dataNode =  | 
|---|
| 470 |                                                         vertexNode->InsertEndChild(TiXmlElement("colour_specular"))->ToElement(); | 
|---|
| 471 |                                                 { | 
|---|
| 472 |                                                         ARGB rc = *pColour++; | 
|---|
| 473 |                                                         ColourValue cv; | 
|---|
| 474 |                                                         cv.b = (rc & 0xFF) / 255.0f;            rc >>= 8; | 
|---|
| 475 |                                                         cv.g = (rc & 0xFF) / 255.0f;            rc >>= 8; | 
|---|
| 476 |                                                         cv.r = (rc & 0xFF) / 255.0f;            rc >>= 8; | 
|---|
| 477 |                                                         cv.a = (rc & 0xFF) / 255.0f; | 
|---|
| 478 |                                                         dataNode->SetAttribute("value", StringConverter::toString(cv)); | 
|---|
| 479 |                                                 } | 
|---|
| 480 |                                                 break; | 
|---|
| 481 |                                         case VES_TEXTURE_COORDINATES: | 
|---|
| 482 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 483 |                                                 dataNode =  | 
|---|
| 484 |                                                         vertexNode->InsertEndChild(TiXmlElement("texcoord"))->ToElement(); | 
|---|
| 485 |  | 
|---|
| 486 |                                                 switch(elem.getType()) | 
|---|
| 487 |                         { | 
|---|
| 488 |                         case VET_FLOAT1: | 
|---|
| 489 |                                                 dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); | 
|---|
| 490 |                             break; | 
|---|
| 491 |                         case VET_FLOAT2: | 
|---|
| 492 |                                                 dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); | 
|---|
| 493 |                                                 dataNode->SetAttribute("v", StringConverter::toString(*pFloat++)); | 
|---|
| 494 |                             break; | 
|---|
| 495 |                         case VET_FLOAT3: | 
|---|
| 496 |                                                 dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); | 
|---|
| 497 |                                                 dataNode->SetAttribute("v", StringConverter::toString(*pFloat++)); | 
|---|
| 498 |                                                 dataNode->SetAttribute("w", StringConverter::toString(*pFloat++)); | 
|---|
| 499 |                             break; | 
|---|
| 500 |                         default: | 
|---|
| 501 |                             break; | 
|---|
| 502 |                         } | 
|---|
| 503 |                                                 break; | 
|---|
| 504 |                     default: | 
|---|
| 505 |                         break; | 
|---|
| 506 |  | 
|---|
| 507 |                                         } | 
|---|
| 508 |                                 } | 
|---|
| 509 |                                 pVert += vbuf->getVertexSize(); | 
|---|
| 510 |                         } | 
|---|
| 511 |                         vbuf->unlock(); | 
|---|
| 512 |                 } | 
|---|
| 513 |  | 
|---|
| 514 |     } | 
|---|
| 515 |     //--------------------------------------------------------------------- | 
|---|
| 516 |     void XMLMeshSerializer::writeSkeletonLink(TiXmlElement* mMeshNode, const String& skelName) | 
|---|
| 517 |     { | 
|---|
| 518 |  | 
|---|
| 519 |         TiXmlElement* skelNode =  | 
|---|
| 520 |             mMeshNode->InsertEndChild(TiXmlElement("skeletonlink"))->ToElement(); | 
|---|
| 521 |         skelNode->SetAttribute("name", skelName); | 
|---|
| 522 |     } | 
|---|
| 523 |     //--------------------------------------------------------------------- | 
|---|
| 524 |     void XMLMeshSerializer::writeBoneAssignment(TiXmlElement* mBoneAssignNode, const VertexBoneAssignment* assign) | 
|---|
| 525 |     { | 
|---|
| 526 |         TiXmlElement* assignNode =  | 
|---|
| 527 |             mBoneAssignNode->InsertEndChild( | 
|---|
| 528 |             TiXmlElement("vertexboneassignment"))->ToElement(); | 
|---|
| 529 |  | 
|---|
| 530 |         assignNode->SetAttribute("vertexindex",  | 
|---|
| 531 |             StringConverter::toString(assign->vertexIndex)); | 
|---|
| 532 |         assignNode->SetAttribute("boneindex",  | 
|---|
| 533 |             StringConverter::toString(assign->boneIndex)); | 
|---|
| 534 |         assignNode->SetAttribute("weight", | 
|---|
| 535 |             StringConverter::toString(assign->weight)); | 
|---|
| 536 |  | 
|---|
| 537 |  | 
|---|
| 538 |     } | 
|---|
| 539 |     //--------------------------------------------------------------------- | 
|---|
| 540 |     void XMLMeshSerializer::writeTextureAliases(TiXmlElement* mSubmeshesNode, const SubMesh* subMesh) | 
|---|
| 541 |     { | 
|---|
| 542 |         if (!subMesh->hasTextureAliases()) | 
|---|
| 543 |             return; // do nothing | 
|---|
| 544 |  | 
|---|
| 545 |         TiXmlElement* textureAliasesNode =  | 
|---|
| 546 |             mSubmeshesNode->InsertEndChild(TiXmlElement("textures"))->ToElement(); | 
|---|
| 547 |  | 
|---|
| 548 |         // use ogre map iterator | 
|---|
| 549 |         SubMesh::AliasTextureIterator aliasIterator = subMesh->getAliasTextureIterator(); | 
|---|
| 550 |  | 
|---|
| 551 |         while (aliasIterator.hasMoreElements()) | 
|---|
| 552 |         { | 
|---|
| 553 |             TiXmlElement* aliasTextureNode =  | 
|---|
| 554 |                 textureAliasesNode->InsertEndChild(TiXmlElement("texture"))->ToElement(); | 
|---|
| 555 |             // iterator key is alias and value is texture name | 
|---|
| 556 |             aliasTextureNode->SetAttribute("alias", aliasIterator.peekNextKey()); | 
|---|
| 557 |             aliasTextureNode->SetAttribute("name", aliasIterator.peekNextValue()); | 
|---|
| 558 |             aliasIterator.moveNext(); | 
|---|
| 559 |         } | 
|---|
| 560 |  | 
|---|
| 561 |     } | 
|---|
| 562 |     //--------------------------------------------------------------------- | 
|---|
| 563 |     void XMLMeshSerializer::readSubMeshes(TiXmlElement* mSubmeshesNode) | 
|---|
| 564 |     { | 
|---|
| 565 |         LogManager::getSingleton().logMessage("Reading submeshes..."); | 
|---|
| 566 |  | 
|---|
| 567 |         for (TiXmlElement* smElem = mSubmeshesNode->FirstChildElement(); | 
|---|
| 568 |             smElem != 0; smElem = smElem->NextSiblingElement()) | 
|---|
| 569 |         { | 
|---|
| 570 |             // All children should be submeshes  | 
|---|
| 571 |             SubMesh* sm = mpMesh->createSubMesh(); | 
|---|
| 572 |  | 
|---|
| 573 |             const char* mat = smElem->Attribute("material"); | 
|---|
| 574 |             if (mat) | 
|---|
| 575 |                 sm->setMaterialName(mat); | 
|---|
| 576 |  | 
|---|
| 577 |             // Read operation type | 
|---|
| 578 |             const char* optype = smElem->Attribute("operationtype"); | 
|---|
| 579 |             if (optype) | 
|---|
| 580 |             { | 
|---|
| 581 |                 if (!strcmp(optype, "triangle_list")) | 
|---|
| 582 |                 { | 
|---|
| 583 |                     sm->operationType = RenderOperation::OT_TRIANGLE_LIST; | 
|---|
| 584 |                 } | 
|---|
| 585 |                 else if (!strcmp(optype, "triangle_fan")) | 
|---|
| 586 |                 { | 
|---|
| 587 |                     sm->operationType = RenderOperation::OT_TRIANGLE_FAN; | 
|---|
| 588 |                 } | 
|---|
| 589 |                 else if (!strcmp(optype, "triangle_strip")) | 
|---|
| 590 |                 { | 
|---|
| 591 |                     sm->operationType = RenderOperation::OT_TRIANGLE_STRIP; | 
|---|
| 592 |                 } | 
|---|
| 593 |  | 
|---|
| 594 |             } | 
|---|
| 595 |  | 
|---|
| 596 |             const char* tmp = smElem->Attribute("usesharedvertices"); | 
|---|
| 597 |             if (tmp) | 
|---|
| 598 |                 sm->useSharedVertices = StringConverter::parseBool(tmp); | 
|---|
| 599 |             tmp = smElem->Attribute("use32bitindexes"); | 
|---|
| 600 |             bool use32BitIndexes = false; | 
|---|
| 601 |             if (tmp) | 
|---|
| 602 |                 use32BitIndexes = StringConverter::parseBool(tmp); | 
|---|
| 603 |              | 
|---|
| 604 |             // Faces | 
|---|
| 605 |             TiXmlElement* faces = smElem->FirstChildElement("faces"); | 
|---|
| 606 |             size_t actualCount = 0; | 
|---|
| 607 |             for (TiXmlElement *faceElem = faces->FirstChildElement(); faceElem != 0; faceElem = faceElem->NextSiblingElement()) | 
|---|
| 608 |             { | 
|---|
| 609 |                     actualCount++; | 
|---|
| 610 |             } | 
|---|
| 611 |             const char *claimedCount_ = faces->Attribute("count"); | 
|---|
| 612 |             if (claimedCount_ && StringConverter::parseInt(claimedCount_)!=actualCount) | 
|---|
| 613 |             { | 
|---|
| 614 |                                 StringUtil::StrStreamType str; | 
|---|
| 615 |                 str << "WARNING: face count (" << actualCount << ") " << | 
|---|
| 616 |                                         "is not as claimed (" << claimedCount_ << ")"; | 
|---|
| 617 |                                 LogManager::getSingleton().logMessage(str.str()); | 
|---|
| 618 |             } | 
|---|
| 619 |  | 
|---|
| 620 |  | 
|---|
| 621 |             // Faces | 
|---|
| 622 |             if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST) | 
|---|
| 623 |             { | 
|---|
| 624 |                     // tri list | 
|---|
| 625 |                     sm->indexData->indexCount = actualCount * 3; | 
|---|
| 626 |             } else { | 
|---|
| 627 |                     // tri strip or fan | 
|---|
| 628 |                     sm->indexData->indexCount = actualCount + 2; | 
|---|
| 629 |             } | 
|---|
| 630 |  | 
|---|
| 631 |             // Allocate space | 
|---|
| 632 |             HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). | 
|---|
| 633 |                 createIndexBuffer( | 
|---|
| 634 |                     use32BitIndexes? HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT,  | 
|---|
| 635 |                     sm->indexData->indexCount,  | 
|---|
| 636 |                     HardwareBuffer::HBU_DYNAMIC, | 
|---|
| 637 |                     false); | 
|---|
| 638 |             sm->indexData->indexBuffer = ibuf; | 
|---|
| 639 |             unsigned int *pInt; | 
|---|
| 640 |             unsigned short *pShort; | 
|---|
| 641 |             if (use32BitIndexes) | 
|---|
| 642 |             { | 
|---|
| 643 |                 pInt = static_cast<unsigned int*>( | 
|---|
| 644 |                     ibuf->lock(HardwareBuffer::HBL_DISCARD)); | 
|---|
| 645 |             } | 
|---|
| 646 |             else | 
|---|
| 647 |             { | 
|---|
| 648 |                 pShort = static_cast<unsigned short*>( | 
|---|
| 649 |                     ibuf->lock(HardwareBuffer::HBL_DISCARD)); | 
|---|
| 650 |             } | 
|---|
| 651 |             TiXmlElement* faceElem; | 
|---|
| 652 |             bool firstTri = true; | 
|---|
| 653 |             for (faceElem = faces->FirstChildElement(); | 
|---|
| 654 |                 faceElem != 0; faceElem = faceElem->NextSiblingElement()) | 
|---|
| 655 |             { | 
|---|
| 656 |                 if (use32BitIndexes) | 
|---|
| 657 |                 { | 
|---|
| 658 |                     *pInt++ = StringConverter::parseInt(faceElem->Attribute("v1")); | 
|---|
| 659 |                     // only need all 3 vertices if it's a trilist or first tri | 
|---|
| 660 |                     if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri) | 
|---|
| 661 |                     { | 
|---|
| 662 |                         *pInt++ = StringConverter::parseInt(faceElem->Attribute("v2")); | 
|---|
| 663 |                         *pInt++ = StringConverter::parseInt(faceElem->Attribute("v3")); | 
|---|
| 664 |                     } | 
|---|
| 665 |                 } | 
|---|
| 666 |                 else | 
|---|
| 667 |                 { | 
|---|
| 668 |                     *pShort++ = StringConverter::parseInt(faceElem->Attribute("v1")); | 
|---|
| 669 |                     // only need all 3 vertices if it's a trilist or first tri | 
|---|
| 670 |                     if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri) | 
|---|
| 671 |                     { | 
|---|
| 672 |                         *pShort++ = StringConverter::parseInt(faceElem->Attribute("v2")); | 
|---|
| 673 |                         *pShort++ = StringConverter::parseInt(faceElem->Attribute("v3")); | 
|---|
| 674 |                     } | 
|---|
| 675 |                 } | 
|---|
| 676 |                 firstTri = false; | 
|---|
| 677 |             } | 
|---|
| 678 |             ibuf->unlock(); | 
|---|
| 679 |  | 
|---|
| 680 |             // Geometry | 
|---|
| 681 |             if (!sm->useSharedVertices) | 
|---|
| 682 |             { | 
|---|
| 683 |                 TiXmlElement* geomNode = smElem->FirstChildElement("geometry"); | 
|---|
| 684 |                 if (geomNode) | 
|---|
| 685 |                 { | 
|---|
| 686 |                     sm->vertexData = new VertexData(); | 
|---|
| 687 |                     readGeometry(geomNode, sm->vertexData); | 
|---|
| 688 |                 } | 
|---|
| 689 |             } | 
|---|
| 690 |  | 
|---|
| 691 |             // texture aliases | 
|---|
| 692 |             TiXmlElement* textureAliasesNode = smElem->FirstChildElement("textures"); | 
|---|
| 693 |             if(textureAliasesNode) | 
|---|
| 694 |                 readTextureAliases(textureAliasesNode, sm); | 
|---|
| 695 |  | 
|---|
| 696 |             // Bone assignments | 
|---|
| 697 |             TiXmlElement* boneAssigns = smElem->FirstChildElement("boneassignments"); | 
|---|
| 698 |             if(boneAssigns) | 
|---|
| 699 |                 readBoneAssignments(boneAssigns, sm); | 
|---|
| 700 |  | 
|---|
| 701 |         } | 
|---|
| 702 |         LogManager::getSingleton().logMessage("Submeshes done."); | 
|---|
| 703 |     } | 
|---|
| 704 |     //--------------------------------------------------------------------- | 
|---|
| 705 |     void XMLMeshSerializer::readGeometry(TiXmlElement* mGeometryNode, VertexData* vertexData) | 
|---|
| 706 |     { | 
|---|
| 707 |         LogManager::getSingleton().logMessage("Reading geometry..."); | 
|---|
| 708 |         unsigned char *pVert; | 
|---|
| 709 |         float *pFloat; | 
|---|
| 710 |         ARGB *pCol; | 
|---|
| 711 |  | 
|---|
| 712 |         const char *claimedVertexCount_ = mGeometryNode->Attribute("vertexcount"); | 
|---|
| 713 |         ptrdiff_t claimedVertexCount; | 
|---|
| 714 |         if (claimedVertexCount_) | 
|---|
| 715 |         { | 
|---|
| 716 |                 claimedVertexCount = | 
|---|
| 717 |                         StringConverter::parseInt(claimedVertexCount_); | 
|---|
| 718 |         } | 
|---|
| 719 |         // Skip empty  | 
|---|
| 720 |         if (claimedVertexCount_ && claimedVertexCount <= 0) return; | 
|---|
| 721 |          | 
|---|
| 722 |  | 
|---|
| 723 |         VertexDeclaration* decl = vertexData->vertexDeclaration; | 
|---|
| 724 |         VertexBufferBinding* bind = vertexData->vertexBufferBinding; | 
|---|
| 725 |         unsigned short bufCount = 0; | 
|---|
| 726 |         unsigned short totalTexCoords = 0; // across all buffers | 
|---|
| 727 |  | 
|---|
| 728 |         // Information for calculating bounds | 
|---|
| 729 |         Vector3 min, max, pos; | 
|---|
| 730 |         Real maxSquaredRadius = -1; | 
|---|
| 731 |         bool first = true; | 
|---|
| 732 |  | 
|---|
| 733 |         // Iterate over all children (vertexbuffer entries)  | 
|---|
| 734 |         for (TiXmlElement* vbElem = mGeometryNode->FirstChildElement(); | 
|---|
| 735 |             vbElem != 0; vbElem = vbElem->NextSiblingElement()) | 
|---|
| 736 |         { | 
|---|
| 737 |             size_t offset = 0; | 
|---|
| 738 |             // Skip non-vertexbuffer elems | 
|---|
| 739 |             if (stricmp(vbElem->Value(), "vertexbuffer")) continue; | 
|---|
| 740 |             | 
|---|
| 741 |             const char* attrib = vbElem->Attribute("positions"); | 
|---|
| 742 |             if (attrib && StringConverter::parseBool(attrib)) | 
|---|
| 743 |             { | 
|---|
| 744 |                 // Add element | 
|---|
| 745 |                 decl->addElement(bufCount, offset, VET_FLOAT3, VES_POSITION); | 
|---|
| 746 |                 offset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 747 |             } | 
|---|
| 748 |             attrib = vbElem->Attribute("normals"); | 
|---|
| 749 |             if (attrib && StringConverter::parseBool(attrib)) | 
|---|
| 750 |             { | 
|---|
| 751 |                 // Add element | 
|---|
| 752 |                 decl->addElement(bufCount, offset, VET_FLOAT3, VES_NORMAL); | 
|---|
| 753 |                 offset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 754 |             } | 
|---|
| 755 |                         attrib = vbElem->Attribute("tangents"); | 
|---|
| 756 |                         if (attrib && StringConverter::parseBool(attrib)) | 
|---|
| 757 |                         { | 
|---|
| 758 |                                 // Add element | 
|---|
| 759 |                                 decl->addElement(bufCount, offset, VET_FLOAT3, VES_TANGENT); | 
|---|
| 760 |                                 offset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 761 |                         } | 
|---|
| 762 |                         attrib = vbElem->Attribute("binormals"); | 
|---|
| 763 |                         if (attrib && StringConverter::parseBool(attrib)) | 
|---|
| 764 |                         { | 
|---|
| 765 |                                 // Add element | 
|---|
| 766 |                                 decl->addElement(bufCount, offset, VET_FLOAT3, VES_BINORMAL); | 
|---|
| 767 |                                 offset += VertexElement::getTypeSize(VET_FLOAT3); | 
|---|
| 768 |                         } | 
|---|
| 769 |             attrib = vbElem->Attribute("colours_diffuse"); | 
|---|
| 770 |             if (attrib && StringConverter::parseBool(attrib)) | 
|---|
| 771 |             { | 
|---|
| 772 |                 // Add element | 
|---|
| 773 |                 decl->addElement(bufCount, offset, mColourElementType, VES_DIFFUSE); | 
|---|
| 774 |                 offset += VertexElement::getTypeSize(mColourElementType); | 
|---|
| 775 |             } | 
|---|
| 776 |             attrib = vbElem->Attribute("colours_specular"); | 
|---|
| 777 |             if (attrib && StringConverter::parseBool(attrib)) | 
|---|
| 778 |             { | 
|---|
| 779 |                 // Add element | 
|---|
| 780 |                 decl->addElement(bufCount, offset, mColourElementType, VES_SPECULAR); | 
|---|
| 781 |                 offset += VertexElement::getTypeSize(mColourElementType); | 
|---|
| 782 |             } | 
|---|
| 783 |             attrib = vbElem->Attribute("texture_coords"); | 
|---|
| 784 |             if (attrib && StringConverter::parseInt(attrib)) | 
|---|
| 785 |             { | 
|---|
| 786 |                 unsigned short numTexCoords = StringConverter::parseInt(vbElem->Attribute("texture_coords")); | 
|---|
| 787 |                 for (unsigned short tx = 0; tx < numTexCoords; ++tx) | 
|---|
| 788 |                 { | 
|---|
| 789 |                     // NB set is local to this buffer, but will be translated into a  | 
|---|
| 790 |                     // global set number across all vertex buffers | 
|---|
| 791 |                                         StringUtil::StrStreamType str; | 
|---|
| 792 |                                         str << "texture_coord_dimensions_" << tx; | 
|---|
| 793 |                     attrib = vbElem->Attribute(str.str().c_str()); | 
|---|
| 794 |                     unsigned short dims; | 
|---|
| 795 |                     if (attrib) | 
|---|
| 796 |                     { | 
|---|
| 797 |                         dims = StringConverter::parseInt(attrib); | 
|---|
| 798 |                     } | 
|---|
| 799 |                     else | 
|---|
| 800 |                     { | 
|---|
| 801 |                         // Default | 
|---|
| 802 |                         dims = 2; | 
|---|
| 803 |                     } | 
|---|
| 804 |                     // Add element | 
|---|
| 805 |                     VertexElementType vtype = VertexElement::multiplyTypeCount(VET_FLOAT1, dims); | 
|---|
| 806 |                     decl->addElement(bufCount, offset, vtype,  | 
|---|
| 807 |                         VES_TEXTURE_COORDINATES, totalTexCoords++); | 
|---|
| 808 |                     offset += VertexElement::getTypeSize(vtype); | 
|---|
| 809 |                 } | 
|---|
| 810 |             }  | 
|---|
| 811 |  | 
|---|
| 812 |             // calculate how many vertexes there actually are | 
|---|
| 813 |             int actualVertexCount = 0; | 
|---|
| 814 |             for (TiXmlElement * vertexElem = vbElem->FirstChildElement(); vertexElem != 0; vertexElem = vertexElem->NextSiblingElement()) | 
|---|
| 815 |             { | 
|---|
| 816 |                     actualVertexCount++; | 
|---|
| 817 |             } | 
|---|
| 818 |             if (claimedVertexCount_ && actualVertexCount!=claimedVertexCount) | 
|---|
| 819 |             { | 
|---|
| 820 |                                 StringUtil::StrStreamType str; | 
|---|
| 821 |                                 str << "WARNING: vertex count (" << actualVertexCount  | 
|---|
| 822 |                                         << ") is not as claimed (" << claimedVertexCount_ << ")"; | 
|---|
| 823 |                                 LogManager::getSingleton().logMessage(str.str()); | 
|---|
| 824 |             } | 
|---|
| 825 |  | 
|---|
| 826 |             vertexData->vertexCount = actualVertexCount; | 
|---|
| 827 |             // Now create the vertex buffer | 
|---|
| 828 |             HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). | 
|---|
| 829 |                 createVertexBuffer(offset, vertexData->vertexCount,  | 
|---|
| 830 |                     HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); | 
|---|
| 831 |             // Bind it | 
|---|
| 832 |             bind->setBinding(bufCount, vbuf); | 
|---|
| 833 |             // Lock it | 
|---|
| 834 |             pVert = static_cast<unsigned char*>( | 
|---|
| 835 |                 vbuf->lock(HardwareBuffer::HBL_DISCARD)); | 
|---|
| 836 |  | 
|---|
| 837 |             // Get the element list for this buffer alone | 
|---|
| 838 |             VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufCount); | 
|---|
| 839 |             // Now the buffer is set up, parse all the vertices | 
|---|
| 840 |             for (TiXmlElement* vertexElem = vbElem->FirstChildElement(); | 
|---|
| 841 |             vertexElem != 0; vertexElem = vertexElem->NextSiblingElement()) | 
|---|
| 842 |             { | 
|---|
| 843 |                 // Now parse the elements, ensure they are all matched | 
|---|
| 844 |                 VertexDeclaration::VertexElementList::const_iterator ielem, ielemend; | 
|---|
| 845 |                 TiXmlElement* xmlElem; | 
|---|
| 846 |                 TiXmlElement* texCoordElem = 0; | 
|---|
| 847 |                 ielemend = elems.end(); | 
|---|
| 848 |                 for (ielem = elems.begin(); ielem != ielemend; ++ielem) | 
|---|
| 849 |                 { | 
|---|
| 850 |                     const VertexElement& elem = *ielem; | 
|---|
| 851 |                     // Find child for this element | 
|---|
| 852 |                     switch(elem.getSemantic()) | 
|---|
| 853 |                     { | 
|---|
| 854 |                     case VES_POSITION: | 
|---|
| 855 |                         xmlElem = vertexElem->FirstChildElement("position"); | 
|---|
| 856 |                         if (!xmlElem) | 
|---|
| 857 |                         { | 
|---|
| 858 |                             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <position> element.", | 
|---|
| 859 |                                 "XMLSerializer::readGeometry"); | 
|---|
| 860 |                         } | 
|---|
| 861 |                         elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 862 |  | 
|---|
| 863 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 864 |                             xmlElem->Attribute("x")); | 
|---|
| 865 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 866 |                             xmlElem->Attribute("y")); | 
|---|
| 867 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 868 |                             xmlElem->Attribute("z")); | 
|---|
| 869 |  | 
|---|
| 870 |                         pos.x = StringConverter::parseReal( | 
|---|
| 871 |                             xmlElem->Attribute("x")); | 
|---|
| 872 |                         pos.y = StringConverter::parseReal( | 
|---|
| 873 |                             xmlElem->Attribute("y")); | 
|---|
| 874 |                         pos.z = StringConverter::parseReal( | 
|---|
| 875 |                             xmlElem->Attribute("z")); | 
|---|
| 876 |                          | 
|---|
| 877 |                         if (first) | 
|---|
| 878 |                         { | 
|---|
| 879 |                             min = max = pos; | 
|---|
| 880 |                             maxSquaredRadius = pos.squaredLength(); | 
|---|
| 881 |                             first = false; | 
|---|
| 882 |                         } | 
|---|
| 883 |                         else | 
|---|
| 884 |                         { | 
|---|
| 885 |                             min.makeFloor(pos); | 
|---|
| 886 |                             max.makeCeil(pos); | 
|---|
| 887 |                             maxSquaredRadius = std::max(pos.squaredLength(), maxSquaredRadius); | 
|---|
| 888 |                         } | 
|---|
| 889 |                         break; | 
|---|
| 890 |                     case VES_NORMAL: | 
|---|
| 891 |                         xmlElem = vertexElem->FirstChildElement("normal"); | 
|---|
| 892 |                         if (!xmlElem) | 
|---|
| 893 |                         { | 
|---|
| 894 |                             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <normal> element.", | 
|---|
| 895 |                                 "XMLSerializer::readGeometry"); | 
|---|
| 896 |                         } | 
|---|
| 897 |                         elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 898 |  | 
|---|
| 899 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 900 |                             xmlElem->Attribute("x")); | 
|---|
| 901 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 902 |                             xmlElem->Attribute("y")); | 
|---|
| 903 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 904 |                             xmlElem->Attribute("z")); | 
|---|
| 905 |                         break; | 
|---|
| 906 |                                         case VES_TANGENT: | 
|---|
| 907 |                                                 xmlElem = vertexElem->FirstChildElement("tangent"); | 
|---|
| 908 |                                                 if (!xmlElem) | 
|---|
| 909 |                                                 { | 
|---|
| 910 |                                                         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <tangent> element.", | 
|---|
| 911 |                                                                 "XMLSerializer::readGeometry"); | 
|---|
| 912 |                                                 } | 
|---|
| 913 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 914 |  | 
|---|
| 915 |                                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 916 |                                                         xmlElem->Attribute("x")); | 
|---|
| 917 |                                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 918 |                                                         xmlElem->Attribute("y")); | 
|---|
| 919 |                                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 920 |                                                         xmlElem->Attribute("z")); | 
|---|
| 921 |                                                 break; | 
|---|
| 922 |                                         case VES_BINORMAL: | 
|---|
| 923 |                                                 xmlElem = vertexElem->FirstChildElement("binormal"); | 
|---|
| 924 |                                                 if (!xmlElem) | 
|---|
| 925 |                                                 { | 
|---|
| 926 |                                                         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <binormal> element.", | 
|---|
| 927 |                                                                 "XMLSerializer::readGeometry"); | 
|---|
| 928 |                                                 } | 
|---|
| 929 |                                                 elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 930 |  | 
|---|
| 931 |                                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 932 |                                                         xmlElem->Attribute("x")); | 
|---|
| 933 |                                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 934 |                                                         xmlElem->Attribute("y")); | 
|---|
| 935 |                                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 936 |                                                         xmlElem->Attribute("z")); | 
|---|
| 937 |                                                 break; | 
|---|
| 938 |                     case VES_DIFFUSE: | 
|---|
| 939 |                         xmlElem = vertexElem->FirstChildElement("colour_diffuse"); | 
|---|
| 940 |                         if (!xmlElem) | 
|---|
| 941 |                         { | 
|---|
| 942 |                             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_diffuse> element.", | 
|---|
| 943 |                                 "XMLSerializer::readGeometry"); | 
|---|
| 944 |                         } | 
|---|
| 945 |                         elem.baseVertexPointerToElement(pVert, &pCol); | 
|---|
| 946 |                                                 { | 
|---|
| 947 |                                                         ColourValue cv; | 
|---|
| 948 |                                                         cv = StringConverter::parseColourValue( | 
|---|
| 949 |                                                                 xmlElem->Attribute("value")); | 
|---|
| 950 |                                                         *pCol++ = VertexElement::convertColourValue(cv, mColourElementType); | 
|---|
| 951 |                                                 } | 
|---|
| 952 |                         break; | 
|---|
| 953 |                     case VES_SPECULAR: | 
|---|
| 954 |                         xmlElem = vertexElem->FirstChildElement("colour_specular"); | 
|---|
| 955 |                         if (!xmlElem) | 
|---|
| 956 |                         { | 
|---|
| 957 |                             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <colour_specular> element.", | 
|---|
| 958 |                                 "XMLSerializer::readGeometry"); | 
|---|
| 959 |                         } | 
|---|
| 960 |                         elem.baseVertexPointerToElement(pVert, &pCol); | 
|---|
| 961 |                                                 { | 
|---|
| 962 |                                                         ColourValue cv; | 
|---|
| 963 |                                                         cv = StringConverter::parseColourValue( | 
|---|
| 964 |                                                                 xmlElem->Attribute("value")); | 
|---|
| 965 |                                                         *pCol++ = VertexElement::convertColourValue(cv, mColourElementType); | 
|---|
| 966 |                                                 } | 
|---|
| 967 |                         break; | 
|---|
| 968 |                     case VES_TEXTURE_COORDINATES: | 
|---|
| 969 |                         if (!texCoordElem) | 
|---|
| 970 |                         { | 
|---|
| 971 |                             // Get first texcoord | 
|---|
| 972 |                             xmlElem = vertexElem->FirstChildElement("texcoord"); | 
|---|
| 973 |                         } | 
|---|
| 974 |                         else | 
|---|
| 975 |                         { | 
|---|
| 976 |                             // Get next texcoord | 
|---|
| 977 |                             xmlElem = texCoordElem->NextSiblingElement("texcoord"); | 
|---|
| 978 |                         } | 
|---|
| 979 |                         if (!xmlElem) | 
|---|
| 980 |                         { | 
|---|
| 981 |                             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing <texcoord> element.", | 
|---|
| 982 |                                 "XMLSerializer::readGeometry"); | 
|---|
| 983 |                         } | 
|---|
| 984 |                                                 // Record the latest texture coord entry | 
|---|
| 985 |                                                 texCoordElem = xmlElem; | 
|---|
| 986 |                         elem.baseVertexPointerToElement(pVert, &pFloat); | 
|---|
| 987 |  | 
|---|
| 988 |                         *pFloat++ = StringConverter::parseReal( | 
|---|
| 989 |                             xmlElem->Attribute("u")); | 
|---|
| 990 |                         if (VertexElement::getTypeCount(elem.getType()) > 1) | 
|---|
| 991 |                         { | 
|---|
| 992 |                             *pFloat++ = StringConverter::parseReal( | 
|---|
| 993 |                                 xmlElem->Attribute("v")); | 
|---|
| 994 |                         } | 
|---|
| 995 |                         if (VertexElement::getTypeCount(elem.getType()) > 2) | 
|---|
| 996 |                         { | 
|---|
| 997 |                             *pFloat++ = StringConverter::parseReal( | 
|---|
| 998 |                                 xmlElem->Attribute("w")); | 
|---|
| 999 |                         } | 
|---|
| 1000 |  | 
|---|
| 1001 |                         break; | 
|---|
| 1002 |                     default: | 
|---|
| 1003 |                         break; | 
|---|
| 1004 |                     } | 
|---|
| 1005 |                 } // semantic | 
|---|
| 1006 |                 pVert += vbuf->getVertexSize(); | 
|---|
| 1007 |             } // vertex | 
|---|
| 1008 |             bufCount++; | 
|---|
| 1009 |             vbuf->unlock(); | 
|---|
| 1010 |         } // vertexbuffer | 
|---|
| 1011 |  | 
|---|
| 1012 |         // Set bounds | 
|---|
| 1013 |         const AxisAlignedBox& currBox = mpMesh->getBounds(); | 
|---|
| 1014 |         Real currRadius = mpMesh->getBoundingSphereRadius(); | 
|---|
| 1015 |         if (currBox.isNull()) | 
|---|
| 1016 |         { | 
|---|
| 1017 |             //do not pad the bounding box | 
|---|
| 1018 |             mpMesh->_setBounds(AxisAlignedBox(min, max), false); | 
|---|
| 1019 |             mpMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius)); | 
|---|
| 1020 |         } | 
|---|
| 1021 |         else | 
|---|
| 1022 |         { | 
|---|
| 1023 |             AxisAlignedBox newBox(min, max); | 
|---|
| 1024 |             newBox.merge(currBox); | 
|---|
| 1025 |             //do not pad the bounding box | 
|---|
| 1026 |             mpMesh->_setBounds(newBox, false); | 
|---|
| 1027 |             mpMesh->_setBoundingSphereRadius(std::max(Math::Sqrt(maxSquaredRadius), currRadius)); | 
|---|
| 1028 |         } | 
|---|
| 1029 |          | 
|---|
| 1030 |  | 
|---|
| 1031 |         LogManager::getSingleton().logMessage("Geometry done..."); | 
|---|
| 1032 |     } | 
|---|
| 1033 |     //--------------------------------------------------------------------- | 
|---|
| 1034 |     void XMLMeshSerializer::readSkeletonLink(TiXmlElement* mSkelNode) | 
|---|
| 1035 |     { | 
|---|
| 1036 |         mpMesh->setSkeletonName(mSkelNode->Attribute("name")); | 
|---|
| 1037 |     } | 
|---|
| 1038 |     //--------------------------------------------------------------------- | 
|---|
| 1039 |     void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode) | 
|---|
| 1040 |     { | 
|---|
| 1041 |         LogManager::getSingleton().logMessage("Reading bone assignments..."); | 
|---|
| 1042 |  | 
|---|
| 1043 |         // Iterate over all children (vertexboneassignment entries) | 
|---|
| 1044 |         for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement(); | 
|---|
| 1045 |         elem != 0; elem = elem->NextSiblingElement()) | 
|---|
| 1046 |         { | 
|---|
| 1047 |             VertexBoneAssignment vba; | 
|---|
| 1048 |             vba.vertexIndex = StringConverter::parseInt( | 
|---|
| 1049 |                 elem->Attribute("vertexindex")); | 
|---|
| 1050 |             vba.boneIndex = StringConverter::parseInt( | 
|---|
| 1051 |                 elem->Attribute("boneindex")); | 
|---|
| 1052 |             vba.weight= StringConverter::parseReal( | 
|---|
| 1053 |                 elem->Attribute("weight")); | 
|---|
| 1054 |  | 
|---|
| 1055 |             mpMesh->addBoneAssignment(vba); | 
|---|
| 1056 |         } | 
|---|
| 1057 |  | 
|---|
| 1058 |         LogManager::getSingleton().logMessage("Bone assignments done."); | 
|---|
| 1059 |     } | 
|---|
| 1060 |     //--------------------------------------------------------------------- | 
|---|
| 1061 |     void XMLMeshSerializer::readTextureAliases(TiXmlElement* mTextureAliasesNode, SubMesh* subMesh) | 
|---|
| 1062 |     { | 
|---|
| 1063 |         LogManager::getSingleton().logMessage("Reading sub mesh texture aliases..."); | 
|---|
| 1064 |  | 
|---|
| 1065 |         // Iterate over all children (texture entries) | 
|---|
| 1066 |         for (TiXmlElement* elem = mTextureAliasesNode->FirstChildElement(); | 
|---|
| 1067 |              elem != 0; elem = elem->NextSiblingElement()) | 
|---|
| 1068 |         { | 
|---|
| 1069 |             // pass alias and texture name to submesh | 
|---|
| 1070 |             // read attribute "alias" | 
|---|
| 1071 |             String alias = elem->Attribute("alias"); | 
|---|
| 1072 |             // read attribute "name" | 
|---|
| 1073 |             String name = elem->Attribute("name"); | 
|---|
| 1074 |  | 
|---|
| 1075 |             subMesh->addTextureAlias(alias, name); | 
|---|
| 1076 |         } | 
|---|
| 1077 |  | 
|---|
| 1078 |         LogManager::getSingleton().logMessage("Texture aliases done."); | 
|---|
| 1079 |     } | 
|---|
| 1080 |     //--------------------------------------------------------------------- | 
|---|
| 1081 |         void XMLMeshSerializer::readSubMeshNames(TiXmlElement* mMeshNamesNode, Mesh *sm) | 
|---|
| 1082 |         { | 
|---|
| 1083 |                 LogManager::getSingleton().logMessage("Reading mesh names..."); | 
|---|
| 1084 |  | 
|---|
| 1085 |                 // Iterate over all children (vertexboneassignment entries) | 
|---|
| 1086 |                 for (TiXmlElement* elem = mMeshNamesNode->FirstChildElement(); | 
|---|
| 1087 |                         elem != 0; elem = elem->NextSiblingElement()) | 
|---|
| 1088 |                 { | 
|---|
| 1089 |                         String meshName = elem->Attribute("name"); | 
|---|
| 1090 |                         int index = StringConverter::parseInt(elem->Attribute("index")); | 
|---|
| 1091 |  | 
|---|
| 1092 |                         sm->nameSubMesh(meshName, index); | 
|---|
| 1093 |                 } | 
|---|
| 1094 |  | 
|---|
| 1095 |                 LogManager::getSingleton().logMessage("Mesh names done."); | 
|---|
| 1096 |         } | 
|---|
| 1097 |     //--------------------------------------------------------------------- | 
|---|
| 1098 |     void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode, SubMesh* sm) | 
|---|
| 1099 |     { | 
|---|
| 1100 |         LogManager::getSingleton().logMessage("Reading bone assignments..."); | 
|---|
| 1101 |         // Iterate over all children (vertexboneassignment entries) | 
|---|
| 1102 |         for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement(); | 
|---|
| 1103 |         elem != 0; elem = elem->NextSiblingElement()) | 
|---|
| 1104 |         { | 
|---|
| 1105 |             VertexBoneAssignment vba; | 
|---|
| 1106 |             vba.vertexIndex = StringConverter::parseInt( | 
|---|
| 1107 |                 elem->Attribute("vertexindex")); | 
|---|
| 1108 |             vba.boneIndex = StringConverter::parseInt( | 
|---|
| 1109 |                 elem->Attribute("boneindex")); | 
|---|
| 1110 |             vba.weight= StringConverter::parseReal( | 
|---|
| 1111 |                 elem->Attribute("weight")); | 
|---|
| 1112 |  | 
|---|
| 1113 |             sm->addBoneAssignment(vba); | 
|---|
| 1114 |         } | 
|---|
| 1115 |         LogManager::getSingleton().logMessage("Bone assignments done."); | 
|---|
| 1116 |     } | 
|---|
| 1117 |     //--------------------------------------------------------------------- | 
|---|
| 1118 |         void XMLMeshSerializer::writeLodInfo(TiXmlElement* mMeshNode, const Mesh* pMesh) | 
|---|
| 1119 |         { | 
|---|
| 1120 |         TiXmlElement* lodNode =  | 
|---|
| 1121 |             mMeshNode->InsertEndChild(TiXmlElement("levelofdetail"))->ToElement(); | 
|---|
| 1122 |  | 
|---|
| 1123 |                 unsigned short numLvls = pMesh->getNumLodLevels(); | 
|---|
| 1124 |                 bool manual = pMesh->isLodManual(); | 
|---|
| 1125 |                 lodNode->SetAttribute("numlevels", StringConverter::toString(numLvls)); | 
|---|
| 1126 |                 lodNode->SetAttribute("manual", StringConverter::toString(manual)); | 
|---|
| 1127 |  | 
|---|
| 1128 |                 // Iterate from level 1, not 0 (full detail) | 
|---|
| 1129 |                 for (unsigned short i = 1; i < numLvls; ++i) | 
|---|
| 1130 |                 { | 
|---|
| 1131 |                         const MeshLodUsage& usage = pMesh->getLodLevel(i); | 
|---|
| 1132 |                         if (manual) | 
|---|
| 1133 |                         { | 
|---|
| 1134 |                                 writeLodUsageManual(lodNode, i, usage); | 
|---|
| 1135 |                         } | 
|---|
| 1136 |                         else | 
|---|
| 1137 |                         { | 
|---|
| 1138 |                                 writeLodUsageGenerated(lodNode, i, usage, pMesh); | 
|---|
| 1139 |                         } | 
|---|
| 1140 |                 } | 
|---|
| 1141 |  | 
|---|
| 1142 |         } | 
|---|
| 1143 |     //--------------------------------------------------------------------- | 
|---|
| 1144 |     void XMLMeshSerializer::writeSubMeshNames(TiXmlElement* mMeshNode, const Mesh* m) | 
|---|
| 1145 |     { | 
|---|
| 1146 |         const Mesh::SubMeshNameMap& nameMap = m->getSubMeshNameMap(); | 
|---|
| 1147 |         if (nameMap.empty()) | 
|---|
| 1148 |             return; // do nothing | 
|---|
| 1149 |  | 
|---|
| 1150 |         TiXmlElement* namesNode =  | 
|---|
| 1151 |             mMeshNode->InsertEndChild(TiXmlElement("submeshnames"))->ToElement(); | 
|---|
| 1152 |         Mesh::SubMeshNameMap::const_iterator i, iend; | 
|---|
| 1153 |         iend = nameMap.end(); | 
|---|
| 1154 |         for (i = nameMap.begin(); i != iend; ++i) | 
|---|
| 1155 |         { | 
|---|
| 1156 |             TiXmlElement* subNameNode =  | 
|---|
| 1157 |                 namesNode->InsertEndChild(TiXmlElement("submeshname"))->ToElement(); | 
|---|
| 1158 |  | 
|---|
| 1159 |             subNameNode->SetAttribute("name", i->first); | 
|---|
| 1160 |             subNameNode->SetAttribute("index",  | 
|---|
| 1161 |                 StringConverter::toString(i->second)); | 
|---|
| 1162 |         } | 
|---|
| 1163 |  | 
|---|
| 1164 |     } | 
|---|
| 1165 |     //--------------------------------------------------------------------- | 
|---|
| 1166 |         void XMLMeshSerializer::writeLodUsageManual(TiXmlElement* usageNode,  | 
|---|
| 1167 |                 unsigned short levelNum, const MeshLodUsage& usage) | 
|---|
| 1168 |         { | 
|---|
| 1169 |                 TiXmlElement* manualNode =  | 
|---|
| 1170 |                         usageNode->InsertEndChild(TiXmlElement("lodmanual"))->ToElement(); | 
|---|
| 1171 |  | 
|---|
| 1172 |                 manualNode->SetAttribute("fromdepthsquared",  | 
|---|
| 1173 |                         StringConverter::toString(usage.fromDepthSquared)); | 
|---|
| 1174 |                 manualNode->SetAttribute("meshname", usage.manualName); | 
|---|
| 1175 |  | 
|---|
| 1176 |         } | 
|---|
| 1177 |     //--------------------------------------------------------------------- | 
|---|
| 1178 |         void XMLMeshSerializer::writeLodUsageGenerated(TiXmlElement* usageNode,  | 
|---|
| 1179 |                 unsigned short levelNum,  const MeshLodUsage& usage,  | 
|---|
| 1180 |                 const Mesh* pMesh) | 
|---|
| 1181 |         { | 
|---|
| 1182 |                 TiXmlElement* generatedNode =  | 
|---|
| 1183 |                         usageNode->InsertEndChild(TiXmlElement("lodgenerated"))->ToElement(); | 
|---|
| 1184 |                 generatedNode->SetAttribute("fromdepthsquared",  | 
|---|
| 1185 |                         StringConverter::toString(usage.fromDepthSquared)); | 
|---|
| 1186 |  | 
|---|
| 1187 |                 // Iterate over submeshes at this level | 
|---|
| 1188 |                 unsigned short numsubs = pMesh->getNumSubMeshes(); | 
|---|
| 1189 |  | 
|---|
| 1190 |                 for (unsigned short subi = 0; subi < numsubs; ++subi) | 
|---|
| 1191 |                 { | 
|---|
| 1192 |                         TiXmlElement* subNode =  | 
|---|
| 1193 |                                 generatedNode->InsertEndChild(TiXmlElement("lodfacelist"))->ToElement(); | 
|---|
| 1194 |                         SubMesh* sub = pMesh->getSubMesh(subi); | 
|---|
| 1195 |                         subNode->SetAttribute("submeshindex", StringConverter::toString(subi)); | 
|---|
| 1196 |                         // NB level - 1 because SubMeshes don't store the first index in geometry | 
|---|
| 1197 |                     IndexData* facedata = sub->mLodFaceList[levelNum - 1]; | 
|---|
| 1198 |                         subNode->SetAttribute("numfaces", StringConverter::toString(facedata->indexCount / 3)); | 
|---|
| 1199 |  | 
|---|
| 1200 |                         // Write each face in turn | 
|---|
| 1201 |                     bool use32BitIndexes = (facedata->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT); | 
|---|
| 1202 |  | 
|---|
| 1203 |             // Write each face in turn | 
|---|
| 1204 |                     unsigned int* pInt; | 
|---|
| 1205 |                     unsigned short* pShort; | 
|---|
| 1206 |                     HardwareIndexBufferSharedPtr ibuf = facedata->indexBuffer; | 
|---|
| 1207 |                     if (use32BitIndexes) | 
|---|
| 1208 |                     { | 
|---|
| 1209 |                             pInt = static_cast<unsigned int*>( | 
|---|
| 1210 |                                     ibuf->lock(HardwareBuffer::HBL_READ_ONLY));  | 
|---|
| 1211 |                     } | 
|---|
| 1212 |                     else | 
|---|
| 1213 |                     { | 
|---|
| 1214 |                             pShort = static_cast<unsigned short*>( | 
|---|
| 1215 |                                     ibuf->lock(HardwareBuffer::HBL_READ_ONLY));  | 
|---|
| 1216 |                     } | 
|---|
| 1217 |                          | 
|---|
| 1218 |                         for (size_t f = 0; f < facedata->indexCount; f += 3) | 
|---|
| 1219 |                         { | 
|---|
| 1220 |                                 TiXmlElement* faceNode =  | 
|---|
| 1221 |                                         subNode->InsertEndChild(TiXmlElement("face"))->ToElement(); | 
|---|
| 1222 |                 if (use32BitIndexes) | 
|---|
| 1223 |                 { | 
|---|
| 1224 |                                     faceNode->SetAttribute("v1", StringConverter::toString(*pInt++)); | 
|---|
| 1225 |                                     faceNode->SetAttribute("v2", StringConverter::toString(*pInt++)); | 
|---|
| 1226 |                                     faceNode->SetAttribute("v3", StringConverter::toString(*pInt++)); | 
|---|
| 1227 |                 } | 
|---|
| 1228 |                 else | 
|---|
| 1229 |                 { | 
|---|
| 1230 |                                     faceNode->SetAttribute("v1", StringConverter::toString(*pShort++)); | 
|---|
| 1231 |                                     faceNode->SetAttribute("v2", StringConverter::toString(*pShort++)); | 
|---|
| 1232 |                                     faceNode->SetAttribute("v3", StringConverter::toString(*pShort++)); | 
|---|
| 1233 |                 } | 
|---|
| 1234 |  | 
|---|
| 1235 |                         } | 
|---|
| 1236 |  | 
|---|
| 1237 |  | 
|---|
| 1238 |  | 
|---|
| 1239 |                 } | 
|---|
| 1240 |  | 
|---|
| 1241 |         } | 
|---|
| 1242 |     //--------------------------------------------------------------------- | 
|---|
| 1243 |         void XMLMeshSerializer::writeExtremes(TiXmlElement* mMeshNode, const Mesh* m) | 
|---|
| 1244 |         { | 
|---|
| 1245 |                 TiXmlElement* extremesNode = NULL; | 
|---|
| 1246 |                 int idx = 0; | 
|---|
| 1247 |                 for (Mesh::SubMeshIterator i = ((Mesh &)*m).getSubMeshIterator (); | 
|---|
| 1248 |                          i.hasMoreElements (); i.moveNext (), ++idx) | 
|---|
| 1249 |                 { | 
|---|
| 1250 |                         SubMesh *sm = i.peekNext (); | 
|---|
| 1251 |                         if (sm->extremityPoints.empty()) | 
|---|
| 1252 |                                 continue; // do nothing | 
|---|
| 1253 |  | 
|---|
| 1254 |                         if (!extremesNode) | 
|---|
| 1255 |                                 extremesNode = mMeshNode->InsertEndChild(TiXmlElement("extremes"))->ToElement(); | 
|---|
| 1256 |  | 
|---|
| 1257 |                         TiXmlElement* submeshNode = | 
|---|
| 1258 |                                 extremesNode->InsertEndChild(TiXmlElement("submesh_extremes"))->ToElement(); | 
|---|
| 1259 |  | 
|---|
| 1260 |                         submeshNode->SetAttribute("index",  StringConverter::toString(idx)); | 
|---|
| 1261 |  | 
|---|
| 1262 |                         for (std::vector<Vector3>::const_iterator v = sm->extremityPoints.begin (); | 
|---|
| 1263 |                                  v != sm->extremityPoints.end (); ++v) | 
|---|
| 1264 |                         { | 
|---|
| 1265 |                                 TiXmlElement* vert = submeshNode->InsertEndChild( | 
|---|
| 1266 |                                         TiXmlElement("position"))->ToElement(); | 
|---|
| 1267 |                                 vert->SetAttribute("x", StringConverter::toString(v->x)); | 
|---|
| 1268 |                                 vert->SetAttribute("y", StringConverter::toString(v->y)); | 
|---|
| 1269 |                                 vert->SetAttribute("z", StringConverter::toString(v->z)); | 
|---|
| 1270 |                         } | 
|---|
| 1271 |                 } | 
|---|
| 1272 |         } | 
|---|
| 1273 |         //--------------------------------------------------------------------- | 
|---|
| 1274 |         void XMLMeshSerializer::readLodInfo(TiXmlElement*  lodNode) | 
|---|
| 1275 |         { | 
|---|
| 1276 |                  | 
|---|
| 1277 |         LogManager::getSingleton().logMessage("Parsing LOD information..."); | 
|---|
| 1278 |  | 
|---|
| 1279 |                 const char* val = lodNode->Attribute("numlevels"); | 
|---|
| 1280 |                 unsigned short numLevels = static_cast<unsigned short>( | 
|---|
| 1281 |                         StringConverter::parseUnsignedInt(val)); | 
|---|
| 1282 |  | 
|---|
| 1283 |                 val = lodNode->Attribute("manual"); | 
|---|
| 1284 |                 bool manual = StringConverter::parseBool(val); | 
|---|
| 1285 |  | 
|---|
| 1286 |                 // Set up the basic structures | 
|---|
| 1287 |                 mpMesh->_setLodInfo(numLevels, manual); | 
|---|
| 1288 |  | 
|---|
| 1289 |                 // Parse the detail, start from 1 (the first sub-level of detail) | 
|---|
| 1290 |                 unsigned short i = 1; | 
|---|
| 1291 |                 TiXmlElement* usageElem; | 
|---|
| 1292 |                 if (manual) | 
|---|
| 1293 |                 { | 
|---|
| 1294 |                         usageElem = lodNode->FirstChildElement("lodmanual"); | 
|---|
| 1295 |                 } | 
|---|
| 1296 |                 else | 
|---|
| 1297 |                 { | 
|---|
| 1298 |                         usageElem = lodNode->FirstChildElement("lodgenerated"); | 
|---|
| 1299 |                 } | 
|---|
| 1300 |                 while (usageElem) | 
|---|
| 1301 |                 { | 
|---|
| 1302 |                         if (manual) | 
|---|
| 1303 |                         { | 
|---|
| 1304 |                                 readLodUsageManual(usageElem, i); | 
|---|
| 1305 |                                 usageElem = usageElem->NextSiblingElement(); | 
|---|
| 1306 |                         } | 
|---|
| 1307 |                         else | 
|---|
| 1308 |                         { | 
|---|
| 1309 |                                 readLodUsageGenerated(usageElem, i); | 
|---|
| 1310 |                                 usageElem = usageElem->NextSiblingElement(); | 
|---|
| 1311 |                         } | 
|---|
| 1312 |                         ++i; | 
|---|
| 1313 |                 } | 
|---|
| 1314 |                  | 
|---|
| 1315 |         LogManager::getSingleton().logMessage("LOD information done."); | 
|---|
| 1316 |                  | 
|---|
| 1317 |         } | 
|---|
| 1318 |     //--------------------------------------------------------------------- | 
|---|
| 1319 |         void XMLMeshSerializer::readLodUsageManual(TiXmlElement* manualNode, unsigned short index) | 
|---|
| 1320 |         { | 
|---|
| 1321 |                 MeshLodUsage usage; | 
|---|
| 1322 |                 const char* val = manualNode->Attribute("fromdepthsquared"); | 
|---|
| 1323 |                 usage.fromDepthSquared = StringConverter::parseReal(val); | 
|---|
| 1324 |                 usage.manualName = manualNode->Attribute("meshname"); | 
|---|
| 1325 |         usage.edgeData = NULL; | 
|---|
| 1326 |  | 
|---|
| 1327 |                 mpMesh->_setLodUsage(index, usage); | 
|---|
| 1328 |         } | 
|---|
| 1329 |     //--------------------------------------------------------------------- | 
|---|
| 1330 |         void XMLMeshSerializer::readLodUsageGenerated(TiXmlElement* genNode, unsigned short index) | 
|---|
| 1331 |         { | 
|---|
| 1332 |                 MeshLodUsage usage; | 
|---|
| 1333 |                 const char* val = genNode->Attribute("fromdepthsquared"); | 
|---|
| 1334 |                 usage.fromDepthSquared = StringConverter::parseReal(val); | 
|---|
| 1335 |                 usage.manualMesh.setNull(); | 
|---|
| 1336 |                 usage.manualName = ""; | 
|---|
| 1337 |         usage.edgeData = NULL; | 
|---|
| 1338 |  | 
|---|
| 1339 |                 mpMesh->_setLodUsage(index, usage); | 
|---|
| 1340 |  | 
|---|
| 1341 |                 // Read submesh face lists | 
|---|
| 1342 |                 TiXmlElement* faceListElem = genNode->FirstChildElement("lodfacelist"); | 
|---|
| 1343 |                 while (faceListElem) | 
|---|
| 1344 |                 { | 
|---|
| 1345 |                         val = faceListElem->Attribute("submeshindex"); | 
|---|
| 1346 |                         unsigned short subidx = StringConverter::parseUnsignedInt(val); | 
|---|
| 1347 |                         val = faceListElem->Attribute("numfaces"); | 
|---|
| 1348 |                         unsigned short numFaces = StringConverter::parseUnsignedInt(val); | 
|---|
| 1349 |             // use of 32bit indexes depends on submesh | 
|---|
| 1350 |             HardwareIndexBuffer::IndexType itype =  | 
|---|
| 1351 |                 mpMesh->getSubMesh(subidx)->indexData->indexBuffer->getType(); | 
|---|
| 1352 |             bool use32bitindexes = (itype == HardwareIndexBuffer::IT_32BIT); | 
|---|
| 1353 |  | 
|---|
| 1354 |             // Assign memory: this will be deleted by the submesh  | 
|---|
| 1355 |             HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). | 
|---|
| 1356 |                 createIndexBuffer( | 
|---|
| 1357 |                     itype, numFaces * 3, HardwareBuffer::HBU_STATIC_WRITE_ONLY); | 
|---|
| 1358 |  | 
|---|
| 1359 |             unsigned short *pShort; | 
|---|
| 1360 |             unsigned int *pInt; | 
|---|
| 1361 |             if (use32bitindexes) | 
|---|
| 1362 |             { | 
|---|
| 1363 |                 pInt = static_cast<unsigned int*>( | 
|---|
| 1364 |                     ibuf->lock(HardwareBuffer::HBL_DISCARD)); | 
|---|
| 1365 |             } | 
|---|
| 1366 |             else | 
|---|
| 1367 |             { | 
|---|
| 1368 |                 pShort = static_cast<unsigned short*>( | 
|---|
| 1369 |                     ibuf->lock(HardwareBuffer::HBL_DISCARD)); | 
|---|
| 1370 |             } | 
|---|
| 1371 |             TiXmlElement* faceElem = faceListElem->FirstChildElement("face"); | 
|---|
| 1372 |                         for (unsigned int face = 0; face < numFaces; ++face, faceElem = faceElem->NextSiblingElement()) | 
|---|
| 1373 |                         { | 
|---|
| 1374 |                 if (use32bitindexes) | 
|---|
| 1375 |                 { | 
|---|
| 1376 |                     val = faceElem->Attribute("v1"); | 
|---|
| 1377 |                                     *pInt++ = StringConverter::parseUnsignedInt(val); | 
|---|
| 1378 |                                     val = faceElem->Attribute("v2"); | 
|---|
| 1379 |                                     *pInt++ = StringConverter::parseUnsignedInt(val); | 
|---|
| 1380 |                                     val = faceElem->Attribute("v3"); | 
|---|
| 1381 |                                     *pInt++ = StringConverter::parseUnsignedInt(val); | 
|---|
| 1382 |                 } | 
|---|
| 1383 |                 else | 
|---|
| 1384 |                 { | 
|---|
| 1385 |                     val = faceElem->Attribute("v1"); | 
|---|
| 1386 |                                     *pShort++ = StringConverter::parseUnsignedInt(val); | 
|---|
| 1387 |                                     val = faceElem->Attribute("v2"); | 
|---|
| 1388 |                                     *pShort++ = StringConverter::parseUnsignedInt(val); | 
|---|
| 1389 |                                     val = faceElem->Attribute("v3"); | 
|---|
| 1390 |                                     *pShort++ = StringConverter::parseUnsignedInt(val); | 
|---|
| 1391 |                 } | 
|---|
| 1392 |  | 
|---|
| 1393 |                         } | 
|---|
| 1394 |  | 
|---|
| 1395 |             ibuf->unlock(); | 
|---|
| 1396 |                         IndexData* facedata = new IndexData(); // will be deleted by SubMesh | 
|---|
| 1397 |                         facedata->indexCount = numFaces * 3; | 
|---|
| 1398 |             facedata->indexStart = 0; | 
|---|
| 1399 |             facedata->indexBuffer = ibuf; | 
|---|
| 1400 |                         mpMesh->_setSubMeshLodFaceList(subidx, index, facedata); | 
|---|
| 1401 |  | 
|---|
| 1402 |                         faceListElem = faceListElem->NextSiblingElement(); | 
|---|
| 1403 |                 } | 
|---|
| 1404 |          | 
|---|
| 1405 |         } | 
|---|
| 1406 |         //----------------------------------------------------------------------------- | 
|---|
| 1407 |         void XMLMeshSerializer::readExtremes(TiXmlElement* extremesNode, Mesh *m) | 
|---|
| 1408 |         { | 
|---|
| 1409 |                 LogManager::getSingleton().logMessage("Reading extremes..."); | 
|---|
| 1410 |  | 
|---|
| 1411 |                 // Iterate over all children (submesh_extreme list) | 
|---|
| 1412 |                 for (TiXmlElement* elem = extremesNode->FirstChildElement(); | 
|---|
| 1413 |                          elem != 0; elem = elem->NextSiblingElement()) | 
|---|
| 1414 |                 { | 
|---|
| 1415 |                         int index = StringConverter::parseInt(elem->Attribute("index")); | 
|---|
| 1416 |  | 
|---|
| 1417 |                         SubMesh *sm = m->getSubMesh(index); | 
|---|
| 1418 |                         sm->extremityPoints.clear (); | 
|---|
| 1419 |                         for (TiXmlElement* vert = elem->FirstChildElement(); | 
|---|
| 1420 |                                  vert != 0; vert = vert->NextSiblingElement()) | 
|---|
| 1421 |                         { | 
|---|
| 1422 |                                 Vector3 v; | 
|---|
| 1423 |                                 v.x = StringConverter::parseReal(vert->Attribute("x")); | 
|---|
| 1424 |                                 v.y = StringConverter::parseReal(vert->Attribute("y")); | 
|---|
| 1425 |                                 v.z = StringConverter::parseReal(vert->Attribute("z")); | 
|---|
| 1426 |                                 sm->extremityPoints.push_back (v); | 
|---|
| 1427 |                         } | 
|---|
| 1428 |                 } | 
|---|
| 1429 |  | 
|---|
| 1430 |                 LogManager::getSingleton().logMessage("Extremes done."); | 
|---|
| 1431 |         } | 
|---|
| 1432 |         //----------------------------------------------------------------------------- | 
|---|
| 1433 |         void XMLMeshSerializer::readPoses(TiXmlElement* posesNode, Mesh *m) | 
|---|
| 1434 |         { | 
|---|
| 1435 |                 TiXmlElement* poseNode = posesNode->FirstChildElement("pose"); | 
|---|
| 1436 |  | 
|---|
| 1437 |                 while (poseNode) | 
|---|
| 1438 |                 { | 
|---|
| 1439 |                         const char* target = poseNode->Attribute("target"); | 
|---|
| 1440 |                         if (!target) | 
|---|
| 1441 |                         { | 
|---|
| 1442 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1443 |                                         "Required attribute 'target' missing on pose",  | 
|---|
| 1444 |                                         "XMLMeshSerializer::readPoses"); | 
|---|
| 1445 |                         } | 
|---|
| 1446 |                         unsigned short targetID; | 
|---|
| 1447 |                         if(String(target) == "mesh") | 
|---|
| 1448 |                         { | 
|---|
| 1449 |                                 targetID = 0; | 
|---|
| 1450 |                         } | 
|---|
| 1451 |                         else | 
|---|
| 1452 |                         { | 
|---|
| 1453 |                                 // submesh, get index | 
|---|
| 1454 |                                 const char* val = poseNode->Attribute("index"); | 
|---|
| 1455 |                                 if (!val) | 
|---|
| 1456 |                                 { | 
|---|
| 1457 |                                         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1458 |                                                 "Required attribute 'index' missing on pose",  | 
|---|
| 1459 |                                                 "XMLMeshSerializer::readPoses"); | 
|---|
| 1460 |                                 } | 
|---|
| 1461 |                                 unsigned short submeshIndex = static_cast<unsigned short>( | 
|---|
| 1462 |                                         StringConverter::parseUnsignedInt(val)); | 
|---|
| 1463 |  | 
|---|
| 1464 |                                 targetID = submeshIndex + 1; | 
|---|
| 1465 |                         } | 
|---|
| 1466 |  | 
|---|
| 1467 |                         String name; | 
|---|
| 1468 |                         const char* val = poseNode->Attribute("name"); | 
|---|
| 1469 |                         if (val) | 
|---|
| 1470 |                                 name = val; | 
|---|
| 1471 |                         Pose* pose = m->createPose(targetID, name); | 
|---|
| 1472 |  | 
|---|
| 1473 |                         TiXmlElement* poseOffsetNode = poseNode->FirstChildElement("poseoffset"); | 
|---|
| 1474 |                         while (poseOffsetNode) | 
|---|
| 1475 |                         { | 
|---|
| 1476 |                                 uint index = StringConverter::parseUnsignedInt( | 
|---|
| 1477 |                                         poseOffsetNode->Attribute("index")); | 
|---|
| 1478 |                                 Vector3 offset; | 
|---|
| 1479 |                                 offset.x = StringConverter::parseReal(poseOffsetNode->Attribute("x")); | 
|---|
| 1480 |                                 offset.y = StringConverter::parseReal(poseOffsetNode->Attribute("y")); | 
|---|
| 1481 |                                 offset.z = StringConverter::parseReal(poseOffsetNode->Attribute("z")); | 
|---|
| 1482 |  | 
|---|
| 1483 |                                 pose->addVertex(index, offset); | 
|---|
| 1484 |  | 
|---|
| 1485 |                                 poseOffsetNode = poseOffsetNode->NextSiblingElement(); | 
|---|
| 1486 |                         } | 
|---|
| 1487 |  | 
|---|
| 1488 |                         poseNode = poseNode->NextSiblingElement(); | 
|---|
| 1489 |  | 
|---|
| 1490 |                 } | 
|---|
| 1491 |  | 
|---|
| 1492 |  | 
|---|
| 1493 |         } | 
|---|
| 1494 |         //----------------------------------------------------------------------------- | 
|---|
| 1495 |         void XMLMeshSerializer::readAnimations(TiXmlElement* mAnimationsNode, Mesh *pMesh) | 
|---|
| 1496 |         { | 
|---|
| 1497 |                 TiXmlElement* animElem = mAnimationsNode->FirstChildElement("animation"); | 
|---|
| 1498 |                 while (animElem) | 
|---|
| 1499 |                 { | 
|---|
| 1500 |                         String name = animElem->Attribute("name"); | 
|---|
| 1501 |                         const char* charLen = animElem->Attribute("length"); | 
|---|
| 1502 |                         Real len = StringConverter::parseReal(charLen); | 
|---|
| 1503 |  | 
|---|
| 1504 |                         Animation* anim = pMesh->createAnimation(name, len); | 
|---|
| 1505 |  | 
|---|
| 1506 |                         TiXmlElement* tracksNode = animElem->FirstChildElement("tracks"); | 
|---|
| 1507 |                         if (tracksNode) | 
|---|
| 1508 |                         { | 
|---|
| 1509 |                                 readTracks(tracksNode, pMesh, anim); | 
|---|
| 1510 |                         } | 
|---|
| 1511 |  | 
|---|
| 1512 |                         animElem = animElem->NextSiblingElement(); | 
|---|
| 1513 |  | 
|---|
| 1514 |                 } | 
|---|
| 1515 |  | 
|---|
| 1516 |  | 
|---|
| 1517 |         } | 
|---|
| 1518 |         //----------------------------------------------------------------------------- | 
|---|
| 1519 |         void XMLMeshSerializer::readTracks(TiXmlElement* tracksNode, Mesh *m, Animation* anim) | 
|---|
| 1520 |         { | 
|---|
| 1521 |                 TiXmlElement* trackNode = tracksNode->FirstChildElement("track"); | 
|---|
| 1522 |                 while (trackNode) | 
|---|
| 1523 |                 { | 
|---|
| 1524 |                         String target = trackNode->Attribute("target"); | 
|---|
| 1525 |                         unsigned short targetID; | 
|---|
| 1526 |                         VertexData* vertexData = 0; | 
|---|
| 1527 |                         if(target == "mesh") | 
|---|
| 1528 |                         { | 
|---|
| 1529 |                                 targetID = 0; | 
|---|
| 1530 |                                 vertexData = m->sharedVertexData; | 
|---|
| 1531 |                         } | 
|---|
| 1532 |                         else | 
|---|
| 1533 |                         { | 
|---|
| 1534 |                                 // submesh, get index | 
|---|
| 1535 |                                 const char* val = trackNode->Attribute("index"); | 
|---|
| 1536 |                                 if (!val) | 
|---|
| 1537 |                                 { | 
|---|
| 1538 |                                         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1539 |                                                 "Required attribute 'index' missing on submesh track",  | 
|---|
| 1540 |                                                 "XMLMeshSerializer::readTracks"); | 
|---|
| 1541 |                                 } | 
|---|
| 1542 |                                 unsigned short submeshIndex = static_cast<unsigned short>( | 
|---|
| 1543 |                                         StringConverter::parseUnsignedInt(val)); | 
|---|
| 1544 |  | 
|---|
| 1545 |                                 targetID = submeshIndex + 1; | 
|---|
| 1546 |                                 vertexData = m->getSubMesh(submeshIndex)->vertexData; | 
|---|
| 1547 |  | 
|---|
| 1548 |                         } | 
|---|
| 1549 |  | 
|---|
| 1550 |                         if (!vertexData) | 
|---|
| 1551 |                         { | 
|---|
| 1552 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1553 |                                         "Track cannot be created for " + target + " since VertexData " | 
|---|
| 1554 |                                         "does not exist at the specified index",  | 
|---|
| 1555 |                                         "XMLMeshSerializer::readTracks"); | 
|---|
| 1556 |                         } | 
|---|
| 1557 |  | 
|---|
| 1558 |                         // Get type | 
|---|
| 1559 |                         VertexAnimationType animType = VAT_NONE; | 
|---|
| 1560 |                         String strAnimType = trackNode->Attribute("type"); | 
|---|
| 1561 |                         if (strAnimType == "morph") | 
|---|
| 1562 |                         { | 
|---|
| 1563 |                                 animType = VAT_MORPH; | 
|---|
| 1564 |                         } | 
|---|
| 1565 |                         else if (strAnimType == "pose") | 
|---|
| 1566 |                         { | 
|---|
| 1567 |                                 animType = VAT_POSE; | 
|---|
| 1568 |                         } | 
|---|
| 1569 |                         else | 
|---|
| 1570 |                         { | 
|---|
| 1571 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1572 |                                         "Unrecognised animation track type '" + strAnimType + "'", | 
|---|
| 1573 |                                         "XMLMeshSerializer::readTracks"); | 
|---|
| 1574 |                         } | 
|---|
| 1575 |  | 
|---|
| 1576 |                         // Create track | 
|---|
| 1577 |                         VertexAnimationTrack* track =  | 
|---|
| 1578 |                                 anim->createVertexTrack(targetID, vertexData, animType); | 
|---|
| 1579 |  | 
|---|
| 1580 |                         TiXmlElement* keyframesNode = trackNode->FirstChildElement("keyframes"); | 
|---|
| 1581 |                         if (keyframesNode) | 
|---|
| 1582 |                         { | 
|---|
| 1583 |                                 if (track->getAnimationType() == VAT_MORPH) | 
|---|
| 1584 |                                 { | 
|---|
| 1585 |                                         readMorphKeyFrames(keyframesNode, track, vertexData->vertexCount); | 
|---|
| 1586 |                                 } | 
|---|
| 1587 |                                 else // VAT_POSE | 
|---|
| 1588 |                                 { | 
|---|
| 1589 |                                         readPoseKeyFrames(keyframesNode, track); | 
|---|
| 1590 |                                 } | 
|---|
| 1591 |                         } | 
|---|
| 1592 |  | 
|---|
| 1593 |                         trackNode = trackNode->NextSiblingElement(); | 
|---|
| 1594 |                 } | 
|---|
| 1595 |         } | 
|---|
| 1596 |         //----------------------------------------------------------------------------- | 
|---|
| 1597 |         void XMLMeshSerializer::readMorphKeyFrames(TiXmlElement* keyframesNode,  | 
|---|
| 1598 |                 VertexAnimationTrack* track, size_t vertexCount) | 
|---|
| 1599 |         { | 
|---|
| 1600 |                 TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe"); | 
|---|
| 1601 |                 while (keyNode) | 
|---|
| 1602 |                 { | 
|---|
| 1603 |                         const char* val = keyNode->Attribute("time"); | 
|---|
| 1604 |                         if (!val) | 
|---|
| 1605 |                         { | 
|---|
| 1606 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1607 |                                         "Required attribute 'time' missing on keyframe",  | 
|---|
| 1608 |                                         "XMLMeshSerializer::readKeyFrames"); | 
|---|
| 1609 |                         } | 
|---|
| 1610 |                         Real time = StringConverter::parseReal(val); | 
|---|
| 1611 |  | 
|---|
| 1612 |                         VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(time); | 
|---|
| 1613 |  | 
|---|
| 1614 |                         // create a vertex buffer | 
|---|
| 1615 |                         HardwareVertexBufferSharedPtr vbuf =  | 
|---|
| 1616 |                                 HardwareBufferManager::getSingleton().createVertexBuffer( | 
|---|
| 1617 |                                 VertexElement::getTypeSize(VET_FLOAT3), vertexCount,  | 
|---|
| 1618 |                                 HardwareBuffer::HBU_STATIC, true); | 
|---|
| 1619 |  | 
|---|
| 1620 |                         float* pFloat = static_cast<float*>( | 
|---|
| 1621 |                                 vbuf->lock(HardwareBuffer::HBL_DISCARD)); | 
|---|
| 1622 |  | 
|---|
| 1623 |  | 
|---|
| 1624 |                         TiXmlElement* posNode = keyNode->FirstChildElement("position"); | 
|---|
| 1625 |                         for (size_t v = 0; v < vertexCount; ++v) | 
|---|
| 1626 |                         { | 
|---|
| 1627 |                                 if (!posNode) | 
|---|
| 1628 |                                 { | 
|---|
| 1629 |                                         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1630 |                                                 "Not enough 'position' elements under keyframe",  | 
|---|
| 1631 |                                                 "XMLMeshSerializer::readKeyFrames"); | 
|---|
| 1632 |  | 
|---|
| 1633 |                                 } | 
|---|
| 1634 |  | 
|---|
| 1635 |                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 1636 |                                         posNode->Attribute("x")); | 
|---|
| 1637 |                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 1638 |                                         posNode->Attribute("y")); | 
|---|
| 1639 |                                 *pFloat++ = StringConverter::parseReal( | 
|---|
| 1640 |                                         posNode->Attribute("z")); | 
|---|
| 1641 |  | 
|---|
| 1642 |  | 
|---|
| 1643 |                                 posNode = posNode->NextSiblingElement("position"); | 
|---|
| 1644 |                         } | 
|---|
| 1645 |  | 
|---|
| 1646 |                         vbuf->unlock(); | 
|---|
| 1647 |  | 
|---|
| 1648 |                         kf->setVertexBuffer(vbuf); | 
|---|
| 1649 |                                  | 
|---|
| 1650 |  | 
|---|
| 1651 |                         keyNode = keyNode->NextSiblingElement(); | 
|---|
| 1652 |                 } | 
|---|
| 1653 |  | 
|---|
| 1654 |  | 
|---|
| 1655 |         } | 
|---|
| 1656 |         //----------------------------------------------------------------------------- | 
|---|
| 1657 |         void XMLMeshSerializer::readPoseKeyFrames(TiXmlElement* keyframesNode, VertexAnimationTrack* track) | 
|---|
| 1658 |         { | 
|---|
| 1659 |                 TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe"); | 
|---|
| 1660 |                 while (keyNode) | 
|---|
| 1661 |                 { | 
|---|
| 1662 |                         const char* val = keyNode->Attribute("time"); | 
|---|
| 1663 |                         if (!val) | 
|---|
| 1664 |                         { | 
|---|
| 1665 |                                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1666 |                                         "Required attribute 'time' missing on keyframe",  | 
|---|
| 1667 |                                         "XMLMeshSerializer::readKeyFrames"); | 
|---|
| 1668 |                         } | 
|---|
| 1669 |                         Real time = StringConverter::parseReal(val); | 
|---|
| 1670 |  | 
|---|
| 1671 |                         VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(time); | 
|---|
| 1672 |  | 
|---|
| 1673 |                         // Read all pose references | 
|---|
| 1674 |                         TiXmlElement* poseRefNode = keyNode->FirstChildElement("poseref"); | 
|---|
| 1675 |                         while (poseRefNode) | 
|---|
| 1676 |                         { | 
|---|
| 1677 |                                 const char* val = poseRefNode->Attribute("poseindex"); | 
|---|
| 1678 |                                 if (!val) | 
|---|
| 1679 |                                 { | 
|---|
| 1680 |                                         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,  | 
|---|
| 1681 |                                                 "Required attribute 'poseindex' missing on poseref",  | 
|---|
| 1682 |                                                 "XMLMeshSerializer::readPoseKeyFrames"); | 
|---|
| 1683 |                                 } | 
|---|
| 1684 |                                 unsigned short poseIndex = StringConverter::parseUnsignedInt(val); | 
|---|
| 1685 |                                 Real influence = 1.0f; | 
|---|
| 1686 |                                 val = poseRefNode->Attribute("influence"); | 
|---|
| 1687 |                                 if (val) | 
|---|
| 1688 |                                 { | 
|---|
| 1689 |                                         influence = StringConverter::parseReal(val); | 
|---|
| 1690 |                                 } | 
|---|
| 1691 |  | 
|---|
| 1692 |                                 kf->addPoseReference(poseIndex, influence); | 
|---|
| 1693 |  | 
|---|
| 1694 |                                 poseRefNode = poseRefNode->NextSiblingElement(); | 
|---|
| 1695 |                         } | 
|---|
| 1696 |  | 
|---|
| 1697 |                         keyNode = keyNode->NextSiblingElement(); | 
|---|
| 1698 |                 } | 
|---|
| 1699 |  | 
|---|
| 1700 |         } | 
|---|
| 1701 |         //----------------------------------------------------------------------------- | 
|---|
| 1702 |         void XMLMeshSerializer::writePoses(TiXmlElement* meshNode, const Mesh* m) | 
|---|
| 1703 |         { | 
|---|
| 1704 |                 if (m->getPoseCount() == 0) | 
|---|
| 1705 |                         return; | 
|---|
| 1706 |  | 
|---|
| 1707 |                 TiXmlElement* posesNode =  | 
|---|
| 1708 |                         meshNode->InsertEndChild(TiXmlElement("poses"))->ToElement(); | 
|---|
| 1709 |  | 
|---|
| 1710 |                 Mesh::ConstPoseIterator poseIt = m->getPoseIterator(); | 
|---|
| 1711 |                 while (poseIt.hasMoreElements()) | 
|---|
| 1712 |                 { | 
|---|
| 1713 |                         const Pose* pose = poseIt.getNext(); | 
|---|
| 1714 |                         TiXmlElement* poseNode =  | 
|---|
| 1715 |                                 posesNode->InsertEndChild(TiXmlElement("pose"))->ToElement(); | 
|---|
| 1716 |                         unsigned short target = pose->getTarget(); | 
|---|
| 1717 |                         if (target == 0) | 
|---|
| 1718 |                         { | 
|---|
| 1719 |                                 // Main mesh | 
|---|
| 1720 |                                 poseNode->SetAttribute("target", "mesh"); | 
|---|
| 1721 |                         } | 
|---|
| 1722 |                         else | 
|---|
| 1723 |                         { | 
|---|
| 1724 |                                 // Submesh - rebase index | 
|---|
| 1725 |                                 poseNode->SetAttribute("target", "submesh"); | 
|---|
| 1726 |                                 poseNode->SetAttribute("index",  | 
|---|
| 1727 |                                         StringConverter::toString(target - 1)); | 
|---|
| 1728 |                         } | 
|---|
| 1729 |                         poseNode->SetAttribute("name", pose->getName()); | 
|---|
| 1730 |  | 
|---|
| 1731 |                         Pose::ConstVertexOffsetIterator vit = pose->getVertexOffsetIterator(); | 
|---|
| 1732 |                         while (vit.hasMoreElements()) | 
|---|
| 1733 |                         { | 
|---|
| 1734 |                                 TiXmlElement* poseOffsetElement = poseNode->InsertEndChild( | 
|---|
| 1735 |                                         TiXmlElement("poseoffset"))->ToElement(); | 
|---|
| 1736 |  | 
|---|
| 1737 |                                 poseOffsetElement->SetAttribute("index",  | 
|---|
| 1738 |                                         StringConverter::toString(vit.peekNextKey())); | 
|---|
| 1739 |  | 
|---|
| 1740 |                                 Vector3 offset = vit.getNext(); | 
|---|
| 1741 |                                 poseOffsetElement->SetAttribute("x", StringConverter::toString(offset.x)); | 
|---|
| 1742 |                                 poseOffsetElement->SetAttribute("y", StringConverter::toString(offset.y)); | 
|---|
| 1743 |                                 poseOffsetElement->SetAttribute("z", StringConverter::toString(offset.z)); | 
|---|
| 1744 |  | 
|---|
| 1745 |  | 
|---|
| 1746 |                         } | 
|---|
| 1747 |  | 
|---|
| 1748 |                 } | 
|---|
| 1749 |  | 
|---|
| 1750 |         } | 
|---|
| 1751 |         //----------------------------------------------------------------------------- | 
|---|
| 1752 |         void XMLMeshSerializer::writeAnimations(TiXmlElement* meshNode, const Mesh* m) | 
|---|
| 1753 |         { | 
|---|
| 1754 |                 // Skip if no animation | 
|---|
| 1755 |                 if (!m->hasVertexAnimation()) | 
|---|
| 1756 |                         return; | 
|---|
| 1757 |  | 
|---|
| 1758 |                 TiXmlElement* animationsNode =  | 
|---|
| 1759 |                         meshNode->InsertEndChild(TiXmlElement("animations"))->ToElement(); | 
|---|
| 1760 |  | 
|---|
| 1761 |                 for (unsigned short a = 0; a < m->getNumAnimations(); ++a) | 
|---|
| 1762 |                 { | 
|---|
| 1763 |                         Animation* anim = m->getAnimation(a); | 
|---|
| 1764 |  | 
|---|
| 1765 |                         TiXmlElement* animNode =  | 
|---|
| 1766 |                                 animationsNode->InsertEndChild(TiXmlElement("animation"))->ToElement(); | 
|---|
| 1767 |                         animNode->SetAttribute("name", anim->getName()); | 
|---|
| 1768 |                         animNode->SetAttribute("length",  | 
|---|
| 1769 |                                 StringConverter::toString(anim->getLength())); | 
|---|
| 1770 |  | 
|---|
| 1771 |                         TiXmlElement* tracksNode =  | 
|---|
| 1772 |                                 animNode->InsertEndChild(TiXmlElement("tracks"))->ToElement(); | 
|---|
| 1773 |                         Animation::VertexTrackIterator iter = anim->getVertexTrackIterator(); | 
|---|
| 1774 |                         while(iter.hasMoreElements()) | 
|---|
| 1775 |                         { | 
|---|
| 1776 |                                 const VertexAnimationTrack* track = iter.getNext(); | 
|---|
| 1777 |                                 TiXmlElement* trackNode =  | 
|---|
| 1778 |                                         tracksNode->InsertEndChild(TiXmlElement("track"))->ToElement(); | 
|---|
| 1779 |  | 
|---|
| 1780 |                                 unsigned short targetID = track->getHandle(); | 
|---|
| 1781 |                                 if (targetID == 0) | 
|---|
| 1782 |                                 { | 
|---|
| 1783 |                                         trackNode->SetAttribute("target", "mesh"); | 
|---|
| 1784 |                                 } | 
|---|
| 1785 |                                 else | 
|---|
| 1786 |                                 { | 
|---|
| 1787 |                                         trackNode->SetAttribute("target", "submesh"); | 
|---|
| 1788 |                                         trackNode->SetAttribute("index",  | 
|---|
| 1789 |                                                 StringConverter::toString(targetID-1)); | 
|---|
| 1790 |                                 } | 
|---|
| 1791 |  | 
|---|
| 1792 |                                 if (track->getAnimationType() == VAT_MORPH) | 
|---|
| 1793 |                                 { | 
|---|
| 1794 |                                         trackNode->SetAttribute("type", "morph"); | 
|---|
| 1795 |                                         writeMorphKeyFrames(trackNode, track); | 
|---|
| 1796 |                                 } | 
|---|
| 1797 |                                 else | 
|---|
| 1798 |                                 { | 
|---|
| 1799 |                                         trackNode->SetAttribute("type", "pose"); | 
|---|
| 1800 |                                         writePoseKeyFrames(trackNode, track); | 
|---|
| 1801 |                                 } | 
|---|
| 1802 |  | 
|---|
| 1803 |  | 
|---|
| 1804 |                         } | 
|---|
| 1805 |                 } | 
|---|
| 1806 |  | 
|---|
| 1807 |                  | 
|---|
| 1808 |         } | 
|---|
| 1809 |         //----------------------------------------------------------------------------- | 
|---|
| 1810 |         void XMLMeshSerializer::writeMorphKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track) | 
|---|
| 1811 |         { | 
|---|
| 1812 |                 TiXmlElement* keyframesNode =  | 
|---|
| 1813 |                         trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement(); | 
|---|
| 1814 |  | 
|---|
| 1815 |                 size_t vertexCount = track->getAssociatedVertexData()->vertexCount; | 
|---|
| 1816 |  | 
|---|
| 1817 |                 for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k) | 
|---|
| 1818 |                 { | 
|---|
| 1819 |                         VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(k); | 
|---|
| 1820 |                         TiXmlElement* keyNode =  | 
|---|
| 1821 |                                 keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement(); | 
|---|
| 1822 |                         keyNode->SetAttribute("time",  | 
|---|
| 1823 |                                 StringConverter::toString(kf->getTime())); | 
|---|
| 1824 |  | 
|---|
| 1825 |                         HardwareVertexBufferSharedPtr vbuf = kf->getVertexBuffer(); | 
|---|
| 1826 |                         float* pFloat = static_cast<float*>( | 
|---|
| 1827 |                                 vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); | 
|---|
| 1828 |  | 
|---|
| 1829 |                         for (size_t v = 0; v < vertexCount; ++v) | 
|---|
| 1830 |                         { | 
|---|
| 1831 |                                 TiXmlElement* posNode =  | 
|---|
| 1832 |                                         keyNode->InsertEndChild(TiXmlElement("position"))->ToElement(); | 
|---|
| 1833 |                                 posNode->SetAttribute("x", StringConverter::toString(*pFloat++)); | 
|---|
| 1834 |                                 posNode->SetAttribute("y", StringConverter::toString(*pFloat++)); | 
|---|
| 1835 |                                 posNode->SetAttribute("z", StringConverter::toString(*pFloat++)); | 
|---|
| 1836 |                         } | 
|---|
| 1837 |  | 
|---|
| 1838 |                 } | 
|---|
| 1839 |         } | 
|---|
| 1840 |         //----------------------------------------------------------------------------- | 
|---|
| 1841 |         void XMLMeshSerializer::writePoseKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track) | 
|---|
| 1842 |         { | 
|---|
| 1843 |                 TiXmlElement* keyframesNode =  | 
|---|
| 1844 |                         trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement(); | 
|---|
| 1845 |  | 
|---|
| 1846 |                 for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k) | 
|---|
| 1847 |                 { | 
|---|
| 1848 |                         VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(k); | 
|---|
| 1849 |                         TiXmlElement* keyNode =  | 
|---|
| 1850 |                                 keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement(); | 
|---|
| 1851 |                         keyNode->SetAttribute("time",  | 
|---|
| 1852 |                                 StringConverter::toString(kf->getTime())); | 
|---|
| 1853 |  | 
|---|
| 1854 |                         VertexPoseKeyFrame::PoseRefIterator poseIt = kf->getPoseReferenceIterator(); | 
|---|
| 1855 |                         while (poseIt.hasMoreElements()) | 
|---|
| 1856 |                         { | 
|---|
| 1857 |                                 const VertexPoseKeyFrame::PoseRef& poseRef = poseIt.getNext(); | 
|---|
| 1858 |                                 TiXmlElement* poseRefNode =  | 
|---|
| 1859 |                                         keyNode->InsertEndChild(TiXmlElement("poseref"))->ToElement(); | 
|---|
| 1860 |  | 
|---|
| 1861 |                                 poseRefNode->SetAttribute("poseindex",  | 
|---|
| 1862 |                                         StringConverter::toString(poseRef.poseIndex)); | 
|---|
| 1863 |                                 poseRefNode->SetAttribute("influence",  | 
|---|
| 1864 |                                         StringConverter::toString(poseRef.influence)); | 
|---|
| 1865 |  | 
|---|
| 1866 |                         } | 
|---|
| 1867 |  | 
|---|
| 1868 |                 } | 
|---|
| 1869 |  | 
|---|
| 1870 |  | 
|---|
| 1871 |         } | 
|---|
| 1872 |  | 
|---|
| 1873 |  | 
|---|
| 1874 |  | 
|---|
| 1875 |  | 
|---|
| 1876 | } | 
|---|
| 1877 |  | 
|---|