| 1 | /* |
|---|
| 2 | ----------------------------------------------------------------------------- |
|---|
| 3 | This source file is part of LEXIExporter |
|---|
| 4 | |
|---|
| 5 | Copyright 2006 NDS Limited |
|---|
| 6 | |
|---|
| 7 | Author(s): |
|---|
| 8 | Mark Folkenberg, |
|---|
| 9 | Bo Krohn |
|---|
| 10 | |
|---|
| 11 | This program is free software; you can redistribute it and/or modify it under |
|---|
| 12 | the terms of the GNU Lesser General Public License as published by the Free Software |
|---|
| 13 | Foundation; either version 2 of the License, or (at your option) any later |
|---|
| 14 | version. |
|---|
| 15 | |
|---|
| 16 | This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|---|
| 18 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
|---|
| 19 | |
|---|
| 20 | You should have received a copy of the GNU Lesser General Public License along with |
|---|
| 21 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
|---|
| 22 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
|---|
| 23 | http://www.gnu.org/copyleft/lesser.txt. |
|---|
| 24 | ----------------------------------------------------------------------------- |
|---|
| 25 | */ |
|---|
| 26 | |
|---|
| 27 | #include "LexiStdAfx.h" |
|---|
| 28 | #include "LexiOgreMeshCompiler.h" |
|---|
| 29 | #include "OgreDefaultHardwareBufferManager.h" |
|---|
| 30 | #include "LexiExportObject.h" |
|---|
| 31 | |
|---|
| 32 | COgreMeshCompiler::COgreMeshCompiler( CIntermediateMesh* pIntermediateMesh, const CDDObject* pConfig, Ogre::String filename) : |
|---|
| 33 | m_iBind(0), |
|---|
| 34 | m_MaxSquaredLength(0.0), |
|---|
| 35 | m_pOgreMesh(NULL), |
|---|
| 36 | m_bReindex(false), |
|---|
| 37 | m_bExportNormals(false), |
|---|
| 38 | m_bExportColours(false), |
|---|
| 39 | m_bExportTexUVs(false), |
|---|
| 40 | m_bExportSkeleton(false), |
|---|
| 41 | m_iNrVerts(0), |
|---|
| 42 | m_iNrPoses(0) |
|---|
| 43 | { |
|---|
| 44 | m_IndexBitType = Ogre::HardwareIndexBuffer::IT_16BIT; |
|---|
| 45 | |
|---|
| 46 | ReadConfig(pConfig); |
|---|
| 47 | |
|---|
| 48 | if(m_bReindex) |
|---|
| 49 | ReindexIntermediateBuffers(pIntermediateMesh); |
|---|
| 50 | |
|---|
| 51 | ///////////////////////////////////// |
|---|
| 52 | //MessageBox(NULL, "PreOgreMeshCreate","BREAK!",0); |
|---|
| 53 | ///////////////////////////////////// |
|---|
| 54 | |
|---|
| 55 | CreateOgreMesh(pIntermediateMesh); |
|---|
| 56 | |
|---|
| 57 | ///////////////////////////////////// |
|---|
| 58 | //MessageBox(NULL, "PreCreateBuffer","BREAK!",0); |
|---|
| 59 | ///////////////////////////////////// |
|---|
| 60 | |
|---|
| 61 | CreateBuffers(pIntermediateMesh); |
|---|
| 62 | |
|---|
| 63 | Ogre::LogManager::getSingletonPtr()->logMessage("OgreMeshCompiler: Creating Bounds"); |
|---|
| 64 | // create and register bounding box |
|---|
| 65 | CreateMeshBounds(); |
|---|
| 66 | |
|---|
| 67 | // ready for serialization! |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | COgreMeshCompiler::~COgreMeshCompiler() |
|---|
| 71 | { |
|---|
| 72 | LOGDEBUG "OgreMeshCompiler cleaned.."); |
|---|
| 73 | |
|---|
| 74 | Ogre::MeshManager* pMeshMgr = Ogre::MeshManager::getSingletonPtr(); |
|---|
| 75 | delete m_pOgreMesh->sharedVertexData; |
|---|
| 76 | pMeshMgr->unloadAll(); |
|---|
| 77 | pMeshMgr->removeAll(); |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | |
|---|
| 81 | void COgreMeshCompiler::ReadConfig( const CDDObject* pConfig ) |
|---|
| 82 | { |
|---|
| 83 | assert(pConfig); |
|---|
| 84 | |
|---|
| 85 | m_bReindex = pConfig->GetBool("reindexID"); |
|---|
| 86 | m_bExportNormals = pConfig->GetBool("normalsID"); |
|---|
| 87 | m_bExportColours = pConfig->GetBool("vertexColorsID"); |
|---|
| 88 | m_bExportTexUVs = pConfig->GetBool("uvID"); |
|---|
| 89 | |
|---|
| 90 | m_bExportSkeleton = false; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | |
|---|
| 94 | void COgreMeshCompiler::ReindexIntermediateBuffers( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 95 | { |
|---|
| 96 | assert(pIntermediateMesh); |
|---|
| 97 | |
|---|
| 98 | SharedUtilities::fastvector< CMeshArray* > bufferList; |
|---|
| 99 | bufferList.push_back(pIntermediateMesh->GetArray("position",0)); |
|---|
| 100 | |
|---|
| 101 | CMeshArray* pArray; |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | if(m_bExportNormals) |
|---|
| 105 | { |
|---|
| 106 | pArray = pIntermediateMesh->GetArray("normal",0); |
|---|
| 107 | if (pArray == NULL) |
|---|
| 108 | LOGWARNING "No Normals found, ignoring \"export normals\" option."); |
|---|
| 109 | else |
|---|
| 110 | bufferList.push_back(pArray); |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | |
|---|
| 114 | if(m_bExportColours) |
|---|
| 115 | { |
|---|
| 116 | pArray = pIntermediateMesh->GetArray("diffuse",0); |
|---|
| 117 | if (pArray != NULL) |
|---|
| 118 | bufferList.push_back(pArray); |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | if(m_bExportTexUVs) |
|---|
| 123 | { |
|---|
| 124 | // check all uv sets |
|---|
| 125 | for(unsigned int x = 1; x <= 99; x++) |
|---|
| 126 | { |
|---|
| 127 | char temp[32]; |
|---|
| 128 | sprintf(temp, "uv%i", x); |
|---|
| 129 | pArray = pIntermediateMesh->GetArray(temp,0); |
|---|
| 130 | if (pArray == NULL) |
|---|
| 131 | continue; |
|---|
| 132 | else |
|---|
| 133 | bufferList.push_back(pArray); |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | // Prepare bone vertex assignments |
|---|
| 138 | CIntermediateSkeleton* pISkel = pIntermediateMesh->GetSkeleton(); |
|---|
| 139 | SharedUtilities::fastvector< CMeshArray* > boneBuffer; |
|---|
| 140 | |
|---|
| 141 | if(pISkel != NULL) |
|---|
| 142 | { |
|---|
| 143 | // extract declaration map into individual arrays for reindexing |
|---|
| 144 | pISkel->ExtractVertexAssignmentsArrays(boneBuffer); |
|---|
| 145 | |
|---|
| 146 | for(int i=0; i < boneBuffer.size(); i++) |
|---|
| 147 | { |
|---|
| 148 | bufferList.push_back( boneBuffer[i] ); |
|---|
| 149 | } |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | pIntermediateMesh->Reindex( bufferList ); |
|---|
| 153 | |
|---|
| 154 | if(pISkel != NULL) |
|---|
| 155 | { |
|---|
| 156 | pISkel->ApplyVertexAssignmentsArrays(boneBuffer); |
|---|
| 157 | //Clean up |
|---|
| 158 | for(int i=0; i < boneBuffer.size(); i++) |
|---|
| 159 | { |
|---|
| 160 | delete boneBuffer[i]; |
|---|
| 161 | } |
|---|
| 162 | boneBuffer.clear(); |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | void COgreMeshCompiler::CreateOgreMesh( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 168 | { |
|---|
| 169 | Ogre::String sMeshName = pIntermediateMesh->getName(); |
|---|
| 170 | Ogre::MeshManager* pMeshMgr = Ogre::MeshManager::getSingletonPtr(); |
|---|
| 171 | Ogre::MeshPtr pOgreMesh = pMeshMgr->getByName(sMeshName); |
|---|
| 172 | |
|---|
| 173 | if(!pOgreMesh.isNull()) { |
|---|
| 174 | pMeshMgr->unload(pOgreMesh->getHandle()); |
|---|
| 175 | pMeshMgr->remove(pOgreMesh->getHandle()); |
|---|
| 176 | pOgreMesh.setNull(); |
|---|
| 177 | } |
|---|
| 178 | pOgreMesh = pMeshMgr->createManual(sMeshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); |
|---|
| 179 | m_pOgreMesh = pOgreMesh; |
|---|
| 180 | m_pOgreMesh->sharedVertexData = new Ogre::VertexData(); |
|---|
| 181 | |
|---|
| 182 | CreateSubMeshes( pIntermediateMesh ); |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | void COgreMeshCompiler::CreateSubMeshes( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 186 | { |
|---|
| 187 | assert(pIntermediateMesh); |
|---|
| 188 | assert(!m_pOgreMesh.isNull()); |
|---|
| 189 | |
|---|
| 190 | unsigned int iCount = pIntermediateMesh->GetNumMaterials(); |
|---|
| 191 | for (int i = 0; i < iCount; i++) |
|---|
| 192 | { |
|---|
| 193 | Ogre::SubMesh* pSubMesh = m_pOgreMesh->createSubMesh(); |
|---|
| 194 | CIntermediateMaterial* mat = pIntermediateMesh->GetMaterial(i); |
|---|
| 195 | m_lMaterialSubMeshMap.insert( std::pair<CIntermediateMaterial*,Ogre::SubMesh*>(mat,pSubMesh) ); |
|---|
| 196 | } |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | void COgreMeshCompiler::CreateBuffers( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 200 | { |
|---|
| 201 | assert(pIntermediateMesh); |
|---|
| 202 | assert(!m_pOgreMesh.isNull()); |
|---|
| 203 | |
|---|
| 204 | ///////////////////////////////////// |
|---|
| 205 | //MessageBox(NULL, "PreVertexBuffer","BREAK!",0); |
|---|
| 206 | ///////////////////////////////////// |
|---|
| 207 | CreateVertexBuffer(pIntermediateMesh); |
|---|
| 208 | |
|---|
| 209 | ///////////////////////////////////// |
|---|
| 210 | //MessageBox(NULL, "PreIndexBuffer","BREAK!",0); |
|---|
| 211 | ///////////////////////////////////// |
|---|
| 212 | CreateIndexBuffer(pIntermediateMesh); |
|---|
| 213 | |
|---|
| 214 | if(m_bExportNormals) |
|---|
| 215 | { |
|---|
| 216 | ///////////////////////////////////// |
|---|
| 217 | //MessageBox(NULL, "PreNormalBuffer","BREAK!",0); |
|---|
| 218 | ///////////////////////////////////// |
|---|
| 219 | CreateNormalBuffer(pIntermediateMesh); |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | if(m_bExportColours) |
|---|
| 223 | { |
|---|
| 224 | ///////////////////////////////////// |
|---|
| 225 | //MessageBox(NULL, "PreDiffuseBuffer","BREAK!",0); |
|---|
| 226 | ///////////////////////////////////// |
|---|
| 227 | CreateDiffuseBuffer(pIntermediateMesh); |
|---|
| 228 | } |
|---|
| 229 | if (m_bExportTexUVs) |
|---|
| 230 | { |
|---|
| 231 | ///////////////////////////////////// |
|---|
| 232 | //MessageBox(NULL, "PreTextureCoordBuffer","BREAK!",0); |
|---|
| 233 | ///////////////////////////////////// |
|---|
| 234 | CreateTexCoordBuffer(pIntermediateMesh); |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | if( pIntermediateMesh->HasPoseData() ) |
|---|
| 238 | { |
|---|
| 239 | CreatePoseBuffers(pIntermediateMesh); |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | //"specular" |
|---|
| 243 | //"boneindex" |
|---|
| 244 | //"blendweight" |
|---|
| 245 | //"binormal" |
|---|
| 246 | //"tangent" |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | void COgreMeshCompiler::CreateVertexBuffer( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 250 | { |
|---|
| 251 | assert(pIntermediateMesh); |
|---|
| 252 | CMeshArray* pMeshArray = pIntermediateMesh->GetArray("position",0); |
|---|
| 253 | if(pMeshArray == NULL) |
|---|
| 254 | return; |
|---|
| 255 | |
|---|
| 256 | m_iNrVerts = pMeshArray->Size(); |
|---|
| 257 | |
|---|
| 258 | Ogre::VertexData* vertexData = m_pOgreMesh->sharedVertexData; |
|---|
| 259 | Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; |
|---|
| 260 | |
|---|
| 261 | // allocate the position vertex buffer |
|---|
| 262 | vertexDecl->addElement(m_iBind, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); |
|---|
| 263 | vertexData->vertexCount = m_iNrVerts; |
|---|
| 264 | |
|---|
| 265 | { // DEBUG INFO |
|---|
| 266 | //Ogre::StringUtil::StrStreamType strStrm; |
|---|
| 267 | //strStrm << "Export: Vertex Size: " << vertexDecl->getVertexSize(m_iBind) << " | Vertex Count: " << vertexData->vertexCount << " | Buffer Size: " << vertexDecl->getVertexSize(m_iBind)*vertexData->vertexCount; |
|---|
| 268 | //Ogre::LogManager::getSingletonPtr()->logMessage(strStrm.str()); |
|---|
| 269 | } |
|---|
| 270 | |
|---|
| 271 | vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(m_iBind), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); |
|---|
| 272 | Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding; |
|---|
| 273 | binding->setBinding(m_iBind, vBuf); |
|---|
| 274 | const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->getElement(m_iBind); |
|---|
| 275 | unsigned char* vertex = static_cast<unsigned char*>(vBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); |
|---|
| 276 | m_iBind++; |
|---|
| 277 | |
|---|
| 278 | |
|---|
| 279 | // Ok, Let´s fill in the buffer with data :D |
|---|
| 280 | |
|---|
| 281 | const Ogre::Vector3* data = (const Ogre::Vector3*)pMeshArray->Data(); |
|---|
| 282 | |
|---|
| 283 | Ogre::Real* pReal; |
|---|
| 284 | posElem->baseVertexPointerToElement(vertex, &pReal); |
|---|
| 285 | |
|---|
| 286 | unsigned int j = 0; |
|---|
| 287 | for(unsigned int i=0; i< m_iNrVerts; i++) { |
|---|
| 288 | |
|---|
| 289 | Ogre::Vector3 vert = data[i]; |
|---|
| 290 | |
|---|
| 291 | *pReal++ = vert.x; |
|---|
| 292 | *pReal++ = vert.y; |
|---|
| 293 | *pReal++ = vert.z; |
|---|
| 294 | |
|---|
| 295 | // Bounding Sphere radius |
|---|
| 296 | m_MaxSquaredLength = std::max(m_MaxSquaredLength, vert.squaredLength()); |
|---|
| 297 | |
|---|
| 298 | // update AABB |
|---|
| 299 | m_AABB.merge( vert ); |
|---|
| 300 | } |
|---|
| 301 | vBuf->unlock(); |
|---|
| 302 | |
|---|
| 303 | //Ogre::StringUtil::StrStreamType strStrm; |
|---|
| 304 | //strStrm << "Export: #Vertices: " << iNrVerts; |
|---|
| 305 | //Ogre::LogManager::getSingletonPtr()->logMessage(strStrm.str()); |
|---|
| 306 | |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | void COgreMeshCompiler::CreateIndexBuffer( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 310 | { |
|---|
| 311 | assert(pIntermediateMesh); |
|---|
| 312 | |
|---|
| 313 | const CTriangleArray& triangleArray = pIntermediateMesh->GetTriangles(); |
|---|
| 314 | int iNrTriangles = triangleArray.Size(); |
|---|
| 315 | |
|---|
| 316 | // allocate index buffer for each submesh |
|---|
| 317 | std::map<CIntermediateMaterial*, Ogre::SubMesh*>::iterator it = m_lMaterialSubMeshMap.begin(); |
|---|
| 318 | while( it != m_lMaterialSubMeshMap.end() ) |
|---|
| 319 | { |
|---|
| 320 | Ogre::SubMesh* pSubMesh = it->second; |
|---|
| 321 | CIntermediateMaterial* pMat = it->first; |
|---|
| 322 | |
|---|
| 323 | std::vector< unsigned int > lMatTriangles; |
|---|
| 324 | pIntermediateMesh->GetTrianglesUsingMaterial( pMat, lMatTriangles); |
|---|
| 325 | |
|---|
| 326 | int iNrIndices = lMatTriangles.size() *3; |
|---|
| 327 | pSubMesh->indexData->indexCount = iNrIndices; |
|---|
| 328 | |
|---|
| 329 | // We should use a 32bit buffer if the vertex buffer has more than 65536 entries (otherwise we cannot reference them) |
|---|
| 330 | // From the vertex buffer decleration we know the vertex count: |
|---|
| 331 | |
|---|
| 332 | m_IndexBitType = Ogre::HardwareIndexBuffer::IT_16BIT; |
|---|
| 333 | if(m_iNrVerts >= 65536) |
|---|
| 334 | m_IndexBitType = Ogre::HardwareIndexBuffer::IT_32BIT; |
|---|
| 335 | |
|---|
| 336 | pSubMesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(m_IndexBitType, pSubMesh->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); |
|---|
| 337 | |
|---|
| 338 | Ogre::HardwareIndexBufferSharedPtr iBuf = pSubMesh->indexData->indexBuffer; |
|---|
| 339 | pSubMesh->useSharedVertices = true; |
|---|
| 340 | it++; |
|---|
| 341 | |
|---|
| 342 | // Ok, Let´s fill in the buffer with data :D |
|---|
| 343 | |
|---|
| 344 | // We lock the buffer before adding content |
|---|
| 345 | if(m_IndexBitType == Ogre::HardwareIndexBuffer::IT_32BIT) |
|---|
| 346 | { // 32 Bit Index Buffer |
|---|
| 347 | unsigned int* pIndices = static_cast<unsigned int*>(iBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); |
|---|
| 348 | |
|---|
| 349 | //Ogre::StringUtil::StrStreamType strStrm3; |
|---|
| 350 | //strStrm3 << "Export: #Indices: " << iBuf->getNumIndexes(); |
|---|
| 351 | //Ogre::LogManager::getSingletonPtr()->logMessage(strStrm3.str()); |
|---|
| 352 | |
|---|
| 353 | unsigned int j = 0; |
|---|
| 354 | for(unsigned int i = 0; i< lMatTriangles.size(); i++) { |
|---|
| 355 | |
|---|
| 356 | const CTriangle& face = triangleArray[ lMatTriangles[i] ]; |
|---|
| 357 | |
|---|
| 358 | // indices |
|---|
| 359 | pIndices[j++] = face.m_Vertices[0]; |
|---|
| 360 | pIndices[j++] = face.m_Vertices[1]; |
|---|
| 361 | pIndices[j++] = face.m_Vertices[2]; |
|---|
| 362 | |
|---|
| 363 | SetBoneAssignments(face,pIntermediateMesh); |
|---|
| 364 | |
|---|
| 365 | // skeleton |
|---|
| 366 | |
|---|
| 367 | |
|---|
| 368 | } |
|---|
| 369 | |
|---|
| 370 | // Unlock |
|---|
| 371 | iBuf->unlock(); |
|---|
| 372 | } |
|---|
| 373 | else |
|---|
| 374 | { // 16 Bit Index Buffer |
|---|
| 375 | unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); |
|---|
| 376 | |
|---|
| 377 | //Ogre::StringUtil::StrStreamType strStrm3; |
|---|
| 378 | //strStrm3 << "Export: #Indices: " << iBuf->getNumIndexes(); |
|---|
| 379 | //Ogre::LogManager::getSingletonPtr()->logMessage(strStrm3.str()); |
|---|
| 380 | |
|---|
| 381 | unsigned int j = 0; |
|---|
| 382 | for(unsigned int i = 0; i< lMatTriangles.size(); i++) { |
|---|
| 383 | |
|---|
| 384 | const CTriangle& face = triangleArray[ lMatTriangles[i] ]; |
|---|
| 385 | |
|---|
| 386 | // indices |
|---|
| 387 | pIndices[j++] = face.m_Vertices[0]; |
|---|
| 388 | pIndices[j++] = face.m_Vertices[1]; |
|---|
| 389 | pIndices[j++] = face.m_Vertices[2]; |
|---|
| 390 | |
|---|
| 391 | |
|---|
| 392 | // skeleton |
|---|
| 393 | SetBoneAssignments(face,pIntermediateMesh); |
|---|
| 394 | } |
|---|
| 395 | |
|---|
| 396 | // Unlock |
|---|
| 397 | iBuf->unlock(); |
|---|
| 398 | } |
|---|
| 399 | |
|---|
| 400 | if(pMat != NULL) |
|---|
| 401 | pSubMesh->setMaterialName(pMat->GetName().c_str()); |
|---|
| 402 | else |
|---|
| 403 | pSubMesh->setMaterialName("NoMaterial"); |
|---|
| 404 | } |
|---|
| 405 | } |
|---|
| 406 | |
|---|
| 407 | void COgreMeshCompiler::SetBoneAssignments( const CTriangle& face, CIntermediateMesh* pIntermediateMesh ) |
|---|
| 408 | { |
|---|
| 409 | CIntermediateSkeleton* pISkel = pIntermediateMesh->GetSkeleton(); |
|---|
| 410 | if(pISkel != NULL) { |
|---|
| 411 | Ogre::VertexBoneAssignment vertexBoneAssignment; |
|---|
| 412 | |
|---|
| 413 | for (int w=0; w < 3; w++) |
|---|
| 414 | { |
|---|
| 415 | int vertIndex = face.m_Vertices[w];//startIndex-3+w; |
|---|
| 416 | int iBoneCount = pISkel->GetNrOfAssignmentsOnVertex(vertIndex); |
|---|
| 417 | |
|---|
| 418 | SVertexBoneData maxBoneData; |
|---|
| 419 | maxBoneData.weight = 0; |
|---|
| 420 | int maxVertIndex = 0; |
|---|
| 421 | for (int i=0; i < iBoneCount; i++) |
|---|
| 422 | { |
|---|
| 423 | SVertexBoneData boneData; |
|---|
| 424 | if(pISkel->GetVertexData(vertIndex,i,boneData)) |
|---|
| 425 | { |
|---|
| 426 | if(maxBoneData.weight < boneData.weight) |
|---|
| 427 | maxBoneData = boneData; |
|---|
| 428 | |
|---|
| 429 | if(boneData.weight < 0.001f) continue; |
|---|
| 430 | |
|---|
| 431 | vertexBoneAssignment.vertexIndex = vertIndex; |
|---|
| 432 | vertexBoneAssignment.boneIndex = boneData.boneIndex; |
|---|
| 433 | vertexBoneAssignment.weight = boneData.weight; |
|---|
| 434 | |
|---|
| 435 | m_pOgreMesh->addBoneAssignment(vertexBoneAssignment); |
|---|
| 436 | } |
|---|
| 437 | } |
|---|
| 438 | } |
|---|
| 439 | } |
|---|
| 440 | } |
|---|
| 441 | |
|---|
| 442 | void COgreMeshCompiler::CreateNormalBuffer( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 443 | { |
|---|
| 444 | assert(pIntermediateMesh); |
|---|
| 445 | |
|---|
| 446 | CMeshArray* pNormalArray = pIntermediateMesh->GetArray("normal",0); |
|---|
| 447 | if(pNormalArray == NULL) |
|---|
| 448 | return; |
|---|
| 449 | |
|---|
| 450 | int iNrNormals = pNormalArray->Size(); |
|---|
| 451 | |
|---|
| 452 | Ogre::VertexData* vertexData = m_pOgreMesh->sharedVertexData; |
|---|
| 453 | Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; |
|---|
| 454 | |
|---|
| 455 | // normals |
|---|
| 456 | vertexDecl->addElement(m_iBind, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); |
|---|
| 457 | |
|---|
| 458 | // allocate the normal vertex buffer |
|---|
| 459 | vertexData->vertexCount = iNrNormals; |
|---|
| 460 | Ogre::HardwareVertexBufferSharedPtr nBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(m_iBind), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); |
|---|
| 461 | Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding; |
|---|
| 462 | binding->setBinding(m_iBind, nBuf); |
|---|
| 463 | const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->getElement(m_iBind); |
|---|
| 464 | unsigned char* vertex = static_cast<unsigned char*>(nBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); |
|---|
| 465 | m_iBind++; |
|---|
| 466 | |
|---|
| 467 | Ogre::Real* pReal; |
|---|
| 468 | posElem->baseVertexPointerToElement(vertex, &pReal); |
|---|
| 469 | |
|---|
| 470 | //Ogre::StringUtil::StrStreamType strStrm3; |
|---|
| 471 | //strStrm3 << "Export: #Normals2Export: " << iNrNormals; |
|---|
| 472 | //Ogre::LogManager::getSingletonPtr()->logMessage(strStrm3.str()); |
|---|
| 473 | |
|---|
| 474 | const Ogre::Vector3* data = (const Ogre::Vector3*)pNormalArray->Data(); |
|---|
| 475 | |
|---|
| 476 | int j = 0; |
|---|
| 477 | for (int i = 0 ; i < iNrNormals; i++) |
|---|
| 478 | { |
|---|
| 479 | const Ogre::Vector3& vert = data[i]; |
|---|
| 480 | |
|---|
| 481 | *pReal++ = vert.x; |
|---|
| 482 | *pReal++ = vert.y; |
|---|
| 483 | *pReal++ = vert.z; |
|---|
| 484 | } |
|---|
| 485 | nBuf->unlock(); |
|---|
| 486 | } |
|---|
| 487 | |
|---|
| 488 | void COgreMeshCompiler::CreateDiffuseBuffer( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 489 | { |
|---|
| 490 | assert(pIntermediateMesh); |
|---|
| 491 | |
|---|
| 492 | CMeshArray* pDiffuseArray = pIntermediateMesh->GetArray("diffuse",0); |
|---|
| 493 | |
|---|
| 494 | bool bCleanUp = false; |
|---|
| 495 | if(pDiffuseArray == NULL) |
|---|
| 496 | { |
|---|
| 497 | LOGWARNING "No Vertex Colours defined, will export white colors on each vertex!."); |
|---|
| 498 | |
|---|
| 499 | // Fallback on standard white. |
|---|
| 500 | unsigned int iVIndex = 0; |
|---|
| 501 | CVec4Array* pArray = new CVec4Array(m_iNrVerts); |
|---|
| 502 | bCleanUp = true; |
|---|
| 503 | for(unsigned int x = 0; x < m_iNrVerts; x++) |
|---|
| 504 | { |
|---|
| 505 | Ogre::Vector4& vColor = (*pArray)[iVIndex++]; |
|---|
| 506 | vColor.x = 1.0f; |
|---|
| 507 | vColor.y = 1.0f; |
|---|
| 508 | vColor.z = 1.0f; |
|---|
| 509 | vColor.w = 1.0f; |
|---|
| 510 | } |
|---|
| 511 | pDiffuseArray = pArray; |
|---|
| 512 | } |
|---|
| 513 | |
|---|
| 514 | int iNrVerts = pDiffuseArray->Size(); |
|---|
| 515 | |
|---|
| 516 | Ogre::VertexData* vertexData = m_pOgreMesh->sharedVertexData; |
|---|
| 517 | Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; |
|---|
| 518 | |
|---|
| 519 | // diffuse colours |
|---|
| 520 | vertexDecl->addElement(m_iBind, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); |
|---|
| 521 | |
|---|
| 522 | // allocate the diffuse vertex buffer |
|---|
| 523 | vertexData->vertexCount = iNrVerts; |
|---|
| 524 | int vsize = vertexDecl->getVertexSize(m_iBind); |
|---|
| 525 | Ogre::HardwareVertexBufferSharedPtr dBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(m_iBind), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); |
|---|
| 526 | Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding; |
|---|
| 527 | binding->setBinding(m_iBind, dBuf); |
|---|
| 528 | const Ogre::VertexElement* diffuseElem = vertexData->vertexDeclaration->getElement(m_iBind); |
|---|
| 529 | unsigned char* vertex = static_cast<unsigned char*>(dBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); |
|---|
| 530 | m_iBind++; |
|---|
| 531 | |
|---|
| 532 | Ogre::ARGB* pReal; |
|---|
| 533 | diffuseElem->baseVertexPointerToElement(vertex, &pReal); |
|---|
| 534 | |
|---|
| 535 | //Ogre::StringUtil::StrStreamType strStrm3; |
|---|
| 536 | //strStrm3 << "Export: #Diffuse2Export: " << iNrVerts; |
|---|
| 537 | //Ogre::LogManager::getSingletonPtr()->logMessage(strStrm3.str()); |
|---|
| 538 | |
|---|
| 539 | const Ogre::Vector4* data = (const Ogre::Vector4*)pDiffuseArray->Data(); |
|---|
| 540 | |
|---|
| 541 | for (int i = 0 ; i < iNrVerts; i++) |
|---|
| 542 | { |
|---|
| 543 | const Ogre::Vector4& vert = data[i]; |
|---|
| 544 | |
|---|
| 545 | *pReal++= (((unsigned int)(vert.w*255.0))<<24)| |
|---|
| 546 | (((unsigned int)(vert.x*255.0))<<16)| |
|---|
| 547 | (((unsigned int)(vert.y*255.0))<<8)| |
|---|
| 548 | (((unsigned int)(vert.z*255.0))); |
|---|
| 549 | } |
|---|
| 550 | dBuf->unlock(); |
|---|
| 551 | |
|---|
| 552 | if(bCleanUp) |
|---|
| 553 | delete [] pDiffuseArray; |
|---|
| 554 | } |
|---|
| 555 | |
|---|
| 556 | void COgreMeshCompiler::CreateTexCoordBuffer( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 557 | { |
|---|
| 558 | assert(pIntermediateMesh); |
|---|
| 559 | |
|---|
| 560 | |
|---|
| 561 | unsigned int iUVIndex = 0; |
|---|
| 562 | for(unsigned int x = 1; x <= 99; x++) |
|---|
| 563 | { |
|---|
| 564 | char temp[32]; |
|---|
| 565 | sprintf(temp, "uv%i", x); |
|---|
| 566 | CMeshArray* pUVArray = pIntermediateMesh->GetArray(temp,0); |
|---|
| 567 | iUVIndex = x; |
|---|
| 568 | |
|---|
| 569 | if(pUVArray == NULL) |
|---|
| 570 | continue; |
|---|
| 571 | |
|---|
| 572 | //Ogre::String msg = Ogre::String("Exporting UV Channel: ")+Ogre::String(temp); |
|---|
| 573 | //Ogre::LogManager::getSingletonPtr()->logMessage(msg); |
|---|
| 574 | |
|---|
| 575 | |
|---|
| 576 | int iNrUVs = pUVArray->Size(); |
|---|
| 577 | |
|---|
| 578 | Ogre::VertexData* vertexData = m_pOgreMesh->sharedVertexData; |
|---|
| 579 | Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; |
|---|
| 580 | |
|---|
| 581 | // normals |
|---|
| 582 | vertexDecl->addElement(m_iBind, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES,iUVIndex-1); |
|---|
| 583 | |
|---|
| 584 | // allocate the position vertex buffer |
|---|
| 585 | vertexData->vertexCount = iNrUVs; |
|---|
| 586 | Ogre::HardwareVertexBufferSharedPtr uvBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(m_iBind), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); |
|---|
| 587 | Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding; |
|---|
| 588 | binding->setBinding(m_iBind, uvBuf); |
|---|
| 589 | |
|---|
| 590 | const Ogre::VertexElement* uvElem = vertexData->vertexDeclaration->getElement(m_iBind); |
|---|
| 591 | unsigned char* vertex = static_cast<unsigned char*>(uvBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); |
|---|
| 592 | m_iBind++; |
|---|
| 593 | |
|---|
| 594 | Ogre::Real* pReal; |
|---|
| 595 | uvElem->baseVertexPointerToElement(vertex, &pReal); |
|---|
| 596 | |
|---|
| 597 | const Ogre::Vector2* data = (const Ogre::Vector2*)pUVArray->Data(); |
|---|
| 598 | |
|---|
| 599 | for (int i = 0 ; i < iNrUVs; i++) |
|---|
| 600 | { |
|---|
| 601 | const Ogre::Vector2& vert = data[i]; |
|---|
| 602 | *pReal++= vert.x; |
|---|
| 603 | *pReal++= vert.y; |
|---|
| 604 | } |
|---|
| 605 | uvBuf->unlock(); |
|---|
| 606 | |
|---|
| 607 | } |
|---|
| 608 | } |
|---|
| 609 | |
|---|
| 610 | void COgreMeshCompiler::CreateMeshBounds( void ) |
|---|
| 611 | { |
|---|
| 612 | Ogre::Real width = Ogre::Math::Sqrt(m_MaxSquaredLength); |
|---|
| 613 | m_pOgreMesh->_setBounds(m_AABB); |
|---|
| 614 | m_pOgreMesh->_setBoundingSphereRadius(width); |
|---|
| 615 | } |
|---|
| 616 | |
|---|
| 617 | void COgreMeshCompiler::PrintVertexDataToLog( void ) |
|---|
| 618 | { |
|---|
| 619 | Ogre::VertexData* vertexData = m_pOgreMesh->sharedVertexData; |
|---|
| 620 | Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; |
|---|
| 621 | |
|---|
| 622 | Ogre::Real* pReal; |
|---|
| 623 | const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); |
|---|
| 624 | Ogre::HardwareVertexBufferSharedPtr vBuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); |
|---|
| 625 | unsigned char* vertex = static_cast<unsigned char*>(vBuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); |
|---|
| 626 | |
|---|
| 627 | for(size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vBuf->getVertexSize()) |
|---|
| 628 | { |
|---|
| 629 | posElem->baseVertexPointerToElement(vertex, &pReal); |
|---|
| 630 | Ogre::StringUtil::StrStreamType str; |
|---|
| 631 | str << "x: " << (*pReal++) << "\ty: " << (*pReal++) << "\tz:" << (*pReal++); |
|---|
| 632 | Ogre::LogManager::getSingletonPtr()->logMessage( str.str()); |
|---|
| 633 | } |
|---|
| 634 | } |
|---|
| 635 | |
|---|
| 636 | bool COgreMeshCompiler::WriteOgreMesh( const Ogre::String& sFilename ) |
|---|
| 637 | { |
|---|
| 638 | assert(Ogre::MeshManager::getSingletonPtr()); |
|---|
| 639 | |
|---|
| 640 | Ogre::MeshSerializer* pMeshWriter = new Ogre::MeshSerializer(); |
|---|
| 641 | try |
|---|
| 642 | { |
|---|
| 643 | pMeshWriter->exportMesh(m_pOgreMesh.get(), sFilename); |
|---|
| 644 | } |
|---|
| 645 | catch (Ogre::Exception& e) |
|---|
| 646 | { |
|---|
| 647 | LOGERROR "OgreException: %s", e.getFullDescription().c_str()); |
|---|
| 648 | // MessageBox( NULL, e.getFullDescription().c_str(), "ERROR", MB_ICONERROR); |
|---|
| 649 | return false; |
|---|
| 650 | } catch(...) |
|---|
| 651 | { |
|---|
| 652 | LOGERROR "Unhandled exception caught in COgreMeshCompiler::WriteOgreMesh()"); |
|---|
| 653 | } |
|---|
| 654 | delete pMeshWriter; |
|---|
| 655 | |
|---|
| 656 | //if(m_bExportSkeleton) |
|---|
| 657 | // if( !m_pSkeletonCompiler->WriteOgreSkeleton( sFilename+".skeleton") ) |
|---|
| 658 | // return false; |
|---|
| 659 | |
|---|
| 660 | return true; |
|---|
| 661 | } |
|---|
| 662 | |
|---|
| 663 | Ogre::MeshPtr COgreMeshCompiler::GetOgreMesh( void ) |
|---|
| 664 | { |
|---|
| 665 | return m_pOgreMesh; |
|---|
| 666 | } |
|---|
| 667 | |
|---|
| 668 | void COgreMeshCompiler::CreatePoseBuffers( CIntermediateMesh* pIntermediateMesh ) |
|---|
| 669 | { |
|---|
| 670 | // Create static pose data |
|---|
| 671 | unsigned int iPoseCount = pIntermediateMesh->GetPoseCount(); |
|---|
| 672 | for(unsigned int i=0; i<iPoseCount; i++) |
|---|
| 673 | { |
|---|
| 674 | Ogre::String poseName; |
|---|
| 675 | unsigned int iFrame; |
|---|
| 676 | bool bOptimize; |
|---|
| 677 | pIntermediateMesh->GetPose(i, poseName, iFrame,bOptimize); |
|---|
| 678 | iFrame *= GetTicksPerFrame(); |
|---|
| 679 | |
|---|
| 680 | CreatePose(pIntermediateMesh, poseName, iFrame, bOptimize ); |
|---|
| 681 | } |
|---|
| 682 | |
|---|
| 683 | // Create pose animations |
|---|
| 684 | unsigned int iPoseAnimCount = pIntermediateMesh->GetPoseAnimCount(); |
|---|
| 685 | for(unsigned int i=0; i<iPoseAnimCount; i++) |
|---|
| 686 | { |
|---|
| 687 | Ogre::String animName; |
|---|
| 688 | unsigned int iStartFrame; |
|---|
| 689 | unsigned int iEndFrame; |
|---|
| 690 | float fRate; |
|---|
| 691 | bool bOptimize; |
|---|
| 692 | pIntermediateMesh->GetPoseAnimation(i, animName, iStartFrame, iEndFrame, fRate, bOptimize); |
|---|
| 693 | |
|---|
| 694 | float fps = 1.0 / float(GetFrameRate()); |
|---|
| 695 | float fAnimLength = (iEndFrame - iStartFrame) * fps; |
|---|
| 696 | |
|---|
| 697 | Ogre::Animation* pAnim = m_pOgreMesh->createAnimation(animName,fAnimLength); |
|---|
| 698 | Ogre::VertexAnimationTrack* pTrack = pAnim->createVertexTrack(0, Ogre::VAT_POSE); |
|---|
| 699 | |
|---|
| 700 | float x = iStartFrame; |
|---|
| 701 | int frameCount = 0; |
|---|
| 702 | while(x <= iEndFrame) |
|---|
| 703 | { |
|---|
| 704 | float time = (x- iStartFrame)*fps; // local in this animation |
|---|
| 705 | Ogre::VertexPoseKeyFrame* pKeyFrame = pTrack->createVertexPoseKeyFrame(time); |
|---|
| 706 | |
|---|
| 707 | Ogre::String poseName = animName; |
|---|
| 708 | poseName += "_"; |
|---|
| 709 | poseName += Ogre::StringConverter::toString(frameCount++); |
|---|
| 710 | unsigned int poseID = CreatePose(pIntermediateMesh, poseName, x*GetTicksPerFrame(), bOptimize ); |
|---|
| 711 | |
|---|
| 712 | pKeyFrame->addPoseReference(poseID,1.0f); |
|---|
| 713 | |
|---|
| 714 | x += fRate; |
|---|
| 715 | } |
|---|
| 716 | |
|---|
| 717 | if(bOptimize) |
|---|
| 718 | pAnim->optimise(); |
|---|
| 719 | } |
|---|
| 720 | } |
|---|
| 721 | |
|---|
| 722 | unsigned int COgreMeshCompiler::CreatePose( CIntermediateMesh* pIntermediateMesh, Ogre::String poseName, unsigned int iFrame, bool bOptimize ) |
|---|
| 723 | { |
|---|
| 724 | Ogre::Pose* pPose = m_pOgreMesh->createPose(0 /*shared geometry buffer*/, poseName); |
|---|
| 725 | |
|---|
| 726 | if(iFrame != 0) // then the pose is the same as the reference, so nothing is needed to be checked |
|---|
| 727 | { |
|---|
| 728 | CMeshArray* pVerts = new CVec3Array(); |
|---|
| 729 | CMeshArray* pTmpBuf = pIntermediateMesh->GetArray("position", iFrame); |
|---|
| 730 | pVerts->Create(pTmpBuf->Size(), pTmpBuf->Data()); |
|---|
| 731 | |
|---|
| 732 | CMeshArray* pOrigVerts = new CVec3Array(); |
|---|
| 733 | pTmpBuf = pIntermediateMesh->GetArray("position", 0); |
|---|
| 734 | pOrigVerts->Create(pTmpBuf->Size(), pTmpBuf->Data()); |
|---|
| 735 | |
|---|
| 736 | if(m_bReindex) |
|---|
| 737 | { |
|---|
| 738 | SharedUtilities::fastvector< CMeshArray* > bufferList; |
|---|
| 739 | |
|---|
| 740 | bufferList.push_back(pVerts); |
|---|
| 741 | bufferList.push_back(pOrigVerts); |
|---|
| 742 | |
|---|
| 743 | pIntermediateMesh->PostReindex( bufferList ); |
|---|
| 744 | } |
|---|
| 745 | |
|---|
| 746 | const Ogre::Vector3* data = (const Ogre::Vector3*)pVerts->Data(); |
|---|
| 747 | const Ogre::Vector3* origData = (const Ogre::Vector3*)pOrigVerts->Data(); |
|---|
| 748 | for(unsigned int j=0; j< pVerts->Size(); j++) |
|---|
| 749 | { |
|---|
| 750 | Ogre::Vector3 vert = data[j]; |
|---|
| 751 | Ogre::Vector3 origVert = origData[j]; |
|---|
| 752 | |
|---|
| 753 | vert = vert - origVert; |
|---|
| 754 | |
|---|
| 755 | if( !bOptimize ) |
|---|
| 756 | { |
|---|
| 757 | pPose->addVertex(j,vert); |
|---|
| 758 | } |
|---|
| 759 | else if(vert != Ogre::Vector3::ZERO) |
|---|
| 760 | pPose->addVertex(j,vert); |
|---|
| 761 | } |
|---|
| 762 | |
|---|
| 763 | delete pOrigVerts; |
|---|
| 764 | delete pVerts; |
|---|
| 765 | } |
|---|
| 766 | else |
|---|
| 767 | { |
|---|
| 768 | // ensure the buffer is clean (been known to be polluted right after creation) |
|---|
| 769 | pPose->clearVertexOffsets(); |
|---|
| 770 | } |
|---|
| 771 | |
|---|
| 772 | return m_iNrPoses++; |
|---|
| 773 | } |
|---|