Explorar el Código

Added brief documentation on skeletal animation.
Added missing morphs attribute to AnimatedModel.

Lasse Öörni hace 14 años
padre
commit
a5681746e1
Se han modificado 3 ficheros con 38 adiciones y 2 borrados
  1. 14 1
      Docs/Reference.dox
  2. 18 1
      Engine/Graphics/AnimatedModel.cpp
  3. 6 0
      Engine/Graphics/AnimatedModel.h

+ 14 - 1
Docs/Reference.dox

@@ -435,7 +435,7 @@ Note that many more optimization opportunities are possible at the content level
 
 \section Rendering_Further Further details
 
-See also \ref Materials "Materials", \ref Lights "Lights and shadows", \ref Particles "Particle systems", \ref Postprocessing "Post-processing", \ref Zones "Zones", and \ref AuxiliaryViews "Auxiliary views".
+See also \ref Materials "Materials", \ref Lights "Lights and shadows", \ref SkeletalAnimation "Skeletal animation", \ref Particles "Particle systems", \ref Postprocessing "Post-processing", \ref Zones "Zones", and \ref AuxiliaryViews "Auxiliary views".
 
 See \ref RenderingModes "Rendering modes" for detailed discussion on the forward, light pre-pass and deferred rendering modes.
 
@@ -648,6 +648,19 @@ When reuse is enabled, only one shadow texture of each shadow map size needs to
 When reuse is disabled, all shadow maps are rendered before the actual scene rendering. Now multiple shadow textures need to be reserved based on the number of simultaneous shadow casting lights. See the function \ref Renderer::SetNumShadowMaps "SetNumShadowMaps()". If there are not enough shadow textures, they will be assigned to the closest/brightest lights, and the rest will be rendered unshadowed. Now more texture memory is needed, but the advantage is that also transparent objects can receive shadows.
 
 
+\page SkeletalAnimation Skeletal animation
+
+There are two ways to play skeletal animations. Either manually, by adding or removing animation states to the AnimatedModel, and advancing their time positions & weights, see \ref AnimatedModel::AddAnimationState "AddAnimationState()", \ref AnimatedModel::RemoveAnimationState "RemoveAnimationState()", \ref AnimationState::AddTime "AddTime()" and \ref AnimationState::SetWeight "SetWeight()". Alternatively the helper component AnimationController can be used by adding it into the same Node as the AnimatedModel, and using its functions, such as \ref AnimationController::Play "Play()" and \ref AnimationController::Stop "Stop()". AnimationController will advance the animations automatically during scene update. It also enables automatic network synchronization of animations, which the AnimatedModel does not do on its own.
+
+Note that AnimationController does not by default stop non-looping animations automatically once they reach the end, so their final pose will stay in effect. Rather they must either be stopped manually, or the \ref AnimationController::SetAutoFade "SetAutoFade()" function can be used to make them automatically fade out once reaching the end.
+
+\section SkeletalAnimation_Blending Animation blending
+
+%Animation blending uses the concept of numbered layers. Layer numbers are unsigned 8-bit integers, and the active \ref AnimationState "AnimationStates" on each layer are processed in order from the lowest layer to the highest. As animations are applied by lerp-blending between absolute bone transforms, the effect is that the higher layer numbers have higher priority, as they will remain in effect last.
+
+By default an Animation is played back by using all the available bone tracks. However an animation can be only partially applied by setting a start bone, see \ref AnimationState::SetStartBone "SetStartBone()". Once set, the bone tracks will be applied hierarchically starting from the start bone. For example, to apply an animation only to a bipedal character's upper body, which is typically parented to the spine bone, one could set the spine as the start bone.
+
+
 \page Particles %Particle systems
 
 The ParticleEmitter class derives from BillboardSet to implement a particle system that updates automatically.

+ 18 - 1
Engine/Graphics/AnimatedModel.cpp

@@ -93,6 +93,7 @@ void AnimatedModel::RegisterObject(Context* context)
     ATTRIBUTE(AnimatedModel, VAR_INT, "Ray/Occl. LOD Level", softwareLodLevel_, M_MAX_UNSIGNED, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_VARIANTVECTOR, "Bone Animation Enabled", GetBonesEnabledAttr, SetBonesEnabledAttr, VariantVector, VariantVector(), AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_VARIANTVECTOR, "Animation States", GetAnimationStatesAttr, SetAnimationStatesAttr, VariantVector, VariantVector(), AM_FILE | AM_NOEDIT);
+    REF_ACCESSOR_ATTRIBUTE(AnimatedModel, VAR_BUFFER, "Morphs", GetMorphsAttr, SetMorphsAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_DEFAULT | AM_NOEDIT);
 }
 
 void AnimatedModel::ApplyAttributes()
@@ -703,10 +704,17 @@ void AnimatedModel::SetAnimationStatesAttr(VariantVector value)
             state->SetLayer(value[index++].GetInt());
         }
         else
-            index += 6;
+            index += 5;
     }
 }
 
+void AnimatedModel::SetMorphsAttr(const PODVector<unsigned char>& value)
+{
+    unsigned index = 0;
+    while (index < value.Size())
+        SetMorphWeight(index, (float)value[index] / 255.0f);
+}
+
 ResourceRef AnimatedModel::GetModelAttr() const
 {
     return GetResourceRef(model_, Model::GetTypeStatic());
@@ -738,6 +746,15 @@ VariantVector AnimatedModel::GetAnimationStatesAttr() const
     return ret;
 }
 
+const PODVector<unsigned char>& AnimatedModel::GetMorphsAttr() const
+{
+    attrBuffer_.Clear();
+    for (Vector<ModelMorph>::ConstIterator i = morphs_.Begin(); i != morphs_.End(); ++i)
+        attrBuffer_.WriteUByte((unsigned char)(i->weight_ * 255.0f));
+    
+    return attrBuffer_.GetBuffer();
+}
+
 void AnimatedModel::OnNodeSet(Node* node)
 {
     Drawable::OnNodeSet(node);

+ 6 - 0
Engine/Graphics/AnimatedModel.h

@@ -129,12 +129,16 @@ public:
     void SetBonesEnabledAttr(VariantVector value);
     /// %Set animation states attribute.
     void SetAnimationStatesAttr(VariantVector value);
+    /// %Set morphs attribute.
+    void SetMorphsAttr(const PODVector<unsigned char>& value);
     /// Return model attribute.
     ResourceRef GetModelAttr() const;
     /// Return bones' animation enabled attribute.
     VariantVector GetBonesEnabledAttr() const;
     /// Return animation states attribute.
     VariantVector GetAnimationStatesAttr() const;
+    /// Return morphs attribute.
+    const PODVector<unsigned char>& GetMorphsAttr() const;
     
 protected:
     /// Handle node being assigned.
@@ -186,6 +190,8 @@ private:
     Vector<PODVector<Matrix3x4> > geometrySkinMatrices_;
     /// Subgeometry skinning matrix pointers, if more bones than skinning shader can manage.
     Vector<PODVector<Matrix3x4*> > geometrySkinMatrixPtrs_;
+   /// Attribute buffer.
+    mutable VectorBuffer attrBuffer_;
     /// The frame number animation LOD distance was last calculated on.
     unsigned animationLodFrameNumber_;
     /// Animation LOD bias.