Skinning
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset> <contributor> <author>gcorson</author> <authoring_tool>Maya 8.0 | ColladaMaya v3.02 | FCollada v3.2</authoring_tool> <comments>Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
curveConstrainSampling=0;exportCameraAsLookat=0; exportLights=1;exportCameras=1;exportJointsAndSkin=1; exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0; exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0; exportTexTangents=0;exportConstraints=1;exportPhysics=0;exportXRefs=1; dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
<source_data>file:///C:/Documents%20and%20Settings/gcorson/Desktop/Physics%20Tests/New_Project/scenes/bind%20sample.mb</source_data> </contributor> <created>2007-04-04T23:08:51Z</created> <modified>2007-04-04T23:08:51Z</modified> <unit meter="0.01" name="centimeter"></unit> <up_axis>Y_UP</up_axis> </asset> <library_materials> <material id="lambert1" name="lambert1"> <instance_effect url="#lambert1-fx"></instance_effect> </material> </library_materials> <library_effects> <effect id="lambert1-fx"> <profile_COMMON> <technique sid="common"> <lambert> <emission> <color>0 0 0 1</color> </emission> <ambient> <color>0 0 0 1</color> </ambient> <diffuse> <color>0.5 0.5 0.5 1</color> </diffuse> <transparent opaque="A_ONE"> <color>0 0 0 1</color> </transparent> <transparency> <float>1</float> </transparency> <index_of_refraction> <float>1</float> </index_of_refraction> </lambert> <extra> <technique profile="FCOLLADA"></technique> </extra> </technique> </profile_COMMON> </effect> </library_effects> <library_geometries>
This is a pretty standard mesh for use in our skin sample. It's a 6 sided cylinder divided into 6 sections with a total of 42 vertices.
<geometry id="pCylinderShape1" name="pCylinderShape1"> <mesh>
<float_array id="pCylinderShape1-positions-array" count="126">20 -90 -34.641 -20 -90 -34.641 -40 -90 -0.000005 -20 -90 34.641 20 -90 34.641 40 -90 0 20 -60 -34.641 -20 -60 -34.641 -40 -60 -0.000005 -20 -60 34.641 20 -60 34.641 40 -60 0 20 -30 -34.641 -20 -30 -34.641 -40 -30 -0.000005 -20 -30 34.641 20 -30 34.641 40 -30 0 20 0 -34.641 -20 0 -34.641 -40 0 -0.000005 -20 0 34.641 20 0 34.641 40 0 0 20 30 -34.641 -20 30 -34.641 -40 30 -0.000005 -20 30 34.641 20 30 34.641 40 30 0 20 60 -34.641 -20 60 -34.641 -40 60 -0.000005 -20 60 34.641 20 60 34.641 40 60 0 20 90 -34.641 -20 90 -34.641 -40 90 -0.000005 -20 90 34.641 20 90 34.641 40 90 0</float_array>
<technique_common>
<accessor source="#pCylinderShape1-positions-array" count="42" stride="3">
<param name="X" type="float"></param>
<param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
<float_array id="pCylinderShape1-normals-array" count="288">0.000000 0 -1 0.000000 0 -1 0.000000 0 -1 0.000000 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866026 0 0.5 0.866026 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.000000 0 -1 0.000000 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.000000 0 -1 0.000000 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.000000 0 -1 0.000000 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.000000 0 -1 0.000000 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.000000 0 -1 0.000000 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0.866026 0 0.5 0.866026 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0</float_array>
<technique_common>
<accessor source="#pCylinderShape1-normals-array" count="96" stride="3">
<param name="X" type="float"></param>
<param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
<float_array id="pCylinderShape1-map1-array" count="122">0.578125 0.020933 0.421875 0.020933 0.34375 0.15625 0.421875 0.291566 0.578125 0.291566 0.65625 0.15625 0.375 0.3125 0.416667 0.3125 0.458333 0.3125 0.5 0.3125 0.541667 0.3125 0.583333 0.3125 0.625 0.3125 0.375 0.375157 0.416667 0.375157 0.458333 0.375157 0.5 0.375157 0.541667 0.375157 0.583333 0.375157 0.625 0.375157 0.375 0.437813 0.416667 0.437813 0.458333 0.437813 0.5 0.437813 0.541667 0.437813 0.583333 0.437813 0.625 0.437813 0.375 0.50047 0.416667 0.50047 0.458333 0.50047 0.5 0.50047 0.541667 0.50047 0.583333 0.50047 0.625 0.50047 0.375 0.563127 0.416667 0.563127 0.458333 0.563127 0.5 0.563127 0.541667 0.563127 0.583333 0.563127 0.625 0.563127 0.375 0.625783 0.416667 0.625783 0.458333 0.625783 0.5 0.625783 0.541667 0.625783 0.583333 0.625783 0.625 0.625783 0.375 0.68844 0.416667 0.68844 0.458333 0.68844 0.5 0.68844 0.541667 0.68844 0.583333 0.68844 0.625 0.68844 0.578125 0.708434 0.421875 0.708434 0.34375 0.84375 0.421875 0.979066 0.578125 0.979066 0.65625 0.84375</float_array>
<technique_common>
<accessor source="#pCylinderShape1-map1-array" count="61" stride="2">
<param name="S" type="float"></param>
<param name="T" type="float"></param>
</accessor>
</technique_common>
<vertices id="pCylinderShape1-vertices"> <input semantic="POSITION" source="#pCylinderShape1-positions"></input> </vertices> <polylist material="initialShadingGroup" count="38"> <input semantic="VERTEX" source="#pCylinderShape1-vertices" offset="0"></input> <input semantic="NORMAL" source="#pCylinderShape1-normals" offset="1"></input> <input semantic="TEXCOORD" source="#pCylinderShape1-map1" offset="2" set="0"></input> <vcount>4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 6 6</vcount> <p>0 0 6 1 1 7 7 2 14 6 3 13 1 4 7 2 5 8 8 6 15 7 7 14 2 8 8 3 9 9 9 10 16 8 11 15 3 12 9 4 13 10 10 14 17 9 15 16 4 16 10 5 17 11 11 18 18 10 19 17 5 20 11 0 21 12 6 22 19 11 23 18 6 3 13 7 2 14 13 24 21 12 25 20 7 7 14 8 6 15 14 26 22 13 27 21 8 11 15 9 10 16 15 28 23 14 29 22 9 15 16 10 14 17 16 30 24 15 31 23 10 19 17 11 18 18 17 32 25 16 33 24 11 23 18 6 22 19 12 34 26 17 35 25 12 25 20 13 24 21 19 36 28 18 37 27 13 27 21 14 26 22 20 38 29 19 39 28 14 29 22 15 28 23 21 40 30 20 41 29 15 31 23 16 30 24 22 42 31 21 43 30 16 33 24 17 32 25 23 44 32 22 45 31 17 35 25 12 34 26 18 46 33 23 47 32 18 37 27 19 36 28 25 48 35 24 49 34 19 39 28 20 38 29 26 50 36 25 51 35 20 41 29 21 40 30 27 52 37 26 53 36 21 43 30 22 42 31 28 54 38 27 55 37 22 45 31 23 44 32 29 56 39 28 57 38 23 47 32 18 46 33 24 58 40 29 59 39 24 49 34 25 48 35 31 60 42 30 61 41 25 51 35 26 50 36 32 62 43 31 63 42 26 53 36 27 52 37 33 64 44 32 65 43 27 55 37 28 54 38 34 66 45 33 67 44 28 57 38 29 56 39 35 68 46 34 69 45 29 59 39 24 58 40 30 70 47 35 71 46 30 61 41 31 60 42 37 72 49 36 73 48 31 63 42 32 62 43 38 74 50 37 75 49 32 65 43 33 64 44 39 76 51 38 77 50 33 67 44 34 66 45 40 78 52 39 79 51 34 69 45 35 68 46 41 80 53 40 81 52 35 71 46 30 70 47 36 82 54 41 83 53 0 84 0 5 85 5 4 86 4 3 87 3 2 88 2 1 89 1 36 90 59 37 91 58 38 92 57 39 93 56 40 94 55 41 95 60</p> </polylist> </mesh> <extra> <technique profile="MAYA"> <double_sided>1</double_sided> </technique> </extra> </geometry> </library_geometries> <library_controllers>
This is the start of the controller that takes the geometry in pCylinderShape1 and defines how to skin it.
<controller id="pCylinderShape1-skin" name="skinCluster1"> <skin source="#pCylinderShape1">
The bind shape matrix describes how to transform the pCylinderShape1 geometry into the right coordinate system for use with the joints. In this case we do an +90 Y transform because the pCylinderShape1 geometry was initially a 180 unit long cylinder with 0,0,0 at it's center. This moves it so 0,0,0 is at the base of the cylinder.
<bind_shape_matrix> 1 0 0 0 0 1 0 90 0 0 1 0 0 0 0 1 </bind_shape_matrix>
This source contains a list of the SIDs of the 7 joints that will influence the skin. You can also use an IDREF_Array here but use of SIDs is prefered because they allow a controller to be used several times with different skeletons.
<Name_array id="pCylinderShape1-skin-joints-array" count="7">joint1 joint2 joint3 joint4 joint5 joint6 joint7</Name_array>
<technique_common>
<accessor source="#pCylinderShape1-skin-joints-array" count="7" stride="1">
<param name="JOINT" type="Name"></param>
</accessor>
</technique_common>
This source defines the inverse bind matrix for each joint, these are used to bring coordinates being skinned into the same space as each joint. Note that in this case the joints begin at 0,0,0 and move up 30 units for each joint, so the inverse bind matrices are the opposite of that.
<float_array id="pCylinderShape1-skin-bind_poses-array" count="112">
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 -30
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 -60
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 -90
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 -120
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 -150
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 -180
0 0 1 0
0 0 0 1
</float_array>
<technique_common>
<accessor source="#pCylinderShape1-skin-bind_poses-array" count="7" stride="16">
<param name="TRANSFORM" type="float4x4"></param>
</accessor>
</technique_common>
This source defines a weight for each vertex and each joint. The weight defines how much a particular joint will contribute to moving a particular vertex's position. This allows several joints to influence vertices by different amounts, giving a nice smooth bend.
Since there are 42 vertices and 7 joints there should be at most 294 weights. In this case the skinning algorithm was told that each vertex should be effected by the 5 nearest joints so we have 5 weights per vertex giving a total of 210. Maya has thrown in an extra weight of 1 at the beginning giving us a total of 211.
Weights 1-6 will be applied to the first vertex, you can see how they work. The first weight represents the closest joint to the vertex and has the largest value, the remaining 4 weights get smaller and smaller as the associated joint gets farther from the vertex.
<float_array id="pCylinderShape1-skin-weights-array" count="211">1 0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487 0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025</float_array>
<technique_common>
<accessor source="#pCylinderShape1-skin-weights-array" count="211" stride="1">
<param name="WEIGHT" type="float"></param>
</accessor>
</technique_common>
<joints> <input semantic="JOINT" source="#pCylinderShape1-skin-joints"></input> <input semantic="INV_BIND_MATRIX" source="#pCylinderShape1-skin-bind_poses"></input> </joints>
The vertex_weights tag associates the weights and joints from the previously defined sources with the vertices in the geometry being skinned. Each entry in this list matches a vertex in the original geometry, so the count here should be the same as the count in the geometry being skinned.
Each weight/joint pair is referred to as an "influence", a vertex can have any number of influences applied to it. The <vcount> value for a vertex defines the number of influences on that vertex. In this case every vertex has 5 influences. The values in the <v> array are the indices of the joint and weight that make up that influence.
<vertex_weights count="42"> <input semantic="JOINT" source="#pCylinderShape1-skin-joints" offset="0"></input> <input semantic="WEIGHT" source="#pCylinderShape1-skin-weights" offset="1"></input> <vcount>5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </vcount> <v>0 1 1 2 2 3 3 4 4 5 0 6 1 7 2 8 3 9 4 10 0 11 1 12 2 13 3 14 4 15 0 16 1 17 2 18 3 19 4 20 0 21 1 22 2 23 3 24 4 25 0 26 1 27 2 28 3 29 4 30 0 31 1 32 2 33 3 34 4 35 0 36 1 37 2 38 3 39 4 40 0 41 1 42 2 43 3 44 4 45 0 46 1 47 2 48 3 49 4 50 0 51 1 52 2 53 3 54 4 55 0 56 1 57 2 58 3 59 4 60 0 61 1 62 2 63 3 64 4 65 0 66 1 67 2 68 3 69 4 70 0 71 1 72 2 73 3 74 4 75 0 76 1 77 2 78 3 79 4 80 0 81 1 82 2 83 3 84 4 85 0 86 1 87 2 88 3 89 4 90 0 91 1 92 2 93 3 94 4 95 0 96 1 97 2 98 3 99 4 100 0 101 1 102 2 103 3 104 4 105 0 106 1 107 2 108 3 109 4 110 0 111 1 112 2 113 3 114 4 115 0 116 1 117 2 118 3 119 4 120 2 121 3 122 4 123 5 124 6 125 2 126 3 127 4 128 5 129 6 130 1 131 2 132 3 133 4 134 5 135 1 136 2 137 3 138 4 139 5 140 1 141 2 142 3 143 4 144 5 145 1 146 2 147 3 148 4 149 5 150 2 151 3 152 4 153 5 154 6 155 2 156 3 157 4 158 5 159 6 160 2 161 3 162 4 163 5 164 6 165 2 166 3 167 4 168 5 169 6 170 2 171 3 172 4 173 5 174 6 175 2 176 3 177 4 178 5 179 6 180 2 181 3 182 4 183 5 184 6 185 2 186 3 187 4 188 5 189 6 190 2 191 3 192 4 193 5 194 6 195 2 196 3 197 4 198 5 199 6 200 2 201 3 202 4 203 5 204 6 205 2 206 3 207 4 208 5 209 6 210</v> </vertex_weights> </skin> </controller> </library_controllers> <library_visual_scenes> <visual_scene id="VisualSceneNode" name="bind_sample">
This is the node hierarchy that represents the skeleton of the skinned object. The first node has an ID to act as a starting point for SID searches, the rest of the nodes in the hierarchy only need SIDs. It is preferable to use SIDs to identify the joints of the skeleton because it allows the skin controller to be used several times with different skeletons. For example we could have a second joint hierarchy using the same SIDs but with a different id (like skeleton2_root) on the first node and different transforms.
In this example the root joint of the skeleton is 20 units above the ground. All the other joints are 30 units apart in the Y direction.
<node id="skeleton_root" name="joint1" sid="joint1" type="JOINT"> <translate sid="translate">0 20 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate>
Some people try to put the instance_controller here. This will not work correctly for a skin because the skinning process has already transformed all the vertices using the full transform in the joints that the skin controller references. This means the data coming out of the instance_controller is effectively in world space. If we put the instance_controller here, the geometry coming out of it would be transformed (again) by this node, moving it up an additional 20 units.
<node name="joint2" sid="joint2" type="JOINT"> <translate sid="translate">0 30 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate> <node name="joint3" sid="joint3" type="JOINT"> <translate sid="translate">0 30 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate> <node name="joint4" sid="joint4" type="JOINT"> <translate sid="translate">0 30 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate> <node name="joint5" sid="joint5" type="JOINT"> <translate sid="translate">0 30 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate> <rotate sid="rotateZ">0 0 1 1.22906</rotate> <node name="joint6" sid="joint6" type="JOINT"> <translate sid="translate">0 30 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate> <node name="joint7" sid="joint7" type="JOINT"> <translate sid="translate">0 30 0</translate> <rotate sid="jointOrientZ">0 0 1 0</rotate> <rotate sid="jointOrientY">0 1 0 0</rotate> <rotate sid="jointOrientX">1 0 0 0</rotate> </node> </node> </node> </node> </node> </node> </node>
This node is where the skinned geometry is instantiated. The geometry that comes out of a skin controller has already been transformed by the joints referenced in the skin which puts the geometry in world space. This is why we are instantiating the skin at the root of the hierarchy rather than up in the "skeleton_root" node
<node id="pCylinder1" name="pCylinder1" type="NODE"> <instance_controller url="#pCylinderShape1-skin">
The skeleton tag tells the controller where it should start searching for any SIDs found in the skin. This allows the same controller to be re-used with different joint hierarchies.
<skeleton>#skeleton_root</skeleton> <bind_material> <technique_common> <instance_material symbol="initialShadingGroup" target="#lambert1"></instance_material> </technique_common> </bind_material> </instance_controller> </node> <extra> <technique profile="FCOLLADA"> <start_time>0.041666</start_time> <end_time>2</end_time> </technique> </extra> </visual_scene> </library_visual_scenes> <scene> <instance_visual_scene url="#VisualSceneNode"></instance_visual_scene> </scene>
</COLLADA>