ASE: Added WIP support for *SMOOTHSKINMESH elements in ASE/ASC files. Fixes in the ASE loader. Fixed animation parsing. Temporary implementation of target lights and cameras, including animations.

3DS: Fixed transformation problems (Pivot points), added WIP animation support. No target animation yet (cameras, spot lights). Not yet fully tested, but static models that worked before should still work now, except all look correct now :-) (some problems with very large models remaining)
Further work on the IRR and IRRMESH loaders. IRR still WIP, IRRMESH more stable now.
Work on the LWo loader. Added support for the "one-layer-only" mode. Hierarchy bug still unfixed, UV coords bug still unfixed.
Further work on the FindInvalidDataprocess. Improved validation for normals, no false positives anymore.
Further work on the MDR loader, still WIP.
Moved DeterminePType-Step to ScenePreprocessor.
aiAnimation::mDuration is optional now, ScenePreprocessor computes it automatically if set to -1.
Fixes in the SMD loader. Still crashes on some files.
Updated animation documentation.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@236 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2008-11-09 23:17:19 +00:00
parent 06e4262f80
commit f7aa836330
50 changed files with 4252 additions and 737 deletions

View File

@@ -47,6 +47,7 @@ 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;
@@ -528,7 +529,7 @@ 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
// Append the "real" name of the dummy to the string
pcIn->mName.append(pcIn->mDummyName);
}
else // if (pcIn->mName != "$$$DUMMY")
@@ -538,25 +539,18 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
ai_assert(NULL != pcMesh);
// do case independent comparisons here, just for safety
if (!ASSIMP_stricmp(pcIn->mName,pcMesh->mName))
if (pcIn->mName == pcMesh->mName)
iArray.push_back(a);
}
if (!iArray.empty())
{
// The matrix should be identical for all meshes.
// 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();
/* abs = mTrafo;
pcOut->mTransformation = absTrafo;
pcOut->mTransformation = pcOut->mTransformation.Inverse() * mTrafo;
const aiVector3D& pivot = pcIn->vPivot;
aiMatrix4x4 trans;
*/
const aiVector3D& pivot = pcIn->vPivot;
pcOut->mNumMeshes = (unsigned int)iArray.size();
@@ -566,7 +560,8 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
const unsigned int iIndex = iArray[i];
aiMesh* const mesh = pcSOut->mMeshes[iIndex];
// http://www.zfx.info/DisplayThread.php?MID=235690#235690
// 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;
@@ -578,11 +573,9 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
pvCurrent->x -= pivot.x;
pvCurrent->y -= pivot.y;
pvCurrent->z -= pivot.z;
*pvCurrent = mTrafo * (*pvCurrent);
++pvCurrent;
}
}
#if 0
else
{
while (pvCurrent != pvEnd)
@@ -591,7 +584,6 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
++pvCurrent;
}
}
#endif
// Setup the mesh index
pcOut->mMeshes[i] = iIndex;
@@ -599,75 +591,143 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
}
}
// Now build the transformation matrix of the node
// ROTATION
if (pcIn->aRotationKeys.size())
{
pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() );
}
else if (pcIn->aCameraRollKeys.size())
{
aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue),
pcOut->mTransformation);
}
// SCALING
aiMatrix4x4& m = pcOut->mTransformation;
if (pcIn->aScalingKeys.size())
{
const aiVector3D& v = pcIn->aScalingKeys[0].mValue;
m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x;
m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y;
m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z;
}
// TRANSLATION
if (pcIn->aPositionKeys.size())
{
const aiVector3D& v = pcIn->aPositionKeys[0].mValue;
m.a4 += v.x;
m.b4 += v.y;
m.c4 += v.z;
}
// Generate animation channels for the node
if (pcIn->aPositionKeys.size() > 0 || pcIn->aRotationKeys.size() > 0 ||
pcIn->aScalingKeys.size() > 0 || pcIn->aCameraRollKeys.size() > 0 ||
pcIn->aTargetPositionKeys.size() > 0)
if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 ||
pcIn->aScalingKeys.size() > 1 || pcIn->aCameraRollKeys.size() > 1 ||
pcIn->aTargetPositionKeys.size() > 1)
{
aiAnimation* anim = pcSOut->mAnimations[0];
ai_assert(NULL != anim);
// Allocate a new channel, increment the channel index
aiNodeAnim* channel = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
// POSITION keys
if (pcIn->aPositionKeys.size() > 0)
if (pcIn->aCameraRollKeys.size() > 1)
{
// Sort all keys with ascending time values
std::sort(pcIn->aPositionKeys.begin(),pcIn->aPositionKeys.end());
DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
channel->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
channel->mPositionKeys = new aiVectorKey[channel->mNumPositionKeys];
::memcpy(channel->mPositionKeys,&pcIn->aPositionKeys[0],
sizeof(aiVectorKey)*channel->mNumPositionKeys);
// Camera roll keys - in fact they're just rotations
// around the camera's z axis. The angles are given
// in degrees (and they're clockwise).
pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size());
for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i)
{
aiQuatKey& q = pcIn->aRotationKeys[i];
aiFloatKey& f = pcIn->aCameraRollKeys[i];
// Get the maximum key
anim->mDuration = std::max(anim->mDuration,channel->
mPositionKeys[channel->mNumPositionKeys-1].mTime);
q.mTime = f.mTime;
q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD(- f.mValue));
}
}
// ROTATION keys
if (pcIn->aRotationKeys.size() > 0)
if (pcIn->aTargetPositionKeys.size() > 1)
{
// Sort all keys with ascending time values
std::sort(pcIn->aRotationKeys.begin(),pcIn->aRotationKeys.end());
//DefaultLogger::get()->debug("3DS: Converting target track ...");
channel->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
channel->mRotationKeys = new aiQuatKey[channel->mNumRotationKeys];
::memcpy(channel->mRotationKeys,&pcIn->aRotationKeys[0],
sizeof(aiQuatKey)*channel->mNumRotationKeys);
//// Camera or spot light - need to convert the separate
//// target position channel to our representation
//TargetAnimationHelper helper;
// Get the maximum key
anim->mDuration = std::max(anim->mDuration,channel->
mRotationKeys[channel->mNumRotationKeys-1].mTime);
//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);
}
// SCALING keys
if (pcIn->aScalingKeys.size() > 0)
// Just for safety ... we *should* have at least one track here
if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 ||
pcIn->aScalingKeys.size() > 1)
{
// Sort all keys with ascending time values
std::sort(pcIn->aScalingKeys.begin(),pcIn->aScalingKeys.end());
// Allocate a new nda, increment the nda index
aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
nda->mNodeName.Set(pcIn->mName);
channel->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
channel->mScalingKeys = new aiVectorKey[channel->mNumScalingKeys];
::memcpy(channel->mScalingKeys,&pcIn->aScalingKeys[0],
sizeof(aiVectorKey)*channel->mNumScalingKeys);
// POSITION keys
if (pcIn->aPositionKeys.size() > 0)
{
nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
sizeof(aiVectorKey)*nda->mNumPositionKeys);
}
// Get the maximum key
anim->mDuration = std::max(anim->mDuration,channel->
mScalingKeys[channel->mNumScalingKeys-1].mTime);
// 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);
}
// 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);
}
}
}
// Setup the name of the node
pcOut->mName.Set(pcIn->mName);
// Allocate storage for children
// Allocate storage for children
pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
// Recursively process all children
for (unsigned int i = 0; i < pcIn->mChildren.size();++i)
const unsigned int size = pcIn->mChildren.size();
for (unsigned int i = 0; i < size;++i)
{
pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut;
@@ -683,11 +743,13 @@ void CountTracks(D3DS::Node* node, unsigned int& cnt)
// We will never generate more than one channel for a node, so
// this is rather easy here.
if (node->aPositionKeys.size() > 0 || node->aRotationKeys.size() > 0 ||
node->aScalingKeys.size() > 0 || node->aCameraRollKeys.size() > 0 ||
node->aTargetPositionKeys.size() > 0)
if (node->aPositionKeys.size() > 1 || node->aRotationKeys.size() > 1 ||
node->aScalingKeys.size() > 1 || node->aCameraRollKeys.size() > 1 ||
node->aTargetPositionKeys.size() > 1)
{
++cnt;
if (node->aTargetPositionKeys.size() > 1)++cnt;
}
// Recursively process all children
@@ -778,6 +840,14 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
aiMatrix4x4 m;
AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m);
// If the root node is unnamed name it "<3DSRoot>"
if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" )
|| pcOut->mRootNode->mName.data[0] == '$'
&& pcOut->mRootNode->mName.data[1] == '$')
{
pcOut->mRootNode->mName.Set("<3DSRoot>");
}
}
// We used the first vertex color set to store some
@@ -795,10 +865,6 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
delete pcOld;
}
// if the root node is a default node setup a name for it
if (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$')
pcOut->mRootNode->mName.Set("<root>");
#if 0
// modify the transformation of the root node to change
// the coordinate system of the whole scene from Max' to OpenGL