source: OGRE/trunk/ogrenew/OgreMain/src/OgreAnimationTrack.cpp @ 692

Revision 692, 29.1 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreAnimationTrack.h"
27#include "OgreAnimation.h"
28#include "OgreKeyFrame.h"
29#include "OgreNode.h"
30#include "OgreLogManager.h"
31#include "OgreHardwareBufferManager.h"
32#include "OgreMesh.h"
33#include "OgreException.h"
34
35namespace Ogre {
36
37    //---------------------------------------------------------------------
38    AnimationTrack::AnimationTrack(Animation* parent, unsigned short handle) :
39                mMaxKeyFrameTime(-1), mParent(parent), mHandle(handle)
40    {
41    }
42    //---------------------------------------------------------------------
43    AnimationTrack::~AnimationTrack()
44    {
45        removeAllKeyFrames();
46    }
47    //---------------------------------------------------------------------
48    unsigned short AnimationTrack::getNumKeyFrames(void) const
49    {
50        return (unsigned short)mKeyFrames.size();
51    }
52    //---------------------------------------------------------------------
53    KeyFrame* AnimationTrack::getKeyFrame(unsigned short index) const
54    {
55                // If you hit this assert, then the keyframe index is out of bounds
56        assert( index < (ushort)mKeyFrames.size() );
57
58        return mKeyFrames[index];
59    }
60    //---------------------------------------------------------------------
61    Real AnimationTrack::getKeyFramesAtTime(Real timePos, KeyFrame** keyFrame1, KeyFrame** keyFrame2,
62            unsigned short* firstKeyIndex) const
63    {
64        short firstIndex = -1;
65        Real totalAnimationLength = mParent->getLength();
66
67        // Wrap time
68        while (timePos > totalAnimationLength)
69        {
70            timePos -= totalAnimationLength;
71        }
72
73        KeyFrameList::const_iterator i = mKeyFrames.begin();
74        // Find last keyframe before or on current time
75        while (i != mKeyFrames.end() && (*i)->getTime() <= timePos)
76        {
77            *keyFrame1 = *i++;
78            ++firstIndex;
79        }
80
81        // Trap case where there is no key before this time (problem with animation config)
82        // In this case use the first key anyway and pretend it's time index 0
83        if (firstIndex == -1)
84        {
85            *keyFrame1 = *i;
86            ++firstIndex;
87        }
88
89        // Fill index of the first key
90        if (firstKeyIndex != NULL)
91        {
92            *firstKeyIndex = firstIndex;
93        }
94
95        // Parametric time
96        // t1 = time of previous keyframe
97        // t2 = time of next keyframe
98        Real t1, t2;
99        // Find first keyframe after the time
100        // If no next keyframe, wrap back to first
101        if (i == mKeyFrames.end())
102        {
103            *keyFrame2 = mKeyFrames[0];
104            t2 = totalAnimationLength;
105        }
106        else
107        {
108            *keyFrame2 = *i;
109            t2 = (*keyFrame2)->getTime();
110        }
111
112        t1 = (*keyFrame1)->getTime();
113
114        if (t1 == t2)
115        {
116            // Same KeyFrame (only one)
117            return 0.0;
118        }
119        else
120        {
121            return (timePos - t1) / (t2 - t1);
122        }
123    }
124    //---------------------------------------------------------------------
125    KeyFrame* AnimationTrack::createKeyFrame(Real timePos)
126    {
127        KeyFrame* kf = createKeyFrameImpl(timePos);
128
129        // Insert at correct location
130        if (timePos > mMaxKeyFrameTime || (timePos == 0 && mKeyFrames.empty()))
131        {
132            // Quick insert at end
133            mKeyFrames.push_back(kf);
134            mMaxKeyFrameTime = timePos;
135        }
136        else
137        {
138            // Search
139            KeyFrameList::iterator i = mKeyFrames.begin();
140            while ((*i)->getTime() < timePos && i != mKeyFrames.end())
141            {
142                ++i;
143            }
144            mKeyFrames.insert(i, kf);
145        }
146
147        _keyFrameDataChanged();
148
149        return kf;
150
151    }
152    //---------------------------------------------------------------------
153    void AnimationTrack::removeKeyFrame(unsigned short index)
154    {
155                // If you hit this assert, then the keyframe index is out of bounds
156        assert( index < (ushort)mKeyFrames.size() );
157
158        KeyFrameList::iterator i = mKeyFrames.begin();
159
160        i += index;
161
162        delete *i;
163
164        mKeyFrames.erase(i);
165
166        _keyFrameDataChanged();
167
168
169    }
170    //---------------------------------------------------------------------
171    void AnimationTrack::removeAllKeyFrames(void)
172    {
173        KeyFrameList::iterator i = mKeyFrames.begin();
174
175        for (; i != mKeyFrames.end(); ++i)
176        {
177            delete *i;
178        }
179
180        _keyFrameDataChanged();
181
182        mKeyFrames.clear();
183
184    }
185        //---------------------------------------------------------------------
186        //---------------------------------------------------------------------
187        // Numeric specialisations
188        //---------------------------------------------------------------------
189        NumericAnimationTrack::NumericAnimationTrack(Animation* parent,
190                unsigned short handle)
191                : AnimationTrack(parent, handle)
192        {
193        }
194        //---------------------------------------------------------------------
195        NumericAnimationTrack::NumericAnimationTrack(Animation* parent,
196                unsigned short handle, AnimableValuePtr& target)
197                :AnimationTrack(parent, handle), mTargetAnim(target)
198        {
199        }
200        //---------------------------------------------------------------------
201        const AnimableValuePtr& NumericAnimationTrack::getAssociatedAnimable(void) const
202        {
203                return mTargetAnim;
204        }
205        //---------------------------------------------------------------------
206        void NumericAnimationTrack::setAssociatedAnimable(const AnimableValuePtr& val)
207        {
208                mTargetAnim = val;
209        }
210        //---------------------------------------------------------------------
211        KeyFrame* NumericAnimationTrack::createKeyFrameImpl(Real time)
212        {
213                return new NumericKeyFrame(this, time);
214        }
215        //---------------------------------------------------------------------
216        void NumericAnimationTrack::getInterpolatedKeyFrame(Real timeIndex,
217                KeyFrame* kf) const
218        {
219                NumericKeyFrame* kret = static_cast<NumericKeyFrame*>(kf);
220
221        // Keyframe pointers
222                KeyFrame *kBase1, *kBase2;
223        NumericKeyFrame *k1, *k2;
224        unsigned short firstKeyIndex;
225
226        Real t = this->getKeyFramesAtTime(timeIndex, &kBase1, &kBase2, &firstKeyIndex);
227                k1 = static_cast<NumericKeyFrame*>(kBase1);
228                k2 = static_cast<NumericKeyFrame*>(kBase2);
229
230        if (t == 0.0)
231        {
232            // Just use k1
233            kret->setValue(k1->getValue());
234        }
235        else
236        {
237            // Interpolate by t
238                        AnyNumeric diff = k2->getValue() - k1->getValue();
239                        kret->setValue(k1->getValue() + diff * t);
240        }
241        }
242        //---------------------------------------------------------------------
243        void NumericAnimationTrack::apply(Real timePos, Real weight, bool accumulate,
244                Real scale)
245        {
246                applyToAnimable(mTargetAnim, timePos, weight, scale);
247        }
248        //---------------------------------------------------------------------
249        void NumericAnimationTrack::applyToAnimable(const AnimableValuePtr& anim, Real timePos,
250                Real weight, Real scale)
251        {
252                NumericKeyFrame kf(0, timePos);
253                getInterpolatedKeyFrame(timePos, &kf);
254                // add to existing. Weights are not relative, but treated as
255                // absolute multipliers for the animation
256                AnyNumeric val = kf.getValue() * weight * scale;
257
258                anim->applyDeltaValue(val);
259
260        }
261        //--------------------------------------------------------------------------
262        NumericKeyFrame* NumericAnimationTrack::createNumericKeyFrame(Real timePos)
263        {
264                return static_cast<NumericKeyFrame*>(createKeyFrame(timePos));
265        }
266        //--------------------------------------------------------------------------
267        NumericKeyFrame* NumericAnimationTrack::getNumericKeyFrame(unsigned short index) const
268        {
269                return static_cast<NumericKeyFrame*>(getKeyFrame(index));
270        }
271    //---------------------------------------------------------------------
272        //---------------------------------------------------------------------
273        // Node specialisations
274        //---------------------------------------------------------------------
275        NodeAnimationTrack::NodeAnimationTrack(Animation* parent, unsigned short handle)
276                : AnimationTrack(parent, handle), mTargetNode(0), mSplineBuildNeeded(false),
277                mUseShortestRotationPath(true)
278        {
279        }
280        //---------------------------------------------------------------------
281        NodeAnimationTrack::NodeAnimationTrack(Animation* parent, unsigned short handle,
282                Node* targetNode)
283                : AnimationTrack(parent, handle), mTargetNode(targetNode),
284                mSplineBuildNeeded(false), mUseShortestRotationPath(true)
285        {
286        }
287        //---------------------------------------------------------------------
288    void NodeAnimationTrack::getInterpolatedKeyFrame(Real timeIndex, KeyFrame* kf) const
289    {
290                TransformKeyFrame* kret = static_cast<TransformKeyFrame*>(kf);
291
292        // Keyframe pointers
293                KeyFrame *kBase1, *kBase2;
294        TransformKeyFrame *k1, *k2;
295        unsigned short firstKeyIndex;
296
297        Real t = this->getKeyFramesAtTime(timeIndex, &kBase1, &kBase2, &firstKeyIndex);
298                k1 = static_cast<TransformKeyFrame*>(kBase1);
299                k2 = static_cast<TransformKeyFrame*>(kBase2);
300
301        if (t == 0.0)
302        {
303            // Just use k1
304            kret->setRotation(k1->getRotation());
305            kret->setTranslate(k1->getTranslate());
306            kret->setScale(k1->getScale());
307        }
308        else
309        {
310            // Interpolate by t
311            Animation::InterpolationMode im = mParent->getInterpolationMode();
312            Animation::RotationInterpolationMode rim =
313                mParent->getRotationInterpolationMode();
314            Vector3 base;
315            switch(im)
316            {
317            case Animation::IM_LINEAR:
318                // Interpolate linearly
319                // Rotation
320                // Interpolate to nearest rotation if mUseShortestRotationPath set
321                if (rim == Animation::RIM_LINEAR)
322                {
323                    kret->setRotation( Quaternion::nlerp(t, k1->getRotation(),
324                        k2->getRotation(), mUseShortestRotationPath) );
325                }
326                else //if (rim == Animation::RIM_SPHERICAL)
327                {
328                    kret->setRotation( Quaternion::Slerp(t, k1->getRotation(),
329                                            k2->getRotation(), mUseShortestRotationPath) );
330                }
331
332                // Translation
333                base = k1->getTranslate();
334                kret->setTranslate( base + ((k2->getTranslate() - base) * t) );
335
336                // Scale
337                base = k1->getScale();
338                kret->setScale( base + ((k2->getScale() - base) * t) );
339                break;
340
341            case Animation::IM_SPLINE:
342                // Spline interpolation
343
344                // Build splines if required
345                if (mSplineBuildNeeded)
346                {
347                    buildInterpolationSplines();
348                }
349
350                // Rotation, take mUseShortestRotationPath into account
351                kret->setRotation( mRotationSpline.interpolate(firstKeyIndex, t,
352                                        mUseShortestRotationPath) );
353
354                // Translation
355                kret->setTranslate( mPositionSpline.interpolate(firstKeyIndex, t) );
356
357                // Scale
358                kret->setScale( mScaleSpline.interpolate(firstKeyIndex, t) );
359
360                break;
361            }
362
363        }
364
365    }
366    //---------------------------------------------------------------------
367    void NodeAnimationTrack::apply(Real timePos, Real weight, bool accumulate,
368                Real scale)
369    {
370        applyToNode(mTargetNode, timePos, weight, accumulate, scale);
371
372    }
373    //---------------------------------------------------------------------
374    Node* NodeAnimationTrack::getAssociatedNode(void) const
375    {
376        return mTargetNode;
377    }
378    //---------------------------------------------------------------------
379    void NodeAnimationTrack::setAssociatedNode(Node* node)
380    {
381        mTargetNode = node;
382    }
383    //---------------------------------------------------------------------
384    void NodeAnimationTrack::applyToNode(Node* node, Real timePos, Real weight,
385                bool accumulate, Real scl)
386    {
387        TransformKeyFrame kf(0, timePos);
388                getInterpolatedKeyFrame(timePos, &kf);
389                if (accumulate)
390        {
391            // add to existing. Weights are not relative, but treated as absolute multipliers for the animation
392            Vector3 translate = kf.getTranslate() * weight * scl;
393                        node->translate(translate);
394
395                        // interpolate between no-rotation and full rotation, to point 'weight', so 0 = no rotate, 1 = full
396            Quaternion rotate;
397            Animation::RotationInterpolationMode rim =
398                mParent->getRotationInterpolationMode();
399            if (rim == Animation::RIM_LINEAR)
400            {
401                rotate = Quaternion::nlerp(weight, Quaternion::IDENTITY, kf.getRotation());
402            }
403            else //if (rim == Animation::RIM_SPHERICAL)
404            {
405                rotate = Quaternion::Slerp(weight, Quaternion::IDENTITY, kf.getRotation());
406            }
407                        node->rotate(rotate);
408
409                        Vector3 scale = kf.getScale();
410                        // Not sure how to modify scale for cumulative anims... leave it alone
411                        //scale = ((Vector3::UNIT_SCALE - kf.getScale()) * weight) + Vector3::UNIT_SCALE;
412                        if (scl != 1.0f && scale != Vector3::UNIT_SCALE)
413                        {
414                                scale = Vector3::UNIT_SCALE + (scale - Vector3::UNIT_SCALE) * scl;
415                        }
416                        node->scale(scale);
417                }
418        else
419        {
420                        // apply using weighted transform method
421                        Vector3 scale = kf.getScale();
422                        if (scl != 1.0f && scale != Vector3::UNIT_SCALE)
423                        {
424                                scale = Vector3::UNIT_SCALE + (scale - Vector3::UNIT_SCALE) * scl;
425                        }
426                        node->_weightedTransform(weight, kf.getTranslate() * scl, kf.getRotation(),
427                                scale);
428                }
429
430        /*
431        // DEBUG
432        if (!mMainWindow)
433        {
434            mMainWindow = Root::getSingleton().getRenderWindow("OGRE Render Window");
435        }
436        String msg = "Time: ";
437        msg << timePos;
438        mMainWindow->setDebugText(msg);
439        */
440
441        //node->rotate(kf.getRotation() * weight);
442        //node->translate(kf.getTranslate() * weight);
443
444
445
446
447    }
448    //---------------------------------------------------------------------
449    void NodeAnimationTrack::buildInterpolationSplines(void) const
450    {
451        // Don't calc automatically, do it on request at the end
452        mPositionSpline.setAutoCalculate(false);
453        mRotationSpline.setAutoCalculate(false);
454        mScaleSpline.setAutoCalculate(false);
455
456        mPositionSpline.clear();
457        mRotationSpline.clear();
458        mScaleSpline.clear();
459
460        KeyFrameList::const_iterator i, iend;
461        iend = mKeyFrames.end(); // precall to avoid overhead
462        for (i = mKeyFrames.begin(); i != iend; ++i)
463        {
464                        TransformKeyFrame* kf = static_cast<TransformKeyFrame*>(*i);
465            mPositionSpline.addPoint(kf->getTranslate());
466            mRotationSpline.addPoint(kf->getRotation());
467            mScaleSpline.addPoint(kf->getScale());
468        }
469
470        mPositionSpline.recalcTangents();
471        mRotationSpline.recalcTangents();
472        mScaleSpline.recalcTangents();
473
474
475        mSplineBuildNeeded = false;
476    }
477
478    //---------------------------------------------------------------------
479        void NodeAnimationTrack::setUseShortestRotationPath(bool useShortestPath)
480        {
481                mUseShortestRotationPath = useShortestPath ;
482        }
483
484    //---------------------------------------------------------------------
485        bool NodeAnimationTrack::getUseShortestRotationPath() const
486        {
487                return mUseShortestRotationPath ;
488        }
489    //---------------------------------------------------------------------
490    void NodeAnimationTrack::_keyFrameDataChanged(void) const
491    {
492        mSplineBuildNeeded = true;
493    }
494    //---------------------------------------------------------------------
495        bool NodeAnimationTrack::hasNonZeroKeyFrames(void) const
496        {
497        KeyFrameList::const_iterator i = mKeyFrames.begin();
498        for (; i != mKeyFrames.end(); ++i)
499        {
500                        // look for keyframes which have any component which is non-zero
501                        // Since exporters can be a little inaccurate sometimes we use a
502                        // tolerance value rather than looking for nothing
503                        TransformKeyFrame* kf = static_cast<TransformKeyFrame*>(*i);
504                        Vector3 trans = kf->getTranslate();
505                        Vector3 scale = kf->getScale();
506                        Vector3 axis;
507                        Radian angle;
508                        kf->getRotation().ToAngleAxis(angle, axis);
509                        Real tolerance = 1e-3f;
510                        if (!trans.positionEquals(Vector3::ZERO, tolerance) ||
511                                !scale.positionEquals(Vector3::UNIT_SCALE, tolerance) ||
512                                !Math::RealEqual(angle.valueRadians(), 0.0f, tolerance))
513                        {
514                                return true;
515                        }
516
517                }
518
519                return false;
520        }
521    //---------------------------------------------------------------------
522        void NodeAnimationTrack::optimise(void)
523        {
524                // Eliminate duplicate keyframes from 2nd to penultimate keyframe
525                // NB only eliminate middle keys from sequences of 5+ identical keyframes
526                // since we need to preserve the boundary keys in place, and we need
527                // 2 at each end to preserve tangents for spline interpolation
528                Vector3 lasttrans;
529                Vector3 lastscale;
530                Quaternion lastorientation;
531        KeyFrameList::iterator i = mKeyFrames.begin();
532                Radian quatTolerance(1e-3f);
533                std::list<unsigned short> removeList;
534                unsigned short k = 0;
535                ushort dupKfCount = 0;
536        for (; i != mKeyFrames.end(); ++i, ++k)
537        {
538                        TransformKeyFrame* kf = static_cast<TransformKeyFrame*>(*i);
539                        Vector3 newtrans = kf->getTranslate();
540                        Vector3 newscale = kf->getScale();
541                        Quaternion neworientation = kf->getRotation();
542                        // Ignore first keyframe; now include the last keyframe as we eliminate
543                        // only k-2 in a group of 5 to ensure we only eliminate middle keys
544                        if (i != mKeyFrames.begin() &&
545                                newtrans.positionEquals(lasttrans) &&
546                                newscale.positionEquals(lastscale) &&
547                                neworientation.equals(lastorientation, quatTolerance))
548                        {
549                                ++dupKfCount;
550
551                                // 4 indicates this is the 5th duplicate keyframe
552                                if (dupKfCount == 4)
553                                {
554                                        // remove the 'middle' keyframe
555                                        removeList.push_back(k-2);
556                                        --dupKfCount;
557                                }
558                        }
559                        else
560                        {
561                                // reset
562                                dupKfCount = 0;
563                                lasttrans = newtrans;
564                                lastscale = newscale;
565                                lastorientation = neworientation;
566                        }
567                }
568
569                // Now remove keyframes, in reverse order to avoid index revocation
570                std::list<unsigned short>::reverse_iterator r = removeList.rbegin();
571                for (; r!= removeList.rend(); ++r)
572                {
573                        removeKeyFrame(*r);
574                }
575
576
577        }
578        //--------------------------------------------------------------------------
579        KeyFrame* NodeAnimationTrack::createKeyFrameImpl(Real time)
580        {
581                return new TransformKeyFrame(this, time);
582        }
583        //--------------------------------------------------------------------------
584        TransformKeyFrame* NodeAnimationTrack::createNodeKeyFrame(Real timePos)
585        {
586                return static_cast<TransformKeyFrame*>(createKeyFrame(timePos));
587        }
588        //--------------------------------------------------------------------------
589        TransformKeyFrame* NodeAnimationTrack::getNodeKeyFrame(unsigned short index) const
590        {
591                return static_cast<TransformKeyFrame*>(getKeyFrame(index));
592        }
593        //--------------------------------------------------------------------------
594        VertexAnimationTrack::VertexAnimationTrack(Animation* parent,
595                unsigned short handle, VertexAnimationType animType)
596                : AnimationTrack(parent, handle), mAnimationType(animType)
597        {
598        }
599        //--------------------------------------------------------------------------
600        VertexAnimationTrack::VertexAnimationTrack(Animation* parent, unsigned short handle,
601                VertexAnimationType animType, VertexData* targetData, TargetMode target)
602                : AnimationTrack(parent, handle), mAnimationType(animType),
603                mTargetVertexData(targetData), mTargetMode(target)
604        {
605        }
606        //--------------------------------------------------------------------------
607        VertexMorphKeyFrame* VertexAnimationTrack::createVertexMorphKeyFrame(Real timePos)
608        {
609                if (mAnimationType != VAT_MORPH)
610                {
611                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
612                                "Morph keyframes can only be created on vertex tracks of type morph.",
613                                "VertexAnimationTrack::createVertexMorphKeyFrame");
614                }
615                return static_cast<VertexMorphKeyFrame*>(createKeyFrame(timePos));
616        }
617        //--------------------------------------------------------------------------
618        VertexPoseKeyFrame* VertexAnimationTrack::createVertexPoseKeyFrame(Real timePos)
619        {
620                if (mAnimationType != VAT_POSE)
621                {
622                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
623                                "Pose keyframes can only be created on vertex tracks of type pose.",
624                                "VertexAnimationTrack::createVertexPoseKeyFrame");
625                }
626                return static_cast<VertexPoseKeyFrame*>(createKeyFrame(timePos));
627        }
628        //--------------------------------------------------------------------------
629        void VertexAnimationTrack::apply(Real timePos, Real weight, bool accumulate,
630                Real scale)
631        {
632                applyToVertexData(mTargetVertexData, timePos, weight);
633        }
634        //--------------------------------------------------------------------------
635        void VertexAnimationTrack::applyToVertexData(VertexData* data,
636                Real timePos, Real weight,  const PoseList* poseList)
637        {
638                // Get keyframes
639                KeyFrame *kf1, *kf2;
640                Real t = getKeyFramesAtTime(timePos, &kf1, &kf2);
641
642                if (mAnimationType == VAT_MORPH)
643                {
644                        VertexMorphKeyFrame* vkf1 = static_cast<VertexMorphKeyFrame*>(kf1);
645                        VertexMorphKeyFrame* vkf2 = static_cast<VertexMorphKeyFrame*>(kf2);
646
647                        if (mTargetMode == TM_HARDWARE)
648                        {
649                                // If target mode is hardware, need to bind our 2 keyframe buffers,
650                                // one to main pos, one to morph target texcoord
651                                assert(!data->hwAnimationDataList.empty() &&
652                                        "Haven't set up hardware vertex animation elements!");
653
654                                // no use for TempBlendedBufferInfo here btw
655                                // NB we assume that position buffer is unshared
656                                // VertexDeclaration::getAutoOrganisedDeclaration should see to that
657                                const VertexElement* posElem =
658                                        data->vertexDeclaration->findElementBySemantic(VES_POSITION);
659                                // Set keyframe1 data as original position
660                                data->vertexBufferBinding->setBinding(
661                                        posElem->getSource(), vkf1->getVertexBuffer());
662                                // Set keyframe2 data as derived
663                                data->vertexBufferBinding->setBinding(
664                                        data->hwAnimationDataList[0].targetVertexElement->getSource(),
665                                        vkf2->getVertexBuffer());
666                                // save T for use later
667                                data->hwAnimationDataList[0].parametric = t;
668
669                        }
670                        else
671                        {
672                                // If target mode is software, need to software interpolate each vertex
673
674                                Mesh::softwareVertexMorph(
675                                        t, vkf1->getVertexBuffer(), vkf2->getVertexBuffer(), data);
676                        }
677                }
678                else
679                {
680                        // Pose
681
682                        VertexPoseKeyFrame* vkf1 = static_cast<VertexPoseKeyFrame*>(kf1);
683                        VertexPoseKeyFrame* vkf2 = static_cast<VertexPoseKeyFrame*>(kf2);
684
685                        // For each pose reference in key 1, we need to locate the entry in
686                        // key 2 and interpolate the influence
687                        const VertexPoseKeyFrame::PoseRefList& poseList1 = vkf1->getPoseReferences();
688                        const VertexPoseKeyFrame::PoseRefList& poseList2 = vkf2->getPoseReferences();
689                        for (VertexPoseKeyFrame::PoseRefList::const_iterator p1 = poseList1.begin();
690                                p1 != poseList1.end(); ++p1)
691                        {
692                                Real startInfluence = p1->influence;
693                                Real endInfluence = 0;
694                                // Search for entry in keyframe 2 list (if not there, will be 0)
695                                for (VertexPoseKeyFrame::PoseRefList::const_iterator p2 = poseList2.begin();
696                                        p2 != poseList2.end(); ++p2)
697                                {
698                                        if (p1->poseIndex == p2->poseIndex)
699                                        {
700                                                endInfluence = p2->influence;
701                                                break;
702                                        }
703                                }
704                                // Interpolate influence
705                                Real influence = startInfluence + t*(endInfluence - startInfluence);
706                                // Scale by animation weight
707                                influence = weight * influence;
708                                // Get pose
709                                assert (p1->poseIndex <= poseList->size());
710                                Pose* pose = (*poseList)[p1->poseIndex];
711                                // apply
712                                applyPoseToVertexData(pose, data, influence);
713                        }
714                        // Now deal with any poses in key 2 which are not in key 1
715                        for (VertexPoseKeyFrame::PoseRefList::const_iterator p2 = poseList2.begin();
716                                p2 != poseList2.end(); ++p2)
717                        {
718                                bool found = false;
719                                for (VertexPoseKeyFrame::PoseRefList::const_iterator p1 = poseList1.begin();
720                                        p1 != poseList1.end(); ++p1)
721                                {
722                                        if (p1->poseIndex == p2->poseIndex)
723                                        {
724                                                found = true;
725                                                break;
726                                        }
727                                }
728                                if (!found)
729                                {
730                                        // Need to apply this pose too, scaled from 0 start
731                                        Real influence = t * p2->influence;
732                                        // Scale by animation weight
733                                        influence = weight * influence;
734                                        // Get pose
735                                        assert (p2->poseIndex <= poseList->size());
736                                        const Pose* pose = (*poseList)[p2->poseIndex];
737                                        // apply
738                                        applyPoseToVertexData(pose, data, influence);
739                                }
740                        } // key 2 iteration
741                } // morph or pose animation
742        }
743        //-----------------------------------------------------------------------------
744        void VertexAnimationTrack::applyPoseToVertexData(const Pose* pose,
745                VertexData* data, Real influence)
746        {
747                if (mTargetMode == TM_HARDWARE)
748                {
749                        // Hardware
750                        // If target mode is hardware, need to bind our pose buffer
751                        // to a target texcoord
752                        assert(!data->hwAnimationDataList.empty() &&
753                                "Haven't set up hardware vertex animation elements!");
754                        // no use for TempBlendedBufferInfo here btw
755                        // Set pose target as required
756                        size_t hwIndex = data->hwAnimDataItemsUsed++;
757                        // If we try to use too many poses, ignore extras
758                        if (hwIndex < data->hwAnimationDataList.size())
759                        {
760                                VertexData::HardwareAnimationData& animData = data->hwAnimationDataList[hwIndex];
761                                data->vertexBufferBinding->setBinding(
762                                        animData.targetVertexElement->getSource(),
763                                        pose->_getHardwareVertexBuffer(data->vertexCount));
764                                // save final influence in parametric
765                                animData.parametric = influence;
766
767                        }
768
769                }
770                else
771                {
772                        // Software
773                        Mesh::softwareVertexPoseBlend(influence, pose->getVertexOffsets(), data);
774                }
775
776        }
777        //--------------------------------------------------------------------------
778        VertexMorphKeyFrame* VertexAnimationTrack::getVertexMorphKeyFrame(unsigned short index) const
779        {
780                if (mAnimationType != VAT_MORPH)
781                {
782                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
783                                "Morph keyframes can only be created on vertex tracks of type morph.",
784                                "VertexAnimationTrack::getVertexMorphKeyFrame");
785                }
786
787                return static_cast<VertexMorphKeyFrame*>(getKeyFrame(index));
788        }
789        //--------------------------------------------------------------------------
790        VertexPoseKeyFrame* VertexAnimationTrack::getVertexPoseKeyFrame(unsigned short index) const
791        {
792                if (mAnimationType != VAT_POSE)
793                {
794                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
795                                "Pose keyframes can only be created on vertex tracks of type pose.",
796                                "VertexAnimationTrack::getVertexPoseKeyFrame");
797                }
798
799                return static_cast<VertexPoseKeyFrame*>(getKeyFrame(index));
800        }
801        //--------------------------------------------------------------------------
802        KeyFrame* VertexAnimationTrack::createKeyFrameImpl(Real time)
803        {
804                switch(mAnimationType)
805                {
806                default:
807                case VAT_MORPH:
808            return new VertexMorphKeyFrame(this, time);
809                case VAT_POSE:
810                        return new VertexPoseKeyFrame(this, time);
811                };
812
813        }
814        //---------------------------------------------------------------------
815        bool VertexAnimationTrack::hasNonZeroKeyFrames(void) const
816        {
817                if (mAnimationType == VAT_MORPH)
818                {
819                        return !mKeyFrames.empty();
820                }
821                else
822                {
823
824                        KeyFrameList::const_iterator i = mKeyFrames.begin();
825                        for (; i != mKeyFrames.end(); ++i)
826                        {
827                                // look for keyframes which have a pose influence which is non-zero
828                                const VertexPoseKeyFrame* kf = static_cast<const VertexPoseKeyFrame*>(*i);
829                                VertexPoseKeyFrame::ConstPoseRefIterator poseIt
830                                        = kf->getPoseReferenceIterator();
831                                while (poseIt.hasMoreElements())
832                                {
833                                        const VertexPoseKeyFrame::PoseRef& poseRef = poseIt.getNext();
834                                        if (poseRef.influence > 0.0f)
835                                                return true;
836                                }
837
838                        }
839
840                        return false;
841                }
842        }
843        //---------------------------------------------------------------------
844        void VertexAnimationTrack::optimise(void)
845        {
846                // TODO - remove sequences of duplicate pose references?
847
848
849        }
850
851
852}
853
Note: See TracBrowser for help on using the repository browser.