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
#include "3DSLoader.h"
#include "TextureTransform.h"
#include "TargetAnimation.h"
using namespace Assimp;
@ -159,41 +158,60 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh)
// Generate out unique verbose format representation
void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh)
{
unsigned int iBase = 0;
// Allocate output storage
std::vector<aiVector3D> vNew (sMesh.mFaces.size() * 3);
std::vector<aiVector2D> vNew2;
if (sMesh.mTexCoords.size())vNew2.resize(sMesh.mFaces.size() * 3);
std::vector<aiVector3D> vNew2;
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
vNew[iBase] = sMesh.mPositions[sMesh.mFaces[i].mIndices[2]];
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())
// Positions
for (unsigned int a = 0; a < 3;++a,++base)
{
vNew2[iTemp1] = sMesh.mTexCoords[sMesh.mFaces[i].mIndices[2]];
vNew2[iTemp2] = sMesh.mTexCoords[sMesh.mFaces[i].mIndices[1]];
vNew2[iBase] = sMesh.mTexCoords[sMesh.mFaces[i].mIndices[0]];
}
vNew[base] = sMesh.mPositions[face.mIndices[a]];
if (sMesh.mTexCoords.size())
vNew2[base] = sMesh.mTexCoords[face.mIndices[a]];
sMesh.mFaces[i].mIndices[2] = iBase++;
sMesh.mFaces[i].mIndices[0] = iTemp1;
sMesh.mFaces[i].mIndices[1] = iTemp2;
face.mIndices[a] = base;
}
}
sMesh.mPositions = vNew;
sMesh.mTexCoords = vNew2;
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
void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
@ -207,12 +225,11 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
tex.Set( mBackgroundImage);
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("");
}
// At first add the base ambient color of the
// scene to the material
// At first add the base ambient color of the scene to the material
oldMat.mAmbient.r += mClrAmbient.r;
oldMat.mAmbient.g += mClrAmbient.g;
oldMat.mAmbient.b += mClrAmbient.b;
@ -221,13 +238,13 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
name.Set( oldMat.mName);
mat.AddProperty( &name, AI_MATKEY_NAME);
// material colors
// Material colors
mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
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 ||
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);
// bump height scaling
// Bump height scaling
mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
// two sided rendering?
// Two sided rendering?
if (oldMat.mTwoSided)
{
int i = 1;
mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
}
// shading mode
// Shading mode
aiShadingMode eShading = aiShadingMode_NoShading;
switch (oldMat.mShading)
{
@ -263,8 +280,14 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
eShading = aiShadingMode_Flat; break;
// 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:
{
// Set the wireframe flag
unsigned int iWire = 1;
mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
}
case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud; break;
@ -283,112 +306,29 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
}
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
if( oldMat.sTexDiffuse.mMapName.length() > 0)
{
aiString tex;
tex.Set( oldMat.sTexDiffuse.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE);
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
if( oldMat.sTexSpecular.mMapName.length() > 0)
{
aiString tex;
tex.Set( oldMat.sTexSpecular.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0));
CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR);
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
if( oldMat.sTexOpacity.mMapName.length() > 0)
{
aiString tex;
tex.Set( oldMat.sTexOpacity.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY(0));
CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY);
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
if( oldMat.sTexEmissive.mMapName.length() > 0)
{
aiString tex;
tex.Set( oldMat.sTexEmissive.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(0));
CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE);
if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend))
mat.AddProperty<float>( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0));
if (aiTextureMapMode_Clamp != oldMat.sTexEmissive.mMapMode)
{
int i = (int)oldMat.sTexEmissive.mMapMode;
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_EMISSIVE(0));
mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_EMISSIVE(0));
}
}
// BUMP texturee
// BUMP texture
if( oldMat.sTexBump.mMapName.length() > 0)
{
aiString tex;
tex.Set( oldMat.sTexBump.mMapName);
mat.AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0));
CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT);
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
if( oldMat.sTexShininess.mMapName.length() > 0)
{
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));
}
}
CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS);
// Store the name of the material itself, too
if( oldMat.mName.length())
@ -425,74 +365,51 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
// now generate submeshes
for (unsigned int p = 0; p < mScene->mMaterials.size();++p)
{
if (aiSplit[p].size() != 0)
if (aiSplit[p].size())
{
aiMesh* p_pcOut = new aiMesh();
p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
aiMesh* meshOut = new aiMesh();
meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
// be sure to setup the correct material index
p_pcOut->mMaterialIndex = p;
meshOut->mMaterialIndex = p;
// use the color data as temporary storage
p_pcOut->mColors[0] = (aiColor4D*)(&*i);
avOutMeshes.push_back(p_pcOut);
meshOut->mColors[0] = (aiColor4D*)(&*i);
avOutMeshes.push_back(meshOut);
// convert vertices
p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
p_pcOut->mNumVertices = p_pcOut->mNumFaces*3;
meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
meshOut->mNumVertices = meshOut->mNumFaces*3;
// allocate enough storage for faces
p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
iFaceCnt += p_pcOut->mNumFaces;
meshOut->mFaces = new aiFace[meshOut->mNumFaces];
iFaceCnt += meshOut->mNumFaces;
if (p_pcOut->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
meshOut->mVertices = new aiVector3D[meshOut->mNumVertices];
meshOut->mNormals = new aiVector3D[meshOut->mNumVertices];
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;
for (unsigned int q = 0; q < aiSplit[p].size();++q)
face.mIndices = new unsigned int[3];
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]];
p_pcOut->mTextureCoords[0][iBase++] = aiVector3D(pc->x,pc->y,0.0f);
if ((*i).mTexCoords.size())
meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx];
pc = &(*i).mTexCoords[(*i).mFaces[iIndex2].mIndices[1]];
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);
face.mIndices[a] = base;
}
// 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
if (!iFaceCnt)
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
void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
aiMatrix4x4& absTrafo)
void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
D3DS::Node* pcIn, aiMatrix4x4& absTrafo)
{
std::vector<unsigned int> iArray;
iArray.reserve(3);
@ -529,11 +438,12 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
aiMatrix4x4 abs;
if (pcIn->mName == "$$$DUMMY")
{
// Append the "real" name of the dummy to the string
pcIn->mName.append(pcIn->mDummyName);
// FIX: Append the "real" name of the dummy to the string
pcIn->mName = "Dummy." + pcIn->mDummyName;
}
else // if (pcIn->mName != "$$$DUMMY")
{
// Find all meshes with the same name as the node
for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
{
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())
{
// The matrix should be identical for all meshes with the same name.
// It HAS to be identical for all meshes ........
aiMatrix4x4& mTrafo = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
aiMatrix4x4 mInv = mTrafo;
if (!configSkipPivot)
mInv.Inverse();
// The matrix should be identical for all meshes with the
// same name. It HAS to be identical for all meshes .....
aiMatrix4x4 mInv = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
mInv.Inverse();
const aiVector3D& pivot = pcIn->vPivot;
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];
aiMesh* const mesh = pcSOut->mMeshes[iIndex];
// Pivot point adjustment.
// Pivot point adjustment
// See: http://www.zfx.info/DisplayThread.php?MID=235690#235690
const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices;
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->x -= pivot.x;
pvCurrent->y -= pivot.y;
pvCurrent->z -= pivot.z;
++pvCurrent;
*pvCurrent -= pivot;
}
}
else
{
while (pvCurrent != pvEnd)
{
for (;pvCurrent != pvEnd;++pvCurrent)
*pvCurrent = mInv * (*pvCurrent);
++pvCurrent;
}
}
// Setup the mesh index
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 ...");
//// Camera or spot light - need to convert the separate
//// target position channel to our representation
//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);
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
sizeof(aiVectorKey)*nda->mNumPositionKeys);
}
// Just for safety ... we *should* have at least one track here
if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 ||
pcIn->aScalingKeys.size() > 1)
// ROTATION keys
if (pcIn->aRotationKeys.size() > 0)
{
// Allocate a new nda, increment the nda index
aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
nda->mNodeName.Set(pcIn->mName);
nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
// POSITION keys
if (pcIn->aPositionKeys.size() > 0)
// Rotations are quaternion offsets
aiQuaternion abs;
for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
{
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
sizeof(aiVectorKey)*nda->mNumPositionKeys);
}
const aiQuatKey& q = pcIn->aRotationKeys[n];
// ROTATION keys
if (pcIn->aRotationKeys.size() > 0)
{
nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
::memcpy(nda->mRotationKeys,&pcIn->aRotationKeys[0],
sizeof(aiQuatKey)*nda->mNumRotationKeys);
abs = (n ? abs * q.mValue : q.mValue);
nda->mRotationKeys[n].mTime = q.mTime;
nda->mRotationKeys[n].mValue = abs.Normalize();
}
}
// SCALING keys
if (pcIn->aScalingKeys.size() > 0)
{
nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
sizeof(aiVectorKey)*nda->mNumScalingKeys);
}
// SCALING keys
if (pcIn->aScalingKeys.size() > 0)
{
nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
sizeof(aiVectorKey)*nda->mNumScalingKeys);
}
}
@ -864,14 +773,6 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
pcOld->mChildren[0] = NULL;
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.
http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */
/** @file Defines helper data structures for the import of 3DS files */
#ifndef 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 "SmoothingGroups.h"
@ -66,12 +56,13 @@ namespace D3DS {
/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
* and data structures.
*/
// ---------------------------------------------------------------------------
class Discreet3DS
{
public:
private:
inline Discreet3DS() {}
public:
//! data structure for a single chunk in a .3ds file
struct Chunk
{
@ -79,10 +70,6 @@ public:
uint32_t Size;
} 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
//! From AutoDesk 3ds SDK
@ -301,26 +288,22 @@ public:
};
};
#include "./../include/Compiler/poppack1.h"
// ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */
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 */
struct Texture
{
//! Default constructor
Texture()
: mScaleU (1.0f)
, mScaleV (1.0f)
, mOffsetU (0.0f)
: mOffsetU (0.0f)
, mOffsetV (0.0f)
, mScaleU (1.0f)
, mScaleV (1.0f)
, mRotation (0.0f)
, mMapMode (aiTextureMapMode_Wrap)
, iUVSrc (0)
@ -335,10 +318,10 @@ struct Texture
std::string mMapName;
//! Specifies texture coordinate offsets/scaling/rotations
float mScaleU;
float mScaleV;
float mOffsetU;
float mOffsetV;
float mScaleU;
float mScaleV;
float mRotation;
//! Specifies the mapping mode to be used for the texture
@ -348,6 +331,9 @@ struct Texture
bool bPrivate;
int iUVSrc;
};
#include "./../include/Compiler/poppack1.h"
// ---------------------------------------------------------------------------
/** Helper structure representing a 3ds material */
struct Material
@ -414,6 +400,7 @@ struct Material
unsigned int iBakeUVTransform;
Texture* pcSingleTexture;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent a 3ds file mesh */
struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
@ -433,7 +420,7 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
std::string mName;
//! Texture coordinates
std::vector<aiVector2D> mTexCoords;
std::vector<aiVector3D> mTexCoords;
//! Face materials
std::vector<unsigned int> mFaceMaterials;

View File

@ -104,7 +104,7 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle
// Setup configuration properties
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
// vectors from the smoothing groups we read from the
// 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)
{
CheckIndices(*i);
@ -149,9 +149,6 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
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
// valid material. Generate it if no material containing
// DEFAULT in its name has been found in the file
@ -678,6 +675,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
}
else l = & mCurrentNode->aPositionKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i)
{
unsigned int fidx = stream->GetI2();
@ -724,6 +722,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
stream->IncPtr(10);
unsigned int numFrames = stream->GetI2();
l->reserve(numFrames);
stream->IncPtr(2);
for (unsigned int i = 0; i < numFrames;++i)
@ -776,6 +775,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
bool sortKeys = false;
std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i)
{
@ -825,6 +825,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
bool sortKeys = false;
std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys;
l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i)
{
@ -924,7 +925,7 @@ void Discreet3DSImporter::ParseFaceChunk()
}
// Now continue and read all material indices
cnt = stream->GetI2();
cnt = (uint16_t)stream->GetI2();
for (unsigned int i = 0; i < cnt;++i)
{
unsigned int fidx = (uint16_t)stream->GetI2();
@ -957,7 +958,8 @@ void Discreet3DSImporter::ParseMeshChunk()
case Discreet3DS::CHUNK_VERTLIST:
{
// 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)
{
aiVector3D v;
@ -985,8 +987,8 @@ void Discreet3DSImporter::ParseMeshChunk()
mMesh.mMat.c4 = stream->GetF4();
// Now check whether the matrix has got a negative determinant
// If yes, we need to flip all vertices' x axis ....
// From lib3ds, mesh.c
// If yes, we need to flip all vertices' Z axis ....
// This code has been taken from lib3ds
if (mMesh.mMat.Determinant() < 0.0f)
{
// Compute the inverse of the matrix
@ -994,10 +996,10 @@ void Discreet3DSImporter::ParseMeshChunk()
mInv.Inverse();
aiMatrix4x4 mMe = mMesh.mMat;
mMe.a1 *= -1.0f;
mMe.b1 *= -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;
// 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];
mMesh.mPositions[i] = c;
}
DefaultLogger::get()->info("3DS: Flipping mesh Z-Axis");
}}
break;
case Discreet3DS::CHUNK_MAPLIST:
{
// 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)
{
aiVector2D v;
aiVector3D v;
v.x = stream->GetF4();
v.y = stream->GetF4();
mMesh.mTexCoords.push_back(v);
@ -1029,7 +1034,8 @@ void Discreet3DSImporter::ParseMeshChunk()
case Discreet3DS::CHUNK_FACELIST:
{
// 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)
{
// 3DS faces are ALWAYS triangles
@ -1226,6 +1232,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
// recursively continue processing this hierarchy level
return ParseMaterialChunk();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
{
@ -1262,7 +1269,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
if (0.0f == pcOut->mScaleU)
{
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;
}
break;
@ -1272,14 +1279,14 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
if (0.0f == pcOut->mScaleV)
{
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;
}
break;
case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
// Texture coordinate offset in the U direction
pcOut->mOffsetU = stream->GetF4();
pcOut->mOffsetU = -stream->GetF4();
break;
case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
@ -1288,24 +1295,24 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
break;
case Discreet3DS::CHUNK_MAT_MAP_ANG:
// Texture coordinate rotation, CCW in radians
pcOut->mRotation = stream->GetF4();
// Texture coordinate rotation, CCW in DEGREES
pcOut->mRotation = -AI_DEG_TO_RAD( stream->GetF4() );
break;
case Discreet3DS::CHUNK_MAT_MAP_TILING:
{
uint16_t iFlags = stream->GetI2();
// check whether the mirror flag is set
// Get the mapping mode (for both axes)
if (iFlags & 0x2u)
{
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;
};

View File

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

View File

@ -151,11 +151,30 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
if (!TokenMatch(buffer,"OBJECT",6))
return;
SkipSpaces(&buffer);
++mNumMeshes;
objects.push_back(Object());
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())
{
if (TokenMatch(buffer,"kids",4))
@ -176,6 +195,13 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
{
SkipSpaces(&buffer);
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))
{
@ -219,8 +245,6 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
obj.vertices.push_back(aiVector3D());
aiVector3D& v = obj.vertices.back();
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))
@ -597,7 +621,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
node->mTransformation = aiMatrix4x4 ( object.rotation );
node->mTransformation.a4 = object.translation.x;
node->mTransformation.b4 = object.translation.y;
node->mTransformation.b4 = -object.translation.y;
node->mTransformation.c4 = object.translation.z;
return node;
@ -644,6 +668,9 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
std::vector<Object> rootObjects;
rootObjects.reserve(5);
std::vector<aiLight*> lights;
mLights = & lights;
while (GetNextLine())
{
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("amb",3,3,&mat.rgb);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.rgb);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.rgb);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
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("trans",5,1,&mat.trans);
}
@ -701,6 +728,9 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
if (1 != rootObjects.size())delete root;
if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
pScene->mRootNode->mName.Set("<AC3DWorld>");
// build output arrays
if (meshes.empty())
{
@ -710,10 +740,17 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
// build output arrays
pScene->mNumMaterials = (unsigned int)omaterials.size();
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
::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

View File

@ -236,6 +236,9 @@ private:
// basing on this information we can find a
// good estimate how many meshes we'll have in the final scene.
unsigned int mNumMeshes;
// current list of light sources
std::vector<aiLight*>* mLights;
};
} // 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 "MaterialSystem.h"
#include "StringComparison.h"
#include "TextureTransform.h"
#include "SkeletonMeshBuilder.h"
#include "TargetAnimation.h"
// utilities
#include "fast_atof.h"
#include "qnan.h"
using namespace Assimp;
using namespace Assimp::ASE;
@ -156,15 +155,15 @@ void ASEImporter::InternReadFile( const std::string& pFile,
std::vector<aiMesh*> avOutMeshes;
avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
for (std::vector<ASE::Mesh>::iterator
i = mParser->m_vMeshes.begin();
i != mParser->m_vMeshes.end();++i)
i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i)
{
if ((*i).bSkip)continue;
// Now we need to create proper meshes from the import we
// need to split them by materials, build valid vertex/
// face lists ...
BuildUniqueRepresentation(*i);
// First of all - we need to build an unique mesh representation
// that we can recompute the normal vectors easily. This is
// also a prerequisite for the second code path in ConvertMeshes()
// so it's difficult to optimize it away. TODO!
BuildUniqueRepresentation(*i);
// Need to generate proper vertex normals if necessary
if(GenerateNormals(*i))
@ -305,8 +304,12 @@ void ASEImporter::BuildAnimations()
// that represent the node transformation.
if ((*i)->mAnim.akeyPositions.size() > 1 ||
(*i)->mAnim.akeyRotations.size() > 1 ||
(*i)->mAnim.akeyScaling.size() > 1 ||
(*i)->mTargetAnim.akeyPositions.size() > 1
(*i)->mAnim.akeyScaling.size() > 1)
{
++iNum;
}
if ((*i)->mTargetAnim.akeyPositions.size() > 1
&& is_not_qnan( (*i)->mTargetPosition.x ))
{
++iNum;
@ -337,6 +340,21 @@ void ASEImporter::BuildAnimations()
aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
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
nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size();
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
@ -345,7 +363,8 @@ void ASEImporter::BuildAnimations()
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
aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
@ -424,8 +443,6 @@ void ASEImporter::BuildCameras()
out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
out->mHorizontalFOV = in.mFOV;
// TODO: Implement proper camera target
out->mName.Set(in.mName);
}
}
@ -480,7 +497,7 @@ void ASEImporter::AddNodes(std::vector<BaseNode*>& nodes,
aiNode* pcParent,const char* szName)
{
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();
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
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*
// node's animation track but the exact target position
// would be lost otherwise)
apcNodes.push_back(new aiNode());
aiNode* node = apcNodes.back();
if (!node->mNumChildren)
{
node->mChildren = new aiNode*[1];
}
node->mName.Set ( snode->mName + ".Target" );
node->mTransformation.a4 = snode->mTargetPosition.x;
node->mTransformation.b4 = snode->mTargetPosition.y;
node->mTransformation.c4 = snode->mTargetPosition.z;
aiNode* nd = new aiNode();
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
// aiMatrix4x4 mNewAbs = mat * node->mTransformation;
nd->mParent = node;
// prevent stack overflow
if (node->mName != node->mParent->mName)
{
AddNodes(nodes,node,node->mName.data,snode->mTransform);
// The .Target node is always the first child node
for (unsigned int m = 0; m < node->mNumChildren;++m)
node->mChildren[m+1] = node->mChildren[m];
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();
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
for (unsigned int p = 0; p < apcNodes.size();++p)
{
pcParent->mChildren[p] = apcNodes[p];
}
}
return;
}
@ -643,7 +670,7 @@ void ASEImporter::BuildNodes()
pcScene->mRootNode = new aiNode();
pcScene->mRootNode->mNumMeshes = 0;
pcScene->mRootNode->mMeshes = 0;
pcScene->mRootNode->mName.Set("<root>");
pcScene->mRootNode->mName.Set("<ASERoot>");
// Setup the coordinate system transformation
//pcScene->mRootNode->mTransformation.c3 *= -1.f;
@ -708,7 +735,7 @@ void ASEImporter::BuildNodes()
{
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
aiNode* pcNode = new aiNode();
pcNode->mParent = pcScene->mRootNode;
@ -731,16 +758,18 @@ void ASEImporter::BuildNodes()
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
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
if (1 == pcScene->mRootNode->mNumChildren && !pcScene->mNumAnimations)
{
aiNode* cc = pcScene->mRootNode->mChildren[0];
aiNode* pc = pcScene->mRootNode;
if (!cc->mName.length)
cc->mName = pc->mName;
pcScene->mRootNode = cc;
pcScene->mRootNode->mParent = NULL;
cc->mTransformation = pc->mTransformation * cc->mTransformation;
cc->mParent = NULL;
// make sure the destructor won't delete us ...
delete[] pc->mChildren;
@ -803,17 +832,12 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
for (unsigned int n = 0; n < 3;++n,++iCurrent)
{
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
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
{
if (!mesh.amTexCoords[c].empty())
{
amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
// amTexCoords[c][iCurrent].y = 1.f- amTexCoords[c][iCurrent].y; // DX-to-OGL
}
if (mesh.amTexCoords[c].empty())break;
amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
}
// add vertex colors
if (!mesh.mVertexColors.empty())
@ -825,9 +849,6 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
{
mNormals[iCurrent] = mesh.mNormals[fi*3+n];
mNormals[iCurrent].Normalize();
//std::swap((float&)mNormals[iCurrent].z,(float&)mNormals[iCurrent].y); // DX-to-OGL
//mNormals[iCurrent].y *= -1.0f;
}
// handle bone vertices
@ -838,11 +859,9 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
// will fix that again ...)
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
@ -852,20 +871,37 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++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)
{
// allocate the output material
// LARGE TODO: Much code her is copied from 3DS ... join them maybe?
// Allocate the output material
mat.pcInstance = new MaterialHelper();
// At first add the base ambient color of the
// scene to the material
mat.mAmbient.r += this->mParser->m_clrAmbient.r;
mat.mAmbient.g += this->mParser->m_clrAmbient.g;
mat.mAmbient.b += this->mParser->m_clrAmbient.b;
mat.mAmbient.r += mParser->m_clrAmbient.r;
mat.mAmbient.g += mParser->m_clrAmbient.g;
mat.mAmbient.b += mParser->m_clrAmbient.b;
aiString name;
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.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 ||
D3DS::Discreet3DS::Phong == mat.mShading ||
D3DS::Discreet3DS::Blinn == mat.mShading)
@ -894,6 +930,12 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
// 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
aiShadingMode eShading = aiShadingMode_NoShading;
@ -906,9 +948,14 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
case D3DS::Discreet3DS::Blinn :
eShading = aiShadingMode_Blinn; break;
// I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse (L dot N) shading
// I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse (L dot N) shading
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:
eShading = aiShadingMode_Gouraud; break;
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);
if (D3DS::Discreet3DS::Wire == mat.mShading)
{
// set the wireframe flag
unsigned int iWire = 1;
mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
}
// texture, if there is one
// DIFFUSE texture
if( mat.sTexDiffuse.mMapName.length() > 0)
{
aiString tex;
tex.Set( mat.sTexDiffuse.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE);
if (is_not_qnan(mat.sTexDiffuse.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexDiffuse.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_DIFFUSE(0));
}
// SPECULAR texture
if( mat.sTexSpecular.mMapName.length() > 0)
{
aiString tex;
tex.Set( mat.sTexSpecular.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(0));
CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR);
if (is_not_qnan(mat.sTexSpecular.mTextureBlend))
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));
}
// AMBIENT texture
if( mat.sTexAmbient.mMapName.length() > 0)
{
aiString tex;
tex.Set( mat.sTexAmbient.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(0));
CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT);
if (is_not_qnan(mat.sTexAmbient.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexAmbient.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_AMBIENT(0));
}
// OPACITY texture
if( mat.sTexOpacity.mMapName.length() > 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)
{
aiString tex;
tex.Set( mat.sTexBump.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(0));
CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT);
if (is_not_qnan(mat.sTexBump.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexBump.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_HEIGHT(0));
}
// SHININESS texture
if( mat.sTexShininess.mMapName.length() > 0)
{
aiString tex;
tex.Set( mat.sTexShininess.mMapName);
mat.pcInstance->AddProperty( &tex, AI_MATKEY_TEXTURE_SHININESS(0));
if (is_not_qnan(mat.sTexShininess.mTextureBlend))
mat.pcInstance->AddProperty<float>( &mat.sTexBump.mTextureBlend, 1,
AI_MATKEY_TEXBLEND_SHININESS(0));
}
CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS);
// store the name of the material itself, too
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];
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].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];
@ -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)
@ -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]];
}
}
// setup the number of valid vertex components
// Setup the number of valid vertex components
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())
{
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())
{
p_pcOut->mNumBones = 0;
@ -1211,7 +1203,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
p_pcOut->mColors[2] = (aiColor4D*) &mesh;
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
// helper object which we are going to remove later ...
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].mIndices = new unsigned int[3];
// copy indices (flip the face order, too)
p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[2];
// copy indices
p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[0];
p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
}
// copy vertex bones
@ -1328,23 +1320,20 @@ void ASEImporter::BuildMaterialIndices()
// iterate through all materials and check whether we need them
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
ASE::Material& mat = mParser->m_vMaterials[iMat];
// Convert it to the aiMaterial layout
ConvertMaterial(mat);
TextureTransform::ApplyScaleNOffset(mat);
++pcScene->mNumMaterials;
}
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)
{
// convert it to the aiMaterial layout
ASE::Material& mat = mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
ConvertMaterial(mat);
TextureTransform::ApplyScaleNOffset(mat);
// Convert it to the aiMaterial layout
ConvertMaterial(submat);
++pcScene->mNumMaterials;
}
}
@ -1357,77 +1346,60 @@ void ASEImporter::BuildMaterialIndices()
unsigned int iNum = 0;
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);
pcScene->mMaterials[iNum] = mParser->m_vMaterials[iMat].pcInstance;
ai_assert(NULL != mat.pcInstance);
pcScene->mMaterials[iNum] = mat.pcInstance;
// store the internal material, too
pcIntMaterials[iNum] = &mParser->m_vMaterials[iMat];
// Store the internal material, too
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
for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
{
if (ASE::Face::DEFAULT_MATINDEX == pcScene->mMeshes[iMesh]->mMaterialIndex &&
iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3])
aiMesh* mesh = pcScene->mMeshes[iMesh];
if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex &&
iMat == (uintptr_t)mesh->mColors[3])
{
pcScene->mMeshes[iMesh]->mMaterialIndex = iNum;
pcScene->mMeshes[iMesh]->mColors[3] = NULL;
mesh->mMaterialIndex = iNum;
mesh->mColors[3] = NULL;
}
}
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);
pcScene->mMaterials[iNum] = mParser->m_vMaterials[iMat].
avSubMaterials[iSubMat].pcInstance;
ai_assert(NULL != submat.pcInstance);
pcScene->mMaterials[iNum] = submat.pcInstance;
// store the internal material, too
pcIntMaterials[iNum] = &mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
// Store the internal material, too
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
for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
{
if (iSubMat == pcScene->mMeshes[iMesh]->mMaterialIndex &&
iMat == (uintptr_t)pcScene->mMeshes[iMesh]->mColors[3])
aiMesh* mesh = pcScene->mMeshes[iMesh];
if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3])
{
pcScene->mMeshes[iMesh]->mMaterialIndex = iNum;
pcScene->mMeshes[iMesh]->mColors[3] = NULL;
mesh->mMaterialIndex = iNum;
mesh->mColors[3] = NULL;
}
}
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,
// 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]);
}
// Dekete our temporary array
delete[] pcIntMaterials;
// finished!
return;
}
// ------------------------------------------------------------------------------------------------
// Generate normal vectors basing on smoothing groups
bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)
@ -1446,6 +1418,7 @@ bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)
}
}
}
// The array will be reused
ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
return false;

View File

@ -634,6 +634,12 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
mat.mSpecularExponent *= 15;
continue;
}
// two-sided material
if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
{
mat.mTwoSided = true;
continue;
}
// material shininess strength
if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
{
@ -1387,7 +1393,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
continue;
}
// Number of vertex colors in the mesh
if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,14))
if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
{
ParseLV4MeshLong(iNumCVertices);
continue;
@ -1877,44 +1883,38 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
{
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 ));
unsigned int iIndex = 0, faceIdx = 0xffffffff;
unsigned int index, faceIdx = 0xffffffff;
// ********************************************************************
// just smooth both vertex and face normals together, so it will still
// 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.
// ********************************************************************
// Smooth the vertex and face normals together. The result
// will be edgy then, but otherwise everything would be soft ...
while (true)
{
if ('*' == *filePtr)
{
++filePtr;
if (0xffffffff != faceIdx && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17))
if (faceIdx != 0xffffffff && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17))
{
aiVector3D vNormal;
ParseLV4MeshFloatTriple(&vNormal.x,iIndex);
ParseLV4MeshFloatTriple(&vNormal.x,index);
if (iIndex == sMesh.mFaces[faceIdx].mIndices[0])
{
iIndex = 0;
}
else if (iIndex == sMesh.mFaces[faceIdx].mIndices[1])
{
iIndex = 1;
}
else if (iIndex == sMesh.mFaces[faceIdx].mIndices[2])
{
iIndex = 2;
}
// Make sure we assign it to the correct face
const ASE::Face& face = sMesh.mFaces[faceIdx];
if (index == face.mIndices[0])
index = 0;
else if (index == face.mIndices[1])
index = 1;
else if (index == face.mIndices[2])
index = 2;
else
{
LogWarning("Normal index doesn't fit to face index");
DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
continue;
}
// We'll renormalize later
sMesh.mNormals[faceIdx*3 + iIndex] += vNormal;
sMesh.mNormals[faceIdx*3+index] += vNormal;
continue;
}
if (TokenMatch(filePtr,"MESH_FACENORMAL",15))
@ -1922,15 +1922,14 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
aiVector3D vNormal;
ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
if (iIndex >= sMesh.mFaces.size())
if (faceIdx >= sMesh.mFaces.size())
{
LogWarning("Face normal index is too large");
faceIdx = 0xffffffff;
DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
continue;
}
sMesh.mNormals[faceIdx*3] += vNormal;
sMesh.mNormals[faceIdx*3 +1] += vNormal;
sMesh.mNormals[faceIdx*3 +2] += vNormal;
// We'll renormalize later
sMesh.mNormals[faceIdx*3] += vNormal;
continue;
}
}
@ -2037,7 +2036,7 @@ void Parser::ParseLV4MeshFace(ASE::Face& out)
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
while (true)
{

View File

@ -82,6 +82,7 @@ struct Material : public D3DS::Material
//! Can we remove this material?
bool bNeed;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file face */
struct Face : public FaceWithSmoothingGroup
@ -175,12 +176,6 @@ struct Animation
, 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
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
# include "../include/BoostWorkaround/boost/scoped_ptr.hpp"
# include "../include/BoostWorkaround/boost/scoped_array.hpp"
# include "../include/BoostWorkaround/boost/format.hpp"
# include "../include/BoostWorkaround/boost/common_factor_rt.hpp"
#else
# include <boost/scoped_ptr.hpp>
# include <boost/scoped_array.hpp>
# include <boost/format.hpp>
# include <boost/math/common_factor_rt.hpp>

View File

@ -110,7 +110,7 @@ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler,
if (pStream.get() )
{
// 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();
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++)
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
for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
{
@ -155,6 +159,25 @@ void ConvertToLHProcess::Execute( aiScene* pScene)
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.
void ConvertToLHProcess::ProcessMesh( aiMesh* pMesh)

View File

@ -108,6 +108,13 @@ protected:
*/
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.
* 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.
face.mIndices[face.mNumIndices] = 0xdeadbeef;
if(first)
{
++deg;

View File

@ -284,7 +284,16 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
{
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
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
// they are invalid or not.
// 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
// Normals and tangents are undefined for point and line faces.
if (pMesh->mNormals || pMesh->mTangents)
{
if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
@ -322,8 +329,7 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes)
{
// we need the lookup table
dirtyMask.resize(pMesh->mNumVertices,false);
// We need to update the lookup-table
for (unsigned int m = 0; m < pMesh->mNumFaces;++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;
}
}
// Normals, tangents and bitangents are undefined for
// the whole mesh (and should not even be there)
else return ret;
}
// process mesh normals
// Process mesh normals
if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
"normals",dirtyMask,true,false))
ret = true;
// process mesh tangents
// Process mesh tangents
if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,
"tangents",dirtyMask))
{
delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
delete[] pMesh->mTangents; pMesh->mTangents = NULL;
ret = true;
}
// process mesh bitangents
// Process mesh bitangents
if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,
"bitangents",dirtyMask))
{
delete[] pMesh->mTangents; pMesh->mTangents = NULL;
delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
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
// (incremental version of the hashing function)
// (stdint.h should have been been included here)
// ------------------------------------------------------------------------------------------------
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| 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.
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;
// Additive lightmap?
@ -460,8 +446,8 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
{
f = 4.f;
}
mat->AddProperty( &f, 1, PropArray [cnt-1]);
mat->AddProperty( &op,1, PropArray2 [cnt-1]);
mat->AddProperty( &f, 1, AI_MATKEY_TEXBLEND_DIFFUSE(cnt-1));
mat->AddProperty( &op,1, AI_MATKEY_TEXOP_DIFFUSE(cnt-1));
}
return mat;
@ -600,13 +586,28 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
if (curMat)
{
DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
delete curMat;
delete curMat;curMat = NULL;
}
curMat = ParseMaterial(curMatFlags);
}
/* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices"))
{
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);
curNormals.reserve (num);
curColors.reserve (num);
@ -648,6 +649,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}
else if (ASSIMP_stricmp("standard", t))
{
delete curMat;
DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
}
else vertexFormat = 0;
@ -655,8 +657,11 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
}
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");
}
textMeaning = 2;
@ -665,6 +670,23 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// allocate storage for all faces
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)
{
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)

View File

@ -189,6 +189,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS
# include "SortByPTypeProcess.h"
#endif
#ifndef AI_BUILD_NO_GENUVCOORDS_PROCESS
# include "ComputeUVMappingProcess.h"
#endif
#ifndef AI_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
# include "TextureTransform.h"
#endif
using namespace Assimp;
@ -290,7 +297,7 @@ Importer::Importer() :
mImporter.push_back( new ColladaLoader());
#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 -
// as RegisterPPStep() does - all dependencies must be there.
mPostProcessingSteps.reserve(25);
@ -310,6 +317,17 @@ Importer::Importer() :
#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)
mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess());
#endif
@ -371,6 +389,9 @@ Importer::Importer() :
mPostProcessingSteps.push_back( new ImproveCacheLocalityProcess());
#endif
// allocate a SharedPostProcessInfo object and store pointers to it
// in all post-process steps in the list.
mPPShared = new SharedPostProcessInfo();
@ -412,7 +433,9 @@ aiReturn Importer::RegisterLoader(BaseImporter* 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;
pImp->GetExtensionList(st);
@ -423,15 +446,14 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
{
if (IsExtensionSupported(std::string(sz)))
{
DefaultLogger::get()->error(std::string( "The file extension " ) + sz + " is already in use");
return AI_FAILURE;
DefaultLogger::get()->warn(std::string( "The file extension " ) + sz + " is already in use");
}
sz = ::strtok(NULL,";");
}
#endif
// add the loader
this->mImporter.push_back(pImp);
mImporter.push_back(pImp);
DefaultLogger::get()->info("Registering custom importer: " + st);
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(unsigned int) * pcNode->mNumMeshes;
@ -816,6 +838,10 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
}
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
AddNodeWeight(in.nodes,mScene->mRootNode);
in.total += in.nodes;
@ -832,6 +858,5 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
}
}
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"
// internal headers
// Internal headers
#include "LWOLoader.h"
#include "MaterialSystem.h"
#include "ByteSwap.h"
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_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
#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_GVAL AI_IFF_FOURCC('G','V','A','L')
#define AI_LWO_BLOK AI_IFF_FOURCC('B','L','O','K')
#define AI_LWO_VCOL AI_IFF_FOURCC('V','C','O','L')
/* texture layer */
#define AI_LWO_TYPE AI_IFF_FOURCC('T','Y','P','E')
@ -236,10 +238,13 @@ namespace LWO {
/* VMAP types */
#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_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
@ -318,15 +323,11 @@ struct VColorChannel : public VMapEntry
register unsigned int m = num*dims;
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);
}
};
@ -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
@ -515,8 +525,10 @@ struct Surface
, mColorHighlights (0.f)
, mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing
, mVCMap ("")
, mVCMapType (AI_LWO_RGBA)
, mIOR (1.f) // vakuum
, mBumpIntensity (1.f)
, mWireframe (false)
{}
//! Name of the surface
@ -537,6 +549,7 @@ struct Surface
//! Vertex color map to be used to color the surface
std::string mVCMap;
uint32_t mVCMapType;
//! Names of the special shaders to be applied to the surface
ShaderList mShaders;
@ -554,6 +567,9 @@ struct Surface
//! Bump intensity scaling
float mBumpIntensity;
//! Wireframe flag
bool mWireframe;
};
// ---------------------------------------------------------------------------
@ -606,6 +622,9 @@ struct Layer
/** UV channel list from the file */
UVChannelList mUVChannels;
/** Normal vector channel from the file */
NormalChannel mNormals;
/** Temporary face list from the file*/
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[0] != '.')return false;
if (extension[1] != 'l' && extension[1] != 'L')return false;
if (extension[2] != 'w' && extension[2] != 'W')return false;
if (extension[3] != 'o' && extension[3] != 'O')return false;
return true;
return ! (extension[1] != 'l' && extension[1] != 'L' ||
extension[2] != 'w' && extension[2] != 'W' &&
extension[2] != 'x' && extension[2] != 'X' ||
extension[3] != 'o' && extension[3] != 'O');
}
// ------------------------------------------------------------------------------------------------
@ -151,11 +150,29 @@ void LWOImporter::InternReadFile( const std::string& pFile,
LoadLWOBFile();
}
// new lightwave format
// New lightwave format
else if (AI_LWO_FOURCC_LWO2 == fileType)
{
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;
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
ResolveTags();
ResolveClips();
@ -249,7 +255,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
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];
mesh->mMaterialIndex = i;
@ -276,9 +282,13 @@ void LWOImporter::InternReadFile( const std::string& pFile,
pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices];
// LightWave doesn't support more than 2 UV components
// so we can directly setup this value
mesh->mNumUVComponents[0] = 2;
}
if (layer.mNormals.name.length())
nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS];
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++;
}
// process normals (MODO extension)
if (nrm)
{
*nrm++ = ((aiVector3D*)&layer.mNormals.rawData[0])[idx];
}
// process vertex colors
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w)
{
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
@ -343,16 +366,19 @@ void LWOImporter::InternReadFile( const std::string& pFile,
pf++;
}
// compute normal vectors for the mesh - we can't use our GenSmoothNormal-
// Step here since it wouldn't handle smoothing groups correctly for LWO.
// So we use a separate implementation.
ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]);
if (!mesh->mNormals)
{
// Compute normal vectors for the mesh - we can't use our GenSmoothNormal-
// 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;
}
}
// 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
aiNode* pcNode = new aiNode();
apcNodes.push_back(pcNode);
@ -367,7 +393,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
if (apcNodes.empty() || apcMeshes.empty())
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()];
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)
{
parent -= 1;
for (uintptr_t i = 0; i < (uintptr_t)apcNodes.size();++i)
{
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);
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.");
return;
case AI_LWO_PTCH:
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
@ -829,19 +859,26 @@ VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPol
// ------------------------------------------------------------------------------------------------
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
it = list.begin(), end = list.end();
it != end;++it)
{
T& chan = *it;
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]);
CreateNewEntry( *it, srcIdx );
}
}
@ -911,7 +948,24 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
}
base = FindEntry(mCurLayer->mVColorChannels,name,perPoly);
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());
@ -946,20 +1000,22 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
if (polyIdx >= numFaces)
{
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];
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)
{
register unsigned int srcIdx = src.mIndices[i];
if (idx == srcIdx)
{
idx = (unsigned int)pointList.size();
}
if (idx != srcIdx)continue;
refList.resize(refList.size()+1, 0xffffffff);
idx = (unsigned int)pointList.size();
src.mIndices[i] = (unsigned int)pointList.size();
// 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->mUVChannels, srcIdx );
CreateNewEntry(mCurLayer->mWeightChannels, srcIdx );
CreateNewEntry(mCurLayer->mNormals, srcIdx );
}
}
}

View File

@ -100,7 +100,7 @@ protected:
*/
void GetExtensionList(std::string& append)
{
append.append("*.lwo");
append.append("*.lwo;*.lxo");
}
// -------------------------------------------------------------------
@ -257,12 +257,10 @@ private:
*
* @param pcMat Output material
* @param in Input texture list
* @param type Type identifier of the texture list. This is the string
* that appears in the middle of all material keys - e.g. "diffuse",
* "shininess", "glossiness" or "specular".
* @param type Type identifier of the texture list
*/
bool HandleTextures(MaterialHelper* pcMat, const TextureList& in,
const char* type);
aiTextureType type);
// -------------------------------------------------------------------
/** 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)
{
switch (in)
{
case LWO::Texture::REPEAT:
return aiTextureMapMode_Wrap;
case LWO::Texture::MIRROR:
return aiTextureMapMode_Mirror;
case LWO::Texture::RESET:
DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
// fall though here
case LWO::Texture::EDGE:
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;
char buffer[512];
aiString s;
bool ret = false;
for (TextureList::const_iterator it = in.begin(), end = in.end();
it != end;++it)
{
if (!(*it).enabled || !(*it).bCanUse || 0xffffffff == (*it).mRealUVIndex)continue;
if (!(*it).enabled || !(*it).bCanUse)continue;
ret = true;
// add the path to the texture
sprintf(buffer,"$tex.file.%s[%i]",type,cur);
// Convert lightwave's mapping modes to ours. We let them
// 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 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);
s.Set(ss);
}
pcMat->AddProperty(&s,buffer);
pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
// add the blend factor
sprintf(buffer,"$tex.blend.%s[%i]",type,cur);
pcMat->AddProperty(&(*it).mStrength,1,buffer);
pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
// add the blend operation
sprintf(buffer,"$tex.op.%s[%i]",type,cur);
switch ((*it).blendType)
{
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");
}
pcMat->AddProperty<int>((int*)&temp,1,buffer);
pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
// add the UV source index
sprintf(buffer,"$tex.uvw.%s[%i]",type,cur);
temp = (*it).mRealUVIndex;
pcMat->AddProperty<int>((int*)&temp,1,buffer);
// setup the mapping mode
pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
// add the u-wrapping
sprintf(buffer,"$tex.mapmodeu.%s[%i]",type,cur);
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
sprintf(buffer,"$tex.mapmodev.%s[%i]",type,cur);
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;
}
@ -237,17 +279,20 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
// opacity
float f = 1.0f-surf.mTransparency;
pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
if (10e10f != surf.mTransparency)
{
float f = 1.0f-surf.mTransparency;
pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
}
// ADD TEXTURES to the material
// TODO: find out how we can handle COLOR textures correctly...
bool b = HandleTextures(pcMat,surf.mColorTextures,"diffuse");
b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,"diffuse"));
HandleTextures(pcMat,surf.mSpecularTextures,"specular");
HandleTextures(pcMat,surf.mGlossinessTextures,"shininess");
HandleTextures(pcMat,surf.mBumpTextures,"height");
HandleTextures(pcMat,surf.mOpacityTextures,"opacity");
bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
// now we need to know which shader we must use
// 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();
it != end;++it)
{
if (!(*it).enabled)continue;
//if (!(*it).enabled)continue;
if ((*it).functionName == "LW_SuperCelShader" ||
(*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();
it != end;++it)
{
if (!(*it).enabled || !(*it).bCanUse || 0xffffffff != (*it).mRealUVIndex)continue;
switch ((*it).mapMode)
// Ignore textures with non-UV mappings for the moment.
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;
default: ;
}
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)
{
case AI_LWO_PROJ:
tex.mapMode = (Texture::MappingMode)GetU2();
break;
case AI_LWO_WRAP:
tex.wrapModeWidth = (Texture::Wrap)GetU2();
tex.wrapModeHeight = (Texture::Wrap)GetU2();
break;
@ -650,10 +689,45 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// transparency
case AI_LWO_TRAN:
{
if (surf.mTransparency == 10e10f)break;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
surf.mTransparency = GetF4();
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
case AI_LWO_GLOS:
{
@ -696,6 +770,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
surf.mMaximumSmoothAngle = GetF4();
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
case AI_LWO_BLOK:
{

View File

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

View File

@ -43,15 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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,
const char* pKey,
unsigned int type,
unsigned int index,
const aiMaterialProperty** pPropOut)
{
ai_assert (pMat != NULL);
@ -59,22 +55,25 @@ aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
ai_assert (pPropOut != NULL);
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])
{
if (0 == ASSIMP_stricmp( pMat->mProperties[i]->mKey.data, pKey ))
{
*pPropOut = pMat->mProperties[i];
return AI_SUCCESS;
}
}
*pPropOut = pMat->mProperties[i];
return AI_SUCCESS;
}
}
*pPropOut = NULL;
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
const char* pKey,
unsigned int type,
unsigned int index,
float* pOut,
unsigned int* pMax)
{
@ -84,56 +83,51 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
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
if( aiPTI_Float == pMat->mProperties[i]->mType ||
aiPTI_Buffer == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(float);
unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(float);
if (NULL != pMax)
iWrite = *pMax < iWrite ? *pMax : iWrite;
if (pMax)iWrite = *pMax < iWrite ? *pMax : iWrite;
::memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (float));
memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (float));
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;
if (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 (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;
}
// ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
const char* pKey,
unsigned int type,
unsigned int index,
int* pOut,
unsigned int* pMax)
{
@ -142,69 +136,66 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
ai_assert (pOut != NULL);
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
if( aiPTI_Integer == pMat->mProperties[i]->mType ||
aiPTI_Buffer == pMat->mProperties[i]->mType)
{
unsigned int iWrite = pMat->mProperties[i]->
mDataLength / sizeof(int);
unsigned int iWrite = pMat->mProperties[i]->mDataLength / sizeof(int);
if (NULL != pMax)
iWrite = *pMax < iWrite ? *pMax : iWrite;
if (pMax)iWrite = *pMax < iWrite ? *pMax : iWrite;
::memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (int));
memcpy (pOut, pMat->mProperties[i]->mData, iWrite * sizeof (int));
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;
if (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 (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;
}
// ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialColor(const aiMaterial* pMat,
const char* pKey,
unsigned int type,
unsigned int index,
aiColor4D* pOut)
{
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 (3 == iMax)pOut->a = 1.0f;
return eRet;
}
// ------------------------------------------------------------------------------------------------
aiReturn aiGetMaterialString(const aiMaterial* pMat,
const char* pKey,
unsigned int type,
unsigned int index,
aiString* pOut)
{
ai_assert (pMat != NULL);
@ -213,37 +204,39 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
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);
}
// wrong type
else return AI_FAILURE;
return AI_SUCCESS;
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;
}
}
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
MaterialHelper::MaterialHelper()
{
// allocate 5 entries by default
this->mNumProperties = 0;
this->mNumAllocated = 5;
this->mProperties = new aiMaterialProperty*[5];
return;
// Allocate 5 entries by default
mNumProperties = 0;
mNumAllocated = 5;
mProperties = new aiMaterialProperty*[5];
}
// ------------------------------------------------------------------------------------------------
MaterialHelper::~MaterialHelper()
{
Clear();
}
// ------------------------------------------------------------------------------------------------
void MaterialHelper::Clear()
{
@ -252,7 +245,11 @@ void MaterialHelper::Clear()
// delete this entry
delete mProperties[i];
}
mNumProperties = 0;
// The array remains
}
// ------------------------------------------------------------------------------------------------
uint32_t MaterialHelper::ComputeHash()
{
@ -262,45 +259,62 @@ uint32_t MaterialHelper::ComputeHash()
aiMaterialProperty* prop;
// 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->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;
}
// ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::RemoveProperty (const char* pKey)
aiReturn MaterialHelper::RemoveProperty (const char* pKey,unsigned int type,
unsigned int index)
{
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
{
if (0 == ASSIMP_stricmp( this->mProperties[i]->mKey.data, pKey ))
{
// delete this entry
delete this->mProperties[i];
aiMaterialProperty* prop = mProperties[i];
// collapse the array behind --.
--this->mNumProperties;
for (unsigned int a = i; a < this->mNumProperties;++a)
{
this->mProperties[a] = this->mProperties[a+1];
}
return AI_SUCCESS;
if (prop && !::strcmp( prop->mKey.data, pKey ) &&
prop->mSemantic == type && prop->mIndex == index)
{
// Delete this entry
delete mProperties[i];
// collapse the array behind --.
--mNumProperties;
for (unsigned int a = i; a < mNumProperties;++a)
{
mProperties[a] = mProperties[a+1];
}
return AI_SUCCESS;
}
}
return AI_FAILURE;
}
// ------------------------------------------------------------------------------------------------
aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
const unsigned int pSizeInBytes,
unsigned int pSizeInBytes,
const char* pKey,
unsigned int type,
unsigned int index,
aiPropertyTypeInfo pType)
{
ai_assert (pInput != NULL);
@ -310,27 +324,30 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
// first search the list whether there is already an entry
// with this name.
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];
iOutIndex = i;
}
// delete this entry
delete this->mProperties[i];
iOutIndex = i;
}
}
// Allocate a new material property
aiMaterialProperty* pcNew = new aiMaterialProperty();
// fill this
// Fill this
pcNew->mType = pType;
pcNew->mSemantic = type;
pcNew->mIndex = index;
pcNew->mDataLength = pSizeInBytes;
pcNew->mData = new char[pSizeInBytes];
memcpy (pcNew->mData,pInput,pSizeInBytes);
::memcpy (pcNew->mData,pInput,pSizeInBytes);
pcNew->mKey.length = ::strlen(pKey);
ai_assert ( MAXLEN > pcNew->mKey.length);
@ -338,37 +355,41 @@ aiReturn MaterialHelper::AddBinaryProperty (const void* pInput,
if (0xFFFFFFFF != iOutIndex)
{
this->mProperties[iOutIndex] = pcNew;
mProperties[iOutIndex] = pcNew;
return AI_SUCCESS;
}
// resize the array ... allocate storage for 5 other properties
if (this->mNumProperties == this->mNumAllocated)
if (mNumProperties == mNumAllocated)
{
unsigned int iOld = this->mNumAllocated;
this->mNumAllocated += 5;
unsigned int iOld = mNumAllocated;
mNumAllocated += 5;
aiMaterialProperty** ppTemp = new aiMaterialProperty*[this->mNumAllocated];
aiMaterialProperty** ppTemp = new aiMaterialProperty*[mNumAllocated];
if (NULL == ppTemp)return AI_OUTOFMEMORY;
::memcpy (ppTemp,this->mProperties,iOld * sizeof(void*));
::memcpy (ppTemp,mProperties,iOld * sizeof(void*));
delete[] this->mProperties;
this->mProperties = ppTemp;
delete[] mProperties;
mProperties = ppTemp;
}
// push back ...
this->mProperties[this->mNumProperties++] = pcNew;
mProperties[mNumProperties++] = pcNew;
return AI_SUCCESS;
}
// ------------------------------------------------------------------------------------------------
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+
(unsigned int)(((uint8_t*)&pInput->data - (uint8_t*)&pInput->length)),
pKey,aiPTI_String);
pKey,type,index, aiPTI_String);
}
// ------------------------------------------------------------------------------------------------
void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
const MaterialHelper* pcSrc)
@ -400,7 +421,8 @@ void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest,
for (unsigned int q = 0; q < iOldNum;++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;
@ -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->mKey = propSrc->mKey;
prop->mDataLength = propSrc->mDataLength;
prop->mType = propSrc->mType;
prop->mSemantic = propSrc->mSemantic;
prop->mIndex = propSrc->mIndex;
prop->mData = new char[propSrc->mDataLength];
::memcpy(prop->mData,propSrc->mData,prop->mDataLength);
}
return;
}
// ------------------------------------------------------------------------------------------------
// we need this dummy because the compiler would otherwise complain about
// empty, but controlled statements ...
void DummyAssertFunction()
aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
aiTextureType type,
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);
}
// ------------------------------------------------------------------------------------------------
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);
ai_assert(NULL != mat && NULL != path);
const char* szPathBase;
const char* szUVBase;
const char* szBlendBase;
const char* szOpBase;
const char* aszMapModeBase[3];
switch (iTexType)
{
case AI_TEXTYPE_DIFFUSE:
szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_;
szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_;
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))
// Get the path to the texture
aiString string;
if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),&string))
{
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;
}
// get the blend factor of the texture
if (pfBlendFactor)
{
float fBlend;
if(0 >= sprintf(szKey,"%s[%i]",szBlendBase,iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialFloat(pcMat,szKey,&fBlend))
fBlend = 1.0f;
// Determine the mapping type of the texture
aiTextureMapping mapping = aiTextureMapping_UV;
aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
if (_mapping)*_mapping = mapping;
*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
if (peTextureOp)
// Get the blend factor of the texture
if (blend)
{
aiTextureOp op;
if(0 >= sprintf(szKey,"%s[%i]",szOpBase,iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&op))
op = aiTextureOp_Multiply;
aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend);
}
*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
if (peMapMode)
if (mapmode)
{
aiTextureMapMode eMode;
for (unsigned int q = 0; q < 3;++q)
{
if(0 >= sprintf(szKey,"%s[%i]",aszMapModeBase[q],iIndex))DummyAssertFunction();
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&eMode))
{
eMode = aiTextureMapMode_Wrap;
}
peMapMode[q] = eMode;
}
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_W(type,index),(int*)&mapmode[2]);
}
return AI_SUCCESS;
}

View File

@ -65,11 +65,15 @@ public:
* \param pInput Pointer to input data
* \param pSizeInBytes Size of input data
* \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
*/
aiReturn AddBinaryProperty (const void* pInput,
const unsigned int pSizeInBytes,
unsigned int pSizeInBytes,
const char* pKey,
unsigned int type,
unsigned int index,
aiPropertyTypeInfo pType);
@ -79,9 +83,13 @@ public:
*
* \param pInput Input string
* \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,
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 pNumValues Number of values in the array
* \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>
aiReturn AddProperty (const TYPE* pInput,
const unsigned int pNumValues,
const char* pKey);
unsigned int pNumValues,
const char* pKey,
unsigned int type,
unsigned int index);
// -------------------------------------------------------------------
/** Remove a given key from the list
* 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>
aiReturn MaterialHelper::AddProperty (const TYPE* pInput,
const unsigned int pNumValues,
const char* pKey)
const char* pKey,
unsigned int type,
unsigned int index)
{
return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(TYPE),
pKey,aiPTI_Buffer);
pKey,type,index,aiPTI_Buffer);
}
@ -149,11 +165,13 @@ aiReturn MaterialHelper::AddProperty (const TYPE* pInput,
template<>
inline aiReturn MaterialHelper::AddProperty<float> (const float* pInput,
const unsigned int pNumValues,
const char* pKey)
const char* pKey,
unsigned int type,
unsigned int index)
{
return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(float),
pKey,aiPTI_Float);
pKey,type,index,aiPTI_Float);
}
@ -162,11 +180,13 @@ inline aiReturn MaterialHelper::AddProperty<float> (const float* pInput,
template<>
inline aiReturn MaterialHelper::AddProperty<aiColor4D> (const aiColor4D* pInput,
const unsigned int pNumValues,
const char* pKey)
const char* pKey,
unsigned int type,
unsigned int index)
{
return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiColor4D),
pKey,aiPTI_Float);
pKey,type,index,aiPTI_Float);
}
@ -175,11 +195,13 @@ inline aiReturn MaterialHelper::AddProperty<aiColor4D> (const aiColor4D* pInput,
template<>
inline aiReturn MaterialHelper::AddProperty<aiColor3D> (const aiColor3D* pInput,
const unsigned int pNumValues,
const char* pKey)
const char* pKey,
unsigned int type,
unsigned int index)
{
return this->AddBinaryProperty((const void*)pInput,
pNumValues * sizeof(aiColor3D),
pKey,aiPTI_Float);
pKey,type,index,aiPTI_Float);
}
@ -188,11 +210,13 @@ inline aiReturn MaterialHelper::AddProperty<aiColor3D> (const aiColor3D* pInput,
template<>
inline aiReturn MaterialHelper::AddProperty<int> (const int* pInput,
const unsigned int pNumValues,
const char* pKey)
const char* pKey,
unsigned int type,
unsigned int index)
{
return this->AddBinaryProperty((const void*)pInput,
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
{

View File

@ -47,34 +47,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
#if _MSC_VER >= 1400
# define sprintf sprintf_s
#endif
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RemoveRedundantMatsProcess::RemoveRedundantMatsProcess()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RemoveRedundantMatsProcess::~RemoveRedundantMatsProcess()
{
// nothing to do here
}
// -------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const
{
return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
}
// -------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin");
unsigned int iCnt = 0;
unsigned int iCnt = 0, unreferenced = 0;
if (pScene->mNumMaterials)
{
// 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)
{
// 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();
for (unsigned int a = 0; a < i;++a)
@ -153,7 +157,8 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
else
{
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);
}
}

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

View File

@ -69,7 +69,7 @@ public:
* @param defaultTargetPos Default target position to be used if
* 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 aiVector3D* defaultObjectPos = NULL,
const aiVector3D* defaultTargetPos = NULL);
@ -129,7 +129,8 @@ class ASSIMP_API TargetAnimationHelper
public:
TargetAnimationHelper()
: objectPositions (NULL)
: targetPositions (NULL)
, objectPositions (NULL)
{}
@ -141,8 +142,8 @@ public:
*
* @param targetPositions Translation channel
*/
void SetTargetAnimationChannel (
const std::vector<aiVectorKey>* targetPositions);
void SetTargetAnimationChannel (const
std::vector<aiVectorKey>* targetPositions);
// ------------------------------------------------------------------
@ -150,9 +151,16 @@ public:
*
* @param objectPositions Translation channel
*/
void SetMainAnimationChannel (
void SetMainAnimationChannel ( const
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
@ -163,8 +171,8 @@ public:
private:
const std::vector<aiVectorKey>* targetPositions;
std::vector<aiVectorKey> *objectPositions;
const std::vector<aiVectorKey>* targetPositions,*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
#define AI_TEXTURE_TRANSFORM_H_INCLUDED
#include "BaseImporter.h"
#include "../include/aiTypes.h"
#include "../include/aiMaterial.h"
#include "../include/aiMesh.h"
#include "BaseProcess.h"
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
*/
struct STransformVecInfo
struct STransformVecInfo : public aiUVTransform
{
//! Construction. The resulting matrix is the identity
STransformVecInfo ()
:
fScaleU(1.0f),fScaleV(1.0f),
fOffsetU(0.0f),fOffsetV(0.0f),
fRotation(0.0f),
iUVIndex(0)
STransformVecInfo()
: uvIndex (0)
, mapU (aiTextureMapMode_Wrap)
, mapV (aiTextureMapMode_Wrap)
, lockedPos (AI_TT_UV_IDX_LOCK_NONE)
{}
//! 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
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
std::vector<D3DS::Texture*> pcTextures;
// -------------------------------------------------------------------
/** Compare two transform setups
*/
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
{
return 1.0f == fScaleU && 1.0f == fScaleV &&
!fOffsetU && !fOffsetV && !fRotation;
return (1.0f == mScaling.x && 1.f == mScaling.y &&
!mTranslation.x && !mTranslation.y &&
mRotation < AI_TT_ROTATION_EPSILON);
}
// -------------------------------------------------------------------
@ -106,26 +158,26 @@ struct STransformVecInfo
{
mOut = aiMatrix3x3();
if (1.0f != this->fScaleU || 1.0f != this->fScaleV)
if (1.0f != mScaling.x || 1.0f != mScaling.y)
{
aiMatrix3x3 mScale;
mScale.a1 = this->fScaleU;
mScale.b2 = this->fScaleV;
mScale.a1 = mScaling.x;
mScale.b2 = mScaling.y;
mOut = mScale;
}
if (this->fRotation)
if (mRotation)
{
aiMatrix3x3 mRot;
mRot.a1 = mRot.b2 = cosf(this->fRotation);
mRot.a2 = mRot.b1 = sinf(this->fRotation);
mRot.a1 = mRot.b2 = cos(mRotation);
mRot.a2 = mRot.b1 = sin(mRotation);
mRot.a2 = -mRot.a2;
mOut *= mRot;
}
if (this->fOffsetU || this->fOffsetV)
if (mTranslation.x || mTranslation.y)
{
aiMatrix3x3 mTrans;
mTrans.a3 = this->fOffsetU;
mTrans.b3 = this->fOffsetV;
mTrans.a3 = mTranslation.x;
mTrans.b3 = mTranslation.y;
mOut *= mTrans;
}
}
@ -133,73 +185,39 @@ struct STransformVecInfo
// ---------------------------------------------------------------------------
/** Helper class used by the ASE/ASK and 3DS loaders to handle texture
* coordinate transformations correctly (such as offsets, scaling)
/** Helper step to compute final UV coordinate sets if there are scalings
* 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:
TextureTransformStep();
~TextureTransformStep();
// -------------------------------------------------------------------
/** Returns true if a texture requires UV transformations
* \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);
}
bool IsActive( unsigned int pFlags) const;
// -------------------------------------------------------------------
/** Must be called before HasUVTransform(rcIn) is called
* \param rcIn Input texture
*/
static void PreProcessUVTransform(
D3DS::Texture& rcIn);
void Execute( aiScene* pScene);
// -------------------------------------------------------------------
/** Check whether the texture coordinate transformation of
* 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);
void SetupProperties(const Importer* pImp);
// -------------------------------------------------------------------
/** 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);
// -------------------------------------------------------------------
/** 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);
protected:
// -------------------------------------------------------------------
/** Setup the correct UV source for a material
* \param pcMat Final material to be changed
* \param pcMatIn Input material, unconverted
/** Preprocess a specific UV transformation setup
*
* @param info Transformation setup to be preprocessed.
*/
static void SetupMatUVSrc (aiMaterial* pcMat,
const D3DS::Material* pcMatIn);
void PreProcessUVTransform(STransformVecInfo& info);
private:
unsigned int configFlags;
};
}

View File

@ -418,7 +418,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
{
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
// 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");
}
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMesh* pMesh,
const aiBone* pBone,float* afSum)
@ -548,6 +549,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh,
afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
}
}
// ------------------------------------------------------------------------------------------------
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.
// if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
}
// ------------------------------------------------------------------------------------------------
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 ...
// textures must be specified with rising indices (e.g. diffuse #2 may not be
// specified if diffuse #1 is not there ...)
case aiTextureType_SPECULAR:
szType = "Specular";break;
// "$tex.file.<szType>[<index>]"
char szBaseBuf[512];
int iLen;
iLen = ::sprintf(szBaseBuf,"$tex.file.%s",szType);
if (0 >= iLen)return;
case aiTextureType_AMBIENT:
szType = "Ambient";break;
case aiTextureType_EMISSIVE:
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 iIndex = -1;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++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];
if (*sz)
{
++sz;
iIndex = std::max(iIndex, (int)strtol10(sz,0));
++iNumIndices;
}
iIndex = std::max(iIndex, (int) prop->mIndex);
++iNumIndices;
if (aiPTI_String != prop->mType)
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)
{
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);
}
if (!iNumIndices)return;
// now check whether all UV indices are valid ...
iLen = ::sprintf(szBaseBuf,"$tex.uvw.%s",szType);
if (0 >= iLen)return;
// TODO: check whether the mappings are correctly
std::vector<aiTextureMapping> mappings(iNumIndices);
// Now check whether all UV indices are valid ...
bool bNoSpecified = true;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++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)
this->ReportError("Material property %s is expected to be an integer",prop->mKey.data);
const char* sz = &prop->mKey.data[iLen];
if (*sz)
{
++sz;
iIndex = strtol10(sz,NULL);
bNoSpecified = false;
ReportError("Material property %s%i is expected to be an integer (size is %i)",
prop->mKey.data,prop->mIndex,prop->mDataLength);
}
bNoSpecified = false;
// ignore UV indices for texture channel that are not there ...
if (iIndex >= iNumIndices)
// Ignore UV indices for texture channels that are not there ...
// 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
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)
int iChannels = 0;
while (mesh->HasTextureCoords(iChannels))++iChannels;
if (iIndex >= iChannels)
{
aiMesh* mesh = this->mScene->mMeshes[a];
if(mesh->mMaterialIndex == (unsigned int)iIndex)
{
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);
}
}
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
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->mTextureCoords[0])
@ -766,15 +807,16 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
}
// check whether there are invalid texture keys
SearchForInvalidTextures(pMaterial,"diffuse");
SearchForInvalidTextures(pMaterial,"specular");
SearchForInvalidTextures(pMaterial,"ambient");
SearchForInvalidTextures(pMaterial,"emissive");
SearchForInvalidTextures(pMaterial,"opacity");
SearchForInvalidTextures(pMaterial,"shininess");
SearchForInvalidTextures(pMaterial,"normals");
SearchForInvalidTextures(pMaterial,"height");
SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE);
SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR);
SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT);
SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE);
SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY);
SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS);
SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT);
SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS);
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiTexture* pTexture)
{
@ -806,7 +848,7 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
}
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[2] >= 'A' && sz[2] <= '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");
}
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
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
if (pNodeAnim->mNumPositionKeys)
{
@ -934,11 +954,12 @@ __break_out:
ReportError("A node animation channel must have at least one subtrack");
}
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiNode* pNode)
{
if (!pNode)this->ReportError("A node of the scenegraph is NULL");
if (pNode != this->mScene->mRootNode && !pNode->mParent)
if (!pNode)ReportError("A node of the scenegraph is NULL");
if (pNode != mScene->mRootNode && !pNode->mParent)
this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
this->Validate(&pNode->mName);
@ -948,21 +969,21 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
{
if (!pNode->mMeshes)
{
this->ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
pNode->mNumMeshes);
}
std::vector<bool> abHadMesh;
abHadMesh.resize(this->mScene->mNumMeshes,false);
abHadMesh.resize(mScene->mNumMeshes,false);
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)",
pNode->mMeshes[i],this->mScene->mNumMeshes-1);
ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)",
pNode->mMeshes[i],mScene->mNumMeshes-1);
}
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]);
}
abHadMesh[pNode->mMeshes[i]] = true;
@ -977,10 +998,11 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
}
for (unsigned int i = 0; i < pNode->mNumChildren;++i)
{
this->Validate(pNode->mChildren[i]);
Validate(pNode->mChildren[i]);
}
}
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiString* pString)
{
@ -995,11 +1017,11 @@ void ValidateDSProcess::Validate( const aiString* pString)
if ('\0' == *sz)
{
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;
}
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;
}
}

View File

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

View File

@ -611,7 +611,6 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
std::string sz = otex.mName;
if (!sz.length())continue;
char key[256];
// find the file name
const size_t iLen = sz.length();
@ -634,35 +633,35 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
if( isalpha( sz[c]))
sz[c] = tolower( sz[c]);
// Place texture filename property under the corresponding name
aiString tex( oldMat.mTextures[b].mName);
// bump map
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
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
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
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
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
{
// assume it is a diffuse texture
::sprintf(key,AI_MATKEY_TEXTURE_DIFFUSE_ "[%i]",iDM++);
// Assume it is a diffuse texture
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 \
ScenePreprocessor.cpp \
B3DImporter.cpp \
TargetAnimation.cpp
TargetAnimation.cpp \
ComputeUVMappingProcess.cpp \
ColladaLoader.cpp \
ColladaParser.cpp
OBJECTS = $(SOURCES:.cpp=.o)

View File

@ -74,8 +74,10 @@ SOURCES = AssimpPCH.cpp \
Q3DLoader.cpp \
ScenePreprocessor.cpp \
B3DImporter.cpp \
TargetAnimation.cpp
TargetAnimation.cpp \
ComputeUVMappingProcess.cpp \
ColladaLoader.cpp \
ColladaParser.cpp
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
scoped_ptr()
: ptr(NULL)
: ptr(0)
{
}
@ -48,6 +48,17 @@ public:
return ptr;
}
inline void reset (T* t = 0)
{
delete ptr;
ptr = t;
}
void swap(scoped_ptr & b)
{
std::swap(ptr, b.ptr);
}
private:
// 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
#else

View File

@ -55,6 +55,12 @@ extern "C" {
/** Helper structure to describe a virtual camera.
*
* 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

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"
// ---------------------------------------------------------------------------
/** \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
@ -305,6 +296,23 @@ enum aiComponent
#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.
*

View File

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

View File

@ -87,6 +87,12 @@ enum aiLightSourceType
* Assimp supports multiple sorts of light sources, including
* directional, point and spot lights. All of them are defined with just
* 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
{

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
// ---------------------------------------------------------------------------
inline aiReturn aiMaterial::GetTexture(unsigned int iIndex,
unsigned int iTexType,
aiString* szPath,
unsigned int* piUVIndex ,
float* pfBlendFactor ,
aiTextureOp* peTextureOp ,
aiTextureMapMode* peMapMode )
inline aiReturn aiMaterial::GetTexture( aiTextureType type,
unsigned int idx,
C_STRUCT aiString* path,
aiTextureMapping* mapping /*= NULL*/,
unsigned int* uvindex /*= NULL*/,
float* blend /*= NULL*/,
aiTextureOp* op /*= NULL*/,
aiTextureMapMode* mapmode /*= NULL*/)
{
return aiGetMaterialTexture(this,iIndex,iTexType,szPath,
piUVIndex,pfBlendFactor,peTextureOp,peMapMode);
return aiGetMaterialTexture(this,type,idx,path,mapping,uvindex,blend,op,mapmode);
}
// ---------------------------------------------------------------------------
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 iNum = pMax ? *pMax : 1;
aiMaterialProperty* prop;
aiReturn ret = aiGetMaterialProperty(this,pKey,&prop);
aiReturn ret = aiGetMaterialProperty(this,pKey,type,idx,&prop);
if ( AI_SUCCESS == ret )
{
if (prop->mDataLength < sizeof(Type)*iNum)return AI_FAILURE;
@ -78,12 +80,14 @@ inline aiReturn aiMaterial::Get(const char* pKey,Type* pOut,
}
return ret;
}
// ---------------------------------------------------------------------------
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;
aiReturn ret = aiGetMaterialProperty(this,pKey,&prop);
aiReturn ret = aiGetMaterialProperty(this,pKey,type,idx,&prop);
if ( AI_SUCCESS == ret )
{
if (prop->mDataLength < sizeof(Type))return AI_FAILURE;
@ -93,43 +97,50 @@ inline aiReturn aiMaterial::Get(const char* pKey,Type& pOut)
}
return ret;
}
// ---------------------------------------------------------------------------
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)
{
return aiGetMaterialFloatArray(this,pKey,pOut,pMax);
return aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
}
// ---------------------------------------------------------------------------
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)
{
return aiGetMaterialIntegerArray(this,pKey,pOut,pMax);
return aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
}
// ---------------------------------------------------------------------------
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 <>
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 <>
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 <>
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

View File

@ -48,11 +48,11 @@ extern "C" {
#endif
struct aiMatrix4x4;
struct aiVector2D;
// ---------------------------------------------------------------------------
/** Represents a row-major 3x3 matrix
*/
// ---------------------------------------------------------------------------
struct aiMatrix3x3
{
#ifdef __cplusplus
@ -77,6 +77,22 @@ struct aiMatrix3x3
aiMatrix3x3 operator* (const aiMatrix3x3& m) const;
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

View File

@ -51,6 +51,27 @@ inline aiMatrix3x3& aiMatrix3x3::Transpose()
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

View File

@ -504,6 +504,23 @@ struct aiMesh
else
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
inline bool HasBones() const
{ return mBones != NULL && mNumBones > 0; }

View File

@ -230,7 +230,6 @@ enum aiPostProcessSteps
*/
aiProcess_FindDegenerates = 0x10000,
/** This step searches all meshes for invalid data, such as zeroed
* 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.
*/
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_GenNormals | \
aiProcess_JoinIdenticalVertices | \
aiProcess_Triangulate
aiProcess_Triangulate | \
aiProcess_GenUVCoords
/** @def AI_POSTPROCESS_DEFAULT_REALTIME
@ -274,7 +294,8 @@ enum aiPostProcessSteps
aiProcess_RemoveRedundantMaterials | \
aiProcess_SplitLargeMeshes | \
aiProcess_OptimizeGraph | \
aiProcess_Triangulate
aiProcess_Triangulate | \
aiProcess_GenUVCoords
#ifdef __cplusplus

View File

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

View File

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

View File

@ -786,6 +786,9 @@ int CMaterialManager::CreateMaterial(
aiString szPath;
aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap);
bool bib =false;
if (pcSource->mTextureCoords[0])
{
@ -795,6 +798,9 @@ int CMaterialManager::CreateMaterial(
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&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])
@ -833,7 +839,7 @@ int CMaterialManager::CreateMaterial(
// NOTE: This special value is set by the tree view if the user
// 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->AddRef();
@ -879,6 +885,7 @@ int CMaterialManager::CreateMaterial(
{
LoadTexture(&pcMesh->piNormalTexture,&szPath);
}
else bib = true;
bHM = true;
}
@ -968,6 +975,28 @@ int CMaterialManager::CreateMaterial(
sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE";
sMacro[iCurrent].Definition = "1";
++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)
{
@ -993,7 +1022,7 @@ int CMaterialManager::CreateMaterial(
sMacro[iCurrent].Definition = "1";
++iCurrent;
}
if (pcMesh->piNormalTexture)
if (pcMesh->piNormalTexture && !bib)
{
sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE";
sMacro[iCurrent].Definition = "1";

View File

@ -530,6 +530,24 @@ std::string g_szMaterialShader = std::string(
"sampler DIFFUSE_SAMPLER\n"
"{\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"
"MagFilter=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_ValidateDataStructure | aiProcess_ImproveCacheLocality
| 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
double fEnd = (double)timeGetTime();

View File

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