|
|
@ -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; |
|
|
|
|
|
|
|
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); |
|
|
|
geomToJoint.put(bGeom, joint); |
|
|
|
bGeomO = new Geometry(joint.getName() + "BoneOutline", new Line(start, end)); |
|
|
|
bGeom.setUserData("start", getWorldTransform().transformVector(start, start)); |
|
|
|
setColor(bGeomO, ColorRGBA.White); |
|
|
|
for (int i = 0; i < ends.length; i++) { |
|
|
|
bGeom.setUserData("start", wires.getWorldTransform().transformVector(start, start)); |
|
|
|
getWorldTransform().transformVector(ends[i], ends[i]); |
|
|
|
bGeom.setUserData("end", wires.getWorldTransform().transformVector(end, end)); |
|
|
|
} |
|
|
|
|
|
|
|
bGeom.setUserData("end", ends); |
|
|
|
bGeom.setQueueBucket(RenderQueue.Bucket.Transparent); |
|
|
|
bGeom.setQueueBucket(RenderQueue.Bucket.Transparent); |
|
|
|
attach(wires, deforms, bGeom); |
|
|
|
attach(wireAttach, deforms, bGeom); |
|
|
|
attach(outlines, deforms, bGeomO); |
|
|
|
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(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|