From f9158592e1478b2013afc7041d9ed041cf2d2f4a Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 13 Jan 2014 19:47:58 +1000 Subject: Update Irrlicht to 1.8.1. Include actual change markers this time. lol --- .../irrlicht-1.8/source/Irrlicht/CSkinnedMesh.cpp | 1471 -------------------- 1 file changed, 1471 deletions(-) delete mode 100644 libraries/irrlicht-1.8/source/Irrlicht/CSkinnedMesh.cpp (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CSkinnedMesh.cpp') diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CSkinnedMesh.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CSkinnedMesh.cpp deleted file mode 100644 index e0226af..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/CSkinnedMesh.cpp +++ /dev/null @@ -1,1471 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ - -#include "CSkinnedMesh.h" -#include "CBoneSceneNode.h" -#include "IAnimatedMeshSceneNode.h" -#include "os.h" - -namespace irr -{ -namespace scene -{ - - -//! constructor -CSkinnedMesh::CSkinnedMesh() -: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f), - LastAnimatedFrame(-1), SkinnedLastFrame(false), - InterpolationMode(EIM_LINEAR), - HasAnimation(false), PreparedForSkinning(false), - AnimateNormals(true), HardwareSkinning(false) -{ - #ifdef _DEBUG - setDebugName("CSkinnedMesh"); - #endif - - SkinningBuffers=&LocalBuffers; -} - - -//! destructor -CSkinnedMesh::~CSkinnedMesh() -{ - for (u32 i=0; idrop(); - } -} - - -//! returns the amount of frames in milliseconds. -//! If the amount is 1, it is a static (=non animated) mesh. -u32 CSkinnedMesh::getFrameCount() const -{ - return core::floor32(AnimationFrames); -} - - -//! Gets the default animation speed of the animated mesh. -/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ -f32 CSkinnedMesh::getAnimationSpeed() const -{ - return FramesPerSecond; -} - - -//! Gets the frame count of the animated mesh. -/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. -The actual speed is set in the scene node the mesh is instantiated in.*/ -void CSkinnedMesh::setAnimationSpeed(f32 fps) -{ - FramesPerSecond=fps; -} - - -//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. -IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) -{ - //animate(frame,startFrameLoop, endFrameLoop); - if (frame==-1) - return this; - - animateMesh((f32)frame, 1.0f); - skinMesh(); - return this; -} - - -//-------------------------------------------------------------------------- -// Keyframe Animation -//-------------------------------------------------------------------------- - - -//! Animates this mesh's joints based on frame input -//! blend: {0-old position, 1-New position} -void CSkinnedMesh::animateMesh(f32 frame, f32 blend) -{ - if (!HasAnimation || LastAnimatedFrame==frame) - return; - - LastAnimatedFrame=frame; - SkinnedLastFrame=false; - - if (blend<=0.f) - return; //No need to animate - - for (u32 i=0; iAnimatedposition; - const core::vector3df oldScale = joint->Animatedscale; - const core::quaternion oldRotation = joint->Animatedrotation; - - core::vector3df position = oldPosition; - core::vector3df scale = oldScale; - core::quaternion rotation = oldRotation; - - getFrameData(frame, joint, - position, joint->positionHint, - scale, joint->scaleHint, - rotation, joint->rotationHint); - - if (blend==1.0f) - { - //No blending needed - joint->Animatedposition = position; - joint->Animatedscale = scale; - joint->Animatedrotation = rotation; - } - else - { - //Blend animation - joint->Animatedposition = core::lerp(oldPosition, position, blend); - joint->Animatedscale = core::lerp(oldScale, scale, blend); - joint->Animatedrotation.slerp(oldRotation, rotation, blend); - } - } - - //Note: - //LocalAnimatedMatrix needs to be built at some point, but this function may be called lots of times for - //one render (to play two animations at the same time) LocalAnimatedMatrix only needs to be built once. - //a call to buildAllLocalAnimatedMatrices is needed before skinning the mesh, and before the user gets the joints to move - - //---------------- - // Temp! - buildAllLocalAnimatedMatrices(); - //----------------- - - updateBoundingBox(); -} - - -void CSkinnedMesh::buildAllLocalAnimatedMatrices() -{ - for (u32 i=0; iUseAnimationFrom && - (joint->UseAnimationFrom->PositionKeys.size() || - joint->UseAnimationFrom->ScaleKeys.size() || - joint->UseAnimationFrom->RotationKeys.size() )) - { - joint->GlobalSkinningSpace=false; - - // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched to getMatrix_transposed instead of getMatrix for downward compatibility. - // Not tested so far if this was correct or wrong before quaternion fix! - joint->Animatedrotation.getMatrix_transposed(joint->LocalAnimatedMatrix); - - // --- joint->LocalAnimatedMatrix *= joint->Animatedrotation.getMatrix() --- - f32 *m1 = joint->LocalAnimatedMatrix.pointer(); - core::vector3df &Pos = joint->Animatedposition; - m1[0] += Pos.X*m1[3]; - m1[1] += Pos.Y*m1[3]; - m1[2] += Pos.Z*m1[3]; - m1[4] += Pos.X*m1[7]; - m1[5] += Pos.Y*m1[7]; - m1[6] += Pos.Z*m1[7]; - m1[8] += Pos.X*m1[11]; - m1[9] += Pos.Y*m1[11]; - m1[10] += Pos.Z*m1[11]; - m1[12] += Pos.X*m1[15]; - m1[13] += Pos.Y*m1[15]; - m1[14] += Pos.Z*m1[15]; - // ----------------------------------- - - if (joint->ScaleKeys.size()) - { - /* - core::matrix4 scaleMatrix; - scaleMatrix.setScale(joint->Animatedscale); - joint->LocalAnimatedMatrix *= scaleMatrix; - */ - - // -------- joint->LocalAnimatedMatrix *= scaleMatrix ----------------- - core::matrix4& mat = joint->LocalAnimatedMatrix; - mat[0] *= joint->Animatedscale.X; - mat[1] *= joint->Animatedscale.X; - mat[2] *= joint->Animatedscale.X; - mat[3] *= joint->Animatedscale.X; - mat[4] *= joint->Animatedscale.Y; - mat[5] *= joint->Animatedscale.Y; - mat[6] *= joint->Animatedscale.Y; - mat[7] *= joint->Animatedscale.Y; - mat[8] *= joint->Animatedscale.Z; - mat[9] *= joint->Animatedscale.Z; - mat[10] *= joint->Animatedscale.Z; - mat[11] *= joint->Animatedscale.Z; - // ----------------------------------- - } - } - else - { - joint->LocalAnimatedMatrix=joint->LocalMatrix; - } - } - SkinnedLastFrame=false; -} - - -void CSkinnedMesh::buildAllGlobalAnimatedMatrices(SJoint *joint, SJoint *parentJoint) -{ - if (!joint) - { - for (u32 i=0; iGlobalSkinningSpace) - joint->GlobalAnimatedMatrix = joint->LocalAnimatedMatrix; - else - joint->GlobalAnimatedMatrix = parentJoint->GlobalAnimatedMatrix * joint->LocalAnimatedMatrix; - } - - for (u32 j=0; jChildren.size(); ++j) - buildAllGlobalAnimatedMatrices(joint->Children[j], joint); -} - - -void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint, - core::vector3df &position, s32 &positionHint, - core::vector3df &scale, s32 &scaleHint, - core::quaternion &rotation, s32 &rotationHint) -{ - s32 foundPositionIndex = -1; - s32 foundScaleIndex = -1; - s32 foundRotationIndex = -1; - - if (joint->UseAnimationFrom) - { - const core::array &PositionKeys=joint->UseAnimationFrom->PositionKeys; - const core::array &ScaleKeys=joint->UseAnimationFrom->ScaleKeys; - const core::array &RotationKeys=joint->UseAnimationFrom->RotationKeys; - - if (PositionKeys.size()) - { - foundPositionIndex = -1; - - //Test the Hints... - if (positionHint>=0 && (u32)positionHint < PositionKeys.size()) - { - //check this hint - if (positionHint>0 && PositionKeys[positionHint].frame>=frame && PositionKeys[positionHint-1].frame=frame && - PositionKeys[positionHint+0].frame= frame) //Keys should to be sorted by frame - { - foundPositionIndex=i; - positionHint=i; - break; - } - } - } - - //Do interpolation... - if (foundPositionIndex!=-1) - { - if (InterpolationMode==EIM_CONSTANT || foundPositionIndex==0) - { - position = PositionKeys[foundPositionIndex].position; - } - else if (InterpolationMode==EIM_LINEAR) - { - const SPositionKey& KeyA = PositionKeys[foundPositionIndex]; - const SPositionKey& KeyB = PositionKeys[foundPositionIndex-1]; - - const f32 fd1 = frame - KeyA.frame; - const f32 fd2 = KeyB.frame - frame; - position = ((KeyB.position-KeyA.position)/(fd1+fd2))*fd1 + KeyA.position; - } - } - } - - //------------------------------------------------------------ - - if (ScaleKeys.size()) - { - foundScaleIndex = -1; - - //Test the Hints... - if (scaleHint>=0 && (u32)scaleHint < ScaleKeys.size()) - { - //check this hint - if (scaleHint>0 && ScaleKeys[scaleHint].frame>=frame && ScaleKeys[scaleHint-1].frame=frame && - ScaleKeys[scaleHint+0].frame= frame) //Keys should to be sorted by frame - { - foundScaleIndex=i; - scaleHint=i; - break; - } - } - } - - //Do interpolation... - if (foundScaleIndex!=-1) - { - if (InterpolationMode==EIM_CONSTANT || foundScaleIndex==0) - { - scale = ScaleKeys[foundScaleIndex].scale; - } - else if (InterpolationMode==EIM_LINEAR) - { - const SScaleKey& KeyA = ScaleKeys[foundScaleIndex]; - const SScaleKey& KeyB = ScaleKeys[foundScaleIndex-1]; - - const f32 fd1 = frame - KeyA.frame; - const f32 fd2 = KeyB.frame - frame; - scale = ((KeyB.scale-KeyA.scale)/(fd1+fd2))*fd1 + KeyA.scale; - } - } - } - - //------------------------------------------------------------- - - if (RotationKeys.size()) - { - foundRotationIndex = -1; - - //Test the Hints... - if (rotationHint>=0 && (u32)rotationHint < RotationKeys.size()) - { - //check this hint - if (rotationHint>0 && RotationKeys[rotationHint].frame>=frame && RotationKeys[rotationHint-1].frame=frame && - RotationKeys[rotationHint+0].frame= frame) //Keys should be sorted by frame - { - foundRotationIndex=i; - rotationHint=i; - break; - } - } - } - - //Do interpolation... - if (foundRotationIndex!=-1) - { - if (InterpolationMode==EIM_CONSTANT || foundRotationIndex==0) - { - rotation = RotationKeys[foundRotationIndex].rotation; - } - else if (InterpolationMode==EIM_LINEAR) - { - const SRotationKey& KeyA = RotationKeys[foundRotationIndex]; - const SRotationKey& KeyB = RotationKeys[foundRotationIndex-1]; - - const f32 fd1 = frame - KeyA.frame; - const f32 fd2 = KeyB.frame - frame; - const f32 t = fd1/(fd1+fd2); - - /* - f32 t = 0; - if (KeyA.frame!=KeyB.frame) - t = (frame-KeyA.frame) / (KeyB.frame - KeyA.frame); - */ - - rotation.slerp(KeyA.rotation, KeyB.rotation, t); - } - } - } - } -} - -//-------------------------------------------------------------------------- -// Software Skinning -//-------------------------------------------------------------------------- - -//! Preforms a software skin on this mesh based of joint positions -void CSkinnedMesh::skinMesh() -{ - if (!HasAnimation || SkinnedLastFrame) - return; - - //---------------- - // This is marked as "Temp!". A shiny dubloon to whomever can tell me why. - buildAllGlobalAnimatedMatrices(); - //----------------- - - SkinnedLastFrame=true; - if (!HardwareSkinning) - { - //Software skin.... - u32 i; - - //rigid animation - for (i=0; iAttachedMeshes.size(); ++j) - { - SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ]; - Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix; - } - } - - //clear skinning helper array - for (i=0; isize(); ++i) - (*SkinningBuffers)[i]->setDirty(EBT_VERTEX); - } - updateBoundingBox(); -} - - -void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint) -{ - if (joint->Weights.size()) - { - //Find this joints pull on vertices... - core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING); - jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix); - - core::vector3df thisVertexMove, thisNormalMove; - - core::array &buffersUsed=*SkinningBuffers; - - //Skin Vertices Positions and Normals... - for (u32 i=0; iWeights.size(); ++i) - { - SWeight& weight = joint->Weights[i]; - - // Pull this vertex... - jointVertexPull.transformVect(thisVertexMove, weight.StaticPos); - - if (AnimateNormals) - jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal); - - if (! (*(weight.Moved)) ) - { - *(weight.Moved) = true; - - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength; - - if (AnimateNormals) - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength; - - //*(weight._Pos) = thisVertexMove * weight.strength; - } - else - { - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength; - - if (AnimateNormals) - buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength; - - //*(weight._Pos) += thisVertexMove * weight.strength; - } - - buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated(); - } - } - - //Skin all children - for (u32 j=0; jChildren.size(); ++j) - skinJoint(joint->Children[j], joint); -} - - -E_ANIMATED_MESH_TYPE CSkinnedMesh::getMeshType() const -{ - return EAMT_SKINNED; -} - - -//! Gets joint count. -u32 CSkinnedMesh::getJointCount() const -{ - return AllJoints.size(); -} - - -//! Gets the name of a joint. -const c8* CSkinnedMesh::getJointName(u32 number) const -{ - if (number >= AllJoints.size()) - return 0; - return AllJoints[number]->Name.c_str(); -} - - -//! Gets a joint number from its name -s32 CSkinnedMesh::getJointNumber(const c8* name) const -{ - for (u32 i=0; iName == name) - return i; - } - - return -1; -} - - -//! returns amount of mesh buffers. -u32 CSkinnedMesh::getMeshBufferCount() const -{ - return LocalBuffers.size(); -} - - -//! returns pointer to a mesh buffer -IMeshBuffer* CSkinnedMesh::getMeshBuffer(u32 nr) const -{ - if (nr < LocalBuffers.size()) - return LocalBuffers[nr]; - else - return 0; -} - - -//! Returns pointer to a mesh buffer which fits a material -IMeshBuffer* CSkinnedMesh::getMeshBuffer(const video::SMaterial &material) const -{ - for (u32 i=0; igetMaterial() == material) - return LocalBuffers[i]; - } - return 0; -} - - -//! returns an axis aligned bounding box -const core::aabbox3d& CSkinnedMesh::getBoundingBox() const -{ - return BoundingBox; -} - - -//! set user axis aligned bounding box -void CSkinnedMesh::setBoundingBox( const core::aabbox3df& box) -{ - BoundingBox = box; -} - - -//! sets a flag of all contained materials to a new value -void CSkinnedMesh::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) -{ - for (u32 i=0; iMaterial.setFlag(flag,newvalue); -} - - -//! set the hardware mapping hint, for driver -void CSkinnedMesh::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, - E_BUFFER_TYPE buffer) -{ - for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); -} - - -//! flags the meshbuffer as changed, reloads hardware buffers -void CSkinnedMesh::setDirty(E_BUFFER_TYPE buffer) -{ - for (u32 i=0; isetDirty(buffer); -} - - -//! uses animation from another mesh -bool CSkinnedMesh::useAnimationFrom(const ISkinnedMesh *mesh) -{ - bool unmatched=false; - - for(u32 i=0;iUseAnimationFrom=0; - - if (joint->Name=="") - unmatched=true; - else - { - for(u32 j=0;jgetAllJoints().size();++j) - { - SJoint *otherJoint=mesh->getAllJoints()[j]; - if (joint->Name==otherJoint->Name) - { - joint->UseAnimationFrom=otherJoint; - } - } - if (!joint->UseAnimationFrom) - unmatched=true; - } - } - - checkForAnimation(); - - return !unmatched; -} - - -//!Update Normals when Animating -//!False= Don't animate them, faster -//!True= Update normals (default) -void CSkinnedMesh::updateNormalsWhenAnimating(bool on) -{ - AnimateNormals = on; -} - - -//!Sets Interpolation Mode -void CSkinnedMesh::setInterpolationMode(E_INTERPOLATION_MODE mode) -{ - InterpolationMode = mode; -} - - -core::array &CSkinnedMesh::getMeshBuffers() -{ - return LocalBuffers; -} - - -core::array &CSkinnedMesh::getAllJoints() -{ - return AllJoints; -} - - -const core::array &CSkinnedMesh::getAllJoints() const -{ - return AllJoints; -} - - -//! (This feature is not implementated in irrlicht yet) -bool CSkinnedMesh::setHardwareSkinning(bool on) -{ - if (HardwareSkinning!=on) - { - if (on) - { - - //set mesh to static pose... - for (u32 i=0; iWeights.size(); ++j) - { - const u16 buffer_id=joint->Weights[j].buffer_id; - const u32 vertex_id=joint->Weights[j].vertex_id; - LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos; - LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal; - LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated(); - } - } - } - - HardwareSkinning=on; - } - return HardwareSkinning; -} - - -void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint,SJoint *parentJoint) -{ - if (!joint && parentJoint) // bit of protection from endless loops - return; - - //Go through the root bones - if (!joint) - { - for (u32 i=0; iGlobalMatrix = joint->LocalMatrix; - else - joint->GlobalMatrix = parentJoint->GlobalMatrix * joint->LocalMatrix; - - joint->LocalAnimatedMatrix=joint->LocalMatrix; - joint->GlobalAnimatedMatrix=joint->GlobalMatrix; - - if (joint->GlobalInversedMatrix.isIdentity())//might be pre calculated - { - joint->GlobalInversedMatrix = joint->GlobalMatrix; - joint->GlobalInversedMatrix.makeInverse(); // slow - } - - for (u32 j=0; jChildren.size(); ++j) - calculateGlobalMatrices(joint->Children[j],joint); - SkinnedLastFrame=false; -} - - -void CSkinnedMesh::checkForAnimation() -{ - u32 i,j; - //Check for animation... - HasAnimation = false; - for(i=0;iUseAnimationFrom) - { - if (AllJoints[i]->UseAnimationFrom->PositionKeys.size() || - AllJoints[i]->UseAnimationFrom->ScaleKeys.size() || - AllJoints[i]->UseAnimationFrom->RotationKeys.size() ) - { - HasAnimation = true; - } - } - } - - //meshes with weights, are still counted as animated for ragdolls, etc - if (!HasAnimation) - { - for(i=0;iWeights.size()) - HasAnimation = true; - } - } - - if (HasAnimation) - { - //--- Find the length of the animation --- - AnimationFrames=0; - for(i=0;iUseAnimationFrom) - { - if (AllJoints[i]->UseAnimationFrom->PositionKeys.size()) - if (AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame > AnimationFrames) - AnimationFrames=AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame; - - if (AllJoints[i]->UseAnimationFrom->ScaleKeys.size()) - if (AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame > AnimationFrames) - AnimationFrames=AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame; - - if (AllJoints[i]->UseAnimationFrom->RotationKeys.size()) - if (AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame > AnimationFrames) - AnimationFrames=AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame; - } - } - } - - if (HasAnimation && !PreparedForSkinning) - { - PreparedForSkinning=true; - - //check for bugs: - for(i=0; i < AllJoints.size(); ++i) - { - SJoint *joint = AllJoints[i]; - for (j=0; jWeights.size(); ++j) - { - const u16 buffer_id=joint->Weights[j].buffer_id; - const u32 vertex_id=joint->Weights[j].vertex_id; - - //check for invalid ids - if (buffer_id>=LocalBuffers.size()) - { - os::Printer::log("Skinned Mesh: Weight buffer id too large", ELL_WARNING); - joint->Weights[j].buffer_id = joint->Weights[j].vertex_id =0; - } - else if (vertex_id>=LocalBuffers[buffer_id]->getVertexCount()) - { - os::Printer::log("Skinned Mesh: Weight vertex id too large", ELL_WARNING); - joint->Weights[j].buffer_id = joint->Weights[j].vertex_id =0; - } - } - } - - //An array used in skinning - - for (i=0; iWeights.size(); ++j) - { - const u16 buffer_id=joint->Weights[j].buffer_id; - const u32 vertex_id=joint->Weights[j].vertex_id; - - joint->Weights[j].Moved = &Vertices_Moved[buffer_id] [vertex_id]; - joint->Weights[j].StaticPos = LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos; - joint->Weights[j].StaticNormal = LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal; - - //joint->Weights[j]._Pos=&Buffers[buffer_id]->getVertex(vertex_id)->Pos; - } - } - - // normalize weights - normalizeWeights(); - } - SkinnedLastFrame=false; -} - - -//! called by loader after populating with mesh and bone data -void CSkinnedMesh::finalize() -{ - u32 i; - - // Make sure we recalc the next frame - LastAnimatedFrame=-1; - SkinnedLastFrame=false; - - //calculate bounding box - for (i=0; irecalculateBoundingBox(); - } - - if (AllJoints.size() || RootJoints.size()) - { - // populate AllJoints or RootJoints, depending on which is empty - if (!RootJoints.size()) - { - - for(u32 CheckingIdx=0; CheckingIdx < AllJoints.size(); ++CheckingIdx) - { - - bool foundParent=false; - for(i=0; i < AllJoints.size(); ++i) - { - for(u32 n=0; n < AllJoints[i]->Children.size(); ++n) - { - if (AllJoints[i]->Children[n] == AllJoints[CheckingIdx]) - foundParent=true; - } - } - - if (!foundParent) - RootJoints.push_back(AllJoints[CheckingIdx]); - } - } - else - { - AllJoints=RootJoints; - } - } - - for(i=0; i < AllJoints.size(); ++i) - { - AllJoints[i]->UseAnimationFrom=AllJoints[i]; - } - - //Set array sizes... - - for (i=0; i() ); - Vertices_Moved[i].set_used(LocalBuffers[i]->getVertexCount()); - } - - //Todo: optimise keys here... - - checkForAnimation(); - - if (HasAnimation) - { - //--- optimize and check keyframes --- - for(i=0;i &PositionKeys =AllJoints[i]->PositionKeys; - core::array &ScaleKeys = AllJoints[i]->ScaleKeys; - core::array &RotationKeys = AllJoints[i]->RotationKeys; - - if (PositionKeys.size()>2) - { - for(u32 j=0;j1) - { - for(u32 j=0;j= PositionKeys[j+1].frame) //bad frame, unneed and may cause problems - { - PositionKeys.erase(j+1); - --j; - } - } - } - - if (ScaleKeys.size()>2) - { - for(u32 j=0;j1) - { - for(u32 j=0;j= ScaleKeys[j+1].frame) //bad frame, unneed and may cause problems - { - ScaleKeys.erase(j+1); - --j; - } - } - } - - if (RotationKeys.size()>2) - { - for(u32 j=0;j1) - { - for(u32 j=0;j= RotationKeys[j+1].frame) //bad frame, unneed and may cause problems - { - RotationKeys.erase(j+1); - --j; - } - } - } - - - //Fill empty keyframe areas - if (PositionKeys.size()) - { - SPositionKey *Key; - Key=&PositionKeys[0];//getFirst - if (Key->frame!=0) - { - PositionKeys.push_front(*Key); - Key=&PositionKeys[0];//getFirst - Key->frame=0; - } - - Key=&PositionKeys.getLast(); - if (Key->frame!=AnimationFrames) - { - PositionKeys.push_back(*Key); - Key=&PositionKeys.getLast(); - Key->frame=AnimationFrames; - } - } - - if (ScaleKeys.size()) - { - SScaleKey *Key; - Key=&ScaleKeys[0];//getFirst - if (Key->frame!=0) - { - ScaleKeys.push_front(*Key); - Key=&ScaleKeys[0];//getFirst - Key->frame=0; - } - - Key=&ScaleKeys.getLast(); - if (Key->frame!=AnimationFrames) - { - ScaleKeys.push_back(*Key); - Key=&ScaleKeys.getLast(); - Key->frame=AnimationFrames; - } - } - - if (RotationKeys.size()) - { - SRotationKey *Key; - Key=&RotationKeys[0];//getFirst - if (Key->frame!=0) - { - RotationKeys.push_front(*Key); - Key=&RotationKeys[0];//getFirst - Key->frame=0; - } - - Key=&RotationKeys.getLast(); - if (Key->frame!=AnimationFrames) - { - RotationKeys.push_back(*Key); - Key=&RotationKeys.getLast(); - Key->frame=AnimationFrames; - } - } - } - } - - //Needed for animation and skinning... - - calculateGlobalMatrices(0,0); - - //animateMesh(0, 1); - //buildAllLocalAnimatedMatrices(); - //buildAllGlobalAnimatedMatrices(); - - //rigid animation for non animated meshes - for (i=0; iAttachedMeshes.size(); ++j) - { - SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ]; - Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix; - } - } - - //calculate bounding box - if (LocalBuffers.empty()) - BoundingBox.reset(0,0,0); - else - { - irr::core::aabbox3df bb(LocalBuffers[0]->BoundingBox); - LocalBuffers[0]->Transformation.transformBoxEx(bb); - BoundingBox.reset(bb); - - for (u32 j=1; jBoundingBox; - LocalBuffers[j]->Transformation.transformBoxEx(bb); - - BoundingBox.addInternalBox(bb); - } - } -} - - -void CSkinnedMesh::updateBoundingBox(void) -{ - if(!SkinningBuffers) - return; - - core::array & buffer = *SkinningBuffers; - BoundingBox.reset(0,0,0); - - if (!buffer.empty()) - { - for (u32 j=0; jrecalculateBoundingBox(); - core::aabbox3df bb = buffer[j]->BoundingBox; - buffer[j]->Transformation.transformBoxEx(bb); - - BoundingBox.addInternalBox(bb); - } - } -} - - -scene::SSkinMeshBuffer *CSkinnedMesh::addMeshBuffer() -{ - scene::SSkinMeshBuffer *buffer=new scene::SSkinMeshBuffer(); - LocalBuffers.push_back(buffer); - return buffer; -} - - -CSkinnedMesh::SJoint *CSkinnedMesh::addJoint(SJoint *parent) -{ - SJoint *joint=new SJoint; - - AllJoints.push_back(joint); - if (!parent) - { - //Add root joints to array in finalize() - } - else - { - //Set parent (Be careful of the mesh loader also setting the parent) - parent->Children.push_back(joint); - } - - return joint; -} - - -CSkinnedMesh::SPositionKey *CSkinnedMesh::addPositionKey(SJoint *joint) -{ - if (!joint) - return 0; - - joint->PositionKeys.push_back(SPositionKey()); - return &joint->PositionKeys.getLast(); -} - - -CSkinnedMesh::SScaleKey *CSkinnedMesh::addScaleKey(SJoint *joint) -{ - if (!joint) - return 0; - - joint->ScaleKeys.push_back(SScaleKey()); - return &joint->ScaleKeys.getLast(); -} - - -CSkinnedMesh::SRotationKey *CSkinnedMesh::addRotationKey(SJoint *joint) -{ - if (!joint) - return 0; - - joint->RotationKeys.push_back(SRotationKey()); - return &joint->RotationKeys.getLast(); -} - - -CSkinnedMesh::SWeight *CSkinnedMesh::addWeight(SJoint *joint) -{ - if (!joint) - return 0; - - joint->Weights.push_back(SWeight()); - return &joint->Weights.getLast(); -} - - -bool CSkinnedMesh::isStatic() -{ - return !HasAnimation; -} - - -void CSkinnedMesh::normalizeWeights() -{ - // note: unsure if weights ids are going to be used. - - // Normalise the weights on bones.... - - u32 i,j; - core::array< core::array > verticesTotalWeight; - - verticesTotalWeight.reallocate(LocalBuffers.size()); - for (i=0; i()); - verticesTotalWeight[i].set_used(LocalBuffers[i]->getVertexCount()); - } - - for (i=0; iWeights.size(); ++j) - { - if (joint->Weights[j].strength<=0)//Check for invalid weights - { - joint->Weights.erase(j); - --j; - } - else - { - verticesTotalWeight[joint->Weights[j].buffer_id] [joint->Weights[j].vertex_id] += joint->Weights[j].strength; - } - } - } - - for (i=0; iWeights.size(); ++j) - { - const f32 total = verticesTotalWeight[joint->Weights[j].buffer_id] [joint->Weights[j].vertex_id]; - if (total != 0 && total != 1) - joint->Weights[j].strength /= total; - } - } -} - - -void CSkinnedMesh::recoverJointsFromMesh(core::array &jointChildSceneNodes) -{ - for (u32 i=0; isetPosition(joint->LocalAnimatedMatrix.getTranslation()); - node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees()); - node->setScale(joint->LocalAnimatedMatrix.getScale()); - - node->positionHint=joint->positionHint; - node->scaleHint=joint->scaleHint; - node->rotationHint=joint->rotationHint; - - node->updateAbsolutePosition(); - } -} - - -void CSkinnedMesh::transferJointsToMesh(const core::array &jointChildSceneNodes) -{ - for (u32 i=0; iLocalAnimatedMatrix.setRotationDegrees(node->getRotation()); - joint->LocalAnimatedMatrix.setTranslation(node->getPosition()); - joint->LocalAnimatedMatrix *= core::matrix4().setScale(node->getScale()); - - joint->positionHint=node->positionHint; - joint->scaleHint=node->scaleHint; - joint->rotationHint=node->rotationHint; - - joint->GlobalSkinningSpace=(node->getSkinningSpace()==EBSS_GLOBAL); - } - // Make sure we recalc the next frame - LastAnimatedFrame=-1; - SkinnedLastFrame=false; -} - - -void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array &jointChildSceneNodes) -{ - for (u32 i=0; ipositionHint=node->positionHint; - joint->scaleHint=node->scaleHint; - joint->rotationHint=node->rotationHint; - } - SkinnedLastFrame=false; -} - - -void CSkinnedMesh::addJoints(core::array &jointChildSceneNodes, - IAnimatedMeshSceneNode* node, ISceneManager* smgr) -{ - //Create new joints - for (u32 i=0; iName.c_str())); - } - - //Match up parents - for (u32 i=0; iChildren.size(); ++n) - { - if (parentTest->Children[n]==joint) - { - parentID=j; - break; - } - } - } - } - - IBoneSceneNode* bone=jointChildSceneNodes[i]; - if (parentID!=-1) - bone->setParent(jointChildSceneNodes[parentID]); - else - bone->setParent(node); - - bone->drop(); - } - SkinnedLastFrame=false; -} - - -void CSkinnedMesh::convertMeshToTangents() -{ - // now calculate tangents - for (u32 b=0; b < LocalBuffers.size(); ++b) - { - if (LocalBuffers[b]) - { - LocalBuffers[b]->convertToTangents(); - - const s32 idxCnt = LocalBuffers[b]->getIndexCount(); - - u16* idx = LocalBuffers[b]->getIndices(); - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)LocalBuffers[b]->getVertices(); - - for (s32 i=0; i