nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: nuclear@0: /** @file Defines the helper data structures for importing PLY files */ nuclear@0: #ifndef AI_PLYFILEHELPER_H_INC nuclear@0: #define AI_PLYFILEHELPER_H_INC nuclear@0: nuclear@0: nuclear@0: #include "ParsingUtils.h" nuclear@0: nuclear@0: nuclear@0: namespace Assimp nuclear@0: { nuclear@0: nuclear@0: // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ nuclear@0: // http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf nuclear@0: // http://www.okino.com/conv/exp_ply.htm nuclear@0: namespace PLY nuclear@0: { nuclear@0: nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /* nuclear@0: name type number of bytes nuclear@0: --------------------------------------- nuclear@0: char character 1 nuclear@0: uchar unsigned character 1 nuclear@0: short short integer 2 nuclear@0: ushort unsigned short integer 2 nuclear@0: int integer 4 nuclear@0: uint unsigned integer 4 nuclear@0: float single-precision float 4 nuclear@0: double double-precision float 8 nuclear@0: nuclear@0: int8 nuclear@0: int16 nuclear@0: uint8 ... forms are also used nuclear@0: */ nuclear@0: enum EDataType nuclear@0: { nuclear@0: EDT_Char = 0x0u, nuclear@0: EDT_UChar, nuclear@0: EDT_Short, nuclear@0: EDT_UShort, nuclear@0: EDT_Int, nuclear@0: EDT_UInt, nuclear@0: EDT_Float, nuclear@0: EDT_Double, nuclear@0: nuclear@0: // Marks invalid entries nuclear@0: EDT_INVALID nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Specifies semantics for PLY element properties nuclear@0: * nuclear@0: * Semantics define the usage of a property, e.g. x coordinate nuclear@0: */ nuclear@0: enum ESemantic nuclear@0: { nuclear@0: //! vertex position x coordinate nuclear@0: EST_XCoord = 0x0u, nuclear@0: //! vertex position x coordinate nuclear@0: EST_YCoord, nuclear@0: //! vertex position x coordinate nuclear@0: EST_ZCoord, nuclear@0: nuclear@0: //! vertex normal x coordinate nuclear@0: EST_XNormal, nuclear@0: //! vertex normal y coordinate nuclear@0: EST_YNormal, nuclear@0: //! vertex normal z coordinate nuclear@0: EST_ZNormal, nuclear@0: nuclear@0: //! u texture coordinate nuclear@0: EST_UTextureCoord, nuclear@0: //! v texture coordinate nuclear@0: EST_VTextureCoord, nuclear@0: nuclear@0: //! vertex colors, red channel nuclear@0: EST_Red, nuclear@0: //! vertex colors, green channel nuclear@0: EST_Green, nuclear@0: //! vertex colors, blue channel nuclear@0: EST_Blue, nuclear@0: //! vertex colors, alpha channel nuclear@0: EST_Alpha, nuclear@0: nuclear@0: //! vertex index list nuclear@0: EST_VertexIndex, nuclear@0: nuclear@0: //! texture index nuclear@0: EST_TextureIndex, nuclear@0: nuclear@0: //! texture coordinates (stored as element of a face) nuclear@0: EST_TextureCoordinates, nuclear@0: nuclear@0: //! material index nuclear@0: EST_MaterialIndex, nuclear@0: nuclear@0: //! ambient color, red channel nuclear@0: EST_AmbientRed, nuclear@0: //! ambient color, green channel nuclear@0: EST_AmbientGreen, nuclear@0: //! ambient color, blue channel nuclear@0: EST_AmbientBlue, nuclear@0: //! ambient color, alpha channel nuclear@0: EST_AmbientAlpha, nuclear@0: nuclear@0: //! diffuse color, red channel nuclear@0: EST_DiffuseRed, nuclear@0: //! diffuse color, green channel nuclear@0: EST_DiffuseGreen, nuclear@0: //! diffuse color, blue channel nuclear@0: EST_DiffuseBlue, nuclear@0: //! diffuse color, alpha channel nuclear@0: EST_DiffuseAlpha, nuclear@0: nuclear@0: //! specular color, red channel nuclear@0: EST_SpecularRed, nuclear@0: //! specular color, green channel nuclear@0: EST_SpecularGreen, nuclear@0: //! specular color, blue channel nuclear@0: EST_SpecularBlue, nuclear@0: //! specular color, alpha channel nuclear@0: EST_SpecularAlpha, nuclear@0: nuclear@0: //! specular power for phong shading nuclear@0: EST_PhongPower, nuclear@0: nuclear@0: //! opacity between 0 and 1 nuclear@0: EST_Opacity, nuclear@0: nuclear@0: //! Marks invalid entries nuclear@0: EST_INVALID nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Specifies semantics for PLY elements nuclear@0: * nuclear@0: * Semantics define the usage of an element, e.g. vertex or material nuclear@0: */ nuclear@0: enum EElementSemantic nuclear@0: { nuclear@0: //! The element is a vertex nuclear@0: EEST_Vertex = 0x0u, nuclear@0: nuclear@0: //! The element is a face description (index table) nuclear@0: EEST_Face, nuclear@0: nuclear@0: //! The element is a tristrip description (index table) nuclear@0: EEST_TriStrip, nuclear@0: nuclear@0: //! The element is an edge description (ignored) nuclear@0: EEST_Edge, nuclear@0: nuclear@0: //! The element is a material description nuclear@0: EEST_Material, nuclear@0: nuclear@0: //! Marks invalid entries nuclear@0: EEST_INVALID nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Helper class for a property in a PLY file. nuclear@0: * nuclear@0: * This can e.g. be a part of the vertex declaration nuclear@0: */ nuclear@0: class Property nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: //! Default constructor nuclear@0: Property() nuclear@0: : eType (EDT_Int), bIsList(false), eFirstType(EDT_UChar) nuclear@0: {} nuclear@0: nuclear@0: //! Data type of the property nuclear@0: EDataType eType; nuclear@0: nuclear@0: //! Semantical meaning of the property nuclear@0: ESemantic Semantic; nuclear@0: nuclear@0: //! Of the semantic of the property could not be parsed: nuclear@0: //! Contains the semantic specified in the file nuclear@0: std::string szName; nuclear@0: nuclear@0: //! Specifies whether the data type is a list where nuclear@0: //! the first element specifies the size of the list nuclear@0: bool bIsList; nuclear@0: EDataType eFirstType; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a property from a string. The end of the nuclear@0: //! string is either '\n', '\r' or '\0'. Return valie is false nuclear@0: //! if the input string is NOT a valid property (E.g. does nuclear@0: //! not start with the "property" keyword) nuclear@0: static bool ParseProperty (const char* pCur, const char** pCurOut, nuclear@0: Property* pOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a data type from a string nuclear@0: static EDataType ParseDataType(const char* pCur,const char** pCurOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a semantic from a string nuclear@0: static ESemantic ParseSemantic(const char* pCur,const char** pCurOut); nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Helper class for an element in a PLY file. nuclear@0: * nuclear@0: * This can e.g. be the vertex declaration. Elements contain a nuclear@0: * well-defined number of properties. nuclear@0: */ nuclear@0: class Element nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: //! Default constructor nuclear@0: Element() nuclear@0: : eSemantic (EEST_INVALID) nuclear@0: , NumOccur(0) nuclear@0: {} nuclear@0: nuclear@0: //! List of properties assigned to the element nuclear@0: //! std::vector to support operator[] nuclear@0: std::vector alProperties; nuclear@0: nuclear@0: //! Semantic of the element nuclear@0: EElementSemantic eSemantic; nuclear@0: nuclear@0: //! Of the semantic of the element could not be parsed: nuclear@0: //! Contains the semantic specified in the file nuclear@0: std::string szName; nuclear@0: nuclear@0: //! How many times will the element occur? nuclear@0: unsigned int NumOccur; nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse an element from a string. nuclear@0: //! The function will parse all properties contained in the nuclear@0: //! element, too. nuclear@0: static bool ParseElement (const char* pCur, const char** pCurOut, nuclear@0: Element* pOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a semantic from a string nuclear@0: static EElementSemantic ParseSemantic(const char* pCur, nuclear@0: const char** pCurOut); nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Instance of a property in a PLY file nuclear@0: */ nuclear@0: class PropertyInstance nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: //! Default constructor nuclear@0: PropertyInstance () nuclear@0: {} nuclear@0: nuclear@0: union ValueUnion nuclear@0: { nuclear@0: nuclear@0: //! uInt32 representation of the property. All nuclear@0: // uint types are automatically converted to uint32 nuclear@0: uint32_t iUInt; nuclear@0: nuclear@0: //! Int32 representation of the property. All nuclear@0: // int types are automatically converted to int32 nuclear@0: int32_t iInt; nuclear@0: nuclear@0: //! Float32 representation of the property nuclear@0: float fFloat; nuclear@0: nuclear@0: //! Float64 representation of the property nuclear@0: double fDouble; nuclear@0: nuclear@0: }; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! List of all values parsed. Contains only one value nuclear@0: // for non-list properties nuclear@0: std::vector avList; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a property instance nuclear@0: static bool ParseInstance (const char* pCur,const char** pCurOut, nuclear@0: const Property* prop, PropertyInstance* p_pcOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a property instance in binary format nuclear@0: static bool ParseInstanceBinary (const char* pCur,const char** pCurOut, nuclear@0: const Property* prop, PropertyInstance* p_pcOut,bool p_bBE); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Get the default value for a given data type nuclear@0: static ValueUnion DefaultValue(EDataType eType); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a value nuclear@0: static bool ParseValue(const char* pCur,const char** pCurOut, nuclear@0: EDataType eType,ValueUnion* out); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a binary value nuclear@0: static bool ParseValueBinary(const char* pCur,const char** pCurOut, nuclear@0: EDataType eType,ValueUnion* out,bool p_bBE); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Convert a property value to a given type TYPE nuclear@0: template nuclear@0: static TYPE ConvertTo(ValueUnion v, EDataType eType); nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Class for an element instance in a PLY file nuclear@0: */ nuclear@0: class ElementInstance nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: //! Default constructor nuclear@0: ElementInstance () nuclear@0: {} nuclear@0: nuclear@0: //! List of all parsed properties nuclear@0: std::vector< PropertyInstance > alProperties; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse an element instance nuclear@0: static bool ParseInstance (const char* pCur,const char** pCurOut, nuclear@0: const Element* pcElement, ElementInstance* p_pcOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a binary element instance nuclear@0: static bool ParseInstanceBinary (const char* pCur,const char** pCurOut, nuclear@0: const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE); nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Class for an element instance list in a PLY file nuclear@0: */ nuclear@0: class ElementInstanceList nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: //! Default constructor nuclear@0: ElementInstanceList () nuclear@0: {} nuclear@0: nuclear@0: //! List of all element instances nuclear@0: std::vector< ElementInstance > alInstances; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse an element instance list nuclear@0: static bool ParseInstanceList (const char* pCur,const char** pCurOut, nuclear@0: const Element* pcElement, ElementInstanceList* p_pcOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Parse a binary element instance list nuclear@0: static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut, nuclear@0: const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE); nuclear@0: }; nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Class to represent the document object model of an ASCII or binary nuclear@0: * (both little and big-endian) PLY file nuclear@0: */ nuclear@0: class DOM nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: //! Default constructor nuclear@0: DOM() nuclear@0: {} nuclear@0: nuclear@0: nuclear@0: //! Contains all elements of the file format nuclear@0: std::vector alElements; nuclear@0: //! Contains the real data of each element's instance list nuclear@0: std::vector alElementData; nuclear@0: nuclear@0: //! Parse the DOM for a PLY file. The input string is assumed nuclear@0: //! to be terminated with zero nuclear@0: static bool ParseInstance (const char* pCur,DOM* p_pcOut); nuclear@0: static bool ParseInstanceBinary (const char* pCur, nuclear@0: DOM* p_pcOut,bool p_bBE); nuclear@0: nuclear@0: //! Skip all comment lines after this nuclear@0: static bool SkipComments (const char* pCur,const char** pCurOut); nuclear@0: nuclear@0: private: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Handle the file header and read all element descriptions nuclear@0: bool ParseHeader (const char* pCur,const char** pCurOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Read in all element instance lists nuclear@0: bool ParseElementInstanceLists (const char* pCur,const char** pCurOut); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: //! Read in all element instance lists for a binary file format nuclear@0: bool ParseElementInstanceListsBinary (const char* pCur, nuclear@0: const char** pCurOut,bool p_bBE); nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: /** \brief Helper class to represent a loaded PLY face nuclear@0: */ nuclear@0: class Face nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: Face() nuclear@0: : iMaterialIndex(0xFFFFFFFF) nuclear@0: { nuclear@0: // set all indices to zero by default nuclear@0: mIndices.resize(3,0); nuclear@0: } nuclear@0: nuclear@0: public: nuclear@0: nuclear@0: //! List of vertex indices nuclear@0: std::vector mIndices; nuclear@0: nuclear@0: //! Material index nuclear@0: unsigned int iMaterialIndex; nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------------- nuclear@0: template nuclear@0: inline TYPE PLY::PropertyInstance::ConvertTo( nuclear@0: PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType) nuclear@0: { nuclear@0: switch (eType) nuclear@0: { nuclear@0: case EDT_Float: nuclear@0: return (TYPE)v.fFloat; nuclear@0: case EDT_Double: nuclear@0: return (TYPE)v.fDouble; nuclear@0: nuclear@0: case EDT_UInt: nuclear@0: case EDT_UShort: nuclear@0: case EDT_UChar: nuclear@0: return (TYPE)v.iUInt; nuclear@0: nuclear@0: case EDT_Int: nuclear@0: case EDT_Short: nuclear@0: case EDT_Char: nuclear@0: return (TYPE)v.iInt; nuclear@0: default: ; nuclear@0: }; nuclear@0: return (TYPE)0; nuclear@0: } nuclear@0: nuclear@0: } // Namespace PLY nuclear@0: } // Namespace AssImp nuclear@0: nuclear@0: #endif // !! include guard