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