PlyLoader.cpp 28 KB

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