Просмотр исходного кода

Removed the autosyncsource feature from AnimatedModel as it is difficult to ensure that animation LOD updates line up correctly. Manual sync should be used instead.
Added local animation flag for AnimatedModel. When enabled, animation and morph updates will not be sent over network.
Added missing registration of syncAnimation() & syncMorphs() to script.

Lasse Öörni 15 лет назад
Родитель
Сommit
09644088b8

+ 4 - 2
Engine/Engine/RegisterRenderer.cpp

@@ -660,8 +660,10 @@ static void registerAnimatedModel(asIScriptEngine* engine)
     engine->RegisterObjectMethod("AnimatedModel", "void setAnimationLodBias(float)", asMETHOD(AnimatedModel, setAnimationLodBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "void setMorphWeight(uint, float)", asMETHODPR(AnimatedModel, setMorphWeight, (unsigned, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "void setMorphWeight(const string& in, float)", asMETHODPR(AnimatedModel, setMorphWeight, (const std::string&, float), void), asCALL_THISCALL);
-    engine->RegisterObjectMethod("AnimatedModel", "void setAutoSyncSource(AnimatedModel@+)", asMETHOD(AnimatedModel, setAutoSyncSource), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "void resetMorphWeights()", asMETHOD(AnimatedModel, resetMorphWeights), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AnimatedModel", "void syncAnimation(AnimatedModel@+)", asMETHOD(AnimatedModel, syncAnimation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AnimatedModel", "void syncMorphs(AnimatedModel@+)", asMETHOD(AnimatedModel, syncMorphs), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AnimatedModel", "void setLocalAnimation(bool)", asMETHOD(AnimatedModel, setLocalAnimation), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "Skeleton@+ getSkeleton() const", asMETHOD(AnimatedModel, getSkeleton), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "AnimationState@+ getAnimationState(Animation@+) const", asMETHODPR(AnimatedModel, getAnimationState, (Animation*) const, AnimationState*), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "AnimationState@+ getAnimationState(const string& in) const", asMETHODPR(AnimatedModel, getAnimationState, (const std::string&) const, AnimationState*), asCALL_THISCALL);
@@ -669,7 +671,7 @@ static void registerAnimatedModel(asIScriptEngine* engine)
     engine->RegisterObjectMethod("AnimatedModel", "uint getNumMorphs() const", asMETHOD(AnimatedModel, getNumMorphs), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "float getMorphWeight(uint) const", asMETHODPR(AnimatedModel, getMorphWeight, (unsigned) const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimatedModel", "float getMorphWeight(const string& in) const", asMETHODPR(AnimatedModel, getMorphWeight, (const std::string&) const, float), asCALL_THISCALL);
-    engine->RegisterObjectMethod("AnimatedModel", "AnimatedModel@+ getAutoSyncSource() const", asMETHOD(AnimatedModel, getAutoSyncSource), asCALL_THISCALL);
+    engine->RegisterObjectMethod("AnimatedModel", "bool getLocalAnimation() const", asMETHOD(AnimatedModel, getLocalAnimation), asCALL_THISCALL);
     registerRefCasts<Component, AnimatedModel>(engine, "Component", "AnimatedModel");
     registerRefCasts<Node, AnimatedModel>(engine, "Node", "AnimatedModel");
 }

+ 15 - 65
Engine/Renderer/AnimatedModel.cpp

@@ -57,7 +57,8 @@ AnimatedModel::AnimatedModel(Octant* octant, const std::string& name) :
     mAnimationLodTimer(0.0f),
     mAnimationDirty(true),
     mAnimationOrderDirty(true),
-    mMorphsDirty(true)
+    mMorphsDirty(true),
+    mLocalAnimation(false)
 {
 }
 
@@ -91,10 +92,6 @@ void AnimatedModel::save(Serializer& dest)
     dest.writeVLE(mMorphs.size());
     for (unsigned i = 0; i < mMorphs.size(); ++i)
         dest.writeFloat(mMorphs[i].mWeight);
-    
-    // Write autosyncsource reference
-    ComponentRef autoSyncSourceRef(mAutoSyncSource.getPtr());
-    autoSyncSourceRef.write(dest);
 }
 
 void AnimatedModel::load(Deserializer& source, ResourceCache* cache)
@@ -127,9 +124,6 @@ void AnimatedModel::load(Deserializer& source, ResourceCache* cache)
     unsigned numMorphs = source.readVLE();
     for (unsigned i = 0; i < numMorphs; ++i)
         setMorphWeight(i, source.readFloat());
-    
-    // Read autosyncsource reference
-    mAutoSyncSourceRef.read(source);
 }
 
 void AnimatedModel::saveXML(XMLElement& dest)
@@ -164,14 +158,6 @@ void AnimatedModel::saveXML(XMLElement& dest)
         morphElem.setInt("index", i);
         morphElem.setFloat("weight", mMorphs[i].mWeight);
     }
-    
-    // Write autosyncsource reference
-    ComponentRef autoSyncSourceRef(mAutoSyncSource.getPtr(), true);
-    if (autoSyncSourceRef.mEntityID)
-    {
-        XMLElement syncSourceElem = dest.createChildElement("syncsource");
-        autoSyncSourceRef.writeXML(syncSourceElem);
-    }
 }
 
 void AnimatedModel::loadXML(const XMLElement& source, ResourceCache* cache)
@@ -212,22 +198,6 @@ void AnimatedModel::loadXML(const XMLElement& source, ResourceCache* cache)
         setMorphWeight(index, morphElem.getFloat("weight"));
         morphElem = morphElem.getNextElement("morph");
     }
-    
-    // Read autosyncsource reference
-    XMLElement syncSourceElem = source.getChildElement("syncsource", false);
-    if (syncSourceElem.notNull())
-        mAutoSyncSourceRef.readXML(syncSourceElem);
-}
-
-void AnimatedModel::postLoad(ResourceCache* cache)
-{
-    Node::postLoad(cache);
-    
-    if (mAutoSyncSourceRef.mDirty)
-    {
-        mAutoSyncSource = static_cast<AnimatedModel*>(mEntity->getScene()->getComponent(mAutoSyncSourceRef));
-        mAutoSyncSourceRef.mDirty = false;
-    }
 }
 
 bool AnimatedModel::writeNetUpdate(Serializer& dest, Serializer& destRevision, Deserializer& baseRevision, const NetUpdateInfo& info)
@@ -322,11 +292,10 @@ bool AnimatedModel::writeNetUpdate(Serializer& dest, Serializer& destRevision, D
         else
             baseRevision.readUByte();
     }
-    // Autosyncsource
-    ComponentRef autoSyncSourceRef(mAutoSyncSource);
-    checkComponentRef(autoSyncSourceRef, baseRevision, bits, 32);
-    // If autosyncsource exists, do not send animation or morph data
-    if (mAutoSyncSource)
+    
+    // If local animation, do not send even if changed. It is slightly unoptimal to first check, then disable, but it ensures
+    // that the base revision data stays the same (otherwise out of bounds reads might result when toggling local animation)
+    if (mLocalAnimation)
         bits &= ~(8 | 16);
     
     // Update replication state fully, and network stream by delta
@@ -374,7 +343,6 @@ bool AnimatedModel::writeNetUpdate(Serializer& dest, Serializer& destRevision, D
     writeVLEDelta(mMorphs.size(), dest, destRevision, bits & 16);
     for (unsigned i = 0; i < mMorphs.size(); ++i)
         writeUByteDelta((unsigned char)(mMorphs[i].mWeight * 255.0f), dest, destRevision, bits & 16);
-    writeComponentRefDelta(autoSyncSourceRef, dest, destRevision, bits & 32);
     
     return prevBits || (bits != 0);
 }
@@ -454,12 +422,6 @@ void AnimatedModel::readNetUpdate(Deserializer& source, ResourceCache* cache, co
         for (unsigned i = 0; i < numMorphs; ++i)
             setMorphWeight(i, source.readUByte() / 255.0f);
     }
-    readComponentRefDelta(mAutoSyncSourceRef, source, bits & 32);
-}
-
-void AnimatedModel::postNetUpdate(ResourceCache* cache)
-{
-    postLoad(cache);
 }
 
 void AnimatedModel::interpolate(bool snapToEnd)
@@ -472,14 +434,6 @@ void AnimatedModel::interpolate(bool snapToEnd)
         (*i)->interpolate(snapToEnd, t);
 }
 
-void AnimatedModel::getComponentRefs(std::vector<ComponentRef>& dest)
-{
-    if (mParent)
-        dest.push_back(ComponentRef(mParent));
-    if (mAutoSyncSource)
-        dest.push_back(ComponentRef(mAutoSyncSource));
-}
-
 void AnimatedModel::processRayQuery(RayOctreeQuery& query, float initialDistance)
 {
     // If no bones or no bone-level testing, use the GeometryNode test
@@ -600,13 +554,6 @@ void AnimatedModel::updateDistance(const FrameInfo& frame)
 
 void AnimatedModel::updateGeometry(const FrameInfo& frame, Renderer* renderer)
 {
-    // Update animation from sync source if one is defined
-    if (!mAutoSyncSource.isExpired())
-    {
-        syncAnimation(mAutoSyncSource);
-        syncMorphs(mAutoSyncSource);
-    }
-    
     if (mLodLevelsDirty)
         calculateLodLevels();
     
@@ -835,11 +782,6 @@ void AnimatedModel::setMorphWeight(StringHash nameHash, float weight)
     }
 }
 
-void AnimatedModel::setAutoSyncSource(AnimatedModel* source)
-{
-    mAutoSyncSource = source;
-}
-
 void AnimatedModel::resetMorphWeights()
 {
     for (std::vector<ModelMorph>::iterator i = mMorphs.begin(); i != mMorphs.end(); ++i)
@@ -853,7 +795,10 @@ void AnimatedModel::syncAnimation(AnimatedModel* srcNode)
     if (!srcNode)
         return;
     
-    setAnimationLodBias(srcNode->getAnimationLodBias());
+    // Make sure the animation proceeds at the same rate as in the source
+    mAnimationLodBias = srcNode->mAnimationLodBias;
+    mAnimationLodDistance = srcNode->mAnimationLodDistance;
+    mAnimationLodFrameNumber = srcNode->mAnimationLodFrameNumber;
     
     const std::vector<AnimationState*>& srcStates = srcNode->getAnimationStates();
     std::set<Animation*> srcAnimations;
@@ -891,6 +836,11 @@ void AnimatedModel::syncMorphs(AnimatedModel* srcNode)
     }
 }
 
+void AnimatedModel::setLocalAnimation(bool enable)
+{
+    mLocalAnimation = enable;
+}
+
 float AnimatedModel::getMorphWeight(unsigned index) const
 {
     if (index >= mMorphs.size())

+ 8 - 16
Engine/Renderer/AnimatedModel.h

@@ -54,18 +54,12 @@ public:
     virtual void saveXML(XMLElement& dest);
     //! Read component state from an XML element
     virtual void loadXML(const XMLElement& source, ResourceCache* cache);
-    //! Resolve component references after loading
-    virtual void postLoad(ResourceCache* cache);
     //! Write a network update
     virtual bool writeNetUpdate(Serializer& dest, Serializer& destRevision, Deserializer& baseRevision, const NetUpdateInfo& info);
     //! Read a network update
     virtual void readNetUpdate(Deserializer& source, ResourceCache* cache, const NetUpdateInfo& info);
-    //! Resolve component references after a network update
-    virtual void postNetUpdate(ResourceCache* cache);
     //! Perform client-side visual smoothing
     virtual void interpolate(bool snapToEnd);
-    //! Return component references
-    virtual void getComponentRefs(std::vector<ComponentRef>& refs);
     
     //! Process renderer raycast
     virtual void processRayQuery(RayOctreeQuery& query, float initialDistance);
@@ -100,14 +94,14 @@ public:
     void setMorphWeight(const std::string& name, float weight);
     //! Set vertex morph weight by name hash
     void setMorphWeight(StringHash nameHash, float weight);
-    //! Enable automatic animation and morph sync from another animated model
-    void setAutoSyncSource(AnimatedModel* source);
     //! Reset all vertex morphs to zero
     void resetMorphWeights();
-    //! Sync animation manually from another animated model
+    //! Sync animation from another animated model
     void syncAnimation(AnimatedModel* srcNode);
-    //! Sync morphs manually from another animated model
+    //! Sync morphs from another animated model
     void syncMorphs(AnimatedModel* srcNode);
+    //! Set animation & morphs local mode. If enabled, they are not sent over network even if the node is otherwise replicated
+    void setLocalAnimation(bool enable);
     
     //! Return skeleton
     const Skeleton& getSkeleton() const { return mSkeleton; }
@@ -133,8 +127,8 @@ public:
     float getMorphWeight(const std::string& name) const;
     //! Return vertex morph weight by name hash
     float getMorphWeight(StringHash nameHash) const;
-    //! Return automatic animation sync source
-    AnimatedModel* getAutoSyncSource() const { return mAutoSyncSource; }
+    //! Return whether animation is local
+    bool getLocalAnimation() const { return mLocalAnimation; }
     
 protected:
     //! Update world-space bounding box
@@ -185,8 +179,6 @@ private:
     std::vector<std::vector<Matrix4x3> > mGeometrySkinMatrices;
     //! Subgeometry skinning matrix pointers, if more bones than skinning shader can manage
     std::vector<std::vector<Matrix4x3*> > mGeometrySkinMatrixPtrs;
-    //! Automatic animation sync source
-    WeakPtr<AnimatedModel> mAutoSyncSource;
     //! Animation LOD bias
     float mAnimationLodBias;
     //! Animation LOD timer
@@ -197,8 +189,8 @@ private:
     bool mAnimationOrderDirty;
     //! Vertex morphs dirty flag
     bool mMorphsDirty;
-    //! Automatic animation sync source component reference
-    ComponentRef mAutoSyncSourceRef;
+    //! Local animation flag
+    bool mLocalAnimation;
 };
 
 #endif // RENDERER_ANIMATEDMODEL_H