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