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
|