6262import java .util .logging .Logger ;
6363
6464/**
65- * The Skinning control deforms a model according to an armature, It handles the
66- * computation of the deformation matrices and performs the transformations on
67- * the mesh
65+ * The `SkinningControl` deforms a 3D model according to an {@link Armature}. It manages the
66+ * computation of deformation matrices and applies these transformations to the mesh,
67+ * supporting both software and hardware-accelerated skinning.
68+ *
69+ * <p>
70+ * **Software Skinning:** Performed on the CPU, offering broader compatibility but
71+ * potentially lower performance for complex models.
6872 * <p>
69- * It can perform software skinning or Hardware skinning
73+ * **Hardware Skinning:** Utilizes the GPU for deformation, providing significantly
74+ * better performance but requiring shader support and having a limit on the number
75+ * of bones (typically 255 in common shaders).
7076 *
71- * @author Rémy Bouquet Based on SkeletonControl by Kirill Vainer
77+ * @author Nehon
7278 */
7379public class SkinningControl extends AbstractControl implements JmeCloneable {
7480
@@ -80,7 +86,7 @@ public class SkinningControl extends AbstractControl implements JmeCloneable {
8086 private Armature armature ;
8187
8288 /**
83- * List of geometries affected by this control.
89+ * A list of geometries that this control will deform .
8490 */
8591 private SafeArrayList <Geometry > targets = new SafeArrayList <>(Geometry .class );
8692
@@ -91,29 +97,32 @@ public class SkinningControl extends AbstractControl implements JmeCloneable {
9197 private boolean meshUpdateRequired = true ;
9298
9399 /**
94- * User wishes to use hardware skinning if available.
100+ * Indicates whether hardware skinning is preferred. If `true` and the GPU
101+ * supports it, hardware skinning will be enabled.
95102 */
96103 private transient boolean hwSkinningPreferred = true ;
97104
98105 /**
99- * Hardware skinning is currently being used.
106+ * Indicates if hardware skinning is currently active and being used.
100107 */
101108 private transient boolean hwSkinningEnabled = false ;
102109
103110 /**
104- * Hardware skinning was tested on this GPU, results
105- * are stored in {@link #hwSkinningSupported} variable .
111+ * Flag indicating whether hardware skinning compatibility has been tested
112+ * on the current GPU. Results are stored in {@link #hwSkinningSupported}.
106113 */
107114 private transient boolean hwSkinningTested = false ;
108115
109116 /**
110- * If hardware skinning was {@link #hwSkinningTested tested}, then
111- * this variable will be set to true if supported, and false if otherwise.
117+ * Stores the result of the hardware skinning compatibility test. `true` if
118+ * supported, `false` otherwise. This is only valid after
119+ * {@link #hwSkinningTested} is `true`.
112120 */
113121 private transient boolean hwSkinningSupported = false ;
114122
115123 /**
116- * Bone offset matrices, recreated each frame
124+ * Bone offset matrices, computed each frame to deform the mesh based on
125+ * the armature's current pose.
117126 */
118127 private transient Matrix4f [] boneOffsetMatrices ;
119128
@@ -127,14 +136,13 @@ protected SkinningControl() {
127136 }
128137
129138 /**
130- * Creates an armature control. The list of targets will be acquired
131- * automatically when the control is attached to a node.
139+ * Creates a new `SkinningControl` for the given armature.
132140 *
133- * @param armature the armature
141+ * @param armature The armature that drives the deformation (not null).
134142 */
135143 public SkinningControl (Armature armature ) {
136144 if (armature == null ) {
137- throw new IllegalArgumentException ("armature cannot be null" );
145+ throw new IllegalArgumentException ("armature cannot be null. " );
138146 }
139147 this .armature = armature ;
140148 }
@@ -146,7 +154,8 @@ private void enableHardwareSkinning() {
146154 numberOfJointsParam .setEnabled (true );
147155 jointMatricesParam .setEnabled (true );
148156
149- // Next full 10 bones (e.g. 30 on 24 bones)
157+ // Calculate the number of bones rounded up to the nearest multiple of 10.
158+ // This is often required by shaders for array uniform declarations.
150159 int numBones = ((armature .getJointCount () / 10 ) + 1 ) * 10 ;
151160 numberOfJointsParam .setValue (numBones );
152161
@@ -187,7 +196,7 @@ private boolean testHardwareSupported(RenderManager renderManager) {
187196 return false ;
188197 }
189198
190- // Temporarily switch to hardware to test shader compilation
199+ // Temporarily enable hardware skinning to test shader compilation.
191200 enableHardwareSkinning ();
192201 boolean hwSkinningEngaged = false ;
193202
@@ -281,7 +290,7 @@ private void controlRenderSoftware() {
281290 for (Geometry geometry : targets ) {
282291 Mesh mesh = geometry .getMesh ();
283292 // NOTE: This assumes code higher up has already ensured this mesh is animated.
284- // Otherwise a crash will happen in skin update.
293+ // Otherwise, a crash will happen in skin update.
285294 applySoftwareSkinning (mesh , boneOffsetMatrices );
286295 }
287296 }
@@ -304,6 +313,7 @@ protected void controlRender(RenderManager rm, ViewPort vp) {
304313 assert !hwSkinningEnabled || (hwSkinningEnabled && hwSkinningTested && hwSkinningSupported );
305314
306315 if (hwSkinningPreferred && !hwSkinningTested ) {
316+ // If hardware skinning is preferred and hasn't been tested yet, test it.
307317 hwSkinningTested = true ;
308318 hwSkinningSupported = testHardwareSupported (rm );
309319
@@ -313,9 +323,12 @@ protected void controlRender(RenderManager rm, ViewPort vp) {
313323 enableSoftwareSkinning ();
314324 }
315325 } else if (hwSkinningPreferred && hwSkinningSupported && !hwSkinningEnabled ) {
326+ // If hardware skinning is preferred, supported, but not yet enabled, enable it.
316327 enableHardwareSkinning ();
317328 hwSkinningEnabled = true ;
329+
318330 } else if (!hwSkinningPreferred && hwSkinningEnabled ) {
331+ // If hardware skinning is no longer preferred but is enabled, switch to software.
319332 enableSoftwareSkinning ();
320333 hwSkinningEnabled = false ;
321334 }
@@ -336,7 +349,12 @@ protected void controlUpdate(float tpf) {
336349 armature .update ();
337350 }
338351
339- //only do this for software updates
352+ /**
353+ * Resets the vertex, normal, and tangent buffers of animated meshes to their
354+ * original bind pose. This is crucial for software skinning to ensure
355+ * transformations are applied from a consistent base.
356+ * This method is only applied when performing software updates.
357+ */
340358 void resetToBind () {
341359 for (Geometry geometry : targets ) {
342360 Mesh mesh = geometry .getMesh ();
@@ -400,10 +418,10 @@ public void cloneFields(Cloner cloner, Object original) {
400418 }
401419
402420 /**
403- * Access the attachments node of the named bone. If the bone doesn't
404- * already have an attachments node, create one and attach it to the scene
405- * graph. Models and effects attached to the attachments node will follow
406- * the bone's motions .
421+ * Provides access to the attachment node for a specific joint in the armature.
422+ * If an attachment node does not already exist for the named joint, one will be
423+ * created and attached to the scene graph. Models or effects attached to this
424+ * node will follow the motion of the corresponding bone .
407425 *
408426 * @param jointName the name of the joint
409427 * @return the attachments node of the joint
@@ -419,7 +437,7 @@ public Node getAttachmentsNode(String jointName) {
419437 int jointIndex = armature .getJointIndex (joint );
420438 Node attachNode = joint .getAttachmentsNode (jointIndex , targets );
421439
422- // Select a node to parent the attachments node.
440+ // Determine the appropriate parent for the attachment node.
423441 Node parent ;
424442 if (spatial instanceof Node ) {
425443 parent = (Node ) spatial ; // the usual case
@@ -432,18 +450,19 @@ public Node getAttachmentsNode(String jointName) {
432450 }
433451
434452 /**
435- * returns the armature of this control
453+ * Returns the armature associated with this skinning control.
436454 *
437- * @return the pre-existing instance
455+ * @return The pre-existing `Armature` instance.
438456 */
439457 public Armature getArmature () {
440458 return armature ;
441459 }
442460
443461 /**
444- * Enumerate the target meshes of this control.
462+ * Returns an array containing all the target meshes that this control
463+ * is currently affecting.
445464 *
446- * @return a new array
465+ * @return A new array of `Mesh` objects.
447466 */
448467 public Mesh [] getTargets () {
449468 Mesh [] result = new Mesh [targets .size ()];
@@ -458,10 +477,11 @@ public Mesh[] getTargets() {
458477 }
459478
460479 /**
461- * Update the mesh according to the given transformation matrices
480+ * Applies software skinning transformations to the given mesh using the
481+ * provided bone offset matrices.
462482 *
463- * @param mesh then mesh
464- * @param offsetMatrices the transformation matrices to apply
483+ * @param mesh The mesh to deform.
484+ * @param offsetMatrices The array of transformation matrices for each bone.
465485 */
466486 private void applySoftwareSkinning (Mesh mesh , Matrix4f [] offsetMatrices ) {
467487
@@ -476,10 +496,12 @@ private void applySoftwareSkinning(Mesh mesh, Matrix4f[] offsetMatrices) {
476496 }
477497
478498 /**
479- * Method to apply skinning transforms to a mesh's buffers
499+ * Applies skinning transformations to a mesh's position and normal buffers.
500+ * This method iterates through each vertex, applies the weighted sum of
501+ * bone transformations, and updates the vertex buffers.
480502 *
481- * @param mesh the mesh
482- * @param offsetMatrices the offset matrices to apply
503+ * @param mesh The mesh to apply skinning to.
504+ * @param offsetMatrices The bone offset matrices to use for transformation.
483505 */
484506 private void applySkinning (Mesh mesh , Matrix4f [] offsetMatrices ) {
485507 int maxWeightsPerVert = mesh .getMaxNumWeights ();
@@ -577,15 +599,13 @@ private void applySkinning(Mesh mesh, Matrix4f[] offsetMatrices) {
577599 }
578600
579601 /**
580- * Specific method for skinning with tangents to avoid cluttering the
581- * classic skinning calculation with null checks that would slow down the
582- * process even if tangents don't have to be computed. Also the iteration
583- * has additional indexes since tangent has 4 components instead of 3 for
584- * pos and norm
602+ * Applies skinning transformations to a mesh's position, normal, and tangent buffers.
603+ * This method is specifically designed for meshes that include tangent data,
604+ * ensuring proper deformation of tangents alongside positions and normals.
585605 *
586- * @param mesh the mesh
587- * @param offsetMatrices the offsetMatrices to apply
588- * @param tb the tangent vertexBuffer
606+ * @param mesh The mesh to apply skinning to.
607+ * @param offsetMatrices The bone offset matrices to use for transformation.
608+ * @param tb The tangent `VertexBuffer`.
589609 */
590610 private void applySkinningTangents (Mesh mesh , Matrix4f [] offsetMatrices , VertexBuffer tb ) {
591611 int maxWeightsPerVert = mesh .getMaxNumWeights ();
0 commit comments