Minor changes to the logger (was necessary for the integration of jAssimp)

Fixed face winding bugs (cw now ...)
jAssimp incremental Update
3DS hierarchy bug fixed
Added "MakeVerboseFormat" postprocess step
Viewer bugfixes

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@41 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2008-05-25 22:29:05 +00:00
parent 522ce03d00
commit 0d728ce17b
46 changed files with 2242 additions and 334 deletions

View File

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the 3ds importer class */
#include "3DSLoader.h"
#include "MaterialSystem.h"
#include "DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
@@ -98,11 +99,18 @@ void Dot3DSImporter::ReplaceDefaultMaterial()
{
// NOTE: The additional check seems to be necessary,
// some exporters seem to generate invalid data here
if (0xcdcdcdcd == (*a) || (*a) >= this->mScene->mMaterials.size())
if (0xcdcdcdcd == (*a))
{
(*a) = iIndex;
++iCnt;
}
else if ( (*a) >= this->mScene->mMaterials.size())
{
(*a) = iIndex;
++iCnt;
DefaultLogger::get()->warn("Material index overflow in 3DS file. Assigning "
"default material ...");
}
}
}
if (0 != iCnt && iIndex == this->mScene->mMaterials.size())
@@ -125,14 +133,17 @@ void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh)
// check whether all indices are in range
if ((*i).i1 >= sMesh->mPositions.size())
{
DefaultLogger::get()->warn("Face index overflow in 3DS file (#1)");
(*i).i1 = sMesh->mPositions.size()-1;
}
if ((*i).i2 >= sMesh->mPositions.size())
{
DefaultLogger::get()->warn("Face index overflow in 3DS file (#2)");
(*i).i2 = sMesh->mPositions.size()-1;
}
if ((*i).i3 >= sMesh->mPositions.size())
{
DefaultLogger::get()->warn("Face index overflow in 3DS file (#3)");
(*i).i3 = sMesh->mPositions.size()-1;
}
}
@@ -155,31 +166,55 @@ void Dot3DSImporter::MakeUnique(Dot3DS::Mesh* sMesh)
vNew2.resize(sMesh->mFaces.size() * 3);
for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
{
uint32_t iTemp1,iTemp2;
// position and texture coordinates
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1];
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i1];
sMesh->mFaces[i].i1 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i3];
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i3];
iTemp1 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i2];
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i2];
sMesh->mFaces[i].i2 = iBase++;
iTemp2 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i3];
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i3];
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1];
vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i1];
sMesh->mFaces[i].i3 = iBase++;
sMesh->mFaces[i].i1 = iTemp1;
sMesh->mFaces[i].i2 = iTemp2;
// handle the face order ...
/*if (iTemp1 > iTemp2)
{
sMesh->mFaces[i].bFlipped = true;
}*/
}
}
else
{
for (unsigned int i = 0; i < sMesh->mFaces.size();++i)
{
uint32_t iTemp1,iTemp2;
// position only
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1];
sMesh->mFaces[i].i1 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i2];
sMesh->mFaces[i].i2 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i3];
iTemp1 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i2];
iTemp2 = iBase++;
vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1];
sMesh->mFaces[i].i3 = iBase++;
sMesh->mFaces[i].i1 = iTemp1;
sMesh->mFaces[i].i2 = iTemp2;
// handle the face order ...
/*if (iTemp1 > iTemp2)
{
sMesh->mFaces[i].bFlipped = true;
}*/
}
}
sMesh->mPositions = vNew;
@@ -216,9 +251,16 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
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.mSpecularExponent, 1, AI_MATKEY_SHININESS);
mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
// phong shininess and shininess strength
if (Dot3DS::Dot3DSFile::Phong == oldMat.mShading ||
Dot3DS::Dot3DSFile::Metal == oldMat.mShading)
{
mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
}
// opacity
mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
@@ -231,8 +273,6 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
{
case Dot3DS::Dot3DSFile::Flat:
eShading = aiShadingMode_Flat; break;
case Dot3DS::Dot3DSFile::Phong :
eShading = aiShadingMode_Phong; break;
// I don't know what "Wire" shading should be,
// assume it is simple lambertian diffuse (L dot N) shading
@@ -243,6 +283,9 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
// assume cook-torrance shading for metals.
// NOTE: I assume the real shader inside 3ds max is an anisotropic
// Phong-Blinn shader, but this is a good approximation too
case Dot3DS::Dot3DSFile::Phong :
eShading = aiShadingMode_Phong; break;
case Dot3DS::Dot3DSFile::Metal :
eShading = aiShadingMode_CookTorrance; break;
}
@@ -361,9 +404,8 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
else aiSplit[*a].push_back(iNum);
}
// now generate submeshes
#if 0
bool bFirst = true;
#endif
for (unsigned int p = 0; p < this->mScene->mMaterials.size();++p)
{
if (aiSplit[p].size() != 0)
@@ -377,7 +419,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
p_pcOut->mColors[0] = (aiColor4D*)new std::string((*i).mName);
avOutMeshes.push_back(p_pcOut);
#if 0
if (bFirst)
{
p_pcOut->mColors[1] = (aiColor4D*)new aiMatrix4x4();
@@ -385,7 +427,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
*((aiMatrix4x4*)p_pcOut->mColors[1]) = (*i).mMat;
bFirst = false;
}
#endif
// convert vertices
p_pcOut->mNumVertices = aiSplit[p].size()*3;
@@ -408,7 +450,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
p_pcOut->mFaces[q].mIndices = new unsigned int[3];
p_pcOut->mFaces[q].mNumIndices = 3;
p_pcOut->mFaces[q].mIndices[0] = iBase;
p_pcOut->mFaces[q].mIndices[2] = iBase;
p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].i1];
p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].i1];
@@ -416,7 +458,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].i2];
p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].i2];
p_pcOut->mFaces[q].mIndices[2] = iBase;
p_pcOut->mFaces[q].mIndices[0] = iBase;
p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].i3];
p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].i3];
}
@@ -505,7 +547,7 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
for (unsigned int i = 0;i < iArray.size();++i)
{
const unsigned int iIndex = iArray[i];
#if 0
if (NULL != pcSOut->mMeshes[iIndex]->mColors[1])
{
pcOut->mTransformation = *((aiMatrix4x4*)
@@ -514,13 +556,11 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
delete (aiMatrix4x4*)pcSOut->mMeshes[iIndex]->mColors[1];
pcSOut->mMeshes[iIndex]->mColors[1] = NULL;
}
#endif
pcOut->mMeshes[i] = iIndex;
}
// NOTE: Not necessary. We can use the given transformation matrix.
// However, we'd need it if we wanted to implement keyframe animation
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
// build the scaling matrix. Toggle y and z axis
aiMatrix4x4 mS;
@@ -536,11 +576,34 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node*
// build the pivot matrix. Toggle y and z axis
aiMatrix4x4 mP;
mP.a4 = pcIn->vPivot.x;
mP.b4 = pcIn->vPivot.z;
mP.c4 = pcIn->vPivot.y;
mP.a4 = -pcIn->vPivot.x;
mP.b4 = -pcIn->vPivot.z;
mP.c4 = -pcIn->vPivot.y;
#endif
// build a matrix to flip the z coordinate of the vertices
aiMatrix4x4 mF;
mF.c3 = -1.0f;
// build the final matrix
// NOTE: This should be the identity. Theoretically. In reality
// there are many models with very funny local matrices and
// very different keyframe values ... this is the only reason
// why we extract the data from the first keyframe.
pcOut->mTransformation = mF; /* mF * mT * pcIn->mRotation * mS * mP *
pcOut->mTransformation.Inverse(); */
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
if (pcOut->mTransformation != mF)
{
DefaultLogger::get()->warn("The local transformation matrix of the "
"3ds file does not match the first keyframe. Using the "
"information from the keyframe.");
}
#endif
pcOut->mTransformation = aiMatrix4x4(); // mT * pcIn->mRotation * mS * mP * pcOut->mTransformation.Inverse();
pcOut->mNumChildren = pcIn->mChildren.size();
pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
@@ -748,6 +811,10 @@ void Dot3DSImporter::BakeScaleNOffset(
{
(*a)->iUVSrc = 0;
}
DefaultLogger::get()->error("There are too many "
"combinations of different UV scaling/offset/rotation operations "
"to generate an UV channel for each (maximum is 4). Using the "
"first UV channel ...");
continue;
}
const aiVector3D* pvBase = _pvBase;
@@ -815,6 +882,9 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
//
unsigned int iCnt = 0;
DefaultLogger::get()->warn("No hierarchy information has been "
"found in the file. A flat hierarchy tree is built ...");
pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes;
pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mNumMeshes ];
@@ -827,7 +897,12 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
pcNode->mMeshes = new unsigned int[1];
pcNode->mMeshes[0] = i;
pcNode->mNumMeshes = 1;
pcNode->mName.Set("UNNAMED");
std::string s;
std::stringstream ss(s);
ss << "UNNAMED[" << i << + "]";
pcNode->mName.Set(s);
// add the new child to the parent node
pcOut->mRootNode->mChildren[i] = pcNode;
@@ -860,6 +935,7 @@ void Dot3DSImporter::ConvertScene(aiScene* pcOut)
this->ConvertMeshes(pcOut);
return;
}
#if 0
// ------------------------------------------------------------------------------------------------
void Dot3DSImporter::GenTexCoord (Dot3DS::Texture* pcTexture,
const std::vector<aiVector2D>& p_vIn,
@@ -886,4 +962,5 @@ void Dot3DSImporter::GenTexCoord (Dot3DS::Texture* pcTexture,
(*a).y += pcTexture->mOffsetV;
}
return;
}
}
#endif

View File

@@ -59,7 +59,7 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh)
sMesh->mNormals.resize(sMesh->mPositions.size(),aiVector3D());
for( unsigned int a = 0; a < sMesh->mFaces.size(); a++)
{
const Dot3DS::Face& face = sMesh->mFaces[a];
Dot3DS::Face& face = sMesh->mFaces[a];
// assume it is a triangle
aiVector3D* pV1 = &sMesh->mPositions[face.i1];

View File

@@ -199,6 +199,7 @@ public:
// Specifies the shininess of the material
// followed by percentage chunk
CHUNK_MAT_SHININESS = 0xA040,
CHUNK_MAT_SHININESS_PERCENT = 0xA041 ,
// Specifies the shading mode to be used
// followed by a short
@@ -304,7 +305,7 @@ public:
/** Helper structure representing a 3ds mesh face */
struct Face
{
Face() : iSmoothGroup(0), bDirection(true), i1(0), i2(0), i3(0)
Face() : iSmoothGroup(0), i1(0), i2(0), i3(0), bFlipped(false)
{
// let the rest uninitialized for performance
}
@@ -327,9 +328,8 @@ struct Face
//! specifies to which smoothing group the face belongs to
uint32_t iSmoothGroup;
//! Direction the normal vector of the face
//! will be pointing to
bool bDirection;
//! Specifies that the face normal must be flipped
bool bFlipped;
};
// ---------------------------------------------------------------------------
/** Helper structure representing a texture */
@@ -376,7 +376,8 @@ struct Material
mTransparency (1.0f),
mBumpHeight (1.0f),
iBakeUVTransform (0),
pcSingleTexture (NULL)
pcSingleTexture (NULL),
mShininessStrength (1.0f)
{
static int iCnt = 0;
std::stringstream ss(mName);
@@ -389,6 +390,8 @@ struct Material
aiColor3D mDiffuse;
//! Specular exponent
float mSpecularExponent;
//! Shininess strength, in percent
float mShininessStrength;
//! Specular color of the material
aiColor3D mSpecular;
//! Ambient color of the material
@@ -462,9 +465,12 @@ struct Mesh
struct Node
{
Node()
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
: vScaling(1.0f,1.0f,1.0f)
#endif
{
static int iCnt = 0;
std::stringstream ss(mName);
@@ -489,6 +495,7 @@ struct Node
//! Index of the node
int16_t mHierarchyIndex;
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
aiVector3D vPivot;
aiVector3D vScaling;
@@ -502,7 +509,7 @@ struct Node
{
mChildren.push_back(pc);
pc->mParent = this;
pc->mHierarchyPos = this->mHierarchyPos+1;
//pc->mHierarchyPos = this->mHierarchyPos+1;
return *this;
}
};

View File

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the 3ds importer class */
#include "3DSLoader.h"
#include "MaterialSystem.h"
#include "DefaultLogger.h"
#include "../include/IOStream.h"
#include "../include/IOSystem.h"
@@ -59,7 +60,6 @@ using namespace Assimp;
"specified in the higher-level chunk header." \
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
Dot3DSImporter::Dot3DSImporter()
@@ -145,6 +145,7 @@ void Dot3DSImporter::InternReadFile(
this->mMasterScale = 1.0f;
this->mBackgroundImage = "";
this->bHasBG = false;
this->mErrorText = "";
int iRemaining = (unsigned int)fileSize;
this->ParseMainChunk(&iRemaining);
@@ -170,31 +171,10 @@ void Dot3DSImporter::InternReadFile(
// Generate it if no material containing DEFAULT in its name has been
// found in the file
this->ReplaceDefaultMaterial();
try
{
// Convert the scene from our internal representation to an aiScene object
this->ConvertScene(pScene);
}
catch (ImportErrorException ex)
{
// delete the scene itself
if (pScene->mMeshes)
{
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
delete pScene->mMeshes[i];
delete[] pScene->mMeshes;
}
if (pScene->mMaterials)
{
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
delete pScene->mMaterials[i];
delete[] pScene->mMaterials;
}
// there are no animations
if (pScene->mRootNode)DeleteNodeRecursively(pScene->mRootNode);
throw ex;
}
// Convert the scene from our internal representation to an aiScene object
this->ConvertScene(pScene);
// Generate the node graph for the scene. This is a little bit
// tricky since we'll need to split some meshes into submeshes
@@ -205,6 +185,12 @@ void Dot3DSImporter::InternReadFile(
delete[] this->mBuffer;
delete this->mScene;
// check whether an error occured during reading ... set it as warning
if ("" != this->mErrorText)
{
DefaultLogger::get()->warn(this->mErrorText);
}
return;
}
// ------------------------------------------------------------------------------------------------
@@ -532,7 +518,7 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
const unsigned char* sz = (unsigned char*)this->mCurrent;
unsigned int iCnt = 0;
uint16_t iHierarchy;
//uint16_t iTemp;
// uint16_t iTemp;
Dot3DS::Node* pcNode;
switch (psChunk->Flag)
{
@@ -554,20 +540,28 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
iHierarchy++;
pcNode->mHierarchyPos = iHierarchy;
pcNode->mHierarchyIndex = this->mLastNodeIndex;
if (iHierarchy > this->mLastNodeIndex)
if (this->mCurrentNode && this->mCurrentNode->mHierarchyPos == iHierarchy)
{
// add to the parent of the last touched node
this->mCurrentNode->mParent->push_back(pcNode);
this->mLastNodeIndex++;
}
else if(iHierarchy >= this->mLastNodeIndex)
{
// place it at the current position in the hierarchy
this->mCurrentNode->push_back(pcNode);
this->mLastNodeIndex = iHierarchy;
}
else
{
// need to go back to the specified position in the hierarchy.
this->InverseNodeSearch(pcNode,this->mCurrentNode);
this->mLastNodeIndex++;
}
this->mLastNodeIndex++;
this->mCurrentNode = pcNode;
break;
// (code for keyframe animation. however, this is currently not supported by Assimp)
#if 0
case Dot3DSFile::CHUNK_TRACKPIVOT:
@@ -651,42 +645,33 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
if (0.0f != fRadians)
{
// if the radians go beyond PI then the rotations
// thereafter must be inversed
#if 0
if (neg)fRadians *= -1.0f;
if ((fRadians >= 3.1415926f || fRadians <= -3.1415926f))
{
neg = !neg;
}
#endif
// get the rotation matrix around the axis
const float fSin = sinf(-fRadians);
const float fCos = cosf(-fRadians);
const float fOneMinusCos = 1.0f - fCos;
std::swap(vAxis.z,vAxis.y);
vAxis.Normalize();
//vAxis.z *= -1.0f;
//vAxis.Normalize();
aiMatrix4x4 mRot = aiMatrix4x4(
(vAxis.x * vAxis.x) * fOneMinusCos + fCos,
(vAxis.x * vAxis.y) * fOneMinusCos - (vAxis.z * fSin),
(vAxis.x * vAxis.z) * fOneMinusCos + (vAxis.y * fSin),
(vAxis.x * vAxis.y) * fOneMinusCos /*-*/- (vAxis.z * fSin),
(vAxis.x * vAxis.z) * fOneMinusCos /*+*/+ (vAxis.y * fSin),
0.0f,
(vAxis.y * vAxis.x) * fOneMinusCos + (vAxis.z * fSin),
(vAxis.y * vAxis.x) * fOneMinusCos /*+*/+ (vAxis.z * fSin),
(vAxis.y * vAxis.y) * fOneMinusCos + fCos,
(vAxis.y * vAxis.z) * fOneMinusCos - (vAxis.x * fSin),
(vAxis.y * vAxis.z) * fOneMinusCos /*-*/- (vAxis.x * fSin),
0.0f,
(vAxis.z * vAxis.x) * fOneMinusCos - (vAxis.y * fSin),
(vAxis.z * vAxis.y) * fOneMinusCos + (vAxis.x * fSin),
(vAxis.z * vAxis.x) * fOneMinusCos /*-*/- (vAxis.y * fSin),
(vAxis.z * vAxis.y) * fOneMinusCos /*+*/+ (vAxis.x * fSin),
(vAxis.z * vAxis.z) * fOneMinusCos + fCos,
0.0f,0.0f,0.0f,0.0f,1.0f);
//mRot.Transpose();
mRot.Transpose();
// build a chain of concatenated rotation matrix'
// if there are multiple track chunks for the same frame
// (there are some silly files usinf this ...)
if (0 != iNum0)
{
this->mCurrentNode->mRotation = this->mCurrentNode->mRotation * mRot;
@@ -739,14 +724,19 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
this->mCurrentNode->vScaling.y *= vMe.y;
this->mCurrentNode->vScaling.z *= vMe.z;
}
else
{
DefaultLogger::get()->warn("Found zero scaling factors. "
"This will be ignored.");
}
this->mCurrent += sizeof(aiVector3D);
}
else this->mCurrent += sizeof(uint32_t) + sizeof(aiVector3D);
}
}
break;
#endif // end keyframe animation code
#endif // 0
};
if ((unsigned int)pcCurNext < (unsigned int)this->mCurrent)
{
@@ -790,13 +780,6 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
{
// nth bit is set for nth smoothing group
(*i).iSmoothGroup = *((uint32_t*)this->mCurrent);
#if 0
for (unsigned int x = 0, a = 1; x < 32;++x,a <<= 1)
{
if ((*i).iSmoothGroup & a)
mMesh.bSmoothGroupRequired[x] = true;
}
#endif
this->mCurrent += sizeof(uint32_t);
}
break;
@@ -955,10 +938,10 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
aiMatrix4x4 mMe = mMesh.mMat;
mMe.a1 *= -1.0f;
mMe.a2 *= -1.0f;
mMe.a3 *= -1.0f;
mMe.a4 *= -1.0f;
mInv = mMe * mInv;
mMe.b1 *= -1.0f;
mMe.c1 *= -1.0f;
mMe.d1 *= -1.0f;
mInv = mInv * mMe;
for (register unsigned int i = 0; i < mMesh.mPositions.size();++i)
{
aiVector3D a,c;
@@ -1007,8 +990,6 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
sFace.i3 = *((uint16_t*)this->mCurrent);
this->mCurrent += 2*sizeof(uint16_t);
mMesh.mFaces.push_back(sFace);
//if (sFace.i1 < sFace.i2)sFace.bDirection = false;
}
// resize the material array (0xcdcdcdcd marks the
@@ -1131,6 +1112,14 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
else *pcf *= (float)0xFFFF;
break;
case Dot3DSFile::CHUNK_MAT_SHININESS_PERCENT:
pcf = &this->mScene->mMaterials.back().mShininessStrength;
*pcf = this->ParsePercentageChunk();
if (is_qnan(*pcf))
*pcf = 0.0f;
else *pcf *= (float)0xffff / 100.0f;
break;
case Dot3DSFile::CHUNK_MAT_SELF_ILPCT:
pcf = &this->mScene->mMaterials.back().sTexEmissive.mTextureBlend;
*pcf = this->ParsePercentageChunk();

View File

@@ -507,10 +507,12 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene)
for (unsigned int t = 0; t < 3;++t)
{
p_pcOut->mFaces[q].mIndices[t] = iBase;
p_pcOut->mVertices[iBase] = mesh.mPositions[mesh.mFaces[iIndex].mIndices[t]];
p_pcOut->mNormals[iBase++] = mesh.mNormals[mesh.mFaces[iIndex].mIndices[t]];
}
p_pcOut->mFaces[q].mIndices[0] = iBase-2;
p_pcOut->mFaces[q].mIndices[1] = iBase-1;
p_pcOut->mFaces[q].mIndices[2] = iBase;
}
}
// convert texture coordinates

View File

@@ -81,24 +81,39 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
{
DefaultLogger::get()->debug("CalcTangentsProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
ProcessMesh( pScene->mMeshes[a]);
if(ProcessMesh( pScene->mMeshes[a]))bHas = true;
DefaultLogger::get()->debug("CalcTangentsProcess finished");
if (bHas)DefaultLogger::get()->debug("CalcTangentsProcess finished. There was much work to do ...");
else DefaultLogger::get()->debug("CalcTangentsProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Calculates tangents and bitangents for the given mesh
void CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
{
// we assume that the mesh is still in the verbose vertex format where each face has its own set
// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
// assert() it here.
//assert( must be verbose, dammit);
// TODO (Aramis)
// If we had a model format in the lib which has native support for
// tangents and bitangents, it would be necessary to add a
// "KillTangentsAndBitangents" flag ...
if (pMesh->mTangents && pMesh->mBitangents)
{
return false;
}
// what we can check, though, is if the mesh has normals and texture coord. That's a requirement
if( pMesh->mNormals == NULL || pMesh->mTextureCoords[0] == NULL)
return;
{
DefaultLogger::get()->error("Normal vectors and at least one "
"texture coordinate set are required to calculate tangents. ");
return false;
}
// calculate the position bounds so we have a reliable epsilon to check position differences against
aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f);
@@ -229,4 +244,5 @@ void CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
meshBitang[ closeVertices[b] ] = smoothBitangent;
}
}
return true;
}

View File

@@ -89,7 +89,7 @@ protected:
/** Calculates tangents and bitangents for the given mesh
* @param pMesh The mesh to process.
*/
void ProcessMesh( aiMesh* pMesh);
bool ProcessMesh( aiMesh* pMesh);
};
} // end of namespace Assimp

View File

@@ -51,7 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
// ---------------------------------------------------------------------------
DefaultLogger *DefaultLogger::m_pLogger = NULL;
NullLogger DefaultLogger::s_pNullLogger;
Logger *DefaultLogger::m_pLogger = &DefaultLogger::s_pNullLogger;
// ---------------------------------------------------------------------------
//
@@ -72,17 +73,29 @@ struct LogStreamInfo
// Creates the only singleton instance
Logger *DefaultLogger::create(const std::string &name, LogSeverity severity)
{
ai_assert (NULL == m_pLogger);
m_pLogger = new DefaultLogger( name, severity );
return m_pLogger;
}
// ---------------------------------------------------------------------------
void DefaultLogger::set (Logger *logger)
{
if (!logger)
{
DefaultLogger::m_pLogger = &s_pNullLogger;
return;
}
DefaultLogger::m_pLogger = logger;
}
// ---------------------------------------------------------------------------
bool DefaultLogger::isNullLogger()
{
return m_pLogger == &s_pNullLogger;
}
// ---------------------------------------------------------------------------
// Singleton getter
Logger *DefaultLogger::get()
{
ai_assert (NULL != m_pLogger);
return m_pLogger;
}
@@ -92,7 +105,7 @@ void DefaultLogger::kill()
{
ai_assert (NULL != m_pLogger);
delete m_pLogger;
m_pLogger = NULL;
m_pLogger = &s_pNullLogger;
}
// ---------------------------------------------------------------------------
@@ -142,6 +155,22 @@ void DefaultLogger::setLogSeverity( LogSeverity log_severity )
void DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
{
ai_assert ( NULL != pStream );
// fix (Aramis)
if (0 == severity)
{
severity = Logger::INFO | Logger::ERR | Logger::WARN | Logger::DEBUGGING;
}
for ( StreamIt it = m_StreamArray.begin();
it != m_StreamArray.end();
++it )
{
if ( (*it)->m_pStream == pStream )
{
(*it)->m_uiErrorSeverity |= severity;
}
}
LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
m_StreamArray.push_back( pInfo );
@@ -152,6 +181,12 @@ void DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
void DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
{
ai_assert ( NULL != pStream );
// fix (Aramis)
if (0 == severity)
{
severity = Logger::INFO | Logger::ERR | Logger::WARN | Logger::DEBUGGING;
}
for ( StreamIt it = m_StreamArray.begin();
it != m_StreamArray.end();
@@ -166,6 +201,9 @@ void DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
uiSev &= ( ~Logger::WARN );
if ( severity & Logger::ERR )
uiSev &= ( ~Logger::ERR );
// fix (Aramis)
if ( severity & Logger::DEBUGGING )
uiSev &= ( ~Logger::DEBUGGING );
(*it)->m_uiErrorSeverity = uiSev;

View File

@@ -38,6 +38,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#if (!defined AI_DEFAULTLOGGER_H_INCLUDED)
#define AI_DEFAULTLOGGER_H_INCLUDED
#include "../include/Logger.h"
#include <vector>
@@ -47,6 +50,39 @@ namespace Assimp
class IOStream;
struct LogStreamInfo;
// ---------------------------------------------------------------------------
/** @class NullLogger
* @brief Empty logging implementation. Does nothing. Used by default
* if the application hasn't specified a custom logger (or DefaultLogger)
* via DefaultLogger::set() or DefaultLogger::create();
*/
class NullLogger : public Logger
{
public:
/** @brief Logs a debug message */
void debug(const std::string &message) {}
/** @brief Logs an info message */
void info(const std::string &message) {}
/** @brief Logs a warning message */
void warn(const std::string &message) {}
/** @brief Logs an error message */
void error(const std::string &message) {}
/** @brief Log severity setter */
void setLogSeverity(LogSeverity log_severity) {}
/** @brief Detach a still attached stream from logger */
void attachStream(LogStream *pStream, unsigned int severity) {}
/** @brief Detach a still attached stream from logger */
void detatchStream(LogStream *pStream, unsigned int severity) {}
};
// ---------------------------------------------------------------------------
/** @class DefaultLogger
* @brief Default logging implementation. The logger writes into a file.
@@ -57,18 +93,39 @@ class DefaultLogger :
public Logger
{
public:
/** @brief Creates the only logging instance
/** @brief Creates a custom logging instance (DefaultLogger)
* @param name Name for logfile
* @param severity Log severity, VERBOSE will activate debug messages
*
* This replaces the default NullLogger with a DefaultLogger instance.
*/
static Logger *create(const std::string &name, LogSeverity severity);
/** @brief Setup a custom implementation of the Logger interface as
* default logger.
*
* Use this if the provided DefaultLogger class doesn't fit into
* your needs. If the provided message formatting is OK for you,
* it is easier to use create() to create a DefaultLogger and to attach
* your own custom output streams to it than using this method.
* @param logger Pass NULL to setup a default NullLogger
*/
static void set (Logger *logger);
/** @brief Getter for singleton instance
* @return Only instance
* @return Only instance. This is never null, but it could be a
* NullLogger. Use isNullLogger to check this.
*/
static Logger *get();
/** @brief Return whether a default NullLogger is currently active
* @return true if the current logger id a NullLogger.
* Use create() or set() to setup a custom logger.
*/
static bool isNullLogger();
/** @brief Will kill the singleton instance */
/** @brief Will kill the singleton instance and setup a NullLogger as
logger */
static void kill();
/** @brief Logs debug infos, only been written when severity level VERBOSE is set */
@@ -112,7 +169,9 @@ private:
typedef std::vector<LogStreamInfo*>::const_iterator ConstStreamIt;
//! only logging instance
static DefaultLogger *m_pLogger;
static Logger *m_pLogger;
static NullLogger s_pNullLogger;
//! Logger severity
LogSeverity m_Severity;
//! Attached streams
@@ -123,3 +182,5 @@ private:
// ---------------------------------------------------------------------------
} // Namespace Assimp
#endif // !! AI_DEFAULTLOGGER_H_INCLUDED

View File

@@ -109,6 +109,9 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
aiVector3D pDelta2 = *pV3 - *pV1;
aiVector3D vNor = pDelta1 ^ pDelta2;
if (face.mIndices[1] > face.mIndices[2])
vNor *= -1.0f;
for (unsigned int i = 0;i < face.mNumIndices;++i)
{
pMesh->mNormals[face.mIndices[i]] = vNor;

View File

@@ -110,6 +110,9 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
aiVector3D pDelta2 = *pV3 - *pV1;
aiVector3D vNor = pDelta1 ^ pDelta2;
if (face.mIndices[1] > face.mIndices[2])
vNor *= -1.0f;
for (unsigned int i = 0;i < face.mNumIndices;++i)
{
pMesh->mNormals[face.mIndices[i]] = vNor;

View File

@@ -99,10 +99,6 @@ Importer::Importer() :
mScene(NULL),
mErrorString("")
{
// construct a new logger
/*DefaultLogger::create( "test.log", DefaultLogger::VERBOSE );
DefaultLogger::get()->info("Start logging");*/
// allocate a default IO handler
mIOHandler = new DefaultIOSystem;

View File

@@ -244,6 +244,7 @@ void MD2Importer::InternReadFile(
unsigned int iCurrent = 0;
if (0 != this->m_pcHeader->numTexCoords)
{
for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i)
{
// allocate the face
@@ -253,10 +254,9 @@ void MD2Importer::InternReadFile(
// copy texture coordinates
// check whether they are different from the previous value at this index.
// In this case, create a full separate set of vertices/normals/texcoords
unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent)
{
pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
// validate vertex indices
if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
@@ -295,6 +295,9 @@ void MD2Importer::InternReadFile(
pcOut->x = u;
pcOut->y = v;
}
pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2;
pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1;
pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0;
}
}
else
@@ -308,10 +311,9 @@ void MD2Importer::InternReadFile(
// copy texture coordinates
// check whether they are different from the previous value at this index.
// In this case, create a full separate set of vertices/normals/texcoords
unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent)
{
pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
// validate vertex indices
if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices)
pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1;
@@ -343,6 +345,9 @@ void MD2Importer::InternReadFile(
pcOut->x = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth;
pcOut->y = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight;
}
pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2;
pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1;
pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0;
}
}

View File

@@ -254,7 +254,7 @@ struct Vertex
* \note This has been taken from q3 source (misc_model.c)
*/
// ---------------------------------------------------------------------------
inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
inline void LatLngNormalToVec3(int16_t p_iNormal, float* p_afOut)
{
float lat = (float)(( p_iNormal >> 8 ) & 0xff);
float lng = (float)(( p_iNormal & 0xff ));

View File

@@ -201,25 +201,28 @@ void MD3Importer::InternReadFile(
pcMesh->mFaces[i].mIndices = new unsigned int[3];
pcMesh->mFaces[i].mNumIndices = 3;
unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent)
{
pcMesh->mFaces[i].mIndices[c] = iCurrent;
// read vertices
pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X;
pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y;
pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z * -1.0f;
pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z*-1.0f;
// convert the normal vector to uncompressed float3 format
LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
(float*)&pcMesh->mNormals[iCurrent]);
std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
//std::swap(pcMesh->mNormals[iCurrent].z,pcMesh->mNormals[iCurrent].y);
pcMesh->mNormals[iCurrent].z *= -1.0f;
// read texture coordinates
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V;
}
pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
pcTriangles++;
}

View File

@@ -654,6 +654,7 @@ void MDLImporter::InternReadFile_Quake1( )
pcMesh->mFaces[i].mIndices = new unsigned int[3];
pcMesh->mFaces[i].mNumIndices = 3;
unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent)
{
pcMesh->mFaces[i].mIndices[c] = iCurrent;
@@ -705,6 +706,9 @@ void MDLImporter::InternReadFile_Quake1( )
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
}
pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
pcTriangles++;
}
return;
@@ -824,10 +828,9 @@ void MDLImporter::InternReadFile_GameStudio( )
pcMesh->mFaces[i].mIndices = new unsigned int[3];
pcMesh->mFaces[i].mNumIndices = 3;
unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent)
{
pcMesh->mFaces[i].mIndices[c] = iCurrent;
// read vertices
unsigned int iIndex = pcTriangles->index_xyz[c];
if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
@@ -879,6 +882,9 @@ void MDLImporter::InternReadFile_GameStudio( )
vTexCoords[iCurrent].x = s;
vTexCoords[iCurrent].y = t;
}
pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
pcTriangles++;
}
@@ -901,10 +907,9 @@ void MDLImporter::InternReadFile_GameStudio( )
pcMesh->mFaces[i].mIndices = new unsigned int[3];
pcMesh->mFaces[i].mNumIndices = 3;
unsigned int iTemp = iCurrent;
for (unsigned int c = 0; c < 3;++c,++iCurrent)
{
pcMesh->mFaces[i].mIndices[c] = iCurrent;
// read vertices
unsigned int iIndex = pcTriangles->index_xyz[c];
if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
@@ -956,6 +961,9 @@ void MDLImporter::InternReadFile_GameStudio( )
vTexCoords[iCurrent].x = s;
vTexCoords[iCurrent].y = t;
}
pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
pcTriangles++;
}
}
@@ -1384,7 +1392,7 @@ void MDLImporter::InternReadFile_GameStudioA7( )
unsigned int iOutIndex = iTriangle * 3 + c;
// write the output face index
pcFaces[iTriangle].mIndices[c] = iOutIndex;
pcFaces[iTriangle].mIndices[c] = iTriangle * 3 + (2-c);
// swap z and y axis
vPositions[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x;

221
code/MakeVerboseFormat.cpp Normal file
View File

@@ -0,0 +1,221 @@
/*
---------------------------------------------------------------------------
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 Implementation of the post processing step "MakeVerboseFormat"
*/
#include "MakeVerboseFormat.h"
#include "DefaultLogger.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
using namespace Assimp;
MakeVerboseFormatProcess::MakeVerboseFormatProcess()
{
// nothing to do here
}
MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
{
// nothing to do here
}
// -------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MakeVerboseFormatProcess::Execute( aiScene* pScene)
{
ai_assert(NULL != pScene);
DefaultLogger::get()->debug("MakeVerboseFormatProcess begin");
bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
{
if( this->MakeVerboseFormat( pScene->mMeshes[a]))
bHas = true;
}
if (bHas)DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ...");
else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");
}
// -------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
{
ai_assert(NULL != pcMesh);
unsigned int iOldNumVertices = pcMesh->mNumVertices;
const unsigned int iNumVerts = pcMesh->mNumFaces*3;
aiVector3D* pvPositions = new aiVector3D[iNumVerts];
aiVector3D* pvNormals;
if (pcMesh->HasNormals())
{
pvNormals = new aiVector3D[iNumVerts];
}
aiVector3D* pvTangents, *pvBitangents;
if (pcMesh->HasTangentsAndBitangents())
{
pvTangents = new aiVector3D[iNumVerts];
pvBitangents = new aiVector3D[iNumVerts];
}
ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == 4);
ai_assert(AI_MAX_NUMBER_OF_COLOR_SETS == 4);
aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {NULL,NULL,NULL,NULL};
aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {NULL,NULL,NULL,NULL};
unsigned int p = 0;
while (pcMesh->HasTextureCoords(p))
apvTextureCoords[p++] = new aiVector3D[iNumVerts];
p = 0;
while (pcMesh->HasVertexColors(p))
apvColorSets[p++] = new aiColor4D[iNumVerts];
// allocate enough memory to hold output bones and vertex weights ...
std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{
newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
}
// iterate through all faces and build a clean list
unsigned int iIndex = 0;
for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
{
aiFace* pcFace = &pcMesh->mFaces[a];
for (unsigned int q = 0; q < 3;++q,++iIndex)
{
// need to build a clean list of bones, too
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{
for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++)
{
const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a];
if(pcFace->mIndices[q] == w.mVertexId)
{
aiVertexWeight wNew;
wNew.mVertexId = iIndex;
wNew.mWeight = w.mWeight;
newWeights[i].push_back(wNew);
}
}
}
pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
if (pcMesh->HasNormals())
{
pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
}
if (pcMesh->HasTangentsAndBitangents())
{
pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
}
unsigned int p = 0;
while (pcMesh->HasTextureCoords(p))
{
apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]];
++p;
}
p = 0;
while (pcMesh->HasVertexColors(p))
{
apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]];
++p;
}
pcFace->mIndices[q] = iIndex;
}
}
// build output vertex weights
for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{
delete pcMesh->mBones[i]->mWeights;
if (!newWeights[i].empty())
{
pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
memcpy(pcMesh->mBones[i]->mWeights,&newWeights[i][0],
sizeof(aiVertexWeight) * newWeights[i].size());
}
else pcMesh->mBones[i]->mWeights = NULL;
}
// delete the old members
delete[] pcMesh->mVertices;
pcMesh->mVertices = pvPositions;
p = 0;
while (pcMesh->HasTextureCoords(p))
{
delete pcMesh->mTextureCoords[p];
pcMesh->mTextureCoords[p] = apvTextureCoords[p];
++p;
}
p = 0;
while (pcMesh->HasVertexColors(p))
{
delete pcMesh->mColors[p];
pcMesh->mColors[p] = apvColorSets[p];
++p;
}
pcMesh->mNumVertices = iNumVerts;
if (pcMesh->HasNormals())
{
delete[] pcMesh->mNormals;
pcMesh->mNormals = pvNormals;
}
if (pcMesh->HasTangentsAndBitangents())
{
delete[] pcMesh->mTangents;
pcMesh->mTangents = pvTangents;
delete[] pcMesh->mBitangents;
pcMesh->mBitangents = pvBitangents;
}
return (pcMesh->mNumVertices != iOldNumVertices);
}

106
code/MakeVerboseFormat.h Normal file
View File

@@ -0,0 +1,106 @@
/*
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 bring a given scene
into the verbose format that is expected by most postprocess steps.
This is the inverse of the "JoinIdenticalVertices" steps */
#ifndef AI_MAKEVERBOSEFORMAT_H_INC
#define AI_MAKEVERBOSEFORMAT_H_INC
#include "BaseProcess.h"
#include "../include/aiMesh.h"
namespace Assimp
{
// ---------------------------------------------------------------------------
/** MakeVerboseFormatProcess: Class to convert an asset to the verbose
* format which is expected by most postprocess steps.
*
* This is the inverse of what the "JoinIdenticalVertices" step is doing.
* This step has no official flag (since it wouldn't make sense to run it
* during import). It is intended for applications intending to modify the
* returned aiScene. After this step has been executed, they can execute
* other postprocess steps on the data.
* The step has been added because it was required by the viewer, however
* it has been moved to the main library since others might find it
* useful, too.
*/
class MakeVerboseFormatProcess : public BaseProcess
{
friend class Importer;
public:
/** Constructor to be privately used by Importer, or by applications
which know what they are doing if they modify the aiScene object */
MakeVerboseFormatProcess();
/** Destructor, private as well */
~MakeVerboseFormatProcess();
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
{
// NOTE: There is no direct flag that corresponds to
// this postprocess step.
return false;
}
// -------------------------------------------------------------------
/** 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);
private:
//! Apply the postprocess step to a given submesh
bool MakeVerboseFormat (aiMesh* pcMesh);
};
}; // end of namespace Assimp
#endif // !!AI_KILLNORMALPROCESS_H_INC

View File

@@ -64,7 +64,7 @@ aiReturn aiSetVertexSplitLimit(unsigned int pLimit)
}
SplitLargeMeshesProcess_Vertex::LIMIT = pLimit;
//DefaultLogger::get()->debug("aiSetVertexSplitLimit() - vertex split limit was changed");
DefaultLogger::get()->debug("aiSetVertexSplitLimit() - vertex split limit was changed");
return AI_SUCCESS;
}
// ------------------------------------------------------------------------------------------------
@@ -77,7 +77,7 @@ aiReturn aiSetTriangleSplitLimit(unsigned int pLimit)
}
SplitLargeMeshesProcess_Triangle::LIMIT = pLimit;
//DefaultLogger::get()->debug("aiSetTriangleSplitLimit() - triangle split limit was changed");
DefaultLogger::get()->debug("aiSetTriangleSplitLimit() - triangle split limit was changed");
return AI_SUCCESS;
}
}; //! extern "C"

View File

@@ -570,7 +570,8 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
// material colours
mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
// FIX: Setup this as ambient not as emissive color
mat->AddProperty( &oldMat.mEmissive, 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.mSpecularExponent, 1, AI_MATKEY_SHININESS);

134
code/jAssimp/JNILogger.cpp Normal file
View File

@@ -0,0 +1,134 @@
/*
---------------------------------------------------------------------------
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 Implementation of the JNI API for jAssimp */
#if (defined ASSIMP_JNI_EXPORT)
// include assimp
#include "../../include/aiTypes.h"
#include "../../include/aiMesh.h"
#include "../../include/aiAnim.h"
#include "../../include/aiScene.h"
#include "../../include/aiAssert.h"
#include "../../include/aiPostProcess.h"
#include "../../include/assimp.hpp"
#include "../DefaultLogger.h"
#include "JNILogger.h"
using namespace Assimp;
namespace Assimp {
namespace JNIBridge {
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::SetJNIEnvironment(JNIEnv* ptr)
{
// there is much error handling code in this function.
// However, it is not impossible that the jAssimp package
// loaded by the JVM is incomplete ...
jclass java_lang_Exception = this->GetJNIEnv()->FindClass("java.lang.Exception");
// get a handle to the assimp.DefaultLogger class
this->m_pcJNIEnv = ptr;
if( NULL == (this->m_pcClass = this->GetJNIEnv()->FindClass("assimp.DefaultLogger")))
{
this->GetJNIEnv()->ThrowNew(java_lang_Exception,
"Unable to get class handle to assimp.DefaultLogger");
return;
}
// get handles to the logging functions
if( NULL == (this->m_pcMethodError = this->GetJNIEnv()->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteError","(Ljava/lang/String;)V")))
{
this->GetJNIEnv()->ThrowNew(java_lang_Exception,
"Unable to get class handle to assimp.DefaultLogger._NativeCallWriteError()");
return;
}
if( NULL == (this->m_pcMethodWarn = this->GetJNIEnv()->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteWarn","(Ljava/lang/String;)V")))
{
this->GetJNIEnv()->ThrowNew(java_lang_Exception,
"Unable to get class handle to assimp.DefaultLogger._NativeCallWriteWarn()");
return;
}
if( NULL == (this->m_pcMethodInfo = this->GetJNIEnv()->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteInfo","(Ljava/lang/String;)V")))
{
this->GetJNIEnv()->ThrowNew(java_lang_Exception,
"Unable to get class handle to assimp.DefaultLogger._NativeCallWriteInfo()");
return;
}
if( NULL == (this->m_pcMethodDebug = this->GetJNIEnv()->GetStaticMethodID(
this->m_pcClass,"_NativeCallWriteDebug","(Ljava/lang/String;)V")))
{
this->GetJNIEnv()->ThrowNew(java_lang_Exception,
"Unable to get class handle to assimp.DefaultLogger._NativeCallWriteDebug()");
}
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::debug(const std::string &message)
{
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::info(const std::string &message)
{
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::warn(const std::string &message)
{
}
// ------------------------------------------------------------------------------------------------
void JNILogDispatcher::error(const std::string &message)
{
}
};};
#endif // jni

122
code/jAssimp/JNILogger.h Normal file
View File

@@ -0,0 +1,122 @@
/*
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.
----------------------------------------------------------------------
*/
#if (!defined AI_JNILOGGER_H_INCLUDED)
#define AI_JNILOGGER_H_INCLUDED
#include "../../include/Logger.h"
#include <vector>
#include <jni.h>
namespace Assimp {
namespace JNIBridge {
// ---------------------------------------------------------------------------
class IOStream;
struct LogStreamInfo;
// ---------------------------------------------------------------------------
/** @class JNILogDispatcher
* @brief Logging system implementation that is used to send all
* log messages generated by native code to the Java logging system.
*/
class JNILogDispatcher : public Logger
{
public:
/** @brief Logs a debug message */
void debug(const std::string &message);
/** @brief Logs an info message */
void info(const std::string &message);
/** @brief Logs a warning message */
void warn(const std::string &message);
/** @brief Logs an error message */
void error(const std::string &message);
/** @brief Log severity setter */
void setLogSeverity(LogSeverity log_severity) {}
/** @brief Detach a still attached stream from logger */
void attachStream(LogStream *pStream, unsigned int severity) {}
/** @brief Detach a still attached stream from logger */
void detatchStream(LogStream *pStream, unsigned int severity) {}
//! Setup the JNI environment to use
//! (must be attached to the thread)
//! \param ptr Java environment to be used. != 0
void SetJNIEnvironment(JNIEnv* ptr);
//! Get the current JNI environment
inline JNIEnv* GetJNIEnv()
{
ai_assert(NULL != m_pcJNIEnv);
return m_pcJNIEnv;
}
private:
//! JNI environment pointer
JNIEnv* m_pcJNIEnv;
//! Handle to assimp.DefaultLogger class
jclass m_pcClass;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteError() method
jmethodID m_pcMethodError;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteInfo() method
jmethodID m_pcMethodInfo;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteDebug() method
jmethodID m_pcMethodDebug;
//! Handle to the static assimp.DefaultLogger._NativeCallWriteWarn() method
jmethodID m_pcMethodWarn;
};
};};
#endif // AI_JNILOGGER_H_INCLUDED