Pārlūkot izejas kodu

Further Armature debugger enhancements

Nehon 7 gadi atpakaļ
vecāks
revīzija
886f8da2f7

+ 20 - 1
jme3-core/src/main/java/com/jme3/math/MathUtils.java

@@ -1,5 +1,6 @@
 package com.jme3.math;
 
+import com.jme3.renderer.Camera;
 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
         // Paul Bourke at http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/
         TempVars vars = TempVars.get();
@@ -220,6 +233,12 @@ public class MathUtils {
             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();
         vars.release();
         return length;

+ 2 - 8
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureDebugAppState.java

@@ -37,7 +37,7 @@ public class ArmatureDebugAppState extends BaseAppState {
         vp.setClearDepth(true);
         this.app = app;
         for (ArmatureDebugger armatureDebugger : armatures.values()) {
-            armatureDebugger.initialize(app.getAssetManager());
+            armatureDebugger.initialize(app.getAssetManager(), app.getCamera());
         }
         app.getInputManager().addListener(actionListener, "shoot", "toggleJoints");
         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);
         debugNode.attachChild(ad);
         if (isInitialized()) {
-            ad.initialize(app.getAssetManager());
+            ad.initialize(app.getAssetManager(), app.getCamera());
         }
         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() {
         public void onAction(String name, boolean isPressed, float tpf) {
             if (name.equals("shoot") && isPressed) {

+ 37 - 25
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureDebugger.java

@@ -34,16 +34,17 @@ package com.jme3.scene.debug.custom;
 
 import com.jme3.anim.Armature;
 import com.jme3.anim.Joint;
-import com.jme3.animation.Bone;
 import com.jme3.asset.AssetManager;
+import com.jme3.collision.Collidable;
+import com.jme3.collision.CollisionResults;
 import com.jme3.material.Material;
 import com.jme3.material.RenderState;
+import com.jme3.renderer.Camera;
 import com.jme3.renderer.queue.RenderQueue;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.texture.Texture;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -63,15 +64,11 @@ public class ArmatureDebugger extends Node {
     private Node joints;
     private Node outlines;
     private Node wires;
-    private List<Joint> deformingJoints;
-
     /**
      * 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;
-    //private Geometry wires;
-    private List<Bone> selectedJoints = new ArrayList<Bone>();
 
     public ArmatureDebugger() {
     }
@@ -86,7 +83,6 @@ public class ArmatureDebugger extends Node {
      */
     public ArmatureDebugger(String name, Armature armature, List<Joint> deformingJoints) {
         super(name);
-        this.deformingJoints = deformingJoints;
         this.armature = armature;
         armature.update();
 
@@ -102,25 +98,40 @@ public class ArmatureDebugger extends Node {
         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"));
+        outlines.attachChild(outlineDashed);
+        wires.attachChild(wiresDashed);
 
         armatureNode = new ArmatureNode(armature, joints, wires, outlines, deformingJoints);
 
         this.attachChild(armatureNode);
 
         displayNonDeformingJoint(false);
-        //interJointWires = new ArmatureInterJointsWire(armature, bonesLength, guessJointsOrientation);
-        //wires = new Geometry(name + "_interwires", interJointWires);
-        //       this.attachChild(wires);
     }
 
     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);
     }
 
-    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");
         matWires.setBoolean("VertexColor", true);
         matWires.getAdditionalRenderState().setLineWidth(3);
@@ -128,19 +139,16 @@ public class ArmatureDebugger extends Node {
 
         Material matOutline = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         matOutline.setBoolean("VertexColor", true);
-        //matOutline.setColor("Color", ColorRGBA.White);
         matOutline.getAdditionalRenderState().setLineWidth(5);
         outlines.setMaterial(matOutline);
 
-        Material matJoints = new Material(assetManager, "Common/MatDefs/Misc/Billboard.j3md");
-        Texture t = assetManager.loadTexture("Common/Textures/dot.png");
-//        matJoints.setBoolean("VertexColor", true);
-//        matJoints.setTexture("ColorMap", t);
-        matJoints.setTexture("Texture", t);
-        matJoints.getAdditionalRenderState().setDepthTest(false);
-        matJoints.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
-        joints.setQueueBucket(RenderQueue.Bucket.Translucent);
-        joints.setMaterial(matJoints);
+        Material matOutline2 = new Material(assetManager, "Common/MatDefs/Misc/DashedLine.j3md");
+        matOutline2.getAdditionalRenderState().setLineWidth(1);
+        outlines.getChild(1).setMaterial(matOutline2);
+
+        Material matWires2 = new Material(assetManager, "Common/MatDefs/Misc/DashedLine.j3md");
+        matWires2.getAdditionalRenderState().setLineWidth(1);
+        wires.getChild(1).setMaterial(matWires2);
 
     }
 
@@ -152,9 +160,13 @@ public class ArmatureDebugger extends Node {
     public void updateLogicalState(float tpf) {
         super.updateLogicalState(tpf);
         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) {

+ 53 - 78
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureInterJointsWire.java

@@ -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.scene.Mesh;
 import com.jme3.scene.VertexBuffer;
-import com.jme3.scene.VertexBuffer.*;
-import com.jme3.util.BufferUtils;
+import com.jme3.scene.VertexBuffer.Type;
 
 import java.nio.FloatBuffer;
-import java.util.Map;
 
 /**
  * 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)
  */
 public class ArmatureInterJointsWire extends Mesh {
-    private static final int POINT_AMOUNT = 50;
-    /**
-     * 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 Vector3f tmp = new Vector3f();
 
-    private boolean guessBonesOrientation = false;
 
-    /**
-     * Creates buffers for points. Each line has POINT_AMOUNT of points.
-     *
-     * @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;
+    public ArmatureInterJointsWire(Vector3f start, Vector3f[] ends) {
+        setMode(Mode.Lines);
+        updateGeometry(start, ends);
+    }
 
-        for (Joint joint : armature.getRoots()) {
-            this.countConnections(joint);
+    protected void updateGeometry(Vector3f start, Vector3f[] ends) {
+        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);
 
-        this.setMode(Mode.Points);
-        this.boneLengths = boneLengths;
-
-        VertexBuffer pb = new VertexBuffer(Type.Position);
-        FloatBuffer fpb = BufferUtils.createFloatBuffer(POINT_AMOUNT * connectionsAmount * 3);
-        pb.setupData(Usage.Stream, 3, Format.Float, fpb);
-        this.setBuffer(pb);
+        float[] texCoord = new float[ends.length * 2 + 2];
+        texCoord[0] = 0;
+        texCoord[1] = 0;
+        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;
-        this.updateCounts();
+        float[] normal = new float[ends.length * 3 + 3];
+        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() {
-        VertexBuffer vb = this.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) {
-                parentTail = joint.getModelTransform().getTranslation();
-            }
-
-            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);
+    public void updatePoints(Vector3f start, Vector3f end) {
+        VertexBuffer posBuf = getBuffer(Type.Position);
 
-        this.updateBound();
-    }
+        FloatBuffer fb = (FloatBuffer) posBuf.getData();
+        fb.rewind();
+        fb.put(start.x).put(start.y).put(start.z);
+        fb.put(end.x).put(end.y).put(end.z);
 
-    /**
-     * 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);
-        }
+        posBuf.updateData(fb);
+
+        updateBound();
     }
+
 }

+ 85 - 45
jme3-core/src/main/java/com/jme3/scene/debug/custom/ArmatureNode.java

@@ -36,6 +36,7 @@ import com.jme3.anim.Armature;
 import com.jme3.anim.Joint;
 import com.jme3.collision.*;
 import com.jme3.math.*;
+import com.jme3.renderer.Camera;
 import com.jme3.renderer.queue.RenderQueue;
 import com.jme3.scene.*;
 import com.jme3.scene.shape.Line;
@@ -60,11 +61,13 @@ public class ArmatureNode extends Node {
     private Map<Geometry, Joint> geomToJoint = new HashMap<>();
     private Joint selectedJoint = null;
     private Vector3f tmpStart = new Vector3f();
-    private Vector3f tmpEnd = new Vector3f();
-    ColorRGBA selectedColor = ColorRGBA.Orange;
-    ColorRGBA selectedColorJ = ColorRGBA.Yellow;
-    ;//new ColorRGBA(0.2f, 1f, 1.0f, 1.0f);
-    ColorRGBA baseColor = new ColorRGBA(0.05f, 0.05f, 0.05f, 1f);
+    private List<Vector3f> tmpEnds = new ArrayList<>();
+    private final static ColorRGBA selectedColor = ColorRGBA.Orange;
+    private final static ColorRGBA selectedColorJ = ColorRGBA.Yellow;
+    private final static ColorRGBA outlineColor = ColorRGBA.LightGray;
+    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) {
         Vector3f start = joint.getModelTransform().getTranslation().clone();
-        Vector3f end = null;
 
-        //One child only, the bone direction is from the parent joint to the child joint.
-        if (joint.getChildren().size() == 1) {
-            end = joint.getChildren().get(0).getModelTransform().getTranslation().clone();
+        Vector3f[] ends = null;
+        if (!joint.getChildren().isEmpty()) {
+            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);
@@ -99,19 +105,36 @@ public class ArmatureNode extends Node {
         attach(joints, deforms, jGeom);
         Geometry bGeom = null;
         Geometry bGeomO = null;
-        if (end != null) {
-            bGeom = new Geometry(joint.getName() + "Bone", new Line(start, end));
-            setColor(bGeom, baseColor);
+        if (ends != null) {
+            Mesh m = null;
+            Mesh mO = null;
+            Node wireAttach = wires;
+            Node outlinesAttach = outlines;
+            if (ends.length == 1) {
+                m = new Line(start, ends[0]);
+                mO = new Line(start, ends[0]);
+            } else {
+                m = new ArmatureInterJointsWire(start, ends);
+                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);
-            bGeomO = new Geometry(joint.getName() + "BoneOutline", new Line(start, end));
-            setColor(bGeomO, ColorRGBA.White);
-            bGeom.setUserData("start", wires.getWorldTransform().transformVector(start, start));
-            bGeom.setUserData("end", wires.getWorldTransform().transformVector(end, end));
+            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(wires, deforms, bGeom);
-            attach(outlines, deforms, bGeomO);
+            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});
 
         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) {
         if (deforms) {
             parent.attachChild(geom);
@@ -142,7 +169,10 @@ public class ArmatureNode extends Node {
             Geometry[] geomArray = jointToGeoms.get(selectedJoint);
             setColor(geomArray[0], selectedColorJ);
             setColor(geomArray[1], selectedColor);
-            setColor(geomArray[2], baseColor);
+
+            if (geomArray[2] != null) {
+                setColor(geomArray[2], baseColor);
+            }
             return j;
         }
         return null;
@@ -154,8 +184,10 @@ public class ArmatureNode extends Node {
         }
         Geometry[] geoms = jointToGeoms.get(selectedJoint);
         setColor(geoms[0], ColorRGBA.White);
-        setColor(geoms[1], baseColor);
-        setColor(geoms[2], ColorRGBA.White);
+        setColor(geoms[1], geoms[2] == null ? outlineColor : baseColor);
+        if (geoms[2] != null) {
+            setColor(geoms[2], outlineColor);
+        }
         selectedJoint = null;
     }
 
@@ -171,20 +203,25 @@ public class ArmatureNode extends Node {
             jGeom.setLocalTranslation(joint.getModelTransform().getTranslation());
             Geometry bGeom = geoms[1];
             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);
+                Vector3f start = bGeom.getUserData("start");
+                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());
+                    }
+                    updateBoneMesh(bGeom, start, ends);
                     Geometry bGeomO = geoms[2];
-                    updateBoneMesh(bGeomO);
-                    Vector3f start = bGeom.getUserData("start");
-                    Vector3f end = bGeom.getUserData("end");
-                    bGeom.setUserData("start", bGeom.getParent().getWorldTransform().transformVector(tmpStart, start));
-                    bGeom.setUserData("end", bGeom.getParent().getWorldTransform().transformVector(tmpEnd, end));
+                    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;
         for (Geometry g : geomToJoint.keySet()) {
-            float len = MathUtils.raySegmentShortestDistance((Ray) other, (Vector3f) g.getUserData("start"), (Vector3f) g.getUserData("end"));
-            if (len > 0 && len < 0.1f) {
-                CollisionResult res = new CollisionResult();
-                res.setGeometry(g);
-                results.addCollision(res);
-                nbCol++;
+            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) {
+                    CollisionResult res = new CollisionResult();
+                    res.setGeometry(g);
+                    results.addCollision(res);
+                    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);
         FloatBuffer fb = (FloatBuffer) pos.getData();
         fb.rewind();
-        fb.put(new float[]{tmpStart.x, tmpStart.y, tmpStart.z,
-                tmpEnd.x, tmpEnd.y, tmpEnd.z,});
+        fb.put(new float[]{start.x, start.y, start.z,
+                ends[0].x, ends[0].y, ends[0].z,});
         pos.updateData(fb);
-
         bGeom.updateModelBound();
     }
 

+ 59 - 0
jme3-core/src/main/resources/Common/MatDefs/Misc/DashedLine.j3md

@@ -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
+                }
+            }
+        }
+
+    }
+}

+ 37 - 0
jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Misc/Dashed.j3sn

@@ -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
+        }
+    }
+}

+ 10 - 0
jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Misc/Dashed100.frag

@@ -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;
+    }
+
+}

+ 30 - 0
jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Misc/PerspectiveDivide.j3sn

@@ -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
+        }
+    }
+}

+ 3 - 0
jme3-core/src/main/resources/Common/MatDefs/ShaderNodes/Misc/PerspectiveDivide100.frag

@@ -0,0 +1,3 @@
+void main(){
+	outVec = vec4(inVec.xyz / inVec.w,1.0);
+}

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

@@ -26,7 +26,7 @@ public class TestAnimMigration extends SimpleApplication {
     ArmatureDebugAppState debugAppState;
     AnimComposer composer;
     Queue<String> anims = new LinkedList<>();
-    boolean playAnim = true;
+    boolean playAnim = false;
 
     public static void main(String... argv) {
         TestAnimMigration app = new TestAnimMigration();
@@ -36,15 +36,15 @@ public class TestAnimMigration extends SimpleApplication {
     @Override
     public void simpleInitApp() {
         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);
         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");
+        //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");
+        Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);
 
         AnimMigrationUtils.migrate(model);