Adds a MigrationUtil to migrate from old system to new system
This commit is contained in:
parent
74f9a648d1
commit
a4267393e1
@ -4,8 +4,7 @@ import com.jme3.renderer.RenderManager;
|
|||||||
import com.jme3.renderer.ViewPort;
|
import com.jme3.renderer.ViewPort;
|
||||||
import com.jme3.scene.control.AbstractControl;
|
import com.jme3.scene.control.AbstractControl;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Nehon on 20/12/2017.
|
* Created by Nehon on 20/12/2017.
|
||||||
@ -65,6 +64,14 @@ public class AnimComposer extends AbstractControl {
|
|||||||
time = 0;
|
time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<AnimClip> getAnimClips() {
|
||||||
|
return Collections.unmodifiableCollection(animClipMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getAnimClipsNames() {
|
||||||
|
return Collections.unmodifiableCollection(animClipMap.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
if (currentAnimClip != null) {
|
if (currentAnimClip != null) {
|
||||||
|
@ -169,7 +169,7 @@ public class Armature implements JmeCloneable, Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the current Armature state as it's bind pose.
|
* Saves the current Armature state as its bind pose.
|
||||||
*/
|
*/
|
||||||
public void setBindPose() {
|
public void setBindPose() {
|
||||||
//make sure all bones are updated
|
//make sure all bones are updated
|
||||||
|
@ -34,11 +34,6 @@ public class Joint implements Savable, JmeCloneable {
|
|||||||
* Or relative to the model's origin for the root joint.
|
* Or relative to the model's origin for the root joint.
|
||||||
*/
|
*/
|
||||||
private Transform localTransform = new Transform();
|
private Transform localTransform = new Transform();
|
||||||
/**
|
|
||||||
* The base transform of the joint in local space.
|
|
||||||
* Those transform are the joint's initial value.
|
|
||||||
*/
|
|
||||||
private Transform baseLocalTransform = new Transform();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transform of the joint in model space. Relative to the origin of the model.
|
* The transform of the joint in model space. Relative to the origin of the model.
|
||||||
@ -134,7 +129,6 @@ public class Joint implements Savable, JmeCloneable {
|
|||||||
//Note that the whole Armature must be updated before calling this method.
|
//Note that the whole Armature must be updated before calling this method.
|
||||||
getModelTransform().toTransformMatrix(inverseModelBindMatrix);
|
getModelTransform().toTransformMatrix(inverseModelBindMatrix);
|
||||||
inverseModelBindMatrix.invertLocal();
|
inverseModelBindMatrix.invertLocal();
|
||||||
baseLocalTransform.set(localTransform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resetToBindPose() {
|
protected void resetToBindPose() {
|
||||||
@ -267,8 +261,6 @@ public class Joint implements Savable, JmeCloneable {
|
|||||||
this.children = cloner.clone(children);
|
this.children = cloner.clone(children);
|
||||||
this.attachedNode = cloner.clone(attachedNode);
|
this.attachedNode = cloner.clone(attachedNode);
|
||||||
this.targetGeometry = cloner.clone(targetGeometry);
|
this.targetGeometry = cloner.clone(targetGeometry);
|
||||||
|
|
||||||
this.baseLocalTransform = cloner.clone(baseLocalTransform);
|
|
||||||
this.localTransform = cloner.clone(localTransform);
|
this.localTransform = cloner.clone(localTransform);
|
||||||
this.jointModelTransform = cloner.clone(jointModelTransform);
|
this.jointModelTransform = cloner.clone(jointModelTransform);
|
||||||
this.inverseModelBindMatrix = cloner.clone(inverseModelBindMatrix);
|
this.inverseModelBindMatrix = cloner.clone(inverseModelBindMatrix);
|
||||||
@ -283,8 +275,6 @@ public class Joint implements Savable, JmeCloneable {
|
|||||||
name = input.readString("name", null);
|
name = input.readString("name", null);
|
||||||
attachedNode = (Node) input.readSavable("attachedNode", null);
|
attachedNode = (Node) input.readSavable("attachedNode", null);
|
||||||
targetGeometry = (Geometry) input.readSavable("targetGeometry", null);
|
targetGeometry = (Geometry) input.readSavable("targetGeometry", null);
|
||||||
baseLocalTransform = (Transform) input.readSavable("baseLocalTransforms", baseLocalTransform);
|
|
||||||
localTransform.set(baseLocalTransform);
|
|
||||||
inverseModelBindMatrix = (Matrix4f) input.readSavable("inverseModelBindMatrix", inverseModelBindMatrix);
|
inverseModelBindMatrix = (Matrix4f) input.readSavable("inverseModelBindMatrix", inverseModelBindMatrix);
|
||||||
jointModelTransform = (JointModelTransform) input.readSavable("jointModelTransform", null);
|
jointModelTransform = (JointModelTransform) input.readSavable("jointModelTransform", null);
|
||||||
|
|
||||||
@ -301,7 +291,6 @@ public class Joint implements Savable, JmeCloneable {
|
|||||||
output.write(name, "name", null);
|
output.write(name, "name", null);
|
||||||
output.write(attachedNode, "attachedNode", null);
|
output.write(attachedNode, "attachedNode", null);
|
||||||
output.write(targetGeometry, "targetGeometry", null);
|
output.write(targetGeometry, "targetGeometry", null);
|
||||||
output.write(baseLocalTransform, "baseLocalTransform", new Transform());
|
|
||||||
output.write(inverseModelBindMatrix, "inverseModelBindMatrix", new Matrix4f());
|
output.write(inverseModelBindMatrix, "inverseModelBindMatrix", new Matrix4f());
|
||||||
output.writeSavableArrayList(children, "children", null);
|
output.writeSavableArrayList(children, "children", null);
|
||||||
output.write(jointModelTransform, "jointModelTransform", null);
|
output.write(jointModelTransform, "jointModelTransform", null);
|
||||||
|
@ -1,24 +1,189 @@
|
|||||||
package com.jme3.anim.util;
|
package com.jme3.anim.util;
|
||||||
|
|
||||||
import com.jme3.animation.AnimControl;
|
import com.jme3.anim.*;
|
||||||
import com.jme3.scene.SceneGraphVisitor;
|
import com.jme3.animation.*;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.math.Quaternion;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public class AnimMigrationUtils {
|
public class AnimMigrationUtils {
|
||||||
|
|
||||||
|
private static AnimControlVisitor animControlVisitor = new AnimControlVisitor();
|
||||||
|
private static SkeletonControlVisitor skeletonControlVisitor = new SkeletonControlVisitor();
|
||||||
|
|
||||||
|
|
||||||
public static Spatial migrate(Spatial source) {
|
public static Spatial migrate(Spatial source) {
|
||||||
//source.depthFirstTraversal();
|
Map<Skeleton, Armature> skeletonArmatureMap = new HashMap<>();
|
||||||
|
animControlVisitor.setMappings(skeletonArmatureMap);
|
||||||
|
source.depthFirstTraversal(animControlVisitor);
|
||||||
|
skeletonControlVisitor.setMappings(skeletonArmatureMap);
|
||||||
|
source.depthFirstTraversal(skeletonControlVisitor);
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AnimControlVisitor implements SceneGraphVisitor {
|
private static class AnimControlVisitor implements SceneGraphVisitor {
|
||||||
|
|
||||||
|
Map<Skeleton, Armature> skeletonArmatureMap;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(Spatial spatial) {
|
public void visit(Spatial spatial) {
|
||||||
AnimControl control = spatial.getControl(AnimControl.class);
|
AnimControl control = spatial.getControl(AnimControl.class);
|
||||||
if (control != null) {
|
if (control != null) {
|
||||||
|
AnimComposer composer = new AnimComposer();
|
||||||
|
Skeleton skeleton = control.getSkeleton();
|
||||||
|
if (skeleton == null) {
|
||||||
|
//only bone anim for now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Joint[] joints = new Joint[skeleton.getBoneCount()];
|
||||||
|
for (int i = 0; i < skeleton.getBoneCount(); i++) {
|
||||||
|
Bone b = skeleton.getBone(i);
|
||||||
|
Joint j = joints[i];
|
||||||
|
if (j == null) {
|
||||||
|
j = fromBone(b);
|
||||||
|
joints[i] = j;
|
||||||
|
}
|
||||||
|
for (Bone bone : b.getChildren()) {
|
||||||
|
int index = skeleton.getBoneIndex(bone);
|
||||||
|
Joint joint = joints[index];
|
||||||
|
if (joint == null) {
|
||||||
|
joint = fromBone(bone);
|
||||||
|
}
|
||||||
|
j.addChild(joint);
|
||||||
|
joints[index] = joint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Armature armature = new Armature(joints);
|
||||||
|
armature.setBindPose();
|
||||||
|
skeletonArmatureMap.put(skeleton, armature);
|
||||||
|
|
||||||
|
for (String animName : control.getAnimationNames()) {
|
||||||
|
Animation anim = control.getAnim(animName);
|
||||||
|
AnimClip clip = new AnimClip(animName);
|
||||||
|
Joint[] staticJoints = new Joint[joints.length];
|
||||||
|
System.arraycopy(joints, 0, staticJoints, 0, joints.length);
|
||||||
|
for (Track track : anim.getTracks()) {
|
||||||
|
if (track instanceof BoneTrack) {
|
||||||
|
BoneTrack boneTrack = (BoneTrack) track;
|
||||||
|
int index = boneTrack.getTargetBoneIndex();
|
||||||
|
Bone bone = skeleton.getBone(index);
|
||||||
|
Joint joint = joints[index];
|
||||||
|
JointTrack jointTrack = fromBoneTrack(boneTrack, bone, joint);
|
||||||
|
clip.addTrack(jointTrack);
|
||||||
|
//this joint is animated let's remove it from the static joints
|
||||||
|
staticJoints[index] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < staticJoints.length; i++) {
|
||||||
|
Joint j = staticJoints[i];
|
||||||
|
if (j != null) {
|
||||||
|
// joint has no track , we create one with the default pose
|
||||||
|
float[] times = new float[]{0};
|
||||||
|
Vector3f[] translations = new Vector3f[]{j.getLocalTranslation()};
|
||||||
|
Quaternion[] rotations = new Quaternion[]{j.getLocalRotation()};
|
||||||
|
Vector3f[] scales = new Vector3f[]{j.getLocalScale()};
|
||||||
|
JointTrack track = new JointTrack(j, times, translations, rotations, scales);
|
||||||
|
clip.addTrack(track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
composer.addAnimClip(clip);
|
||||||
|
}
|
||||||
|
spatial.removeControl(control);
|
||||||
|
spatial.addControl(composer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappings(Map<Skeleton, Armature> skeletonArmatureMap) {
|
||||||
|
this.skeletonArmatureMap = skeletonArmatureMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SkeletonControlVisitor implements SceneGraphVisitor {
|
||||||
|
|
||||||
|
Map<Skeleton, Armature> skeletonArmatureMap;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Spatial spatial) {
|
||||||
|
SkeletonControl control = spatial.getControl(SkeletonControl.class);
|
||||||
|
if (control != null) {
|
||||||
|
Armature armature = skeletonArmatureMap.get(control.getSkeleton());
|
||||||
|
SkinningControl skinningControl = new SkinningControl(armature);
|
||||||
|
Map<String, List<Spatial>> attachedSpatials = new HashMap<>();
|
||||||
|
for (int i = 0; i < control.getSkeleton().getBoneCount(); i++) {
|
||||||
|
Bone b = control.getSkeleton().getBone(i);
|
||||||
|
Node n = control.getAttachmentsNode(b.getName());
|
||||||
|
n.removeFromParent();
|
||||||
|
if (!n.getChildren().isEmpty()) {
|
||||||
|
attachedSpatials.put(b.getName(), n.getChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spatial.removeControl(control);
|
||||||
|
spatial.addControl(skinningControl);
|
||||||
|
for (String name : attachedSpatials.keySet()) {
|
||||||
|
List<Spatial> spatials = attachedSpatials.get(name);
|
||||||
|
for (Spatial child : spatials) {
|
||||||
|
skinningControl.getAttachmentsNode(name).attachChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMappings(Map<Skeleton, Armature> skeletonArmatureMap) {
|
||||||
|
this.skeletonArmatureMap = skeletonArmatureMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JointTrack fromBoneTrack(BoneTrack boneTrack, Bone bone, Joint joint) {
|
||||||
|
float[] times = new float[boneTrack.getTimes().length];
|
||||||
|
int length = times.length;
|
||||||
|
System.arraycopy(boneTrack.getTimes(), 0, times, 0, length);
|
||||||
|
//translation
|
||||||
|
Vector3f[] translations = new Vector3f[length];
|
||||||
|
if (boneTrack.getTranslations() != null) {
|
||||||
|
for (int i = 0; i < boneTrack.getTranslations().length; i++) {
|
||||||
|
Vector3f oldTrans = boneTrack.getTranslations()[i];
|
||||||
|
Vector3f newTrans = new Vector3f();
|
||||||
|
newTrans.set(bone.getBindPosition()).addLocal(oldTrans);
|
||||||
|
translations[i] = newTrans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//rotation
|
||||||
|
Quaternion[] rotations = new Quaternion[length];
|
||||||
|
if (boneTrack.getRotations() != null) {
|
||||||
|
for (int i = 0; i < boneTrack.getRotations().length; i++) {
|
||||||
|
Quaternion oldRot = boneTrack.getRotations()[i];
|
||||||
|
Quaternion newRot = new Quaternion();
|
||||||
|
newRot.set(bone.getBindRotation()).multLocal(oldRot);
|
||||||
|
rotations[i] = newRot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//scale
|
||||||
|
Vector3f[] scales = new Vector3f[length];
|
||||||
|
if (boneTrack.getScales() != null) {
|
||||||
|
for (int i = 0; i < boneTrack.getScales().length; i++) {
|
||||||
|
Vector3f oldScale = boneTrack.getScales()[i];
|
||||||
|
Vector3f newScale = new Vector3f();
|
||||||
|
newScale.set(bone.getBindScale()).multLocal(oldScale);
|
||||||
|
scales[i] = newScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JointTrack(joint, times, translations, rotations, scales);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Joint fromBone(Bone b) {
|
||||||
|
Joint j = new Joint(b.getName());
|
||||||
|
j.setLocalTranslation(b.getBindPosition());
|
||||||
|
j.setLocalRotation(b.getBindRotation());
|
||||||
|
j.setLocalScale(b.getBindScale());
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -6,8 +6,7 @@ package com.jme3.scene.debug.custom;
|
|||||||
|
|
||||||
import com.jme3.anim.*;
|
import com.jme3.anim.*;
|
||||||
import com.jme3.app.Application;
|
import com.jme3.app.Application;
|
||||||
import com.jme3.app.state.AbstractAppState;
|
import com.jme3.app.state.BaseAppState;
|
||||||
import com.jme3.app.state.AppStateManager;
|
|
||||||
import com.jme3.collision.CollisionResults;
|
import com.jme3.collision.CollisionResults;
|
||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
import com.jme3.input.controls.ActionListener;
|
import com.jme3.input.controls.ActionListener;
|
||||||
@ -22,15 +21,17 @@ import java.util.*;
|
|||||||
/**
|
/**
|
||||||
* @author Nehon
|
* @author Nehon
|
||||||
*/
|
*/
|
||||||
public class ArmatureDebugAppState extends AbstractAppState {
|
public class ArmatureDebugAppState extends BaseAppState {
|
||||||
|
|
||||||
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;
|
||||||
|
ViewPort vp;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(AppStateManager stateManager, Application app) {
|
protected void initialize(Application app) {
|
||||||
ViewPort vp = app.getRenderManager().createMainView("debug", app.getCamera());
|
vp = app.getRenderManager().createMainView("debug", app.getCamera());
|
||||||
vp.attachScene(debugNode);
|
vp.attachScene(debugNode);
|
||||||
vp.setClearDepth(true);
|
vp.setClearDepth(true);
|
||||||
this.app = app;
|
this.app = app;
|
||||||
@ -39,12 +40,26 @@ public class ArmatureDebugAppState extends AbstractAppState {
|
|||||||
}
|
}
|
||||||
app.getInputManager().addListener(actionListener, "shoot");
|
app.getInputManager().addListener(actionListener, "shoot");
|
||||||
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));
|
||||||
super.initialize(stateManager, app);
|
|
||||||
|
|
||||||
|
|
||||||
debugNode.addLight(new DirectionalLight(new Vector3f(-1f, -1f, -1f).normalizeLocal()));
|
debugNode.addLight(new DirectionalLight(new Vector3f(-1f, -1f, -1f).normalizeLocal()));
|
||||||
|
|
||||||
debugNode.addLight(new DirectionalLight(new Vector3f(1f, 1f, 1f).normalizeLocal(), new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f)));
|
debugNode.addLight(new DirectionalLight(new Vector3f(1f, 1f, 1f).normalizeLocal(), new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f)));
|
||||||
|
vp.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cleanup(Application app) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onEnable() {
|
||||||
|
vp.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDisable() {
|
||||||
|
vp.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,13 +68,13 @@ public class ArmatureDebugAppState extends AbstractAppState {
|
|||||||
debugNode.updateGeometricState();
|
debugNode.updateGeometricState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArmatureDebugger addArmature(SkinningControl skinningControl) {
|
public ArmatureDebugger addArmatureFrom(SkinningControl skinningControl) {
|
||||||
Armature armature = skinningControl.getArmature();
|
Armature armature = skinningControl.getArmature();
|
||||||
Spatial forSpatial = skinningControl.getSpatial();
|
Spatial forSpatial = skinningControl.getSpatial();
|
||||||
return addArmature(armature, forSpatial);
|
return addArmatureFrom(armature, forSpatial);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArmatureDebugger addArmature(Armature armature, Spatial forSpatial) {
|
public ArmatureDebugger addArmatureFrom(Armature armature, Spatial forSpatial) {
|
||||||
|
|
||||||
ArmatureDebugger ad = new ArmatureDebugger(forSpatial.getName() + "_Armature", armature);
|
ArmatureDebugger ad = new ArmatureDebugger(forSpatial.getName() + "_Armature", armature);
|
||||||
ad.setLocalTransform(forSpatial.getWorldTransform());
|
ad.setLocalTransform(forSpatial.getWorldTransform());
|
||||||
|
@ -0,0 +1,147 @@
|
|||||||
|
package jme3test.model.anim;
|
||||||
|
|
||||||
|
import com.jme3.anim.AnimComposer;
|
||||||
|
import com.jme3.anim.SkinningControl;
|
||||||
|
import com.jme3.anim.util.AnimMigrationUtils;
|
||||||
|
import com.jme3.app.ChaseCameraAppState;
|
||||||
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.controls.ActionListener;
|
||||||
|
import com.jme3.input.controls.KeyTrigger;
|
||||||
|
import com.jme3.light.AmbientLight;
|
||||||
|
import com.jme3.light.DirectionalLight;
|
||||||
|
import com.jme3.math.*;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.scene.debug.custom.ArmatureDebugAppState;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Nehon on 18/12/2017.
|
||||||
|
*/
|
||||||
|
public class TestAnimMigration extends SimpleApplication {
|
||||||
|
|
||||||
|
ArmatureDebugAppState debugAppState;
|
||||||
|
AnimComposer composer;
|
||||||
|
Queue<String> anims = new LinkedList<>();
|
||||||
|
boolean playAnim = true;
|
||||||
|
|
||||||
|
public static void main(String... argv) {
|
||||||
|
TestAnimMigration app = new TestAnimMigration();
|
||||||
|
app.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleInitApp() {
|
||||||
|
setTimer(new EraseTimer());
|
||||||
|
//cam.setFrustumPerspective(90f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 10f);
|
||||||
|
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/Sinbad/Sinbad.mesh.xml");
|
||||||
|
//Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
|
||||||
|
|
||||||
|
AnimMigrationUtils.migrate(model);
|
||||||
|
|
||||||
|
rootNode.attachChild(model);
|
||||||
|
|
||||||
|
|
||||||
|
debugAppState = new ArmatureDebugAppState();
|
||||||
|
stateManager.attach(debugAppState);
|
||||||
|
|
||||||
|
setupModel(model);
|
||||||
|
|
||||||
|
flyCam.setEnabled(false);
|
||||||
|
|
||||||
|
Node target = new Node("CamTarget");
|
||||||
|
//target.setLocalTransform(model.getLocalTransform());
|
||||||
|
target.move(0, 1, 0);
|
||||||
|
ChaseCameraAppState chaseCam = new ChaseCameraAppState();
|
||||||
|
chaseCam.setTarget(target);
|
||||||
|
getStateManager().attach(chaseCam);
|
||||||
|
chaseCam.setInvertHorizontalAxis(true);
|
||||||
|
chaseCam.setInvertVerticalAxis(true);
|
||||||
|
chaseCam.setZoomSpeed(0.5f);
|
||||||
|
chaseCam.setMinVerticalRotation(-FastMath.HALF_PI);
|
||||||
|
chaseCam.setRotationSpeed(3);
|
||||||
|
chaseCam.setDefaultDistance(3);
|
||||||
|
chaseCam.setMinDistance(0.01f);
|
||||||
|
chaseCam.setZoomSpeed(0.01f);
|
||||||
|
chaseCam.setDefaultVerticalRotation(0.3f);
|
||||||
|
|
||||||
|
initInputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initInputs() {
|
||||||
|
inputManager.addMapping("toggleAnim", new KeyTrigger(KeyInput.KEY_RETURN));
|
||||||
|
|
||||||
|
inputManager.addListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void onAction(String name, boolean isPressed, float tpf) {
|
||||||
|
if (isPressed) {
|
||||||
|
playAnim = !playAnim;
|
||||||
|
if (playAnim) {
|
||||||
|
String anim = anims.poll();
|
||||||
|
anims.add(anim);
|
||||||
|
composer.setCurrentAnimClip(anim);
|
||||||
|
System.err.println(anim);
|
||||||
|
} else {
|
||||||
|
composer.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "toggleAnim");
|
||||||
|
inputManager.addMapping("nextAnim", new KeyTrigger(KeyInput.KEY_RIGHT));
|
||||||
|
inputManager.addListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void onAction(String name, boolean isPressed, float tpf) {
|
||||||
|
if (isPressed && composer != null) {
|
||||||
|
String anim = anims.poll();
|
||||||
|
anims.add(anim);
|
||||||
|
composer.setCurrentAnimClip(anim);
|
||||||
|
System.err.println(anim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "nextAnim");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupModel(Spatial model) {
|
||||||
|
if (composer != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
composer = model.getControl(AnimComposer.class);
|
||||||
|
if (composer != null) {
|
||||||
|
|
||||||
|
SkinningControl sc = model.getControl(SkinningControl.class);
|
||||||
|
debugAppState.addArmatureFrom(sc);
|
||||||
|
|
||||||
|
anims.clear();
|
||||||
|
for (String name : composer.getAnimClipsNames()) {
|
||||||
|
anims.add(name);
|
||||||
|
}
|
||||||
|
if (anims.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (playAnim) {
|
||||||
|
String anim = anims.poll();
|
||||||
|
anims.add(anim);
|
||||||
|
composer.setCurrentAnimClip(anim);
|
||||||
|
System.err.println(anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (model instanceof Node) {
|
||||||
|
Node n = (Node) model;
|
||||||
|
for (Spatial child : n.getChildren()) {
|
||||||
|
setupModel(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@ import com.jme3.app.SimpleApplication;
|
|||||||
import com.jme3.input.KeyInput;
|
import com.jme3.input.KeyInput;
|
||||||
import com.jme3.input.controls.ActionListener;
|
import com.jme3.input.controls.ActionListener;
|
||||||
import com.jme3.input.controls.KeyTrigger;
|
import com.jme3.input.controls.KeyTrigger;
|
||||||
import com.jme3.light.DirectionalLight;
|
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
import com.jme3.scene.*;
|
import com.jme3.scene.*;
|
||||||
@ -37,6 +36,7 @@ public class TestArmature extends SimpleApplication {
|
|||||||
//cam.setFrustumPerspective(90f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 10f);
|
//cam.setFrustumPerspective(90f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 10f);
|
||||||
viewPort.setBackgroundColor(ColorRGBA.DarkGray);
|
viewPort.setBackgroundColor(ColorRGBA.DarkGray);
|
||||||
|
|
||||||
|
//create armature
|
||||||
Joint root = new Joint("Root_Joint");
|
Joint root = new Joint("Root_Joint");
|
||||||
j1 = new Joint("Joint_1");
|
j1 = new Joint("Joint_1");
|
||||||
j2 = new Joint("Joint_2");
|
j2 = new Joint("Joint_2");
|
||||||
@ -52,9 +52,9 @@ public class TestArmature extends SimpleApplication {
|
|||||||
|
|
||||||
final Armature armature = new Armature(joints);
|
final Armature armature = new Armature(joints);
|
||||||
// armature.setModelTransformClass(SeparateJointModelTransform.class);
|
// armature.setModelTransformClass(SeparateJointModelTransform.class);
|
||||||
|
|
||||||
armature.setBindPose();
|
armature.setBindPose();
|
||||||
|
|
||||||
|
//create animations
|
||||||
AnimClip clip = new AnimClip("anim");
|
AnimClip clip = new AnimClip("anim");
|
||||||
float[] times = new float[]{0, 2, 4};
|
float[] times = new float[]{0, 2, 4};
|
||||||
Quaternion[] rotations = new Quaternion[]{
|
Quaternion[] rotations = new Quaternion[]{
|
||||||
@ -83,15 +83,18 @@ public class TestArmature extends SimpleApplication {
|
|||||||
clip.addTrack(track1);
|
clip.addTrack(track1);
|
||||||
clip.addTrack(track2);
|
clip.addTrack(track2);
|
||||||
|
|
||||||
|
//create the animComposer control
|
||||||
final AnimComposer composer = new AnimComposer();
|
final AnimComposer composer = new AnimComposer();
|
||||||
composer.addAnimClip(clip);
|
composer.addAnimClip(clip);
|
||||||
|
|
||||||
|
//create the SkinningControl
|
||||||
SkinningControl ac = new SkinningControl(armature);
|
SkinningControl ac = new SkinningControl(armature);
|
||||||
ac.setHardwareSkinningPreferred(false);
|
ac.setHardwareSkinningPreferred(false);
|
||||||
Node node = new Node("Test Armature");
|
Node node = new Node("Test Armature");
|
||||||
|
|
||||||
rootNode.attachChild(node);
|
rootNode.attachChild(node);
|
||||||
|
|
||||||
|
//Create the mesh to deform.
|
||||||
Geometry cylinder = new Geometry("cylinder", createMesh());
|
Geometry cylinder = new Geometry("cylinder", createMesh());
|
||||||
Material m = new Material(assetManager, "Common/MatDefs/Misc/fakeLighting.j3md");
|
Material m = new Material(assetManager, "Common/MatDefs/Misc/fakeLighting.j3md");
|
||||||
m.setColor("Color", ColorRGBA.randomColor());
|
m.setColor("Color", ColorRGBA.randomColor());
|
||||||
@ -103,14 +106,9 @@ public class TestArmature extends SimpleApplication {
|
|||||||
composer.setCurrentAnimClip("anim");
|
composer.setCurrentAnimClip("anim");
|
||||||
|
|
||||||
ArmatureDebugAppState debugAppState = new ArmatureDebugAppState();
|
ArmatureDebugAppState debugAppState = new ArmatureDebugAppState();
|
||||||
debugAppState.addArmature(ac);
|
debugAppState.addArmatureFrom(ac);
|
||||||
stateManager.attach(debugAppState);
|
stateManager.attach(debugAppState);
|
||||||
|
|
||||||
rootNode.addLight(new DirectionalLight(new Vector3f(-1f, -1f, -1f).normalizeLocal()));
|
|
||||||
|
|
||||||
rootNode.addLight(new DirectionalLight(new Vector3f(1f, 1f, 1f).normalizeLocal(), new ColorRGBA(0.7f, 0.7f, 0.7f, 1.0f)));
|
|
||||||
|
|
||||||
|
|
||||||
flyCam.setEnabled(false);
|
flyCam.setEnabled(false);
|
||||||
|
|
||||||
ChaseCameraAppState chaseCam = new ChaseCameraAppState();
|
ChaseCameraAppState chaseCam = new ChaseCameraAppState();
|
||||||
@ -132,12 +130,10 @@ public class TestArmature extends SimpleApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void onAction(String name, boolean isPressed, float tpf) {
|
public void onAction(String name, boolean isPressed, float tpf) {
|
||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
play = false;
|
|
||||||
composer.reset();
|
composer.reset();
|
||||||
armature.resetToBindPose();
|
armature.resetToBindPose();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
play = true;
|
|
||||||
composer.setCurrentAnimClip("anim");
|
composer.setCurrentAnimClip("anim");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,12 +198,10 @@ public class TestArmature extends SimpleApplication {
|
|||||||
|
|
||||||
c.updateCounts();
|
c.updateCounts();
|
||||||
c.updateBound();
|
c.updateBound();
|
||||||
//the mesh has some skinning let's create needed buffers for HW skinning
|
|
||||||
//creating empty buffers for HW skinning
|
|
||||||
//the buffers will be setup if ever used.
|
|
||||||
VertexBuffer weightsHW = new VertexBuffer(VertexBuffer.Type.HWBoneWeight);
|
VertexBuffer weightsHW = new VertexBuffer(VertexBuffer.Type.HWBoneWeight);
|
||||||
VertexBuffer indicesHW = new VertexBuffer(VertexBuffer.Type.HWBoneIndex);
|
VertexBuffer indicesHW = new VertexBuffer(VertexBuffer.Type.HWBoneIndex);
|
||||||
//setting usage to cpuOnly so that the buffer is not send empty to the GPU
|
|
||||||
indicesHW.setUsage(VertexBuffer.Usage.CpuOnly);
|
indicesHW.setUsage(VertexBuffer.Usage.CpuOnly);
|
||||||
weightsHW.setUsage(VertexBuffer.Usage.CpuOnly);
|
weightsHW.setUsage(VertexBuffer.Usage.CpuOnly);
|
||||||
c.setBuffer(weightsHW);
|
c.setBuffer(weightsHW);
|
||||||
@ -220,20 +214,4 @@ public class TestArmature extends SimpleApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float time = 0;
|
|
||||||
boolean play = true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void simpleUpdate(float tpf) {
|
|
||||||
|
|
||||||
|
|
||||||
// if (play == false) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// time += tpf;
|
|
||||||
// float rot = FastMath.sin(time);
|
|
||||||
// j1.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI * rot, Vector3f.UNIT_Z));
|
|
||||||
// j2.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI * rot, Vector3f.UNIT_Z));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user