ASE and 3DS cleanup - face ordering improved.

Further work on target camera animation support in both loaders. Some general animation problems in both formats remaining, too. 
Added GenUVCoords and TransformUV-steps (see ML). The latter has been fully implemented, test file are there. GenUVCoords is a dummy for the moment.
Boost workaround for shared_array.
Further work on the documentation.
Updated material system (see ML).
Bug fixing in the AC loader, lights are now supported, too.


git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@243 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-11-16 21:56:45 +00:00
parent 130f0f39f7
commit 32342857d8
57 changed files with 3522 additions and 2475 deletions

View File

@ -46,7 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers // internal headers
#include "3DSLoader.h" #include "3DSLoader.h"
#include "TextureTransform.h"
#include "TargetAnimation.h" #include "TargetAnimation.h"
using namespace Assimp; using namespace Assimp;
@ -159,41 +158,60 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh)
// Generate out unique verbose format representation // Generate out unique verbose format representation
void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh) void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh)
{ {
unsigned int iBase = 0;
// Allocate output storage // Allocate output storage
std::vector<aiVector3D> vNew (sMesh.mFaces.size() * 3); std::vector<aiVector3D> vNew (sMesh.mFaces.size() * 3);
std::vector<aiVector2D> vNew2; std::vector<aiVector3D> vNew2;
if (sMesh.mTexCoords.size())vNew2.resize(sMesh.mFaces.size() * 3); if (sMesh.mTexCoords.size())
vNew2.resize(sMesh.mFaces.size() * 3);
for (unsigned int i = 0; i < sMesh.mFaces.size();++i) for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i)
{ {
uint32_t iTemp1,iTemp2; D3DS::Face& face = sMesh.mFaces[i];
// positions // Positions
vNew[iBase] = sMesh.mPositions[sMesh.mFaces[i].mIndices[2]]; for (unsigned int a = 0; a < 3;++a,++base)
iTemp1 = iBase++;
vNew[iBase] = sMesh.mPositions[sMesh.mFaces[i].mIndices[1]];
iTemp2 = iBase++;
vNew[iBase] = sMesh.mPositions[sMesh.mFaces[i].mIndices[0]];
// texture coordinates
if (sMesh.mTexCoords.size())
{ {
vNew2[iTemp1] = sMesh.mTexCoords[sMesh.mFaces[i].mIndices[2]]; vNew[base] = sMesh.mPositions[face.mIndices[a]];
vNew2[iTemp2] = sMesh.mTexCoords[sMesh.mFaces[i].mIndices[1]]; if (sMesh.mTexCoords.size())
vNew2[iBase] = sMesh.mTexCoords[sMesh.mFaces[i].mIndices[0]]; vNew2[base] = sMesh.mTexCoords[face.mIndices[a]];
}
sMesh.mFaces[i].mIndices[2] = iBase++; face.mIndices[a] = base;
sMesh.mFaces[i].mIndices[0] = iTemp1; }
sMesh.mFaces[i].mIndices[1] = iTemp2;
} }
sMesh.mPositions = vNew; sMesh.mPositions = vNew;
sMesh.mTexCoords = vNew2; sMesh.mTexCoords = vNew2;
return; return;
} }
// ------------------------------------------------------------------------------------------------
void CopyTexture(MaterialHelper& mat, D3DS::Texture& texture, aiTextureType type)
{
// Setup the texture name
aiString tex;
tex.Set( texture.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
// Setup the texture blend factor
if (is_not_qnan(texture.mTextureBlend))
mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup the texture mapping mode
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
// Mirroring - double the scaling values
if (texture.mMapMode == aiTextureMapMode_Mirror)
{
texture.mScaleU *= 2.f;
texture.mScaleV *= 2.f;
texture.mOffsetU /= 2.f;
texture.mOffsetV /= 2.f;
}
// Setup texture UV transformations
mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a 3DS material to an aiMaterial // Convert a 3DS material to an aiMaterial
void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
@ -207,12 +225,11 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
tex.Set( mBackgroundImage); tex.Set( mBackgroundImage);
mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
// be sure this is only done for the first material // Be sure this is only done for the first material
mBackgroundImage = std::string(""); mBackgroundImage = std::string("");
} }
// At first add the base ambient color of the // At first add the base ambient color of the scene to the material
// scene to the material
oldMat.mAmbient.r += mClrAmbient.r; oldMat.mAmbient.r += mClrAmbient.r;
oldMat.mAmbient.g += mClrAmbient.g; oldMat.mAmbient.g += mClrAmbient.g;
oldMat.mAmbient.b += mClrAmbient.b; oldMat.mAmbient.b += mClrAmbient.b;
@ -221,13 +238,13 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
name.Set( oldMat.mName); name.Set( oldMat.mName);
mat.AddProperty( &name, AI_MATKEY_NAME); mat.AddProperty( &name, AI_MATKEY_NAME);
// material colors // Material colors
mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
// phong shininess and shininess strength // Phong shininess and shininess strength
if (D3DS::Discreet3DS::Phong == oldMat.mShading || if (D3DS::Discreet3DS::Phong == oldMat.mShading ||
D3DS::Discreet3DS::Metal == oldMat.mShading) D3DS::Discreet3DS::Metal == oldMat.mShading)
{ {
@ -242,20 +259,20 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
} }
} }
// opacity // Opacity
mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY); mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
// bump height scaling // Bump height scaling
mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING); mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
// two sided rendering? // Two sided rendering?
if (oldMat.mTwoSided) if (oldMat.mTwoSided)
{ {
int i = 1; int i = 1;
mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED); mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
} }
// shading mode // Shading mode
aiShadingMode eShading = aiShadingMode_NoShading; aiShadingMode eShading = aiShadingMode_NoShading;
switch (oldMat.mShading) switch (oldMat.mShading)
{ {
@ -263,8 +280,14 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
eShading = aiShadingMode_Flat; break; eShading = aiShadingMode_Flat; break;
// I don't know what "Wire" shading should be, // I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse (L dot N) shading // assume it is simple lambertian diffuse shading
case D3DS::Discreet3DS::Wire: case D3DS::Discreet3DS::Wire:
{
// Set the wireframe flag
unsigned int iWire = 1;
mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
}
case D3DS::Discreet3DS::Gouraud: case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud; break; eShading = aiShadingMode_Gouraud; break;
@ -283,112 +306,29 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
} }
mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
if (D3DS::Discreet3DS::Wire == oldMat.mShading)
{
// set the wireframe flag
unsigned int iWire = 1;
mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
}
// texture, if there is one
// DIFFUSE texture // DIFFUSE texture
if( oldMat.sTexDiffuse.mMapName.length() > 0) if( oldMat.sTexDiffuse.mMapName.length() > 0)
{ CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE);
aiString tex;
tex.Set( oldMat.sTexDiffuse.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
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));
}
}
// SPECULAR texture // SPECULAR texture
if( oldMat.sTexSpecular.mMapName.length() > 0) if( oldMat.sTexSpecular.mMapName.length() > 0)
{ CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR);
aiString tex;
tex.Set( oldMat.sTexSpecular.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0));
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));
}
}
// OPACITY texture // OPACITY texture
if( oldMat.sTexOpacity.mMapName.length() > 0) if( oldMat.sTexOpacity.mMapName.length() > 0)
{ CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY);
aiString tex;
tex.Set( oldMat.sTexOpacity.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0));
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));
}
}
// EMISSIVE texture // EMISSIVE texture
if( oldMat.sTexEmissive.mMapName.length() > 0) if( oldMat.sTexEmissive.mMapName.length() > 0)
{ CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE);
aiString tex;
tex.Set( oldMat.sTexEmissive.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0));
if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend)) // BUMP texture
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));
}
}
// BUMP texturee
if( oldMat.sTexBump.mMapName.length() > 0) if( oldMat.sTexBump.mMapName.length() > 0)
{ CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT);
aiString tex;
tex.Set( oldMat.sTexBump.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0));
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));
}
}
// SHININESS texture // SHININESS texture
if( oldMat.sTexShininess.mMapName.length() > 0) if( oldMat.sTexShininess.mMapName.length() > 0)
{ CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS);
aiString tex;
tex.Set( oldMat.sTexShininess.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0));
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 // Store the name of the material itself, too
if( oldMat.mName.length()) if( oldMat.mName.length())
@ -425,74 +365,51 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
// now generate submeshes // now generate submeshes
for (unsigned int p = 0; p < mScene->mMaterials.size();++p) for (unsigned int p = 0; p < mScene->mMaterials.size();++p)
{ {
if (aiSplit[p].size() != 0) if (aiSplit[p].size())
{ {
aiMesh* p_pcOut = new aiMesh(); aiMesh* meshOut = new aiMesh();
p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// be sure to setup the correct material index // be sure to setup the correct material index
p_pcOut->mMaterialIndex = p; meshOut->mMaterialIndex = p;
// use the color data as temporary storage // use the color data as temporary storage
p_pcOut->mColors[0] = (aiColor4D*)(&*i); meshOut->mColors[0] = (aiColor4D*)(&*i);
avOutMeshes.push_back(p_pcOut); avOutMeshes.push_back(meshOut);
// convert vertices // convert vertices
p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size(); meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
p_pcOut->mNumVertices = p_pcOut->mNumFaces*3; meshOut->mNumVertices = meshOut->mNumFaces*3;
// allocate enough storage for faces // allocate enough storage for faces
p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; meshOut->mFaces = new aiFace[meshOut->mNumFaces];
iFaceCnt += p_pcOut->mNumFaces; iFaceCnt += meshOut->mNumFaces;
if (p_pcOut->mNumVertices) meshOut->mVertices = new aiVector3D[meshOut->mNumVertices];
{ meshOut->mNormals = new aiVector3D[meshOut->mNumVertices];
p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
unsigned int iBase = 0;
for (unsigned int q = 0; q < aiSplit[p].size();++q)
{
unsigned int iIndex = aiSplit[p][q];
p_pcOut->mFaces[q].mIndices = new unsigned int[3];
p_pcOut->mFaces[q].mNumIndices = 3;
p_pcOut->mFaces[q].mIndices[2] = iBase;
p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].mIndices[0]];
p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].mIndices[0]];
p_pcOut->mFaces[q].mIndices[1] = iBase;
p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].mIndices[1]];
p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].mIndices[1]];
p_pcOut->mFaces[q].mIndices[0] = iBase;
p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].mIndices[2]];
p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].mIndices[2]];
}
}
// convert texture coordinates
if ((*i).mTexCoords.size()) if ((*i).mTexCoords.size())
{ {
p_pcOut->mTextureCoords[0] = new aiVector3D[p_pcOut->mNumVertices]; meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices];
}
for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
{
register unsigned int index = aiSplit[p][q];
aiFace& face = meshOut->mFaces[q];
unsigned int iBase = 0; face.mIndices = new unsigned int[3];
for (unsigned int q = 0; q < aiSplit[p].size();++q) face.mNumIndices = 3;
for (unsigned int a = 0; a < 3;++a,++base)
{ {
unsigned int iIndex2 = aiSplit[p][q]; unsigned int idx = (*i).mFaces[index].mIndices[a];
meshOut->mVertices[base] = (*i).mPositions[idx];
meshOut->mNormals [base] = (*i).mNormals[idx];
aiVector2D* pc = &(*i).mTexCoords[(*i).mFaces[iIndex2].mIndices[0]]; if ((*i).mTexCoords.size())
p_pcOut->mTextureCoords[0][iBase++] = aiVector3D(pc->x,pc->y,0.0f); meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx];
pc = &(*i).mTexCoords[(*i).mFaces[iIndex2].mIndices[1]]; face.mIndices[a] = base;
p_pcOut->mTextureCoords[0][iBase++] = aiVector3D(pc->x,pc->y,0.0f);
pc = &(*i).mTexCoords[(*i).mFaces[iIndex2].mIndices[2]];
p_pcOut->mTextureCoords[0][iBase++] = aiVector3D(pc->x,pc->y,0.0f);
} }
// apply texture coordinate scalings
TextureTransform::BakeScaleNOffset ( p_pcOut, &mScene->mMaterials[
p_pcOut->mMaterialIndex] );
} }
} }
} }
@ -508,20 +425,12 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
// We should have at least one face here // We should have at least one face here
if (!iFaceCnt) if (!iFaceCnt)
throw new ImportErrorException("No faces loaded. The mesh is empty"); throw new ImportErrorException("No faces loaded. The mesh is empty");
// for each material in the scene we need to setup the UV source
// set for each texture
for (unsigned int a = 0; a < pcOut->mNumMaterials;++a)
{
TextureTransform::SetupMatUVSrc( pcOut->mMaterials[a], &mScene->mMaterials[a] );
}
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Add a node to the scenegraph and setup its final transformation // Add a node to the scenegraph and setup its final transformation
void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
aiMatrix4x4& absTrafo) D3DS::Node* pcIn, aiMatrix4x4& absTrafo)
{ {
std::vector<unsigned int> iArray; std::vector<unsigned int> iArray;
iArray.reserve(3); iArray.reserve(3);
@ -529,11 +438,12 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
aiMatrix4x4 abs; aiMatrix4x4 abs;
if (pcIn->mName == "$$$DUMMY") if (pcIn->mName == "$$$DUMMY")
{ {
// Append the "real" name of the dummy to the string // FIX: Append the "real" name of the dummy to the string
pcIn->mName.append(pcIn->mDummyName); pcIn->mName = "Dummy." + pcIn->mDummyName;
} }
else // if (pcIn->mName != "$$$DUMMY") else // if (pcIn->mName != "$$$DUMMY")
{ {
// Find all meshes with the same name as the node
for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a) for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
{ {
const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0]; const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
@ -544,13 +454,10 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
} }
if (!iArray.empty()) if (!iArray.empty())
{ {
// The matrix should be identical for all meshes with the same name. // The matrix should be identical for all meshes with the
// It HAS to be identical for all meshes ........ // same name. It HAS to be identical for all meshes .....
aiMatrix4x4& mTrafo = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat; aiMatrix4x4 mInv = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
aiMatrix4x4 mInv = mTrafo; mInv.Inverse();
if (!configSkipPivot)
mInv.Inverse();
const aiVector3D& pivot = pcIn->vPivot; const aiVector3D& pivot = pcIn->vPivot;
pcOut->mNumMeshes = (unsigned int)iArray.size(); pcOut->mNumMeshes = (unsigned int)iArray.size();
@ -560,31 +467,24 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
const unsigned int iIndex = iArray[i]; const unsigned int iIndex = iArray[i];
aiMesh* const mesh = pcSOut->mMeshes[iIndex]; aiMesh* const mesh = pcSOut->mMeshes[iIndex];
// Pivot point adjustment. // Pivot point adjustment
// See: http://www.zfx.info/DisplayThread.php?MID=235690#235690 // See: http://www.zfx.info/DisplayThread.php?MID=235690#235690
const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices; const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices;
aiVector3D* pvCurrent = mesh->mVertices; aiVector3D* pvCurrent = mesh->mVertices;
if(pivot.x || pivot.y || pivot.z && !configSkipPivot) if(pivot.x || pivot.y || pivot.z)
{ {
while (pvCurrent != pvEnd) for (;pvCurrent != pvEnd;++pvCurrent)
{ {
*pvCurrent = mInv * (*pvCurrent); *pvCurrent = mInv * (*pvCurrent);
pvCurrent->x -= pivot.x; *pvCurrent -= pivot;
pvCurrent->y -= pivot.y;
pvCurrent->z -= pivot.z;
++pvCurrent;
} }
} }
else else
{ {
while (pvCurrent != pvEnd) for (;pvCurrent != pvEnd;++pvCurrent)
{
*pvCurrent = mInv * (*pvCurrent); *pvCurrent = mInv * (*pvCurrent);
++pvCurrent;
}
} }
// Setup the mesh index // Setup the mesh index
pcOut->mMeshes[i] = iIndex; pcOut->mMeshes[i] = iIndex;
} }
@ -648,73 +548,82 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
} }
} }
if (pcIn->aTargetPositionKeys.size() > 1) //if (pcIn->aTargetPositionKeys.size() > 1)
//{
// DefaultLogger::get()->debug("3DS: Converting target track ...");
// // Camera or spot light - need to convert the separate
// // target position channel to our representation
// TargetAnimationHelper helper;
// if (pcIn->aPositionKeys.empty())
// {
// // We can just pass zero here ...
// helper.SetFixedMainAnimationChannel(aiVector3D());
// }
// else helper.SetMainAnimationChannel(&pcIn->aPositionKeys);
// helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys);
// // Do the conversion
// std::vector<aiVectorKey> distanceTrack;
// helper.Process(&distanceTrack);
// // Now add a new node as child, name it <ourName>.Target
// // and assign the distance track to it. This is that the
// // information where the target is and how it moves is
// // not lost
// D3DS::Node* nd = new D3DS::Node();
// pcIn->push_back(nd);
// nd->mName = pcIn->mName + ".Target";
// aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
// nda->mNodeName.Set(nd->mName);
// nda->mNumPositionKeys = (unsigned int)distanceTrack.size();
// nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
// ::memcpy(nda->mPositionKeys,&distanceTrack[0],
// sizeof(aiVectorKey)*nda->mNumPositionKeys);
//}
// Allocate a new nda, increment the nda index
aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
nda->mNodeName.Set(pcIn->mName);
// POSITION keys
if (pcIn->aPositionKeys.size() > 0)
{ {
//DefaultLogger::get()->debug("3DS: Converting target track ..."); nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
//// Camera or spot light - need to convert the separate ::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
//// target position channel to our representation sizeof(aiVectorKey)*nda->mNumPositionKeys);
//TargetAnimationHelper helper;
//helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys);
//helper.SetMainAnimationChannel(&pcIn->aPositionKeys);
//// Do the conversion
//std::vector<aiVectorKey> distanceTrack;
//helper.Process(&distanceTrack);
//// Now add a new node as child, name it <ourName>.Target
//// and assign the distance track to it. This is that the
//// information where the target is and how it moves is
//// not lost
//D3DS::Node* nd = new D3DS::Node();
//pcIn->push_back(nd);
//nd->mName = pcIn->mName + ".Target";
//aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
//nda->mNodeName.Set(nd->mName);
//nda->mNumPositionKeys = (unsigned int)distanceTrack.size();
//nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
//::memcpy(nda->mPositionKeys,&distanceTrack[0],
// sizeof(aiVectorKey)*nda->mNumPositionKeys);
} }
// Just for safety ... we *should* have at least one track here // ROTATION keys
if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 || if (pcIn->aRotationKeys.size() > 0)
pcIn->aScalingKeys.size() > 1)
{ {
// Allocate a new nda, increment the nda index nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
nda->mNodeName.Set(pcIn->mName);
// POSITION keys // Rotations are quaternion offsets
if (pcIn->aPositionKeys.size() > 0) aiQuaternion abs;
for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
{ {
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size(); const aiQuatKey& q = pcIn->aRotationKeys[n];
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
sizeof(aiVectorKey)*nda->mNumPositionKeys);
}
// ROTATION keys abs = (n ? abs * q.mValue : q.mValue);
if (pcIn->aRotationKeys.size() > 0) nda->mRotationKeys[n].mTime = q.mTime;
{ nda->mRotationKeys[n].mValue = abs.Normalize();
nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
::memcpy(nda->mRotationKeys,&pcIn->aRotationKeys[0],
sizeof(aiQuatKey)*nda->mNumRotationKeys);
} }
}
// SCALING keys // SCALING keys
if (pcIn->aScalingKeys.size() > 0) if (pcIn->aScalingKeys.size() > 0)
{ {
nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size(); nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys]; nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0], ::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
sizeof(aiVectorKey)*nda->mNumScalingKeys); sizeof(aiVectorKey)*nda->mNumScalingKeys);
}
} }
} }
@ -864,14 +773,6 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
pcOld->mChildren[0] = NULL; pcOld->mChildren[0] = NULL;
delete pcOld; delete pcOld;
} }
#if 0
// modify the transformation of the root node to change
// the coordinate system of the whole scene from Max' to OpenGL
pcOut->mRootNode->mTransformation.a3 *= -1.f;
pcOut->mRootNode->mTransformation.b3 *= -1.f;
pcOut->mRootNode->mTransformation.c3 *= -1.f;
#endif
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -38,21 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file Defines helper data structures for the import of 3DS files. /** @file Defines helper data structures for the import of 3DS files */
http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */
#ifndef AI_3DSFILEHELPER_H_INC #ifndef AI_3DSFILEHELPER_H_INC
#define AI_3DSFILEHELPER_H_INC #define AI_3DSFILEHELPER_H_INC
#include <string>
#include <vector>
#include <sstream>
#include "../include/aiTypes.h"
#include "../include/aiQuaternion.h"
#include "../include/aiMesh.h"
#include "../include/aiAnim.h"
#include "../include/aiMaterial.h"
#include "SpatialSort.h" #include "SpatialSort.h"
#include "SmoothingGroups.h" #include "SmoothingGroups.h"
@ -66,12 +56,13 @@ namespace D3DS {
/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks /** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
* and data structures. * and data structures.
*/ */
// ---------------------------------------------------------------------------
class Discreet3DS class Discreet3DS
{ {
public: private:
inline Discreet3DS() {} inline Discreet3DS() {}
public:
//! data structure for a single chunk in a .3ds file //! data structure for a single chunk in a .3ds file
struct Chunk struct Chunk
{ {
@ -79,10 +70,6 @@ public:
uint32_t Size; uint32_t Size;
} PACK_STRUCT; } PACK_STRUCT;
//! source for this used own structures,
//! replaced it with out standard math helpers
typedef aiMatrix3x3 MatTransform;
typedef aiVector3D MatTranslate;
//! Used for shading field in material3ds structure //! Used for shading field in material3ds structure
//! From AutoDesk 3ds SDK //! From AutoDesk 3ds SDK
@ -301,26 +288,22 @@ public:
}; };
}; };
#include "./../include/Compiler/poppack1.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */ /** Helper structure representing a 3ds mesh face */
struct Face : public FaceWithSmoothingGroup struct Face : public FaceWithSmoothingGroup
{ {
//! Specifies that the face normal must be flipped.
//! todo: do we really need this?
bool bFlipped;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a texture */ /** Helper structure representing a texture */
struct Texture struct Texture
{ {
//! Default constructor //! Default constructor
Texture() Texture()
: mScaleU (1.0f) : mOffsetU (0.0f)
, mScaleV (1.0f)
, mOffsetU (0.0f)
, mOffsetV (0.0f) , mOffsetV (0.0f)
, mScaleU (1.0f)
, mScaleV (1.0f)
, mRotation (0.0f) , mRotation (0.0f)
, mMapMode (aiTextureMapMode_Wrap) , mMapMode (aiTextureMapMode_Wrap)
, iUVSrc (0) , iUVSrc (0)
@ -335,10 +318,10 @@ struct Texture
std::string mMapName; std::string mMapName;
//! Specifies texture coordinate offsets/scaling/rotations //! Specifies texture coordinate offsets/scaling/rotations
float mScaleU;
float mScaleV;
float mOffsetU; float mOffsetU;
float mOffsetV; float mOffsetV;
float mScaleU;
float mScaleV;
float mRotation; float mRotation;
//! Specifies the mapping mode to be used for the texture //! Specifies the mapping mode to be used for the texture
@ -348,6 +331,9 @@ struct Texture
bool bPrivate; bool bPrivate;
int iUVSrc; int iUVSrc;
}; };
#include "./../include/Compiler/poppack1.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a 3ds material */ /** Helper structure representing a 3ds material */
struct Material struct Material
@ -414,6 +400,7 @@ struct Material
unsigned int iBakeUVTransform; unsigned int iBakeUVTransform;
Texture* pcSingleTexture; Texture* pcSingleTexture;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent a 3ds file mesh */ /** Helper structure to represent a 3ds file mesh */
struct Mesh : public MeshWithSmoothingGroups<D3DS::Face> struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
@ -433,7 +420,7 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
std::string mName; std::string mName;
//! Texture coordinates //! Texture coordinates
std::vector<aiVector2D> mTexCoords; std::vector<aiVector3D> mTexCoords;
//! Face materials //! Face materials
std::vector<unsigned int> mFaceMaterials; std::vector<unsigned int> mFaceMaterials;

View File

@ -104,7 +104,7 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle
// Setup configuration properties // Setup configuration properties
void Discreet3DSImporter::SetupProperties(const Importer* pImp) void Discreet3DSImporter::SetupProperties(const Importer* pImp)
{ {
configSkipPivot = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT,0) ? true : false; // nothing to be done for the moment
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -141,7 +141,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
// internal verbose representation. Finally compute normal // internal verbose representation. Finally compute normal
// vectors from the smoothing groups we read from the // vectors from the smoothing groups we read from the
// file. // file.
for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(), for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(),
end = mScene->mMeshes.end(); i != end;++i) end = mScene->mMeshes.end(); i != end;++i)
{ {
CheckIndices(*i); CheckIndices(*i);
@ -149,9 +149,6 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(*i); ComputeNormalsWithSmoothingsGroups<D3DS::Face>(*i);
} }
// Apply scaling and offsets to all texture coordinates
TextureTransform::ApplyScaleNOffset(mScene->mMaterials);
// Replace all occurences of the default material with a // Replace all occurences of the default material with a
// valid material. Generate it if no material containing // valid material. Generate it if no material containing
// DEFAULT in its name has been found in the file // DEFAULT in its name has been found in the file
@ -678,6 +675,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
} }
else l = & mCurrentNode->aPositionKeys; else l = & mCurrentNode->aPositionKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i)
{ {
unsigned int fidx = stream->GetI2(); unsigned int fidx = stream->GetI2();
@ -724,6 +722,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
stream->IncPtr(10); stream->IncPtr(10);
unsigned int numFrames = stream->GetI2(); unsigned int numFrames = stream->GetI2();
l->reserve(numFrames);
stream->IncPtr(2); stream->IncPtr(2);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i)
@ -776,6 +775,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
bool sortKeys = false; bool sortKeys = false;
std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys; std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i)
{ {
@ -825,6 +825,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
bool sortKeys = false; bool sortKeys = false;
std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys; std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i)
{ {
@ -924,7 +925,7 @@ void Discreet3DSImporter::ParseFaceChunk()
} }
// Now continue and read all material indices // Now continue and read all material indices
cnt = stream->GetI2(); cnt = (uint16_t)stream->GetI2();
for (unsigned int i = 0; i < cnt;++i) for (unsigned int i = 0; i < cnt;++i)
{ {
unsigned int fidx = (uint16_t)stream->GetI2(); unsigned int fidx = (uint16_t)stream->GetI2();
@ -957,7 +958,8 @@ void Discreet3DSImporter::ParseMeshChunk()
case Discreet3DS::CHUNK_VERTLIST: case Discreet3DS::CHUNK_VERTLIST:
{ {
// This is the list of all vertices in the current mesh // This is the list of all vertices in the current mesh
int num = stream->GetI2(); int num = (int)(uint16_t)stream->GetI2();
mMesh.mPositions.reserve(num);
while (num-- > 0) while (num-- > 0)
{ {
aiVector3D v; aiVector3D v;
@ -985,8 +987,8 @@ void Discreet3DSImporter::ParseMeshChunk()
mMesh.mMat.c4 = stream->GetF4(); mMesh.mMat.c4 = stream->GetF4();
// Now check whether the matrix has got a negative determinant // Now check whether the matrix has got a negative determinant
// If yes, we need to flip all vertices' x axis .... // If yes, we need to flip all vertices' Z axis ....
// From lib3ds, mesh.c // This code has been taken from lib3ds
if (mMesh.mMat.Determinant() < 0.0f) if (mMesh.mMat.Determinant() < 0.0f)
{ {
// Compute the inverse of the matrix // Compute the inverse of the matrix
@ -994,10 +996,10 @@ void Discreet3DSImporter::ParseMeshChunk()
mInv.Inverse(); mInv.Inverse();
aiMatrix4x4 mMe = mMesh.mMat; aiMatrix4x4 mMe = mMesh.mMat;
mMe.a1 *= -1.0f;
mMe.b1 *= -1.0f;
mMe.c1 *= -1.0f; mMe.c1 *= -1.0f;
mMe.d1 *= -1.0f; mMe.c2 *= -1.0f;
mMe.c3 *= -1.0f;
mMe.c4 *= -1.0f;
mInv = mInv * mMe; mInv = mInv * mMe;
// Now transform all vertices // Now transform all vertices
@ -1010,16 +1012,19 @@ void Discreet3DSImporter::ParseMeshChunk()
c[2]= mInv[0][2]*a[0] + mInv[1][2]*a[1] + mInv[2][2]*a[2] + mInv[3][2]; c[2]= mInv[0][2]*a[0] + mInv[1][2]*a[1] + mInv[2][2]*a[2] + mInv[3][2];
mMesh.mPositions[i] = c; mMesh.mPositions[i] = c;
} }
DefaultLogger::get()->info("3DS: Flipping mesh Z-Axis");
}} }}
break; break;
case Discreet3DS::CHUNK_MAPLIST: case Discreet3DS::CHUNK_MAPLIST:
{ {
// This is the list of all UV coords in the current mesh // This is the list of all UV coords in the current mesh
int num = stream->GetI2(); int num = (int)(uint16_t)stream->GetI2();
mMesh.mTexCoords.reserve(num);
while (num-- > 0) while (num-- > 0)
{ {
aiVector2D v; aiVector3D v;
v.x = stream->GetF4(); v.x = stream->GetF4();
v.y = stream->GetF4(); v.y = stream->GetF4();
mMesh.mTexCoords.push_back(v); mMesh.mTexCoords.push_back(v);
@ -1029,7 +1034,8 @@ void Discreet3DSImporter::ParseMeshChunk()
case Discreet3DS::CHUNK_FACELIST: case Discreet3DS::CHUNK_FACELIST:
{ {
// This is the list of all faces in the current mesh // This is the list of all faces in the current mesh
int num = stream->GetI2(); int num = (int)(uint16_t)stream->GetI2();
mMesh.mFaces.reserve(num);
while (num-- > 0) while (num-- > 0)
{ {
// 3DS faces are ALWAYS triangles // 3DS faces are ALWAYS triangles
@ -1226,6 +1232,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
// recursively continue processing this hierarchy level // recursively continue processing this hierarchy level
return ParseMaterialChunk(); return ParseMaterialChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
{ {
@ -1262,7 +1269,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
if (0.0f == pcOut->mScaleU) if (0.0f == pcOut->mScaleU)
{ {
DefaultLogger::get()->warn("Texture coordinate scaling in the " DefaultLogger::get()->warn("Texture coordinate scaling in the "
"x direction is zero. Assuming this should be 1.0 ... "); "x direction is zero. Assuming 1");
pcOut->mScaleU = 1.0f; pcOut->mScaleU = 1.0f;
} }
break; break;
@ -1272,14 +1279,14 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
if (0.0f == pcOut->mScaleV) if (0.0f == pcOut->mScaleV)
{ {
DefaultLogger::get()->warn("Texture coordinate scaling in the " DefaultLogger::get()->warn("Texture coordinate scaling in the "
"y direction is zero. Assuming this should be 1.0 ... "); "y direction is zero. Assuming 1");
pcOut->mScaleV = 1.0f; pcOut->mScaleV = 1.0f;
} }
break; break;
case Discreet3DS::CHUNK_MAT_MAP_UOFFSET: case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
// Texture coordinate offset in the U direction // Texture coordinate offset in the U direction
pcOut->mOffsetU = stream->GetF4(); pcOut->mOffsetU = -stream->GetF4();
break; break;
case Discreet3DS::CHUNK_MAT_MAP_VOFFSET: case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
@ -1288,24 +1295,24 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
break; break;
case Discreet3DS::CHUNK_MAT_MAP_ANG: case Discreet3DS::CHUNK_MAT_MAP_ANG:
// Texture coordinate rotation, CCW in radians // Texture coordinate rotation, CCW in DEGREES
pcOut->mRotation = stream->GetF4(); pcOut->mRotation = -AI_DEG_TO_RAD( stream->GetF4() );
break; break;
case Discreet3DS::CHUNK_MAT_MAP_TILING: case Discreet3DS::CHUNK_MAT_MAP_TILING:
{ {
uint16_t iFlags = stream->GetI2(); uint16_t iFlags = stream->GetI2();
// check whether the mirror flag is set // Get the mapping mode (for both axes)
if (iFlags & 0x2u) if (iFlags & 0x2u)
{
pcOut->mMapMode = aiTextureMapMode_Mirror; pcOut->mMapMode = aiTextureMapMode_Mirror;
else if (iFlags & 0x10u)
pcOut->mMapMode = aiTextureMapMode_Decal;
// wrapping in all remaining cases
else pcOut->mMapMode = aiTextureMapMode_Wrap;
} }
// assume that "decal" means clamping ...
else if (iFlags & 0x10u && iFlags & 0x1u)
{
pcOut->mMapMode = aiTextureMapMode_Clamp;
}}
break; break;
}; };

View File

@ -238,12 +238,8 @@ protected:
*/ */
void CheckIndices(D3DS::Mesh& sMesh); void CheckIndices(D3DS::Mesh& sMesh);
protected: protected:
/** Configuration option: skip pivot chunks */
bool configSkipPivot;
/** Stream to read from */ /** Stream to read from */
StreamReaderLE* stream; StreamReaderLE* stream;

View File

@ -151,11 +151,30 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
if (!TokenMatch(buffer,"OBJECT",6)) if (!TokenMatch(buffer,"OBJECT",6))
return; return;
SkipSpaces(&buffer);
++mNumMeshes; ++mNumMeshes;
objects.push_back(Object()); objects.push_back(Object());
Object& obj = objects.back(); Object& obj = objects.back();
aiLight* light = NULL;
if (!ASSIMP_stricmp(buffer,"light"))
{
// This is a light source. Add it to the list
mLights->push_back(light = new aiLight());
// Return a point light with no attenuation
light->mType = aiLightSource_POINT;
light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f);
light->mAttenuationConstant = 1.f;
// Generate a default name for both the light source and the node
light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",mLights->size()-1);
obj.name = std::string( light->mName.data );
}
while (GetNextLine()) while (GetNextLine())
{ {
if (TokenMatch(buffer,"kids",4)) if (TokenMatch(buffer,"kids",4))
@ -176,6 +195,13 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
{ {
SkipSpaces(&buffer); SkipSpaces(&buffer);
AI_AC_GET_STRING(obj.name); AI_AC_GET_STRING(obj.name);
// If this is a light source, we'll also need to store
// the name of the node in it.
if (light)
{
light->mName.Set(obj.name);
}
} }
else if (TokenMatch(buffer,"texture",7)) else if (TokenMatch(buffer,"texture",7))
{ {
@ -219,8 +245,6 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
obj.vertices.push_back(aiVector3D()); obj.vertices.push_back(aiVector3D());
aiVector3D& v = obj.vertices.back(); aiVector3D& v = obj.vertices.back();
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x);
//std::swap(v.z,v.y);
v.z *= -1.f;
} }
} }
else if (TokenMatch(buffer,"numsurf",7)) else if (TokenMatch(buffer,"numsurf",7))
@ -597,7 +621,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
node->mTransformation = aiMatrix4x4 ( object.rotation ); node->mTransformation = aiMatrix4x4 ( object.rotation );
node->mTransformation.a4 = object.translation.x; node->mTransformation.a4 = object.translation.x;
node->mTransformation.b4 = object.translation.y; node->mTransformation.b4 = -object.translation.y;
node->mTransformation.c4 = object.translation.z; node->mTransformation.c4 = object.translation.z;
return node; return node;
@ -644,6 +668,9 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
std::vector<Object> rootObjects; std::vector<Object> rootObjects;
rootObjects.reserve(5); rootObjects.reserve(5);
std::vector<aiLight*> lights;
mLights = & lights;
while (GetNextLine()) while (GetNextLine())
{ {
if (TokenMatch(buffer,"MATERIAL",8)) if (TokenMatch(buffer,"MATERIAL",8))
@ -662,9 +689,9 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
} }
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.rgb); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.rgb); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.rgb); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans); AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans);
} }
@ -701,6 +728,9 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials); pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
if (1 != rootObjects.size())delete root; if (1 != rootObjects.size())delete root;
if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
pScene->mRootNode->mName.Set("<AC3DWorld>");
// build output arrays // build output arrays
if (meshes.empty()) if (meshes.empty())
{ {
@ -710,10 +740,17 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*)); ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
// build output arrays
pScene->mNumMaterials = (unsigned int)omaterials.size(); pScene->mNumMaterials = (unsigned int)omaterials.size();
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*)); ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*));
pScene->mNumLights = (unsigned int)lights.size();
if (lights.size())
{
pScene->mLights = new aiLight*[lights.size()];
::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*));
}
} }
#endif //!defined AI_BUILD_NO_AC_IMPORTER #endif //!defined AI_BUILD_NO_AC_IMPORTER

View File

@ -236,6 +236,9 @@ private:
// basing on this information we can find a // basing on this information we can find a
// good estimate how many meshes we'll have in the final scene. // good estimate how many meshes we'll have in the final scene.
unsigned int mNumMeshes; unsigned int mNumMeshes;
// current list of light sources
std::vector<aiLight*>* mLights;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -48,12 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ASELoader.h" #include "ASELoader.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "StringComparison.h" #include "StringComparison.h"
#include "TextureTransform.h"
#include "SkeletonMeshBuilder.h" #include "SkeletonMeshBuilder.h"
#include "TargetAnimation.h"
// utilities // utilities
#include "fast_atof.h" #include "fast_atof.h"
#include "qnan.h"
using namespace Assimp; using namespace Assimp;
using namespace Assimp::ASE; using namespace Assimp::ASE;
@ -156,15 +155,15 @@ void ASEImporter::InternReadFile( const std::string& pFile,
std::vector<aiMesh*> avOutMeshes; std::vector<aiMesh*> avOutMeshes;
avOutMeshes.reserve(mParser->m_vMeshes.size()*2); avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
for (std::vector<ASE::Mesh>::iterator for (std::vector<ASE::Mesh>::iterator
i = mParser->m_vMeshes.begin(); i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i)
i != mParser->m_vMeshes.end();++i)
{ {
if ((*i).bSkip)continue; if ((*i).bSkip)continue;
// Now we need to create proper meshes from the import we // First of all - we need to build an unique mesh representation
// need to split them by materials, build valid vertex/ // that we can recompute the normal vectors easily. This is
// face lists ... // also a prerequisite for the second code path in ConvertMeshes()
BuildUniqueRepresentation(*i); // so it's difficult to optimize it away. TODO!
BuildUniqueRepresentation(*i);
// Need to generate proper vertex normals if necessary // Need to generate proper vertex normals if necessary
if(GenerateNormals(*i)) if(GenerateNormals(*i))
@ -305,8 +304,12 @@ void ASEImporter::BuildAnimations()
// that represent the node transformation. // that represent the node transformation.
if ((*i)->mAnim.akeyPositions.size() > 1 || if ((*i)->mAnim.akeyPositions.size() > 1 ||
(*i)->mAnim.akeyRotations.size() > 1 || (*i)->mAnim.akeyRotations.size() > 1 ||
(*i)->mAnim.akeyScaling.size() > 1 || (*i)->mAnim.akeyScaling.size() > 1)
(*i)->mTargetAnim.akeyPositions.size() > 1 {
++iNum;
}
if ((*i)->mTargetAnim.akeyPositions.size() > 1
&& is_not_qnan( (*i)->mTargetPosition.x )) && is_not_qnan( (*i)->mTargetPosition.x ))
{ {
++iNum; ++iNum;
@ -337,6 +340,21 @@ void ASEImporter::BuildAnimations()
aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
nd->mNodeName.Set(me->mName + ".Target"); nd->mNodeName.Set(me->mName + ".Target");
// If there is no input position channel we will need
// to supply the default position from the node's
// local transformation matrix.
/*TargetAnimationHelper helper;
if (me->mAnim.akeyPositions.empty())
{
aiMatrix4x4& mat = (*i)->mTransform;
helper.SetFixedMainAnimationChannel(aiVector3D(
mat.a4, mat.b4, mat.c4));
}
else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
helper.Process(&me->mTargetAnim.akeyPositions);*/
// Allocate the key array and fill it // Allocate the key array and fill it
nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size(); nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size();
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
@ -345,7 +363,8 @@ void ASEImporter::BuildAnimations()
nd->mNumPositionKeys * sizeof(aiVectorKey)); nd->mNumPositionKeys * sizeof(aiVectorKey));
} }
if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1) if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 ||
me->mAnim.akeyScaling.size() > 1)
{ {
// Begin a new node animation channel for this node // Begin a new node animation channel for this node
aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
@ -424,8 +443,6 @@ void ASEImporter::BuildCameras()
out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f); out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
out->mHorizontalFOV = in.mFOV; out->mHorizontalFOV = in.mFOV;
// TODO: Implement proper camera target
out->mName.Set(in.mName); out->mName.Set(in.mName);
} }
} }
@ -480,7 +497,7 @@ void ASEImporter::AddNodes(std::vector<BaseNode*>& nodes,
aiNode* pcParent,const char* szName) aiNode* pcParent,const char* szName)
{ {
aiMatrix4x4 m; aiMatrix4x4 m;
this->AddNodes(nodes,pcParent,szName,m); AddNodes(nodes,pcParent,szName,m);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -580,6 +597,12 @@ void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes,
mParentAdjust.Inverse(); mParentAdjust.Inverse();
node->mTransformation = mParentAdjust*snode->mTransform; node->mTransformation = mParentAdjust*snode->mTransform;
// Add sub nodes - prevent stack overflow
if (node->mName != node->mParent->mName)
{
AddNodes(nodes,node,node->mName.data,snode->mTransform);
}
// Further processing depends on the type of the node // Further processing depends on the type of the node
if (snode->mType == ASE::BaseNode::Mesh) if (snode->mType == ASE::BaseNode::Mesh)
{ {
@ -597,39 +620,43 @@ void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes,
// target (the direction information is contained in *this* // target (the direction information is contained in *this*
// node's animation track but the exact target position // node's animation track but the exact target position
// would be lost otherwise) // would be lost otherwise)
apcNodes.push_back(new aiNode()); if (!node->mNumChildren)
aiNode* node = apcNodes.back(); {
node->mChildren = new aiNode*[1];
}
node->mName.Set ( snode->mName + ".Target" ); aiNode* nd = new aiNode();
node->mTransformation.a4 = snode->mTargetPosition.x;
node->mTransformation.b4 = snode->mTargetPosition.y;
node->mTransformation.c4 = snode->mTargetPosition.z;
node->mParent = pcParent; nd->mName.Set ( snode->mName + ".Target" );
}
nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4;
nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4;
nd->mTransformation.c4 = snode->mTargetPosition.z - snode->mTransform.c4;
// add sub nodes nd->mParent = node;
// aiMatrix4x4 mNewAbs = mat * node->mTransformation;
// prevent stack overflow // The .Target node is always the first child node
if (node->mName != node->mParent->mName) for (unsigned int m = 0; m < node->mNumChildren;++m)
{ node->mChildren[m+1] = node->mChildren[m];
AddNodes(nodes,node,node->mName.data,snode->mTransform);
node->mChildren[0] = nd;
node->mNumChildren++;
// What we did is so great, it is at least worth a debug message
DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
} }
} }
// allocate enough space for the child nodes // Allocate enough space for the child nodes
// We allocate one slot more in case this is a target camera/light
pcParent->mNumChildren = (unsigned int)apcNodes.size(); pcParent->mNumChildren = (unsigned int)apcNodes.size();
if (pcParent->mNumChildren) if (pcParent->mNumChildren)
{ {
pcParent->mChildren = new aiNode*[apcNodes.size()]; pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */];
// now build all nodes for our nice new children // now build all nodes for our nice new children
for (unsigned int p = 0; p < apcNodes.size();++p) for (unsigned int p = 0; p < apcNodes.size();++p)
{
pcParent->mChildren[p] = apcNodes[p]; pcParent->mChildren[p] = apcNodes[p];
}
} }
return; return;
} }
@ -643,7 +670,7 @@ void ASEImporter::BuildNodes()
pcScene->mRootNode = new aiNode(); pcScene->mRootNode = new aiNode();
pcScene->mRootNode->mNumMeshes = 0; pcScene->mRootNode->mNumMeshes = 0;
pcScene->mRootNode->mMeshes = 0; pcScene->mRootNode->mMeshes = 0;
pcScene->mRootNode->mName.Set("<root>"); pcScene->mRootNode->mName.Set("<ASERoot>");
// Setup the coordinate system transformation // Setup the coordinate system transformation
//pcScene->mRootNode->mTransformation.c3 *= -1.f; //pcScene->mRootNode->mTransformation.c3 *= -1.f;
@ -708,7 +735,7 @@ void ASEImporter::BuildNodes()
{ {
const ASE::BaseNode* src = *i; const ASE::BaseNode* src = *i;
// the parent is not known, so we can assume that we must add // The parent is not known, so we can assume that we must add
// this node to the root node of the whole scene // this node to the root node of the whole scene
aiNode* pcNode = new aiNode(); aiNode* pcNode = new aiNode();
pcNode->mParent = pcScene->mRootNode; pcNode->mParent = pcScene->mRootNode;
@ -731,16 +758,18 @@ void ASEImporter::BuildNodes()
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
pcScene->mMeshes[i]->mColors[2] = NULL; pcScene->mMeshes[i]->mColors[2] = NULL;
// if there is only one subnode, set it as root node // If there is only one subnode, set it as root node
// FIX: The sub node may not have animations assigned // FIX: The sub node may not have animations assigned
if (1 == pcScene->mRootNode->mNumChildren && !pcScene->mNumAnimations) if (1 == pcScene->mRootNode->mNumChildren && !pcScene->mNumAnimations)
{ {
aiNode* cc = pcScene->mRootNode->mChildren[0]; aiNode* cc = pcScene->mRootNode->mChildren[0];
aiNode* pc = pcScene->mRootNode; aiNode* pc = pcScene->mRootNode;
if (!cc->mName.length)
cc->mName = pc->mName;
pcScene->mRootNode = cc; pcScene->mRootNode = cc;
pcScene->mRootNode->mParent = NULL; cc->mParent = NULL;
cc->mTransformation = pc->mTransformation * cc->mTransformation;
// make sure the destructor won't delete us ... // make sure the destructor won't delete us ...
delete[] pc->mChildren; delete[] pc->mChildren;
@ -803,17 +832,12 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
for (unsigned int n = 0; n < 3;++n,++iCurrent) for (unsigned int n = 0; n < 3;++n,++iCurrent)
{ {
mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]]; mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
//std::swap((float&)mPositions[iCurrent].z,(float&)mPositions[iCurrent].y); // DX-to-OGL
//mPositions[iCurrent].y *= -1.f;
// add texture coordinates // add texture coordinates
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
{ {
if (!mesh.amTexCoords[c].empty()) if (mesh.amTexCoords[c].empty())break;
{ amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
// amTexCoords[c][iCurrent].y = 1.f- amTexCoords[c][iCurrent].y; // DX-to-OGL
}
} }
// add vertex colors // add vertex colors
if (!mesh.mVertexColors.empty()) if (!mesh.mVertexColors.empty())
@ -825,9 +849,6 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
{ {
mNormals[iCurrent] = mesh.mNormals[fi*3+n]; mNormals[iCurrent] = mesh.mNormals[fi*3+n];
mNormals[iCurrent].Normalize(); mNormals[iCurrent].Normalize();
//std::swap((float&)mNormals[iCurrent].z,(float&)mNormals[iCurrent].y); // DX-to-OGL
//mNormals[iCurrent].y *= -1.0f;
} }
// handle bone vertices // handle bone vertices
@ -838,11 +859,9 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
// will fix that again ...) // will fix that again ...)
mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]]; mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]];
} }
(*i).mIndices[n] = iCurrent;
} }
// we need to flip the order of the indices
(*i).mIndices[0] = iCurrent-1;
(*i).mIndices[1] = iCurrent-2;
(*i).mIndices[2] = iCurrent-3;
} }
// replace the old arrays // replace the old arrays
@ -852,20 +871,37 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
mesh.amTexCoords[c] = amTexCoords[c]; mesh.amTexCoords[c] = amTexCoords[c];
return; }
// ------------------------------------------------------------------------------------------------
void CopyASETexture(MaterialHelper& mat, ASE::Texture& texture, aiTextureType type)
{
// Setup the texture name
aiString tex;
tex.Set( texture.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
// Setup the texture blend factor
if (is_not_qnan(texture.mTextureBlend))
mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup texture UV transformations
mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ASEImporter::ConvertMaterial(ASE::Material& mat) void ASEImporter::ConvertMaterial(ASE::Material& mat)
{ {
// allocate the output material // LARGE TODO: Much code her is copied from 3DS ... join them maybe?
// Allocate the output material
mat.pcInstance = new MaterialHelper(); mat.pcInstance = new MaterialHelper();
// At first add the base ambient color of the // At first add the base ambient color of the
// scene to the material // scene to the material
mat.mAmbient.r += this->mParser->m_clrAmbient.r; mat.mAmbient.r += mParser->m_clrAmbient.r;
mat.mAmbient.g += this->mParser->m_clrAmbient.g; mat.mAmbient.g += mParser->m_clrAmbient.g;
mat.mAmbient.b += this->mParser->m_clrAmbient.b; mat.mAmbient.b += mParser->m_clrAmbient.b;
aiString name; aiString name;
name.Set( mat.mName); name.Set( mat.mName);
@ -883,7 +919,7 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS); mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
} }
// if there is no shininess, we can disable phong lighting // If there is no shininess, we can disable phong lighting
else if (D3DS::Discreet3DS::Metal == mat.mShading || else if (D3DS::Discreet3DS::Metal == mat.mShading ||
D3DS::Discreet3DS::Phong == mat.mShading || D3DS::Discreet3DS::Phong == mat.mShading ||
D3DS::Discreet3DS::Blinn == mat.mShading) D3DS::Discreet3DS::Blinn == mat.mShading)
@ -894,6 +930,12 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
// opacity // opacity
mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY); mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
// Two sided rendering?
if (mat.mTwoSided)
{
int i = 1;
mat.pcInstance->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
}
// shading mode // shading mode
aiShadingMode eShading = aiShadingMode_NoShading; aiShadingMode eShading = aiShadingMode_NoShading;
@ -906,9 +948,14 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
case D3DS::Discreet3DS::Blinn : case D3DS::Discreet3DS::Blinn :
eShading = aiShadingMode_Blinn; break; eShading = aiShadingMode_Blinn; break;
// I don't know what "Wire" shading should be, // I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse (L dot N) shading // assume it is simple lambertian diffuse (L dot N) shading
case D3DS::Discreet3DS::Wire: case D3DS::Discreet3DS::Wire:
{
// set the wireframe flag
unsigned int iWire = 1;
mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
}
case D3DS::Discreet3DS::Gouraud: case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud; break; eShading = aiShadingMode_Gouraud; break;
case D3DS::Discreet3DS::Metal : case D3DS::Discreet3DS::Metal :
@ -916,84 +963,33 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
} }
mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
if (D3DS::Discreet3DS::Wire == mat.mShading) // DIFFUSE texture
{
// set the wireframe flag
unsigned int iWire = 1;
mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
}
// texture, if there is one
if( mat.sTexDiffuse.mMapName.length() > 0) if( mat.sTexDiffuse.mMapName.length() > 0)
{ CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE);
aiString tex;
tex.Set( mat.sTexDiffuse.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
if (is_not_qnan(mat.sTexDiffuse.mTextureBlend)) // SPECULAR texture
mat.pcInstance->AddProperty<float>( &mat.sTexDiffuse.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_DIFFUSE(0));
}
if( mat.sTexSpecular.mMapName.length() > 0) if( mat.sTexSpecular.mMapName.length() > 0)
{ CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR);
aiString tex;
tex.Set( mat.sTexSpecular.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0));
if (is_not_qnan(mat.sTexSpecular.mTextureBlend)) // AMBIENT texture
mat.pcInstance->AddProperty<float>( &mat.sTexSpecular.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_SPECULAR(0));
}
if( mat.sTexOpacity.mMapName.length() > 0)
{
aiString tex;
tex.Set( mat.sTexOpacity.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0));
if (is_not_qnan(mat.sTexOpacity.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexOpacity.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_OPACITY(0));
}
if( mat.sTexEmissive.mMapName.length() > 0)
{
aiString tex;
tex.Set( mat.sTexEmissive.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0));
if (is_not_qnan(mat.sTexEmissive.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexEmissive.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_EMISSIVE(0));
}
if( mat.sTexAmbient.mMapName.length() > 0) if( mat.sTexAmbient.mMapName.length() > 0)
{ CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT);
aiString tex;
tex.Set( mat.sTexAmbient.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(0));
if (is_not_qnan(mat.sTexAmbient.mTextureBlend)) // OPACITY texture
mat.pcInstance->AddProperty<float>( &mat.sTexAmbient.mTextureBlend, 1, if( mat.sTexOpacity.mMapName.length() > 0)
AI_MATKEY_TEXBLEND_AMBIENT(0)); CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY);
}
// EMISSIVE texture
if( mat.sTexEmissive.mMapName.length() > 0)
CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE);
// BUMP texture
if( mat.sTexBump.mMapName.length() > 0) if( mat.sTexBump.mMapName.length() > 0)
{ CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT);
aiString tex;
tex.Set( mat.sTexBump.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0));
if (is_not_qnan(mat.sTexBump.mTextureBlend)) // SHININESS texture
mat.pcInstance->AddProperty<float>( &mat.sTexBump.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_HEIGHT(0));
}
if( mat.sTexShininess.mMapName.length() > 0) if( mat.sTexShininess.mMapName.length() > 0)
{ CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS);
aiString tex;
tex.Set( mat.sTexShininess.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0));
if (is_not_qnan(mat.sTexShininess.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexBump.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_SHININESS(0));
}
// store the name of the material itself, too // store the name of the material itself, too
if( mat.mName.length() > 0) if( mat.mName.length() > 0)
@ -1081,12 +1077,12 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices]; p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
for (unsigned int q = 0; q < aiSplit[p].size();++q) for (unsigned int q = 0; q < aiSplit[p].size();++q)
{ {
iIndex = aiSplit[p][q]; iIndex = aiSplit[p][q];
p_pcOut->mFaces[q].mIndices = new unsigned int[3]; p_pcOut->mFaces[q].mIndices = new unsigned int[3];
p_pcOut->mFaces[q].mNumIndices = 3; p_pcOut->mFaces[q].mNumIndices = 3;
for (unsigned int t = 0; t < 3;++t) for (unsigned int t = 0; t < 3;++t, ++iBase)
{ {
const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t]; const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
@ -1110,13 +1106,8 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
} }
} }
} }
++iBase; p_pcOut->mFaces[q].mIndices[t] = iBase;
} }
// Flip the face order
p_pcOut->mFaces[q].mIndices[0] = iBase-3;
p_pcOut->mFaces[q].mIndices[1] = iBase-2;
p_pcOut->mFaces[q].mIndices[2] = iBase-1;
} }
} }
// convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported) // convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported)
@ -1134,12 +1125,12 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]]; p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
} }
} }
// setup the number of valid vertex components // Setup the number of valid vertex components
p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c]; p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
} }
} }
// convert vertex colors (only one set supported) // Convert vertex colors (only one set supported)
if (!mesh.mVertexColors.empty()) if (!mesh.mVertexColors.empty())
{ {
p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices]; p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
@ -1153,6 +1144,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
} }
} }
} }
// Copy bones
if (!mesh.mBones.empty()) if (!mesh.mBones.empty())
{ {
p_pcOut->mNumBones = 0; p_pcOut->mNumBones = 0;
@ -1211,7 +1203,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
p_pcOut->mColors[2] = (aiColor4D*) &mesh; p_pcOut->mColors[2] = (aiColor4D*) &mesh;
avOutMeshes.push_back(p_pcOut); avOutMeshes.push_back(p_pcOut);
// if the mesh hasn't faces or vertices, there are two cases // If the mesh hasn't faces or vertices, there are two cases
// possible: 1. the model is invalid. 2. This is a dummy // possible: 1. the model is invalid. 2. This is a dummy
// helper object which we are going to remove later ... // helper object which we are going to remove later ...
if (mesh.mFaces.empty() || mesh.mPositions.empty()) if (mesh.mFaces.empty() || mesh.mPositions.empty())
@ -1264,10 +1256,10 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
p_pcOut->mFaces[iFace].mNumIndices = 3; p_pcOut->mFaces[iFace].mNumIndices = 3;
p_pcOut->mFaces[iFace].mIndices = new unsigned int[3]; p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
// copy indices (flip the face order, too) // copy indices
p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[2]; p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1]; p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[0]; p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
} }
// copy vertex bones // copy vertex bones
@ -1328,23 +1320,20 @@ void ASEImporter::BuildMaterialIndices()
// iterate through all materials and check whether we need them // iterate through all materials and check whether we need them
for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
{ {
if (mParser->m_vMaterials[iMat].bNeed) ASE::Material& mat = mParser->m_vMaterials[iMat];
if (mat.bNeed)
{ {
// convert it to the aiMaterial layout // Convert it to the aiMaterial layout
ASE::Material& mat = mParser->m_vMaterials[iMat];
ConvertMaterial(mat); ConvertMaterial(mat);
TextureTransform::ApplyScaleNOffset(mat);
++pcScene->mNumMaterials; ++pcScene->mNumMaterials;
} }
for (unsigned int iSubMat = 0; iSubMat < mParser->m_vMaterials[ for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)
iMat].avSubMaterials.size();++iSubMat)
{ {
if (mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed) ASE::Material& submat = mat.avSubMaterials[iSubMat];
if (submat.bNeed)
{ {
// convert it to the aiMaterial layout // Convert it to the aiMaterial layout
ASE::Material& mat = mParser->m_vMaterials[iMat].avSubMaterials[iSubMat]; ConvertMaterial(submat);
ConvertMaterial(mat);
TextureTransform::ApplyScaleNOffset(mat);
++pcScene->mNumMaterials; ++pcScene->mNumMaterials;
} }
} }
@ -1357,77 +1346,60 @@ void ASEImporter::BuildMaterialIndices()
unsigned int iNum = 0; unsigned int iNum = 0;
for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
{ {
if (mParser->m_vMaterials[iMat].bNeed) ASE::Material& mat = mParser->m_vMaterials[iMat];
if (mat.bNeed)
{ {
ai_assert(NULL != mParser->m_vMaterials[iMat].pcInstance); ai_assert(NULL != mat.pcInstance);
pcScene->mMaterials[iNum] = mParser->m_vMaterials[iMat].pcInstance; pcScene->mMaterials[iNum] = mat.pcInstance;
// store the internal material, too // Store the internal material, too
pcIntMaterials[iNum] = &mParser->m_vMaterials[iMat]; pcIntMaterials[iNum] = &mat;
// iterate through all meshes and search for one which is using // Iterate through all meshes and search for one which is using
// this top-level material index // this top-level material index
for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
{ {
if (ASE::Face::DEFAULT_MATINDEX == pcScene->mMeshes[iMesh]->mMaterialIndex && aiMesh* mesh = pcScene->mMeshes[iMesh];
iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3]) if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex &&
iMat == (uintptr_t)mesh->mColors[3])
{ {
pcScene->mMeshes[iMesh]->mMaterialIndex = iNum; mesh->mMaterialIndex = iNum;
pcScene->mMeshes[iMesh]->mColors[3] = NULL; mesh->mColors[3] = NULL;
} }
} }
iNum++; iNum++;
} }
for (unsigned int iSubMat = 0; iSubMat < mParser->m_vMaterials[iMat].avSubMaterials.size();++iSubMat) for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)
{ {
if (mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].bNeed) ASE::Material& submat = mat.avSubMaterials[iSubMat];
if (submat.bNeed)
{ {
ai_assert(NULL != mParser->m_vMaterials[iMat].avSubMaterials[iSubMat].pcInstance); ai_assert(NULL != submat.pcInstance);
pcScene->mMaterials[iNum] = mParser->m_vMaterials[iMat]. pcScene->mMaterials[iNum] = submat.pcInstance;
avSubMaterials[iSubMat].pcInstance;
// store the internal material, too // Store the internal material, too
pcIntMaterials[iNum] = &mParser->m_vMaterials[iMat].avSubMaterials[iSubMat]; pcIntMaterials[iNum] = &submat;
// iterate through all meshes and search for one which is using // Iterate through all meshes and search for one which is using
// this sub-level material index // this sub-level material index
for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
{ {
if (iSubMat == pcScene->mMeshes[iMesh]->mMaterialIndex && aiMesh* mesh = pcScene->mMeshes[iMesh];
iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3]) if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3])
{ {
pcScene->mMeshes[iMesh]->mMaterialIndex = iNum; mesh->mMaterialIndex = iNum;
pcScene->mMeshes[iMesh]->mColors[3] = NULL; mesh->mColors[3] = NULL;
} }
} }
iNum++; iNum++;
} }
} }
} }
// prepare for the next step
for (unsigned int hans = 0; hans < mParser->m_vMaterials.size();++hans)
TextureTransform::ApplyScaleNOffset(mParser->m_vMaterials[hans]);
// now we need to iterate through all meshes, // Dekete our temporary array
// 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; delete[] pcIntMaterials;
// finished!
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Generate normal vectors basing on smoothing groups // Generate normal vectors basing on smoothing groups
bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)
@ -1446,6 +1418,7 @@ bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)
} }
} }
} }
// The array will be reused // The array will be reused
ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh); ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
return false; return false;

View File

@ -634,6 +634,12 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
mat.mSpecularExponent *= 15; mat.mSpecularExponent *= 15;
continue; continue;
} }
// two-sided material
if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
{
mat.mTwoSided = true;
continue;
}
// material shininess strength // material shininess strength
if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22)) if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
{ {
@ -1387,7 +1393,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
continue; continue;
} }
// Number of vertex colors in the mesh // Number of vertex colors in the mesh
if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,14)) if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
{ {
ParseLV4MeshLong(iNumCVertices); ParseLV4MeshLong(iNumCVertices);
continue; continue;
@ -1877,44 +1883,38 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
{ {
AI_ASE_PARSER_INIT(); AI_ASE_PARSER_INIT();
// allocate enough storage for the normals // Allocate enough storage for the normals
sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f )); sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
unsigned int iIndex = 0, faceIdx = 0xffffffff; unsigned int index, faceIdx = 0xffffffff;
// ******************************************************************** // Smooth the vertex and face normals together. The result
// just smooth both vertex and face normals together, so it will still // will be edgy then, but otherwise everything would be soft ...
// work if one one of the two is missing. If one of the two is invalid
// the result will be partly corrected by this trick.
// ********************************************************************
while (true) while (true)
{ {
if ('*' == *filePtr) if ('*' == *filePtr)
{ {
++filePtr; ++filePtr;
if (0xffffffff != faceIdx && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) if (faceIdx != 0xffffffff && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17))
{ {
aiVector3D vNormal; aiVector3D vNormal;
ParseLV4MeshFloatTriple(&vNormal.x,iIndex); ParseLV4MeshFloatTriple(&vNormal.x,index);
if (iIndex == sMesh.mFaces[faceIdx].mIndices[0]) // Make sure we assign it to the correct face
{ const ASE::Face& face = sMesh.mFaces[faceIdx];
iIndex = 0; if (index == face.mIndices[0])
} index = 0;
else if (iIndex == sMesh.mFaces[faceIdx].mIndices[1]) else if (index == face.mIndices[1])
{ index = 1;
iIndex = 1; else if (index == face.mIndices[2])
} index = 2;
else if (iIndex == sMesh.mFaces[faceIdx].mIndices[2])
{
iIndex = 2;
}
else else
{ {
LogWarning("Normal index doesn't fit to face index"); DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
continue; continue;
} }
// We'll renormalize later // We'll renormalize later
sMesh.mNormals[faceIdx*3 + iIndex] += vNormal; sMesh.mNormals[faceIdx*3+index] += vNormal;
continue; continue;
} }
if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) if (TokenMatch(filePtr,"MESH_FACENORMAL",15))
@ -1922,15 +1922,14 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
aiVector3D vNormal; aiVector3D vNormal;
ParseLV4MeshFloatTriple(&vNormal.x,faceIdx); ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
if (iIndex >= sMesh.mFaces.size()) if (faceIdx >= sMesh.mFaces.size())
{ {
LogWarning("Face normal index is too large"); DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
faceIdx = 0xffffffff;
continue; continue;
} }
sMesh.mNormals[faceIdx*3] += vNormal;
sMesh.mNormals[faceIdx*3 +1] += vNormal; // We'll renormalize later
sMesh.mNormals[faceIdx*3 +2] += vNormal; sMesh.mNormals[faceIdx*3] += vNormal;
continue; continue;
} }
} }
@ -2037,7 +2036,7 @@ void Parser::ParseLV4MeshFace(ASE::Face& out)
return; return;
} }
// parse smoothing groups until we don_t anymore see commas // Parse smoothing groups until we don't anymore see commas
// FIX: There needn't always be a value, sad but true // FIX: There needn't always be a value, sad but true
while (true) while (true)
{ {

View File

@ -82,6 +82,7 @@ struct Material : public D3DS::Material
//! Can we remove this material? //! Can we remove this material?
bool bNeed; bool bNeed;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file face */ /** Helper structure to represent an ASE file face */
struct Face : public FaceWithSmoothingGroup struct Face : public FaceWithSmoothingGroup
@ -175,12 +176,6 @@ struct Animation
, mPositionType (TRACK) , mPositionType (TRACK)
{} {}
/** ONLY ONE OF THESE SETS IS USED
*
* Bezier and TCB channels are converted to a normal
* trac later.
*/
//! List of track rotation keyframes //! List of track rotation keyframes
std::vector< aiQuatKey > akeyRotations; std::vector< aiQuatKey > akeyRotations;

View File

@ -107,12 +107,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_BUILD_BOOST_WORKAROUND #ifdef ASSIMP_BUILD_BOOST_WORKAROUND
# include "../include/BoostWorkaround/boost/scoped_ptr.hpp" # include "../include/BoostWorkaround/boost/scoped_ptr.hpp"
# include "../include/BoostWorkaround/boost/scoped_array.hpp"
# include "../include/BoostWorkaround/boost/format.hpp" # include "../include/BoostWorkaround/boost/format.hpp"
# include "../include/BoostWorkaround/boost/common_factor_rt.hpp" # include "../include/BoostWorkaround/boost/common_factor_rt.hpp"
#else #else
# include <boost/scoped_ptr.hpp> # include <boost/scoped_ptr.hpp>
# include <boost/scoped_array.hpp>
# include <boost/format.hpp> # include <boost/format.hpp>
# include <boost/math/common_factor_rt.hpp> # include <boost/math/common_factor_rt.hpp>

View File

@ -110,7 +110,7 @@ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler,
if (pStream.get() ) if (pStream.get() )
{ {
// read 200 characters from the file // read 200 characters from the file
boost::scoped_ptr<char> _buffer (new char[searchBytes]); boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]);
char* buffer = _buffer.get(); char* buffer = _buffer.get();
unsigned int read = (unsigned int)pStream->Read(buffer,1,searchBytes); unsigned int read = (unsigned int)pStream->Read(buffer,1,searchBytes);

View File

@ -0,0 +1,175 @@
/*
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 GenUVCoords step */
#include "AssimpPCH.h"
#include "ComputeUVMappingProcess.h"
#include "ProcessHelper.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ComputeUVMappingProcess::ComputeUVMappingProcess()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ComputeUVMappingProcess::~ComputeUVMappingProcess()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
{
return (pFlags & aiProcess_GenUVCoords) != 0;
}
// ------------------------------------------------------------------------------------------------
unsigned int ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,aiAxis axis)
{
DefaultLogger::get()->error("Mapping type currently not implemented");
return 0;
}
// ------------------------------------------------------------------------------------------------
unsigned int ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,aiAxis axis)
{
DefaultLogger::get()->error("Mapping type currently not implemented");
return 0;
}
// ------------------------------------------------------------------------------------------------
unsigned int ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,aiAxis axis)
{
DefaultLogger::get()->error("Mapping type currently not implemented");
return 0;
}
// ------------------------------------------------------------------------------------------------
unsigned int ComputeUVMappingProcess::ComputeBoxMapping(aiMesh* mesh)
{
DefaultLogger::get()->error("Mapping type currently not implemented");
return 0;
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("GenUVCoordsProcess begin");
char buffer[1024];
/* Iterate through all materials and search for non-UV mapped textures
*/
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{
aiMaterial* mat = pScene->mMaterials[i];
for (unsigned int a = 0; a < mat->mNumProperties;++a)
{
aiMaterialProperty* prop = mat->mProperties[a];
if (!::strcmp( prop->mKey.data, "$tex.mapping"))
{
aiTextureMapping mapping = *((aiTextureMapping*)prop->mData);
if (aiTextureMapping_UV != mapping)
{
if (!DefaultLogger::isNullLogger())
{
sprintf(buffer, "Found non-UV mapped texture (%s,%i). Mapping type: %s",
TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
MappingTypeToString(mapping));
DefaultLogger::get()->info(buffer);
}
aiAxis axis;
// Get further properties - currently only the major axis
for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
{
aiMaterialProperty* prop2 = mat->mProperties[a2];
if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
continue;
if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis"))
{
axis = *((aiAxis*)prop2->mData);
break;
}
}
/* We have found a non-UV mapped texture. Now
* we need to find all meshes using this material
* that we can compute UV channels for them.
*/
for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
{
aiMesh* mesh = pScene->mMeshes[m];
if (mesh->mMaterialIndex != i) continue;
switch (mapping)
{
case aiTextureMapping_SPHERE:
ComputeSphereMapping(mesh,axis);
break;
case aiTextureMapping_CYLINDER:
ComputeCylinderMapping(mesh,axis);
break;
case aiTextureMapping_PLANE:
ComputePlaneMapping(mesh,axis);
break;
case aiTextureMapping_BOX:
ComputeBoxMapping(mesh);
break;
}
}
}
}
}
}
DefaultLogger::get()->debug("GenUVCoordsProcess finished");
}

View File

@ -0,0 +1,125 @@
/*
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 a post processing step to compute UV coordinates
from abstract mappings, such as box or spherical*/
#ifndef AI_COMPUTEUVMAPPING_H_INC
#define AI_COMPUTEUVMAPPING_H_INC
#include "BaseProcess.h"
#include "../include/aiMesh.h"
class ComputeUVMappingTest;
namespace Assimp
{
// ---------------------------------------------------------------------------
/** ComputeUVMappingProcess - converts special mappings, such as spherical,
* cylindrical or boxed to proper UV coordinates for rendering.
*/
class ASSIMP_API ComputeUVMappingProcess : public BaseProcess
{
friend class Importer;
friend class ::ComputeUVMappingTest; // grant the unit test full access to us
protected:
/** Constructor to be privately used by Importer */
ComputeUVMappingProcess();
/** Destructor, private as well */
~ComputeUVMappingProcess();
public:
// -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag field.
* @param pFlags The processing flags the importer was called with. A bitwise
* combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, false if not.
*/
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene);
protected:
// -------------------------------------------------------------------
/** Computes spherical UV coordinates for a mesh
*
* @param mesh Mesh to be processed
* @param axis Main axis
* @return Index of the newly generated UV channel
*/
unsigned int ComputeSphereMapping(aiMesh* mesh,aiAxis axis);
// -------------------------------------------------------------------
/** Computes cylindrical UV coordinates for a mesh
*
* @param mesh Mesh to be processed
* @param axis Main axis
* @return Index of the newly generated UV channel
*/
unsigned int ComputeCylinderMapping(aiMesh* mesh,aiAxis axis);
// -------------------------------------------------------------------
/** Computes planar UV coordinates for a mesh
*
* @param mesh Mesh to be processed
* @param axis Main axis
* @return Index of the newly generated UV channel
*/
unsigned int ComputePlaneMapping(aiMesh* mesh,aiAxis axis);
// -------------------------------------------------------------------
/** Computes cubic UV coordinates for a mesh
*
* @param mesh Mesh to be processed
* @return Index of the newly generated UV channel
*/
unsigned int ComputeBoxMapping(aiMesh* mesh);
};
} // end of namespace Assimp
#endif // AI_COMPUTEUVMAPPING_H_INC

View File

@ -141,6 +141,10 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
ProcessMesh( pScene->mMeshes[a]); ProcessMesh( pScene->mMeshes[a]);
// process all materials - we need to adjust UV transformations
for( unsigned int a = 0; a < pScene->mNumMaterials; a++)
ProcessMaterial( pScene->mMaterials[a]);
// transform all animation channels affecting the root node as well // transform all animation channels affecting the root node as well
for( unsigned int a = 0; a < pScene->mNumAnimations; a++) for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
{ {
@ -155,6 +159,25 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
DefaultLogger::get()->debug("ConvertToLHProcess finished"); DefaultLogger::get()->debug("ConvertToLHProcess finished");
} }
// ------------------------------------------------------------------------------------------------
// Converts a single material to left handed coordinates.
void ConvertToLHProcess::ProcessMaterial (aiMaterial* mat)
{
for (unsigned int a = 0; a < mat->mNumProperties;++a)
{
aiMaterialProperty* prop = mat->mProperties[a];
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))
{
ai_assert( prop->mDataLength >= sizeof(aiUVTransform));
aiUVTransform* uv = (aiUVTransform*)prop->mData;
// just flip it, that's everything
uv->mTranslation.y *= -1.f;
uv->mRotation *= -1.f;
}
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts a single mesh to left handed coordinates. // Converts a single mesh to left handed coordinates.
void ConvertToLHProcess::ProcessMesh( aiMesh* pMesh) void ConvertToLHProcess::ProcessMesh( aiMesh* pMesh)

View File

@ -108,6 +108,13 @@ protected:
*/ */
void ProcessMesh( aiMesh* pMesh); void ProcessMesh( aiMesh* pMesh);
// -------------------------------------------------------------------
/** Converts a single material to left handed coordinates.
* This simply means all UV offsets are inverted.
* @param mat The material to convert.
*/
void ProcessMaterial (aiMaterial* mat);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Converts the given animation to LH coordinates. /** Converts the given animation to LH coordinates.
* The rotation and translation keys are transformed, the scale keys * The rotation and translation keys are transformed, the scale keys

View File

@ -108,6 +108,7 @@ void FindDegeneratesProcess::Execute( aiScene* pScene)
// application attemps to access this data. // application attemps to access this data.
face.mIndices[face.mNumIndices] = 0xdeadbeef; face.mIndices[face.mNumIndices] = 0xdeadbeef;
if(first) if(first)
{ {
++deg; ++deg;

View File

@ -284,7 +284,16 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
{ {
bool ret = false; bool ret = false;
std::vector<bool> dirtyMask; std::vector<bool> dirtyMask(pMesh->mNumVertices,true);
// Ignore elements that are not referenced by vertices.
// (they are, for example, caused by the FindDegenerates step)
for (unsigned int m = 0; m < pMesh->mNumFaces;++m)
{
const aiFace& f = pMesh->mFaces[m];
for (unsigned int i = 0; i < f.mNumIndices;++i)
dirtyMask[f.mIndices[i]] = false;
}
// process vertex positions // process vertex positions
if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask)) if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask))
@ -311,9 +320,7 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
// -- we don't validate vertex colors, it's difficult to say whether // -- we don't validate vertex colors, it's difficult to say whether
// they are invalid or not. // they are invalid or not.
// normals and tangents are undefined for point and line faces. // Normals and tangents are undefined for point and line faces.
// we generate a small lookup table in which we mark all
// indices into the normals/tangents array that MAY be invalid
if (pMesh->mNormals || pMesh->mTangents) if (pMesh->mNormals || pMesh->mTangents)
{ {
if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes || if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
@ -322,8 +329,7 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes || if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes) aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes)
{ {
// we need the lookup table // We need to update the lookup-table
dirtyMask.resize(pMesh->mNumVertices,false);
for (unsigned int m = 0; m < pMesh->mNumFaces;++m) for (unsigned int m = 0; m < pMesh->mNumFaces;++m)
{ {
const aiFace& f = pMesh->mFaces[m]; const aiFace& f = pMesh->mFaces[m];
@ -334,27 +340,29 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
else if (1 == f.mNumIndices)dirtyMask[f.mIndices[0]] = true; else if (1 == f.mNumIndices)dirtyMask[f.mIndices[0]] = true;
} }
} }
// Normals, tangents and bitangents are undefined for
// the whole mesh (and should not even be there)
else return ret; else return ret;
} }
// process mesh normals // Process mesh normals
if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices, if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
"normals",dirtyMask,true,false)) "normals",dirtyMask,true,false))
ret = true; ret = true;
// process mesh tangents // Process mesh tangents
if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices, if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,
"tangents",dirtyMask)) "tangents",dirtyMask))
{ {
delete[] pMesh->mBitangents; pMesh->mBitangents = NULL; delete[] pMesh->mTangents; pMesh->mTangents = NULL;
ret = true; ret = true;
} }
// process mesh bitangents // Process mesh bitangents
if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices, if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,
"bitangents",dirtyMask)) "bitangents",dirtyMask))
{ {
delete[] pMesh->mTangents; pMesh->mTangents = NULL; delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
ret = true; ret = true;
} }
} }

View File

@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// http://www.azillionmonkeys.com/qed/hash.html // http://www.azillionmonkeys.com/qed/hash.html
// (incremental version of the hashing function) // (incremental version of the hashing function)
// (stdint.h should have been been included here) // (stdint.h should have been been included here)
// ------------------------------------------------------------------------------------------------
#undef get16bits #undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)

View File

@ -429,20 +429,6 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
// lightmap settings to the last texture. // lightmap settings to the last texture.
if (cnt && matFlags & AI_IRRMESH_MAT_lightmap) if (cnt && matFlags & AI_IRRMESH_MAT_lightmap)
{ {
static const char* PropArray[4] =
{
AI_MATKEY_TEXBLEND_DIFFUSE(0),
AI_MATKEY_TEXBLEND_DIFFUSE(1),
AI_MATKEY_TEXBLEND_DIFFUSE(2),
AI_MATKEY_TEXBLEND_DIFFUSE(3)
};
static const char* PropArray2[4] =
{
AI_MATKEY_TEXOP_DIFFUSE(0),
AI_MATKEY_TEXOP_DIFFUSE(1),
AI_MATKEY_TEXOP_DIFFUSE(2),
AI_MATKEY_TEXOP_DIFFUSE(3)
};
float f = 1.f; float f = 1.f;
// Additive lightmap? // Additive lightmap?
@ -460,8 +446,8 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
{ {
f = 4.f; f = 4.f;
} }
mat->AddProperty( &f, 1, PropArray [cnt-1]); mat->AddProperty( &f, 1, AI_MATKEY_TEXBLEND_DIFFUSE(cnt-1));
mat->AddProperty( &op,1, PropArray2 [cnt-1]); mat->AddProperty( &op,1, AI_MATKEY_TEXOP_DIFFUSE(cnt-1));
} }
return mat; return mat;
@ -600,13 +586,28 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
if (curMat) if (curMat)
{ {
DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please"); DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
delete curMat; delete curMat;curMat = NULL;
} }
curMat = ParseMaterial(curMatFlags); curMat = ParseMaterial(curMatFlags);
} }
/* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices")) /* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices"))
{ {
int num = reader->getAttributeValueAsInt("vertexCount"); int num = reader->getAttributeValueAsInt("vertexCount");
if (!num)
{
// This is possible ... remove the mesh from the list
// and skip further reading
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
delete curMat;curMat = NULL;
curMesh = NULL;
textMeaning = 0;
continue;
}
curVertices.reserve (num); curVertices.reserve (num);
curNormals.reserve (num); curNormals.reserve (num);
curColors.reserve (num); curColors.reserve (num);
@ -648,6 +649,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
} }
else if (ASSIMP_stricmp("standard", t)) else if (ASSIMP_stricmp("standard", t))
{ {
delete curMat;
DefaultLogger::get()->warn("IRRMESH: Unknown vertex format"); DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
} }
else vertexFormat = 0; else vertexFormat = 0;
@ -655,8 +657,11 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
} }
else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) else if (!ASSIMP_stricmp(reader->getNodeName(),"indices"))
{ {
if (curVertices.empty()) if (curVertices.empty() && curMat)
{
delete curMat;
throw new ImportErrorException("IRRMESH: indices must come after vertices"); throw new ImportErrorException("IRRMESH: indices must come after vertices");
}
textMeaning = 2; textMeaning = 2;
@ -665,6 +670,23 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// allocate storage for all faces // allocate storage for all faces
curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount"); curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
if (!curMesh->mNumVertices)
{
// This is possible ... remove the mesh from the list
// and skip further reading
DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
// mesh - away
delete curMesh; curMesh = NULL;
// material - away
delete curMat;curMat = NULL;
textMeaning = 0;
continue;
}
if (curMesh->mNumVertices % 3) if (curMesh->mNumVertices % 3)
{ {
DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3"); DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
@ -888,7 +910,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}; };
} }
// end of the last buffer. A material and a mesh should be there // End of the last buffer. A material and a mesh should be there
if (curMat || curMesh) if (curMat || curMesh)
{ {
if ( !curMat || !curMesh) if ( !curMat || !curMesh)

View File

@ -189,6 +189,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS #ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS
# include "SortByPTypeProcess.h" # include "SortByPTypeProcess.h"
#endif #endif
#ifndef AI_BUILD_NO_GENUVCOORDS_PROCESS
# include "ComputeUVMappingProcess.h"
#endif
#ifndef AI_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
# include "TextureTransform.h"
#endif
using namespace Assimp; using namespace Assimp;
@ -290,7 +297,7 @@ Importer::Importer() :
mImporter.push_back( new ColladaLoader()); mImporter.push_back( new ColladaLoader());
#endif #endif
// add an instance of each post processing step here in the order // Add an instance of each post processing step here in the order
// of sequence it is executed. steps that are added here are not validated - // of sequence it is executed. steps that are added here are not validated -
// as RegisterPPStep() does - all dependencies must be there. // as RegisterPPStep() does - all dependencies must be there.
mPostProcessingSteps.reserve(25); mPostProcessingSteps.reserve(25);
@ -310,6 +317,17 @@ Importer::Importer() :
#endif #endif
#ifndef AI_BUILD_NO_GENUVCOORDS_PROCESS
mPostProcessingSteps.push_back( new ComputeUVMappingProcess());
#endif
#ifndef AI_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
mPostProcessingSteps.push_back( new TextureTransformStep());
#endif
#if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS) #if (!defined AI_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess()); mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
#endif #endif
@ -371,6 +389,9 @@ Importer::Importer() :
mPostProcessingSteps.push_back( new ImproveCacheLocalityProcess()); mPostProcessingSteps.push_back( new ImproveCacheLocalityProcess());
#endif #endif
// allocate a SharedPostProcessInfo object and store pointers to it // allocate a SharedPostProcessInfo object and store pointers to it
// in all post-process steps in the list. // in all post-process steps in the list.
mPPShared = new SharedPostProcessInfo(); mPPShared = new SharedPostProcessInfo();
@ -412,7 +433,9 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
{ {
ai_assert(NULL != pImp); ai_assert(NULL != pImp);
// check whether we would have two loaders for the same file extension now // Check whether we would have two loaders for the same file extension now
// This is absolutely OK, but we should warn the developer of the new
// loader that his code will propably never be called.
std::string st; std::string st;
pImp->GetExtensionList(st); pImp->GetExtensionList(st);
@ -423,15 +446,14 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
{ {
if (IsExtensionSupported(std::string(sz))) if (IsExtensionSupported(std::string(sz)))
{ {
DefaultLogger::get()->error(std::string( "The file extension " ) + sz + " is already in use"); DefaultLogger::get()->warn(std::string( "The file extension " ) + sz + " is already in use");
return AI_FAILURE;
} }
sz = ::strtok(NULL,";"); sz = ::strtok(NULL,";");
} }
#endif #endif
// add the loader // add the loader
this->mImporter.push_back(pImp); mImporter.push_back(pImp);
DefaultLogger::get()->info("Registering custom importer: " + st); DefaultLogger::get()->info("Registering custom importer: " + st);
return AI_SUCCESS; return AI_SUCCESS;
} }
@ -729,7 +751,7 @@ const std::string& Importer::GetPropertyString(const char* szName,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
{ {
iScene += sizeof(aiNode); iScene += sizeof(aiNode);
iScene += sizeof(unsigned int) * pcNode->mNumMeshes; iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
@ -816,6 +838,10 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
} }
in.total += in.animations; in.total += in.animations;
// add all cameras and all lights
in.total += in.cameras = sizeof(aiCamera) * mScene->mNumCameras;
in.total += in.lights = sizeof(aiLight) * mScene->mNumLights;
// add all nodes // add all nodes
AddNodeWeight(in.nodes,mScene->mRootNode); AddNodeWeight(in.nodes,mScene->mRootNode);
in.total += in.nodes; in.total += in.nodes;
@ -832,6 +858,5 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
} }
} }
in.total += in.materials; in.total += in.materials;
return;
} }

View File

@ -45,11 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssimpPCH.h" #include "AssimpPCH.h"
// internal headers // Internal headers
#include "LWOLoader.h" #include "LWOLoader.h"
#include "MaterialSystem.h"
#include "ByteSwap.h"
using namespace Assimp; using namespace Assimp;

View File

@ -62,6 +62,7 @@ namespace LWO {
#define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L','W','O','B') #define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L','W','O','B')
#define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L','W','O','2') #define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L','W','O','2')
#define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L','X','O','B')
// chunks specific to the LWOB format // chunks specific to the LWOB format
#define AI_LWO_SRFS AI_IFF_FOURCC('S','R','F','S') #define AI_LWO_SRFS AI_IFF_FOURCC('S','R','F','S')
@ -178,6 +179,7 @@ namespace LWO {
#define AI_LWO_AVAL AI_IFF_FOURCC('A','V','A','L') #define AI_LWO_AVAL AI_IFF_FOURCC('A','V','A','L')
#define AI_LWO_GVAL AI_IFF_FOURCC('G','V','A','L') #define AI_LWO_GVAL AI_IFF_FOURCC('G','V','A','L')
#define AI_LWO_BLOK AI_IFF_FOURCC('B','L','O','K') #define AI_LWO_BLOK AI_IFF_FOURCC('B','L','O','K')
#define AI_LWO_VCOL AI_IFF_FOURCC('V','C','O','L')
/* texture layer */ /* texture layer */
#define AI_LWO_TYPE AI_IFF_FOURCC('T','Y','P','E') #define AI_LWO_TYPE AI_IFF_FOURCC('T','Y','P','E')
@ -236,10 +238,13 @@ namespace LWO {
/* VMAP types */ /* VMAP types */
#define AI_LWO_TXUV AI_IFF_FOURCC('T','X','U','V') #define AI_LWO_TXUV AI_IFF_FOURCC('T','X','U','V')
#define AI_LWO_RGB AI_IFF_FOURCC(' ','R','G','B') #define AI_LWO_RGB AI_IFF_FOURCC('R','G','B',' ')
#define AI_LWO_RGBA AI_IFF_FOURCC('R','G','B','A') #define AI_LWO_RGBA AI_IFF_FOURCC('R','G','B','A')
#define AI_LWO_WGHT AI_IFF_FOURCC('W','G','H','T') #define AI_LWO_WGHT AI_IFF_FOURCC('W','G','H','T')
// MODO extension - per-vertex normal vectors
#define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M')
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a face in a LWO file /** \brief Data structure for a face in a LWO file
@ -318,15 +323,11 @@ struct VColorChannel : public VMapEntry
register unsigned int m = num*dims; register unsigned int m = num*dims;
rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
rawData.resize(m,0.f); rawData.resize(m);
for (aiColor4D* p = (aiColor4D*)&rawData[0]; p < (aiColor4D*)&rawData[m-1]; ++p)
*p = aiColor4D();
for (std::vector<float>::iterator it = rawData.begin(), end = rawData.end();
it != end;++it )
{
for (unsigned int i = 0; i< 3;++i,++it)
*it = 0.f;
*it = 1.f;
}
abAssigned.resize(num,false); abAssigned.resize(num,false);
} }
}; };
@ -351,6 +352,15 @@ struct WeightChannel : public VMapEntry
{} {}
}; };
// ---------------------------------------------------------------------------
/** \brief Represents a vertex-normals channel (MODO extension)
*/
struct NormalChannel : public VMapEntry
{
NormalChannel()
: VMapEntry(3)
{}
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Data structure for a LWO file texture /** \brief Data structure for a LWO file texture
@ -515,8 +525,10 @@ struct Surface
, mColorHighlights (0.f) , mColorHighlights (0.f)
, mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing , mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing
, mVCMap ("") , mVCMap ("")
, mVCMapType (AI_LWO_RGBA)
, mIOR (1.f) // vakuum , mIOR (1.f) // vakuum
, mBumpIntensity (1.f) , mBumpIntensity (1.f)
, mWireframe (false)
{} {}
//! Name of the surface //! Name of the surface
@ -537,6 +549,7 @@ struct Surface
//! Vertex color map to be used to color the surface //! Vertex color map to be used to color the surface
std::string mVCMap; std::string mVCMap;
uint32_t mVCMapType;
//! Names of the special shaders to be applied to the surface //! Names of the special shaders to be applied to the surface
ShaderList mShaders; ShaderList mShaders;
@ -554,6 +567,9 @@ struct Surface
//! Bump intensity scaling //! Bump intensity scaling
float mBumpIntensity; float mBumpIntensity;
//! Wireframe flag
bool mWireframe;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -606,6 +622,9 @@ struct Layer
/** UV channel list from the file */ /** UV channel list from the file */
UVChannelList mUVChannels; UVChannelList mUVChannels;
/** Normal vector channel from the file */
NormalChannel mNormals;
/** Temporary face list from the file*/ /** Temporary face list from the file*/
FaceList mFaces; FaceList mFaces;

View File

@ -79,11 +79,10 @@ bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
if (extension.length() < 4)return false; if (extension.length() < 4)return false;
if (extension[0] != '.')return false; if (extension[0] != '.')return false;
if (extension[1] != 'l' && extension[1] != 'L')return false; return ! (extension[1] != 'l' && extension[1] != 'L' ||
if (extension[2] != 'w' && extension[2] != 'W')return false; extension[2] != 'w' && extension[2] != 'W' &&
if (extension[3] != 'o' && extension[3] != 'O')return false; extension[2] != 'x' && extension[2] != 'X' ||
extension[3] != 'o' && extension[3] != 'O');
return true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -151,11 +150,29 @@ void LWOImporter::InternReadFile( const std::string& pFile,
LoadLWOBFile(); LoadLWOBFile();
} }
// new lightwave format // New lightwave format
else if (AI_LWO_FOURCC_LWO2 == fileType) else if (AI_LWO_FOURCC_LWO2 == fileType)
{ {
DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)"); DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)");
}
// MODO file format
else if (AI_LWO_FOURCC_LXOB == fileType)
{
DefaultLogger::get()->info("LWO file format: LXOB (Modo)");
}
// we don't know this format
else
{
char szBuff[5];
szBuff[0] = (char)(fileType >> 24u);
szBuff[1] = (char)(fileType >> 16u);
szBuff[2] = (char)(fileType >> 8u);
szBuff[3] = (char)(fileType);
throw new ImportErrorException(std::string("Unknown LWO sub format: ") + szBuff);
}
if (AI_LWO_FOURCC_LWOB != fileType)
{
mIsLWO2 = true; mIsLWO2 = true;
LoadLWO2File(); LoadLWO2File();
@ -172,17 +189,6 @@ void LWOImporter::InternReadFile( const std::string& pFile,
} }
} }
// we don't know this format
else
{
char szBuff[5];
szBuff[0] = (char)(fileType >> 24u);
szBuff[1] = (char)(fileType >> 16u);
szBuff[2] = (char)(fileType >> 8u);
szBuff[3] = (char)(fileType);
throw new ImportErrorException(std::string("Unknown LWO sub format: ") + szBuff);
}
// now, as we have loaded all data, we can resolve cross-referenced tags and clips // now, as we have loaded all data, we can resolve cross-referenced tags and clips
ResolveTags(); ResolveTags();
ResolveClips(); ResolveClips();
@ -249,7 +255,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
mesh->mNumVertices += layer.mFaces[*it].mNumIndices; mesh->mNumVertices += layer.mFaces[*it].mNumIndices;
} }
aiVector3D* pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; aiVector3D *nrm = NULL, * pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces]; aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces];
mesh->mMaterialIndex = i; mesh->mMaterialIndex = i;
@ -276,9 +282,13 @@ void LWOImporter::InternReadFile( const std::string& pFile,
pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices]; pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices];
// LightWave doesn't support more than 2 UV components // LightWave doesn't support more than 2 UV components
// so we can directly setup this value
mesh->mNumUVComponents[0] = 2; mesh->mNumUVComponents[0] = 2;
} }
if (layer.mNormals.name.length())
nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS]; aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS];
for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui)
{ {
@ -320,11 +330,24 @@ void LWOImporter::InternReadFile( const std::string& pFile,
pp++; pp++;
} }
// process normals (MODO extension)
if (nrm)
{
*nrm++ = ((aiVector3D*)&layer.mNormals.rawData[0])[idx];
}
// process vertex colors // process vertex colors
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w) for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w)
{ {
if (0xffffffff == vVColorIndices[w])break; if (0xffffffff == vVColorIndices[w])break;
*(pvVC[w])++ = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx]; *pvVC[w] = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx];
// If a RGB color map is explicitly requested delete the
// alpha channel - it could theoretically be != 1.
if(_mSurfaces[i].mVCMapType == AI_LWO_RGB)
pvVC[w]->a = 1.f;
pvVC[w]++;
} }
#if 0 #if 0
@ -343,16 +366,19 @@ void LWOImporter::InternReadFile( const std::string& pFile,
pf++; pf++;
} }
// compute normal vectors for the mesh - we can't use our GenSmoothNormal- if (!mesh->mNormals)
// Step here since it wouldn't handle smoothing groups correctly for LWO. {
// So we use a separate implementation. // Compute normal vectors for the mesh - we can't use our GenSmoothNormal-
ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]); // Step here since it wouldn't handle smoothing groups correctly for LWO.
// So we use a separate implementation.
ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]);
}
else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there");
++p; ++p;
} }
} }
// generate nodes to render the mesh. Store the parent index // Generate nodes to render the mesh. Store the parent index
// in the mParent member of the nodes // in the mParent member of the nodes
aiNode* pcNode = new aiNode(); aiNode* pcNode = new aiNode();
apcNodes.push_back(pcNode); apcNodes.push_back(pcNode);
@ -367,7 +393,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
if (apcNodes.empty() || apcMeshes.empty()) if (apcNodes.empty() || apcMeshes.empty())
throw new ImportErrorException("LWO: No meshes loaded"); throw new ImportErrorException("LWO: No meshes loaded");
// the RemoveRedundantMaterials step will clean this up later // The RemoveRedundantMaterials step will clean this up later
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()]; pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()];
for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat)
{ {
@ -510,7 +536,6 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector<aiNode*>& apcNodes) void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector<aiNode*>& apcNodes)
{ {
parent -= 1;
for (uintptr_t i = 0; i < (uintptr_t)apcNodes.size();++i) for (uintptr_t i = 0; i < (uintptr_t)apcNodes.size();++i)
{ {
if (i == parent)continue; if (i == parent)continue;
@ -706,10 +731,15 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
uint32_t type = GetU4(); uint32_t type = GetU4();
if (type != AI_LWO_FACE) // Determine the type of the polygons
switch (type)
{ {
DefaultLogger::get()->warn("LWO2: Only POLS.FACE chunks are supported."); case AI_LWO_PTCH:
return; case AI_LWO_FACE:
break;
default:
DefaultLogger::get()->warn("LWO2: Unsupported polygon type (PTCH and FACE are supported)");
} }
// first find out how many faces and vertices we'll finally need // first find out how many faces and vertices we'll finally need
@ -829,19 +859,26 @@ VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPol
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <class T> template <class T>
void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx) inline void CreateNewEntry(T& chan, unsigned int srcIdx)
{
if (!chan.name.length())return;
chan.abAssigned[srcIdx] = true;
chan.abAssigned.resize(chan.abAssigned.size()+1,false);
for (unsigned int a = 0; a < chan.dims;++a)
chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]);
}
// ------------------------------------------------------------------------------------------------
template <class T>
inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx)
{ {
for (typename std::vector< T >::iterator for (typename std::vector< T >::iterator
it = list.begin(), end = list.end(); it = list.begin(), end = list.end();
it != end;++it) it != end;++it)
{ {
T& chan = *it; CreateNewEntry( *it, srcIdx );
chan.abAssigned[srcIdx] = true;
chan.abAssigned.resize(chan.abAssigned.size()+1,false);
for (unsigned int a = 0; a < chan.dims;++a)
chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]);
} }
} }
@ -911,7 +948,24 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
} }
base = FindEntry(mCurLayer->mVColorChannels,name,perPoly); base = FindEntry(mCurLayer->mVColorChannels,name,perPoly);
break; break;
default: return;
case AI_LWO_MODO_NORM:
/* This is a non-standard extension chunk used by Luxology's MODO.
* It stores per-vertex normals. This VMAP exists just once, has
* 3 dimensions and is btw extremely beautiful.
*/
if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length())
return;
DefaultLogger::get()->info("Non-standard extension: MODO VMAP.NORM.vert_normals");
mCurLayer->mNormals.name = name;
base = & mCurLayer->mNormals;
break;
default:
return;
}; };
base->Allocate((unsigned int)mCurLayer->mTempPoints.size()); base->Allocate((unsigned int)mCurLayer->mTempPoints.size());
@ -946,20 +1000,22 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
if (polyIdx >= numFaces) if (polyIdx >= numFaces)
{ {
DefaultLogger::get()->warn("LWO2: VMAD polygon index is out of range"); DefaultLogger::get()->warn("LWO2: VMAD polygon index is out of range");
mFileBuffer += base->dims*4;continue; mFileBuffer += base->dims*4;
continue;
} }
LWO::Face& src = list[polyIdx]; LWO::Face& src = list[polyIdx];
refList.resize(refList.size()+src.mNumIndices, 0xffffffff);
// generate new vertex positions // generate a new unique vertex for the corresponding index - but only
// if we can find the index in the face
for (unsigned int i = 0; i < src.mNumIndices;++i) for (unsigned int i = 0; i < src.mNumIndices;++i)
{ {
register unsigned int srcIdx = src.mIndices[i]; register unsigned int srcIdx = src.mIndices[i];
if (idx == srcIdx) if (idx != srcIdx)continue;
{
idx = (unsigned int)pointList.size(); refList.resize(refList.size()+1, 0xffffffff);
}
idx = (unsigned int)pointList.size();
src.mIndices[i] = (unsigned int)pointList.size(); src.mIndices[i] = (unsigned int)pointList.size();
// store the index of the new vertex in the old vertex // store the index of the new vertex in the old vertex
@ -971,6 +1027,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
CreateNewEntry(mCurLayer->mVColorChannels, srcIdx ); CreateNewEntry(mCurLayer->mVColorChannels, srcIdx );
CreateNewEntry(mCurLayer->mUVChannels, srcIdx ); CreateNewEntry(mCurLayer->mUVChannels, srcIdx );
CreateNewEntry(mCurLayer->mWeightChannels, srcIdx ); CreateNewEntry(mCurLayer->mWeightChannels, srcIdx );
CreateNewEntry(mCurLayer->mNormals, srcIdx );
} }
} }
} }

View File

@ -100,7 +100,7 @@ protected:
*/ */
void GetExtensionList(std::string& append) void GetExtensionList(std::string& append)
{ {
append.append("*.lwo"); append.append("*.lwo;*.lxo");
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -257,12 +257,10 @@ private:
* *
* @param pcMat Output material * @param pcMat Output material
* @param in Input texture list * @param in Input texture list
* @param type Type identifier of the texture list. This is the string * @param type Type identifier of the texture list
* that appears in the middle of all material keys - e.g. "diffuse",
* "shininess", "glossiness" or "specular".
*/ */
bool HandleTextures(MaterialHelper* pcMat, const TextureList& in, bool HandleTextures(MaterialHelper* pcMat, const TextureList& in,
const char* type); aiTextureType type);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Adjust a texture path /** Adjust a texture path

View File

@ -59,16 +59,20 @@ T lerp(const T& one, const T& two, float val)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a lightwave mapping mode to our's
inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
{ {
switch (in) switch (in)
{ {
case LWO::Texture::REPEAT: case LWO::Texture::REPEAT:
return aiTextureMapMode_Wrap; return aiTextureMapMode_Wrap;
case LWO::Texture::MIRROR: case LWO::Texture::MIRROR:
return aiTextureMapMode_Mirror; return aiTextureMapMode_Mirror;
case LWO::Texture::RESET: case LWO::Texture::RESET:
DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET"); DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
// fall though here // fall though here
case LWO::Texture::EDGE: case LWO::Texture::EDGE:
return aiTextureMapMode_Clamp; return aiTextureMapMode_Clamp;
@ -77,23 +81,67 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, const char* type) bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, aiTextureType type)
{ {
ai_assert(NULL != pcMat && NULL != type); ai_assert(NULL != pcMat);
unsigned int cur = 0, temp = 0; unsigned int cur = 0, temp = 0;
char buffer[512];
aiString s; aiString s;
bool ret = false; bool ret = false;
for (TextureList::const_iterator it = in.begin(), end = in.end(); for (TextureList::const_iterator it = in.begin(), end = in.end();
it != end;++it) it != end;++it)
{ {
if (!(*it).enabled || !(*it).bCanUse || 0xffffffff == (*it).mRealUVIndex)continue; if (!(*it).enabled || !(*it).bCanUse)continue;
ret = true; ret = true;
// add the path to the texture // Convert lightwave's mapping modes to ours. We let them
sprintf(buffer,"$tex.file.%s[%i]",type,cur); // as they are, the GenUVcoords step will compute UV
// channels if they're not there.
aiTextureMapping mapping;
switch ((*it).mapMode)
{
case LWO::Texture::Planar:
mapping = aiTextureMapping_PLANE;
break;
case LWO::Texture::Cylindrical:
mapping = aiTextureMapping_CYLINDER;
break;
case LWO::Texture::Spherical:
mapping = aiTextureMapping_SPHERE;
break;
case LWO::Texture::Cubic:
mapping = aiTextureMapping_BOX;
break;
case LWO::Texture::FrontProjection:
DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
mapping = aiTextureMapping_OTHER;
break;
case LWO::Texture::UV:
{
if( 0xffffffff == (*it).mRealUVIndex )
{
// We have no UV index for this texture, so we can't display it
continue;
}
// add the UV source index
temp = (*it).mRealUVIndex;
pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
mapping = aiTextureMapping_UV;
}
break;
};
if (mapping != aiTextureMapping_UV)
{
// Setup the main axis (the enum values map one to one)
pcMat->AddProperty<int>((int*)&(*it).majorAxis,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
}
// The older LWOB format does not use indirect references to clips. // The older LWOB format does not use indirect references to clips.
// The file name of a texture is directly specified in the tex chunk. // The file name of a texture is directly specified in the tex chunk.
@ -133,14 +181,12 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, c
AdjustTexturePath(ss); AdjustTexturePath(ss);
s.Set(ss); s.Set(ss);
} }
pcMat->AddProperty(&s,buffer); pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
// add the blend factor // add the blend factor
sprintf(buffer,"$tex.blend.%s[%i]",type,cur); pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
pcMat->AddProperty(&(*it).mStrength,1,buffer);
// add the blend operation // add the blend operation
sprintf(buffer,"$tex.op.%s[%i]",type,cur);
switch ((*it).blendType) switch ((*it).blendType)
{ {
case LWO::Texture::Normal: case LWO::Texture::Normal:
@ -166,22 +212,18 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, c
DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement"); DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
} }
pcMat->AddProperty<int>((int*)&temp,1,buffer); pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
// add the UV source index // setup the mapping mode
sprintf(buffer,"$tex.uvw.%s[%i]",type,cur); pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
temp = (*it).mRealUVIndex;
pcMat->AddProperty<int>((int*)&temp,1,buffer);
// add the u-wrapping // add the u-wrapping
sprintf(buffer,"$tex.mapmodeu.%s[%i]",type,cur);
temp = (unsigned int)GetMapMode((*it).wrapModeWidth); temp = (unsigned int)GetMapMode((*it).wrapModeWidth);
pcMat->AddProperty<int>((int*)&temp,1,buffer); pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
// add the v-wrapping // add the v-wrapping
sprintf(buffer,"$tex.mapmodev.%s[%i]",type,cur);
temp = (unsigned int)GetMapMode((*it).wrapModeHeight); temp = (unsigned int)GetMapMode((*it).wrapModeHeight);
pcMat->AddProperty<int>((int*)&temp,1,buffer); pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
++cur; ++cur;
} }
@ -237,17 +279,20 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE); pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
// opacity // opacity
float f = 1.0f-surf.mTransparency; if (10e10f != surf.mTransparency)
pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY); {
float f = 1.0f-surf.mTransparency;
pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
}
// ADD TEXTURES to the material // ADD TEXTURES to the material
// TODO: find out how we can handle COLOR textures correctly... // TODO: find out how we can handle COLOR textures correctly...
bool b = HandleTextures(pcMat,surf.mColorTextures,"diffuse"); bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,"diffuse")); b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
HandleTextures(pcMat,surf.mSpecularTextures,"specular"); HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
HandleTextures(pcMat,surf.mGlossinessTextures,"shininess"); HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
HandleTextures(pcMat,surf.mBumpTextures,"height"); HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
HandleTextures(pcMat,surf.mOpacityTextures,"opacity"); HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
// now we need to know which shader we must use // now we need to know which shader we must use
// iterate through the shader list of the surface and // iterate through the shader list of the surface and
@ -255,7 +300,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end(); for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();
it != end;++it) it != end;++it)
{ {
if (!(*it).enabled)continue; //if (!(*it).enabled)continue;
if ((*it).functionName == "LW_SuperCelShader" || if ((*it).functionName == "LW_SuperCelShader" ||
(*it).functionName == "AH_CelShader") (*it).functionName == "AH_CelShader")
{ {
@ -298,20 +343,11 @@ void LWOImporter::FindUVChannels(LWO::TextureList& list, LWO::Layer& layer,
for (TextureList::iterator it = list.begin(), end = list.end(); for (TextureList::iterator it = list.begin(), end = list.end();
it != end;++it) it != end;++it)
{ {
if (!(*it).enabled || !(*it).bCanUse || 0xffffffff != (*it).mRealUVIndex)continue; // Ignore textures with non-UV mappings for the moment.
switch ((*it).mapMode) if (!(*it).enabled || !(*it).bCanUse || 0xffffffff != (*it).mRealUVIndex ||
(*it).mapMode != LWO::Texture::UV)
{ {
// TODO: implement these special mappings ...
case LWO::Texture::Spherical:
case LWO::Texture::Cylindrical:
case LWO::Texture::Cubic:
case LWO::Texture::Planar:
case LWO::Texture::FrontProjection:
DefaultLogger::get()->warn("LWO2: Only UV mapping is currently supported.");
continue; continue;
default: ;
} }
for (unsigned int i = 0; i < layer.mUVChannels.size();++i) for (unsigned int i = 0; i < layer.mUVChannels.size();++i)
{ {
@ -391,6 +427,9 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
switch (head->type) switch (head->type)
{ {
case AI_LWO_PROJ: case AI_LWO_PROJ:
tex.mapMode = (Texture::MappingMode)GetU2();
break;
case AI_LWO_WRAP:
tex.wrapModeWidth = (Texture::Wrap)GetU2(); tex.wrapModeWidth = (Texture::Wrap)GetU2();
tex.wrapModeHeight = (Texture::Wrap)GetU2(); tex.wrapModeHeight = (Texture::Wrap)GetU2();
break; break;
@ -650,10 +689,45 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// transparency // transparency
case AI_LWO_TRAN: case AI_LWO_TRAN:
{ {
if (surf.mTransparency == 10e10f)break;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
surf.mTransparency = GetF4(); surf.mTransparency = GetF4();
break; break;
} }
// transparency mode
case AI_LWO_ALPH:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ALPH,6);
uint16_t mode = GetU2();
switch (mode)
{
// The surface has no effect on the alpha channel when rendered
case 0:
surf.mTransparency = 10e10f;
break;
// The alpha channel will be written with the constant value
// following the mode in the subchunk.
case 1:
surf.mTransparency = GetF4();
break;
// The alpha value comes from the shadow density
case 3:
DefaultLogger::get()->error("LWO2: Unsupported alpha mode: shadow_density");
surf.mTransparency = 10e10f;
}
break;
}
// wireframe mode
case AI_LWO_LINE:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2);
if (GetU2() & 0x1)
surf.mWireframe = true;
break;
}
// glossiness // glossiness
case AI_LWO_GLOS: case AI_LWO_GLOS:
{ {
@ -696,6 +770,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
surf.mMaximumSmoothAngle = GetF4(); surf.mMaximumSmoothAngle = GetF4();
break; break;
} }
// vertex color channel to be applied to the surface
case AI_LWO_VCOL:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12);
surf.mDiffuseValue *= GetF4(); // strength
ReadVSizedIntLWO2(mFileBuffer); // skip envelope
surf.mVCMapType = GetU4(); // type of the channel
// name of the channel
GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
break;
}
// surface bock entry // surface bock entry
case AI_LWO_BLOK: case AI_LWO_BLOK:
{ {

View File

@ -110,7 +110,7 @@ namespace MDL {
// material key that is set for dummy materials that are // material key that is set for dummy materials that are
// just referencing another material // just referencing another material
#if (!defined AI_MDL7_REFERRER_MATERIAL) #if (!defined AI_MDL7_REFERRER_MATERIAL)
# define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&" # define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&",0,0
#endif #endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -43,15 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
// we are using sprintf only on fixed-size buffers, so the
// compiler should automatically expand the template sprintf_s<>
#if _MSC_VER >= 1400
# define sprintf sprintf_s
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialProperty(const aiMaterial* pMat, aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
const aiMaterialProperty** pPropOut) const aiMaterialProperty** pPropOut)
{ {
ai_assert (pMat != NULL); ai_assert (pMat != NULL);
@ -59,22 +55,25 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
ai_assert (pPropOut != NULL); ai_assert (pPropOut != NULL);
for (unsigned int i = 0; i < pMat->mNumProperties;++i) for (unsigned int i = 0; i < pMat->mNumProperties;++i)
{
aiMaterialProperty* prop = pMat->mProperties[i];
if (prop && !::strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index)
{ {
if (NULL != pMat->mProperties[i]) *pPropOut = pMat->mProperties[i];
{ return AI_SUCCESS;
if (0 == ASSIMP_stricmp( pMat->mProperties[i]->mKey.data, pKey ))
{
*pPropOut = pMat->mProperties[i];
return AI_SUCCESS;
}
}
} }
}
*pPropOut = NULL; *pPropOut = NULL;
return AI_FAILURE; return AI_FAILURE;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
float* pOut, float* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
@ -84,56 +83,51 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
for (unsigned int i = 0; i < pMat->mNumProperties;++i) for (unsigned int i = 0; i < pMat->mNumProperties;++i)
{ {
if (NULL != pMat->mProperties[i]) aiMaterialProperty* prop = pMat->mProperties[i];
if (prop && !::strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index)
{ {
if (0 == ASSIMP_stricmp( pMat->mProperties[i]->mKey.data, pKey )) // data is given in floats, simply copy it
if( aiPTI_Float == pMat->mProperties[i]->mType ||
aiPTI_Buffer == pMat->mProperties[i]->mType)
{ {
// data is given in floats, simply copy it unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(float);
if( aiPTI_Float == pMat->mProperties[i]->mType ||
aiPTI_Buffer == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(float);
if (NULL != pMax) if (pMax)iWrite = *pMax < iWrite ? *pMax : iWrite;
iWrite = *pMax < iWrite ? *pMax : iWrite; ::memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (float));
memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (float)); if (pMax)*pMax = iWrite;
if (NULL != pMax)
*pMax = iWrite;
}
// data is given in ints, convert to float
else if( aiPTI_Integer == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->
mDataLength / sizeof(int);
if (NULL != pMax)
iWrite = *pMax < iWrite ? *pMax : iWrite;
for (unsigned int a = 0; a < iWrite;++a)
{
pOut[a] = (float) ((int*)pMat->mProperties[i]->mData)[a];
}
if (NULL != pMax)
*pMax = iWrite;
}
// it is a string ... no way to read something out of this
else
{
if (NULL != pMax)
*pMax = 0;
return AI_FAILURE;
}
return AI_SUCCESS;
} }
// data is given in ints, convert to float
else if( aiPTI_Integer == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(int);
if (pMax)iWrite = *pMax < iWrite ? *pMax : iWrite;
for (unsigned int a = 0; a < iWrite;++a)
{
pOut[a] = (float) ((int*)pMat->mProperties[i]->mData)[a];
}
if (pMax)*pMax = iWrite;
}
// it is a string ... no way to read something out of this
else
{
if (pMax)*pMax = 0;
return AI_FAILURE;
}
return AI_SUCCESS;
} }
} }
return AI_FAILURE; return AI_FAILURE;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
int* pOut, int* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
@ -142,69 +136,66 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
ai_assert (pOut != NULL); ai_assert (pOut != NULL);
for (unsigned int i = 0; i < pMat->mNumProperties;++i) for (unsigned int i = 0; i < pMat->mNumProperties;++i)
{ {
if (NULL != pMat->mProperties[i]) aiMaterialProperty* prop = pMat->mProperties[i];
if (prop && !::strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index)
{ {
if (0 == ASSIMP_stricmp( pMat->mProperties[i]->mKey.data, pKey )) // data is given in ints, simply copy it
if( aiPTI_Integer == pMat->mProperties[i]->mType ||
aiPTI_Buffer == pMat->mProperties[i]->mType)
{ {
// data is given in ints, simply copy it unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(int);
if( aiPTI_Integer == pMat->mProperties[i]->mType ||
aiPTI_Buffer == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->
mDataLength / sizeof(int);
if (NULL != pMax) if (pMax)iWrite = *pMax < iWrite ? *pMax : iWrite;
iWrite = *pMax < iWrite ? *pMax : iWrite; ::memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (int));
memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (int)); if (pMax)*pMax = iWrite;
if (NULL != pMax)
*pMax = iWrite;
}
// data is given in floats convert to int (lossy!)
else if( aiPTI_Float == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->
mDataLength / sizeof(float);
if (NULL != pMax)
iWrite = *pMax < iWrite ? *pMax : iWrite;
for (unsigned int a = 0; a < iWrite;++a)
{
pOut[a] = (int) ((float*)pMat->mProperties[i]->mData)[a];
}
if (NULL != pMax)
*pMax = iWrite;
}
// it is a string ... no way to read something out of this
else
{
if (NULL != pMax)
*pMax = 0;
return AI_FAILURE;
}
return AI_SUCCESS;
} }
// data is given in floats convert to int (lossy!)
else if( aiPTI_Float == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(float);
if (pMax)iWrite = *pMax < iWrite ? *pMax : iWrite;
for (unsigned int a = 0; a < iWrite;++a)
{
pOut[a] = (int) ((float*)pMat->mProperties[i]->mData)[a];
}
if (pMax)*pMax = iWrite;
}
// it is a string ... no way to read something out of this
else
{
if (pMax)*pMax = 0;
return AI_FAILURE;
}
return AI_SUCCESS;
} }
} }
return AI_FAILURE; return AI_FAILURE;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialColor(const aiMaterial* pMat, aiReturn aiGetMaterialColor(const aiMaterial* pMat,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
aiColor4D* pOut) aiColor4D* pOut)
{ {
unsigned int iMax = 4; unsigned int iMax = 4;
aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,(float*)pOut,&iMax); aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
// if no alpha channel is provided set it to 1.0 by default // if no alpha channel is provided set it to 1.0 by default
if (3 == iMax)pOut->a = 1.0f; if (3 == iMax)pOut->a = 1.0f;
return eRet; return eRet;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialString(const aiMaterial* pMat, aiReturn aiGetMaterialString(const aiMaterial* pMat,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
aiString* pOut) aiString* pOut)
{ {
ai_assert (pMat != NULL); ai_assert (pMat != NULL);
@ -213,37 +204,39 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
for (unsigned int i = 0; i < pMat->mNumProperties;++i) for (unsigned int i = 0; i < pMat->mNumProperties;++i)
{ {
if (NULL != pMat->mProperties[i]) aiMaterialProperty* prop = pMat->mProperties[i];
if (prop && !::strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index)
{ {
if (0 == ASSIMP_stricmp( pMat->mProperties[i]->mKey.data, pKey )) if( aiPTI_String == pMat->mProperties[i]->mType)
{ {
if( aiPTI_String == pMat->mProperties[i]->mType) const aiString* pcSrc = (const aiString*)pMat->mProperties[i]->mData;
{ ::memcpy (pOut->data, pcSrc->data, (pOut->length = pcSrc->length)+1);
const aiString* pcSrc = (const aiString*)pMat->mProperties[i]->mData;
::memcpy (pOut->data, pcSrc->data, (pOut->length = pcSrc->length)+1);
}
// wrong type
else return AI_FAILURE;
return AI_SUCCESS;
} }
// Wrong type
else return AI_FAILURE;
return AI_SUCCESS;
} }
} }
return AI_FAILURE; return AI_FAILURE;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
MaterialHelper::MaterialHelper() MaterialHelper::MaterialHelper()
{ {
// allocate 5 entries by default // Allocate 5 entries by default
this->mNumProperties = 0; mNumProperties = 0;
this->mNumAllocated = 5; mNumAllocated = 5;
this->mProperties = new aiMaterialProperty*[5]; mProperties = new aiMaterialProperty*[5];
return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
MaterialHelper::~MaterialHelper() MaterialHelper::~MaterialHelper()
{ {
Clear(); Clear();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MaterialHelper::Clear() void MaterialHelper::Clear()
{ {
@ -252,7 +245,11 @@ void MaterialHelper::Clear()
// delete this entry // delete this entry
delete mProperties[i]; delete mProperties[i];
} }
mNumProperties = 0;
// The array remains
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint32_t MaterialHelper::ComputeHash() uint32_t MaterialHelper::ComputeHash()
{ {
@ -262,45 +259,62 @@ uint32_t MaterialHelper::ComputeHash()
aiMaterialProperty* prop; aiMaterialProperty* prop;
// NOTE: We need to exclude the material name from the hash // NOTE: We need to exclude the material name from the hash
if ((prop = this->mProperties[i]) && 0 != ::strcmp(prop->mKey.data,AI_MATKEY_NAME)) if ((prop = this->mProperties[i]) && ::strcmp(prop->mKey.data,"$mat.name"))
{ {
hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash); hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
hash = SuperFastHash(prop->mData,prop->mDataLength,hash); hash = SuperFastHash(prop->mData,prop->mDataLength,hash);
// Combine the semantic and the index with the hash
// We print them to a string to make sure the quality
// of the hash isn't decreased.
char buff[32];
unsigned int len;
len = itoa10(buff,prop->mSemantic);
hash = SuperFastHash(buff,len-1,hash);
len = itoa10(buff,prop->mIndex);
hash = SuperFastHash(buff,len-1,hash);
} }
} }
return hash; return hash;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::RemoveProperty (const char* pKey) aiReturn MaterialHelper::RemoveProperty (const char* pKey,unsigned int type,
unsigned int index)
{ {
ai_assert(NULL != pKey); ai_assert(NULL != pKey);
for (unsigned int i = 0; i < this->mNumProperties;++i) for (unsigned int i = 0; i < mNumProperties;++i)
{ {
if (this->mProperties[i]) // just for safety aiMaterialProperty* prop = mProperties[i];
{
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey ))
{
// delete this entry
delete this->mProperties[i];
// collapse the array behind --. if (prop && !::strcmp( prop->mKey.data, pKey ) &&
--this->mNumProperties; prop->mSemantic == type && prop->mIndex == index)
for (unsigned int a = i; a < this->mNumProperties;++a) {
{ // Delete this entry
this->mProperties[a] = this->mProperties[a+1]; delete mProperties[i];
}
return AI_SUCCESS; // collapse the array behind --.
--mNumProperties;
for (unsigned int a = i; a < mNumProperties;++a)
{
mProperties[a] = mProperties[a+1];
} }
return AI_SUCCESS;
} }
} }
return AI_FAILURE; return AI_FAILURE;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::AddBinaryProperty (const void* pInput, aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
const unsigned int pSizeInBytes, unsigned int pSizeInBytes,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
aiPropertyTypeInfo pType) aiPropertyTypeInfo pType)
{ {
ai_assert (pInput != NULL); ai_assert (pInput != NULL);
@ -310,27 +324,30 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
// first search the list whether there is already an entry // first search the list whether there is already an entry
// with this name. // with this name.
unsigned int iOutIndex = 0xFFFFFFFF; unsigned int iOutIndex = 0xFFFFFFFF;
for (unsigned int i = 0; i < this->mNumProperties;++i) for (unsigned int i = 0; i < mNumProperties;++i)
{ {
if (this->mProperties[i]) aiMaterialProperty* prop = mProperties[i];
if (prop && !::strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index)
{ {
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey )) // delete this entry
{ delete this->mProperties[i];
// delete this entry iOutIndex = i;
delete this->mProperties[i];
iOutIndex = i;
}
} }
} }
// Allocate a new material property
aiMaterialProperty* pcNew = new aiMaterialProperty(); aiMaterialProperty* pcNew = new aiMaterialProperty();
// fill this // Fill this
pcNew->mType = pType; pcNew->mType = pType;
pcNew->mSemantic = type;
pcNew->mIndex = index;
pcNew->mDataLength = pSizeInBytes; pcNew->mDataLength = pSizeInBytes;
pcNew->mData = new char[pSizeInBytes]; pcNew->mData = new char[pSizeInBytes];
memcpy (pcNew->mData,pInput,pSizeInBytes); ::memcpy (pcNew->mData,pInput,pSizeInBytes);
pcNew->mKey.length = ::strlen(pKey); pcNew->mKey.length = ::strlen(pKey);
ai_assert ( MAXLEN > pcNew->mKey.length); ai_assert ( MAXLEN > pcNew->mKey.length);
@ -338,37 +355,41 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
if (0xFFFFFFFF != iOutIndex) if (0xFFFFFFFF != iOutIndex)
{ {
this->mProperties[iOutIndex] = pcNew; mProperties[iOutIndex] = pcNew;
return AI_SUCCESS; return AI_SUCCESS;
} }
// resize the array ... allocate storage for 5 other properties // resize the array ... allocate storage for 5 other properties
if (this->mNumProperties == this->mNumAllocated) if (mNumProperties == mNumAllocated)
{ {
unsigned int iOld = this->mNumAllocated; unsigned int iOld = mNumAllocated;
this->mNumAllocated += 5; mNumAllocated += 5;
aiMaterialProperty** ppTemp = new aiMaterialProperty*[this->mNumAllocated]; aiMaterialProperty** ppTemp = new aiMaterialProperty*[mNumAllocated];
if (NULL == ppTemp)return AI_OUTOFMEMORY; if (NULL == ppTemp)return AI_OUTOFMEMORY;
::memcpy (ppTemp,this->mProperties,iOld * sizeof(void*)); ::memcpy (ppTemp,mProperties,iOld * sizeof(void*));
delete[] this->mProperties; delete[] mProperties;
this->mProperties = ppTemp; mProperties = ppTemp;
} }
// push back ... // push back ...
this->mProperties[this->mNumProperties++] = pcNew; mProperties[mNumProperties++] = pcNew;
return AI_SUCCESS; return AI_SUCCESS;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::AddProperty (const aiString* pInput, aiReturn MaterialHelper::AddProperty (const aiString* pInput,
const char* pKey) const char* pKey,
unsigned int type,
unsigned int index)
{ {
// fix ... don't keep the whole string buffer // Fix ... don't keep the whole string buffer
return this->AddBinaryProperty(pInput,(unsigned int)pInput->length+1+ return this->AddBinaryProperty(pInput,(unsigned int)pInput->length+1+
(unsigned int)(((uint8_t*)&pInput->data - (uint8_t*)&pInput->length)), (unsigned int)(((uint8_t*)&pInput->data - (uint8_t*)&pInput->length)),
pKey,aiPTI_String); pKey,type,index, aiPTI_String);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest, void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
const MaterialHelper* pcSrc) const MaterialHelper* pcSrc)
@ -400,7 +421,8 @@ void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
for (unsigned int q = 0; q < iOldNum;++q) for (unsigned int q = 0; q < iOldNum;++q)
{ {
prop = pcDest->mProperties[q]; prop = pcDest->mProperties[q];
if (!ASSIMP_stricmp(propSrc->mKey.data,prop->mKey.data)) if (prop && prop->mKey == propSrc->mKey &&
prop->mSemantic == propSrc->mSemantic && prop->mIndex == propSrc->mIndex)
{ {
delete prop; delete prop;
@ -411,171 +433,69 @@ void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
} }
} }
// Allocate the output property and copy the source property
prop = pcDest->mProperties[i] = new aiMaterialProperty(); prop = pcDest->mProperties[i] = new aiMaterialProperty();
prop->mKey = propSrc->mKey; prop->mKey = propSrc->mKey;
prop->mDataLength = propSrc->mDataLength; prop->mDataLength = propSrc->mDataLength;
prop->mType = propSrc->mType; prop->mType = propSrc->mType;
prop->mSemantic = propSrc->mSemantic;
prop->mIndex = propSrc->mIndex;
prop->mData = new char[propSrc->mDataLength]; prop->mData = new char[propSrc->mDataLength];
::memcpy(prop->mData,propSrc->mData,prop->mDataLength); ::memcpy(prop->mData,propSrc->mData,prop->mDataLength);
} }
return; return;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// we need this dummy because the compiler would otherwise complain about aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
// empty, but controlled statements ... aiTextureType type,
void DummyAssertFunction() unsigned int index,
C_STRUCT aiString* path,
aiTextureMapping* _mapping /*= NULL*/,
unsigned int* uvindex /*= NULL*/,
float* blend /*= NULL*/,
aiTextureOp* op /*= NULL*/,
aiTextureMapMode* mapmode /*= NULL*/)
{ {
ai_assert(false); ai_assert(NULL != mat && NULL != path);
}
// ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
unsigned int iIndex,
unsigned int iTexType,
aiString* szOut,
unsigned int* piUVIndex,
float* pfBlendFactor,
aiTextureOp* peTextureOp,
aiTextureMapMode* peMapMode)
{
ai_assert(NULL != pcMat);
ai_assert(NULL != szOut);
const char* szPathBase; // Get the path to the texture
const char* szUVBase; aiString string;
const char* szBlendBase; if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),&string))
const char* szOpBase;
const char* aszMapModeBase[3];
switch (iTexType)
{
case AI_TEXTYPE_DIFFUSE:
szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_;
szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_;
szBlendBase = AI_MATKEY_TEXBLEND_DIFFUSE_;
szOpBase = AI_MATKEY_TEXOP_DIFFUSE_;
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_;
szBlendBase = AI_MATKEY_TEXBLEND_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_;
szBlendBase = AI_MATKEY_TEXBLEND_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_;
szBlendBase = AI_MATKEY_TEXBLEND_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_;
szBlendBase = AI_MATKEY_TEXBLEND_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_;
szBlendBase = AI_MATKEY_TEXBLEND_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_;
szBlendBase = AI_MATKEY_TEXBLEND_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_;
szBlendBase = AI_MATKEY_TEXBLEND_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;
};
char szKey[256];
if (iIndex > 100)return AI_FAILURE;
// get the path to the texture
if(0 >= sprintf(szKey,"%s[%i]",szPathBase,iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialString(pcMat,szKey,szOut))
{ {
return AI_FAILURE; return AI_FAILURE;
} }
// get the UV index of the texture
if (piUVIndex)
{
int iUV;
if(0 >= sprintf(szKey,"%s[%i]",szUVBase,iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,&iUV))
iUV = 0;
*piUVIndex = iUV; // Determine the mapping type of the texture
} aiTextureMapping mapping = aiTextureMapping_UV;
// get the blend factor of the texture aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
if (pfBlendFactor) if (_mapping)*_mapping = mapping;
{
float fBlend;
if(0 >= sprintf(szKey,"%s[%i]",szBlendBase,iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialFloat(pcMat,szKey,&fBlend))
fBlend = 1.0f;
*pfBlendFactor = fBlend; // Get the UV index of the texture
if (aiTextureMapping_UV == mapping && uvindex)
{
aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex);
} }
// get the texture operation of the texture // Get the blend factor of the texture
if (peTextureOp) if (blend)
{ {
aiTextureOp op; aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend);
if(0 >= sprintf(szKey,"%s[%i]",szOpBase,iIndex))DummyAssertFunction(); }
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&op))
op = aiTextureOp_Multiply;
*peTextureOp = op; // Get the texture operation of the texture
if (op)
{
aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op);
} }
// get the texture mapping modes for the texture // get the texture mapping modes for the texture
if (peMapMode) if (mapmode)
{ {
aiTextureMapMode eMode; aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]);
for (unsigned int q = 0; q < 3;++q) aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]);
{ aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_W(type,index),(int*)&mapmode[2]);
if(0 >= sprintf(szKey,"%s[%i]",aszMapModeBase[q],iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&eMode))
{
eMode = aiTextureMapMode_Wrap;
}
peMapMode[q] = eMode;
}
} }
return AI_SUCCESS; return AI_SUCCESS;
} }

View File

@ -65,11 +65,15 @@ public:
* \param pInput Pointer to input data * \param pInput Pointer to input data
* \param pSizeInBytes Size of input data * \param pSizeInBytes Size of input data
* \param pKey Key/Usage of the property (AI_MATKEY_XXX) * \param pKey Key/Usage of the property (AI_MATKEY_XXX)
* \param type Set by the AI_MATKEY_XXX macro
* \param index Set by the AI_MATKEY_XXX macro
* \param pType Type information hint * \param pType Type information hint
*/ */
aiReturn AddBinaryProperty (const void* pInput, aiReturn AddBinaryProperty (const void* pInput,
const unsigned int pSizeInBytes, unsigned int pSizeInBytes,
const char* pKey, const char* pKey,
unsigned int type,
unsigned int index,
aiPropertyTypeInfo pType); aiPropertyTypeInfo pType);
@ -79,9 +83,13 @@ public:
* *
* \param pInput Input string * \param pInput Input string
* \param pKey Key/Usage of the property (AI_MATKEY_XXX) * \param pKey Key/Usage of the property (AI_MATKEY_XXX)
* \param type Set by the AI_MATKEY_XXX macro
* \param index Set by the AI_MATKEY_XXX macro
*/ */
aiReturn AddProperty (const aiString* pInput, aiReturn AddProperty (const aiString* pInput,
const char* pKey); const char* pKey,
unsigned int type,
unsigned int index);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -89,20 +97,26 @@ public:
* \param pInput Pointer to the input data * \param pInput Pointer to the input data
* \param pNumValues Number of values in the array * \param pNumValues Number of values in the array
* \param pKey Key/Usage of the property (AI_MATKEY_XXX) * \param pKey Key/Usage of the property (AI_MATKEY_XXX)
* \param type Set by the AI_MATKEY_XXX macro
* \param index Set by the AI_MATKEY_XXX macro
*/ */
template<class TYPE> template<class TYPE>
aiReturn AddProperty (const TYPE* pInput, aiReturn AddProperty (const TYPE* pInput,
const unsigned int pNumValues, unsigned int pNumValues,
const char* pKey); const char* pKey,
unsigned int type,
unsigned int index);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Remove a given key from the list /** Remove a given key from the list
* The function fails if the key isn't found * The function fails if the key isn't found
* *
* \param pKey Key/Usage to be deleted * \param pKey Key to be deleted
*/ */
aiReturn RemoveProperty (const char* pKey); aiReturn RemoveProperty (const char* pKey,
unsigned int type,
unsigned int index);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -136,11 +150,13 @@ public:
template<class TYPE> template<class TYPE>
aiReturn MaterialHelper::AddProperty (const TYPE* pInput, aiReturn MaterialHelper::AddProperty (const TYPE* pInput,
const unsigned int pNumValues, const unsigned int pNumValues,
const char* pKey) const char* pKey,
unsigned int type,
unsigned int index)
{ {
return this->AddBinaryProperty((const void*)pInput, return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(TYPE), pNumValues * sizeof(TYPE),
pKey,aiPTI_Buffer); pKey,type,index,aiPTI_Buffer);
} }
@ -149,11 +165,13 @@ aiReturn MaterialHelper::AddProperty (const TYPE* pInput,
template<> template<>
inline aiReturn MaterialHelper::AddProperty<float> (const float* pInput, inline aiReturn MaterialHelper::AddProperty<float> (const float* pInput,
const unsigned int pNumValues, const unsigned int pNumValues,
const char* pKey) const char* pKey,
unsigned int type,
unsigned int index)
{ {
return this->AddBinaryProperty((const void*)pInput, return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(float), pNumValues * sizeof(float),
pKey,aiPTI_Float); pKey,type,index,aiPTI_Float);
} }
@ -162,11 +180,13 @@ inline aiReturn MaterialHelper::AddProperty<float> (const float* pInput,
template<> template<>
inline aiReturn MaterialHelper::AddProperty<aiColor4D> (const aiColor4D* pInput, inline aiReturn MaterialHelper::AddProperty<aiColor4D> (const aiColor4D* pInput,
const unsigned int pNumValues, const unsigned int pNumValues,
const char* pKey) const char* pKey,
unsigned int type,
unsigned int index)
{ {
return this->AddBinaryProperty((const void*)pInput, return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiColor4D), pNumValues * sizeof(aiColor4D),
pKey,aiPTI_Float); pKey,type,index,aiPTI_Float);
} }
@ -175,11 +195,13 @@ inline aiReturn MaterialHelper::AddProperty<aiColor4D> (const aiColor4D* pInput,
template<> template<>
inline aiReturn MaterialHelper::AddProperty<aiColor3D> (const aiColor3D* pInput, inline aiReturn MaterialHelper::AddProperty<aiColor3D> (const aiColor3D* pInput,
const unsigned int pNumValues, const unsigned int pNumValues,
const char* pKey) const char* pKey,
unsigned int type,
unsigned int index)
{ {
return this->AddBinaryProperty((const void*)pInput, return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiColor3D), pNumValues * sizeof(aiColor3D),
pKey,aiPTI_Float); pKey,type,index,aiPTI_Float);
} }
@ -188,11 +210,13 @@ inline aiReturn MaterialHelper::AddProperty<aiColor3D> (const aiColor3D* pInput,
template<> template<>
inline aiReturn MaterialHelper::AddProperty<int> (const int* pInput, inline aiReturn MaterialHelper::AddProperty<int> (const int* pInput,
const unsigned int pNumValues, const unsigned int pNumValues,
const char* pKey) const char* pKey,
unsigned int type,
unsigned int index)
{ {
return this->AddBinaryProperty((const void*)pInput, return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(int), pNumValues * sizeof(int),
pKey,aiPTI_Integer); pKey,type,index,aiPTI_Integer);
} }
} }

View File

@ -93,6 +93,54 @@ inline VertexWeightTable* ComputeVertexBoneWeightTable(aiMesh* pMesh)
} }
// ------------------------------------------------------------------------------------------------
// Get a string for a given aiTextureType
inline const char* TextureTypeToString(aiTextureType in)
{
switch (in)
{
case aiTextureType_DIFFUSE:
return "Diffuse";
case aiTextureType_SPECULAR:
return "Specular";
case aiTextureType_AMBIENT:
return "Ambient";
case aiTextureType_EMISSIVE:
return "Emissive";
case aiTextureType_OPACITY:
return "Opacity";
case aiTextureType_NORMALS:
return "Normals";
case aiTextureType_HEIGHT:
return "Height";
case aiTextureType_SHININESS:
return "Shininess";
}
return "LARGE ERROR, please leave the room immediately and call the police";
}
// ------------------------------------------------------------------------------------------------
// Get a string for a given aiTextureMapping
inline const char* MappingTypeToString(aiTextureMapping in)
{
switch (in)
{
case aiTextureMapping_UV:
return "UV";
case aiTextureMapping_BOX:
return "Box";
case aiTextureMapping_SPHERE:
return "Sphere";
case aiTextureMapping_CYLINDER:
return "Cylinder";
case aiTextureMapping_PLANE:
return "Plane";
case aiTextureMapping_OTHER:
return "Other";
}
return "LARGE ERROR, please leave the room immediately and call the police";
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
class ComputeSpatialSortProcess : public BaseProcess class ComputeSpatialSortProcess : public BaseProcess
{ {

View File

@ -47,34 +47,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
#if _MSC_VER >= 1400
# define sprintf sprintf_s
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() RemoveRedundantMatsProcess::RemoveRedundantMatsProcess()
{ {
// nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
RemoveRedundantMatsProcess::~RemoveRedundantMatsProcess() RemoveRedundantMatsProcess::~RemoveRedundantMatsProcess()
{ {
// nothing to do here // nothing to do here
} }
// -------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const
{ {
return (pFlags & aiProcess_RemoveRedundantMaterials) != 0; return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
} }
// -------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void RemoveRedundantMatsProcess::Execute( aiScene* pScene) void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
{ {
DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin"); DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin");
unsigned int iCnt = 0; unsigned int iCnt = 0, unreferenced = 0;
if (pScene->mNumMaterials) if (pScene->mNumMaterials)
{ {
// TODO: reimplement this algorithm to work in-place // TODO: reimplement this algorithm to work in-place
@ -95,7 +95,11 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{ {
// if the material is not referenced ... remove it // if the material is not referenced ... remove it
if (!abReferenced[i])continue; if (!abReferenced[i])
{
++unreferenced;
continue;
}
uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash(); uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash();
for (unsigned int a = 0; a < i;++a) for (unsigned int a = 0; a < i;++a)
@ -153,7 +157,8 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
else else
{ {
char szBuffer[128]; // should be sufficiently large char szBuffer[128]; // should be sufficiently large
::sprintf(szBuffer,"RemoveRedundantMatsProcess finished. Found %i redundant materials",iCnt); ::sprintf(szBuffer,"RemoveRedundantMatsProcess finished. %i redundant and %i unused materials",
iCnt,unreferenced);
DefaultLogger::get()->info(szBuffer); DefaultLogger::get()->info(szBuffer);
} }
} }

View File

@ -45,20 +45,20 @@ using namespace Assimp;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
KeyIterator::KeyIterator(std::vector<aiVectorKey>* _objPos, KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos,
const std::vector<aiVectorKey>* _targetObjPos, const std::vector<aiVectorKey>* _targetObjPos,
const aiVector3D* defaultObjectPos /*= NULL*/, const aiVector3D* defaultObjectPos /*= NULL*/,
const aiVector3D* defaultTargetPos /*= NULL*/) const aiVector3D* defaultTargetPos /*= NULL*/)
: reachedEnd (false) : reachedEnd (false)
, curTime (-1.) , curTime (-1.)
, objPos(_objPos) , objPos (_objPos)
, targetObjPos (_targetObjPos) , targetObjPos (_targetObjPos)
, nextObjPos (0) , nextObjPos (0)
, nextTargetObjPos(0) , nextTargetObjPos(0)
{ {
// Generate default transformation tracks if necessary // Generate default transformation tracks if necessary
if (!objPos) if (!objPos || objPos->empty())
{ {
defaultObjPos.resize(1); defaultObjPos.resize(1);
defaultObjPos.front().mTime = 10e10; defaultObjPos.front().mTime = 10e10;
@ -68,7 +68,7 @@ KeyIterator::KeyIterator(std::vector<aiVectorKey>* _objPos,
objPos = & defaultObjPos; objPos = & defaultObjPos;
} }
if (!targetObjPos) if (!targetObjPos || targetObjPos->empty())
{ {
defaultTargetObjPos.resize(1); defaultTargetObjPos.resize(1);
defaultTargetObjPos.front().mTime = 10e10; defaultTargetObjPos.front().mTime = 10e10;
@ -129,7 +129,7 @@ void KeyIterator::operator ++()
const aiVectorKey& last = targetObjPos->at(nextTargetObjPos); const aiVectorKey& last = targetObjPos->at(nextTargetObjPos);
const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1); const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1);
/*curTargetPosition = Interpolate(first.mValue, last.mValue, /* curTargetPosition = Interpolate(first.mValue, last.mValue,
(curTime-first.mTime) / (last.mTime-first.mTime));*/ (curTime-first.mTime) / (last.mTime-first.mTime));*/
} }
@ -177,23 +177,31 @@ void TargetAnimationHelper::SetTargetAnimationChannel (
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void TargetAnimationHelper::SetMainAnimationChannel ( void TargetAnimationHelper::SetMainAnimationChannel (
std::vector<aiVectorKey>* _objectPositions) const std::vector<aiVectorKey>* _objectPositions)
{ {
ai_assert(NULL != _objectPositions); ai_assert(NULL != _objectPositions);
objectPositions = _objectPositions; objectPositions = _objectPositions;
} }
// ---------------------------------------------------------------------------
void TargetAnimationHelper::SetFixedMainAnimationChannel(
const aiVector3D& fixed)
{
objectPositions = NULL; // just to avoid confusion
fixedMain = fixed;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack) void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
{ {
ai_assert(NULL != objectPositions); ai_assert(NULL != targetPositions);
// Iterate through all object keys and interpolate their values if necessary. // Iterate through all object keys and interpolate their values if necessary.
// Then get the corresponding target position, compute the difference // Then get the corresponding target position, compute the difference
// vector between object and target position. Then compute a rotation matrix // vector between object and target position. Then compute a rotation matrix
// that rotates the base vector of the object coordinate system at that time // that rotates the base vector of the object coordinate system at that time
// to match the diff vector. // to match the diff vector.
KeyIterator iter(objectPositions,targetPositions); KeyIterator iter(objectPositions,targetPositions,&fixedMain);
unsigned int curTarget; unsigned int curTarget;
for (;!iter.Finished();++iter) for (;!iter.Finished();++iter)
{ {

View File

@ -69,7 +69,7 @@ public:
* @param defaultTargetPos Default target position to be used if * @param defaultTargetPos Default target position to be used if
* no animated track is available. May be NULL. * no animated track is available. May be NULL.
*/ */
KeyIterator(std::vector<aiVectorKey>* _objPos, KeyIterator(const std::vector<aiVectorKey>* _objPos,
const std::vector<aiVectorKey>* _targetObjPos, const std::vector<aiVectorKey>* _targetObjPos,
const aiVector3D* defaultObjectPos = NULL, const aiVector3D* defaultObjectPos = NULL,
const aiVector3D* defaultTargetPos = NULL); const aiVector3D* defaultTargetPos = NULL);
@ -129,7 +129,8 @@ class ASSIMP_API TargetAnimationHelper
public: public:
TargetAnimationHelper() TargetAnimationHelper()
: objectPositions (NULL) : targetPositions (NULL)
, objectPositions (NULL)
{} {}
@ -141,8 +142,8 @@ public:
* *
* @param targetPositions Translation channel * @param targetPositions Translation channel
*/ */
void SetTargetAnimationChannel ( void SetTargetAnimationChannel (const
const std::vector<aiVectorKey>* targetPositions); std::vector<aiVectorKey>* targetPositions);
// ------------------------------------------------------------------ // ------------------------------------------------------------------
@ -150,9 +151,16 @@ public:
* *
* @param objectPositions Translation channel * @param objectPositions Translation channel
*/ */
void SetMainAnimationChannel ( void SetMainAnimationChannel ( const
std::vector<aiVectorKey>* objectPositions); std::vector<aiVectorKey>* objectPositions);
// ------------------------------------------------------------------
/** Sets the main animation channel to a fixed value
*
* @param fixed Fixed value for the main animation channel
*/
void SetFixedMainAnimationChannel(const aiVector3D& fixed);
// ------------------------------------------------------------------ // ------------------------------------------------------------------
/** Computes final animation channels /** Computes final animation channels
@ -163,8 +171,8 @@ public:
private: private:
const std::vector<aiVectorKey>* targetPositions; const std::vector<aiVectorKey>* targetPositions,*objectPositions;
std::vector<aiVectorKey> *objectPositions; aiVector3D fixedMain;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -38,56 +38,107 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file Definition of a helper class that processes texture transformations */ /** @file Definition of a helper step that processes texture transformations */
#ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED #ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED
#define AI_TEXTURE_TRANSFORM_H_INCLUDED #define AI_TEXTURE_TRANSFORM_H_INCLUDED
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/aiTypes.h" #include "BaseProcess.h"
#include "../include/aiMaterial.h"
#include "../include/aiMesh.h"
struct aiNode; struct aiNode;
#include "3DSHelper.h"
namespace Assimp namespace Assimp {
#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
// ---------------------------------------------------------------------------
/** Small helper structure representing a shortcut into the material list
* to be able to update some values quickly.
*/
struct TTUpdateInfo
{ {
TTUpdateInfo()
: mat (NULL)
, directShortcut (NULL)
, semantic (0)
, index (0)
{}
//! Direct shortcut, if available
unsigned int* directShortcut;
//! Material
MaterialHelper* mat;
//! Texture type and index
unsigned int semantic, index;
};
using namespace Assimp::D3DS;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper class representing texture coordinate transformations /** Helper class representing texture coordinate transformations
*/ */
struct STransformVecInfo struct STransformVecInfo : public aiUVTransform
{ {
//! Construction. The resulting matrix is the identity
STransformVecInfo () STransformVecInfo()
: : uvIndex (0)
fScaleU(1.0f),fScaleV(1.0f), , mapU (aiTextureMapMode_Wrap)
fOffsetU(0.0f),fOffsetV(0.0f), , mapV (aiTextureMapMode_Wrap)
fRotation(0.0f), , lockedPos (AI_TT_UV_IDX_LOCK_NONE)
iUVIndex(0)
{} {}
//! Texture coordinate scaling in the x-direction
float fScaleU;
//! Texture coordinate scaling in the y-direction
float fScaleV;
//! Texture coordinate offset in the x-direction
float fOffsetU;
//! Texture coordinate offset in the y-direction
float fOffsetV;
//! Texture coordinate rotation, clockwise, in radians
float fRotation;
//! Source texture coordinate index //! Source texture coordinate index
unsigned int iUVIndex; unsigned int uvIndex;
//! Texture mapping mode in the u, v direction
aiTextureMapMode mapU,mapV;
//! Locked destination UV index
//! AI_TT_UV_IDX_LOCK_TBD - to be determined
//! AI_TT_UV_IDX_LOCK_NONE - none (default)
unsigned int lockedPos;
//! Update info - shortcuts into all materials
//! that are referencing this transform setup
std::list<TTUpdateInfo> updateList;
//! List of all textures that use this texture // -------------------------------------------------------------------
//! coordinate transformations /** Compare two transform setups
std::vector<D3DS::Texture*> pcTextures; */
inline bool operator== (const STransformVecInfo& other) const
{
// We use a small epsilon here
const float epsilon = 0.05f;
if (fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
{
return false;
}
if (fabs( mScaling.x - other.mScaling.x ) > epsilon ||
fabs( mScaling.y - other.mScaling.y ) > epsilon)
{
return false;
}
if (fabs( mRotation - other.mRotation) > epsilon)
{
return false;
}
return true;
}
inline bool operator!= (const STransformVecInfo& other) const
{
return !(*this == other);
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -95,8 +146,9 @@ struct STransformVecInfo
*/ */
inline bool IsUntransformed() const inline bool IsUntransformed() const
{ {
return 1.0f == fScaleU && 1.0f == fScaleV && return (1.0f == mScaling.x && 1.f == mScaling.y &&
!fOffsetU && !fOffsetV && !fRotation; !mTranslation.x && !mTranslation.y &&
mRotation < AI_TT_ROTATION_EPSILON);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -106,26 +158,26 @@ struct STransformVecInfo
{ {
mOut = aiMatrix3x3(); mOut = aiMatrix3x3();
if (1.0f != this->fScaleU || 1.0f != this->fScaleV) if (1.0f != mScaling.x || 1.0f != mScaling.y)
{ {
aiMatrix3x3 mScale; aiMatrix3x3 mScale;
mScale.a1 = this->fScaleU; mScale.a1 = mScaling.x;
mScale.b2 = this->fScaleV; mScale.b2 = mScaling.y;
mOut = mScale; mOut = mScale;
} }
if (this->fRotation) if (mRotation)
{ {
aiMatrix3x3 mRot; aiMatrix3x3 mRot;
mRot.a1 = mRot.b2 = cosf(this->fRotation); mRot.a1 = mRot.b2 = cos(mRotation);
mRot.a2 = mRot.b1 = sinf(this->fRotation); mRot.a2 = mRot.b1 = sin(mRotation);
mRot.a2 = -mRot.a2; mRot.a2 = -mRot.a2;
mOut *= mRot; mOut *= mRot;
} }
if (this->fOffsetU || this->fOffsetV) if (mTranslation.x || mTranslation.y)
{ {
aiMatrix3x3 mTrans; aiMatrix3x3 mTrans;
mTrans.a3 = this->fOffsetU; mTrans.a3 = mTranslation.x;
mTrans.b3 = this->fOffsetV; mTrans.b3 = mTranslation.y;
mOut *= mTrans; mOut *= mTrans;
} }
} }
@ -133,73 +185,39 @@ struct STransformVecInfo
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper class used by the ASE/ASK and 3DS loaders to handle texture /** Helper step to compute final UV coordinate sets if there are scalings
* coordinate transformations correctly (such as offsets, scaling) * or rotations in the original data read from the file.
*/ */
class ASSIMP_API TextureTransform class ASSIMP_API TextureTransformStep : public BaseProcess
{ {
//! Constructor, it is not possible to create instances of this class
TextureTransform() {}
public: public:
TextureTransformStep();
~TextureTransformStep();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns true if a texture requires UV transformations bool IsActive( unsigned int pFlags) const;
* \param rcIn Input texture
*/
inline static bool HasUVTransform(
const D3DS::Texture& rcIn)
{
return (rcIn.mOffsetU || rcIn.mOffsetV ||
1.0f != rcIn.mScaleU || 1.0f != rcIn.mScaleV || rcIn.mRotation);
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Must be called before HasUVTransform(rcIn) is called void Execute( aiScene* pScene);
* \param rcIn Input texture
*/
static void PreProcessUVTransform(
D3DS::Texture& rcIn);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Check whether the texture coordinate transformation of void SetupProperties(const Importer* pImp);
* a texture is already contained in a given list
* \param rasVec List of transformations
* \param pcTex Pointer to the texture
*/
static void AddToList(std::vector<STransformVecInfo>& rasVec,
D3DS::Texture* pcTex);
// -------------------------------------------------------------------
/** Get a full list of all texture coordinate offsets required
* for a material
* \param materials List of materials to be processed
*/
static void ApplyScaleNOffset(std::vector<D3DS::Material>& materials);
// ------------------------------------------------------------------- protected:
/** Get a full list of all texture coordinate offsets required
* for a material
* \param material Material to be processed
*/
static void ApplyScaleNOffset(D3DS::Material& material);
// -------------------------------------------------------------------
/** Precompute as many texture coordinate transformations as possible
* \param pcMesh Mesh containing the texture coordinate data
* \param pcSrc Input material. Must have been passed to
* ApplyScaleNOffset
*/
static void BakeScaleNOffset(aiMesh* pcMesh, D3DS::Material* pcSrc);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Setup the correct UV source for a material /** Preprocess a specific UV transformation setup
* \param pcMat Final material to be changed *
* \param pcMatIn Input material, unconverted * @param info Transformation setup to be preprocessed.
*/ */
static void SetupMatUVSrc (aiMaterial* pcMat, void PreProcessUVTransform(STransformVecInfo& info);
const D3DS::Material* pcMatIn);
private:
unsigned int configFlags;
}; };
} }

View File

@ -418,7 +418,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
{ {
if (face.mIndices[a] >= pMesh->mNumVertices) if (face.mIndices[a] >= pMesh->mNumVertices)
{ {
this->ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a); ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
} }
// the MSB flag is temporarily used by the extra verbose // the MSB flag is temporarily used by the extra verbose
// mode to tell us that the JoinVerticesProcess might have // mode to tell us that the JoinVerticesProcess might have
@ -523,6 +523,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
ReportError("aiMesh::mBones is non-null although there are no bones"); ReportError("aiMesh::mBones is non-null although there are no bones");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMesh* pMesh, void ValidateDSProcess::Validate( const aiMesh* pMesh,
const aiBone* pBone,float* afSum) const aiBone* pBone,float* afSum)
@ -548,6 +549,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh,
afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight; afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation) void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
{ {
@ -576,36 +578,54 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
// Animation duration is allowed to be zero in cases where the anim contains only a single key frame. // Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
// if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero"); // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
const char* szType) aiTextureType type)
{ {
ai_assert(NULL != szType); const char* szType;
switch (type)
{
case aiTextureType_DIFFUSE:
szType = "Diffuse";break;
// search all keys of the material ... case aiTextureType_SPECULAR:
// textures must be specified with rising indices (e.g. diffuse #2 may not be szType = "Specular";break;
// specified if diffuse #1 is not there ...)
// "$tex.file.<szType>[<index>]" case aiTextureType_AMBIENT:
char szBaseBuf[512]; szType = "Ambient";break;
int iLen;
iLen = ::sprintf(szBaseBuf,"$tex.file.%s",szType); case aiTextureType_EMISSIVE:
if (0 >= iLen)return; szType = "Emissive";break;
case aiTextureType_OPACITY:
szType = "Opacity";break;
case aiTextureType_SHININESS:
szType = "Shininess";break;
case aiTextureType_NORMALS:
szType = "Normals";break;
case aiTextureType_HEIGHT:
szType = "Height";break;
};
// ****************************************************************************
// Search all keys of the material ...
// textures must be specified with ascending indices
// (e.g. diffuse #2 may not be specified if diffuse #1 is not there ...)
// ****************************************************************************
int iNumIndices = 0; int iNumIndices = 0;
int iIndex = -1; int iIndex = -1;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{ {
aiMaterialProperty* prop = pMaterial->mProperties[i]; aiMaterialProperty* prop = pMaterial->mProperties[i];
if (0 == ASSIMP_strincmp( prop->mKey.data, szBaseBuf, iLen )) if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type)
{ {
const char* sz = &prop->mKey.data[iLen]; iIndex = std::max(iIndex, (int) prop->mIndex);
if (*sz) ++iNumIndices;
{
++sz;
iIndex = std::max(iIndex, (int)strtol10(sz,0));
++iNumIndices;
}
if (aiPTI_String != prop->mType) if (aiPTI_String != prop->mType)
this->ReportError("Material property %s is expected to be a string",prop->mKey.data); this->ReportError("Material property %s is expected to be a string",prop->mKey.data);
@ -613,52 +633,73 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
} }
if (iIndex +1 != iNumIndices) if (iIndex +1 != iNumIndices)
{ {
this->ReportError("%s #%i is set, but there are only %i %s textures", ReportError("%s #%i is set, but there are only %i %s textures",
szType,iIndex,iNumIndices,szType); szType,iIndex,iNumIndices,szType);
} }
if (!iNumIndices)return; if (!iNumIndices)return;
// now check whether all UV indices are valid ... // TODO: check whether the mappings are correctly
iLen = ::sprintf(szBaseBuf,"$tex.uvw.%s",szType); std::vector<aiTextureMapping> mappings(iNumIndices);
if (0 >= iLen)return;
// Now check whether all UV indices are valid ...
bool bNoSpecified = true; bool bNoSpecified = true;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{ {
aiMaterialProperty* prop = pMaterial->mProperties[i]; aiMaterialProperty* prop = pMaterial->mProperties[i];
if (0 == ASSIMP_strincmp( prop->mKey.data, szBaseBuf, iLen )) if (prop->mSemantic != type)continue;
if ((int)prop->mIndex >= iNumIndices)
{
ReportError("Found texture property with index %i, although there "
"are only %i textures of type %s",
prop->mIndex, iNumIndices, szType);
}
if (!::strcmp(prop->mKey.data,"$tex.mapping"))
{
if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping))
{
ReportError("Material property %s%i is expected to be an integer (size is %i)",
prop->mKey.data,prop->mIndex,prop->mDataLength);
}
mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
}
else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo"))
{
if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform))
{
ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
prop->mKey.data,prop->mIndex, prop->mDataLength);
}
mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
}
else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc"))
{ {
if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
this->ReportError("Material property %s is expected to be an integer",prop->mKey.data);
const char* sz = &prop->mKey.data[iLen];
if (*sz)
{ {
++sz; ReportError("Material property %s%i is expected to be an integer (size is %i)",
iIndex = strtol10(sz,NULL); prop->mKey.data,prop->mIndex,prop->mDataLength);
bNoSpecified = false; }
bNoSpecified = false;
// ignore UV indices for texture channel that are not there ... // Ignore UV indices for texture channels that are not there ...
if (iIndex >= iNumIndices)
// Get the value
iIndex = *((unsigned int*)prop->mData);
// Check whether there is a mesh using this material
// which has not enough UV channels ...
for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
{
aiMesh* mesh = this->mScene->mMeshes[a];
if(mesh->mMaterialIndex == (unsigned int)i)
{ {
// get the value int iChannels = 0;
iIndex = *((unsigned int*)prop->mData); while (mesh->HasTextureCoords(iChannels))++iChannels;
if (iIndex >= iChannels)
// check whether there is a mesh using this material
// which has not enough UV channels ...
for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
{ {
aiMesh* mesh = this->mScene->mMeshes[a]; ReportError("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
if(mesh->mMaterialIndex == (unsigned int)iIndex) iIndex,prop->mKey.data,a,iChannels);
{
int iChannels = 0;
while (mesh->HasTextureCoords(iChannels))++iChannels;
if (iIndex >= iChannels)
{
this->ReportError("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
iIndex,prop->mKey.data,a,iChannels);
}
}
} }
} }
} }
@ -669,7 +710,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
// Assume that all textures are using the first UV channel // Assume that all textures are using the first UV channel
for (unsigned int a = 0; a < mScene->mNumMeshes;++a) for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
{ {
aiMesh* mesh = this->mScene->mMeshes[a]; aiMesh* mesh = mScene->mMeshes[a];
if(mesh->mMaterialIndex == (unsigned int)iIndex) if(mesh->mMaterialIndex == (unsigned int)iIndex)
{ {
if (!mesh->mTextureCoords[0]) if (!mesh->mTextureCoords[0])
@ -766,15 +807,16 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
} }
// check whether there are invalid texture keys // check whether there are invalid texture keys
SearchForInvalidTextures(pMaterial,"diffuse"); SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE);
SearchForInvalidTextures(pMaterial,"specular"); SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR);
SearchForInvalidTextures(pMaterial,"ambient"); SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT);
SearchForInvalidTextures(pMaterial,"emissive"); SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE);
SearchForInvalidTextures(pMaterial,"opacity"); SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY);
SearchForInvalidTextures(pMaterial,"shininess"); SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS);
SearchForInvalidTextures(pMaterial,"normals"); SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT);
SearchForInvalidTextures(pMaterial,"height"); SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiTexture* pTexture) void ValidateDSProcess::Validate( const aiTexture* pTexture)
{ {
@ -806,7 +848,7 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
} }
const char* sz = pTexture->achFormatHint; const char* sz = pTexture->achFormatHint;
if ( sz[0] >= 'A' && sz[0] <= 'Z' || if (sz[0] >= 'A' && sz[0] <= 'Z' ||
sz[1] >= 'A' && sz[1] <= 'Z' || sz[1] >= 'A' && sz[1] <= 'Z' ||
sz[2] >= 'A' && sz[2] <= 'Z' || sz[2] >= 'A' && sz[2] <= 'Z' ||
sz[3] >= 'A' && sz[3] <= 'Z') sz[3] >= 'A' && sz[3] <= 'Z')
@ -814,35 +856,13 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
this->ReportError("aiTexture::achFormatHint contains non-lowercase characters"); this->ReportError("aiTexture::achFormatHint contains non-lowercase characters");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation, void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
const aiNodeAnim* pNodeAnim) const aiNodeAnim* pNodeAnim)
{ {
this->Validate(&pNodeAnim->mNodeName); Validate(&pNodeAnim->mNodeName);
#if 0
// check whether there is a bone with this name ...
unsigned int i = 0;
for (; i < this->mScene->mNumMeshes;++i)
{
aiMesh* mesh = this->mScene->mMeshes[i];
for (unsigned int a = 0; a < mesh->mNumBones;++a)
{
if (mesh->mBones[a]->mName == pNodeAnim->mBoneName)
goto __break_out;
}
}
__break_out:
if (i == this->mScene->mNumMeshes)
{
this->ReportWarning("aiNodeAnim::mBoneName is \"%s\". However, no bone with this name was found",
pNodeAnim->mBoneName.data);
}
if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mNumRotationKeys && !pNodeAnim->mNumScalingKeys)
{
this->ReportWarning("A bone animation channel has no keys");
}
#endif
// otherwise check whether one of the keys exceeds the total duration of the animation // otherwise check whether one of the keys exceeds the total duration of the animation
if (pNodeAnim->mNumPositionKeys) if (pNodeAnim->mNumPositionKeys)
{ {
@ -934,11 +954,12 @@ __break_out:
ReportError("A node animation channel must have at least one subtrack"); ReportError("A node animation channel must have at least one subtrack");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiNode* pNode) void ValidateDSProcess::Validate( const aiNode* pNode)
{ {
if (!pNode)this->ReportError("A node of the scenegraph is NULL"); if (!pNode)ReportError("A node of the scenegraph is NULL");
if (pNode != this->mScene->mRootNode && !pNode->mParent) if (pNode != mScene->mRootNode && !pNode->mParent)
this->ReportError("A node has no valid parent (aiNode::mParent is NULL)"); this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
this->Validate(&pNode->mName); this->Validate(&pNode->mName);
@ -948,21 +969,21 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
{ {
if (!pNode->mMeshes) if (!pNode->mMeshes)
{ {
this->ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)", ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
pNode->mNumMeshes); pNode->mNumMeshes);
} }
std::vector<bool> abHadMesh; std::vector<bool> abHadMesh;
abHadMesh.resize(this->mScene->mNumMeshes,false); abHadMesh.resize(mScene->mNumMeshes,false);
for (unsigned int i = 0; i < pNode->mNumMeshes;++i) for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
{ {
if (pNode->mMeshes[i] >= this->mScene->mNumMeshes) if (pNode->mMeshes[i] >= mScene->mNumMeshes)
{ {
this->ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)", ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)",
pNode->mMeshes[i],this->mScene->mNumMeshes-1); pNode->mMeshes[i],mScene->mNumMeshes-1);
} }
if (abHadMesh[pNode->mMeshes[i]]) if (abHadMesh[pNode->mMeshes[i]])
{ {
this->ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)", ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)",
i,pNode->mMeshes[i]); i,pNode->mMeshes[i]);
} }
abHadMesh[pNode->mMeshes[i]] = true; abHadMesh[pNode->mMeshes[i]] = true;
@ -977,10 +998,11 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
} }
for (unsigned int i = 0; i < pNode->mNumChildren;++i) for (unsigned int i = 0; i < pNode->mNumChildren;++i)
{ {
this->Validate(pNode->mChildren[i]); Validate(pNode->mChildren[i]);
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiString* pString) void ValidateDSProcess::Validate( const aiString* pString)
{ {
@ -995,11 +1017,11 @@ void ValidateDSProcess::Validate( const aiString* pString)
if ('\0' == *sz) if ('\0' == *sz)
{ {
if (pString->length != (unsigned int)(sz-pString->data)) if (pString->length != (unsigned int)(sz-pString->data))
this->ReportError("aiString::data is invalid: the terminal zero is at a wrong offset"); ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
break; break;
} }
else if (sz >= &pString->data[MAXLEN]) else if (sz >= &pString->data[MAXLEN])
this->ReportError("aiString::data is invalid. There is no terminal character"); ReportError("aiString::data is invalid. There is no terminal character");
++sz; ++sz;
} }
} }

View File

@ -134,11 +134,10 @@ protected:
/** Search the material data structure for invalid or corrupt /** Search the material data structure for invalid or corrupt
* texture keys. * texture keys.
* @param pMaterial Input material * @param pMaterial Input material
* @param szType Type of the texture (the purpose string that * @param type Type of the texture
* occurs in material keys, e.g. "diffuse", "ambient")
*/ */
void SearchForInvalidTextures(const aiMaterial* pMaterial, void SearchForInvalidTextures(const aiMaterial* pMaterial,
const char* szType); aiTextureType type);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Validates a texture /** Validates a texture

View File

@ -611,7 +611,6 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
std::string sz = otex.mName; std::string sz = otex.mName;
if (!sz.length())continue; if (!sz.length())continue;
char key[256];
// find the file name // find the file name
const size_t iLen = sz.length(); const size_t iLen = sz.length();
@ -634,35 +633,35 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
if( isalpha( sz[c])) if( isalpha( sz[c]))
sz[c] = tolower( sz[c]); sz[c] = tolower( sz[c]);
// Place texture filename property under the corresponding name
aiString tex( oldMat.mTextures[b].mName);
// bump map // bump map
if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s))
{ {
::sprintf(key,AI_MATKEY_TEXTURE_HEIGHT_ "[%i]",iHM++); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++));
} else } else
if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s))
{ {
::sprintf(key,AI_MATKEY_TEXTURE_NORMALS_ "[%i]",iNM++); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++));
} else } else
if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s))
{ {
::sprintf(key,AI_MATKEY_TEXTURE_SPECULAR_ "[%i]",iSM++); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++));
} else } else
if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s))
{ {
::sprintf(key,AI_MATKEY_TEXTURE_AMBIENT_ "[%i]",iAM++); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++));
} else } else
if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s))
{ {
::sprintf(key,AI_MATKEY_TEXTURE_EMISSIVE_ "[%i]",iEM++); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++));
} else } else
{ {
// assume it is a diffuse texture // Assume it is a diffuse texture
::sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++); mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++));
} }
// place texture filename property under the corresponding name
aiString tex( oldMat.mTextures[b].mName);
mat->AddProperty( &tex, key);
} }
} }

View File

@ -74,7 +74,10 @@ SOURCES = AssimpPCH.cpp \
Q3DLoader.cpp \ Q3DLoader.cpp \
ScenePreprocessor.cpp \ ScenePreprocessor.cpp \
B3DImporter.cpp \ B3DImporter.cpp \
TargetAnimation.cpp TargetAnimation.cpp \
ComputeUVMappingProcess.cpp \
ColladaLoader.cpp \
ColladaParser.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)

View File

@ -74,8 +74,10 @@ SOURCES = AssimpPCH.cpp \
Q3DLoader.cpp \ Q3DLoader.cpp \
ScenePreprocessor.cpp \ ScenePreprocessor.cpp \
B3DImporter.cpp \ B3DImporter.cpp \
TargetAnimation.cpp TargetAnimation.cpp \
ComputeUVMappingProcess.cpp \
ColladaLoader.cpp \
ColladaParser.cpp
OBJECTS = $(SOURCES:.cpp=.o) OBJECTS = $(SOURCES:.cpp=.o)

View File

@ -0,0 +1,85 @@
#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED
#define __AI_BOOST_SCOPED_ARRAY_INCLUDED
#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
#include <assert.h>
namespace boost {
// small replacement for boost::scoped_array
template <class T>
class scoped_array
{
public:
// provide a default construtctor
scoped_array()
: ptr(0)
{
}
// construction from an existing heap object of type T
scoped_array(T* _ptr)
: ptr(_ptr)
{
}
// automatic destruction of the wrapped object at the
// end of our lifetime
~scoped_array()
{
delete[] ptr;
}
inline T* get()
{
return ptr;
}
inline operator T*()
{
return ptr;
}
inline T* operator-> ()
{
return ptr;
}
inline void reset (T* t = 0)
{
delete[] ptr;
ptr = t;
}
T & operator[](std::ptrdiff_t i) const
{
return ptr[i];
}
void swap(scoped_array & b)
{
std::swap(ptr, b.ptr);
}
private:
// encapsulated object pointer
T* ptr;
};
template<class T>
inline void swap(scoped_array<T> & a, scoped_array<T> & b)
{
a.swap(b);
}
} // end of namespace boost
#else
# error "scoped_array.h was already included"
#endif
#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED

View File

@ -16,7 +16,7 @@ public:
// provide a default construtctor // provide a default construtctor
scoped_ptr() scoped_ptr()
: ptr(NULL) : ptr(0)
{ {
} }
@ -48,6 +48,17 @@ public:
return ptr; return ptr;
} }
inline void reset (T* t = 0)
{
delete ptr;
ptr = t;
}
void swap(scoped_ptr & b)
{
std::swap(ptr, b.ptr);
}
private: private:
// encapsulated object pointer // encapsulated object pointer
@ -55,6 +66,12 @@ private:
}; };
template<class T>
inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b)
{
a.swap(b);
}
} // end of namespace boost } // end of namespace boost
#else #else

View File

@ -55,6 +55,12 @@ extern "C" {
/** Helper structure to describe a virtual camera. /** Helper structure to describe a virtual camera.
* *
* Cameras have a representation in the node graph and can be animated. * Cameras have a representation in the node graph and can be animated.
* Note - some file formats (such as 3DS, ASE) export a "target point" -
* the point the camera is looking at (it can even be animated). Assimp
* writes the target point as a subnode of the camera's main node,
* called "<camName>.Target". However, this is just additional information
* then, the transformation tracks of the camera main node make the
* camera already point in the right direction.
* *
*/ */
struct aiCamera struct aiCamera

View File

@ -101,15 +101,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_CONFIG_IMPORT_SMD_KEYFRAME "imp.smd.kf" #define AI_CONFIG_IMPORT_SMD_KEYFRAME "imp.smd.kf"
// ---------------------------------------------------------------------------
/** \brief Configures the 3DS loader to ignore pivot points in the file
*
* There are some faulty 3DS files which look only correctly with
* pivot points disabled.
* Property type: integer (0: false; !0: true). Default value: false.
*/
#define AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT "imp.3ds.nopivot"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Configures the AC loader to collect all surfaces which have the /** \brief Configures the AC loader to collect all surfaces which have the
@ -305,6 +296,23 @@ enum aiComponent
#define AI_CONFIG_PP_SBP_REMOVE "pp.sbp.remove" #define AI_CONFIG_PP_SBP_REMOVE "pp.sbp.remove"
#define AI_UVTRAFO_SCALING 0x1
#define AI_UVTRAFO_ROTATION 0x2
#define AI_UVTRAFO_TRANSLATION 0x4
#define AI_UVTRAFO_ALL (AI_UVTRAFO_SCALING | AI_UVTRAFO_ROTATION | AI_UVTRAFO_TRANSLATION)
// ---------------------------------------------------------------------------
/** \brief Input parameter to the #aiProcess_TransformUVCoords step:
* Specifies which UV transformations are evaluated.
*
* This is a bitwise combination of the AI_UVTRAFO_XXX flags (integer
* property, of course). By default all transformations are enabled
* (AI_UVTRAFO_ALL).
*/
#define AI_CONFIG_PP_TUV_EVALUATE "pp.tuv.process"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** \brief Causes assimp to favour speed against import quality. /** \brief Causes assimp to favour speed against import quality.
* *

View File

@ -78,6 +78,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// OPTIMIZEGRAPH // OPTIMIZEGRAPH
// SORTBYPTYPE // SORTBYPTYPE
// FINDINVALIDDATA // FINDINVALIDDATA
// TRANSFORMTEXCOORDS
// GENUVCOORDS
// ************************************************************ // ************************************************************

View File

@ -87,6 +87,12 @@ enum aiLightSourceType
* Assimp supports multiple sorts of light sources, including * Assimp supports multiple sorts of light sources, including
* directional, point and spot lights. All of them are defined with just * directional, point and spot lights. All of them are defined with just
* a single structure and distinguished by their parameters. * a single structure and distinguished by their parameters.
* Note - some file formats (such as 3DS, ASE) export a "target point" -
* the point a spot light is looking at (it can even be animated). Assimp
* writes the target point as a subnode of a spotlights's main node,
* called "<spotName>.Target". However, this is just additional information
* then, the transformation tracks of the main node make the
* spot light already point in the right direction.
*/ */
struct aiLight struct aiLight
{ {

File diff suppressed because it is too large Load Diff

View File

@ -47,26 +47,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MATERIAL_INL_INC #define AI_MATERIAL_INL_INC
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
inline aiReturn aiMaterial::GetTexture(unsigned int iIndex, inline aiReturn aiMaterial::GetTexture( aiTextureType type,
unsigned int iTexType, unsigned int idx,
aiString* szPath, C_STRUCT aiString* path,
unsigned int* piUVIndex , aiTextureMapping* mapping /*= NULL*/,
float* pfBlendFactor , unsigned int* uvindex /*= NULL*/,
aiTextureOp* peTextureOp , float* blend /*= NULL*/,
aiTextureMapMode* peMapMode ) aiTextureOp* op /*= NULL*/,
aiTextureMapMode* mapmode /*= NULL*/)
{ {
return aiGetMaterialTexture(this,iIndex,iTexType,szPath, return aiGetMaterialTexture(this,type,idx,path,mapping,uvindex,blend,op,mapmode);
piUVIndex,pfBlendFactor,peTextureOp,peMapMode);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename Type> template <typename Type>
inline aiReturn aiMaterial::Get(const char* pKey,Type* pOut, inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
unsigned int idx, Type* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
unsigned int iNum = pMax ? *pMax : 1; unsigned int iNum = pMax ? *pMax : 1;
aiMaterialProperty* prop; aiMaterialProperty* prop;
aiReturn ret = aiGetMaterialProperty(this,pKey,&prop); aiReturn ret = aiGetMaterialProperty(this,pKey,type,idx,&prop);
if ( AI_SUCCESS == ret ) if ( AI_SUCCESS == ret )
{ {
if (prop->mDataLength < sizeof(Type)*iNum)return AI_FAILURE; if (prop->mDataLength < sizeof(Type)*iNum)return AI_FAILURE;
@ -78,12 +80,14 @@ inline aiReturn aiMaterial::Get(const char* pKey,Type* pOut,
} }
return ret; return ret;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename Type> template <typename Type>
inline aiReturn aiMaterial::Get(const char* pKey,Type& pOut) inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
unsigned int idx,Type& pOut)
{ {
aiMaterialProperty* prop; aiMaterialProperty* prop;
aiReturn ret = aiGetMaterialProperty(this,pKey,&prop); aiReturn ret = aiGetMaterialProperty(this,pKey,type,idx,&prop);
if ( AI_SUCCESS == ret ) if ( AI_SUCCESS == ret )
{ {
if (prop->mDataLength < sizeof(Type))return AI_FAILURE; if (prop->mDataLength < sizeof(Type))return AI_FAILURE;
@ -93,43 +97,50 @@ inline aiReturn aiMaterial::Get(const char* pKey,Type& pOut)
} }
return ret; return ret;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterial::Get<float>(const char* pKey,float* pOut, inline aiReturn aiMaterial::Get<float>(const char* pKey,unsigned int type,
unsigned int idx,float* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
return aiGetMaterialFloatArray(this,pKey,pOut,pMax); return aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterial::Get<int>(const char* pKey,int* pOut, inline aiReturn aiMaterial::Get<int>(const char* pKey,unsigned int type,
unsigned int idx,int* pOut,
unsigned int* pMax) unsigned int* pMax)
{ {
return aiGetMaterialIntegerArray(this,pKey,pOut,pMax); return aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterial::Get<float>(const char* pKey,float& pOut) inline aiReturn aiMaterial::Get<float>(const char* pKey,unsigned int type,
unsigned int idx,float& pOut)
{ {
return aiGetMaterialFloat(this,pKey,&pOut); return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterial::Get<int>(const char* pKey,int& pOut) inline aiReturn aiMaterial::Get<int>(const char* pKey,unsigned int type,
unsigned int idx,int& pOut)
{ {
return aiGetMaterialInteger(this,pKey,&pOut); return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterial::Get<aiColor4D>(const char* pKey,aiColor4D& pOut) inline aiReturn aiMaterial::Get<aiColor4D>(const char* pKey,unsigned int type,
unsigned int idx,aiColor4D& pOut)
{ {
return aiGetMaterialColor(this,pKey,&pOut); return aiGetMaterialColor(this,pKey,type,idx,&pOut);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
inline aiReturn aiMaterial::Get<aiString>(const char* pKey,aiString& pOut) inline aiReturn aiMaterial::Get<aiString>(const char* pKey,unsigned int type,
unsigned int idx,aiString& pOut)
{ {
return aiGetMaterialString(this,pKey,&pOut); return aiGetMaterialString(this,pKey,type,idx,&pOut);
} }
#endif //! AI_MATERIAL_INL_INC #endif //! AI_MATERIAL_INL_INC

View File

@ -48,11 +48,11 @@ extern "C" {
#endif #endif
struct aiMatrix4x4; struct aiMatrix4x4;
struct aiVector2D;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a row-major 3x3 matrix /** Represents a row-major 3x3 matrix
*/ */
// ---------------------------------------------------------------------------
struct aiMatrix3x3 struct aiMatrix3x3
{ {
#ifdef __cplusplus #ifdef __cplusplus
@ -77,6 +77,22 @@ struct aiMatrix3x3
aiMatrix3x3 operator* (const aiMatrix3x3& m) const; aiMatrix3x3 operator* (const aiMatrix3x3& m) const;
aiMatrix3x3& Transpose(); aiMatrix3x3& Transpose();
/** \brief Returns a rotation matrix
* \param a Rotation angle, in radians
* \param out Receives the output matrix
* \return Reference to the output matrix
*/
static aiMatrix3x3& Rotation(float a, aiMatrix3x3& out);
/** \brief Returns a translation matrix
* \param v Translation vector
* \param out Receives the output matrix
* \return Reference to the output matrix
*/
static aiMatrix3x3& Translation( const aiVector2D& v, aiMatrix3x3& out);
#endif // __cplusplus #endif // __cplusplus

View File

@ -51,6 +51,27 @@ inline aiMatrix3x3& aiMatrix3x3::Transpose()
return *this; return *this;
} }
// ------------------------------------------------------------------------------------------------
inline aiMatrix3x3& aiMatrix3x3::Rotation(float a, aiMatrix3x3& out)
{
out.a1 = out.b2 = ::cos(a);
out.b1 = ::sin(a);
out.a2 = - out.b1;
out.a3 = out.b3 = out.c1 = out.c2 = 0.f;
out.c3 = 1.f;
return out;
}
// ------------------------------------------------------------------------------------------------
inline aiMatrix3x3& aiMatrix3x3::Translation( const aiVector2D& v, aiMatrix3x3& out)
{
out = aiMatrix3x3();
out.a3 = v.x;
out.b3 = v.y;
return out;
}
#endif // __cplusplus #endif // __cplusplus

View File

@ -504,6 +504,23 @@ struct aiMesh
else else
return mTextureCoords[pIndex] != NULL && mNumVertices > 0; return mTextureCoords[pIndex] != NULL && mNumVertices > 0;
} }
//! Get the number of UV channels the mesh contains
inline unsigned int GetNumUVChannels() const
{
unsigned int n = 0;
while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mTextureCoords[n])++n;
return n;
}
//! Get the number of vertex color channels the mesh contains
inline unsigned int GetNumColorChannels() const
{
unsigned int n = 0;
while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n])++n;
return n;
}
//! Check whether the mesh contains bones //! Check whether the mesh contains bones
inline bool HasBones() const inline bool HasBones() const
{ return mBones != NULL && mNumBones > 0; } { return mBones != NULL && mNumBones > 0; }

View File

@ -230,7 +230,6 @@ enum aiPostProcessSteps
*/ */
aiProcess_FindDegenerates = 0x10000, aiProcess_FindDegenerates = 0x10000,
/** This step searches all meshes for invalid data, such as zeroed /** This step searches all meshes for invalid data, such as zeroed
* normal vectors or invalid UV coords and removes them. * normal vectors or invalid UV coords and removes them.
* *
@ -240,6 +239,26 @@ enum aiPostProcessSteps
* The step will also remove meshes that are infinitely small. * The step will also remove meshes that are infinitely small.
*/ */
aiProcess_FindInvalidData = 0x20000, aiProcess_FindInvalidData = 0x20000,
/** This step converts non-UV mappings (such as spherical or
* cylindrical) to proper UV mapping channels.
*
* Most applications will support UV mapping only, so you will
* propably want to specify this step in every case.
*/
aiProcess_GenUVCoords = 0x40000,
/** This step pretransforms UV coordinates by the UV transformations
* (such as scalings or rotations).
*
* UV transformations are specified per-texture - see the
* AI_MATKEY_UVTRANSFORM key for more information on this topic.
* This step finds all textures with transformed input UV
* coordinates and generates a new, transformed, UV channel for it.
* Most applications won't support UV transformations, so you will
* propably want to specify this step in every case.
*/
aiProcess_TransformUVCoords = 0x80000,
}; };
@ -254,7 +273,8 @@ enum aiPostProcessSteps
aiProcess_CalcTangentSpace | \ aiProcess_CalcTangentSpace | \
aiProcess_GenNormals | \ aiProcess_GenNormals | \
aiProcess_JoinIdenticalVertices | \ aiProcess_JoinIdenticalVertices | \
aiProcess_Triangulate aiProcess_Triangulate | \
aiProcess_GenUVCoords
/** @def AI_POSTPROCESS_DEFAULT_REALTIME /** @def AI_POSTPROCESS_DEFAULT_REALTIME
@ -274,7 +294,8 @@ enum aiPostProcessSteps
aiProcess_RemoveRedundantMaterials | \ aiProcess_RemoveRedundantMaterials | \
aiProcess_SplitLargeMeshes | \ aiProcess_SplitLargeMeshes | \
aiProcess_OptimizeGraph | \ aiProcess_OptimizeGraph | \
aiProcess_Triangulate aiProcess_Triangulate | \
aiProcess_GenUVCoords
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -47,13 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "aiDefines.h" #include "aiDefines.h"
// include math helper classes and their implementations // include math helper classes
#include "aiVector3D.h" #include "aiVector3D.h"
#include "aiMatrix3x3.h" #include "aiMatrix3x3.h"
#include "aiMatrix4x4.h" #include "aiMatrix4x4.h"
#include "aiVector3D.inl"
#include "aiMatrix3x3.inl"
#include "aiMatrix4x4.inl"
#ifdef __cplusplus #ifdef __cplusplus
# include <string> # include <string>
@ -72,7 +69,6 @@ const size_t MAXLEN = 1024;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a two-dimensional vector. /** Represents a two-dimensional vector.
*/ */
// ---------------------------------------------------------------------------
struct aiVector2D struct aiVector2D
{ {
#ifdef __cplusplus #ifdef __cplusplus
@ -86,6 +82,25 @@ struct aiVector2D
float x, y; float x, y;
} PACK_STRUCT; } PACK_STRUCT;
// ---------------------------------------------------------------------------
/** Represents a plane in a three-dimensional, euclidean space
*/
struct aiPlane
{
#ifdef __cplusplus
aiPlane () : a(0.f), b(0.f), c(0.f), d(0.f) {}
aiPlane (float _a, float _b, float _c, float _d)
: a(_a), b(_b), c(_c), d(_d) {}
aiPlane (const aiPlane& o) : a(o.a), b(o.b), c(o.c), d(o.d) {}
#endif // !__cplusplus
//! Plane equation
float a,b,c,d;
} PACK_STRUCT;
// aiVector3D type moved to separate header due to size of operators // aiVector3D type moved to separate header due to size of operators
// aiQuaternion type moved to separate header due to size of operators // aiQuaternion type moved to separate header due to size of operators
// aiMatrix4x4 type moved to separate header due to size of operators // aiMatrix4x4 type moved to separate header due to size of operators
@ -93,7 +108,6 @@ struct aiVector2D
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a color in Red-Green-Blue space. /** Represents a color in Red-Green-Blue space.
*/ */
// ---------------------------------------------------------------------------
struct aiColor3D struct aiColor3D
{ {
#ifdef __cplusplus #ifdef __cplusplus
@ -136,7 +150,6 @@ struct aiColor3D
/** Represents a color in Red-Green-Blue space including an /** Represents a color in Red-Green-Blue space including an
* alpha component. * alpha component.
*/ */
// ---------------------------------------------------------------------------
struct aiColor4D struct aiColor4D
{ {
#ifdef __cplusplus #ifdef __cplusplus
@ -157,7 +170,7 @@ struct aiColor4D
inline bool IsBlack() const inline bool IsBlack() const
{ {
// the alpha component doesn't care here. black is black. // The alpha component doesn't care here. black is black.
return !r && !g && !b; return !r && !g && !b;
} }
@ -173,7 +186,6 @@ struct aiColor4D
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a string, zero byte terminated /** Represents a string, zero byte terminated
*/ */
// ---------------------------------------------------------------------------
struct aiString struct aiString
{ {
#ifdef __cplusplus #ifdef __cplusplus
@ -188,7 +200,7 @@ struct aiString
length(rOther.length) length(rOther.length)
{ {
::memcpy( data, rOther.data, rOther.length); ::memcpy( data, rOther.data, rOther.length);
this->data[this->length] = '\0'; data[length] = '\0';
} }
//! Constructor from std::string //! Constructor from std::string
@ -212,17 +224,36 @@ struct aiString
//! comparison operator //! comparison operator
bool operator==(const aiString& other) const bool operator==(const aiString& other) const
{ {
return (this->length == other.length && return (length == other.length &&
0 == strcmp(this->data,other.data)); 0 == strcmp(this->data,other.data));
} }
//! inverse comparison operator //! inverse comparison operator
bool operator!=(const aiString& other) const bool operator!=(const aiString& other) const
{ {
return (this->length != other.length || return (length != other.length ||
0 != ::strcmp(this->data,other.data)); 0 != ::strcmp(this->data,other.data));
} }
//! Append a string to the string
inline void Append (const char* app)
{
const size_t len = ::strlen(app);
if (!len)return;
if (length + len >= MAXLEN)
return;
::memcpy(&data[length],app,len+1);
length += len;
}
//! Clear the string
inline void Clear ()
{
length = 0;
data[0] = '\0';
}
#endif // !__cplusplus #endif // !__cplusplus
@ -240,18 +271,21 @@ struct aiString
* To check whether or not a function failed check against * To check whether or not a function failed check against
* AI_SUCCESS. The error codes are mainly used by the C-API. * AI_SUCCESS. The error codes are mainly used by the C-API.
*/ */
// ---------------------------------------------------------------------------
enum aiReturn enum aiReturn
{ {
//! Indicates that a function was successful //! Indicates that a function was successful
AI_SUCCESS = 0x0, AI_SUCCESS = 0x0,
//! Indicates that a function failed //! Indicates that a function failed
AI_FAILURE = -0x1, AI_FAILURE = -0x1,
//! Indicates that a file was invalid //! Indicates that a file was invalid
AI_INVALIDFILE = -0x2, AI_INVALIDFILE = -0x2,
//! Indicates that not enough memory was available //! Indicates that not enough memory was available
//! to perform the requested operation //! to perform the requested operation
AI_OUTOFMEMORY = -0x3, AI_OUTOFMEMORY = -0x3,
//! Indicates that an illegal argument has been //! Indicates that an illegal argument has been
//! passed to a function. This is rarely used, //! passed to a function. This is rarely used,
//! most functions assert in this case. //! most functions assert in this case.
@ -264,7 +298,6 @@ enum aiReturn
* animations) of an import. * animations) of an import.
* @see Importer::GetMemoryRequirements() * @see Importer::GetMemoryRequirements()
*/ */
// ---------------------------------------------------------------------------
struct aiMemoryInfo struct aiMemoryInfo
{ {
#ifdef __cplusplus #ifdef __cplusplus
@ -276,6 +309,8 @@ struct aiMemoryInfo
, meshes (0) , meshes (0)
, nodes (0) , nodes (0)
, animations (0) , animations (0)
, cameras (0)
, lights (0)
, total (0) , total (0)
{} {}
@ -283,14 +318,25 @@ struct aiMemoryInfo
//! Storage allocated for texture data, in bytes //! Storage allocated for texture data, in bytes
unsigned int textures; unsigned int textures;
//! Storage allocated for material data, in bytes //! Storage allocated for material data, in bytes
unsigned int materials; unsigned int materials;
//! Storage allocated for mesh data, in bytes //! Storage allocated for mesh data, in bytes
unsigned int meshes; unsigned int meshes;
//! Storage allocated for node data, in bytes //! Storage allocated for node data, in bytes
unsigned int nodes; unsigned int nodes;
//! Storage allocated for animation data, in bytes //! Storage allocated for animation data, in bytes
unsigned int animations; unsigned int animations;
//! Storage allocated for camera data, in bytes
unsigned int cameras;
//! Storage allocated for light data, in bytes
unsigned int lights;
//! Storage allocated for the import, in bytes //! Storage allocated for the import, in bytes
unsigned int total; unsigned int total;
}; };
@ -299,5 +345,12 @@ struct aiMemoryInfo
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif //! __cplusplus #endif //! __cplusplus
// Include implementations
#include "aiVector3D.inl"
#include "aiMatrix3x3.inl"
#include "aiMatrix4x4.inl"
#endif //!! include guard #endif //!! include guard

View File

@ -244,7 +244,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[i]; AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[i];
switch (this->m_pcCurrentTexture->iType) switch (this->m_pcCurrentTexture->iType)
{ {
case AI_TEXTYPE_DIFFUSE: case aiTextureType_DIFFUSE:
if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture != piTexture) if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture != piTexture)
{ {
pcMesh->piDiffuseTexture->Release(); pcMesh->piDiffuseTexture->Release();
@ -257,7 +257,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
} }
} }
break; break;
case AI_TEXTYPE_AMBIENT: case aiTextureType_AMBIENT:
if (pcMesh->piAmbientTexture && pcMesh->piAmbientTexture != piTexture) if (pcMesh->piAmbientTexture && pcMesh->piAmbientTexture != piTexture)
{ {
pcMesh->piAmbientTexture->Release(); pcMesh->piAmbientTexture->Release();
@ -270,7 +270,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
} }
} }
break; break;
case AI_TEXTYPE_SPECULAR: case aiTextureType_SPECULAR:
if (pcMesh->piSpecularTexture && pcMesh->piSpecularTexture != piTexture) if (pcMesh->piSpecularTexture && pcMesh->piSpecularTexture != piTexture)
{ {
pcMesh->piSpecularTexture->Release(); pcMesh->piSpecularTexture->Release();
@ -283,7 +283,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
} }
} }
break; break;
case AI_TEXTYPE_EMISSIVE: case aiTextureType_EMISSIVE:
if (pcMesh->piEmissiveTexture && pcMesh->piEmissiveTexture != piTexture) if (pcMesh->piEmissiveTexture && pcMesh->piEmissiveTexture != piTexture)
{ {
pcMesh->piEmissiveTexture->Release(); pcMesh->piEmissiveTexture->Release();
@ -296,7 +296,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
} }
} }
break; break;
case AI_TEXTYPE_SHININESS: case aiTextureType_SHININESS:
if (pcMesh->piShininessTexture && pcMesh->piShininessTexture != piTexture) if (pcMesh->piShininessTexture && pcMesh->piShininessTexture != piTexture)
{ {
pcMesh->piShininessTexture->Release(); pcMesh->piShininessTexture->Release();
@ -309,8 +309,8 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
} }
} }
break; break;
case AI_TEXTYPE_NORMALS: case aiTextureType_NORMALS:
case AI_TEXTYPE_HEIGHT: case aiTextureType_HEIGHT:
if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture) if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture)
{ {
pcMesh->piNormalTexture->Release(); pcMesh->piNormalTexture->Release();
@ -325,7 +325,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
} }
} }
break; break;
default: //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000: default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000:
if (pcMesh->piOpacityTexture && pcMesh->piOpacityTexture != piTexture) if (pcMesh->piOpacityTexture && pcMesh->piOpacityTexture != piTexture)
{ {
pcMesh->piOpacityTexture->Release(); pcMesh->piOpacityTexture->Release();
@ -340,42 +340,44 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
break; break;
}; };
} }
// now update the material itself // now update the material itself
aiString szOld; aiString szOld;
const char* szKey = NULL; const char* szKey = NULL;
#if 0
switch (this->m_pcCurrentTexture->iType) switch (this->m_pcCurrentTexture->iType)
{ {
case AI_TEXTYPE_DIFFUSE: case aiTextureType_DIFFUSE:
szKey = AI_MATKEY_TEXTURE_DIFFUSE(0); szKey = AI_MATKEY_TEXTURE_DIFFUSE(0);
break; break;
case AI_TEXTYPE_AMBIENT: case aiTextureType_AMBIENT:
szKey = AI_MATKEY_TEXTURE_AMBIENT(0); szKey = AI_MATKEY_TEXTURE_AMBIENT(0);
break; break;
case AI_TEXTYPE_SPECULAR: case aiTextureType_SPECULAR:
szKey = AI_MATKEY_TEXTURE_SPECULAR(0); szKey = AI_MATKEY_TEXTURE_SPECULAR(0);
break; break;
case AI_TEXTYPE_EMISSIVE: case aiTextureType_EMISSIVE:
szKey = AI_MATKEY_TEXTURE_EMISSIVE(0); szKey = AI_MATKEY_TEXTURE_EMISSIVE(0);
break; break;
case AI_TEXTYPE_NORMALS: case aiTextureType_NORMALS:
szKey = AI_MATKEY_TEXTURE_NORMALS(0); szKey = AI_MATKEY_TEXTURE_NORMALS(0);
break; break;
case AI_TEXTYPE_HEIGHT: case aiTextureType_HEIGHT:
szKey = AI_MATKEY_TEXTURE_HEIGHT(0); szKey = AI_MATKEY_TEXTURE_HEIGHT(0);
break; break;
case AI_TEXTYPE_SHININESS: case aiTextureType_SHININESS:
szKey = AI_MATKEY_TEXTURE_SHININESS(0); szKey = AI_MATKEY_TEXTURE_SHININESS(0);
break; break;
default: //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000: default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000:
szKey = AI_MATKEY_TEXTURE_OPACITY(0); szKey = AI_MATKEY_TEXTURE_OPACITY(0);
break; break;
}; };
#endif
ai_assert(NULL != szKey); ai_assert(NULL != szKey);
aiGetMaterialString(pcMat,szKey,&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0),&szOld);
pcMat->AddProperty(&szString,szKey); pcMat->AddProperty(&szString,AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0));
#if 0
char szBuffer[512]; char szBuffer[512];
sprintf(szBuffer,"%s%s",szKey,"_old"); sprintf(szBuffer,"%s%s",szKey,"_old");
@ -388,6 +390,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
{ {
pcMat->RemoveProperty(szBuffer); pcMat->RemoveProperty(szBuffer);
} }
#endif
return 1; return 1;
} }
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
@ -426,31 +429,31 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType,
IDirect3DTexture9** piTexture; IDirect3DTexture9** piTexture;
switch (iType) switch (iType)
{ {
case AI_TEXTYPE_DIFFUSE: case aiTextureType_DIFFUSE:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture;
szType = "Diffuse"; szType = "Diffuse";
break; break;
case AI_TEXTYPE_SPECULAR: case aiTextureType_SPECULAR:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture;
szType = "Specular"; szType = "Specular";
break; break;
case AI_TEXTYPE_AMBIENT: case aiTextureType_AMBIENT:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture;
szType = "Ambient"; szType = "Ambient";
break; break;
case AI_TEXTYPE_EMISSIVE: case aiTextureType_EMISSIVE:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture;
szType = "Emissive"; szType = "Emissive";
break; break;
case AI_TEXTYPE_HEIGHT: case aiTextureType_HEIGHT:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
szType = "HeightMap"; szType = "HeightMap";
break; break;
case AI_TEXTYPE_NORMALS: case aiTextureType_NORMALS:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
szType = "NormalMap"; szType = "NormalMap";
break; break;
case AI_TEXTYPE_SHININESS: case aiTextureType_SHININESS:
piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture; piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture;
szType = "Shininess"; szType = "Shininess";
break; break;
@ -578,8 +581,8 @@ int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot,
(LPARAM)(LPTVINSERTSTRUCT)&sNew); (LPARAM)(LPTVINSERTSTRUCT)&sNew);
// for each texture in the list ... add it // for each texture in the list ... add it
// NOTE: This expects that AI_TEXTYPE_DIFFUSE is 7 // NOTE: This expects that aiTextureType_DIFFUSE is 7
ai_assert(7 == AI_TEXTYPE_DIFFUSE); ai_assert(7 == aiTextureType_DIFFUSE);
unsigned int iUV; unsigned int iUV;
float fBlend; float fBlend;
aiTextureOp eOp; aiTextureOp eOp;
@ -590,12 +593,12 @@ int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot,
unsigned int iNum = 0; unsigned int iNum = 0;
while (true) while (true)
{ {
if (AI_SUCCESS != aiGetMaterialTexture(pcMat,iNum,i, if (AI_SUCCESS != aiGetMaterialTexture(pcMat,(aiTextureType)i,iNum,
&szPath,&iUV,&fBlend,&eOp)) &szPath,NULL, &iUV,&fBlend,&eOp))
{ {
break; break;
} }
if (AI_TEXTYPE_OPACITY == i)bNoOpacity = false; if (aiTextureType_OPACITY == i)bNoOpacity = false;
AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh); AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
++iNum; ++iNum;
} }
@ -619,7 +622,7 @@ int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot,
{ {
// seems the diffuse texture contains alpha, therefore it has been // seems the diffuse texture contains alpha, therefore it has been
// added to the opacity channel, too. Add a special value ... // added to the opacity channel, too. Add a special value ...
AddTextureToDisplayList(AI_TEXTYPE_OPACITY | 0x40000000, AddTextureToDisplayList(aiTextureType_OPACITY | 0x40000000,
0,&szPath,hTexture,iUV,fBlend,eOp,iMesh); 0,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
} }
} }
@ -967,7 +970,7 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
ShowNormalUIComponents(); ShowNormalUIComponents();
} }
if ((AI_TEXTYPE_OPACITY | 0x40000000) == pcNew->iType) if ((aiTextureType_OPACITY | 0x40000000) == pcNew->iType)
{ {
// for opacity textures display a warn message // for opacity textures display a warn message
CLogDisplay::Instance().AddEntry("[INFO] This texture is not existing in the " CLogDisplay::Instance().AddEntry("[INFO] This texture is not existing in the "
@ -1204,7 +1207,7 @@ int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR")); g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR"));
} }
} }
szMatKey = AI_MATKEY_COLOR_DIFFUSE; szMatKey = "$clr.diffuse";
break; break;
case ID_SOLONG_CLEARSPECULARCOLOR: case ID_SOLONG_CLEARSPECULARCOLOR:
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
@ -1215,7 +1218,7 @@ int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
g_pcAsset->apcMeshes[i],"SPECULAR_COLOR")); g_pcAsset->apcMeshes[i],"SPECULAR_COLOR"));
} }
} }
szMatKey = AI_MATKEY_COLOR_SPECULAR; szMatKey = "$clr.specular";
break; break;
case ID_SOLONG_CLEARAMBIENTCOLOR: case ID_SOLONG_CLEARAMBIENTCOLOR:
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
@ -1226,7 +1229,7 @@ int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
g_pcAsset->apcMeshes[i],"AMBIENT_COLOR")); g_pcAsset->apcMeshes[i],"AMBIENT_COLOR"));
} }
} }
szMatKey = AI_MATKEY_COLOR_AMBIENT; szMatKey = "$clr.ambient";
break; break;
case ID_SOLONG_CLEAREMISSIVECOLOR: case ID_SOLONG_CLEAREMISSIVECOLOR:
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
@ -1237,7 +1240,7 @@ int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
g_pcAsset->apcMeshes[i],"EMISSIVE_COLOR")); g_pcAsset->apcMeshes[i],"EMISSIVE_COLOR"));
} }
} }
szMatKey = AI_MATKEY_COLOR_EMISSIVE; szMatKey = "$clr.emissive";
break; break;
default: default:
@ -1283,7 +1286,7 @@ int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
// change the material key ... // change the material key ...
Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)g_pcAsset->pcScene->mMaterials[ Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)g_pcAsset->pcScene->mMaterials[
this->m_pcCurrentMaterial->iIndex]; this->m_pcCurrentMaterial->iIndex];
pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey); pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey,0,0);
if (ID_SOLONG_CLEARSPECULARCOLOR == LOWORD(wParam) && if (ID_SOLONG_CLEARSPECULARCOLOR == LOWORD(wParam) &&
aiShadingMode_Gouraud == apclrOut.front().pMesh->eShadingMode) aiShadingMode_Gouraud == apclrOut.front().pMesh->eShadingMode)
@ -1420,35 +1423,35 @@ int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam)
switch (this->m_pcCurrentTexture->iType) switch (this->m_pcCurrentTexture->iType)
{ {
case AI_TEXTYPE_DIFFUSE: case aiTextureType_DIFFUSE:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_DIFFUSE(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_DIFFUSE(0));
break; break;
case AI_TEXTYPE_SPECULAR: case aiTextureType_SPECULAR:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SPECULAR(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SPECULAR(0));
break; break;
case AI_TEXTYPE_AMBIENT: case aiTextureType_AMBIENT:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_AMBIENT(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_AMBIENT(0));
break; break;
case AI_TEXTYPE_EMISSIVE: case aiTextureType_EMISSIVE:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_EMISSIVE(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_EMISSIVE(0));
break; break;
case AI_TEXTYPE_NORMALS: case aiTextureType_NORMALS:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_NORMALS(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_NORMALS(0));
break; break;
case AI_TEXTYPE_HEIGHT: case aiTextureType_HEIGHT:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_HEIGHT(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_HEIGHT(0));
break; break;
case AI_TEXTYPE_SHININESS: case aiTextureType_SHININESS:
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SHININESS(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SHININESS(0));
break; break;
case (AI_TEXTYPE_OPACITY | 0x40000000): case (aiTextureType_OPACITY | 0x40000000):
// set a special property to indicate that no alpha channel is required // set a special property to indicate that no alpha channel is required
{int iVal = 1; {int iVal = 1;
pcMat->AddProperty<int>(&iVal,1,"no_a_from_d");} pcMat->AddProperty<int>(&iVal,1,"no_a_from_d",0,0);}
break; break;
default: //case AI_TEXTYPE_OPACITY default: //case aiTextureType_OPACITY
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_OPACITY(0)); pcMat->RemoveProperty(AI_MATKEY_TEXTURE_OPACITY(0));
}; };
@ -1505,41 +1508,42 @@ int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam)
TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),this->m_hRoot,TVGN_CARET); TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),this->m_hRoot,TVGN_CARET);
return 1; return 1;
} }
#if 0
case ID_HEY_RESETTEXTURE: case ID_HEY_RESETTEXTURE:
{ {
aiString szOld; aiString szOld;
aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex]; aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex];
switch (this->m_pcCurrentTexture->iType) switch (this->m_pcCurrentTexture->iType)
{ {
case AI_TEXTYPE_DIFFUSE: case aiTextureType_DIFFUSE:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0) "_old",&szOld);
break; break;
case AI_TEXTYPE_SPECULAR: case aiTextureType_SPECULAR:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0) "_old",&szOld);
break; break;
case AI_TEXTYPE_AMBIENT: case aiTextureType_AMBIENT:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0) "_old",&szOld);
break; break;
case AI_TEXTYPE_EMISSIVE: case aiTextureType_EMISSIVE:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0) "_old",&szOld);
break; break;
case AI_TEXTYPE_NORMALS: case aiTextureType_NORMALS:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0) "_old",&szOld);
break; break;
case AI_TEXTYPE_HEIGHT: case aiTextureType_HEIGHT:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0) "_old",&szOld);
break; break;
case AI_TEXTYPE_SHININESS: case aiTextureType_SHININESS:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0) "_old",&szOld);
break; break;
default : //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000: default : //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000:
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0) "_old",&szOld); aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0) "_old",&szOld);
break; break;
}; };
if (0 != szOld.length)this->ReplaceCurrentTexture(szOld.data); if (0 != szOld.length)this->ReplaceCurrentTexture(szOld.data);
return 1; return 1;
} }
#endif
} }
return 0; return 0;
} }
@ -2195,11 +2199,11 @@ int CDisplay::RenderTextureView()
// commit the texture to the shader // commit the texture to the shader
g_piPassThroughEffect->SetTexture("TEXTURE_2D",*this->m_pcCurrentTexture->piTexture); g_piPassThroughEffect->SetTexture("TEXTURE_2D",*this->m_pcCurrentTexture->piTexture);
if (AI_TEXTYPE_OPACITY == this->m_pcCurrentTexture->iType) if (aiTextureType_OPACITY == this->m_pcCurrentTexture->iType)
{ {
g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR"); g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR");
} }
else if ((AI_TEXTYPE_OPACITY | 0x40000000) == this->m_pcCurrentTexture->iType) else if ((aiTextureType_OPACITY | 0x40000000) == this->m_pcCurrentTexture->iType)
{ {
g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA"); g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA");
} }
@ -2212,8 +2216,8 @@ int CDisplay::RenderTextureView()
g_piPassThroughEffect->Begin(&dw,0); g_piPassThroughEffect->Begin(&dw,0);
g_piPassThroughEffect->BeginPass(0); g_piPassThroughEffect->BeginPass(0);
if (AI_TEXTYPE_HEIGHT == this->m_pcCurrentTexture->iType || if (aiTextureType_HEIGHT == this->m_pcCurrentTexture->iType ||
AI_TEXTYPE_NORMALS == this->m_pcCurrentTexture->iType) aiTextureType_NORMALS == this->m_pcCurrentTexture->iType)
{ {
// manually disable alpha blending // manually disable alpha blending
g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE); g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);

View File

@ -786,6 +786,9 @@ int CMaterialManager::CreateMaterial(
aiString szPath; aiString szPath;
aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap);
bool bib =false;
if (pcSource->mTextureCoords[0]) if (pcSource->mTextureCoords[0])
{ {
@ -795,6 +798,9 @@ int CMaterialManager::CreateMaterial(
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath))
{ {
LoadTexture(&pcMesh->piDiffuseTexture,&szPath); LoadTexture(&pcMesh->piDiffuseTexture,&szPath);
aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
} }
if (pcSource->mTextureCoords[1]) if (pcSource->mTextureCoords[1])
@ -833,7 +839,7 @@ int CMaterialManager::CreateMaterial(
// NOTE: This special value is set by the tree view if the user // NOTE: This special value is set by the tree view if the user
// manually removes the alpha texture from the view ... // manually removes the alpha texture from the view ...
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",&iVal)) if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",0,0,&iVal))
{ {
pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture; pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
pcMesh->piOpacityTexture->AddRef(); pcMesh->piOpacityTexture->AddRef();
@ -879,6 +885,7 @@ int CMaterialManager::CreateMaterial(
{ {
LoadTexture(&pcMesh->piNormalTexture,&szPath); LoadTexture(&pcMesh->piNormalTexture,&szPath);
} }
else bib = true;
bHM = true; bHM = true;
} }
@ -968,6 +975,28 @@ int CMaterialManager::CreateMaterial(
sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE"; sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE";
sMacro[iCurrent].Definition = "1"; sMacro[iCurrent].Definition = "1";
++iCurrent; ++iCurrent;
if (mapU == aiTextureMapMode_Wrap)
sMacro[iCurrent].Name = "AV_WRAPU";
else if (mapU == aiTextureMapMode_Mirror)
sMacro[iCurrent].Name = "AV_MIRRORU";
else // if (mapU == aiTextureMapMode_Clamp)
sMacro[iCurrent].Name = "AV_CLAMPU";
sMacro[iCurrent].Definition = "1";
++iCurrent;
if (mapV == aiTextureMapMode_Wrap)
sMacro[iCurrent].Name = "AV_WRAPV";
else if (mapV == aiTextureMapMode_Mirror)
sMacro[iCurrent].Name = "AV_MIRRORV";
else // if (mapV == aiTextureMapMode_Clamp)
sMacro[iCurrent].Name = "AV_CLAMPV";
sMacro[iCurrent].Definition = "1";
++iCurrent;
} }
if (pcMesh->piDiffuseTexture2) if (pcMesh->piDiffuseTexture2)
{ {
@ -993,7 +1022,7 @@ int CMaterialManager::CreateMaterial(
sMacro[iCurrent].Definition = "1"; sMacro[iCurrent].Definition = "1";
++iCurrent; ++iCurrent;
} }
if (pcMesh->piNormalTexture) if (pcMesh->piNormalTexture && !bib)
{ {
sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE"; sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE";
sMacro[iCurrent].Definition = "1"; sMacro[iCurrent].Definition = "1";

View File

@ -530,6 +530,24 @@ std::string g_szMaterialShader = std::string(
"sampler DIFFUSE_SAMPLER\n" "sampler DIFFUSE_SAMPLER\n"
"{\n" "{\n"
"Texture = <DIFFUSE_TEXTURE>;\n" "Texture = <DIFFUSE_TEXTURE>;\n"
"#ifdef AV_WRAPU\n"
"AddressU = WRAP;\n"
"#endif\n"
"#ifdef AV_MIRRORU\n"
"AddressU = MIRROR;\n"
"#endif\n"
"#ifdef AV_CLAMPU\n"
"AddressU = CLAMP;\n"
"#endif\n"
"#ifdef AV_WRAPV\n"
"AddressV = WRAP;\n"
"#endif\n"
"#ifdef AV_MIRRORV\n"
"AddressV = MIRROR;\n"
"#endif\n"
"#ifdef AV_CLAMPV\n"
"AddressV = CLAMP;\n"
"#endif\n"
"MinFilter=LINEAR;\n" "MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n" "MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n" "MipFilter=LINEAR;\n"

View File

@ -140,7 +140,8 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes
aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality
| aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType | | aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType |
aiProcess_FindDegenerates | aiProcess_FindInvalidData); // validate the output data structure aiProcess_FindDegenerates | aiProcess_FindInvalidData |
aiProcess_GenUVCoords | aiProcess_TransformUVCoords ); // validate the output data structure
// get the end time of zje operation, calculate delta t // get the end time of zje operation, calculate delta t
double fEnd = (double)timeGetTime(); double fEnd = (double)timeGetTime();

View File

@ -726,6 +726,10 @@
RelativePath="..\..\include\BoostWorkaround\boost\format.hpp" RelativePath="..\..\include\BoostWorkaround\boost\format.hpp"
> >
</File> </File>
<File
RelativePath="..\..\include\BoostWorkaround\boost\scoped_array.h"
>
</File>
<File <File
RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp" RelativePath="..\..\include\BoostWorkaround\boost\scoped_ptr.hpp"
> >
@ -903,14 +907,6 @@
RelativePath="..\..\code\TargetAnimation.h" RelativePath="..\..\code\TargetAnimation.h"
> >
</File> </File>
<File
RelativePath="..\..\code\TextureTransform.cpp"
>
</File>
<File
RelativePath="..\..\code\TextureTransform.h"
>
</File>
<File <File
RelativePath="..\..\code\VertexTriangleAdjacency.cpp" RelativePath="..\..\code\VertexTriangleAdjacency.cpp"
> >
@ -1344,6 +1340,14 @@
<File <File
RelativePath="..\..\code\ACLoader.cpp" RelativePath="..\..\code\ACLoader.cpp"
> >
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
GeneratePreprocessedFile="0"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath="..\..\code\ACLoader.h" RelativePath="..\..\code\ACLoader.h"
@ -1454,6 +1458,14 @@
RelativePath="..\..\code\CalcTangentsProcess.h" RelativePath="..\..\code\CalcTangentsProcess.h"
> >
</File> </File>
<File
RelativePath="..\..\code\ComputeUVMappingProcess.cpp"
>
</File>
<File
RelativePath="..\..\code\ComputeUVMappingProcess.h"
>
</File>
<File <File
RelativePath="..\..\code\ConvertToLHProcess.cpp" RelativePath="..\..\code\ConvertToLHProcess.cpp"
> >
@ -1574,6 +1586,14 @@
RelativePath="..\..\code\SplitLargeMeshes.h" RelativePath="..\..\code\SplitLargeMeshes.h"
> >
</File> </File>
<File
RelativePath="..\..\code\TextureTransform.cpp"
>
</File>
<File
RelativePath="..\..\code\TextureTransform.h"
>
</File>
<File <File
RelativePath="..\..\code\TriangulateProcess.cpp" RelativePath="..\..\code\TriangulateProcess.cpp"
> >