Browse Source

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

Lasse Öörni 14 years ago
parent
commit
a5681746e1
3 changed files with 38 additions and 2 deletions
  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
 \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.
 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.
 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
 \page Particles %Particle systems
 
 
 The ParticleEmitter class derives from BillboardSet to implement a particle system that updates automatically.
 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);
     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, "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);
     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()
 void AnimatedModel::ApplyAttributes()
@@ -703,10 +704,17 @@ void AnimatedModel::SetAnimationStatesAttr(VariantVector value)
             state->SetLayer(value[index++].GetInt());
             state->SetLayer(value[index++].GetInt());
         }
         }
         else
         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
 ResourceRef AnimatedModel::GetModelAttr() const
 {
 {
     return GetResourceRef(model_, Model::GetTypeStatic());
     return GetResourceRef(model_, Model::GetTypeStatic());
@@ -738,6 +746,15 @@ VariantVector AnimatedModel::GetAnimationStatesAttr() const
     return ret;
     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)
 void AnimatedModel::OnNodeSet(Node* node)
 {
 {
     Drawable::OnNodeSet(node);
     Drawable::OnNodeSet(node);

+ 6 - 0
Engine/Graphics/AnimatedModel.h

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