Further Armature debugger enhancements
This commit is contained in:
parent
054d54f4b9
commit
886f8da2f7
@ -1,5 +1,6 @@
|
|||||||
package com.jme3.math;
|
package com.jme3.math;
|
||||||
|
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.util.TempVars;
|
import com.jme3.util.TempVars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,7 +165,19 @@ public class MathUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static float raySegmentShortestDistance(Ray ray, Vector3f segStart, Vector3f segEnd) {
|
/**
|
||||||
|
* Returns the shortest distance between a Ray and a segment.
|
||||||
|
* The segment is defined by a start position and an end position in world space
|
||||||
|
* The distance returned will be in world space (world units).
|
||||||
|
* If the camera parameter is not null the distance will be returned in screen space (pixels)
|
||||||
|
*
|
||||||
|
* @param ray The ray
|
||||||
|
* @param segStart The start position of the segment in world space
|
||||||
|
* @param segEnd The end position of the segment in world space
|
||||||
|
* @param camera The renderer camera if the distance is required in screen space. Null if the distance is required in world space
|
||||||
|
* @return the shortest distance between the ray and the segment or -1 if no solution is found.
|
||||||
|
*/
|
||||||
|
public static float raySegmentShortestDistance(Ray ray, Vector3f segStart, Vector3f segEnd, Camera camera) {
|
||||||
// Algorithm is ported from the C algorithm of
|
// Algorithm is ported from the C algorithm of
|
||||||
// Paul Bourke at http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/
|
// Paul Bourke at http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
@ -220,6 +233,12 @@ public class MathUtils {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (camera != null) {
|
||||||
|
//camera is not null let's convert the points in screen space
|
||||||
|
camera.getScreenCoordinates(resultSegmentPoint1, resultSegmentPoint1);
|
||||||
|
camera.getScreenCoordinates(resultSegmentPoint2, resultSegmentPoint2);
|
||||||
|
}
|
||||||
|
|
||||||
float length = resultSegmentPoint1.subtractLocal(resultSegmentPoint2).length();
|
float length = resultSegmentPoint1.subtractLocal(resultSegmentPoint2).length();
|
||||||
vars.release();
|
vars.release();
|
||||||
return length;
|
return length;
|
||||||
|
@ -37,7 +37,7 @@ public class ArmatureDebugAppState extends BaseAppState {
|
|||||||
vp.setClearDepth(true);
|
vp.setClearDepth(true);
|
||||||
this.app = app;
|
this.app = app;
|
||||||
for (ArmatureDebugger armatureDebugger : armatures.values()) {
|
for (ArmatureDebugger armatureDebugger : armatures.values()) {
|
||||||
armatureDebugger.initialize(app.getAssetManager());
|
armatureDebugger.initialize(app.getAssetManager(), app.getCamera());
|
||||||
}
|
}
|
||||||
app.getInputManager().addListener(actionListener, "shoot", "toggleJoints");
|
app.getInputManager().addListener(actionListener, "shoot", "toggleJoints");
|
||||||
app.getInputManager().addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT), new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
|
app.getInputManager().addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT), new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
|
||||||
@ -93,7 +93,7 @@ public class ArmatureDebugAppState extends BaseAppState {
|
|||||||
armatures.put(armature, ad);
|
armatures.put(armature, ad);
|
||||||
debugNode.attachChild(ad);
|
debugNode.attachChild(ad);
|
||||||
if (isInitialized()) {
|
if (isInitialized()) {
|
||||||
ad.initialize(app.getAssetManager());
|
ad.initialize(app.getAssetManager(), app.getCamera());
|
||||||
}
|
}
|
||||||
return ad;
|
return ad;
|
||||||
}
|
}
|
||||||
@ -108,12 +108,6 @@ public class ArmatureDebugAppState extends BaseAppState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Pick a Target Using the Mouse Pointer. <ol><li>Map "pick target" action
|
|
||||||
* to a MouseButtonTrigger. <li>flyCam.setEnabled(false);
|
|
||||||
* <li>inputManager.setCursorVisible(true); <li>Implement action in
|
|
||||||
* AnalogListener (TODO).</ol>
|
|
||||||
*/
|
|
||||||
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) {
|
||||||
|
@ -34,16 +34,17 @@ package com.jme3.scene.debug.custom;
|
|||||||
|
|
||||||
import com.jme3.anim.Armature;
|
import com.jme3.anim.Armature;
|
||||||
import com.jme3.anim.Joint;
|
import com.jme3.anim.Joint;
|
||||||
import com.jme3.animation.Bone;
|
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.collision.Collidable;
|
||||||
|
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.renderer.Camera;
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
import com.jme3.renderer.queue.RenderQueue;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,15 +64,11 @@ public class ArmatureDebugger extends Node {
|
|||||||
private Node joints;
|
private Node joints;
|
||||||
private Node outlines;
|
private Node outlines;
|
||||||
private Node wires;
|
private Node wires;
|
||||||
private List<Joint> deformingJoints;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dotted lines between a bone's tail and the had of its children. Not
|
* The dotted lines between a bone's tail and the had of its children. Not
|
||||||
* available if the length data was not provided.
|
* available if the length data was not provided.
|
||||||
*/
|
*/
|
||||||
private ArmatureInterJointsWire interJointWires;
|
private ArmatureInterJointsWire interJointWires;
|
||||||
//private Geometry wires;
|
|
||||||
private List<Bone> selectedJoints = new ArrayList<Bone>();
|
|
||||||
|
|
||||||
public ArmatureDebugger() {
|
public ArmatureDebugger() {
|
||||||
}
|
}
|
||||||
@ -86,7 +83,6 @@ public class ArmatureDebugger extends Node {
|
|||||||
*/
|
*/
|
||||||
public ArmatureDebugger(String name, Armature armature, List<Joint> deformingJoints) {
|
public ArmatureDebugger(String name, Armature armature, List<Joint> deformingJoints) {
|
||||||
super(name);
|
super(name);
|
||||||
this.deformingJoints = deformingJoints;
|
|
||||||
this.armature = armature;
|
this.armature = armature;
|
||||||
armature.update();
|
armature.update();
|
||||||
|
|
||||||
@ -102,25 +98,40 @@ public class ArmatureDebugger extends Node {
|
|||||||
joints.attachChild(ndJoints);
|
joints.attachChild(ndJoints);
|
||||||
outlines.attachChild(ndOutlines);
|
outlines.attachChild(ndOutlines);
|
||||||
wires.attachChild(ndWires);
|
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"));
|
||||||
|
outlines.attachChild(outlineDashed);
|
||||||
|
wires.attachChild(wiresDashed);
|
||||||
|
|
||||||
armatureNode = new ArmatureNode(armature, joints, wires, outlines, deformingJoints);
|
armatureNode = new ArmatureNode(armature, joints, wires, outlines, deformingJoints);
|
||||||
|
|
||||||
this.attachChild(armatureNode);
|
this.attachChild(armatureNode);
|
||||||
|
|
||||||
displayNonDeformingJoint(false);
|
displayNonDeformingJoint(false);
|
||||||
//interJointWires = new ArmatureInterJointsWire(armature, bonesLength, guessJointsOrientation);
|
|
||||||
//wires = new Geometry(name + "_interwires", interJointWires);
|
|
||||||
// this.attachChild(wires);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displayNonDeformingJoint(boolean display) {
|
public void displayNonDeformingJoint(boolean display) {
|
||||||
joints.getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
joints.getChild(0).setCullHint(display ? CullHint.Dynamic : CullHint.Always);
|
||||||
outlines.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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initialize(AssetManager assetManager) {
|
protected void initialize(AssetManager assetManager, Camera camera) {
|
||||||
|
|
||||||
|
armatureNode.setCamera(camera);
|
||||||
|
|
||||||
|
Material matJoints = new Material(assetManager, "Common/MatDefs/Misc/Billboard.j3md");
|
||||||
|
Texture t = assetManager.loadTexture("Common/Textures/dot.png");
|
||||||
|
matJoints.setTexture("Texture", t);
|
||||||
|
matJoints.getAdditionalRenderState().setDepthTest(false);
|
||||||
|
matJoints.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
|
||||||
|
joints.setQueueBucket(RenderQueue.Bucket.Translucent);
|
||||||
|
joints.setMaterial(matJoints);
|
||||||
|
|
||||||
Material matWires = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
Material matWires = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
matWires.setBoolean("VertexColor", true);
|
matWires.setBoolean("VertexColor", true);
|
||||||
matWires.getAdditionalRenderState().setLineWidth(3);
|
matWires.getAdditionalRenderState().setLineWidth(3);
|
||||||
@ -128,19 +139,16 @@ public class ArmatureDebugger extends Node {
|
|||||||
|
|
||||||
Material matOutline = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
Material matOutline = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
matOutline.setBoolean("VertexColor", true);
|
matOutline.setBoolean("VertexColor", true);
|
||||||
//matOutline.setColor("Color", ColorRGBA.White);
|
|
||||||
matOutline.getAdditionalRenderState().setLineWidth(5);
|
matOutline.getAdditionalRenderState().setLineWidth(5);
|
||||||
outlines.setMaterial(matOutline);
|
outlines.setMaterial(matOutline);
|
||||||
|
|
||||||
Material matJoints = new Material(assetManager, "Common/MatDefs/Misc/Billboard.j3md");
|
Material matOutline2 = new Material(assetManager, "Common/MatDefs/Misc/DashedLine.j3md");
|
||||||
Texture t = assetManager.loadTexture("Common/Textures/dot.png");
|
matOutline2.getAdditionalRenderState().setLineWidth(1);
|
||||||
// matJoints.setBoolean("VertexColor", true);
|
outlines.getChild(1).setMaterial(matOutline2);
|
||||||
// matJoints.setTexture("ColorMap", t);
|
|
||||||
matJoints.setTexture("Texture", t);
|
Material matWires2 = new Material(assetManager, "Common/MatDefs/Misc/DashedLine.j3md");
|
||||||
matJoints.getAdditionalRenderState().setDepthTest(false);
|
matWires2.getAdditionalRenderState().setLineWidth(1);
|
||||||
matJoints.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
|
wires.getChild(1).setMaterial(matWires2);
|
||||||
joints.setQueueBucket(RenderQueue.Bucket.Translucent);
|
|
||||||
joints.setMaterial(matJoints);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,9 +160,13 @@ public class ArmatureDebugger extends Node {
|
|||||||
public void updateLogicalState(float tpf) {
|
public void updateLogicalState(float tpf) {
|
||||||
super.updateLogicalState(tpf);
|
super.updateLogicalState(tpf);
|
||||||
armatureNode.updateGeometry();
|
armatureNode.updateGeometry();
|
||||||
if (interJointWires != null) {
|
|
||||||
// interJointWires.updateGeometry();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int collideWith(Collidable other, CollisionResults results) {
|
||||||
|
|
||||||
|
return armatureNode.collideWith(other, results);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Joint select(Geometry g) {
|
protected Joint select(Geometry g) {
|
||||||
|
@ -33,16 +33,12 @@ package com.jme3.scene.debug.custom;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import com.jme3.anim.Armature;
|
|
||||||
import com.jme3.anim.Joint;
|
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.VertexBuffer;
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.VertexBuffer.*;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
import com.jme3.util.BufferUtils;
|
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that displays a dotted line between a bone tail and its childrens' heads.
|
* A class that displays a dotted line between a bone tail and its childrens' heads.
|
||||||
@ -50,90 +46,69 @@ import java.util.Map;
|
|||||||
* @author Marcin Roguski (Kaelthas)
|
* @author Marcin Roguski (Kaelthas)
|
||||||
*/
|
*/
|
||||||
public class ArmatureInterJointsWire extends Mesh {
|
public class ArmatureInterJointsWire extends Mesh {
|
||||||
private static final int POINT_AMOUNT = 50;
|
private Vector3f tmp = new Vector3f();
|
||||||
/**
|
|
||||||
* The amount of connections between bones.
|
|
||||||
*/
|
|
||||||
private int connectionsAmount;
|
|
||||||
/**
|
|
||||||
* The armature that will be showed.
|
|
||||||
*/
|
|
||||||
private Armature armature;
|
|
||||||
/**
|
|
||||||
* The map between the bone index and its length.
|
|
||||||
*/
|
|
||||||
private Map<Integer, Float> boneLengths;
|
|
||||||
|
|
||||||
private boolean guessBonesOrientation = false;
|
|
||||||
|
|
||||||
/**
|
public ArmatureInterJointsWire(Vector3f start, Vector3f[] ends) {
|
||||||
* Creates buffers for points. Each line has POINT_AMOUNT of points.
|
setMode(Mode.Lines);
|
||||||
*
|
updateGeometry(start, ends);
|
||||||
* @param armature the armature that will be showed
|
|
||||||
* @param boneLengths the lengths of the bones
|
|
||||||
*/
|
|
||||||
public ArmatureInterJointsWire(Armature armature, Map<Integer, Float> boneLengths, boolean guessBonesOrientation) {
|
|
||||||
this.armature = armature;
|
|
||||||
|
|
||||||
for (Joint joint : armature.getRoots()) {
|
|
||||||
this.countConnections(joint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setMode(Mode.Points);
|
protected void updateGeometry(Vector3f start, Vector3f[] ends) {
|
||||||
this.boneLengths = boneLengths;
|
float[] pos = new float[ends.length * 3 + 3];
|
||||||
|
pos[0] = start.x;
|
||||||
|
pos[1] = start.y;
|
||||||
|
pos[2] = start.z;
|
||||||
|
int index;
|
||||||
|
for (int i = 0; i < ends.length; i++) {
|
||||||
|
index = i * 3 + 3;
|
||||||
|
pos[index] = ends[i].x;
|
||||||
|
pos[index + 1] = ends[i].y;
|
||||||
|
pos[index + 2] = ends[i].z;
|
||||||
|
}
|
||||||
|
setBuffer(Type.Position, 3, pos);
|
||||||
|
|
||||||
VertexBuffer pb = new VertexBuffer(Type.Position);
|
float[] texCoord = new float[ends.length * 2 + 2];
|
||||||
FloatBuffer fpb = BufferUtils.createFloatBuffer(POINT_AMOUNT * connectionsAmount * 3);
|
texCoord[0] = 0;
|
||||||
pb.setupData(Usage.Stream, 3, Format.Float, fpb);
|
texCoord[1] = 0;
|
||||||
this.setBuffer(pb);
|
for (int i = 0; i < ends.length * 2; i++) {
|
||||||
|
texCoord[i + 2] = tmp.set(start).subtractLocal(ends[i / 2]).length();
|
||||||
|
}
|
||||||
|
setBuffer(Type.TexCoord, 2, texCoord);
|
||||||
|
|
||||||
this.guessBonesOrientation = guessBonesOrientation;
|
float[] normal = new float[ends.length * 3 + 3];
|
||||||
this.updateCounts();
|
for (int i = 0; i < ends.length * 3 + 3; i += 3) {
|
||||||
|
normal[i] = start.x;
|
||||||
|
normal[i + 1] = start.y;
|
||||||
|
normal[i + 2] = start.z;
|
||||||
|
}
|
||||||
|
setBuffer(Type.Normal, 3, normal);
|
||||||
|
|
||||||
|
short[] id = new short[ends.length * 2];
|
||||||
|
index = 1;
|
||||||
|
for (int i = 0; i < ends.length * 2; i += 2) {
|
||||||
|
id[i] = 0;
|
||||||
|
id[i + 1] = (short) (index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
setBuffer(Type.Index, 2, id);
|
||||||
|
updateBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method updates the geometry according to the positions of the bones.
|
* Update the start and end points of the line.
|
||||||
*/
|
*/
|
||||||
public void updateGeometry() {
|
public void updatePoints(Vector3f start, Vector3f end) {
|
||||||
VertexBuffer vb = this.getBuffer(Type.Position);
|
VertexBuffer posBuf = getBuffer(Type.Position);
|
||||||
FloatBuffer posBuf = this.getFloatBuffer(Type.Position);
|
|
||||||
posBuf.clear();
|
|
||||||
for (int i = 0; i < armature.getJointCount(); ++i) {
|
|
||||||
Joint joint = armature.getJoint(i);
|
|
||||||
Vector3f parentTail = joint.getModelTransform().getTranslation().add(joint.getModelTransform().getRotation().mult(Vector3f.UNIT_Y.mult(boneLengths.get(i))));
|
|
||||||
|
|
||||||
if (guessBonesOrientation) {
|
FloatBuffer fb = (FloatBuffer) posBuf.getData();
|
||||||
parentTail = joint.getModelTransform().getTranslation();
|
fb.rewind();
|
||||||
|
fb.put(start.x).put(start.y).put(start.z);
|
||||||
|
fb.put(end.x).put(end.y).put(end.z);
|
||||||
|
|
||||||
|
posBuf.updateData(fb);
|
||||||
|
|
||||||
|
updateBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Joint child : joint.getChildren()) {
|
|
||||||
Vector3f childHead = child.getModelTransform().getTranslation();
|
|
||||||
Vector3f v = childHead.subtract(parentTail);
|
|
||||||
float len = v.length();
|
|
||||||
float pointDelta = 1f / POINT_AMOUNT;
|
|
||||||
v.normalizeLocal().multLocal(pointDelta);
|
|
||||||
Vector3f pointPosition = parentTail.clone();
|
|
||||||
for (int j = 0; j < POINT_AMOUNT * len; ++j) {
|
|
||||||
posBuf.put(pointPosition.getX()).put(pointPosition.getY()).put(pointPosition.getZ());
|
|
||||||
pointPosition.addLocal(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
posBuf.flip();
|
|
||||||
vb.updateData(posBuf);
|
|
||||||
|
|
||||||
this.updateBound();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Th method counts the connections between bones.
|
|
||||||
*
|
|
||||||
* @param joint the bone where counting starts
|
|
||||||
*/
|
|
||||||
private void countConnections(Joint joint) {
|
|
||||||
for (Joint child : joint.getChildren()) {
|
|
||||||
++connectionsAmount;
|
|
||||||
this.countConnections(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import com.jme3.anim.Armature;
|
|||||||
import com.jme3.anim.Joint;
|
import com.jme3.anim.Joint;
|
||||||
import com.jme3.collision.*;
|
import com.jme3.collision.*;
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
import com.jme3.renderer.queue.RenderQueue;
|
||||||
import com.jme3.scene.*;
|
import com.jme3.scene.*;
|
||||||
import com.jme3.scene.shape.Line;
|
import com.jme3.scene.shape.Line;
|
||||||
@ -60,11 +61,13 @@ public class ArmatureNode extends Node {
|
|||||||
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 tmpStart = new Vector3f();
|
||||||
private Vector3f tmpEnd = new Vector3f();
|
private List<Vector3f> tmpEnds = new ArrayList<>();
|
||||||
ColorRGBA selectedColor = ColorRGBA.Orange;
|
private final static ColorRGBA selectedColor = ColorRGBA.Orange;
|
||||||
ColorRGBA selectedColorJ = ColorRGBA.Yellow;
|
private final static ColorRGBA selectedColorJ = ColorRGBA.Yellow;
|
||||||
;//new ColorRGBA(0.2f, 1f, 1.0f, 1.0f);
|
private final static ColorRGBA outlineColor = ColorRGBA.LightGray;
|
||||||
ColorRGBA baseColor = new ColorRGBA(0.05f, 0.05f, 0.05f, 1f);
|
private final static ColorRGBA baseColor = new ColorRGBA(0.05f, 0.05f, 0.05f, 1f);
|
||||||
|
|
||||||
|
private Camera camera;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,11 +88,14 @@ public class ArmatureNode extends Node {
|
|||||||
|
|
||||||
protected final void createSkeletonGeoms(Joint joint, Node joints, Node wires, Node outlines, List<Joint> deformingJoints) {
|
protected final void createSkeletonGeoms(Joint joint, Node joints, Node wires, Node outlines, List<Joint> deformingJoints) {
|
||||||
Vector3f start = joint.getModelTransform().getTranslation().clone();
|
Vector3f start = joint.getModelTransform().getTranslation().clone();
|
||||||
Vector3f end = null;
|
|
||||||
|
|
||||||
//One child only, the bone direction is from the parent joint to the child joint.
|
Vector3f[] ends = null;
|
||||||
if (joint.getChildren().size() == 1) {
|
if (!joint.getChildren().isEmpty()) {
|
||||||
end = joint.getChildren().get(0).getModelTransform().getTranslation().clone();
|
ends = new Vector3f[joint.getChildren().size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < joint.getChildren().size(); i++) {
|
||||||
|
ends[i] = joint.getChildren().get(i).getModelTransform().getTranslation().clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean deforms = deformingJoints.contains(joint);
|
boolean deforms = deformingJoints.contains(joint);
|
||||||
@ -99,19 +105,36 @@ 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 (end != null) {
|
if (ends != null) {
|
||||||
bGeom = new Geometry(joint.getName() + "Bone", new Line(start, end));
|
Mesh m = null;
|
||||||
setColor(bGeom, baseColor);
|
Mesh mO = null;
|
||||||
geomToJoint.put(bGeom, joint);
|
Node wireAttach = wires;
|
||||||
bGeomO = new Geometry(joint.getName() + "BoneOutline", new Line(start, end));
|
Node outlinesAttach = outlines;
|
||||||
setColor(bGeomO, ColorRGBA.White);
|
if (ends.length == 1) {
|
||||||
bGeom.setUserData("start", wires.getWorldTransform().transformVector(start, start));
|
m = new Line(start, ends[0]);
|
||||||
bGeom.setUserData("end", wires.getWorldTransform().transformVector(end, end));
|
mO = new Line(start, ends[0]);
|
||||||
bGeom.setQueueBucket(RenderQueue.Bucket.Transparent);
|
} else {
|
||||||
attach(wires, deforms, bGeom);
|
m = new ArmatureInterJointsWire(start, ends);
|
||||||
attach(outlines, deforms, bGeomO);
|
mO = new ArmatureInterJointsWire(start, ends);
|
||||||
|
wireAttach = (Node) wires.getChild(1);
|
||||||
|
outlinesAttach = null;
|
||||||
|
}
|
||||||
|
bGeom = new Geometry(joint.getName() + "Bone", m);
|
||||||
|
setColor(bGeom, outlinesAttach == null ? outlineColor : baseColor);
|
||||||
|
geomToJoint.put(bGeom, joint);
|
||||||
|
bGeom.setUserData("start", getWorldTransform().transformVector(start, start));
|
||||||
|
for (int i = 0; i < ends.length; i++) {
|
||||||
|
getWorldTransform().transformVector(ends[i], ends[i]);
|
||||||
|
}
|
||||||
|
bGeom.setUserData("end", ends);
|
||||||
|
bGeom.setQueueBucket(RenderQueue.Bucket.Transparent);
|
||||||
|
attach(wireAttach, deforms, bGeom);
|
||||||
|
if (outlinesAttach != null) {
|
||||||
|
bGeomO = new Geometry(joint.getName() + "BoneOutline", mO);
|
||||||
|
setColor(bGeomO, outlineColor);
|
||||||
|
attach(outlinesAttach, deforms, bGeomO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jointToGeoms.put(joint, new Geometry[]{jGeom, bGeom, bGeomO});
|
jointToGeoms.put(joint, new Geometry[]{jGeom, bGeom, bGeomO});
|
||||||
|
|
||||||
for (Joint child : joint.getChildren()) {
|
for (Joint child : joint.getChildren()) {
|
||||||
@ -119,6 +142,10 @@ public class ArmatureNode extends Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCamera(Camera camera) {
|
||||||
|
this.camera = camera;
|
||||||
|
}
|
||||||
|
|
||||||
private void attach(Node parent, boolean deforms, Geometry geom) {
|
private void attach(Node parent, boolean deforms, Geometry geom) {
|
||||||
if (deforms) {
|
if (deforms) {
|
||||||
parent.attachChild(geom);
|
parent.attachChild(geom);
|
||||||
@ -142,7 +169,10 @@ public class ArmatureNode extends Node {
|
|||||||
Geometry[] geomArray = jointToGeoms.get(selectedJoint);
|
Geometry[] geomArray = jointToGeoms.get(selectedJoint);
|
||||||
setColor(geomArray[0], selectedColorJ);
|
setColor(geomArray[0], selectedColorJ);
|
||||||
setColor(geomArray[1], selectedColor);
|
setColor(geomArray[1], selectedColor);
|
||||||
|
|
||||||
|
if (geomArray[2] != null) {
|
||||||
setColor(geomArray[2], baseColor);
|
setColor(geomArray[2], baseColor);
|
||||||
|
}
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -154,8 +184,10 @@ 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);
|
||||||
setColor(geoms[1], baseColor);
|
setColor(geoms[1], geoms[2] == null ? outlineColor : baseColor);
|
||||||
setColor(geoms[2], ColorRGBA.White);
|
if (geoms[2] != null) {
|
||||||
|
setColor(geoms[2], outlineColor);
|
||||||
|
}
|
||||||
selectedJoint = null;
|
selectedJoint = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,20 +203,25 @@ public class ArmatureNode extends Node {
|
|||||||
jGeom.setLocalTranslation(joint.getModelTransform().getTranslation());
|
jGeom.setLocalTranslation(joint.getModelTransform().getTranslation());
|
||||||
Geometry bGeom = geoms[1];
|
Geometry bGeom = geoms[1];
|
||||||
if (bGeom != null) {
|
if (bGeom != null) {
|
||||||
tmpStart.set(joint.getModelTransform().getTranslation());
|
|
||||||
boolean hasEnd = false;
|
|
||||||
if (joint.getChildren().size() == 1) {
|
|
||||||
tmpEnd.set(joint.getChildren().get(0).getModelTransform().getTranslation());
|
|
||||||
hasEnd = true;
|
|
||||||
}
|
|
||||||
if (hasEnd) {
|
|
||||||
updateBoneMesh(bGeom);
|
|
||||||
Geometry bGeomO = geoms[2];
|
|
||||||
updateBoneMesh(bGeomO);
|
|
||||||
Vector3f start = bGeom.getUserData("start");
|
Vector3f start = bGeom.getUserData("start");
|
||||||
Vector3f end = bGeom.getUserData("end");
|
Vector3f[] ends = bGeom.getUserData("end");
|
||||||
bGeom.setUserData("start", bGeom.getParent().getWorldTransform().transformVector(tmpStart, start));
|
start.set(joint.getModelTransform().getTranslation());
|
||||||
bGeom.setUserData("end", bGeom.getParent().getWorldTransform().transformVector(tmpEnd, end));
|
if (ends != null) {
|
||||||
|
tmpEnds.clear();
|
||||||
|
for (int i = 0; i < joint.getChildren().size(); i++) {
|
||||||
|
ends[i].set(joint.getChildren().get(i).getModelTransform().getTranslation());
|
||||||
|
}
|
||||||
|
updateBoneMesh(bGeom, start, ends);
|
||||||
|
Geometry bGeomO = geoms[2];
|
||||||
|
if (bGeomO != null) {
|
||||||
|
updateBoneMesh(bGeomO, start, ends);
|
||||||
|
}
|
||||||
|
bGeom.setUserData("start", getWorldTransform().transformVector(start, start));
|
||||||
|
for (int i = 0; i < ends.length; i++) {
|
||||||
|
getWorldTransform().transformVector(ends[i], ends[i]);
|
||||||
|
}
|
||||||
|
bGeom.setUserData("end", ends);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,25 +238,28 @@ public class ArmatureNode extends Node {
|
|||||||
}
|
}
|
||||||
int nbCol = 0;
|
int nbCol = 0;
|
||||||
for (Geometry g : geomToJoint.keySet()) {
|
for (Geometry g : geomToJoint.keySet()) {
|
||||||
float len = MathUtils.raySegmentShortestDistance((Ray) other, (Vector3f) g.getUserData("start"), (Vector3f) g.getUserData("end"));
|
Vector3f start = g.getUserData("start");
|
||||||
if (len > 0 && len < 0.1f) {
|
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) {
|
||||||
CollisionResult res = new CollisionResult();
|
CollisionResult res = new CollisionResult();
|
||||||
res.setGeometry(g);
|
res.setGeometry(g);
|
||||||
results.addCollision(res);
|
results.addCollision(res);
|
||||||
nbCol++;
|
nbCol++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nbCol;
|
return nbCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBoneMesh(Geometry bGeom) {
|
private void updateBoneMesh(Geometry bGeom, Vector3f start, Vector3f[] ends) {
|
||||||
VertexBuffer pos = bGeom.getMesh().getBuffer(VertexBuffer.Type.Position);
|
VertexBuffer pos = bGeom.getMesh().getBuffer(VertexBuffer.Type.Position);
|
||||||
FloatBuffer fb = (FloatBuffer) pos.getData();
|
FloatBuffer fb = (FloatBuffer) pos.getData();
|
||||||
fb.rewind();
|
fb.rewind();
|
||||||
fb.put(new float[]{tmpStart.x, tmpStart.y, tmpStart.z,
|
fb.put(new float[]{start.x, start.y, start.z,
|
||||||
tmpEnd.x, tmpEnd.y, tmpEnd.z,});
|
ends[0].x, ends[0].y, ends[0].z,});
|
||||||
pos.updateData(fb);
|
pos.updateData(fb);
|
||||||
|
|
||||||
bGeom.updateModelBound();
|
bGeom.updateModelBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
MaterialDef DashedLine {
|
||||||
|
MaterialParameters {
|
||||||
|
}
|
||||||
|
|
||||||
|
Technique {
|
||||||
|
WorldParameters {
|
||||||
|
WorldViewProjectionMatrix
|
||||||
|
Resolution
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexShaderNodes {
|
||||||
|
ShaderNode TransformPosition {
|
||||||
|
Definition: TransformPosition: Common/MatDefs/ShaderNodes/Basic/TransformPosition.j3sn
|
||||||
|
InputMappings {
|
||||||
|
transformsMatrix = WorldParam.WorldViewProjectionMatrix
|
||||||
|
inputPosition = Attr.inNormal
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderNode PerspectiveDivide {
|
||||||
|
Definition: PerspectiveDivide: Common/MatDefs/ShaderNodes/Misc/PerspectiveDivide.j3sn
|
||||||
|
InputMappings {
|
||||||
|
inVec = TransformPosition.outPosition
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderNode CommonVert {
|
||||||
|
Definition: CommonVert: Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn
|
||||||
|
InputMappings {
|
||||||
|
worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
|
||||||
|
modelPosition = Attr.inPosition
|
||||||
|
vertColor = Attr.inColor
|
||||||
|
texCoord1 = Attr.inTexCoord
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
Global.position = projPosition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FragmentShaderNodes {
|
||||||
|
ShaderNode Dashed {
|
||||||
|
Definition: Dashed: Common/MatDefs/ShaderNodes/Misc/Dashed.j3sn
|
||||||
|
InputMappings {
|
||||||
|
texCoord = CommonVert.texCoord1
|
||||||
|
inColor = CommonVert.vertColor
|
||||||
|
resolution = WorldParam.Resolution
|
||||||
|
startPos = PerspectiveDivide.outVec
|
||||||
|
}
|
||||||
|
OutputMappings {
|
||||||
|
Global.color = outColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
ShaderNodeDefinitions{
|
||||||
|
ShaderNodeDefinition Dashed {
|
||||||
|
//Vertex/Fragment
|
||||||
|
Type: Fragment
|
||||||
|
|
||||||
|
//Shader GLSL<version>: <Path to shader>
|
||||||
|
Shader GLSL100: Common/MatDefs/ShaderNodes/Misc/Dashed100.frag
|
||||||
|
|
||||||
|
Documentation{
|
||||||
|
//type documentation here. This is optional but recommended
|
||||||
|
Output a dashed line (better have a LINE mode mesh)
|
||||||
|
|
||||||
|
//@input <glsltype> <varName> <description>
|
||||||
|
@input vec2 texCoord the texture coordinates
|
||||||
|
@input vec4 inColor The input color
|
||||||
|
|
||||||
|
|
||||||
|
//@output <glslType> <varName> <description>
|
||||||
|
@output vec4 outColor The modified output color
|
||||||
|
}
|
||||||
|
Input {
|
||||||
|
//all the node inputs
|
||||||
|
//<glslType> <varName>
|
||||||
|
vec2 texCoord
|
||||||
|
vec4 inColor
|
||||||
|
vec4 startPos
|
||||||
|
vec2 resolution
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Output {
|
||||||
|
//all the node outputs
|
||||||
|
//<glslType> <varName>
|
||||||
|
vec4 outColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
void main(){
|
||||||
|
startPos.xy = (startPos * 0.5 + 0.5).xy * resolution;
|
||||||
|
float len = distance(gl_FragCoord.xy,startPos.xy);
|
||||||
|
outColor = inColor;
|
||||||
|
float factor = int(len * 0.25);
|
||||||
|
if(mod(factor, 2) > 0.0){
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
ShaderNodeDefinitions{
|
||||||
|
ShaderNodeDefinition PerspectiveDivide {
|
||||||
|
//Vertex/Fragment
|
||||||
|
Type: Vertex
|
||||||
|
|
||||||
|
//Shader GLSL<version>: <Path to shader>
|
||||||
|
Shader GLSL100: Common/MatDefs/ShaderNodes/Misc/PerspectiveDivide100.frag
|
||||||
|
|
||||||
|
Documentation{
|
||||||
|
//type documentation here. This is optional but recommended
|
||||||
|
performs inVec.xyz / inVec.w
|
||||||
|
|
||||||
|
//@input <glsltype> <varName> <description>
|
||||||
|
@input vec4 inVec The input vector
|
||||||
|
|
||||||
|
//@output <glslType> <varName> <description>
|
||||||
|
@output vec4 outVec The modified output vector
|
||||||
|
}
|
||||||
|
Input {
|
||||||
|
//all the node inputs
|
||||||
|
//<glslType> <varName>
|
||||||
|
vec4 inVec
|
||||||
|
}
|
||||||
|
Output {
|
||||||
|
//all the node outputs
|
||||||
|
//<glslType> <varName>
|
||||||
|
vec4 outVec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
void main(){
|
||||||
|
outVec = vec4(inVec.xyz / inVec.w,1.0);
|
||||||
|
}
|
@ -26,7 +26,7 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
ArmatureDebugAppState debugAppState;
|
ArmatureDebugAppState debugAppState;
|
||||||
AnimComposer composer;
|
AnimComposer composer;
|
||||||
Queue<String> anims = new LinkedList<>();
|
Queue<String> anims = new LinkedList<>();
|
||||||
boolean playAnim = true;
|
boolean playAnim = false;
|
||||||
|
|
||||||
public static void main(String... argv) {
|
public static void main(String... argv) {
|
||||||
TestAnimMigration app = new TestAnimMigration();
|
TestAnimMigration app = new TestAnimMigration();
|
||||||
@ -36,15 +36,15 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void simpleInitApp() {
|
public void simpleInitApp() {
|
||||||
setTimer(new EraseTimer());
|
setTimer(new EraseTimer());
|
||||||
//cam.setFrustumPerspective(90f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 10f);
|
cam.setFrustumPerspective(45f, (float) cam.getWidth() / cam.getHeight(), 0.1f, 100f);
|
||||||
viewPort.setBackgroundColor(ColorRGBA.DarkGray);
|
viewPort.setBackgroundColor(ColorRGBA.DarkGray);
|
||||||
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");
|
//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");
|
Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);
|
||||||
|
|
||||||
AnimMigrationUtils.migrate(model);
|
AnimMigrationUtils.migrate(model);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user