|
@@ -1,7 +1,5 @@
|
|
|
-package com.jme3.scene.debug.custom;
|
|
|
-
|
|
|
/*
|
|
|
- * Copyright (c) 2009-2021 jMonkeyEngine
|
|
|
+ * Copyright (c) 2009-2025 jMonkeyEngine
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -31,9 +29,11 @@ package com.jme3.scene.debug.custom;
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
*/
|
|
|
+package com.jme3.scene.debug.custom;
|
|
|
|
|
|
import com.jme3.anim.Armature;
|
|
|
import com.jme3.anim.Joint;
|
|
|
+import com.jme3.anim.SkinningControl;
|
|
|
import com.jme3.asset.AssetManager;
|
|
|
import com.jme3.collision.Collidable;
|
|
|
import com.jme3.collision.CollisionResults;
|
|
@@ -55,104 +55,166 @@ import java.util.List;
|
|
|
public class ArmatureDebugger extends Node {
|
|
|
|
|
|
/**
|
|
|
- * The lines of the bones or the wires between their heads.
|
|
|
+ * The node responsible for rendering the bones/wires and their outlines.
|
|
|
*/
|
|
|
private ArmatureNode armatureNode;
|
|
|
-
|
|
|
+ /**
|
|
|
+ * The {@link Armature} instance being debugged.
|
|
|
+ */
|
|
|
private Armature armature;
|
|
|
-
|
|
|
+ /**
|
|
|
+ * A node containing all {@link Geometry} objects representing the joint points.
|
|
|
+ */
|
|
|
private Node joints;
|
|
|
+ /**
|
|
|
+ * A node containing all {@link Geometry} objects representing the bone outlines.
|
|
|
+ */
|
|
|
private Node outlines;
|
|
|
+ /**
|
|
|
+ * A node containing all {@link Geometry} objects representing the bone wires/lines.
|
|
|
+ */
|
|
|
private Node wires;
|
|
|
/**
|
|
|
* The dotted lines between a bone's tail and the had of its children. Not
|
|
|
* available if the length data was not provided.
|
|
|
*/
|
|
|
private ArmatureInterJointsWire interJointWires;
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Default constructor for `ArmatureDebugger`.
|
|
|
+ * Use {@link #ArmatureDebugger(String, Armature, List)} for a functional instance.
|
|
|
+ */
|
|
|
public ArmatureDebugger() {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Creates a debugger with no length data. The wires will be a connection
|
|
|
- * between the bones' heads only. The points will show the bones' heads only
|
|
|
- * and no dotted line of inter bones connection will be visible.
|
|
|
+ * Convenience constructor that creates an {@code ArmatureDebugger} and immediately
|
|
|
+ * initializes its materials based on the provided {@code AssetManager}
|
|
|
+ * and {@code SkinningControl}.
|
|
|
+ *
|
|
|
+ * @param assetManager The {@link AssetManager} used to load textures and materials
|
|
|
+ * for the debug visualization.
|
|
|
+ * @param skControl The {@link SkinningControl} from which to extract the
|
|
|
+ * {@link Armature} and its associated joints.
|
|
|
+ */
|
|
|
+ public ArmatureDebugger(AssetManager assetManager, SkinningControl skControl) {
|
|
|
+ this(null, skControl.getArmature(), skControl.getArmature().getJointList());
|
|
|
+ initialize(assetManager, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Creates an `ArmatureDebugger` instance without explicit bone length data.
|
|
|
+ * In this configuration, the visual representation will consist of wires
|
|
|
+ * connecting the bone heads, and points representing the bone heads.
|
|
|
+ * No dotted lines for inter-bone connections will be visible.
|
|
|
*
|
|
|
- * @param name the name of the debugger's node
|
|
|
- * @param armature the armature that will be shown
|
|
|
- * @param deformingJoints a list of joints
|
|
|
+ * @param name The name of this debugger's root node.
|
|
|
+ * @param armature The {@link Armature} to be visualized.
|
|
|
+ * @param deformingJoints A {@link List} of {@link Joint} objects that are
|
|
|
+ * considered deforming joints.
|
|
|
*/
|
|
|
public ArmatureDebugger(String name, Armature armature, List<Joint> deformingJoints) {
|
|
|
super(name);
|
|
|
this.armature = armature;
|
|
|
+ // Ensure the armature's world transforms are up-to-date before visualization.
|
|
|
armature.update();
|
|
|
|
|
|
+ // Initialize the main container nodes for different visual elements.
|
|
|
joints = new Node("joints");
|
|
|
outlines = new Node("outlines");
|
|
|
wires = new Node("bones");
|
|
|
this.attachChild(joints);
|
|
|
this.attachChild(outlines);
|
|
|
this.attachChild(wires);
|
|
|
- Node ndJoints = new Node("non deforming Joints");
|
|
|
- Node ndOutlines = new Node("non deforming Joints outlines");
|
|
|
- Node ndWires = new Node("non deforming Joints wires");
|
|
|
+
|
|
|
+ // Create child nodes specifically for non-deforming joints' visualization
|
|
|
+ Node ndJoints = new Node("NonDeformingJoints");
|
|
|
+ Node ndOutlines = new Node("NonDeformingOutlines");
|
|
|
+ Node ndWires = new Node("NonDeformingWires");
|
|
|
joints.attachChild(ndJoints);
|
|
|
outlines.attachChild(ndOutlines);
|
|
|
wires.attachChild(ndWires);
|
|
|
- Node outlineDashed = new Node("Outlines Dashed");
|
|
|
- Node wiresDashed = new Node("Wires Dashed");
|
|
|
- wiresDashed.attachChild(new Node("dashed non defrom"));
|
|
|
- outlineDashed.attachChild(new Node("dashed non defrom"));
|
|
|
+
|
|
|
+ Node outlineDashed = new Node("DashedOutlines");
|
|
|
+ Node wiresDashed = new Node("DashedWires");
|
|
|
+ wiresDashed.attachChild(new Node("DashedNonDeformingWires"));
|
|
|
+ outlineDashed.attachChild(new Node("DashedNonDeformingOutlines"));
|
|
|
outlines.attachChild(outlineDashed);
|
|
|
wires.attachChild(wiresDashed);
|
|
|
|
|
|
+ // Initialize the core ArmatureNode which handles the actual mesh generation.
|
|
|
armatureNode = new ArmatureNode(armature, joints, wires, outlines, deformingJoints);
|
|
|
-
|
|
|
this.attachChild(armatureNode);
|
|
|
|
|
|
+ // By default, non-deforming joints are hidden.
|
|
|
displayNonDeformingJoint(false);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Sets the visibility of non-deforming joints and their associated outlines and wires.
|
|
|
+ *
|
|
|
+ * @param display `true` to make non-deforming joints visible, `false` to hide them.
|
|
|
+ */
|
|
|
public void displayNonDeformingJoint(boolean display) {
|
|
|
- joints.getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
|
|
- outlines.getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
|
|
- wires.getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
|
|
- ((Node) outlines.getChild(1)).getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
|
|
- ((Node) wires.getChild(1)).getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
|
|
+ CullHint cullHint = display ? CullHint.Dynamic : CullHint.Always;
|
|
|
+
|
|
|
+ joints.getChild(0).setCullHint(cullHint);
|
|
|
+ outlines.getChild(0).setCullHint(cullHint);
|
|
|
+ wires.getChild(0).setCullHint(cullHint);
|
|
|
+
|
|
|
+ ((Node) outlines.getChild(1)).getChild(0).setCullHint(cullHint);
|
|
|
+ ((Node) wires.getChild(1)).getChild(0).setCullHint(cullHint);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Initializes the materials and camera for the debugger's visual components.
|
|
|
+ * This method should be called after the `ArmatureDebugger` is added to a scene graph
|
|
|
+ * and an {@link AssetManager} and {@link Camera} are available.
|
|
|
+ *
|
|
|
+ * @param assetManager The {@link AssetManager} to load textures and materials.
|
|
|
+ * @param camera The scene's primary {@link Camera}, used by the `ArmatureNode`
|
|
|
+ * for billboard rendering of joint points.
|
|
|
+ */
|
|
|
public void initialize(AssetManager assetManager, Camera camera) {
|
|
|
|
|
|
armatureNode.setCamera(camera);
|
|
|
|
|
|
+ // Material for joint points (billboarded dots).
|
|
|
Material matJoints = new Material(assetManager, "Common/MatDefs/Misc/Billboard.j3md");
|
|
|
- Texture t = assetManager.loadTexture("Common/Textures/dot.png");
|
|
|
- matJoints.setTexture("Texture", t);
|
|
|
+ Texture tex = assetManager.loadTexture("Common/Textures/dot.png");
|
|
|
+ matJoints.setTexture("Texture", tex);
|
|
|
matJoints.getAdditionalRenderState().setDepthTest(false);
|
|
|
matJoints.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
|
|
|
joints.setQueueBucket(RenderQueue.Bucket.Translucent);
|
|
|
joints.setMaterial(matJoints);
|
|
|
|
|
|
+ // Material for bone wires/lines (unshaded, vertex colored).
|
|
|
Material matWires = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
matWires.setBoolean("VertexColor", true);
|
|
|
- matWires.getAdditionalRenderState().setLineWidth(1f);
|
|
|
+ matWires.getAdditionalRenderState().setDepthTest(false);
|
|
|
wires.setMaterial(matWires);
|
|
|
|
|
|
+ // Material for bone outlines (unshaded, vertex colored).
|
|
|
Material matOutline = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
matOutline.setBoolean("VertexColor", true);
|
|
|
- matOutline.getAdditionalRenderState().setLineWidth(1f);
|
|
|
+ matOutline.getAdditionalRenderState().setDepthTest(false);
|
|
|
outlines.setMaterial(matOutline);
|
|
|
|
|
|
+ // Material for dashed outlines. This assumes a "DashedLine.j3md" shader.
|
|
|
Material matOutline2 = new Material(assetManager, "Common/MatDefs/Misc/DashedLine.j3md");
|
|
|
- matOutline2.getAdditionalRenderState().setLineWidth(1);
|
|
|
+ matOutline2.getAdditionalRenderState().setDepthTest(false);
|
|
|
outlines.getChild(1).setMaterial(matOutline2);
|
|
|
|
|
|
+ // Material for dashed wires. This assumes a "DashedLine.j3md" shader.
|
|
|
Material matWires2 = new Material(assetManager, "Common/MatDefs/Misc/DashedLine.j3md");
|
|
|
- matWires2.getAdditionalRenderState().setLineWidth(1);
|
|
|
+ matWires2.getAdditionalRenderState().setDepthTest(false);
|
|
|
wires.getChild(1).setMaterial(matWires2);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns the {@link Armature} instance associated with this debugger.
|
|
|
+ *
|
|
|
+ * @return The {@link Armature} being debugged.
|
|
|
+ */
|
|
|
public Armature getArmature() {
|
|
|
return armature;
|
|
|
}
|
|
@@ -168,21 +230,35 @@ public class ArmatureDebugger extends Node {
|
|
|
return armatureNode.collideWith(other, results);
|
|
|
}
|
|
|
|
|
|
- protected Joint select(Geometry g) {
|
|
|
- return armatureNode.select(g);
|
|
|
+ /**
|
|
|
+ * Selects and returns the {@link Joint} associated with a given {@link Geometry}.
|
|
|
+ * This is an internal helper method, likely used for picking operations.
|
|
|
+ *
|
|
|
+ * @param geo The {@link Geometry} representing a part of a joint.
|
|
|
+ * @return The {@link Joint} corresponding to the geometry, or `null` if not found.
|
|
|
+ */
|
|
|
+ protected Joint select(Geometry geo) {
|
|
|
+ return armatureNode.select(geo);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @return the armature wires
|
|
|
+ * Returns the {@link ArmatureNode} which is responsible for generating and
|
|
|
+ * managing the visual mesh of the bones and wires.
|
|
|
+ *
|
|
|
+ * @return The {@link ArmatureNode} instance.
|
|
|
*/
|
|
|
public ArmatureNode getBoneShapes() {
|
|
|
return armatureNode;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @return the dotted line between bones (can be null)
|
|
|
+ * Returns the {@link ArmatureInterJointsWire} instance, which represents the
|
|
|
+ * dotted lines connecting a bone's tail to the head of its children.
|
|
|
+ * This will be `null` if the debugger was created without bone length data.
|
|
|
+ *
|
|
|
+ * @return The {@link ArmatureInterJointsWire} instance, or `null` if not present.
|
|
|
*/
|
|
|
public ArmatureInterJointsWire getInterJointWires() {
|
|
|
return interJointWires;
|
|
|
}
|
|
|
-}
|
|
|
+}
|