1 /* 2 Copyright (C) 2005-2007 Feeling Software Inc. 3 Portions of the code are: 4 Copyright (C) 2005-2007 Sony Computer Entertainment America 5 6 MIT License: http://www.opensource.org/licenses/mit-license.php 7 */ 8 /* 9 Based on the FS Import classes: 10 Copyright (C) 2005-2006 Feeling Software Inc 11 Copyright (C) 2005-2006 Autodesk Media Entertainment 12 MIT License: http://www.opensource.org/licenses/mit-license.php 13 */ 14 15 /** 16 @file FCDSkinController.h 17 This file contains the FCDSkinController class. 18 */ 19 20 #ifndef _FCD_SKIN_CONTROLLER_H_ 21 #define _FCD_SKIN_CONTROLLER_H_ 22 23 #ifndef __FCD_OBJECT_H_ 24 #include "FCDocument/FCDObject.h" 25 #endif // __FCD_OBJECT_H_ 26 #ifndef _FU_PARAMETER_H_ 27 #include "FUtils/FUParameter.h" 28 #endif // _FU_PARAMETER_H_ 29 30 class FCDocument; 31 class FCDController; 32 class FCDGeometry; 33 class FCDSceneNode; 34 class FCDEntityReference; 35 class FUUri; 36 37 /** 38 A COLLADA weighted vertex-joint binding used in skinning. 39 @ingroup FCDGeometry 40 */ 41 struct FCOLLADA_EXPORT FCDJointWeightPair 42 { 43 /** Default constructor: sets both the joint index and the weight to zero. */ FCDJointWeightPairFCDJointWeightPair44 FCDJointWeightPair() { jointIndex = -1; weight = 0.0f; } 45 46 /** Constructor: sets the joint index and the weight to the given values. 47 @param _jointIndex The jointIndex. 48 @param _weight Its weight. */ FCDJointWeightPairFCDJointWeightPair49 FCDJointWeightPair(int32 _jointIndex, float _weight) { jointIndex = _jointIndex; weight = _weight; } 50 51 /** A joint index. 52 Use this index within the skin's joint list. 53 Look-out for the special joint index: -1. It indicates that 54 the bind-shape position should be used. */ 55 int32 jointIndex; 56 57 /** The weight of this influence on the vertex. */ 58 float weight; 59 }; 60 61 /** 62 A COLLADA skin controller vertex. 63 This structure contains a list of joint-weight pairs that defines 64 how to modify a given mesh vertex in order to skin it properly. 65 @ingroup FCDGeometry 66 */ 67 class FCOLLADA_EXPORT FCDSkinControllerVertex 68 { 69 private: 70 fm::vector<FCDJointWeightPair> pairs; 71 72 public: 73 /** Retrieve the number of joint-weight pairs defined for this vertex. 74 @return The number of joint-weight pairs. */ GetPairCount()75 inline size_t GetPairCount() const { return pairs.size(); } 76 77 /** Sets the number of joint-weight pairs defined for this vertex. 78 @param count The number of joint-weight pairs defined for this vertex. */ 79 void SetPairCount(size_t count); 80 81 /** Retrieves a joint-weight pair. 82 @param index The index of the joint-weight pair. 83 @return The joint-weight pair at the given index. */ GetPair(size_t index)84 inline FCDJointWeightPair* GetPair(size_t index) { FUAssert(index < pairs.size(), return NULL); return &(pairs.at(index)); } GetPair(size_t index)85 inline const FCDJointWeightPair* GetPair(size_t index) const { FUAssert(index < pairs.size(), return NULL); return &(pairs.at(index)); } /**< See above. */ 86 87 /** Adds a new joint-weight pair to this vertex. 88 No verification will be made to ensure that the sum of the weights equal 1.0. 89 @param jointIndex The index of the joint within the skin controller's joint list. 90 @param weight The influence weight for this joint, on this vertex. */ 91 void AddPair(int32 jointIndex, float weight); 92 }; 93 94 /** 95 A COLLADA skin controller joint. 96 The controller does not reference the scene nodes directly: that's the instance's job. 97 Instead, the skin controllers keeps track of the sub-ids of the scene nodes and their 98 bind poses. 99 @ingroup FCDGeometry 100 */ 101 class FCOLLADA_EXPORT FCDSkinControllerJoint 102 { 103 private: 104 fm::string id; 105 FMMatrix44 bindPoseInverse; 106 107 public: 108 /** Retrieves the identifier of the scene node(s) representing this joint. 109 @return The identifier of the joint. */ GetId()110 inline const fm::string& GetId() const { return id; } 111 112 /** Sets the identifier of the scene node(s) representing this joint. 113 @param id The identifier of the joint. */ 114 void SetId(const fm::string& id); 115 116 /** Retrieves the inverse bind-pose matrix of the joint. 117 @return The inverse bind-pose matrix. */ GetBindPoseInverse()118 inline const FMMatrix44& GetBindPoseInverse() const { return bindPoseInverse; } 119 120 /** Sets the inverse bind-pose matrix of the joint. 121 @param inverseBindPose The inverse bind-pose matrix. */ SetBindPoseInverse(const FMMatrix44 & inverseBindPose)122 inline void SetBindPoseInverse(const FMMatrix44& inverseBindPose) { bindPoseInverse = inverseBindPose; } 123 }; 124 125 /** 126 A COLLADA skin controller. 127 128 The skin controller holds the information to skin a geometric object. 129 That information includes a target/base entity and its bind-pose matrix, 130 a list of joints and their bind pose and the influences for the joints. 131 132 The influences are a list, for each vertex of the target entity, of which 133 joints affect the vertex and by how much. 134 135 @ingroup FCDGeometry 136 */ 137 138 class FCOLLADA_EXPORT FCDSkinController : public FCDObject 139 { 140 private: 141 DeclareObjectType(FCDObject); 142 FCDController* parent; 143 144 FUObjectRef<FCDEntityReference> target; 145 DeclareParameter(FMMatrix44, FUParameterQualifiers::SIMPLE, bindShapeTransform, FC("Base Mesh Bind-pose Transform")); 146 147 fm::vector<FCDSkinControllerJoint> joints; 148 fm::vector<FCDSkinControllerVertex> influences; 149 150 public: 151 /** Constructor: do not use directly. 152 Instead, use the FCDController::CreateSkinController function. 153 @param document The COLLADA document that owns the skin. 154 @param parent The COLLADA controller that contains this skin. */ 155 FCDSkinController(FCDocument* document, FCDController* parent); 156 157 /** Destructor. */ 158 virtual ~FCDSkinController(); 159 160 /** Retrieves the parent entity for the morpher. 161 @return The parent controller entity. */ GetParent()162 inline FCDController* GetParent() { return parent; } GetParent()163 inline const FCDController* GetParent() const { return parent; } /**< See above. */ 164 165 /** Retrieves the target entity. 166 This entity may be a geometric entity or another controller. 167 @return The target entity. */ 168 FCDEntity* GetTarget(); 169 const FCDEntity* GetTarget() const; 170 171 /** Retrieves the Uri to the skin target. 172 This can be an internal or external link 173 @return The uri to the target */ 174 FUUri GetTargetUri() const; 175 176 /** Sets the URI of the target mesh. 177 @param uri The Uri to a local or external controller or geometry */ 178 void SetTargetUri(const FUUri& uri); 179 180 /** Sets the target entity. 181 This function has very important ramifications, as the number 182 of vertices may change. The influences list will be modified to 183 follow the number of vertices. 184 This entity may be a geometric entity or another controller. 185 @param _target The target entity. */ 186 void SetTarget(FCDEntity* _target); 187 188 /** Retrieves the bind-pose transform of the target entity. 189 @return The bind-pose transform. */ GetBindShapeTransform()190 const FMMatrix44& GetBindShapeTransform() const { return *bindShapeTransform; } 191 192 /** Sets the bind-pose transform of the target entity. 193 @param bindPose The bind-pose transform. */ SetBindShapeTransform(const FMMatrix44 & bindPose)194 void SetBindShapeTransform(const FMMatrix44& bindPose) { bindShapeTransform = bindPose; SetDirtyFlag(); } 195 196 /** Retrieves the number of joints that influence the skin. 197 @return The number of joints. */ GetJointCount()198 inline size_t GetJointCount() const { return joints.size(); } 199 200 /** Sets the number of joints that influence the skin. 201 @param count The number of joints that influence the skin. */ 202 void SetJointCount(size_t count); 203 204 /** Retrieves the list of joints that influence the skin. 205 @return The list of joints that influence the skin. */ GetJoints()206 inline FCDSkinControllerJoint* GetJoints() { return !joints.empty() ? &(joints.front()) : NULL; } GetJoints()207 inline const FCDSkinControllerJoint* GetJoints() const { return !joints.empty() ? &(joints.front()) : NULL; } /**< See above. */ 208 209 /** Retrieves an indexed joint from the list of joints that influence this skin. 210 @param index The index of the joint. 211 @return The joint at the given index. */ GetJoint(size_t index)212 inline FCDSkinControllerJoint* GetJoint(size_t index) { FUAssert(index < joints.size(), return NULL); return &joints.at(index); } GetJoint(size_t index)213 inline const FCDSkinControllerJoint* GetJoint(size_t index) const { FUAssert(index < joints.size(), return NULL); return &joints.at(index); } /**< See above. */ 214 215 /** Adds a joint to influence the skin. 216 @param jSubId The sub-id of the scene node(s) that represent the joint. 217 @param inverseBindPose The inverse bind-pose of the joint. */ 218 FCDSkinControllerJoint* AddJoint(const fm::string jSubId = "", const FMMatrix44& inverseBindPose = FMMatrix44::Identity); 219 220 /** Retrieves the number of vertices with influences defined in the skin controller. 221 @return The number of influenced vertices. */ GetInfluenceCount()222 inline size_t GetInfluenceCount() const { return influences.size(); } 223 224 /** Sets the number of vertices with influences defined in the skin controller. 225 @param count The number of influences vertices. */ 226 void SetInfluenceCount(size_t count); 227 228 /** Retrieves a list of the per-vertex influences for the skin. 229 @return The list of per-vertex influences. */ GetVertexInfluences()230 inline FCDSkinControllerVertex* GetVertexInfluences() { return influences.size() > 0 ? &(influences.front()) : NULL; } GetVertexInfluences()231 inline const FCDSkinControllerVertex* GetVertexInfluences() const { return influences.size() > 0 ? &(influences.front()) : NULL; } /**< See above. */ 232 233 /** Retrieves the per-vertex influences for a given vertex. 234 @param index The vertex index. 235 @return The per-vertex influences. */ GetVertexInfluence(size_t index)236 inline FCDSkinControllerVertex* GetVertexInfluence(size_t index) { FUAssert(index < influences.size(), return NULL); return &influences.at(index); } GetVertexInfluence(size_t index)237 inline const FCDSkinControllerVertex* GetVertexInfluence(size_t index) const { FUAssert(index < influences.size(), return NULL); return &influences.at(index); } /**< See above. */ 238 239 /** Reduces the number of joints influencing each vertex. 240 1) All the influences with a weight less than the minimum will be removed. 241 2) If a vertex has more influences than the given maximum, they will be sorted and the 242 most important influences will be kept. 243 If some of the influences for a vertex are removed, the weight will be normalized. 244 @param maxInfluenceCount The maximum number of influence to keep for each vertex. 245 @param minimumWeight The smallest weight to keep. */ 246 void ReduceInfluences(uint32 maxInfluenceCount, float minimumWeight=0.0f); 247 }; 248 249 #endif // _FCD_SKIN_CONTROLLER_H_ 250 251