Added ScenePreProcessor helper class to add missing dummy animation channels.
Modified FindInvalidData's behaviour regarding animation channels Futher work on the IRR scene and IRRMESH loaders. Q3D fix. Updated aiNodeAnim documentation. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@218 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
4daa0294a2
commit
ac200212a9
|
@ -134,30 +134,11 @@ void FindInvalidDataProcess::Execute( aiScene* pScene)
|
|||
|
||||
// Process animations
|
||||
for (unsigned int a = 0; a < pScene->mNumAnimations;++a)
|
||||
{
|
||||
int result;
|
||||
if ((result = ProcessAnimation( pScene->mAnimations[a])))
|
||||
{
|
||||
out = true;
|
||||
ProcessAnimation( pScene->mAnimations[a]);
|
||||
|
||||
if (2 == result)
|
||||
{
|
||||
// remove this animation
|
||||
delete pScene->mAnimations[a];
|
||||
AI_DEBUG_INVALIDATE_PTR(pScene->mAnimations[a]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pScene->mAnimations[realAnimations++] = pScene->mAnimations[a];
|
||||
}
|
||||
|
||||
if (out)
|
||||
{
|
||||
if(!(pScene->mNumAnimations = realAnimations))
|
||||
{
|
||||
delete[] pScene->mAnimations;
|
||||
pScene->mAnimations = NULL;
|
||||
}
|
||||
if ( real != pScene->mNumMeshes)
|
||||
{
|
||||
if (!real)
|
||||
|
@ -237,55 +218,60 @@ inline bool AllIdentical(T* in, unsigned int num)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Search an animation for invalid content
|
||||
int FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim)
|
||||
void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim)
|
||||
{
|
||||
bool out = false;
|
||||
unsigned int real = 0;
|
||||
|
||||
// Process all animation channels
|
||||
for (unsigned int a = 0; a < anim->mNumChannels;++a)
|
||||
{
|
||||
int result;
|
||||
if ((result = ProcessAnimationChannel( anim->mChannels[a])))
|
||||
{
|
||||
out = true;
|
||||
// remove this animation channel
|
||||
delete anim->mChannels[a];
|
||||
AI_DEBUG_INVALIDATE_PTR(anim->mChannels[a]);
|
||||
continue;
|
||||
}
|
||||
anim->mChannels[real++] = anim->mChannels[a];
|
||||
}
|
||||
if (out)
|
||||
{
|
||||
anim->mNumChannels = real;
|
||||
if (!real)
|
||||
{
|
||||
DefaultLogger::get()->error("Deleting anim: it consists of dummy tracks");
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
ProcessAnimationChannel( anim->mChannels[a]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
|
||||
void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
|
||||
{
|
||||
// TODO: (thom) For some reason, even proper channels are deleted as well. Therefore deactivated it for the moment.
|
||||
//return 0;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Check whether all values are identical or whether there is just one keyframe
|
||||
if ((anim->mNumPositionKeys < 1 || AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys)) &&
|
||||
(anim->mNumScalingKeys < 1 || AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys)) &&
|
||||
(anim->mNumRotationKeys < 1 || AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys)))
|
||||
// ScenePreprocessor's work ...
|
||||
ai_assert(0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys);
|
||||
|
||||
// Check whether all values in a tracks are identical - in this case
|
||||
// we can remove al keys except one.
|
||||
// POSITIONS
|
||||
if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys))
|
||||
{
|
||||
DefaultLogger::get()->error("Deleting dummy position animation channel");
|
||||
return 1;
|
||||
aiVectorKey v = anim->mPositionKeys[0];
|
||||
|
||||
// Reallocate ... we need just ONE element, it makes no sense to reuse the array
|
||||
delete[] anim->mPositionKeys;
|
||||
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1];
|
||||
anim->mPositionKeys[0] = v;
|
||||
i = 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
// ROTATIONS
|
||||
if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys))
|
||||
{
|
||||
aiQuatKey v = anim->mRotationKeys[0];
|
||||
|
||||
// Reallocate ... we need just ONE element, it makes no sense to reuse the array
|
||||
delete[] anim->mRotationKeys;
|
||||
anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1];
|
||||
anim->mRotationKeys[0] = v;
|
||||
i = 1;
|
||||
}
|
||||
|
||||
// SCALINGS
|
||||
if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys))
|
||||
{
|
||||
aiVectorKey v = anim->mScalingKeys[0];
|
||||
|
||||
// Reallocate ... we need just ONE element, it makes no sense to reuse the array
|
||||
delete[] anim->mScalingKeys;
|
||||
anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1];
|
||||
anim->mScalingKeys[0] = v;
|
||||
i = 1;
|
||||
}
|
||||
if (1 == i)
|
||||
DefaultLogger::get()->warn("Simplified dummy tracks with just one key");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -97,16 +97,14 @@ protected:
|
|||
// -------------------------------------------------------------------
|
||||
/** Executes the postprocessing step on the given animation
|
||||
* @param anim The animation to process.
|
||||
* @return 0 - nothing, 1 - removed sth, 2 - please delete me
|
||||
*/
|
||||
int ProcessAnimation (aiAnimation* anim);
|
||||
void ProcessAnimation (aiAnimation* anim);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Executes the postprocessing step on the given anim channel
|
||||
* @param anim The animation channel to process.
|
||||
* @return 0 - nothing, 1 - removed sth, 2 - please delete me
|
||||
*/
|
||||
int ProcessAnimationChannel (aiNodeAnim* anim);
|
||||
void ProcessAnimationChannel (aiNodeAnim* anim);
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -46,7 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "IRRLoader.h"
|
||||
#include "ParsingUtils.h"
|
||||
#include "fast_atof.h"
|
||||
#include "GenericProperty.h"
|
||||
|
||||
#include "SceneCombiner.h"
|
||||
#include "StandardShapes.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
@ -131,20 +133,14 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
// List of output lights
|
||||
std::vector<aiLight*> lights;
|
||||
|
||||
// List of output meshes
|
||||
std::vector<aiMesh*> meshes;
|
||||
|
||||
// List of output animation channels
|
||||
std::vector<aiNodeAnim*> animations;
|
||||
|
||||
BatchLoader batch(pIOHandler);
|
||||
|
||||
cameras.reserve(5);
|
||||
lights.reserve(5);
|
||||
animations.reserve(5);
|
||||
meshes.reserve(5);
|
||||
|
||||
bool inMaterials = false;
|
||||
bool inMaterials = false, inAnimator = false;
|
||||
unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0;
|
||||
|
||||
// Parse the XML file
|
||||
while (reader->read())
|
||||
|
@ -179,11 +175,13 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
else if (!ASSIMP_stricmp(sz,"cube"))
|
||||
{
|
||||
nd = new Node(Node::CUBE);
|
||||
meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
|
||||
++guessedMeshCnt;
|
||||
// meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
|
||||
}
|
||||
else if (!ASSIMP_stricmp(sz,"skybox"))
|
||||
{
|
||||
nd = new Node(Node::SKYBOX);
|
||||
++guessedMeshCnt;
|
||||
}
|
||||
else if (!ASSIMP_stricmp(sz,"camera"))
|
||||
{
|
||||
|
@ -206,6 +204,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
else if (!ASSIMP_stricmp(sz,"sphere"))
|
||||
{
|
||||
nd = new Node(Node::SPHERE);
|
||||
++guessedMeshCnt;
|
||||
}
|
||||
else if (!ASSIMP_stricmp(sz,"animatedMesh"))
|
||||
{
|
||||
|
@ -236,6 +235,10 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
inMaterials = true;
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators"))
|
||||
{
|
||||
inAnimator = true;
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes"))
|
||||
{
|
||||
/* We should have a valid node here
|
||||
|
@ -247,6 +250,8 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
continue;
|
||||
}
|
||||
|
||||
Animator* curAnim = NULL;
|
||||
|
||||
if (inMaterials && curNode->type == Node::ANIMMESH ||
|
||||
curNode->type == Node::MESH )
|
||||
{
|
||||
|
@ -258,6 +263,16 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
p.first = ParseMaterial(p.second);
|
||||
continue;
|
||||
}
|
||||
else if (inAnimator)
|
||||
{
|
||||
/* This is an animation path - add a new animator
|
||||
* to the list.
|
||||
*/
|
||||
curNode->animators.push_back(Animator());
|
||||
curAnim = & curNode->animators.back();
|
||||
|
||||
++guessedAnimCnt;
|
||||
}
|
||||
|
||||
/* Parse all elements in the attributes block
|
||||
* and process them.
|
||||
|
@ -274,6 +289,56 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
// Convert to our coordinate system
|
||||
std::swap( (float&)prop.value.z, (float&)prop.value.y );
|
||||
prop.value.y *= -1.f;
|
||||
|
||||
if (inAnimator)
|
||||
{
|
||||
if (curAnim->type == Animator::ROTATION && prop.name == "Rotation")
|
||||
{
|
||||
// We store the rotation euler angles in 'direction'
|
||||
curAnim->direction = prop.value;
|
||||
}
|
||||
else if (curAnim->type == Animator::FOLLOW_SPLINE)
|
||||
{
|
||||
// Check whether the vector follows the PointN naming scheme,
|
||||
// here N is the ONE-based index of the point
|
||||
if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point")
|
||||
{
|
||||
// Add a new key to the list
|
||||
curAnim->splineKeys.push_back(aiVectorKey());
|
||||
aiVectorKey& key = curAnim->splineKeys.back();
|
||||
|
||||
// and parse its properties
|
||||
key.mValue = prop.value;
|
||||
key.mTime = strtol10(&prop.name.c_str()[5]);
|
||||
}
|
||||
}
|
||||
else if (curAnim->type == Animator::FLY_CIRCLE)
|
||||
{
|
||||
if (prop.name == "Center")
|
||||
{
|
||||
curAnim->circleCenter = prop.value;
|
||||
}
|
||||
else if (prop.name == "Direction")
|
||||
{
|
||||
curAnim->direction = prop.value;
|
||||
}
|
||||
}
|
||||
else if (curAnim->type == Animator::FLY_STRAIGHT)
|
||||
{
|
||||
if (prop.name == "Start")
|
||||
{
|
||||
// We reuse the field here
|
||||
curAnim->circleCenter = prop.value;
|
||||
}
|
||||
else if (prop.name == "End")
|
||||
{
|
||||
// We reuse the field here
|
||||
curAnim->direction = prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prop.name == "Position")
|
||||
{
|
||||
curNode->position = prop.value;
|
||||
|
@ -299,11 +364,36 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"bool"))
|
||||
{
|
||||
BoolProperty prop;
|
||||
ReadBoolProperty(prop);
|
||||
|
||||
if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop")
|
||||
{
|
||||
curAnim->loop = prop.value;
|
||||
}
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))
|
||||
{
|
||||
FloatProperty prop;
|
||||
ReadFloatProperty(prop);
|
||||
|
||||
if (inAnimator)
|
||||
{
|
||||
// The speed property exists for several animators
|
||||
if (prop.name == "Speed")
|
||||
{
|
||||
curAnim->speed = prop.value;
|
||||
}
|
||||
else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius")
|
||||
{
|
||||
curAnim->circleRadius = prop.value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prop.name == "FramesPerSecond" &&
|
||||
Node::ANIMMESH == curNode->type)
|
||||
{
|
||||
|
@ -332,8 +422,63 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
cameras.back()->mClipPlaneFar = prop.value;
|
||||
}
|
||||
}
|
||||
else if (Node::LIGHT == curNode->type)
|
||||
{
|
||||
/* Additional light information
|
||||
*/
|
||||
if (prop.name == "Attenuation")
|
||||
{
|
||||
lights.back()->mAttenuationLinear = prop.value;
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"string"))
|
||||
else if (prop.name == "OuterCone")
|
||||
{
|
||||
lights.back()->mAngleOuterCone = AI_DEG_TO_RAD( prop.value );
|
||||
}
|
||||
else if (prop.name == "InnerCone")
|
||||
{
|
||||
lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value );
|
||||
}
|
||||
}
|
||||
// radius of the sphere to be generated
|
||||
else if (Node::SPHERE == curNode->type)
|
||||
{
|
||||
if (prop.name == "Radius")
|
||||
{
|
||||
curNode->sphereRadius = prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"int"))
|
||||
{
|
||||
IntProperty prop;
|
||||
ReadIntProperty(prop);
|
||||
|
||||
if (inAnimator)
|
||||
{
|
||||
if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay")
|
||||
{
|
||||
curAnim->timeForWay = prop.value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// sphere polgon numbers in each direction
|
||||
if (Node::SPHERE == curNode->type)
|
||||
{
|
||||
if (prop.name == "PolyCountX")
|
||||
{
|
||||
curNode->spherePolyCountX = prop.value;
|
||||
}
|
||||
else if (prop.name == "PolyCountY")
|
||||
{
|
||||
curNode->spherePolyCountY = prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||
|
||||
!ASSIMP_stricmp(reader->getNodeName(),"enum"))
|
||||
{
|
||||
StringProperty prop;
|
||||
ReadStringProperty(prop);
|
||||
|
@ -356,17 +501,29 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
lights.back()->mName.Set(prop.value);
|
||||
}
|
||||
}
|
||||
else if (Node::LIGHT == curNode->type && "LightType" == prop.name)
|
||||
{
|
||||
}
|
||||
else if (prop.name == "Mesh" && Node::MESH == curNode->type ||
|
||||
Node::ANIMMESH == curNode->type)
|
||||
{
|
||||
/* This is the file name of the mesh - either
|
||||
* animated or not. We don't need any postprocessing
|
||||
* steps here. However, it would be useful it we'd
|
||||
* be able to use RemoveVC to remove animations
|
||||
* if this isn't an animated mesh. But that's not
|
||||
* possible at the moment.
|
||||
* animated or not. We need to make sure we setup
|
||||
* the correct postprocessing settings here.
|
||||
*/
|
||||
batch.AddLoadRequest(prop.value);
|
||||
unsigned int pp = 0;
|
||||
BatchLoader::PropertyMap map;
|
||||
|
||||
/* If the mesh is a static one remove all animations
|
||||
*/
|
||||
if (Node::ANIMMESH != curNode->type)
|
||||
{
|
||||
pp |= aiProcess_RemoveComponent;
|
||||
SetGenericProperty<int>(map.ints,AI_CONFIG_PP_RVC_FLAGS,
|
||||
aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS);
|
||||
}
|
||||
|
||||
batch.AddLoadRequest(prop.value,pp,&map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -382,6 +539,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
case EXN_ELEMENT_END:
|
||||
|
||||
// If we reached the end of a node, we need to continue processing its parent
|
||||
if (!ASSIMP_stricmp(reader->getNodeName(),"node"))
|
||||
{
|
||||
if (!curNode)
|
||||
|
@ -397,10 +555,15 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
else curNode = NULL;
|
||||
}
|
||||
// clear all flags
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))
|
||||
{
|
||||
inMaterials = false;
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getNodeName(),"animators"))
|
||||
{
|
||||
inAnimator = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -421,4 +584,69 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
|
||||
}
|
||||
|
||||
/* Allocate a tempoary scene data structure
|
||||
*/
|
||||
aiScene* tempScene = new aiScene();
|
||||
tempScene->mRootNode = new aiNode();
|
||||
tempScene->mRootNode->mName.Set("<IRRRoot>");
|
||||
|
||||
/* Copy the cameras to the output array
|
||||
*/
|
||||
tempScene->mNumCameras = (unsigned int)cameras.size();
|
||||
tempScene->mCameras = new aiCamera*[tempScene->mNumCameras];
|
||||
::memcpy(tempScene->mCameras,&cameras[0],sizeof(void*)*tempScene->mNumCameras);
|
||||
|
||||
/* Copy the light sources to the output array
|
||||
*/
|
||||
tempScene->mNumLights = (unsigned int)lights.size();
|
||||
tempScene->mLights = new aiLight*[tempScene->mNumLights];
|
||||
::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
|
||||
|
||||
|
||||
// temporary data
|
||||
std::vector< aiNodeAnim*> anims;
|
||||
std::vector< AttachmentInfo > attach;
|
||||
std::vector<aiMesh*> meshes;
|
||||
|
||||
anims.reserve(guessedAnimCnt + (guessedAnimCnt >> 2));
|
||||
meshes.reserve(guessedMeshCnt + (guessedMeshCnt >> 2));
|
||||
|
||||
/* Now process our scenegraph recursively: generate final
|
||||
* meshes and generate animation channels for all nodes.
|
||||
*/
|
||||
// GenerateGraph(root,tempScene->mRootNode, tempScene,
|
||||
// batch, meshes, anims, attach);
|
||||
|
||||
if (!anims.empty())
|
||||
{
|
||||
tempScene->mNumAnimations = 1;
|
||||
tempScene->mAnimations = new aiAnimation*[tempScene->mNumAnimations];
|
||||
aiAnimation* an = tempScene->mAnimations[0] = new aiAnimation();
|
||||
|
||||
// ***********************************************************
|
||||
// This is only the global animation channel of the scene.
|
||||
// If there are animated models, they will have separate
|
||||
// animation channels in the scene. To display IRR scenes
|
||||
// correctly, users will need to combine the global anim
|
||||
// channel with all the local animations they want to play
|
||||
// ***********************************************************
|
||||
an->mName.Set("Irr_GlobalAnimChannel");
|
||||
|
||||
// copy all node animation channels to the global channel
|
||||
an->mNumChannels = (unsigned int)anims.size();
|
||||
an->mChannels = new aiNodeAnim*[an->mNumChannels];
|
||||
::memcpy(an->mChannels, & anims [0], sizeof(void*)*an->mNumChannels);
|
||||
}
|
||||
if (meshes.empty())
|
||||
{
|
||||
// There are no meshes in the scene - the scene is incomplete
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
DefaultLogger::get()->info("IRR: No Meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE flag");
|
||||
}
|
||||
|
||||
/* Now merge all sub scenes and attach them to the correct
|
||||
* attachment points in the scenegraph.
|
||||
*/
|
||||
SceneCombiner::MergeScenes(pScene,tempScene,attach);
|
||||
}
|
||||
|
|
|
@ -100,6 +100,54 @@ protected:
|
|||
|
||||
private:
|
||||
|
||||
/** Data structure for a scenegraph node animator
|
||||
*/
|
||||
struct Animator
|
||||
{
|
||||
// Type of the animator
|
||||
enum AT
|
||||
{
|
||||
UNKNOWN = 0x0,
|
||||
ROTATION = 0x1,
|
||||
FLY_CIRCLE = 0x2,
|
||||
FLY_STRAIGHT = 0x3,
|
||||
FOLLOW_SPLINE = 0x4,
|
||||
OTHER = 0x5
|
||||
|
||||
} type;
|
||||
|
||||
Animator(AT t = UNKNOWN)
|
||||
: type (t)
|
||||
, speed (0.001f)
|
||||
, direction (0.f,1.f,0.f)
|
||||
, circleRadius (1.f)
|
||||
, tightness (0.5f)
|
||||
, loop (true)
|
||||
, timeForWay (100)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// common parameters
|
||||
float speed;
|
||||
aiVector3D direction;
|
||||
|
||||
// FLY_CIRCLE
|
||||
aiVector3D circleCenter;
|
||||
float circleRadius;
|
||||
|
||||
// FOLLOW_SPLINE
|
||||
float tightness;
|
||||
std::vector<aiVectorKey> splineKeys;
|
||||
|
||||
// ROTATION (angles given in direction)
|
||||
|
||||
// FLY STRAIGHT
|
||||
// circleCenter = start, direction = end
|
||||
bool loop;
|
||||
int timeForWay;
|
||||
};
|
||||
|
||||
/** Data structure for a scenegraph node in an IRR file
|
||||
*/
|
||||
struct Node
|
||||
|
@ -123,6 +171,9 @@ private:
|
|||
, scaling (1.f,1.f,1.f) // assume uniform scaling by default
|
||||
, animation (NULL)
|
||||
, framesPerSecond (0.f)
|
||||
, sphereRadius (1.f)
|
||||
, spherePolyCountX (100)
|
||||
, spherePolyCountY (100)
|
||||
{
|
||||
|
||||
// Generate a default name for the node
|
||||
|
@ -157,9 +208,18 @@ private:
|
|||
// 0.f if not specified
|
||||
float framesPerSecond;
|
||||
|
||||
//! Meshes: List of materials to be assigned
|
||||
//! along with their corresponding material flags
|
||||
// Meshes: List of materials to be assigned
|
||||
// along with their corresponding material flags
|
||||
std::vector< std::pair<aiMaterial*, unsigned int> > materials;
|
||||
|
||||
// Spheres: radius of the sphere to be generates
|
||||
float sphereRadius;
|
||||
|
||||
// Spheres: Number of polygons in the x,y direction
|
||||
unsigned int spherePolyCountX,spherePolyCountY;
|
||||
|
||||
// List of all animators assigned to the node
|
||||
std::list<Animator> animators;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -70,6 +70,24 @@ void IrrlichtBase::ReadHexProperty (HexProperty& out)
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read a decimal property
|
||||
void IrrlichtBase::ReadIntProperty (IntProperty& out)
|
||||
{
|
||||
for (int i = 0; i < reader->getAttributeCount();++i)
|
||||
{
|
||||
if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
|
||||
{
|
||||
out.name = std::string( reader->getAttributeValue(i) );
|
||||
}
|
||||
else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
|
||||
{
|
||||
// parse the ecimal value
|
||||
out.value = strtol10s(reader->getAttributeValue(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read a string property
|
||||
void IrrlichtBase::ReadStringProperty (StringProperty& out)
|
||||
|
|
|
@ -73,6 +73,7 @@ protected:
|
|||
typedef Property<bool> BoolProperty;
|
||||
typedef Property<float> FloatProperty;
|
||||
typedef Property<aiVector3D> VectorProperty;
|
||||
typedef Property<int> IntProperty;
|
||||
|
||||
/** XML reader instance
|
||||
*/
|
||||
|
@ -96,6 +97,7 @@ protected:
|
|||
void ReadBoolProperty (BoolProperty& out);
|
||||
void ReadFloatProperty (FloatProperty& out);
|
||||
void ReadVectorProperty (VectorProperty& out);
|
||||
void ReadIntProperty (IntProperty& out);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "DefaultIOSystem.h"
|
||||
#include "GenericProperty.h"
|
||||
#include "ProcessHelper.h"
|
||||
#include "ScenePreprocessor.h"
|
||||
|
||||
// Importers
|
||||
#ifndef AI_BUILD_NO_X_IMPORTER
|
||||
|
@ -565,6 +566,10 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
|
|||
// if successful, apply all active post processing steps to the imported data
|
||||
if( mScene)
|
||||
{
|
||||
// FIRST of all - preprocess the scene
|
||||
ScenePreprocessor pre;
|
||||
pre.ProcessScene(mScene);
|
||||
|
||||
DefaultLogger::get()->info("Import successful, entering postprocessing-steps");
|
||||
#ifdef _DEBUG
|
||||
if (bExtraVerbose)
|
||||
|
|
|
@ -436,8 +436,8 @@ outer:
|
|||
mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
|
||||
mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
|
||||
|
||||
//if (!(minor > '0' && major == '3'))
|
||||
// srcMat.transparency = 1.0f - srcMat.transparency;
|
||||
if (!(minor > '0' && major == '3'))
|
||||
srcMat.transparency = 1.0f - srcMat.transparency;
|
||||
mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
|
||||
|
||||
// add shininess - Quick3D seems to use it ins its viewer
|
||||
|
|
|
@ -274,6 +274,14 @@ void SceneCombiner::MergeScenes(aiScene* dest,std::vector<aiScene*>& src,
|
|||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SceneCombiner::MergeScenes(aiScene* dest, const aiScene* master,
|
||||
std::vector<AttachmentInfo>& src,
|
||||
unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SceneCombiner::MergeMeshes(aiMesh* dest,std::vector<aiMesh*>& src,
|
||||
unsigned int flags)
|
||||
|
|
|
@ -48,6 +48,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper data structure for SceneCombiner.
|
||||
*
|
||||
* Describes to which node a scene must be attached to.
|
||||
*/
|
||||
struct AttachmentInfo
|
||||
{
|
||||
AttachmentInfo()
|
||||
: scene (NULL)
|
||||
, attachToNode (NULL)
|
||||
{}
|
||||
|
||||
AttachmentInfo(aiScene* _scene, aiNode* _attachToNode)
|
||||
: scene (_scene)
|
||||
, attachToNode (_attachToNode)
|
||||
{}
|
||||
|
||||
aiScene* scene;
|
||||
aiNode* attachToNode;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Static helper class providing various utilities to merge two
|
||||
|
@ -73,7 +93,24 @@ public:
|
|||
* @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
|
||||
*/
|
||||
static void MergeScenes(aiScene* dest,std::vector<aiScene*>& src,
|
||||
unsigned int flags);
|
||||
unsigned int flags = 0);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Merges two or more scenes and attaches all sceenes to a specific
|
||||
* position in the node graph of the masteer scene.
|
||||
*
|
||||
* @param dest Destination scene. Must be empty.
|
||||
* @param master Master scene. It will be deleted afterwards. All
|
||||
* other scenes will be inserted in its node graph.
|
||||
* @param src Non-empty list of scenes to be merged along with their
|
||||
* corresponding attachment points in the master scene. The function
|
||||
* deletes the input scenes afterwards.
|
||||
* @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
|
||||
*/
|
||||
static void MergeScenes(aiScene* dest, const aiScene* master,
|
||||
std::vector<AttachmentInfo>& src,
|
||||
unsigned int flags = 0);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
#include "ScenePreprocessor.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
void ScenePreprocessor::ProcessScene (aiScene* _scene)
|
||||
{
|
||||
scene = _scene;
|
||||
|
||||
// - nothing to do for meshes for the moment
|
||||
// - nothing to do for materials for the moment
|
||||
// - nothing to do for nodes for the moment
|
||||
// - nothing to do for textures for the moment
|
||||
// - nothing to do for lights for the moment
|
||||
// - nothing to do for cameras for the moment
|
||||
|
||||
// Process all animations
|
||||
for (unsigned int i = 0; i < scene->mNumAnimations;++i)
|
||||
ProcessAnimation(scene->mAnimations[i]);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
|
||||
{
|
||||
for (unsigned int i = 0; i < anim->mNumChannels;++i)
|
||||
{
|
||||
aiNodeAnim* channel = anim->mChannels[i];
|
||||
|
||||
/* Check whether the animation channel has no rotation
|
||||
* or position tracks. In this case we generate a dummy
|
||||
* track from the information we have in the transformation
|
||||
* matrix of the corresponding node.
|
||||
*/
|
||||
if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys)
|
||||
{
|
||||
// Find the node that belongs to this animation
|
||||
aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
|
||||
if (node) // ValidateDS will complain later if 'node' is NULL
|
||||
{
|
||||
// Decompose the transformation matrix of the node
|
||||
aiVector3D scaling, position;
|
||||
aiQuaternion rotation;
|
||||
|
||||
node->mTransformation.Decompose(scaling, rotation,position);
|
||||
|
||||
// No rotation keys? Generate a dummy track
|
||||
if (!channel->mNumRotationKeys)
|
||||
{
|
||||
channel->mNumRotationKeys = 1;
|
||||
channel->mRotationKeys = new aiQuatKey[1];
|
||||
aiQuatKey& q = channel->mRotationKeys[0];
|
||||
|
||||
q.mTime = 0.;
|
||||
q.mValue = rotation;
|
||||
|
||||
DefaultLogger::get()->debug("ScenePreprocessor: Dummy rotation track has been generated");
|
||||
}
|
||||
|
||||
// No scaling keys? Generate a dummy track
|
||||
if (!channel->mNumScalingKeys)
|
||||
{
|
||||
channel->mNumScalingKeys = 1;
|
||||
channel->mScalingKeys = new aiVectorKey[1];
|
||||
aiVectorKey& q = channel->mScalingKeys[0];
|
||||
|
||||
q.mTime = 0.;
|
||||
q.mValue = scaling;
|
||||
|
||||
DefaultLogger::get()->debug("ScenePreprocessor: Dummy scaling track has been generated");
|
||||
}
|
||||
|
||||
// No position keys? Generate a dummy track
|
||||
if (!channel->mNumPositionKeys)
|
||||
{
|
||||
channel->mNumPositionKeys = 1;
|
||||
channel->mPositionKeys = new aiVectorKey[1];
|
||||
aiVectorKey& q = channel->mPositionKeys[0];
|
||||
|
||||
q.mTime = 0.;
|
||||
q.mValue = position;
|
||||
|
||||
DefaultLogger::get()->debug("ScenePreprocessor: Dummy position track has been generated");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
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 search all meshes for
|
||||
degenerated faces */
|
||||
#ifndef AI_SCENE_PREPROCESSOR_H_INC
|
||||
#define AI_SCENE_PREPROCESSOR_H_INC
|
||||
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** ScenePreprocessor: Preprocess a scene before any post-processing
|
||||
* steps are executed.
|
||||
*/
|
||||
class ASSIMP_API ScenePreprocessor
|
||||
{
|
||||
public:
|
||||
|
||||
/** Preprocess a given scene.
|
||||
*
|
||||
* @param _scene Scene to be preprocessed
|
||||
*/
|
||||
void ProcessScene (aiScene* _scene);
|
||||
|
||||
protected:
|
||||
|
||||
void ProcessAnimation (aiAnimation* anim);
|
||||
|
||||
protected:
|
||||
|
||||
//! Scene we're currently working on
|
||||
aiScene* scene;
|
||||
};
|
||||
|
||||
|
||||
} // ! end namespace Assimp
|
||||
|
||||
#endif // include guard
|
|
@ -71,7 +71,8 @@ SOURCES = AssimpPCH.cpp \
|
|||
./irrXML/irrXML.cpp \
|
||||
IRRMeshLoader.cpp \
|
||||
IRRLoader.cpp \
|
||||
Q3DLoader.cpp
|
||||
Q3DLoader.cpp \
|
||||
ScenePreprocessor.cpp
|
||||
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ SOURCES = AssimpPCH.cpp \
|
|||
./irrXML/irrXML.cpp \
|
||||
IRRMeshLoader.cpp \
|
||||
IRRLoader.cpp \
|
||||
Q3DLoader.cpp
|
||||
Q3DLoader.cpp \
|
||||
ScenePreprocessor.cpp
|
||||
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
||||
|
|
|
@ -66,6 +66,14 @@ struct aiVectorKey
|
|||
bool operator != (const aiVectorKey& o) const
|
||||
{return o.mValue != this->mValue;}
|
||||
|
||||
|
||||
|
||||
// Only time is compared. This operator is defined
|
||||
// for use with std::sort
|
||||
bool operator < (const aiVectorKey& o) const
|
||||
{return mTime < o.mTime;}
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -86,6 +94,14 @@ struct aiQuatKey
|
|||
bool operator != (const aiQuatKey& o) const
|
||||
{return o.mValue != this->mValue;}
|
||||
|
||||
|
||||
// Only time is compared. This operator is defined
|
||||
// for use with std::sort
|
||||
bool operator < (const aiQuatKey& o) const
|
||||
{return mTime < o.mTime;}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -126,8 +142,8 @@ struct aiNodeAnim
|
|||
/** The position keys of this animation channel. Positions are
|
||||
* specified as 3D vector. The array is mNumPositionKeys in size.
|
||||
*
|
||||
* If there are rotation or scaling keys, but no position keys,
|
||||
* a constant position of 0|0|0 should be assumed.
|
||||
* If there are position keys, there will also be at least one
|
||||
* scaling and one rotation key.
|
||||
*/
|
||||
C_STRUCT aiVectorKey* mPositionKeys;
|
||||
|
||||
|
@ -138,8 +154,8 @@ struct aiNodeAnim
|
|||
* given as quaternions, which are 4D vectors. The array is
|
||||
* mNumRotationKeys in size.
|
||||
*
|
||||
* If there are position or scaling keys, but no rotation keys,
|
||||
* a constant rotation of 0|0|0 should be assumed.
|
||||
* If there are rotation keys, there will also be at least one
|
||||
* scaling and one position key.
|
||||
*/
|
||||
C_STRUCT aiQuatKey* mRotationKeys;
|
||||
|
||||
|
@ -150,8 +166,8 @@ struct aiNodeAnim
|
|||
/** The scaling keys of this animation channel. Scalings are
|
||||
* specified as 3D vector. The array is mNumScalingKeys in size.
|
||||
*
|
||||
* If there are position or rotation keys, but no scaling keys,
|
||||
* a constant scaling of 1|1|1 should be assumed.
|
||||
* If there are scaling keys, there will also be at least one
|
||||
* position and one rotation key.
|
||||
*/
|
||||
C_STRUCT aiVectorKey* mScalingKeys;
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
|
|||
|
||||
// extract the rows of the matrix
|
||||
aiVector3D vRows[3] = {
|
||||
aiVector3D(_this[0][0],_this[1][1],_this[2][0]),
|
||||
aiVector3D(_this[0][0],_this[1][0],_this[2][0]),
|
||||
aiVector3D(_this[0][1],_this[1][1],_this[2][1]),
|
||||
aiVector3D(_this[0][2],_this[1][2],_this[2][2])
|
||||
};
|
||||
|
@ -186,9 +186,9 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
|
|||
}
|
||||
|
||||
// build a 3x3 rotation matrix
|
||||
aiMatrix3x3 m(vRows[0].x,vRows[0].y,vRows[0].z,
|
||||
vRows[1].x,vRows[1].y,vRows[1].z,
|
||||
vRows[2].x,vRows[2].y,vRows[2].z);
|
||||
aiMatrix3x3 m(vRows[0].x,vRows[1].x,vRows[2].x,
|
||||
vRows[0].y,vRows[1].y,vRows[2].y,
|
||||
vRows[0].z,vRows[1].z,vRows[2].z);
|
||||
|
||||
// and generate the rotation quaternion from it
|
||||
rotation = aiQuaternion(m);
|
||||
|
|
Binary file not shown.
|
@ -839,6 +839,14 @@
|
|||
RelativePath="..\..\code\SceneCombiner.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\ScenePreprocessor.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\ScenePreprocessor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\SGSpatialSort.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue