summaryrefslogtreecommitdiff
path: root/Runtime/mecanim/graph
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/mecanim/graph')
-rw-r--r--Runtime/mecanim/graph/binarynode.h291
-rw-r--r--Runtime/mecanim/graph/factory.cpp172
-rw-r--r--Runtime/mecanim/graph/factory.h35
-rw-r--r--Runtime/mecanim/graph/genericnode.h1093
-rw-r--r--Runtime/mecanim/graph/graph.cpp476
-rw-r--r--Runtime/mecanim/graph/graph.h188
-rw-r--r--Runtime/mecanim/graph/node.cpp11
-rw-r--r--Runtime/mecanim/graph/node.h346
-rw-r--r--Runtime/mecanim/graph/plug.h123
-rw-r--r--Runtime/mecanim/graph/plugbinder.cpp180
-rw-r--r--Runtime/mecanim/graph/plugbinder.h85
-rw-r--r--Runtime/mecanim/graph/quaternionnode.h283
-rw-r--r--Runtime/mecanim/graph/unarynode.h112
-rw-r--r--Runtime/mecanim/graph/xformnode.h348
14 files changed, 3743 insertions, 0 deletions
diff --git a/Runtime/mecanim/graph/binarynode.h b/Runtime/mecanim/graph/binarynode.h
new file mode 100644
index 0000000..82ff596
--- /dev/null
+++ b/Runtime/mecanim/graph/binarynode.h
@@ -0,0 +1,291 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/Math/Simd/float4.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+#include "Runtime/mecanim/graph/node.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ template <typename TYPE1, typename TYPE2, typename RESULT, typename BinaryPolicies> class BinaryNode : public Node
+ {
+ public:
+ TypePlug<TYPE1> mA;
+ TypePlug<TYPE2> mB;
+
+ TypePlug<RESULT> mResult;
+
+ BinaryNode()
+ :mA(true, CRCKey(eA) ),
+ mB(true,CRCKey(eB)),
+ mResult(false,CRCKey(eResult))
+ {
+ mA.m_Owner = this;
+ mB.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~BinaryNode(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 3;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1: return mB;
+ case 2:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1: return mB;
+ case 2:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ TYPE1 a;
+ TYPE2 b;
+ RESULT result;
+
+ mA.ReadData(&a, arEvaluationInfo);
+ mB.ReadData(&b, arEvaluationInfo);
+
+ result = BinaryPolicies::template Operation<TYPE1, TYPE2, RESULT>(a, b);
+
+ mResult.WriteData(&result, arEvaluationInfo);
+ }
+ };
+
+ class AdditionOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l+r; }
+ };
+
+ class SubstractionOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l-r; }
+ };
+
+ class MultiplicationOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l*r; }
+ };
+
+ class DivisionOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l/r; }
+ };
+
+ class GreaterThanOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l > r; }
+ };
+ class LesserThanOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l < r; }
+ };
+ class GreaterThanOrEqualOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l >= r; }
+ };
+ class LesserThanOrEqualOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l <= r; }
+ };
+ class AndOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l && r; }
+ };
+ class OrOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return l || r; }
+ };
+ class XorOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return ((!l)&&r)||(l&&(!r)); }
+ };
+
+ class AdditionFloat : public BinaryNode<float, float, float, AdditionOp>
+ {
+ public:
+ static const eNodeType mId = AdditionFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class AdditionUInt : public BinaryNode<uint32_t, uint32_t, uint32_t,AdditionOp>
+ {
+ public:
+ static const eNodeType mId = AdditionUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class AdditionInt : public BinaryNode<int32_t, int32_t, int32_t, AdditionOp>
+ {
+ public:
+ static const eNodeType mId = AdditionIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class AdditionFloat4 : public BinaryNode<math::float4, math::float4, math::float4, AdditionOp>
+ {
+ public:
+ static const eNodeType mId = AdditionFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class SubstractionFloat : public BinaryNode<float, float, float, SubstractionOp>
+ {
+ public:
+ static const eNodeType mId = SubstractionFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class SubstractionUInt : public BinaryNode<uint32_t, uint32_t, uint32_t, SubstractionOp>
+ {
+ public:
+ static const eNodeType mId = SubstractionUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class SubstractionInt : public BinaryNode<int32_t, int32_t, int32_t, SubstractionOp>
+ {
+ public:
+ static const eNodeType mId = SubstractionIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class SubstractionFloat4 : public BinaryNode<math::float4, math::float4, math::float4, SubstractionOp>
+ {
+ public:
+ static const eNodeType mId = SubstractionFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class MultiplicationFloat : public BinaryNode<float, float, float, MultiplicationOp>
+ {
+ public:
+ static const eNodeType mId = MultiplicationFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MultiplicationUInt : public BinaryNode<uint32_t, uint32_t, uint32_t, MultiplicationOp>
+ {
+ public:
+ static const eNodeType mId = MultiplicationUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MultiplicationInt : public BinaryNode<int32_t, int32_t, int32_t, MultiplicationOp>
+ {
+ public:
+ static const eNodeType mId = MultiplicationIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MultiplicationFloat4 : public BinaryNode<math::float4, math::float4, math::float4, MultiplicationOp>
+ {
+ public:
+ static const eNodeType mId = MultiplicationFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class DivisionFloat : public BinaryNode<float, float, float, DivisionOp>
+ {
+ public:
+ static const eNodeType mId = DivisionFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class DivisionUInt : public BinaryNode<uint32_t, uint32_t, uint32_t, DivisionOp>
+ {
+ public:
+ static const eNodeType mId = DivisionUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class DivisionInt : public BinaryNode<int32_t, int32_t, int32_t, DivisionOp>
+ {
+ public:
+ static const eNodeType mId = DivisionIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class DivisionFloat4 : public BinaryNode<math::float4, math::float4, math::float4, DivisionOp>
+ {
+ public:
+ static const eNodeType mId = DivisionFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class GreaterThan : public BinaryNode<float, float, bool, GreaterThanOp>
+ {
+ public:
+ static const eNodeType mId = GreaterThanId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class LesserThan : public BinaryNode<float, float, bool, LesserThanOp>
+ {
+ public:
+ static const eNodeType mId = LesserThanId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class GreaterThanOrEqual : public BinaryNode<float, float, bool, GreaterThanOrEqualOp>
+ {
+ public:
+ static const eNodeType mId = GreaterThanOrEqualId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class LesserThanOrEqual : public BinaryNode<float, float, bool, LesserThanOrEqualOp>
+ {
+ public:
+ static const eNodeType mId = LesserThanOrEqualId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class And : public BinaryNode<bool, bool, bool, AndOp>
+ {
+ public:
+ static const eNodeType mId = AndId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class Or : public BinaryNode<bool, bool, bool, OrOp>
+ {
+ public:
+ static const eNodeType mId = OrId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class Xor : public BinaryNode<bool, bool, bool, XorOp>
+ {
+ public:
+ static const eNodeType mId = XorId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+}
+
+} \ No newline at end of file
diff --git a/Runtime/mecanim/graph/factory.cpp b/Runtime/mecanim/graph/factory.cpp
new file mode 100644
index 0000000..3efe757
--- /dev/null
+++ b/Runtime/mecanim/graph/factory.cpp
@@ -0,0 +1,172 @@
+#include "UnityPrefix.h"
+#include "Runtime/mecanim/graph/factory.h"
+
+#include "Runtime/mecanim/graph/unarynode.h"
+#include "Runtime/mecanim/graph/binarynode.h"
+#include "Runtime/mecanim/graph/genericnode.h"
+#include "Runtime/mecanim/graph/xformnode.h"
+#include "Runtime/mecanim/graph/quaternionnode.h"
+
+#define REGISTERNODE(classnode) \
+ case classnode::mId: \
+ { \
+ node = arAlloc.Construct<classnode>(); \
+ break; \
+ }
+
+namespace mecanim
+{
+
+namespace graph
+{
+ Node* GraphFactory::Create(eNodeType aNodeId, memory::Allocator& arAlloc)const
+ {
+ Node* node = 0;
+ switch(aNodeId)
+ {
+ REGISTERNODE(NegationFloat);
+ REGISTERNODE(NegationInt);
+ REGISTERNODE(NegationFloat4);
+ REGISTERNODE(NegationBool);
+ REGISTERNODE(AdditionFloat);
+ REGISTERNODE(AdditionUInt);
+ REGISTERNODE(AdditionInt);
+ REGISTERNODE(AdditionFloat4);
+ REGISTERNODE(SubstractionFloat);
+ REGISTERNODE(SubstractionUInt);
+ REGISTERNODE(SubstractionInt);
+ REGISTERNODE(SubstractionFloat4);
+ REGISTERNODE(MultiplicationFloat);
+ REGISTERNODE(MultiplicationUInt);
+ REGISTERNODE(MultiplicationInt);
+ REGISTERNODE(MultiplicationFloat4);
+ REGISTERNODE(DivisionFloat);
+ REGISTERNODE(DivisionUInt);
+ REGISTERNODE(DivisionInt);
+ REGISTERNODE(DivisionFloat4);
+ REGISTERNODE(CondFloat);
+ REGISTERNODE(CondUInt);
+ REGISTERNODE(CondInt);
+ REGISTERNODE(CondFloat4);
+ REGISTERNODE(AbsFloat);
+ REGISTERNODE(AbsFloat4);
+ REGISTERNODE(CrossFloat4);
+ REGISTERNODE(DegreesFloat);
+ REGISTERNODE(DegreesFloat4);
+ REGISTERNODE(DotFloat4);
+ REGISTERNODE(LengthFloat4);
+ REGISTERNODE(MaximumFloat);
+ REGISTERNODE(MaximumUInt);
+ REGISTERNODE(MaximumInt);
+ REGISTERNODE(MaximumFloat4);
+ REGISTERNODE(MinimumFloat);
+ REGISTERNODE(MinimumUInt);
+ REGISTERNODE(MinimumInt);
+ REGISTERNODE(MinimumFloat4);
+ REGISTERNODE(NormalizeFloat4);
+ REGISTERNODE(RadiansFloat);
+ REGISTERNODE(RadiansFloat4);
+ REGISTERNODE(FloatToFloat4);
+ REGISTERNODE(Float4ToFloat);
+ REGISTERNODE(GreaterThan);
+ REGISTERNODE(LesserThan);
+ REGISTERNODE(GreaterThanOrEqual);
+ REGISTERNODE(LesserThanOrEqual);
+ REGISTERNODE(SmoothStepFloat);
+ REGISTERNODE(Mux5Float);
+ REGISTERNODE(Mul5Float);
+ REGISTERNODE(Sin);
+ REGISTERNODE(Fmod);
+ REGISTERNODE(And);
+ REGISTERNODE(Or);
+ REGISTERNODE(xformMulInv);
+ REGISTERNODE(xformIdentity);
+ REGISTERNODE(xformMulVec);
+ REGISTERNODE(xformInvMulVec);
+ REGISTERNODE(xformMul);
+ REGISTERNODE(xformInvMul);
+ REGISTERNODE(xformEqual);
+ REGISTERNODE(xformWeight);
+ REGISTERNODE(xformAdd);
+ REGISTERNODE(xformSub);
+ REGISTERNODE(xformBlend);
+ REGISTERNODE(quatIdentity);
+ REGISTERNODE(quatConj);
+ REGISTERNODE(quatMul);
+ REGISTERNODE(quatMulVec);
+ REGISTERNODE(quatLerp);
+ REGISTERNODE(quatArcRotate);
+ REGISTERNODE(quatArcRotateX);
+ REGISTERNODE(quatXcos);
+ REGISTERNODE(quatYcos);
+ REGISTERNODE(quatZcos);
+ REGISTERNODE(quatEulerToQuat);
+ REGISTERNODE(quatQuatToEuler);
+ REGISTERNODE(quatProjOnYPlane);
+ REGISTERNODE(quat2Qtan);
+ REGISTERNODE(qtan2Quat);
+ REGISTERNODE(ZYRoll2Quat);
+ REGISTERNODE(quat2ZYRoll);
+ REGISTERNODE(RollZY2Quat);
+ REGISTERNODE(quat2RollZY);
+ REGISTERNODE(quatWeight);
+ REGISTERNODE(xformCompose);
+ REGISTERNODE(xformDecompose);
+ REGISTERNODE(CondXform);
+ REGISTERNODE(Rand);
+ REGISTERNODE(Damp);
+ REGISTERNODE(xformRefChange);
+ REGISTERNODE(Xor);
+ REGISTERNODE(SmoothPulseFloat);
+ }
+ return node;
+ }
+
+ GraphPlug* GraphFactory::Create(ePlugType aPlugType, memory::Allocator& arAlloc)const
+ {
+ GraphPlug* plug = 0;
+ switch(aPlugType)
+ {
+ case Float4Id:
+ {
+ plug = arAlloc.Construct< TypePlug<math::float4> >();
+ break;
+ }
+ case Float1Id:
+ case FloatId:
+ {
+ plug = arAlloc.Construct< TypePlug<float> >();
+ break;
+ }
+ case UInt32Id:
+ {
+ plug = arAlloc.Construct< TypePlug<uint32_t> >();
+ break;
+ }
+ case Int32Id:
+ {
+ plug = arAlloc.Construct< TypePlug<int32_t> >();
+ break;
+ }
+ case BoolId:
+ {
+ plug = arAlloc.Construct< TypePlug<bool> >();
+ break;
+ }
+ case Bool4Id:
+ {
+ plug = arAlloc.Construct< TypePlug<math::bool4> >();
+ break;
+ }
+ case XformId:
+ {
+ plug = arAlloc.Construct< TypePlug<math::xform> >();
+ break;
+ }
+
+ }
+ return plug;
+ }
+}
+
+}
diff --git a/Runtime/mecanim/graph/factory.h b/Runtime/mecanim/graph/factory.h
new file mode 100644
index 0000000..d76fcbf
--- /dev/null
+++ b/Runtime/mecanim/graph/factory.h
@@ -0,0 +1,35 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+#include "Runtime/mecanim/graph/node.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ // This class can be subclassed if you need to create custom node and want to add them to the list of
+ // instanciable node
+ class GraphFactory
+ {
+ public:
+ virtual Node* Create(eNodeType aNodeId, memory::Allocator& arAlloc)const;
+ virtual GraphPlug* Create(ePlugType aPlugType, memory::Allocator& arAlloc)const;
+ };
+
+ template <typename TYPE> TYPE* Create(GraphFactory const& arFactory, memory::Allocator& arAlloc)
+ {
+ return static_cast<TYPE*>(arFactory.Create(TYPE::mId, arAlloc));
+ }
+}
+
+} \ No newline at end of file
diff --git a/Runtime/mecanim/graph/genericnode.h b/Runtime/mecanim/graph/genericnode.h
new file mode 100644
index 0000000..2bc82e7
--- /dev/null
+++ b/Runtime/mecanim/graph/genericnode.h
@@ -0,0 +1,1093 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include <cstdlib>
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/Math/Simd/math.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+#include "Runtime/mecanim/graph/node.h"
+
+#include "Runtime/mecanim/graph/unarynode.h"
+
+#include "Runtime/mecanim/generic/stringtable.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ template <typename COND, typename TYPE, typename POLICIES> class CondNode : public Node
+ {
+ public:
+ TypePlug<COND> mCondition;
+ TypePlug<TYPE> mA;
+ TypePlug<TYPE> mB;
+
+ TypePlug<TYPE> mResult;
+
+ CondNode()
+ :mCondition(true,CRCKey(eCondition)),
+ mA(true, CRCKey(eA)),
+ mB(true,CRCKey(eB)),
+ mResult(false,CRCKey(eResult))
+ {
+ mCondition.m_Owner = this;
+ mA.m_Owner = this;
+ mB.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~CondNode(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 4;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mCondition;
+ case 1: return mA;
+ case 2: return mB;
+ case 3:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mCondition;
+ case 1: return mA;
+ case 2: return mB;
+ case 3:
+ default: return mResult;
+ }
+ }
+
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ TYPE a, b, result;
+ COND cond;
+
+ mCondition.ReadData(&cond, arEvaluationInfo);
+ mA.ReadData(&a, arEvaluationInfo);
+ mB.ReadData(&b, arEvaluationInfo);
+
+ result = POLICIES::template Operation<COND, TYPE>(cond, a, b);
+
+ mResult.WriteData(&result, arEvaluationInfo);
+ }
+ };
+
+ class CondFloatOp
+ {
+ public:
+ template< typename COND, typename TYPE > static TYPE Operation( COND const& p, TYPE const& l, TYPE const& r){ return math::cond(p, l, r); }
+ };
+ class CondUIntOp
+ {
+ public:
+ template< typename COND, typename TYPE > static TYPE Operation( COND const& p, TYPE const& l, TYPE const& r){ return math::cond(p, l, r); }
+ };
+ class CondIntOp
+ {
+ public:
+ template< typename COND, typename TYPE > static TYPE Operation( COND const& p, TYPE const& l, TYPE const& r){ return math::cond(p, l, r); }
+ };
+ class CondFloat4Op
+ {
+ public:
+ template< typename COND, typename TYPE > static math::float4 Operation( bool const& p, math::float4 const& l, math::float4 const& r){ return math::cond(math::bool1(p), l, r); }
+ };
+ class CondXformOp
+ {
+ public:
+ template< typename COND, typename TYPE > static TYPE Operation( COND const& p, TYPE const& l, TYPE const& r){ return math::cond(p, l, r); }
+ };
+
+ class CondFloat : public CondNode<bool, float, CondFloatOp>
+ {
+ public:
+ static const eNodeType mId = CondFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class CondUInt : public CondNode<bool, uint32_t, CondUIntOp>
+ {
+ public:
+ static const eNodeType mId = CondUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class CondInt : public CondNode<bool, int32_t, CondIntOp>
+ {
+ public:
+ static const eNodeType mId = CondIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class CondFloat4 : public CondNode<bool, math::float4, CondFloat4Op>
+ {
+ public:
+ static const eNodeType mId = CondFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class CondXform : public CondNode<bool, math::xform, CondXformOp>
+ {
+ public:
+ static const eNodeType mId = CondXformId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template< typename TYPE, typename RESULT > class AbsOp
+ {
+ public:
+ static RESULT Operation( TYPE const& l){ return math::abs(l); }
+ };
+
+ class AbsFloat : public UnaryNode<float, float, AbsOp<float, float> >
+ {
+ public:
+ static const eNodeType mId = AbsFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class AbsFloat4 : public UnaryNode<math::float4, math::float4, AbsOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = AbsFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class CrossOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return math::cross(l, r); }
+ };
+
+ class CrossFloat4 : public BinaryNode<math::float4, math::float4, math::float4, CrossOp>
+ {
+ public:
+ static const eNodeType mId = CrossFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template< typename TYPE, typename RESULT > class DegreesOp
+ {
+ public:
+ static RESULT Operation( TYPE const& l){ return math::degrees(l); }
+ };
+
+ class DegreesFloat : public UnaryNode<float, float, DegreesOp<float, float> >
+ {
+ public:
+ static const eNodeType mId = DegreesFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class DegreesFloat4 : public UnaryNode<math::float4, math::float4, DegreesOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = DegreesFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class DotOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return float(math::dot(l, r)); }
+ };
+
+ class DotFloat4 : public BinaryNode<math::float4, math::float4, float, DotOp>
+ {
+ public:
+ static const eNodeType mId = DotFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template< typename TYPE, typename RESULT > class LengthOp
+ {
+ public:
+ static RESULT Operation( TYPE const& l){ return float(math::length(l)); }
+ };
+
+ class LengthFloat4 : public UnaryNode<math::float4, float, LengthOp<math::float4, float> >
+ {
+ public:
+ static const eNodeType mId = LengthFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class MaximumOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return math::maximum(l, r); }
+ };
+
+ class MaximumFloat : public BinaryNode<float, float, float, MaximumOp>
+ {
+ public:
+ static const eNodeType mId = MaximumFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MaximumUInt : public BinaryNode<uint32_t, uint32_t, uint32_t, MaximumOp>
+ {
+ public:
+ static const eNodeType mId = MaximumUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MaximumInt : public BinaryNode<int32_t, int32_t, int32_t, MaximumOp>
+ {
+ public:
+ static const eNodeType mId = MaximumIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MaximumFloat4 : public BinaryNode<math::float4, math::float4, math::float4, MaximumOp>
+ {
+ public:
+ static const eNodeType mId = MaximumFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class MinimumOp
+ {
+ public:
+ template< typename TYPE1, typename TYPE2, typename RESULT > static RESULT Operation( TYPE1 const& l, TYPE2 const& r){ return math::minimum(l, r); }
+ };
+
+ class MinimumFloat : public BinaryNode<float, float, float, MinimumOp>
+ {
+ public:
+ static const eNodeType mId = MinimumFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MinimumUInt : public BinaryNode<uint32_t, uint32_t, uint32_t, MinimumOp>
+ {
+ public:
+ static const eNodeType mId = MinimumUIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MinimumInt : public BinaryNode<int32_t, int32_t, int32_t, MinimumOp>
+ {
+ public:
+ static const eNodeType mId = MinimumIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class MinimumFloat4 : public BinaryNode<math::float4, math::float4, math::float4, MinimumOp>
+ {
+ public:
+ static const eNodeType mId = MinimumFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template< typename TYPE, typename RESULT > class NormalizeOp
+ {
+ public:
+ static RESULT Operation( TYPE const& l){ return math::normalize(l); }
+ };
+
+ class NormalizeFloat4 : public UnaryNode<math::float4, math::float4, NormalizeOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = NormalizeFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template< typename TYPE, typename RESULT > class RadiansOp
+ {
+ public:
+ static RESULT Operation( TYPE const& l){ return math::radians(l); }
+ };
+
+ class RadiansFloat : public UnaryNode<float, float, RadiansOp<float, float> >
+ {
+ public:
+ static const eNodeType mId = RadiansFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class RadiansFloat4 : public UnaryNode<math::float4, math::float4, RadiansOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = RadiansFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class Float4ToFloat : public Node
+ {
+ public:
+ static const eNodeType mId = Float4ToFloatId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<math::float4> mA;
+ TypePlug<float> mX;
+ TypePlug<float> mY;
+ TypePlug<float> mZ;
+ TypePlug<float> mW;
+
+ Float4ToFloat()
+ :mA(true, CRCKey(eA)),
+ mX(false, CRCKey(eX)),
+ mY(false, CRCKey(eY)),
+ mZ(false, CRCKey(eZ)),
+ mW(false, CRCKey(eW))
+ {
+ mA.m_Owner = this;
+ mX.m_Owner = this;
+ mY.m_Owner = this;
+ mZ.m_Owner = this;
+ mW.m_Owner = this;
+ }
+
+ virtual ~Float4ToFloat(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 5;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1: return mX;
+ case 2: return mY;
+ case 3: return mZ;
+ case 4:
+ default: return mW;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1: return mX;
+ case 2: return mY;
+ case 3: return mZ;
+ case 4:
+ default: return mW;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ math::float4 a;
+
+ mA.ReadData(&a, arEvaluationInfo);
+
+ float ATTRIBUTE_ALIGN(ALIGN4F) b[4];
+
+ math::store(a, b);
+
+ mX.WriteData(&b[0], arEvaluationInfo);
+ mY.WriteData(&b[1], arEvaluationInfo);
+ mZ.WriteData(&b[2], arEvaluationInfo);
+ mW.WriteData(&b[3], arEvaluationInfo);
+ }
+ };
+
+ class FloatToFloat4 : public Node
+ {
+ public:
+ static const eNodeType mId = FloatToFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mX;
+ TypePlug<float> mY;
+ TypePlug<float> mZ;
+ TypePlug<float> mW;
+
+ TypePlug<math::float4> mResult;
+
+
+ FloatToFloat4()
+ :mX(true,CRCKey(eX)),
+ mY(true,CRCKey(eY)),
+ mZ(true,CRCKey(eZ)),
+ mW(true,CRCKey(eW)),
+ mResult(false,CRCKey(eResult))
+ {
+ mX.m_Owner = this;
+ mY.m_Owner = this;
+ mZ.m_Owner = this;
+ mW.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~FloatToFloat4(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 5;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mResult;
+ case 1: return mX;
+ case 2: return mY;
+ case 3: return mZ;
+ case 4:
+ default: return mW;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mResult;
+ case 1: return mX;
+ case 2: return mY;
+ case 3: return mZ;
+ case 4:
+ default: return mW;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float ATTRIBUTE_ALIGN(ALIGN4F) a[4];
+
+ mX.ReadData(&a[0], arEvaluationInfo);
+ mY.ReadData(&a[1], arEvaluationInfo);
+ mZ.ReadData(&a[2], arEvaluationInfo);
+ mW.ReadData(&a[3], arEvaluationInfo);
+
+ math::float4 b = math::load(a);
+ mResult.WriteData(&b, arEvaluationInfo);
+ }
+ };
+
+
+ class SmoothStepFloat : public Node
+ {
+ public:
+ static const eNodeType mId = SmoothstepFloatId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mMin;
+ TypePlug<float> mMax;
+ TypePlug<float> mValue;
+ TypePlug<float> mResult;
+
+ SmoothStepFloat()
+ :mMin(true, CRCKey(eMin)),
+ mMax(true,CRCKey(eMax)),
+ mValue(true,CRCKey(eValue)),
+ mResult(false,CRCKey(eResult))
+ {
+ mMin.m_Owner = this;
+ mMax.m_Owner = this;
+ mValue.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~SmoothStepFloat(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 4;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mMin;
+ case 1: return mMax;
+ case 2: return mValue;
+ case 3:
+ default: return mResult;
+
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mMin;
+ case 1: return mMax;
+ case 2: return mValue;
+ case 3:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float min, max, value;
+
+ mMin.ReadData(&min, arEvaluationInfo);
+ mMax.ReadData(&max, arEvaluationInfo);
+ mValue.ReadData(&value, arEvaluationInfo);
+
+ float ret = math::smoothstep( min, max, value);
+
+ mResult.WriteData(&ret, arEvaluationInfo);
+ }
+ };
+
+ class SmoothPulseFloat : public Node
+ {
+ public:
+ static const eNodeType mId = SmoothPulseFloatId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mMinMin;
+ TypePlug<float> mMinMax;
+ TypePlug<float> mMaxMin;
+ TypePlug<float> mMaxMax;
+ TypePlug<float> mValue;
+ TypePlug<float> mResult;
+
+ SmoothPulseFloat():
+ mMinMin(true, CRCKey(eMinMin)),
+ mMinMax(true, CRCKey(eMinMax)),
+ mMaxMin(true, CRCKey(eMaxMin)),
+ mMaxMax(true, CRCKey(eMaxMax)),
+ mValue(true, CRCKey(eValue)),
+ mResult(false, CRCKey(eResult))
+ {
+ mMinMin.m_Owner = this;
+ mMinMax.m_Owner = this;
+ mMaxMin.m_Owner = this;
+ mMaxMax.m_Owner = this;
+ mValue.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~SmoothPulseFloat(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 6;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mMinMin;
+ case 1: return mMinMax;
+ case 2: return mMaxMin;
+ case 3: return mMaxMax;
+ case 4: return mValue;
+ case 5:
+ default: return mResult;
+
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mMinMin;
+ case 1: return mMinMax;
+ case 2: return mMaxMin;
+ case 3: return mMaxMax;
+ case 4: return mValue;
+ case 5:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float minmin, minmax, maxmin, maxmax, value;
+
+ mMinMin.ReadData(&minmin, arEvaluationInfo);
+ mMinMax.ReadData(&minmax, arEvaluationInfo);
+ mMaxMin.ReadData(&maxmin, arEvaluationInfo);
+ mMaxMax.ReadData(&maxmax, arEvaluationInfo);
+ mValue.ReadData(&value, arEvaluationInfo);
+
+ float ret = math::smoothpulse( minmin, minmax, maxmin, maxmax, value);
+
+ mResult.WriteData(&ret, arEvaluationInfo);
+ }
+ };
+
+ class Mux5Float : public Node
+ {
+ public:
+ static const eNodeType mId = Mux5FloatId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mIn;
+ TypePlug<float> mRangeA;
+ TypePlug<float> mRangeB;
+ TypePlug<float> mRangeC;
+ TypePlug<float> mRangeD;
+ TypePlug<float> mRangeE;
+ TypePlug<float> mWeightA;
+ TypePlug<float> mWeightB;
+ TypePlug<float> mWeightC;
+ TypePlug<float> mWeightD;
+ TypePlug<float> mWeightE;
+
+ Mux5Float() : mIn(true,CRCKey(eIn)),
+ mRangeA(true,CRCKey(eRangeA)),
+ mRangeB(true,CRCKey(eRangeB)),
+ mRangeC(true,CRCKey(eRangeC)),
+ mRangeD(true,CRCKey(eRangeD)),
+ mRangeE(true,CRCKey(eRangeE)),
+ mWeightA(false,CRCKey(eWeightA)),
+ mWeightB(false,CRCKey(eWeightB)),
+ mWeightC(false,CRCKey(eWeightC)),
+ mWeightD(false,CRCKey(eWeightD)),
+ mWeightE(false,CRCKey(eWeightE))
+ {
+ mIn.m_Owner = this;
+ mRangeA.m_Owner = this;
+ mRangeB.m_Owner = this;
+ mRangeC.m_Owner = this;
+ mRangeD.m_Owner = this;
+ mRangeE.m_Owner = this;
+ mWeightA.m_Owner = this;
+ mWeightB.m_Owner = this;
+ mWeightC.m_Owner = this;
+ mWeightD.m_Owner = this;
+ mWeightE.m_Owner = this;
+ }
+
+ virtual ~Mux5Float(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 11;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mIn;
+ case 1: return mRangeA;
+ case 2: return mRangeB;
+ case 3: return mRangeC;
+ case 4: return mRangeD;
+ case 5: return mRangeE;
+ case 6: return mWeightA;
+ case 7: return mWeightB;
+ case 8: return mWeightC;
+ case 9: return mWeightD;
+ case 10:
+ default: return mWeightE;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mIn;
+ case 1: return mRangeA;
+ case 2: return mRangeB;
+ case 3: return mRangeC;
+ case 4: return mRangeD;
+ case 5: return mRangeE;
+ case 6: return mWeightA;
+ case 7: return mWeightB;
+ case 8: return mWeightC;
+ case 9: return mWeightD;
+ case 10:
+ default: return mWeightE;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float in;
+ float r[5];
+ float w[5];
+
+ mIn.ReadData(&in,arEvaluationInfo);
+ mRangeA.ReadData(&r[0],arEvaluationInfo);
+ mRangeB.ReadData(&r[1],arEvaluationInfo);
+ mRangeC.ReadData(&r[2],arEvaluationInfo);
+ mRangeD.ReadData(&r[3],arEvaluationInfo);
+ mRangeE.ReadData(&r[4],arEvaluationInfo);
+
+ w[0] = 1.0f;
+ w[1] = 0.0f;
+ w[2] = 0.0f;
+ w[3] = 0.0f;
+ w[4] = 0.0f;
+
+ if(in > r[0])
+ {
+ w[0] = 0.f;
+ for(uint32_t i = 0; i < 4; i++)
+ {
+ float d = r[i+1] - r[i];
+
+ if(d > 0.0f)
+ {
+ if(in >= r[i] && in <= r[i+1])
+ {
+ w[i] = (d-(in-r[i]))/(r[i+1]-r[i]);
+ w[i+1] = 1.f-w[i];
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ mWeightA.WriteData(&w[0],arEvaluationInfo);
+ mWeightB.WriteData(&w[1],arEvaluationInfo);
+ mWeightC.WriteData(&w[2],arEvaluationInfo);
+ mWeightD.WriteData(&w[3],arEvaluationInfo);
+ mWeightE.WriteData(&w[4],arEvaluationInfo);
+ }
+ };
+
+ class Mul5Float : public Node
+ {
+ public:
+ static const eNodeType mId = Mul5FloatId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mIn;
+ TypePlug<float> mA;
+ TypePlug<float> mB;
+ TypePlug<float> mC;
+ TypePlug<float> mD;
+ TypePlug<float> mE;
+ TypePlug<float> mOutA;
+ TypePlug<float> mOutB;
+ TypePlug<float> mOutC;
+ TypePlug<float> mOutD;
+ TypePlug<float> mOutE;
+
+ Mul5Float() : mIn(true,CRCKey(eIn)),
+ mA(true,CRCKey(eA)),
+ mB(true,CRCKey(eB)),
+ mC(true,CRCKey(eC)),
+ mD(true,CRCKey(eD)),
+ mE(true,CRCKey(eE)),
+ mOutA(false,CRCKey(eOutA)),
+ mOutB(false,CRCKey(eOutB)),
+ mOutC(false,CRCKey(eOutC)),
+ mOutD(false,CRCKey(eOutD)),
+ mOutE(false,CRCKey(eOutE))
+ {
+ mIn.m_Owner = this;
+ mOutA.m_Owner = this;
+ mOutB.m_Owner = this;
+ mOutC.m_Owner = this;
+ mD.m_Owner = this;
+ mE.m_Owner = this;
+ mOutA.m_Owner = this;
+ mOutB.m_Owner = this;
+ mOutC.m_Owner = this;
+ mOutD.m_Owner = this;
+ mOutE.m_Owner = this;
+ }
+
+ virtual ~Mul5Float(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 11;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mIn;
+ case 1: return mA;
+ case 2: return mB;
+ case 3: return mC;
+ case 4: return mD;
+ case 5: return mE;
+ case 6: return mOutA;
+ case 7: return mOutB;
+ case 8: return mOutC;
+ case 9: return mOutD;
+ case 10:
+ default: return mOutE;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mIn;
+ case 1: return mA;
+ case 2: return mB;
+ case 3: return mC;
+ case 4: return mD;
+ case 5: return mE;
+ case 6: return mOutA;
+ case 7: return mOutB;
+ case 8: return mOutC;
+ case 9: return mOutD;
+ case 10:
+ default: return mOutE;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float in;
+ float i[5];
+ float o[5];
+
+ mIn.ReadData(&in,arEvaluationInfo);
+ mA.ReadData(&i[0],arEvaluationInfo);
+ mB.ReadData(&i[1],arEvaluationInfo);
+ mC.ReadData(&i[2],arEvaluationInfo);
+ mD.ReadData(&i[3],arEvaluationInfo);
+ mE.ReadData(&i[4],arEvaluationInfo);
+
+ for(uint32_t iter = 0; iter < 5; iter++)
+ {
+ o[iter] = i[iter] * in;
+ }
+
+ mOutA.WriteData(&o[0],arEvaluationInfo);
+ mOutB.WriteData(&o[1],arEvaluationInfo);
+ mOutC.WriteData(&o[2],arEvaluationInfo);
+ mOutD.WriteData(&o[3],arEvaluationInfo);
+ mOutE.WriteData(&o[4],arEvaluationInfo);
+ }
+ };
+
+ class Fmod : public Node
+ {
+ public:
+ static const eNodeType mId = FmodId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mNum;
+ TypePlug<float> mDen;
+ TypePlug<float> mRem;
+
+ Fmod() : mNum(true,CRCKey(eNum)), mDen(true,CRCKey(eDen)), mRem(false, CRCKey(eRem))
+ {
+ mNum.m_Owner = this;
+ mDen.m_Owner = this;
+ mRem.m_Owner = this;
+ }
+
+ virtual ~Fmod(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 3;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mNum;
+ case 1: return mDen;
+ case 2:
+ default: return mRem;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mNum;
+ case 1: return mDen;
+ case 2:
+ default: return mRem;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float n,d,r;
+
+ mNum.ReadData(&n, arEvaluationInfo);
+ mDen.ReadData(&d, arEvaluationInfo);
+
+ r = math::fmod(n,d);
+
+ mRem.WriteData(&r,arEvaluationInfo);
+ }
+ };
+
+ class Sin : public Node
+ {
+ public:
+ static const eNodeType mId = SinId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mIn;
+ TypePlug<float> mOut;
+
+ Sin() : mIn(true,CRCKey(eIn)), mOut(false,CRCKey(eOut))
+ {
+ mIn.m_Owner = this;
+ mOut.m_Owner = this;
+ }
+
+ virtual ~Sin(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 2;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mIn;
+ case 1:
+ default: return mOut;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mIn;
+ case 1:
+ default: return mOut;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float i,o;
+
+ mIn.ReadData(&i, arEvaluationInfo);
+
+ o = math::sin(i);
+
+ mOut.WriteData(&o,arEvaluationInfo);
+ }
+ };
+
+ class Rand : public Node
+ {
+ public:
+ static const eNodeType mId = RandId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mResult;
+
+ Rand() : mResult(false,CRCKey(eResult))
+ {
+ mResult.m_Owner = this;
+ }
+
+ virtual ~Rand(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 1;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float intpart = static_cast<float>(std::rand());
+ float fractpart = (std::rand() % 100) / 100.f;
+
+ float result = intpart+fractpart;
+
+ mResult.WriteData(&result,arEvaluationInfo);
+ }
+ };
+
+ class Damp : public Node
+ {
+ public:
+ static const eNodeType mId = DampId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<float> mDampTime;
+ TypePlug<float> mValue;
+ TypePlug<float> mDeltaTime;
+ TypePlug<float> mPreviousValue;
+ TypePlug<float> mResult;
+
+ Damp()
+ :mDampTime(true,CRCKey(eDampTime)),
+ mValue(true,CRCKey(eValue)),
+ mDeltaTime(true,CRCKey(eDeltaTime)),
+ mPreviousValue(true,CRCKey(ePreviousValue)),
+ mResult(false,CRCKey(eResult))
+ {
+ mDampTime.m_Owner = this;
+ mValue.m_Owner = this;
+ mDeltaTime.m_Owner = this;
+ mPreviousValue.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~Damp(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 5;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mDampTime;
+ case 1: return mValue;
+ case 2: return mDeltaTime;
+ case 3: return mPreviousValue;
+ case 4:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mDampTime;
+ case 1: return mValue;
+ case 2: return mDeltaTime;
+ case 3: return mPreviousValue;
+ case 4:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ float dampTime,value,deltaTime,previousValue, result;
+
+ mDampTime.ReadData(&dampTime, arEvaluationInfo);
+ mValue.ReadData(&value, arEvaluationInfo);
+ mDeltaTime.ReadData(&deltaTime, arEvaluationInfo);
+ mPreviousValue.ReadData(&previousValue, arEvaluationInfo);
+
+ result = math::cond(dampTime > 0, previousValue + (value - previousValue) * deltaTime / (dampTime + deltaTime), value);
+
+ mResult.WriteData(&result,arEvaluationInfo);
+ }
+ };
+
+}
+
+}
diff --git a/Runtime/mecanim/graph/graph.cpp b/Runtime/mecanim/graph/graph.cpp
new file mode 100644
index 0000000..4edbec7
--- /dev/null
+++ b/Runtime/mecanim/graph/graph.cpp
@@ -0,0 +1,476 @@
+#include "UnityPrefix.h"
+#include "Runtime/Math/Simd/math.h"
+#include "Runtime/mecanim/graph/graph.h"
+#include "Runtime/mecanim/graph/factory.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ static void AssignPlugId(EvaluationGraph* apGraph)
+ {
+ // Assigning id to each graph plug
+ uint32_t i, id = 0;
+ for(i=0;i<apGraph->m_NodeCount;i++)
+ {
+ Node* node = apGraph->m_NodeArray[i];
+
+ apGraph->m_Graph.m_Vertices[i].m_Id = node->NodeType();
+ apGraph->m_Graph.m_Vertices[i].m_Binding = node->mID;
+ uint32_t j;
+ for(j=0;j<node->GetPlugCount();j++)
+ {
+ node->GetPlug(j).m_PlugId = id++;
+ }
+ }
+
+ for(i=0;i<apGraph->m_Input->GetPlugCount();i++)
+ {
+ apGraph->m_Input->GetPlug(i).m_PlugId = id++;
+ }
+
+ for(i=0;i<apGraph->m_Output->GetPlugCount();i++)
+ {
+ apGraph->m_Output->GetPlug(i).m_PlugId = id++;
+ }
+ }
+
+ static void AssignPlugOffset(EvaluationGraph* apGraph, memory::Allocator& arAlloc)
+ {
+ // assigning value offset for each plug
+ uint32_t i, offset = 0;
+ for(i=0;i<apGraph->m_NodeCount;i++)
+ {
+ Node* node = apGraph->m_NodeArray[i];
+ uint32_t j;
+ for(j=0;j<node->GetPlugCount();j++)
+ {
+ GraphPlug& plug = node->GetPlug(j);
+ offset = plug.m_Offset = arAlloc.AlignAddress(offset, plug.ValueAlign());
+ offset += plug.ValueSize();
+ }
+ }
+
+ for(i=0;i<apGraph->m_Input->GetPlugCount();i++)
+ {
+ GraphPlug& plug = apGraph->m_Input->GetPlug(i);
+ offset = plug.m_Offset = arAlloc.AlignAddress(offset, plug.ValueAlign());
+ offset += plug.ValueSize();
+ }
+
+ for(i=0;i<apGraph->m_Output->GetPlugCount();i++)
+ {
+ GraphPlug& plug = apGraph->m_Output->GetPlug(i);
+ offset = plug.m_Offset = arAlloc.AlignAddress(offset, plug.ValueAlign());
+ offset += plug.ValueSize();
+ }
+ }
+
+ static void ConnectEdges(EvaluationGraph* apGraph)
+ {
+ uint32_t i, edgesIt = 0;
+ for(i=0;i<apGraph->m_NodeCount;i++)
+ {
+ Node* node = apGraph->m_NodeArray[i];
+ uint32_t j;
+ for(j=0;j<node->GetPlugCount();j++)
+ {
+ GraphPlug* plug = node->GetPlug(j).GetSource();
+ if(plug)
+ {
+ apGraph->m_Graph.m_Edges[edgesIt].m_SourceId = plug->m_PlugId;
+ apGraph->m_Graph.m_Edges[edgesIt].m_DestinationId = node->GetPlug(j).m_PlugId;
+ edgesIt++;
+ }
+ }
+ }
+
+ for(i=0;i<apGraph->m_Output->GetPlugCount();i++)
+ {
+ GraphPlug* plug = apGraph->m_Output->mPlugArray[i]->GetSource();
+ if(plug)
+ {
+ apGraph->m_Graph.m_Edges[edgesIt].m_SourceId = plug->m_PlugId;
+ apGraph->m_Graph.m_Edges[edgesIt].m_DestinationId = apGraph->m_Output->mPlugArray[i]->m_PlugId;
+ edgesIt++;
+ }
+ }
+ }
+
+ static EvaluationGraph* CreateGraph(Node** apNodeArray, uint32_t aNodeCount,
+ GraphPlug** apInputPlugArray, uint32_t aInputPlugCount,
+ GraphPlug** apOutputPlugArray, uint32_t aOutputPlugCount,
+ uint32_t aConnectionCount,
+ Constant** apConstantArray, uint32_t aConstantCount,
+ memory::Allocator& arAlloc)
+ {
+ EvaluationGraph* cst = arAlloc.Construct<EvaluationGraph>();
+
+ cst->m_NodeCount = aNodeCount;
+ cst->m_NodeArray = arAlloc.ConstructArray<Node*>(aNodeCount);
+
+ cst->m_Graph.m_VerticesCount = aNodeCount;
+ cst->m_Graph.m_Vertices = arAlloc.ConstructArray<Vertex>(aNodeCount);
+
+ cst->m_Graph.m_EdgesCount = aConnectionCount;
+ cst->m_Graph.m_Edges = arAlloc.ConstructArray<Edge>(aConnectionCount);
+
+ cst->m_Graph.m_InEdgesCount = aInputPlugCount;
+ cst->m_Graph.m_InEdges = arAlloc.ConstructArray<ExternalEdge>(aInputPlugCount);
+
+ cst->m_Graph.m_OutEdgesCount = aOutputPlugCount;
+ cst->m_Graph.m_OutEdges = arAlloc.ConstructArray<ExternalEdge>(aOutputPlugCount);
+
+ cst->m_Graph.m_ConstantCount = aConstantCount;
+ cst->m_Graph.m_ConstantEdges = arAlloc.ConstructArray<ConstantEdge>(cst->m_Graph.m_ConstantCount);
+
+ cst->m_Input = arAlloc.Construct<GraphInput>();
+
+ cst->m_Input->mPlugArray = arAlloc.ConstructArray<GraphPlug*>(aInputPlugCount);
+
+ cst->m_Output = arAlloc.Construct<GraphOutput>();
+
+ cst->m_Output->mPlugArray = arAlloc.ConstructArray<GraphPlug*>(aOutputPlugCount);
+
+ cst->m_ConstantCount = aConstantCount;
+ cst->m_ConstantArray = arAlloc.ConstructArray<Constant*>(aConstantCount);
+
+ memcpy(&cst->m_NodeArray[0], &apNodeArray[0], sizeof(Node*)*aNodeCount);
+
+ memcpy(&cst->m_ConstantArray[0], &apConstantArray[0], sizeof(Constant*)*aConstantCount);
+
+ cst->m_Input->mPlugCount = aInputPlugCount;
+ memcpy(&cst->m_Input->mPlugArray[0], &apInputPlugArray[0], sizeof(GraphPlug*)*aInputPlugCount);
+ uint32_t i;
+ for(i=0;i<aInputPlugCount;i++)
+ {
+ cst->m_Input->mPlugArray[i]->m_Owner = cst->m_Input;
+ cst->m_Graph.m_InEdges[i].m_Id = GetPlugType(*apInputPlugArray[i]);
+ cst->m_Graph.m_InEdges[i].m_Binding = apInputPlugArray[i]->m_ID;
+ }
+
+ cst->m_Output->mPlugCount = aOutputPlugCount;
+ memcpy(&cst->m_Output->mPlugArray[0], &apOutputPlugArray[0], sizeof(GraphPlug*)*aOutputPlugCount);
+ for(i=0;i<aOutputPlugCount;i++)
+ {
+ cst->m_Output->mPlugArray[i]->m_Owner = cst->m_Output;
+ cst->m_Graph.m_OutEdges[i].m_Id = GetPlugType(*apOutputPlugArray[i]);
+ cst->m_Graph.m_OutEdges[i].m_Binding = apOutputPlugArray[i]->m_ID;
+ }
+
+ AssignPlugId(cst);
+ AssignPlugOffset(cst, arAlloc);
+
+ for(i=0;i<aConstantCount;i++)
+ {
+ // copy the largest data element
+ cst->m_Graph.m_ConstantEdges[i].m_FloatValue = cst->m_ConstantArray[i]->m_FloatValue;
+ cst->m_Graph.m_ConstantEdges[i].m_VectorValue = cst->m_ConstantArray[i]->m_VectorValue;
+ if(cst->m_ConstantArray[i]->m_Plug)
+ {
+ cst->m_Graph.m_ConstantEdges[i].m_Id = cst->m_ConstantArray[i]->m_Plug->m_PlugId;
+ }
+ }
+
+ return cst;
+ }
+
+ EvaluationGraph* CreateEvaluationGraph(Node** apNodeArray, uint32_t aNodeCount,
+ GraphPlug** apInputPlugArray, uint32_t aInputPlugCount,
+ GraphPlug** apOutputPlugArray, uint32_t aOutputPlugCount,
+ Constant** apConstantArray, uint32_t aConstantCount,
+ memory::Allocator& arAlloc)
+ {
+ uint32_t connectionCount = 0;
+ uint32_t i;
+ for(i=0;i<aNodeCount;i++)
+ {
+ Node* node = apNodeArray[i];
+ uint32_t j;
+ for(j=0;j<node->GetPlugCount();j++)
+ {
+ GraphPlug* plug = node->GetPlug(j).GetSource();
+ if(plug)
+ {
+ connectionCount++;
+ }
+ }
+ }
+
+ for(i=0;i<aOutputPlugCount;i++)
+ {
+ GraphPlug* plug = apOutputPlugArray[i]->GetSource();
+ if(plug)
+ {
+ connectionCount++;
+ }
+ }
+
+ EvaluationGraph* cst = CreateGraph(apNodeArray, aNodeCount, apInputPlugArray, aInputPlugCount, apOutputPlugArray, aOutputPlugCount, connectionCount, apConstantArray, aConstantCount, arAlloc);
+
+ ConnectEdges(cst);
+
+ return cst;
+ }
+
+ static void Connect(Edge const& arEdges, EvaluationGraph& arGraph)
+ {
+ GraphPlug *source = 0, *destination = 0;
+
+ uint32_t i, j;
+ for(i=0;i < arGraph.m_NodeCount && (source == 0 || destination == 0);i++)
+ {
+ Node* node = arGraph.m_NodeArray[i];
+ for(j=0;j<node->GetPlugCount() && (source == 0 || destination == 0);j++)
+ {
+ if(node->GetPlug(j).m_PlugId == arEdges.m_SourceId)
+ source = &node->GetPlug(j);
+ if(node->GetPlug(j).m_PlugId == arEdges.m_DestinationId)
+ destination = &node->GetPlug(j);
+ }
+ }
+
+ for(j=0;j<arGraph.m_Input->GetPlugCount() && (source == 0 || destination == 0);j++)
+ {
+ if(arGraph.m_Input->GetPlug(j).m_PlugId == arEdges.m_SourceId)
+ source = &arGraph.m_Input->GetPlug(j);
+ if(arGraph.m_Input->GetPlug(j).m_PlugId == arEdges.m_DestinationId)
+ destination = &arGraph.m_Input->GetPlug(j);
+ }
+
+
+ for(j=0;j<arGraph.m_Output->GetPlugCount() && (source == 0 || destination == 0);j++)
+ {
+ if(arGraph.m_Output->GetPlug(j).m_PlugId == arEdges.m_SourceId)
+ source = &arGraph.m_Output->GetPlug(j);
+ if(arGraph.m_Output->GetPlug(j).m_PlugId == arEdges.m_DestinationId)
+ destination = &arGraph.m_Output->GetPlug(j);
+ }
+
+ if(source && destination)
+ {
+ destination->m_Source = source;
+ }
+ }
+
+ static void Connect(ConstantEdge const& arConstantEdge, Constant& arConstant, EvaluationGraph& arGraph)
+ {
+ GraphPlug *plug = 0;
+
+ uint32_t i, j;
+ for(i=0;i < arGraph.m_NodeCount && plug == 0; i++)
+ {
+ Node* node = arGraph.m_NodeArray[i];
+ for(j=0;j<node->GetPlugCount() && plug == 0; j++)
+ {
+ if(node->GetPlug(j).m_PlugId == arConstantEdge.m_Id)
+ plug = &node->GetPlug(j);
+ }
+ }
+
+ for(j=0;j<arGraph.m_Input->GetPlugCount() && plug == 0; j++)
+ {
+ if(arGraph.m_Input->GetPlug(j).m_PlugId == arConstantEdge.m_Id)
+ plug = &arGraph.m_Input->GetPlug(j);
+ }
+
+
+ for(j=0;j<arGraph.m_Output->GetPlugCount() && plug == 0; j++)
+ {
+ if(arGraph.m_Output->GetPlug(j).m_PlugId == arConstantEdge.m_Id)
+ plug = &arGraph.m_Output->GetPlug(j);
+ }
+
+ if(plug)
+ {
+ arConstant.m_Plug = plug;
+ }
+ }
+
+ EvaluationGraph* CreateEvaluationGraph(Graph* apGraph, GraphFactory const& arFactory, memory::Allocator& arAlloc)
+ {
+ EvaluationGraph* cst = 0;
+ uint32_t i;
+ Node** nodes = arAlloc.ConstructArray<Node*>(apGraph->m_VerticesCount);
+ GraphPlug** inputPlug = arAlloc.ConstructArray<GraphPlug*>(apGraph->m_InEdgesCount);
+ GraphPlug** outputPlug = arAlloc.ConstructArray<GraphPlug*>(apGraph->m_OutEdgesCount);
+ Constant** constants = arAlloc.ConstructArray<Constant*>(apGraph->m_ConstantCount);
+
+ for(i=0;i<apGraph->m_VerticesCount;i++)
+ {
+ nodes[i] = arFactory.Create(static_cast<eNodeType>(apGraph->m_Vertices[i].m_Id), arAlloc);
+ nodes[i]->mID = apGraph->m_Vertices[i].m_Binding;
+ }
+
+ for(i=0;i<apGraph->m_InEdgesCount;i++)
+ {
+ inputPlug[i] = arFactory.Create(static_cast<ePlugType>(apGraph->m_InEdges[i].m_Id), arAlloc);
+ inputPlug[i]->m_ID = apGraph->m_InEdges[i].m_Binding;
+ inputPlug[i]->m_Input = false;
+ }
+
+ for(i=0;i<apGraph->m_OutEdgesCount;i++)
+ {
+ outputPlug[i] = arFactory.Create(static_cast<ePlugType>(apGraph->m_OutEdges[i].m_Id), arAlloc);
+ outputPlug[i]->m_ID = apGraph->m_OutEdges[i].m_Binding;
+ outputPlug[i]->m_Input = true;
+ }
+
+ for(i=0;i<apGraph->m_ConstantCount;i++)
+ {
+ constants[i] = arAlloc.Construct<Constant>();
+
+ constants[i]->m_FloatValue = apGraph->m_ConstantEdges[i].m_FloatValue;
+ constants[i]->m_VectorValue = apGraph->m_ConstantEdges[i].m_VectorValue;
+ }
+
+ cst = CreateGraph(nodes, apGraph->m_VerticesCount, inputPlug, apGraph->m_InEdgesCount, outputPlug, apGraph->m_OutEdgesCount, apGraph->m_EdgesCount, constants, apGraph->m_ConstantCount, arAlloc);
+
+ for(i=0;i<apGraph->m_EdgesCount;i++)
+ {
+ cst->m_Graph.m_Edges[i] = apGraph->m_Edges[i];
+ Connect(apGraph->m_Edges[i], *cst);
+ }
+
+ for(i=0;i<apGraph->m_ConstantCount;i++)
+ {
+ cst->m_Graph.m_ConstantEdges[i].m_Id = apGraph->m_ConstantEdges[i].m_Id;
+ Connect(apGraph->m_ConstantEdges[i], *cst->m_ConstantArray[i], *cst);
+ }
+
+ arAlloc.Deallocate(nodes);
+ arAlloc.Deallocate(inputPlug);
+ arAlloc.Deallocate(outputPlug);
+ arAlloc.Deallocate(constants);
+
+ return cst;
+ }
+
+ void DestroyEvaluationGraph(EvaluationGraph* apGraph, memory::Allocator& arAlloc)
+ {
+ if(apGraph)
+ {
+ uint32_t i;
+ for(i=0;i<apGraph->m_NodeCount;i++)
+ {
+ arAlloc.Deallocate(apGraph->m_NodeArray[i]);
+ }
+ arAlloc.Deallocate(apGraph->m_NodeArray);
+
+ for(i=0;i<apGraph->m_Graph.m_InEdgesCount;i++)
+ {
+ arAlloc.Deallocate(apGraph->m_Input->mPlugArray[i]);
+ }
+ arAlloc.Deallocate(apGraph->m_Input->mPlugArray);
+ arAlloc.Deallocate(apGraph->m_Input);
+
+ for(i=0;i<apGraph->m_Graph.m_OutEdgesCount;i++)
+ {
+ arAlloc.Deallocate(apGraph->m_Output->mPlugArray[i]);
+ }
+ arAlloc.Deallocate(apGraph->m_Output->mPlugArray);
+ arAlloc.Deallocate(apGraph->m_Output);
+
+ for(i=0;i<apGraph->m_ConstantCount;i++)
+ {
+ arAlloc.Deallocate(apGraph->m_ConstantArray[i]);
+ }
+ arAlloc.Deallocate(apGraph->m_ConstantArray);
+
+ arAlloc.Deallocate(apGraph->m_Graph.m_Vertices);
+ arAlloc.Deallocate(apGraph->m_Graph.m_Edges);
+ arAlloc.Deallocate(apGraph->m_Graph.m_InEdges);
+ arAlloc.Deallocate(apGraph->m_Graph.m_OutEdges);
+ arAlloc.Deallocate(apGraph->m_Graph.m_ConstantEdges);
+
+ arAlloc.Deallocate(apGraph);
+ }
+ }
+
+ EvaluationGraphWorkspace* CreateEvaluationGraphWorkspace(EvaluationGraph* apGraph, memory::Allocator& arAlloc)
+ {
+ std::size_t sizePlugDataBlock = 0;
+ uint32_t i, plugCount = 0;
+
+ for(i=0;i<apGraph->m_NodeCount;i++)
+ {
+ Node* node = apGraph->m_NodeArray[i];
+ uint32_t j;
+ for(j=0;j<node->GetPlugCount();j++)
+ {
+ plugCount++;
+ sizePlugDataBlock = arAlloc.AlignAddress(sizePlugDataBlock, node->GetPlug(j).ValueAlign());
+ sizePlugDataBlock += node->GetPlug(j).ValueSize();
+ }
+ }
+
+ for(i=0;i<apGraph->m_Input->GetPlugCount();i++)
+ {
+ plugCount++;
+ sizePlugDataBlock = arAlloc.AlignAddress(sizePlugDataBlock, apGraph->m_Input->GetPlug(i).ValueAlign());
+ sizePlugDataBlock += apGraph->m_Input->GetPlug(i).ValueSize();
+ }
+
+ for(i=0;i<apGraph->m_Output->GetPlugCount();i++)
+ {
+ plugCount++;
+ sizePlugDataBlock = arAlloc.AlignAddress(sizePlugDataBlock, apGraph->m_Output->GetPlug(i).ValueAlign());
+ sizePlugDataBlock += apGraph->m_Output->GetPlug(i).ValueSize();
+ }
+
+ EvaluationGraphWorkspace* ws = arAlloc.Construct<EvaluationGraphWorkspace>();
+
+ ws->m_EvaluationInfo.m_DataBlock.m_PlugCount = plugCount;
+ ws->m_EvaluationInfo.m_DataBlock.m_EvaluationId = arAlloc.ConstructArray<uint32_t>(plugCount);
+
+ ws->m_EvaluationInfo.m_DataBlock.m_Buffer = reinterpret_cast<char*>(arAlloc.Allocate( sizePlugDataBlock, ALIGN4F) );
+ ws->m_EvaluationInfo.m_EvaluationId = 0;
+
+ memset(ws->m_EvaluationInfo.m_DataBlock.m_EvaluationId, numeric_limits<uint32_t>::max_value, sizeof(mecanim::uint32_t)*plugCount);
+ memset(ws->m_EvaluationInfo.m_DataBlock.m_Buffer, 0, sizePlugDataBlock);
+
+ for(i=0;i<apGraph->m_ConstantCount;i++)
+ {
+ if(apGraph->m_ConstantArray[i]->m_Plug)
+ {
+ ePlugType plugType = GetPlugType(*apGraph->m_ConstantArray[i]->m_Plug);
+ switch(plugType)
+ {
+ case Float4Id:
+ ws->m_EvaluationInfo.m_DataBlock.SetData(apGraph->m_ConstantArray[i]->m_VectorValue, apGraph->m_ConstantArray[i]->m_Plug->m_PlugId, apGraph->m_ConstantArray[i]->m_Plug->m_Offset, 0);
+ break;
+ case Float1Id:
+ ws->m_EvaluationInfo.m_DataBlock.SetData(apGraph->m_ConstantArray[i]->m_VectorValue, apGraph->m_ConstantArray[i]->m_Plug->m_PlugId, apGraph->m_ConstantArray[i]->m_Plug->m_Offset, 0);
+ break;
+ case FloatId:
+ ws->m_EvaluationInfo.m_DataBlock.SetData(apGraph->m_ConstantArray[i]->m_FloatValue, apGraph->m_ConstantArray[i]->m_Plug->m_PlugId, apGraph->m_ConstantArray[i]->m_Plug->m_Offset, 0);
+ break;
+ case UInt32Id:
+ ws->m_EvaluationInfo.m_DataBlock.SetData(apGraph->m_ConstantArray[i]->m_UIntValue, apGraph->m_ConstantArray[i]->m_Plug->m_PlugId, apGraph->m_ConstantArray[i]->m_Plug->m_Offset, 0);
+ break;
+ case Int32Id:
+ ws->m_EvaluationInfo.m_DataBlock.SetData(apGraph->m_ConstantArray[i]->m_IntValue, apGraph->m_ConstantArray[i]->m_Plug->m_PlugId, apGraph->m_ConstantArray[i]->m_Plug->m_Offset, 0);
+ break;
+ case BoolId:
+ ws->m_EvaluationInfo.m_DataBlock.SetData(apGraph->m_ConstantArray[i]->m_BoolValue, apGraph->m_ConstantArray[i]->m_Plug->m_PlugId, apGraph->m_ConstantArray[i]->m_Plug->m_Offset, 0);
+ break;
+ }
+ }
+ }
+
+ return ws;
+ }
+
+ void DestroyEvaluationGraphWorkspace(EvaluationGraphWorkspace* apGraphWorkspace, memory::Allocator& arAlloc)
+ {
+ if(apGraphWorkspace)
+ {
+ arAlloc.Deallocate(apGraphWorkspace->m_EvaluationInfo.m_DataBlock.m_Buffer);
+ arAlloc.Deallocate(apGraphWorkspace->m_EvaluationInfo.m_DataBlock.m_EvaluationId);
+ arAlloc.Deallocate(apGraphWorkspace);
+ }
+ }
+}
+
+} \ No newline at end of file
diff --git a/Runtime/mecanim/graph/graph.h b/Runtime/mecanim/graph/graph.h
new file mode 100644
index 0000000..2c12b4f
--- /dev/null
+++ b/Runtime/mecanim/graph/graph.h
@@ -0,0 +1,188 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+#include "Runtime/mecanim/bitset.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+#include "Runtime/mecanim/graph/node.h"
+#include "Runtime/mecanim/graph/factory.h"
+
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+#include "Runtime/Animation/MecanimArraySerialization.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ // If somebody change a node interface, like adding a new plug, he should create a new class instead for his new node
+ // because some user's file may still use the old node and won't have the data to handle new plug, unexpected behavior
+ // can result if this rule is not respected
+
+ struct Vertex : public Object
+ {
+ DEFINE_GET_TYPESTRING(Vertex)
+
+ DeclareObject(Vertex)
+
+ Vertex():m_Id(numeric_limits<uint32_t>::max_value){}
+ uint32_t m_Id;
+ uint32_t m_Binding;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER(m_Id);
+ TRANSFER(m_Binding);
+ }
+ };
+
+ struct Edge : public Object
+ {
+ DEFINE_GET_TYPESTRING(Edge)
+
+ DeclareObject(Edge)
+
+ Edge():m_SourceId(numeric_limits<uint32_t>::max_value),m_DestinationId(numeric_limits<uint32_t>::max_value){}
+ uint32_t m_SourceId;
+ uint32_t m_DestinationId;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER(m_SourceId);
+ TRANSFER(m_DestinationId);
+ }
+ };
+
+ struct ConstantEdge : public Object
+ {
+ DEFINE_GET_TYPESTRING(ConstantEdge)
+
+ DeclareObject(ConstantEdge)
+
+ ConstantEdge():m_Id(numeric_limits<uint32_t>::max_value){}
+ union {
+ float m_FloatValue;
+ uint32_t m_UIntValue;
+ int32_t m_IntValue;
+ bool m_BoolValue;
+ };
+ math::float4 m_VectorValue;
+
+ uint32_t m_Id;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER(m_Id);
+ TRANSFER(m_VectorValue);
+ TRANSFER(m_UIntValue);
+ }
+ };
+
+ struct ExternalEdge : public Object
+ {
+ DEFINE_GET_TYPESTRING(ExternalEdge)
+
+ DeclareObject(ExternalEdge)
+
+ ExternalEdge():m_Id(numeric_limits<uint32_t>::max_value), m_Binding(numeric_limits<uint32_t>::max_value){}
+ uint32_t m_Id;
+ uint32_t m_Binding;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER(m_Id);
+ TRANSFER(m_Binding);
+ }
+ };
+
+ struct Graph : public Object
+ {
+ DEFINE_GET_TYPESTRING(Graph)
+
+ DeclareObject(Graph)
+
+ Graph()
+ :m_VerticesCount(0),m_Vertices(0),
+ m_EdgesCount(0),m_Edges(0),
+ m_InEdgesCount(0),m_InEdges(0),
+ m_OutEdgesCount(0),m_OutEdges(0),
+ m_ConstantCount(0),m_ConstantEdges(0)
+ {}
+
+ uint32_t m_VerticesCount;
+ Vertex* m_Vertices;
+
+ uint32_t m_EdgesCount;
+ Edge* m_Edges;
+
+ uint32_t m_InEdgesCount;
+ ExternalEdge* m_InEdges;
+
+ uint32_t m_OutEdgesCount;
+ ExternalEdge* m_OutEdges;
+
+ uint32_t m_ConstantCount;
+ ConstantEdge* m_ConstantEdges;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ MANUAL_ARRAY_TRANSFER(mecanim::graph::Vertex, m_Vertices, m_VerticesCount);
+ MANUAL_ARRAY_TRANSFER(mecanim::graph::Edge, m_Edges, m_EdgesCount);
+ MANUAL_ARRAY_TRANSFER(mecanim::graph::ExternalEdge, m_InEdges, m_InEdgesCount);
+ MANUAL_ARRAY_TRANSFER(mecanim::graph::ExternalEdge, m_OutEdges, m_OutEdgesCount);
+ MANUAL_ARRAY_TRANSFER(mecanim::graph::ConstantEdge, m_ConstantEdges, m_ConstantCount);
+ }
+ };
+
+ struct EvaluationGraph
+ {
+ public:
+ EvaluationGraph():m_NodeCount(0),m_NodeArray(0),m_Input(0),m_Output(0),m_ConstantCount(0),m_ConstantArray(0){}
+
+ Graph m_Graph;
+
+ uint32_t m_NodeCount;
+ Node** m_NodeArray;
+
+ GraphInput* m_Input;
+ GraphOutput* m_Output;
+
+ uint32_t m_ConstantCount;
+ Constant** m_ConstantArray;
+ };
+
+ struct EvaluationGraphWorkspace
+ {
+ public:
+ EvaluationGraphWorkspace(){}
+
+ EvaluationInfo m_EvaluationInfo;
+ };
+
+ EvaluationGraph* CreateEvaluationGraph(Node** apNodeArray, uint32_t aNodeCount,
+ GraphPlug** apInputPlugArray, uint32_t aInputPlugCount,
+ GraphPlug** apOutputPlugArray, uint32_t aOutputPlugCount,
+ Constant** apConstantArray, uint32_t aConstantCount,
+ memory::Allocator& arAlloc);
+
+ EvaluationGraph* CreateEvaluationGraph(Graph* apGraph, GraphFactory const& arFactory, memory::Allocator& arAlloc);
+
+ void DestroyEvaluationGraph(EvaluationGraph* apGraph, memory::Allocator& arAlloc);
+
+ EvaluationGraphWorkspace* CreateEvaluationGraphWorkspace(EvaluationGraph* apGraph, memory::Allocator& arAlloc);
+ void DestroyEvaluationGraphWorkspace(EvaluationGraphWorkspace* apGraphWorkspace, memory::Allocator& arAlloc);
+}
+
+}
diff --git a/Runtime/mecanim/graph/node.cpp b/Runtime/mecanim/graph/node.cpp
new file mode 100644
index 0000000..8e1ead8
--- /dev/null
+++ b/Runtime/mecanim/graph/node.cpp
@@ -0,0 +1,11 @@
+#include "UnityPrefix.h"
+#include "Runtime/mecanim/graph/node.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+}
+
+}
diff --git a/Runtime/mecanim/graph/node.h b/Runtime/mecanim/graph/node.h
new file mode 100644
index 0000000..7dcea89
--- /dev/null
+++ b/Runtime/mecanim/graph/node.h
@@ -0,0 +1,346 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+#include "Runtime/mecanim/generic/stringtable.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ // If you add a new node id, add it at the end of this list, otherwise you will break
+ // saved graph asset.
+ enum eNodeType {
+ InvalidNodeId,
+ NegationFloatId,
+ NegationIntId,
+ NegationFloat4Id,
+ AdditionFloatId,
+ AdditionUIntId,
+ AdditionIntId,
+ AdditionFloat4Id,
+ SubstractionFloatId,
+ SubstractionUIntId,
+ SubstractionIntId,
+ SubstractionFloat4Id,
+ MultiplicationFloatId,
+ MultiplicationUIntId,
+ MultiplicationIntId,
+ MultiplicationFloat4Id,
+ DivisionFloatId,
+ DivisionUIntId,
+ DivisionIntId,
+ DivisionFloat4Id,
+ CondFloatId,
+ CondUIntId,
+ CondIntId,
+ CondFloat4Id,
+ AbsFloatId,
+ AbsFloat4Id,
+ CrossFloat4Id,
+ DegreesFloatId,
+ DegreesFloat4Id,
+ DotFloat4Id,
+ LengthFloat4Id,
+ MaximumFloatId,
+ MaximumUIntId,
+ MaximumIntId,
+ MaximumFloat4Id,
+ MinimumFloatId,
+ MinimumUIntId,
+ MinimumIntId,
+ MinimumFloat4Id,
+ NormalizeFloat4Id,
+ RadiansFloatId,
+ RadiansFloat4Id,
+ FloatToFloat4Id,
+ Float4ToFloatId,
+ GreaterThanId,
+ LesserThanId,
+ SmoothstepFloatId,
+ Mux5FloatId,
+ Mul5FloatId,
+ FmodId,
+ SinId,
+ AndId,
+ OrId,
+ NegationBoolId,
+ GreaterThanOrEqualId,
+ LesserThanOrEqualId,
+ xformMulInvId,
+ xformIdentityId,
+ xformMulVecId,
+ xformInvMulVecId,
+ xformMulId,
+ xformInvMulId,
+ xformEqualId,
+ xformWeightId,
+ xformAddId,
+ xformSubId,
+ quatIdentityId,
+ quatConjId,
+ quatMulId,
+ quatMulVecId,
+ quatLerpId,
+ quatArcRotateId,
+ quatArcRotateXId,
+ quatXcosId,
+ quatYcosId,
+ quatZcosId,
+ quatEulerToQuatId,
+ quatQuatToEulerId,
+ quatProjOnYPlaneId,
+ quat2QtanId,
+ qtan2QuatId,
+ ZYRoll2QuatId,
+ quat2ZYRollId,
+ RollZY2QuatId,
+ quat2RollZYId,
+ quatWeightId,
+ xformComposeId,
+ xformDecomposeId,
+ CondXformId,
+ xformBlendId,
+ FloatToFloat1Id, // Not used anymore
+ Float1ToFloatId, // Not used anymore
+ RandId,
+ DampId,
+ xformRefChangeId,
+ XorId,
+ SmoothPulseFloatId,
+ InputId,
+ OutputId,
+ LastNodeId
+ };
+
+ class Node : public Object
+ {
+ public:
+ uint32_t mID;
+
+ Node(){}
+ virtual ~Node(){}
+
+ virtual eNodeType NodeType()=0;
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)=0;
+
+ virtual uint32_t GetPlugCount()const=0;
+ virtual GraphPlug& GetPlug(uint32_t aIndex)=0;
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const=0;
+ };
+
+ template<typename TYPE> class TypePlug : public GraphPlug
+ {
+ public:
+ typedef TYPE value_type;
+ typedef TYPE& reference;
+ typedef TYPE const& const_reference;
+ typedef TYPE* pointer;
+ typedef TYPE const* const_pointer;
+
+ TypePlug(){}
+ TypePlug(bool input, uint32_t id, Node* apOwner=0):GraphPlug(input, id, apOwner){}
+
+ virtual std::size_t ValueSize()const
+ {
+ return sizeof(value_type);
+ }
+
+ virtual std::size_t ValueAlign()const
+ {
+ return ALIGN_OF(value_type);
+ }
+
+ virtual ePlugType PlugType()const
+ {
+ return Trait<value_type>::PlugType();
+ }
+
+ void ConnectTo(TypePlug& arPlug)
+ {
+ m_Source = &arPlug;
+ }
+
+ bool ReadData(void* apData, EvaluationInfo& arEvaluationInfo)const
+ {
+ uint32_t offset = m_Offset;
+ if(m_Source)
+ {
+ offset = m_Source->m_Offset;
+ if(arEvaluationInfo.m_DataBlock.IsDirty(m_Source->m_PlugId, arEvaluationInfo.m_EvaluationId))
+ {
+ m_Source->m_Owner->Evaluate(arEvaluationInfo);
+ }
+ }
+
+ *reinterpret_cast<pointer>(apData) = arEvaluationInfo.m_DataBlock.GetData<value_type>(offset);
+
+ return true;
+ }
+
+ bool WriteData(void const* apData, EvaluationInfo& arEvaluationInfo)const
+ {
+ arEvaluationInfo.m_DataBlock.SetData(*reinterpret_cast<const_pointer>(apData), m_PlugId, m_Offset, arEvaluationInfo.m_EvaluationId);
+ return true;
+ }
+ };
+
+
+ class GraphOutput : public Node
+ {
+ public:
+ uint32_t mPlugCount;
+ GraphPlug** mPlugArray;
+
+ GraphOutput():mPlugCount(0), mPlugArray(0){}
+ virtual ~GraphOutput(){}
+
+ virtual eNodeType NodeType(){return OutputId;}
+
+ virtual uint32_t GetPlugCount()const{return mPlugCount;}
+ virtual GraphPlug& GetPlug(uint32_t aIndex){return *(mPlugArray[aIndex]);}
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const{return *(mPlugArray[aIndex]);}
+
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo){};
+ };
+
+ class GraphInput : public Node
+ {
+ public:
+ uint32_t mPlugCount;
+ GraphPlug** mPlugArray;
+
+ GraphInput():mPlugCount(0), mPlugArray(0){}
+ virtual ~GraphInput(){}
+
+ virtual eNodeType NodeType(){return InputId;}
+
+ virtual uint32_t GetPlugCount()const{return mPlugCount;}
+ virtual GraphPlug& GetPlug(uint32_t aIndex){return *(mPlugArray[aIndex]);}
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const{return *(mPlugArray[aIndex]);}
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo){};
+ };
+
+ template <typename RESULT, typename ResultPolicies> class ResultNode : public Node
+ {
+ public:
+ TypePlug<RESULT> mResult;
+
+ ResultNode()
+ :mResult(false,CRCKey(eResult))
+ {
+ mResult.m_Owner = this;
+ }
+ virtual ~ResultNode(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 1;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ RESULT result = ResultPolicies::template Operation<RESULT>();
+ mResult.WriteData(&result, arEvaluationInfo);
+ }
+ };
+
+ template <typename TYPE1, typename TYPE2, typename TYPE3, typename RESULT, typename TernaryPolicies> class TernaryNode : public Node
+ {
+ public:
+ TypePlug<TYPE1> mA;
+ TypePlug<TYPE2> mB;
+ TypePlug<TYPE3> mC;
+
+ TypePlug<RESULT> mResult;
+
+ TernaryNode()
+ :mA(true, CRCKey(eA)),
+ mB(true,CRCKey(eB)),
+ mC(true,CRCKey(eC)),
+ mResult(false,CRCKey(eResult))
+ {
+ mA.m_Owner = this;
+ mB.m_Owner = this;
+ mC.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+
+ virtual ~TernaryNode(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 4;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1: return mB;
+ case 2: return mC;
+ case 3:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1: return mB;
+ case 2: return mC;
+ case 3:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ TYPE1 a;
+ TYPE2 b;
+ TYPE3 c;
+ RESULT result;
+
+ mA.ReadData(&a, arEvaluationInfo);
+ mB.ReadData(&b, arEvaluationInfo);
+ mC.ReadData(&c, arEvaluationInfo);
+
+ result = TernaryPolicies::template Operation<TYPE1, TYPE2, TYPE3, RESULT>(a, b, c);
+
+ mResult.WriteData(&result, arEvaluationInfo);
+ }
+ };
+
+
+
+}
+
+}
diff --git a/Runtime/mecanim/graph/plug.h b/Runtime/mecanim/graph/plug.h
new file mode 100644
index 0000000..ce90020
--- /dev/null
+++ b/Runtime/mecanim/graph/plug.h
@@ -0,0 +1,123 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/Math/Simd/float4.h"
+#include "Runtime/Math/Simd/xform.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ class Node;
+
+ enum ePlugType
+ {
+ InvalidPlugId,
+ Float4Id,
+ FloatId,
+ UInt32Id, // Not used anymore
+ Int32Id,
+ BoolId,
+ Float1Id, // Not used anymore
+ Bool4Id, // Not used anymore
+ XformId,
+ LastPlugId
+ };
+
+ template<typename T> struct Trait;
+
+ template<> struct Trait<math::float4> { static ePlugType PlugType(){return Float4Id;} };
+ template<> struct Trait<float> { static ePlugType PlugType(){return FloatId;} };
+ template<> struct Trait<math::float1> { static ePlugType PlugType(){return FloatId;} };
+ template<> struct Trait<uint32_t> { static ePlugType PlugType(){return UInt32Id;} };
+ template<> struct Trait<int32_t> { static ePlugType PlugType(){return Int32Id;} };
+ template<> struct Trait<bool> { static ePlugType PlugType(){return BoolId;} };
+ template<> struct Trait<math::bool4> { static ePlugType PlugType(){return Bool4Id;} };
+ template<> struct Trait<math::xform> { static ePlugType PlugType(){return XformId;} };
+
+ class DataBlock
+ {
+ public:
+ uint32_t m_PlugCount;
+ uint32_t* m_EvaluationId;
+ char* m_Buffer;
+
+ bool IsDirty(uint32_t aPlugId, uint32_t aEvaluationId)const
+ {
+ return m_EvaluationId[aPlugId] != aEvaluationId;
+ }
+ template<typename TYPE> TYPE GetData(uint32_t offset)const
+ {
+ return *reinterpret_cast<TYPE*>(&m_Buffer[offset]);
+ }
+ template<typename TYPE> void SetData(TYPE const& arValue, uint32_t aPlugId, uint32_t offset, uint32_t aEvaluationId)
+ {
+ *reinterpret_cast<TYPE*>(&m_Buffer[offset]) = arValue;
+ m_EvaluationId[aPlugId] = aEvaluationId;
+ }
+ };
+
+ class EvaluationInfo
+ {
+ public:
+ DataBlock m_DataBlock;
+ uint32_t m_EvaluationId;
+ };
+
+ class GraphPlug
+ {
+ public:
+ GraphPlug():m_PlugId(numeric_limits<uint32_t>::max_value),m_Input(false),m_Owner(0),m_Source(0),m_Offset(0){}
+ GraphPlug(bool input, uint32_t id, Node* owner=0):m_PlugId(numeric_limits<uint32_t>::max_value),m_Input(input),m_Owner(owner),m_Source(0),m_ID(id){}
+
+ virtual ~GraphPlug(){}
+
+ virtual std::size_t ValueSize()const=0;
+ virtual std::size_t ValueAlign()const=0;
+ virtual ePlugType PlugType()const=0;
+
+ GraphPlug* GetSource(){return m_Source;}
+
+ virtual bool ReadData(void* apData, EvaluationInfo& arEvaluationInfo)const=0;
+ virtual bool WriteData(void const* apData, EvaluationInfo& arEvaluationInfo)const=0;
+
+ uint32_t m_PlugId;
+ bool m_Input;
+ Node* m_Owner;
+ GraphPlug* m_Source;
+ uint32_t m_ID;
+ uint32_t m_Offset;
+ };
+
+ struct Constant
+ {
+ Constant():m_Plug(0),m_VectorValue(0),m_FloatValue(0){}
+
+ union {
+ float m_FloatValue;
+ uint32_t m_UIntValue;
+ int32_t m_IntValue;
+ bool m_BoolValue;
+ };
+ // Cannot put float4 in union because of operator=
+ math::float4 m_VectorValue;
+ graph::GraphPlug* m_Plug;
+ };
+
+
+ STATIC_INLINE ePlugType GetPlugType(GraphPlug const& arPlug)
+ {
+ return arPlug.PlugType();
+ }
+}
+
+}
diff --git a/Runtime/mecanim/graph/plugbinder.cpp b/Runtime/mecanim/graph/plugbinder.cpp
new file mode 100644
index 0000000..03ffb30
--- /dev/null
+++ b/Runtime/mecanim/graph/plugbinder.cpp
@@ -0,0 +1,180 @@
+#include "UnityPrefix.h"
+#include "Runtime/mecanim/graph/plugbinder.h"
+
+namespace mecanim
+{
+ void InitializeSetPlugBinder3(uint32_t& arCount, SetPlugBinder3 *& arSetPlugBinder3, ValuesList const& arValuesList, graph::EvaluationGraph const* apGraph, memory::Allocator& arAlloc)
+ {
+ arCount = 0;
+ arSetPlugBinder3 = 0;
+
+ uint32_t i;
+ for(i = 0 ; i < apGraph->m_Input->mPlugCount; i++)
+ {
+ graph::GraphPlug& plug = *apGraph->m_Input->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_InValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_InValuesConstant[j], plug.m_ID);
+ if(index > -1)
+ {
+ arCount++;
+ }
+ }
+ }
+
+ if(arCount)
+ {
+ arSetPlugBinder3 = arAlloc.ConstructArray<SetPlugBinder3>(arCount);
+ uint32_t binderCount;
+ for(i = 0, binderCount = 0; i < apGraph->m_Input->mPlugCount; i++)
+ {
+ graph::GraphPlug const* plug = apGraph->m_Input->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_InValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_InValuesConstant[j], plug->m_ID);
+ if(index > -1)
+ {
+ uint32_t valueIndex = static_cast<uint32_t>(index);
+ arSetPlugBinder3[binderCount++] = bind( SetPlugValueList, plug, j, valueIndex);
+ }
+ }
+ }
+ }
+ }
+
+ void InitializeGetPlugBinder3(uint32_t& arCount,
+ GetPlugBinder3 *& arGetPlugBinder3,
+ ValuesList const& arValuesList,
+ graph::EvaluationGraph const* apGraph,
+ memory::Allocator& arAlloc)
+ {
+ arCount = 0;
+ arGetPlugBinder3 = 0;
+
+ uint32_t i;
+ for(i = 0 ; i < apGraph->m_Output->mPlugCount; i++)
+ {
+ graph::GraphPlug& plug = *apGraph->m_Output->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_OutValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_OutValuesConstant[j], plug.m_ID);
+ if(index > -1)
+ {
+ arCount++;
+ }
+ }
+ }
+
+ if(arCount)
+ {
+ arGetPlugBinder3 = arAlloc.ConstructArray<GetPlugBinder3>(arCount);
+ uint32_t binderCount;
+ for(i = 0, binderCount = 0; i < apGraph->m_Output->mPlugCount; i++)
+ {
+ graph::GraphPlug const* plug = apGraph->m_Output->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_OutValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_OutValuesConstant[j], plug->m_ID);
+ if(index > -1)
+ {
+ uint32_t valueIndex = static_cast<uint32_t>(index);
+ arGetPlugBinder3[binderCount++] = bind( GetPlugValueList, plug, j, valueIndex);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ void InitializeSetPlugBinder2(uint32_t& arCount, SetPlugBinder2 *& arSetPlugBinder2, ValuesList const& arValuesList, graph::EvaluationGraph const* apGraph, memory::Allocator& arAlloc)
+ {
+ arCount = 0;
+ arSetPlugBinder2 = 0;
+
+ uint32_t i;
+ for(i = 0 ; i < apGraph->m_Input->mPlugCount; i++)
+ {
+ graph::GraphPlug& plug = *apGraph->m_Input->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_InValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_InValuesConstant[j], plug.m_ID);
+ if(index > -1)
+ {
+ arCount++;
+ }
+ }
+ }
+
+ if(arCount)
+ {
+ arSetPlugBinder2 = arAlloc.ConstructArray<SetPlugBinder2>(arCount);
+ uint32_t binderCount;
+ for(i = 0, binderCount = 0; i < apGraph->m_Input->mPlugCount; i++)
+ {
+ graph::GraphPlug const* plug = apGraph->m_Input->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_InValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_InValuesConstant[j], plug->m_ID);
+ if(index > -1)
+ {
+ uint32_t valueIndex = static_cast<uint32_t>(index);
+ arSetPlugBinder2[binderCount++] = bind( SetPlugValue, plug, valueIndex);
+ }
+ }
+ }
+ }
+ }
+
+ void InitializeGetPlugBinder5(uint32_t& arCount,
+ GetPlugBinder2 *& arGetPlugBinder2,
+ ValuesList const& arValuesList,
+ graph::EvaluationGraph const* apGraph,
+ memory::Allocator& arAlloc)
+ {
+ arCount = 0;
+ arGetPlugBinder2 = 0;
+
+ uint32_t i;
+ for(i = 0 ; i < apGraph->m_Output->mPlugCount; i++)
+ {
+ graph::GraphPlug& plug = *apGraph->m_Output->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_OutValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_OutValuesConstant[j], plug.m_ID);
+ if(index > -1)
+ {
+ arCount++;
+ }
+ }
+ }
+
+ if(arCount)
+ {
+ arGetPlugBinder2 = arAlloc.ConstructArray<GetPlugBinder2>(arCount);
+ uint32_t binderCount;
+ for(i = 0, binderCount = 0; i < apGraph->m_Output->mPlugCount; i++)
+ {
+ graph::GraphPlug const* plug = apGraph->m_Output->mPlugArray[i];
+ uint32_t j;
+ for(j=0;j<arValuesList.m_OutValuesCount;++j)
+ {
+ int32_t index = FindValueIndex(arValuesList.m_OutValuesConstant[j], plug->m_ID);
+ if(index > -1)
+ {
+ uint32_t valueIndex = static_cast<uint32_t>(index);
+ arGetPlugBinder2[binderCount++] = bind( GetPlugValue, plug, valueIndex);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/Runtime/mecanim/graph/plugbinder.h b/Runtime/mecanim/graph/plugbinder.h
new file mode 100644
index 0000000..f224440
--- /dev/null
+++ b/Runtime/mecanim/graph/plugbinder.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/bind.h"
+#include "Runtime/mecanim/graph/graph.h"
+#include "Runtime/mecanim/generic/valuearray.h"
+
+namespace mecanim
+{
+ typedef binder2<function<void (graph::GraphPlug const*, uint32_t, ValueArray const*, graph::EvaluationGraphWorkspace*)>::ptr,
+ graph::GraphPlug const*,
+ uint32_t>
+ SetPlugBinder2;
+
+ typedef binder2<function<void (graph::GraphPlug const*, uint32_t, ValueArray*, graph::EvaluationGraphWorkspace*)>::ptr,
+ graph::GraphPlug const*,
+ uint32_t >
+ GetPlugBinder2;
+
+ typedef binder3<function<void (graph::GraphPlug const*, uint32_t, uint32_t, ValuesList const&, graph::EvaluationGraphWorkspace*)>::ptr,
+ graph::GraphPlug const*,
+ uint32_t,
+ uint32_t>
+ SetPlugBinder3;
+
+
+ typedef binder3<function<void (graph::GraphPlug const*, uint32_t, uint32_t, ValuesList const&, graph::EvaluationGraphWorkspace*)>::ptr,
+ graph::GraphPlug const*,
+ uint32_t,
+ uint32_t>
+ GetPlugBinder3;
+
+ STATIC_INLINE void SetPlugValue(mecanim::graph::GraphPlug const* plug, mecanim::uint32_t valueIndex, mecanim::ValueArray const* valueArray, mecanim::graph::EvaluationGraphWorkspace* graphWS)
+ {
+ char ATTRIBUTE_ALIGN(ALIGN4F) value[48];
+ valueArray->m_ValueArray[valueIndex]->ReadData(value);
+ plug->WriteData( value, graphWS->m_EvaluationInfo);
+ }
+ STATIC_INLINE void GetPlugValue(mecanim::graph::GraphPlug const* plug, mecanim::uint32_t valueIndex, mecanim::ValueArray* valueArray, mecanim::graph::EvaluationGraphWorkspace* graphWS)
+ {
+ char ATTRIBUTE_ALIGN(ALIGN4F) value[48];
+ plug->ReadData( value, graphWS->m_EvaluationInfo);
+ valueArray->m_ValueArray[valueIndex]->WriteData(value);
+ }
+
+ STATIC_INLINE void SetPlugValueList(mecanim::graph::GraphPlug const* plug, mecanim::uint32_t listIndex, mecanim::uint32_t valueIndex, ValuesList const& valuesList, mecanim::graph::EvaluationGraphWorkspace* graphWS)
+ {
+ char ATTRIBUTE_ALIGN(ALIGN4F) value[48];
+ valuesList.m_InValues[listIndex]->m_ValueArray[valueIndex]->ReadData(value);
+ plug->WriteData( value, graphWS->m_EvaluationInfo);
+ }
+ STATIC_INLINE void GetPlugValueList(mecanim::graph::GraphPlug const* plug, mecanim::uint32_t listIndex, mecanim::uint32_t valueIndex, ValuesList const& valuesList, mecanim::graph::EvaluationGraphWorkspace* graphWS)
+ {
+ char ATTRIBUTE_ALIGN(ALIGN4F) value[48];
+ plug->ReadData( value, graphWS->m_EvaluationInfo);
+ valuesList.m_OutValues[listIndex]->m_ValueArray[valueIndex]->WriteData(value);
+ }
+
+ void InitializeSetPlugBinder3(uint32_t& arCount,
+ SetPlugBinder3 *& arSetPlugBinder3,
+ ValuesList const& arValuesList,
+ graph::EvaluationGraph const* apGraph,
+ memory::Allocator& arAlloc);
+
+ void InitializeGetPlugBinder3(uint32_t& arCount,
+ GetPlugBinder3 *& arGetPlugBinder3,
+ ValuesList const& arValuesList,
+ graph::EvaluationGraph const* apGraph,
+ memory::Allocator& arAlloc);
+
+ void InitializeSetPlugBinder2(uint32_t& arCount,
+ SetPlugBinder2 *& arSetPlugBinder2,
+ ValuesList const& arValuesList,
+ graph::EvaluationGraph const* apGraph,
+ memory::Allocator& arAlloc);
+
+ void InitializeGetPlugBinder2(uint32_t& arCount,
+ GetPlugBinder2 *& arGetPlugBinder2,
+ ValuesList const& arValuesList,
+ graph::EvaluationGraph const* apGraph,
+ memory::Allocator& arAlloc);
+} \ No newline at end of file
diff --git a/Runtime/mecanim/graph/quaternionnode.h b/Runtime/mecanim/graph/quaternionnode.h
new file mode 100644
index 0000000..19f1f86
--- /dev/null
+++ b/Runtime/mecanim/graph/quaternionnode.h
@@ -0,0 +1,283 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/Math/Simd/math.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+#include "Runtime/mecanim/graph/node.h"
+
+#include "Runtime/mecanim/graph/unarynode.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ class quatIdentityOp
+ {
+ public:
+ template<typename RESULT> static math::float4 Operation(){ return math::quatIdentity(); }
+ };
+
+ class quatIdentity : public ResultNode<math::float4, quatIdentityOp>
+ {
+ public:
+ static const eNodeType mId = quatIdentityId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE, typename RESULT> class quatConjOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatConj(l); }
+ };
+
+ class quatConj : public UnaryNode<math::float4, math::float4, quatConjOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatConjId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class quatMulOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::float4 Operation( math::float4 const& l, math::float4 const& r){ return math::quatMul(l, r); }
+ };
+
+ class quatMul : public BinaryNode<math::float4, math::float4, math::float4, quatMulOp>
+ {
+ public:
+ static const eNodeType mId = quatMulId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class quatMulVecOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::float4 Operation( math::float4 const& l, math::float4 const& r){ return math::quatMulVec(l, r); }
+ };
+
+ class quatMulVec : public BinaryNode<math::float4, math::float4, math::float4, quatMulVecOp>
+ {
+ public:
+ static const eNodeType mId = quatMulVecId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class quatLerpOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename TYPE3, typename RESULT> static math::float4 Operation( math::float4 const& a, math::float4 const& b, float c){ return math::quatLerp(a, b, math::float1(c)); }
+ };
+
+ class quatLerp : public TernaryNode<math::float4, math::float4, float, math::float4, quatLerpOp>
+ {
+ public:
+ static const eNodeType mId = quatLerpId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class quatArcRotateOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::float4 Operation( math::float4 const& l, math::float4 const& r){ return math::quatArcRotate(l, r); }
+ };
+
+ class quatArcRotate : public BinaryNode<math::float4, math::float4, math::float4, quatArcRotateOp>
+ {
+ public:
+ static const eNodeType mId = quatArcRotateId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quatArcRotateXOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatArcRotateX(l); }
+ };
+
+ class quatArcRotateX : public UnaryNode<math::float4, math::float4, quatArcRotateXOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatArcRotateXId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quatXcosOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatXcos(l); }
+ };
+
+ class quatXcos : public UnaryNode<math::float4, math::float4, quatXcosOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatXcosId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quatYcosOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatYcos(l); }
+ };
+
+ class quatYcos : public UnaryNode<math::float4, math::float4, quatYcosOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatYcosId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quatZcosOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatZcos(l); }
+ };
+
+ class quatZcos : public UnaryNode<math::float4, math::float4, quatZcosOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatZcosId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quatEulerToQuatOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatEulerToQuat(l); }
+ };
+
+ class quatEulerToQuat : public UnaryNode<math::float4, math::float4, quatEulerToQuatOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatEulerToQuatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ template<typename TYPE1, typename RESULT> class quatQuatToEulerOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatQuatToEuler(l); }
+ };
+
+ class quatQuatToEuler : public UnaryNode<math::float4, math::float4, quatQuatToEulerOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatQuatToEulerId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quatProjOnYPlaneOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quatProjOnYPlane(l); }
+ };
+
+ class quatProjOnYPlane : public UnaryNode<math::float4, math::float4, quatProjOnYPlaneOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quatProjOnYPlaneId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quat2QtanOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quat2Qtan(l); }
+ };
+
+ class quat2Qtan : public UnaryNode<math::float4, math::float4, quat2QtanOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quat2QtanId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class qtan2QuatOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::qtan2Quat(l); }
+ };
+
+ class qtan2Quat : public UnaryNode<math::float4, math::float4, qtan2QuatOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = qtan2QuatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class ZYRoll2QuatOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::ZYRoll2Quat(l); }
+ };
+
+ class ZYRoll2Quat : public UnaryNode<math::float4, math::float4, ZYRoll2QuatOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = ZYRoll2QuatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quat2ZYRollOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quat2ZYRoll(l); }
+ };
+
+ class quat2ZYRoll : public UnaryNode<math::float4, math::float4, quat2ZYRollOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quat2ZYRollId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class RollZY2QuatOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::RollZY2Quat(l); }
+ };
+
+ class RollZY2Quat : public UnaryNode<math::float4, math::float4, RollZY2QuatOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = RollZY2QuatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ template<typename TYPE1, typename RESULT> class quat2RollZYOp
+ {
+ public:
+ static math::float4 Operation( math::float4 const& l){ return math::quat2RollZY(l); }
+ };
+
+ class quat2RollZY : public UnaryNode<math::float4, math::float4, quat2RollZYOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = quat2RollZYId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class quatWeightOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::float4 Operation( math::float4 const& l, float r){ return math::quatWeight(l, math::float1(r)); }
+ };
+
+ class quatWeight : public BinaryNode<math::float4, float, math::float4, quatWeightOp>
+ {
+ public:
+ static const eNodeType mId = quatWeightId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+}
+} \ No newline at end of file
diff --git a/Runtime/mecanim/graph/unarynode.h b/Runtime/mecanim/graph/unarynode.h
new file mode 100644
index 0000000..8ed5b82
--- /dev/null
+++ b/Runtime/mecanim/graph/unarynode.h
@@ -0,0 +1,112 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/Math/Simd/float4.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ template <typename TYPE, typename RESULT, typename UnaryPolicies> class UnaryNode : public Node
+ {
+ public:
+ TypePlug<TYPE> mA;
+
+ TypePlug<RESULT> mResult;
+
+ UnaryNode()
+ :mA(true,CRCKey(eA)),
+ mResult(false,CRCKey(eResult))
+ {
+ mA.m_Owner = this;
+ mResult.m_Owner = this;
+ }
+ virtual ~UnaryNode(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 2;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1:
+ default: return mResult;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mA;
+ case 1:
+ default: return mResult;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ TYPE a;
+ RESULT result;
+
+ mA.ReadData(&a, arEvaluationInfo);
+
+ result = UnaryPolicies::Operation(a);
+
+ mResult.WriteData(&result, arEvaluationInfo);
+ }
+ };
+
+
+ template< typename TYPE, typename RESULT > class NegationOp
+ {
+ public:
+ static RESULT Operation( TYPE const& l){ return -l; }
+ };
+
+ template<> class NegationOp<bool, bool>
+ {
+ public:
+ static bool Operation(bool const &l) { return !l; }
+ };
+
+ class NegationFloat : public UnaryNode<float, float, NegationOp<float, float> >
+ {
+ public:
+ static const eNodeType mId = NegationFloatId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class NegationInt : public UnaryNode<int32_t, int32_t, NegationOp<int32_t, int32_t> >
+ {
+ public:
+ static const eNodeType mId = NegationIntId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class NegationFloat4 : public UnaryNode<math::float4, math::float4, NegationOp<math::float4, math::float4> >
+ {
+ public:
+ static const eNodeType mId = NegationFloat4Id;
+ virtual eNodeType NodeType(){return mId;}
+ };
+ class NegationBool : public UnaryNode<bool, bool, NegationOp<bool, bool> >
+ {
+ public:
+ static const eNodeType mId = NegationBoolId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+}
+
+}
diff --git a/Runtime/mecanim/graph/xformnode.h b/Runtime/mecanim/graph/xformnode.h
new file mode 100644
index 0000000..d0abf24
--- /dev/null
+++ b/Runtime/mecanim/graph/xformnode.h
@@ -0,0 +1,348 @@
+/*
+ Copyright (c) 7244339 Canada Inc. (Mecanim)
+ All Rights Reserved.
+*/
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/object.h"
+
+#include "Runtime/Math/Simd/math.h"
+
+#include "Runtime/mecanim/graph/plug.h"
+#include "Runtime/mecanim/graph/node.h"
+
+#include "Runtime/mecanim/graph/unarynode.h"
+
+#include "Runtime/mecanim/generic/stringtable.h"
+
+namespace mecanim
+{
+
+namespace graph
+{
+ class IdentityOp
+ {
+ public:
+ template<typename RESULT> static math::xform Operation(){ return math::xformIdentity(); }
+ };
+
+ class xformIdentity : public ResultNode<math::xform, IdentityOp>
+ {
+ public:
+ static const eNodeType mId = xformIdentityId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformMulVecOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::float4 Operation( math::xform const& l, math::float4 const& r){ return math::xformMulVec(l, r); }
+ };
+
+ class xformMulVec : public BinaryNode<math::xform, math::float4, math::float4, xformMulVecOp>
+ {
+ public:
+ static const eNodeType mId = xformMulVecId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformInvMulVecOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::float4 Operation( math::xform const& l, math::float4 const& r){ return math::xformInvMulVec(l, r); }
+ };
+
+ class xformInvMulVec : public BinaryNode<math::xform, math::float4, math::float4, xformInvMulVecOp>
+ {
+ public:
+ static const eNodeType mId = xformInvMulVecId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformMulOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::xform Operation( math::xform const& l, math::xform const& r){ return math::xformMul(l, r); }
+ };
+
+ class xformMul : public BinaryNode<math::xform, math::xform, math::xform, xformMulOp>
+ {
+ public:
+ static const eNodeType mId = xformMulId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformInvMulOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::xform Operation( math::xform const& l, math::xform const& r){ return math::xformInvMul(l, r); }
+ };
+
+ class xformInvMul : public BinaryNode<math::xform, math::xform, math::xform, xformInvMulOp>
+ {
+ public:
+ static const eNodeType mId = xformInvMulId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformMulInvOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::xform Operation( math::xform const& l, math::xform const& r){ return math::xformMulInv(l, r); }
+ };
+
+ class xformMulInv : public BinaryNode<math::xform, math::xform, math::xform, xformMulInvOp>
+ {
+ public:
+ static const eNodeType mId = xformMulInvId;
+ virtual eNodeType NodeType(){ return mId;}
+ };
+
+ class xformEqualOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static bool Operation( math::xform const& l, math::xform const& r){ return l == r; }
+ };
+
+ class xformEqual : public BinaryNode<math::xform, math::xform, bool, xformEqualOp>
+ {
+ public:
+ static const eNodeType mId = xformEqualId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformWeightOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::xform Operation( math::xform const& l, float r){ return math::xformWeight(l, math::float1(r)); }
+ };
+
+ class xformWeight : public BinaryNode<math::xform, float, math::xform, xformWeightOp>
+ {
+ public:
+ static const eNodeType mId = xformWeightId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformBlendOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename TYPE3, typename RESULT> static math::xform Operation( math::xform const& a,math::xform const& b, float const& c){ return math::xformBlend(a,b,math::float1(c)); }
+ };
+
+ class xformBlend : public TernaryNode<math::xform, math::xform, float, math::xform, xformBlendOp>
+ {
+ public:
+ static const eNodeType mId = xformBlendId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformAddOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::xform Operation( math::xform const& l, math::xform const& r){ return math::xformAdd(l, r); }
+ };
+
+ class xformAdd : public BinaryNode<math::xform, math::xform, math::xform, xformAddOp>
+ {
+ public:
+ static const eNodeType mId = xformAddId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformSubOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename RESULT> static math::xform Operation( math::xform const& l, math::xform const& r){ return math::xformSub(l, r); }
+ };
+
+ class xformSub : public BinaryNode<math::xform, math::xform, math::xform, xformSubOp>
+ {
+ public:
+ static const eNodeType mId = xformSubId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformComposeOp
+ {
+ public:
+ template<typename TYPE1, typename TYPE2, typename TYPE3, typename RESULT> static math::xform Operation( math::float4 const& t, math::float4 const& q, math::float4 const& s){ return math::xform(t, q, s); }
+ };
+
+ class xformCompose : public TernaryNode<math::float4, math::float4, math::float4, math::xform, xformComposeOp>
+ {
+ public:
+ xformCompose()
+ {
+ mA.m_ID = CRCKey(eT);
+ mB.m_ID = CRCKey(eQ);
+ mC.m_ID = CRCKey(eS);
+ }
+ static const eNodeType mId = xformComposeId;
+ virtual eNodeType NodeType(){return mId;}
+ };
+
+ class xformDecompose : public Node
+ {
+ public:
+ static const eNodeType mId = xformDecomposeId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<math::xform> mX;
+ TypePlug<math::float4> mT;
+ TypePlug<math::float4> mQ;
+ TypePlug<math::float4> mS;
+
+ xformDecompose()
+ :mX(true,CRCKey(eX)),
+ mT(false,CRCKey(eT)),
+ mQ(false,CRCKey(eQ)),
+ mS(false,CRCKey(eS))
+ {
+ mX.m_Owner = this;
+ mT.m_Owner = this;
+ mQ.m_Owner = this;
+ mS.m_Owner = this;
+ }
+
+ virtual ~xformDecompose(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 4;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mX;
+ case 1: return mT;
+ case 2: return mQ;
+ case 3:
+ default:return mS;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mX;
+ case 1: return mT;
+ case 2: return mQ;
+ case 3:
+ default:return mS;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ math::xform x;
+
+ mX.ReadData(&x, arEvaluationInfo);
+
+ mT.WriteData(&x.t, arEvaluationInfo);
+ mQ.WriteData(&x.q, arEvaluationInfo);
+ mS.WriteData(&x.s, arEvaluationInfo);
+ }
+ };
+
+ class xformRefChange : public Node
+ {
+ public:
+ static const eNodeType mId = xformRefChangeId;
+ virtual eNodeType NodeType(){return mId;}
+
+ TypePlug<math::xform> mSrcRefX;
+ TypePlug<math::xform> mDstRefX;
+ TypePlug<math::xform> mSrcPivotX;
+ TypePlug<math::xform> mDstPivotX;
+ TypePlug<float> mRefWeight;
+ TypePlug<float> mPivotWeight;
+ TypePlug<math::xform> mXI;
+ TypePlug<math::xform> mXO;
+
+ xformRefChange() : mSrcRefX(true,CRCKey(eSrcRefX)),
+ mDstRefX(true,CRCKey(eDstRefX)),
+ mSrcPivotX(true,CRCKey(eSrcPivotX)),
+ mDstPivotX(true,CRCKey(eDstPivotX)),
+ mRefWeight(true,CRCKey(eRefWeight)),
+ mPivotWeight(true,CRCKey(ePivotWeight)),
+ mXI(true,CRCKey(eXI)),
+ mXO(false,CRCKey(eXO))
+ {
+ mSrcRefX.m_Owner = this;
+ mDstRefX.m_Owner = this;
+ mSrcPivotX.m_Owner = this;
+ mDstPivotX.m_Owner = this;
+ mRefWeight.m_Owner = this;
+ mPivotWeight.m_Owner = this;
+ mXI.m_Owner = this;
+ mXO.m_Owner = this;
+ }
+
+ virtual ~xformRefChange(){}
+
+ virtual uint32_t GetPlugCount()const
+ {
+ return 8;
+ }
+ virtual GraphPlug& GetPlug(uint32_t aIndex)
+ {
+ switch(aIndex)
+ {
+ case 0: return mSrcRefX;
+ case 1: return mDstRefX;
+ case 2: return mSrcPivotX;
+ case 3: return mDstPivotX;
+ case 4: return mRefWeight;
+ case 5: return mPivotWeight;
+ case 6: return mXI;
+ case 7:
+ default: return mXO;
+ }
+ }
+ virtual GraphPlug const& GetPlug(uint32_t aIndex)const
+ {
+ switch(aIndex)
+ {
+ case 0: return mSrcRefX;
+ case 1: return mDstRefX;
+ case 2: return mSrcPivotX;
+ case 3: return mDstPivotX;
+ case 4: return mRefWeight;
+ case 5: return mPivotWeight;
+ case 6: return mXI;
+ case 7:
+ default: return mXO;
+ }
+ }
+
+ virtual void Evaluate(EvaluationInfo& arEvaluationInfo)
+ {
+ math::xform srcRefX, dstRefX, srcPivotX, dstPivotX, xi, xo;
+ float rw,pw;
+
+ mSrcRefX.ReadData(&srcRefX, arEvaluationInfo);
+ mDstRefX.ReadData(&dstRefX, arEvaluationInfo);
+ mSrcPivotX.ReadData(&srcPivotX, arEvaluationInfo);
+ mDstPivotX.ReadData(&dstPivotX, arEvaluationInfo);
+ mRefWeight.ReadData(&rw, arEvaluationInfo);
+ mPivotWeight.ReadData(&pw, arEvaluationInfo);
+ mXI.ReadData(&xi,arEvaluationInfo);
+
+ xo = math::xformMul(xi,srcPivotX);
+ xo = math::xformInvMul(srcRefX,xo);
+ xo = math::xformWeight(xo,math::float1(1-pw));
+ xo = math::xformMul(dstRefX,xo);
+ xo = math::xformMulInv(xo,dstPivotX);
+ xo = math::xformBlend(xi,xo,math::float1(rw));
+
+ mXO.WriteData(&xo, arEvaluationInfo);
+ }
+ };
+}
+
+} \ No newline at end of file