vrshoot

annotate libs/assimp/PlyLoader.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 /** @file PlyLoader.cpp
nuclear@0 43 * @brief Implementation of the PLY importer class
nuclear@0 44 */
nuclear@0 45
nuclear@0 46 #include "AssimpPCH.h"
nuclear@0 47 #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
nuclear@0 48
nuclear@0 49 // internal headers
nuclear@0 50 #include "PlyLoader.h"
nuclear@0 51
nuclear@0 52 using namespace Assimp;
nuclear@0 53
nuclear@0 54 static const aiImporterDesc desc = {
nuclear@0 55 "Stanford Polygon Library (PLY) Importer",
nuclear@0 56 "",
nuclear@0 57 "",
nuclear@0 58 "",
nuclear@0 59 aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
nuclear@0 60 0,
nuclear@0 61 0,
nuclear@0 62 0,
nuclear@0 63 0,
nuclear@0 64 "ply"
nuclear@0 65 };
nuclear@0 66
nuclear@0 67 // ------------------------------------------------------------------------------------------------
nuclear@0 68 // Constructor to be privately used by Importer
nuclear@0 69 PLYImporter::PLYImporter()
nuclear@0 70 {}
nuclear@0 71
nuclear@0 72 // ------------------------------------------------------------------------------------------------
nuclear@0 73 // Destructor, private as well
nuclear@0 74 PLYImporter::~PLYImporter()
nuclear@0 75 {}
nuclear@0 76
nuclear@0 77 // ------------------------------------------------------------------------------------------------
nuclear@0 78 // Returns whether the class can handle the format of the given file.
nuclear@0 79 bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
nuclear@0 80 {
nuclear@0 81 const std::string extension = GetExtension(pFile);
nuclear@0 82
nuclear@0 83 if (extension == "ply")
nuclear@0 84 return true;
nuclear@0 85 else if (!extension.length() || checkSig)
nuclear@0 86 {
nuclear@0 87 if (!pIOHandler)return true;
nuclear@0 88 const char* tokens[] = {"ply"};
nuclear@0 89 return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
nuclear@0 90 }
nuclear@0 91 return false;
nuclear@0 92 }
nuclear@0 93
nuclear@0 94 // ------------------------------------------------------------------------------------------------
nuclear@0 95 const aiImporterDesc* PLYImporter::GetInfo () const
nuclear@0 96 {
nuclear@0 97 return &desc;
nuclear@0 98 }
nuclear@0 99
nuclear@0 100 // ------------------------------------------------------------------------------------------------
nuclear@0 101 // Imports the given file into the given scene structure.
nuclear@0 102 void PLYImporter::InternReadFile( const std::string& pFile,
nuclear@0 103 aiScene* pScene, IOSystem* pIOHandler)
nuclear@0 104 {
nuclear@0 105 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
nuclear@0 106
nuclear@0 107 // Check whether we can read from the file
nuclear@0 108 if( file.get() == NULL) {
nuclear@0 109 throw DeadlyImportError( "Failed to open PLY file " + pFile + ".");
nuclear@0 110 }
nuclear@0 111
nuclear@0 112 // allocate storage and copy the contents of the file to a memory buffer
nuclear@0 113 std::vector<char> mBuffer2;
nuclear@0 114 TextFileToBuffer(file.get(),mBuffer2);
nuclear@0 115 mBuffer = (unsigned char*)&mBuffer2[0];
nuclear@0 116
nuclear@0 117 // the beginning of the file must be PLY - magic, magic
nuclear@0 118 if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') ||
nuclear@0 119 (mBuffer[1] != 'L' && mBuffer[1] != 'l') ||
nuclear@0 120 (mBuffer[2] != 'Y' && mBuffer[2] != 'y')) {
nuclear@0 121 throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there");
nuclear@0 122 }
nuclear@0 123
nuclear@0 124 char* szMe = (char*)&this->mBuffer[3];
nuclear@0 125 SkipSpacesAndLineEnd(szMe,(const char**)&szMe);
nuclear@0 126
nuclear@0 127 // determine the format of the file data
nuclear@0 128 PLY::DOM sPlyDom;
nuclear@0 129 if (TokenMatch(szMe,"format",6))
nuclear@0 130 {
nuclear@0 131 if (TokenMatch(szMe,"ascii",5))
nuclear@0 132 {
nuclear@0 133 SkipLine(szMe,(const char**)&szMe);
nuclear@0 134 if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
nuclear@0 135 throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)");
nuclear@0 136 }
nuclear@0 137 else if (!::strncmp(szMe,"binary_",7))
nuclear@0 138 {
nuclear@0 139 bool bIsBE = false;
nuclear@0 140 szMe+=7;
nuclear@0 141
nuclear@0 142 // binary_little_endian
nuclear@0 143 // binary_big_endian
nuclear@0 144 #if (defined AI_BUILD_BIG_ENDIAN)
nuclear@0 145 if ('l' == *szMe || 'L' == *szMe)bIsBE = true;
nuclear@0 146 #else
nuclear@0 147 if ('b' == *szMe || 'B' == *szMe)bIsBE = true;
nuclear@0 148 #endif // ! AI_BUILD_BIG_ENDIAN
nuclear@0 149
nuclear@0 150 // skip the line, parse the rest of the header and build the DOM
nuclear@0 151 SkipLine(szMe,(const char**)&szMe);
nuclear@0 152 if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE))
nuclear@0 153 throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)");
nuclear@0 154 }
nuclear@0 155 else throw DeadlyImportError( "Invalid .ply file: Unknown file format");
nuclear@0 156 }
nuclear@0 157 else
nuclear@0 158 {
nuclear@0 159 delete[] this->mBuffer;
nuclear@0 160 AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
nuclear@0 161 throw DeadlyImportError( "Invalid .ply file: Missing format specification");
nuclear@0 162 }
nuclear@0 163 this->pcDOM = &sPlyDom;
nuclear@0 164
nuclear@0 165 // now load a list of vertices. This must be sucessfull in order to procede
nuclear@0 166 std::vector<aiVector3D> avPositions;
nuclear@0 167 this->LoadVertices(&avPositions,false);
nuclear@0 168
nuclear@0 169 if (avPositions.empty())
nuclear@0 170 throw DeadlyImportError( "Invalid .ply file: No vertices found. "
nuclear@0 171 "Unable to parse the data format of the PLY file.");
nuclear@0 172
nuclear@0 173 // now load a list of normals.
nuclear@0 174 std::vector<aiVector3D> avNormals;
nuclear@0 175 LoadVertices(&avNormals,true);
nuclear@0 176
nuclear@0 177 // load the face list
nuclear@0 178 std::vector<PLY::Face> avFaces;
nuclear@0 179 LoadFaces(&avFaces);
nuclear@0 180
nuclear@0 181 // if no face list is existing we assume that the vertex
nuclear@0 182 // list is containing a list of triangles
nuclear@0 183 if (avFaces.empty())
nuclear@0 184 {
nuclear@0 185 if (avPositions.size() < 3)
nuclear@0 186 {
nuclear@0 187 throw DeadlyImportError( "Invalid .ply file: Not enough "
nuclear@0 188 "vertices to build a proper face list. ");
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 const unsigned int iNum = (unsigned int)avPositions.size() / 3;
nuclear@0 192 for (unsigned int i = 0; i< iNum;++i)
nuclear@0 193 {
nuclear@0 194 PLY::Face sFace;
nuclear@0 195 sFace.mIndices.push_back((iNum*3));
nuclear@0 196 sFace.mIndices.push_back((iNum*3)+1);
nuclear@0 197 sFace.mIndices.push_back((iNum*3)+2);
nuclear@0 198 avFaces.push_back(sFace);
nuclear@0 199 }
nuclear@0 200 }
nuclear@0 201
nuclear@0 202 // now load a list of all materials
nuclear@0 203 std::vector<aiMaterial*> avMaterials;
nuclear@0 204 LoadMaterial(&avMaterials);
nuclear@0 205
nuclear@0 206 // now load a list of all vertex color channels
nuclear@0 207 std::vector<aiColor4D> avColors;
nuclear@0 208 avColors.reserve(avPositions.size());
nuclear@0 209 LoadVertexColor(&avColors);
nuclear@0 210
nuclear@0 211 // now try to load texture coordinates
nuclear@0 212 std::vector<aiVector2D> avTexCoords;
nuclear@0 213 avTexCoords.reserve(avPositions.size());
nuclear@0 214 LoadTextureCoordinates(&avTexCoords);
nuclear@0 215
nuclear@0 216 // now replace the default material in all faces and validate all material indices
nuclear@0 217 ReplaceDefaultMaterial(&avFaces,&avMaterials);
nuclear@0 218
nuclear@0 219 // now convert this to a list of aiMesh instances
nuclear@0 220 std::vector<aiMesh*> avMeshes;
nuclear@0 221 avMeshes.reserve(avMaterials.size()+1);
nuclear@0 222 ConvertMeshes(&avFaces,&avPositions,&avNormals,
nuclear@0 223 &avColors,&avTexCoords,&avMaterials,&avMeshes);
nuclear@0 224
nuclear@0 225 if (avMeshes.empty())
nuclear@0 226 throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data ");
nuclear@0 227
nuclear@0 228 // now generate the output scene object. Fill the material list
nuclear@0 229 pScene->mNumMaterials = (unsigned int)avMaterials.size();
nuclear@0 230 pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
nuclear@0 231 for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
nuclear@0 232 pScene->mMaterials[i] = avMaterials[i];
nuclear@0 233
nuclear@0 234 // fill the mesh list
nuclear@0 235 pScene->mNumMeshes = (unsigned int)avMeshes.size();
nuclear@0 236 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
nuclear@0 237 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
nuclear@0 238 pScene->mMeshes[i] = avMeshes[i];
nuclear@0 239
nuclear@0 240 // generate a simple node structure
nuclear@0 241 pScene->mRootNode = new aiNode();
nuclear@0 242 pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
nuclear@0 243 pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
nuclear@0 244
nuclear@0 245 for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes;++i)
nuclear@0 246 pScene->mRootNode->mMeshes[i] = i;
nuclear@0 247 }
nuclear@0 248
nuclear@0 249 // ------------------------------------------------------------------------------------------------
nuclear@0 250 // Split meshes by material IDs
nuclear@0 251 void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
nuclear@0 252 const std::vector<aiVector3D>* avPositions,
nuclear@0 253 const std::vector<aiVector3D>* avNormals,
nuclear@0 254 const std::vector<aiColor4D>* avColors,
nuclear@0 255 const std::vector<aiVector2D>* avTexCoords,
nuclear@0 256 const std::vector<aiMaterial*>* avMaterials,
nuclear@0 257 std::vector<aiMesh*>* avOut)
nuclear@0 258 {
nuclear@0 259 ai_assert(NULL != avFaces);
nuclear@0 260 ai_assert(NULL != avPositions);
nuclear@0 261 ai_assert(NULL != avMaterials);
nuclear@0 262
nuclear@0 263 // split by materials
nuclear@0 264 std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()];
nuclear@0 265
nuclear@0 266 unsigned int iNum = 0;
nuclear@0 267 for (std::vector<PLY::Face>::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum)
nuclear@0 268 aiSplit[(*i).iMaterialIndex].push_back(iNum);
nuclear@0 269
nuclear@0 270 // now generate submeshes
nuclear@0 271 for (unsigned int p = 0; p < avMaterials->size();++p)
nuclear@0 272 {
nuclear@0 273 if (aiSplit[p].size() != 0)
nuclear@0 274 {
nuclear@0 275 // allocate the mesh object
nuclear@0 276 aiMesh* p_pcOut = new aiMesh();
nuclear@0 277 p_pcOut->mMaterialIndex = p;
nuclear@0 278
nuclear@0 279 p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
nuclear@0 280 p_pcOut->mFaces = new aiFace[aiSplit[p].size()];
nuclear@0 281
nuclear@0 282 // at first we need to determine the size of the output vector array
nuclear@0 283 unsigned int iNum = 0;
nuclear@0 284 for (unsigned int i = 0; i < aiSplit[p].size();++i)
nuclear@0 285 {
nuclear@0 286 iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
nuclear@0 287 }
nuclear@0 288 p_pcOut->mNumVertices = iNum;
nuclear@0 289 p_pcOut->mVertices = new aiVector3D[iNum];
nuclear@0 290
nuclear@0 291 if (!avColors->empty())
nuclear@0 292 p_pcOut->mColors[0] = new aiColor4D[iNum];
nuclear@0 293 if (!avTexCoords->empty())
nuclear@0 294 {
nuclear@0 295 p_pcOut->mNumUVComponents[0] = 2;
nuclear@0 296 p_pcOut->mTextureCoords[0] = new aiVector3D[iNum];
nuclear@0 297 }
nuclear@0 298 if (!avNormals->empty())
nuclear@0 299 p_pcOut->mNormals = new aiVector3D[iNum];
nuclear@0 300
nuclear@0 301 // add all faces
nuclear@0 302 iNum = 0;
nuclear@0 303 unsigned int iVertex = 0;
nuclear@0 304 for (std::vector<unsigned int>::const_iterator i = aiSplit[p].begin();
nuclear@0 305 i != aiSplit[p].end();++i,++iNum)
nuclear@0 306 {
nuclear@0 307 p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size();
nuclear@0 308 p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices];
nuclear@0 309
nuclear@0 310 // build an unique set of vertices/colors for this face
nuclear@0 311 for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q)
nuclear@0 312 {
nuclear@0 313 p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
nuclear@0 314 p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]];
nuclear@0 315
nuclear@0 316 if (!avColors->empty())
nuclear@0 317 p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]];
nuclear@0 318
nuclear@0 319 if (!avTexCoords->empty())
nuclear@0 320 {
nuclear@0 321 const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]];
nuclear@0 322 p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
nuclear@0 323 p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
nuclear@0 324 }
nuclear@0 325
nuclear@0 326 if (!avNormals->empty())
nuclear@0 327 p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]];
nuclear@0 328 iVertex++;
nuclear@0 329 }
nuclear@0 330
nuclear@0 331 }
nuclear@0 332 // add the mesh to the output list
nuclear@0 333 avOut->push_back(p_pcOut);
nuclear@0 334 }
nuclear@0 335 }
nuclear@0 336 delete[] aiSplit; // cleanup
nuclear@0 337 }
nuclear@0 338
nuclear@0 339 // ------------------------------------------------------------------------------------------------
nuclear@0 340 // Generate a default material if none was specified and apply it to all vanilla faces
nuclear@0 341 void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
nuclear@0 342 std::vector<aiMaterial*>* avMaterials)
nuclear@0 343 {
nuclear@0 344 bool bNeedDefaultMat = false;
nuclear@0 345
nuclear@0 346 for (std::vector<PLY::Face>::iterator i = avFaces->begin();i != avFaces->end();++i) {
nuclear@0 347 if (0xFFFFFFFF == (*i).iMaterialIndex) {
nuclear@0 348 bNeedDefaultMat = true;
nuclear@0 349 (*i).iMaterialIndex = (unsigned int)avMaterials->size();
nuclear@0 350 }
nuclear@0 351 else if ((*i).iMaterialIndex >= avMaterials->size() ) {
nuclear@0 352 // clamp the index
nuclear@0 353 (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1;
nuclear@0 354 }
nuclear@0 355 }
nuclear@0 356
nuclear@0 357 if (bNeedDefaultMat) {
nuclear@0 358 // generate a default material
nuclear@0 359 aiMaterial* pcHelper = new aiMaterial();
nuclear@0 360
nuclear@0 361 // fill in a default material
nuclear@0 362 int iMode = (int)aiShadingMode_Gouraud;
nuclear@0 363 pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
nuclear@0 364
nuclear@0 365 aiColor3D clr;
nuclear@0 366 clr.b = clr.g = clr.r = 0.6f;
nuclear@0 367 pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
nuclear@0 368 pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
nuclear@0 369
nuclear@0 370 clr.b = clr.g = clr.r = 0.05f;
nuclear@0 371 pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
nuclear@0 372
nuclear@0 373 // The face order is absolutely undefined for PLY, so we have to
nuclear@0 374 // use two-sided rendering to be sure it's ok.
nuclear@0 375 const int two_sided = 1;
nuclear@0 376 pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
nuclear@0 377
nuclear@0 378 avMaterials->push_back(pcHelper);
nuclear@0 379 }
nuclear@0 380 }
nuclear@0 381
nuclear@0 382 // ------------------------------------------------------------------------------------------------
nuclear@0 383 void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
nuclear@0 384 {
nuclear@0 385 ai_assert(NULL != pvOut);
nuclear@0 386
nuclear@0 387 unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF};
nuclear@0 388 PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char};
nuclear@0 389 PLY::ElementInstanceList* pcList = NULL;
nuclear@0 390 unsigned int cnt = 0;
nuclear@0 391
nuclear@0 392 // serach in the DOM for a vertex entry
nuclear@0 393 unsigned int _i = 0;
nuclear@0 394 for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
nuclear@0 395 i != pcDOM->alElements.end();++i,++_i)
nuclear@0 396 {
nuclear@0 397 if (PLY::EEST_Vertex == (*i).eSemantic)
nuclear@0 398 {
nuclear@0 399 pcList = &this->pcDOM->alElementData[_i];
nuclear@0 400
nuclear@0 401 // now check whether which normal components are available
nuclear@0 402 unsigned int _a = 0;
nuclear@0 403 for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
nuclear@0 404 a != (*i).alProperties.end();++a,++_a)
nuclear@0 405 {
nuclear@0 406 if ((*a).bIsList)continue;
nuclear@0 407 if (PLY::EST_UTextureCoord == (*a).Semantic)
nuclear@0 408 {
nuclear@0 409 cnt++;
nuclear@0 410 aiPositions[0] = _a;
nuclear@0 411 aiTypes[0] = (*a).eType;
nuclear@0 412 }
nuclear@0 413 else if (PLY::EST_VTextureCoord == (*a).Semantic)
nuclear@0 414 {
nuclear@0 415 cnt++;
nuclear@0 416 aiPositions[1] = _a;
nuclear@0 417 aiTypes[1] = (*a).eType;
nuclear@0 418 }
nuclear@0 419 }
nuclear@0 420 }
nuclear@0 421 }
nuclear@0 422 // check whether we have a valid source for the texture coordinates data
nuclear@0 423 if (NULL != pcList && 0 != cnt)
nuclear@0 424 {
nuclear@0 425 pvOut->reserve(pcList->alInstances.size());
nuclear@0 426 for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
nuclear@0 427 i != pcList->alInstances.end();++i)
nuclear@0 428 {
nuclear@0 429 // convert the vertices to sp floats
nuclear@0 430 aiVector2D vOut;
nuclear@0 431
nuclear@0 432 if (0xFFFFFFFF != aiPositions[0])
nuclear@0 433 {
nuclear@0 434 vOut.x = PLY::PropertyInstance::ConvertTo<float>(
nuclear@0 435 (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
nuclear@0 436 }
nuclear@0 437
nuclear@0 438 if (0xFFFFFFFF != aiPositions[1])
nuclear@0 439 {
nuclear@0 440 vOut.y = PLY::PropertyInstance::ConvertTo<float>(
nuclear@0 441 (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
nuclear@0 442 }
nuclear@0 443 // and add them to our nice list
nuclear@0 444 pvOut->push_back(vOut);
nuclear@0 445 }
nuclear@0 446 }
nuclear@0 447 }
nuclear@0 448
nuclear@0 449 // ------------------------------------------------------------------------------------------------
nuclear@0 450 // Try to extract vertices from the PLY DOM
nuclear@0 451 void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
nuclear@0 452 {
nuclear@0 453 ai_assert(NULL != pvOut);
nuclear@0 454
nuclear@0 455 unsigned int aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
nuclear@0 456 PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char};
nuclear@0 457 PLY::ElementInstanceList* pcList = NULL;
nuclear@0 458 unsigned int cnt = 0;
nuclear@0 459
nuclear@0 460 // serach in the DOM for a vertex entry
nuclear@0 461 unsigned int _i = 0;
nuclear@0 462 for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
nuclear@0 463 i != pcDOM->alElements.end();++i,++_i)
nuclear@0 464 {
nuclear@0 465 if (PLY::EEST_Vertex == (*i).eSemantic)
nuclear@0 466 {
nuclear@0 467 pcList = &pcDOM->alElementData[_i];
nuclear@0 468
nuclear@0 469 // load normal vectors?
nuclear@0 470 if (p_bNormals)
nuclear@0 471 {
nuclear@0 472 // now check whether which normal components are available
nuclear@0 473 unsigned int _a = 0;
nuclear@0 474 for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
nuclear@0 475 a != (*i).alProperties.end();++a,++_a)
nuclear@0 476 {
nuclear@0 477 if ((*a).bIsList)continue;
nuclear@0 478 if (PLY::EST_XNormal == (*a).Semantic)
nuclear@0 479 {
nuclear@0 480 cnt++;
nuclear@0 481 aiPositions[0] = _a;
nuclear@0 482 aiTypes[0] = (*a).eType;
nuclear@0 483 }
nuclear@0 484 else if (PLY::EST_YNormal == (*a).Semantic)
nuclear@0 485 {
nuclear@0 486 cnt++;
nuclear@0 487 aiPositions[1] = _a;
nuclear@0 488 aiTypes[1] = (*a).eType;
nuclear@0 489 }
nuclear@0 490 else if (PLY::EST_ZNormal == (*a).Semantic)
nuclear@0 491 {
nuclear@0 492 cnt++;
nuclear@0 493 aiPositions[2] = _a;
nuclear@0 494 aiTypes[2] = (*a).eType;
nuclear@0 495 }
nuclear@0 496 }
nuclear@0 497 }
nuclear@0 498 // load vertex coordinates
nuclear@0 499 else
nuclear@0 500 {
nuclear@0 501 // now check whether which coordinate sets are available
nuclear@0 502 unsigned int _a = 0;
nuclear@0 503 for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
nuclear@0 504 a != (*i).alProperties.end();++a,++_a)
nuclear@0 505 {
nuclear@0 506 if ((*a).bIsList)continue;
nuclear@0 507 if (PLY::EST_XCoord == (*a).Semantic)
nuclear@0 508 {
nuclear@0 509 cnt++;
nuclear@0 510 aiPositions[0] = _a;
nuclear@0 511 aiTypes[0] = (*a).eType;
nuclear@0 512 }
nuclear@0 513 else if (PLY::EST_YCoord == (*a).Semantic)
nuclear@0 514 {
nuclear@0 515 cnt++;
nuclear@0 516 aiPositions[1] = _a;
nuclear@0 517 aiTypes[1] = (*a).eType;
nuclear@0 518 }
nuclear@0 519 else if (PLY::EST_ZCoord == (*a).Semantic)
nuclear@0 520 {
nuclear@0 521 cnt++;
nuclear@0 522 aiPositions[2] = _a;
nuclear@0 523 aiTypes[2] = (*a).eType;
nuclear@0 524 }
nuclear@0 525 if (3 == cnt)break;
nuclear@0 526 }
nuclear@0 527 }
nuclear@0 528 break;
nuclear@0 529 }
nuclear@0 530 }
nuclear@0 531 // check whether we have a valid source for the vertex data
nuclear@0 532 if (NULL != pcList && 0 != cnt)
nuclear@0 533 {
nuclear@0 534 pvOut->reserve(pcList->alInstances.size());
nuclear@0 535 for (std::vector<ElementInstance>::const_iterator
nuclear@0 536 i = pcList->alInstances.begin();
nuclear@0 537 i != pcList->alInstances.end();++i)
nuclear@0 538 {
nuclear@0 539 // convert the vertices to sp floats
nuclear@0 540 aiVector3D vOut;
nuclear@0 541
nuclear@0 542 if (0xFFFFFFFF != aiPositions[0])
nuclear@0 543 {
nuclear@0 544 vOut.x = PLY::PropertyInstance::ConvertTo<float>(
nuclear@0 545 (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
nuclear@0 546 }
nuclear@0 547
nuclear@0 548 if (0xFFFFFFFF != aiPositions[1])
nuclear@0 549 {
nuclear@0 550 vOut.y = PLY::PropertyInstance::ConvertTo<float>(
nuclear@0 551 (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
nuclear@0 552 }
nuclear@0 553
nuclear@0 554 if (0xFFFFFFFF != aiPositions[2])
nuclear@0 555 {
nuclear@0 556 vOut.z = PLY::PropertyInstance::ConvertTo<float>(
nuclear@0 557 (*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
nuclear@0 558 }
nuclear@0 559
nuclear@0 560 // and add them to our nice list
nuclear@0 561 pvOut->push_back(vOut);
nuclear@0 562 }
nuclear@0 563 }
nuclear@0 564 }
nuclear@0 565
nuclear@0 566 // ------------------------------------------------------------------------------------------------
nuclear@0 567 // Convert a color component to [0...1]
nuclear@0 568 float PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,
nuclear@0 569 PLY::EDataType eType)
nuclear@0 570 {
nuclear@0 571 switch (eType)
nuclear@0 572 {
nuclear@0 573 case EDT_Float:
nuclear@0 574 return val.fFloat;
nuclear@0 575 case EDT_Double:
nuclear@0 576 return (float)val.fDouble;
nuclear@0 577
nuclear@0 578 case EDT_UChar:
nuclear@0 579 return (float)val.iUInt / (float)0xFF;
nuclear@0 580 case EDT_Char:
nuclear@0 581 return (float)(val.iInt+(0xFF/2)) / (float)0xFF;
nuclear@0 582 case EDT_UShort:
nuclear@0 583 return (float)val.iUInt / (float)0xFFFF;
nuclear@0 584 case EDT_Short:
nuclear@0 585 return (float)(val.iInt+(0xFFFF/2)) / (float)0xFFFF;
nuclear@0 586 case EDT_UInt:
nuclear@0 587 return (float)val.iUInt / (float)0xFFFF;
nuclear@0 588 case EDT_Int:
nuclear@0 589 return ((float)val.iInt / (float)0xFF) + 0.5f;
nuclear@0 590 default: ;
nuclear@0 591 };
nuclear@0 592 return 0.0f;
nuclear@0 593 }
nuclear@0 594
nuclear@0 595 // ------------------------------------------------------------------------------------------------
nuclear@0 596 // Try to extract proper vertex colors from the PLY DOM
nuclear@0 597 void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
nuclear@0 598 {
nuclear@0 599 ai_assert(NULL != pvOut);
nuclear@0 600
nuclear@0 601 unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
nuclear@0 602 PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc
nuclear@0 603 unsigned int cnt = 0;
nuclear@0 604 PLY::ElementInstanceList* pcList = NULL;
nuclear@0 605
nuclear@0 606 // serach in the DOM for a vertex entry
nuclear@0 607 unsigned int _i = 0;
nuclear@0 608 for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
nuclear@0 609 i != pcDOM->alElements.end();++i,++_i)
nuclear@0 610 {
nuclear@0 611 if (PLY::EEST_Vertex == (*i).eSemantic)
nuclear@0 612 {
nuclear@0 613 pcList = &this->pcDOM->alElementData[_i];
nuclear@0 614
nuclear@0 615 // now check whether which coordinate sets are available
nuclear@0 616 unsigned int _a = 0;
nuclear@0 617 for (std::vector<PLY::Property>::const_iterator
nuclear@0 618 a = (*i).alProperties.begin();
nuclear@0 619 a != (*i).alProperties.end();++a,++_a)
nuclear@0 620 {
nuclear@0 621 if ((*a).bIsList)continue;
nuclear@0 622 if (PLY::EST_Red == (*a).Semantic)
nuclear@0 623 {
nuclear@0 624 cnt++;
nuclear@0 625 aiPositions[0] = _a;
nuclear@0 626 aiTypes[0] = (*a).eType;
nuclear@0 627 }
nuclear@0 628 else if (PLY::EST_Green == (*a).Semantic)
nuclear@0 629 {
nuclear@0 630 cnt++;
nuclear@0 631 aiPositions[1] = _a;
nuclear@0 632 aiTypes[1] = (*a).eType;
nuclear@0 633 }
nuclear@0 634 else if (PLY::EST_Blue == (*a).Semantic)
nuclear@0 635 {
nuclear@0 636 cnt++;
nuclear@0 637 aiPositions[2] = _a;
nuclear@0 638 aiTypes[2] = (*a).eType;
nuclear@0 639 }
nuclear@0 640 else if (PLY::EST_Alpha == (*a).Semantic)
nuclear@0 641 {
nuclear@0 642 cnt++;
nuclear@0 643 aiPositions[3] = _a;
nuclear@0 644 aiTypes[3] = (*a).eType;
nuclear@0 645 }
nuclear@0 646 if (4 == cnt)break;
nuclear@0 647 }
nuclear@0 648 break;
nuclear@0 649 }
nuclear@0 650 }
nuclear@0 651 // check whether we have a valid source for the vertex data
nuclear@0 652 if (NULL != pcList && 0 != cnt)
nuclear@0 653 {
nuclear@0 654 pvOut->reserve(pcList->alInstances.size());
nuclear@0 655 for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
nuclear@0 656 i != pcList->alInstances.end();++i)
nuclear@0 657 {
nuclear@0 658 // convert the vertices to sp floats
nuclear@0 659 aiColor4D vOut;
nuclear@0 660
nuclear@0 661 if (0xFFFFFFFF != aiPositions[0])
nuclear@0 662 {
nuclear@0 663 vOut.r = NormalizeColorValue((*i).alProperties[
nuclear@0 664 aiPositions[0]].avList.front(),aiTypes[0]);
nuclear@0 665 }
nuclear@0 666
nuclear@0 667 if (0xFFFFFFFF != aiPositions[1])
nuclear@0 668 {
nuclear@0 669 vOut.g = NormalizeColorValue((*i).alProperties[
nuclear@0 670 aiPositions[1]].avList.front(),aiTypes[1]);
nuclear@0 671 }
nuclear@0 672
nuclear@0 673 if (0xFFFFFFFF != aiPositions[2])
nuclear@0 674 {
nuclear@0 675 vOut.b = NormalizeColorValue((*i).alProperties[
nuclear@0 676 aiPositions[2]].avList.front(),aiTypes[2]);
nuclear@0 677 }
nuclear@0 678
nuclear@0 679 // assume 1.0 for the alpha channel ifit is not set
nuclear@0 680 if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
nuclear@0 681 else
nuclear@0 682 {
nuclear@0 683 vOut.a = NormalizeColorValue((*i).alProperties[
nuclear@0 684 aiPositions[3]].avList.front(),aiTypes[3]);
nuclear@0 685 }
nuclear@0 686
nuclear@0 687 // and add them to our nice list
nuclear@0 688 pvOut->push_back(vOut);
nuclear@0 689 }
nuclear@0 690 }
nuclear@0 691 }
nuclear@0 692
nuclear@0 693 // ------------------------------------------------------------------------------------------------
nuclear@0 694 // Try to extract proper faces from the PLY DOM
nuclear@0 695 void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
nuclear@0 696 {
nuclear@0 697 ai_assert(NULL != pvOut);
nuclear@0 698
nuclear@0 699 PLY::ElementInstanceList* pcList = NULL;
nuclear@0 700 bool bOne = false;
nuclear@0 701
nuclear@0 702 // index of the vertex index list
nuclear@0 703 unsigned int iProperty = 0xFFFFFFFF;
nuclear@0 704 PLY::EDataType eType = EDT_Char;
nuclear@0 705 bool bIsTristrip = false;
nuclear@0 706
nuclear@0 707 // index of the material index property
nuclear@0 708 unsigned int iMaterialIndex = 0xFFFFFFFF;
nuclear@0 709 PLY::EDataType eType2 = EDT_Char;
nuclear@0 710
nuclear@0 711 // serach in the DOM for a face entry
nuclear@0 712 unsigned int _i = 0;
nuclear@0 713 for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
nuclear@0 714 i != pcDOM->alElements.end();++i,++_i)
nuclear@0 715 {
nuclear@0 716 // face = unique number of vertex indices
nuclear@0 717 if (PLY::EEST_Face == (*i).eSemantic)
nuclear@0 718 {
nuclear@0 719 pcList = &pcDOM->alElementData[_i];
nuclear@0 720 unsigned int _a = 0;
nuclear@0 721 for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
nuclear@0 722 a != (*i).alProperties.end();++a,++_a)
nuclear@0 723 {
nuclear@0 724 if (PLY::EST_VertexIndex == (*a).Semantic)
nuclear@0 725 {
nuclear@0 726 // must be a dynamic list!
nuclear@0 727 if (!(*a).bIsList)continue;
nuclear@0 728 iProperty = _a;
nuclear@0 729 bOne = true;
nuclear@0 730 eType = (*a).eType;
nuclear@0 731 }
nuclear@0 732 else if (PLY::EST_MaterialIndex == (*a).Semantic)
nuclear@0 733 {
nuclear@0 734 if ((*a).bIsList)continue;
nuclear@0 735 iMaterialIndex = _a;
nuclear@0 736 bOne = true;
nuclear@0 737 eType2 = (*a).eType;
nuclear@0 738 }
nuclear@0 739 }
nuclear@0 740 break;
nuclear@0 741 }
nuclear@0 742 // triangle strip
nuclear@0 743 // TODO: triangle strip and material index support???
nuclear@0 744 else if (PLY::EEST_TriStrip == (*i).eSemantic)
nuclear@0 745 {
nuclear@0 746 // find a list property in this ...
nuclear@0 747 pcList = &this->pcDOM->alElementData[_i];
nuclear@0 748 unsigned int _a = 0;
nuclear@0 749 for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
nuclear@0 750 a != (*i).alProperties.end();++a,++_a)
nuclear@0 751 {
nuclear@0 752 // must be a dynamic list!
nuclear@0 753 if (!(*a).bIsList)continue;
nuclear@0 754 iProperty = _a;
nuclear@0 755 bOne = true;
nuclear@0 756 bIsTristrip = true;
nuclear@0 757 eType = (*a).eType;
nuclear@0 758 break;
nuclear@0 759 }
nuclear@0 760 break;
nuclear@0 761 }
nuclear@0 762 }
nuclear@0 763 // check whether we have at least one per-face information set
nuclear@0 764 if (pcList && bOne)
nuclear@0 765 {
nuclear@0 766 if (!bIsTristrip)
nuclear@0 767 {
nuclear@0 768 pvOut->reserve(pcList->alInstances.size());
nuclear@0 769 for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
nuclear@0 770 i != pcList->alInstances.end();++i)
nuclear@0 771 {
nuclear@0 772 PLY::Face sFace;
nuclear@0 773
nuclear@0 774 // parse the list of vertex indices
nuclear@0 775 if (0xFFFFFFFF != iProperty)
nuclear@0 776 {
nuclear@0 777 const unsigned int iNum = (unsigned int)(*i).alProperties[iProperty].avList.size();
nuclear@0 778 sFace.mIndices.resize(iNum);
nuclear@0 779
nuclear@0 780 std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
nuclear@0 781 (*i).alProperties[iProperty].avList.begin();
nuclear@0 782
nuclear@0 783 for (unsigned int a = 0; a < iNum;++a,++p)
nuclear@0 784 {
nuclear@0 785 sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p,eType);
nuclear@0 786 }
nuclear@0 787 }
nuclear@0 788
nuclear@0 789 // parse the material index
nuclear@0 790 if (0xFFFFFFFF != iMaterialIndex)
nuclear@0 791 {
nuclear@0 792 sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
nuclear@0 793 (*i).alProperties[iMaterialIndex].avList.front(),eType2);
nuclear@0 794 }
nuclear@0 795 pvOut->push_back(sFace);
nuclear@0 796 }
nuclear@0 797 }
nuclear@0 798 else // triangle strips
nuclear@0 799 {
nuclear@0 800 // normally we have only one triangle strip instance where
nuclear@0 801 // a value of -1 indicates a restart of the strip
nuclear@0 802 bool flip = false;
nuclear@0 803 for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
nuclear@0 804 const std::vector<PLY::PropertyInstance::ValueUnion>& quak = (*i).alProperties[iProperty].avList;
nuclear@0 805 pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
nuclear@0 806
nuclear@0 807 int aiTable[2] = {-1,-1};
nuclear@0 808 for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin();a != quak.end();++a) {
nuclear@0 809 const int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType);
nuclear@0 810
nuclear@0 811 if (-1 == p) {
nuclear@0 812 // restart the strip ...
nuclear@0 813 aiTable[0] = aiTable[1] = -1;
nuclear@0 814 flip = false;
nuclear@0 815 continue;
nuclear@0 816 }
nuclear@0 817 if (-1 == aiTable[0]) {
nuclear@0 818 aiTable[0] = p;
nuclear@0 819 continue;
nuclear@0 820 }
nuclear@0 821 if (-1 == aiTable[1]) {
nuclear@0 822 aiTable[1] = p;
nuclear@0 823 continue;
nuclear@0 824 }
nuclear@0 825
nuclear@0 826 pvOut->push_back(PLY::Face());
nuclear@0 827 PLY::Face& sFace = pvOut->back();
nuclear@0 828 sFace.mIndices[0] = aiTable[0];
nuclear@0 829 sFace.mIndices[1] = aiTable[1];
nuclear@0 830 sFace.mIndices[2] = p;
nuclear@0 831 if ((flip = !flip)) {
nuclear@0 832 std::swap(sFace.mIndices[0],sFace.mIndices[1]);
nuclear@0 833 }
nuclear@0 834
nuclear@0 835 aiTable[0] = aiTable[1];
nuclear@0 836 aiTable[1] = p;
nuclear@0 837 }
nuclear@0 838 }
nuclear@0 839 }
nuclear@0 840 }
nuclear@0 841 }
nuclear@0 842
nuclear@0 843 // ------------------------------------------------------------------------------------------------
nuclear@0 844 // Get a RGBA color in [0...1] range
nuclear@0 845 void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
nuclear@0 846 unsigned int aiPositions[4],
nuclear@0 847 PLY::EDataType aiTypes[4],
nuclear@0 848 aiColor4D* clrOut)
nuclear@0 849 {
nuclear@0 850 ai_assert(NULL != clrOut);
nuclear@0 851
nuclear@0 852 if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
nuclear@0 853 else
nuclear@0 854 {
nuclear@0 855 clrOut->r = NormalizeColorValue(avList[
nuclear@0 856 aiPositions[0]].avList.front(),aiTypes[0]);
nuclear@0 857 }
nuclear@0 858
nuclear@0 859 if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
nuclear@0 860 else
nuclear@0 861 {
nuclear@0 862 clrOut->g = NormalizeColorValue(avList[
nuclear@0 863 aiPositions[1]].avList.front(),aiTypes[1]);
nuclear@0 864 }
nuclear@0 865
nuclear@0 866 if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
nuclear@0 867 else
nuclear@0 868 {
nuclear@0 869 clrOut->b = NormalizeColorValue(avList[
nuclear@0 870 aiPositions[2]].avList.front(),aiTypes[2]);
nuclear@0 871 }
nuclear@0 872
nuclear@0 873 // assume 1.0 for the alpha channel ifit is not set
nuclear@0 874 if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
nuclear@0 875 else
nuclear@0 876 {
nuclear@0 877 clrOut->a = NormalizeColorValue(avList[
nuclear@0 878 aiPositions[3]].avList.front(),aiTypes[3]);
nuclear@0 879 }
nuclear@0 880 }
nuclear@0 881
nuclear@0 882 // ------------------------------------------------------------------------------------------------
nuclear@0 883 // Extract a material from the PLY DOM
nuclear@0 884 void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
nuclear@0 885 {
nuclear@0 886 ai_assert(NULL != pvOut);
nuclear@0 887
nuclear@0 888 // diffuse[4], specular[4], ambient[4]
nuclear@0 889 // rgba order
nuclear@0 890 unsigned int aaiPositions[3][4] = {
nuclear@0 891
nuclear@0 892 {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
nuclear@0 893 {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
nuclear@0 894 {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
nuclear@0 895 };
nuclear@0 896
nuclear@0 897 PLY::EDataType aaiTypes[3][4] = {
nuclear@0 898 {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
nuclear@0 899 {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
nuclear@0 900 {EDT_Char,EDT_Char,EDT_Char,EDT_Char}
nuclear@0 901 };
nuclear@0 902 PLY::ElementInstanceList* pcList = NULL;
nuclear@0 903
nuclear@0 904 unsigned int iPhong = 0xFFFFFFFF;
nuclear@0 905 PLY::EDataType ePhong = EDT_Char;
nuclear@0 906
nuclear@0 907 unsigned int iOpacity = 0xFFFFFFFF;
nuclear@0 908 PLY::EDataType eOpacity = EDT_Char;
nuclear@0 909
nuclear@0 910 // serach in the DOM for a vertex entry
nuclear@0 911 unsigned int _i = 0;
nuclear@0 912 for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
nuclear@0 913 i != this->pcDOM->alElements.end();++i,++_i)
nuclear@0 914 {
nuclear@0 915 if (PLY::EEST_Material == (*i).eSemantic)
nuclear@0 916 {
nuclear@0 917 pcList = &this->pcDOM->alElementData[_i];
nuclear@0 918
nuclear@0 919 // now check whether which coordinate sets are available
nuclear@0 920 unsigned int _a = 0;
nuclear@0 921 for (std::vector<PLY::Property>::const_iterator
nuclear@0 922 a = (*i).alProperties.begin();
nuclear@0 923 a != (*i).alProperties.end();++a,++_a)
nuclear@0 924 {
nuclear@0 925 if ((*a).bIsList)continue;
nuclear@0 926
nuclear@0 927 // pohng specularity -----------------------------------
nuclear@0 928 if (PLY::EST_PhongPower == (*a).Semantic)
nuclear@0 929 {
nuclear@0 930 iPhong = _a;
nuclear@0 931 ePhong = (*a).eType;
nuclear@0 932 }
nuclear@0 933
nuclear@0 934 // general opacity -----------------------------------
nuclear@0 935 if (PLY::EST_Opacity == (*a).Semantic)
nuclear@0 936 {
nuclear@0 937 iOpacity = _a;
nuclear@0 938 eOpacity = (*a).eType;
nuclear@0 939 }
nuclear@0 940
nuclear@0 941 // diffuse color channels -----------------------------------
nuclear@0 942 if (PLY::EST_DiffuseRed == (*a).Semantic)
nuclear@0 943 {
nuclear@0 944 aaiPositions[0][0] = _a;
nuclear@0 945 aaiTypes[0][0] = (*a).eType;
nuclear@0 946 }
nuclear@0 947 else if (PLY::EST_DiffuseGreen == (*a).Semantic)
nuclear@0 948 {
nuclear@0 949 aaiPositions[0][1] = _a;
nuclear@0 950 aaiTypes[0][1] = (*a).eType;
nuclear@0 951 }
nuclear@0 952 else if (PLY::EST_DiffuseBlue == (*a).Semantic)
nuclear@0 953 {
nuclear@0 954 aaiPositions[0][2] = _a;
nuclear@0 955 aaiTypes[0][2] = (*a).eType;
nuclear@0 956 }
nuclear@0 957 else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
nuclear@0 958 {
nuclear@0 959 aaiPositions[0][3] = _a;
nuclear@0 960 aaiTypes[0][3] = (*a).eType;
nuclear@0 961 }
nuclear@0 962 // specular color channels -----------------------------------
nuclear@0 963 else if (PLY::EST_SpecularRed == (*a).Semantic)
nuclear@0 964 {
nuclear@0 965 aaiPositions[1][0] = _a;
nuclear@0 966 aaiTypes[1][0] = (*a).eType;
nuclear@0 967 }
nuclear@0 968 else if (PLY::EST_SpecularGreen == (*a).Semantic)
nuclear@0 969 {
nuclear@0 970 aaiPositions[1][1] = _a;
nuclear@0 971 aaiTypes[1][1] = (*a).eType;
nuclear@0 972 }
nuclear@0 973 else if (PLY::EST_SpecularBlue == (*a).Semantic)
nuclear@0 974 {
nuclear@0 975 aaiPositions[1][2] = _a;
nuclear@0 976 aaiTypes[1][2] = (*a).eType;
nuclear@0 977 }
nuclear@0 978 else if (PLY::EST_SpecularAlpha == (*a).Semantic)
nuclear@0 979 {
nuclear@0 980 aaiPositions[1][3] = _a;
nuclear@0 981 aaiTypes[1][3] = (*a).eType;
nuclear@0 982 }
nuclear@0 983 // ambient color channels -----------------------------------
nuclear@0 984 else if (PLY::EST_AmbientRed == (*a).Semantic)
nuclear@0 985 {
nuclear@0 986 aaiPositions[2][0] = _a;
nuclear@0 987 aaiTypes[2][0] = (*a).eType;
nuclear@0 988 }
nuclear@0 989 else if (PLY::EST_AmbientGreen == (*a).Semantic)
nuclear@0 990 {
nuclear@0 991 aaiPositions[2][1] = _a;
nuclear@0 992 aaiTypes[2][1] = (*a).eType;
nuclear@0 993 }
nuclear@0 994 else if (PLY::EST_AmbientBlue == (*a).Semantic)
nuclear@0 995 {
nuclear@0 996 aaiPositions[2][2] = _a;
nuclear@0 997 aaiTypes[2][2] = (*a).eType;
nuclear@0 998 }
nuclear@0 999 else if (PLY::EST_AmbientAlpha == (*a).Semantic)
nuclear@0 1000 {
nuclear@0 1001 aaiPositions[2][3] = _a;
nuclear@0 1002 aaiTypes[2][3] = (*a).eType;
nuclear@0 1003 }
nuclear@0 1004 }
nuclear@0 1005 break;
nuclear@0 1006 }
nuclear@0 1007 }
nuclear@0 1008 // check whether we have a valid source for the material data
nuclear@0 1009 if (NULL != pcList) {
nuclear@0 1010 for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
nuclear@0 1011 aiColor4D clrOut;
nuclear@0 1012 aiMaterial* pcHelper = new aiMaterial();
nuclear@0 1013
nuclear@0 1014 // build the diffuse material color
nuclear@0 1015 GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
nuclear@0 1016 pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE);
nuclear@0 1017
nuclear@0 1018 // build the specular material color
nuclear@0 1019 GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
nuclear@0 1020 pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR);
nuclear@0 1021
nuclear@0 1022 // build the ambient material color
nuclear@0 1023 GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
nuclear@0 1024 pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT);
nuclear@0 1025
nuclear@0 1026 // handle phong power and shading mode
nuclear@0 1027 int iMode;
nuclear@0 1028 if (0xFFFFFFFF != iPhong) {
nuclear@0 1029 float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong);
nuclear@0 1030
nuclear@0 1031 // if shininess is 0 (and the pow() calculation would therefore always
nuclear@0 1032 // become 1, not depending on the angle), use gouraud lighting
nuclear@0 1033 if (fSpec) {
nuclear@0 1034 // scale this with 15 ... hopefully this is correct
nuclear@0 1035 fSpec *= 15;
nuclear@0 1036 pcHelper->AddProperty<float>(&fSpec, 1, AI_MATKEY_SHININESS);
nuclear@0 1037
nuclear@0 1038 iMode = (int)aiShadingMode_Phong;
nuclear@0 1039 }
nuclear@0 1040 else iMode = (int)aiShadingMode_Gouraud;
nuclear@0 1041 }
nuclear@0 1042 else iMode = (int)aiShadingMode_Gouraud;
nuclear@0 1043 pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
nuclear@0 1044
nuclear@0 1045 // handle opacity
nuclear@0 1046 if (0xFFFFFFFF != iOpacity) {
nuclear@0 1047 float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity);
nuclear@0 1048 pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
nuclear@0 1049 }
nuclear@0 1050
nuclear@0 1051 // The face order is absolutely undefined for PLY, so we have to
nuclear@0 1052 // use two-sided rendering to be sure it's ok.
nuclear@0 1053 const int two_sided = 1;
nuclear@0 1054 pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
nuclear@0 1055
nuclear@0 1056 // add the newly created material instance to the list
nuclear@0 1057 pvOut->push_back(pcHelper);
nuclear@0 1058 }
nuclear@0 1059 }
nuclear@0 1060 }
nuclear@0 1061
nuclear@0 1062 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER