1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | All rights reserved. |
7 | |
8 | Redistribution and use of this software in source and binary forms, |
9 | with or without modification, are permitted provided that the |
10 | following conditions are met: |
11 | |
12 | * Redistributions of source code must retain the above |
13 | copyright notice, this list of conditions and the |
14 | following disclaimer. |
15 | |
16 | * Redistributions in binary form must reproduce the above |
17 | copyright notice, this list of conditions and the |
18 | following disclaimer in the documentation and/or other |
19 | materials provided with the distribution. |
20 | |
21 | * Neither the name of the assimp team, nor the names of its |
22 | contributors may be used to endorse or promote products |
23 | derived from this software without specific prior |
24 | written permission of the assimp team. |
25 | |
26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
27 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
29 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
30 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
31 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
32 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
33 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
34 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
36 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | |
38 | ---------------------------------------------------------------------- |
39 | */ |
40 | |
41 | |
42 | /** @file Defines the helper data structures for importing PLY files */ |
43 | #ifndef AI_PLYFILEHELPER_H_INC |
44 | #define AI_PLYFILEHELPER_H_INC |
45 | |
46 | |
47 | #include "ParsingUtils.h" |
48 | #include "IOStreamBuffer.h" |
49 | #include <vector> |
50 | |
51 | namespace Assimp |
52 | { |
53 | |
54 | //pre-declaration |
55 | class PLYImporter; |
56 | |
57 | // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ |
58 | // http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf |
59 | // http://www.okino.com/conv/exp_ply.htm |
60 | namespace PLY |
61 | { |
62 | |
63 | // --------------------------------------------------------------------------------- |
64 | /* |
65 | name type number of bytes |
66 | --------------------------------------- |
67 | char character 1 |
68 | uchar unsigned character 1 |
69 | short short integer 2 |
70 | ushort unsigned short integer 2 |
71 | int integer 4 |
72 | uint unsigned integer 4 |
73 | float single-precision float 4 |
74 | double double-precision float 8 |
75 | |
76 | int8 |
77 | int16 |
78 | uint8 ... forms are also used |
79 | */ |
80 | enum EDataType |
81 | { |
82 | EDT_Char = 0x0u, |
83 | EDT_UChar, |
84 | EDT_Short, |
85 | EDT_UShort, |
86 | EDT_Int, |
87 | EDT_UInt, |
88 | EDT_Float, |
89 | EDT_Double, |
90 | |
91 | // Marks invalid entries |
92 | EDT_INVALID |
93 | }; |
94 | |
95 | // --------------------------------------------------------------------------------- |
96 | /** \brief Specifies semantics for PLY element properties |
97 | * |
98 | * Semantics define the usage of a property, e.g. x coordinate |
99 | */ |
100 | enum ESemantic |
101 | { |
102 | //! vertex position x coordinate |
103 | EST_XCoord = 0x0u, |
104 | //! vertex position x coordinate |
105 | EST_YCoord, |
106 | //! vertex position x coordinate |
107 | EST_ZCoord, |
108 | |
109 | //! vertex normal x coordinate |
110 | EST_XNormal, |
111 | //! vertex normal y coordinate |
112 | EST_YNormal, |
113 | //! vertex normal z coordinate |
114 | EST_ZNormal, |
115 | |
116 | //! u texture coordinate |
117 | EST_UTextureCoord, |
118 | //! v texture coordinate |
119 | EST_VTextureCoord, |
120 | |
121 | //! vertex colors, red channel |
122 | EST_Red, |
123 | //! vertex colors, green channel |
124 | EST_Green, |
125 | //! vertex colors, blue channel |
126 | EST_Blue, |
127 | //! vertex colors, alpha channel |
128 | EST_Alpha, |
129 | |
130 | //! vertex index list |
131 | EST_VertexIndex, |
132 | |
133 | //! texture index |
134 | EST_TextureIndex, |
135 | |
136 | //! texture coordinates (stored as element of a face) |
137 | EST_TextureCoordinates, |
138 | |
139 | //! material index |
140 | EST_MaterialIndex, |
141 | |
142 | //! ambient color, red channel |
143 | EST_AmbientRed, |
144 | //! ambient color, green channel |
145 | EST_AmbientGreen, |
146 | //! ambient color, blue channel |
147 | EST_AmbientBlue, |
148 | //! ambient color, alpha channel |
149 | EST_AmbientAlpha, |
150 | |
151 | //! diffuse color, red channel |
152 | EST_DiffuseRed, |
153 | //! diffuse color, green channel |
154 | EST_DiffuseGreen, |
155 | //! diffuse color, blue channel |
156 | EST_DiffuseBlue, |
157 | //! diffuse color, alpha channel |
158 | EST_DiffuseAlpha, |
159 | |
160 | //! specular color, red channel |
161 | EST_SpecularRed, |
162 | //! specular color, green channel |
163 | EST_SpecularGreen, |
164 | //! specular color, blue channel |
165 | EST_SpecularBlue, |
166 | //! specular color, alpha channel |
167 | EST_SpecularAlpha, |
168 | |
169 | //! specular power for phong shading |
170 | EST_PhongPower, |
171 | |
172 | //! opacity between 0 and 1 |
173 | EST_Opacity, |
174 | |
175 | //! Marks invalid entries |
176 | EST_INVALID |
177 | }; |
178 | |
179 | // --------------------------------------------------------------------------------- |
180 | /** \brief Specifies semantics for PLY elements |
181 | * |
182 | * Semantics define the usage of an element, e.g. vertex or material |
183 | */ |
184 | enum EElementSemantic |
185 | { |
186 | //! The element is a vertex |
187 | EEST_Vertex = 0x0u, |
188 | |
189 | //! The element is a face description (index table) |
190 | EEST_Face, |
191 | |
192 | //! The element is a tristrip description (index table) |
193 | EEST_TriStrip, |
194 | |
195 | //! The element is an edge description (ignored) |
196 | EEST_Edge, |
197 | |
198 | //! The element is a material description |
199 | EEST_Material, |
200 | |
201 | //! texture path |
202 | EEST_TextureFile, |
203 | |
204 | //! Marks invalid entries |
205 | EEST_INVALID |
206 | }; |
207 | |
208 | // --------------------------------------------------------------------------------- |
209 | /** \brief Helper class for a property in a PLY file. |
210 | * |
211 | * This can e.g. be a part of the vertex declaration |
212 | */ |
213 | class Property |
214 | { |
215 | public: |
216 | |
217 | //! Default constructor |
218 | Property() |
219 | : eType (EDT_Int), |
220 | Semantic(), |
221 | bIsList(false), |
222 | eFirstType(EDT_UChar) |
223 | {} |
224 | |
225 | //! Data type of the property |
226 | EDataType eType; |
227 | |
228 | //! Semantical meaning of the property |
229 | ESemantic Semantic; |
230 | |
231 | //! Of the semantic of the property could not be parsed: |
232 | //! Contains the semantic specified in the file |
233 | std::string szName; |
234 | |
235 | //! Specifies whether the data type is a list where |
236 | //! the first element specifies the size of the list |
237 | bool bIsList; |
238 | EDataType eFirstType; |
239 | |
240 | // ------------------------------------------------------------------- |
241 | //! Parse a property from a string. The end of the |
242 | //! string is either '\n', '\r' or '\0'. Return value is false |
243 | //! if the input string is NOT a valid property (E.g. does |
244 | //! not start with the "property" keyword) |
245 | static bool ParseProperty(std::vector<char> &buffer, Property* pOut); |
246 | |
247 | // ------------------------------------------------------------------- |
248 | //! Parse a data type from a string |
249 | static EDataType ParseDataType(std::vector<char> &buffer); |
250 | |
251 | // ------------------------------------------------------------------- |
252 | //! Parse a semantic from a string |
253 | static ESemantic ParseSemantic(std::vector<char> &buffer); |
254 | }; |
255 | |
256 | // --------------------------------------------------------------------------------- |
257 | /** \brief Helper class for an element in a PLY file. |
258 | * |
259 | * This can e.g. be the vertex declaration. Elements contain a |
260 | * well-defined number of properties. |
261 | */ |
262 | class Element |
263 | { |
264 | public: |
265 | |
266 | //! Default constructor |
267 | Element() |
268 | : eSemantic (EEST_INVALID) |
269 | , NumOccur(0) |
270 | {} |
271 | |
272 | //! List of properties assigned to the element |
273 | //! std::vector to support operator[] |
274 | std::vector<Property> alProperties; |
275 | |
276 | //! Semantic of the element |
277 | EElementSemantic eSemantic; |
278 | |
279 | //! Of the semantic of the element could not be parsed: |
280 | //! Contains the semantic specified in the file |
281 | std::string szName; |
282 | |
283 | //! How many times will the element occur? |
284 | unsigned int NumOccur; |
285 | |
286 | |
287 | // ------------------------------------------------------------------- |
288 | //! Parse an element from a string. |
289 | //! The function will parse all properties contained in the |
290 | //! element, too. |
291 | static bool ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, Element* pOut); |
292 | |
293 | // ------------------------------------------------------------------- |
294 | //! Parse a semantic from a string |
295 | static EElementSemantic ParseSemantic(std::vector<char> &buffer); |
296 | }; |
297 | |
298 | // --------------------------------------------------------------------------------- |
299 | /** \brief Instance of a property in a PLY file |
300 | */ |
301 | class PropertyInstance |
302 | { |
303 | public: |
304 | |
305 | //! Default constructor |
306 | PropertyInstance () |
307 | {} |
308 | |
309 | union ValueUnion |
310 | { |
311 | |
312 | //! uInt32 representation of the property. All |
313 | // uint types are automatically converted to uint32 |
314 | uint32_t iUInt; |
315 | |
316 | //! Int32 representation of the property. All |
317 | // int types are automatically converted to int32 |
318 | int32_t iInt; |
319 | |
320 | //! Float32 representation of the property |
321 | float fFloat; |
322 | |
323 | //! Float64 representation of the property |
324 | double fDouble; |
325 | |
326 | }; |
327 | |
328 | // ------------------------------------------------------------------- |
329 | //! List of all values parsed. Contains only one value |
330 | // for non-list properties |
331 | std::vector<ValueUnion> avList; |
332 | |
333 | // ------------------------------------------------------------------- |
334 | //! Parse a property instance |
335 | static bool ParseInstance(const char* &pCur, |
336 | const Property* prop, PropertyInstance* p_pcOut); |
337 | |
338 | // ------------------------------------------------------------------- |
339 | //! Parse a property instance in binary format |
340 | static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
341 | const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE); |
342 | |
343 | // ------------------------------------------------------------------- |
344 | //! Get the default value for a given data type |
345 | static ValueUnion DefaultValue(EDataType eType); |
346 | |
347 | // ------------------------------------------------------------------- |
348 | //! Parse a value |
349 | static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out); |
350 | |
351 | // ------------------------------------------------------------------- |
352 | //! Parse a binary value |
353 | static bool ParseValueBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
354 | const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE); |
355 | |
356 | // ------------------------------------------------------------------- |
357 | //! Convert a property value to a given type TYPE |
358 | template <typename TYPE> |
359 | static TYPE ConvertTo(ValueUnion v, EDataType eType); |
360 | }; |
361 | |
362 | // --------------------------------------------------------------------------------- |
363 | /** \brief Class for an element instance in a PLY file |
364 | */ |
365 | class ElementInstance |
366 | { |
367 | public: |
368 | |
369 | //! Default constructor |
370 | ElementInstance () |
371 | {} |
372 | |
373 | //! List of all parsed properties |
374 | std::vector< PropertyInstance > alProperties; |
375 | |
376 | // ------------------------------------------------------------------- |
377 | //! Parse an element instance |
378 | static bool ParseInstance(const char* &pCur, |
379 | const Element* pcElement, ElementInstance* p_pcOut); |
380 | |
381 | // ------------------------------------------------------------------- |
382 | //! Parse a binary element instance |
383 | static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
384 | const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE); |
385 | }; |
386 | |
387 | // --------------------------------------------------------------------------------- |
388 | /** \brief Class for an element instance list in a PLY file |
389 | */ |
390 | class ElementInstanceList |
391 | { |
392 | public: |
393 | |
394 | //! Default constructor |
395 | ElementInstanceList () |
396 | {} |
397 | |
398 | //! List of all element instances |
399 | std::vector< ElementInstance > alInstances; |
400 | |
401 | // ------------------------------------------------------------------- |
402 | //! Parse an element instance list |
403 | static bool ParseInstanceList(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
404 | const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader); |
405 | |
406 | // ------------------------------------------------------------------- |
407 | //! Parse a binary element instance list |
408 | static bool ParseInstanceListBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, |
409 | const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE); |
410 | }; |
411 | // --------------------------------------------------------------------------------- |
412 | /** \brief Class to represent the document object model of an ASCII or binary |
413 | * (both little and big-endian) PLY file |
414 | */ |
415 | class DOM |
416 | { |
417 | public: |
418 | |
419 | //! Default constructor |
420 | DOM() |
421 | {} |
422 | |
423 | |
424 | //! Contains all elements of the file format |
425 | std::vector<Element> alElements; |
426 | //! Contains the real data of each element's instance list |
427 | std::vector<ElementInstanceList> alElementData; |
428 | |
429 | //! Parse the DOM for a PLY file. The input string is assumed |
430 | //! to be terminated with zero |
431 | static bool ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader); |
432 | static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE); |
433 | |
434 | //! Skip all comment lines after this |
435 | static bool (std::vector<char> &buffer); |
436 | |
437 | static bool SkipSpaces(std::vector<char> &buffer); |
438 | |
439 | static bool SkipLine(std::vector<char> &buffer); |
440 | |
441 | static bool TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len); |
442 | |
443 | static bool SkipSpacesAndLineEnd(std::vector<char> &buffer); |
444 | |
445 | private: |
446 | |
447 | // ------------------------------------------------------------------- |
448 | //! Handle the file header and read all element descriptions |
449 | bool (IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool p_bBE); |
450 | |
451 | // ------------------------------------------------------------------- |
452 | //! Read in all element instance lists |
453 | bool ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader); |
454 | |
455 | // ------------------------------------------------------------------- |
456 | //! Read in all element instance lists for a binary file format |
457 | bool ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE); |
458 | }; |
459 | |
460 | // --------------------------------------------------------------------------------- |
461 | template <typename TYPE> |
462 | inline TYPE PLY::PropertyInstance::ConvertTo( |
463 | PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType) |
464 | { |
465 | switch (eType) |
466 | { |
467 | case EDT_Float: |
468 | return (TYPE)v.fFloat; |
469 | case EDT_Double: |
470 | return (TYPE)v.fDouble; |
471 | |
472 | case EDT_UInt: |
473 | case EDT_UShort: |
474 | case EDT_UChar: |
475 | return (TYPE)v.iUInt; |
476 | |
477 | case EDT_Int: |
478 | case EDT_Short: |
479 | case EDT_Char: |
480 | return (TYPE)v.iInt; |
481 | default: ; |
482 | }; |
483 | return (TYPE)0; |
484 | } |
485 | |
486 | } // Namespace PLY |
487 | } // Namespace AssImp |
488 | |
489 | #endif // !! include guard |
490 | |