2
0
Эх сурвалжийг харах

Better armature joint selection

Nehon 7 жил өмнө
parent
commit
02a1fd544a

+ 23 - 5
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureDebugAppState.java

@@ -23,11 +23,13 @@ import java.util.*;
  */
 public class ArmatureDebugAppState extends BaseAppState {
 
+    public static final float CLICK_MAX_DELAY = 0.2f;
     private Node debugNode = new Node("debugNode");
     private Map<Armature, ArmatureDebugger> armatures = new HashMap<>();
     private Map<Armature, Joint> selectedBones = new HashMap<>();
     private Application app;
     private boolean displayAllJoints = false;
+    private float clickDelay = -1;
     ViewPort vp;
 
     @Override
@@ -66,8 +68,12 @@ public class ArmatureDebugAppState extends BaseAppState {
 
     @Override
     public void update(float tpf) {
+        if (clickDelay > -1) {
+            clickDelay += tpf;
+        }
         debugNode.updateLogicalState(tpf);
         debugNode.updateGeometricState();
+
     }
 
     public ArmatureDebugger addArmatureFrom(SkinningControl skinningControl) {
@@ -111,19 +117,31 @@ public class ArmatureDebugAppState extends BaseAppState {
     private ActionListener actionListener = new ActionListener() {
         public void onAction(String name, boolean isPressed, float tpf) {
             if (name.equals("shoot") && isPressed) {
-                CollisionResults results = new CollisionResults();
+                clickDelay = 0;
+            }
+            if (name.equals("shoot") && !isPressed && clickDelay < CLICK_MAX_DELAY) {
                 Vector2f click2d = app.getInputManager().getCursorPosition();
-                Vector3f click3d = app.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
-                Vector3f dir = app.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d);
-                Ray ray = new Ray(click3d, dir);
+                CollisionResults results = new CollisionResults();
+                //first check 2d collision with joints
+                for (ArmatureDebugger ad : armatures.values()) {
+                    ad.pick(click2d, results);
+                }
+
+                if (results.size() == 0) {
+                    //no result, let's ray cast for bone geometries
+                    Vector3f click3d = app.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
+                    Vector3f dir = app.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d);
+                    Ray ray = new Ray(click3d, dir);
+                    debugNode.collideWith(ray, results);
+                }
 
-                debugNode.collideWith(ray, results);
                 if (results.size() == 0) {
                     for (ArmatureDebugger ad : armatures.values()) {
                         ad.select(null);
                     }
                     return;
                 }
+                
                 // The closest result is the target that the player picked:
                 Geometry target = results.getClosestCollision().getGeometry();
                 for (ArmatureDebugger ad : armatures.values()) {

+ 5 - 0
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureDebugger.java

@@ -39,6 +39,7 @@ import com.jme3.collision.Collidable;
 import com.jme3.collision.CollisionResults;
 import com.jme3.material.Material;
 import com.jme3.material.RenderState;
+import com.jme3.math.Vector2f;
 import com.jme3.renderer.Camera;
 import com.jme3.renderer.queue.RenderQueue;
 import com.jme3.scene.Geometry;
@@ -152,6 +153,10 @@ public class ArmatureDebugger extends Node {
 
     }
 
+    public int pick(Vector2f cursor, CollisionResults results) {
+        return armatureNode.pick(cursor, results);
+    }
+
     public Armature getArmature() {
         return armature;
     }

+ 32 - 7
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureNode.java

@@ -50,6 +50,7 @@ import java.util.*;
  */
 public class ArmatureNode extends Node {
 
+    public static final float PIXEL_BOX = 10f;
     /**
      * The armature to be displayed.
      */
@@ -60,8 +61,7 @@ public class ArmatureNode extends Node {
     private Map<Joint, Geometry[]> jointToGeoms = new HashMap<>();
     private Map<Geometry, Joint> geomToJoint = new HashMap<>();
     private Joint selectedJoint = null;
-    private Vector3f tmpStart = new Vector3f();
-    private List<Vector3f> tmpEnds = new ArrayList<>();
+    private Vector3f tmp = new Vector3f();
     private final static ColorRGBA selectedColor = ColorRGBA.Orange;
     private final static ColorRGBA selectedColorJ = ColorRGBA.Yellow;
     private final static ColorRGBA outlineColor = ColorRGBA.LightGray;
@@ -109,7 +109,9 @@ public class ArmatureNode extends Node {
         attach(joints, deforms, jGeom);
         Geometry bGeom = null;
         Geometry bGeomO = null;
-        if (ends != null) {
+        if (ends == null) {
+            geomToJoint.put(jGeom, joint);
+        } else {
             Mesh m = null;
             Mesh mO = null;
             Node wireAttach = wires;
@@ -172,7 +174,10 @@ public class ArmatureNode extends Node {
             selectedJoint = j;
             Geometry[] geomArray = jointToGeoms.get(selectedJoint);
             setColor(geomArray[0], selectedColorJ);
-            setColor(geomArray[1], selectedColor);
+
+            if (geomArray[1] != null) {
+                setColor(geomArray[1], selectedColor);
+            }
 
             if (geomArray[2] != null) {
                 setColor(geomArray[2], baseColor);
@@ -188,7 +193,9 @@ public class ArmatureNode extends Node {
         }
         Geometry[] geoms = jointToGeoms.get(selectedJoint);
         setColor(geoms[0], ColorRGBA.White);
-        setColor(geoms[1], geoms[2] == null ? outlineColor : baseColor);
+        if (geoms[1] != null) {
+            setColor(geoms[1], geoms[2] == null ? outlineColor : baseColor);
+        }
         if (geoms[2] != null) {
             setColor(geoms[2], outlineColor);
         }
@@ -211,7 +218,6 @@ public class ArmatureNode extends Node {
                 Vector3f[] ends = bGeom.getUserData("end");
                 start.set(joint.getModelTransform().getTranslation());
                 if (ends != null) {
-                    tmpEnds.clear();
                     for (int i = 0; i < joint.getChildren().size(); i++) {
                         ends[i].set(joint.getChildren().get(i).getModelTransform().getTranslation());
                     }
@@ -235,6 +241,22 @@ public class ArmatureNode extends Node {
         }
     }
 
+    public int pick(Vector2f cursor, CollisionResults results) {
+
+        for (Geometry g : geomToJoint.keySet()) {
+            if (g.getMesh() instanceof JointShape) {
+                camera.getScreenCoordinates(g.getWorldTranslation(), tmp);
+                if (cursor.x <= tmp.x + PIXEL_BOX && cursor.x >= tmp.x - PIXEL_BOX
+                        && cursor.y <= tmp.y + PIXEL_BOX && cursor.y >= tmp.y - PIXEL_BOX) {
+                    CollisionResult res = new CollisionResult();
+                    res.setGeometry(g);
+                    results.addCollision(res);
+                }
+            }
+        }
+        return 0;
+    }
+
     @Override
     public int collideWith(Collidable other, CollisionResults results) {
         if (!(other instanceof Ray)) {
@@ -242,11 +264,14 @@ public class ArmatureNode extends Node {
         }
         int nbCol = 0;
         for (Geometry g : geomToJoint.keySet()) {
+            if (g.getMesh() instanceof JointShape) {
+                continue;
+            }
             Vector3f start = g.getUserData("start");
             Vector3f[] ends = g.getUserData("end");
             for (int i = 0; i < ends.length; i++) {
                 float len = MathUtils.raySegmentShortestDistance((Ray) other, start, ends[i], camera);
-                if (len > 0 && len < 10f) {
+                if (len > 0 && len < PIXEL_BOX) {
                     CollisionResult res = new CollisionResult();
                     res.setGeometry(g);
                     results.addCollision(res);

+ 2 - 2
jme3-examples/src/main/java/jme3test/model/anim/TestAnimMigration.java

@@ -41,8 +41,8 @@ public class TestAnimMigration extends SimpleApplication {
         rootNode.addLight(new DirectionalLight(new Vector3f(-1, -1, -1).normalizeLocal()));
         rootNode.addLight(new AmbientLight(ColorRGBA.DarkGray));
 
-//        Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o");
-        Spatial model = assetManager.loadModel("Models/Oto/Oto.mesh.xml").scale(0.2f).move(0, 1, 0);
+        Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o");
+        // Spatial model = assetManager.loadModel("Models/Oto/Oto.mesh.xml").scale(0.2f).move(0, 1, 0);
         //Spatial model = assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
         //  Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);