From 8b2ca95419936f38cdd86e6a2f9f7bbe6e53979a Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Tue, 3 Jun 2008 21:50:53 +0000 Subject: [PATCH] Finalized material system. Fixed texture coordinate transformation. Improvements to the ASE loaders, normals for the 3DS loader fixed. First try to load bones for MDL7 models (first try = failure ;-)). git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@54 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/3DSConverter.cpp | 56 ++- code/3DSHelper.h | 31 +- code/3DSLoader.cpp | 32 +- code/ASELoader.cpp | 52 +++ code/ASELoader.h | 7 + code/ASEParser.cpp | 59 ++- code/MDLFileData.h | 2 +- code/MDLLoader.cpp | 92 +++- code/MDLLoader.h | 8 + code/MaterialSystem.cpp | 91 ++-- code/TextureTransform.cpp | 347 ++++++++++----- code/TextureTransform.h | 24 +- include/aiMaterial.h | 636 +++++++++++++++++++-------- include/aiMaterial.inl | 160 +++++++ include/aiMesh.h | 14 + tools/assimp_view/assimp_view.aps | Bin 353728 -> 353776 bytes tools/assimp_view/assimp_view.rc | 2 +- workspaces/vc8/assimp.vcproj | 686 +++++++++++++++--------------- 18 files changed, 1601 insertions(+), 698 deletions(-) create mode 100644 include/aiMaterial.inl diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index 5b578e2e4..36db5eb86 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -258,8 +258,15 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (Dot3DS::Dot3DSFile::Phong == oldMat.mShading || Dot3DS::Dot3DSFile::Metal == oldMat.mShading) { - mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); + if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) + { + oldMat.mShading = Dot3DS::Dot3DSFile::Gouraud; + } + else + { + mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); + mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); + } } // opacity @@ -268,6 +275,13 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, // bump height scaling mat.AddProperty( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING); + // two sided rendering? + if (oldMat.mTwoSided) + { + int i = 0; + mat.AddProperty(&i,1,AI_MATKEY_TWOSIDED); + } + // shading mode aiShadingMode eShading = aiShadingMode_NoShading; switch (oldMat.mShading) @@ -308,6 +322,13 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (is_not_qnan(oldMat.sTexDiffuse.mTextureBlend)) mat.AddProperty( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0)); + + if (aiTextureMapMode_Clamp != oldMat.sTexDiffuse.mMapMode) + { + int i = (int)oldMat.sTexSpecular.mMapMode; + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0)); + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0)); + } } if( oldMat.sTexSpecular.mMapName.length() > 0) { @@ -317,6 +338,13 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (is_not_qnan(oldMat.sTexSpecular.mTextureBlend)) mat.AddProperty( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0)); + + if (aiTextureMapMode_Clamp != oldMat.sTexSpecular.mMapMode) + { + int i = (int)oldMat.sTexSpecular.mMapMode; + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_U_SPECULAR(0)); + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_V_SPECULAR(0)); + } } if( oldMat.sTexOpacity.mMapName.length() > 0) { @@ -326,6 +354,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (is_not_qnan(oldMat.sTexOpacity.mTextureBlend)) mat.AddProperty( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0)); + if (aiTextureMapMode_Clamp != oldMat.sTexOpacity.mMapMode) + { + int i = (int)oldMat.sTexOpacity.mMapMode; + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_U_OPACITY(0)); + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_V_OPACITY(0)); + } } if( oldMat.sTexEmissive.mMapName.length() > 0) { @@ -335,6 +369,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend)) mat.AddProperty( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0)); + if (aiTextureMapMode_Clamp != oldMat.sTexEmissive.mMapMode) + { + int i = (int)oldMat.sTexEmissive.mMapMode; + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_U_EMISSIVE(0)); + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_V_EMISSIVE(0)); + } } if( oldMat.sTexBump.mMapName.length() > 0) { @@ -344,6 +384,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (is_not_qnan(oldMat.sTexBump.mTextureBlend)) mat.AddProperty( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_HEIGHT(0)); + if (aiTextureMapMode_Clamp != oldMat.sTexBump.mMapMode) + { + int i = (int)oldMat.sTexBump.mMapMode; + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_U_HEIGHT(0)); + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_V_HEIGHT(0)); + } } if( oldMat.sTexShininess.mMapName.length() > 0) { @@ -353,6 +399,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, if (is_not_qnan(oldMat.sTexShininess.mTextureBlend)) mat.AddProperty( &oldMat.sTexShininess.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0)); + if (aiTextureMapMode_Clamp != oldMat.sTexShininess.mMapMode) + { + int i = (int)oldMat.sTexShininess.mMapMode; + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_U_SHININESS(0)); + mat.AddProperty(&i,1,AI_MATKEY_MAPPINGMODE_V_SHININESS(0)); + } } // store the name of the material itself, too diff --git a/code/3DSHelper.h b/code/3DSHelper.h index da65b322c..b086bb384 100644 --- a/code/3DSHelper.h +++ b/code/3DSHelper.h @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/aiQuaternion.h" #include "../include/aiMesh.h" #include "../include/aiAnim.h" +#include "../include/aiMaterial.h" #include "SpatialSort.h" @@ -263,8 +264,14 @@ public: // Assumed to be in radians. CHUNK_MAT_MAP_ANG = 0xA35C, + // Tiling flags for 3DS files + CHUNK_MAT_MAP_TILING = 0xa351, + // Specifies the file name of a texture CHUNK_MAPFILE = 0xA300, + + // Specifies whether a materail requires two-sided rendering + CHUNK_MAT_TWO_SIDE = 0xA081, // ************************************************************** // Main keyframer chunk. Contains translation/rotation/scaling data @@ -338,7 +345,8 @@ struct Texture mOffsetU(0.0f), mOffsetV(0.0f), mRotation(0.0f), - iUVSrc(0) + iUVSrc(0), + mMapMode(aiTextureMapMode_Wrap) { mTextureBlend = std::numeric_limits::quiet_NaN(); } @@ -355,6 +363,9 @@ struct Texture float mOffsetV; float mRotation; + //! Specifies the mapping mode to be used for the texture + aiTextureMapMode mMapMode; + //! Used internally bool bPrivate; int iUVSrc; @@ -372,11 +383,13 @@ struct Material mBumpHeight (1.0f), iBakeUVTransform (0), pcSingleTexture (NULL), - mShininessStrength (1.0f) + mShininessStrength (1.0f), + mTwoSided (false) { static int iCnt = 0; - std::stringstream ss(mName); + std::stringstream ss; ss << "$$_UNNAMED_" << iCnt++ << "_$$"; + ss >> mName; } //! Name of the material @@ -395,7 +408,6 @@ struct Material Dot3DSFile::shadetype3ds mShading; //! Opacity of the material float mTransparency; - //! Diffuse texture channel Texture sTexDiffuse; //! Opacity texture channel @@ -408,16 +420,15 @@ struct Material Texture sTexEmissive; //! Shininess texture channel Texture sTexShininess; - //! Scaling factor for the bump values float mBumpHeight; - //! Emissive color aiColor3D mEmissive; - //! Ambient texture channel //! (used by the ASE format) Texture sTexAmbient; + //! True if the material must be rendered from two sides + bool mTwoSided; //! Used internally unsigned int iBakeUVTransform; @@ -431,8 +442,9 @@ struct Mesh Mesh() { static int iCnt = 0; - std::stringstream ss(mName); + std::stringstream ss; ss << "$$_UNNAMED_" << iCnt++ << "_$$"; + ss >> mName; } //! Name of the mesh @@ -469,8 +481,9 @@ struct Node { static int iCnt = 0; - std::stringstream ss(mName); + std::stringstream ss; ss << "$$_UNNAMED_" << iCnt++ << "_$$"; + ss >> mName; mHierarchyPos = 0; mHierarchyIndex = 0; diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 28a78202c..8c8f9804f 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -1096,6 +1096,10 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining) this->mCurrent += sizeof(uint16_t); break; + case Dot3DSFile::CHUNK_MAT_TWO_SIDE: + this->mScene->mMaterials.back().mTwoSided = true; + break; + case Dot3DSFile::CHUNK_MAT_SHININESS: pcf = &this->mScene->mMaterials.back().mSpecularExponent; *pcf = this->ParsePercentageChunk(); @@ -1203,21 +1207,23 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut) pcOut->mScaleU = *((float*)this->mCurrent); if (0.0f == pcOut->mScaleU) { - DefaultLogger::get()->warn("Inverse texture coordinate scaling in the " - "x direction is zero. This would be a division through zero. "); + DefaultLogger::get()->warn("Texture coordinate scaling in the " + "x direction is zero. Assuming this should be 1.0 ... "); pcOut->mScaleU = 1.0f; } - pcOut->mScaleU = 1.0f / pcOut->mScaleU; + // NOTE: some docs state it is 1/u, others say it is u ... ARGHH! + //pcOut->mScaleU = 1.0f / pcOut->mScaleU; break; case Dot3DSFile::CHUNK_MAT_MAP_VSCALE: pcOut->mScaleV = *((float*)this->mCurrent); if (0.0f == pcOut->mScaleV) { - DefaultLogger::get()->warn("Inverse texture coordinate scaling in the " - "y direction is zero. This would be a division through zero. "); + DefaultLogger::get()->warn("Texture coordinate scaling in the " + "y direction is zero. Assuming this should be 1.0 ... "); pcOut->mScaleV = 1.0f; } - pcOut->mScaleV = 1.0f / pcOut->mScaleV; + // NOTE: some docs state it is 1/v, others say it is v ... ARGHH! + //pcOut->mScaleV = 1.0f / pcOut->mScaleV; break; case Dot3DSFile::CHUNK_MAT_MAP_UOFFSET: pcOut->mOffsetU = *((float*)this->mCurrent); @@ -1228,6 +1234,20 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut) case Dot3DSFile::CHUNK_MAT_MAP_ANG: pcOut->mRotation = *((float*)this->mCurrent); break; + case Dot3DSFile::CHUNK_MAT_MAP_TILING: + uint16_t iFlags = *((uint16_t*)this->mCurrent); + + // check whether the mirror flag is set + if (iFlags & 0x2u) + { + pcOut->mMapMode = aiTextureMapMode_Mirror; + } + // assume that "decal" means clamping ... + else if (iFlags & 0x10u && iFlags & 0x1u) + { + pcOut->mMapMode = aiTextureMapMode_Clamp; + } + break; }; // Go to the starting position of the next chunk on this level diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 7cc604fd1..a700c8e00 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -128,6 +128,13 @@ void ASEImporter::InternReadFile( this->mParser = new ASE::Parser((const char*)this->mBuffer); this->mParser->Parse(); + // if absolutely no material has been loaded from the file + // we need to generate a default material + if (this->mParser->m_vMaterials.empty()) + { + this->GenerateDefaultMaterial(); + } + // process all meshes std::vector avOutMeshes; avOutMeshes.reserve(this->mParser->m_vMeshes.size()*2); @@ -171,6 +178,21 @@ void ASEImporter::InternReadFile( return; } // ------------------------------------------------------------------------------------------------ +void ASEImporter::GenerateDefaultMaterial() +{ + ai_assert(NULL != this->mParser); + + // add a simple material without sub materials to the parser's list + this->mParser->m_vMaterials.push_back ( ASE::Material() ); + ASE::Material& mat = this->mParser->m_vMaterials.back(); + + mat.mDiffuse = aiColor3D(0.5f,0.5f,0.5f); + mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f); + mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f); + mat.mShading = Dot3DSFile::Gouraud; + mat.mName = "$$$ASE_DEFAULT"; +} +// ------------------------------------------------------------------------------------------------ void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent, const char* szName) { @@ -953,6 +975,7 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene) // allocate the output material array pcScene->mNumMaterials = iNum; pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials]; + Dot3DS::Material** pcIntMaterials = new Dot3DS::Material*[pcScene->mNumMaterials]; iNum = 0; for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat) @@ -962,6 +985,9 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene) ai_assert(NULL != this->mParser->m_vMaterials[iMat].pcInstance); pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].pcInstance; + // store the internal material, too + pcIntMaterials[iNum] = &this->mParser->m_vMaterials[iMat]; + // 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) @@ -983,6 +1009,9 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene) pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat]. avSubMaterials[iSubMat].pcInstance; + // store the internal material, too + pcIntMaterials[iNum] = &this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat]; + // 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) @@ -998,6 +1027,29 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene) } } } + // prepare for the next step + for (unsigned int hans = 0; hans < pcScene->mNumMaterials;++hans) + { + TextureTransform::ApplyScaleNOffset(this->mParser->m_vMaterials[hans]); + } + + // now we need to iterate through all meshes, + // generating correct texture coordinates and material uv indices + for (unsigned int curie = 0; curie < pcScene->mNumMeshes;++curie) + { + aiMesh* pcMesh = pcScene->mMeshes[curie]; + + // apply texture coordinate transformations + TextureTransform::BakeScaleNOffset(pcMesh,pcIntMaterials[pcMesh->mMaterialIndex]); + } + for (unsigned int hans = 0; hans < pcScene->mNumMaterials;++hans) + { + // setup the correct UV indices for each material + TextureTransform::SetupMatUVSrc(pcScene->mMaterials[hans], + pcIntMaterials[hans]); + } + delete[] pcIntMaterials; + // finished! return; } diff --git a/code/ASELoader.h b/code/ASELoader.h index 0e0a2e483..7c5bbf8d0 100644 --- a/code/ASELoader.h +++ b/code/ASELoader.h @@ -149,6 +149,13 @@ protected: void AddNodes(aiScene* pcScene,aiNode* pcParent, const char* szName); + // ------------------------------------------------------------------- + /** Generate a default material and add it to the parser's list + * Called if no material has been found in the file (rare for ASE, + * but not impossible) + */ + void GenerateDefaultMaterial(); + protected: /** Parser instance */ diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp index bc2e07872..cfcf85029 100644 --- a/code/ASEParser.cpp +++ b/code/ASEParser.cpp @@ -1544,20 +1544,30 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) } // ------------------------------------------------------------------------------------------------ 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]") + { + this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]"); + this->SkipToNextToken(); + return; + } // 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]") + if(!SkipSpaces(this->m_szFile,&this->m_szFile)) + { + // FIX: there are some ASE files which haven't got : here .... + this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]"); + this->SkipToNextToken(); + return; + } + // FIX: there are some ASE files which haven't got : here .... + if(':' == *this->m_szFile)++this->m_szFile; // parse all mesh indices - ++this->m_szFile; for (unsigned int i = 0; i < 3;++i) { unsigned int iIndex = 0; @@ -1565,7 +1575,10 @@ void Parser::ParseLV4MeshFace(ASE::Face& out) { // LOG __EARTHQUAKE_XXL: - BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. A,B or C expected [#3]") + this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " + "A,B or C expected [#3]"); + this->SkipToNextToken(); + return; } switch (*this->m_szFile) { @@ -1586,13 +1599,21 @@ __EARTHQUAKE_XXL: // 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->LogWarning("Unable to parse *MESH_FACE Element: " + "Unexpected EOL. \':\' expected [#2]"); + this->SkipToNextToken(); + return; + } ++this->m_szFile; - if(!SkipSpaces(this->m_szFile,&this->m_szFile)) - BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. Vertex index ecpected [#4]") - + { + this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " + "Vertex index ecpected [#4]"); + this->SkipToNextToken(); + return; + } out.mIndices[iIndex] = strtol10(this->m_szFile,&this->m_szFile); } @@ -1609,11 +1630,17 @@ __EARTHQUAKE_XXL: } // parse the smoothing group of the face - if (0 == strncmp(this->m_szFile,"*MESH_SMOOTHING",15) && IsSpaceOrNewLine(*(this->m_szFile+15))) + 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]") + { + this->LogWarning("Unable to parse *MESH_SMOOTHING Element: " + "Unexpected EOL. Smoothing group(s) expected [#5]"); + this->SkipToNextToken(); + return; + } // parse smoothing groups until we don_t anymore see commas // FIX: There needn't always be a value, sad but true @@ -1649,10 +1676,14 @@ __EARTHQUAKE_XXL: { 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]") + { + this->LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. " + "Material index expected [#6]"); + this->SkipToNextToken(); + return; + } out.iMaterial = strtol10(this->m_szFile,&this->m_szFile); } - //this->SkipToNextToken(); return; } // ------------------------------------------------------------------------------------------------ diff --git a/code/MDLFileData.h b/code/MDLFileData.h index e34da4399..a5927db7b 100644 --- a/code/MDLFileData.h +++ b/code/MDLFileData.h @@ -548,7 +548,7 @@ struct Vertex_MDL4 struct Vertex_MDL7 { float x,y,z; - uint16_t vertindex; + uint16_t vertindex; // = bone index union { uint16_t norm162index; float norm[3]; diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 1103b3208..4e49715ae 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -1282,6 +1282,72 @@ void MDLImporter::ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader) return; } // ------------------------------------------------------------------------------------------------ +void MDLImporter::CalculateAbsBoneAnimMatrices(const MDL::Bone_MDL7* pcBones, + aiBone** apcOutBones) +{ + ai_assert(NULL != pcBones); + ai_assert(NULL != apcOutBones); + + const MDL::Header_MDL7* pcHeader = (const MDL::Header_MDL7*)this->m_pcHeader; + + // first find the bone that has NO parent, calculate the + // animation matrix for it, then go on and search for the next parent + // index (0) and so on until we can't find a new node. + + std::vector abHadMe; + abHadMe.resize(pcHeader->bones_num,false); + + uint16_t iParent = 0xffff; + int32_t iIterations = 0; + while (iIterations++ < pcHeader->bones_num) + { + for (int32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) + { + if (abHadMe[iBone])continue; + const MDL::Bone_MDL7* pcBone = &pcBones[iBone]; + abHadMe[iBone] = true; + + if (iParent == pcBone->parent_index) + { + // yeah, calculate my matrix! I'm happy now + + /************************************************************ + The animation matrix is then calculated the following way: + + vector3 bPos = + matrix44 laM; // local animation matrix + sphrvector key_rotate = + + matrix44 m1,m2; + create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z); + create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z); + + create_rotation_matrix(laM,key_rotate); + + laM = sm1 * laM; + laM = laM * sm2; + *************************************************************/ + aiVector3D vAbsPos; + if (0xffff != iParent) + { + const aiBone* pcParentBone = apcOutBones[iParent]; + vAbsPos.x = pcParentBone->mOffsetMatrix.a3; + vAbsPos.y = pcParentBone->mOffsetMatrix.b3; + vAbsPos.z = pcParentBone->mOffsetMatrix.c3; + } + vAbsPos.x -= pcBone->x; // TODO: + or -? + vAbsPos.y -= pcBone->y; + vAbsPos.z -= pcBone->z; + aiBone* pcOutBone = apcOutBones[iBone]; + pcOutBone->mOffsetMatrix.a3 = vAbsPos.x; + pcOutBone->mOffsetMatrix.b3 = vAbsPos.y; + pcOutBone->mOffsetMatrix.c3 = vAbsPos.z; + } + } + ++iParent; + } +} +// ------------------------------------------------------------------------------------------------ void MDLImporter::InternReadFile_GameStudioA7( ) { ai_assert(NULL != pScene); @@ -1294,8 +1360,30 @@ void MDLImporter::InternReadFile_GameStudioA7( ) // 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; + // load all bones (they are shared by all groups, so + // we'll need to add them to all groups later) + const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)szCurrent; + szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size; + + aiBone** apcBonesOut = NULL; + unsigned int iNumBonesOut = 0; + if (pcHeader->bone_stc_size != sizeof(MDL::Bone_MDL7)) + { + DefaultLogger::get()->warn("[3DGS MDL7] Unknown size of bone data structure. " + "Ignoring bones ..."); + } + else + { + // create an output bone array + iNumBonesOut = pcHeader->bones_num; + apcBonesOut = new aiBone*[iNumBonesOut]; + for (unsigned int crank = 0; crank < iNumBonesOut;++crank) + apcBonesOut[crank] = new aiBone(); + + // and calculate absolute bone animation matrices + // aiBone.mTransformation member + this->CalculateAbsBoneAnimMatrices(pcBones,apcBonesOut); + } // allocate a material list std::vector pcMats; diff --git a/code/MDLLoader.h b/code/MDLLoader.h index c50b682bc..d5c82bfd0 100644 --- a/code/MDLLoader.h +++ b/code/MDLLoader.h @@ -211,6 +211,14 @@ protected: const std::vector& vTextureCoords2); + // ------------------------------------------------------------------- + /** Calculate absolute bone animation matrices for each bone + * \param pcBones Pointer to the bone section in the file + * \param apcOutBones Output bones array + */ + void CalculateAbsBoneAnimMatrices(const MDL::Bone_MDL7* pcBones, + aiBone** apcOutBones); + // ------------------------------------------------------------------- /** Try to load a palette from the current directory (colormap.lmp) * If it is not found the default palette of Quake1 is returned diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 065ef0f0c..6a6362e28 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -369,7 +369,8 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat, aiString* szOut, unsigned int* piUVIndex, float* pfBlendFactor, - aiTextureOp* peTextureOp) + aiTextureOp* peTextureOp, + aiTextureMapMode* peMapMode) { ai_assert(NULL != pcMat); ai_assert(NULL != szOut); @@ -378,55 +379,80 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat, const char* szUVBase; const char* szBlendBase; const char* szOpBase; + const char* aszMapModeBase[3]; switch (iTexType) { case AI_TEXTYPE_DIFFUSE: - szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_; - szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_; + szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_; + szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_; szBlendBase = AI_MATKEY_TEXBLEND_DIFFUSE_; - szOpBase = AI_MATKEY_TEXOP_DIFFUSE_; + szOpBase = AI_MATKEY_TEXOP_DIFFUSE_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_DIFFUSE_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_DIFFUSE_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_DIFFUSE_; break; case AI_TEXTYPE_SPECULAR: - szPathBase = AI_MATKEY_TEXTURE_SPECULAR_; - szUVBase = AI_MATKEY_UVWSRC_SPECULAR_; + szPathBase = AI_MATKEY_TEXTURE_SPECULAR_; + szUVBase = AI_MATKEY_UVWSRC_SPECULAR_; szBlendBase = AI_MATKEY_TEXBLEND_SPECULAR_; - szOpBase = AI_MATKEY_TEXOP_SPECULAR_; + szOpBase = AI_MATKEY_TEXOP_SPECULAR_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_SPECULAR_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_SPECULAR_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_SPECULAR_; break; case AI_TEXTYPE_AMBIENT: - szPathBase = AI_MATKEY_TEXTURE_AMBIENT_; - szUVBase = AI_MATKEY_UVWSRC_AMBIENT_; + szPathBase = AI_MATKEY_TEXTURE_AMBIENT_; + szUVBase = AI_MATKEY_UVWSRC_AMBIENT_; szBlendBase = AI_MATKEY_TEXBLEND_AMBIENT_; - szOpBase = AI_MATKEY_TEXOP_AMBIENT_; + szOpBase = AI_MATKEY_TEXOP_AMBIENT_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_AMBIENT_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_AMBIENT_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_AMBIENT_; break; case AI_TEXTYPE_EMISSIVE: - szPathBase = AI_MATKEY_TEXTURE_EMISSIVE_; - szUVBase = AI_MATKEY_UVWSRC_EMISSIVE_; + szPathBase = AI_MATKEY_TEXTURE_EMISSIVE_; + szUVBase = AI_MATKEY_UVWSRC_EMISSIVE_; szBlendBase = AI_MATKEY_TEXBLEND_EMISSIVE_; - szOpBase = AI_MATKEY_TEXOP_EMISSIVE_; + szOpBase = AI_MATKEY_TEXOP_EMISSIVE_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_EMISSIVE_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_EMISSIVE_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_EMISSIVE_; break; case AI_TEXTYPE_HEIGHT: - szPathBase = AI_MATKEY_TEXTURE_HEIGHT_; - szUVBase = AI_MATKEY_UVWSRC_HEIGHT_; + szPathBase = AI_MATKEY_TEXTURE_HEIGHT_; + szUVBase = AI_MATKEY_UVWSRC_HEIGHT_; szBlendBase = AI_MATKEY_TEXBLEND_HEIGHT_; - szOpBase = AI_MATKEY_TEXOP_HEIGHT_; + szOpBase = AI_MATKEY_TEXOP_HEIGHT_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_HEIGHT_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_HEIGHT_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_HEIGHT_; break; case AI_TEXTYPE_NORMALS: - szPathBase = AI_MATKEY_TEXTURE_NORMALS_; - szUVBase = AI_MATKEY_UVWSRC_NORMALS_; + szPathBase = AI_MATKEY_TEXTURE_NORMALS_; + szUVBase = AI_MATKEY_UVWSRC_NORMALS_; szBlendBase = AI_MATKEY_TEXBLEND_NORMALS_; - szOpBase = AI_MATKEY_TEXOP_NORMALS_; + szOpBase = AI_MATKEY_TEXOP_NORMALS_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_NORMALS_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_NORMALS_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_NORMALS_; break; case AI_TEXTYPE_SHININESS: - szPathBase = AI_MATKEY_TEXTURE_SHININESS_; - szUVBase = AI_MATKEY_UVWSRC_SHININESS_; + szPathBase = AI_MATKEY_TEXTURE_SHININESS_; + szUVBase = AI_MATKEY_UVWSRC_SHININESS_; szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_; - szOpBase = AI_MATKEY_TEXOP_SHININESS_; + szOpBase = AI_MATKEY_TEXOP_SHININESS_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_SHININESS_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_SHININESS_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_SHININESS_; break; case AI_TEXTYPE_OPACITY: - szPathBase = AI_MATKEY_TEXTURE_OPACITY_; - szUVBase = AI_MATKEY_UVWSRC_OPACITY_; + szPathBase = AI_MATKEY_TEXTURE_OPACITY_; + szUVBase = AI_MATKEY_UVWSRC_OPACITY_; szBlendBase = AI_MATKEY_TEXBLEND_OPACITY_; - szOpBase = AI_MATKEY_TEXOP_OPACITY_; + szOpBase = AI_MATKEY_TEXOP_OPACITY_; + aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_OPACITY_; + aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_OPACITY_; + aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_OPACITY_; break; default: return AI_FAILURE; }; @@ -470,6 +496,21 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat, *peTextureOp = op; } + + // get the texture mapping modes for the texture + if (peMapMode) + { + aiTextureMapMode eMode; + for (unsigned int q = 0; q < 3;++q) + { + sprintf(szKey,"%s[%i]",aszMapModeBase[q],iIndex); + if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&eMode)) + { + eMode = aiTextureMapMode_Wrap; + } + peMapMode[q] = eMode; + } + } return AI_SUCCESS; } diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index 8da570c62..c616ac5b2 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -55,28 +55,90 @@ namespace Assimp void TextureTransform::PreProcessUVTransform( Dot3DS::Texture& rcIn) { - if (rcIn.mOffsetU && 0.0f == fmodf(rcIn.mOffsetU, 1.0f )) + std::string s; + std::stringstream ss; + int iField; + + if (rcIn.mOffsetU) { - DefaultLogger::get()->warn("Texture coordinate offset in the x direction " - "is a multiple of 1. This is redundant ..."); - rcIn.mOffsetU = 1.0f; + if (iField = (int)rcIn.mOffsetU) + { + if (aiTextureMapMode_Wrap == rcIn.mMapMode) + { + float fNew = rcIn.mOffsetU-(float)iField; + ss << "[wrap] Found texture coordinate U offset " << rcIn.mOffsetU << ". " + "This can be optimized to " << fNew; + ss >> s; + DefaultLogger::get()->info(s); + rcIn.mOffsetU = fNew; + } + else if (aiTextureMapMode_Mirror == rcIn.mMapMode) + { + if (0 != (iField % 2))iField--; + float fNew = rcIn.mOffsetU-(float)iField; + + ss << "[mirror] Found texture coordinate U offset " << rcIn.mOffsetU << ". " + "This can be optimized to " << fNew; + ss >> s; + DefaultLogger::get()->info(s); + rcIn.mOffsetU = fNew; + } + else if (aiTextureMapMode_Clamp == rcIn.mMapMode) + { + ss << "[clamp] Found texture coordinate U offset " << rcIn.mOffsetU << ". " + "This can be clamped to 1.0f"; + ss >> s; + DefaultLogger::get()->info(s); + rcIn.mOffsetU = 1.0f; + } + } } - if (rcIn.mOffsetV && 0.0f == fmodf(rcIn.mOffsetV, 1.0f )) + if (rcIn.mOffsetV) { - DefaultLogger::get()->warn("Texture coordinate offset in the y direction " - "is a multiple of 1. This is redundant ..."); - rcIn.mOffsetV = 1.0f; + if (iField = (int)rcIn.mOffsetV) + { + if (aiTextureMapMode_Wrap == rcIn.mMapMode) + { + float fNew = rcIn.mOffsetV-(float)iField; + ss << "[wrap] Found texture coordinate V offset " << rcIn.mOffsetV << ". " + "This can be optimized to " << fNew; + ss >> s; + DefaultLogger::get()->info(s); + rcIn.mOffsetV = fNew; + } + else if (aiTextureMapMode_Mirror == rcIn.mMapMode) + { + if (0 != (iField % 2))iField--; + float fNew = rcIn.mOffsetV-(float)iField; + + ss << "[mirror] Found texture coordinate V offset " << rcIn.mOffsetV << ". " + "This can be optimized to " << fNew; + ss >> s; + DefaultLogger::get()->info(s); + rcIn.mOffsetV = fNew; + } + else if (aiTextureMapMode_Clamp == rcIn.mMapMode) + { + ss << "[clamp] Found texture coordinate V offset " << rcIn.mOffsetV << ". " + "This can be clamped to 1.0f"; + ss >> s; + DefaultLogger::get()->info(s); + rcIn.mOffsetV = 1.0f; + } + } } if (rcIn.mRotation) { - const float f = fmodf(rcIn.mRotation,2.0f * 3.141592653f ); - if (f <= 0.05f && f >= -0.05f) + if (iField = (int)(rcIn.mRotation / 3.141592654f)) { - DefaultLogger::get()->warn("Texture coordinate rotation is a multiple " - "of 2 * PI. This is redundant"); - rcIn.mRotation = 0.0f; + float fNew = rcIn.mRotation-(float)iField*3.141592654f; + ss << "[wrap] Found texture coordinate rotation " << rcIn.mRotation << ". " + "This can be optimized to " << fNew; + DefaultLogger::get()->info(s); + rcIn.mRotation = fNew; } } + return; } // ------------------------------------------------------------------------------------------------ void TextureTransform::AddToList(std::vector& rasVec, @@ -94,7 +156,8 @@ void TextureTransform::AddToList(std::vector& rasVec, (*i).fOffsetV == pcTex->mOffsetV && (*i).fScaleU == pcTex->mScaleU && (*i).fScaleV == pcTex->mScaleV && - (*i).fRotation == pcTex->mRotation) + (*i).fRotation == pcTex->mRotation && + (*i).iUVIndex == pcTex->iUVSrc) { (*i).pcTextures.push_back(pcTex); return; @@ -107,8 +170,12 @@ void TextureTransform::AddToList(std::vector& rasVec, sInfo.fOffsetU = pcTex->mOffsetU; sInfo.fOffsetV = pcTex->mOffsetV; sInfo.fRotation = pcTex->mRotation; + sInfo.iUVIndex = pcTex->iUVSrc; + + // add the texture to the list sInfo.pcTextures.push_back(pcTex); + // and add the transformation itself to the second list rasVec.push_back(sInfo); } // ------------------------------------------------------------------------------------------------ @@ -116,6 +183,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material) { unsigned int iCnt = 0; Dot3DS::Texture* pcTexture = NULL; + // diffuse texture if (material.sTexDiffuse.mMapName.length()) { @@ -200,7 +268,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material) // coordinate sets of all meshes referencing *this* material // However, we can't do it now. We need to wait until // everything is sorted by materials. - if (1 == iCnt) + if (1 == iCnt && 0 == pcTexture->iUVSrc) { material.iBakeUVTransform = 1; material.pcSingleTexture = pcTexture; @@ -213,7 +281,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material) } } // ------------------------------------------------------------------------------------------------ -void TextureTransform::ApplyScaleNOffset(std::vector materials) +void TextureTransform::ApplyScaleNOffset(std::vector& materials) { unsigned int iNum = 0; for (std::vector::iterator @@ -234,15 +302,19 @@ void TextureTransform::BakeScaleNOffset( if (!pcMesh->mTextureCoords[0])return; if (1 == pcSrc->iBakeUVTransform) { - std::string s; - std::stringstream ss(s); - ss << "Transforming existing UV channel. Source UV: " << 0 - << " OffsetU: " << pcSrc->pcSingleTexture->mOffsetU - << " OffsetV: " << pcSrc->pcSingleTexture->mOffsetV - << " ScaleU: " << pcSrc->pcSingleTexture->mScaleU - << " ScaleV: " << pcSrc->pcSingleTexture->mScaleV - << " Rotation (rad): " << pcSrc->pcSingleTexture->mRotation; - DefaultLogger::get()->info(s); + char szTemp[512]; + sprintf(szTemp,"Transforming existing UV channel. Source UV: %i" + " OffsetU: %f" + " OffsetV: %f" + " ScaleU: %f" + " ScaleV: %f" + " Rotation (rad): %f",0, + pcSrc->pcSingleTexture->mOffsetU, + pcSrc->pcSingleTexture->mOffsetV, + pcSrc->pcSingleTexture->mScaleU, + pcSrc->pcSingleTexture->mScaleV, + pcSrc->pcSingleTexture->mRotation); + DefaultLogger::get()->info(std::string(szTemp)); if (!pcSrc->pcSingleTexture->mRotation) { @@ -279,6 +351,19 @@ void TextureTransform::BakeScaleNOffset( } else if (2 == pcSrc->iBakeUVTransform) { + // first save all texture coordinate sets + aiVector3D* apvOriginalSets[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) + { + apvOriginalSets[i] = pcMesh->mTextureCoords[i]; + } + unsigned int iNextEmpty = 0; + while (pcMesh->mTextureCoords[++iNextEmpty]); + + aiVector3D* apvOutputSets[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) + apvOutputSets[i] = NULL; + // now we need to find all textures in the material // which require scaling/offset operations std::vector sOps; @@ -290,108 +375,148 @@ void TextureTransform::BakeScaleNOffset( AddToList(sOps,&pcSrc->sTexShininess); AddToList(sOps,&pcSrc->sTexAmbient); - const aiVector3D* _pvBase; - if (0.0f == sOps[0].fOffsetU && 0.0f == sOps[0].fOffsetV && - 1.0f == sOps[0].fScaleU && 1.0f == sOps[0].fScaleV && - 0.0f == sOps[0].fRotation) + // check the list and find out how many we won't be able + // to generate. + std::vector sFilteredOps; + unsigned int iNumUntransformed = 0; + sFilteredOps.reserve(sOps.size()); { - // we'll have an unmodified set, so we can use *this* one - _pvBase = pcMesh->mTextureCoords[0]; - } - else - { - _pvBase = new aiVector3D[pcMesh->mNumVertices]; - memcpy(const_cast(_pvBase),pcMesh->mTextureCoords[0], - pcMesh->mNumVertices * sizeof(aiVector3D)); - } - - unsigned int iCnt = 0; - for (std::vector::iterator - i = sOps.begin(); - i != sOps.end();++i,++iCnt) - { - if (!pcMesh->mTextureCoords[iCnt]) + std::vector sWishList; + sWishList.reserve(sOps.size()); + for (unsigned int iUV = 0; iUV < AI_MAX_NUMBER_OF_TEXTURECOORDS;++iUV) { - pcMesh->mTextureCoords[iCnt] = new aiVector3D[pcMesh->mNumVertices]; - } - - // more than 4 UV texture channels are not available - if (iCnt >= AI_MAX_NUMBER_OF_TEXTURECOORDS) - { - for (std::vector::iterator - a = (*i).pcTextures.begin(); - a != (*i).pcTextures.end();++a) + for (std::vector::iterator + i = sOps.begin(); + i != sOps.end();++i) { - (*a)->iUVSrc = 0; + if (iUV != (*i).iUVIndex)continue; + if ((*i).IsUntransformed()) + { + sFilteredOps.push_back(&(*i)); + } + else sWishList.push_back(&(*i)); } - DefaultLogger::get()->error("There are too many " - "combinations of different UV scaling/offset/rotation operations " - "to generate an UV channel for each (maximum is 4). Using the " - "first UV channel ..."); - continue; } + // are we able to generate all? + const int iDiff = AI_MAX_NUMBER_OF_TEXTURECOORDS-(int) + (sWishList.size()+sFilteredOps.size()); - std::string s; - std::stringstream ss(s); - ss << "Generating additional UV channel. Source UV: " << 0 - << " OffsetU: " << (*i).fOffsetU - << " OffsetV: " << (*i).fOffsetV - << " ScaleU: " << (*i).fScaleU - << " ScaleV: " << (*i).fScaleV - << " Rotation (rad): " << (*i).fRotation; - DefaultLogger::get()->info(s); - - const aiVector3D* pvBase = _pvBase; - - if (0.0f == (*i).fRotation) + iNumUntransformed = (unsigned int)sFilteredOps.size(); + if (0 >= iDiff) { - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) + DefaultLogger::get()->warn("There are too many combinations of different " + "UV transformation operations to generate an own UV channel for each " + "(maximum is AI_MAX_NUMBER_OF_TEXTURECOORDS = 4 or 6). " + "An untransformed UV channel will be used for all remaining transformations"); + + std::vector::const_iterator nash = sWishList.begin(); + for (;nash != sWishList.end()-iDiff;++nash) { - // scaling - pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU; - pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV; - - // offset - pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU; - pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV; - - pvBase++; + sFilteredOps.push_back(*nash); } } else { - const float fSin = sinf((*i).fRotation); - const float fCos = cosf((*i).fRotation); - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) - { - // scaling - pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU; - pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV; - - // rotation - pcMesh->mTextureCoords[iCnt][n].x *= fCos; - pcMesh->mTextureCoords[iCnt][n].y *= fSin; - - // offset - pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU; - pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV; - - pvBase++; - } - } - // setup the UV source index for each texture - for (std::vector::iterator - a = (*i).pcTextures.begin(); - a != (*i).pcTextures.end();++a) - { - (*a)->iUVSrc = iCnt; + for (std::vector::const_iterator + nash = sWishList.begin(); + nash != sWishList.end();++nash)sFilteredOps.push_back(*nash); } } - // release temporary storage - if (_pvBase != pcMesh->mTextureCoords[0]) - delete[] _pvBase; + // now fill in all output IV indices + unsigned int iNum = 0; + for (std::vector::iterator + bogart = sFilteredOps.begin(); + bogart != sFilteredOps.end();++bogart,++iNum) + { + (**bogart).iUVIndex = iNum; + } + + iNum = 0; + for (; iNum < iNumUntransformed; ++iNum) + pcMesh->mTextureCoords[iNum] = apvOriginalSets[iNum]; + + // now generate the texture coordinate sets + for (std::vector::iterator + i = sFilteredOps.begin()+iNumUntransformed; + i != sFilteredOps.end();++i,++iNum) + { + const aiVector3D* _pvBase = apvOriginalSets[(**i).iUVIndex]; + aiVector3D* _pvOut = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mTextureCoords[iNum] = _pvOut; + + char szTemp[512]; + sprintf(szTemp,"Generating additional UV channel. Source UV: %i" + " OffsetU: %f" + " OffsetV: %f" + " ScaleU: %f" + " ScaleV: %f" + " Rotation (rad): %f",0, + (**i).fOffsetU, + (**i).fOffsetV, + (**i).fScaleU, + (**i).fScaleV, + (**i).fRotation); + DefaultLogger::get()->info(std::string(szTemp)); + + const aiVector3D* pvBase = _pvBase; + aiVector3D* pvOut = _pvOut; + if (0.0f == (**i).fRotation) + { + for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) + { + // scaling + pvOut->x = pvBase->x * (**i).fScaleU; + pvOut->y = pvBase->y * (**i).fScaleV; + + // offset + pvOut->x += (**i).fOffsetU; + pvOut->y += (**i).fOffsetV; + + pvBase++; + pvOut++; + } + } + else + { + const float fSin = sinf((**i).fRotation); + const float fCos = cosf((**i).fRotation); + for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) + { + // scaling + pvOut->x = pvBase->x * (**i).fScaleU; + pvOut->y = pvBase->y * (**i).fScaleV; + + // rotation + pvOut->x *= fCos; + pvOut->y *= fSin; + + // offset + pvOut->x += (**i).fOffsetU; + pvOut->y += (**i).fOffsetV; + + pvBase++; + pvOut++; + } + } + } + + // now check which source texture coordinate sets + // can be deleted because they're not anymore required + for (iNum = 0; iNum < AI_MAX_NUMBER_OF_TEXTURECOORDS;++iNum) + { + for (unsigned int z = 0; z < iNumUntransformed;++z) + { + if (apvOriginalSets[iNum] == pcMesh->mTextureCoords[z]) + { + apvOriginalSets[iNum] = NULL; + break; + } + } + if (apvOriginalSets[iNum])delete[] apvOriginalSets[iNum]; + } } + return; } // ------------------------------------------------------------------------------------------------ void TextureTransform::SetupMatUVSrc (aiMaterial* pcMat, const Dot3DS::Material* pcMatIn) diff --git a/code/TextureTransform.h b/code/TextureTransform.h index d5b9c63b4..fd6e17a81 100644 --- a/code/TextureTransform.h +++ b/code/TextureTransform.h @@ -61,6 +61,15 @@ using namespace Assimp::Dot3DS; */ struct STransformVecInfo { + //! Construction. The resulting matrix is the identity + STransformVecInfo () + : + fScaleU(1.0f),fScaleV(1.0f), + fOffsetU(0.0f),fOffsetV(0.0f), + fRotation(0.0f), + iUVIndex(0) + {} + //! Texture coordinate scaling in the x-direction float fScaleU; //! Texture coordinate scaling in the y-direction @@ -72,11 +81,24 @@ struct STransformVecInfo //! Texture coordinate rotation, clockwise, in radians float fRotation; + //! Source texture coordinate index + unsigned int iUVIndex; + + //! List of all textures that use this texture //! coordinate transformations std::vector pcTextures; + // ------------------------------------------------------------------- + /** Returns whether this is an untransformed texture coordinate set + */ + inline bool IsUntransformed() const + { + return 1.0f == fScaleU && 1.0f == fScaleV && + !fOffsetU && !fOffsetV && !fRotation; + } + // ------------------------------------------------------------------- /** Build a 3x3 matrix from the transformations */ @@ -153,7 +175,7 @@ public: * for a material * \param materials List of materials to be processed */ - static void ApplyScaleNOffset(std::vector materials); + static void ApplyScaleNOffset(std::vector& materials); // ------------------------------------------------------------------- /** Get a full list of all texture coordinate offsets required diff --git a/include/aiMaterial.h b/include/aiMaterial.h index 09aacb994..f1aff07ed 100644 --- a/include/aiMaterial.h +++ b/include/aiMaterial.h @@ -59,21 +59,21 @@ extern "C" { // --------------------------------------------------------------------------- enum aiPropertyTypeInfo { - /** Array of single-precision floats - */ - aiPTI_Float = 0x1, + /** Array of single-precision floats + */ + aiPTI_Float = 0x1, - /** aiString data structure - */ - aiPTI_String = 0x3, + /** aiString data structure + */ + aiPTI_String = 0x3, - /** Array of Integers - */ - aiPTI_Integer = 0x4, + /** Array of Integers + */ + aiPTI_Integer = 0x4, - /** Simple binary buffer - */ - aiPTI_Buffer = 0x5, + /** Simple binary buffer + */ + aiPTI_Buffer = 0x5, }; // --------------------------------------------------------------------------- @@ -83,29 +83,51 @@ enum aiPropertyTypeInfo // --------------------------------------------------------------------------- enum aiTextureOp { - /** T = T1 * T2 - */ - aiTextureOp_Multiply = 0x0, + /** T = T1 * T2 + */ + aiTextureOp_Multiply = 0x0, - /** T = T1 + T2 - */ - aiTextureOp_Add = 0x1, + /** T = T1 + T2 + */ + aiTextureOp_Add = 0x1, - /** T = T1 - T2 - */ - aiTextureOp_Subtract = 0x2, + /** T = T1 - T2 + */ + aiTextureOp_Subtract = 0x2, - /** T = T1 / T2 - */ - aiTextureOp_Divide = 0x3, + /** T = T1 / T2 + */ + aiTextureOp_Divide = 0x3, - /** T = (T1 + T2) - (T1 * T2) - */ - aiTextureOp_SmoothAdd = 0x4, + /** T = (T1 + T2) - (T1 * T2) + */ + aiTextureOp_SmoothAdd = 0x4, - /** T = T1 + (T2-0.5) - */ - aiTextureOp_SignedAdd = 0x5 + /** T = T1 + (T2-0.5) + */ + aiTextureOp_SignedAdd = 0x5 +}; + +// --------------------------------------------------------------------------- +/** Defines texture mapping for use within the material system. +* +*/ +// --------------------------------------------------------------------------- +enum aiTextureMapMode +{ + /** A texture coordinate u|v is translated to u%1|v%1 + */ + aiTextureMapMode_Wrap = 0x0, + + /** Texture coordinates outside the area formed by 1|1 and 0|0 + * are clamped to the nearest valid value on an axis + */ + aiTextureMapMode_Clamp = 0x1, + + /** A texture coordinate u|v becomes u%1|v%1 if (u-(u%1))%2 is zero and + * 1-(u%1)|1-(v%1) otherwise + */ + aiTextureMapMode_Mirror = 0x2 }; // --------------------------------------------------------------------------- @@ -120,59 +142,59 @@ enum aiTextureOp // --------------------------------------------------------------------------- enum aiShadingMode { - /** Flat shading. Shading is done on per-face base, - * diffuse only. - */ - aiShadingMode_Flat = 0x1, + /** Flat shading. Shading is done on per-face base, + * diffuse only. + */ + aiShadingMode_Flat = 0x1, - /** Diffuse gouraud shading. Shading on per-vertex base - */ - aiShadingMode_Gouraud = 0x2, + /** 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 - * slowest algorithm, but generates the best results. - */ - aiShadingMode_Phong = 0x3, + /** Diffuse/Specular Phong-Shading + * + * Shading is applied on per-pixel base. This is the + * slowest algorithm, but generates the best results. + */ + aiShadingMode_Phong = 0x3, - /** Diffuse/Specular Phong-Blinn-Shading - * - * Shading is applied on per-pixel base. This is a little - * bit faster than phong and in some cases even - * more realistic - */ - aiShadingMode_Blinn = 0x4, + /** Diffuse/Specular Phong-Blinn-Shading + * + * Shading is applied on per-pixel base. This is a little + * bit faster than phong and in some cases even + * more realistic + */ + aiShadingMode_Blinn = 0x4, - /** Toon-Shading per pixel - * - * Shading is applied on per-pixel base. The output looks - * like a comic. Often combined with edge detection. - */ - aiShadingMode_Toon = 0x5, + /** Toon-Shading per pixel + * + * Shading is applied on per-pixel base. The output looks + * like a comic. Often combined with edge detection. + */ + aiShadingMode_Toon = 0x5, - /** OrenNayar-Shading per pixel - * - * Extension to standard lambertian shading, taking the - * roughness of the material into account - * - */ - aiShadingMode_OrenNayar = 0x6, + /** OrenNayar-Shading per pixel + * + * Extension to standard lambertian shading, taking the + * roughness of the material into account + * + */ + aiShadingMode_OrenNayar = 0x6, - /** Minnaert-Shading per pixel - * - * Extension to standard lambertian shading, taking the - * "darkness" of the material into account - */ - aiShadingMode_Minnaert = 0x7, + /** Minnaert-Shading per pixel + * + * Extension to standard lambertian shading, taking the + * "darkness" of the material into account + */ + aiShadingMode_Minnaert = 0x7, - /** CookTorrance-Shading per pixel - */ - aiShadingMode_CookTorrance = 0x8, + /** CookTorrance-Shading per pixel + */ + aiShadingMode_CookTorrance = 0x8, - /** No shading at all - */ - aiShadingMode_NoShading = 0x8 + /** No shading at all + */ + aiShadingMode_NoShading = 0x8 }; @@ -184,31 +206,31 @@ enum aiShadingMode // --------------------------------------------------------------------------- struct aiMaterialProperty { - /** Specifies the name of the property (key) - * - * Keys are case insensitive. - */ - C_STRUCT aiString* mKey; + /** Specifies the name of the property (key) + * + * Keys are case insensitive. + */ + C_STRUCT aiString* mKey; - /** Size of the buffer mData is pointing to, in bytes - */ - unsigned int mDataLength; + /** Size of the buffer mData is pointing to, in bytes + */ + unsigned int mDataLength; - /** Type information for the property. - * - * Defines the data layout inside the - * data buffer. This is used by the library - * internally to perform debug checks. - */ - aiPropertyTypeInfo mType; + /** Type information for the property. + * + * Defines the data layout inside the + * data buffer. This is used by the library + * internally to perform debug checks. + */ + aiPropertyTypeInfo mType; - /** Binary buffer to hold the property's value - * - * The buffer has no terminal character. However, - * if a string is stored inside it may use 0 as terminal, - * but it would be contained in mDataLength. - */ - char* mData; + /** Binary buffer to hold the property's value + * + * The buffer has no terminal character. However, + * if a string is stored inside it may use 0 as terminal, + * but it would be contained in mDataLength. + */ + char* mData; }; @@ -225,157 +247,261 @@ struct aiMaterial { #ifdef __cplusplus protected: - aiMaterial() {} + aiMaterial() {} public: #endif // __cplusplus - /** List of all material properties loaded. - */ - C_STRUCT aiMaterialProperty** mProperties; + /** List of all material properties loaded. + */ + C_STRUCT aiMaterialProperty** mProperties; - /** Number of properties loaded - */ - unsigned int mNumProperties; - unsigned int mNumAllocated; + /** Number of properties loaded + */ + unsigned int mNumProperties; + unsigned int mNumAllocated; }; // --------------------------------------------------------------------------- /** @def AI_MATKEY_NAME -* Defines the name of the material (aiString) + * Defines the name of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_NAME "$mat.name" +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_TWOSIDED + * Indicates that the material must be rendered two-sided + *
+ * Type: int
+ * Default value: 0
+*/ +#define AI_MATKEY_TWOSIDED "$mat.twosided" + /** @def AI_MATKEY_SHADING_MODE -* Defines the shading model to use (aiShadingMode) + * Defines the shading model to use (aiShadingMode) + *
+ * Type: int (aiShadingMode)
+ * Default value: aiShadingMode_Gouraud
*/ #define AI_MATKEY_SHADING_MODEL "$mat.shadingm" /** @def AI_MATKEY_ENABLE_WIREFRAM -* Integer property. 1 to enable wireframe for rendering + * Integer property. 1 to enable wireframe for rendering + *
+ * Type: int
+ * Default value: 0
*/ #define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe" /** @def AI_MATKEY_OPACITY -* Defines the base opacity of the material + * Defines the base opacity of the material + *
+ * Type: float
+ * Default value: 1.0f
*/ #define AI_MATKEY_OPACITY "$mat.opacity" /** @def AI_MATKEY_BUMPSCALING -* Defines the height scaling of a bump map (for stuff like Parallax -* Occlusion Mapping) + * Defines the height scaling of a bump map (for stuff like Parallax + * Occlusion Mapping) + *
+ * Type: float
+ * Default value: 1.0f
*/ #define AI_MATKEY_BUMPSCALING "$mat.bumpscaling" /** @def AI_MATKEY_SHININESS -* Defines the base shininess of the material -* This is the exponent of the phong shading equation. + * Defines the base shininess of the material + * This is the exponent of the phong shading equation. + *
+ * Type: float
+ * Default value: 0.0f
*/ #define AI_MATKEY_SHININESS "$mat.shininess" /** @def AI_MATKEY_SHININESS_STRENGTH -* Defines the strength of the specular highlight. + * Defines the strength of the specular highlight. + * This is simply a multiplier to the specular color of a material + *
+ * Type: float
+ * Default value: 1.0f
*/ #define AI_MATKEY_SHININESS_STRENGTH "$mat.shinpercent" +// --------------------------------------------------------------------------- /** @def AI_MATKEY_COLOR_DIFFUSE -* Defines the diffuse base color of the material + * Defines the diffuse base color of the material + *
+ * Type: color (aiColor4D or aiColor3D)
+ * Default value: 0.0f|0.0f|0.0f|1.0f
*/ #define AI_MATKEY_COLOR_DIFFUSE "$clr.diffuse" /** @def AI_MATKEY_COLOR_AMBIENT -* Defines the ambient base color of the material + * Defines the ambient base color of the material + *
+ * Type: color (aiColor4D or aiColor3D)
+ * Default value: 0.0f|0.0f|0.0f|1.0f
*/ #define AI_MATKEY_COLOR_AMBIENT "$clr.ambient" /** @def AI_MATKEY_COLOR_SPECULAR -* Defines the specular base color of the material + * Defines the specular base color of the material + *
+ * Type: color (aiColor4D or aiColor3D)
+ * Default value: 0.0f|0.0f|0.0f|1.0f
*/ #define AI_MATKEY_COLOR_SPECULAR "$clr.specular" /** @def AI_MATKEY_COLOR_EMISSIVE -* Defines the emissive base color of the material + * Defines the emissive base color of the material + *
+ * Type: color (aiColor4D or aiColor3D)
+ * Default value: 0.0f|0.0f|0.0f|1.0f
*/ #define AI_MATKEY_COLOR_EMISSIVE "$clr.emissive" +// --------------------------------------------------------------------------- /** @def AI_MATKEY_TEXTURE_DIFFUSE * Defines a specified diffuse texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_DIFFUSE(N) "$tex.file.diffuse["#N"]" #define AI_MATKEY_TEXTURE_DIFFUSE_ "$tex.file.diffuse" /** @def AI_MATKEY_TEXTURE_AMBIENT -* Defines a specified ambient texture channel of the material + * Defines a specified ambient texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_AMBIENT(N) "$tex.file.ambient["#N"]" #define AI_MATKEY_TEXTURE_AMBIENT_ "$tex.file.ambient" /** @def AI_MATKEY_TEXTURE_SPECULAR -* Defines a specified specular texture channel of the material + * Defines a specified specular texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_SPECULAR(N) "$tex.file.specular["#N"]" #define AI_MATKEY_TEXTURE_SPECULAR_ "$tex.file.specular" /** @def AI_MATKEY_TEXTURE_EMISSIVE -* Defines a specified emissive texture channel of the material + * Defines a specified emissive texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_EMISSIVE(N) "$tex.file.emissive["#N"]" #define AI_MATKEY_TEXTURE_EMISSIVE_ "$tex.file.emissive" /** @def AI_MATKEY_TEXTURE_NORMALS -* Defines a specified normal texture channel of the material + * Defines a specified normal texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_NORMALS(N) "$tex.file.normals["#N"]" #define AI_MATKEY_TEXTURE_NORMALS_ "$tex.file.normals" /** @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 from -* a heightmap to a normal map. + * 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 from + * a heightmap to a normal map. + *
+ * Type: string (aiString)
+ * Default value: none
*/ #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 + * Defines a specified shininess texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_SHININESS(N) "$tex.file.shininess["#N"]" #define AI_MATKEY_TEXTURE_SHININESS_ "$tex.file.shininess" /** @def AI_MATKEY_TEXTURE_OPACITY -* Defines a specified opacity texture channel of the material + * Defines a specified opacity texture channel of the material + *
+ * Type: string (aiString)
+ * Default value: none
*/ #define AI_MATKEY_TEXTURE_OPACITY(N) "$tex.file.opacity["#N"]" #define AI_MATKEY_TEXTURE_OPACITY_ "$tex.file.opacity" +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_TEXOP_DIFFUSE + * Specifies the blend operation too be used to combine the Nth + * diffuse texture with the (N-1)th diffuse texture (or the diffuse + * base color for the first diffuse texture) + *
+ * Type: int (aiTextureOp)
+ * Default value: 0
+ * Requires: AI_MATKEY_TEXTURE_DIFFUSE(0)
+ * @note Never use an non-numeric index (like a variable) for this. + * Remember, the key string is built by the preprocessor + */ +#define AI_MATKEY_TEXOP_DIFFUSE(N) "$tex.op.diffuse["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_AMBIENT(N) "$tex.op.ambient["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_SPECULAR(N) "$tex.op.specular["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_EMISSIVE(N) "$tex.op.emissive["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_NORMALS(N) "$tex.op.normals["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_HEIGHT(N) "$tex.op.height["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_SHININESS(N)"$tex.op.shininess["#N"]" +/** @see AI_MATKEY_TEXOP_DIFFUSE */ +#define AI_MATKEY_TEXOP_OPACITY(N) "$tex.op.opacity["#N"]" -#define AI_MATKEY_TEXOP_DIFFUSE(N) "$tex.op.diffuse["#N"]" -#define AI_MATKEY_TEXOP_AMBIENT(N) "$tex.op.ambient["#N"]" -#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_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_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.height" +#define AI_MATKEY_TEXOP_SHININESS_ "$tex.op.shininess" +#define AI_MATKEY_TEXOP_OPACITY_ "$tex.op.opacity" +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_UVWSRC_DIFFUSE + * Specifies the UV channel to be used for the Nth diffuse texture + *
+ * Type: int
+ * Default value: 0
+ * Requires: AI_MATKEY_TEXTURE_DIFFUSE(0)
+ * @note Never use an non-numeric index (like a variable) for this. + * Remember, the key string is built by the preprocessor + */ #define AI_MATKEY_UVWSRC_DIFFUSE(N) "$tex.uvw.diffuse["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ #define AI_MATKEY_UVWSRC_AMBIENT(N) "$tex.uvw.ambient["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ #define AI_MATKEY_UVWSRC_SPECULAR(N) "$tex.uvw.specular["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ #define AI_MATKEY_UVWSRC_EMISSIVE(N) "$tex.uvw.emissive["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ #define AI_MATKEY_UVWSRC_NORMALS(N) "$tex.uvw.normals["#N"]" -#define AI_MATKEY_UVWSRC_HEIGHT(N) "$tex.uvw.bump["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ +#define AI_MATKEY_UVWSRC_HEIGHT(N) "$tex.uvw.height["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ #define AI_MATKEY_UVWSRC_SHININESS(N) "$tex.uvw.shininess["#N"]" +/** @see AI_MATKEY_UVWSRC_DIFFUSE */ #define AI_MATKEY_UVWSRC_OPACITY(N) "$tex.uvw.opacity["#N"]" #define AI_MATKEY_UVWSRC_DIFFUSE_ "$tex.uvw.diffuse" @@ -383,17 +509,34 @@ public: #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_HEIGHT_ "$tex.uvw.height" #define AI_MATKEY_UVWSRC_SHININESS_ "$tex.uvw.shininess" #define AI_MATKEY_UVWSRC_OPACITY_ "$tex.uvw.opacity" +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_TEXBLEND_DIFFUSE + * Specifies the blend factor to be used for the Nth diffuse texture. + *
+ * Type: float
+ * Default value: 1.0f
+ * Requires: AI_MATKEY_TEXTURE_DIFFUSE(0)
+ * @note Never use an non-numeric index (like a variable) for this. + * Remember, the key string is built by the preprocessor + */ #define AI_MATKEY_TEXBLEND_DIFFUSE(N) "$tex.blend.diffuse["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ #define AI_MATKEY_TEXBLEND_AMBIENT(N) "$tex.blend.ambient["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ #define AI_MATKEY_TEXBLEND_SPECULAR(N) "$tex.blend.specular["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ #define AI_MATKEY_TEXBLEND_EMISSIVE(N) "$tex.blend.emissive["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ #define AI_MATKEY_TEXBLEND_NORMALS(N) "$tex.blend.normals["#N"]" -#define AI_MATKEY_TEXBLEND_HEIGHT(N) "$tex.blend.bump["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ +#define AI_MATKEY_TEXBLEND_HEIGHT(N) "$tex.blend.height["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ #define AI_MATKEY_TEXBLEND_SHININESS(N) "$tex.blend.shininess["#N"]" +/** @see AI_MATKEY_TEXBLEND_DIFFUSE */ #define AI_MATKEY_TEXBLEND_OPACITY(N) "$tex.blend.opacity["#N"]" #define AI_MATKEY_TEXBLEND_DIFFUSE_ "$tex.blend.diffuse" @@ -401,17 +544,123 @@ public: #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_HEIGHT_ "$tex.blend.height" #define AI_MATKEY_TEXBLEND_SHININESS_ "$tex.blend.shininess" #define AI_MATKEY_TEXBLEND_OPACITY_ "$tex.blend.opacity" +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_MAPPINGMODE_U_DIFFUSE + * Specifies the texture mapping mode for the Nth diffuse texture in + * the u (x) direction + *
+ * Type: int (aiTextureMapMode)
+ * Default value: aiTextureMapMode_Wrap
+ * Requires: AI_MATKEY_TEXTURE_DIFFUSE(0)
+ * @note Never use an non-numeric index (like a variable) for this. + * Remember, the key string is built by the preprocessor + */ +#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N) "$tex.mapmodeu.diffuse["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_AMBIENT(N) "$tex.mapmodeu.ambient["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_SPECULAR(N) "$tex.mapmodeu.specular["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE(N) "$tex.mapmodeu.emissive["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_NORMALS(N) "$tex.mapmodeu.normals["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_HEIGHT(N) "$tex.mapmodeu.height["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_SHININESS(N)"$tex.mapmodeu.shininess["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_U_OPACITY(N) "$tex.mapmodeu.opacity["#N"]" + +#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE_ "$tex.mapmodeu.diffuse" +#define AI_MATKEY_MAPPINGMODE_U_AMBIENT_ "$tex.mapmodeu.ambient" +#define AI_MATKEY_MAPPINGMODE_U_SPECULAR_ "$tex.mapmodeu.specular" +#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE_ "$tex.mapmodeu.emissive" +#define AI_MATKEY_MAPPINGMODE_U_NORMALS_ "$tex.mapmodeu.normals" +#define AI_MATKEY_MAPPINGMODE_U_HEIGHT_ "$tex.mapmodeu.height" +#define AI_MATKEY_MAPPINGMODE_U_SHININESS_ "$tex.mapmodeu.shininess" +#define AI_MATKEY_MAPPINGMODE_U_OPACITY_ "$tex.mapmodeu.opacity" + +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_MAPPINGMODE_V_DIFFUSE + * Specifies the texture mapping mode for the Nth diffuse texture in + * the v (y) direction + *
+ * Type: int (aiTextureMapMode)
+ * Default value: aiTextureMapMode_Wrap
+ * Requires: AI_MATKEY_TEXTURE_DIFFUSE(0)
+ * @note Never use an non-numeric index (like a variable) for this. + * Remember, the key string is built by the preprocessor + */ +#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N) "$tex.mapmodev.diffuse["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_AMBIENT(N) "$tex.mapmodev.ambient["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_SPECULAR(N) "$tex.mapmodev.specular["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE(N) "$tex.mapmodev.emissive["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_NORMALS(N) "$tex.mapmodev.normals["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_HEIGHT(N) "$tex.mapmodev.height["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_SHININESS(N)"$tex.mapmodev.shininess["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_V_OPACITY(N) "$tex.mapmodev.opacity["#N"]" + +#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE_ "$tex.mapmodev.diffuse" +#define AI_MATKEY_MAPPINGMODE_V_AMBIENT_ "$tex.mapmodev.ambient" +#define AI_MATKEY_MAPPINGMODE_V_SPECULAR_ "$tex.mapmodev.specular" +#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE_ "$tex.mapmodev.emissive" +#define AI_MATKEY_MAPPINGMODE_V_NORMALS_ "$tex.mapmodev.normals" +#define AI_MATKEY_MAPPINGMODE_V_HEIGHT_ "$tex.mapmodev.height" +#define AI_MATKEY_MAPPINGMODE_V_SHININESS_ "$tex.mapmodev.shininess" +#define AI_MATKEY_MAPPINGMODE_V_OPACITY_ "$tex.mapmodev.opacity" + +// --------------------------------------------------------------------------- +/** @def AI_MATKEY_MAPPINGMODE_W_DIFFUSE + * Specifies the texture mapping mode for the Nth diffuse texture in + * the w (z) direction + *
+ * Type: int (aiTextureMapMode)
+ * Default value: aiTextureMapMode_Wrap
+ * Requires: AI_MATKEY_TEXTURE_DIFFUSE(0)
+ * @note Never use an non-numeric index (like a variable) for this. + * Remember, the key string is built by the preprocessor + */ +#define AI_MATKEY_MAPPINGMODE_W_DIFFUSE(N) "$tex.mapmodew.diffuse["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_AMBIENT(N) "$tex.mapmodew.ambient["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_SPECULAR(N) "$tex.mapmodew.specular["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_EMISSIVE(N) "$tex.mapmodew.emissive["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_NORMALS(N) "$tex.mapmodew.normals["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_HEIGHT(N) "$tex.mapmodew.bump["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_SHININESS(N)"$tex.mapmodew.shininess["#N"]" +/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */ +#define AI_MATKEY_MAPPINGMODE_W_OPACITY(N) "$tex.mapmodew.opacity["#N"]" + +#define AI_MATKEY_MAPPINGMODE_W_DIFFUSE_ "$tex.mapmodew.diffuse" +#define AI_MATKEY_MAPPINGMODE_W_AMBIENT_ "$tex.mapmodew.ambient" +#define AI_MATKEY_MAPPINGMODE_W_SPECULAR_ "$tex.mapmodew.specular" +#define AI_MATKEY_MAPPINGMODE_W_EMISSIVE_ "$tex.mapmodew.emissive" +#define AI_MATKEY_MAPPINGMODE_W_NORMALS_ "$tex.mapmodew.normals" +#define AI_MATKEY_MAPPINGMODE_W_HEIGHT_ "$tex.mapmodew.height" +#define AI_MATKEY_MAPPINGMODE_W_SHININESS_ "$tex.mapmodew.shininess" +#define AI_MATKEY_MAPPINGMODE_W_OPACITY_ "$tex.mapmodew.opacity" #define AI_MATKEY_ORENNAYAR_ROUGHNESS "$shading.orennayar.roughness" #define AI_MATKEY_MINNAERT_DARKNESS "$shading.minnaert.darkness" #define AI_MATKEY_COOK_TORRANCE_REFRACTI "$shading.cookt.refracti" #define AI_MATKEY_COOK_TORRANCE_PARAM "$shading.cookt.param" - /** @def AI_MATKEY_GLOBAL_BACKGROUND_IMAGE * Global property defined by some loaders. Contains the path to * the image file to be used as background image. @@ -429,8 +678,8 @@ public: */ // --------------------------------------------------------------------------- aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, - const char* pKey, - const C_STRUCT aiMaterialProperty** pPropOut); + const char* pKey, + const C_STRUCT aiMaterialProperty** pPropOut); // --------------------------------------------------------------------------- @@ -445,20 +694,20 @@ aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, */ // --------------------------------------------------------------------------- aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat, - const char* pKey, - float* pOut, - unsigned int* pMax); + const char* pKey, + float* pOut, + unsigned int* pMax); #ifdef __cplusplus // inline it inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat, - const char* pKey, - float* pOut) - {return aiGetMaterialFloatArray(pMat,pKey,pOut,(unsigned int*)0x0);} + const char* pKey, + float* pOut) + {return aiGetMaterialFloatArray(pMat,pKey,pOut,(unsigned int*)0x0);} #else // use our friend, the C preprocessor #define aiGetMaterialFloat (pMat, pKey, pOut) \ - aiGetMaterialFloatArray(pMat, pKey, pOut, NULL) + aiGetMaterialFloatArray(pMat, pKey, pOut, NULL) #endif //!__cplusplus @@ -474,20 +723,20 @@ inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat, */ // --------------------------------------------------------------------------- aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, - const char* pKey, - int* pOut, - unsigned int* pMax); + const char* pKey, + int* pOut, + unsigned int* pMax); #ifdef __cplusplus // inline it inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, - const char* pKey, - int* pOut) - {return aiGetMaterialIntegerArray(pMat,pKey,pOut,(unsigned int*)0x0);} + const char* pKey, + int* pOut) + {return aiGetMaterialIntegerArray(pMat,pKey,pOut,(unsigned int*)0x0);} #else // use our friend, the C preprocessor #define aiGetMaterialInteger (pMat, pKey, pOut) \ - aiGetMaterialIntegerArray(pMat, pKey, pOut, NULL) + aiGetMaterialIntegerArray(pMat, pKey, pOut, NULL) #endif //!__cplusplus @@ -501,8 +750,8 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, */ // --------------------------------------------------------------------------- aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, - const char* pKey, - aiColor4D* pOut); + const char* pKey, + aiColor4D* pOut); // --------------------------------------------------------------------------- @@ -514,8 +763,8 @@ aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, */ // --------------------------------------------------------------------------- aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, - const char* pKey, - aiString* pOut); + const char* pKey, + aiString* pOut); #define AI_TEXTYPE_OPACITY 0x0 @@ -533,31 +782,48 @@ aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, * 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. + * 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 ...) + * the texture to retrieve (e.g. diffuse, specular, height map ...) * @param szPath Receives the output path - * NULL is no allowed as value + * NULL is no allowed as value * @param piUVIndex Receives the UV index of the texture. - * NULL is allowed as value. + * NULL is allowed as value. * @param pfBlendFactor Receives the blend factor for the texture - * NULL is allowed as value. + * 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. + * this texture and the previous texture. NULL is allowed as value. + * @param peMapMode Receives the mapping modes to be used for the texture. + * The parameter may be NULL but if it is a valid pointer it MUST + * point to an array of 3 aiTextureMapMode variables (one for each + * axis: UVW order (=XYZ)). */ // --------------------------------------------------------------------------- +#ifdef __cplusplus aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat, - unsigned int iIndex, - unsigned int iTexType, - C_STRUCT aiString* szPath, - unsigned int* piUVIndex, - float* pfBlendFactor, - aiTextureOp* peTextureOp); - + unsigned int iIndex, + unsigned int iTexType, + C_STRUCT aiString* szPath, + unsigned int* piUVIndex = NULL, + float* pfBlendFactor = NULL, + aiTextureOp* peTextureOp = NULL, + aiTextureMapMode* peMapMode = NULL); +#else +aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat, + unsigned int iIndex, + unsigned int iTexType, + C_STRUCT aiString* szPath, + unsigned int* piUVIndex, + float* pfBlendFactor, + aiTextureOp* peTextureOp, + aiTextureMapMode* peMapMode); +#endif // !#ifdef __cplusplus #ifdef __cplusplus } + +#include "aiMaterial.inl" + #endif //!__cplusplus #endif //!!AI_MATERIAL_H_INC diff --git a/include/aiMaterial.inl b/include/aiMaterial.inl new file mode 100644 index 000000000..52145084b --- /dev/null +++ b/include/aiMaterial.inl @@ -0,0 +1,160 @@ +/* +--------------------------------------------------------------------------- +Open 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 + * + */ + +#ifndef AI_MATERIAL_INL_INC +#define AI_MATERIAL_INL_INC + + +// --------------------------------------------------------------------------- +/** @brief A class that provides easy access to the property list of a + * material (aiMaterial) via template methods. You can cast an + * aiMaterial* to aiMaterialCPP* + * @note This extra class is necessary since template methods + * are not allowed within C-linkage blocks (extern "C") + */ +class aiMaterialCPP : public aiMaterial +{ +public: + + // ------------------------------------------------------------------- + /** Retrieve an array of Type values with a specific key + * from the material + * + * @param pKey Key to search for. One of the AI_MATKEY_XXX constants. + * @param pOut Pointer to a buffer to receive the result. + * @param pMax Specifies the size of the given buffer, in Type's. + * Receives the number of values (not bytes!) read. + * NULL is a valid value for this parameter. + */ + template + inline aiReturn Get(const char* pKey,Type* pOut, + unsigned int* pMax); + + // ------------------------------------------------------------------- + /** Retrieve a Type value with a specific key + * from the material + * + * @param pKey Key to search for. One of the AI_MATKEY_XXX constants. + * @param pOut Reference to receive the output value + */ + template + inline aiReturn Get(const char* pKey,Type& pOut); +}; + +// --------------------------------------------------------------------------- +template +inline aiReturn aiMaterialCPP::Get(const char* pKey,Type* pOut, + unsigned int* pMax) +{ + unsigned int iNum = pMax ? *pMax : 1; + + aiMaterialProperty* prop; + aiReturn ret = aiGetMaterialProperty(this,pKey,&prop); + if ( AI_SUCCESS == ret ) + { + if (prop->mDataLength < sizeof(Type)*iNum)return AI_FAILURE; + if (prop->mData != aiPTI_Buffer)return AI_FAILURE; + + iNum = std::min(iNum,prop->mDataLength / sizeof(Type)); + ::memcpy(pOut,prop->mData,iNum * sizeof(Type)); + if (pMax)*pMax = iNum; + } + return ret; +} +// --------------------------------------------------------------------------- +template +inline aiReturn aiMaterialCPP::Get(const char* pKey,Type& pOut) +{ + aiMaterialProperty* prop; + aiReturn ret = aiGetMaterialProperty(this,pKey,&prop); + if ( AI_SUCCESS == ret ) + { + if (prop->mDataLength < sizeof(Type))return AI_FAILURE; + if (prop->mData != aiPTI_Buffer)return AI_FAILURE; + + ::memcpy(&pOut,prop->mData,sizeof(Type)); + } + return ret; +} +// --------------------------------------------------------------------------- +template <> +inline aiReturn aiMaterialCPP::Get(const char* pKey,float* pOut, + unsigned int* pMax) +{ + return aiGetMaterialFloatArray(this,pKey,pOut,pMax); +} +// --------------------------------------------------------------------------- +template <> +inline aiReturn aiMaterialCPP::Get(const char* pKey,int* pOut, + unsigned int* pMax) +{ + return aiGetMaterialIntegerArray(this,pKey,pOut,pMax); +} +// --------------------------------------------------------------------------- +template <> +inline aiReturn aiMaterialCPP::Get(const char* pKey,float& pOut) +{ + return aiGetMaterialFloat(this,pKey,&pOut); +} +// --------------------------------------------------------------------------- +template <> +inline aiReturn aiMaterialCPP::Get(const char* pKey,int& pOut) +{ + return aiGetMaterialInteger(this,pKey,&pOut); +} +// --------------------------------------------------------------------------- +template <> +inline aiReturn aiMaterialCPP::Get(const char* pKey,aiColor4D& pOut) +{ + return aiGetMaterialColor(this,pKey,&pOut); +} +// --------------------------------------------------------------------------- +template <> +inline aiReturn aiMaterialCPP::Get(const char* pKey,aiString& pOut) +{ + return aiGetMaterialString(this,pKey,&pOut); +} + +#endif //! AI_MATERIAL_INL_INC \ No newline at end of file diff --git a/include/aiMesh.h b/include/aiMesh.h index bd1d88aba..1fae980bf 100644 --- a/include/aiMesh.h +++ b/include/aiMesh.h @@ -185,6 +185,20 @@ struct aiBone mNumWeights = 0; mWeights = NULL; } + //! Copy constructor + aiBone(const aiBone& other) + { + mNumWeights = other.mNumWeights; + mOffsetMatrix = other.mOffsetMatrix; + mName = other.mName; + + if (other.mWeights && other.mNumWeights) + { + mWeights = new aiVertexWeight[mNumWeights]; + memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight)); + } + } + //! Destructor to delete the array of vertex weights ~aiBone() { diff --git a/tools/assimp_view/assimp_view.aps b/tools/assimp_view/assimp_view.aps index 23b7098a493c276ff63efde274c13fc3807f354a..5608fcd493019ee364e03e1c0406302d5d1ce470 100644 GIT binary patch delta 2298 zcmZ9MZA?>F7{{M;%f-^x4iG4%ue1f+CejuVSjJ4D6`8zLij(1>fU==7$DD7gpvZJ? z4z=*;jxK@V<`$DJ+e~BR3(lCmn7C}}qT7<8CfkQ)S&WN<(*fPNw-hei=A8dI|MPp! zeeUU#bMZ>@y(`H*WR?0~DEF+bbk%~x zo>vGP0LtAnUQKyj#BS}EYq*yIi*t136?`$r@LZb!im{#=|LQg6wUFy9D9D42qVIQ= zRIiCx`LHQst@KoQMQ9mp#-KclYX|&??e{9)kXy(W{8z4*y#|1OqXw78#U^%$VU?|0 zwhK{(PIw)U*wa(CN?*KET*`wtuq#f-Z3Db(HyXB!L~V6-h0kAF;c?YeRF{cd0qg*D zI1FSb-jB0!y8yc!M($0(Qw}o;V7pI`zxDB8mHi;G%rk6Pd2?c-$qf z(p93n4EBm{)by8$DHRn!H(-a;V%Rr#*y&!^ev$K(Re4rb zlzGbh9@a6e(C&l-7*uMww^{1B$>bn@rA#63;7z5CdlxX6Ya@p+U1cNh;R;oTtd||& zKC^xSi*(rGF!rhRu0Pz-4G|R%K+J|Iz19u0LL)6 zFq1nD*qN{6-Ul4WHxr5%@-5^9YSm`zNg>@*zpvI+TV4v;4)_4T@ACTmRn`8=6{X;S zA$&<~BB!uZZRS1%BsoUzBf#64I`wIQbPyia{~iwgr7qz}H)bc)NU9UhB;-h@{fQ3A z4C@oWkW53)Ma{DKd1af5{V7ffME2p`l+{w>5N^~oOO50BK+`QXF5+NnrNqF^S_K-l zHi<>zv0ZDI7-&dS;E&o2iA568m^LSuMHon1DkYNedfL+x19$5bXxCXJ7D>TQUAENF z;7@Z5+^dhp9DSCQ(PFoLPLMhDv%Z;=B5Sb46p$EP3&CHM`jFLpok(o5A5E4e5(9s* z#A3iAOT3m{lbc2 z-v1}wMi812W zfHqRcX<0(T)5Ek!Tni09e1>3VSl$2Vc_Fgm(Ir9RAKz3)z;!I=21*E7l>8)j9+V)T z*<&57onFEv|0!m8_bh*99$yvZJ0*O@EPs0*?~U@`OL$+DU(69QHy>A&*H6smQ$KC$ z7jsGT_!?-KJ|=9M*pwzYG7h{q3BXo}6F;|qDitRt6nmqGcWf4ABeh76&CrnpW*3R% zi7+M--7&)SNr>n^u6g^g>nZx+fyo5CbUzW#Ogg!6m}R9}$+Th-`x(?45!P(Q7Td zfi}jFM81xF(;Z=+D{JQoeS#<1{9+kEkQS}yO|l6&p-1JUI9C1%0hNLdu4kL((Gj*r z{-C3R9HWzhxT#?SlLxd|kkhn5kiTh{AbE5^kWM-x$k%j~38(6!QybWB`>COoxw~kw hAVajFmCqtxdVtOJy&j$wsDibiSR{5>5EHGI{{c0vx>*1K delta 2309 zcmZveZBSHI7{{M;cQ5P<3-Tf_%Pza@E@~yP3of8Vu)rFOtgO6g__D5wi3yRYm|_A} zA_gH3cAUnk)oJ=r!$h+>`k|C*m|lixst-;d9LwrM(?szhB^B7t*@flGw9MK6eSYWv zJmhkHp&Sc(MnJ z6gtv~+Z6iZy#N(up85*sW@oi$Q(Z+ZhR(F4WM(L^K})cJtFh%U&o9Vh9J#@6G6HFJe# zptg`MJgL@^ZoH`0YEK2z%AL=9s-5miN2!yQE3oFmYplQA<;ky0rd?I_p;zH_{cn zdX5d=X0fr1@>WYdHMNe~ic-k5!36-1!(HRqSmkl8F9jRCy8xV9YT519RMl0NIz9D{ z$~q_5>;>>1;L~{q!N*$4*2xRt65yj1spK+}n0S9|Op!o(a8qox+7e2Al7eV-q-06}7N@At zm$FiV$TFNt$&vv4n|Xe<#Nscp$r4QB@Um9wBk}k^`;^p?fUZ<2z{*q=ewb>Jc+i)s z8q`S%NkW%ywZuY_@v=_ZG%@)9)p-S}r53vl$0R`T5)7zy{u1L4M1sjFEHphmRKMV;G+ZYnQAm%Xk&j(&WpjiF$>S2>#XC zcfJsg1TgA;x6mHIf%^?y{=EMrm*nZaTso&qRnQk%25xghXfR+dK!m$8$JoubP#Sd?-3mLb93$_Q#90(T#5Zq4)*FX)5aKWvxdER$8 zfbK_$;q|BA(XjTXRtivS!1Wq7Lsf%B{yYt%TKcyi%!3^CLd z-l9<2y(MYLJiSXi2J(1m_Kt$@mUtXX>I^c^{L{p%v#|nut$j6H!o@n5991qjKsDbk z1EzV72j)}@mjerz2{IQO8M#fG%kn%EP|4lUj85e*USX9Z?V_|TL_eI8LR zTr}f5<}|T)8Ne9*+9R4tE1hIUa+GRzG8v_rTzaUBi<>qx5q{iE`*(_I#7BoY-A5-v zo=GkPRO96yO0&E{kBf!O)6D7A7240~bvn#xC!Gk=LHZY`3aZ(~sE=kc5q|rJZrsJ_ zHrmW-C+!PO4s&UxWVfiN{c;i~ZejN{!sA@oGa{iyBFPk2$pCiJrrn}J_Kkwjn+j4G zq4(TbI>}{-Y8qLK ww>xN7Bdb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +