vrshoot

annotate libs/assimp/ObjFileImporter.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
rev   line source
nuclear@0 1 /*
nuclear@0 2 ---------------------------------------------------------------------------
nuclear@0 3 Open Asset Import Library (assimp)
nuclear@0 4 ---------------------------------------------------------------------------
nuclear@0 5
nuclear@0 6 Copyright (c) 2006-2012, assimp team
nuclear@0 7
nuclear@0 8 All rights reserved.
nuclear@0 9
nuclear@0 10 Redistribution and use of this software in source and binary forms,
nuclear@0 11 with or without modification, are permitted provided that the following
nuclear@0 12 conditions are met:
nuclear@0 13
nuclear@0 14 * Redistributions of source code must retain the above
nuclear@0 15 copyright notice, this list of conditions and the
nuclear@0 16 following disclaimer.
nuclear@0 17
nuclear@0 18 * Redistributions in binary form must reproduce the above
nuclear@0 19 copyright notice, this list of conditions and the
nuclear@0 20 following disclaimer in the documentation and/or other
nuclear@0 21 materials provided with the distribution.
nuclear@0 22
nuclear@0 23 * Neither the name of the assimp team, nor the names of its
nuclear@0 24 contributors may be used to endorse or promote products
nuclear@0 25 derived from this software without specific prior
nuclear@0 26 written permission of the assimp team.
nuclear@0 27
nuclear@0 28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 39 ---------------------------------------------------------------------------
nuclear@0 40 */
nuclear@0 41
nuclear@0 42 #include "AssimpPCH.h"
nuclear@0 43 #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
nuclear@0 44
nuclear@0 45 #include "DefaultIOSystem.h"
nuclear@0 46 #include "ObjFileImporter.h"
nuclear@0 47 #include "ObjFileParser.h"
nuclear@0 48 #include "ObjFileData.h"
nuclear@0 49
nuclear@0 50 static const aiImporterDesc desc = {
nuclear@0 51 "Wavefront Object Importer",
nuclear@0 52 "",
nuclear@0 53 "",
nuclear@0 54 "surfaces not supported",
nuclear@0 55 aiImporterFlags_SupportTextFlavour,
nuclear@0 56 0,
nuclear@0 57 0,
nuclear@0 58 0,
nuclear@0 59 0,
nuclear@0 60 "obj"
nuclear@0 61 };
nuclear@0 62
nuclear@0 63
nuclear@0 64 namespace Assimp {
nuclear@0 65
nuclear@0 66 using namespace std;
nuclear@0 67
nuclear@0 68 // ------------------------------------------------------------------------------------------------
nuclear@0 69 // Default constructor
nuclear@0 70 ObjFileImporter::ObjFileImporter() :
nuclear@0 71 m_Buffer(),
nuclear@0 72 m_pRootObject( NULL ),
nuclear@0 73 m_strAbsPath( "" )
nuclear@0 74 {
nuclear@0 75 DefaultIOSystem io;
nuclear@0 76 m_strAbsPath = io.getOsSeparator();
nuclear@0 77 }
nuclear@0 78
nuclear@0 79 // ------------------------------------------------------------------------------------------------
nuclear@0 80 // Destructor.
nuclear@0 81 ObjFileImporter::~ObjFileImporter()
nuclear@0 82 {
nuclear@0 83 // Release root object instance
nuclear@0 84 if (NULL != m_pRootObject)
nuclear@0 85 {
nuclear@0 86 delete m_pRootObject;
nuclear@0 87 m_pRootObject = NULL;
nuclear@0 88 }
nuclear@0 89 }
nuclear@0 90
nuclear@0 91 // ------------------------------------------------------------------------------------------------
nuclear@0 92 // Returns true, if file is an obj file.
nuclear@0 93 bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const
nuclear@0 94 {
nuclear@0 95 if(!checkSig) //Check File Extension
nuclear@0 96 {
nuclear@0 97 return SimpleExtensionCheck(pFile,"obj");
nuclear@0 98 }
nuclear@0 99 else //Check file Header
nuclear@0 100 {
nuclear@0 101 static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
nuclear@0 102 return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
nuclear@0 103 }
nuclear@0 104 }
nuclear@0 105
nuclear@0 106 // ------------------------------------------------------------------------------------------------
nuclear@0 107 const aiImporterDesc* ObjFileImporter::GetInfo () const
nuclear@0 108 {
nuclear@0 109 return &desc;
nuclear@0 110 }
nuclear@0 111
nuclear@0 112 // ------------------------------------------------------------------------------------------------
nuclear@0 113 // Obj-file import implementation
nuclear@0 114 void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
nuclear@0 115 {
nuclear@0 116 DefaultIOSystem io;
nuclear@0 117
nuclear@0 118 // Read file into memory
nuclear@0 119 const std::string mode = "rb";
nuclear@0 120 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
nuclear@0 121 if (NULL == file.get())
nuclear@0 122 throw DeadlyImportError( "Failed to open file " + pFile + ".");
nuclear@0 123
nuclear@0 124 // Get the file-size and validate it, throwing an exception when fails
nuclear@0 125 size_t fileSize = file->FileSize();
nuclear@0 126 if( fileSize < 16)
nuclear@0 127 throw DeadlyImportError( "OBJ-file is too small.");
nuclear@0 128
nuclear@0 129 // Allocate buffer and read file into it
nuclear@0 130 TextFileToBuffer(file.get(),m_Buffer);
nuclear@0 131
nuclear@0 132 // Get the model name
nuclear@0 133 std::string strModelName;
nuclear@0 134 std::string::size_type pos = pFile.find_last_of( "\\/" );
nuclear@0 135 if ( pos != std::string::npos )
nuclear@0 136 {
nuclear@0 137 strModelName = pFile.substr(pos+1, pFile.size() - pos - 1);
nuclear@0 138 }
nuclear@0 139 else
nuclear@0 140 {
nuclear@0 141 strModelName = pFile;
nuclear@0 142 }
nuclear@0 143
nuclear@0 144 // parse the file into a temporary representation
nuclear@0 145 ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
nuclear@0 146
nuclear@0 147 // And create the proper return structures out of it
nuclear@0 148 CreateDataFromImport(parser.GetModel(), pScene);
nuclear@0 149
nuclear@0 150 // Clean up allocated storage for the next import
nuclear@0 151 m_Buffer.clear();
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 // ------------------------------------------------------------------------------------------------
nuclear@0 155 // Create the data from parsed obj-file
nuclear@0 156 void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene)
nuclear@0 157 {
nuclear@0 158 if (0L == pModel)
nuclear@0 159 return;
nuclear@0 160
nuclear@0 161 // Create the root node of the scene
nuclear@0 162 pScene->mRootNode = new aiNode;
nuclear@0 163 if ( !pModel->m_ModelName.empty() )
nuclear@0 164 {
nuclear@0 165 // Set the name of the scene
nuclear@0 166 pScene->mRootNode->mName.Set(pModel->m_ModelName);
nuclear@0 167 }
nuclear@0 168 else
nuclear@0 169 {
nuclear@0 170 // This is an error, so break down the application
nuclear@0 171 ai_assert(false);
nuclear@0 172 }
nuclear@0 173
nuclear@0 174 // Create nodes for the whole scene
nuclear@0 175 std::vector<aiMesh*> MeshArray;
nuclear@0 176 for (size_t index = 0; index < pModel->m_Objects.size(); index++)
nuclear@0 177 {
nuclear@0 178 createNodes(pModel, pModel->m_Objects[ index ], index, pScene->mRootNode, pScene, MeshArray);
nuclear@0 179 }
nuclear@0 180
nuclear@0 181 // Create mesh pointer buffer for this scene
nuclear@0 182 if (pScene->mNumMeshes > 0)
nuclear@0 183 {
nuclear@0 184 pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
nuclear@0 185 for (size_t index =0; index < MeshArray.size(); index++)
nuclear@0 186 {
nuclear@0 187 pScene->mMeshes [ index ] = MeshArray[ index ];
nuclear@0 188 }
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 // Create all materials
nuclear@0 192 createMaterials( pModel, pScene );
nuclear@0 193 }
nuclear@0 194
nuclear@0 195 // ------------------------------------------------------------------------------------------------
nuclear@0 196 // Creates all nodes of the model
nuclear@0 197 aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject,
nuclear@0 198 unsigned int /*uiMeshIndex*/,
nuclear@0 199 aiNode *pParent, aiScene* pScene,
nuclear@0 200 std::vector<aiMesh*> &MeshArray )
nuclear@0 201 {
nuclear@0 202 ai_assert( NULL != pModel );
nuclear@0 203 if ( NULL == pObject )
nuclear@0 204 return NULL;
nuclear@0 205
nuclear@0 206 // Store older mesh size to be able to computes mesh offsets for new mesh instances
nuclear@0 207 const size_t oldMeshSize = MeshArray.size();
nuclear@0 208 aiNode *pNode = new aiNode;
nuclear@0 209
nuclear@0 210 pNode->mName = pObject->m_strObjName;
nuclear@0 211
nuclear@0 212 // If we have a parent node, store it
nuclear@0 213 if (pParent != NULL)
nuclear@0 214 appendChildToParentNode(pParent, pNode);
nuclear@0 215
nuclear@0 216 for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
nuclear@0 217 {
nuclear@0 218 unsigned int meshId = pObject->m_Meshes[ i ];
nuclear@0 219 aiMesh *pMesh = new aiMesh;
nuclear@0 220 createTopology( pModel, pObject, meshId, pMesh );
nuclear@0 221 if ( pMesh->mNumVertices > 0 )
nuclear@0 222 {
nuclear@0 223 MeshArray.push_back( pMesh );
nuclear@0 224 }
nuclear@0 225 else
nuclear@0 226 {
nuclear@0 227 delete pMesh;
nuclear@0 228 }
nuclear@0 229 }
nuclear@0 230
nuclear@0 231 // Create all nodes from the sub-objects stored in the current object
nuclear@0 232 if ( !pObject->m_SubObjects.empty() )
nuclear@0 233 {
nuclear@0 234 size_t numChilds = pObject->m_SubObjects.size();
nuclear@0 235 pNode->mNumChildren = static_cast<unsigned int>( numChilds );
nuclear@0 236 pNode->mChildren = new aiNode*[ numChilds ];
nuclear@0 237 pNode->mNumMeshes = 1;
nuclear@0 238 pNode->mMeshes = new unsigned int[ 1 ];
nuclear@0 239 }
nuclear@0 240
nuclear@0 241 // Set mesh instances into scene- and node-instances
nuclear@0 242 const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
nuclear@0 243 if ( meshSizeDiff > 0 )
nuclear@0 244 {
nuclear@0 245 pNode->mMeshes = new unsigned int[ meshSizeDiff ];
nuclear@0 246 pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
nuclear@0 247 size_t index = 0;
nuclear@0 248 for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
nuclear@0 249 {
nuclear@0 250 pNode->mMeshes[ index ] = pScene->mNumMeshes;
nuclear@0 251 pScene->mNumMeshes++;
nuclear@0 252 index++;
nuclear@0 253 }
nuclear@0 254 }
nuclear@0 255
nuclear@0 256 return pNode;
nuclear@0 257 }
nuclear@0 258
nuclear@0 259 // ------------------------------------------------------------------------------------------------
nuclear@0 260 // Create topology data
nuclear@0 261 void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
nuclear@0 262 const ObjFile::Object* pData,
nuclear@0 263 unsigned int uiMeshIndex,
nuclear@0 264 aiMesh* pMesh )
nuclear@0 265 {
nuclear@0 266 // Checking preconditions
nuclear@0 267 ai_assert( NULL != pModel );
nuclear@0 268 if (NULL == pData)
nuclear@0 269 return;
nuclear@0 270
nuclear@0 271 // Create faces
nuclear@0 272 ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
nuclear@0 273 ai_assert( NULL != pObjMesh );
nuclear@0 274
nuclear@0 275 pMesh->mNumFaces = 0;
nuclear@0 276 for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
nuclear@0 277 {
nuclear@0 278 ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
nuclear@0 279 if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
nuclear@0 280 pMesh->mNumFaces += inp->m_pVertices->size() - 1;
nuclear@0 281 }
nuclear@0 282 else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
nuclear@0 283 pMesh->mNumFaces += inp->m_pVertices->size();
nuclear@0 284 }
nuclear@0 285 else {
nuclear@0 286 ++pMesh->mNumFaces;
nuclear@0 287 }
nuclear@0 288 }
nuclear@0 289
nuclear@0 290 unsigned int uiIdxCount = 0u;
nuclear@0 291 if ( pMesh->mNumFaces > 0 )
nuclear@0 292 {
nuclear@0 293 pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
nuclear@0 294 if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial )
nuclear@0 295 {
nuclear@0 296 pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
nuclear@0 297 }
nuclear@0 298
nuclear@0 299 unsigned int outIndex = 0;
nuclear@0 300
nuclear@0 301 // Copy all data from all stored meshes
nuclear@0 302 for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
nuclear@0 303 {
nuclear@0 304 ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
nuclear@0 305 if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
nuclear@0 306 for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
nuclear@0 307 aiFace& f = pMesh->mFaces[ outIndex++ ];
nuclear@0 308 uiIdxCount += f.mNumIndices = 2;
nuclear@0 309 f.mIndices = new unsigned int[2];
nuclear@0 310 }
nuclear@0 311 continue;
nuclear@0 312 }
nuclear@0 313 else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
nuclear@0 314 for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
nuclear@0 315 aiFace& f = pMesh->mFaces[ outIndex++ ];
nuclear@0 316 uiIdxCount += f.mNumIndices = 1;
nuclear@0 317 f.mIndices = new unsigned int[1];
nuclear@0 318 }
nuclear@0 319 continue;
nuclear@0 320 }
nuclear@0 321
nuclear@0 322 aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
nuclear@0 323 const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
nuclear@0 324 uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
nuclear@0 325 if (pFace->mNumIndices > 0) {
nuclear@0 326 pFace->mIndices = new unsigned int[ uiNumIndices ];
nuclear@0 327 }
nuclear@0 328 }
nuclear@0 329 }
nuclear@0 330
nuclear@0 331 // Create mesh vertices
nuclear@0 332 createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
nuclear@0 333 }
nuclear@0 334
nuclear@0 335 // ------------------------------------------------------------------------------------------------
nuclear@0 336 // Creates a vertex array
nuclear@0 337 void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
nuclear@0 338 const ObjFile::Object* pCurrentObject,
nuclear@0 339 unsigned int uiMeshIndex,
nuclear@0 340 aiMesh* pMesh,
nuclear@0 341 unsigned int uiIdxCount)
nuclear@0 342 {
nuclear@0 343 // Checking preconditions
nuclear@0 344 ai_assert( NULL != pCurrentObject );
nuclear@0 345
nuclear@0 346 // Break, if no faces are stored in object
nuclear@0 347 if ( pCurrentObject->m_Meshes.empty() )
nuclear@0 348 return;
nuclear@0 349
nuclear@0 350 // Get current mesh
nuclear@0 351 ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
nuclear@0 352 if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
nuclear@0 353 return;
nuclear@0 354
nuclear@0 355 // Copy vertices of this mesh instance
nuclear@0 356 pMesh->mNumVertices = uiIdxCount;
nuclear@0 357 pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
nuclear@0 358
nuclear@0 359 // Allocate buffer for normal vectors
nuclear@0 360 if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
nuclear@0 361 pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
nuclear@0 362
nuclear@0 363 // Allocate buffer for texture coordinates
nuclear@0 364 if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
nuclear@0 365 {
nuclear@0 366 pMesh->mNumUVComponents[ 0 ] = 2;
nuclear@0 367 pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
nuclear@0 368 }
nuclear@0 369
nuclear@0 370 // Copy vertices, normals and textures into aiMesh instance
nuclear@0 371 unsigned int newIndex = 0, outIndex = 0;
nuclear@0 372 for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
nuclear@0 373 {
nuclear@0 374 // Get source face
nuclear@0 375 ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
nuclear@0 376
nuclear@0 377 // Copy all index arrays
nuclear@0 378 for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
nuclear@0 379 {
nuclear@0 380 const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
nuclear@0 381 if ( vertex >= pModel->m_Vertices.size() )
nuclear@0 382 throw DeadlyImportError( "OBJ: vertex index out of range" );
nuclear@0 383
nuclear@0 384 pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
nuclear@0 385
nuclear@0 386 // Copy all normals
nuclear@0 387 if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty())
nuclear@0 388 {
nuclear@0 389 const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
nuclear@0 390 if ( normal >= pModel->m_Normals.size() )
nuclear@0 391 throw DeadlyImportError("OBJ: vertex normal index out of range");
nuclear@0 392
nuclear@0 393 pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
nuclear@0 394 }
nuclear@0 395
nuclear@0 396 // Copy all texture coordinates
nuclear@0 397 if ( !pModel->m_TextureCoord.empty() )
nuclear@0 398 {
nuclear@0 399 if ( !pSourceFace->m_pTexturCoords->empty() )
nuclear@0 400 {
nuclear@0 401 const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
nuclear@0 402 ai_assert( tex < pModel->m_TextureCoord.size() );
nuclear@0 403 for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ )
nuclear@0 404 {
nuclear@0 405 if ( tex >= pModel->m_TextureCoord.size() )
nuclear@0 406 throw DeadlyImportError("OBJ: texture coord index out of range");
nuclear@0 407
nuclear@0 408 aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
nuclear@0 409 pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
nuclear@0 410 }
nuclear@0 411 }
nuclear@0 412 }
nuclear@0 413
nuclear@0 414 ai_assert( pMesh->mNumVertices > newIndex );
nuclear@0 415
nuclear@0 416 // Get destination face
nuclear@0 417 aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
nuclear@0 418
nuclear@0 419 const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 );
nuclear@0 420 if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last)
nuclear@0 421 {
nuclear@0 422 pDestFace->mIndices[ outVertexIndex ] = newIndex;
nuclear@0 423 outVertexIndex++;
nuclear@0 424 }
nuclear@0 425
nuclear@0 426 if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT)
nuclear@0 427 {
nuclear@0 428 outIndex++;
nuclear@0 429 outVertexIndex = 0;
nuclear@0 430 }
nuclear@0 431 else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE)
nuclear@0 432 {
nuclear@0 433 outVertexIndex = 0;
nuclear@0 434
nuclear@0 435 if(!last)
nuclear@0 436 outIndex++;
nuclear@0 437
nuclear@0 438 if (vertexIndex) {
nuclear@0 439 if(!last) {
nuclear@0 440 pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
nuclear@0 441 if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
nuclear@0 442 pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
nuclear@0 443 }
nuclear@0 444 if ( !pModel->m_TextureCoord.empty() ) {
nuclear@0 445 for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
nuclear@0 446 pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
nuclear@0 447 }
nuclear@0 448 }
nuclear@0 449 ++newIndex;
nuclear@0 450 }
nuclear@0 451
nuclear@0 452 pDestFace[-1].mIndices[1] = newIndex;
nuclear@0 453 }
nuclear@0 454 }
nuclear@0 455 else if (last) {
nuclear@0 456 outIndex++;
nuclear@0 457 }
nuclear@0 458 ++newIndex;
nuclear@0 459 }
nuclear@0 460 }
nuclear@0 461 }
nuclear@0 462
nuclear@0 463 // ------------------------------------------------------------------------------------------------
nuclear@0 464 // Counts all stored meshes
nuclear@0 465 void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
nuclear@0 466 {
nuclear@0 467 iNumMeshes = 0;
nuclear@0 468 if ( rObjects.empty() )
nuclear@0 469 return;
nuclear@0 470
nuclear@0 471 iNumMeshes += static_cast<unsigned int>( rObjects.size() );
nuclear@0 472 for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
nuclear@0 473 it != rObjects.end();
nuclear@0 474 ++it)
nuclear@0 475 {
nuclear@0 476 if (!(*it)->m_SubObjects.empty())
nuclear@0 477 {
nuclear@0 478 countObjects((*it)->m_SubObjects, iNumMeshes);
nuclear@0 479 }
nuclear@0 480 }
nuclear@0 481 }
nuclear@0 482
nuclear@0 483 // ------------------------------------------------------------------------------------------------
nuclear@0 484 // Creates the material
nuclear@0 485 void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
nuclear@0 486 {
nuclear@0 487 ai_assert( NULL != pScene );
nuclear@0 488 if ( NULL == pScene )
nuclear@0 489 return;
nuclear@0 490
nuclear@0 491 const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
nuclear@0 492 pScene->mNumMaterials = 0;
nuclear@0 493 if ( pModel->m_MaterialLib.empty() ) {
nuclear@0 494 DefaultLogger::get()->debug("OBJ: no materials specified");
nuclear@0 495 return;
nuclear@0 496 }
nuclear@0 497
nuclear@0 498 pScene->mMaterials = new aiMaterial*[ numMaterials ];
nuclear@0 499 for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
nuclear@0 500 {
nuclear@0 501 // Store material name
nuclear@0 502 std::map<std::string, ObjFile::Material*>::const_iterator it;
nuclear@0 503 it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
nuclear@0 504
nuclear@0 505 // No material found, use the default material
nuclear@0 506 if ( pModel->m_MaterialMap.end() == it )
nuclear@0 507 continue;
nuclear@0 508
nuclear@0 509 aiMaterial* mat = new aiMaterial;
nuclear@0 510 ObjFile::Material *pCurrentMaterial = (*it).second;
nuclear@0 511 mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
nuclear@0 512
nuclear@0 513 // convert illumination model
nuclear@0 514 int sm = 0;
nuclear@0 515 switch (pCurrentMaterial->illumination_model)
nuclear@0 516 {
nuclear@0 517 case 0:
nuclear@0 518 sm = aiShadingMode_NoShading;
nuclear@0 519 break;
nuclear@0 520 case 1:
nuclear@0 521 sm = aiShadingMode_Gouraud;
nuclear@0 522 break;
nuclear@0 523 case 2:
nuclear@0 524 sm = aiShadingMode_Phong;
nuclear@0 525 break;
nuclear@0 526 default:
nuclear@0 527 sm = aiShadingMode_Gouraud;
nuclear@0 528 DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
nuclear@0 529 }
nuclear@0 530
nuclear@0 531 mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
nuclear@0 532
nuclear@0 533 // multiplying the specular exponent with 2 seems to yield better results
nuclear@0 534 pCurrentMaterial->shineness *= 4.f;
nuclear@0 535
nuclear@0 536 // Adding material colors
nuclear@0 537 mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
nuclear@0 538 mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
nuclear@0 539 mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
nuclear@0 540 mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
nuclear@0 541 mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
nuclear@0 542
nuclear@0 543 // Adding refraction index
nuclear@0 544 mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
nuclear@0 545
nuclear@0 546 // Adding textures
nuclear@0 547 if ( 0 != pCurrentMaterial->texture.length )
nuclear@0 548 mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
nuclear@0 549
nuclear@0 550 if ( 0 != pCurrentMaterial->textureAmbient.length )
nuclear@0 551 mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
nuclear@0 552
nuclear@0 553 if ( 0 != pCurrentMaterial->textureSpecular.length )
nuclear@0 554 mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
nuclear@0 555
nuclear@0 556 if ( 0 != pCurrentMaterial->textureBump.length )
nuclear@0 557 mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
nuclear@0 558
nuclear@0 559 if ( 0 != pCurrentMaterial->textureNormal.length )
nuclear@0 560 mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
nuclear@0 561
nuclear@0 562 if ( 0 != pCurrentMaterial->textureDisp.length )
nuclear@0 563 mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
nuclear@0 564
nuclear@0 565 if ( 0 != pCurrentMaterial->textureOpacity.length )
nuclear@0 566 mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
nuclear@0 567
nuclear@0 568 if ( 0 != pCurrentMaterial->textureSpecularity.length )
nuclear@0 569 mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
nuclear@0 570
nuclear@0 571 // Store material property info in material array in scene
nuclear@0 572 pScene->mMaterials[ pScene->mNumMaterials ] = mat;
nuclear@0 573 pScene->mNumMaterials++;
nuclear@0 574 }
nuclear@0 575
nuclear@0 576 // Test number of created materials.
nuclear@0 577 ai_assert( pScene->mNumMaterials == numMaterials );
nuclear@0 578 }
nuclear@0 579
nuclear@0 580 // ------------------------------------------------------------------------------------------------
nuclear@0 581 // Appends this node to the parent node
nuclear@0 582 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
nuclear@0 583 {
nuclear@0 584 // Checking preconditions
nuclear@0 585 ai_assert( NULL != pParent );
nuclear@0 586 ai_assert( NULL != pChild );
nuclear@0 587
nuclear@0 588 // Assign parent to child
nuclear@0 589 pChild->mParent = pParent;
nuclear@0 590 size_t sNumChildren = 0;
nuclear@0 591 (void)sNumChildren; // remove warning on release build
nuclear@0 592
nuclear@0 593 // If already children was assigned to the parent node, store them in a
nuclear@0 594 std::vector<aiNode*> temp;
nuclear@0 595 if (pParent->mChildren != NULL)
nuclear@0 596 {
nuclear@0 597 sNumChildren = pParent->mNumChildren;
nuclear@0 598 ai_assert( 0 != sNumChildren );
nuclear@0 599 for (size_t index = 0; index < pParent->mNumChildren; index++)
nuclear@0 600 {
nuclear@0 601 temp.push_back(pParent->mChildren [ index ] );
nuclear@0 602 }
nuclear@0 603 delete [] pParent->mChildren;
nuclear@0 604 }
nuclear@0 605
nuclear@0 606 // Copy node instances into parent node
nuclear@0 607 pParent->mNumChildren++;
nuclear@0 608 pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
nuclear@0 609 for (size_t index = 0; index < pParent->mNumChildren-1; index++)
nuclear@0 610 {
nuclear@0 611 pParent->mChildren[ index ] = temp [ index ];
nuclear@0 612 }
nuclear@0 613 pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
nuclear@0 614 }
nuclear@0 615
nuclear@0 616 // ------------------------------------------------------------------------------------------------
nuclear@0 617
nuclear@0 618 } // Namespace Assimp
nuclear@0 619
nuclear@0 620 #endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER