diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index ac82e4cee..30a5d5f28 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -280,6 +280,7 @@ SOURCE_GROUP( Obj FILES SOURCE_GROUP( Ogre FILES OgreImporter.h OgreImporter.cpp + OgreImporterMaterial.cpp ) SOURCE_GROUP( Ply FILES @@ -549,6 +550,7 @@ ADD_LIBRARY( assimp SHARED ObjTools.h OgreImporter.h OgreImporter.cpp + OgreImporterMaterial.cpp" OptimizeGraph.cpp OptimizeGraph.h OptimizeMeshes.cpp diff --git a/code/OgreImporter.cpp b/code/OgreImporter.cpp index 47177557b..d7adda67e 100644 --- a/code/OgreImporter.cpp +++ b/code/OgreImporter.cpp @@ -362,8 +362,8 @@ void OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vectormNumWeights=aiWeights[i].size(); NewBone->mWeights=new aiVertexWeight[aiWeights[i].size()]; memcpy(NewBone->mWeights, &(aiWeights[i][0]), sizeof(aiVertexWeight)*aiWeights[i].size()); - NewBone->mName=Bones[i].Name;//The bone list should be sorted after its ids, this was done in LoadSkeleton - NewBone->mOffsetMatrix=aiMatrix4x4();//(Bones[i].WorldToBoneSpace).Inverse();//we suggest, that the mesh space is the world space! + NewBone->mName=Bones[i].Name;//The bone list should be sorted after its id's, this was done in LoadSkeleton + NewBone->mOffsetMatrix=Bones[i].BoneToWorldSpace; aiBones.push_back(NewBone); } @@ -393,170 +393,6 @@ void OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vectormMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh } -aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) -{ - MaterialHelper *NewMaterial=new MaterialHelper(); - - aiString ts(MaterialName.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_NAME); - /*For bettetr understanding of the material parser, here is a material example file: - - material Sarg - { - receive_shadows on - technique - { - pass - { - ambient 0.500000 0.500000 0.500000 1.000000 - diffuse 0.640000 0.640000 0.640000 1.000000 - specular 0.500000 0.500000 0.500000 1.000000 12.500000 - emissive 0.000000 0.000000 0.000000 1.000000 - texture_unit - { - texture SargTextur.tga - tex_address_mode wrap - filtering linear linear none - } - } - } - } - - */ - - - string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material"; - DefaultLogger::get()->info(str(format("Trying to load %1%") % MaterialFileName)); - - //Read the file into memory and put it in a stringstream - stringstream ss; - {// after this block, the temporarly loaded data will be released - IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName); - if(NULL==MatFilePtr) - { - MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename); - if(NULL==MatFilePtr) - { - DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opned, Material will not be loaded!"); - return NewMaterial; - } - } - scoped_ptr MaterialFile(MatFilePtr); - vector FileData(MaterialFile->FileSize()); - MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1); - BaseImporter::ConvertToUTF8(FileData); - - ss << &FileData[0]; - } - - string Line; - ss >> Line; -// unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another - while(!ss.eof()) - { - if(Line=="material") - { - ss >> Line; - if(Line==MaterialName)//Load the next material - { - ss >> Line; - if(Line!="{") - throw DeadlyImportError("empty material!"); - - while(Line!="}")//read until the end of the material - { - //Proceed to the first technique - ss >> Line; - if(Line=="technique") - { - ss >> Line; - if(Line!="{") - throw DeadlyImportError("empty technique!"); - while(Line!="}")//read until the end of the technique - { - ss >> Line; - if(Line=="pass") - { - ss >> Line; - if(Line!="{") - throw DeadlyImportError("empty pass!"); - while(Line!="}")//read until the end of the pass - { - ss >> Line; - if(Line=="ambient") - { - //read the ambient light values: - } - else if(Line=="diffuse") - { - } - else if(Line=="specular") - { - } - else if(Line=="emmisive") - { - } - else if(Line=="texture_unit") - { - ss >> Line; - if(Line!="{") - throw DeadlyImportError("empty texture unit!"); - while(Line!="}")//read until the end of the texture_unit - { - ss >> Line; - if(Line=="texture") - { - ss >> Line; - aiString ts(Line.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); - } - }//end of texture unit - } - } - } - }//end of technique - - - } - - - DefaultLogger::get()->info(Line); - //read informations from a custom material: - if(Line=="set") - { - ss >> Line; - if(Line=="$specular")//todo load this values: - { - } - if(Line=="$diffuse") - { - } - if(Line=="$ambient") - { - } - if(Line=="$colormap") - { - ss >> Line; - aiString ts(Line.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); - } - if(Line=="$normalmap") - { - ss >> Line; - aiString ts(Line.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); - } - } - }//end of material - } - else {} //this is the wrong material, proceed the file until we reach the next material - } - ss >> Line; - } - - return NewMaterial; -} - void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vector &Animations) { @@ -594,7 +430,7 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vecto while(string("bone")==SkeletonFile->getNodeName()) { - //TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appera, so what.... + //TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appear, so what.... //read a new bone: Bone NewBone; @@ -678,7 +514,7 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vecto { if(-1==theBone.ParentId) //the bone is a root bone { - theBone.CalculateWorldToBoneSpaceMatrix(Bones); + theBone.CalculateBoneToWorldSpaceMatrix(Bones); } } //_______________________________________________________________________ @@ -716,13 +552,12 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vecto NewKeyframe.Time=GetAttribute(SkeletonFile, "time"); //Position: - //It seams that we have to flip some axies, i really dont know why XmlRead(SkeletonFile); if(string("translate")!=SkeletonFile->getNodeName()) throw DeadlyImportError("translate node not first in keyframe"); - NewKeyframe.Position.x=GetAttribute(SkeletonFile, "y"); - NewKeyframe.Position.y=-GetAttribute(SkeletonFile, "z"); - NewKeyframe.Position.z=-GetAttribute(SkeletonFile, "x"); + NewKeyframe.Position.x=GetAttribute(SkeletonFile, "x"); + NewKeyframe.Position.y=GetAttribute(SkeletonFile, "y"); + NewKeyframe.Position.z=GetAttribute(SkeletonFile, "z"); //Rotation: XmlRead(SkeletonFile); @@ -765,7 +600,7 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vecto void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const std::vector &Animations) { - //-----------------skeleton is completly loaded, now but it in the assimp scene:------------------------------- + //-----------------skeleton is completly loaded, now put it in the assimp scene:------------------------------- if(!m_CurrentScene->mRootNode) throw DeadlyImportError("No root node exists!!"); @@ -780,7 +615,7 @@ void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const st if(-1==theBone.ParentId) //the bone is a root bone { DefaultLogger::get()->debug(theBone.Name); - RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode)); + RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));//which will recursily add all other nodes } } m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size(); @@ -809,6 +644,9 @@ void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const st aiNodeAnim* NewNodeAnim=new aiNodeAnim(); NewNodeAnim->mNodeName=Animations[i].Tracks[j].BoneName; + //we need this, to acces the bones default pose, which we need to make keys absolute + vector::const_iterator CurBone=find(Bones.begin(), Bones.end(), NewNodeAnim->mNodeName); + //Create the keyframe arrays... unsigned int KeyframeCount=Animations[i].Tracks[j].Keyframes.size(); NewNodeAnim->mNumPositionKeys=KeyframeCount; @@ -821,14 +659,46 @@ void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const st //...and fill them for(unsigned int k=0; kPosition, t2) + * aiMatrix4x4::Rotation(CurBone->RotationAngle, CurBone->RotationAxis, t3); + //The defautl bone pose doesnt have a scaling value + + //calculate the complete transformation from world space to bone space + aiMatrix4x4 CompleteTransform=DefBonePose * PoseToKey; + + aiVector3D Pos; + aiQuaternion Rot; + aiVector3D Scale; + + CompleteTransform.Decompose(Scale, Rot, Pos); + + NewNodeAnim->mPositionKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; - NewNodeAnim->mPositionKeys[k].mValue=Animations[i].Tracks[j].Keyframes[k].Position; + NewNodeAnim->mPositionKeys[k].mValue=Pos; NewNodeAnim->mRotationKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; - NewNodeAnim->mRotationKeys[k].mValue=Animations[i].Tracks[j].Keyframes[k].Rotation; + NewNodeAnim->mRotationKeys[k].mValue=Rot; NewNodeAnim->mScalingKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; - NewNodeAnim->mScalingKeys[k].mValue=Animations[i].Tracks[j].Keyframes[k].Scaling; + NewNodeAnim->mScalingKeys[k].mValue=Scale; + + /*NewNodeAnim->mPositionKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; + NewNodeAnim->mPositionKeys[k].mValue=CurBone->Position + + Animations[i].Tracks[j].Keyframes[k].Position; + + NewNodeAnim->mRotationKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; + NewNodeAnim->mRotationKeys[k].mValue=aiQuaternion(CurBone->RotationAxis, CurBone->RotationAngle) + * Animations[i].Tracks[j].Keyframes[k].Rotation; + + NewNodeAnim->mScalingKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; + NewNodeAnim->mScalingKeys[k].mValue=1.0f //TODO currently bones don't save scaling! we need to change this, if we want to support them! + * Animations[i].Tracks[j].Keyframes[k].Scaling;*/ } NewAnimation->mChannels[j]=NewNodeAnim; @@ -850,9 +720,9 @@ aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector & aiMatrix4x4 t0,t1; //create a matrix from the transformation values of the ogre bone - NewNode->mTransformation=aiMatrix4x4::Translation(Bones[BoneId].Position, t0) - * - aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, t1) + NewNode->mTransformation=aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, t1) + * aiMatrix4x4::Translation(Bones[BoneId].Position, t0) + ; //__________________________________________________________ @@ -871,29 +741,27 @@ aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector & } -void Bone::CalculateWorldToBoneSpaceMatrix(vector &Bones) +void Bone::CalculateBoneToWorldSpaceMatrix(vector &Bones) { //Calculate the matrix for this bone: + aiMatrix4x4 t0,t1; + aiMatrix4x4 Transf=aiMatrix4x4::Translation(-Position, t0) + * aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1) + ; if(-1==ParentId) { - WorldToBoneSpace= aiMatrix4x4::Translation(Position, t0) - * aiMatrix4x4::Rotation(RotationAngle, RotationAxis, t1) - ; + BoneToWorldSpace=Transf; } else { - WorldToBoneSpace= Bones[ParentId].WorldToBoneSpace - * aiMatrix4x4::Rotation(RotationAngle, RotationAxis, t1) - * aiMatrix4x4::Translation(Position, t0) - ; - + BoneToWorldSpace=Bones[ParentId].BoneToWorldSpace * Transf; } //and recursivly for all children: BOOST_FOREACH(int theChildren, Children) { - Bones[theChildren].CalculateWorldToBoneSpaceMatrix(Bones); + Bones[theChildren].CalculateBoneToWorldSpaceMatrix(Bones); } } diff --git a/code/OgreImporter.h b/code/OgreImporter.h index 9390b9be2..624c8fe07 100644 --- a/code/OgreImporter.h +++ b/code/OgreImporter.h @@ -95,7 +95,7 @@ struct Bone float RotationAngle; aiVector3D RotationAxis; std::vector Children; - aiMatrix4x4 WorldToBoneSpace; + aiMatrix4x4 BoneToWorldSpace; ///ctor Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {} @@ -105,8 +105,10 @@ struct Bone ///this operator is needed to find a bone by its name in a vector bool operator==(const std::string& rval) const {return Name==rval; } + bool operator==(const aiString& rval) const + {return Name==std::string(rval.data); } - void CalculateWorldToBoneSpaceMatrix(std::vector& Bones); + void CalculateBoneToWorldSpaceMatrix(std::vector& Bones); }; diff --git a/code/OgreImporterMaterial.cpp b/code/OgreImporterMaterial.cpp new file mode 100644 index 000000000..9ec54a382 --- /dev/null +++ b/code/OgreImporterMaterial.cpp @@ -0,0 +1,198 @@ +/* +This file contains material related code. This is +spilitted up from the main file OgreImporter.cpp +to make it shorter and better amintainable. +*/ +#include "AssimpPCH.h" + +#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER + +#include +#include +using namespace std; + +//#include "boost/format.hpp" +//#include "boost/foreach.hpp" +using namespace boost; + +#include "OgreImporter.h" +#include "irrXMLWrapper.h" + + +namespace Assimp +{ +namespace Ogre +{ + + + +aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) +{ + MaterialHelper *NewMaterial=new MaterialHelper(); + + aiString ts(MaterialName.c_str()); + NewMaterial->AddProperty(&ts, AI_MATKEY_NAME); + /*For bettetr understanding of the material parser, here is a material example file: + + material Sarg + { + receive_shadows on + technique + { + pass + { + ambient 0.500000 0.500000 0.500000 1.000000 + diffuse 0.640000 0.640000 0.640000 1.000000 + specular 0.500000 0.500000 0.500000 1.000000 12.500000 + emissive 0.000000 0.000000 0.000000 1.000000 + texture_unit + { + texture SargTextur.tga + tex_address_mode wrap + filtering linear linear none + } + } + } + } + + */ + + + string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material"; + DefaultLogger::get()->info(str(format("Trying to load %1%") % MaterialFileName)); + + //Read the file into memory and put it in a stringstream + stringstream ss; + {// after this block, the temporarly loaded data will be released + IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName); + if(NULL==MatFilePtr) + { + MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename); + if(NULL==MatFilePtr) + { + DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opned, Material will not be loaded!"); + return NewMaterial; + } + } + scoped_ptr MaterialFile(MatFilePtr); + vector FileData(MaterialFile->FileSize()); + MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1); + BaseImporter::ConvertToUTF8(FileData); + + ss << &FileData[0]; + } + + string Line; + ss >> Line; +// unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another + while(!ss.eof()) + { + if(Line=="material") + { + ss >> Line; + if(Line==MaterialName)//Load the next material + { + ss >> Line; + if(Line!="{") + throw DeadlyImportError("empty material!"); + + while(Line!="}")//read until the end of the material + { + //Proceed to the first technique + ss >> Line; + if(Line=="technique") + { + ss >> Line; + if(Line!="{") + throw DeadlyImportError("empty technique!"); + while(Line!="}")//read until the end of the technique + { + ss >> Line; + if(Line=="pass") + { + ss >> Line; + if(Line!="{") + throw DeadlyImportError("empty pass!"); + while(Line!="}")//read until the end of the pass + { + ss >> Line; + if(Line=="ambient") + { + //read the ambient light values: + } + else if(Line=="diffuse") + { + } + else if(Line=="specular") + { + } + else if(Line=="emmisive") + { + } + else if(Line=="texture_unit") + { + ss >> Line; + if(Line!="{") + throw DeadlyImportError("empty texture unit!"); + while(Line!="}")//read until the end of the texture_unit + { + ss >> Line; + if(Line=="texture") + { + ss >> Line; + aiString ts(Line.c_str()); + NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + } + }//end of texture unit + } + } + } + }//end of technique + + + } + + + DefaultLogger::get()->info(Line); + //read informations from a custom material: + if(Line=="set") + { + ss >> Line; + if(Line=="$specular")//todo load this values: + { + } + if(Line=="$diffuse") + { + } + if(Line=="$ambient") + { + } + if(Line=="$colormap") + { + ss >> Line; + aiString ts(Line.c_str()); + NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + } + if(Line=="$normalmap") + { + ss >> Line; + aiString ts(Line.c_str()); + NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); + } + } + }//end of material + } + else {} //this is the wrong material, proceed the file until we reach the next material + } + ss >> Line; + } + + return NewMaterial; +} + + + +}//namespace Ogre +}//namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index 65d510b17..59d4de112 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -1943,6 +1943,10 @@ RelativePath="..\..\code\OgreImporter.h" > + + diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 96e3d4d9a..6a108fa95 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -1950,6 +1950,10 @@ RelativePath="..\..\code\OgreImporter.h" > + +