Better armature joint selection
This commit is contained in:
parent
f1a3593070
commit
e99a093b5a
@ -23,11 +23,13 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class ArmatureDebugAppState extends BaseAppState {
|
public class ArmatureDebugAppState extends BaseAppState {
|
||||||
|
|
||||||
|
public static final float CLICK_MAX_DELAY = 0.2f;
|
||||||
private Node debugNode = new Node("debugNode");
|
private Node debugNode = new Node("debugNode");
|
||||||
private Map<Armature, ArmatureDebugger> armatures = new HashMap<>();
|
private Map<Armature, ArmatureDebugger> armatures = new HashMap<>();
|
||||||
private Map<Armature, Joint> selectedBones = new HashMap<>();
|
private Map<Armature, Joint> selectedBones = new HashMap<>();
|
||||||
private Application app;
|
private Application app;
|
||||||
private boolean displayAllJoints = false;
|
private boolean displayAllJoints = false;
|
||||||
|
private float clickDelay = -1;
|
||||||
ViewPort vp;
|
ViewPort vp;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -66,8 +68,12 @@ public class ArmatureDebugAppState extends BaseAppState {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
|
if (clickDelay > -1) {
|
||||||
|
clickDelay += tpf;
|
||||||
|
}
|
||||||
debugNode.updateLogicalState(tpf);
|
debugNode.updateLogicalState(tpf);
|
||||||
debugNode.updateGeometricState();
|
debugNode.updateGeometricState();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArmatureDebugger addArmatureFrom(SkinningControl skinningControl) {
|
public ArmatureDebugger addArmatureFrom(SkinningControl skinningControl) {
|
||||||
@ -111,19 +117,31 @@ public class ArmatureDebugAppState extends BaseAppState {
|
|||||||
private ActionListener actionListener = new ActionListener() {
|
private ActionListener actionListener = new ActionListener() {
|
||||||
public void onAction(String name, boolean isPressed, float tpf) {
|
public void onAction(String name, boolean isPressed, float tpf) {
|
||||||
if (name.equals("shoot") && isPressed) {
|
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();
|
Vector2f click2d = app.getInputManager().getCursorPosition();
|
||||||
|
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 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);
|
Vector3f dir = app.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d);
|
||||||
Ray ray = new Ray(click3d, dir);
|
Ray ray = new Ray(click3d, dir);
|
||||||
|
|
||||||
debugNode.collideWith(ray, results);
|
debugNode.collideWith(ray, results);
|
||||||
|
}
|
||||||
|
|
||||||
if (results.size() == 0) {
|
if (results.size() == 0) {
|
||||||
for (ArmatureDebugger ad : armatures.values()) {
|
for (ArmatureDebugger ad : armatures.values()) {
|
||||||
ad.select(null);
|
ad.select(null);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The closest result is the target that the player picked:
|
// The closest result is the target that the player picked:
|
||||||
Geometry target = results.getClosestCollision().getGeometry();
|
Geometry target = results.getClosestCollision().getGeometry();
|
||||||
for (ArmatureDebugger ad : armatures.values()) {
|
for (ArmatureDebugger ad : armatures.values()) {
|
||||||
|
@ -39,6 +39,7 @@ import com.jme3.collision.Collidable;
|
|||||||
import com.jme3.collision.CollisionResults;
|
import com.jme3.collision.CollisionResults;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.material.RenderState;
|
import com.jme3.material.RenderState;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
import com.jme3.renderer.queue.RenderQueue;
|
||||||
import com.jme3.scene.Geometry;
|
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() {
|
public Armature getArmature() {
|
||||||
return armature;
|
return armature;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class ArmatureNode extends Node {
|
public class ArmatureNode extends Node {
|
||||||
|
|
||||||
|
public static final float PIXEL_BOX = 10f;
|
||||||
/**
|
/**
|
||||||
* The armature to be displayed.
|
* The armature to be displayed.
|
||||||
*/
|
*/
|
||||||
@ -60,8 +61,7 @@ public class ArmatureNode extends Node {
|
|||||||
private Map<Joint, Geometry[]> jointToGeoms = new HashMap<>();
|
private Map<Joint, Geometry[]> jointToGeoms = new HashMap<>();
|
||||||
private Map<Geometry, Joint> geomToJoint = new HashMap<>();
|
private Map<Geometry, Joint> geomToJoint = new HashMap<>();
|
||||||
private Joint selectedJoint = null;
|
private Joint selectedJoint = null;
|
||||||
private Vector3f tmpStart = new Vector3f();
|
private Vector3f tmp = new Vector3f();
|
||||||
private List<Vector3f> tmpEnds = new ArrayList<>();
|
|
||||||
private final static ColorRGBA selectedColor = ColorRGBA.Orange;
|
private final static ColorRGBA selectedColor = ColorRGBA.Orange;
|
||||||
private final static ColorRGBA selectedColorJ = ColorRGBA.Yellow;
|
private final static ColorRGBA selectedColorJ = ColorRGBA.Yellow;
|
||||||
private final static ColorRGBA outlineColor = ColorRGBA.LightGray;
|
private final static ColorRGBA outlineColor = ColorRGBA.LightGray;
|
||||||
@ -109,7 +109,9 @@ public class ArmatureNode extends Node {
|
|||||||
attach(joints, deforms, jGeom);
|
attach(joints, deforms, jGeom);
|
||||||
Geometry bGeom = null;
|
Geometry bGeom = null;
|
||||||
Geometry bGeomO = null;
|
Geometry bGeomO = null;
|
||||||
if (ends != null) {
|
if (ends == null) {
|
||||||
|
geomToJoint.put(jGeom, joint);
|
||||||
|
} else {
|
||||||
Mesh m = null;
|
Mesh m = null;
|
||||||
Mesh mO = null;
|
Mesh mO = null;
|
||||||
Node wireAttach = wires;
|
Node wireAttach = wires;
|
||||||
@ -172,7 +174,10 @@ public class ArmatureNode extends Node {
|
|||||||
selectedJoint = j;
|
selectedJoint = j;
|
||||||
Geometry[] geomArray = jointToGeoms.get(selectedJoint);
|
Geometry[] geomArray = jointToGeoms.get(selectedJoint);
|
||||||
setColor(geomArray[0], selectedColorJ);
|
setColor(geomArray[0], selectedColorJ);
|
||||||
|
|
||||||
|
if (geomArray[1] != null) {
|
||||||
setColor(geomArray[1], selectedColor);
|
setColor(geomArray[1], selectedColor);
|
||||||
|
}
|
||||||
|
|
||||||
if (geomArray[2] != null) {
|
if (geomArray[2] != null) {
|
||||||
setColor(geomArray[2], baseColor);
|
setColor(geomArray[2], baseColor);
|
||||||
@ -188,7 +193,9 @@ public class ArmatureNode extends Node {
|
|||||||
}
|
}
|
||||||
Geometry[] geoms = jointToGeoms.get(selectedJoint);
|
Geometry[] geoms = jointToGeoms.get(selectedJoint);
|
||||||
setColor(geoms[0], ColorRGBA.White);
|
setColor(geoms[0], ColorRGBA.White);
|
||||||
|
if (geoms[1] != null) {
|
||||||
setColor(geoms[1], geoms[2] == null ? outlineColor : baseColor);
|
setColor(geoms[1], geoms[2] == null ? outlineColor : baseColor);
|
||||||
|
}
|
||||||
if (geoms[2] != null) {
|
if (geoms[2] != null) {
|
||||||
setColor(geoms[2], outlineColor);
|
setColor(geoms[2], outlineColor);
|
||||||
}
|
}
|
||||||
@ -211,7 +218,6 @@ public class ArmatureNode extends Node {
|
|||||||
Vector3f[] ends = bGeom.getUserData("end");
|
Vector3f[] ends = bGeom.getUserData("end");
|
||||||
start.set(joint.getModelTransform().getTranslation());
|
start.set(joint.getModelTransform().getTranslation());
|
||||||
if (ends != null) {
|
if (ends != null) {
|
||||||
tmpEnds.clear();
|
|
||||||
for (int i = 0; i < joint.getChildren().size(); i++) {
|
for (int i = 0; i < joint.getChildren().size(); i++) {
|
||||||
ends[i].set(joint.getChildren().get(i).getModelTransform().getTranslation());
|
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
|
@Override
|
||||||
public int collideWith(Collidable other, CollisionResults results) {
|
public int collideWith(Collidable other, CollisionResults results) {
|
||||||
if (!(other instanceof Ray)) {
|
if (!(other instanceof Ray)) {
|
||||||
@ -242,11 +264,14 @@ public class ArmatureNode extends Node {
|
|||||||
}
|
}
|
||||||
int nbCol = 0;
|
int nbCol = 0;
|
||||||
for (Geometry g : geomToJoint.keySet()) {
|
for (Geometry g : geomToJoint.keySet()) {
|
||||||
|
if (g.getMesh() instanceof JointShape) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Vector3f start = g.getUserData("start");
|
Vector3f start = g.getUserData("start");
|
||||||
Vector3f[] ends = g.getUserData("end");
|
Vector3f[] ends = g.getUserData("end");
|
||||||
for (int i = 0; i < ends.length; i++) {
|
for (int i = 0; i < ends.length; i++) {
|
||||||
float len = MathUtils.raySegmentShortestDistance((Ray) other, start, ends[i], camera);
|
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();
|
CollisionResult res = new CollisionResult();
|
||||||
res.setGeometry(g);
|
res.setGeometry(g);
|
||||||
results.addCollision(res);
|
results.addCollision(res);
|
||||||
|
@ -41,8 +41,8 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
rootNode.addLight(new DirectionalLight(new Vector3f(-1, -1, -1).normalizeLocal()));
|
rootNode.addLight(new DirectionalLight(new Vector3f(-1, -1, -1).normalizeLocal()));
|
||||||
rootNode.addLight(new AmbientLight(ColorRGBA.DarkGray));
|
rootNode.addLight(new AmbientLight(ColorRGBA.DarkGray));
|
||||||
|
|
||||||
// Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o");
|
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/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/Sinbad/Sinbad.mesh.xml");
|
||||||
// Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);
|
// Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user