/src/assimp/code/AssetLib/Ply/PlyParser.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | --------------------------------------------------------------------------- |
3 | | Open Asset Import Library (assimp) |
4 | | --------------------------------------------------------------------------- |
5 | | |
6 | | Copyright (c) 2006-2025, assimp team |
7 | | |
8 | | All rights reserved. |
9 | | |
10 | | Redistribution and use of this software in source and binary forms, |
11 | | with or without modification, are permitted provided that the following |
12 | | conditions are met: |
13 | | |
14 | | * Redistributions of source code must retain the above |
15 | | copyright notice, this list of conditions and the |
16 | | following disclaimer. |
17 | | |
18 | | * Redistributions in binary form must reproduce the above |
19 | | copyright notice, this list of conditions and the |
20 | | following disclaimer in the documentation and/or other |
21 | | materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the assimp team, nor the names of its |
24 | | contributors may be used to endorse or promote products |
25 | | derived from this software without specific prior |
26 | | written permission of the assimp team. |
27 | | |
28 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
29 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
30 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
31 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
32 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
33 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
34 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
35 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
36 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
37 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
38 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
39 | | --------------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | /** @file Implementation of the PLY parser class */ |
43 | | |
44 | | #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER |
45 | | |
46 | | #include "PlyLoader.h" |
47 | | #include <assimp/ByteSwapper.h> |
48 | | #include <assimp/fast_atof.h> |
49 | | #include <assimp/DefaultLogger.hpp> |
50 | | #include <unordered_set> |
51 | | #include <utility> |
52 | | |
53 | | namespace Assimp { |
54 | | |
55 | 0 | std::string to_string(EElementSemantic e) { |
56 | |
|
57 | 0 | switch (e) { |
58 | 0 | case EEST_Vertex: |
59 | 0 | return std::string{ "vertex" }; |
60 | 0 | case EEST_TriStrip: |
61 | 0 | return std::string{ "tristrips" }; |
62 | 0 | case EEST_Edge: |
63 | 0 | return std::string{ "edge" }; |
64 | 0 | case EEST_Material: |
65 | 0 | return std::string{ "material" }; |
66 | 0 | case EEST_TextureFile: |
67 | 0 | return std::string{ "TextureFile" }; |
68 | 0 | default: |
69 | 0 | return std::string{ "invalid" }; |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | // ------------------------------------------------------------------------------------------------ |
74 | 0 | PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) { |
75 | 0 | ai_assert(!buffer.empty()); |
76 | |
|
77 | 0 | PLY::EDataType eOut = PLY::EDT_INVALID; |
78 | |
|
79 | 0 | if (PLY::DOM::TokenMatch(buffer, "char", 4) || |
80 | 0 | PLY::DOM::TokenMatch(buffer, "int8", 4)) { |
81 | 0 | eOut = PLY::EDT_Char; |
82 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) || |
83 | 0 | PLY::DOM::TokenMatch(buffer, "uint8", 5)) { |
84 | 0 | eOut = PLY::EDT_UChar; |
85 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "short", 5) || |
86 | 0 | PLY::DOM::TokenMatch(buffer, "int16", 5)) { |
87 | 0 | eOut = PLY::EDT_Short; |
88 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) || |
89 | 0 | PLY::DOM::TokenMatch(buffer, "uint16", 6)) { |
90 | 0 | eOut = PLY::EDT_UShort; |
91 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3)) { |
92 | 0 | eOut = PLY::EDT_Int; |
93 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4)) { |
94 | 0 | eOut = PLY::EDT_UInt; |
95 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7)) { |
96 | 0 | eOut = PLY::EDT_Float; |
97 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) || |
98 | 0 | PLY::DOM::TokenMatch(buffer, "float64", 7)) { |
99 | 0 | eOut = PLY::EDT_Double; |
100 | 0 | } |
101 | 0 | if (PLY::EDT_INVALID == eOut) { |
102 | 0 | ASSIMP_LOG_INFO("Found unknown data type in PLY file. This is OK"); |
103 | 0 | } |
104 | |
|
105 | 0 | return eOut; |
106 | 0 | } |
107 | | |
108 | | // ------------------------------------------------------------------------------------------------ |
109 | 0 | PLY::ESemantic PLY::Property::ParseSemantic(std::vector<char> &buffer) { |
110 | 0 | ai_assert(!buffer.empty()); |
111 | |
|
112 | 0 | PLY::ESemantic eOut = PLY::EST_INVALID; |
113 | 0 | if (PLY::DOM::TokenMatch(buffer, "red", 3)) { |
114 | 0 | eOut = PLY::EST_Red; |
115 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "green", 5)) { |
116 | 0 | eOut = PLY::EST_Green; |
117 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) { |
118 | 0 | eOut = PLY::EST_Blue; |
119 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) { |
120 | 0 | eOut = PLY::EST_Alpha; |
121 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) { |
122 | 0 | eOut = PLY::EST_VertexIndex; |
123 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces |
124 | 0 | { |
125 | 0 | eOut = PLY::EST_TextureCoordinates; |
126 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "material_index", 14)) { |
127 | 0 | eOut = PLY::EST_MaterialIndex; |
128 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11)) { |
129 | 0 | eOut = PLY::EST_AmbientRed; |
130 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13)) { |
131 | 0 | eOut = PLY::EST_AmbientGreen; |
132 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12)) { |
133 | 0 | eOut = PLY::EST_AmbientBlue; |
134 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13)) { |
135 | 0 | eOut = PLY::EST_AmbientAlpha; |
136 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11)) { |
137 | 0 | eOut = PLY::EST_DiffuseRed; |
138 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13)) { |
139 | 0 | eOut = PLY::EST_DiffuseGreen; |
140 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12)) { |
141 | 0 | eOut = PLY::EST_DiffuseBlue; |
142 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13)) { |
143 | 0 | eOut = PLY::EST_DiffuseAlpha; |
144 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12)) { |
145 | 0 | eOut = PLY::EST_SpecularRed; |
146 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14)) { |
147 | 0 | eOut = PLY::EST_SpecularGreen; |
148 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13)) { |
149 | 0 | eOut = PLY::EST_SpecularBlue; |
150 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14)) { |
151 | 0 | eOut = PLY::EST_SpecularAlpha; |
152 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "opacity", 7)) { |
153 | 0 | eOut = PLY::EST_Opacity; |
154 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14)) { |
155 | 0 | eOut = PLY::EST_PhongPower; |
156 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "r", 1)) { |
157 | 0 | eOut = PLY::EST_Red; |
158 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "g", 1)) { |
159 | 0 | eOut = PLY::EST_Green; |
160 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "b", 1)) { |
161 | 0 | eOut = PLY::EST_Blue; |
162 | 0 | } |
163 | | |
164 | | // NOTE: Blender3D exports texture coordinates as s,t tuples |
165 | 0 | else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2) || PLY::DOM::TokenMatch(buffer, "texture_u", 9)) { |
166 | 0 | eOut = PLY::EST_UTextureCoord; |
167 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9)) { |
168 | 0 | eOut = PLY::EST_VTextureCoord; |
169 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "x", 1)) { |
170 | 0 | eOut = PLY::EST_XCoord; |
171 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "y", 1)) { |
172 | 0 | eOut = PLY::EST_YCoord; |
173 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "z", 1)) { |
174 | 0 | eOut = PLY::EST_ZCoord; |
175 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) { |
176 | 0 | eOut = PLY::EST_XNormal; |
177 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) { |
178 | 0 | eOut = PLY::EST_YNormal; |
179 | 0 | } else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) { |
180 | 0 | eOut = PLY::EST_ZNormal; |
181 | 0 | } else { |
182 | 0 | ASSIMP_LOG_INFO("Found unknown property semantic in file. This is ok"); |
183 | 0 | PLY::DOM::SkipLine(buffer); |
184 | 0 | } |
185 | 0 | return eOut; |
186 | 0 | } |
187 | | |
188 | | // ------------------------------------------------------------------------------------------------ |
189 | 8 | bool PLY::Property::ParseProperty(std::vector<char> &buffer, PLY::Property *pOut) { |
190 | 8 | ai_assert(!buffer.empty()); |
191 | | |
192 | | // Forms supported: |
193 | | // "property float x" |
194 | | // "property list uchar int vertex_index" |
195 | | |
196 | | // skip leading spaces |
197 | 8 | if (!PLY::DOM::SkipSpaces(buffer)) { |
198 | 0 | return false; |
199 | 0 | } |
200 | | |
201 | | // skip the "property" string at the beginning |
202 | 8 | if (!PLY::DOM::TokenMatch(buffer, "property", 8)) { |
203 | | // seems not to be a valid property entry |
204 | 8 | return false; |
205 | 8 | } |
206 | | // get next word |
207 | 0 | if (!PLY::DOM::SkipSpaces(buffer)) { |
208 | 0 | return false; |
209 | 0 | } |
210 | 0 | if (PLY::DOM::TokenMatch(buffer, "list", 4)) { |
211 | 0 | pOut->bIsList = true; |
212 | | |
213 | | // seems to be a list. |
214 | 0 | if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer))) { |
215 | | // unable to parse list size data type |
216 | 0 | PLY::DOM::SkipLine(buffer); |
217 | 0 | return false; |
218 | 0 | } |
219 | 0 | if (!PLY::DOM::SkipSpaces(buffer)) return false; |
220 | 0 | if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) { |
221 | | // unable to parse list data type |
222 | 0 | PLY::DOM::SkipLine(buffer); |
223 | 0 | return false; |
224 | 0 | } |
225 | 0 | } else { |
226 | 0 | if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) { |
227 | | // unable to parse data type. Skip the property |
228 | 0 | PLY::DOM::SkipLine(buffer); |
229 | 0 | return false; |
230 | 0 | } |
231 | 0 | } |
232 | | |
233 | 0 | if (!PLY::DOM::SkipSpaces(buffer)) |
234 | 0 | return false; |
235 | | |
236 | 0 | pOut->Semantic = PLY::Property::ParseSemantic(buffer); |
237 | |
|
238 | 0 | if (PLY::EST_INVALID == pOut->Semantic) { |
239 | 0 | ASSIMP_LOG_INFO("Found unknown semantic in PLY file. This is OK"); |
240 | 0 | std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); |
241 | 0 | } |
242 | |
|
243 | 0 | PLY::DOM::SkipSpacesAndLineEnd(buffer); |
244 | 0 | return true; |
245 | 0 | } |
246 | | |
247 | | // ------------------------------------------------------------------------------------------------ |
248 | 8 | PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector<char> &buffer) { |
249 | 8 | ai_assert(!buffer.empty()); |
250 | | |
251 | 8 | PLY::EElementSemantic eOut = PLY::EEST_INVALID; |
252 | 8 | if (PLY::DOM::TokenMatch(buffer, "vertex", 6)) { |
253 | 0 | eOut = PLY::EEST_Vertex; |
254 | 8 | } else if (PLY::DOM::TokenMatch(buffer, "face", 4)) { |
255 | 0 | eOut = PLY::EEST_Face; |
256 | 8 | } else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9)) { |
257 | 0 | eOut = PLY::EEST_TriStrip; |
258 | 0 | } |
259 | | #if 0 |
260 | | // TODO: maybe implement this? |
261 | | else if (PLY::DOM::TokenMatch(buffer,"range_grid",10)) |
262 | | { |
263 | | eOut = PLY::EEST_Face; |
264 | | } |
265 | | #endif |
266 | 8 | else if (PLY::DOM::TokenMatch(buffer, "edge", 4)) { |
267 | 0 | eOut = PLY::EEST_Edge; |
268 | 8 | } else if (PLY::DOM::TokenMatch(buffer, "material", 8)) { |
269 | 0 | eOut = PLY::EEST_Material; |
270 | 8 | } else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11)) { |
271 | 0 | eOut = PLY::EEST_TextureFile; |
272 | 0 | } |
273 | | |
274 | 8 | return eOut; |
275 | 8 | } |
276 | | |
277 | | // ------------------------------------------------------------------------------------------------ |
278 | 771 | bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLY::Element *pOut) { |
279 | 771 | ai_assert(nullptr != pOut); |
280 | | // Example format: "element vertex 8" |
281 | | |
282 | | // skip leading spaces |
283 | 771 | if (!PLY::DOM::SkipSpaces(buffer)) { |
284 | 326 | return false; |
285 | 326 | } |
286 | | |
287 | | // skip the "element" string at the beginning |
288 | 445 | if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7)) { |
289 | | // seems not to be a valid property entry |
290 | 437 | return false; |
291 | 437 | } |
292 | | // get next word |
293 | 8 | if (!PLY::DOM::SkipSpaces(buffer)) |
294 | 0 | return false; |
295 | | |
296 | | // parse the semantic of the element |
297 | 8 | pOut->eSemantic = PLY::Element::ParseSemantic(buffer); |
298 | 8 | if (PLY::EEST_INVALID == pOut->eSemantic) { |
299 | | // if the exact semantic can't be determined, just store |
300 | | // the original string identifier |
301 | 8 | pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); |
302 | 8 | auto pos = pOut->szName.find_last_of(' '); |
303 | 8 | if (pos != std::string::npos) { |
304 | 8 | pOut->szName.erase(pos, pOut->szName.size()); |
305 | 8 | } |
306 | 8 | } |
307 | | |
308 | 8 | if (!PLY::DOM::SkipSpaces(buffer)) |
309 | 0 | return false; |
310 | | |
311 | 8 | if (PLY::EEST_TextureFile == pOut->eSemantic) { |
312 | 0 | char *endPos = &buffer[0] + (strlen(&buffer[0]) - 1); |
313 | 0 | pOut->szName = std::string(&buffer[0], endPos); |
314 | | |
315 | | // go to the next line |
316 | 0 | PLY::DOM::SkipSpacesAndLineEnd(buffer); |
317 | |
|
318 | 0 | return true; |
319 | 0 | } |
320 | | |
321 | | // parse the number of occurrences of this element |
322 | 8 | const char *pCur = (char *)&buffer[0]; |
323 | 8 | pOut->NumOccur = strtoul10(pCur, &pCur); |
324 | | |
325 | | // go to the next line |
326 | 8 | PLY::DOM::SkipSpacesAndLineEnd(buffer); |
327 | | |
328 | | // now parse all properties of the element |
329 | 8 | while (true) { |
330 | 8 | streamBuffer.getNextLine(buffer); |
331 | 8 | pCur = (char *)&buffer[0]; |
332 | | |
333 | | // skip all comments and go to next line |
334 | 8 | if (PLY::DOM::SkipComments(buffer)) continue; |
335 | | |
336 | 8 | PLY::Property prop; |
337 | 8 | if (!PLY::Property::ParseProperty(buffer, &prop)) |
338 | 8 | break; |
339 | | |
340 | 0 | pOut->alProperties.push_back(prop); |
341 | 0 | } |
342 | | |
343 | 8 | return true; |
344 | 8 | } |
345 | | |
346 | 1.57k | bool PLY::DOM::SkipSpaces(std::vector<char> &buffer) { |
347 | 1.57k | const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; |
348 | 1.57k | const char *end = pCur + buffer.size(); |
349 | 1.57k | bool ret = false; |
350 | 1.57k | if (pCur) { |
351 | 1.57k | const char *szCur = pCur; |
352 | 1.57k | ret = Assimp::SkipSpaces(pCur, &pCur, end); |
353 | | |
354 | 1.57k | uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; |
355 | 1.57k | buffer.erase(buffer.begin(), buffer.begin() + iDiff); |
356 | 1.57k | return ret; |
357 | 1.57k | } |
358 | | |
359 | 0 | return ret; |
360 | 1.57k | } |
361 | | |
362 | 0 | bool PLY::DOM::SkipLine(std::vector<char> &buffer) { |
363 | 0 | const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; |
364 | 0 | const char *end = pCur + buffer.size(); |
365 | 0 | bool ret = false; |
366 | 0 | if (pCur) { |
367 | 0 | const char *szCur = pCur; |
368 | 0 | ret = Assimp::SkipLine(pCur, &pCur, end); |
369 | |
|
370 | 0 | uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; |
371 | 0 | buffer.erase(buffer.begin(), buffer.begin() + iDiff); |
372 | 0 | return ret; |
373 | 0 | } |
374 | | |
375 | 0 | return ret; |
376 | 0 | } |
377 | | |
378 | 2.15k | bool PLY::DOM::TokenMatch(std::vector<char> &buffer, const char *token, unsigned int len) { |
379 | 2.15k | const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; |
380 | 2.15k | bool ret = false; |
381 | 2.15k | if (pCur) { |
382 | 2.15k | const char *szCur = pCur; |
383 | 2.15k | ret = Assimp::TokenMatch(pCur, token, len); |
384 | | |
385 | 2.15k | uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; |
386 | 2.15k | buffer.erase(buffer.begin(), buffer.begin() + iDiff); |
387 | 2.15k | return ret; |
388 | 2.15k | } |
389 | | |
390 | 0 | return ret; |
391 | 2.15k | } |
392 | | |
393 | 8 | bool PLY::DOM::SkipSpacesAndLineEnd(std::vector<char> &buffer) { |
394 | 8 | const char *pCur = buffer.empty() ? nullptr : (char *)&buffer[0]; |
395 | 8 | const char *end = pCur + buffer.size(); |
396 | 8 | bool ret = false; |
397 | 8 | if (pCur) { |
398 | 8 | const char *szCur = pCur; |
399 | 8 | ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur, end); |
400 | | |
401 | 8 | uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; |
402 | 8 | buffer.erase(buffer.begin(), buffer.begin() + iDiff); |
403 | 8 | return ret; |
404 | 8 | } |
405 | | |
406 | 0 | return ret; |
407 | 8 | } |
408 | | |
409 | 779 | bool PLY::DOM::SkipComments(std::vector<char> buffer) { |
410 | 779 | ai_assert(!buffer.empty()); |
411 | | |
412 | 779 | std::vector<char> nbuffer = std::move(buffer); |
413 | | // skip spaces |
414 | 779 | if (!SkipSpaces(nbuffer)) { |
415 | 326 | return false; |
416 | 326 | } |
417 | | |
418 | 453 | if (TokenMatch(nbuffer, "comment", 7)) { |
419 | 0 | if (!SkipSpaces(nbuffer)) |
420 | 0 | SkipLine(nbuffer); |
421 | |
|
422 | 0 | if (!TokenMatch(nbuffer, "TextureFile", 11)) { |
423 | 0 | SkipLine(nbuffer); |
424 | 0 | buffer = nbuffer; |
425 | 0 | return true; |
426 | 0 | } |
427 | | |
428 | 0 | return true; |
429 | 0 | } |
430 | | |
431 | 453 | return false; |
432 | 453 | } |
433 | | |
434 | | // ------------------------------------------------------------------------------------------------ |
435 | 2 | bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) { |
436 | 2 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin"); |
437 | | |
438 | 2 | std::unordered_set<std::string> definedAlElements; |
439 | | // parse all elements |
440 | 771 | while (!buffer.empty()) { |
441 | | // skip all comments |
442 | 771 | PLY::DOM::SkipComments(buffer); |
443 | | |
444 | 771 | PLY::Element out; |
445 | 771 | if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { |
446 | | // add the element to the list of elements |
447 | | |
448 | 8 | const auto propertyName = (out.szName.empty()) ? to_string(out.eSemantic) : out.szName; |
449 | 8 | auto alreadyDefined = definedAlElements.find(propertyName); |
450 | 8 | if (alreadyDefined != definedAlElements.end()) { |
451 | 0 | throw DeadlyImportError("Property '" + propertyName + "' in header already defined "); |
452 | 0 | } |
453 | 8 | definedAlElements.insert(propertyName); |
454 | 8 | alElements.push_back(out); |
455 | 763 | } else if (TokenMatch(buffer, "end_header", 10)) { |
456 | | // we have reached the end of the header |
457 | 0 | break; |
458 | 763 | } else { |
459 | | // ignore unknown header elements |
460 | 763 | if (!streamBuffer.getNextLine(buffer)) |
461 | 2 | return false; |
462 | 763 | } |
463 | 771 | } |
464 | | |
465 | 0 | if (!isBinary) // it would occur an error, if binary data start with values as space or line end. |
466 | 0 | SkipSpacesAndLineEnd(buffer); |
467 | |
|
468 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() succeeded"); |
469 | 0 | return true; |
470 | 2 | } |
471 | | |
472 | | // ------------------------------------------------------------------------------------------------ |
473 | 0 | bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter *loader) { |
474 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceLists() begin"); |
475 | 0 | alElementData.resize(alElements.size()); |
476 | |
|
477 | 0 | std::vector<PLY::Element>::const_iterator i = alElements.begin(); |
478 | 0 | std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin(); |
479 | | |
480 | | // parse all element instances |
481 | | // construct vertices and faces |
482 | 0 | for (; i != alElements.end(); ++i, ++a) { |
483 | 0 | if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) { |
484 | 0 | PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), nullptr, loader); |
485 | 0 | } else { |
486 | 0 | (*a).alInstances.resize((*i).NumOccur); |
487 | 0 | PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), nullptr); |
488 | 0 | } |
489 | 0 | } |
490 | |
|
491 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceLists() succeeded"); |
492 | 0 | return true; |
493 | 0 | } |
494 | | |
495 | | // ------------------------------------------------------------------------------------------------ |
496 | | bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
497 | | const char *&pCur, |
498 | | unsigned int &bufferSize, |
499 | | PLYImporter *loader, |
500 | 0 | bool p_bBE) { |
501 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() begin"); |
502 | 0 | alElementData.resize(alElements.size()); |
503 | |
|
504 | 0 | std::vector<PLY::Element>::const_iterator i = alElements.begin(); |
505 | 0 | std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin(); |
506 | | |
507 | | // parse all element instances |
508 | 0 | for (; i != alElements.end(); ++i, ++a) { |
509 | 0 | if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) { |
510 | 0 | PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), nullptr, loader, p_bBE); |
511 | 0 | } else { |
512 | 0 | (*a).alInstances.resize((*i).NumOccur); |
513 | 0 | PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), nullptr, p_bBE); |
514 | 0 | } |
515 | 0 | } |
516 | |
|
517 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); |
518 | 0 | return true; |
519 | 0 | } |
520 | | |
521 | | // ------------------------------------------------------------------------------------------------ |
522 | 1 | bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM *p_pcOut, PLYImporter *loader, bool p_bBE) { |
523 | 1 | ai_assert(nullptr != p_pcOut); |
524 | 1 | ai_assert(nullptr != loader); |
525 | | |
526 | 1 | std::vector<char> buffer; |
527 | 1 | streamBuffer.getNextLine(buffer); |
528 | | |
529 | 1 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() begin"); |
530 | | |
531 | 1 | if (!p_pcOut->ParseHeader(streamBuffer, buffer, true)) { |
532 | 1 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); |
533 | 1 | return false; |
534 | 1 | } |
535 | | |
536 | 0 | streamBuffer.getNextBlock(buffer); |
537 | |
|
538 | 0 | unsigned int bufferSize = static_cast<unsigned int>(buffer.size()); |
539 | 0 | const char *pCur = (char *)&buffer[0]; |
540 | 0 | if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) { |
541 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); |
542 | 0 | return false; |
543 | 0 | } |
544 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() succeeded"); |
545 | 0 | return true; |
546 | 0 | } |
547 | | |
548 | | // ------------------------------------------------------------------------------------------------ |
549 | 1 | bool PLY::DOM::ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM *p_pcOut, PLYImporter *loader) { |
550 | 1 | ai_assert(nullptr != p_pcOut); |
551 | 1 | ai_assert(nullptr != loader); |
552 | | |
553 | 1 | std::vector<char> buffer; |
554 | 1 | streamBuffer.getNextLine(buffer); |
555 | | |
556 | 1 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() begin"); |
557 | | |
558 | 1 | if (!p_pcOut->ParseHeader(streamBuffer, buffer, false)) { |
559 | 1 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); |
560 | 1 | return false; |
561 | 1 | } |
562 | | |
563 | | // get next line after header |
564 | 0 | streamBuffer.getNextLine(buffer); |
565 | 0 | if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader)) { |
566 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); |
567 | 0 | return false; |
568 | 0 | } |
569 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() succeeded"); |
570 | 0 | return true; |
571 | 0 | } |
572 | | |
573 | | // ------------------------------------------------------------------------------------------------ |
574 | | bool PLY::ElementInstanceList::ParseInstanceList( |
575 | | IOStreamBuffer<char> &streamBuffer, |
576 | | std::vector<char> &buffer, |
577 | | const PLY::Element *pcElement, |
578 | | PLY::ElementInstanceList *p_pcOut, |
579 | 0 | PLYImporter *loader) { |
580 | 0 | ai_assert(nullptr != pcElement); |
581 | | |
582 | | // parse all elements |
583 | 0 | if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) { |
584 | | // if the element has an unknown semantic we can skip all lines |
585 | | // However, there could be comments |
586 | 0 | for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { |
587 | 0 | PLY::DOM::SkipComments(buffer); |
588 | 0 | PLY::DOM::SkipLine(buffer); |
589 | 0 | streamBuffer.getNextLine(buffer); |
590 | 0 | } |
591 | 0 | } else { |
592 | 0 | const char *pCur = (const char *)&buffer[0]; |
593 | 0 | const char *end = pCur + buffer.size(); |
594 | | // be sure to have enough storage |
595 | 0 | for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { |
596 | 0 | if (p_pcOut) |
597 | 0 | PLY::ElementInstance::ParseInstance(pCur, end, pcElement, &p_pcOut->alInstances[i]); |
598 | 0 | else { |
599 | 0 | ElementInstance elt; |
600 | 0 | PLY::ElementInstance::ParseInstance(pCur, end, pcElement, &elt); |
601 | | |
602 | | // Create vertex or face |
603 | 0 | if (pcElement->eSemantic == EEST_Vertex) { |
604 | | // call loader instance from here |
605 | 0 | loader->LoadVertex(pcElement, &elt, i); |
606 | 0 | } else if (pcElement->eSemantic == EEST_Face) { |
607 | | // call loader instance from here |
608 | 0 | loader->LoadFace(pcElement, &elt, i); |
609 | 0 | } else if (pcElement->eSemantic == EEST_TriStrip) { |
610 | | // call loader instance from here |
611 | 0 | loader->LoadFace(pcElement, &elt, i); |
612 | 0 | } |
613 | 0 | } |
614 | |
|
615 | 0 | streamBuffer.getNextLine(buffer); |
616 | 0 | pCur = (buffer.empty()) ? nullptr : (const char *)&buffer[0]; |
617 | 0 | } |
618 | 0 | } |
619 | 0 | return true; |
620 | 0 | } |
621 | | |
622 | | // ------------------------------------------------------------------------------------------------ |
623 | | bool PLY::ElementInstanceList::ParseInstanceListBinary( |
624 | | IOStreamBuffer<char> &streamBuffer, |
625 | | std::vector<char> &buffer, |
626 | | const char *&pCur, |
627 | | unsigned int &bufferSize, |
628 | | const PLY::Element *pcElement, |
629 | | PLY::ElementInstanceList *p_pcOut, |
630 | | PLYImporter *loader, |
631 | 0 | bool p_bBE /* = false */) { |
632 | 0 | ai_assert(nullptr != pcElement); |
633 | | |
634 | | // we can add special handling code for unknown element semantics since |
635 | | // we can't skip it as a whole block (we don't know its exact size |
636 | | // due to the fact that lists could be contained in the property list |
637 | | // of the unknown element) |
638 | 0 | for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { |
639 | 0 | if (p_pcOut) |
640 | 0 | PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[i], p_bBE); |
641 | 0 | else { |
642 | 0 | ElementInstance elt; |
643 | 0 | PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE); |
644 | | |
645 | | // Create vertex or face |
646 | 0 | if (pcElement->eSemantic == EEST_Vertex) { |
647 | | // call loader instance from here |
648 | 0 | loader->LoadVertex(pcElement, &elt, i); |
649 | 0 | } else if (pcElement->eSemantic == EEST_Face) { |
650 | | // call loader instance from here |
651 | 0 | loader->LoadFace(pcElement, &elt, i); |
652 | 0 | } else if (pcElement->eSemantic == EEST_TriStrip) { |
653 | | // call loader instance from here |
654 | 0 | loader->LoadFace(pcElement, &elt, i); |
655 | 0 | } |
656 | 0 | } |
657 | 0 | } |
658 | 0 | return true; |
659 | 0 | } |
660 | | |
661 | | // ------------------------------------------------------------------------------------------------ |
662 | | bool PLY::ElementInstance::ParseInstance(const char *&pCur, const char *end, |
663 | | const PLY::Element *pcElement, |
664 | 0 | PLY::ElementInstance *p_pcOut) { |
665 | 0 | ai_assert(nullptr != pcElement); |
666 | 0 | ai_assert(nullptr != p_pcOut); |
667 | | |
668 | | // allocate enough storage |
669 | 0 | p_pcOut->alProperties.resize(pcElement->alProperties.size()); |
670 | |
|
671 | 0 | std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin(); |
672 | 0 | std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); |
673 | 0 | for (; i != p_pcOut->alProperties.end(); ++i, ++a) { |
674 | 0 | if (!(PLY::PropertyInstance::ParseInstance(pCur, end, &(*a), &(*i)))) { |
675 | 0 | ASSIMP_LOG_WARN("Unable to parse property instance. " |
676 | 0 | "Skipping this element instance"); |
677 | |
|
678 | 0 | PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); |
679 | 0 | (*i).avList.push_back(v); |
680 | 0 | } |
681 | 0 | } |
682 | 0 | return true; |
683 | 0 | } |
684 | | |
685 | | // ------------------------------------------------------------------------------------------------ |
686 | | bool PLY::ElementInstance::ParseInstanceBinary( |
687 | | IOStreamBuffer<char> &streamBuffer, |
688 | | std::vector<char> &buffer, |
689 | | const char *&pCur, |
690 | | unsigned int &bufferSize, |
691 | | const PLY::Element *pcElement, |
692 | | PLY::ElementInstance *p_pcOut, |
693 | 0 | bool p_bBE /* = false */) { |
694 | 0 | ai_assert(nullptr != pcElement); |
695 | 0 | ai_assert(nullptr != p_pcOut); |
696 | | |
697 | | // allocate enough storage |
698 | 0 | p_pcOut->alProperties.resize(pcElement->alProperties.size()); |
699 | |
|
700 | 0 | std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin(); |
701 | 0 | std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); |
702 | 0 | for (; i != p_pcOut->alProperties.end(); ++i, ++a) { |
703 | 0 | if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE))) { |
704 | 0 | ASSIMP_LOG_WARN("Unable to parse binary property instance. " |
705 | 0 | "Skipping this element instance"); |
706 | |
|
707 | 0 | (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); |
708 | 0 | } |
709 | 0 | } |
710 | 0 | return true; |
711 | 0 | } |
712 | | |
713 | | // ------------------------------------------------------------------------------------------------ |
714 | | bool PLY::PropertyInstance::ParseInstance(const char *&pCur, const char *end, const PLY::Property *prop, |
715 | 0 | PLY::PropertyInstance *p_pcOut) { |
716 | 0 | ai_assert(nullptr != prop); |
717 | 0 | ai_assert(nullptr != p_pcOut); |
718 | | |
719 | | // skip spaces at the beginning |
720 | 0 | if (!SkipSpaces(&pCur, end)) { |
721 | 0 | return false; |
722 | 0 | } |
723 | | |
724 | 0 | if (prop->bIsList) { |
725 | | // parse the number of elements in the list |
726 | 0 | PLY::PropertyInstance::ValueUnion v; |
727 | 0 | PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v); |
728 | | |
729 | | // convert to unsigned int |
730 | 0 | unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType); |
731 | | |
732 | | // parse all list elements |
733 | 0 | p_pcOut->avList.resize(iNum); |
734 | 0 | for (unsigned int i = 0; i < iNum; ++i) { |
735 | 0 | if (!SkipSpaces(&pCur, end)) |
736 | 0 | return false; |
737 | | |
738 | 0 | PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]); |
739 | 0 | } |
740 | 0 | } else { |
741 | | // parse the property |
742 | 0 | PLY::PropertyInstance::ValueUnion v; |
743 | |
|
744 | 0 | PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v); |
745 | 0 | p_pcOut->avList.push_back(v); |
746 | 0 | } |
747 | 0 | SkipSpacesAndLineEnd(&pCur, end); |
748 | 0 | return true; |
749 | 0 | } |
750 | | |
751 | | // ------------------------------------------------------------------------------------------------ |
752 | | bool PLY::PropertyInstance::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
753 | | const char *&pCur, |
754 | | unsigned int &bufferSize, |
755 | | const PLY::Property *prop, |
756 | | PLY::PropertyInstance *p_pcOut, |
757 | 0 | bool p_bBE) { |
758 | 0 | ai_assert(nullptr != prop); |
759 | 0 | ai_assert(nullptr != p_pcOut); |
760 | | |
761 | | // parse all elements |
762 | 0 | if (prop->bIsList) { |
763 | | // parse the number of elements in the list |
764 | 0 | PLY::PropertyInstance::ValueUnion v; |
765 | 0 | PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eFirstType, &v, p_bBE); |
766 | | |
767 | | // convert to unsigned int |
768 | 0 | unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType); |
769 | | |
770 | | // parse all list elements |
771 | 0 | p_pcOut->avList.resize(iNum); |
772 | 0 | for (unsigned int i = 0; i < iNum; ++i) { |
773 | 0 | PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE); |
774 | 0 | } |
775 | 0 | } else { |
776 | | // parse the property |
777 | 0 | PLY::PropertyInstance::ValueUnion v; |
778 | 0 | PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE); |
779 | 0 | p_pcOut->avList.push_back(v); |
780 | 0 | } |
781 | 0 | return true; |
782 | 0 | } |
783 | | |
784 | | // ------------------------------------------------------------------------------------------------ |
785 | 0 | PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType) { |
786 | 0 | PLY::PropertyInstance::ValueUnion out; |
787 | |
|
788 | 0 | switch (eType) { |
789 | 0 | case EDT_Float: |
790 | 0 | out.fFloat = 0.f; |
791 | 0 | return out; |
792 | | |
793 | 0 | case EDT_Double: |
794 | 0 | out.fDouble = 0.; |
795 | 0 | return out; |
796 | | |
797 | 0 | default:; |
798 | 0 | }; |
799 | 0 | out.iUInt = 0; |
800 | 0 | return out; |
801 | 0 | } |
802 | | |
803 | | // ------------------------------------------------------------------------------------------------ |
804 | | bool PLY::PropertyInstance::ParseValue(const char *&pCur, |
805 | | PLY::EDataType eType, |
806 | 0 | PLY::PropertyInstance::ValueUnion *out) { |
807 | 0 | ai_assert(nullptr != pCur); |
808 | 0 | ai_assert(nullptr != out); |
809 | | |
810 | | // calc element size |
811 | 0 | bool ret = true; |
812 | 0 | switch (eType) { |
813 | 0 | case EDT_UInt: |
814 | 0 | case EDT_UShort: |
815 | 0 | case EDT_UChar: |
816 | |
|
817 | 0 | out->iUInt = (uint32_t)strtoul10(pCur, &pCur); |
818 | 0 | break; |
819 | | |
820 | 0 | case EDT_Int: |
821 | 0 | case EDT_Short: |
822 | 0 | case EDT_Char: |
823 | |
|
824 | 0 | out->iInt = (int32_t)strtol10(pCur, &pCur); |
825 | 0 | break; |
826 | | |
827 | 0 | case EDT_Float: |
828 | | // technically this should cast to float, but people tend to use float descriptors for double data |
829 | | // this is the best way to not risk losing precision on import and it doesn't hurt to do this |
830 | 0 | ai_real f; |
831 | 0 | pCur = fast_atoreal_move(pCur, f); |
832 | 0 | out->fFloat = (ai_real)f; |
833 | 0 | break; |
834 | | |
835 | 0 | case EDT_Double: |
836 | 0 | double d; |
837 | 0 | pCur = fast_atoreal_move(pCur, d); |
838 | 0 | out->fDouble = (double)d; |
839 | 0 | break; |
840 | | |
841 | 0 | case EDT_INVALID: |
842 | 0 | default: |
843 | 0 | ret = false; |
844 | 0 | break; |
845 | 0 | } |
846 | | |
847 | 0 | return ret; |
848 | 0 | } |
849 | | |
850 | | // ------------------------------------------------------------------------------------------------ |
851 | | bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer, |
852 | | std::vector<char> &buffer, |
853 | | const char *&pCur, |
854 | | unsigned int &bufferSize, |
855 | | PLY::EDataType eType, |
856 | | PLY::PropertyInstance::ValueUnion *out, |
857 | 0 | bool p_bBE) { |
858 | 0 | ai_assert(nullptr != out); |
859 | | |
860 | | // calc element size |
861 | 0 | unsigned int lsize = 0; |
862 | 0 | switch (eType) { |
863 | 0 | case EDT_Char: |
864 | 0 | case EDT_UChar: |
865 | 0 | lsize = 1; |
866 | 0 | break; |
867 | | |
868 | 0 | case EDT_UShort: |
869 | 0 | case EDT_Short: |
870 | 0 | lsize = 2; |
871 | 0 | break; |
872 | | |
873 | 0 | case EDT_UInt: |
874 | 0 | case EDT_Int: |
875 | 0 | case EDT_Float: |
876 | 0 | lsize = 4; |
877 | 0 | break; |
878 | | |
879 | 0 | case EDT_Double: |
880 | 0 | lsize = 8; |
881 | 0 | break; |
882 | | |
883 | 0 | case EDT_INVALID: |
884 | 0 | default: |
885 | 0 | break; |
886 | 0 | } |
887 | | |
888 | | // read the next file block if needed |
889 | 0 | if (bufferSize < lsize) { |
890 | 0 | std::vector<char> nbuffer; |
891 | 0 | if (streamBuffer.getNextBlock(nbuffer)) { |
892 | | // concat buffer contents |
893 | 0 | buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end()); |
894 | 0 | buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); |
895 | 0 | nbuffer.clear(); |
896 | 0 | bufferSize = static_cast<unsigned int>(buffer.size()); |
897 | 0 | pCur = (char *)&buffer[0]; |
898 | 0 | } else { |
899 | 0 | throw DeadlyImportError("Invalid .ply file: File corrupted"); |
900 | 0 | } |
901 | 0 | } |
902 | | |
903 | 0 | bool ret = true; |
904 | 0 | switch (eType) { |
905 | 0 | case EDT_UInt: { |
906 | 0 | uint32_t t; |
907 | 0 | memcpy(&t, pCur, sizeof(uint32_t)); |
908 | 0 | pCur += sizeof(uint32_t); |
909 | | |
910 | | // Swap endianness |
911 | 0 | if (p_bBE) ByteSwap::Swap(&t); |
912 | 0 | out->iUInt = t; |
913 | 0 | break; |
914 | 0 | } |
915 | | |
916 | 0 | case EDT_UShort: { |
917 | 0 | uint16_t t; |
918 | 0 | memcpy(&t, pCur, sizeof(uint16_t)); |
919 | 0 | pCur += sizeof(uint16_t); |
920 | | |
921 | | // Swap endianness |
922 | 0 | if (p_bBE) ByteSwap::Swap(&t); |
923 | 0 | out->iUInt = t; |
924 | 0 | break; |
925 | 0 | } |
926 | | |
927 | 0 | case EDT_UChar: { |
928 | 0 | uint8_t t; |
929 | 0 | memcpy(&t, pCur, sizeof(uint8_t)); |
930 | 0 | pCur += sizeof(uint8_t); |
931 | 0 | out->iUInt = t; |
932 | 0 | break; |
933 | 0 | } |
934 | | |
935 | 0 | case EDT_Int: { |
936 | 0 | int32_t t; |
937 | 0 | memcpy(&t, pCur, sizeof(int32_t)); |
938 | 0 | pCur += sizeof(int32_t); |
939 | | |
940 | | // Swap endianness |
941 | 0 | if (p_bBE) ByteSwap::Swap(&t); |
942 | 0 | out->iInt = t; |
943 | 0 | break; |
944 | 0 | } |
945 | | |
946 | 0 | case EDT_Short: { |
947 | 0 | int16_t t; |
948 | 0 | memcpy(&t, pCur, sizeof(int16_t)); |
949 | 0 | pCur += sizeof(int16_t); |
950 | | |
951 | | // Swap endianness |
952 | 0 | if (p_bBE) ByteSwap::Swap(&t); |
953 | 0 | out->iInt = t; |
954 | 0 | break; |
955 | 0 | } |
956 | | |
957 | 0 | case EDT_Char: { |
958 | 0 | int8_t t; |
959 | 0 | memcpy(&t, pCur, sizeof(int8_t)); |
960 | 0 | pCur += sizeof(int8_t); |
961 | 0 | out->iInt = t; |
962 | 0 | break; |
963 | 0 | } |
964 | | |
965 | 0 | case EDT_Float: { |
966 | 0 | float t; |
967 | 0 | memcpy(&t, pCur, sizeof(float)); |
968 | 0 | pCur += sizeof(float); |
969 | | |
970 | | // Swap endianness |
971 | 0 | if (p_bBE) ByteSwap::Swap(&t); |
972 | 0 | out->fFloat = t; |
973 | 0 | break; |
974 | 0 | } |
975 | 0 | case EDT_Double: { |
976 | 0 | double t; |
977 | 0 | memcpy(&t, pCur, sizeof(double)); |
978 | 0 | pCur += sizeof(double); |
979 | | |
980 | | // Swap endianness |
981 | 0 | if (p_bBE) ByteSwap::Swap(&t); |
982 | 0 | out->fDouble = t; |
983 | 0 | break; |
984 | 0 | } |
985 | 0 | default: |
986 | 0 | ret = false; |
987 | 0 | } |
988 | | |
989 | 0 | bufferSize -= lsize; |
990 | |
|
991 | 0 | return ret; |
992 | 0 | } |
993 | | |
994 | | } // namespace Assimp |
995 | | |
996 | | #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER |