diff --git a/README b/README index 23ae4ebb6..e69de29bb 100644 --- a/README +++ b/README @@ -1,5 +0,0 @@ - AssetImporter - --------------- -To use the asset importer lbrary just compile it with visual-c++ 8.0 (at this -moment no other build enviroments are supported). - \ No newline at end of file diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index fb4cdabb2..6ec6b5339 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the 3ds importer class */ #include "3DSLoader.h" #include "MaterialSystem.h" @@ -207,48 +248,67 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, } mat.AddProperty( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); + if (Dot3DS::Dot3DSFile::Wire == oldMat.mShading) + { + // set the wireframe flag + unsigned int iWire = 1; + mat.AddProperty( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); + } + // texture, if there is one if( oldMat.sTexDiffuse.mMapName.length() > 0) { aiString tex; tex.Set( oldMat.sTexDiffuse.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0)); - mat.AddProperty( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0)); + + if (is_not_qnan(oldMat.sTexDiffuse.mTextureBlend)) + mat.AddProperty( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0)); } if( oldMat.sTexSpecular.mMapName.length() > 0) { aiString tex; tex.Set( oldMat.sTexSpecular.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0)); - mat.AddProperty( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0)); + + if (is_not_qnan(oldMat.sTexSpecular.mTextureBlend)) + mat.AddProperty( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0)); } if( oldMat.sTexOpacity.mMapName.length() > 0) { aiString tex; tex.Set( oldMat.sTexOpacity.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0)); - mat.AddProperty( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0)); + + if (is_not_qnan(oldMat.sTexOpacity.mTextureBlend)) + mat.AddProperty( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0)); } if( oldMat.sTexEmissive.mMapName.length() > 0) { aiString tex; tex.Set( oldMat.sTexEmissive.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0)); - mat.AddProperty( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0)); + + if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend)) + mat.AddProperty( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0)); } if( oldMat.sTexBump.mMapName.length() > 0) { aiString tex; tex.Set( oldMat.sTexBump.mMapName); - mat.AddProperty( &tex, AI_MATKEY_TEXTURE_BUMP(0)); - mat.AddProperty( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_BUMP(0)); + mat.AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0)); + + if (is_not_qnan(oldMat.sTexBump.mTextureBlend)) + mat.AddProperty( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_HEIGHT(0)); } if( oldMat.sTexShininess.mMapName.length() > 0) { aiString tex; tex.Set( oldMat.sTexShininess.mMapName); mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0)); - mat.AddProperty( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0)); + + if (is_not_qnan(oldMat.sTexShininess.mTextureBlend)) + mat.AddProperty( &oldMat.sTexShininess.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0)); } // store the name of the material itself, too @@ -267,7 +327,7 @@ void SetupMatUVSrc (aiMaterial* pcMat, const Dot3DS::Material* pcMatIn) pcHelper->AddProperty(&pcMatIn->sTexDiffuse.iUVSrc,1,AI_MATKEY_UVWSRC_DIFFUSE(0)); pcHelper->AddProperty(&pcMatIn->sTexSpecular.iUVSrc,1,AI_MATKEY_UVWSRC_SPECULAR(0)); pcHelper->AddProperty(&pcMatIn->sTexEmissive.iUVSrc,1,AI_MATKEY_UVWSRC_EMISSIVE(0)); - pcHelper->AddProperty(&pcMatIn->sTexBump.iUVSrc,1,AI_MATKEY_UVWSRC_BUMP(0)); + pcHelper->AddProperty(&pcMatIn->sTexBump.iUVSrc,1,AI_MATKEY_UVWSRC_HEIGHT(0)); pcHelper->AddProperty(&pcMatIn->sTexShininess.iUVSrc,1,AI_MATKEY_UVWSRC_SHININESS(0)); pcHelper->AddProperty(&pcMatIn->sTexOpacity.iUVSrc,1,AI_MATKEY_UVWSRC_OPACITY(0)); } @@ -331,14 +391,16 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut) p_pcOut->mNumVertices = aiSplit[p].size()*3; p_pcOut->mNumFaces = aiSplit[p].size(); + // allocate enough storage for faces + p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; iFaceCnt += p_pcOut->mNumFaces; + if (p_pcOut->mNumVertices != 0) { p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices]; p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices]; unsigned int iBase = 0; - p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; for (unsigned int q = 0; q < aiSplit[p].size();++q) { unsigned int iIndex = aiSplit[p][q]; @@ -617,8 +679,8 @@ void Dot3DSImporter::BakeScaleNOffset( { for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) { - pcMesh->mTextureCoords[0][i].x *= pcSrc->pcSingleTexture->mScaleU; - pcMesh->mTextureCoords[0][i].y *= pcSrc->pcSingleTexture->mScaleV; + pcMesh->mTextureCoords[0][i].x /= pcSrc->pcSingleTexture->mScaleU; + pcMesh->mTextureCoords[0][i].y /= pcSrc->pcSingleTexture->mScaleV; pcMesh->mTextureCoords[0][i].x += pcSrc->pcSingleTexture->mOffsetU; pcMesh->mTextureCoords[0][i].y += pcSrc->pcSingleTexture->mOffsetV; @@ -630,8 +692,8 @@ void Dot3DSImporter::BakeScaleNOffset( const float fCos = cosf(pcSrc->pcSingleTexture->mRotation); for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) { - pcMesh->mTextureCoords[0][i].x *= pcSrc->pcSingleTexture->mScaleU; - pcMesh->mTextureCoords[0][i].y *= pcSrc->pcSingleTexture->mScaleV; + pcMesh->mTextureCoords[0][i].x /= pcSrc->pcSingleTexture->mScaleU; + pcMesh->mTextureCoords[0][i].y /= pcSrc->pcSingleTexture->mScaleV; pcMesh->mTextureCoords[0][i].x *= fCos; pcMesh->mTextureCoords[0][i].y *= fSin; @@ -694,8 +756,8 @@ void Dot3DSImporter::BakeScaleNOffset( { for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU; - pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV; + pcMesh->mTextureCoords[iCnt][n].x = pvBase->x / (*i).fScaleU; + pcMesh->mTextureCoords[iCnt][n].y = pvBase->y / (*i).fScaleV; pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU; pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV; @@ -709,8 +771,8 @@ void Dot3DSImporter::BakeScaleNOffset( const float fCos = cosf((*i).fRotation); for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU; - pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV; + pcMesh->mTextureCoords[iCnt][n].x = pvBase->x / (*i).fScaleU; + pcMesh->mTextureCoords[iCnt][n].y = pvBase->y / (*i).fScaleV; pcMesh->mTextureCoords[iCnt][n].x *= fCos; pcMesh->mTextureCoords[iCnt][n].y *= fSin; diff --git a/code/3DSGenNormals.cpp b/code/3DSGenNormals.cpp index 661bf711a..2e9356ecf 100644 --- a/code/3DSGenNormals.cpp +++ b/code/3DSGenNormals.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the 3ds importer class */ #include "3DSLoader.h" #include "MaterialSystem.h" @@ -14,7 +55,6 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh) { - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // First generate face normals sMesh->mNormals.resize(sMesh->mPositions.size(),aiVector3D()); for( unsigned int a = 0; a < sMesh->mFaces.size(); a++) @@ -29,17 +69,12 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh) aiVector3D pDelta1 = *pV2 - *pV1; aiVector3D pDelta2 = *pV3 - *pV1; aiVector3D vNor = pDelta1 ^ pDelta2; - - //float fLength = vNor.Length(); - //if (0.0f != fLength)vNor /= fLength; - sMesh->mNormals[face.i1] = vNor; sMesh->mNormals[face.i2] = vNor; sMesh->mNormals[face.i3] = vNor; } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // calculate the position bounds so we have a reliable epsilon to // check position differences against // @Schrompf: This is the 6th time this snippet is repeated! @@ -54,81 +89,48 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh) maxVec.z = std::max( maxVec.z, sMesh->mPositions[a].z); } const float posEpsilon = (maxVec - minVec).Length() * 1e-5f; - - std::vector avNormals; avNormals.resize(sMesh->mNormals.size()); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // now generate the spatial sort tree - D3DSSpatialSorter sSort(sMesh); + D3DSSpatialSorter sSort; + for( std::vector::iterator + i = sMesh->mFaces.begin(); + i != sMesh->mFaces.end();++i) + { + sSort.AddFace(&(*i),sMesh->mPositions); + } + sSort.Prepare(); for( std::vector::iterator i = sMesh->mFaces.begin(); i != sMesh->mFaces.end();++i) - { + { std::vector poResult; - // need to repeat the code for all three vertices of the triangle - // vertex 1 - sSort.FindPositions(sMesh->mPositions[(*i).i1],(*i).iSmoothGroup, - posEpsilon,poResult); + for (unsigned int c = 0; c < 3;++c) + { - aiVector3D vNormals; - float fDiv = 0.0f; - for (std::vector::const_iterator - a = poResult.begin(); - a != poResult.end();++a) + sSort.FindPositions(sMesh->mPositions[(*i).mIndices[c]],(*i).iSmoothGroup, + posEpsilon,poResult); + + aiVector3D vNormals; + float fDiv = 0.0f; + for (std::vector::const_iterator + a = poResult.begin(); + a != poResult.end();++a) { - vNormals += sMesh->mNormals[(*a)]; - fDiv += 1.0f; + vNormals += sMesh->mNormals[(*a)]; + fDiv += 1.0f; } - vNormals.x /= fDiv; - vNormals.y /= fDiv; - vNormals.z /= fDiv; - vNormals.Normalize(); - avNormals[(*i).i1] = vNormals; - poResult.clear(); - - // vertex 2 - sSort.FindPositions(sMesh->mPositions[(*i).i2],(*i).iSmoothGroup, - posEpsilon,poResult); - - vNormals = aiVector3D(); - fDiv = 0.0f; - for (std::vector::const_iterator - a = poResult.begin(); - a != poResult.end();++a) - { - vNormals += sMesh->mNormals[(*a)]; - fDiv += 1.0f; - } - vNormals.x /= fDiv; - vNormals.y /= fDiv; - vNormals.z /= fDiv; - vNormals.Normalize(); - avNormals[(*i).i2] = vNormals; - poResult.clear(); - - // vertex 3 - sSort.FindPositions(sMesh->mPositions[(*i).i3],(*i).iSmoothGroup, - posEpsilon ,poResult); - - vNormals = aiVector3D(); - fDiv = 0.0f; - for (std::vector::const_iterator - a = poResult.begin(); - a != poResult.end();++a) - { - vNormals += sMesh->mNormals[(*a)]; - fDiv += 1.0f; - } - vNormals.x /= fDiv; - vNormals.y /= fDiv; - vNormals.z /= fDiv; - vNormals.Normalize(); - avNormals[(*i).i3] = vNormals; + vNormals.x /= fDiv; + vNormals.y /= fDiv; + vNormals.z /= fDiv; + vNormals.Normalize(); + avNormals[(*i).mIndices[c]] = vNormals; + poResult.clear(); } + } sMesh->mNormals = avNormals; return; } \ No newline at end of file diff --git a/code/3DSHelper.h b/code/3DSHelper.h index e450a21fe..43989639e 100644 --- a/code/3DSHelper.h +++ b/code/3DSHelper.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines the helper data structures for importing XFiles */ #ifndef AI_3DSFILEHELPER_H_INC #define AI_3DSFILEHELPER_H_INC @@ -35,27 +75,30 @@ class Dot3DSFile public: inline Dot3DSFile() {} - // data structure for a single chunk in a .3ds file + //! data structure for a single chunk in a .3ds file struct Chunk { unsigned short Flag; long Size; } PACK_STRUCT; - // source for this used own structures, - // replaced it with out standard math helpers + //! source for this used own structures, + //! replaced it with out standard math helpers typedef aiMatrix3x3 MatTransform; typedef aiVector3D MatTranslate; - // Used for shading field in material3ds structure - // From AutoDesk 3ds SDK + //! Used for shading field in material3ds structure + //! From AutoDesk 3ds SDK typedef enum { Wire = 0, Flat = 1, Gouraud = 2, Phong = 3, - Metal = 4 + Metal = 4, + + // required by the ASE loader + Blinn = 5 } shadetype3ds; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -261,30 +304,38 @@ public: /** Helper structure representing a 3ds mesh face */ struct Face { - Face() : iSmoothGroup(0), bDirection(true) + Face() : iSmoothGroup(0), bDirection(true), i1(0), i2(0), i3(0) { // let the rest uninitialized for performance } - // Indices. .3ds is using uint16. However, after - // an unique vrtex set has been geneerated it might - // be an index becomes > 2^16 - uint32_t i1; - uint32_t i2; - uint32_t i3; + //! Indices. .3ds is using uint16. However, after + //! an unique vrtex set has been geneerated it might + //! be an index becomes > 2^16 + union + { + struct + { + uint32_t i1; + uint32_t i2; + uint32_t i3; + }; + uint32_t mIndices[3]; + }; - // specifies to which smoothing group the face belongs to + //! specifies to which smoothing group the face belongs to uint32_t iSmoothGroup; - // Direction the normal vector of the face - // will be pointing to + //! Direction the normal vector of the face + //! will be pointing to bool bDirection; }; // --------------------------------------------------------------------------- /** Helper structure representing a texture */ struct Texture { + //! Default constructor Texture() : mScaleU(1.0f), @@ -296,20 +347,20 @@ struct Texture { mTextureBlend = std::numeric_limits::quiet_NaN(); } - // Specifies the blending factor for the texture + //! Specifies the blending factor for the texture float mTextureBlend; - // Specifies the filename of the texture + //! Specifies the filename of the texture std::string mMapName; - // Specifies texture coordinate offsets/scaling/rotations + //! Specifies texture coordinate offsets/scaling/rotations float mScaleU; float mScaleV; float mOffsetU; float mOffsetV; float mRotation; - // Used internally + //! Used internally bool bPrivate; int iUVSrc; }; @@ -317,6 +368,7 @@ struct Texture /** Helper structure representing a 3ds material */ struct Material { + //! Default constructor. Builds a default name for the material Material() : mSpecularExponent (0.0f), @@ -331,27 +383,32 @@ struct Material ss << "%%_UNNAMED_" << iCnt++ << "_%%"; } - // Name of the material + //! Name of the material std::string mName; - // Diffuse color of the material + //! Diffuse color of the material aiColor3D mDiffuse; - // Specular exponent + //! Specular exponent float mSpecularExponent; - // Specular color of the material + //! Specular color of the material aiColor3D mSpecular; - // Ambient color of the material + //! Ambient color of the material aiColor3D mAmbient; - // Shading type to be used + //! Shading type to be used Dot3DSFile::shadetype3ds mShading; - // Opacity of the material + //! Opacity of the material float mTransparency; - // Different texture channels + //! Diffuse texture channel Texture sTexDiffuse; + //! Opacity texture channel Texture sTexOpacity; + //! Specular texture channel Texture sTexSpecular; + //! Bump texture channel Texture sTexBump; + //! Emissive texture channel Texture sTexEmissive; + //! Shininess texture channel Texture sTexShininess; /* @@ -360,10 +417,10 @@ struct Material */ float mBumpHeight; - // Emissive color + //! Emissive color aiColor3D mEmissive; - // Used internally + //! Used internally unsigned int iBakeUVTransform; Texture* pcSingleTexture; }; @@ -371,28 +428,33 @@ struct Material /** Helper structure to represent a 3ds file mesh */ struct Mesh { + //! Default constructor Mesh() { static int iCnt = 0; std::stringstream ss(mName); ss << "%%_UNNAMED_" << iCnt++ << "_%%"; -#if 0 - for (unsigned int i = 0; i < 32;++i) - bSmoothGroupRequired[i] = false; -#endif } + + //! Name of the mesh std::string mName; + //! Vertex positions std::vector mPositions; + + //! Face lists std::vector mFaces; + + //! Texture coordinates std::vector mTexCoords; + + //! Face materials std::vector mFaceMaterials; + + //! Normal vectors std::vector mNormals; -#if 0 - bool bSmoothGroupRequired[32]; -#endif - + //! Local transformation matrix aiMatrix4x4 mMat; }; // --------------------------------------------------------------------------- @@ -412,10 +474,19 @@ struct Node mHierarchyIndex = 0; } + //! Pointer to the parent node Node* mParent; + + //! Holds all child nodes std::vector mChildren; + + //! Name of the node std::string mName; + + //! Position of the node in the hierarchy (tree depth) int16_t mHierarchyPos; + + //! Index of the node int16_t mHierarchyIndex; #if 0 @@ -425,6 +496,8 @@ struct Node aiVector3D vPosition; #endif + //! Add a child node, setup the right parent node for it + //! \param pc Node to be 'adopted' inline Node& push_back(Node* pc) { mChildren.push_back(pc); @@ -438,10 +511,14 @@ struct Node struct Scene { - // NOTE: 3ds references materials globally + //! List of all materials loaded + //! NOTE: 3ds references materials globally std::vector mMaterials; + + //! List of all meshes loaded std::vector mMeshes; + //! Pointer to the root node of the scene Node* pcRootNode; }; diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 85bb42092..e2c5eef40 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the 3ds importer class */ #include "3DSLoader.h" #include "MaterialSystem.h" diff --git a/code/3DSLoader.h b/code/3DSLoader.h index 7c0ff6c4a..517cb25b7 100644 --- a/code/3DSLoader.h +++ b/code/3DSLoader.h @@ -1,3 +1,44 @@ + +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definition of the .3ds importer class. */ #ifndef AI_3DSIMPORTER_H_INC #define AI_3DSIMPORTER_H_INC @@ -5,230 +46,238 @@ #include #include "BaseImporter.h" - #include "../include/aiTypes.h" struct aiNode; - #include "3DSHelper.h" + namespace Assimp { - class MaterialHelper; +class MaterialHelper; - using namespace Dot3DS; +using namespace Dot3DS; - // --------------------------------------------------------------------------- - /** The Dot3DSImporter is a worker class capable of importing a scene from a - * 3ds Max 4/5 File (.3ds) - */ - class Dot3DSImporter : public BaseImporter +// --------------------------------------------------------------------------- +/** The Dot3DSImporter is a worker class capable of importing a scene from a +* 3ds Max 4/5 Files (.3ds) +*/ +class Dot3DSImporter : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + Dot3DSImporter(); + + /** Destructor, private as well */ + ~Dot3DSImporter(); + +public: + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) { - friend class Importer; + append.append("*.3ds"); + } - protected: - /** Constructor to be privately used by Importer */ - Dot3DSImporter(); + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); - /** Destructor, private as well */ - ~Dot3DSImporter(); + // ------------------------------------------------------------------- + /** Converts a temporary material to the outer representation + */ + void ConvertMaterial(Dot3DS::Material& p_cMat, + MaterialHelper& p_pcOut); - public: - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + // ------------------------------------------------------------------- + /** Read a chunk, get a pointer to it + * The mCurrent pointer will be increased by sizeof(Dot3DSFile::Chunk), + * thus pointing directly to the data of the chunk + */ + void ReadChunk(const Dot3DSFile::Chunk** p_ppcOut); - protected: - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + // ------------------------------------------------------------------- + /** Parse a percentage chunk. mCurrent will point to the next + * chunk behind afterwards. If no percentage chunk is found + * QNAN is returned. + */ + float ParsePercentageChunk(); + + // ------------------------------------------------------------------- + /** Parse a color chunk. mCurrent will point to the next + * chunk behind afterwards. If no color chunk is found + * QNAN is returned in all members. + */ + void ParseColorChunk(aiColor3D* p_pcOut, + bool p_bAcceptPercent = true); - // ------------------------------------------------------------------- - /** Converts a temporary material to the outer representation - */ - void ConvertMaterial(Dot3DS::Material& p_cMat, - MaterialHelper& p_pcOut); + // ------------------------------------------------------------------- + /** Skip a chunk in the file + */ + void SkipChunk(); + + // ------------------------------------------------------------------- + /** Generate the nodegraph + */ + void GenerateNodeGraph(aiScene* pcOut); + + // ------------------------------------------------------------------- + /** Parse a main top-level chunk in the file + */ + void ParseMainChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a top-level chunk in the file + */ + void ParseChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a top-level editor chunk in the file + */ + void ParseEditorChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a top-level object chunk in the file + */ + void ParseObjectChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a material chunk in the file + */ + void ParseMaterialChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Apply texture coordinate offsets + */ + void ApplyScaleNOffset(); + void BakeScaleNOffset(aiMesh* pcMesh, Dot3DS::Material* pcSrc); + + // ------------------------------------------------------------------- + /** Parse a mesh chunk in the file + */ + void ParseMeshChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a face list chunk in the file + */ + void ParseFaceChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a keyframe chunk in the file + */ + void ParseKeyframeChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a hierarchy chunk in the file + */ + void ParseHierarchyChunk(int* piRemaining); + + // ------------------------------------------------------------------- + /** Parse a texture chunk in the file + */ + void ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut); + + // ------------------------------------------------------------------- + /** Convert the meshes in the file + */ + void ConvertMeshes(aiScene* pcOut); + + // ------------------------------------------------------------------- + /** Replace the default material in the scene + */ + void ReplaceDefaultMaterial(); + + // ------------------------------------------------------------------- + /** Convert the whole scene + */ + void ConvertScene(aiScene* pcOut); + + // ------------------------------------------------------------------- + /** U/V Scaling/Offset handling + */ + void GenTexCoord (Dot3DS::Texture* pcTexture, + const std::vector& p_vIn, + std::vector& p_vOut); + + // ------------------------------------------------------------------- + /** generate normal vectors for a given mesh + */ + void GenNormals(Dot3DS::Mesh* sMesh); - // ------------------------------------------------------------------- - /** Read a chunk, get a pointer to it - * The mCurrent pointer will be increased by sizeof(Dot3DSFile::Chunk), - * thus pointing directly to the data of the chunk - */ - void ReadChunk(const Dot3DSFile::Chunk** p_ppcOut); - - // ------------------------------------------------------------------- - /** Parse a percentage chunk. mCurrent will point to the next - * chunk behind afterwards. If no percentage chunk is found - * QNAN is returned. - */ - float ParsePercentageChunk(); - - // ------------------------------------------------------------------- - /** Parse a color chunk. mCurrent will point to the next - * chunk behind afterwards. If no color chunk is found - * QNAN is returned in all members. - */ - void ParseColorChunk(aiColor3D* p_pcOut, - bool p_bAcceptPercent = true); + // ------------------------------------------------------------------- + /** generate unique vertices for a mesh + */ + void MakeUnique(Dot3DS::Mesh* sMesh); - // ------------------------------------------------------------------- - /** Skip a chunk in the file - */ - void SkipChunk(); + // ------------------------------------------------------------------- + /** Add a node to the node graph + */ + void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* pcIn); - // ------------------------------------------------------------------- - /** Generate the nodegraph - */ - void GenerateNodeGraph(aiScene* pcOut); - - // ------------------------------------------------------------------- - /** Parse a main top-level chunk in the file - */ - void ParseMainChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a top-level chunk in the file - */ - void ParseChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a top-level editor chunk in the file - */ - void ParseEditorChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a top-level object chunk in the file - */ - void ParseObjectChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a material chunk in the file - */ - void ParseMaterialChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Apply texture coordinate offsets - */ - void ApplyScaleNOffset(); - void BakeScaleNOffset(aiMesh* pcMesh, Dot3DS::Material* pcSrc); - - // ------------------------------------------------------------------- - /** Parse a mesh chunk in the file - */ - void ParseMeshChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a face list chunk in the file - */ - void ParseFaceChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a keyframe chunk in the file - */ - void ParseKeyframeChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a hierarchy chunk in the file - */ - void ParseHierarchyChunk(int* piRemaining); - - // ------------------------------------------------------------------- - /** Parse a texture chunk in the file - */ - void ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut); - - // ------------------------------------------------------------------- - /** Convert the meshes in the file - */ - void ConvertMeshes(aiScene* pcOut); - - // ------------------------------------------------------------------- - /** Replace the default material in the scene - */ - void ReplaceDefaultMaterial(); - - // ------------------------------------------------------------------- - /** Convert the whole scene - */ - void ConvertScene(aiScene* pcOut); - - // ------------------------------------------------------------------- - /** U/V Scaling/Offset handling - */ - void GenTexCoord (Dot3DS::Texture* pcTexture, - const std::vector& p_vIn, - std::vector& p_vOut); - - // ------------------------------------------------------------------- - /** generate normal vectors for a given mesh - */ - void GenNormals(Dot3DS::Mesh* sMesh); + // ------------------------------------------------------------------- + /** Search for a node in the graph. + * Called recursively + */ + void InverseNodeSearch(Dot3DS::Node* pcNode,Dot3DS::Node* pcCurrent); - // ------------------------------------------------------------------- - /** generate unique vertices for a mesh - */ - void MakeUnique(Dot3DS::Mesh* sMesh); + // ------------------------------------------------------------------- + /** Apply the master scaling factor to the mesh + */ + void ApplyMasterScale(aiScene* pScene); - // ------------------------------------------------------------------- - /** Add a node to the node graph - */ - void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* pcIn); - - // ------------------------------------------------------------------- - /** Search for a node in the graph. - * Called recursively - */ - void InverseNodeSearch(Dot3DS::Node* pcNode,Dot3DS::Node* pcCurrent); + // ------------------------------------------------------------------- + /** Clamp all indices in the file to a valid range + */ + void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh); - // ------------------------------------------------------------------- - /** Apply the master scaling factor to the mesh - */ - void ApplyMasterScale(aiScene* pScene); +protected: + /** Buffer to hold the loaded file */ + unsigned char* mBuffer; + /** Pointer to the current read position */ + const unsigned char* mCurrent; - // ------------------------------------------------------------------- - /** Clamp all indices in the file to a valid range - */ - void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh); + /** Used to store old chunk addresses to jump back in the file*/ + const unsigned char* mLast; + /** Last touched node index */ + short mLastNodeIndex; - protected: - /** Buffer to hold the loaded file */ - unsigned char* mBuffer; + /** Current node, root node */ + Dot3DS::Node* mCurrentNode, *mRootNode; - /** Pointer to the current read position */ - const unsigned char* mCurrent; + /** Scene under construction */ + Dot3DS::Scene* mScene; - /** Used to store old chunk addresses to jump back in the file*/ - const unsigned char* mLast; + /** Ambient base color of the scene */ + aiColor3D mClrAmbient; - /** Last touched node index */ - short mLastNodeIndex; + /** Master scaling factor of the scene */ + float mMasterScale; - /** Current node, root node */ - Dot3DS::Node* mCurrentNode, *mRootNode; - - /** Scene under construction */ - Dot3DS::Scene* mScene; - - /** Ambient base color of the scene */ - aiColor3D mClrAmbient; - - /** Master scaling factor of the scene */ - float mMasterScale; - - /** Path to the background image of the scene */ - std::string mBackgroundImage; - bool bHasBG; - }; + /** Path to the background image of the scene */ + std::string mBackgroundImage; + bool bHasBG; +}; } // end of namespace Assimp diff --git a/code/3DSSpatialSort.cpp b/code/3DSSpatialSort.cpp index 40962b74c..bf288d94d 100644 --- a/code/3DSSpatialSort.cpp +++ b/code/3DSSpatialSort.cpp @@ -1,67 +1,64 @@ -/** @file Implementation of the helper class to quickly find vertices close to a given position */ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the helper class to quickly find + vertices close to a given position. Special implementation for + the 3ds loader handling smooth groups correctly */ + #include #include "3DSSpatialSort.h" +#include "aiAssert.h" + using namespace Assimp; using namespace Assimp::Dot3DS; + // ------------------------------------------------------------------------------------------------ -// Constructs a spatially sorted representation from the given position array. -D3DSSpatialSorter::D3DSSpatialSorter( const aiVector3D* pPositions, - unsigned int pNumPositions, unsigned int pElementOffset) +D3DSSpatialSorter::D3DSSpatialSorter() { // define the reference plane. We choose some arbitrary vector away from all basic axises // in the hope that no model spreads all its vertices along this plane. mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f); mPlaneNormal.Normalize(); - - // store references to all given positions along with their distance to the reference plane - mPositions.reserve( pNumPositions); - for( unsigned int a = 0; a < pNumPositions; a++) - { - const char* tempPointer = reinterpret_cast (pPositions); - const aiVector3D* vec = reinterpret_cast (tempPointer + a * pElementOffset); - - // store position by index and distance - float distance = *vec * mPlaneNormal; - mPositions.push_back( Entry( a, *vec, distance,0)); - } - - // now sort the array ascending by distance. - std::sort( mPositions.begin(), mPositions.end()); - } -// ------------------------------------------------------------------------------------------------ -D3DSSpatialSorter::D3DSSpatialSorter( const Dot3DS::Mesh* p_pcMesh) - { - // define the reference plane. We choose some arbitrary vector away from all basic axises - // in the hope that no model spreads all its vertices along this plane. - mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f); - mPlaneNormal.Normalize(); - - // store references to all given positions along with their distance to the reference plane - mPositions.reserve( p_pcMesh->mPositions.size()); - for( std::vector::const_iterator - i = p_pcMesh->mFaces.begin(); - i != p_pcMesh->mFaces.end();++i) - { - // store position by index and distance - float distance = p_pcMesh->mPositions[(*i).i1] * mPlaneNormal; - mPositions.push_back( Entry( (*i).i1, p_pcMesh->mPositions[(*i).i1], - distance, (*i).iSmoothGroup)); - - // triangle vertex 2 - distance = p_pcMesh->mPositions[(*i).i2] * mPlaneNormal; - mPositions.push_back( Entry( (*i).i2, p_pcMesh->mPositions[(*i).i2], - distance, (*i).iSmoothGroup)); - - // triangle vertex 3 - distance = p_pcMesh->mPositions[(*i).i3] * mPlaneNormal; - mPositions.push_back( Entry( (*i).i3, p_pcMesh->mPositions[(*i).i3], - distance, (*i).iSmoothGroup)); - } - - // now sort the array ascending by distance. - std::sort( this->mPositions.begin(), this->mPositions.end()); } // ------------------------------------------------------------------------------------------------ // Destructor @@ -69,11 +66,39 @@ D3DSSpatialSorter::~D3DSSpatialSorter() { // nothing to do here, everything destructs automatically } +// ------------------------------------------------------------------------------------------------ +void D3DSSpatialSorter::AddFace(const Dot3DS::Face* pcFace, + const std::vector& vPositions) +{ + ai_assert(NULL != pcFace); + // store position by index and distance + float distance = vPositions[pcFace->i1] * mPlaneNormal; + mPositions.push_back( Entry( pcFace->i1, vPositions[pcFace->i1], + distance, pcFace->iSmoothGroup)); + + // triangle vertex 2 + distance = vPositions[pcFace->i2] * mPlaneNormal; + mPositions.push_back( Entry( pcFace->i2, vPositions[pcFace->i2], + distance, pcFace->iSmoothGroup)); + + // triangle vertex 3 + distance = vPositions[pcFace->i3] * mPlaneNormal; + mPositions.push_back( Entry( pcFace->i3, vPositions[pcFace->i3], + distance, pcFace->iSmoothGroup)); +} +// ------------------------------------------------------------------------------------------------ +void D3DSSpatialSorter::Prepare() +{ + // now sort the array ascending by distance. + std::sort( this->mPositions.begin(), this->mPositions.end()); +} // ------------------------------------------------------------------------------------------------ // Returns an iterator for all positions close to the given position. void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition, - uint32_t pSG,float pRadius, std::vector& poResults) const + uint32_t pSG, + float pRadius, + std::vector& poResults) const { float dist = pPosition * mPlaneNormal; float minDist = dist - pRadius, maxDist = dist + pRadius; @@ -113,10 +138,10 @@ void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition, // Mow start iterating from there until the first position lays outside of the distance range. // Add all positions inside the distance range within the given radius to the result aray + float squareEpsilon = pRadius * pRadius; + std::vector::const_iterator it = mPositions.begin() + index; if (0 == pSG) { - std::vector::const_iterator it = mPositions.begin() + index; - float squareEpsilon = pRadius * pRadius; while( it->mDistance < maxDist) { if((it->mPosition - pPosition).SquareLength() < squareEpsilon) @@ -130,8 +155,6 @@ void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition, } else { - std::vector::const_iterator it = mPositions.begin() + index; - float squareEpsilon = pRadius * pRadius; while( it->mDistance < maxDist) { if((it->mPosition - pPosition).SquareLength() < squareEpsilon && @@ -144,5 +167,6 @@ void D3DSSpatialSorter::FindPositions( const aiVector3D& pPosition, break; } } + return; } diff --git a/code/3DSSpatialSort.h b/code/3DSSpatialSort.h index e3590754d..8078ccf81 100644 --- a/code/3DSSpatialSort.h +++ b/code/3DSSpatialSort.h @@ -1,10 +1,55 @@ -/** Small helper classes to optimise finding vertizes close to a given location */ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** Small helper classes to optimise finding vertizes close to a given location + */ #ifndef AI_D3DSSPATIALSORT_H_INC #define AI_D3DSSPATIALSORT_H_INC #include #include "../include/aiVector3D.h" -#include "3DSHelper.h" + + +#if (!defined AI_BUILD_NO_ASE_IMPORTER) +# include "3DSHelper.h" +#endif namespace Assimp { @@ -19,28 +64,30 @@ class D3DSSpatialSorter { public: - D3DSSpatialSorter() {/* This is unintialized. This is evil. This is OK. */} - - /** Constructs a spatially sorted representation from the given position array. - * Supply the positions in its layout in memory, the class will only refer to them - * by index. - * @param pPositions Pointer to the first position vector of the array. - * @param pNumPositions Number of vectors to expect in that array. - * @param pElementOffset Offset in bytes from the beginning of one vector in memory to the beginning of the next vector. - * @note Smoothing groups are ignored - */ - D3DSSpatialSorter( const aiVector3D* pPositions, - unsigned int pNumPositions, unsigned int pElementOffset); + D3DSSpatialSorter(); + // ------------------------------------------------------------------- /** Construction from a given face array, handling smoothing groups properly - * @param p_pcMesh Input mesh. */ - D3DSSpatialSorter( const Dot3DS::Mesh* p_pcMesh); + D3DSSpatialSorter(const std::vector& vPositions); + // ------------------------------------------------------------------- + /** Add a face to the spatial sorter + * @param pcFace Face to be added + * @param vPositions Input position list + */ + void AddFace(const Dot3DS::Face* pcFace, + const std::vector& vPositions); + + // ------------------------------------------------------------------- + /** Prepare the spatial sorter for use + */ + void Prepare(); /** Destructor */ ~D3DSSpatialSorter(); + // ------------------------------------------------------------------- /** Returns an iterator for all positions close to the given position. * @param pPosition The position to look for vertices. * @param pSG Only included vertices with at least one shared smooth group @@ -56,6 +103,7 @@ protected: /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */ aiVector3D mPlaneNormal; + // ------------------------------------------------------------------- /** An entry in a spatially sorted position array. Consists of a vertex index, * its position and its precalculated distance from the reference plane */ struct Entry diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp new file mode 100644 index 000000000..042ba367d --- /dev/null +++ b/code/ASELoader.cpp @@ -0,0 +1,720 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the ASE importer class */ +#include "ASELoader.h" +#include "3DSSpatialSort.h" +#include "MaterialSystem.h" + +#include "../include/IOStream.h" +#include "../include/IOSystem.h" +#include "../include/aiMesh.h" +#include "../include/aiScene.h" +#include "../include/aiAssert.h" + +#include + +using namespace Assimp; +using namespace Assimp::ASE; + +#define LOGOUT_WARN(x) + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +ASEImporter::ASEImporter() +{ +} +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +ASEImporter::~ASEImporter() +{ +} +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const +{ + // simple check of file extension is enough for the moment + std::string::size_type pos = pFile.find_last_of('.'); + // no file extension - can't read + if( pos == std::string::npos) + return false; + std::string extension = pFile.substr( pos); + + if (extension.length() < 4)return false; + if (extension[0] != '.')return false; + + if (extension[1] != 'a' && extension[1] != 'A')return false; + if (extension[2] != 's' && extension[2] != 'S')return false; + + // NOTE: Sometimes the extension .ASK is also used + if (extension[3] != 'e' && extension[3] != 'E' && + extension[3] != 'k' && extension[3] != 'K')return false; + + return true; +} +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void ASEImporter::InternReadFile( + const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) +{ + boost::scoped_ptr file( pIOHandler->Open( pFile)); + + // Check whether we can read from the file + if( file.get() == NULL) + { + throw new ImportErrorException( "Failed to open ASE file " + pFile + "."); + } + + size_t fileSize = file->FileSize(); + + // allocate storage and copy the contents of the file to a memory buffer + // (terminate it with zero) + this->mBuffer = new unsigned char[fileSize+1]; + file->Read( (void*)mBuffer, 1, fileSize); + this->mBuffer[fileSize] = '\0'; + + // construct an ASE parser and parse the file + this->mParser = new ASE::Parser((const char*)this->mBuffer); + this->mParser->Parse(); + + // process all meshes + for (std::vector::iterator + i = this->mParser->m_vMeshes.begin(); + i != this->mParser->m_vMeshes.end();++i) + { + // need to generate proper vertex normals if necessary + this->GenerateNormals(*i); + + // now we need to create proper meshes from the import + // we need to split them by materials, build valid vertex/face lists ... + this->BuildUniqueRepresentation(*i); + this->ConvertMeshes(*i,pScene); + } + // buil final material indices (remove submaterials and make the final list) + this->BuildMaterialIndices(pScene); + + // build the final node graph + this->BuildNodes(pScene); + + // delete the ASE parser + delete this->mParser; + this->mParser = NULL; + return; +} +// ------------------------------------------------------------------------------------------------ +void ASEImporter::BuildNodes(aiScene* pcScene) +{ + ai_assert(NULL != pcScene); + + pcScene->mRootNode = new aiNode(); + pcScene->mRootNode->mNumMeshes = pcScene->mNumMeshes; + pcScene->mRootNode->mMeshes = new unsigned int[pcScene->mRootNode->mNumMeshes]; + + for (unsigned int i = 0; i < pcScene->mRootNode->mNumMeshes;++i) + pcScene->mRootNode->mMeshes[i] = i; + + return; +} +// ------------------------------------------------------------------------------------------------ +void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) +{ + // allocate output storage + std::vector mPositions; + std::vector amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + std::vector mVertexColors; + std::vector mNormals; + + unsigned int iSize = mesh.mFaces.size() * 3; + mPositions.resize(iSize); + + // optional texture coordinates + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) + { + if (!mesh.amTexCoords[i].empty()) + { + amTexCoords[i].resize(iSize); + } + } + // optional vertex colors + if (!mesh.mVertexColors.empty()) + { + mVertexColors.resize(iSize); + } + + // optional vertex normals (vertex normals can simply be copied) + if (!mesh.mNormals.empty()) + { + mNormals.resize(iSize); + } + + // iterate through all faces in the mesh + unsigned int iCurrent = 0; + for (std::vector::iterator + i = mesh.mFaces.begin(); + i != mesh.mFaces.end();++i) + { + for (unsigned int n = 0; n < 3;++n,++iCurrent) + { + mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]]; + + // add texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + if (!mesh.amTexCoords[c].empty()) + { + amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]]; + } + } + // add vertex colors + if (!mesh.mVertexColors.empty()) + { + mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]]; + } + // add normal vectors + if (!mesh.mNormals.empty()) + { + mNormals[iCurrent] = mesh.mNormals[(*i).mIndices[n]]; + } + // assign a new valid index to the face + (*i).mIndices[n] = iCurrent; + } + } + + // replace the old arrays + mesh.mNormals = mNormals; + mesh.mPositions = mPositions; + mesh.mVertexColors = mVertexColors; + + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + mesh.amTexCoords[c] = amTexCoords[c]; + + return; +} +// ------------------------------------------------------------------------------------------------ +void ASEImporter::ConvertMaterial(ASE::Material& mat) +{ + // allocate the output material + mat.pcInstance = new MaterialHelper(); + + // At first add the base ambient color of the + // scene to the material + mat.mAmbient.r += this->mParser->m_clrAmbient.r; + mat.mAmbient.g += this->mParser->m_clrAmbient.g; + mat.mAmbient.b += this->mParser->m_clrAmbient.b; + + aiString name; + name.Set( mat.mName); + mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME); + + // material colors + mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); + mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); + mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS); + mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + + // opacity + mat.pcInstance->AddProperty( &mat.mTransparency,1,AI_MATKEY_OPACITY); + + + // shading mode + aiShadingMode eShading = aiShadingMode_NoShading; + switch (mat.mShading) + { + case Dot3DS::Dot3DSFile::Flat: + eShading = aiShadingMode_Flat; break; + case Dot3DS::Dot3DSFile::Phong : + eShading = aiShadingMode_Phong; break; + + // I don't know what "Wire" shading should be, + // assume it is simple lambertian diffuse (L dot N) shading + case Dot3DS::Dot3DSFile::Wire: + case Dot3DS::Dot3DSFile::Gouraud: + eShading = aiShadingMode_Gouraud; break; + case Dot3DS::Dot3DSFile::Metal : + eShading = aiShadingMode_CookTorrance; break; + } + mat.pcInstance->AddProperty( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); + + if (Dot3DS::Dot3DSFile::Wire == mat.mShading) + { + // set the wireframe flag + unsigned int iWire = 1; + mat.pcInstance->AddProperty( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); + } + + // texture, if there is one + if( mat.sTexDiffuse.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexDiffuse.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0)); + + if (is_not_qnan(mat.sTexDiffuse.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexDiffuse.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_DIFFUSE(0)); + } + if( mat.sTexSpecular.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexSpecular.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0)); + + if (is_not_qnan(mat.sTexSpecular.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexSpecular.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_SPECULAR(0)); + } + if( mat.sTexOpacity.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexOpacity.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0)); + + if (is_not_qnan(mat.sTexOpacity.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexOpacity.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_OPACITY(0)); + } + if( mat.sTexEmissive.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexEmissive.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0)); + + if (is_not_qnan(mat.sTexEmissive.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexEmissive.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_EMISSIVE(0)); + } + if( mat.sTexAmbient.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexAmbient.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(0)); + + if (is_not_qnan(mat.sTexAmbient.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexAmbient.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_AMBIENT(0)); + } + if( mat.sTexBump.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexBump.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0)); + + if (is_not_qnan(mat.sTexBump.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexBump.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_HEIGHT(0)); + } + if( mat.sTexShininess.mMapName.length() > 0) + { + aiString tex; + tex.Set( mat.sTexShininess.mMapName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0)); + + if (is_not_qnan(mat.sTexShininess.mTextureBlend)) + mat.pcInstance->AddProperty( &mat.sTexBump.mTextureBlend, 1, + AI_MATKEY_TEXBLEND_SHININESS(0)); + } + + // store the name of the material itself, too + if( mat.mName.length() > 0) + { + aiString tex; + tex.Set( mat.mName); + mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME); + } + return; +} +// ------------------------------------------------------------------------------------------------ +void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene) +{ + ai_assert(NULL != pcScene); + + // validate the material index of the mesh + if (mesh.iMaterialIndex >= this->mParser->m_vMaterials.size()) + { + mesh.iMaterialIndex = this->mParser->m_vMaterials.size()-1; + LOGOUT_WARN("Material index is out of range"); + } + + // List of all output meshes + std::vector avOutMeshes; + + // if the material the mesh is assigned to is consisting of submeshes + // we'll need to split it ... Quak. + if (!this->mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) + { + std::vector vSubMaterials = this->mParser-> + m_vMaterials[mesh.iMaterialIndex].avSubMaterials; + + std::vector* aiSplit = new std::vector[ + vSubMaterials.size()]; + + // build a list of all faces per submaterial + unsigned int iNum = 0; + for (unsigned int i = 0; i < mesh.mFaces.size();++i) + { + // check range + if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) + { + LOGOUT_WARN("Submaterial index is out of range"); + + // use the last material instead + aiSplit[vSubMaterials.size()-1].push_back(i); + } + else aiSplit[mesh.mFaces[i].iMaterial].push_back(i); + } + + // now generate submeshes + for (unsigned int p = 0; p < vSubMaterials.size();++p) + { + if (aiSplit[p].size() != 0) + { + aiMesh* p_pcOut = new aiMesh(); + + // let the sub material index + p_pcOut->mMaterialIndex = p; + + // we will need this material + this->mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true; + + // store the real index here ... + p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex; + avOutMeshes.push_back(p_pcOut); + + // convert vertices + p_pcOut->mNumVertices = aiSplit[p].size()*3; + p_pcOut->mNumFaces = aiSplit[p].size(); + + // allocate enough storage for faces + p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; + + if (p_pcOut->mNumVertices != 0) + { + p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices]; + p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices]; + unsigned int iBase = 0; + + for (unsigned int q = 0; q < aiSplit[p].size();++q) + { + unsigned int iIndex = aiSplit[p][q]; + + p_pcOut->mFaces[q].mIndices = new unsigned int[3]; + p_pcOut->mFaces[q].mNumIndices = 3; + + for (unsigned int t = 0; t < 3;++t) + { + p_pcOut->mFaces[q].mIndices[t] = iBase; + p_pcOut->mVertices[iBase] = mesh.mPositions[mesh.mFaces[iIndex].mIndices[t]]; + p_pcOut->mNormals[iBase++] = mesh.mNormals[mesh.mFaces[iIndex].mIndices[t]]; + } + } + } + // convert texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + if (!mesh.amTexCoords[c].empty()) + { + p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices]; + unsigned int iBase = 0; + for (unsigned int q = 0; q < aiSplit[p].size();++q) + { + unsigned int iIndex = aiSplit[p][q]; + for (unsigned int t = 0; t < 3;++t) + { + p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]]; + } + } + // setup the number of valid vertex components + p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c]; + } + } + + // convert vertex colors (only one set supported) + if (!mesh.mVertexColors.empty()) + { + p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices]; + unsigned int iBase = 0; + for (unsigned int q = 0; q < aiSplit[p].size();++q) + { + unsigned int iIndex = aiSplit[p][q]; + for (unsigned int t = 0; t < 3;++t) + { + p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]]; + } + } + } + } + } + // delete storage + delete[] aiSplit; + } + else + { + // otherwise we can simply copy the data to one output mesh + aiMesh* p_pcOut = new aiMesh(); + + // set an empty sub material index + p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX; + this->mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true; + + // store the real index here ... + p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex; + avOutMeshes.push_back(p_pcOut); + + // convert vertices + p_pcOut->mNumVertices = mesh.mPositions.size(); + p_pcOut->mNumFaces = mesh.mFaces.size(); + + // allocate enough storage for faces + p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; + + // copy vertices + p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()]; + memcpy(p_pcOut->mVertices,&mesh.mPositions[0], + mesh.mPositions.size() * sizeof(aiVector3D)); + + // copy normals + p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()]; + memcpy(p_pcOut->mNormals,&mesh.mNormals[0], + mesh.mNormals.size() * sizeof(aiVector3D)); + + // copy texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + if (!mesh.amTexCoords[c].empty()) + { + p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()]; + memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0], + mesh.amTexCoords[c].size() * sizeof(aiVector3D)); + + // setup the number of valid vertex components + p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c]; + } + } + + // copy vertex colors + if (!mesh.mVertexColors.empty()) + { + p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()]; + memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0], + mesh.mVertexColors.size() * sizeof(aiColor4D)); + } + + // copy faces + for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace) + { + p_pcOut->mFaces[iFace].mNumIndices = 3; + p_pcOut->mFaces[iFace].mIndices = new unsigned int[3]; + + // copy indices + p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0]; + p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1]; + p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2]; + } + } + + // now build the output mesh list + pcScene->mNumMeshes = avOutMeshes.size(); + pcScene->mMeshes = new aiMesh*[pcScene->mNumMeshes]; + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) + pcScene->mMeshes[i] = avOutMeshes[i]; + + return; +} +// ------------------------------------------------------------------------------------------------ +void ASEImporter::BuildMaterialIndices(aiScene* pcScene) +{ + ai_assert(NULL != pcScene); + + // iterate through all materials and check whether we need them + unsigned int iNum = 0; + for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat) + { + if (this->mParser->m_vMaterials[iMat].bNeed) + { + // convert it to the aiMaterial layout + this->ConvertMaterial(this->mParser->m_vMaterials[iMat]); + iNum++; + } + for (unsigned int iSubMat = 0; iSubMat < this->mParser->m_vMaterials[ + iMat].avSubMaterials.size();++iSubMat) + { + if (this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed) + { + // convert it to the aiMaterial layout + this->ConvertMaterial(this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat]); + iNum++; + } + } + } + + // allocate the output material array + pcScene->mNumMaterials = iNum; + pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials]; + + iNum = 0; + for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat) + { + if (this->mParser->m_vMaterials[iMat].bNeed) + { + ai_assert(NULL != this->mParser->m_vMaterials[iMat].pcInstance); + pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].pcInstance; + + // iterate through all meshes and search for one which is using + // this top-level material index + for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) + { + if (ASE::Face::DEFAULT_MATINDEX == pcScene->mMeshes[iMesh]->mMaterialIndex && + iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3]) + { + pcScene->mMeshes[iMesh]->mMaterialIndex = iNum; + pcScene->mMeshes[iMesh]->mColors[3] = NULL; + } + } + iNum++; + } + for (unsigned int iSubMat = 0; iSubMat < this->mParser->m_vMaterials[iMat].avSubMaterials.size();++iSubMat) + { + if (this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed) + { + ai_assert(NULL != this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].pcInstance); + pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat]. + avSubMaterials[iSubMat].pcInstance; + + // iterate through all meshes and search for one which is using + // this sub-level material index + for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) + { + if (iSubMat == pcScene->mMeshes[iMesh]->mMaterialIndex && + iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3]) + { + pcScene->mMeshes[iMesh]->mMaterialIndex = iNum; + pcScene->mMeshes[iMesh]->mColors[3] = NULL; + } + } + iNum++; + } + } + } + // finished! + return; +} +// ------------------------------------------------------------------------------------------------ +// Generate normal vectors basing on smoothing groups +void ASEImporter::GenerateNormals(ASE::Mesh& mesh) +{ + if (mesh.mNormals.empty()) + { + // need to calculate normals ... + // TODO: Find a way to merge this with the code in 3DSGenNormals.cpp + mesh.mNormals.resize(mesh.mPositions.size(),aiVector3D()); + for( unsigned int a = 0; a < mesh.mFaces.size(); a++) + { + const ASE::Face& face = mesh.mFaces[a]; + + // assume it is a triangle + aiVector3D* pV1 = &mesh.mPositions[face.i1]; + aiVector3D* pV2 = &mesh.mPositions[face.i2]; + aiVector3D* pV3 = &mesh.mPositions[face.i3]; + + aiVector3D pDelta1 = *pV2 - *pV1; + aiVector3D pDelta2 = *pV3 - *pV1; + aiVector3D vNor = pDelta1 ^ pDelta2; + + mesh.mNormals[face.i1] = vNor; + mesh.mNormals[face.i2] = vNor; + mesh.mNormals[face.i3] = vNor; + } + + // calculate the position bounds so we have a reliable epsilon to + // check position differences against + // @Schrompf: This is the 7th time this snippet is repeated! + aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f); + for( unsigned int a = 0; a < mesh.mPositions.size(); a++) + { + minVec.x = std::min( minVec.x, mesh.mPositions[a].x); + minVec.y = std::min( minVec.y, mesh.mPositions[a].y); + minVec.z = std::min( minVec.z, mesh.mPositions[a].z); + maxVec.x = std::max( maxVec.x, mesh.mPositions[a].x); + maxVec.y = std::max( maxVec.y, mesh.mPositions[a].y); + maxVec.z = std::max( maxVec.z, mesh.mPositions[a].z); + } + const float posEpsilon = (maxVec - minVec).Length() * 1e-5f; + + std::vector avNormals; + avNormals.resize(mesh.mNormals.size()); + + // now generate the spatial sort tree + D3DSSpatialSorter sSort; + for( std::vector::iterator + i = mesh.mFaces.begin(); + i != mesh.mFaces.end();++i){sSort.AddFace(&(*i),mesh.mPositions);} + sSort.Prepare(); + + for( std::vector::iterator + i = mesh.mFaces.begin(); + i != mesh.mFaces.end();++i) + { + std::vector poResult; + for (unsigned int c = 0; c < 3;++c) + { + sSort.FindPositions(mesh.mPositions[(*i).mIndices[c]],(*i).iSmoothGroup, + posEpsilon,poResult); + + aiVector3D vNormals; + float fDiv = 0.0f; + for (std::vector::const_iterator + a = poResult.begin(); + a != poResult.end();++a) + { + vNormals += mesh.mNormals[(*a)]; + fDiv += 1.0f; + } + vNormals.x /= fDiv;vNormals.y /= fDiv;vNormals.z /= fDiv; + vNormals.Normalize(); + avNormals[(*i).mIndices[c]] = vNormals; + poResult.clear(); + } + } + mesh.mNormals = avNormals; + } + return; +} diff --git a/code/ASELoader.h b/code/ASELoader.h new file mode 100644 index 000000000..760180779 --- /dev/null +++ b/code/ASELoader.h @@ -0,0 +1,147 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Definition of the .ASE importer class. */ +#ifndef AI_ASELOADER_H_INCLUDED +#define AI_ASELOADER_H_INCLUDED + +#include "BaseImporter.h" +#include "../include/aiTypes.h" + +struct aiNode; +#include "ASEParser.h" + +namespace Assimp +{ +class MaterialHelper; + +using namespace ASE; + +// --------------------------------------------------------------------------- +/** Used to load ASE files +*/ +class ASEImporter : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + ASEImporter(); + + /** Destructor, private as well */ + ~ASEImporter(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) + { + append.append("*.ase;*.ask"); + } + + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); + + // ------------------------------------------------------------------- + /** Generate normal vectors basing on smoothing groups + * (in some cases the normal are already contained in the file) + * \param mesh Mesh to work on + */ + void GenerateNormals(ASE::Mesh& mesh); + + // ------------------------------------------------------------------- + /** Create valid vertex/normal/UV/color/face lists. + * All elements are unique, faces have only one set of indices + * after this step occurs. + * \param mesh Mesh to work on + */ + void BuildUniqueRepresentation(ASE::Mesh& mesh); + + // ------------------------------------------------------------------- + /** Create one-material-per-mesh meshes ;-) + * \param mesh Mesh to work with + * \param pcScene Scene object to be filled + */ + void ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene); + + // ------------------------------------------------------------------- + /** Convert a material to a MaterialHelper object + * \param mat Input material + */ + void ConvertMaterial(ASE::Material& mat); + + // ------------------------------------------------------------------- + /** Setup the final material indices for each mesh + * \param pcScene Scene object to be filled + */ + void BuildMaterialIndices(aiScene* pcScene); + + // ------------------------------------------------------------------- + /** Build the node graph + * \param pcScene Scene object to be filled + */ + void BuildNodes(aiScene* pcScene); + +protected: + + /** Parser instance */ + ASE::Parser* mParser; + + /** Buffer to hold the loaded file */ + unsigned char* mBuffer; +}; + +} // end of namespace Assimp + +#endif // AI_3DSIMPORTER_H_INC \ No newline at end of file diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp new file mode 100644 index 000000000..68345e082 --- /dev/null +++ b/code/ASEParser.cpp @@ -0,0 +1,1644 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the ASE parser class */ + +#include "ASELoader.h" +#include "MaterialSystem.h" +#include "DefaultLogger.h" +#include "fast_atof.h" + +#include "../include/IOStream.h" +#include "../include/IOSystem.h" +#include "../include/aiMesh.h" +#include "../include/aiScene.h" +#include "../include/aiAssert.h" + +#include + +using namespace Assimp; +using namespace Assimp::ASE; + +#if (defined BLUBB) +# undef BLUBB +#endif +#define BLUBB(_message_) \ + {this->LogError(_message_);return;} + +// ------------------------------------------------------------------------------------------------ +Parser::Parser (const char* szFile) +{ + ai_assert(NULL != szFile); + this->m_szFile = szFile; + + // makre sure that the color values are invalid + this->m_clrBackground.r = std::numeric_limits::quiet_NaN(); + this->m_clrAmbient.r = std::numeric_limits::quiet_NaN(); + + this->iLineNumber = 0; +} +// ------------------------------------------------------------------------------------------------ +void Parser::LogWarning(const char* szWarn) +{ + ai_assert(NULL != szWarn); + ai_assert(strlen(szWarn) < 950); + + char szTemp[1024]; + sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn); + + // output the warning to the logger ... + DefaultLogger::get()->warn(szTemp); +} +// ------------------------------------------------------------------------------------------------ +void Parser::LogError(const char* szWarn) +{ + ai_assert(NULL != szWarn); + ai_assert(strlen(szWarn) < 950); + + char szTemp[1024]; + sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn); + + // throw an exception + throw new ImportErrorException(szTemp); +} +// ------------------------------------------------------------------------------------------------ +bool Parser::SkipToNextToken() +{ + while (true) + { + if ('*' == *this->m_szFile)return true; + if ('\0' == *this->m_szFile)return false; + + ++this->m_szFile; + } +} +// ------------------------------------------------------------------------------------------------ +bool Parser::SkipOpeningBracket() +{ + if (!SkipSpaces(this->m_szFile,&this->m_szFile))return false; + if ('{' != *this->m_szFile) + { + this->LogWarning("Unable to parse block: Unexpected character, \'{\' expected [#1]"); + return false; + } + this->SkipToNextToken(); + return true; +} +// ------------------------------------------------------------------------------------------------ +bool Parser::SkipSection() +{ + // must handle subsections ... + unsigned int iCnt = 1; + while (true) + { + if ('}' == *this->m_szFile) + { + --iCnt; + if (0 == iCnt) + { + // go to the next valid token ... + ++this->m_szFile; + this->SkipToNextToken(); + return true; + } + } + else if ('{' == *this->m_szFile) + { + ++iCnt; + } + else if ('\0' == *this->m_szFile) + { + this->LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]"); + return false; + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } +} +// ------------------------------------------------------------------------------------------------ +void Parser::Parse() +{ + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // version should be 200. Validate this ... + if (0 == strncmp(this->m_szFile,"*3DSMAX_ASCIIEXPORT",19) && + IsSpaceOrNewLine(*(this->m_szFile+19))) + { + this->m_szFile+=20; + + unsigned int iVersion; + this->ParseLV4MeshLong(iVersion); + + if (200 != iVersion) + { + this->LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \ + be 200. Continuing happily ..."); + } + } + // main scene information + else if (0 == strncmp(this->m_szFile,"*SCENE",6) && + IsSpaceOrNewLine(*(this->m_szFile+6))) + { + this->m_szFile+=7; + this->ParseLV1SceneBlock(); + } + // material list + else if (0 == strncmp(this->m_szFile,"*MATERIAL_LIST",14) && + IsSpaceOrNewLine(*(this->m_szFile+14))) + { + this->m_szFile+=15; + this->ParseLV1MaterialListBlock(); + } + // geometric object (mesh) + else if (0 == strncmp(this->m_szFile,"*GEOMOBJECT",11) && + IsSpaceOrNewLine(*(this->m_szFile+11))) + { + this->m_szFile+=12; + + this->m_vMeshes.push_back(Mesh()); + this->ParseLV1GeometryObjectBlock(this->m_vMeshes.back()); + } + // ignore comments, lights and cameras + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + if ('\0' == *this->m_szFile) + { + // END OF FILE ... why not? + return; + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV1SceneBlock() +{ + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + if (0 == strncmp(this->m_szFile,"*SCENE_BACKGROUND_STATIC",24) && + IsSpaceOrNewLine(*(this->m_szFile+24))) + { + this->m_szFile+=25; + + // parse a color triple and assume it is really the bg color + this->ParseLV4MeshFloatTriple( &this->m_clrBackground.r ); + } + else if (0 == strncmp(this->m_szFile,"*SCENE_AMBIENT_STATIC",21) && + IsSpaceOrNewLine(*(this->m_szFile+21))) + { + this->m_szFile+=22; + + // parse a color triple and assume it is really the bg color + this->ParseLV4MeshFloatTriple( &this->m_clrAmbient.r ); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... why not? + return; + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV1MaterialListBlock() +{ + unsigned int iDepth = 1; + unsigned int iMaterialCount = 0; + while (true) + { + if ('*' == *this->m_szFile) + { + if (0 == strncmp(this->m_szFile,"*MATERIAL_COUNT",15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->ParseLV4MeshLong(iMaterialCount); + + // now allocate enough storage to hold all materials + this->m_vMaterials.resize(iMaterialCount); + } + else if (0 == strncmp(this->m_szFile,"*MATERIAL",9) && + IsSpaceOrNewLine(*(this->m_szFile+9))) + { + this->m_szFile+=10; + unsigned int iIndex = 0; + this->ParseLV4MeshLong(iIndex); + + if (iIndex >= iMaterialCount) + { + this->LogWarning("Out of range: material index is too large"); + iIndex = iMaterialCount-1; + } + + // get a reference to the material + Material& sMat = this->m_vMaterials[iIndex]; + + // skip the '{' + this->SkipOpeningBracket(); + + // parse the material block + this->ParseLV2MaterialBlock(sMat); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... why not? + return; + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV2MaterialBlock(ASE::Material& mat) +{ + unsigned int iDepth = 1; + unsigned int iNumSubMaterials = 0; + while (true) + { + if ('*' == *this->m_szFile) + { + if (0 == strncmp(this->m_szFile,"*MATERIAL_NAME",14) && + IsSpaceOrNewLine(*(this->m_szFile+14))) + { + this->m_szFile+=15; + + // NOTE: The name could also be the texture in some cases + // be prepared that this might occur ... + if (!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *MATERIAL_NAME block: Unexpected EOL") + + const char* sz = this->m_szFile; + while (!IsSpaceOrNewLine(*sz))sz++; + mat.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile); + this->m_szFile = sz; + } + // ambient material color + else if (0 == strncmp(this->m_szFile,"*MATERIAL_AMBIENT",17) && + IsSpaceOrNewLine(*(this->m_szFile+17))) + { + this->m_szFile+=18; + this->ParseLV4MeshFloatTriple(&mat.mAmbient.r); + } + // diffuse material color + else if (0 == strncmp(this->m_szFile,"*MATERIAL_DIFFUSE",17) && + IsSpaceOrNewLine(*(this->m_szFile+17))) + { + this->m_szFile+=18; + this->ParseLV4MeshFloatTriple(&mat.mDiffuse.r); + } + // specular material color + else if (0 == strncmp(this->m_szFile,"*MATERIAL_SPECULAR",18) && + IsSpaceOrNewLine(*(this->m_szFile+18))) + { + this->m_szFile+=19; + this->ParseLV4MeshFloatTriple(&mat.mSpecular.r); + } + // material shading type + else if (0 == strncmp(this->m_szFile,"*MATERIAL_SHADING",17) && + IsSpaceOrNewLine(*(this->m_szFile+17))) + { + this->m_szFile+=18; + + if (0 == strncmp(this->m_szFile,"Blinn",5) && + IsSpaceOrNewLine(*(this->m_szFile+5))) + { + mat.mShading = Dot3DSFile::Blinn; + this->m_szFile+=6; + } + else if (0 == strncmp(this->m_szFile,"Phong",5) && + IsSpaceOrNewLine(*(this->m_szFile+5))) + { + mat.mShading = Dot3DSFile::Phong; + this->m_szFile+=6; + } + else if (0 == strncmp(this->m_szFile,"Flat",4) && + IsSpaceOrNewLine(*(this->m_szFile+4))) + { + mat.mShading = Dot3DSFile::Flat; + this->m_szFile+=5; + } + else if (0 == strncmp(this->m_szFile,"Wire",4) && + IsSpaceOrNewLine(*(this->m_szFile+4))) + { + mat.mShading = Dot3DSFile::Wire; + this->m_szFile+=5; + } + else + { + // assume gouraud shading + mat.mShading = Dot3DSFile::Gouraud; + this->SkipToNextToken(); + } + } + // material transparency + else if (0 == strncmp(this->m_szFile,"*MATERIAL_TRANSPARENCY",22) && + IsSpaceOrNewLine(*(this->m_szFile+22))) + { + this->m_szFile+=23; + this->ParseLV4MeshFloat(mat.mTransparency); + mat.mTransparency = 1.0f - mat.mTransparency; + } + // material self illumination + else if (0 == strncmp(this->m_szFile,"*MATERIAL_SELFILLUM",19) && + IsSpaceOrNewLine(*(this->m_szFile+19))) + { + this->m_szFile+=20; + float f = 0.0f; + this->ParseLV4MeshFloat(f); + + mat.mEmissive.r = f; + mat.mEmissive.g = f; + mat.mEmissive.b = f; + } + // material shininess + else if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINE",15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->ParseLV4MeshFloat(mat.mSpecularExponent); + mat.mSpecularExponent *= 15; + } + // diffuse color map + else if (0 == strncmp(this->m_szFile,"*MAP_DIFFUSE",12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexDiffuse); + } + // ambient color map + else if (0 == strncmp(this->m_szFile,"*MAP_AMBIENT",12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexAmbient); + } + // specular color map + else if (0 == strncmp(this->m_szFile,"*MAP_SPECULAR",13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexSpecular); + } + // opacity map + else if (0 == strncmp(this->m_szFile,"*MAP_OPACITY",12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexOpacity); + } + // emissive map + else if (0 == strncmp(this->m_szFile,"*MAP_SELFILLUM",14) && + IsSpaceOrNewLine(*(this->m_szFile+14))) + { + this->m_szFile+=15; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexEmissive); + } + // bump map + else if (0 == strncmp(this->m_szFile,"*MAP_BUMP",9) && + IsSpaceOrNewLine(*(this->m_szFile+9))) + { + this->m_szFile+=10; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexBump); + } + // specular/shininess map + else if (0 == strncmp(this->m_szFile,"*MAP_SHINE",10) && + IsSpaceOrNewLine(*(this->m_szFile+10))) + { + this->m_szFile+=11; + // skip the opening bracket + this->SkipOpeningBracket(); + // parse the texture block + this->ParseLV3MapBlock(mat.sTexShininess); + } + // number of submaterials + else if (0 == strncmp(this->m_szFile,"*NUMSUBMTLS",11) && + IsSpaceOrNewLine(*(this->m_szFile+11))) + { + this->m_szFile+=12; + this->ParseLV4MeshLong(iNumSubMaterials); + + // allocate enough storage + mat.avSubMaterials.resize(iNumSubMaterials); + } + // submaterial chunks + else if (0 == strncmp(this->m_szFile,"*SUBMATERIAL",12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + + unsigned int iIndex = 0; + this->ParseLV4MeshLong(iIndex); + + if (iIndex >= iNumSubMaterials) + { + this->LogWarning("Out of range: submaterial index is too large"); + iIndex = iNumSubMaterials-1; + } + + // get a reference to the material + Material& sMat = mat.avSubMaterials[iIndex]; + + // skip the '{' + this->SkipOpeningBracket(); + + // parse the material block + this->ParseLV2MaterialBlock(sMat); + } + + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level2 block, this can't be + BLUBB("Unable to finish parsing a lv2 material block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MapBlock(Texture& map) +{ + unsigned int iDepth = 1; + unsigned int iNumSubMaterials = 0; + while (true) + { + if ('*' == *this->m_szFile) + { + // path to the texture + if (0 == strncmp(this->m_szFile,"*BITMAP" ,7) && + IsSpaceOrNewLine(*(this->m_szFile+7))) + { + this->m_szFile+=8; + + // NOTE: The name could also be the texture in some cases + // be prepared that this might occur ... + if (!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *BITMAP block: Unexpected EOL") + + // there must be " + if ('\"' != *this->m_szFile) + BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks") + + ++this->m_szFile; + const char* sz = this->m_szFile; + while (true) + { + if ('\"' == *sz)break; + else if ('\0' == sz) + { + BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks \ + but EOF was reached before a closing quotation mark was found") + } + sz++; + } + + map.mMapName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile); + this->m_szFile = sz; + } + // offset on the u axis + if (0 == strncmp(this->m_szFile,"*UVW_U_OFFSET" ,13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + this->ParseLV4MeshFloat(map.mOffsetU); + } + // offset on the v axis + if (0 == strncmp(this->m_szFile,"*UVW_V_OFFSET" ,13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + this->ParseLV4MeshFloat(map.mOffsetV); + } + // tiling on the u axis + if (0 == strncmp(this->m_szFile,"*UVW_U_TILING" ,13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + this->ParseLV4MeshFloat(map.mScaleU); + } + // tiling on the v axis + if (0 == strncmp(this->m_szFile,"*UVW_V_TILING" ,13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + this->ParseLV4MeshFloat(map.mScaleV); + } + // rotation around the z-axis + if (0 == strncmp(this->m_szFile,"*UVW_ANGLE" ,10) && + IsSpaceOrNewLine(*(this->m_szFile+10))) + { + this->m_szFile+=11; + this->ParseLV4MeshFloat(map.mRotation); + } + // map blending factor + if (0 == strncmp(this->m_szFile,"*MAP_AMOUNT" ,11) && + IsSpaceOrNewLine(*(this->m_szFile+11))) + { + this->m_szFile+=12; + this->ParseLV4MeshFloat(map.mTextureBlend); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing a lv3 map block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh) +{ + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // name of the mesh/node + if (0 == strncmp(this->m_szFile,"*NODE_NAME" ,10) && + IsSpaceOrNewLine(*(this->m_szFile+10))) + { + this->m_szFile+=11; + + // NOTE: The name could also be the texture in some cases + // be prepared that this might occur ... + if (!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *NODE_NAME block: Unexpected EOL") + + // there must be " + if ('\"' != *this->m_szFile) + BLUBB("Unable to parse *NODE_NAME block: Name is expected to be enclosed in double quotation marks") + + ++this->m_szFile; + const char* sz = this->m_szFile; + while (true) + { + if ('\"' == *sz)break; + else if ('\0' == sz) + { + BLUBB("Unable to parse *NODE_NAME block: Name is expected to be enclosed in double quotation marks \ + but EOF was reached before a closing quotation mark was found") + } + sz++; + } + + mesh.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile); + this->m_szFile = sz; + } + // transformation matrix of the node + else if (0 == strncmp(this->m_szFile,"*NODE_TM" ,8) && + IsSpaceOrNewLine(*(this->m_szFile+8))) + { + this->m_szFile+=9; + this->ParseLV2NodeTransformBlock(mesh); + } + // mesh data + else if (0 == strncmp(this->m_szFile,"*MESH" ,5) && + IsSpaceOrNewLine(*(this->m_szFile+5))) + { + this->m_szFile+=6; + this->ParseLV2MeshBlock(mesh); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level1 block, this can be + return; + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh) +{ + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // first row of the transformation matrix + if (0 == strncmp(this->m_szFile,"*TM_ROW0" ,8) && + IsSpaceOrNewLine(*(this->m_szFile+8))) + { + this->m_szFile+=9; + this->ParseLV4MeshFloatTriple(mesh.mTransform[0]); + } + // second row of the transformation matrix + else if (0 == strncmp(this->m_szFile,"*TM_ROW1" ,8) && + IsSpaceOrNewLine(*(this->m_szFile+8))) + { + this->m_szFile+=9; + this->ParseLV4MeshFloatTriple(mesh.mTransform[1]); + } + // third row of the transformation matrix + else if (0 == strncmp(this->m_szFile,"*TM_ROW2" ,8) && + IsSpaceOrNewLine(*(this->m_szFile+8))) + { + this->m_szFile+=9; + this->ParseLV4MeshFloatTriple(mesh.mTransform[2]); + } + // fourth row of the transformation matrix + else if (0 == strncmp(this->m_szFile,"*TM_ROW3" ,8) && + IsSpaceOrNewLine(*(this->m_szFile+8))) + { + this->m_szFile+=9; + this->ParseLV4MeshFloatTriple(mesh.mTransform[3]); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level2 block, this can't be + BLUBB("Unable to finish parsing a lv2 node transform block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh) +{ + unsigned int iNumVertices = 0; + unsigned int iNumFaces = 0; + unsigned int iNumTVertices = 0; + unsigned int iNumTFaces = 0; + unsigned int iNumCVertices = 0; + unsigned int iNumCFaces = 0; + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Number of vertices in the mesh + if (0 == strncmp(this->m_szFile,"*MESH_NUMVERTEX" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->ParseLV4MeshLong(iNumVertices); + } + // Number of texture coordinates in the mesh + else if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) && + IsSpaceOrNewLine(*(this->m_szFile+16))) + { + this->m_szFile+=17; + this->ParseLV4MeshLong(iNumTVertices); + } + // Number of vertex colors in the mesh + else if (0 == strncmp(this->m_szFile,"*MESH_NUMCVERTEX" ,16) && + IsSpaceOrNewLine(*(this->m_szFile+16))) + { + this->m_szFile+=17; + this->ParseLV4MeshLong(iNumCVertices); + } + // Number of regular faces in the mesh + else if (0 == strncmp(this->m_szFile,"*MESH_NUMFACES" ,14) && + IsSpaceOrNewLine(*(this->m_szFile+14))) + { + this->m_szFile+=15; + this->ParseLV4MeshLong(iNumFaces); + } + // Number of UVWed faces in the mesh + else if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) && + IsSpaceOrNewLine(*(this->m_szFile+16))) + { + this->m_szFile+=17; + this->ParseLV4MeshLong(iNumTFaces); + } + // Number of colored faces in the mesh + else if (0 == strncmp(this->m_szFile,"*MESH_NUMCVFACES" ,16) && + IsSpaceOrNewLine(*(this->m_szFile+16))) + { + this->m_szFile+=17; + this->ParseLV4MeshLong(iNumCFaces); + } + // mesh vertex list block + else if (0 == strncmp(this->m_szFile,"*MESH_VERTEX_LIST" ,17) && + IsSpaceOrNewLine(*(this->m_szFile+17))) + { + this->m_szFile+=18; + this->ParseLV3MeshVertexListBlock(iNumVertices,mesh); + } + // mesh face list block + else if (0 == strncmp(this->m_szFile,"*MESH_FACE_LIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshFaceListBlock(iNumFaces,mesh); + } + // mesh texture vertex list block + else if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshTListBlock(iNumTVertices,mesh); + } + // mesh texture face block + else if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh); + } + // mesh color vertex list block + else if (0 == strncmp(this->m_szFile,"*MESH_CVERTLIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshCListBlock(iNumCVertices,mesh); + } + // mesh color face block + else if (0 == strncmp(this->m_szFile,"*MESH_CFACELIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshCFaceListBlock(iNumCFaces,mesh); + } + // another mesh UV channel ... + else if (0 == strncmp(this->m_szFile,"*MESH_MAPPINGCHANNEL" ,20) && + IsSpaceOrNewLine(*(this->m_szFile+20))) + { + this->m_szFile+=21; + + unsigned int iIndex = 0; + this->ParseLV4MeshLong(iIndex); + + if (iIndex < 2) + { + this->LogWarning("Mapping channel has an invalid index. Skipping UV channel"); + // skip it ... + this->SkipOpeningBracket(); + this->SkipSection(); + } + if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) + { + this->LogWarning("Too many UV channels specified. Skipping channel .."); + // skip it ... + this->SkipOpeningBracket(); + this->SkipSection(); + } + else + { + // skip the '{' + this->SkipOpeningBracket(); + + // parse the mapping channel + this->ParseLV3MappingChannel(iIndex-1,mesh); + } + } + // mesh material index + else if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + this->ParseLV4MeshLong(mesh.iMaterialIndex); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level2 block, this can't be + BLUBB("Unable to finish parsing a lv2 mesh block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshVertexListBlock( + unsigned int iNumVertices, ASE::Mesh& mesh) +{ + // allocate enough storage in the array + mesh.mPositions.resize(iNumVertices); + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Vertex entry + if (0 == strncmp(this->m_szFile,"*MESH_VERTEX" ,12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + + aiVector3D vTemp; + unsigned int iIndex; + this->ParseLV4MeshFloatTriple(&vTemp.x,iIndex); + + if (iIndex >= iNumVertices) + { + this->LogWarning("Vertex has an invalid index. It will be ignored"); + } + else mesh.mPositions[iIndex] = vTemp; + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing a lv3 vertex list block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) +{ + // allocate enough storage in the face array + mesh.mFaces.resize(iNumFaces); + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Face entry + if (0 == strncmp(this->m_szFile,"*MESH_FACE" ,10) && + IsSpaceOrNewLine(*(this->m_szFile+10))) + { + this->m_szFile+=11; + + ASE::Face mFace; + this->ParseLV4MeshFace(mFace); + + if (mFace.iFace >= iNumFaces) + { + this->LogWarning("Face has an invalid index. It will be ignored"); + } + else mesh.mFaces[mFace.iFace] = mFace; + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing LV3 *MESH_FACE_LIST block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, + ASE::Mesh& mesh, unsigned int iChannel) +{ + // allocate enough storage in the array + mesh.amTexCoords[iChannel].resize(iNumVertices); + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Vertex entry + if (0 == strncmp(this->m_szFile,"*MESH_TVERT" ,11) && + IsSpaceOrNewLine(*(this->m_szFile+11))) + { + this->m_szFile+=12; + + aiVector3D vTemp; + unsigned int iIndex; + this->ParseLV4MeshFloatTriple(&vTemp.x,iIndex); + + if (iIndex >= iNumVertices) + { + this->LogWarning("Tvertex has an invalid index. It will be ignored"); + } + else mesh.amTexCoords[iChannel][iIndex] = vTemp; + + if (0.0f != vTemp.z) + { + // we need 3 coordinate channels + mesh.mNumUVComponents[iChannel] = 3; + } + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing LV3 *MESH_VERTEX_LIST block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, + ASE::Mesh& mesh, unsigned int iChannel) +{ + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Face entry + if (0 == strncmp(this->m_szFile,"*MESH_TFACE" ,12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + + unsigned int aiValues[3]; + unsigned int iIndex = 0; + + this->ParseLV4MeshLongTriple(aiValues,iIndex); + if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) + { + this->LogWarning("UV-Face has an invalid index. It will be ignored"); + } + else + { + // copy UV indices + mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0]; + mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1]; + mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2]; + } + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing LV3 *MESH_TFACELIST block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh) +{ + unsigned int iNumTVertices = 0; + unsigned int iNumTFaces = 0; + + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Number of texture coordinates in the mesh + if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) && + IsSpaceOrNewLine(*(this->m_szFile+16))) + { + this->m_szFile+=17; + this->ParseLV4MeshLong(iNumTVertices); + } + // Number of UVWed faces in the mesh + else if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) && + IsSpaceOrNewLine(*(this->m_szFile+16))) + { + this->m_szFile+=17; + this->ParseLV4MeshLong(iNumTFaces); + } + // mesh texture vertex list block + else if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel); + } + // mesh texture face block + else if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) && + IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + this->SkipOpeningBracket(); + this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel); + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level2 block, this can't be + BLUBB("Unable to finish parsing a LV3 *MESH_MAPPINGCHANNEL block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh) +{ + // allocate enough storage in the array + mesh.mVertexColors.resize(iNumVertices); + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Vertex entry + if (0 == strncmp(this->m_szFile,"*MESH_VERTCOL" ,13) && + IsSpaceOrNewLine(*(this->m_szFile+13))) + { + this->m_szFile+=14; + + aiColor4D vTemp; + vTemp.a = 1.0f; + unsigned int iIndex; + this->ParseLV4MeshFloatTriple(&vTemp.r,iIndex); + + if (iIndex >= iNumVertices) + { + this->LogWarning("Vertex color has an invalid index. It will be ignored"); + } + else mesh.mVertexColors[iIndex] = vTemp; + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing LV3 *MESH_CVERTLIST block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) +{ + unsigned int iDepth = 1; + while (true) + { + if ('*' == *this->m_szFile) + { + // Face entry + if (0 == strncmp(this->m_szFile,"*MESH_CFACE" ,12) && + IsSpaceOrNewLine(*(this->m_szFile+12))) + { + this->m_szFile+=13; + + unsigned int aiValues[3]; + unsigned int iIndex = 0; + + this->ParseLV4MeshLongTriple(aiValues,iIndex); + if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) + { + this->LogWarning("UV-Face has an invalid index. It will be ignored"); + } + else + { + // copy color indices + mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0]; + mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1]; + mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2]; + } + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + else if ('\0' == *this->m_szFile) + { + // END OF FILE ... this is a level3 block, this can't be + BLUBB("Unable to finish parsing LV3 *MESH_CFACELIST block. Unexpected EOF") + } + else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; + ++this->m_szFile; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) +{ + // allocate enough storage for the normals + sMesh.mNormals.resize(sMesh.mPositions.size()); + unsigned int iDepth = 1; + + // we need the *MESH_VERTEXNORMAL blocks, ignore the face normals + // if there are only face normals we calculate them outselfes using the SGs + while (true) + { + if ('*' == *this->m_szFile) + { + if (0 == strncmp(this->m_szFile,"*MESH_VERTEXNORMAL",18) && IsSpaceOrNewLine(*(this->m_szFile+18))) + { + this->m_szFile += 19; + + // parse a simple float triple + aiVector3D vNormal; + unsigned int iIndex = 0; + this->ParseLV4MeshFloatTriple(&vNormal.x,iIndex); + + if (iIndex >= sMesh.mNormals.size()) + { + this->LogWarning("Normal index is too large"); + iIndex = sMesh.mNormals.size()-1; + } + + // important: this->m_szFile might now point to '}' ... + sMesh.mNormals[iIndex] = vNormal; + } + } + if ('{' == *this->m_szFile)iDepth++; + if ('}' == *this->m_szFile) + { + if (0 == --iDepth) + { + ++this->m_szFile; + this->SkipToNextToken(); + return; + } + } + // seems we have reached the end of the file ... + else if ('\0' == *this->m_szFile) + { + BLUBB("Unable to parse *MESH_NORMALS Element: Unexpected EOL [#1]") + } + this->m_szFile++; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFace(ASE::Face& out) +{ + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]") + + // parse the face index + out.iFace = strtol10(this->m_szFile,&this->m_szFile); + + // next character should be ':' + if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile) + BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]") + + // parse all mesh indices + ++this->m_szFile; + for (unsigned int i = 0; i < 3;++i) + { + unsigned int iIndex = 0; + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG +__EARTHQUAKE_XXL: + BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. A,B or C expected [#3]") + } + switch (*this->m_szFile) + { + case 'A': + case 'a': + break; + case 'B': + case 'b': + iIndex = 1; + break; + case 'C': + case 'c': + iIndex = 2; + break; + default: goto __EARTHQUAKE_XXL; + }; + ++this->m_szFile; + + // next character should be ':' + if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile) + BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]") + + ++this->m_szFile; + + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. Vertex index ecpected [#4]") + + out.mIndices[iIndex] = strtol10(this->m_szFile,&this->m_szFile); + } + + // now we need to skip the AB, BC, CA blocks. + while (true) + { + if ('*' == *this->m_szFile)break; + if (IsLineEnd(*this->m_szFile)) + { + this->iLineNumber++; + return; + } + this->m_szFile++; + } + + // parse the smoothing group of the face + if (0 == strncmp(this->m_szFile,"*MESH_SMOOTHING",15) && IsSpaceOrNewLine(*(this->m_szFile+15))) + { + this->m_szFile+=16; + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *MESH_SMOOTHING Element: Unexpected EOL. Smoothing group(s) expected [#5]") + + // parse smoothing groups until we don_t anymore see commas + while (true) + { + out.iSmoothGroup |= (1 << strtol10(this->m_szFile,&this->m_szFile)); + SkipSpaces(this->m_szFile,&this->m_szFile); + if (',' != *this->m_szFile) + { + break; + } + ++this->m_szFile; + SkipSpaces(this->m_szFile,&this->m_szFile); + } + } + + // *MESH_MTLID is optional, too + while (true) + { + if ('*' == *this->m_szFile)break; + if (IsLineEnd(*this->m_szFile)) + { + this->iLineNumber++; + return; + } + this->m_szFile++; + } + + if (0 == strncmp(this->m_szFile,"*MESH_MTLID",11) && IsSpaceOrNewLine(*(this->m_szFile+11))) + { + this->m_szFile+=12; + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + BLUBB("Unable to parse *MESH_MTLID Element: Unexpected EOL. Material index expected [#6]") + out.iMaterial = strtol10(this->m_szFile,&this->m_szFile); + } + this->SkipToNextToken(); + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshLongTriple(unsigned int* apOut) +{ + ai_assert(NULL != apOut); + + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#1]"); + ++this->iLineNumber; + apOut[0] = apOut[1] = apOut[2] = 0; + return; + } + apOut[0] = strtol10(this->m_szFile,&this->m_szFile); + + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#2]"); + ++this->iLineNumber; + apOut[1] = apOut[2] = 0; + return; + } + apOut[1] = strtol10(this->m_szFile,&this->m_szFile); + + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#3]"); + apOut[2] = 0; + ++this->iLineNumber; + return; + } + apOut[2] = strtol10(this->m_szFile,&this->m_szFile); + // go to the next valid sequence + SkipSpacesAndLineEnd(this->m_szFile,&this->m_szFile); +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut) +{ + ai_assert(NULL != apOut); + + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#4]"); + rIndexOut = 0; + apOut[0] = apOut[1] = apOut[2] = 0; + ++this->iLineNumber; + return; + } + // parse the index + rIndexOut = strtol10(this->m_szFile,&this->m_szFile); + + // parse the three others + this->ParseLV4MeshLongTriple(apOut); + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut) +{ + ai_assert(NULL != apOut); + + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse indexable float triple: unexpected EOL [#1]"); + rIndexOut = 0; + apOut[0] = apOut[1] = apOut[2] = 0.0f; + ++this->iLineNumber; + return; + } + // parse the index + rIndexOut = strtol10(this->m_szFile,&this->m_szFile); + + // parse the three others + this->ParseLV4MeshFloatTriple(apOut); + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFloatTriple(float* apOut) +{ + ai_assert(NULL != apOut); + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse float triple: unexpected EOL [#5]"); + apOut[0] = apOut[1] = apOut[2] = 0.0f; + ++this->iLineNumber; + return; + } + // parse the first float + this->m_szFile = fast_atof_move(this->m_szFile,apOut[0]); + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse float triple: unexpected EOL [#6]"); + apOut[1] = apOut[2] = 0.0f; + ++this->iLineNumber; + return; + } + // parse the second float + this->m_szFile = fast_atof_move(this->m_szFile,apOut[1]); + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse float triple: unexpected EOL [#7]"); + apOut[2] = 0.0f; + ++this->iLineNumber; + return; + } + // parse the third float + this->m_szFile = fast_atof_move(this->m_szFile,apOut[2]); + // go to the next valid sequence + this->SkipToNextToken(); + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshFloat(float& fOut) +{ + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse float: unexpected EOL [#1]"); + fOut = 0.0f; + ++this->iLineNumber; + return; + } + // parse the first float + this->m_szFile = fast_atof_move(this->m_szFile,fOut); + // go to the next valid sequence + this->SkipToNextToken(); + return; +} +// ------------------------------------------------------------------------------------------------ +void Parser::ParseLV4MeshLong(unsigned int& iOut) +{ + // skip spaces and tabs + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // LOG + this->LogWarning("Unable to parse long: unexpected EOL [#1]"); + iOut = 0; + ++this->iLineNumber; + return; + } + // parse the value + iOut = strtol10(this->m_szFile,&this->m_szFile); + // go to the next valid sequence + this->SkipToNextToken(); + return; +} \ No newline at end of file diff --git a/code/ASEParser.h b/code/ASEParser.h new file mode 100644 index 000000000..012e4b450 --- /dev/null +++ b/code/ASEParser.h @@ -0,0 +1,387 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + +/** @file Defines the helper data structures for importing ASE files */ +#ifndef AI_ASEFILEHELPER_H_INC +#define AI_ASEFILEHELPER_H_INC + +#include +#include +#include +#include + +#include "../include/aiTypes.h" +#include "../include/aiMesh.h" +#include "../include/aiAnim.h" + +// for some helper routines like IsSpace() +#include "PlyParser.h" + +// ASE is quite similar to 3ds. We can reuse some structures +#include "3DSLoader.h" + +namespace Assimp +{ + +// http://wiki.beyondunreal.com/Legacy:ASE_File_Format +namespace ASE +{ + using namespace Dot3DS; + +// --------------------------------------------------------------------------- +/** Helper structure representing an ASE material */ +struct Material : public Dot3DS::Material +{ + //! Default constructor + Material() : pcInstance(NULL), bNeed (false) + {} + + //! Ambient texture channel + Texture sTexAmbient; + + //! Contains all sub materials of this material + std::vector avSubMaterials; + + //! MaterialHelper object + MaterialHelper* pcInstance; + + //! Can we remove this material? + bool bNeed; +}; +// --------------------------------------------------------------------------- +/** Helper structure to represent an ASE file face */ +struct Face : public Dot3DS::Face +{ + //! Default constructor. Initializes everything with 0 + Face() + { + mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) + { + amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0; + } + + iMaterial = DEFAULT_MATINDEX; + iFace = 0; + } + + //! special value to indicate that no material index has + //! been assigned to a face. The default material index + //! will replace this value later. + static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF; + + + //! Indices into the list of vertices + unsigned int mIndices[3]; + + //! Indices into each list of texture coordinates + unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3]; + + //! Index into the list of vertex colors + unsigned int mColorIndices[3]; + + //! (Sub)Material index to be assigned to this face + unsigned int iMaterial; + + //! Index of the face. It is not specified whether it is + //! a requirement of the file format that all faces are + //! written in sequential order, so we have to expect this case + unsigned int iFace; +}; + +// --------------------------------------------------------------------------- +/** Helper structure to represent an ASE file mesh */ +struct Mesh +{ + //! Constructor. Creates a default name for the mesh + Mesh() + { + static int iCnt = 0; + std::stringstream ss(mName); + ss << "%%_UNNAMED_" << iCnt++ << "_%%"; + + // use 2 texture vertex components by default + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + this->mNumUVComponents[c] = 2; + } + std::string mName; + + //! vertex positions + std::vector mPositions; + + //! List of all faces loaded + std::vector mFaces; + + //! List of all texture coordinate sets + std::vector amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + + //! List of all vertex color sets. + std::vector mVertexColors; + + //! List of normal vectors + std::vector mNormals; + + //! Transformation matrix of the mesh + aiMatrix4x4 mTransform; + + //! Material index of the mesh + unsigned int iMaterialIndex; + + //! Number of vertex components for each UVW set + unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; +}; + +// --------------------------------------------------------------------------------- +/** \brief Class to parse ASE files + */ +class Parser +{ + +private: + + Parser() {} + +public: + + //! Construct a parser from a given input file which is + //! guaranted to be terminated with zero. + Parser (const char* szFile); + + // ------------------------------------------------------------------- + //! Parses the file into the parsers internal representation + void Parse(); + + +private: + + // ------------------------------------------------------------------- + //! Parse the *SCENE block in a file + void ParseLV1SceneBlock(); + + // ------------------------------------------------------------------- + //! Parse the *MATERIAL_LIST block in a file + void ParseLV1MaterialListBlock(); + + // ------------------------------------------------------------------- + //! Parse a *GEOMOBJECT block in a file + //! \param mesh Mesh object to be filled + void ParseLV1GeometryObjectBlock(Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MATERIAL blocks in a material list + //! \param mat Material structure to be filled + void ParseLV2MaterialBlock(Material& mat); + + // ------------------------------------------------------------------- + //! Parse a *NODE_TM block in a file + //! \param mesh Mesh object to be filled + void ParseLV2NodeTransformBlock(Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH block in a file + //! \param mesh Mesh object to be filled + void ParseLV2MeshBlock(Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse the *MAP_XXXXXX blocks in a material + //! \param map Texture structure to be filled + void ParseLV3MapBlock(Texture& map); + + // ------------------------------------------------------------------- + //! Parse a *MESH_VERTEX_LIST block in a file + //! \param iNumVertices Value of *MESH_NUMVERTEX, if present. + //! Otherwise zero. This is used to check the consistency of the file. + //! A warning is sent to the logger if the validations fails. + //! \param mesh Mesh object to be filled + void ParseLV3MeshVertexListBlock( + unsigned int iNumVertices,Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH_FACE_LIST block in a file + //! \param iNumFaces Value of *MESH_NUMFACES, if present. + //! Otherwise zero. This is used to check the consistency of the file. + //! A warning is sent to the logger if the validations fails. + //! \param mesh Mesh object to be filled + void ParseLV3MeshFaceListBlock( + unsigned int iNumFaces,Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH_TVERT_LIST block in a file + //! \param iNumVertices Value of *MESH_NUMTVERTEX, if present. + //! Otherwise zero. This is used to check the consistency of the file. + //! A warning is sent to the logger if the validations fails. + //! \param mesh Mesh object to be filled + //! \param iChannel Output UVW channel + void ParseLV3MeshTListBlock( + unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0); + + // ------------------------------------------------------------------- + //! Parse a *MESH_TFACELIST block in a file + //! \param iNumFaces Value of *MESH_NUMTVFACES, if present. + //! Otherwise zero. This is used to check the consistency of the file. + //! A warning is sent to the logger if the validations fails. + //! \param mesh Mesh object to be filled + //! \param iChannel Output UVW channel + void ParseLV3MeshTFaceListBlock( + unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0); + + // ------------------------------------------------------------------- + //! Parse an additional mapping channel + //! (specified via *MESH_MAPPINGCHANNEL) + //! \param iChannel Channel index to be filled + //! \param mesh Mesh object to be filled + void ParseLV3MappingChannel( + unsigned int iChannel, Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH_CVERTLIST block in a file + //! \param iNumVertices Value of *MESH_NUMCVERTEX, if present. + //! Otherwise zero. This is used to check the consistency of the file. + //! A warning is sent to the logger if the validations fails. + //! \param mesh Mesh object to be filled + void ParseLV3MeshCListBlock( + unsigned int iNumVertices, Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH_CFACELIST block in a file + //! \param iNumFaces Value of *MESH_NUMCVFACES, if present. + //! Otherwise zero. This is used to check the consistency of the file. + //! A warning is sent to the logger if the validations fails. + //! \param mesh Mesh object to be filled + void ParseLV3MeshCFaceListBlock( + unsigned int iNumFaces, Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH_NORMALS block in a file + //! \param mesh Mesh object to be filled + void ParseLV3MeshNormalListBlock(Mesh& mesh); + + // ------------------------------------------------------------------- + //! Parse a *MESH_FACE block in a file + //! \param out receive the face data + void ParseLV4MeshFace(ASE::Face& out); + + // ------------------------------------------------------------------- + //! Parse a *MESH_VERT block in a file + //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) + //! \param apOut Output buffer (3 floats) + //! \param rIndexOut Output index + void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut); + + // ------------------------------------------------------------------- + //! Parse a *MESH_VERT block in a file + //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) + //! \param apOut Output buffer (3 floats) + void ParseLV4MeshFloatTriple(float* apOut); + + // ------------------------------------------------------------------- + //! Parse a *MESH_TFACE block in a file + //! (also works for MESH_CFACE) + //! \param apOut Output buffer (3 ints) + //! \param rIndexOut Output index + void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut); + + // ------------------------------------------------------------------- + //! Parse a *MESH_TFACE block in a file + //! (also works for MESH_CFACE) + //! \param apOut Output buffer (3 ints) + void ParseLV4MeshLongTriple(unsigned int* apOut); + + // ------------------------------------------------------------------- + //! Parse a single float element + //! \param fOut Output float + void ParseLV4MeshFloat(float& fOut); + + // ------------------------------------------------------------------- + //! Parse a single int element + //! \param iOut Output integer + void ParseLV4MeshLong(unsigned int& iOut); + + // ------------------------------------------------------------------- + //! Skip the opening bracket at the beginning of a complex statement + bool SkipOpeningBracket(); + + // ------------------------------------------------------------------- + //! Skip everything to the next: '*' or '\0' + bool SkipToNextToken(); + + // ------------------------------------------------------------------- + //! Skip the current section until the token after the closing }. + //! This function handles embedded subsections correctly + bool SkipSection(); + + // ------------------------------------------------------------------- + //! Output a warning to the logger + //! \param szWarn Warn message + void LogWarning(const char* szWarn); + + // ------------------------------------------------------------------- + //! Output an error to the logger + //! \param szWarn Error message + void LogError(const char* szWarn); + +public: + + //! Pointer to current data + const char* m_szFile; + + //! background color to be passed to the viewer + //! QNAN if none was found + aiColor3D m_clrBackground; + + //! Base ambient color to be passed to all materials + //! QNAN if none was found + aiColor3D m_clrAmbient; + + //! List of all materials found in the file + std::vector m_vMaterials; + + //! List of all meshes found in the file + std::vector m_vMeshes; + + //! Current line in the file + unsigned int iLineNumber; +}; + + +};}; + +#endif // !! include guard diff --git a/code/Assimp.cpp b/code/Assimp.cpp index e0abd0d2f..a5cc75d2e 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -1,22 +1,77 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Implementation of the Plain-C API */ #include #include "../include/assimp.h" #include "../include/assimp.hpp" +#include "../include/aiassert.h" +using namespace Assimp; + +#if (defined AI_C_THREADSAFE) +# include +# include +#endif + /** Stores the importer objects for all active import processes */ typedef std::map< const aiScene*, Assimp::Importer* > ImporterMap; + /** Local storage of all active import processes */ static ImporterMap gActiveImports; /** Error message of the last failed import process */ static std::string gLastErrorString; +#if (defined AI_C_THREADSAFE) +/** Global mutex to manage the access to the importer map */ +static boost::mutex gMutex; +#endif // ------------------------------------------------------------------------------------------------ // Reads the given file and returns its content. const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) { + ai_assert(NULL != pFile); + // create an Importer for this file Assimp::Importer* imp = new Assimp::Importer; // and have it read the file @@ -25,6 +80,9 @@ const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) // if succeeded, place it in the collection of active processes if( scene) { +#if (defined AI_C_THREADSAFE) + boost::mutex::scoped_lock lock(gMutex); +#endif gActiveImports[scene] = imp; } else @@ -42,6 +100,13 @@ const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) // Releases all resources associated with the given import process. void aiReleaseImport( const aiScene* pScene) { + if (!pScene)return; + + // lock the mutex +#if (defined AI_C_THREADSAFE) + boost::mutex::scoped_lock lock(gMutex); +#endif + // find the importer associated with this data ImporterMap::iterator it = gActiveImports.find( pScene); // it should be there... else the user is playing fools with us @@ -59,3 +124,52 @@ const char* aiGetErrorString() { return gLastErrorString.c_str(); } +// ------------------------------------------------------------------------------------------------ +// Returns the error text of the last failed import process. +int aiIsExtensionSupported(const char* szExtension) +{ + ai_assert(NULL != szExtension); + + // lock the mutex +#if (defined AI_C_THREADSAFE) + boost::mutex::scoped_lock lock(gMutex); +#endif + + if (!gActiveImports.empty()) + { + return (int)((*(gActiveImports.begin())).second->IsExtensionSupported( + std::string ( szExtension ))); + } + // need to create a temporary Importer instance. + // TODO: Find a better solution ... + Assimp::Importer* pcTemp = new Assimp::Importer(); + int i = (int)pcTemp->IsExtensionSupported(std::string ( szExtension )); + delete pcTemp; + return i; +} +// ------------------------------------------------------------------------------------------------ +// Get a list of all file extensions supported by ASSIMP +void aiGetExtensionList(aiString* szOut) +{ + ai_assert(NULL != szOut); + + // lock the mutex +#if (defined AI_C_THREADSAFE) + boost::mutex::scoped_lock lock(gMutex); +#endif + + std::string szTemp; + if (!gActiveImports.empty()) + { + (*(gActiveImports.begin())).second->GetExtensionList(szTemp); + szOut->Set ( szTemp ); + return; + } + // need to create a temporary Importer instance. + // TODO: Find a better solution ... + Assimp::Importer* pcTemp = new Assimp::Importer(); + pcTemp->GetExtensionList(szTemp); + szOut->Set ( szTemp ); + delete pcTemp; +} + diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 5de86c599..61d0380cc 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -1,5 +1,47 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the few default functions of the base importer class */ #include "BaseImporter.h" +#include "DefaultLogger.h" #include "../include/aiScene.h" #include "aiAssert.h" using namespace Assimp; @@ -33,6 +75,9 @@ aiScene* BaseImporter::ReadFile( const std::string& pFile, IOSystem* pIOHandler) { // extract error description mErrorText = exception->GetErrorText(); + + DefaultLogger::get()->error(mErrorText); + delete exception; // and kill the partially imported data diff --git a/code/BaseImporter.h b/code/BaseImporter.h index ad6a2c8b0..32ab5b22b 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definition of the base class for all importer worker classes. */ #ifndef AI_BASEIMPORTER_H_INC #define AI_BASEIMPORTER_H_INC @@ -22,8 +62,10 @@ public: mErrorText = pErrorText; } + // ------------------------------------------------------------------- /** Returns the error text provided when throwing the exception */ - const std::string& GetErrorText() const { return mErrorText; } + inline const std::string& GetErrorText() const + { return mErrorText; } private: std::string mErrorText; @@ -36,15 +78,16 @@ private: * The interface defines two functions: CanRead() is used to check if the * importer can handle the format of the given file. If an implementation of * this function returns true, the importer then calls ReadFile() which - * imports the given file. ReadFile is not overridable, it just calls InternReadFile() - * and catches any ImportErrorException that might occur. + * imports the given file. ReadFile is not overridable, it just calls + * InternReadFile() and catches any ImportErrorException that might occur. */ class BaseImporter { friend class Importer; protected: - /** Constructor to be privately used by Importer */ + + /** Constructor to be privately used by #Importer */ BaseImporter(); /** Destructor, private as well */ @@ -56,46 +99,73 @@ public: * @param pFile Path and file name of the file to be examined. * @param pIOHandler The IO handler to use for accessing any file. * @return true if the class can read this file, false if not. + * + * @note Sometimes ASSIMP uses this method to determine whether a + * a given file extension is generally supported. In this case the + * file extension is passed in the pFile parameter, pIOHandler is NULL */ - virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const = 0; + virtual bool CanRead( const std::string& pFile, + IOSystem* pIOHandler) const = 0; + // ------------------------------------------------------------------- /** Imports the given file and returns the imported data. - * If the import succeeds, ownership of the data is transferred to the caller. - * If the import failes, NULL is returned. The function takes care that any - * partially constructed data is destroyed beforehand. + * If the import succeeds, ownership of the data is transferred to + * the caller. If the import failes, NULL is returned. The function + * takes care that any partially constructed data is destroyed + * beforehand. * * @param pFile Path of the file to be imported. * @param pIOHandler IO-Handler used to open this and possible other files. - * @return The imported data or NULL if failed. If it failed a human-readable - * error description can be retrieved by calling GetErrorText() + * @return The imported data or NULL if failed. If it failed a + * human-readable error description can be retrieved by calling + * GetErrorText() * - * @note This function is not intended to be overridden. Implement InternReadFile() - * to do the import. If an exception is thrown somewhere in InternReadFile(), - * this function will catch it and transform it into a suitable response to the caller. + * @note This function is not intended to be overridden. Implement + * InternReadFile() to do the import. If an exception is thrown somewhere + * in InternReadFile(), this function will catch it and transform it into + * a suitable response to the caller. */ aiScene* ReadFile( const std::string& pFile, IOSystem* pIOHandler); + // ------------------------------------------------------------------- /** Returns the error description of the last error that occured. - * @return A description of the last error that occured. An empty string if no error. + * @return A description of the last error that occured. An empty + * string if there was no error. */ - const std::string& GetErrorText() const { return mErrorText; } + inline const std::string& GetErrorText() const + { return mErrorText; } protected: + // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. The function is - * expected to throw an ImportErrorException if there is an error. If it - * terminates normally, the data in aiScene is expected to be correct. - * Override this function to implement the actual importing. + /** Called by Importer::GetExtensionList() for each loaded importer. + * Importer implementations should append all file extensions + * which they supported to the passed string. + * Example: "*.blabb;*.quak;*.gug;*.foo" (no comma after the last!) + * @param append Output string + */ + virtual void GetExtensionList(std::string& append) = 0; + + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. The + * function is expected to throw an ImportErrorException if there is + * an error. If it terminates normally, the data in aiScene is + * expected to be correct. Override this function to implement the + * actual importing. * * @param pFile Path of the file to be imported. * @param pScene The scene object to hold the imported data. + * NULL is not a valid parameter. * @param pIOHandler The IO handler to use for any file access. + * NULL is not a valid parameter. */ - virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) = 0; + virtual void InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) = 0; protected: + /** Error description in case there was one. */ std::string mErrorText; }; diff --git a/code/BaseProcess.h b/code/BaseProcess.h index f9a0bba93..8254d971f 100644 --- a/code/BaseProcess.h +++ b/code/BaseProcess.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Base class of all import post processing steps */ #ifndef AI_BASEPROCESS_H_INC #define AI_BASEPROCESS_H_INC diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index 08773f8f9..874c2dfcf 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -1,5 +1,46 @@ -/** @file Implementation of the post processing step to calculate tangents and bitangents - * for all imported meshes +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the post processing step to calculate + * tangents and bitangents for all imported meshes */ #include diff --git a/code/CalcTangentsProcess.h b/code/CalcTangentsProcess.h index 295e07137..97e61b017 100644 --- a/code/CalcTangentsProcess.h +++ b/code/CalcTangentsProcess.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + /** @file Defines a post processing step to calculate tangents and bitangents on all imported meshes.*/ #ifndef AI_CALCTANGENTSPROCESS_H_INC #define AI_CALCTANGENTSPROCESS_H_INC diff --git a/code/ConvertToLHProcess.h b/code/ConvertToLHProcess.h index 428779f43..5647f1e92 100644 --- a/code/ConvertToLHProcess.h +++ b/code/ConvertToLHProcess.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines a post processing step to convert all data to a left-handed coordinate system.*/ #ifndef AI_CONVERTTOLHPROCESS_H_INC #define AI_CONVERTTOLHPROCESS_H_INC diff --git a/code/DefaultIOStream.cpp b/code/DefaultIOStream.cpp index 5e7955c31..4db42fb79 100644 --- a/code/DefaultIOStream.cpp +++ b/code/DefaultIOStream.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Default File I/O implementation for #Importer */ #include "DefaultIOStream.h" @@ -8,7 +48,6 @@ using namespace Assimp; -// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- DefaultIOStream::~DefaultIOStream() { @@ -17,8 +56,6 @@ DefaultIOStream::~DefaultIOStream() fclose(this->mFile); } } - -// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- size_t DefaultIOStream::Read(void* pvBuffer, size_t pSize, @@ -29,9 +66,6 @@ size_t DefaultIOStream::Read(void* pvBuffer, return fread(pvBuffer, pSize, pCount, this->mFile); } - - -// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- size_t DefaultIOStream::Write(const void* pvBuffer, size_t pSize, @@ -42,9 +76,6 @@ size_t DefaultIOStream::Write(const void* pvBuffer, fseek(mFile, 0, SEEK_SET); return fwrite(pvBuffer, pSize, pCount, this->mFile); } - - -// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- aiReturn DefaultIOStream::Seek(size_t pOffset, aiOrigin pOrigin) @@ -56,9 +87,6 @@ aiReturn DefaultIOStream::Seek(size_t pOffset, (aiOrigin_END == pOrigin ? SEEK_END : SEEK_SET))) ? AI_SUCCESS : AI_FAILURE); } - - -// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- size_t DefaultIOStream::Tell() const { @@ -66,8 +94,6 @@ size_t DefaultIOStream::Tell() const return ftell(this->mFile); } - -// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- size_t DefaultIOStream::FileSize() const { diff --git a/code/DefaultIOStream.h b/code/DefaultIOStream.h index 6f486cea9..c2402e5f6 100644 --- a/code/DefaultIOStream.h +++ b/code/DefaultIOStream.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Default file I/O using fXXX()-family of functions */ #ifndef AI_DEFAULTIOSTREAM_H_INC #define AI_DEFAULTIOSTREAM_H_INC diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index a9d99e719..5f1de7f80 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Default implementation of IOSystem using the standard C file functions */ #include #include diff --git a/code/DefaultIOSystem.h b/code/DefaultIOSystem.h index c442fe809..60de8501d 100644 --- a/code/DefaultIOSystem.h +++ b/code/DefaultIOSystem.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Default implementation of IOSystem using the standard C file functions */ #ifndef AI_DEFAULTIOSYSTEM_H_INC #define AI_DEFAULTIOSYSTEM_H_INC diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index b2ac27d2c..ac082a7b3 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the post processing step to generate face * normals for all imported faces. */ diff --git a/code/GenFaceNormalsProcess.h b/code/GenFaceNormalsProcess.h index d1d29da1d..6fbec39bf 100644 --- a/code/GenFaceNormalsProcess.h +++ b/code/GenFaceNormalsProcess.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines a post processing step to compute face normals for all loaded faces*/ #ifndef AI_GENFACENORMALPROCESS_H_INC #define AI_GENFACENORMALPROCESS_H_INC diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index cc0a717b2..3bb8b17fd 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the post processing step to generate face * normals for all imported faces. */ diff --git a/code/GenVertexNormalsProcess.h b/code/GenVertexNormalsProcess.h index 85bd7fc9b..10a03d4be 100644 --- a/code/GenVertexNormalsProcess.h +++ b/code/GenVertexNormalsProcess.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines a post processing step to compute vertex normals for all loaded vertizes */ #ifndef AI_GENVERTEXNORMALPROCESS_H_INC #define AI_GENVERTEXNORMALPROCESS_H_INC diff --git a/code/Importer.cpp b/code/Importer.cpp index cbf84e6c7..b61d5679b 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the CPP-API class #Importer */ #include #include @@ -8,12 +49,35 @@ #include "BaseProcess.h" #include "DefaultIOStream.h" #include "DefaultIOSystem.h" -#include "XFileImporter.h" -#include "3DSLoader.h" -#include "MD3Loader.h" -#include "MD2Loader.h" -#include "PlyLoader.h" -#include "ObjFileImporter.h" + +#if (!defined AI_BUILD_NO_X_IMPORTER) +# include "XFileImporter.h" +#endif +#if (!defined AI_BUILD_NO_3DS_IMPORTER) +# include "3DSLoader.h" +#endif +#if (!defined AI_BUILD_NO_MD3_IMPORTER) +# include "MD3Loader.h" +#endif +#if (!defined AI_BUILD_NO_MD4_IMPORTER) +# include "MD4Loader.h" +#endif +#if (!defined AI_BUILD_NO_MDL_IMPORTER) +# include "MDLLoader.h" +#endif +#if (!defined AI_BUILD_NO_MD2_IMPORTER) +# include "MD2Loader.h" +#endif +#if (!defined AI_BUILD_NO_PLY_IMPORTER) +# include "PlyLoader.h" +#endif +#if (!defined AI_BUILD_NO_ASE_IMPORTER) +# include "ASELoader.h" +#endif +#if (!defined AI_BUILD_NO_OBJ_IMPORTER) +# include "ObjFileImporter.h" +#endif + #include "CalcTangentsProcess.h" #include "JoinVerticesProcess.h" #include "ConvertToLHProcess.h" @@ -32,25 +96,47 @@ Importer::Importer() : mScene(NULL), mErrorString("") { - // default IO handler + // allocate a default IO handler mIOHandler = new DefaultIOSystem; // add an instance of each worker class here +#if (!defined AI_BUILD_NO_X_IMPORTER) mImporter.push_back( new XFileImporter()); +#endif +#if (!defined AI_BUILD_NO_OBJ_IMPORTER) mImporter.push_back( new ObjFileImporter()); +#endif +#if (!defined AI_BUILD_NO_3DS_IMPORTER) mImporter.push_back( new Dot3DSImporter()); +#endif +#if (!defined AI_BUILD_NO_MD3_IMPORTER) mImporter.push_back( new MD3Importer()); +#endif +#if (!defined AI_BUILD_NO_MD2_IMPORTER) mImporter.push_back( new MD2Importer()); +#endif +#if (!defined AI_BUILD_NO_PLY_IMPORTER) mImporter.push_back( new PLYImporter()); +#endif +#if (!defined AI_BUILD_NO_MDL_IMPORTER) + mImporter.push_back( new MDLImporter()); +#endif +#if (!defined AI_BUILD_NO_MD4_IMPORTER) + mImporter.push_back( new MD4Importer()); +#endif +#if (!defined AI_BUILD_NO_ASE_IMPORTER) + mImporter.push_back( new ASEImporter()); +#endif // add an instance of each post processing step here in the order of sequence it is executed mPostProcessingSteps.push_back( new TriangulateProcess()); - mPostProcessingSteps.push_back( new SplitLargeMeshesProcess()); + mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle()); mPostProcessingSteps.push_back( new KillNormalsProcess()); mPostProcessingSteps.push_back( new GenFaceNormalsProcess()); mPostProcessingSteps.push_back( new GenVertexNormalsProcess()); mPostProcessingSteps.push_back( new CalcTangentsProcess()); mPostProcessingSteps.push_back( new JoinVerticesProcess()); + mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex()); mPostProcessingSteps.push_back( new ConvertToLHProcess()); } @@ -63,6 +149,7 @@ Importer::~Importer() for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) delete mPostProcessingSteps[a]; + // delete the assigned IO handler delete mIOHandler; // kill imported scene. Destructors should do that recursivly @@ -73,8 +160,17 @@ Importer::~Importer() // Supplies a custom IO handler to the importer to open and access files. void Importer::SetIOHandler( IOSystem* pIOHandler) { - delete mIOHandler; - mIOHandler = pIOHandler; + if (NULL == pIOHandler) + { + delete mIOHandler; + mIOHandler = new DefaultIOSystem(); + } + else if (mIOHandler != pIOHandler) + { + delete mIOHandler; + mIOHandler = pIOHandler; + } + return; } // ------------------------------------------------------------------------------------------------ @@ -128,9 +224,40 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags } // ------------------------------------------------------------------------------------------------ -// Empty and rpivate copy constructor +// Empty and private copy constructor Importer::Importer(const Importer &other) { // empty } +// ------------------------------------------------------------------------------------------------ +// Helper function to check whether an extension is supported by ASSIMP +bool Importer::IsExtensionSupported(const std::string& szExtension) +{ + for (std::vector::const_iterator + i = this->mImporter.begin(); + i != this->mImporter.end();++i) + { + // pass the file extension to the CanRead(..,NULL)-method + if ((*i)->CanRead(szExtension,NULL))return true; + } + return false; +} +// ------------------------------------------------------------------------------------------------ +// Helper function to build a list of all file extensions supported by ASSIMP +void Importer::GetExtensionList(std::string& szOut) +{ + unsigned int iNum = 0; + for (std::vector::const_iterator + i = this->mImporter.begin(); + i != this->mImporter.end();++i,++iNum) + { + // insert a comma as delimiter character + if (0 != iNum) + szOut.append(";"); + + (*i)->GetExtensionList(szOut); + } + return; +} + diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index 30f0b4c62..3d5e092dd 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the post processing step to join identical vertices * for all imported meshes */ diff --git a/code/JoinVerticesProcess.h b/code/JoinVerticesProcess.h index 2d44dddee..ca1a8e87b 100644 --- a/code/JoinVerticesProcess.h +++ b/code/JoinVerticesProcess.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines a post processing step to join identical vertices on all imported meshes.*/ #ifndef AI_JOINVERTICESPROCESS_H_INC #define AI_CALCTANGENTSPROCESS_H_INC diff --git a/code/KillNormalsProcess.cpp b/code/KillNormalsProcess.cpp index b924d8155..d28a5cdc6 100644 --- a/code/KillNormalsProcess.cpp +++ b/code/KillNormalsProcess.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Implementation of the post processing step tokill mesh normals */ #include "KillNormalsProcess.h" diff --git a/code/KillNormalsProcess.h b/code/KillNormalsProcess.h index 23ff24bde..83a97dba1 100644 --- a/code/KillNormalsProcess.h +++ b/code/KillNormalsProcess.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines a post processing step to kill all loaded normals */ #ifndef AI_KILLNORMALPROCESS_H_INC #define AI_KILLNORMALPROCESS_H_INC diff --git a/code/MD2FileData.h b/code/MD2FileData.h index b6f281688..9a8b8b615 100644 --- a/code/MD2FileData.h +++ b/code/MD2FileData.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines the helper data structures for importing MD2 files */ #ifndef AI_MD2FILEHELPER_H_INC #define AI_MD2FILEHELPER_H_INC diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index 634ace612..57d8a9974 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the MD2 importer class */ #include "MD2Loader.h" #include "MaterialSystem.h" @@ -150,11 +191,11 @@ void MD2Importer::InternReadFile( std::vector vTexCoords; std::vector vNormals; - vPositions.resize(this->m_pcHeader->numVertices,aiVector3D()); - vTexCoords.resize(this->m_pcHeader->numVertices,aiVector3D( + vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D()); + vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D( std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(),0.0f)); - vNormals.resize(this->m_pcHeader->numVertices,aiVector3D()); + vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D()); // not sure whether there are MD2 files without texture coordinates if (0 != this->m_pcHeader->numTexCoords && 0 != this->m_pcHeader->numSkins) @@ -198,32 +239,9 @@ void MD2Importer::InternReadFile( pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); } - // now read all vertices of the frame - for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numVertices;++i) - { - // read x,y, and z component of the vertex - - aiVector3D& vec = vPositions[i]; - - vec.x = (float)pcVerts[i].vertex[0] * pcFrame->scale[0]; - vec.x += pcFrame->translate[0]; - - // (flip z and y component) - vec.z = (float)pcVerts[i].vertex[1] * pcFrame->scale[1]; - vec.z += pcFrame->translate[1]; - - vec.y = (float)pcVerts[i].vertex[2] * pcFrame->scale[2]; - vec.y += pcFrame->translate[2]; - - // read the normal vector from the precalculated normal table - vNormals[i] = *((const aiVector3D*)(&g_avNormals[std::min( - int(pcVerts[i].lightNormalIndex), - int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); - - std::swap ( vNormals[i].y,vNormals[i].z ); - } // now read all triangles of the first frame, apply scaling and translation + unsigned int iCurrent = 0; if (0 != this->m_pcHeader->numTexCoords) { for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i) @@ -235,40 +253,47 @@ void MD2Importer::InternReadFile( // copy texture coordinates // check whether they are different from the previous value at this index. // In this case, create a full separate set of vertices/normals/texcoords - for (unsigned int c = 0; c < 3;++c) + for (unsigned int c = 0; c < 3;++c,++iCurrent) { + pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; + // validate vertex indices if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices) pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1; // copy face indices - pScene->mMeshes[0]->mFaces[i].mIndices[c] = (unsigned int)pcTriangles[i].vertexIndices[c]; + unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; + + // read x,y, and z component of the vertex + aiVector3D& vec = vPositions[iCurrent]; + + vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; + vec.x += pcFrame->translate[0]; + + // (flip z and y component) + vec.z = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1]; + vec.z += pcFrame->translate[1]; + + vec.y = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2]; + vec.y += pcFrame->translate[2]; + + // read the normal vector from the precalculated normal table + vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( + int(pcVerts[iIndex].lightNormalIndex), + int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); + + std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z ); // validate texture coordinates - if (pcTriangles[i].textureIndices[c] >= this->m_pcHeader->numTexCoords) - pcTriangles[i].textureIndices[c] = this->m_pcHeader->numTexCoords-1; + if (pcTriangles[iIndex].textureIndices[c] >= this->m_pcHeader->numTexCoords) + pcTriangles[iIndex].textureIndices[c] = this->m_pcHeader->numTexCoords-1; - aiVector3D* pcOut = &vTexCoords[pScene->mMeshes[0]->mFaces[i].mIndices[c]]; + aiVector3D* pcOut = &vTexCoords[iCurrent]; float u,v; u = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth; v = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight; - - if ( is_not_qnan ( pcOut->x ) && (pcOut->x != u || pcOut->y != v)) - { - // generate a separate vertex/index set - vTexCoords.push_back(aiVector3D(u,v,0.0f)); - vPositions.push_back(vPositions[pcTriangles[i].vertexIndices[c]]); - vNormals.push_back(vPositions[pcTriangles[i].vertexIndices[c]]); - unsigned int iPos = vTexCoords.size()-1; - - pScene->mMeshes[0]->mFaces[i].mIndices[c] = iPos; - } - else - { - pcOut->x = u; - pcOut->y = v; - - } + pcOut->x = u; + pcOut->y = v; } } } @@ -280,18 +305,44 @@ void MD2Importer::InternReadFile( pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3]; pScene->mMeshes[0]->mFaces[i].mNumIndices = 3; - // validate vertex indices - if (pcTriangles[i].vertexIndices[0] >= this->m_pcHeader->numVertices) - pcTriangles[i].vertexIndices[0] = this->m_pcHeader->numVertices-1; - if (pcTriangles[i].vertexIndices[1] >= this->m_pcHeader->numVertices) - pcTriangles[i].vertexIndices[1] = this->m_pcHeader->numVertices-1; - if (pcTriangles[i].vertexIndices[2] >= this->m_pcHeader->numVertices) - pcTriangles[i].vertexIndices[2] = this->m_pcHeader->numVertices-1; + // copy texture coordinates + // check whether they are different from the previous value at this index. + // In this case, create a full separate set of vertices/normals/texcoords + for (unsigned int c = 0; c < 3;++c,++iCurrent) + { + pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; - // copy face indices - pScene->mMeshes[0]->mFaces[i].mIndices[0] = (unsigned int)pcTriangles[i].vertexIndices[0]; - pScene->mMeshes[0]->mFaces[i].mIndices[1] = (unsigned int)pcTriangles[i].vertexIndices[1]; - pScene->mMeshes[0]->mFaces[i].mIndices[2] = (unsigned int)pcTriangles[i].vertexIndices[2]; + // validate vertex indices + if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices) + pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1; + + // copy face indices + unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; + + // read x,y, and z component of the vertex + aiVector3D& vec = vPositions[iCurrent]; + + vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; + vec.x += pcFrame->translate[0]; + + // (flip z and y component) + vec.z = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1]; + vec.z += pcFrame->translate[1]; + + vec.y = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2]; + vec.y += pcFrame->translate[2]; + + // read the normal vector from the precalculated normal table + vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( + int(pcVerts[iIndex].lightNormalIndex), + int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); + + std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z ); + + aiVector3D* pcOut = &vTexCoords[iCurrent]; + pcOut->x = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth; + pcOut->y = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight; + } } } @@ -302,9 +353,16 @@ void MD2Importer::InternReadFile( pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()]; // memcpy() the data to the c-syle arrays - memcpy(pScene->mMeshes[0]->mVertices, &vPositions[0], vPositions.size() * sizeof(aiVector3D)); - memcpy(pScene->mMeshes[0]->mNormals, &vNormals[0], vPositions.size() * sizeof(aiVector3D)); - memcpy(pScene->mMeshes[0]->mTextureCoords[0], &vTexCoords[0], vPositions.size() * sizeof(aiVector3D)); + memcpy(pScene->mMeshes[0]->mVertices, &vPositions[0], + vPositions.size() * sizeof(aiVector3D)); + memcpy(pScene->mMeshes[0]->mNormals, &vNormals[0], + vPositions.size() * sizeof(aiVector3D)); + + if (0 != this->m_pcHeader->numTexCoords) + { + memcpy(pScene->mMeshes[0]->mTextureCoords[0], &vTexCoords[0], + vPositions.size() * sizeof(aiVector3D)); + } return; } \ No newline at end of file diff --git a/code/MD2Loader.h b/code/MD2Loader.h index 5b7f6d619..e70bc7e3b 100644 --- a/code/MD2Loader.h +++ b/code/MD2Loader.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definition of the .MD2 importer class. */ #ifndef AI_MD2LOADER_H_INCLUDED #define AI_MD2LOADER_H_INCLUDED @@ -10,47 +50,57 @@ struct aiNode; namespace Assimp { - class MaterialHelper; +class MaterialHelper; - using namespace MD2; +using namespace MD2; - // --------------------------------------------------------------------------- - /** Used to load MD2 files - */ - class MD2Importer : public BaseImporter +// --------------------------------------------------------------------------- +/** Used to load MD2 files +*/ +class MD2Importer : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + MD2Importer(); + + /** Destructor, private as well */ + ~MD2Importer(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) { - friend class Importer; + append.append("*.md2"); + } - protected: - /** Constructor to be privately used by Importer */ - MD2Importer(); + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); - /** Destructor, private as well */ - ~MD2Importer(); +protected: - public: + /** Header of the MD2 file */ + const MD2::Header* m_pcHeader; - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; - - protected: - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - protected: - - /** Header of the MD2 file */ - const MD2::Header* m_pcHeader; - - /** Buffer to hold the loaded file */ - const unsigned char* mBuffer; - }; + /** Buffer to hold the loaded file */ + const unsigned char* mBuffer; +}; } // end of namespace Assimp diff --git a/code/MD2NormalTable.h b/code/MD2NormalTable.h index 0126055a6..12440707f 100644 --- a/code/MD2NormalTable.h +++ b/code/MD2NormalTable.h @@ -1,11 +1,55 @@ /* - * Slightly modified version of the anorms.h header file released by - * ID software with the Quake 2 source code. +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/* + * @file Slightly modified version of the anorms.h header file + * released by ID software with the Quake 2 source code. * * Table of normals used by MD2 models */ -float g_avNormals[][3] = { +#ifndef AI_MDL_NORMALTABLE_H_INC +#define AI_MDL_NORMALTABLE_H_INC + + +float g_avNormals[162][3] = { { -0.525731f, 0.000000f, 0.850651f }, { -0.442863f, 0.238856f, 0.864188f }, { -0.295242f, 0.000000f, 0.955423f }, @@ -169,3 +213,5 @@ float g_avNormals[][3] = { { -0.587785f, -0.425325f, -0.688191f }, { -0.688191f, -0.587785f, -0.425325f } }; + +#endif // !! include guard diff --git a/code/MD3FileData.h b/code/MD3FileData.h index 038d382b4..21f9b6ee5 100644 --- a/code/MD3FileData.h +++ b/code/MD3FileData.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Defines the helper data structures for importing MD3 files */ #ifndef AI_MD3FILEHELPER_H_INC #define AI_MD3FILEHELPER_H_INC @@ -43,51 +83,51 @@ namespace MD3 #define AI_MD3_XYZ_SCALE (1.0f/64.0f) // --------------------------------------------------------------------------- -/** \brief Data structure for the MD3 main header +/** \brief Data structure for the MD3 main header */ // --------------------------------------------------------------------------- struct Header { - // magic number + //! magic number int32_t IDENT; - // file format version + //! file format version int32_t VERSION; - // original name in .pak archive + //! original name in .pak archive unsigned char NAME[ AI_MD3_MAXQPATH ]; - // unknown + //! unknown int32_t FLAGS; - // number of frames in the file + //! number of frames in the file int32_t NUM_FRAMES; - // number of tags in the file + //! number of tags in the file int32_t NUM_TAGS; - // number of surfaces in the file + //! number of surfaces in the file int32_t NUM_SURFACES; - // number of skins in the file + //! number of skins in the file int32_t NUM_SKINS; - // offset of the first frame + //! offset of the first frame int32_t OFS_FRAMES; - // offset of the first tag + //! offset of the first tag int32_t OFS_TAGS; - // offset of the first surface + //! offset of the first surface int32_t OFS_SURFACES; - // end of file + //! end of file int32_t OFS_EOF; } PACK_STRUCT; // --------------------------------------------------------------------------- -/** \brief Data structure for the frame header +/** \brief Data structure for the frame header */ // --------------------------------------------------------------------------- struct Frame @@ -97,7 +137,7 @@ struct Frame // --------------------------------------------------------------------------- -/** \brief Data structure for the tag header +/** \brief Data structure for the tag header */ // --------------------------------------------------------------------------- struct Tag @@ -107,95 +147,95 @@ struct Tag // --------------------------------------------------------------------------- -/** \brief Data structure for the surface header +/** \brief Data structure for the surface header */ // --------------------------------------------------------------------------- struct Surface { - // magic number + //! magic number int32_t IDENT; - // original name of the surface + //! original name of the surface unsigned char NAME[ AI_MD3_MAXQPATH ]; - // unknown + //! unknown int32_t FLAGS; - // number of frames in the surface + //! number of frames in the surface int32_t NUM_FRAMES; - // number of shaders in the surface + //! number of shaders in the surface int32_t NUM_SHADER; - // number of vertices in the surface + //! number of vertices in the surface int32_t NUM_VERTICES; - // number of triangles in the surface + //! number of triangles in the surface int32_t NUM_TRIANGLES; - // offset to the triangle data + //! offset to the triangle data int32_t OFS_TRIANGLES; - // offset to the shader data + //! offset to the shader data int32_t OFS_SHADERS; - // offset to the texture coordinate data + //! offset to the texture coordinate data int32_t OFS_ST; - // offset to the vertex/normal data + //! offset to the vertex/normal data int32_t OFS_XYZNORMAL; - // offset to the end of the Surface object + //! offset to the end of the Surface object int32_t OFS_END; } PACK_STRUCT; // --------------------------------------------------------------------------- -/** \brief Data structure for a shader +/** \brief Data structure for a shader */ // --------------------------------------------------------------------------- struct Shader { - // filename of the shader + //! filename of the shader unsigned char NAME[ AI_MD3_MAXQPATH ]; - // index of the shader + //! index of the shader int32_t SHADER_INDEX; } PACK_STRUCT; // --------------------------------------------------------------------------- -/** \brief Data structure for a triangle +/** \brief Data structure for a triangle */ // --------------------------------------------------------------------------- struct Triangle { - // triangle indices + //! triangle indices int32_t INDEXES[3]; } PACK_STRUCT; // --------------------------------------------------------------------------- -/** \brief Data structure for an UV coord +/** \brief Data structure for an UV coord */ // --------------------------------------------------------------------------- struct TexCoord { - // UV coordinates + //! UV coordinates float U,V; } PACK_STRUCT; // --------------------------------------------------------------------------- -/** \brief Data structure for a vertex +/** \brief Data structure for a vertex */ // --------------------------------------------------------------------------- struct Vertex { - // X/Y/Z coordinates + //! X/Y/Z coordinates int16_t X,Y,Z; - // encoded normal vector + //! encoded normal vector int16_t NORMAL; } PACK_STRUCT; diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index d8553bd2f..e6197ac7a 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the MD3 importer class */ #include "MD3Loader.h" #include "MaterialSystem.h" @@ -142,7 +183,7 @@ void MD3Importer::InternReadFile( pScene->mMeshes[iNum] = new aiMesh(); aiMesh* pcMesh = pScene->mMeshes[iNum]; - pcMesh->mNumVertices = pcSurfaces->NUM_VERTICES; + pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3; pcMesh->mNumBones = 0; pcMesh->mColors[0] = pcMesh->mColors[1] = pcMesh->mColors[2] = pcMesh->mColors[3] = NULL; pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES; @@ -153,35 +194,32 @@ void MD3Importer::InternReadFile( pcMesh->mTextureCoords[1] = pcMesh->mTextureCoords[2] = pcMesh->mTextureCoords[3] = NULL; pcMesh->mNumUVComponents[0] = 2; - // fill in all vertices and normals - // fill in all texture coordinates - for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_VERTICES;++i) - { - pcMesh->mVertices[i].x = pcVertices->X; - pcMesh->mVertices[i].y = pcVertices->Y; - pcMesh->mVertices[i].z = -1.0f*pcVertices->Z; - - // convert the normal vector to uncompressed float3 format - LatLngNormalToVec3(pcVertices->NORMAL,(float*)&pcMesh->mNormals[i]); - - // read texture coordinates - pcMesh->mTextureCoords[0][i].x = pcUVs->U; - pcMesh->mTextureCoords[0][i].y = 1.0f - pcUVs->V; - - pcVertices++; - pcUVs++; - } - // fill in all triangles + unsigned int iCurrent = 0; for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) { pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; - pcMesh->mFaces[i].mIndices[0] = pcTriangles->INDEXES[0]; - pcMesh->mFaces[i].mIndices[1] = pcTriangles->INDEXES[1]; - pcMesh->mFaces[i].mIndices[2] = pcTriangles->INDEXES[2]; + for (unsigned int c = 0; c < 3;++c,++iCurrent) + { + pcMesh->mFaces[i].mIndices[c] = iCurrent; + // read vertices + pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X; + pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y; + pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z * -1.0f; + + // convert the normal vector to uncompressed float3 format + LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL, + (float*)&pcMesh->mNormals[iCurrent]); + + std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z ); + + // read texture coordinates + pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; + pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V; + } pcTriangles++; } @@ -250,12 +288,15 @@ void MD3Importer::InternReadFile( { MaterialHelper* pcHelper = new MaterialHelper(); - aiString szString; - const size_t iLen = strlen(szEndDir2); - memcpy(szString.data,szEndDir2,iLen+1); - szString.length = iLen-1; + if (szEndDir2) + { + aiString szString; + const size_t iLen = strlen(szEndDir2); + memcpy(szString.data,szEndDir2,iLen+1); + szString.length = iLen-1; - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } int iMode = (int)aiShadingMode_Gouraud; pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); diff --git a/code/MD3Loader.h b/code/MD3Loader.h index 2b669bae7..94f008c09 100644 --- a/code/MD3Loader.h +++ b/code/MD3Loader.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definition of the .MD3 importer class. */ #ifndef AI_MD3LOADER_H_INCLUDED #define AI_MD3LOADER_H_INCLUDED @@ -13,46 +53,56 @@ struct aiNode; #include "MD3FileData.h" namespace Assimp { - class MaterialHelper; +class MaterialHelper; - using namespace MD3; +using namespace MD3; - // --------------------------------------------------------------------------- - /** Used to load MD3 files - */ - class MD3Importer : public BaseImporter +// --------------------------------------------------------------------------- +/** Used to load MD3 files +*/ +class MD3Importer : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + MD3Importer(); + + /** Destructor, private as well */ + ~MD3Importer(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) { - friend class Importer; + append.append("*.md3"); + } - protected: - /** Constructor to be privately used by Importer */ - MD3Importer(); + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); - /** Destructor, private as well */ - ~MD3Importer(); +protected: - public: + /** Header of the MD3 file */ + const MD3::Header* m_pcHeader; - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; - - protected: - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - protected: - - /** Header of the MD3 file */ - const MD3::Header* m_pcHeader; - - /** Buffer to hold the loaded file */ - const unsigned char* mBuffer; + /** Buffer to hold the loaded file */ + const unsigned char* mBuffer; }; } // end of namespace Assimp diff --git a/code/MD4FileData.h b/code/MD4FileData.h index e69de29bb..5a6064aa5 100644 --- a/code/MD4FileData.h +++ b/code/MD4FileData.h @@ -0,0 +1,218 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Defines the helper data structures for importing MD4 files */ +#ifndef AI_MD4FILEHELPER_H_INC +#define AI_MD4FILEHELPER_H_INC + +#include +#include +#include + +#include "../include/aiTypes.h" +#include "../include/aiMesh.h" +#include "../include/aiAnim.h" + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack(push,1) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error Compiler not supported +#endif + + +namespace Assimp +{ +// http://gongo.quakedev.com/md4.html +namespace MD4 +{ + +#define AI_MD4_MAGIC_NUMBER_BE 'IDP4' +#define AI_MD4_MAGIC_NUMBER_LE '4PDI' + +// common limitations +#define AI_MD4_VERSION 4 +#define AI_MD4_MAXQPATH 64 +#define AI_MD4_MAX_FRAMES 2028 +#define AI_MD4_MAX_SURFACES 32 +#define AI_MD4_MAX_BONES 256 +#define AI_MD4_MAX_VERTS 4096 +#define AI_MD4_MAX_TRIANGLES 8192 + +// --------------------------------------------------------------------------- +/** \brief Data structure for the MD4 main header + */ +// --------------------------------------------------------------------------- +struct Header +{ + //! magic number + int32_t magic; + + //! file format version + int32_t version; + + //! original name in .pak archive + unsigned char name[ AI_MD4_MAXQPATH ]; + + //! number of frames in the file + int32_t NUM_FRAMES; + + //! number of bones in the file + int32_t NUM_BONES; + + //! number of surfaces in the file + int32_t NUM_SURFACES; + + //! offset of the first frame + int32_t OFS_FRAMES; + + //! offset of the first bone + int32_t OFS_BONES; + + //! offset of the first surface + int32_t OFS_SURFACES; + + //! end of file + int32_t OFS_EOF; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \brief Stores the local transformation matrix of a bone + */ +// --------------------------------------------------------------------------- +struct BoneFrame +{ + float matrix[3][4]; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \brief Stores the name / parent index / flag of a node + */ +// --------------------------------------------------------------------------- +struct BoneName +{ + char name[32] ; + int parent ; + int flags ; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \brief Data structure for a surface in a MD4 file + */ +// --------------------------------------------------------------------------- +struct Surface +{ + int32_t ident; + char name[64]; + char shader[64]; + int32_t shaderIndex; + int32_t lodBias; + int32_t minLod; + int32_t ofsHeader; + int32_t numVerts; + int32_t ofsVerts; + int32_t numTris; + int32_t ofsTris; + int32_t numBoneRefs; + int32_t ofsBoneRefs; + int32_t ofsCollapseMap; + int32_t ofsEnd; +} PACK_STRUCT; + + +// --------------------------------------------------------------------------- +/** \brief Data structure for a MD4 vertex' weight + */ +// --------------------------------------------------------------------------- +struct Weight +{ + int32_t boneIndex; + float boneWeight; + float offset[3]; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \brief Data structure for a vertex in a MD4 file + */ +// --------------------------------------------------------------------------- +struct Vertex +{ + float vertex[3]; + float normal[3]; + float texCoords[2]; + int32_t numWeights; + Weight weights[1]; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \brief Data structure for a triangle in a MD4 file + */ +// --------------------------------------------------------------------------- +struct Triangle +{ + int32_t indexes[3]; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \brief Data structure for a MD4 frame + */ +// --------------------------------------------------------------------------- +struct Frame +{ + float bounds[3][2]; + float localOrigin[3]; + float radius; + BoneFrame bones[1]; +} PACK_STRUCT; + + +// reset packing to the original value +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop ) +#endif +#undef PACK_STRUCT + + +}; +}; + +#endif // !! AI_MD4FILEHELPER_H_INC \ No newline at end of file diff --git a/code/MD4Loader.cpp b/code/MD4Loader.cpp new file mode 100644 index 000000000..250d08c65 --- /dev/null +++ b/code/MD4Loader.cpp @@ -0,0 +1,115 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the MD4 importer class */ +#include "MD4Loader.h" +#include "MaterialSystem.h" + +#include "../include/IOStream.h" +#include "../include/IOSystem.h" +#include "../include/aiMesh.h" +#include "../include/aiScene.h" +#include "../include/aiAssert.h" + +#include + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +MD4Importer::MD4Importer() +{ +} +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +MD4Importer::~MD4Importer() +{ +} +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool MD4Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler) const +{ + // simple check of file extension is enough for the moment + std::string::size_type pos = pFile.find_last_of('.'); + // no file extension - can't read + if( pos == std::string::npos) + return false; + std::string extension = pFile.substr( pos); + + if (extension.length() < 4)return false; + if (extension[0] != '.')return false; + + // not brilliant but working ;-) + if( extension == ".md4" || extension == ".MD4" || + extension == ".mD4" || extension == ".Md4") + { + return true; + } +#if (!defined AI_MD4_DONT_SUPPORT_RAVENSOFT_MDR) + if (extension[1] != 'm' && extension[1] != 'M')return false; + if (extension[2] != 'd' && extension[2] != 'D')return false; + if (extension[3] != 'r' && extension[3] != 'R')return false; +#endif + + return true; +} +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void MD4Importer::InternReadFile( + const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) +{ + boost::scoped_ptr file( pIOHandler->Open( pFile)); + + // Check whether we can read from the file + if( file.get() == NULL) + { + throw new ImportErrorException( "Failed to open md4/mdr file " + pFile + "."); + } + + // check whether the md4 file is large enough to contain + // at least the file header + size_t fileSize = file->FileSize(); + if( fileSize < sizeof(MD4::Header)) + { + throw new ImportErrorException( ".mdd File is too small."); + } + return; +} \ No newline at end of file diff --git a/code/MD4Loader.h b/code/MD4Loader.h index 5ae65b62d..147c38fc8 100644 --- a/code/MD4Loader.h +++ b/code/MD4Loader.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definition of the .MD4 importer class. */ #ifndef AI_MD4LOADER_H_INCLUDED #define AI_MD4LOADER_H_INCLUDED @@ -10,47 +50,57 @@ struct aiNode; namespace Assimp { - class MaterialHelper; +class MaterialHelper; - using namespace MD4; +using namespace MD4; - // --------------------------------------------------------------------------- - /** Used to load MD4 files - */ - class MD4Importer : public BaseImporter +// --------------------------------------------------------------------------- +/** Used to load MD4 files +*/ +class MD4Importer : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + MD4Importer(); + + /** Destructor, private as well */ + ~MD4Importer(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) { - friend class Importer; + append.append("*.md4;*.mdr"); + } - protected: - /** Constructor to be privately used by Importer */ - MD4Importer(); + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); - /** Destructor, private as well */ - ~MD4Importer(); +protected: - public: + /** Header of the MD4 file */ + const MD4::Header* m_pcHeader; - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; - - protected: - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - protected: - - /** Header of the MD4 file */ - const MD4::Header* m_pcHeader; - - /** Buffer to hold the loaded file */ - const unsigned char* mBuffer; - }; + /** Buffer to hold the loaded file */ + const unsigned char* mBuffer; +}; } // end of namespace Assimp diff --git a/code/MD5Loader.h b/code/MD5Loader.h index cfa8b9f5b..83244d1b3 100644 --- a/code/MD5Loader.h +++ b/code/MD5Loader.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + /** @file Definition of the .MD5 importer class. */ #ifndef AI_MD5LOADER_H_INCLUDED #define AI_MD5LOADER_H_INCLUDED @@ -10,47 +51,57 @@ struct aiNode; namespace Assimp { - class MaterialHelper; +class MaterialHelper; - using namespace MD5; +using namespace MD5; - // --------------------------------------------------------------------------- - /** Used to load MD5 files - */ - class MD5Importer : public BaseImporter +// --------------------------------------------------------------------------- +/** Used to load MD5 files +*/ +class MD5Importer : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + MD5Importer(); + + /** Destructor, private as well */ + ~MD5Importer(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) { - friend class Importer; + append.append("*.md5"); + } - protected: - /** Constructor to be privately used by Importer */ - MD5Importer(); + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); - /** Destructor, private as well */ - ~MD5Importer(); +protected: - public: + /** Header of the MD5 file */ + const MD5::Header* m_pcHeader; - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; - - protected: - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - protected: - - /** Header of the MD5 file */ - const MD5::Header* m_pcHeader; - - /** Buffer to hold the loaded file */ - const unsigned char* mBuffer; - }; + /** Buffer to hold the loaded file */ + const unsigned char* mBuffer; +}; } // end of namespace Assimp diff --git a/code/MDLDefaultColorMap.h b/code/MDLDefaultColorMap.h new file mode 100644 index 000000000..76762edc8 --- /dev/null +++ b/code/MDLDefaultColorMap.h @@ -0,0 +1,118 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + +/** @file Defines the default color map used for Quake 1 model textures + * + * The lib tries to load colormap.lmp from the model's directory. + * This table is only used when required. + */ + +#ifndef AI_MDL_DEFAULTLMP_H_INC +#define AI_MDL_DEFAULTLMP_H_INC + +const unsigned char g_aclrDefaultColorMap[256][3] = { +{ 0, 0, 0}, { 15, 15, 15}, { 31, 31, 31}, { 47, 47, 47}, +{ 63, 63, 63}, { 75, 75, 75}, { 91, 91, 91}, {107, 107, 107}, +{123, 123, 123}, {139, 139, 139}, {155, 155, 155}, {171, 171, 171}, +{187, 187, 187}, {203, 203, 203}, {219, 219, 219}, {235, 235, 235}, +{ 15, 11, 7}, { 23, 15, 11}, { 31, 23, 11}, { 39, 27, 15}, +{ 47, 35, 19}, { 55, 43, 23}, { 63, 47, 23}, { 75, 55, 27}, +{ 83, 59, 27}, { 91, 67, 31}, { 99, 75, 31}, {107, 83, 31}, +{115, 87, 31}, {123, 95, 35}, {131, 103, 35}, {143, 111, 35}, +{ 11, 11, 15}, { 19, 19, 27}, { 27, 27, 39}, { 39, 39, 51}, +{ 47, 47, 63}, { 55, 55, 75}, { 63, 63, 87}, { 71, 71, 103}, +{ 79, 79, 115}, { 91, 91, 127}, { 99, 99, 139}, {107, 107, 151}, +{115, 115, 163}, {123, 123, 175}, {131, 131, 187}, {139, 139, 203}, +{ 0, 0, 0}, { 7, 7, 0}, { 11, 11, 0}, { 19, 19, 0}, +{ 27, 27, 0}, { 35, 35, 0}, { 43, 43, 7}, { 47, 47, 7}, +{ 55, 55, 7}, { 63, 63, 7}, { 71, 71, 7}, { 75, 75, 11}, +{ 83, 83, 11}, { 91, 91, 11}, { 99, 99, 11}, {107, 107, 15}, +{ 7, 0, 0}, { 15, 0, 0}, { 23, 0, 0}, { 31, 0, 0}, +{ 39, 0, 0}, { 47, 0, 0}, { 55, 0, 0}, { 63, 0, 0}, +{ 71, 0, 0}, { 79, 0, 0}, { 87, 0, 0}, { 95, 0, 0}, +{103, 0, 0}, {111, 0, 0}, {119, 0, 0}, {127, 0, 0}, +{ 19, 19, 0}, { 27, 27, 0}, { 35, 35, 0}, { 47, 43, 0}, +{ 55, 47, 0}, { 67, 55, 0}, { 75, 59, 7}, { 87, 67, 7}, +{ 95, 71, 7}, {107, 75, 11}, {119, 83, 15}, {131, 87, 19}, +{139, 91, 19}, {151, 95, 27}, {163, 99, 31}, {175, 103, 35}, +{ 35, 19, 7}, { 47, 23, 11}, { 59, 31, 15}, { 75, 35, 19}, +{ 87, 43, 23}, { 99, 47, 31}, {115, 55, 35}, {127, 59, 43}, +{143, 67, 51}, {159, 79, 51}, {175, 99, 47}, {191, 119, 47}, +{207, 143, 43}, {223, 171, 39}, {239, 203, 31}, {255, 243, 27}, +{ 11, 7, 0}, { 27, 19, 0}, { 43, 35, 15}, { 55, 43, 19}, +{ 71, 51, 27}, { 83, 55, 35}, { 99, 63, 43}, {111, 71, 51}, +{127, 83, 63}, {139, 95, 71}, {155, 107, 83}, {167, 123, 95}, +{183, 135, 107}, {195, 147, 123}, {211, 163, 139}, {227, 179, 151}, +{171, 139, 163}, {159, 127, 151}, {147, 115, 135}, {139, 103, 123}, +{127, 91, 111}, {119, 83, 99}, {107, 75, 87}, { 95, 63, 75}, +{ 87, 55, 67}, { 75, 47, 55}, { 67, 39, 47}, { 55, 31, 35}, +{ 43, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7}, +{187, 115, 159}, {175, 107, 143}, {163, 95, 131}, {151, 87, 119}, +{139, 79, 107}, {127, 75, 95}, {115, 67, 83}, {107, 59, 75}, +{ 95, 51, 63}, { 83, 43, 55}, { 71, 35, 43}, { 59, 31, 35}, +{ 47, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7}, +{219, 195, 187}, {203, 179, 167}, {191, 163, 155}, {175, 151, 139}, +{163, 135, 123}, {151, 123, 111}, {135, 111, 95}, {123, 99, 83}, +{107, 87, 71}, { 95, 75, 59}, { 83, 63, 51}, { 67, 51, 39}, +{ 55, 43, 31}, { 39, 31, 23}, { 27, 19, 15}, { 15, 11, 7}, +{111, 131, 123}, {103, 123, 111}, { 95, 115, 103}, { 87, 107, 95}, +{ 79, 99, 87}, { 71, 91, 79}, { 63, 83, 71}, { 55, 75, 63}, +{ 47, 67, 55}, { 43, 59, 47}, { 35, 51, 39}, { 31, 43, 31}, +{ 23, 35, 23}, { 15, 27, 19}, { 11, 19, 11}, { 7, 11, 7}, +{255, 243, 27}, {239, 223, 23}, {219, 203, 19}, {203, 183, 15}, +{187, 167, 15}, {171, 151, 11}, {155, 131, 7}, {139, 115, 7}, +{123, 99, 7}, {107, 83, 0}, { 91, 71, 0}, { 75, 55, 0}, +{ 59, 43, 0}, { 43, 31, 0}, { 27, 15, 0}, { 11, 7, 0}, +{ 0, 0, 255}, { 11, 11, 239}, { 19, 19, 223}, { 27, 27, 207}, +{ 35, 35, 191}, { 43, 43, 175}, { 47, 47, 159}, { 47, 47, 143}, +{ 47, 47, 127}, { 47, 47, 111}, { 47, 47, 95}, { 43, 43, 79}, +{ 35, 35, 63}, { 27, 27, 47}, { 19, 19, 31}, { 11, 11, 15}, +{ 43, 0, 0}, { 59, 0, 0}, { 75, 7, 0}, { 95, 7, 0}, +{111, 15, 0}, {127, 23, 7}, {147, 31, 7}, {163, 39, 11}, +{183, 51, 15}, {195, 75, 27}, {207, 99, 43}, {219, 127, 59}, +{227, 151, 79}, {231, 171, 95}, {239, 191, 119}, {247, 211, 139}, +{167, 123, 59}, {183, 155, 55}, {199, 195, 55}, {231, 227, 87}, +{127, 191, 255}, {171, 231, 255}, {215, 255, 255}, {103, 0, 0}, +{139, 0, 0}, {179, 0, 0}, {215, 0, 0}, {255, 0, 0}, +{255, 243, 147}, {255, 247, 199}, {255, 255, 255}, {159, 91, 83} }; + + +#endif // !! AI_MDL_DEFAULTLMP_H_INC diff --git a/code/MDLFileData.h b/code/MDLFileData.h new file mode 100644 index 000000000..f15e4ab86 --- /dev/null +++ b/code/MDLFileData.h @@ -0,0 +1,706 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + +// +//! @file Definition of in-memory structures for the MDL file format. +// +// The specification has been taken from various sources on the internet. +// http://tfc.duke.free.fr/coding/mdl-specs-en.html + + +#ifndef AI_MDLFILEHELPER_H_INC +#define AI_MDLFILEHELPER_H_INC + +#include +#include + +#include "../include/aiTypes.h" +#include "../include/aiMesh.h" +#include "../include/aiAnim.h" +#include "../include/aiMaterial.h" + +// ugly compiler dependent packing stuff +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack(push,1) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error Compiler not supported. Never do this again. +#endif + + +namespace Assimp +{ +namespace MDL +{ + +// magic bytes used in Quake 1 MDL meshes +#define AI_MDL_MAGIC_NUMBER_BE 'IDPO' +#define AI_MDL_MAGIC_NUMBER_LE 'OPDI' + +// magic bytes used in GameStudio A4 MDL meshes +#define AI_MDL_MAGIC_NUMBER_BE_GS4 'MDL3' +#define AI_MDL_MAGIC_NUMBER_LE_GS4 '3LDM' + +// magic bytes used in GameStudio A5+ MDL meshes +#define AI_MDL_MAGIC_NUMBER_BE_GS5a 'MDL4' +#define AI_MDL_MAGIC_NUMBER_LE_GS5a '4LDM' +#define AI_MDL_MAGIC_NUMBER_BE_GS5b 'MDL5' +#define AI_MDL_MAGIC_NUMBER_LE_GS5b '5LDM' + +// magic bytes used in GameStudio A6+ MDL meshes +#define AI_MDL_MAGIC_NUMBER_BE_GS6 'MDL6' +#define AI_MDL_MAGIC_NUMBER_LE_GS6 '6LDM' + +// magic bytes used in GameStudio A7+ MDL meshes +#define AI_MDL_MAGIC_NUMBER_BE_GS7 'MDL7' +#define AI_MDL_MAGIC_NUMBER_LE_GS7 '7LDM' + +// common limitations for Quake1 meshes. The loader does not check them, +// but models should not exceed these limits. +#if (!defined AI_MDL_VERSION) +# define AI_MDL_VERSION 6 +#endif +#if (!defined AI_MDL_MAX_FRAMES) +# define AI_MDL_MAX_FRAMES 256 +#endif +#if (!defined AI_MDL_MAX_UVS) +# define AI_MDL_MAX_UVS 1024 +#endif +#if (!defined AI_MDL_MAX_VERTS) +# define AI_MDL_MAX_VERTS 1024 +#endif +#if (!defined AI_MDL_MAX_TRIANGLES) +# define AI_MDL_MAX_TRIANGLES 2048 +#endif + +// --------------------------------------------------------------------------- +/** \struct Header + * \brief Data structure for the MDL main header + */ +// --------------------------------------------------------------------------- +struct Header +{ + //! magic number: "IDPO" + int32_t ident; + + //! version number: 6 + int32_t version; + + //! scale factors for each axis + aiVector3D scale; + + //! translation factors for each axis + aiVector3D translate; + + //! bounding radius of the mesh + float boundingradius; + + //! Position of the viewer's exe. Ignored + aiVector3D vEyePos; + + //! Number of textures + int32_t num_skins; + + //! Texture width in pixels + int32_t skinwidth; + + //! Texture height in pixels + int32_t skinheight; + + //! Number of vertices contained in the file + int32_t num_verts; + + //! Number of triangles contained in the file + int32_t num_tris; + + //! Number of frames contained in the file + int32_t num_frames; + + //! 0 = synchron, 1 = random . Ignored + int32_t synctype; + + //! State flag + int32_t flags; + + //! ??? + float size; +} PACK_STRUCT; + + +// --------------------------------------------------------------------------- +/** \struct Header_MDL7 + * \brief Data structure for the MDL 7 main header + */ +// --------------------------------------------------------------------------- +struct Header_MDL7 +{ + //! magic number: "MDL7" + char ident[4]; + + //! Version number. Ignored + int32_t version; + + //! Number of bones in file + int32_t bones_num; + + //! Number of groups in file + int32_t groups_num; + + //! Size of data in the file + int32_t data_size; + + //! Ignored. Used to store entity specific information + int32_t entlump_size; + + //! Ignored. Used to store MED related data + int32_t medlump_size; + + // ------------------------------------------------------- + // Sizes of some file parts + + uint16_t bone_stc_size; + uint16_t skin_stc_size; + uint16_t colorvalue_stc_size; + uint16_t material_stc_size; + uint16_t skinpoint_stc_size; + uint16_t triangle_stc_size; + uint16_t mainvertex_stc_size; + uint16_t framevertex_stc_size; + uint16_t bonetrans_stc_size; + uint16_t frame_stc_size; +} PACK_STRUCT; + +#define AI_MDL7_MAX_BONENAMESIZE 20 + +// --------------------------------------------------------------------------- +/** \struct Bone_MDL7 + * \brief Bone in a MDL7 file + */ +// --------------------------------------------------------------------------- +struct Bone_MDL7 +{ + uint16_t parent_index; + uint8_t _unused_[2]; // + float x,y,z; + + char name[AI_MDL7_MAX_BONENAMESIZE]; +}; + +#define AI_MDL7_MAX_GROUPNAMESIZE 16 + +// --------------------------------------------------------------------------- +/** \struct Group_MDL7 + * \brief Group in a MDL7 file + */ +// --------------------------------------------------------------------------- +struct Group_MDL7 +{ + //! = '1' -> triangle based Mesh + unsigned char typ; + + int8_t deformers; + int8_t max_weights; + int8_t _unused_; + + //! size of data for this group in bytes ( MD7_GROUP stc. included). + int32_t groupdata_size; + char name[AI_MDL7_MAX_GROUPNAMESIZE]; + + //! Number of skins + int32_t numskins; + + //! Number of texture coordinates + int32_t num_stpts; + + //! Number of triangles + int32_t numtris; + + //! Number of vertices + int32_t numverts; + + //! Number of frames + int32_t numframes; +} PACK_STRUCT; + +#define AI_MDL7_SKINTYPE_MIPFLAG 0x08 +#define AI_MDL7_SKINTYPE_MATERIAL 0x10 +#define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20 +#define AI_MDL7_SKINTYPE_RGBFLAG 0x80 + + +#define AI_MDL7_MAX_BONENAMESIZE 20 + +// --------------------------------------------------------------------------- +/** \struct Deformer_MDL7 + * \brief Deformer in a MDL7 file + */ +// --------------------------------------------------------------------------- +struct Deformer_MDL7 +{ + int8_t deformer_version; // 0 + int8_t deformer_typ; // 0 - bones + int8_t _unused_[2]; + int32_t group_index; + int32_t elements; + int32_t deformerdata_size; +} PACK_STRUCT; + +struct DeformerElement_MDL7 +{ + //! bei deformer_typ==0 (==bones) element_index == bone index + int32_t element_index; + char element_name[AI_MDL7_MAX_BONENAMESIZE]; + int32_t weights; +} PACK_STRUCT; + +struct DeformerWeight_MDL7 +{ + //! for deformer_typ==0 (==bones) index == vertex index + int32_t index; + float weight; +} PACK_STRUCT; + +#define AI_MDL7_MAX_TEXNAMESIZE 0x10 + +typedef int32_t MD7_MATERIAL_ASCDEFSIZE; + +// --------------------------------------------------------------------------- +/** \struct Skin_MDL7 + * \brief Skin in a MDL7 file + */ +// --------------------------------------------------------------------------- +struct Skin_MDL7 +{ + uint8_t typ; + int8_t _unused_[3]; + int32_t width; + int32_t height; + char texture_name[AI_MDL7_MAX_TEXNAMESIZE]; +} PACK_STRUCT; + +struct ColorValue_MDL7 +{ + float r,g,b,a; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \struct Material_MDL7 + * \brief Material in a MDL7 file + */ +// --------------------------------------------------------------------------- +struct Material_MDL7 +{ + //! Diffuse base color of the material + ColorValue_MDL7 Diffuse; + + //! Ambient base color of the material + ColorValue_MDL7 Ambient; + + //! Specular base color of the material + ColorValue_MDL7 Specular; + + //! Emissive base color of the material + ColorValue_MDL7 Emissive; + + //! Phong power + float Power; +} PACK_STRUCT; + + +// --------------------------------------------------------------------------- +/** \struct Skin + * \brief Skin data structure #1 + */ +// --------------------------------------------------------------------------- +struct Skin +{ + //! 0 = single (Skin), 1 = group (GroupSkin) + //! For MDL3-5: Defines the type of the skin and there + //! fore the size of the data to skip: + //------------------------------------------------------- + //! 2 for 565 RGB, + //! 3 for 4444 ARGB, + //! 10 for 565 mipmapped, + //! 11 for 4444 mipmapped (bpp = 2), + //! 12 for 888 RGB mipmapped (bpp = 3), + //! 13 for 8888 ARGB mipmapped (bpp = 4) + //------------------------------------------------------- + int32_t group; + + //! Texture data + uint8_t *data; +} PACK_STRUCT; + +struct Skin_MDL5 +{ + int32_t size, width, height; + uint8_t *data; +} PACK_STRUCT; + +struct RGB565 +{ + uint16_t r : 5; + uint16_t g : 6; + uint16_t b : 5; +} PACK_STRUCT; + +struct ARGB4 +{ + uint16_t a : 4; + uint16_t r : 4; + uint16_t g : 4; + uint16_t b : 4; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \struct GroupSkin + * \brief Skin data structure #2 (group of pictures) + */ +// --------------------------------------------------------------------------- +struct GroupSkin +{ + //! 0 = single (Skin), 1 = group (GroupSkin) + int32_t group; + + //! Number of images + int32_t nb; + + //! Time for each image + float *time; + + //! Data of each image + uint8_t **data; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \struct TexCoord + * \brief Texture coordinate data structure + */ +// --------------------------------------------------------------------------- +struct TexCoord +{ + //! Is the vertex on the noundary between front and back piece? + int32_t onseam; + + //! Texture coordinate in the tx direction + int32_t s; + + //! Texture coordinate in the ty direction + int32_t t; +} PACK_STRUCT; + + +struct TexCoord_MDL3 +{ + //! position, horizontally in range 0..skinwidth-1 + int16_t u; + + //! position, vertically in range 0..skinheight-1 + int16_t v; +} PACK_STRUCT; + +struct TexCoord_MDL7 +{ + //! position, horizontally in range 0..1 + float u; + + //! position, vertically in range 0..1 + float v; +} PACK_STRUCT; + + +// --------------------------------------------------------------------------- +/** \struct Triangle + * \brief Triangle data structure + */ +// --------------------------------------------------------------------------- +struct Triangle +{ + //! 0 = backface, 1 = frontface + int32_t facesfront; + + //! Vertex indices + int32_t vertex[3]; +} PACK_STRUCT; + + +struct Triangle_MDL3 +{ + //! Index of 3 3D vertices in range 0..numverts + uint16_t index_xyz[3]; + + //! Index of 3 skin vertices in range 0..numskinverts + uint16_t index_uv[3]; +} PACK_STRUCT; + + +struct SkinSet_MDL7 +{ + //! Index into the UV coordinate list + uint16_t st_index[3]; // size 6 + + //! Material index + int32_t material; // size 4 +} PACK_STRUCT; + + +struct Triangle_MDL7 +{ + //! Vertex indices + uint16_t v_index[3]; // size 6 + + //! Two skinsets. The second will be used for multi-texturing + SkinSet_MDL7 skinsets[2]; +} PACK_STRUCT; + + +// Helper constants for Triangle::facesfront +#if (!defined AI_MDL_BACKFACE) +# define AI_MDL_BACKFACE 0x0 +#endif +#if (!defined AI_MDL_FRONTFACE) +# define AI_MDL_FRONTFACE 0x1 +#endif + +// --------------------------------------------------------------------------- +/** \struct Vertex + * \brief Vertex data structure + */ +// --------------------------------------------------------------------------- +struct Vertex +{ + uint8_t v[3]; + uint8_t normalIndex; +} PACK_STRUCT; + + +struct Vertex_MDL4 +{ + uint16_t v[3]; + uint8_t normalIndex; + uint8_t unused; +} PACK_STRUCT; + +#define AI_MDL7_FRAMEVERTEX120503_STCSIZE 16 +#define AI_MDL7_FRAMEVERTEX030305_STCSIZE 26 + +// --------------------------------------------------------------------------- +/** \struct Vertex_MDL7 + * \brief Vertex data structure used in MDL7 files + */ +// --------------------------------------------------------------------------- +struct Vertex_MDL7 +{ + float x,y,z; + uint16_t vertindex; + union { + uint16_t norm162index; + float norm[3]; + }; +} PACK_STRUCT; + + +// --------------------------------------------------------------------------- +/** \struct BoneTransform_MDL7 + * \brief bone transformation matrix structure used in MDL7 files + */ +// --------------------------------------------------------------------------- +struct BoneTransform_MDL7 +{ + //! 4*3 + float m [4*4]; + + //! the index of this vertex, 0.. header::bones_num - 1 + uint16_t bone_index; + + //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED + //! THIS STUPID FILE FORMAT! + int8_t _unused_[2]; +} PACK_STRUCT; + + +#define AI_MDL7_MAX_FRAMENAMESIZE 16 + + +// --------------------------------------------------------------------------- +/** \struct Frame_MDL7 + * \brief Frame data structure used by MDL7 files + */ +// --------------------------------------------------------------------------- +struct Frame_MDL7 +{ + char frame_name[AI_MDL7_MAX_FRAMENAMESIZE]; + uint32_t vertices_count; + uint32_t transmatrix_count; +}; + + +// --------------------------------------------------------------------------- +/** \struct SimpleFrame + * \brief Data structure for a simple frame + */ +// --------------------------------------------------------------------------- +struct SimpleFrame +{ + //! Minimum vertex of the bounding box + Vertex bboxmin; + + //! Maximum vertex of the bounding box + Vertex bboxmax; + + //! Name of the frame + char name[16]; + + //! Vertex list of the frame + Vertex *verts; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \struct Frame + * \brief Model frame data structure + */ +// --------------------------------------------------------------------------- +struct Frame +{ + //! 0 = simple frame, !0 = group frame + int32_t type; + + //! Frame data + SimpleFrame frame; +} PACK_STRUCT; + + +struct SimpleFrame_MDLn_SP +{ + //! Minimum vertex of the bounding box + Vertex_MDL4 bboxmin; + + //! Maximum vertex of the bounding box + Vertex_MDL4 bboxmax; + + //! Name of the frame + char name[16]; + + //! Vertex list of the frame + Vertex_MDL4 *verts; +} PACK_STRUCT; + +// --------------------------------------------------------------------------- +/** \struct GroupFrame + * \brief Data structure for a group of frames + */ +// --------------------------------------------------------------------------- +struct GroupFrame +{ + //! 0 = simple frame, !0 = group frame + int32_t type; + + //! Minimum vertex for all single frames + Vertex min; + + //! Maximum vertex for all single frames + Vertex max; + + //! Time for all single frames + float *time; + + //! List of single frames + SimpleFrame *frames; +} PACK_STRUCT; + +// reset packing to the original value +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop ) +#endif +#undef PACK_STRUCT + + +// --------------------------------------------------------------------------- +/** \struct IntFace_MDL7 + * \brief Internal data structure to temporarily represent a face + */ +// --------------------------------------------------------------------------- +struct IntFace_MDL7 +{ + // provide a constructor for our own convenience + IntFace_MDL7() + { + // set everything to zero + mIndices[0] = mIndices[1] = mIndices[2] = 0; + iMatIndex[0] = iMatIndex[1] = 0; + } + + //! Vertex indices + uint32_t mIndices[3]; + + //! Material index (maximally two channels, which are joined later) + unsigned int iMatIndex[2]; +}; + + +// --------------------------------------------------------------------------- +/** \struct IntMaterial_MDL7 + * \brief Internal data structure to temporarily represent a material + * which has been created from two single materials along with the + * original material indices. + */ +// --------------------------------------------------------------------------- +struct IntMaterial_MDL7 +{ + // provide a constructor for our own convenience + IntMaterial_MDL7() + { + pcMat = NULL; + iOldMatIndices[0] = iOldMatIndices[1] = 0; + } + + //! Material instance + MaterialHelper* pcMat; + + //! Old material indices + unsigned int iOldMatIndices[2]; +}; + +};}; // end namespaces + +#endif // !! AI_MDLFILEHELPER_H_INC \ No newline at end of file diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp new file mode 100644 index 000000000..d68ef81d5 --- /dev/null +++ b/code/MDLLoader.cpp @@ -0,0 +1,1715 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the MDL importer class */ + +#include "MaterialSystem.h" +#include "MDLLoader.h" +#include "MDLDefaultColorMap.h" + +#include "../include/IOStream.h" +#include "../include/IOSystem.h" +#include "../include/aiMesh.h" +#include "../include/aiScene.h" +#include "../include/aiAssert.h" + +#include + +using namespace Assimp; + +extern float g_avNormals[162][3]; + + +// ------------------------------------------------------------------------------------------------ +inline bool is_qnan(float p_fIn) +{ + // NOTE: Comparison against qnan is generally problematic + // because qnan == qnan is false AFAIK + union FTOINT + { + float fFloat; + int32_t iInt; + } one, two; + one.fFloat = std::numeric_limits::quiet_NaN(); + two.fFloat = p_fIn; + + return (one.iInt == two.iInt); +} +// ------------------------------------------------------------------------------------------------ +inline bool is_not_qnan(float p_fIn) +{ + return !is_qnan(p_fIn); +} + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +MDLImporter::MDLImporter() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +MDLImporter::~MDLImporter() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const +{ + // simple check of file extension is enough for the moment + std::string::size_type pos = pFile.find_last_of('.'); + // no file extension - can't read + if( pos == std::string::npos) + return false; + std::string extension = pFile.substr( pos); + + if (extension.length() < 4)return false; + if (extension[0] != '.')return false; + if (extension[1] != 'm' && extension[1] != 'M')return false; + if (extension[2] != 'd' && extension[2] != 'D')return false; + if (extension[3] != 'l' && extension[3] != 'L')return false; + + return true; +} +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void MDLImporter::InternReadFile( + const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) +{ + boost::scoped_ptr file( pIOHandler->Open( pFile)); + + // Check whether we can read from the file + if( file.get() == NULL) + { + throw new ImportErrorException( "Failed to open MDL file " + pFile + "."); + } + + // check whether the ply file is large enough to contain + // at least the file header + size_t fileSize = file->FileSize(); + if( fileSize < sizeof(MDL::Header)) + { + throw new ImportErrorException( ".mdl File is too small."); + } + + // allocate storage and copy the contents of the file to a memory buffer + this->pScene = pScene; + this->pIOHandler = pIOHandler; + this->mBuffer = new unsigned char[fileSize+1]; + file->Read( (void*)mBuffer, 1, fileSize); + + // determine the file subtype and call the appropriate member function + + // Original Quake1 format + this->m_pcHeader = (const MDL::Header*)this->mBuffer; + if (AI_MDL_MAGIC_NUMBER_BE == this->m_pcHeader->ident || + AI_MDL_MAGIC_NUMBER_LE == this->m_pcHeader->ident) + { + this->InternReadFile_Quake1(); + } + // GameStudio A4 MDL3 format + else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == this->m_pcHeader->ident || + AI_MDL_MAGIC_NUMBER_LE_GS4 == this->m_pcHeader->ident) + { + this->iGSFileVersion = 3; + this->InternReadFile_GameStudio(); + } + // GameStudio A5+ MDL4 format + else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == this->m_pcHeader->ident || + AI_MDL_MAGIC_NUMBER_LE_GS5a == this->m_pcHeader->ident) + { + this->iGSFileVersion = 4; + this->InternReadFile_GameStudio(); + } + // GameStudio A5+ MDL5 format + else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == this->m_pcHeader->ident || + AI_MDL_MAGIC_NUMBER_LE_GS5b == this->m_pcHeader->ident) + { + this->iGSFileVersion = 5; + this->InternReadFile_GameStudio(); + } + // GameStudio A6+ MDL6 format + else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == this->m_pcHeader->ident || + AI_MDL_MAGIC_NUMBER_LE_GS6 == this->m_pcHeader->ident) + { + this->iGSFileVersion = 6; + this->InternReadFile_GameStudio(); + } + // GameStudio A7 MDL7 format + else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == this->m_pcHeader->ident || + AI_MDL_MAGIC_NUMBER_LE_GS7 == this->m_pcHeader->ident) + { + this->iGSFileVersion = 7; + this->InternReadFile_GameStudioA7(); + } + else + { + // we're definitely unable to load this file + throw new ImportErrorException( "Unknown MDL subformat " + pFile + + ". Magic word is not known"); + } + + // delete the file buffer + delete[] this->mBuffer; + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::SearchPalette(const unsigned char** pszColorMap) +{ + // now try to find the color map in the current directory + IOStream* pcStream = this->pIOHandler->Open("colormap.lmp","rb"); + + const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap; + if(pcStream) + { + if (pcStream->FileSize() >= 768) + { + szColorMap = new unsigned char[256*3]; + pcStream->Read(const_cast(szColorMap),256*3,1); + } + delete pcStream; + pcStream = NULL; + } + *pszColorMap = szColorMap; + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::FreePalette(const unsigned char* szColorMap) +{ + if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap) + { + delete[] szColorMap; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::CreateTextureARGB8(const unsigned char* szData) +{ + // allocate a new texture object + aiTexture* pcNew = new aiTexture(); + pcNew->mWidth = this->m_pcHeader->skinwidth; + pcNew->mHeight = this->m_pcHeader->skinheight; + + pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; + + const unsigned char* szColorMap; + this->SearchPalette(&szColorMap); + + // copy texture data + for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + const unsigned char val = szData[i]; + const unsigned char* sz = &szColorMap[val*3]; + + pcNew->pcData[i].a = 0xFF; + pcNew->pcData[i].r = *sz++; + pcNew->pcData[i].g = *sz++; + pcNew->pcData[i].b = *sz; + } + + this->FreePalette(szColorMap); + + // store the texture + aiTexture** pc = this->pScene->mTextures; + this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1]; + for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) + this->pScene->mTextures[i] = pc[i]; + + this->pScene->mTextures[this->pScene->mNumTextures] = pcNew; + this->pScene->mNumTextures++; + delete[] pc; + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::CreateTextureARGB8_GS4(const unsigned char* szData, + unsigned int iType, + unsigned int* piSkip) +{ + ai_assert(NULL != piSkip); + + // allocate a new texture object + aiTexture* pcNew = new aiTexture(); + pcNew->mWidth = this->m_pcHeader->skinwidth; + pcNew->mHeight = this->m_pcHeader->skinheight; + + pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; + + // 8 Bit paletized. Use Q1 default palette. + if (0 == iType) + { + const unsigned char* szColorMap; + this->SearchPalette(&szColorMap); + + // copy texture data + unsigned int i = 0; + for (; i < pcNew->mWidth*pcNew->mHeight;++i) + { + const unsigned char val = szData[i]; + const unsigned char* sz = &szColorMap[val*3]; + + pcNew->pcData[i].a = 0xFF; + pcNew->pcData[i].r = *sz++; + pcNew->pcData[i].g = *sz++; + pcNew->pcData[i].b = *sz; + } + *piSkip = i; + + this->FreePalette(szColorMap); + } + // R5G6B5 format + else if (2 == iType) + { + // copy texture data + unsigned int i = 0; + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + MDL::RGB565 val = ((MDL::RGB565*)szData)[i]; + + pcNew->pcData[i].a = 0xFF; + pcNew->pcData[i].r = (unsigned char)val.b << 3; + pcNew->pcData[i].g = (unsigned char)val.g << 2; + pcNew->pcData[i].b = (unsigned char)val.r << 3; + } + *piSkip = i * 2; + } + // ARGB4 format + else if (3 == iType) + { + // copy texture data + unsigned int i = 0; + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i]; + + pcNew->pcData[i].a = (unsigned char)val.a << 4; + pcNew->pcData[i].r = (unsigned char)val.r << 4; + pcNew->pcData[i].g = (unsigned char)val.g << 4; + pcNew->pcData[i].b = (unsigned char)val.b << 4; + } + *piSkip = i * 2; + } + // store the texture + aiTexture** pc = this->pScene->mTextures; + this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1]; + for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) + this->pScene->mTextures[i] = pc[i]; + + this->pScene->mTextures[this->pScene->mNumTextures] = pcNew; + this->pScene->mNumTextures++; + delete[] pc; + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::ParseTextureColorData(const unsigned char* szData, + unsigned int iType, + unsigned int* piSkip, + aiTexture* pcNew) +{ + // allocate storage for the texture image + pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; + + // R5G6B5 format (with or without MIPs) + if (2 == iType || 10 == iType) + { + // copy texture data + unsigned int i = 0; + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + MDL::RGB565 val = ((MDL::RGB565*)szData)[i]; + + pcNew->pcData[i].a = 0xFF; + pcNew->pcData[i].r = (unsigned char)val.b << 3; + pcNew->pcData[i].g = (unsigned char)val.g << 2; + pcNew->pcData[i].b = (unsigned char)val.r << 3; + } + *piSkip = i * 2; + + // apply MIP maps + if (10 == iType) + { + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1; + } + } + // ARGB4 format (with or without MIPs) + else if (3 == iType || 11 == iType) + { + // copy texture data + unsigned int i = 0; + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i]; + + pcNew->pcData[i].a = (unsigned char)val.a << 4; + pcNew->pcData[i].r = (unsigned char)val.r << 4; + pcNew->pcData[i].g = (unsigned char)val.g << 4; + pcNew->pcData[i].b = (unsigned char)val.b << 4; + } + *piSkip = i * 2; + + // apply MIP maps + if (11 == iType) + { + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1; + } + } + // RGB8 format (with or without MIPs) + else if (4 == iType || 12 == iType) + { + // copy texture data + unsigned int i = 0; + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + const unsigned char* _szData = &szData[i*3]; + + pcNew->pcData[i].a = 0xFF; + pcNew->pcData[i].b = *_szData++; + pcNew->pcData[i].g = *_szData++; + pcNew->pcData[i].r = *_szData; + } + // apply MIP maps + *piSkip = i * 3; + if (12 == iType) + { + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3; + } + } + // ARGB8 format (with ir without MIPs) + else if (5 == iType || 13 == iType) + { + // copy texture data + unsigned int i = 0; + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) + { + const unsigned char* _szData = &szData[i*4]; + + pcNew->pcData[i].b = *_szData++; + pcNew->pcData[i].g = *_szData++; + pcNew->pcData[i].r = *_szData++; + pcNew->pcData[i].a = *_szData; + } + // apply MIP maps + *piSkip = i << 2; + if (13 == iType) + { + *piSkip += (i + (i >> 2) + (i >> 4) + (i >> 6)) << 2; + } + } + // palletized 8 bit texture. As for Quake 1 + else if (0 == iType) + { + const unsigned char* szColorMap; + this->SearchPalette(&szColorMap); + + // copy texture data + unsigned int i = 0; + for (; i < pcNew->mWidth*pcNew->mHeight;++i) + { + const unsigned char val = szData[i]; + const unsigned char* sz = &szColorMap[val*3]; + + pcNew->pcData[i].a = 0xFF; + pcNew->pcData[i].r = *sz++; + pcNew->pcData[i].g = *sz++; + pcNew->pcData[i].b = *sz; + } + *piSkip = i; + + this->FreePalette(szColorMap); + } + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::CreateTextureARGB8_GS5(const unsigned char* szData, + unsigned int iType, + unsigned int* piSkip) +{ + ai_assert(NULL != piSkip); + + // allocate a new texture object + aiTexture* pcNew = new aiTexture(); + + // first read the size of the texture + pcNew->mWidth = *((uint32_t*)szData); + szData += sizeof(uint32_t); + + pcNew->mHeight = *((uint32_t*)szData); + szData += sizeof(uint32_t); + + if (6 == iType) + { + // this is a compressed texture in DDS format + *piSkip = pcNew->mWidth; + + pcNew->mHeight = 0; + pcNew->achFormatHint[0] = 'd'; + pcNew->achFormatHint[1] = 'd'; + pcNew->achFormatHint[2] = 's'; + pcNew->achFormatHint[3] = '\0'; + + pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth]; + memcpy(pcNew->pcData,szData,pcNew->mWidth); + } + else + { + // parse the color data of the texture + this->ParseTextureColorData(szData,iType, + piSkip,pcNew); + } + *piSkip += sizeof(uint32_t) * 2; + + // store the texture + aiTexture** pc = this->pScene->mTextures; + this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1]; + for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) + this->pScene->mTextures[i] = pc[i]; + + this->pScene->mTextures[this->pScene->mNumTextures] = pcNew; + this->pScene->mNumTextures++; + delete[] pc; + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::InternReadFile_Quake1( ) +{ + ai_assert(NULL != pScene); + + if(0 == this->m_pcHeader->num_frames) + { + throw new ImportErrorException( "[Quake 1 MDL] No frames found"); + } + + // allocate enough storage to hold all vertices and triangles + aiMesh* pcMesh = new aiMesh(); + + // current cursor position in the file + const unsigned char* szCurrent = (const unsigned char*)(this->m_pcHeader+1); + + // need to read all textures + for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->num_skins;++i) + { + union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;}; + pcSkin = (const MDL::Skin*)szCurrent; + if (0 == pcSkin->group) + { + // create one output image + this->CreateTextureARGB8((unsigned char*)pcSkin + sizeof(uint32_t)); + + // need to skip one image + szCurrent += this->m_pcHeader->skinheight * this->m_pcHeader->skinwidth+ sizeof(uint32_t); + } + else + { + // need to skip multiple images + const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb; + szCurrent += sizeof(uint32_t) * 2; + + if (0 != iNumImages) + { + // however, create only one output image (the first) + this->CreateTextureARGB8(szCurrent + iNumImages * sizeof(float)); + + for (unsigned int a = 0; a < iNumImages;++a) + { + szCurrent += this->m_pcHeader->skinheight * this->m_pcHeader->skinwidth + + sizeof(float); + } + } + } + } + // get a pointer to the texture coordinates + const MDL::TexCoord* pcTexCoords = (const MDL::TexCoord*)szCurrent; + szCurrent += sizeof(MDL::TexCoord) * this->m_pcHeader->num_verts; + + // get a pointer to the triangles + const MDL::Triangle* pcTriangles = (const MDL::Triangle*)szCurrent; + szCurrent += sizeof(MDL::Triangle) * this->m_pcHeader->num_tris; + + // now get a pointer to the first frame in the file + const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent; + const MDL::SimpleFrame* pcFirstFrame; + + if (0 == pcFrames->type) + { + // get address of single frame + pcFirstFrame = &pcFrames->frame; + } + else + { + // get the first frame in the group + const MDL::GroupFrame* pcFrames2 = (const MDL::GroupFrame*)pcFrames; + pcFirstFrame = (const MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type); + } + const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + + sizeof(pcFirstFrame->name)); + + pcMesh->mNumVertices = this->m_pcHeader->num_tris * 3; + pcMesh->mNumFaces = this->m_pcHeader->num_tris; + pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; + pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNumUVComponents[0] = 2; + + // there won't be more than one mesh inside the file + pScene->mNumMaterials = 1; + pScene->mRootNode = new aiNode(); + pScene->mRootNode->mNumMeshes = 1; + pScene->mRootNode->mMeshes = new unsigned int[1]; + pScene->mRootNode->mMeshes[0] = 0; + pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials[0] = new MaterialHelper(); + pScene->mNumMeshes = 1; + pScene->mMeshes = new aiMesh*[1]; + pScene->mMeshes[0] = pcMesh; + + // setup the material properties + const int iMode = (int)aiShadingMode_Gouraud; + MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0]; + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + aiColor3D clr; + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + + clr.b = clr.g = clr.r = 0.05f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + + if (0 != this->m_pcHeader->num_skins) + { + aiString szString; + memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3); + szString.length = 2; + pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + + // now iterate through all triangles + unsigned int iCurrent = 0; + for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i) + { + pcMesh->mFaces[i].mIndices = new unsigned int[3]; + pcMesh->mFaces[i].mNumIndices = 3; + + for (unsigned int c = 0; c < 3;++c,++iCurrent) + { + pcMesh->mFaces[i].mIndices[c] = iCurrent; + + // read vertices + unsigned int iIndex = pcTriangles->vertex[c]; + if (iIndex >= (unsigned int)this->m_pcHeader->num_verts) + { + iIndex = this->m_pcHeader->num_verts-1; + // LOG + } + + aiVector3D& vec = pcMesh->mVertices[iCurrent]; + vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0]; + vec.x += this->m_pcHeader->translate[0]; + + // (flip z and y component) + vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1]; + vec.z += this->m_pcHeader->translate[1]; + + vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2]; + vec.y += this->m_pcHeader->translate[2]; + + // flip the Z-axis + //pcMesh->mVertices[iBase+c].z *= -1.0f; + + // read the normal vector from the precalculated normal table + pcMesh->mNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( + int(pcVertices[iIndex].normalIndex), + int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); + + //pcMesh->mNormals[iBase+c].z *= -1.0f; + std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z ); + + // read texture coordinates + float s = (float)pcTexCoords[iIndex].s; + float t = (float)pcTexCoords[iIndex].t; + + // translate texture coordinates + if (0 == pcTriangles->facesfront && + 0 != pcTexCoords[iIndex].onseam) + { + s += this->m_pcHeader->skinwidth * 0.5f; + } + + // Scale s and t to range from 0.0 to 1.0 + pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / this->m_pcHeader->skinwidth; + pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight; + + } + pcTriangles++; + } + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::InternReadFile_GameStudio( ) +{ + ai_assert(NULL != pScene); + + if(0 == this->m_pcHeader->num_frames) + { + throw new ImportErrorException( "[3DGS MDL] No frames found"); + } + + // allocate enough storage to hold all vertices and triangles + aiMesh* pcMesh = new aiMesh(); + + // current cursor position in the file + const unsigned char* szCurrent = (const unsigned char*)(this->m_pcHeader+1); + + // need to read all textures + for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->num_skins;++i) + { + union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;}; + pcSkin = (const MDL::Skin*)szCurrent; + + // create one output image + unsigned int iSkip = 0; + if (5 <= this->iGSFileVersion) + { + // MDL5 format could contain MIPmaps + this->CreateTextureARGB8_GS5((unsigned char*)pcSkin + sizeof(uint32_t), + pcSkin->group,&iSkip); + } + else + { + this->CreateTextureARGB8_GS4((unsigned char*)pcSkin + sizeof(uint32_t), + pcSkin->group,&iSkip); + } + // need to skip one image + szCurrent += iSkip + sizeof(uint32_t); + + } + // get a pointer to the texture coordinates + const MDL::TexCoord_MDL3* pcTexCoords = (const MDL::TexCoord_MDL3*)szCurrent; + szCurrent += sizeof(MDL::TexCoord_MDL3) * this->m_pcHeader->synctype; + + // NOTE: for MDLn formats syntype corresponds to the number of UV coords + + // get a pointer to the triangles + const MDL::Triangle_MDL3* pcTriangles = (const MDL::Triangle_MDL3*)szCurrent; + szCurrent += sizeof(MDL::Triangle_MDL3) * this->m_pcHeader->num_tris; + + pcMesh->mNumVertices = this->m_pcHeader->num_tris * 3; + pcMesh->mNumFaces = this->m_pcHeader->num_tris; + pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; + pcMesh->mNumUVComponents[0] = 2; + + // there won't be more than one mesh inside the file + pScene->mNumMaterials = 1; + pScene->mRootNode = new aiNode(); + pScene->mRootNode->mNumMeshes = 1; + pScene->mRootNode->mMeshes = new unsigned int[1]; + pScene->mRootNode->mMeshes[0] = 0; + pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials[0] = new MaterialHelper(); + pScene->mNumMeshes = 1; + pScene->mMeshes = new aiMesh*[1]; + pScene->mMeshes[0] = pcMesh; + + std::vector vPositions; + std::vector vTexCoords; + std::vector vNormals; + + vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D()); + vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D()); + vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D()); + + // setup the material properties + const int iMode = (int)aiShadingMode_Gouraud; + MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0]; + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + aiColor3D clr; + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + + clr.b = clr.g = clr.r = 0.05f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + + if (0 != this->m_pcHeader->num_skins) + { + aiString szString; + memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3); + szString.length = 2; + pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + + // now get a pointer to the first frame in the file + const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent; + + // byte packed vertices + if (0 == pcFrames->type || 3 == this->iGSFileVersion) + { + const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*) + (szCurrent + sizeof(uint32_t)); + + // get a pointer to the vertices + const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + + sizeof(pcFirstFrame->name)); + + // now iterate through all triangles + unsigned int iCurrent = 0; + for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i) + { + pcMesh->mFaces[i].mIndices = new unsigned int[3]; + pcMesh->mFaces[i].mNumIndices = 3; + + for (unsigned int c = 0; c < 3;++c,++iCurrent) + { + pcMesh->mFaces[i].mIndices[c] = iCurrent; + + // read vertices + unsigned int iIndex = pcTriangles->index_xyz[c]; + if (iIndex >= (unsigned int)this->m_pcHeader->num_verts) + { + iIndex = this->m_pcHeader->num_verts-1; + // LOG + } + + aiVector3D& vec = vPositions[iCurrent]; + vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0]; + vec.x += this->m_pcHeader->translate[0]; + + // (flip z and y component) + vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1]; + vec.z += this->m_pcHeader->translate[1]; + + vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2]; + vec.y += this->m_pcHeader->translate[2]; + + // read the normal vector from the precalculated normal table + vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( + int(pcVertices[iIndex].normalIndex), + int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); + + //vNormals[iBase+c].z *= -1.0f; + std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z ); + + // read texture coordinates + iIndex = pcTriangles->index_uv[c]; + + // validate UV indices + if (iIndex >= (unsigned int)this->m_pcHeader->synctype) + { + iIndex = this->m_pcHeader->synctype-1; + // LOG + } + + float s = (float)pcTexCoords[iIndex].u; + float t = (float)pcTexCoords[iIndex].v; + + // Scale s and t to range from 0.0 to 1.0 + if (5 != this->iGSFileVersion && + this->m_pcHeader->skinwidth && this->m_pcHeader->skinheight) + { + s = (s + 0.5f) / this->m_pcHeader->skinwidth; + t = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight; + } + + vTexCoords[iCurrent].x = s; + vTexCoords[iCurrent].y = t; + } + pcTriangles++; + } + + } + // short packed vertices + else + { + // now get a pointer to the first frame in the file + const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) + (szCurrent + sizeof(uint32_t)); + + // get a pointer to the vertices + const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) + + sizeof(pcFirstFrame->name)); + + // now iterate through all triangles + unsigned int iCurrent = 0; + for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i) + { + pcMesh->mFaces[i].mIndices = new unsigned int[3]; + pcMesh->mFaces[i].mNumIndices = 3; + + for (unsigned int c = 0; c < 3;++c,++iCurrent) + { + pcMesh->mFaces[i].mIndices[c] = iCurrent; + + // read vertices + unsigned int iIndex = pcTriangles->index_xyz[c]; + if (iIndex >= (unsigned int)this->m_pcHeader->num_verts) + { + iIndex = this->m_pcHeader->num_verts-1; + // LOG + } + + aiVector3D& vec = vPositions[iCurrent]; + vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0]; + vec.x += this->m_pcHeader->translate[0]; + + // (flip z and y component) + vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1]; + vec.z += this->m_pcHeader->translate[1]; + + vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2]; + vec.y += this->m_pcHeader->translate[2]; + + // read the normal vector from the precalculated normal table + vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min( + int(pcVertices[iIndex].normalIndex), + int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); + + std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z ); + + // read texture coordinates + iIndex = pcTriangles->index_uv[c]; + + // validate UV indices + if (iIndex >= (unsigned int) this->m_pcHeader->synctype) + { + iIndex = this->m_pcHeader->synctype-1; + // LOG + } + + float s = (float)pcTexCoords[iIndex].u; + float t = (float)pcTexCoords[iIndex].v; + + + // Scale s and t to range from 0.0 to 1.0 + if (5 != this->iGSFileVersion && + this->m_pcHeader->skinwidth && this->m_pcHeader->skinheight) + { + s = (s + 0.5f) / this->m_pcHeader->skinwidth; + t = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight; + } + + vTexCoords[iCurrent].x = s; + vTexCoords[iCurrent].y = t; + } + pcTriangles++; + } + } + + // For MDL5 we will need to build valid texture coordinates + // basing upon the file loaded (only support one file as skin) + if (5 == this->iGSFileVersion) + { + if (0 != this->m_pcHeader->num_skins && 0 != this->pScene->mNumTextures) + { + aiTexture* pcTex = this->pScene->mTextures[0]; + + // if the file is loaded in DDS format: get the size of the + // texture from the header of the DDS file + // skip three DWORDs and read first height, then the width + unsigned int iWidth, iHeight; + if (0 == pcTex->mHeight) + { + uint32_t* piPtr = (uint32_t*)pcTex->pcData; + + piPtr += 3; + iHeight = (unsigned int)*piPtr++; + iWidth = (unsigned int)*piPtr; + } + else + { + iWidth = pcTex->mWidth; + iHeight = pcTex->mHeight; + } + + for (std::vector::iterator + i = vTexCoords.begin(); + i != vTexCoords.end();++i) + { + (*i).x /= iWidth; + (*i).y /= iHeight; + (*i).y = 1.0f- (*i).y; + } + } + } + + // allocate output storage + pScene->mMeshes[0]->mNumVertices = vPositions.size(); + pScene->mMeshes[0]->mVertices = new aiVector3D[vPositions.size()]; + pScene->mMeshes[0]->mNormals = new aiVector3D[vPositions.size()]; + pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()]; + + // memcpy() the data to the c-syle arrays + memcpy(pScene->mMeshes[0]->mVertices, &vPositions[0], + vPositions.size() * sizeof(aiVector3D)); + memcpy(pScene->mMeshes[0]->mNormals, &vNormals[0], + vPositions.size() * sizeof(aiVector3D)); + memcpy(pScene->mMeshes[0]->mTextureCoords[0], &vTexCoords[0], + vPositions.size() * sizeof(aiVector3D)); + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::ParseSkinLump_GameStudioA7( + const unsigned char* szCurrent, + const unsigned char** szCurrentOut, + std::vector& pcMats) +{ + ai_assert(NULL != szCurrent); + ai_assert(NULL != szCurrentOut); + + *szCurrentOut = szCurrent; + const MDL::Skin_MDL7* pcSkin = (const MDL::Skin_MDL7*)szCurrent; + szCurrent += 12; + + // allocate an output material + MaterialHelper* pcMatOut = new MaterialHelper(); + pcMats.push_back(pcMatOut); + + aiTexture* pcNew = NULL; + + // get the type of the skin + unsigned int iMasked = (unsigned int)(pcSkin->typ & 0xF); + + // skip length of file name + szCurrent += AI_MDL7_MAX_TEXNAMESIZE; + + if (0x1 == iMasked) + { + // ***** REFERENCE TO ANOTHER SKIN INDEX ***** + + // NOTE: Documentation - if you can call it a documentation, I prefer + // the expression "rubbish" - states it is currently unused. However, + // I don't know what ideas the terrible developers of Conitec will + // have tomorrow, so Im going to implement it. + int referrer = pcSkin->width; + pcMatOut->AddProperty(&referrer,1,"quakquakquak"); + } + else if (0x6 == iMasked) + { + // ***** EMBEDDED DDS FILE ***** + if (1 != pcSkin->height) + { + // LOG + } + + pcNew = new aiTexture(); + pcNew->mHeight = 0; + pcNew->achFormatHint[0] = 'd'; + pcNew->achFormatHint[1] = 'd'; + pcNew->achFormatHint[2] = 's'; + pcNew->achFormatHint[3] = '\0'; + + pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth]; + memcpy(pcNew->pcData,szCurrent,pcNew->mWidth); + szCurrent += pcSkin->width; + } + if (0x7 == iMasked) + { + // ***** REFERENCE TO EXTERNAL FILE FILE ***** + if (1 != pcSkin->height) + { + // LOG + } + + aiString szFile; + const size_t iLen = strlen((const char*)szCurrent); + size_t iLen2 = iLen+1; + iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; + memcpy(szFile.data,(const char*)szCurrent,iLen2); + szFile.length = iLen; + + // place this as diffuse texture + pcMatOut->AddProperty(&szFile,1,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + else if (0 != iMasked) + { + // ***** STANDARD COLOR TEXTURE ***** + if (0 == pcSkin->height || 0 == pcSkin->width) + { + // LOG + } + + // it is a standard color texture. Fill in width and height + // and call the same function we used for loading MDL5 files + + pcNew = new aiTexture(); + pcNew->mWidth = pcSkin->width; + pcNew->mHeight = pcSkin->height; + + unsigned int iSkip = 0; + this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew); + + // skip length of texture data + szCurrent += iSkip; + } + + // check whether a material definition is contained in the skin + if (pcSkin->typ & AI_MDL7_SKINTYPE_MATERIAL) + { + const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent; + szCurrent = (unsigned char*)(pcMatIn+1); + + aiColor4D clrTemp; + + // read diffuse color + clrTemp.a = 1.0f; //pcMatIn->Diffuse.a; + clrTemp.r = pcMatIn->Diffuse.r; + clrTemp.g = pcMatIn->Diffuse.g; + clrTemp.b = pcMatIn->Diffuse.b; + pcMatOut->AddProperty(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE); + + // read specular color + clrTemp.a = 1.0f; //pcMatIn->Specular.a; + clrTemp.r = pcMatIn->Specular.r; + clrTemp.g = pcMatIn->Specular.g; + clrTemp.b = pcMatIn->Specular.b; + pcMatOut->AddProperty(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR); + + // read ambient color + clrTemp.a = 1.0f; //pcMatIn->Ambient.a; + clrTemp.r = pcMatIn->Ambient.r; + clrTemp.g = pcMatIn->Ambient.g; + clrTemp.b = pcMatIn->Ambient.b; + pcMatOut->AddProperty(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT); + + // read emissive color + clrTemp.a = 1.0f; //pcMatIn->Emissive.a; + clrTemp.r = pcMatIn->Emissive.r; + clrTemp.g = pcMatIn->Emissive.g; + clrTemp.b = pcMatIn->Emissive.b; + pcMatOut->AddProperty(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE); + + // FIX: Take the opacity from the ambient color + clrTemp.a = pcMatIn->Ambient.a; + pcMatOut->AddProperty(&clrTemp.a,1,AI_MATKEY_OPACITY); + + // read phong power + int iShadingMode = (int)aiShadingMode_Gouraud; + if (0.0f != pcMatIn->Power) + { + iShadingMode = (int)aiShadingMode_Phong; + pcMatOut->AddProperty(&pcMatIn->Power,1,AI_MATKEY_SHININESS); + } + pcMatOut->AddProperty(&iShadingMode,1,AI_MATKEY_SHADING_MODEL); + } + + // if an ASCII effect description (HLSL?) is contained in the file, + // we can simply ignore it ... + if (pcSkin->typ & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) + { + int32_t iMe = *((int32_t*)szCurrent); + szCurrent += sizeof(char) * iMe + sizeof(int32_t); + } + + // if an embedded texture has been loaded setup the corresponding + // data structures in the aiScene instance + if (NULL != pcNew) + { + // place this as diffuse texture + char szCurrent[5]; + sprintf(szCurrent,"*%i",this->pScene->mNumTextures); + + aiString szFile; + const size_t iLen = strlen((const char*)szCurrent); + size_t iLen2 = iLen+1; + iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; + memcpy(szFile.data,(const char*)szCurrent,iLen2); + szFile.length = iLen; + + pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); + + // store the texture + aiTexture** pc = this->pScene->mTextures; + this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1]; + for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) + this->pScene->mTextures[i] = pc[i]; + + this->pScene->mTextures[this->pScene->mNumTextures] = pcNew; + this->pScene->mNumTextures++; + delete[] pc; + } + + *szCurrentOut = szCurrent; + return; +} + +#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \ + (*((const _type*)(((const char*)_data) + _index * _limit))) + +#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \ + _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7) + +// ------------------------------------------------------------------------------------------------ +void MDLImporter::ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader) +{ + ai_assert(NULL != pcHeader); + + if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) + { + // LOG + throw new ImportErrorException( + "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size"); + } + if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) + { + // LOG + throw new ImportErrorException( + "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size"); + } + if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) + { + // LOG + throw new ImportErrorException( + "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size"); + } + + // if there are no groups ... how should we load such a file? + if(0 == pcHeader->groups_num) + { + // LOG + throw new ImportErrorException( "[3DGS MDL7] No frames found"); + } + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::InternReadFile_GameStudioA7( ) +{ + ai_assert(NULL != pScene); + + // current cursor position in the file + const MDL::Header_MDL7* pcHeader = (const MDL::Header_MDL7*)this->m_pcHeader; + const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); + + // validate the header of the file. There are some structure + // sizes that are expected by the loader to be constant + this->ValidateHeader_GameStudioA7(pcHeader); + + // skip all bones + szCurrent += sizeof(MDL::Bone_MDL7) * pcHeader->bones_num; + + // allocate a material list + std::vector pcMats; + + // vector to hold all created meshes + std::vector avOutList; + avOutList.reserve(pcHeader->groups_num); + + // read all groups + for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) + { + const MDL::Group_MDL7* pcGroup = (const MDL::Group_MDL7*)szCurrent; + szCurrent = (const unsigned char*)(pcGroup+1); + + if (1 != pcGroup->typ) + { + // Not a triangle-based mesh + // LOGWRITE("[3DGS MDL7] Mesh group is no basing in triangles. Continuing happily"); + } + + // read all skins + pcMats.reserve(pcMats.size() + pcGroup->numskins); + for (unsigned int iSkin = 0; iSkin < (unsigned int)pcGroup->numskins;++iSkin) + { + this->ParseSkinLump_GameStudioA7(szCurrent,&szCurrent,pcMats); + } + // if we have absolutely no skin loaded we need to generate a default material + if (pcMats.empty()) + { + const int iMode = (int)aiShadingMode_Gouraud; + pcMats.push_back(new MaterialHelper()); + MaterialHelper* pcHelper = (MaterialHelper*)pcMats[0]; + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + aiColor3D clr; + clr.b = clr.g = clr.r = 0.6f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + + clr.b = clr.g = clr.r = 0.05f; + pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + } + + // now get a pointer to all texture coords in the group + const MDL::TexCoord_MDL7* pcGroupUVs = (const MDL::TexCoord_MDL7*)szCurrent; + szCurrent += pcHeader->skinpoint_stc_size * pcGroup->num_stpts; + + // now get a pointer to all triangle in the group + const MDL::Triangle_MDL7* pcGroupTris = (const MDL::Triangle_MDL7*)szCurrent; + szCurrent += pcHeader->triangle_stc_size * pcGroup->numtris; + + // now get a pointer to all vertices in the group + const MDL::Vertex_MDL7* pcGroupVerts = (const MDL::Vertex_MDL7*)szCurrent; + szCurrent += pcHeader->mainvertex_stc_size * pcGroup->numverts; + + // build output vectors + std::vector vPositions; + vPositions.resize(pcGroup->numtris * 3); + + std::vector vNormals; + vNormals.resize(pcGroup->numtris * 3); + + std::vector vTextureCoords1; + vTextureCoords1.resize(pcGroup->numtris * 3, + aiVector3D(std::numeric_limits::quiet_NaN(),0.0f,0.0f)); + + std::vector vTextureCoords2; + + bool bNeed2UV = false; + if (pcHeader->triangle_stc_size >= sizeof(MDL::Triangle_MDL7)) + { + vTextureCoords2.resize(pcGroup->numtris * 3, + aiVector3D(std::numeric_limits::quiet_NaN(),0.0f,0.0f)); + bNeed2UV = true; + } + MDL::IntFace_MDL7* pcFaces = new MDL::IntFace_MDL7[pcGroup->numtris]; + + // iterate through all triangles and build valid display lists + for (unsigned int iTriangle = 0; iTriangle < (unsigned int)pcGroup->numtris; ++iTriangle) + { + // iterate through all indices of the current triangle + for (unsigned int c = 0; c < 3;++c) + { + // validate the vertex index + unsigned int iIndex = pcGroupTris->v_index[c]; + if(iIndex > (unsigned int)pcGroup->numverts) + { + // LOG + iIndex = pcGroup->numverts-1; + } + unsigned int iOutIndex = iTriangle * 3 + c; + + // write the output face index + pcFaces[iTriangle].mIndices[c] = iOutIndex; + + // swap z and y axis + vPositions[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x; + vPositions[iOutIndex].z = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y; + vPositions[iOutIndex].y = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z; + + // now read the normal vector + if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) + { + // read the full normal vector + vNormals[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0]; + vNormals[iOutIndex].z = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1]; + vNormals[iOutIndex].y = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2]; + + // FIX: It seems to be necessary to invert all normals + vNormals[iOutIndex].x *= -1.0f; + vNormals[iOutIndex].y *= -1.0f; + vNormals[iOutIndex].z *= -1.0f; + } + else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) + { + // read the normal vector from Quake2's smart table + vNormals[iOutIndex] = *((const aiVector3D*)(&g_avNormals[std::min( + int(_AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm162index), + int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)])); + + std::swap(vNormals[iOutIndex].z,vNormals[iOutIndex].y); + } + + + // validate and process the first uv coordinate set + // ************************************************************* + const unsigned int iMin = sizeof(MDL::Triangle_MDL7)- + sizeof(MDL::SkinSet_MDL7)-sizeof(uint32_t); + + const unsigned int iMin2 = sizeof(MDL::Triangle_MDL7)- + sizeof(MDL::SkinSet_MDL7); + + if (pcHeader->triangle_stc_size >= iMin) + { + iIndex = pcGroupTris->skinsets[0].st_index[c]; + if(iIndex > (unsigned int)pcGroup->num_stpts) + { + iIndex = pcGroup->num_stpts-1; + } + + float u = pcGroupUVs[iIndex].u; + float v = 1.0f-pcGroupUVs[iIndex].v; + + vTextureCoords1[iOutIndex].x = u; + vTextureCoords1[iOutIndex].y = v; + + // assign the material index, but only if it is existing + if (pcHeader->triangle_stc_size >= iMin2) + { + pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material; + } + } + // validate and process the second uv coordinate set + // ************************************************************* + if (pcHeader->triangle_stc_size >= sizeof(MDL::Triangle_MDL7)) + { + iIndex = pcGroupTris->skinsets[1].st_index[c]; + if(iIndex > (unsigned int)pcGroup->num_stpts) + { + iIndex = pcGroup->num_stpts-1; + } + + float u = pcGroupUVs[iIndex].u; + float v = 1.0f-pcGroupUVs[iIndex].v; + + vTextureCoords2[iOutIndex].x = u; + vTextureCoords2[iOutIndex].y = v; + + // check whether we do really need the second texture + // coordinate set ... wastes memory and loading time + if (0 != iIndex && (u != vTextureCoords1[iOutIndex].x || + v != vTextureCoords1[iOutIndex].y)) + { + bNeed2UV = true; + } + // if the material differs, we need a second skin, too + if (pcGroupTris->skinsets[1].material != pcGroupTris->skinsets[0].material) + { + bNeed2UV = true; + } + + // assign the material index + pcFaces[iTriangle].iMatIndex[1] = pcGroupTris->skinsets[1].material; + } + } + + // get the next triangle in the list + pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size); + } + + // if we don't need a second set of texture coordinates there is no reason to keep it in memory ... + std::vector** aiSplit; + unsigned int iNumMaterials = 0; + if (!bNeed2UV) + { + vTextureCoords2.clear(); + + // allocate the array + aiSplit = new std::vector*[pcMats.size()]; + iNumMaterials = pcMats.size(); + + for (unsigned int m = 0; m < pcMats.size();++m) + aiSplit[m] = new std::vector(); + + // iterate through all faces and sort by material + for (unsigned int iFace = 0; iFace < (unsigned int)pcGroup->numtris;++iFace) + { + // check range + if (pcFaces[iFace].iMatIndex[0] >= iNumMaterials) + { + // use the last material instead + aiSplit[iNumMaterials-1]->push_back(iFace); + + // LOG + } + else aiSplit[pcFaces[iFace].iMatIndex[0]]->push_back(iFace); + } + } + else + { + // we need to build combined materials for each combination of + std::vector avMats; + avMats.reserve(pcMats.size()*2); + + std::vector* > aiTempSplit; + aiTempSplit.reserve(pcMats.size()*2); + + for (unsigned int m = 0; m < pcMats.size();++m) + aiTempSplit[m] = new std::vector(); + + // iterate through all faces and sort by material + for (unsigned int iFace = 0; iFace < (unsigned int)pcGroup->numtris;++iFace) + { + // check range + unsigned int iMatIndex = pcFaces[iFace].iMatIndex[0]; + if (iMatIndex >= iNumMaterials) + { + iMatIndex = iNumMaterials-1; + // LOG + } + unsigned int iMatIndex2 = pcFaces[iFace].iMatIndex[1]; + if (iMatIndex2 >= iNumMaterials) + { + iMatIndex2 = iNumMaterials-1; + // LOG + } + + // do a slow O(log(n)*n) seach in the list ... + unsigned int iNum = 0; + bool bFound = false; + for (std::vector::iterator + i = avMats.begin(); + i != avMats.end();++i,++iNum) + { + if ((*i).iOldMatIndices[0] == iMatIndex && + (*i).iOldMatIndices[1] == iMatIndex2) + { + // reuse this material + bFound = true; + break; + } + } + if (!bFound) + { + // build a new material ... + MDL::IntMaterial_MDL7 sHelper; + sHelper.pcMat = new MaterialHelper(); + sHelper.iOldMatIndices[0] = iMatIndex; + sHelper.iOldMatIndices[1] = iMatIndex2; + this->JoinSkins_GameStudioA7(pcMats[iMatIndex],pcMats[iMatIndex2],sHelper.pcMat); + + // and add it to the list + avMats.push_back(sHelper); + iNum = avMats.size()-1; + } + // adjust the size of the file array + if (iNum == aiTempSplit.size()) + { + aiTempSplit.push_back(new std::vector()); + } + aiTempSplit[iNum]->push_back(iFace); + } + + // now add the newly created materials to the old list + if (0 == iGroup) + { + pcMats.resize(avMats.size()); + for (unsigned int o = 0; o < avMats.size();++o) + pcMats[o] = avMats[o].pcMat; + } + else + { + // TODO: This might result in redundant materials ... + unsigned int iOld = pcMats.size(); + pcMats.resize(pcMats.size() + avMats.size()); + for (unsigned int o = iOld; o < avMats.size();++o) + pcMats[o] = avMats[o].pcMat; + } + iNumMaterials = pcMats.size(); + + // and build the final face-to-material array + aiSplit = new std::vector*[aiTempSplit.size()]; + for (unsigned int m = 0; m < iNumMaterials;++m) + aiSplit[m] = aiTempSplit[m]; + + // no need to delete the member of aiTempSplit + } + + // now generate output meshes + unsigned int iOldSize = avOutList.size(); + this->GenerateOutputMeshes_GameStudioA7( + (const std::vector**)aiSplit,pcMats, + avOutList,pcFaces,vPositions,vNormals, vTextureCoords1,vTextureCoords2); + + // store the group index temporarily + ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS >= 3); + for (unsigned int l = iOldSize;l < avOutList.size();++l) + { + avOutList[l]->mNumUVComponents[2] = iGroup; + } + + // delete the face-to-material helper array + for (unsigned int m = 0; m < iNumMaterials;++m) + delete aiSplit[m]; + delete[] aiSplit; + + // now we need to skip all faces + for(unsigned int iFrame = 0; iFrame < (unsigned int)pcGroup->numframes;++iFrame) + { + const MDL::Frame_MDL7* pcFrame = (const MDL::Frame_MDL7*)szCurrent; + + unsigned int iAdd = pcHeader->frame_stc_size + + pcFrame->vertices_count * pcHeader->framevertex_stc_size + + pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size; + + if (((unsigned int)szCurrent - (unsigned int)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) + { + // LOG + // don't parse more groups if we can't even read one + goto __BREAK_OUT; + } + + szCurrent += iAdd; + } + } +__BREAK_OUT: // EVIL ;-) + + // now we need to build a final mesh list + this->pScene->mNumMeshes = avOutList.size(); + this->pScene->mMeshes = new aiMesh*[avOutList.size()]; + + for (unsigned int i = 0; i < avOutList.size();++i) + { + this->pScene->mMeshes[i] = avOutList[i]; + } + + // build a final material list. Offset all mesh material indices + this->pScene->mNumMaterials = pcMats.size(); + this->pScene->mMaterials = new aiMaterial*[this->pScene->mNumMaterials]; + for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i) + this->pScene->mMaterials[i] = pcMats[i]; + + // search for referrer materials + for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i) + { + int iIndex = 0; + if (AI_SUCCESS == aiGetMaterialInteger(this->pScene->mMaterials[i], + "quakquakquak", &iIndex) ) + { + for (unsigned int a = 0; a < avOutList.size();++a) + { + if (i == avOutList[a]->mMaterialIndex) + { + avOutList[a]->mMaterialIndex = iIndex; + } + } + // TODO: Remove the material from the list + } + } + + // now generate a nodegraph whose rootnode references all meshes + this->pScene->mRootNode = new aiNode(); + this->pScene->mRootNode->mNumMeshes = this->pScene->mNumMeshes; + this->pScene->mRootNode->mMeshes = new unsigned int[this->pScene->mRootNode->mNumMeshes]; + for (unsigned int i = 0; i < this->pScene->mRootNode->mNumMeshes;++i) + this->pScene->mRootNode->mMeshes[i] = i; + + // seems we're finished now + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::GenerateOutputMeshes_GameStudioA7( + const std::vector** aiSplit, + const std::vector& pcMats, + std::vector& avOutList, + const MDL::IntFace_MDL7* pcFaces, + const std::vector& vPositions, + const std::vector& vNormals, + const std::vector& vTextureCoords1, + const std::vector& vTextureCoords2) +{ + for (unsigned int i = 0; i < pcMats.size();++i) + { + if (!aiSplit[i]->empty()) + { + // allocate the output mesh + aiMesh* pcMesh = new aiMesh(); + pcMesh->mNumUVComponents[0] = 2; + pcMesh->mMaterialIndex = i; + + // allocate output storage + pcMesh->mNumFaces = aiSplit[i]->size(); + pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; + + pcMesh->mNumVertices = pcMesh->mNumFaces*3; + pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; + + pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; + if (!vTextureCoords2.empty()) + { + pcMesh->mNumUVComponents[1] = 2; + pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices]; + } + + // iterate through all faces and build an unique set of vertices + unsigned int iCurrent = 0; + for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) + { + pcMesh->mFaces[iFace].mNumIndices = 3; + pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; + + unsigned int iSrcFace = aiSplit[i]->operator[](iFace); + const MDL::IntFace_MDL7& oldFace = pcFaces[iSrcFace]; + + // iterate through all face indices + for (unsigned int c = 0; c < 3;++c) + { + pcMesh->mVertices[iCurrent] = vPositions[oldFace.mIndices[c]]; + pcMesh->mNormals[iCurrent] = vNormals[oldFace.mIndices[c]]; + pcMesh->mTextureCoords[0][iCurrent] = vTextureCoords1[oldFace.mIndices[c]]; + + if (!vTextureCoords2.empty()) + { + pcMesh->mTextureCoords[1][iCurrent] = vTextureCoords2[oldFace.mIndices[c]]; + } + + pcMesh->mFaces[iFace].mIndices[c] = iCurrent; + ++iCurrent; + } + } + + // add the mesh to the list of output meshes + avOutList.push_back(pcMesh); + } + } + return; +} +// ------------------------------------------------------------------------------------------------ +void MDLImporter::JoinSkins_GameStudioA7( + MaterialHelper* pcMat1, + MaterialHelper* pcMat2, + MaterialHelper* pcMatOut) +{ + ai_assert(NULL != pcMat1); + ai_assert(NULL != pcMat2); + ai_assert(NULL != pcMatOut); + + // first create a full copy of the first skin property set + // and assign it to the output material + MaterialHelper::CopyPropertyList(pcMatOut,pcMat1); + + int iVal = 0; + pcMatOut->AddProperty(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0)); + + // then extract the diffuse texture from the second skin, + // setup 1 as UV source and we have it + + aiString sString; + if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) + { + iVal = 1; + pcMatOut->AddProperty(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1)); + pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1)); + } + return; +} \ No newline at end of file diff --git a/code/MDLLoader.h b/code/MDLLoader.h new file mode 100644 index 000000000..e9275c666 --- /dev/null +++ b/code/MDLLoader.h @@ -0,0 +1,241 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + +//! +//! @file Definition of MDL importer class +//! + +#ifndef AI_MDLLOADER_H_INCLUDED +#define AI_MDLLOADER_H_INCLUDED + +#include "BaseImporter.h" +#include "../include/aiTypes.h" +#include "../include/aiTexture.h" +#include "../include/aiMaterial.h" + +struct aiNode; +#include "MDLFileData.h" + +namespace Assimp +{ +class MaterialHelper; + +using namespace MDL; + +// --------------------------------------------------------------------------- +/** Used to load MDL files +*/ +class MDLImporter : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + MDLImporter(); + + /** Destructor, private as well */ + ~MDLImporter(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) + { + append.append("*.mdl"); + } + + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); + +protected: + + // ------------------------------------------------------------------- + /** Import a quake 1 MDL file + */ + void InternReadFile_Quake1( ); + + // ------------------------------------------------------------------- + /** Import a GameStudio A4/A5 file + */ + void InternReadFile_GameStudio( ); + + // ------------------------------------------------------------------- + /** Import a GameStudio A7 file + */ + void InternReadFile_GameStudioA7( ); + + // ------------------------------------------------------------------- + /** Load a paletized texture from the file and convert it to 32bpp + */ + void CreateTextureARGB8(const unsigned char* szData); + + + // ------------------------------------------------------------------- + /** Used to load textures from MDL3/4 + * \param szData Input data + * \param iType Color data type + * \param piSkip Receive: Size to skip + */ + void CreateTextureARGB8_GS4(const unsigned char* szData, + unsigned int iType, + unsigned int* piSkip); + + // ------------------------------------------------------------------- + /** Used to load textures from MDL5 + * \param szData Input data + * \param iType Color data type + * \param piSkip Receive: Size to skip + */ + void CreateTextureARGB8_GS5(const unsigned char* szData, + unsigned int iType, + unsigned int* piSkip); + + // ------------------------------------------------------------------- + /** Parse a skin lump in a MDL7 file with all of its features + * \param szCurrent Current data pointer + * \param szCurrentOut Output data pointer + * \param pcMats Material list for this group. To be filled ... + */ + void ParseSkinLump_GameStudioA7( + const unsigned char* szCurrent, + const unsigned char** szCurrentOut, + std::vector& pcMats); + + // ------------------------------------------------------------------- + /** Parse texture color data for MDL5, MDL6 and MDL7 formats + * \param szData Current data pointer + * \param iType type of the texture data. No DDS or external + * \param piSkip Receive the number of bytes to skip + * \param pcNew Must point to fully initialized data. Width and + * height must be set. + */ + void ParseTextureColorData(const unsigned char* szData, + unsigned int iType, + unsigned int* piSkip, + aiTexture* pcNew); + + // ------------------------------------------------------------------- + /** Validate the header data structure of a game studio MDL7 file + * \param pcHeader Input header to be validated + */ + void ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader); + + // ------------------------------------------------------------------- + /** Join two materials / skins. Setup UV source ... etc + * \param pcMat1 First input material + * \param pcMat2 Second input material + * \param pcMatOut Output material instance to be filled. Must be empty + */ + void JoinSkins_GameStudioA7(MaterialHelper* pcMat1, + MaterialHelper* pcMat2, + MaterialHelper* pcMatOut); + + // ------------------------------------------------------------------- + /** Generate the final output meshes for a7 models + * \param aiSplit Face-per-material list + * \param pcMats List of all materials + * \param avOutList Output: List of all meshes + * \param pcFaces List of all input faces + * \param vPositions List of all input vectors + * \param vNormals List of all input normal vectors + * \param vTextureCoords1 List of all input UV coords #1 + * \param vTextureCoords2 List of all input UV coords #2 + */ + void GenerateOutputMeshes_GameStudioA7( + const std::vector** aiSplit, + const std::vector& pcMats, + std::vector& avOutList, + const MDL::IntFace_MDL7* pcFaces, + const std::vector& vPositions, + const std::vector& vNormals, + const std::vector& vTextureCoords1, + const std::vector& vTextureCoords2); + + + // ------------------------------------------------------------------- + /** Try to load a palette from the current directory (colormap.lmp) + * If it is not found the default palette of Quake1 is returned + */ + void SearchPalette(const unsigned char** pszColorMap); + + // ------------------------------------------------------------------- + /** Free a palette created with a previous call to SearchPalette() + */ + void FreePalette(const unsigned char* pszColorMap); + +private: + + /** Header of the MDL file */ + const MDL::Header* m_pcHeader; + + /** Buffer to hold the loaded file */ + unsigned char* mBuffer; + + /** For GameStudio MDL files: The number in the magic + word, either 3,4 or 5*/ + unsigned int iGSFileVersion; + + /** Output I/O handler. used to load external lmp files + */ + IOSystem* pIOHandler; + + /** Output scene to be filled + */ + aiScene* pScene; +}; +}; // end of namespace Assimp + +#endif // AI_3DSIMPORTER_H_INC \ No newline at end of file diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 751dc0053..3217f3361 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -1,4 +1,42 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ #include "assimp.h" #include "aiMaterial.h" @@ -11,20 +49,15 @@ using namespace Assimp; -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn aiGetMaterialProperty(const aiMaterial* pMat, const char* pKey, const aiMaterialProperty** pPropOut) { -#if (defined DEBUG) - ai_assert (pMat != NULL); ai_assert (pKey != NULL); ai_assert (pPropOut != NULL); -#endif // ASSIMP_DEBUG - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { if (NULL != pMat->mProperties[i]) @@ -39,23 +72,16 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat, *pPropOut = NULL; return AI_FAILURE; } - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, const char* pKey, float* pOut, unsigned int* pMax) { -#if (defined DEBUG) - ai_assert (pMat != NULL); ai_assert (pKey != NULL); ai_assert (pOut != NULL); -#endif // ASSIMP_DEBUG - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { if (NULL != pMat->mProperties[i]) @@ -106,23 +132,15 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, } return AI_FAILURE; } - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, const char* pKey, int* pOut, unsigned int* pMax) { -#if (defined DEBUG) - ai_assert (pMat != NULL); ai_assert (pKey != NULL); ai_assert (pOut != NULL); - -#endif // ASSIMP_DEBUG - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { if (NULL != pMat->mProperties[i]) @@ -173,10 +191,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, } return AI_FAILURE; } - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn aiGetMaterialColor(const aiMaterial* pMat, const char* pKey, aiColor4D* pOut) @@ -188,22 +203,15 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat, if (3 == iMax)pOut->a = 1.0f; return eRet; } - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn aiGetMaterialString(const aiMaterial* pMat, const char* pKey, aiString* pOut) { -#if (defined DEBUG) - ai_assert (pMat != NULL); ai_assert (pKey != NULL); ai_assert (pOut != NULL); -#endif // ASSIMP_DEBUG - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { if (NULL != pMat->mProperties[i]) @@ -223,23 +231,16 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat, } return AI_FAILURE; } - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput, const unsigned int pSizeInBytes, const char* pKey, aiPropertyTypeInfo pType) { -#if (defined DEBUG) - ai_assert (pInput != NULL); ai_assert (pKey != NULL); ai_assert (0 != pSizeInBytes); -#endif // ASSIMP_DEBUG - aiMaterialProperty* pcNew = new aiMaterialProperty(); // fill this @@ -273,13 +274,146 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput, this->mProperties[this->mNumProperties++] = pcNew; return AI_SUCCESS; } - - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ aiReturn MaterialHelper::AddProperty (const aiString* pInput, const char* pKey) { return this->AddBinaryProperty(pInput, sizeof(aiString),pKey,aiPTI_String); } +// ------------------------------------------------------------------------------------------------ +void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest, + const MaterialHelper* pcSrc) +{ + ai_assert(NULL != pcDest); + ai_assert(NULL != pcSrc); + + unsigned int iOldNum = pcDest->mNumProperties; + pcDest->mNumAllocated += pcSrc->mNumAllocated; + pcDest->mNumProperties += pcSrc->mNumProperties; + + aiMaterialProperty** pcOld = pcDest->mProperties; + pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated]; + + if (pcOld) + { + for (unsigned int i = 0; i < iOldNum;++i) + pcDest->mProperties[i] = pcOld[i]; + + delete[] pcDest->mProperties; + } + for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i) + { + pcDest->mProperties[i]->mKey = new aiString(*pcSrc->mProperties[i]->mKey); + pcDest->mProperties[i]->mDataLength = pcSrc->mProperties[i]->mDataLength; + pcDest->mProperties[i]->mType = pcSrc->mProperties[i]->mType; + pcDest->mProperties[i]->mData = new char[pcDest->mProperties[i]->mDataLength]; + memcpy(pcDest->mProperties[i]->mData,pcSrc->mProperties[i]->mData, + pcDest->mProperties[i]->mDataLength); + } + return; +} +// ------------------------------------------------------------------------------------------------ +aiReturn aiGetMaterialTexture(const aiMaterial* pcMat, + unsigned int iIndex, + unsigned int iTexType, + aiString* szOut, + unsigned int* piUVIndex, + float* pfBlendFactor, + aiTextureOp* peTextureOp) +{ + ai_assert(NULL != pcMat); + ai_assert(NULL != szOut); + + const char* szPathBase; + const char* szUVBase; + const char* szBlendBase; + const char* szOpBase; + switch (iTexType) + { + case AI_TEXTYPE_DIFFUSE: + szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_; + szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_; + szBlendBase = AI_MATKEY_TEXBLEND_DIFFUSE_; + szOpBase = AI_MATKEY_TEXOP_DIFFUSE_; + break; + case AI_TEXTYPE_SPECULAR: + szPathBase = AI_MATKEY_TEXTURE_SPECULAR_; + szUVBase = AI_MATKEY_UVWSRC_SPECULAR_; + szBlendBase = AI_MATKEY_TEXBLEND_SPECULAR_; + szOpBase = AI_MATKEY_TEXOP_SPECULAR_; + break; + case AI_TEXTYPE_AMBIENT: + szPathBase = AI_MATKEY_TEXTURE_AMBIENT_; + szUVBase = AI_MATKEY_UVWSRC_AMBIENT_; + szBlendBase = AI_MATKEY_TEXBLEND_AMBIENT_; + szOpBase = AI_MATKEY_TEXOP_AMBIENT_; + break; + case AI_TEXTYPE_EMISSIVE: + szPathBase = AI_MATKEY_TEXTURE_EMISSIVE_; + szUVBase = AI_MATKEY_UVWSRC_EMISSIVE_; + szBlendBase = AI_MATKEY_TEXBLEND_EMISSIVE_; + szOpBase = AI_MATKEY_TEXOP_EMISSIVE_; + break; + case AI_TEXTYPE_HEIGHT: + szPathBase = AI_MATKEY_TEXTURE_HEIGHT_; + szUVBase = AI_MATKEY_UVWSRC_HEIGHT_; + szBlendBase = AI_MATKEY_TEXBLEND_HEIGHT_; + szOpBase = AI_MATKEY_TEXOP_HEIGHT_; + break; + case AI_TEXTYPE_NORMALS: + szPathBase = AI_MATKEY_TEXTURE_NORMALS_; + szUVBase = AI_MATKEY_UVWSRC_NORMALS_; + szBlendBase = AI_MATKEY_TEXBLEND_NORMALS_; + szOpBase = AI_MATKEY_TEXOP_NORMALS_; + break; + case AI_TEXTYPE_SHININESS: + szPathBase = AI_MATKEY_TEXTURE_SHININESS_; + szUVBase = AI_MATKEY_UVWSRC_SHININESS_; + szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_; + szOpBase = AI_MATKEY_TEXOP_SHININESS_; + break; + default: return AI_FAILURE; + }; + + char szKey[256]; + + // get the path to the texture + sprintf(szKey,"%s[%i]",szPathBase,iIndex); + if (AI_SUCCESS != aiGetMaterialString(pcMat,szKey,szOut)) + { + return AI_FAILURE; + } + // get the UV index of the texture + if (piUVIndex) + { + int iUV; + sprintf(szKey,"%s[%i]",szUVBase,iIndex); + if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,&iUV)) + iUV = 0; + + *piUVIndex = iUV; + } + // get the blend factor of the texture + if (pfBlendFactor) + { + float fBlend; + sprintf(szKey,"%s[%i]",szBlendBase,iIndex); + if (AI_SUCCESS != aiGetMaterialFloat(pcMat,szKey,&fBlend)) + fBlend = 1.0f; + + *pfBlendFactor = fBlend; + } + // get the texture operation of the texture + if (peTextureOp) + { + aiTextureOp op; + sprintf(szKey,"%s[%i]",szOpBase,iIndex); + if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&op)) + op = aiTextureOp_Multiply; + + *peTextureOp = op; + } + return AI_SUCCESS; +} + diff --git a/code/MaterialSystem.h b/code/MaterialSystem.h index 8afe0c1ad..37ab3eec4 100644 --- a/code/MaterialSystem.h +++ b/code/MaterialSystem.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definition of the base class for all importer worker classes. */ #ifndef AI_MATERIALSYSTEM_H_INC #define AI_MATERIALSYSTEM_H_INC @@ -8,6 +48,15 @@ namespace Assimp { // --------------------------------------------------------------------------- +/** \brief Helper function to do platform independent string comparison. + * + * This is required since stricmp() is not consistently available on + * all platforms. Some platforms use the '_' prefix, others don't even + * have such a function. Yes, this is called an ISO standard. + * + * \param s1 First input string + * \param s2 Second input string + */ // --------------------------------------------------------------------------- inline int ASSIMP_stricmp(const char *s1, const char *s2) { @@ -28,6 +77,16 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) } // --------------------------------------------------------------------------- +/** \brief Helper function to do platform independent string comparison. + * + * This is required since strincmp() is not consistently available on + * all platforms. Some platforms use the '_' prefix, others don't even + * have such a function. Yes, this is called an ISO standard. + * + * \param s1 First input string + * \param s2 Second input string + * \param n Macimum number of characters to compare + */ // --------------------------------------------------------------------------- inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) { @@ -58,14 +117,20 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) structure easily. */ class MaterialHelper : public ::aiMaterial { - public: +public: inline MaterialHelper(); inline ~MaterialHelper(); // ------------------------------------------------------------------- /** Add a property with a given key and type info to the material - structure */ + * structure + * + * \param pInput Pointer to input data + * \param pSizeInBytes Size of input data + * \param pKey Key/Usage of the property (AI_MATKEY_XXX) + * \param pType Type information hint + */ aiReturn AddBinaryProperty (const void* pInput, const unsigned int pSizeInBytes, const char* pKey, @@ -74,17 +139,33 @@ class MaterialHelper : public ::aiMaterial // ------------------------------------------------------------------- /** Add a string property with a given key and type info to the - material structure */ + * material structure + * + * \param pInput Input string + * \param pKey Key/Usage of the property (AI_MATKEY_XXX) + */ aiReturn AddProperty (const aiString* pInput, const char* pKey); // ------------------------------------------------------------------- - /** Add a property with a given key to the material structure */ + /** Add a property with a given key to the material structure + * \param pInput Pointer to the input data + * \param pNumValues Number of values in the array + * \param pKey Key/Usage of the property (AI_MATKEY_XXX) + */ template aiReturn AddProperty (const TYPE* pInput, const unsigned int pNumValues, const char* pKey); + + // ------------------------------------------------------------------- + /** Copy the property list of a material + * \param pcDest Destination material + * \param pcSrc Source material + */ + static void CopyPropertyList(MaterialHelper* pcDest, + const MaterialHelper* pcSrc); }; diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 8361c7b1a..c97428559 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + #ifndef OBJ_FILEDATA_H_INC #define OBJ_FILEDATA_H_INC @@ -128,16 +169,16 @@ struct Model //! Vector with all generated group std::vector m_GroupLib; //! Vector with all generated vertices - std::vector m_Vertices; + std::vector m_Vertices; //! vector with all generated normals - std::vector m_Normals; + std::vector m_Normals; //! Groupmap GroupMap m_Groups; std::vector *m_pGroupFaceIDs; //! Active group std::string m_strActiveGroup; //! Vector with generated texture coordinates - std::vector m_TextureCoord; + std::vector m_TextureCoord; //! Material map std::map m_MaterialMap; diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index a263b383b..0ea6f2dba 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -260,7 +260,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, // Copy all stored vertices, normals and so on pMesh->mNumVertices = pModel->m_Vertices.size(); - pMesh->mVertices = new aiVector3D_t[pMesh->mNumVertices]; + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; for (size_t index=0; index < pModel->m_Vertices.size(); index++) { pMesh->mVertices[ index ] = *pModel->m_Vertices[ index ]; @@ -268,7 +268,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, if (!pModel->m_Normals.empty()) { - pMesh->mNormals = new aiVector3D_t[pModel->m_Normals.size()]; + pMesh->mNormals = new aiVector3D[pModel->m_Normals.size()]; for (size_t index = 0; index < pModel->m_Normals.size(); index++) { pMesh->mNormals[ index ] = *pModel->m_Normals[ index ]; diff --git a/code/ObjFileImporter.h b/code/ObjFileImporter.h index 5fd7dbb82..7ee8c318b 100644 --- a/code/ObjFileImporter.h +++ b/code/ObjFileImporter.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + #ifndef OBJ_FILE_IMPORTER_H_INC #define OBJ_FILE_IMPORTER_H_INC @@ -39,6 +80,13 @@ public: bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; private: + + //! brief + void GetExtensionList(std::string& append) + { + append.append("*.obj"); + } + //! \brief void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); diff --git a/code/ObjFileMtlImporter.h b/code/ObjFileMtlImporter.h index 7db3707fc..e831b994f 100644 --- a/code/ObjFileMtlImporter.h +++ b/code/ObjFileMtlImporter.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + #ifndef OBJFILEMTLIMPORTER_H_INC #define OBJFILEMTLIMPORTER_H_INC diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index e468416dc..b533846b9 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -161,7 +161,7 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length) // ------------------------------------------------------------------- // Get values for a new 3D vector instance -void ObjFileParser::getVector3(std::vector &point3d_array) +void ObjFileParser::getVector3(std::vector &point3d_array) { float x, y, z; copyNextWord(m_buffer, BUFFERSIZE); @@ -179,7 +179,7 @@ void ObjFileParser::getVector3(std::vector &point3d_array) // ------------------------------------------------------------------- // Get values for a new 2D vector instance -void ObjFileParser::getVector2(std::vector &point2d_array) +void ObjFileParser::getVector2(std::vector &point2d_array) { float x, y; copyNextWord(m_buffer, BUFFERSIZE); diff --git a/code/ObjTools.h b/code/ObjTools.h index 5869542b1..d12886a95 100644 --- a/code/ObjTools.h +++ b/code/ObjTools.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file ObjTools.h * @brief Some helpful templates for text parsing */ diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index c84cb840d..4eda0071b 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the PLY importer class */ #include "PLYLoader.h" #include "MaterialSystem.h" @@ -172,13 +213,17 @@ void PLYImporter::InternReadFile( std::vector avColors; this->LoadVertexColor(&avColors); + // now try to load texture coordinates + std::vector avTexCoords; + this->LoadTextureCoordinates(&avTexCoords); + // now replace the default material in all faces and validate all material indices this->ReplaceDefaultMaterial(&avFaces,&avMaterials); // now convert this to a list of aiMesh instances std::vector avMeshes; this->ConvertMeshes(&avFaces,&avPositions,&avNormals, - &avColors,&avMaterials,&avMeshes); + &avColors,&avTexCoords,&avMaterials,&avMeshes); if (avMeshes.empty()) { @@ -216,6 +261,7 @@ void PLYImporter::ConvertMeshes(std::vector* avFaces, const std::vector* avPositions, const std::vector* avNormals, const std::vector* avColors, + const std::vector* avTexCoords, const std::vector* avMaterials, std::vector* avOut) { @@ -258,6 +304,11 @@ void PLYImporter::ConvertMeshes(std::vector* avFaces, if (!avColors->empty()) p_pcOut->mColors[0] = new aiColor4D[iNum]; + if (!avTexCoords->empty()) + { + p_pcOut->mNumUVComponents[0] = 2; + p_pcOut->mTextureCoords[0] = new aiVector3D[iNum]; + } if (!avNormals->empty()) p_pcOut->mNormals = new aiVector3D[iNum]; @@ -272,53 +323,26 @@ void PLYImporter::ConvertMeshes(std::vector* avFaces, p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices]; // build an unique set of vertices/colors for this face - // hardcode all combinations to speedup this piece of code - if (!avColors->empty()) + for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) { + p_pcOut->mFaces[iNum].mIndices[q] = iVertex; + p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; + + if (!avColors->empty()) + p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]]; + + if (!avTexCoords->empty()) + { + const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]]; + p_pcOut->mTextureCoords[0][iVertex].x = vec.x; + p_pcOut->mTextureCoords[0][iVertex].y = vec.y; + } + if (!avNormals->empty()) - { - for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) - { - p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; - p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]]; - p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]]; - iVertex++; - } - } - else - { - for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) - { - p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; - p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]]; - iVertex++; - } - } - } - else - { - if (!avNormals->empty()) - { - for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) - { - p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; - p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]]; - iVertex++; - } - } - else - { - for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) - { - p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; - iVertex++; - } - } + p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]]; + iVertex++; } + } // add the mesh to the output list avOut->push_back(p_pcOut); @@ -370,8 +394,79 @@ void PLYImporter::ReplaceDefaultMaterial(std::vector* avFaces, return; } // ------------------------------------------------------------------------------------------------ +void PLYImporter::LoadTextureCoordinates(std::vector* pvOut) +{ + ai_assert(NULL != pvOut); + + unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF}; + PLY::EDataType aiTypes[2]; + PLY::ElementInstanceList* pcList = NULL; + unsigned int cnt = 0; + + // serach in the DOM for a vertex entry + unsigned int _i = 0; + for (std::vector::const_iterator + i = this->pcDOM->alElements.begin(); + i != this->pcDOM->alElements.end();++i,++_i) + { + if (PLY::EEST_Vertex == (*i)->eSemantic) + { + pcList = this->pcDOM->alElementData[_i]; + + // now check whether which normal components are available + unsigned int _a = 0; + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) + { + if ((*a)->bIsList)continue; + if (PLY::EST_UTextureCoord == (*a)->Semantic) + { + cnt++; + aiPositions[0] = _a; + aiTypes[0] = (*a)->eType; + } + else if (PLY::EST_VTextureCoord == (*a)->Semantic) + { + cnt++; + aiPositions[1] = _a; + aiTypes[1] = (*a)->eType; + } + } + } + } + // check whether we have a valid source for the texture coordinates data + if (NULL != pcList && 0 != cnt) + { + pvOut->reserve(pcList->alInstances.size()); + for (std::vector::const_iterator + i = pcList->alInstances.begin(); + i != pcList->alInstances.end();++i) + { + // convert the vertices to sp floats + aiVector2D vOut; + + if (0xFFFFFFFF != aiPositions[0]) + { + vOut.x = PLY::PropertyInstance::ConvertTo( + (*i)->alProperties[aiPositions[0]].avList.front(),aiTypes[0]); + } + + if (0xFFFFFFFF != aiPositions[1]) + { + vOut.y = PLY::PropertyInstance::ConvertTo( + (*i)->alProperties[aiPositions[1]].avList.front(),aiTypes[1]); + } + // and add them to our nice list + pvOut->push_back(vOut); + } + } +} +// ------------------------------------------------------------------------------------------------ void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) { + ai_assert(NULL != pvOut); + unsigned int aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; PLY::EDataType aiTypes[3]; PLY::ElementInstanceList* pcList = NULL; @@ -379,43 +474,42 @@ void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) // serach in the DOM for a vertex entry unsigned int _i = 0; - for (std::vector::const_iterator + for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); i != this->pcDOM->alElements.end();++i,++_i) { - if (PLY::EEST_Vertex == (*i).eSemantic) + if (PLY::EEST_Vertex == (*i)->eSemantic) { - pcList = &this->pcDOM->alElementData[_i]; + pcList = this->pcDOM->alElementData[_i]; // load normal vectors? if (p_bNormals) { // now check whether which normal components are available unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) { - if ((*a).bIsList)continue; - if (PLY::EST_XNormal == (*a).Semantic) + if ((*a)->bIsList)continue; + if (PLY::EST_XNormal == (*a)->Semantic) { cnt++; aiPositions[0] = _a; - aiTypes[0] = (*a).eType; + aiTypes[0] = (*a)->eType; } - else if (PLY::EST_YNormal == (*a).Semantic) + else if (PLY::EST_YNormal == (*a)->Semantic) { cnt++; aiPositions[1] = _a; - aiTypes[1] = (*a).eType; + aiTypes[1] = (*a)->eType; } - else if (PLY::EST_ZNormal == (*a).Semantic) + else if (PLY::EST_ZNormal == (*a)->Semantic) { cnt++; aiPositions[2] = _a; - aiTypes[2] = (*a).eType; + aiTypes[2] = (*a)->eType; } - if (3 == cnt)break; } } // load vertex coordinates @@ -423,28 +517,28 @@ void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) { // now check whether which coordinate sets are available unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) { - if ((*a).bIsList)continue; - if (PLY::EST_XCoord == (*a).Semantic) + if ((*a)->bIsList)continue; + if (PLY::EST_XCoord == (*a)->Semantic) { cnt++; aiPositions[0] = _a; - aiTypes[0] = (*a).eType; + aiTypes[0] = (*a)->eType; } - else if (PLY::EST_YCoord == (*a).Semantic) + else if (PLY::EST_YCoord == (*a)->Semantic) { cnt++; aiPositions[1] = _a; - aiTypes[1] = (*a).eType; + aiTypes[1] = (*a)->eType; } - else if (PLY::EST_ZCoord == (*a).Semantic) + else if (PLY::EST_ZCoord == (*a)->Semantic) { cnt++; aiPositions[2] = _a; - aiTypes[2] = (*a).eType; + aiTypes[2] = (*a)->eType; } if (3 == cnt)break; } @@ -456,32 +550,29 @@ void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) if (NULL != pcList && 0 != cnt) { pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end();++i) { // convert the vertices to sp floats aiVector3D vOut; - if (0xFFFFFFFF == aiPositions[0])vOut.x = 0.0f; - else + if (0xFFFFFFFF != aiPositions[0]) { vOut.x = PLY::PropertyInstance::ConvertTo( - (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]); + (*i)->alProperties[aiPositions[0]].avList.front(),aiTypes[0]); } - if (0xFFFFFFFF == aiPositions[1])vOut.y = 0.0f; - else + if (0xFFFFFFFF != aiPositions[1]) { vOut.y = PLY::PropertyInstance::ConvertTo( - (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]); + (*i)->alProperties[aiPositions[1]].avList.front(),aiTypes[1]); } - if (0xFFFFFFFF == aiPositions[2])vOut.z = 0.0f; - else + if (0xFFFFFFFF != aiPositions[2]) { vOut.z = PLY::PropertyInstance::ConvertTo( - (*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]); + (*i)->alProperties[aiPositions[2]].avList.front(),aiTypes[2]); } // and add them to our nice list @@ -491,7 +582,8 @@ void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) return; } // ------------------------------------------------------------------------------------------------ -float NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,PLY::EDataType eType) +float PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val, + PLY::EDataType eType) { switch (eType) { @@ -518,6 +610,8 @@ float NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,PLY::EDataType // ------------------------------------------------------------------------------------------------ void PLYImporter::LoadVertexColor(std::vector* pvOut) { + ai_assert(NULL != pvOut); + unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; PLY::EDataType aiTypes[4]; unsigned int cnt = 0; @@ -525,44 +619,44 @@ void PLYImporter::LoadVertexColor(std::vector* pvOut) // serach in the DOM for a vertex entry unsigned int _i = 0; - for (std::vector::const_iterator + for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); i != this->pcDOM->alElements.end();++i,++_i) { - if (PLY::EEST_Vertex == (*i).eSemantic) + if (PLY::EEST_Vertex == (*i)->eSemantic) { - pcList = &this->pcDOM->alElementData[_i]; + pcList = this->pcDOM->alElementData[_i]; // now check whether which coordinate sets are available unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) { - if ((*a).bIsList)continue; - if (PLY::EST_Red == (*a).Semantic) + if ((*a)->bIsList)continue; + if (PLY::EST_Red == (*a)->Semantic) { cnt++; aiPositions[0] = _a; - aiTypes[0] = (*a).eType; + aiTypes[0] = (*a)->eType; } - else if (PLY::EST_Green == (*a).Semantic) + else if (PLY::EST_Green == (*a)->Semantic) { cnt++; aiPositions[1] = _a; - aiTypes[1] = (*a).eType; + aiTypes[1] = (*a)->eType; } - else if (PLY::EST_Blue == (*a).Semantic) + else if (PLY::EST_Blue == (*a)->Semantic) { cnt++; aiPositions[2] = _a; - aiTypes[2] = (*a).eType; + aiTypes[2] = (*a)->eType; } - else if (PLY::EST_Alpha == (*a).Semantic) + else if (PLY::EST_Alpha == (*a)->Semantic) { cnt++; aiPositions[3] = _a; - aiTypes[3] = (*a).eType; + aiTypes[3] = (*a)->eType; } if (4 == cnt)break; } @@ -573,31 +667,28 @@ void PLYImporter::LoadVertexColor(std::vector* pvOut) if (NULL != pcList && 0 != cnt) { pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end();++i) { // convert the vertices to sp floats aiColor4D vOut; - if (0xFFFFFFFF == aiPositions[0])vOut.r = 0.0f; - else + if (0xFFFFFFFF != aiPositions[0]) { - vOut.r = NormalizeColorValue((*i).alProperties[ + vOut.r = NormalizeColorValue((*i)->alProperties[ aiPositions[0]].avList.front(),aiTypes[0]); } - if (0xFFFFFFFF == aiPositions[1])vOut.g = 0.0f; - else + if (0xFFFFFFFF != aiPositions[1]) { - vOut.g = NormalizeColorValue((*i).alProperties[ + vOut.g = NormalizeColorValue((*i)->alProperties[ aiPositions[1]].avList.front(),aiTypes[1]); } - if (0xFFFFFFFF == aiPositions[2])vOut.b = 0.0f; - else + if (0xFFFFFFFF != aiPositions[2]) { - vOut.b = NormalizeColorValue((*i).alProperties[ + vOut.b = NormalizeColorValue((*i)->alProperties[ aiPositions[2]].avList.front(),aiTypes[2]); } @@ -605,7 +696,7 @@ void PLYImporter::LoadVertexColor(std::vector* pvOut) if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f; else { - vOut.a = NormalizeColorValue((*i).alProperties[ + vOut.a = NormalizeColorValue((*i)->alProperties[ aiPositions[3]].avList.front(),aiTypes[3]); } @@ -619,6 +710,8 @@ void PLYImporter::LoadVertexColor(std::vector* pvOut) // ------------------------------------------------------------------------------------------------ void PLYImporter::LoadFaces(std::vector* pvOut) { + ai_assert(NULL != pvOut); + PLY::ElementInstanceList* pcList = NULL; bool bOne = false; @@ -633,54 +726,54 @@ void PLYImporter::LoadFaces(std::vector* pvOut) // serach in the DOM for a face entry unsigned int _i = 0; - for (std::vector::const_iterator + for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); i != this->pcDOM->alElements.end();++i,++_i) { // face = unique number of vertex indices - if (PLY::EEST_Face == (*i).eSemantic) + if (PLY::EEST_Face == (*i)->eSemantic) { - pcList = &this->pcDOM->alElementData[_i]; + pcList = this->pcDOM->alElementData[_i]; unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) { - if (PLY::EST_VertexIndex == (*a).Semantic) + if (PLY::EST_VertexIndex == (*a)->Semantic) { // must be a dynamic list! - if (!(*a).bIsList)continue; + if (!(*a)->bIsList)continue; iProperty = _a; bOne = true; - eType = (*a).eType; + eType = (*a)->eType; } - else if (PLY::EST_MaterialIndex == (*a).Semantic) + else if (PLY::EST_MaterialIndex == (*a)->Semantic) { - if ((*a).bIsList)continue; + if ((*a)->bIsList)continue; iMaterialIndex = _a; bOne = true; - eType2 = (*a).eType; + eType2 = (*a)->eType; } } break; } // triangle strip // TODO: triangle strip and material index support??? - else if (PLY::EEST_TriStrip == (*i).eSemantic) + else if (PLY::EEST_TriStrip == (*i)->eSemantic) { // find a list property in this ... - pcList = &this->pcDOM->alElementData[_i]; + pcList = this->pcDOM->alElementData[_i]; unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) { // must be a dynamic list! - if (!(*a).bIsList)continue; + if (!(*a)->bIsList)continue; iProperty = _a; bOne = true; bIsTristrip = true; - eType = (*a).eType; + eType = (*a)->eType; break; } break; @@ -692,7 +785,7 @@ void PLYImporter::LoadFaces(std::vector* pvOut) if (!bIsTristrip) { pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end();++i) { @@ -701,11 +794,19 @@ void PLYImporter::LoadFaces(std::vector* pvOut) // parse the list of vertex indices if (0xFFFFFFFF != iProperty) { - const unsigned int iNum = (*i).alProperties[iProperty].avList.size(); + const unsigned int iNum = (*i)->alProperties[iProperty].avList.size(); sFace.mIndices.resize(iNum); + if (3 > iNum) + { + // We must filter out all degenerates. Leave a message + // in the log ... + // LOG + continue; + } + std::list::const_iterator p = - (*i).alProperties[iProperty].avList.begin(); + (*i)->alProperties[iProperty].avList.begin(); for (unsigned int a = 0; a < iNum;++a,++p) { @@ -717,7 +818,7 @@ void PLYImporter::LoadFaces(std::vector* pvOut) if (0xFFFFFFFF != iMaterialIndex) { sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo( - (*i).alProperties[iMaterialIndex].avList.front(),eType2); + (*i)->alProperties[iMaterialIndex].avList.front(),eType2); } pvOut->push_back(sFace); } @@ -726,14 +827,14 @@ void PLYImporter::LoadFaces(std::vector* pvOut) { // normally we have only one triangle strip instance where // a value of -1 indicates a restart of the strip - for (std::vector::const_iterator + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end();++i) { int aiTable[2] = {-1,-1}; for (std::list::const_iterator - a = (*i).alProperties[iProperty].avList.begin(); - a != (*i).alProperties[iProperty].avList.end();++a) + a = (*i)->alProperties[iProperty].avList.begin(); + a != (*i)->alProperties[iProperty].avList.end();++a) { int p = PLY::PropertyInstance::ConvertTo(*a,eType); if (-1 == p) @@ -768,10 +869,10 @@ void PLYImporter::LoadFaces(std::vector* pvOut) return; } // ------------------------------------------------------------------------------------------------ -void GetMaterialColor(const std::vector& avList, - unsigned int aiPositions[4], - PLY::EDataType aiTypes[4], - aiColor4D* clrOut) +void PLYImporter::GetMaterialColor(const std::vector& avList, + unsigned int aiPositions[4], + PLY::EDataType aiTypes[4], + aiColor4D* clrOut) { ai_assert(NULL != clrOut); @@ -809,6 +910,8 @@ void GetMaterialColor(const std::vector& avList, // ------------------------------------------------------------------------------------------------ void PLYImporter::LoadMaterial(std::vector* pvOut) { + ai_assert(NULL != pvOut); + // diffuse[4], specular[4], ambient[4] // rgba order unsigned int aaiPositions[3][4] = { @@ -830,98 +933,98 @@ void PLYImporter::LoadMaterial(std::vector* pvOut) // serach in the DOM for a vertex entry unsigned int _i = 0; - for (std::vector::const_iterator + for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); i != this->pcDOM->alElements.end();++i,++_i) { - if (PLY::EEST_Material == (*i).eSemantic) + if (PLY::EEST_Material == (*i)->eSemantic) { - pcList = &this->pcDOM->alElementData[_i]; + pcList = this->pcDOM->alElementData[_i]; // now check whether which coordinate sets are available unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) + for (std::vector::const_iterator + a = (*i)->alProperties.begin(); + a != (*i)->alProperties.end();++a,++_a) { - if ((*a).bIsList)continue; + if ((*a)->bIsList)continue; // pohng specularity ----------------------------------- - if (PLY::EST_PhongPower == (*a).Semantic) + if (PLY::EST_PhongPower == (*a)->Semantic) { iPhong = _a; - ePhong = (*a).eType; + ePhong = (*a)->eType; } // general opacity ----------------------------------- - if (PLY::EST_Opacity == (*a).Semantic) + if (PLY::EST_Opacity == (*a)->Semantic) { iOpacity = _a; - eOpacity = (*a).eType; + eOpacity = (*a)->eType; } // diffuse color channels ----------------------------------- - if (PLY::EST_DiffuseRed == (*a).Semantic) + if (PLY::EST_DiffuseRed == (*a)->Semantic) { aaiPositions[0][0] = _a; - aaiTypes[0][0] = (*a).eType; + aaiTypes[0][0] = (*a)->eType; } - else if (PLY::EST_DiffuseGreen == (*a).Semantic) + else if (PLY::EST_DiffuseGreen == (*a)->Semantic) { aaiPositions[0][1] = _a; - aaiTypes[0][1] = (*a).eType; + aaiTypes[0][1] = (*a)->eType; } - else if (PLY::EST_DiffuseBlue == (*a).Semantic) + else if (PLY::EST_DiffuseBlue == (*a)->Semantic) { aaiPositions[0][2] = _a; - aaiTypes[0][2] = (*a).eType; + aaiTypes[0][2] = (*a)->eType; } - else if (PLY::EST_DiffuseAlpha == (*a).Semantic) + else if (PLY::EST_DiffuseAlpha == (*a)->Semantic) { aaiPositions[0][3] = _a; - aaiTypes[0][3] = (*a).eType; + aaiTypes[0][3] = (*a)->eType; } // specular color channels ----------------------------------- - else if (PLY::EST_SpecularRed == (*a).Semantic) + else if (PLY::EST_SpecularRed == (*a)->Semantic) { aaiPositions[1][0] = _a; - aaiTypes[1][0] = (*a).eType; + aaiTypes[1][0] = (*a)->eType; } - else if (PLY::EST_SpecularGreen == (*a).Semantic) + else if (PLY::EST_SpecularGreen == (*a)->Semantic) { aaiPositions[1][1] = _a; - aaiTypes[1][1] = (*a).eType; + aaiTypes[1][1] = (*a)->eType; } - else if (PLY::EST_SpecularBlue == (*a).Semantic) + else if (PLY::EST_SpecularBlue == (*a)->Semantic) { aaiPositions[1][2] = _a; - aaiTypes[1][2] = (*a).eType; + aaiTypes[1][2] = (*a)->eType; } - else if (PLY::EST_SpecularAlpha == (*a).Semantic) + else if (PLY::EST_SpecularAlpha == (*a)->Semantic) { aaiPositions[1][3] = _a; - aaiTypes[1][3] = (*a).eType; + aaiTypes[1][3] = (*a)->eType; } // ambient color channels ----------------------------------- - else if (PLY::EST_AmbientRed == (*a).Semantic) + else if (PLY::EST_AmbientRed == (*a)->Semantic) { aaiPositions[2][0] = _a; - aaiTypes[2][0] = (*a).eType; + aaiTypes[2][0] = (*a)->eType; } - else if (PLY::EST_AmbientGreen == (*a).Semantic) + else if (PLY::EST_AmbientGreen == (*a)->Semantic) { aaiPositions[2][1] = _a; - aaiTypes[2][1] = (*a).eType; + aaiTypes[2][1] = (*a)->eType; } - else if (PLY::EST_AmbientBlue == (*a).Semantic) + else if (PLY::EST_AmbientBlue == (*a)->Semantic) { aaiPositions[22][2] = _a; - aaiTypes[2][2] = (*a).eType; + aaiTypes[2][2] = (*a)->eType; } - else if (PLY::EST_AmbientAlpha == (*a).Semantic) + else if (PLY::EST_AmbientAlpha == (*a)->Semantic) { aaiPositions[2][3] = _a; - aaiTypes[2][3] = (*a).eType; + aaiTypes[2][3] = (*a)->eType; } } break; @@ -930,7 +1033,7 @@ void PLYImporter::LoadMaterial(std::vector* pvOut) // check whether we have a valid source for the material data if (NULL != pcList) { - for (std::vector::const_iterator + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end();++i) { @@ -938,15 +1041,15 @@ void PLYImporter::LoadMaterial(std::vector* pvOut) MaterialHelper* pcHelper = new MaterialHelper(); // build the diffuse material color - GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut); + GetMaterialColor((*i)->alProperties,aaiPositions[0],aaiTypes[0],&clrOut); pcHelper->AddProperty(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE); // build the specular material color - GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut); + GetMaterialColor((*i)->alProperties,aaiPositions[1],aaiTypes[1],&clrOut); pcHelper->AddProperty(&clrOut,1,AI_MATKEY_COLOR_SPECULAR); // build the ambient material color - GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut); + GetMaterialColor((*i)->alProperties,aaiPositions[2],aaiTypes[2],&clrOut); pcHelper->AddProperty(&clrOut,1,AI_MATKEY_COLOR_AMBIENT); // handle phong power and shading mode @@ -954,7 +1057,7 @@ void PLYImporter::LoadMaterial(std::vector* pvOut) if (0xFFFFFFFF != iPhong) { float fSpec = PLY::PropertyInstance::ConvertTo( - (*i).alProperties[iPhong].avList.front(),ePhong); + (*i)->alProperties[iPhong].avList.front(),ePhong); // if shininess is 0 (and the pow() calculation would therefore always // become 1, not depending on the angle) use gouraud lighting @@ -962,8 +1065,7 @@ void PLYImporter::LoadMaterial(std::vector* pvOut) { // scale this with 15 ... hopefully this is correct - fSpec += 15; - + fSpec *= 15; pcHelper->AddProperty(&fSpec, 1, AI_MATKEY_SHININESS); iMode = (int)aiShadingMode_Phong; @@ -977,7 +1079,7 @@ void PLYImporter::LoadMaterial(std::vector* pvOut) if (0xFFFFFFFF != iOpacity) { float fOpacity = PLY::PropertyInstance::ConvertTo( - (*i).alProperties[iPhong].avList.front(),eOpacity); + (*i)->alProperties[iPhong].avList.front(),eOpacity); pcHelper->AddProperty(&fOpacity, 1, AI_MATKEY_OPACITY); } diff --git a/code/PlyLoader.h b/code/PlyLoader.h index 6c8915126..8b4a316dc 100644 --- a/code/PlyLoader.h +++ b/code/PlyLoader.h @@ -1,4 +1,45 @@ -/** @file Definition of the .ply importer class. */ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + +/** @file Declaration of the .ply importer class. */ #ifndef AI_PLYLOADER_H_INCLUDED #define AI_PLYLOADER_H_INCLUDED @@ -11,88 +52,124 @@ struct aiNode; namespace Assimp { - class MaterialHelper; +class MaterialHelper; - using namespace PLY; +using namespace PLY; - // --------------------------------------------------------------------------- - /** Used to load PLY files - */ - class PLYImporter : public BaseImporter +// --------------------------------------------------------------------------- +/** Used to load PLY files +*/ +class PLYImporter : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + PLYImporter(); + + /** Destructor, private as well */ + ~PLYImporter(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) { - friend class Importer; + append.append("*.ply"); + } - protected: - /** Constructor to be privately used by Importer */ - PLYImporter(); + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); - /** Destructor, private as well */ - ~PLYImporter(); - - public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; - - protected: - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - protected: +protected: - // ------------------------------------------------------------------- - /** Extract vertices from the DOM - */ - void LoadVertices(std::vector* pvOut,bool p_bNormals = false); + // ------------------------------------------------------------------- + /** Extract vertices from the DOM + */ + void LoadVertices(std::vector* pvOut, + bool p_bNormals = false); - // ------------------------------------------------------------------- - /** Extract vertex color channels - */ - void LoadVertexColor(std::vector* pvOut); + // ------------------------------------------------------------------- + /** Extract vertex color channels from the DOM + */ + void LoadVertexColor(std::vector* pvOut); - // ------------------------------------------------------------------- - /** Extract a face list from the DOM - */ - void LoadFaces(std::vector* pvOut); + // ------------------------------------------------------------------- + /** Extract texture coordinate channels from the DOM + */ + void LoadTextureCoordinates(std::vector* pvOut); - // ------------------------------------------------------------------- - /** Extract a material list from the DOM - */ - void LoadMaterial(std::vector* pvOut); + // ------------------------------------------------------------------- + /** Extract a face list from the DOM + */ + void LoadFaces(std::vector* pvOut); + + // ------------------------------------------------------------------- + /** Extract a material list from the DOM + */ + void LoadMaterial(std::vector* pvOut); - // ------------------------------------------------------------------- - /** Validate material indices, replace default material identifiers - */ - void ReplaceDefaultMaterial(std::vector* avFaces, - std::vector* avMaterials); + // ------------------------------------------------------------------- + /** Validate material indices, replace default material identifiers + */ + void ReplaceDefaultMaterial(std::vector* avFaces, + std::vector* avMaterials); - // ------------------------------------------------------------------- - /** Convert all meshes into our ourer representation - */ - void ConvertMeshes(std::vector* avFaces, - const std::vector* avPositions, - const std::vector* avNormals, - const std::vector* avColors, - const std::vector* avMaterials, - std::vector* avOut); + // ------------------------------------------------------------------- + /** Convert all meshes into our ourer representation + */ + void ConvertMeshes(std::vector* avFaces, + const std::vector* avPositions, + const std::vector* avNormals, + const std::vector* avColors, + const std::vector* avTexCoords, + const std::vector* avMaterials, + std::vector* avOut); - /** Buffer to hold the loaded file */ - unsigned char* mBuffer; + // ------------------------------------------------------------------- + /** Static helper to parse a color from four single channels in + */ + static void GetMaterialColor( + const std::vector& avList, + unsigned int aiPositions[4], + PLY::EDataType aiTypes[4], + aiColor4D* clrOut); - /** Document object model representation extracted from the file */ - PLY::DOM* pcDOM; - }; + + // ------------------------------------------------------------------- + /** Static helper to parse a color channel value. The input value + * is normalized to 0-1. + */ + static float NormalizeColorValue ( + PLY::PropertyInstance::ValueUnion val, + PLY::EDataType eType); + + + /** Buffer to hold the loaded file */ + unsigned char* mBuffer; + + /** Document object model representation extracted from the file */ + PLY::DOM* pcDOM; +}; } // end of namespace Assimp diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index d82c46a0d..83d5577d0 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -1,4 +1,46 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the PLY parser class */ + #include "PLYLoader.h" #include "MaterialSystem.h" #include "fast_atof.h" @@ -13,7 +55,6 @@ using namespace Assimp; - // ------------------------------------------------------------------------------------------------ PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_szOut) { @@ -100,22 +141,7 @@ PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_sz PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_szOut) { PLY::ESemantic eOut = PLY::EST_INVALID; - if (0 == ASSIMP_strincmp(p_szIn,"x",1)) - { - p_szIn++; - eOut = PLY::EST_XCoord; - } - else if (0 == ASSIMP_strincmp(p_szIn,"y",1)) - { - p_szIn++; - eOut = PLY::EST_YCoord; - } - else if (0 == ASSIMP_strincmp(p_szIn,"z",1)) - { - p_szIn++; - eOut = PLY::EST_ZCoord; - } - else if (0 == ASSIMP_strincmp(p_szIn,"red",3)) + if (0 == ASSIMP_strincmp(p_szIn,"red",3)) { p_szIn+=3; eOut = PLY::EST_Red; @@ -235,6 +261,41 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz p_szIn++; eOut = PLY::EST_Blue; } + else if (0 == ASSIMP_strincmp(p_szIn,"tx",2)) + { + p_szIn+=2; + eOut = PLY::EST_UTextureCoord; + } + else if (0 == ASSIMP_strincmp(p_szIn,"ty",2)) + { + p_szIn+=2; + eOut = PLY::EST_VTextureCoord; + } + else if (0 == ASSIMP_strincmp(p_szIn,"u",1)) + { + p_szIn++; + eOut = PLY::EST_UTextureCoord; + } + else if (0 == ASSIMP_strincmp(p_szIn,"v",1)) + { + p_szIn++; + eOut = PLY::EST_VTextureCoord; + } + else if (0 == ASSIMP_strincmp(p_szIn,"x",1)) + { + p_szIn++; + eOut = PLY::EST_XCoord; + } + else if (0 == ASSIMP_strincmp(p_szIn,"y",1)) + { + p_szIn++; + eOut = PLY::EST_YCoord; + } + else if (0 == ASSIMP_strincmp(p_szIn,"z",1)) + { + p_szIn++; + eOut = PLY::EST_ZCoord; + } else { // ... find the next space or new line @@ -250,7 +311,9 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz return eOut; } // ------------------------------------------------------------------------------------------------ -bool PLY::Property::ParseProperty (const char* p_szIn, const char** p_szOut, PLY::Property* pOut) +bool PLY::Property::ParseProperty (const char* p_szIn, + const char** p_szOut, + PLY::Property* pOut) { // Forms supported: // "property float x" @@ -320,7 +383,8 @@ bool PLY::Property::ParseProperty (const char* p_szIn, const char** p_szOut, PLY return true; } // ------------------------------------------------------------------------------------------------ -PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,const char** p_szOut) +PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn, + const char** p_szOut) { PLY::EElementSemantic eOut = PLY::EEST_INVALID; if (0 == ASSIMP_strincmp(p_szIn,"vertex",6)) @@ -365,8 +429,9 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,const char* return eOut; } // ------------------------------------------------------------------------------------------------ -bool PLY::Element::ParseElement (const char* p_szIn, const char** p_szOut, - PLY::Element* pOut) +bool PLY::Element::ParseElement (const char* p_szIn, + const char** p_szOut, + PLY::Element* pOut) { // Example format: "element vertex 8" *p_szOut = p_szIn; @@ -410,8 +475,8 @@ bool PLY::Element::ParseElement (const char* p_szIn, const char** p_szOut, // skip all comments PLY::DOM::SkipComments(p_szIn,&p_szIn); - Property prop; - if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,&prop))break; + PLY::Property* prop = new PLY::Property(); + if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,prop))break; // add the property to the property list pOut->alProperties.push_back(prop); @@ -420,7 +485,8 @@ bool PLY::Element::ParseElement (const char* p_szIn, const char** p_szOut, return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::SkipComments (const char* p_szIn,const char** p_szOut) +bool PLY::DOM::SkipComments (const char* p_szIn, + const char** p_szOut) { *p_szOut = p_szIn; @@ -451,8 +517,8 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut) // skip all comments PLY::DOM::SkipComments(p_szIn,&p_szIn); - Element out; - if(PLY::Element::ParseElement(p_szIn,&p_szIn,&out)) + PLY::Element* out = new PLY::Element(); + if(PLY::Element::ParseElement(p_szIn,&p_szIn,out)) { // add the element to the list of elements this->alElements.push_back(out); @@ -470,34 +536,39 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut) return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceLists (const char* p_szIn,const char** p_szOut) +bool PLY::DOM::ParseElementInstanceLists ( + const char* p_szIn, + const char** p_szOut) { this->alElementData.resize(this->alElements.size()); - std::vector::const_iterator i = this->alElements.begin(); - std::vector::iterator a = this->alElementData.begin(); + std::vector::const_iterator i = this->alElements.begin(); + std::vector::iterator a = this->alElementData.begin(); // parse all element instances for (;i != this->alElements.end();++i,++a) { - *a = PLY::ElementInstanceList(&(*i)); // reserve enough storage - PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,&(*i),&(*a)); + *a = new PLY::ElementInstanceList((*i)); // reserve enough storage + PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,(*i),(*a)); } return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceListsBinary (const char* p_szIn,const char** p_szOut,bool p_bBE) +bool PLY::DOM::ParseElementInstanceListsBinary ( + const char* p_szIn, + const char** p_szOut, + bool p_bBE) { this->alElementData.resize(this->alElements.size()); - std::vector::const_iterator i = this->alElements.begin(); - std::vector::iterator a = this->alElementData.begin(); + std::vector::const_iterator i = this->alElements.begin(); + std::vector::iterator a = this->alElementData.begin(); // parse all element instances for (;i != this->alElements.end();++i,++a) { - *a = PLY::ElementInstanceList(&(*i)); // reserve enough storage - PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,&(*i),&(*a),p_bBE); + *a = new PLY::ElementInstanceList((*i)); // reserve enough storage + PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,(*i),(*a),p_bBE); } return true; } @@ -549,8 +620,8 @@ bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char* { PLY::DOM::SkipComments(p_szIn,&p_szIn); - PLY::ElementInstance out; - PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, &out); + PLY::ElementInstance* out = new PLY::ElementInstance(); + PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, out); // add it to the list p_pcOut->alInstances[i] = out; } @@ -559,8 +630,12 @@ bool PLY::ElementInstanceList::ParseInstanceList (const char* p_szIn,const char* return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstanceList::ParseInstanceListBinary (const char* p_szIn,const char** p_szOut, - const PLY::Element* pcElement, PLY::ElementInstanceList* p_pcOut,bool p_bBE) +bool PLY::ElementInstanceList::ParseInstanceListBinary ( + const char* p_szIn, + const char** p_szOut, + const PLY::Element* pcElement, + PLY::ElementInstanceList* p_pcOut, + bool p_bBE /* = false */) { // we can add special handling code for unknown element semantics since // we can't skip it as a whole block (we don't know its exact size @@ -568,8 +643,8 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (const char* p_szIn,const // of the unknown element) for (unsigned int i = 0; i < pcElement->NumOccur;++i) { - PLY::ElementInstance out; - PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, &out, p_bBE); + PLY::ElementInstance* out = new PLY::ElementInstance(); + PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, out, p_bBE); // add it to the list p_pcOut->alInstances[i] = out; } @@ -577,24 +652,28 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (const char* p_szIn,const return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstance (const char* p_szIn,const char** p_szOut, - const PLY::Element* pcElement, PLY::ElementInstance* p_pcOut) +bool PLY::ElementInstance::ParseInstance ( + const char* p_szIn, + const char** p_szOut, + const PLY::Element* pcElement, + PLY::ElementInstance* p_pcOut) { if (!SkipSpaces(p_szIn, &p_szIn))return false; + // allocate enough storage p_pcOut->alProperties.resize(pcElement->alProperties.size()); *p_szOut = p_szIn; - std::vector::iterator i = p_pcOut->alProperties.begin(); - std::vector::const_iterator a = pcElement->alProperties.begin(); + std::vector::iterator i = p_pcOut->alProperties.begin(); + std::vector::const_iterator a = pcElement->alProperties.begin(); for (;i != p_pcOut->alProperties.end();++i,++a) { - if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,&(*a),&(*i)))) + if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i)))) { // skip the rest of the instance SkipLine(p_szIn, &p_szIn); - PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); + PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType); (*i).avList.push_back(v); } } @@ -602,19 +681,24 @@ bool PLY::ElementInstance::ParseInstance (const char* p_szIn,const char** p_szOu return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstanceBinary (const char* p_szIn,const char** p_szOut, - const PLY::Element* pcElement, PLY::ElementInstance* p_pcOut, bool p_bBE) +bool PLY::ElementInstance::ParseInstanceBinary ( + const char* p_szIn, + const char** p_szOut, + const PLY::Element* pcElement, + PLY::ElementInstance* p_pcOut, + bool p_bBE /* = false */) { + // allocate enough storage p_pcOut->alProperties.resize(pcElement->alProperties.size()); *p_szOut = p_szIn; - std::vector::iterator i = p_pcOut->alProperties.begin(); - std::vector::const_iterator a = pcElement->alProperties.begin(); + std::vector::iterator i = p_pcOut->alProperties.begin(); + std::vector::const_iterator a = pcElement->alProperties.begin(); for (;i != p_pcOut->alProperties.end();++i,++a) { - if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,&(*a),&(*i)))) + if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i)))) { - PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); + PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType); (*i).avList.push_back(v); } } diff --git a/code/PlyParser.h b/code/PlyParser.h index 3ae80c439..cc6dbf488 100644 --- a/code/PlyParser.h +++ b/code/PlyParser.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + /** @file Defines the helper data structures for importing PLY files */ #ifndef AI_PLYFILEHELPER_H_INC #define AI_PLYFILEHELPER_H_INC @@ -54,9 +95,9 @@ enum EDataType }; // --------------------------------------------------------------------------------- -/** \brief Specifies semantics for PLY element properties +/** \brief Specifies semantics for PLY element properties * - * Semantics define the usage of a property, e.g. x coordinate + * Semantics define the usage of a property, e.g. x coordinate */ enum ESemantic { @@ -73,6 +114,11 @@ enum ESemantic EST_YNormal, //! vertex normal z coordinate EST_ZNormal, + + //! u texture coordinate + EST_UTextureCoord, + //! v texture coordinate + EST_VTextureCoord, //! vertex colors, red channel EST_Red, @@ -133,9 +179,9 @@ enum ESemantic }; // --------------------------------------------------------------------------------- -/** \brief Specifies semantics for PLY elements +/** \brief Specifies semantics for PLY elements * - * Semantics define the usage of an element, e.g. vertex or material + * Semantics define the usage of an element, e.g. vertex or material */ enum EElementSemantic { @@ -159,9 +205,9 @@ enum EElementSemantic }; // --------------------------------------------------------------------------------- -/** \brief Helper class for a property in a PLY file. +/** \brief Helper class for a property in a PLY file. * - * This can e.g. be a part of the vertex declaration + * This can e.g. be a part of the vertex declaration */ class Property { @@ -187,6 +233,7 @@ public: bool bIsList; EDataType eFirstType; + // ------------------------------------------------------------------- //! Parse a property from a string. The end of the //! string is either '\n', '\r' or '\0'. Return valie is false //! if the input string is NOT a valid property (E.g. does @@ -194,18 +241,20 @@ public: static bool ParseProperty (const char* p_szIn, const char** p_szOut, Property* pOut); + // ------------------------------------------------------------------- //! Parse a data type from a string static EDataType ParseDataType(const char* p_szIn,const char** p_szOut); + // ------------------------------------------------------------------- //! Parse a semantic from a string static ESemantic ParseSemantic(const char* p_szIn,const char** p_szOut); }; // --------------------------------------------------------------------------------- -/** \brief Helper class for an element in a PLY file. +/** \brief Helper class for an element in a PLY file. * - * This can e.g. be the vertex declaration. Elements contain a - * well-defined number of properties. + * This can e.g. be the vertex declaration. Elements contain a + * well-defined number of properties. */ class Element { @@ -216,9 +265,22 @@ public: : NumOccur(0), eSemantic (EEST_INVALID) {} + //! Destructor. Dallocates all storage + ~Element() + { + // delete all elements + for (std::vector::const_iterator + i = this->alProperties.begin(); + i != this->alProperties.end();++i) + { + delete (*i); + } + return; + } + //! List of properties assigned to the element //! std::vector to support operator[] - std::vector alProperties; + std::vector alProperties; //! Semantic of the element EElementSemantic eSemantic; @@ -230,19 +292,22 @@ public: //! How many times will the element occur? unsigned int NumOccur; + + // ------------------------------------------------------------------- //! Parse an element from a string. //! The function will parse all properties contained in the //! element, too. static bool ParseElement (const char* p_szIn, const char** p_szOut, Element* pOut); + // ------------------------------------------------------------------- //! Parse a semantic from a string static EElementSemantic ParseSemantic(const char* p_szIn, const char** p_szOut); }; // --------------------------------------------------------------------------------- -/** \brief Instance of a property in a PLY file +/** \brief Instance of a property in a PLY file */ class PropertyInstance { @@ -271,36 +336,43 @@ public: }; + // ------------------------------------------------------------------- //! List of all values parsed. Contains only one value // for non-list propertys std::list avList; + // ------------------------------------------------------------------- //! Parse a property instance static bool ParseInstance (const char* p_szIn,const char** p_szOut, const Property* prop, PropertyInstance* p_pcOut); + // ------------------------------------------------------------------- //! Parse a property instance in binary format static bool ParseInstanceBinary (const char* p_szIn,const char** p_szOut, const Property* prop, PropertyInstance* p_pcOut,bool p_bBE); + // ------------------------------------------------------------------- //! Get the default value for a given data type static ValueUnion DefaultValue(EDataType eType); + // ------------------------------------------------------------------- //! Parse a value static bool ParseValue(const char* p_szIn,const char** p_szOut, EDataType eType,ValueUnion* out); + // ------------------------------------------------------------------- //! Parse a binary value static bool ParseValueBinary(const char* p_szIn,const char** p_szOut, EDataType eType,ValueUnion* out,bool p_bBE); + // ------------------------------------------------------------------- //! Convert a property value to a given type TYPE template static TYPE ConvertTo(ValueUnion v, EDataType eType); }; // --------------------------------------------------------------------------------- -/** \brief Class for an element instance in a PLY file +/** \brief Class for an element instance in a PLY file */ class ElementInstance { @@ -313,17 +385,19 @@ public: //! List of all parsed properties std::vector< PropertyInstance > alProperties; + // ------------------------------------------------------------------- //! Parse an element instance static bool ParseInstance (const char* p_szIn,const char** p_szOut, const Element* pcElement, ElementInstance* p_pcOut); + // ------------------------------------------------------------------- //! Parse a binary element instance static bool ParseInstanceBinary (const char* p_szIn,const char** p_szOut, const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE); }; // --------------------------------------------------------------------------------- -/** \brief Class for an element instance list in a PLY file +/** \brief Class for an element instance list in a PLY file */ class ElementInstanceList { @@ -333,25 +407,42 @@ public: ElementInstanceList () {} + //! Construction from a given element description ElementInstanceList (const Element* pc) { + // reserve enough storage to speedup the process alInstances.reserve(pc->NumOccur); } - //! List of all element instances - std::vector< ElementInstance > alInstances; + //! Destructor. Dallocates all storage + ~ElementInstanceList() + { + // delete all elements + for (std::vector::const_iterator + i = this->alInstances.begin(); + i != this->alInstances.end();++i) + { + delete (*i); + } + return; + } + //! List of all element instances + std::vector< ElementInstance* > alInstances; + + // ------------------------------------------------------------------- //! Parse an element instance list static bool ParseInstanceList (const char* p_szIn,const char** p_szOut, const Element* pcElement, ElementInstanceList* p_pcOut); + // ------------------------------------------------------------------- //! Parse a binary element instance list static bool ParseInstanceListBinary (const char* p_szIn,const char** p_szOut, const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE); }; // --------------------------------------------------------------------------------- -/** \brief Class to represent the document object model of an ASCII or binary - * (both little and big-endian) PLY file +/** \brief Class to represent the document object model of an ASCII or binary + * (both little and big-endian) PLY file */ class DOM { @@ -361,9 +452,30 @@ public: DOM() {} + //! Destructor. Dallocates all storage + ~DOM() + { + // delete all elements + for (std::vector::const_iterator + i = this->alElements.begin(); + i != this->alElements.end();++i) + { + delete (*i); + } + // delete all instance lists + for (std::vector::const_iterator + i = this->alElementData.begin(); + i != this->alElementData.end();++i) + { + delete (*i); + } + return; + } - std::vector alElements; - std::vector alElementData; + //! Contains all elements of the file format + std::vector alElements; + //! Contains the real data of each element's instance list + std::vector alElementData; //! Parse the DOM for a PLY file. The input string is assumed //! to be terminated with zero @@ -376,19 +488,22 @@ public: private: + // ------------------------------------------------------------------- //! Handle the file header and read all element descriptions bool ParseHeader (const char* p_szIn,const char** p_szOut); + // ------------------------------------------------------------------- //! Read in all element instance lists bool ParseElementInstanceLists (const char* p_szIn,const char** p_szOut); + // ------------------------------------------------------------------- //! Read in all element instance lists for a binary file format bool ParseElementInstanceListsBinary (const char* p_szIn, const char** p_szOut,bool p_bBE); }; // --------------------------------------------------------------------------------- -/** \brief Helper class to represent a loaded face +/** \brief Helper class to represent a loaded PLY face */ class Face { @@ -434,6 +549,8 @@ TYPE PLY::PropertyInstance::ConvertTo( }; return (TYPE)0; } +}; + // --------------------------------------------------------------------------------- inline bool IsSpace( const char in) { @@ -476,8 +593,6 @@ inline void SkipSpacesAndLineEnd( const char* in, const char** out) while (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n')in++; *out = in; } - -}; }; #endif // !! include guard \ No newline at end of file diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index ea2c71f72..fad57134f 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the helper class to quickly find vertices close to a given position */ #include #include "SpatialSort.h" diff --git a/code/SpatialSort.h b/code/SpatialSort.h index 5ae9736ad..a6e5579f9 100644 --- a/code/SpatialSort.h +++ b/code/SpatialSort.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** Small helper classes to optimise finding vertizes close to a given location */ #ifndef AI_SPATIALSORT_H_INC #define AI_SPATIALSORT_H_INC diff --git a/code/SplitLargeMeshes.cpp b/code/SplitLargeMeshes.cpp index 725b756da..d26b64720 100644 --- a/code/SplitLargeMeshes.cpp +++ b/code/SplitLargeMeshes.cpp @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + /** @file Implementation of the SplitLargeMeshes postprocessing step */ #include "SplitLargeMeshes.h" @@ -7,27 +48,56 @@ using namespace Assimp; -// Constructor to be privately used by Importer -SplitLargeMeshesProcess::SplitLargeMeshesProcess() +/*static*/ unsigned int SplitLargeMeshesProcess_Triangle::LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES; +/*static*/ unsigned int SplitLargeMeshesProcess_Vertex::LIMIT = AI_SLM_DEFAULT_MAX_VERTICES; + +extern "C" { + +// ------------------------------------------------------------------------------------------------ +aiReturn aiSetVertexSplitLimit(unsigned int pLimit) +{ + if (0 == pLimit) { + SplitLargeMeshesProcess_Vertex::LIMIT = 0xFFFFFFFF; + return AI_FAILURE; } -// Destructor, private as well -SplitLargeMeshesProcess::~SplitLargeMeshesProcess() + SplitLargeMeshesProcess_Vertex::LIMIT = pLimit; + return AI_SUCCESS; +} +// ------------------------------------------------------------------------------------------------ +aiReturn aiSetTriangleSplitLimit(unsigned int pLimit) +{ + if (0 == pLimit) + { + SplitLargeMeshesProcess_Triangle::LIMIT = 0xFFFFFFFF; + return AI_FAILURE; + } + + SplitLargeMeshesProcess_Triangle::LIMIT = pLimit; + return AI_SUCCESS; +} +}; //! extern "C" + +// ------------------------------------------------------------------------------------------------ +SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() + { + // nothing to do here + } +// ------------------------------------------------------------------------------------------------ +SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() { // nothing to do here } - // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool SplitLargeMeshesProcess::IsActive( unsigned int pFlags) const +bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const { - return (pFlags & aiProcess_SplitLargeMeshes) != 0; + return (pFlags & aiProcess_SplitLargeMeshes) != 0 && (0xFFFFFFFF != LIMIT); } - // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void SplitLargeMeshesProcess::Execute( aiScene* pScene) +void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) { std::vector > avList; @@ -51,12 +121,10 @@ void SplitLargeMeshesProcess::Execute( aiScene* pScene) } // ------------------------------------------------------------------------------------------------ // Update a node after some meshes have been split -void SplitLargeMeshesProcess::UpdateNode(aiNode* pcNode, +void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector >& avList) { // for every index in out list build a new entry - // TODO: Currently O(n^2) - std::vector aiEntries; aiEntries.reserve(pcNode->mNumMeshes + 1); for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) @@ -81,25 +149,22 @@ void SplitLargeMeshesProcess::UpdateNode(aiNode* pcNode, // recusively update all other nodes for (unsigned int i = 0; i < pcNode->mNumChildren;++i) { - this->UpdateNode ( pcNode->mChildren[i], avList ); + UpdateNode ( pcNode->mChildren[i], avList ); } return; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void SplitLargeMeshesProcess::SplitMesh( +void SplitLargeMeshesProcess_Triangle::SplitMesh( unsigned int a, aiMesh* pMesh, std::vector >& avList) { - // TODO: Mesh splitting is currently not supported for meshes - // containing bones - - if (pMesh->mNumVertices > AI_SLM_MAX_VERTICES && 0 == pMesh->mNumBones) + if (pMesh->mNumFaces > LIMIT) { // we need to split this mesh into sub meshes // determine the size of a submesh - const unsigned int iSubMeshes = (pMesh->mNumVertices / AI_SLM_MAX_VERTICES) + 1; + const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1; const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes; const unsigned int iOutVertexNum = iOutFaceNum * 3; @@ -162,19 +227,25 @@ void SplitLargeMeshesProcess::SplitMesh( } // (we will also need to copy the array of indices) + unsigned int iCurrent = 0; for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) { pcMesh->mFaces[p].mNumIndices = 3; - // allocate a new array - unsigned int* pi = pMesh->mFaces[p + iBase].mIndices; - pcMesh->mFaces[p].mIndices = new unsigned int[3]; + const unsigned int iTemp = p + iBase; + const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices; + + // setup face type and number of indices + pcMesh->mFaces[p].mNumIndices = iNumIndices; + unsigned int* pi = pMesh->mFaces[iTemp].mIndices; + + pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices]; // and copy the contents of the old array, offset by current base - for (unsigned int v = 0; v < 3;++v) + for (unsigned int v = 0; v < iNumIndices;++v) { - unsigned int iIndex = pMesh->mFaces[p+iBase].mIndices[v]; - unsigned int iIndexOut = p*3 + v; + unsigned int iIndex = pMesh->mFaces[iTemp].mIndices[v]; + unsigned int iIndexOut = iCurrent++; pcMesh->mFaces[p].mIndices[v] = iIndexOut; // copy positions @@ -224,4 +295,222 @@ void SplitLargeMeshesProcess::SplitMesh( } else avList.push_back(std::pair(pMesh,a)); return; -} \ No newline at end of file +} +// ------------------------------------------------------------------------------------------------ +SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() + { + // nothing to do here + } +// ------------------------------------------------------------------------------------------------ +SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() + { + // nothing to do here + } +// ------------------------------------------------------------------------------------------------ +// Returns whether the processing step is present in the given flag field. +bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const +{ + return (pFlags & aiProcess_SplitLargeMeshes) != 0 && (0xFFFFFFFF != LIMIT); +} +// ------------------------------------------------------------------------------------------------ +// Executes the post processing step on the given imported data. +void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) +{ + std::vector > avList; + + for( unsigned int a = 0; a < pScene->mNumMeshes; a++) + this->SplitMesh(a, pScene->mMeshes[a],avList); + + if (avList.size() != pScene->mNumMeshes) + { + // it seems something has been splitted. rebuild the mesh list + delete[] pScene->mMeshes; + pScene->mNumMeshes = avList.size(); + pScene->mMeshes = new aiMesh*[avList.size()]; + + for (unsigned int i = 0; i < avList.size();++i) + pScene->mMeshes[i] = avList[i].first; + + // now we need to update all nodes + SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList); + } + return; +} +// ------------------------------------------------------------------------------------------------ +// Executes the post processing step on the given imported data. +void SplitLargeMeshesProcess_Vertex::SplitMesh( + unsigned int a, + aiMesh* pMesh, + std::vector >& avList) +{ + if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) + { + // we need to split this mesh into sub meshes + // determine the estimated size of a submesh + // (this could be too large. Max waste is a single digit percentage) + const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1; + const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes; + + // create a std::vector to indicate which vertices + // have already been copied + std::vector avWasCopied; + avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF); + + // try to find a good estimate for the number of output faces + // per mesh. Add 12.5% as buffer + unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes; + iEstimatedSize += iEstimatedSize >> 3; + + // now generate all submeshes + unsigned int iBase = 0; + while (true) + { + const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT; + + aiMesh* pcMesh = new aiMesh; + pcMesh->mNumVertices = 0; + pcMesh->mMaterialIndex = pMesh->mMaterialIndex; + + // clear the temporary helper array + if (0 != iBase) + { + memset(&avWasCopied[0],0xFF,pMesh->mNumVertices * sizeof(unsigned int)); + } + + // output vectors + std::vector vFaces; + + // reserve enough storage for most cases + if (pMesh->HasPositions()) + { + pcMesh->mVertices = new aiVector3D[iOutVertexNum]; + } + if (pMesh->HasNormals()) + { + pcMesh->mNormals = new aiVector3D[iOutVertexNum]; + } + if (pMesh->HasTangentsAndBitangents()) + { + pcMesh->mTangents = new aiVector3D[iOutVertexNum]; + pcMesh->mBitangents = new aiVector3D[iOutVertexNum]; + } + for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) + { + pcMesh->mColors[c] = new aiColor4D[iOutVertexNum]; + } + for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) + { + pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; + pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum]; + } + vFaces.reserve(iEstimatedSize); + + // (we will also need to copy the array of indices) + while (iBase < pMesh->mNumFaces) + { + // allocate a new array + const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices; + + // doesn't catch degenerates but is quite fast + unsigned int iNeed = 0; + for (unsigned int v = 0; v < iNumIndices;++v) + { + unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; + + // check whether we do already have this vertex + if (0xFFFFFFFF == avWasCopied[iIndex]) + { + iNeed++; + } + } + if (pcMesh->mNumVertices + iNeed > iOutVertexNum) + { + // don't use this face + break; + } + + vFaces.push_back(aiFace()); + aiFace& rFace = vFaces.back(); + + // setup face type and number of indices + rFace.mNumIndices = iNumIndices; + rFace.mIndices = new unsigned int[iNumIndices]; + + // and copy the contents of the old array, offset by current base + for (unsigned int v = 0; v < iNumIndices;++v) + { + unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; + + // check whether we do already have this vertex + if (0xFFFFFFFF != avWasCopied[iIndex]) + { + rFace.mIndices[v] = avWasCopied[iIndex]; + continue; + } + + // copy positions + pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]); + + // copy normals + if (pMesh->HasNormals()) + { + pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]); + } + + // copy tangents/bitangents + if (pMesh->HasTangentsAndBitangents()) + { + pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]); + pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]); + } + + // texture coordinates + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) + { + if (pMesh->HasTextureCoords( c)) + { + pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex]; + } + } + // vertex colors + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) + { + if (pMesh->HasVertexColors( c)) + { + pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex]; + } + } + rFace.mIndices[v] = pcMesh->mNumVertices; + avWasCopied[iIndex] = pcMesh->mNumVertices; + pcMesh->mNumVertices++; + } + iBase++; + if(pcMesh->mNumVertices == iOutVertexNum) + { + // break here. The face is only added if it was complete + break; + } + } + // copy the face list to the mesh + pcMesh->mFaces = new aiFace[vFaces.size()]; + pcMesh->mNumFaces = vFaces.size(); + + for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) + pcMesh->mFaces[p] = vFaces[p]; + + // add the newly created mesh to the list + avList.push_back(std::pair(pcMesh,a)); + + if (iBase == pMesh->mNumFaces) + { + // have all faces ... finish the outer loop, too + break; + } + } + + // now delete the old mesh data + delete pMesh; + } + else avList.push_back(std::pair(pMesh,a)); + return; +} diff --git a/code/SplitLargeMeshes.h b/code/SplitLargeMeshes.h index f5edf90be..becf0fba2 100644 --- a/code/SplitLargeMeshes.h +++ b/code/SplitLargeMeshes.h @@ -1,4 +1,45 @@ -/** @file Defines a post processing step to split large meshes into submeshes*/ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Defines a post processing step to split large meshes into submeshes + */ #ifndef AI_SPLITLARGEMESHES_H_INC #define AI_SPLITLARGEMESHES_H_INC @@ -10,21 +51,32 @@ namespace Assimp { -#define AI_SLM_MAX_VERTICES 1000000 +class SplitLargeMeshesProcess_Triangle; +class SplitLargeMeshesProcess_Vertex; + +// default limit for vertices +#define AI_SLM_DEFAULT_MAX_VERTICES 1000000 + +// default limit for triangles +#define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000 // --------------------------------------------------------------------------- /** Postprocessing filter to split large meshes into submeshes + * + * Applied BEFORE the JoinVertices-Step occurs. + * Returns NON-UNIQUE vertices, splits by triangle number. */ -class SplitLargeMeshesProcess : public BaseProcess +class SplitLargeMeshesProcess_Triangle : public BaseProcess { friend class Importer; + friend class SplitLargeMeshesProcess_Vertex; protected: /** Constructor to be privately used by Importer */ - SplitLargeMeshesProcess(); + SplitLargeMeshesProcess_Triangle(); /** Destructor, private as well */ - ~SplitLargeMeshesProcess(); + ~SplitLargeMeshesProcess_Triangle(); public: // ------------------------------------------------------------------- @@ -49,10 +101,60 @@ private: void SplitMesh (unsigned int a, aiMesh* pcMesh, std::vector >& avList); - //! Update a node in the asset after a few of its meshes - //! have been split - void UpdateNode(aiNode* pcNode, + //! Update a node in the asset after a few of its meshes have been split + static void UpdateNode(aiNode* pcNode, const std::vector >& avList); + +public: + //! Triangle limit set via aiSetTriangleSplitLimit() + static unsigned int LIMIT; +}; + + +// --------------------------------------------------------------------------- +/** Postprocessing filter to split large meshes into submeshes + * + * Applied AFTER the JoinVertices-Step occurs. + * Returns UNIQUE vertices, splits by vertex number. +*/ +class SplitLargeMeshesProcess_Vertex : public BaseProcess +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + SplitLargeMeshesProcess_Vertex(); + + /** Destructor, private as well */ + ~SplitLargeMeshesProcess_Vertex(); + +public: + // ------------------------------------------------------------------- + /** Returns whether the processing step is present in the given flag field. + * @param pFlags The processing flags the importer was called with. A bitwise + * combination of #aiPostProcessSteps. + * @return true if the process is present in this flag fields, false if not. + */ + bool IsActive( unsigned int pFlags) const; + + // ------------------------------------------------------------------- + /** Executes the post processing step on the given imported data. + * At the moment a process is not supposed to fail. + * @param pScene The imported data to work at. + */ + void Execute( aiScene* pScene); + +private: + + //! Apply the algorithm to a given mesh + void SplitMesh (unsigned int a, aiMesh* pcMesh, + std::vector >& avList); + + // NOTE: Reuse SplitLargeMeshesProcess_Triangle::UpdateNode() + +public: + //! Triangle limit set via aiSetTriangleSplitLimit() + static unsigned int LIMIT; }; } // end of namespace Assimp diff --git a/code/TriangulateProcess.h b/code/TriangulateProcess.h index 83424a549..04c59cf72 100644 --- a/code/TriangulateProcess.h +++ b/code/TriangulateProcess.h @@ -1,4 +1,46 @@ -/** @file Defines a post processing step to triangulate all faces with more than three vertices.*/ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Defines a post processing step to triangulate all faces + with more than three vertices. + */ #ifndef AI_TRIANGULATEPROCESS_H_INC #define AI_TRIANGULATEPROCESS_H_INC diff --git a/code/XFileHelper.h b/code/XFileHelper.h index 6143eb18a..e1133a6a4 100644 --- a/code/XFileHelper.h +++ b/code/XFileHelper.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + /** @file Defines the helper data structures for importing XFiles */ #ifndef AI_XFILEHELPER_H_INC #define AI_XFILEHELPER_H_INC diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index 46a6c925a..025831b6e 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -1,3 +1,43 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Implementation of the XFile importer class */ #include "XFileImporter.h" #include "XFileParser.h" @@ -586,7 +626,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector& pMeshes); + void CreateMeshes( aiScene* pScene, aiNode* pNode, + const std::vector& pMeshes); // ------------------------------------------------------------------- - /** Converts the animations from the given imported data and creates them in the scene. + /** Converts the animations from the given imported data and creates + * them in the scene. * @param pScene The scene to hold to converted animations * @param pData The data to read the animations from */ void CreateAnimations( aiScene* pScene, const XFile::Scene* pData); // ------------------------------------------------------------------- - /** Converts all materials in the given array and stores them in the scene's material list. + /** Converts all materials in the given array and stores them in the + * scene's material list. * @param pScene The scene to hold the converted materials. * @param pMaterials The material array to convert. */ - void ConvertMaterials( aiScene* pScene, const std::vector& pMaterials); + void ConvertMaterials( aiScene* pScene, + const std::vector& pMaterials); protected: /** Buffer to hold the loaded file */ diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index 001b4f481..02c3ee815 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Implementation of the XFile parser helper class */ #include "XFileParser.h" #include "XFileHelper.h" diff --git a/code/XFileParser.h b/code/XFileParser.h index 6a098b8d2..a4968e49a 100644 --- a/code/XFileParser.h +++ b/code/XFileParser.h @@ -1,3 +1,43 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Helper class to parse a XFile into a temporary structure */ #ifndef AI_XFILEPARSER_H_INC #define AI_XFILEPARSER_H_INC diff --git a/code/res/assimp.rc b/code/res/assimp.rc new file mode 100644 index 000000000..f20e901e7 --- /dev/null +++ b/code/res/assimp.rc @@ -0,0 +1,103 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x7L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040704b0" + BEGIN + VALUE "Comments", "Licensed under a 3-clause BSD license" + VALUE "CompanyName", "ASSIMP Development Team" + VALUE "FileDescription", "Free Asset Import Library " + VALUE "FileVersion", "1, 0, 0, 0" + VALUE "InternalName", "assimp" + VALUE "LegalCopyright", "Copyright (C) 2008" + VALUE "OriginalFilename", "assimp32.dll" + VALUE "ProductName", "Free Asset Import Library " + VALUE "ProductVersion", "1, 0, 0, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x407, 1200 + END +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/code/res/resource.h b/code/res/resource.h new file mode 100644 index 000000000..41ce1c5ee --- /dev/null +++ b/code/res/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by assimp.rc + +// Nächste Standardwerte für neue Objekte +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/include/ObjFileParser.h b/include/ObjFileParser.h index 6ff4c7c1a..8c9850cbe 100644 --- a/include/ObjFileParser.h +++ b/include/ObjFileParser.h @@ -1,3 +1,44 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + #ifndef OBJ_FILEPARSER_H_INC #define OBJ_FILEPARSER_H_INC @@ -38,8 +79,8 @@ private: void parseFile(); void copyNextWord(char *pBuffer, size_t length); void copyNextLine(char *pBuffer, size_t length); - void getVector3(std::vector &point3d_array); - void getVector2(std::vector &point2d_array); + void getVector3(std::vector &point3d_array); + void getVector2(std::vector &point2d_array); void skipLine(); void getFace(); void getMaterialDesc(); diff --git a/include/aiAnim.h b/include/aiAnim.h index 1a1ead0d6..49f046f16 100644 --- a/include/aiAnim.h +++ b/include/aiAnim.h @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Defines the data structures in which the imported animations are returned. */ #ifndef AI_ANIM_H_INC #define AI_ANIM_H_INC @@ -13,7 +54,7 @@ extern "C" { struct aiVectorKey { double mTime; ///< The time of this key - aiVector3D_t mValue; ///< The value of this key + C_STRUCT aiVector3D mValue; ///< The value of this key }; /** A time-value pair specifying a rotation for the given time. For joint animations @@ -22,7 +63,7 @@ struct aiVectorKey struct aiQuatKey { double mTime; ///< The time of this key - aiQuaternion_t mValue; ///< The value of this key + C_STRUCT aiQuaternion mValue; ///< The value of this key }; /** Describes the animation of a single bone. The name specifies the bone which is affected by this @@ -32,28 +73,28 @@ struct aiQuatKey struct aiBoneAnim { /** The name of the bone affected by this animation. */ - aiString mBoneName; + C_STRUCT aiString mBoneName; /** The number of position keys */ unsigned int mNumPositionKeys; /** The position keys of this animation channel. Positions are specified as 3D vector. * The array is mNumPositionKeys in size. */ - aiVectorKey* mPositionKeys; + C_STRUCT aiVectorKey* mPositionKeys; /** The number of rotation keys */ unsigned int mNumRotationKeys; /** The rotation keys of this animation channel. Rotations are given as quaternions, * which are 4D vectors. The array is mNumRotationKeys in size. */ - aiQuatKey* mRotationKeys; + C_STRUCT aiQuatKey* mRotationKeys; /** The number of scaling keys */ unsigned int mNumScalingKeys; /** The scaling keys of this animation channel. Scalings are specified as 3D vector. * The array is mNumScalingKeys in size. */ - aiVectorKey* mScalingKeys; + C_STRUCT aiVectorKey* mScalingKeys; #ifdef __cplusplus aiBoneAnim() @@ -80,7 +121,7 @@ struct aiAnimation /** The name of the animation. If the modelling package this data was exported from does support * only a single animation channel, this name is usually empty (length is zero). */ - aiString mName; + C_STRUCT aiString mName; /** Duration of the animation in ticks. */ double mDuration; @@ -92,7 +133,7 @@ struct aiAnimation /** The bone animation channels. Each channel affects a single bone. The array * is mNumBones in size. */ - aiBoneAnim** mBones; + C_STRUCT aiBoneAnim** mBones; #ifdef __cplusplus aiAnimation() diff --git a/include/aiFileIO.h b/include/aiFileIO.h index 7378da061..561a4abfe 100644 --- a/include/aiFileIO.h +++ b/include/aiFileIO.h @@ -1,6 +1,45 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Defines generic routines to access memory-mapped files - * */ #ifndef AI_FILEIO_H_INC @@ -14,11 +53,11 @@ extern "C" { struct aiFileIO; -//enum aiOrigin; -typedef aiFileIO (*aiFileOpenProc)(aiFileIO*, const char*, const char*); -typedef aiReturn (*aiFileCloseProc)(aiFileIO*); -typedef unsigned long (*aiFileReadWriteProc)(aiFileIO*, char*, unsigned int, unsigned int); -typedef unsigned long (*aiFileTellProc)(aiFileIO*); + +typedef aiFileIO (*aiFileOpenProc)(C_STRUCT aiFileIO*, const char*, const char*); +typedef aiReturn (*aiFileCloseProc)(C_STRUCT aiFileIO*); +typedef unsigned long (*aiFileReadWriteProc)(C_STRUCT aiFileIO*, char*, unsigned int, unsigned int); +typedef unsigned long (*aiFileTellProc)(C_STRUCT aiFileIO*); // --------------------------------------------------------------------------- /** Define seek origins in fseek()-style. @@ -44,13 +83,27 @@ typedef char* aiUserData; // --------------------------------------------------------------------------- struct aiFileIO { + //! User data assigned to the structure aiUserData UserData; + //! Function used to open a new file aiFileOpenProc OpenFunc; + + //! Function used to close an existing file aiFileCloseProc CloseFunc; + + //! Function used to read from a file aiFileReadWriteProc ReadFunc; + + //! Function used to write to a file aiFileReadWriteProc WriteFunc; + + //! Function used to retrieve the current + //! position of the file cursor (ftell()) aiFileTellProc TellProc; + + //! Function used to set the current position + //! of the file cursor (fseek()) aiFileSeek SeekProc; }; diff --git a/include/aiMaterial.h b/include/aiMaterial.h index aad47d8d4..8c1713b85 100644 --- a/include/aiMaterial.h +++ b/include/aiMaterial.h @@ -1,4 +1,43 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ /** @file Defines the material system of the library * @@ -24,57 +63,51 @@ enum aiPropertyTypeInfo */ aiPTI_Float = 0x1, - /** aiString data structure */ aiPTI_String = 0x3, - /** Array of Integers */ aiPTI_Integer = 0x4, - /** Simple binary buffer */ aiPTI_Buffer = 0x5, }; - // --------------------------------------------------------------------------- -/** Defines algorithms for generating UVW-coords (for texture sampling) -* procedurally. +/** Defines texture operations like add, mul ... +* */ // --------------------------------------------------------------------------- -enum aiTexUVWGen +enum aiTextureOp { - /** The view vector will be reflected to a pixel's normal. - * - * The result is used as UVW-coordinate for - * accessing a cubemap - */ - aiTexUVWGen_VIEWREFLEFT = 0x800001, + /** T = T1 * T2 + */ + aiTextureOp_Multiply = 0x0, + /** T = T1 + T2 + */ + aiTextureOp_Add = 0x1, - /** The view vector will be used as UVW-src - * - * The view vector is used as UVW-coordinate for - * accessing a cubemap - */ - aiTexUVWGen_VIEW = 0x800002, + /** T = T1 - T2 + */ + aiTextureOp_Subtract = 0x2, + /** T = T1 / T2 + */ + aiTextureOp_Divide = 0x3, - /** The view vector will be refracted to the pixel's normal. - * - * If this is used, the refraction index to be applied should - * also be contained in the material description. - * The result is used as UVW-coordinate for - * accessing a cubemap. - */ - aiTexUVWGen_VIEWREFRACT = 0x800003 + /** T = (T1 + T2) - (T1 * T2) + */ + aiTextureOp_SmoothAdd = 0x4, + + /** T = T1 + (T2-0.5) + */ + aiTextureOp_SignedAdd = 0x5 }; - // --------------------------------------------------------------------------- /** Defines all shading models supported by the library * @@ -92,12 +125,10 @@ enum aiShadingMode */ aiShadingMode_Flat = 0x1, - /** Diffuse gouraud shading. Shading on per-vertex base */ aiShadingMode_Gouraud = 0x2, - /** Diffuse/Specular Phong-Shading * * Shading is applied on per-pixel base. This is the @@ -105,7 +136,6 @@ enum aiShadingMode */ aiShadingMode_Phong = 0x3, - /** Diffuse/Specular Phong-Blinn-Shading * * Shading is applied on per-pixel base. This is a little @@ -114,7 +144,6 @@ enum aiShadingMode */ aiShadingMode_Blinn = 0x4, - /** Toon-Shading per pixel * * Shading is applied on per-pixel base. The output looks @@ -122,7 +151,6 @@ enum aiShadingMode */ aiShadingMode_Toon = 0x5, - /** OrenNayar-Shading per pixel * * Extension to standard lambertian shading, taking the @@ -131,7 +159,6 @@ enum aiShadingMode */ aiShadingMode_OrenNayar = 0x6, - /** Minnaert-Shading per pixel * * Extension to standard lambertian shading, taking the @@ -139,12 +166,10 @@ enum aiShadingMode */ aiShadingMode_Minnaert = 0x7, - /** CookTorrance-Shading per pixel */ aiShadingMode_CookTorrance = 0x8, - /** No shading at all */ aiShadingMode_NoShading = 0x8 @@ -163,14 +188,12 @@ struct aiMaterialProperty * * Keys are case insensitive. */ - aiString* mKey; - + C_STRUCT aiString* mKey; /** Size of the buffer mData is pointing to, in bytes */ unsigned int mDataLength; - /** Type information for the property. * * Defines the data layout inside the @@ -179,7 +202,6 @@ struct aiMaterialProperty */ aiPropertyTypeInfo mType; - /** Binary buffer to hold the property's value * * The buffer has no terminal character. However, @@ -199,19 +221,17 @@ struct aiMaterialProperty * for nearly all purposes. */ // --------------------------------------------------------------------------- -#ifdef __cplusplus -class aiMaterial +struct aiMaterial { +#ifdef __cplusplus protected: aiMaterial() {} public: -#else -struct aiMaterial -{ #endif // __cplusplus + /** List of all material properties loaded. */ - aiMaterialProperty** mProperties; + C_STRUCT aiMaterialProperty** mProperties; /** Number of properties loaded */ @@ -231,6 +251,11 @@ struct aiMaterial */ #define AI_MATKEY_SHADING_MODEL "$mat.shadingm" +/** @def AI_MATKEY_ENABLE_WIREFRAM +* Integer property. 1 to enable wireframe for rendering +*/ +#define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe" + /** @def AI_MATKEY_OPACITY * Defines the base opacity of the material */ @@ -297,15 +322,15 @@ struct aiMaterial #define AI_MATKEY_TEXTURE_NORMALS(N) "$tex.file.normals["#N"]" #define AI_MATKEY_TEXTURE_NORMALS_ "$tex.file.normals" -/** @def AI_MATKEY_TEXTURE_BUMP +/** @def AI_MATKEY_TEXTURE_HEIGHT * Defines a specified bumpmap texture (=heightmap) channel of the material * This is very similar to #AI_MATKEY_TEXTURE_NORMALS. It is provided * to allow applications to determine whether the input data for -* normal mapping is already a normal map or needs to be converted to -* a heightmap. +* normal mapping is already a normal map or needs to be converted from +* a heightmap to a normal map. */ -#define AI_MATKEY_TEXTURE_BUMP(N) "$tex.file.bump["#N"]" -#define AI_MATKEY_TEXTURE_BUMP_ "$tex.file.bump" +#define AI_MATKEY_TEXTURE_HEIGHT(N) "$tex.file.bump["#N"]" +#define AI_MATKEY_TEXTURE_HEIGHT_ "$tex.file.bump" /** @def AI_MATKEY_TEXTURE_SHININESS * Defines a specified shininess texture channel of the material @@ -325,37 +350,55 @@ struct aiMaterial #define AI_MATKEY_TEXOP_SPECULAR(N) "$tex.op.specular["#N"]" #define AI_MATKEY_TEXOP_EMISSIVE(N) "$tex.op.emissive["#N"]" #define AI_MATKEY_TEXOP_NORMALS(N) "$tex.op.normals["#N"]" -#define AI_MATKEY_TEXOP_BUMP(N) "$tex.op.bump["#N"]" +#define AI_MATKEY_TEXOP_HEIGHT(N) "$tex.op.bump["#N"]" #define AI_MATKEY_TEXOP_SHININESS(N) "$tex.op.shininess["#N"]" #define AI_MATKEY_TEXOP_OPACITY(N) "$tex.op.opacity["#N"]" +#define AI_MATKEY_TEXOP_DIFFUSE_ "$tex.op.diffuse" +#define AI_MATKEY_TEXOP_AMBIENT_ "$tex.op.ambient" +#define AI_MATKEY_TEXOP_SPECULAR_ "$tex.op.specular" +#define AI_MATKEY_TEXOP_EMISSIVE_ "$tex.op.emissive" +#define AI_MATKEY_TEXOP_NORMALS_ "$tex.op.normals" +#define AI_MATKEY_TEXOP_HEIGHT_ "$tex.op.bump" +#define AI_MATKEY_TEXOP_SHININESS_ "$tex.op.shininess" +#define AI_MATKEY_TEXOP_OPACITY_ "$tex.op.opacity" + #define AI_MATKEY_UVWSRC_DIFFUSE(N) "$tex.uvw.diffuse["#N"]" #define AI_MATKEY_UVWSRC_AMBIENT(N) "$tex.uvw.ambient["#N"]" #define AI_MATKEY_UVWSRC_SPECULAR(N) "$tex.uvw.specular["#N"]" #define AI_MATKEY_UVWSRC_EMISSIVE(N) "$tex.uvw.emissive["#N"]" #define AI_MATKEY_UVWSRC_NORMALS(N) "$tex.uvw.normals["#N"]" -#define AI_MATKEY_UVWSRC_BUMP(N) "$tex.uvw.bump["#N"]" +#define AI_MATKEY_UVWSRC_HEIGHT(N) "$tex.uvw.bump["#N"]" #define AI_MATKEY_UVWSRC_SHININESS(N) "$tex.uvw.shininess["#N"]" #define AI_MATKEY_UVWSRC_OPACITY(N) "$tex.uvw.opacity["#N"]" -#define AI_MATKEY_REFRACTI_DIFFUSE(N) "$tex.refracti.diffuse["#N"]" -#define AI_MATKEY_REFRACTI_AMBIENT(N) "$tex.refracti.ambient["#N"]" -#define AI_MATKEY_REFRACTI_SPECULAR(N) "$tex.refracti.specular["#N"]" -#define AI_MATKEY_REFRACTI_EMISSIVE(N) "$tex.refracti.emissive["#N"]" -#define AI_MATKEY_REFRACTI_NORMALS(N) "$tex.refracti.normals["#N"]" -#define AI_MATKEY_REFRACTI_BUMP(N) "$tex.refracti.bump["#N"]" -#define AI_MATKEY_REFRACTI_SHININESS(N) "$tex.refracti.shininess["#N"]" -#define AI_MATKEY_REFRACTI_OPACITY(N) "$tex.refracti.opacity["#N"]" +#define AI_MATKEY_UVWSRC_DIFFUSE_ "$tex.uvw.diffuse" +#define AI_MATKEY_UVWSRC_AMBIENT_ "$tex.uvw.ambient" +#define AI_MATKEY_UVWSRC_SPECULAR_ "$tex.uvw.specular" +#define AI_MATKEY_UVWSRC_EMISSIVE_ "$tex.uvw.emissive" +#define AI_MATKEY_UVWSRC_NORMALS_ "$tex.uvw.normals" +#define AI_MATKEY_UVWSRC_HEIGHT_ "$tex.uvw.bump" +#define AI_MATKEY_UVWSRC_SHININESS_ "$tex.uvw.shininess" +#define AI_MATKEY_UVWSRC_OPACITY_ "$tex.uvw.opacity" #define AI_MATKEY_TEXBLEND_DIFFUSE(N) "$tex.blend.diffuse["#N"]" #define AI_MATKEY_TEXBLEND_AMBIENT(N) "$tex.blend.ambient["#N"]" #define AI_MATKEY_TEXBLEND_SPECULAR(N) "$tex.blend.specular["#N"]" #define AI_MATKEY_TEXBLEND_EMISSIVE(N) "$tex.blend.emissive["#N"]" #define AI_MATKEY_TEXBLEND_NORMALS(N) "$tex.blend.normals["#N"]" -#define AI_MATKEY_TEXBLEND_BUMP(N) "$tex.blend.bump["#N"]" +#define AI_MATKEY_TEXBLEND_HEIGHT(N) "$tex.blend.bump["#N"]" #define AI_MATKEY_TEXBLEND_SHININESS(N) "$tex.blend.shininess["#N"]" #define AI_MATKEY_TEXBLEND_OPACITY(N) "$tex.blend.opacity["#N"]" +#define AI_MATKEY_TEXBLEND_DIFFUSE_ "$tex.blend.diffuse" +#define AI_MATKEY_TEXBLEND_AMBIENT_ "$tex.blend.ambient" +#define AI_MATKEY_TEXBLEND_SPECULAR_ "$tex.blend.specular" +#define AI_MATKEY_TEXBLEND_EMISSIVE_ "$tex.blend.emissive" +#define AI_MATKEY_TEXBLEND_NORMALS_ "$tex.blend.normals" +#define AI_MATKEY_TEXBLEND_HEIGHT_ "$tex.blend.bump" +#define AI_MATKEY_TEXBLEND_SHININESS_ "$tex.blend.shininess" +#define AI_MATKEY_TEXBLEND_OPACITY_ "$tex.blend.opacity" + #define AI_MATKEY_ORENNAYAR_ROUGHNESS "$shading.orennayar.roughness" #define AI_MATKEY_MINNAERT_DARKNESS "$shading.minnaert.darkness" @@ -379,9 +422,9 @@ struct aiMaterial * structure or NULL if the key has not been found. */ // --------------------------------------------------------------------------- -aiReturn aiGetMaterialProperty(const aiMaterial* pMat, - const char* pKey, - const aiMaterialProperty** pPropOut); +aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, + const char* pKey, + const C_STRUCT aiMaterialProperty** pPropOut); // --------------------------------------------------------------------------- @@ -395,16 +438,16 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat, * Receives the number of values (not bytes!) read. */ // --------------------------------------------------------------------------- -aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, - const char* pKey, - float* pOut, - unsigned int* pMax); +aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat, + const char* pKey, + float* pOut, + unsigned int* pMax); #ifdef __cplusplus // inline it -inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat, - const char* pKey, - float* pOut) +inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat, + const char* pKey, + float* pOut) {return aiGetMaterialFloatArray(pMat,pKey,pOut,(unsigned int*)0x0);} #else // use our friend, the C preprocessor @@ -424,16 +467,16 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat, * Receives the number of values (not bytes!) read. */ // --------------------------------------------------------------------------- -aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, - const char* pKey, - int* pOut, - unsigned int* pMax); +aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, + const char* pKey, + int* pOut, + unsigned int* pMax); #ifdef __cplusplus // inline it -inline aiReturn aiGetMaterialInteger(const aiMaterial* pMat, - const char* pKey, - int* pOut) +inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, + const char* pKey, + int* pOut) {return aiGetMaterialIntegerArray(pMat,pKey,pOut,(unsigned int*)0x0);} #else // use our friend, the C preprocessor @@ -451,9 +494,9 @@ inline aiReturn aiGetMaterialInteger(const aiMaterial* pMat, * @param pOut Pointer to a buffer to receive the result. */ // --------------------------------------------------------------------------- -aiReturn aiGetMaterialColor(const aiMaterial* pMat, - const char* pKey, - aiColor4D* pOut); +aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, + const char* pKey, + aiColor4D* pOut); // --------------------------------------------------------------------------- @@ -464,9 +507,46 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat, * @param pOut Pointer to a buffer to receive the result. */ // --------------------------------------------------------------------------- -aiReturn aiGetMaterialString(const aiMaterial* pMat, - const char* pKey, - aiString* pOut); +aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, + const char* pKey, + aiString* pOut); + + +#define AI_TEXTYPE_DIFFUSE 0x0 +#define AI_TEXTYPE_SPECULAR 0x1 +#define AI_TEXTYPE_AMBIENT 0x2 +#define AI_TEXTYPE_EMISSIVE 0x3 +#define AI_TEXTYPE_HEIGHT 0x4 +#define AI_TEXTYPE_NORMALS 0x5 +#define AI_TEXTYPE_SHININESS 0x6 + +// --------------------------------------------------------------------------- +/** Helper function to get a diffuse texture from a material + * + * This function is provided just for convinience. + * @param pMat Pointer to the input material. May not be NULL + * @param iIndex Index of the texture to retrieve. If the index is too + * large the function fails. + * @param iTexType One of the AI_TEXTYPE constants. Specifies the type of + * the texture to retrieve (e.g. diffuse, specular, height map ...) + * @param szPath Receives the output path + * NULL is no allowed as value + * @param piUVIndex Receives the UV index of the texture. + * NULL is allowed as value. + * @param pfBlendFactor Receives the blend factor for the texture + * NULL is allowed as value. + * @param peTextureOp Receives the texture operation to perform between + * this texture and the previous texture. + * NULL is allowed as value. + */ +// --------------------------------------------------------------------------- +aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat, + unsigned int iIndex, + unsigned int iTexType, + C_STRUCT aiString* szPath, + unsigned int* piUVIndex, + float* pfBlendFactor, + aiTextureOp* peTextureOp); #ifdef __cplusplus diff --git a/include/aiMatrix3x3.h b/include/aiMatrix3x3.h index 02a7b9365..bc3e6592b 100644 --- a/include/aiMatrix3x3.h +++ b/include/aiMatrix3x3.h @@ -12,7 +12,7 @@ struct aiMatrix4x4; /** Represents a column-major 3x3 matrix */ // --------------------------------------------------------------------------- -typedef struct aiMatrix3x3 +struct aiMatrix3x3 { #ifdef __cplusplus aiMatrix3x3 () : @@ -41,7 +41,7 @@ typedef struct aiMatrix3x3 float a1, a2, a3; float b1, b2, b3; float c1, c2, c3; -} aiMatrix3x3_t; +}; #ifdef __cplusplus } // end of extern C diff --git a/include/aiMatrix4x4.h b/include/aiMatrix4x4.h index 71f70254c..f2f6966a7 100644 --- a/include/aiMatrix4x4.h +++ b/include/aiMatrix4x4.h @@ -23,7 +23,7 @@ struct aiMatrix3x3; * use this for homogenious coordinates */ // --------------------------------------------------------------------------- -typedef struct aiMatrix4x4 +struct aiMatrix4x4 { #ifdef __cplusplus aiMatrix4x4 () : @@ -60,7 +60,7 @@ typedef struct aiMatrix4x4 float c1, c2, c3, c4; float d1, d2, d3, d4; -} PACK_STRUCT aiMatrix4x4_t; +} PACK_STRUCT; // Reset packing diff --git a/include/aiMesh.h b/include/aiMesh.h index fa0ba2050..d8746a2f4 100644 --- a/include/aiMesh.h +++ b/include/aiMesh.h @@ -1,4 +1,46 @@ -/** @file Defines the data structures in which the imported geometry is returned. */ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Defines the data structures in which the imported geometry is + returned by ASSIMP */ #ifndef AI_MESH_H_INC #define AI_MESH_H_INC @@ -10,31 +52,43 @@ extern "C" { // --------------------------------------------------------------------------- /** A single face in a mesh, referring to multiple vertices. -* If mNumIndices is 3, the face is a triangle, for mNumIndices > 3 it's a polygon. +* +* If mNumIndices is 3, the face is a triangle, +* for mNumIndices > 3 it's a polygon. +* Point and line primitives are rarely used and are NOT supported. However, +* a load could pass them as degenerated triangles. */ // --------------------------------------------------------------------------- struct aiFace { - unsigned int mNumIndices; ///< Number of indices defining this face. 3 for a triangle, >3 for polygon - unsigned int* mIndices; ///< Pointer to the indices array. Size of the array is given in numIndices. + //! Number of indices defining this face. 3 for a triangle, >3 for polygon + unsigned int mNumIndices; + + //! Pointer to the indices array. Size of the array is given in numIndices. + unsigned int* mIndices; #ifdef __cplusplus + + //! Default constructor aiFace() { mNumIndices = 0; mIndices = NULL; } + //! Default destructor. Delete the index array ~aiFace() { delete [] mIndices; } + //! Copy constructor. Copy the index array aiFace( const aiFace& o) { mIndices = NULL; *this = o; } + //! Assignment operator. Copy the index array const aiFace& operator = ( const aiFace& o) { if (&o == this) @@ -47,21 +101,58 @@ struct aiFace return *this; } + //! Comparison operator. Checks whether the index array + //! of two faces is identical + bool operator== (const aiFace& o) const + { + if (this->mIndices == o.mIndices)return true; + else if (this->mIndices && this->mNumIndices == o.mNumIndices) + { + for (unsigned int i = 0;i < this->mNumIndices;++i) + { + if (this->mIndices[i] != o.mIndices[i])return false; + } + return true; + } + return false; + } + + //! Inverse comparison operator. Checks whether the index + //! array of two faces is NOT identical + bool operator != (const aiFace& o) const + { + return !(*this == o); + } + #endif // __cplusplus }; // --------------------------------------------------------------------------- -/** A single influence of a bone on a vertex. */ +/** A single influence of a bone on a vertex. + */ // --------------------------------------------------------------------------- struct aiVertexWeight { - unsigned int mVertexId; ///< Index of the vertex which is influenced by the bone. - float mWeight; ///< The strength of the influence in the range (0...1). The influence from all bones at one vertex amounts to 1. + //! Index of the vertex which is influenced by the bone. + unsigned int mVertexId; + + //! The strength of the influence in the range (0...1). + //! The influence from all bones at one vertex amounts to 1. + float mWeight; #ifdef __cplusplus + + //! Default constructor aiVertexWeight() { } - aiVertexWeight( unsigned int pID, float pWeight) : mVertexId( pID), mWeight( pWeight) { } + + //! Initialisation from a given index and vertex weight factor + //! \param pID ID + //! \param pWeight Vertex weight factor + aiVertexWeight( unsigned int pID, float pWeight) + : mVertexId( pID), mWeight( pWeight) + { /* nothing to do here */ } + #endif // __cplusplus }; @@ -74,17 +165,27 @@ struct aiVertexWeight // --------------------------------------------------------------------------- struct aiBone { - aiString mName; ///< The name of the bone. - unsigned int mNumWeights; ///< The number of vertices affected by this bone - aiVertexWeight* mWeights; ///< The vertices affected by this bone - aiMatrix4x4 mOffsetMatrix; ///< Matrix that transforms from mesh space to bone space in bind pose + //! The name of the bone. + C_STRUCT aiString mName; + + //! The number of vertices affected by this bone + unsigned int mNumWeights; + + //! The vertices affected by this bone + C_STRUCT aiVertexWeight* mWeights; + + //! Matrix that transforms from mesh space to bone space in bind pose + C_STRUCT aiMatrix4x4 mOffsetMatrix; #ifdef __cplusplus + + //! Default constructor aiBone() { mNumWeights = 0; mWeights = NULL; } + //! Destructor to delete the array of vertex weights ~aiBone() { delete [] mWeights; @@ -92,31 +193,48 @@ struct aiBone #endif // __cplusplus }; +#if (!defined AI_MAX_NUMBER_OF_COLOR_SETS) /** Maximum number of vertex color sets per mesh. * -* Diffuse, specular, ambient and emissive +* Normally: Diffuse, specular, ambient and emissive +* However, one could use the vertex color sets for any other purpose, too. +* +* \note Some internal structures expect (and assert) this value +* to be at least 4 */ #define AI_MAX_NUMBER_OF_COLOR_SETS 0x4 +#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS +#if (!defined AI_MAX_NUMBER_OF_TEXTURECOORDS) -/** Maximum number of texture coord sets (UV channels) per mesh +/** Maximum number of texture coord sets (UV(W) channels) per mesh +* +* The material system uses the AI_MATKEY_UVWSRC_XXX keys to specify +* which UVW channel serves as data source for a texture, +* +* \note Some internal structures expect (and assert) this value +* to be at least 4 */ #define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x4 +#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS + // --------------------------------------------------------------------------- /** A mesh represents a geometry or model with a single material. * * It usually consists of a number of vertices and a series of primitives/faces * referencing the vertices. In addition there might be a series of bones, each -* of them addressing a number of vertices with a certain weight. Vertex data is -* presented in channels with each channel containing a single per-vertex +* of them addressing a number of vertices with a certain weight. Vertex data +* is presented in channels with each channel containing a single per-vertex * information such as a set of texture coords or a normal vector. * If a data pointer is non-null, the corresponding data stream is present. * From C++-programs you can also use the comfort functions Has*() to * test for the presence of various data streams. * * A Mesh uses only a single material which is referenced by a material ID. +* \note The mPositions member is not optional, although a Has()-Method is +* provided for it. */ struct aiMesh { @@ -134,13 +252,13 @@ struct aiMesh * This array is always present in a mesh. The array is * mNumVertices in size. */ - aiVector3D_t* mVertices; + C_STRUCT aiVector3D* mVertices; /** Vertex normals. * The array contains normalized vectors, NULL if not present. * The array is mNumVertices in size. */ - aiVector3D_t* mNormals; + C_STRUCT aiVector3D* mNormals; /** Vertex tangents. * The tangent of a vertex points in the direction of the positive @@ -149,7 +267,7 @@ struct aiMesh * @note If the mesh contains tangents, it automatically also * contains bitangents. */ - aiVector3D_t* mTangents; + C_STRUCT aiVector3D* mTangents; /** Vertex bitangents. * The bitangent of a vertex points in the direction of the positive @@ -158,20 +276,20 @@ struct aiMesh * @note If the mesh contains tangents, it automatically also contains * bitangents. */ - aiVector3D_t* mBitangents; + C_STRUCT aiVector3D* mBitangents; /** Vertex color sets. * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex * colors per vertex. NULL if not present. Each array is * mNumVertices in size if present. */ - aiColor4D_t* mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; + C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; /** Vertex texture coords, also known as UV channels. * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per * vertex. NULL if not present. The array is mNumVertices in size. */ - aiVector3D_t* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; /** Specifies the number of components for a given UV channel. * Up to three channels are supported (UVW, for accessing volume @@ -187,7 +305,7 @@ struct aiMesh * This array is always present in a mesh, its size is given * in mNumFaces. */ - aiFace* mFaces; + C_STRUCT aiFace* mFaces; /** The number of bones this mesh contains. * Can be 0, in which case the mBones array is NULL. @@ -198,7 +316,7 @@ struct aiMesh * A bone consists of a name by which it can be found in the * frame hierarchy and a set of vertex weights. */ - aiBone** mBones; + C_STRUCT aiBone** mBones; /** The material used by this mesh. * A mesh does use only a single material. If an imported model uses multiple materials, @@ -240,23 +358,40 @@ struct aiMesh delete [] mBones; } - bool HasNormals() const { return mNormals != NULL; } - bool HasTangentsAndBitangents() const { return mTangents != NULL && mBitangents != NULL; } - bool HasVertexColors( unsigned int pIndex) + //! Check whether the mesh contains positions. Should always return true + inline bool HasPositions() const + { return mVertices != NULL; } + + //! Check whether the mesh contains normal vectors + inline bool HasNormals() const + { return mNormals != NULL; } + + //! Check whether the mesh contains tangent and bitangent vectors + inline bool HasTangentsAndBitangents() const + { return mTangents != NULL && mBitangents != NULL; } + + //! Check whether the mesh contains a vertex color set + //! \param pIndex Index of the vertex color set + inline bool HasVertexColors( unsigned int pIndex) { if( pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS) return false; else return mColors[pIndex] != NULL; } - bool HasTextureCoords( unsigned int pIndex) + + //! Check whether the mesh contains a texture coordinate set + //! \param pIndex Index of the texture coordinates set + inline bool HasTextureCoords( unsigned int pIndex) { if( pIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) return false; else return mTextureCoords[pIndex] != NULL; } - bool HasBones() const { return mBones != NULL; } + //! Check whether the mesh contains bones + inline bool HasBones() const + { return mBones != NULL; } #endif // __cplusplus }; diff --git a/include/aiPostProcess.h b/include/aiPostProcess.h index acf5a9998..41b32b43d 100644 --- a/include/aiPostProcess.h +++ b/include/aiPostProcess.h @@ -1,7 +1,49 @@ +/* +Free Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + /** @file Definitions for import post processing steps */ #ifndef AI_POSTPROCESS_H_INC #define AI_POSTPROCESS_H_INC +#include "aiTypes.h" + #ifdef __cplusplus extern "C" { #endif @@ -65,12 +107,37 @@ enum aiPostProcessSteps * This is quite useful for realtime rendering where the number of vertices * is usually limited by the video driver. * - * A mesh is split if it consists of more than 1 * 10^6 vertices. This is defined - * in the internal SplitLargeMeshes.h header as AI_SLM_MAX_VERTICES. + * The split limits can be set through aiSetVertexSplitLimit() and + * aiSetTriangleSplitLimit(). The default values for this are defined + * in the internal SplitLargeMeshes.h header as AI_SLM_DEFAULT_MAX_VERTICES + * and AI_SLM_DEFAULT_MAX_TRIANGLES. */ aiProcess_SplitLargeMeshes = 0x80 }; +// --------------------------------------------------------------------------- +/** \brief Set the maximum number of vertices in a mesh. + * + * This is used by the SplitLargeMeshes PostProcess-Step to determine + * whether a mesh must be splitted or not. + * \param pLimit Vertex limit. + * \note The default value is AI_SLM_DEFAULT_MAX_VERTICES, defined in + * the internal header file SplitLargeMeshes.h + */ +aiReturn aiSetVertexSplitLimit(unsigned int pLimit); + + +// --------------------------------------------------------------------------- +/** \brief Set the maximum number of triangles in a mesh. + * + * This is used by the SplitLargeMeshes PostProcess-Step to determine + * whether a mesh must be splitted or not. + * \param pLimit Triangle limit + * \note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES, defined in + * the internal header file SplitLargeMeshes.h + */ +aiReturn aiSetTriangleSplitLimit(unsigned int pLimit); + #ifdef __cplusplus } // end of extern "C" #endif diff --git a/include/aiQuaternion.h b/include/aiQuaternion.h index 153aa495f..6e048c7f8 100644 --- a/include/aiQuaternion.h +++ b/include/aiQuaternion.h @@ -11,7 +11,7 @@ extern "C" { // --------------------------------------------------------------------------- /** Represents a quaternion in a 4D vector. */ -typedef struct aiQuaternion +struct aiQuaternion { #ifdef __cplusplus aiQuaternion() : w(0.0f), x(0.0f), y(0.0f), z(0.0f) {} @@ -23,8 +23,9 @@ typedef struct aiQuaternion aiMatrix3x3 GetMatrix() const; #endif // __cplusplus + //! w,x,y,z components of the quaternion float w, x, y, z; -} aiQuaternion_t; +} ; #ifdef __cplusplus @@ -33,43 +34,44 @@ typedef struct aiQuaternion // Constructs a quaternion from a rotation matrix inline aiQuaternion::aiQuaternion( const aiMatrix3x3 &pRotMatrix) { - float t = 1 + pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3; + float t = 1 + pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3; - // large enough - if( t > 0.00001f) - { - float s = sqrt( t) * 2.0f; - x = (pRotMatrix.b3 - pRotMatrix.c2) / s; - y = (pRotMatrix.c1 - pRotMatrix.a3) / s; - z = (pRotMatrix.a2 - pRotMatrix.b1) / s; - w = 0.25f * s; - } // else we have to check several cases - else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 ) - { - // Column 0: - float s = sqrt( 1.0f + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * 2.0f; - x = 0.25f * s; - y = (pRotMatrix.a2 + pRotMatrix.b1) / s; - z = (pRotMatrix.c1 + pRotMatrix.a3) / s; - w = (pRotMatrix.b3 - pRotMatrix.c2) / s; - } else - if( pRotMatrix.b2 > pRotMatrix.c3) - { - // Column 1: - float s = sqrt( 1.0f + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * 2.0f; - x = (pRotMatrix.a2 + pRotMatrix.b1) / s; - y = 0.25f * s; - z = (pRotMatrix.b3 + pRotMatrix.c2) / s; - w = (pRotMatrix.c1 - pRotMatrix.a3) / s; - } else - { - // Column 2: - float s = sqrt( 1.0f + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * 2.0f; - x = (pRotMatrix.c1 + pRotMatrix.a3) / s; - y = (pRotMatrix.b3 + pRotMatrix.c2) / s; - z = 0.25f * s; - w = (pRotMatrix.a2 - pRotMatrix.b1) / s; - } + // large enough + if( t > 0.00001f) + { + float s = sqrt( t) * 2.0f; + x = (pRotMatrix.b3 - pRotMatrix.c2) / s; + y = (pRotMatrix.c1 - pRotMatrix.a3) / s; + z = (pRotMatrix.a2 - pRotMatrix.b1) / s; + w = 0.25f * s; + } // else we have to check several cases + else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 ) + { + // Column 0: + float s = sqrt( 1.0f + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * 2.0f; + x = 0.25f * s; + y = (pRotMatrix.a2 + pRotMatrix.b1) / s; + z = (pRotMatrix.c1 + pRotMatrix.a3) / s; + w = (pRotMatrix.b3 - pRotMatrix.c2) / s; + } + else if( pRotMatrix.b2 > pRotMatrix.c3) + { + // Column 1: + float s = sqrt( 1.0f + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * 2.0f; + x = (pRotMatrix.a2 + pRotMatrix.b1) / s; + y = 0.25f * s; + z = (pRotMatrix.b3 + pRotMatrix.c2) / s; + w = (pRotMatrix.c1 - pRotMatrix.a3) / s; + } + else + { + // Column 2: + float s = sqrt( 1.0f + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * 2.0f; + x = (pRotMatrix.c1 + pRotMatrix.a3) / s; + y = (pRotMatrix.b3 + pRotMatrix.c2) / s; + z = 0.25f * s; + w = (pRotMatrix.a2 - pRotMatrix.b1) / s; + } } // --------------------------------------------------------------------------- diff --git a/include/aiScene.h b/include/aiScene.h index 6eb747359..dff35f1e9 100644 --- a/include/aiScene.h +++ b/include/aiScene.h @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Defines the data structures in which the imported scene is returned. */ #ifndef AI_SCENE_H_INC #define AI_SCENE_H_INC @@ -5,6 +46,7 @@ #include "aiTypes.h" #include "aiMesh.h" #include "aiMaterial.h" +#include "aiTexture.h" #include "aiAnim.h" #ifdef __cplusplus @@ -28,19 +70,19 @@ struct aiNode * The name might be empty (length of zero) but all nodes which * need to be accessed afterwards by bones or anims are usually named. */ - aiString mName; + C_STRUCT aiString mName; /** The transformation relative to the node's parent. */ aiMatrix4x4 mTransformation; /** Parent node. NULL if this node is the root node. */ - aiNode* mParent; + C_STRUCT aiNode* mParent; /** The number of child nodes of this node. */ unsigned int mNumChildren; /** The child nodes of this node. NULL if mNumChildren is 0. */ - aiNode** mChildren; + C_STRUCT aiNode** mChildren; /** The number of meshes of this node. */ unsigned int mNumMeshes; @@ -83,7 +125,7 @@ struct aiScene * was successful. Presence of further nodes depends on the * format and content of the imported file. */ - aiNode* mRootNode; + C_STRUCT aiNode* mRootNode; /** The number of meshes in the scene. */ unsigned int mNumMeshes; @@ -93,7 +135,7 @@ struct aiScene * Use the indices given in the aiNode structure to access * this array. The array is mNumMeshes in size. */ - aiMesh** mMeshes; + C_STRUCT aiMesh** mMeshes; /** The number of materials in the scene. */ unsigned int mNumMaterials; @@ -103,7 +145,7 @@ struct aiScene * Use the index given in each aiMesh structure to access this * array. The array is mNumMaterials in size. */ - aiMaterial** mMaterials; + C_STRUCT aiMaterial** mMaterials; /** The number of animations in the scene. */ unsigned int mNumAnimations; @@ -113,7 +155,18 @@ struct aiScene * All animations imported from the given file are listed here. * The array is mNumAnimations in size. */ - aiAnimation** mAnimations; + C_STRUCT aiAnimation** mAnimations; + + /** The number of textures embedded into the file */ + unsigned int mNumTextures; + + /** The array of embedded textures. + * + * Not many file formats embedd their textures into the file. + * Examples include Quake's MDL format (which is also used by + * some GameStudio™ versions) + */ + C_STRUCT aiTexture** mTextures; #ifdef __cplusplus aiScene() @@ -122,6 +175,7 @@ struct aiScene mNumMeshes = 0; mMeshes = NULL; mNumMaterials = 0; mMaterials = NULL; mNumAnimations = 0; mAnimations = NULL; + mNumTextures = 0; mTextures = NULL; } ~aiScene() @@ -136,6 +190,9 @@ struct aiScene for( unsigned int a = 0; a < mNumAnimations; a++) delete mAnimations[a]; delete [] mAnimations; + for( unsigned int a = 0; a < mNumTextures; a++) + delete mTextures[a]; + delete [] mTextures; } #endif // __cplusplus }; diff --git a/include/aiTexture.h b/include/aiTexture.h new file mode 100644 index 000000000..764a6b4f8 --- /dev/null +++ b/include/aiTexture.h @@ -0,0 +1,149 @@ + +/** + ** This file is part of the Free Asset Import Library ASSIMP. + ** ------------------------------------------------------------------------- + ** + ** ASSIMP is free software: you can redistribute it and/or modify it + ** under the terms of the GNU Lesser General Public License as published + ** by the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** ASSIMP is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public License + ** along with ASSIMP. If not, see . + ** + ** ------------------------------------------------------------------------- + **/ + +/** @file Defines texture helper structures for the library + * + * Used for file formats that embedd their textures into the file + */ + +#ifndef AI_TEXTURE_H_INC +#define AI_TEXTURE_H_INC + +#include "aiTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// --------------------------------------------------------------------------- +/** \def AI_MAKE_EMBEDDED_TEXNAME + * Used to build the reserved path name used by the material system to + * reference textures that are embedded into their corresponding + * model files. The parameter specifies the index of the texture + * (zero-based, in the aiScene::mTextures array) + */ +// --------------------------------------------------------------------------- +#if (!defined AI_MAKE_EMBEDDED_TEXNAME) +# define AI_MAKE_EMBEDDED_TEXNAME(_n_) "*" # _n_ +#endif + +// ugly compiler dependent packing stuff +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack(push,1) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error Compiler not supported. Never do this again. +#endif + +// --------------------------------------------------------------------------- +/** Helper structure to represent a texel in ARGB8888 format +* +* Used by aiTexture +*/ +// --------------------------------------------------------------------------- +struct aiTexel +{ + unsigned char b; + unsigned char g; + unsigned char r; + unsigned char a; +} PACK_STRUCT; + +// reset packing to the original value +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop ) +#endif +#undef PACK_STRUCT + +// --------------------------------------------------------------------------- +/** Helper structure to describe an embedded texture +* +* Normally textures are contained in external files but some file formats +* do embedd them. Embedded +*/ +// --------------------------------------------------------------------------- +struct aiTexture +{ + /** Width of the texture, in pixels + * + * If mHeight is zero the texture is compressedin a format + * like JPEG. In this case mWidth specifies the size of the + * memory area pcData is pointing to, in bytes. + */ + unsigned int mWidth; + + /** Height of the texture, in pixels + * + * If this value is zero, pcData points to an compressed texture + * in an unknown format (e.g. JPEG). + */ + unsigned int mHeight; + + /** A hint from the loader to make it easier for applications + * to determine the type of embedded compressed textures. + * + * If mHeight != 0 this member is undefined. Otherwise it + * will be set to '\0\0\0\0' if the loader has no additional + * information about the texture file format used OR the + * file extension of the format without a leading dot. + * E.g. 'dds\0', 'pcx\0' + */ + char achFormatHint[4]; + + /** Data of the texture. + * + * Points to an array of mWidth * mHeight aiTexel's. + * The format of the texture data is always ARGB8888 to + * make the implementation for user of the library as easy + * as possible. If mHeight = 0 this is a pointer to a memory + * buffer of size mWidth containing the compressed texture + * data. Good luck, have fun! + */ + aiTexel* pcData; + +#ifdef __cplusplus + + // Construction + aiTexture () + : mHeight(0), mWidth(0), pcData(NULL) + { + achFormatHint[0] = '\0'; + achFormatHint[1] = '\0'; + achFormatHint[2] = '\0'; + achFormatHint[3] = '\0'; + } + + // Destruction + ~aiTexture () + { + delete[] pcData; + } +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif // AI_TEXTURE_H_INC \ No newline at end of file diff --git a/include/aiTypes.h b/include/aiTypes.h index cfaed04fd..3518564c4 100644 --- a/include/aiTypes.h +++ b/include/aiTypes.h @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + #ifndef AI_TYPES_H_INC #define AI_TYPES_H_INC @@ -16,50 +57,57 @@ #include "aiMatrix4x4.inl" #ifdef __cplusplus -#include +# include extern "C" { +# define C_STRUCT +#else +# define C_STRUCT struct #endif /** Maximum dimension for strings, ASSIMP strings are zero terminated */ +#ifdef __cplusplus const size_t MAXLEN = 1024; +#else +# define MAXLEN 1024 +#endif // --------------------------------------------------------------------------- /** Represents a two-dimensional vector. */ // --------------------------------------------------------------------------- -typedef struct aiVector2D +struct aiVector2D { #ifdef __cplusplus aiVector2D () : x(0.0f), y(0.0f) {} aiVector2D (float _x, float _y) : x(_x), y(_y) {} aiVector2D (const aiVector2D& o) : x(o.x), y(o.y) {} -#endif // __cplusplus +#endif // !__cplusplus + //! X and y coordinates float x, y; -} aiVector2D_t; +} ; // aiVector3D type moved to separate header due to size of operators - // aiQuaternion type moved to separate header due to size of operators - // aiMatrix4x4 type moved to separate header due to size of operators // --------------------------------------------------------------------------- /** Represents a color in Red-Green-Blue space. */ // --------------------------------------------------------------------------- -typedef struct aiColor3D +struct aiColor3D { #ifdef __cplusplus aiColor3D () : r(0.0f), g(0.0f), b(0.0f) {} aiColor3D (float _r, float _g, float _b) : r(_r), g(_g), b(_b) {} aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {} -#endif // __cplusplus +#endif // !__cplusplus + //! Red, green and blue color values float r, g, b; -} aiColor3D_t; +}; // --------------------------------------------------------------------------- @@ -67,7 +115,7 @@ typedef struct aiColor3D * alpha component. */ // --------------------------------------------------------------------------- -typedef struct aiColor4D +struct aiColor4D { #ifdef __cplusplus aiColor4D () : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {} @@ -76,17 +124,18 @@ typedef struct aiColor4D aiColor4D (const aiColor4D& o) : r(o.r), g(o.g), b(o.b), a(o.a) {} -#endif // __cplusplus +#endif // !__cplusplus + //! Red, green, blue and alpha color values float r, g, b, a; -} aiColor4D_t; +}; // --------------------------------------------------------------------------- /** Represents a string, zero byte terminated */ // --------------------------------------------------------------------------- -typedef struct aiString +struct aiString { #ifdef __cplusplus inline aiString() : @@ -110,11 +159,14 @@ typedef struct aiString memcpy( data, pString.c_str(), length); data[length] = 0; } -#endif // __cplusplus +#endif // !__cplusplus + //! Length of the string excluding the terminal 0 size_t length; + + //! String buffer. Size limit is MAXLEN char data[MAXLEN]; -} aiString_t; +} ; // --------------------------------------------------------------------------- @@ -124,17 +176,27 @@ typedef struct aiString * AI_SUCCESS. */ // --------------------------------------------------------------------------- + enum aiReturn { + //! Indicates that a function was successful AI_SUCCESS = 0x0, + //! Indicates that a function failed AI_FAILURE = -0x1, + //! Indicates that a file was invalid AI_INVALIDFILE = -0x2, + //! Indicates that not enough memory was available + //! to perform the requested operation AI_OUTOFMEMORY = -0x3, + //! Indicates that an illegal argument has been + //! passed to a function. This is rarely used, + //! most functions assert in this case. AI_INVALIDARG = -0x4 }; + #ifdef __cplusplus } -#endif -#endif +#endif //! __cplusplus +#endif //!! include guard diff --git a/include/aiVector3D.h b/include/aiVector3D.h index bbd8911ae..1f7cc0df5 100644 --- a/include/aiVector3D.h +++ b/include/aiVector3D.h @@ -4,15 +4,13 @@ #include -#include "aiAssert.h" - #ifdef __cplusplus extern "C" { #endif // --------------------------------------------------------------------------- /** Represents a three-dimensional vector. */ -typedef struct aiVector3D +struct aiVector3D { #ifdef __cplusplus aiVector3D () : x(0.0f), y(0.0f), z(0.0f) {} @@ -33,7 +31,7 @@ typedef struct aiVector3D #endif // __cplusplus float x, y, z; -} aiVector3D_t; +}; #ifdef __cplusplus } // end extern "C" @@ -71,16 +69,15 @@ inline aiVector3D operator * ( const aiVector3D& v, float f) // scalar division inline aiVector3D operator / ( const aiVector3D& v, float f) { - //ai_assert(0.0f != f); + return v * (1/f); } // vector division inline aiVector3D operator / ( const aiVector3D& v, const aiVector3D& v2) - { - //ai_assert(0.0f != v2.x && 0.0f != v2.y && 0.0f != v2.z); +{ return aiVector3D(v.x / v2.x,v.y / v2.y,v.z / v2.z); - } +} // cross product inline aiVector3D operator ^ ( const aiVector3D& v1, const aiVector3D& v2) diff --git a/include/assimp.h b/include/assimp.h index a3ae202dd..c55802136 100644 --- a/include/assimp.h +++ b/include/assimp.h @@ -1,14 +1,58 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Defines the C-API to the Asset Import Library. */ #ifndef AI_ASSIMP_H_INC #define AI_ASSIMP_H_INC +#include "aiTypes.h" + #ifdef __cplusplus extern "C" { #endif struct aiScene; struct aiFileIO; -//enum aiOrigin; +struct aiString; + // --------------------------------------------------------------------------- /** Reads the given file and returns its content. @@ -20,14 +64,14 @@ struct aiFileIO; * this file. If the import fails, NULL is returned instead. Call * aiGetErrorString() to retrieve a human-readable error text. * @param pFile Path and filename of the file to be imported, -* expected to be a null-terminated c-string. +* expected to be a null-terminated c-string. NULL is not a valid value. * @param pFlags Optional post processing steps to be executed after * a successful import. Provide a bitwise combination of the #aiPostProcessSteps * flags. * @return Pointer to the imported data or NULL if the import failed. */ // --------------------------------------------------------------------------- -const aiScene* aiImportFile( const char* pFile, unsigned int pFlags); +const C_STRUCT aiScene* aiImportFile( const char* pFile, unsigned int pFlags); // --------------------------------------------------------------------------- @@ -41,13 +85,16 @@ const aiScene* aiImportFile( const char* pFile, unsigned int pFlags); * this file. If the import fails, NULL is returned instead. Call * aiGetErrorString() to retrieve a human-readable error text. * @param pFile aiFileIO structure. All functions pointers must be -* initialized. aiFileIO::OpenFunc() and aiFileIO::CloseFunc() -* will be used to open other files in the fs if the asset to be -* loaded depends on them. +* initialized. aiFileIO::OpenFunc() and aiFileIO::CloseFunc() +* will be used to open other files in the fs if the asset to be +* loaded depends on them. NULL is not a valid value. * @return Pointer to the imported data or NULL if the import failed. +* +* @note The C-API creates a new Importer instance internally for each call +* to this function. Therefore the C-API is thread-safe. */ // --------------------------------------------------------------------------- -const aiScene* aiImportFileEx( const aiFileIO* pFile); +const C_STRUCT aiScene* aiImportFileEx( const C_STRUCT aiFileIO* pFile); @@ -55,10 +102,10 @@ const aiScene* aiImportFileEx( const aiFileIO* pFile); /** Releases all resources associated with the given import process. * * Call this function after you're done with the imported data. -* @param pScene The imported data to release. +* @param pScene The imported data to release. NULL is a valid value. */ // --------------------------------------------------------------------------- -void aiReleaseImport( const aiScene* pScene); +void aiReleaseImport( const C_STRUCT aiScene* pScene); // --------------------------------------------------------------------------- @@ -70,6 +117,29 @@ void aiReleaseImport( const aiScene* pScene); // --------------------------------------------------------------------------- const char* aiGetErrorString(); + +// --------------------------------------------------------------------------- +/** Returns whether a given file extension is supported by ASSIMP +* +* @param szExtension Extension for which the function queries support. +* Must include a leading dot '.'. Example: ".3ds", ".md3" +* @return 1 if the extension is supported, 0 otherwise +*/ +// --------------------------------------------------------------------------- +int aiIsExtensionSupported(const char* szExtension); + + +// --------------------------------------------------------------------------- +/** Get a full list of all file extensions generally supported by ASSIMP. + * + * If a file extension is contained in the list this does, of course, not + * mean that ASSIMP is able to load all files with this extension. + * @param szOut String to receive the extension list. + * Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter. +*/ +// --------------------------------------------------------------------------- +void aiGetExtensionList(C_STRUCT aiString* szOut); + #ifdef __cplusplus } #endif diff --git a/include/assimp.hpp b/include/assimp.hpp index f2c56ed49..df80903a6 100644 --- a/include/assimp.hpp +++ b/include/assimp.hpp @@ -1,3 +1,44 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + /** @file Defines the CPP-API to the Asset Import Library. */ #ifndef AI_ASSIMP_HPP_INC #define AI_ASSIMP_HPP_INC @@ -32,10 +73,13 @@ class IOSystem; * GetErrorString(). * * If you need the Importer to do custom file handling to access the files, -* implement IOSystem and IOStream and supply an instance of your custom IOSystem -* implementation by calling SetIOHandler() before calling ReadFile(). If you -* do not assign a custion IO handler, a default handler using the standard C++ -* IO logic will be used. +* implement IOSystem and IOStream and supply an instance of your custom +* IOSystem implementation by calling SetIOHandler() before calling ReadFile(). +* If you do not assign a custion IO handler, a default handler using the +* standard C++ IO logic will be used. +* +* @note One Importer instance is not thread-safe. If you use multiple +* threads for loading each thread should manage its own Importer instance. */ class Importer { @@ -55,16 +99,17 @@ public: ~Importer(); // ------------------------------------------------------------------- - /** Supplies a custom IO handler to the importer to open and access files. - * If you need the importer to use custion IO logic to access the files, - * you need to provide a custom implementation of IOSystem and IOFile - * to the importer. Then create an instance of your custion IOSystem - * implementation and supply it by this function. + /** Supplies a custom IO handler to the importer to use to open and + * access files. If you need the importer to use custion IO logic to + * access the files, you need to provide a custom implementation of + * IOSystem and IOFile to the importer. Then create an instance of + * your custion IOSystem implementation and supply it by this function. * - * The Importer takes ownership of the object and will destroy it afterwards. - * The previously assigned handler will be deleted. + * The Importer takes ownership of the object and will destroy it + * afterwards. The previously assigned handler will be deleted. * - * @param pIOHandler The IO handler to be used in all file accesses of the Importer. + * @param pIOHandler The IO handler to be used in all file accesses + * of the Importer. NULL resets it to the default handler. */ void SetIOHandler( IOSystem* pIOHandler); @@ -95,6 +140,27 @@ public: inline const std::string& GetErrorString() const { return mErrorString; } + + // ------------------------------------------------------------------- + /** Returns whether a given file extension is supported by ASSIMP + * + * @param szExtension Extension for which the function queries support. + * Must include a leading dot '.'. Example: ".3ds", ".md3" + * @return true if the extension is supported, false otherwise + */ + bool IsExtensionSupported(const std::string& szExtension); + + + // ------------------------------------------------------------------- + /** Get a full list of all file extensions generally supported by ASSIMP. + * + * If a file extension is contained in the list this does, of course, not + * mean that ASSIMP is able to load all files with this extension. + * @param szOut String to receive the extension list. + * Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter. + */ + void GetExtensionList(std::string& szOut); + private: /** Empty copy constructor. */ Importer(const Importer &other); diff --git a/tools/assimp_view/Background.cpp b/tools/assimp_view/Background.cpp index 459b5f6a0..ff76d6d47 100644 --- a/tools/assimp_view/Background.cpp +++ b/tools/assimp_view/Background.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp new file mode 100644 index 000000000..1577c4e3b --- /dev/null +++ b/tools/assimp_view/Display.cpp @@ -0,0 +1 @@ +#include "stdafx.h" \ No newline at end of file diff --git a/tools/assimp_view/Display.h b/tools/assimp_view/Display.h new file mode 100644 index 000000000..e69de29bb diff --git a/tools/assimp_view/HelpDialog.cpp b/tools/assimp_view/HelpDialog.cpp index f13f3b94a..604fba59b 100644 --- a/tools/assimp_view/HelpDialog.cpp +++ b/tools/assimp_view/HelpDialog.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" diff --git a/tools/assimp_view/Input.cpp b/tools/assimp_view/Input.cpp index 8e77cb85a..71b9a6b25 100644 --- a/tools/assimp_view/Input.cpp +++ b/tools/assimp_view/Input.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" diff --git a/tools/assimp_view/LogDisplay.cpp b/tools/assimp_view/LogDisplay.cpp index 529ad4866..c3d73ffc1 100644 --- a/tools/assimp_view/LogDisplay.cpp +++ b/tools/assimp_view/LogDisplay.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" diff --git a/tools/assimp_view/LogDisplay.h b/tools/assimp_view/LogDisplay.h index ea0913609..953c17735 100644 --- a/tools/assimp_view/LogDisplay.h +++ b/tools/assimp_view/LogDisplay.h @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #if (!defined AV_LOG_DISPLAY_H_INCLUDED) #define AV_LOG_DISPLAY_H_INCLUDE diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp new file mode 100644 index 000000000..f33bf5d83 --- /dev/null +++ b/tools/assimp_view/LogWindow.cpp @@ -0,0 +1,103 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "stdafx.h" +#include "assimp_view.h" + + +namespace AssimpView { + +/* extern */ CLogWindow CLogWindow::s_cInstance; + +//------------------------------------------------------------------------------- +// Message procedure for the log window +//------------------------------------------------------------------------------- +INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + lParam; + switch (uMsg) + { + case WM_INITDIALOG: + { + + return TRUE; + } + + case WM_SIZE: + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + + SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),NULL,0,0, + x,y,SWP_NOMOVE|SWP_NOZORDER); + + return TRUE; + } + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + }; + return FALSE; + } + +//------------------------------------------------------------------------------- +void CLogWindow::Init () +{ + this->hwnd = ::CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LOGVIEW), + NULL,&LogDialogProc); + + if (!this->hwnd) + { + CLogDisplay::Instance().AddEntry("[ERROR] Unable to create logger window", + D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + } +} +//------------------------------------------------------------------------------- +void CLogWindow::Show() +{ + if (this->hwnd) + { + ShowWindow(this->hwnd,SW_SHOW); + } +} + +}; //! AssimpView \ No newline at end of file diff --git a/tools/assimp_view/LogWindow.h b/tools/assimp_view/LogWindow.h new file mode 100644 index 000000000..0fef5a20d --- /dev/null +++ b/tools/assimp_view/LogWindow.h @@ -0,0 +1,78 @@ +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#if (!defined AV_LOG_WINDOW_H_INCLUDED) +#define AV_LOG_WINDOW_H_INCLUDE + +//------------------------------------------------------------------------------- +/** \brief Class to display log strings in a separate window +*/ +//------------------------------------------------------------------------------- +class CLogWindow + { +private: + + CLogWindow() : hwnd(NULL) {} + +public: + + + // Singleton accessors + static CLogWindow s_cInstance; + inline static CLogWindow& Instance () + { + return s_cInstance; + } + + // initializes the log window + void Init (); + + // Shows the log window + void Show(); + +private: + + // Window handle + HWND hwnd; + + }; + +#endif // AV_LOG_DISPLA \ No newline at end of file diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index 62a1a7308..fd1760913 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" @@ -27,13 +58,13 @@ unsigned int g_iShaderCount = 0 ; // Used for case insensitive string comparison //------------------------------------------------------------------------------- inline int ASSIMP_stricmp(const char *s1, const char *s2) - { +{ const char *a1, *a2; a1 = s1; a2 = s2; while (true) - { + { char c1 = (char)tolower(*a1); char c2 = (char)tolower(*a2); if ((0 == c1) && (0 == c2)) return 0; @@ -41,8 +72,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) if (c1 > c2) return 1; ++a1; ++a2; - } } +} //------------------------------------------------------------------------------- // D3DX callback function to fill a texture with a checkers pattern @@ -53,7 +84,7 @@ VOID WINAPI FillFunc(D3DXVECTOR4* pOut, CONST D3DXVECTOR2* pTexCoord, CONST D3DXVECTOR2* pTexelSize, LPVOID pData) - { +{ UNREFERENCED_PARAMETER(pData); UNREFERENCED_PARAMETER(pTexelSize); @@ -64,25 +95,25 @@ VOID WINAPI FillFunc(D3DXVECTOR4* pOut, bool bBlack = false; if ((iX / 32) % 2 == 0) - { + { if ((iY / 32) % 2 == 0)bBlack = true; - } + } else - { + { if ((iY / 32) % 2 != 0)bBlack = true; - } + } pOut->w = 1.0f; if (bBlack) - { + { pOut->x = pOut->y = pOut->z = 0.0f; - } + } else - { + { pOut->x = pOut->y = 1.0f; pOut->z = 0.0f; - } - return; } + return; +} //------------------------------------------------------------------------------- // Setup the default texture for a texture channel @@ -90,7 +121,7 @@ VOID WINAPI FillFunc(D3DXVECTOR4* pOut, // Generates a default checker pattern for a texture //------------------------------------------------------------------------------- int SetDefaultTexture(IDirect3DTexture9** p_ppiOut) - { +{ if(FAILED(g_piDevice->CreateTexture( 256, 256, @@ -100,13 +131,13 @@ int SetDefaultTexture(IDirect3DTexture9** p_ppiOut) D3DPOOL_MANAGED, p_ppiOut, NULL))) - { + { CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture", D3DCOLOR_ARGB(0xFF,0xFF,0,0)); - } + } D3DXFillTexture(*p_ppiOut,&FillFunc,NULL); return 1; - } +} //------------------------------------------------------------------------------- @@ -116,7 +147,7 @@ int SetDefaultTexture(IDirect3DTexture9** p_ppiOut) // executable and the asset for a texture with a name very similar to a given one //------------------------------------------------------------------------------- bool TryLongerPath(char* szTemp,aiString* p_szString) - { +{ char szTempB[MAX_PATH]; strcpy(szTempB,szTemp); @@ -124,7 +155,7 @@ bool TryLongerPath(char* szTemp,aiString* p_szString) // go to the beginning of the file name char* szFile = strrchr(szTempB,'\\'); if (!szFile)szFile = strrchr(szTempB,'/'); - + char* szFile2 = szTemp + (szFile - szTempB)+1; szFile++; char* szExt = strrchr(szFile,'.')+1; @@ -139,16 +170,16 @@ bool TryLongerPath(char* szTemp,aiString* p_szString) // build a list of files h = FindFirstFile(szTempB, &info); if (h != INVALID_HANDLE_VALUE) - { + { do - { + { if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0)) - { + { char* szExtFound = strrchr(info.cFileName, '.')+1; if ((char*)0x1 != szExtFound) - { + { if (0 == ASSIMP_stricmp(szExtFound,szExt)) - { + { const unsigned int iSizeFound = (const unsigned int) ( szExtFound - 1 - info.cFileName); @@ -156,7 +187,7 @@ bool TryLongerPath(char* szTemp,aiString* p_szString) info.cFileName[i] = (CHAR)tolower(info.cFileName[i]); if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize))) - { + { // we have it. Build the full path ... char* sz = strrchr(szTempB,'*'); *(sz-2) = 0x0; @@ -170,11 +201,11 @@ bool TryLongerPath(char* szTemp,aiString* p_szString) memcpy(p_szString->data,szTempB,iLen2); p_szString->length = iLen; return true; - } } + } // check whether the 8.3 DOS name is matching if (0 == ASSIMP_stricmp(info.cAlternateFileName,p_szString->data)) - { + { strcat(szTempB,info.cAlternateFileName); // copy the result string back to the aiString @@ -184,16 +215,16 @@ bool TryLongerPath(char* szTemp,aiString* p_szString) memcpy(p_szString->data,szTempB,iLen2); p_szString->length = iLen; return true; - } } } - } + } + } while (FindNextFile(h, &info)); FindClose(h); - } - return false; } + return false; +} //------------------------------------------------------------------------------- // find a valid path to a texture file @@ -202,12 +233,18 @@ bool TryLongerPath(char* szTemp,aiString* p_szString) // executable and the asset for a texture with a name very similar to a given one //------------------------------------------------------------------------------- int FindValidPath(aiString* p_szString) +{ + if ('*' == p_szString->data[0]) { + // '*' as first character indicates an embedded file + return 5; + } + // first check whether we can directly load the file FILE* pFile = fopen(p_szString->data,"rb"); if (pFile)fclose(pFile); else - { + { // check whether we can use the directory of // the asset as relative base char szTemp[MAX_PATH*2]; @@ -218,23 +255,23 @@ int FindValidPath(aiString* p_szString) char* szEnd = strrchr(szTemp,'\\'); if (!szEnd) - { + { szEnd = strrchr(szTemp,'/'); if (!szEnd)szEnd = szTemp; - } + } szEnd++; *szEnd = 0; strcat(szEnd,szData); pFile = fopen(szTemp,"rb"); if (!pFile) - { + { // convert the string to lower case for (unsigned int i = 0;;++i) - { + { if ('\0' == szTemp[i])break; szTemp[i] = (char)tolower(szTemp[i]); - } + } if(TryLongerPath(szTemp,p_szString))return 1; *szEnd = 0; @@ -245,7 +282,7 @@ int FindValidPath(aiString* p_szString) pFile = fopen(szTemp,"rb"); if (!pFile) - { + { if(TryLongerPath(szTemp,p_szString))return 1; *szEnd = 0; @@ -255,16 +292,16 @@ int FindValidPath(aiString* p_szString) pFile = fopen(szTemp,"rb"); if (!pFile) - { + { if(TryLongerPath(szTemp, p_szString))return 1; - + // still unable to load ... however, don't spew // an error message here, simply let it and wait for // D3DXCreateTextureFromFileEx() to fail ;-) - } - return 0; } + return 0; } + } fclose(pFile); // copy the result string back to the aiString @@ -273,9 +310,9 @@ int FindValidPath(aiString* p_szString) iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; memcpy(p_szString->data,szTemp,iLen2); p_szString->length = iLen; - } - return 1; } + return 1; +} //------------------------------------------------------------------------------- // Load a texture into memory and create a native D3D texture resource @@ -283,12 +320,89 @@ int FindValidPath(aiString* p_szString) // The function tries to find a valid path for a texture //------------------------------------------------------------------------------- int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath) - { - // first get a valid path to the texture - FindValidPath(szPath); - +{ *p_ppiOut = NULL; + // first get a valid path to the texture + if( 5 == FindValidPath(szPath)) + { + // embedded file. Find its index + unsigned int iIndex = atoi(szPath->data+1); + if (iIndex < g_pcAsset->pcScene->mNumTextures) + { + if (0 == g_pcAsset->pcScene->mTextures[iIndex]->mHeight) + { + // it is an embedded file ... don't need the file format hint, + // simply let D3DX load the file + if (FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice, + g_pcAsset->pcScene->mTextures[iIndex]->pcData, + g_pcAsset->pcScene->mTextures[iIndex]->mWidth, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_UNKNOWN, + D3DPOOL_MANAGED, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + NULL, + NULL, + p_ppiOut))) + { + std::string sz = "[ERROR] Unable to load embedded texture (#1): "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + SetDefaultTexture(p_ppiOut); + return 1; + } + } + else + { + // fill a new texture ... + if(FAILED(g_piDevice->CreateTexture( + g_pcAsset->pcScene->mTextures[iIndex]->mWidth, + g_pcAsset->pcScene->mTextures[iIndex]->mHeight, + 0,D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,p_ppiOut,NULL))) + { + std::string sz = "[ERROR] Unable to load embedded texture (#2): "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + SetDefaultTexture(p_ppiOut); + return 1; + } + + // now copy the data to it ... (assume non pow2 to be supported) + D3DLOCKED_RECT sLock; + (*p_ppiOut)->LockRect(0,&sLock,NULL,0); + + const aiTexel* pcData = g_pcAsset->pcScene->mTextures[iIndex]->pcData; + + for (unsigned int y = 0; y < g_pcAsset->pcScene->mTextures[iIndex]->mHeight;++y) + { + memcpy(sLock.pBits,pcData,g_pcAsset->pcScene->mTextures[iIndex]-> + mWidth *sizeof(aiTexel)); + sLock.pBits = (char*)sLock.pBits + sLock.Pitch; + pcData += g_pcAsset->pcScene->mTextures[iIndex]->mWidth; + } + (*p_ppiOut)->UnlockRect(0); + (*p_ppiOut)->GenerateMipSubLevels(); + } + return 1; + } + else + { + std::string sz = "[ERROR] Invalid index for embedded texture: "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + SetDefaultTexture(p_ppiOut); + return 1; + } + } + // then call D3DX to load the texture if (FAILED(D3DXCreateTextureFromFileEx( g_piDevice, @@ -305,16 +419,16 @@ int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath) NULL, NULL, p_ppiOut))) - { + { // error ... use the default texture instead std::string sz = "[ERROR] Unable to load texture: "; sz.append(szPath->data); CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); SetDefaultTexture(p_ppiOut); - } - return 1; } + return 1; +} @@ -324,42 +438,42 @@ int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath) // Must be called before CreateMaterial() to prevent memory leaking //------------------------------------------------------------------------------- void DeleteMaterial(AssetHelper::MeshHelper* pcIn) - { +{ if (!pcIn || !pcIn->piEffect)return; pcIn->piEffect->Release(); // release all textures associated with the material if (pcIn->piDiffuseTexture) - { + { pcIn->piDiffuseTexture->Release(); pcIn->piDiffuseTexture = NULL; - } + } if (pcIn->piSpecularTexture) - { + { pcIn->piSpecularTexture->Release(); pcIn->piSpecularTexture = NULL; - } + } if (pcIn->piEmissiveTexture) - { + { pcIn->piEmissiveTexture->Release(); pcIn->piEmissiveTexture = NULL; - } + } if (pcIn->piAmbientTexture) - { + { pcIn->piAmbientTexture->Release(); pcIn->piAmbientTexture = NULL; - } + } if (pcIn->piOpacityTexture) - { + { pcIn->piOpacityTexture->Release(); pcIn->piOpacityTexture = NULL; - } + } if (pcIn->piNormalTexture) - { + { pcIn->piNormalTexture->Release(); pcIn->piNormalTexture = NULL; - } } +} //------------------------------------------------------------------------------- @@ -370,7 +484,7 @@ void DeleteMaterial(AssetHelper::MeshHelper* pcIn) //------------------------------------------------------------------------------- void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextureOut, bool bWasOriginallyHM = true) - { +{ bool bMustConvert = false; uintptr_t iElement = 3; @@ -391,46 +505,46 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur D3DSURFACE_DESC sDesc; piTexture->GetLevelDesc(0,&sDesc); if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY))) - { + { return; - } + } const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); struct SColor - { + { union - { + { struct {unsigned char b,g,r,a;}; char _array[4]; - }; }; + }; const SColor* pcData = (const SColor*)sRect.pBits; union - { + { const SColor* pcPointer; const unsigned char* pcCharPointer; - }; + }; pcPointer = pcData; // 1. If r,g,b channel are identical it MUST be a height map bool bIsEqual = true; for (unsigned int y = 0; y < sDesc.Height;++y) - { + { for (unsigned int x = 0; x < sDesc.Width;++x) - { + { if (pcPointer->b != pcPointer->r || pcPointer->b != pcPointer->g) - { + { bIsEqual = false; break; - } - pcPointer++; } - pcCharPointer += iPitchDiff; + pcPointer++; } + pcCharPointer += iPitchDiff; + } if (bIsEqual)bMustConvert = true; else - { + { // 2. If one of the rgb channels is used and the others are empty it // must be a height map, too. pcPointer = pcData; @@ -444,29 +558,29 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur bIsEqual = true; if (3 != iElement) - { + { for (unsigned int y = 0; y < sDesc.Height;++y) - { + { for (unsigned int x = 0; x < sDesc.Width;++x) - { + { for (unsigned int ii = 0; ii < 3;++ii) - { + { // don't take the alpha channel into account. // if the texture was stored n RGB888 format D3DX has // converted it to ARGB8888 format with a fixed alpha channel if (aiIndex[ii] != 3 && pcPointer->_array[aiIndex[ii]] != 0) - { + { bIsEqual = false; break; - } } - pcPointer++; } - pcCharPointer += iPitchDiff; + pcPointer++; } + pcCharPointer += iPitchDiff; + } if (bIsEqual)bMustConvert = true; else - { + { // If the average color of the whole image is something inside the // purple range we can be sure it is a normal map @@ -474,20 +588,20 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur pcPointer = pcData; aiColor3D clrColor; for (unsigned int y = 0; y < sDesc.Height;++y) - { + { aiColor3D clrColorLine; for (unsigned int x = 0; x < sDesc.Width;++x) - { + { clrColorLine.r += pcPointer->r; clrColorLine.g += pcPointer->g; clrColorLine.b += pcPointer->b; pcPointer++; - } + } clrColor.r += clrColorLine.r /= (float)sDesc.Width; clrColor.g += clrColorLine.g /= (float)sDesc.Width; clrColor.b += clrColorLine.b /= (float)sDesc.Width; pcCharPointer += iPitchDiff; - } + } clrColor.r /= (float)sDesc.Height; clrColor.g /= (float)sDesc.Height; clrColor.b /= (float)sDesc.Height; @@ -495,23 +609,23 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur if (!(clrColor.b > 215 && clrColor.r > 100 && clrColor.r < 140 && clrColor.g > 100 && clrColor.g < 140)) - { + { // Unable to detect. Believe the original value obtained from the loader if (bWasOriginallyHM) - { + { bMustConvert = true; - } } } } } + } piTexture->UnlockRect(0); // if the input data is assumed to be a height map we'll // need to convert it NOW if (bMustConvert) - { + { D3DSURFACE_DESC sDesc; piTexture->GetLevelDesc(0, &sDesc); @@ -523,12 +637,12 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur sDesc.Usage, sDesc.Format, sDesc.Pool, &piTempTexture, NULL))) - { + { CLogDisplay::Instance().AddEntry( "[ERROR] Unable to create normal map texture", D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); return; - } + } DWORD dwFlags; if (3 == iElement)dwFlags = D3DX_CHANNEL_LUMINANCE; @@ -538,18 +652,18 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur if(FAILED(D3DXComputeNormalMap(piTempTexture, piTexture,NULL,0,dwFlags,1.0f))) - { + { CLogDisplay::Instance().AddEntry( "[ERROR] Unable to compute normal map from height map", D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); piTempTexture->Release(); return; - } + } *piTextureOut = piTempTexture; piTexture->Release(); - } } +} //------------------------------------------------------------------------------- @@ -558,44 +672,44 @@ void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextur // A pixel is considered to be non-opaque if its alpha value s less than 255 //------------------------------------------------------------------------------- bool HasAlphaPixels(IDirect3DTexture9* piTexture) - { +{ D3DLOCKED_RECT sRect; D3DSURFACE_DESC sDesc; piTexture->GetLevelDesc(0,&sDesc); if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY))) - { + { return false; - } + } const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); struct SColor - { + { unsigned char b,g,r,a;; - }; + }; const SColor* pcData = (const SColor*)sRect.pBits; union - { + { const SColor* pcPointer; const unsigned char* pcCharPointer; - }; + }; pcPointer = pcData; for (unsigned int y = 0; y < sDesc.Height;++y) - { + { for (unsigned int x = 0; x < sDesc.Width;++x) - { + { if (pcPointer->a != 0xFF) - { + { piTexture->UnlockRect(0); return true; - } - pcPointer++; } - pcCharPointer += iPitchDiff; + pcPointer++; } + pcCharPointer += iPitchDiff; + } piTexture->UnlockRect(0); return false; - } +} //------------------------------------------------------------------------------- @@ -606,7 +720,7 @@ bool HasAlphaPixels(IDirect3DTexture9* piTexture) // and takes the same number of texture channels. //------------------------------------------------------------------------------- int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) - { +{ ID3DXBuffer* piBuffer; D3DXMACRO sMacro[32]; @@ -619,73 +733,73 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE, (aiColor4D*)&pcMesh->vDiffuseColor)) - { + { pcMesh->vDiffuseColor.x = 1.0f; pcMesh->vDiffuseColor.y = 1.0f; pcMesh->vDiffuseColor.z = 1.0f; pcMesh->vDiffuseColor.w = 1.0f; - } + } // // SPECULAR COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR, (aiColor4D*)&pcMesh->vSpecularColor)) - { + { pcMesh->vSpecularColor.x = 1.0f; pcMesh->vSpecularColor.y = 1.0f; pcMesh->vSpecularColor.z = 1.0f; pcMesh->vSpecularColor.w = 1.0f; - } + } // // AMBIENT COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT, (aiColor4D*)&pcMesh->vAmbientColor)) - { + { pcMesh->vAmbientColor.x = 0.0f; pcMesh->vAmbientColor.y = 0.0f; pcMesh->vAmbientColor.z = 0.0f; pcMesh->vAmbientColor.w = 1.0f; - } + } // // EMISSIVE COLOR ------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE, (aiColor4D*)&pcMesh->vEmissiveColor)) - { + { pcMesh->vEmissiveColor.x = 0.0f; pcMesh->vEmissiveColor.y = 0.0f; pcMesh->vEmissiveColor.z = 0.0f; pcMesh->vEmissiveColor.w = 1.0f; - } + } // // Opacity -------------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity)) - { + { pcMesh->fOpacity = 1.0f; - } + } // // Shading Model -------------------------------------------------- // bool bDefault = false; if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode )) - { + { bDefault = true; pcMesh->eShadingMode = aiShadingMode_Gouraud; - } + } // // Shininess ------------------------------------------------------ // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess)) - { + { // assume 15 as default shininess pcMesh->fShininess = 15.0f; - } + } else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong; aiString szPath; @@ -694,97 +808,97 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) // DIFFUSE TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) - { + { LoadTexture(&pcMesh->piDiffuseTexture,&szPath); - } + } // // SPECULAR TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath)) - { + { LoadTexture(&pcMesh->piSpecularTexture,&szPath); - } + } // // OPACITY TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath)) - { + { LoadTexture(&pcMesh->piOpacityTexture,&szPath); - } + } else - { + { // try to find out whether the diffuse texture has any // non-opaque pixels. If we find a few use it as opacity texture if (pcMesh->piDiffuseTexture && HasAlphaPixels(pcMesh->piDiffuseTexture)) - { + { pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture; pcMesh->piOpacityTexture->AddRef(); - } } + } // // AMBIENT TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath)) - { + { LoadTexture(&pcMesh->piAmbientTexture,&szPath); - } + } // // EMISSIVE TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath)) - { + { LoadTexture(&pcMesh->piEmissiveTexture,&szPath); - } + } // // NORMAL/HEIGHT MAP ------------------------------------------------ // bool bHM = false; if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath)) - { + { LoadTexture(&pcMesh->piNormalTexture,&szPath); - } + } else + { + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath)) { - if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_BUMP(0),&szPath)) - { LoadTexture(&pcMesh->piNormalTexture,&szPath); - } - bHM = true; } + bHM = true; + } // normal/height maps are sometimes mixed up. Try to detect the type // of the texture automatically if (pcMesh->piNormalTexture) - { + { HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM); - } + } // check whether a global background texture is contained // in this material. Some loaders set this value ... if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath)) - { + { CBackgroundPainter::Instance().SetTextureBG(szPath.data); - } + } // BUGFIX: If the shininess is 0.0f disable phong lighting // This is a workaround for some meshes in the DX SDK (e.g. tiny.x) if (0.0f == pcMesh->fShininess) - { + { pcMesh->eShadingMode = aiShadingMode_Gouraud; - } + } // check whether we have already a material using the same // shader. This will decrease loading time rapidly ... for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + { if (g_pcAsset->pcScene->mMeshes[i] == pcSource) - { + { break; - } + } AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; if ((pcMesh->piDiffuseTexture != NULL ? true : false) != @@ -814,91 +928,91 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) // we can reuse this material if (pc->piEffect) - { + { pcMesh->piEffect = pc->piEffect; pc->bSharedFX = pcMesh->bSharedFX = true; pcMesh->piEffect->AddRef(); return 2; - } } + } g_iShaderCount++; // build macros for the HLSL compiler unsigned int iCurrent = 0; if (pcMesh->piDiffuseTexture) - { + { sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } if (pcMesh->piSpecularTexture) - { + { sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } if (pcMesh->piAmbientTexture) - { + { sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } if (pcMesh->piEmissiveTexture) - { + { sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } if (pcMesh->piNormalTexture) - { + { sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } if (pcMesh->piOpacityTexture) - { + { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture) - { + { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; sMacro[iCurrent].Definition = "a"; ++iCurrent; - } + } else - { + { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; sMacro[iCurrent].Definition = "r"; ++iCurrent; - } } + } if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular) - { + { sMacro[iCurrent].Name = "AV_SPECULAR_COMPONENT"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } if (1.0f != pcMesh->fOpacity) - { + { sMacro[iCurrent].Name = "AV_OPACITY"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } // If a cubemap is active, we'll need to lookup it for calculating // a physically correct reflection if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) - { + { sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP"; sMacro[iCurrent].Definition = "1"; ++iCurrent; - } + } sMacro[iCurrent].Name = NULL; sMacro[iCurrent].Definition = NULL; @@ -906,34 +1020,34 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) if(FAILED( D3DXCreateEffect(g_piDevice, g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(), (const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer))) - { + { // failed to compile the shader if( piBuffer) - { + { MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); piBuffer->Release(); - } + } // use the default material instead if (g_piDefaultEffect) - { + { pcMesh->piEffect = g_piDefaultEffect; g_piDefaultEffect->AddRef(); - } + } // get the name of the material and use it in the log message if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) && '\0' != szPath.data[0]) - { + { std::string sz = "[ERROR] Unable to load material: "; sz.append(szPath.data); CLogDisplay::Instance().AddEntry(sz); - } - else - { - CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED"); - } - return 0; } + else + { + CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED"); + } + return 0; + } if( piBuffer) piBuffer->Release(); @@ -967,9 +1081,9 @@ int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture); if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) - { + { pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); - } - return 1; } + return 1; +} }; \ No newline at end of file diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index ef857840a..80cf8483d 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" @@ -15,9 +46,7 @@ namespace AssimpView { // Static array to keep custom color values -COLORREF g_aclCustomColors[16] = - {0}; - +COLORREF g_aclCustomColors[16] = {0}; //------------------------------------------------------------------------------- // Setup file associations for all formats supported by the library @@ -27,12 +56,6 @@ COLORREF g_aclCustomColors[16] = //------------------------------------------------------------------------------- void MakeFileAssociations() { - /* - ; .wscript - root: HKCR; Flags: deletekey; Subkey: ".uscript"; ValueType: string; ValueData: "UE_WSCRIPT_CLASS"; Components: rt - root: HKCR; Flags: deletekey; Subkey: "UE_WSCRIPT_CLASS"; ValueName:; ValueType: string; ValueData: "UtopicEngine Console Script"; Components: rt - root: HKCR; Flags: deletekey; Subkey: "UE_WSCRIPT_CLASS\shell\open\command"; ValueName:; ValueType: string; ValueData: "notepad.exe %1"; Components: rt - */ char szTemp2[MAX_PATH]; char szTemp[MAX_PATH + 10]; @@ -45,130 +68,105 @@ void MakeFileAssociations() // .3ds // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.3ds",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AV3DSCLASS",(DWORD)strlen("AV3DSCLASS")+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AV3DSCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AV3DSCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); - RegCloseKey(hTemp); // ------------------------------------------------- // .x // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.x",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVXCLASS",(DWORD)strlen("AVXCLASS")+1); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVXCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVXCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); // ------------------------------------------------- // .obj // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.obj",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVOBJCLASS",(DWORD)strlen("AVOBJCLASS")+1); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVOBJCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVOBJCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); // ------------------------------------------------- // .ms3d // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ms3d",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMS3DCLASS",(DWORD)strlen("AVMS3DCLASS")+1); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMS3DCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMS3DCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); // ------------------------------------------------- // .md3 // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md3",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD3CLASS",(DWORD)strlen("AVMD3CLASS")+1); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD3CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD3CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); // ------------------------------------------------- // .md2 // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md2",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD2CLASS",(DWORD)strlen("AVMD2CLASS")+1); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD3CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD2CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); // ------------------------------------------------- - // .md4 + // .md4/mdr // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md4",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD4CLASS",(DWORD)strlen("AVMD4CLASS")+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD4CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegCloseKey(hTemp); - - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD4CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdr",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); // ------------------------------------------------- // .md5 // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.md5",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVMD5CLASS",(DWORD)strlen("AVMD5CLASS")+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD5CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + // ------------------------------------------------- + // .mdl + // ------------------------------------------------- + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.mdl",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVMD5CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); - RegCloseKey(hTemp); // ------------------------------------------------- // .ply // ------------------------------------------------- RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ply",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); - RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"AVPLYCLASS",(DWORD)strlen("AVPLYCLASS")+1); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVPLYCLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + + // ------------------------------------------------- + // .ase/.ask + // ------------------------------------------------- + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ase",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(hTemp); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\.ask",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); RegCloseKey(hTemp); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\AVPLYCLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + RegCloseKey(hTemp); + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); RegSetValueEx(hTemp,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); RegCloseKey(hTemp); CLogDisplay::Instance().AddEntry("[OK] File assocations have been registered", D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + + aiString sz; + aiGetExtensionList(&sz); + CLogDisplay::Instance().AddEntry(sz.data, + D3DCOLOR_ARGB(0xFF,0,0xFF,0)); } @@ -248,6 +246,47 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, SetDlgItemText(hwndDlg,IDC_EFACE,"0"); SetDlgItemText(hwndDlg,IDC_EMAT,"0"); SetDlgItemText(hwndDlg,IDC_ESHADER,"0"); + SetDlgItemText(hwndDlg,IDC_ENODE,"0"); + SetDlgItemText(hwndDlg,IDC_ETEX,"0"); + + // setup the default window title + SetWindowText(hwndDlg,AI_VIEW_CAPTION_BASE); + { + // read some UI properties from the registry and apply them + DWORD dwValue; + DWORD dwTemp = sizeof( DWORD ); + HKEY hTemp; + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", + NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + + if(ERROR_SUCCESS != RegQueryValueEx(hTemp,"LastUIState",NULL,NULL, + (BYTE*)&dwValue,&dwTemp)) + { + dwValue = 1; + } + if (0 == dwValue) + { + // collapse the viewer + // adjust the size + RECT sRect; + GetWindowRect(hwndDlg,&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + RECT sRect2; + GetWindowRect(GetDlgItem ( hwndDlg, IDC_BLUBB ),&sRect2); + sRect2.left -= sRect.left; + sRect2.top -= sRect.top; + + SetWindowPos(hwndDlg,NULL,0,0,sRect.right-188,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),">>"); + } + else + { + CheckDlgButton(hwndDlg,IDC_BLUBB,BST_CHECKED); + } + RegCloseKey(hTemp);} return TRUE; case WM_MOUSEWHEEL: @@ -365,34 +404,6 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, g_eClick = EClickPos_CircleVert; } } - - // OLD version of this code. Not using a texture lookup to - // determine the exact position, but using maths and the fact - // that we have a circle f(x) = m +rx ;-) -#if 0 - g_eClick = EClickPos_Circle; - if (yPos < 10 && yPos > -10) - { - if ((xPos2 > fHalfX-5 && xPos2 < fHalfX+15) || - (xPos2 > fHalfX+(int)sDesc.Width-10 && xPos2 < fHalfX+(int)sDesc.Width+10)) - { - g_eClick = EClickPos_CircleHor; - } - } - else if (xPos < 10 && xPos > -10) - { - if ((yPos2 > fHalfY-5 && yPos2 < fHalfY+15) || - (yPos2 > fHalfY+(int)sDesc.Height-10 && yPos2 < fHalfY+(int)sDesc.Height+10)) - { - g_eClick = EClickPos_CircleVert; - } - } - else if (sqrtf((float)(xPos * xPos + yPos * yPos)) > (float)(sDesc.Width/2)) - { - g_eClick = EClickPos_Outside; - } -#endif - return TRUE; case WM_RBUTTONDOWN: @@ -467,6 +478,10 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX), hwndDlg,&AboutMessageProc); } + else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) + { + CLogWindow::Instance().Show(); + } else if (ID_VIEWER_H == LOWORD(wParam)) { MakeFileAssociations(); @@ -657,10 +672,24 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, if (!sz)sz = strrchr(szFileName,'/'); if (!sz)*sz = 0; } + + // get a list of all file extensions supported by ASSIMP + aiString sz; + aiGetExtensionList(&sz); + + char szList[MAXLEN + 100]; + strcpy(szList,"ASSIMP assets"); + char* szCur = szList + 14; + strcpy(szCur,sz.data); + szCur += sz.length+1; + strcpy(szCur,"All files"); + szCur += 10; + strcpy(szCur,"*.*"); + szCur[4] = 0; + OPENFILENAME sFilename1 = { sizeof(OPENFILENAME), - g_hDlg,GetModuleHandle(NULL), - "ASSIMP assets\0*.x;*.obj;*.ms3d;*.3ds;*.md3;*.md1;*.md2;*.md4;*.md5;*.ply\0All files\0*.*", NULL, 0, 1, + g_hDlg,GetModuleHandle(NULL), szList, NULL, 0, 1, szFileName, MAX_PATH, NULL, 0, NULL, "Import Asset into ASSIMP", OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, @@ -728,6 +757,44 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, SetupFPSView(); } + else if (IDC_BLUBB == LOWORD(wParam)) + { + // adjust the size + RECT sRect; + GetWindowRect(hwndDlg,&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + RECT sRect2; + GetWindowRect(GetDlgItem ( hwndDlg, IDC_BLUBB ),&sRect2); + sRect2.left -= sRect.left; + sRect2.top -= sRect.top; + + HKEY hTemp; + DWORD dwValue; + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", + NULL,NULL,0,KEY_ALL_ACCESS, NULL, &hTemp,NULL); + + if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg,IDC_BLUBB)) + { + SetWindowPos(hwndDlg,NULL,0,0,sRect.right-188,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + + dwValue = 0; + SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),">>"); + RegSetValueExA(hTemp,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); + } + else + { + SetWindowPos(hwndDlg,NULL,0,0,sRect.right+188,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + + dwValue = 1; + SetWindowText(GetDlgItem(hwndDlg,IDC_BLUBB),"<<"); + RegSetValueExA(hTemp,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); + } + RegCloseKey(hTemp); + } else if (IDC_TOGGLENORMALS == LOWORD(wParam)) { g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; @@ -898,6 +965,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, CLogDisplay::Instance().AddEntry("[OK] The viewer has been initialized successfully"); + // create the log window + CLogWindow::Instance().Init(); + // set the focus to the main window + SetFocus(g_hDlg); + // recover background skyboxes/textures from the last session HKEY hTemp; union diff --git a/tools/assimp_view/Shaders.cpp b/tools/assimp_view/Shaders.cpp index 1c02b9805..22bab2fc8 100644 --- a/tools/assimp_view/Shaders.cpp +++ b/tools/assimp_view/Shaders.cpp @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #include "stdafx.h" #include "assimp_view.h" @@ -15,16 +46,6 @@ namespace AssimpView { std::string g_szNormalsShader = std::string( - //-------------------------------------------------------------------------------\n" - /**\n" - * This program is distributed under the terms of the GNU Lesser General\n - * Public License (LGPL). \n - *\n - * ASSIMP Viewer Utility\n - *\n" - */ - //-------------------------------------------------------------------------------\n" - // World * View * Projection matrix\n" // NOTE: Assume that the material uses a WorldViewProjection matrix\n" @@ -90,16 +111,6 @@ std::string g_szNormalsShader = std::string( ); std::string g_szSkyboxShader = std::string( - //-------------------------------------------------------------------------------\n" - /**\n" - * This program is distributed under the terms of the GNU Lesser General\n - * Public License (LGPL). \n - *\n - * ASSIMP Viewer Utility\n - *\n" - */ - //-------------------------------------------------------------------------------\n" - // ----------------------------------------------------------------------------\n" // Sampler and texture for the skybox\n" @@ -252,16 +263,6 @@ std::string g_szSkyboxShader = std::string( ); std::string g_szDefaultShader = std::string( - //-------------------------------------------------------------------------------\n" - /**\n" - * This program is distributed under the terms of the GNU Lesser General\n - * Public License (LGPL). \n - *\n - * ASSIMP Viewer Utility\n - *\n" - */ - //-------------------------------------------------------------------------------\n" - // World * View * Projection matrix\n" // NOTE: Assume that the material uses a WorldViewProjection matrix\n" @@ -453,16 +454,6 @@ std::string g_szDefaultShader = std::string( std::string g_szMaterialShader = std::string( - //-------------------------------------------------------------------------------\n" - /**\n" - * This program is distributed under the terms of the GNU Lesser General\n - * Public License (LGPL). \n - *\n - * ASSIMP Viewer Utility\n - *\n" - */ - //-------------------------------------------------------------------------------\n" - // World * View * Projection matrix\n" // NOTE: Assume that the material uses a WorldViewProjection matrix\n" @@ -1143,15 +1134,6 @@ std::string g_szMaterialShader = std::string( ); std::string g_szPassThroughShader = std::string( - //-------------------------------------------------------------------------------\n" - /**\n" - * This program is distributed under the terms of the GNU Lesser General\n - * Public License (LGPL). \n - *\n - * ASSIMP Viewer Utility\n - *\n" - */ - //-------------------------------------------------------------------------------\n" "texture TEXTURE_2D;\n" "sampler TEXTURE_SAMPLER = sampler_state\n" diff --git a/tools/assimp_view/assimp_view.aps b/tools/assimp_view/assimp_view.aps new file mode 100644 index 000000000..35f202b8a Binary files /dev/null and b/tools/assimp_view/assimp_view.aps differ diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index c26a4e8a5..32eb57fde 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -67,7 +67,7 @@ AssetHelper *g_pcAsset = NULL; unsigned char* g_szImageMask = NULL; //------------------------------------------------------------------------------- -// table of colors used for normal vectors. +// Table of colors used for normal vectors. //------------------------------------------------------------------------------- D3DXVECTOR4 g_aclNormalColors[14] = { @@ -94,27 +94,41 @@ D3DXVECTOR4 g_aclNormalColors[14] = //------------------------------------------------------------------------------- -//! \brief Entry point for loader thread +// Entry point for the loader thread +// The laoder thread loads the asset while the progress dialog displays the +// smart progress bar //------------------------------------------------------------------------------- DWORD WINAPI LoadThreadProc(LPVOID lpParameter) { UNREFERENCED_PARAMETER(lpParameter); + + // get current time double fCur = (double)timeGetTime(); + // call ASSIMPs C-API to load the file g_pcAsset->pcScene = aiImportFile(g_szFileName, - aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | - aiProcess_GenSmoothNormals | aiProcess_ConvertToLeftHanded | aiProcess_SplitLargeMeshes); + aiProcess_CalcTangentSpace | // calculate tangents and bitangents + aiProcess_JoinIdenticalVertices | // join identical vertices + aiProcess_Triangulate | // triangulate n-polygons + aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing + aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space + aiProcess_SplitLargeMeshes); // split large, unrenderable meshes into submeshes + // get the end time of zje operation, calculate delta t double fEnd = (double)timeGetTime(); double dTime = (fEnd - fCur) / 1000; char szTemp[128]; sprintf(szTemp,"%.5f",(float)dTime); SetDlgItemText(g_hDlg,IDC_ELOAD,szTemp); g_bLoadingFinished = true; + + // check whether the loading process has failed ... if (NULL == g_pcAsset->pcScene) { CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this asset:", D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + + // print ASSIMPs error string to the log display CLogDisplay::Instance().AddEntry(aiGetErrorString(), D3DCOLOR_ARGB(0xFF,0xFF,0,0)); return 1; @@ -123,42 +137,72 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) } //------------------------------------------------------------------------------- +// Recursivly count the number of nodes in an asset's node graph +// Used by LoadAsset() +//------------------------------------------------------------------------------- +void GetNodeCount(aiNode* pcNode, unsigned int* piCnt) +{ + *piCnt = *piCnt+1; + for (unsigned int i = 0; i < pcNode->mNumChildren;++i) + GetNodeCount(pcNode->mChildren[i],piCnt); +} + +//------------------------------------------------------------------------------- +// load the current asset +// THe path to the asset is specified in the global path variable //------------------------------------------------------------------------------- int LoadAsset(void) - { +{ + // set the world and world rotation matrices to the identuty g_mWorldRotate = aiMatrix4x4(); g_mWorld = aiMatrix4x4(); + // create a helper thread to load the asset DWORD dwID; g_bLoadingCanceled = false; g_pcAsset = new AssetHelper(); g_hThreadHandle = CreateThread(NULL,0,&LoadThreadProc,NULL,0,&dwID); + + if (!g_hThreadHandle) + { + CLogDisplay::Instance().AddEntry( + "[ERROR] Unable to create helper thread for loading", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + return 0; + } + + // show the progress bar dialog DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_LOADDIALOG), g_hDlg,&ProgressMessageProc); + // now we should have loaded the asset. Check this ... g_bLoadingFinished = false; if (!g_pcAsset || !g_pcAsset->pcScene) - { + { if (g_pcAsset) - { + { delete g_pcAsset; g_pcAsset = NULL; - } - return 0; } + return 0; + } + // allocate a new MeshHelper array and build a new instance + // for each mesh in the original asset g_pcAsset->apcMeshes = new AssetHelper::MeshHelper*[ g_pcAsset->pcScene->mNumMeshes](); + // get the number of vertices/faces in the model unsigned int iNumVert = 0; unsigned int iNumFaces = 0; for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + { iNumVert += g_pcAsset->pcScene->mMeshes[i]->mNumVertices; iNumFaces += g_pcAsset->pcScene->mMeshes[i]->mNumFaces; g_pcAsset->apcMeshes[i] = new AssetHelper::MeshHelper(); - } - char szOut[120]; + } + // and fill the statistic edit controls + char szOut[1024]; sprintf(szOut,"%i",(int)iNumVert); SetDlgItemText(g_hDlg,IDC_EVERT,szOut); sprintf(szOut,"%i",(int)iNumFaces); @@ -166,25 +210,41 @@ int LoadAsset(void) sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMaterials); SetDlgItemText(g_hDlg,IDC_EMAT,szOut); + // need to get the number of nodes + iNumVert = 0; + GetNodeCount(g_pcAsset->pcScene->mRootNode,&iNumVert); + sprintf(szOut,"%i",(int)iNumVert); + SetDlgItemText(g_hDlg,IDC_ENODE,szOut); + + // build a new caption string for the viewer + sprintf(szOut,AI_VIEW_CAPTION_BASE " [%s]",g_szFileName); + SetWindowText(g_hDlg,szOut); + + // scale the asset vertices to fit into the viewer window ScaleAsset(); + // reset the camera view to the default position g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f); g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f); g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f); g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f); + // build native D3D vertex/index buffers, textures, materials return CreateAssetData(); - } +} //------------------------------------------------------------------------------- +// Delete the loaded asset //------------------------------------------------------------------------------- int DeleteAsset(void) { if (!g_pcAsset)return 0; + // don't anymore know why this was necessary ... Render(); + // delete everything DeleteAssetData(); for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { @@ -195,9 +255,16 @@ int DeleteAsset(void) delete g_pcAsset; g_pcAsset = NULL; + // clear all stats edit controls SetDlgItemText(g_hDlg,IDC_EVERT,"0"); SetDlgItemText(g_hDlg,IDC_EFACE,"0"); SetDlgItemText(g_hDlg,IDC_EMAT,"0"); + SetDlgItemText(g_hDlg,IDC_ENODE,"0"); + SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); + SetDlgItemText(g_hDlg,IDC_ETEX,"0"); + + // reset the caption of the viewer window + SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE); return 1; } @@ -357,12 +424,12 @@ int GenerateNormalsAsLineList(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSo // The animations are added in order //------------------------------------------------------------------------------- int FillAnimList(void) - { +{ // clear the combo box SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0); if (0 == g_pcAsset->pcScene->mNumAnimations) - { + { // disable all UI components related to animations EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),FALSE); EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),FALSE); @@ -374,7 +441,7 @@ int FillAnimList(void) EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),FALSE); } else - { + { // reenable all animation components if they have been // disabled for a previous mesh EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),TRUE); @@ -388,13 +455,276 @@ int FillAnimList(void) // now fill in all animation names for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i) - { + { SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0, ( LPARAM ) g_pcAsset->pcScene->mAnimations[i]->mName.data); - } } - return 1; } + return 1; +} + + +//------------------------------------------------------------------------------- +// Add a node to the display list +// Recusrivly add all subnodes +// iNode - Index of the node image in the tree view's image lust +// iIndex - Index of the node in the parent's child list +// iDepth - Current depth of the node +// pcNode - Node object +// hRoot - Parent tree view node +//------------------------------------------------------------------------------- +int AddNodeToDisplayList(unsigned int iNode, + unsigned int iIndex, + unsigned int iDepth, + const aiNode* pcNode, + HTREEITEM hRoot) +{ + ai_assert(NULL != pcNode); + + char chTemp[512]; + + if(0 == pcNode->mName.length) + { + if (iNode >= 100) + { + iNode += iDepth * 1000; + } + else if (iNode >= 10) + { + iNode += iDepth * 100; + } + else iNode += iDepth * 10; + sprintf(chTemp,"Node %i",iNode); + } + else strcpy(chTemp,pcNode->mName.data); + + TVITEMEX tvi; + TVINSERTSTRUCT sNew; + tvi.pszText = chTemp; + tvi.cchTextMax = (int)strlen(chTemp); + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE; + tvi.iImage = iNode; + tvi.iSelectedImage = iNode; + tvi.lParam = (LPARAM)0; + + sNew.itemex = tvi; + sNew.hInsertAfter = TVI_LAST; + sNew.hParent = hRoot; + + // add the item to the list + HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), + TVM_INSERTITEM, + 0, + (LPARAM)(LPTVINSERTSTRUCT)&sNew); + + // recursively add all child nodes + ++iDepth; + for (unsigned int i = 0; i< pcNode->mNumChildren;++i) + { + AddNodeToDisplayList(iNode,i,iDepth,pcNode->mChildren[i],hTexture); + } + return 1; +} + + +//------------------------------------------------------------------------------- +// Add a texture to the display list +// pcMat - material containing the texture +// hTexture - Handle to the material tree item +// iTexture - Index of the texture image in the image list of the tree view +// szPath - Path to the texture +// iUVIndex - UV index to be used for the texture +// fBlendFactor - Blend factor to be used for the texture +// eTextureOp - texture operation to be used for the texture +//------------------------------------------------------------------------------- +int AddTextureToDisplayList(unsigned int iType, + unsigned int iIndex, + const aiString* szPath, + HTREEITEM hFX, + const aiMaterial* pcMat, + unsigned int iTexture = 0, + unsigned int iUVIndex = 0, + const float fBlendFactor = 0.0f, + aiTextureOp eTextureOp = aiTextureOp_Multiply) +{ + char chTemp[512]; + const char* sz = strrchr(szPath->data,'\\'); + if (!sz)sz = strrchr(szPath->data,'/'); + if (!sz)sz = szPath->data; + + const char* szType; + switch (iType) + { + case AI_TEXTYPE_DIFFUSE: + szType = "Diffuse";break; + case AI_TEXTYPE_SPECULAR: + szType = "Specular";break; + case AI_TEXTYPE_AMBIENT: + szType = "Ambient";break; + case AI_TEXTYPE_EMISSIVE: + szType = "Emissive";break; + case AI_TEXTYPE_HEIGHT: + szType = "HeightMap";break; + case AI_TEXTYPE_NORMALS: + szType = "NormalMap";break; + case AI_TEXTYPE_SHININESS: + szType = "Shininess";break; + }; + sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz); + + TVITEMEX tvi; + TVINSERTSTRUCT sNew; + tvi.pszText = chTemp; + tvi.cchTextMax = (int)strlen(chTemp); + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE; + tvi.iImage = iTexture; + tvi.iSelectedImage = iTexture; + tvi.lParam = (LPARAM)0; + + sNew.itemex = tvi; + sNew.hInsertAfter = TVI_LAST; + sNew.hParent = hFX; + + // add the item to the list + HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), + TVM_INSERTITEM, + 0, + (LPARAM)(LPTVINSERTSTRUCT)&sNew); + return 1; +} + + +//------------------------------------------------------------------------------- +// Add a material and all sub textures to the display mode list +// pcMat - material to be added +// hRoot - Handle to the root of the tree view +// iFX - Index of the material image in the image list of the tree view +// iTexture - Index of the texture image in the image list of the tree view +// iIndex - Material index +//------------------------------------------------------------------------------- +int AddMaterialToDisplayList(HTREEITEM hRoot, const aiMaterial* pcMat, + unsigned int iFX, unsigned int iTexture, unsigned int iIndex) +{ + // use the name of the material, if possible + char chTemp[512]; + aiString szOut; + if (AI_SUCCESS != aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szOut)) + { + sprintf(chTemp,"Material %i",iIndex+1); + } + else + { + sprintf(chTemp,"%s (%i)",szOut.data,iIndex+1); + } + TVITEMEX tvi; + TVINSERTSTRUCT sNew; + tvi.pszText = chTemp; + tvi.cchTextMax = (int)strlen(chTemp); + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE; + tvi.iImage = iFX; + tvi.iSelectedImage = iFX; + tvi.lParam = (LPARAM)0; + tvi.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE ; + + sNew.itemex = tvi; + sNew.hInsertAfter = TVI_LAST; + sNew.hParent = hRoot; + + // add the item to the list + HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), + TVM_INSERTITEM, + 0, + (LPARAM)(LPTVINSERTSTRUCT)&sNew); + + // for each texture in the list ... add it + unsigned int iUV; + float fBlend; + aiTextureOp eOp; + aiString szPath; + for (unsigned int i = 0; i < 7;++i) + { + unsigned int iNum = 0; + while (true) + { + if (AI_SUCCESS != aiGetMaterialTexture(pcMat,iNum,i, + &szPath,&iUV,&fBlend,&eOp)) + { + break; + } + AddTextureToDisplayList(i,iNum,&szPath,hTexture, + pcMat,iTexture,iUV,fBlend,eOp); + ++iNum; + } + } + return 1; +} + +//------------------------------------------------------------------------------- +// Fill the UI combobox with a list of all supported view modi +// +// The display modes are added in order +//------------------------------------------------------------------------------- +int FillDisplayList(void) +{ + // Initialize the tree view window. + + // First, create the image list we will need. +#define NUM_BITMAPS 4 + HIMAGELIST hIml = ImageList_Create( 16,16,ILC_COLOR24, NUM_BITMAPS, 0 ); + + + // Load the bitmaps and add them to the image lists. + HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BFX)); + int iFX = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE)); + int iNode = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX)); + int iTexture = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT)); + int iRoot = ImageList_Add(hIml, hBmp, NULL); + DeleteObject(hBmp); + + // Associate the image list with the tree. + TreeView_SetImageList(GetDlgItem(g_hDlg,IDC_TREE1), hIml, TVSIL_NORMAL); + + // fill in the first entry + TVITEMEX tvi; + TVINSERTSTRUCT sNew; + tvi.pszText = "Model"; + tvi.cchTextMax = (int)strlen(tvi.pszText); + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE; + tvi.state = TVIS_EXPANDED ; + tvi.iImage = iRoot; + tvi.iSelectedImage = iRoot; + tvi.lParam = (LPARAM)0; + + sNew.itemex = tvi; + sNew.hInsertAfter = TVI_ROOT; + sNew.hParent = 0; + + HTREEITEM hRoot = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1), + TVM_INSERTITEM, + 0, + (LPARAM)(LPTVINSERTSTRUCT)&sNew); + + + // add each loaded material + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMaterials;++i) + { + AddMaterialToDisplayList(hRoot,g_pcAsset->pcScene->mMaterials[i], + iFX,iTexture,i); + } + + // now add all loaded nodes recursively + AddNodeToDisplayList(iNode,0,0,g_pcAsset->pcScene->mRootNode,hRoot); + return 1; +} //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- @@ -416,29 +746,59 @@ int CreateAssetData(void) MessageBox(g_hDlg,"Failed to create vertex buffer", "ASSIMP Viewer Utility",MB_OK); return 2; - } - // create index buffer - if(FAILED( g_piDevice->CreateIndexBuffer( 4 * - g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3, - D3DUSAGE_WRITEONLY, - D3DFMT_INDEX32, - D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL))) + } + + // check whether we can use 16 bit indices + if (g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3 >= 65536) + { + // create 32 bit index buffer + if(FAILED( g_piDevice->CreateIndexBuffer( 4 * + g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3, + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX32, + D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL))) { - MessageBox(g_hDlg,"Failed to create index buffer", - "ASSIMP Viewer Utility",MB_OK); - return 2; + MessageBox(g_hDlg,"Failed to create 32 Bit index buffer", + "ASSIMP Viewer Utility",MB_OK); + return 2; } - // now fill the index buffer - unsigned int* pbData; - g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0); - for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x) + // now fill the index buffer + unsigned int* pbData; + g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0); + for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x) { - for (unsigned int a = 0; a < 3;++a) + for (unsigned int a = 0; a < 3;++a) { - *pbData++ = g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a]; + *pbData++ = g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a]; } } + } + else + { + // create 16 bit index buffer + if(FAILED( g_piDevice->CreateIndexBuffer( 2 * + g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3, + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX16, + D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL))) + { + MessageBox(g_hDlg,"Failed to create 16 Bit index buffer", + "ASSIMP Viewer Utility",MB_OK); + return 2; + } + + // now fill the index buffer + uint16_t* pbData; + g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0); + for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x) + { + for (unsigned int a = 0; a < 3;++a) + { + *pbData++ = (uint16_t)g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a]; + } + } + } g_pcAsset->apcMeshes[i]->piIB->Unlock(); // now fill the vertex buffer @@ -504,6 +864,7 @@ int CreateAssetData(void) sprintf(szTemp,"%i", g_iShaderCount); SetDlgItemText(g_hDlg,IDC_ESHADER,szTemp); + FillDisplayList(); return FillAnimList(); } @@ -755,6 +1116,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) { D3DDEVTYPE eType = bHW ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + // get the client rectangle of the window. RECT sRect; GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); sRect.right -= sRect.left; @@ -763,17 +1125,26 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) D3DPRESENT_PARAMETERS sParams; memset(&sParams,0,sizeof(D3DPRESENT_PARAMETERS)); + // get the current display mode D3DDISPLAYMODE sMode; g_piD3D->GetAdapterDisplayMode(0,&sMode); - sParams.Windowed = TRUE; - sParams.hDeviceWindow = GetDlgItem( g_hDlg, IDC_RT ); - sParams.EnableAutoDepthStencil = TRUE; - sParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; - sParams.BackBufferWidth = (UINT)sRect.right; - sParams.BackBufferHeight = (UINT)sRect.bottom; - sParams.AutoDepthStencilFormat = D3DFMT_D24X8; - sParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + // fill the presentation parameter structure + sParams.Windowed = TRUE; + sParams.hDeviceWindow = GetDlgItem( g_hDlg, IDC_RT ); + sParams.EnableAutoDepthStencil = TRUE; + sParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; + sParams.BackBufferWidth = (UINT)sRect.right; + sParams.BackBufferHeight = (UINT)sRect.bottom; + sParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + + // check whether we can use a D32 depth buffer format + if (SUCCEEDED ( g_piD3D->CheckDepthStencilMatch(0,eType, + D3DFMT_X8R8G8B8,D3DFMT_X8R8G8B8,D3DFMT_D32))) + { + sParams.AutoDepthStencilFormat = D3DFMT_D32; + } + else sParams.AutoDepthStencilFormat = D3DFMT_D24X8; // find the highest multisample type available on this device D3DMULTISAMPLE_TYPE sMS = D3DMULTISAMPLE_2_SAMPLES; @@ -797,6 +1168,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) sParams.MultiSampleType = sMSOut; } + // create the D3D9 device object if(FAILED(g_piD3D->CreateDevice(0,eType, g_hDlg,D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,&sParams,&g_piDevice))) { @@ -810,6 +1182,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) } g_piDevice->SetFVF(AssetHelper::Vertex::GetFVF()); + // compile the default material shader (gray gouraud/phong) ID3DXBuffer* piBuffer = NULL; if(FAILED( D3DXCreateEffect(g_piDevice, g_szDefaultShader.c_str(), @@ -833,6 +1206,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) piBuffer = NULL; } + // create the shader used to draw the HUD if(FAILED( D3DXCreateEffect(g_piDevice, g_szPassThroughShader.c_str(),(UINT)g_szPassThroughShader.length(), NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piPassThroughEffect,&piBuffer))) @@ -850,6 +1224,8 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) piBuffer->Release(); piBuffer = NULL; } + + // create the shader used to visualize normal vectors if(FAILED( D3DXCreateEffect(g_piDevice, g_szNormalsShader.c_str(),(UINT)g_szNormalsShader.length(), NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piNormalsEffect, &piBuffer))) @@ -868,6 +1244,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) piBuffer = NULL; } + // get the capabilities of the device object g_piDevice->GetDeviceCaps(&g_sCaps); if(g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0)) { diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index d30fafd82..72f7eecbf 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -1,12 +1,43 @@ -//------------------------------------------------------------------------------- -/** -* This program is distributed under the terms of the GNU Lesser General -* Public License (LGPL). -* -* ASSIMP Viewer Utility -* +/* +--------------------------------------------------------------------------- +Free Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- */ -//------------------------------------------------------------------------------- #if (!defined AV_MAIN_H_INCLUDED) #define AV_MAIN_H_INCLUDED @@ -15,7 +46,6 @@ #include "resource.h" // Include ASSIMP headers -#include "aiDefs.h" #include "aiAnim.h" #include "aiAssert.h" #include "aiFileIO.h" @@ -48,6 +78,7 @@ namespace AssimpView { #include "Shaders.h" #include "Background.h" #include "LogDisplay.h" +#include "LogWindow.h" //------------------------------------------------------------------------------- // Function prototypes @@ -151,13 +182,20 @@ void HandleCommandLine(char* p_szCommand); // Position of the cursor relative to the 3ds max' like control circle //------------------------------------------------------------------------------- enum EClickPos - { +{ + // The click was inside the inner circle (x,y axis) EClickPos_Circle, + // The click was inside one of tghe vertical snap-ins EClickPos_CircleVert, + // The click was inside onf of the horizontal snap-ins EClickPos_CircleHor, + // the cklick was outside the circle (z-axis) EClickPos_Outside - }; +}; +#if (!defined AI_VIEW_CAPTION_BASE) +# define AI_VIEW_CAPTION_BASE "AssimpView 1.0" +#endif // !! AI_VIEW_CAPTION_BASE //------------------------------------------------------------------------------- // Evil globals diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index 9d2913bad..dec9b4741 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/tools/assimp_view/assimp_view.rc @@ -55,56 +55,69 @@ BEGIN CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,138,281,1 END -IDD_DIALOGMAIN DIALOGEX 0, 0, 583, 384 +IDD_DIALOGMAIN DIALOGEX 0, 0, 594, 384 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Free Asset Import Library - ModelViewer " MENU IDR_MENU1 FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - CONTROL "",IDC_RT,"Static",SS_OWNERDRAW,10,10,452,344 - GROUPBOX "Rendering Options",IDC_STATIC,468,108,108,96 - CONTROL "MultiSample image",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,123,80,10 - CONTROL "Toggle Wireframe",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,133,73,10 - CONTROL "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,143,69,10 - GROUPBOX "Statistics",IDC_STATIC,468,6,108,96 - LTEXT "NumVertices:\t 0",IDC_NUMVERTS,477,24,47,8 - LTEXT "NumFaces:\t 0",IDC_NUMFACES,477,36,45,8 - LTEXT "NumMaterials:\t 0",IDC_NUMMATS,477,48,48,8 - LTEXT "FPS:\t\t 0",IDC_FPS,477,73,34,8 - CONTROL "Display Normals",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,153,66,10 - GROUPBOX "Interaction",IDC_STATIC,468,210,108,48 - CONTROL "Toggle AutoRotate",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,223,74,10 - CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,0,360,583,24 - GROUPBOX "Animation",IDC_SANIMGB,468,264,108,90 - EDITTEXT IDC_EVERT,531,21,36,12,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EFACE,531,34,36,12,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EMAT,531,47,36,12,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_EFPS,531,72,36,12,ES_AUTOHSCROLL | ES_READONLY - CONTROL "Rotate light sources",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,242,74,10 - CONTROL "2 directional lights",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,163,73,10 - LTEXT "LoadTime:",IDC_LOADTIME,477,85,34,8 - EDITTEXT IDC_ELOAD,531,85,36,12,ES_AUTOHSCROLL | ES_READONLY - CONTROL "Zoom/Rotate",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,232,58,10 - CONTROL "Low quality lighting",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,173,74,10 - CONTROL "No specular lighting",IDC_NOSPECULAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,478,183,74,10 - CONTROL "Play [OK]",IDC_PLAYANIM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,480,276,42,10 - CONTROL "",IDC_SPEED,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | TBS_TOOLTIPS | WS_TABSTOP,480,288,90,12 - LTEXT "Speed: [+/-]",IDC_SSPEED,528,277,42,8 - LTEXT "NumShaders:\t 0",IDC_NUMMATS2,477,61,48,8 - EDITTEXT IDC_ESHADER,531,59,36,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "[M]",IDC_STATIC,557,123,11,8 - LTEXT "[W]",IDC_STATIC,557,133,11,8 - LTEXT "[D]",IDC_STATIC,557,143,11,8 - LTEXT "[N]",IDC_STATIC,557,153,11,8 - LTEXT "[L]",IDC_STATIC,557,163,11,8 - LTEXT "[P]",IDC_STATIC,557,173,11,8 - LTEXT "[S]",IDC_STATIC,557,183,11,8 - LTEXT "[A]",IDC_STATIC,557,223,11,8 - LTEXT "[Z]",IDC_STATIC,557,232,11,8 - LTEXT "[R]",IDC_STATIC,557,242,11,8 - COMBOBOX IDC_COMBO1,480,315,90,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP - LTEXT "Anim: [Pg up/Pg down]",IDC_SANIM,483,302,74,8 - CONTROL "Play all in order [O]",IDC_PINORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,479,334,77,10 + CONTROL "",IDC_RT,"Static",SS_OWNERDRAW,3,5,462,351 + CONTROL "MultiSample image",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,173,80,10 + CONTROL "Toggle Wireframe",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,183,73,10 + CONTROL "Disable Materials",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,193,69,10 + LTEXT "Verts:",IDC_NUMVERTS,475,15,47,8 + LTEXT "Faces:\t",IDC_NUMFACES,475,27,45,8 + LTEXT "Mats:",IDC_NUMMATS,540,27,26,8 + LTEXT "FPS:",IDC_FPS,475,65,21,8 + CONTROL "Display Normals",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,203,66,10 + CONTROL "Toggle AutoRotate",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,257,74,10 + CONTROL 130,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,0,360,600,25 + EDITTEXT IDC_EVERT,504,12,32,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EFACE,504,25,32,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EMAT,564,25,27,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EFPS,504,63,32,12,ES_AUTOHSCROLL | ES_READONLY + CONTROL "Rotate light sources",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,276,74,10 + CONTROL "2 directional lights",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,213,73,10 + LTEXT "Time:",IDC_LOADTIME,475,76,46,8 + EDITTEXT IDC_ELOAD,504,75,32,12,ES_AUTOHSCROLL | ES_READONLY + CONTROL "Zoom/Rotate",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,266,58,10 + CONTROL "Low quality lighting",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,223,74,10 + CONTROL "No specular lighting",IDC_NOSPECULAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,473,233,74,10 + CONTROL "Play [OK]",IDC_PLAYANIM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,480,297,42,10 + CONTROL "",IDC_SPEED,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | TBS_TOOLTIPS | WS_TABSTOP,480,309,90,12 + LTEXT "Speed: [+/-]",IDC_SSPEED,526,297,42,8 + LTEXT "Shd:",IDC_NUMMATS2,476,41,23,8 + EDITTEXT IDC_ESHADER,504,39,32,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "[M]",IDC_STATIC,570,173,11,8 + LTEXT "[W]",IDC_STATIC,570,183,11,8 + LTEXT "[D]",IDC_STATIC,570,193,11,8 + LTEXT "[N]",IDC_STATIC,570,203,11,8 + LTEXT "[L]",IDC_STATIC,570,213,11,8 + LTEXT "[P]",IDC_STATIC,570,223,11,8 + LTEXT "[S]",IDC_STATIC,570,233,11,8 + LTEXT "[A]",IDC_STATIC,569,257,11,8 + LTEXT "[Z]",IDC_STATIC,569,267,11,8 + LTEXT "[R]",IDC_STATIC,569,276,11,8 + COMBOBOX IDC_COMBO1,480,331,90,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Anim: [Pg up/Pg down]",IDC_SANIM,483,320,74,8 + CONTROL "Play all in order [O]",IDC_PINORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,479,346,77,10 + CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,0,114,9 + CONTROL 148,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,161,114,9 + CONTROL 147,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,245,114,9 + CONTROL 145,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,287,114,9 + CONTROL 146,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,89,114,9 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,469,0,1,360 + CONTROL "<<",IDC_BLUBB,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,439,367,27,10 + CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,0,10,9 + CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,89,10,9 + CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,583,161,10,9 + CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,245,10,9 + CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,584,287,10,9 + LTEXT "Nodes:",IDC_STATIC,540,14,24,8 + EDITTEXT IDC_ENODE,564,12,27,12,ES_AUTOHSCROLL | ES_READONLY + CONTROL "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | WS_BORDER | WS_TABSTOP,470,98,123,64 + LTEXT "Tex:",IDC_STATIC,476,53,16,8 + EDITTEXT IDC_ETEX,504,51,32,12,ES_AUTOHSCROLL | ES_READONLY END IDD_LOADDIALOG DIALOGEX 0, 0, 278, 99 @@ -127,6 +140,15 @@ BEGIN CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,16,490,1 END +IDD_LOGVIEW DIALOGEX 0, 0, 365, 182 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE +CAPTION "AssimpView Log Output" +FONT 8, "Courier New", 400, 0, 0x0 +BEGIN + EDITTEXT IDC_EDIT1,0,0,365,181,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL +END + #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -208,13 +230,6 @@ BEGIN BOTTOMMARGIN, 158 END - IDD_DIALOGMAIN, DIALOG - BEGIN - RIGHTMARGIN, 576 - TOPMARGIN, 7 - BOTTOMMARGIN, 307 - END - IDD_LOADDIALOG, DIALOG BEGIN LEFTMARGIN, 7 @@ -230,6 +245,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 339 END + + IDD_LOGVIEW, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 358 + TOPMARGIN, 14 + BOTTOMMARGIN, 175 + END END #endif // APSTUDIO_INVOKED @@ -240,6 +263,15 @@ END // IDB_BITMAP1 BITMAP "banner.bmp" +IDB_BANIM BITMAP "base_anim.bmp" +IDB_BDISPLAY BITMAP "base_display.bmp" +IDB_BINTER BITMAP "base_inter.bmp" +IDB_BRENDERING BITMAP "base_rendering.bmp" +IDB_BSTATS BITMAP "base_stats.bmp" +IDB_BTX BITMAP "tx.bmp" +IDB_BFX BITMAP "fx.bmp" +IDB_BNODE BITMAP "n.bmp" +IDB_BROOT BITMAP "root.bmp" ///////////////////////////////////////////////////////////////////////////// // @@ -260,6 +292,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Quit", ID_VIEWER_QUIT END + POPUP "Tools" + BEGIN + MENUITEM "Log window", ID_TOOLS_LOGWINDOW + MENUITEM "Save log to file", ID_TOOLS_SAVELOGTOFILE + MENUITEM "Clear log", ID_TOOLS_CLEARLOG + END POPUP "Background" BEGIN MENUITEM "Set color", ID_BACKGROUND_SETCOLOR diff --git a/tools/assimp_view/base.PNG b/tools/assimp_view/base.PNG new file mode 100644 index 000000000..3e13e00eb Binary files /dev/null and b/tools/assimp_view/base.PNG differ diff --git a/tools/assimp_view/base_anim.bmp b/tools/assimp_view/base_anim.bmp new file mode 100644 index 000000000..e65478cb2 Binary files /dev/null and b/tools/assimp_view/base_anim.bmp differ diff --git a/tools/assimp_view/base_display.bmp b/tools/assimp_view/base_display.bmp new file mode 100644 index 000000000..f13410a89 Binary files /dev/null and b/tools/assimp_view/base_display.bmp differ diff --git a/tools/assimp_view/base_inter.bmp b/tools/assimp_view/base_inter.bmp new file mode 100644 index 000000000..073136961 Binary files /dev/null and b/tools/assimp_view/base_inter.bmp differ diff --git a/tools/assimp_view/base_rendering.bmp b/tools/assimp_view/base_rendering.bmp new file mode 100644 index 000000000..bec8699a4 Binary files /dev/null and b/tools/assimp_view/base_rendering.bmp differ diff --git a/tools/assimp_view/base_stats.bmp b/tools/assimp_view/base_stats.bmp new file mode 100644 index 000000000..130ce5336 Binary files /dev/null and b/tools/assimp_view/base_stats.bmp differ diff --git a/tools/assimp_view/fx.bmp b/tools/assimp_view/fx.bmp new file mode 100644 index 000000000..c001aae55 Binary files /dev/null and b/tools/assimp_view/fx.bmp differ diff --git a/tools/assimp_view/n.bmp b/tools/assimp_view/n.bmp new file mode 100644 index 000000000..e3afa633f Binary files /dev/null and b/tools/assimp_view/n.bmp differ diff --git a/tools/assimp_view/resource.h b/tools/assimp_view/resource.h index efaba4434..7de873532 100644 --- a/tools/assimp_view/resource.h +++ b/tools/assimp_view/resource.h @@ -20,6 +20,23 @@ #define IDB_MAXCIRCLE 142 #define IDR_HUD 143 #define IDR_HUDMASK 144 +#define IDB_BANIM 145 +#define IDB_BITMAP4 146 +#define IDB_BDISPLAY 146 +#define IDB_BITMAP5 147 +#define IDB_BINTER 147 +#define IDB_BITMAP6 148 +#define IDB_BRENDERING 148 +#define IDB_BITMAP7 149 +#define IDB_BSTATS 149 +#define IDB_BTX 150 +#define IDB_BITMAP8 151 +#define IDB_BFX 151 +#define IDB_BITMAP9 152 +#define IDB_BNODE 152 +#define IDB_BITMAP10 153 +#define IDB_BROOT 153 +#define IDD_LOGVIEW 154 #define IDC_CHECK1 1000 #define IDC_TOGGLEMS 1000 #define IDC_CHECK2 1001 @@ -61,6 +78,12 @@ #define IDC_SSPEED 1029 #define IDC_SANIM 1030 #define IDC_SANIMGB 1031 +#define IDC_ENODE 1031 +#define IDC_ESHADER2 1032 +#define IDC_ETEX 1032 +#define IDC_TREE1 1033 +#define IDC_EDIT1 1034 +#define IDC_BLUBB 1037 #define ID_VIEWER_OPEN 32771 #define ID_VIEWER_CLOSETHIS 32772 #define ID_VIEWER_CLOSEASSET 32773 @@ -75,6 +98,9 @@ #define ID_Menu 32782 #define ID_BACKGROUND_LOADSKYBOX 32783 #define ID_VIEWER_H 32784 +#define ID_TOOLS_LOGWINDOW 32785 +#define ID_TOOLS_SAVELOGTOFILE 32786 +#define ID_TOOLS_CLEARLOG 32787 #define IDC_STATIC -1 // Next default values for new objects @@ -82,9 +108,9 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 145 -#define _APS_NEXT_COMMAND_VALUE 32785 -#define _APS_NEXT_CONTROL_VALUE 1032 +#define _APS_NEXT_RESOURCE_VALUE 155 +#define _APS_NEXT_COMMAND_VALUE 32788 +#define _APS_NEXT_CONTROL_VALUE 1038 #define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/tools/assimp_view/root.bmp b/tools/assimp_view/root.bmp new file mode 100644 index 000000000..b45baeb96 Binary files /dev/null and b/tools/assimp_view/root.bmp differ diff --git a/tools/assimp_view/tx.bmp b/tools/assimp_view/tx.bmp new file mode 100644 index 000000000..4c303b628 Binary files /dev/null and b/tools/assimp_view/tx.bmp differ diff --git a/workspaces/vc8/assimp.sln b/workspaces/vc8/assimp.sln index 30127cbf2..162cedb1e 100644 --- a/workspaces/vc8/assimp.sln +++ b/workspaces/vc8/assimp.sln @@ -2,24 +2,40 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp", "assimp.vcproj", "{5691E159-2D9B-407F-971F-EA5C592DC524}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "assimp_view", "assimp_view.vcproj", "{B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection ProjectSection(ProjectDependencies) = postProject {5691E159-2D9B-407F-971F-EA5C592DC524} = {5691E159-2D9B-407F-971F-EA5C592DC524} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_DLL|Win32 = Debug_DLL|Win32 Debug|Win32 = Debug|Win32 + Release_DLL|Win32 = Release_DLL|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5691E159-2D9B-407F-971F-EA5C592DC524}.Debug_DLL|Win32.ActiveCfg = Debug_DLL|Win32 + {5691E159-2D9B-407F-971F-EA5C592DC524}.Debug_DLL|Win32.Build.0 = Debug_DLL|Win32 {5691E159-2D9B-407F-971F-EA5C592DC524}.Debug|Win32.ActiveCfg = Debug|Win32 {5691E159-2D9B-407F-971F-EA5C592DC524}.Debug|Win32.Build.0 = Debug|Win32 + {5691E159-2D9B-407F-971F-EA5C592DC524}.Release_DLL|Win32.ActiveCfg = Release_DLL|Win32 + {5691E159-2D9B-407F-971F-EA5C592DC524}.Release_DLL|Win32.Build.0 = Release_DLL|Win32 {5691E159-2D9B-407F-971F-EA5C592DC524}.Release|Win32.ActiveCfg = Release|Win32 {5691E159-2D9B-407F-971F-EA5C592DC524}.Release|Win32.Build.0 = Release|Win32 + {B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}.Debug_DLL|Win32.ActiveCfg = Debug|Win32 {B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}.Debug|Win32.ActiveCfg = Debug|Win32 {B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}.Debug|Win32.Build.0 = Debug|Win32 + {B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}.Release_DLL|Win32.ActiveCfg = Release|Win32 {B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}.Release|Win32.ActiveCfg = Release|Win32 {B17B959B-BB8A-4596-AF0F-A8C8DBBC3C5E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index 4ed16778b..1800313a4 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -80,6 +80,7 @@ OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)" IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)" ConfigurationType="4" + WholeProgramOptimization="0" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -151,10 +295,6 @@ RelativePath="..\..\include\aiAssert.h" > - - @@ -195,6 +335,10 @@ RelativePath="..\..\include\aiScene.h" > + + @@ -223,6 +367,14 @@ RelativePath="..\..\include\IOSystem.h" > + + + + @@ -235,18 +387,6 @@ - - - - - - + + + + + + + + + + + + + + @@ -566,6 +734,10 @@ + + + + + + + + + + + + @@ -600,6 +792,34 @@ + + + + + + + + + + + + + + diff --git a/workspaces/vc8/assimp_view.vcproj b/workspaces/vc8/assimp_view.vcproj index 66edd3bc3..7d465339b 100644 --- a/workspaces/vc8/assimp_view.vcproj +++ b/workspaces/vc8/assimp_view.vcproj @@ -194,6 +194,10 @@ RelativePath="..\..\tools\assimp_view\Background.cpp" > + + @@ -206,6 +210,10 @@ RelativePath="..\..\tools\assimp_view\LogDisplay.cpp" > + + @@ -264,10 +272,18 @@ RelativePath="..\..\tools\assimp_view\Camera.h" > + + + + @@ -302,6 +318,30 @@ RelativePath="..\..\tools\assimp_view\banner.bmp" > + + + + + + + + + + + + @@ -310,6 +350,14 @@ RelativePath="..\..\tools\assimp_view\HUDMask.png" > + + + + @@ -318,6 +366,10 @@ RelativePath="..\..\tools\assimp_view\text1.bin" > + +