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
Property()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
Element()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
PropertyInstance()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
ElementInstance()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
ElementInstanceList()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
DOM()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 SkipComments(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 ParseHeader(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>
ConvertTo(PLY::PropertyInstance::ValueUnion v,PLY::EDataType eType)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