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
This commit is contained in:
aramis_acg
2008-06-03 21:50:53 +00:00
parent a3d2ff5f26
commit 8b2ca95419
18 changed files with 1601 additions and 698 deletions

View File

@@ -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<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
// two sided rendering?
if (oldMat.mTwoSided)
{
int i = 0;
mat.AddProperty<int>(&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<float>( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0));
if (aiTextureMapMode_Clamp != oldMat.sTexDiffuse.mMapMode)
{
int i = (int)oldMat.sTexSpecular.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
mat.AddProperty<int>(&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<float>( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0));
if (aiTextureMapMode_Clamp != oldMat.sTexSpecular.mMapMode)
{
int i = (int)oldMat.sTexSpecular.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_SPECULAR(0));
mat.AddProperty<int>(&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<float>( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0));
if (aiTextureMapMode_Clamp != oldMat.sTexOpacity.mMapMode)
{
int i = (int)oldMat.sTexOpacity.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_OPACITY(0));
mat.AddProperty<int>(&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<float>( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0));
if (aiTextureMapMode_Clamp != oldMat.sTexEmissive.mMapMode)
{
int i = (int)oldMat.sTexEmissive.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_EMISSIVE(0));
mat.AddProperty<int>(&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<float>( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_HEIGHT(0));
if (aiTextureMapMode_Clamp != oldMat.sTexBump.mMapMode)
{
int i = (int)oldMat.sTexBump.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_HEIGHT(0));
mat.AddProperty<int>(&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<float>( &oldMat.sTexShininess.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0));
if (aiTextureMapMode_Clamp != oldMat.sTexShininess.mMapMode)
{
int i = (int)oldMat.sTexShininess.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_SHININESS(0));
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_SHININESS(0));
}
}
// store the name of the material itself, too

View File

@@ -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<float>::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;

View File

@@ -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

View File

@@ -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<aiMesh*> 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;
}

View File

@@ -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 */

View File

@@ -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;
}
// ------------------------------------------------------------------------------------------------

View File

@@ -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];

View File

@@ -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<bool> 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 = <absolute bone position>
matrix44 laM; // local animation matrix
sphrvector key_rotate = <bone rotation>
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<MaterialHelper*> pcMats;

View File

@@ -211,6 +211,14 @@ protected:
const std::vector<aiVector3D>& 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

View File

@@ -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;
}

View File

@@ -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<STransformVecInfo>& rasVec,
@@ -94,7 +156,8 @@ void TextureTransform::AddToList(std::vector<STransformVecInfo>& 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<STransformVecInfo>& 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<Dot3DS::Material> materials)
void TextureTransform::ApplyScaleNOffset(std::vector<Dot3DS::Material>& materials)
{
unsigned int iNum = 0;
for (std::vector<Dot3DS::Material>::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<STransformVecInfo> 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<STransformVecInfo*> 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<aiVector3D*>(_pvBase),pcMesh->mTextureCoords[0],
pcMesh->mNumVertices * sizeof(aiVector3D));
}
unsigned int iCnt = 0;
for (std::vector<STransformVecInfo>::iterator
i = sOps.begin();
i != sOps.end();++i,++iCnt)
{
if (!pcMesh->mTextureCoords[iCnt])
std::vector<STransformVecInfo*> 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<Dot3DS::Texture*>::iterator
a = (*i).pcTextures.begin();
a != (*i).pcTextures.end();++a)
for (std::vector<STransformVecInfo>::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<STransformVecInfo*>::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<Dot3DS::Texture*>::iterator
a = (*i).pcTextures.begin();
a != (*i).pcTextures.end();++a)
{
(*a)->iUVSrc = iCnt;
for (std::vector<STransformVecInfo*>::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<STransformVecInfo*>::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<STransformVecInfo*>::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)

View File

@@ -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<Dot3DS::Texture*> 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<Dot3DS::Material> materials);
static void ApplyScaleNOffset(std::vector<Dot3DS::Material>& materials);
// -------------------------------------------------------------------
/** Get a full list of all texture coordinate offsets required