Merge branch 'fbx-import-animation' into experimental

experimental
Kirill Vainer 9 years ago
commit 962ab22ef4
  1. 5
      jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java
  2. 4
      jme3-core/src/main/resources/com/jme3/asset/General.cfg
  3. 1
      jme3-plugins/build.gradle
  4. 56
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/FbxLoader.java
  5. 10
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxAnimUtil.java
  6. 16
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxBindPose.java
  7. 26
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxCluster.java
  8. 52
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxLimbNode.java
  9. 112
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkeleton.java
  10. 74
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkinDeformer.java
  11. 22
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxToJmeTrack.java
  12. 6
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/material/FbxMaterial.java
  13. 62
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/mesh/FbxMesh.java
  14. 49
      jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/node/FbxNode.java

@ -108,7 +108,7 @@ public class SkeletonControl extends AbstractControl implements Cloneable {
/**
* Material references used for hardware skinning
*/
private Set<Material> materials = new HashSet<Material>();
private final HashSet<Material> materials = new HashSet<Material>();
/**
* Serialization only. Do not use.
@ -202,6 +202,9 @@ public class SkeletonControl extends AbstractControl implements Cloneable {
* @param skeleton the skeleton
*/
public SkeletonControl(Skeleton skeleton) {
if (skeleton == null) {
throw new IllegalArgumentException("skeleton cannot be null");
}
this.skeleton = skeleton;
}

@ -22,5 +22,5 @@ LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend
LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, geom, tsctrl, tseval, glsl, glsllib
LOADER com.jme3.scene.plugins.fbx.SceneLoader : fbx
LOADER com.jme3.scene.plugins.fbx.SceneWithAnimationLoader : fba
LOADER com.jme3.scene.plugins.fbx.FbxLoader : fbx
# LOADER com.jme3.scene.plugins.fbx.SceneWithAnimationLoader : fba

@ -5,6 +5,7 @@ if (!hasProperty('mainClass')) {
sourceSets {
main {
java {
srcDir 'src/main/java'
srcDir 'src/ogre/java'
srcDir 'src/fbx/java'
srcDir 'src/xml/java'

@ -150,7 +150,7 @@ public class FbxLoader implements AssetLoader {
private void loadData(InputStream stream) throws IOException {
FbxFile scene = FbxReader.readFBX(stream);
FbxDump.dumpFile(scene);
// FbxDump.dumpFile(scene);
// TODO: Load FBX object templates
@ -346,33 +346,33 @@ public class FbxLoader implements AssetLoader {
duration = pair.getDuration();
if (pair.node instanceof FbxLimbNode) {
// Find the spatial that has the skeleton for this limb.
FbxLimbNode limbNode = (FbxLimbNode) pair.node;
Bone bone = limbNode.getJmeBone();
Spatial jmeSpatial = limbNode.getSkeletonHolder().getJmeObject();
Skeleton skeleton = limbNode.getSkeletonHolder().getJmeSkeleton();
// Get the animation control (create if missing).
AnimControl animControl = jmeSpatial.getControl(AnimControl.class);
if (animControl.getSkeleton() != skeleton) {
throw new UnsupportedOperationException();
}
// Get the animation (create if missing).
Animation anim = animControl.getAnim(animName);
if (anim == null) {
anim = new Animation(animName, duration);
animControl.addAnim(anim);
}
// Find the bone index from the spatial's skeleton.
int boneIndex = skeleton.getBoneIndex(bone);
// Generate the bone track.
BoneTrack bt = pair.toJmeBoneTrack(boneIndex, bone.getBindInverseTransform());
// Add the bone track to the animation.
anim.addTrack(bt);
// // Find the spatial that has the skeleton for this limb.
// FbxLimbNode limbNode = (FbxLimbNode) pair.node;
// Bone bone = limbNode.getJmeBone();
// Spatial jmeSpatial = limbNode.getSkeletonRoot().getJmeObject();
// Skeleton skeleton = limbNode.getSkeletonRoot().getJmeSkeleton();
//
// // Get the animation control (create if missing).
// AnimControl animControl = jmeSpatial.getControl(AnimControl.class);
// if (animControl.getSkeleton() != skeleton) {
// throw new UnsupportedOperationException();
// }
//
// // Get the animation (create if missing).
// Animation anim = animControl.getAnim(animName);
// if (anim == null) {
// anim = new Animation(animName, duration);
// animControl.addAnim(anim);
// }
//
// // Find the bone index from the spatial's skeleton.
// int boneIndex = skeleton.getBoneIndex(bone);
//
// // Generate the bone track.
// BoneTrack bt = pair.toJmeBoneTrack(boneIndex, bone.getBindInverseTransform());
//
// // Add the bone track to the animation.
// anim.addTrack(bt);
} else {
// Create the spatial animation
Animation anim = new Animation(animName, duration);

@ -31,6 +31,8 @@
*/
package com.jme3.scene.plugins.fbx.anim;
import com.jme3.math.Matrix4f;
public class FbxAnimUtil {
/**
* Conversion factor from FBX animation time unit to seconds.
@ -41,4 +43,12 @@ public class FbxAnimUtil {
public static final String CURVE_NODE_PROPERTY_Y = "d|Y";
public static final String CURVE_NODE_PROPERTY_Z = "d|Z";
public static final String CURVE_NODE_PROPERTY_VISIBILITY = "d|Visibility";
public static Matrix4f toMatrix4(double[] matrixData) {
float[] matrixDataFloat = new float[16];
for (int i = 0; i < matrixData.length; i++) {
matrixDataFloat[i] = (float) matrixData[i];
}
return new Matrix4f(matrixDataFloat);
}
}

@ -56,31 +56,25 @@ public class FbxBindPose extends FbxObject<Map<FbxId, Matrix4f>> {
}
FbxId node = null;
float[] matData = null;
double[] matData = null;
for (FbxElement e : child.children) {
if (e.id.equals("Node")) {
node = FbxId.create(e.properties.get(0));
} else if (e.id.equals("Matrix")) {
double[] matDataDoubles = (double[]) e.properties.get(0);
matData = (double[]) e.properties.get(0);
if (matDataDoubles.length != 16) {
if (matData.length != 16) {
// corrupt
throw new UnsupportedOperationException("Bind pose matrix "
+ "must have 16 doubles, but it has "
+ matDataDoubles.length + ". Data is corrupt");
}
matData = new float[16];
for (int i = 0; i < matDataDoubles.length; i++) {
matData[i] = (float) matDataDoubles[i];
+ matData.length + ". Data is corrupt");
}
}
}
if (node != null && matData != null) {
Matrix4f matrix = new Matrix4f(matData);
bindPose.put(node, matrix);
bindPose.put(node, FbxAnimUtil.toMatrix4(matData));
}
}
}

@ -32,6 +32,7 @@
package com.jme3.scene.plugins.fbx.anim;
import com.jme3.asset.AssetManager;
import com.jme3.math.Matrix4f;
import com.jme3.scene.plugins.fbx.file.FbxElement;
import com.jme3.scene.plugins.fbx.obj.FbxObject;
import java.util.logging.Level;
@ -45,6 +46,10 @@ public class FbxCluster extends FbxObject {
private double[] weights;
private FbxLimbNode limb;
private Matrix4f transformMatrix;
private Matrix4f transformLinkMatrix;
private Matrix4f transformAssociateModelMatrix;
public FbxCluster(AssetManager assetManager, String sceneFolderName) {
super(assetManager, sceneFolderName);
}
@ -57,6 +62,15 @@ public class FbxCluster extends FbxObject {
indexes = (int[]) e.properties.get(0);
} else if (e.id.equals("Weights")) {
weights = (double[]) e.properties.get(0);
} else if (e.id.equals("Transform")) {
double[] data = (double[]) e.properties.get(0);
transformMatrix = FbxAnimUtil.toMatrix4(data);
} else if (e.id.equals("TransformLink")) {
double[] data = (double[]) e.properties.get(0);
transformLinkMatrix = FbxAnimUtil.toMatrix4(data);
} else if (e.id.equals("TransformAssociateModel")) {
double[] data = (double[]) e.properties.get(0);
transformAssociateModelMatrix = FbxAnimUtil.toMatrix4(data);
}
}
}
@ -86,6 +100,18 @@ public class FbxCluster extends FbxObject {
return;
}
limb = (FbxLimbNode) object;
System.out.println(" ----- for limb: " + limb.getName());
System.out.println(" transform : " + transformMatrix);
System.out.println(" transform link : " + transformLinkMatrix);
System.out.println(" transform associate model : " + transformAssociateModelMatrix);
// Invert(Invert(TransformLinkMatrix) * TransformMatrix * Geometry)
Matrix4f accumMatrix = transformLinkMatrix.invert();
accumMatrix.multLocal(transformMatrix);
accumMatrix.invertLocal();
System.out.println(" limb bind pose : " + accumMatrix);
} else {
unsupportedConnectObject(object);
}

@ -31,64 +31,22 @@
*/
package com.jme3.scene.plugins.fbx.anim;
import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.asset.AssetManager;
import com.jme3.scene.plugins.fbx.node.FbxNode;
import java.util.ArrayList;
import java.util.List;
public class FbxLimbNode extends FbxNode {
protected FbxNode skeletonHolder;
protected Bone bone;
protected FbxNode skeletonRoot;
public FbxLimbNode(AssetManager assetManager, String sceneFolderName) {
super(assetManager, sceneFolderName);
}
private static void createBones(FbxNode skeletonHolderNode, FbxLimbNode limb, List<Bone> bones) {
limb.skeletonHolder = skeletonHolderNode;
Bone parentBone = limb.getJmeBone();
bones.add(parentBone);
for (FbxNode child : limb.children) {
if (child instanceof FbxLimbNode) {
FbxLimbNode childLimb = (FbxLimbNode) child;
createBones(skeletonHolderNode, childLimb, bones);
parentBone.addChild(childLimb.getJmeBone());
}
}
}
public static Skeleton createSkeleton(FbxNode skeletonHolderNode) {
if (skeletonHolderNode instanceof FbxLimbNode) {
throw new UnsupportedOperationException("Limb nodes cannot be skeleton holders");
}
List<Bone> bones = new ArrayList<Bone>();
for (FbxNode child : skeletonHolderNode.getChildren()) {
if (child instanceof FbxLimbNode) {
createBones(skeletonHolderNode, (FbxLimbNode) child, bones);
}
}
return new Skeleton(bones.toArray(new Bone[0]));
}
public FbxNode getSkeletonHolder() {
return skeletonHolder;
public FbxNode getSkeletonRoot() {
return skeletonRoot;
}
public Bone getJmeBone() {
if (bone == null) {
bone = new Bone(name);
bone.setBindTransforms(jmeLocalBindPose.getTranslation(),
jmeLocalBindPose.getRotation(),
jmeLocalBindPose.getScale());
}
return bone;
public void setSkeletonRoot(FbxNode skeletonRoot) {
this.skeletonRoot = skeletonRoot;
}
}

@ -0,0 +1,112 @@
/*
* Copyright (c) 2009-2015 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.scene.plugins.fbx.anim;
import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.scene.plugins.fbx.node.FbxNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Similar to {@link Skeleton jME skeleton} except
* contains {@link FbxLimbNode limb nodes}.
*
* This is used to determine the bone indices (for assigning clusters to meshes)
* as well as the limb hierarchy when creating the jME3 Skeleton.
*
* @author Kirill Vainer
*/
public class FbxSkeleton {
FbxLimbNode[] rootLimbs;
FbxLimbNode[] allLimbs;
HashMap<FbxLimbNode, Integer> limbToIndexMap = new HashMap<FbxLimbNode, Integer>();
private FbxSkeleton() {
}
public static void populateSkeletonData(FbxNode skeletonRoot) {
// if (skeletonRoot instanceof FbxLimbNode) {
// throw new UnsupportedOperationException("Limb node cannot be a skeleton root");
// }
//
// FbxSkeleton skeleton = new FbxSkeleton();
// skeleton.scanLimbs(skeletonRoot);
// skeletonRoot.setFbxSkeleton(skeleton);
}
private void scanLimbs(FbxNode skeletonRoot, FbxLimbNode limb, List<FbxLimbNode> limbList) {
// limb.skeletonRoot = skeletonRoot;
// limbList.add(limb);
// for (FbxNode child : limb.getChildren()) {
// if (child instanceof FbxLimbNode) {
// FbxLimbNode childLimb = (FbxLimbNode) child;
// scanLimbs(skeletonRoot, childLimb, limbList);
// }
// }
}
private void scanLimbs(FbxNode skeletonRoot) {
List<FbxLimbNode> limbList = new ArrayList<FbxLimbNode>();
List<FbxLimbNode> rootList = new ArrayList<FbxLimbNode>();
for (FbxNode child : skeletonRoot.getChildren()) {
if (child instanceof FbxLimbNode) {
FbxLimbNode limb = (FbxLimbNode) child;
rootList.add(limb);
scanLimbs(skeletonRoot, limb, limbList);
}
}
allLimbs = limbList.toArray(new FbxLimbNode[0]);
rootLimbs = rootList.toArray(new FbxLimbNode[0]);
for (int i = 0; i < allLimbs.length; i++) {
limbToIndexMap.put(allLimbs[i], i);
}
}
public int getLimbIndex(FbxLimbNode limbNode) {
return limbToIndexMap.get(limbNode);
}
public FbxLimbNode getLimb(int index) {
return allLimbs[index];
}
public FbxLimbNode[] getRootLimbs() {
return rootLimbs;
}
}

@ -31,21 +31,91 @@
*/
package com.jme3.scene.plugins.fbx.anim;
import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.asset.AssetManager;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.fbx.node.FbxNode;
import com.jme3.scene.plugins.fbx.obj.FbxObject;
import java.util.ArrayList;
import java.util.List;
public class FbxSkinDeformer extends FbxObject<List<FbxCluster>> {
public class FbxSkinDeformer extends FbxObject<Skeleton> {
private FbxNode skeletonRoot;
private final List<FbxCluster> clusters = new ArrayList<FbxCluster>();
public FbxSkinDeformer(AssetManager assetManager, String sceneFolderName) {
super(assetManager, sceneFolderName);
}
private boolean isHierarchyCompatible(Bone thisBone, Bone otherBone) {
Transform thisTransform = thisBone.getBindInverseTransform();
Transform otherTransform = otherBone.getBindInverseTransform();
throw new UnsupportedOperationException();
}
/**
* Determine if both skin deformers can share the same
* Skeleton object and hence the same SkeletonControl / AnimControl.
*
* @param skinDeformer The skin deformer to test compatibility against.
* @return True if the skeletons are identical and can be shared, false
* otherwise.
*/
public boolean isCompatible(FbxSkinDeformer skinDeformer) {
Skeleton thisSkeleton = this.getJmeObject();
Skeleton otherSkeleton = skinDeformer.getJmeObject();
Bone[] thisRoots = thisSkeleton.getRoots();
Bone[] otherRoots = otherSkeleton.getRoots();
for (int i = 0; i < thisRoots.length; i++) {
}
throw new UnsupportedOperationException();
}
/**
* Get the root FbxNode containing the skeleton.
*
* The node should have one or more FbxLimbNodes which are
* the root limbs of the skeleton structure.
*
* This is null until prepareSkeletonData() is called.
*
* @return The root node containing the skeleton.
*/
public FbxNode getSkeletonRoot() {
return skeletonRoot;
}
/**
* Derives the skeleton from the skin deformer.
*
* The Skeleton hierarchy is derived via the {@link #getSkeletonRoot() skeleton root}
* whereas the bind poses for the bones is derived from the
* {@link #getClusters() clusters}.
*
* FbxLimbNode.prepareSkeletonData() must have been called first
* The bone's bind pose depends on each cluster's TransformLinkMatrix
* and TransformMatrix.
* The bone's bind pose is derived as follows:
* <code><pre>
* Invert(Invert(TransformLinkMatrix) * TransformMatrix * Geometry)
* </code></pre>
*
* @return The skeleton as described by this skin deformer.
*/
@Override
protected List<FbxCluster> toJmeObject() {
protected Skeleton toJmeObject() {
throw new UnsupportedOperationException();
}
/**
* Get the clusters attached to this skin deformer.
*
* @return The skin deformer's clusters.
*/
public List<FbxCluster> getClusters() {
return clusters;
}

@ -34,6 +34,7 @@ package com.jme3.scene.plugins.fbx.anim;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.SpatialTrack;
import com.jme3.animation.Track;
import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
@ -98,6 +99,7 @@ public final class FbxToJmeTrack {
}
private static void applyInverse(Vector3f translation, Quaternion rotation, Vector3f scale, Transform inverseBindPose) {
/*
Transform t = new Transform();
t.setTranslation(translation);
t.setRotation(rotation);
@ -111,6 +113,24 @@ public final class FbxToJmeTrack {
if (scale != null) {
t.getScale(scale);
}
*/
Matrix4f mat = new Matrix4f();
mat.setTranslation(translation);
mat.setRotationQuaternion(rotation);
if (scale != null) {
mat.setScale(scale);
}
Matrix4f mat2 = inverseBindPose.toTransformMatrix();
mat2.multLocal(mat);
mat = mat2;
mat.toTranslationVector(translation);
mat.toRotationQuat(rotation);
if (scale != null) {
mat.toScaleVector(scale);
}
}
private Track toJmeTrackInternal(int boneIndex, Transform inverseBindPose) {
@ -154,7 +174,7 @@ public final class FbxToJmeTrack {
if (i > 0) {
if (rotations[i - 1].dot(rotations[i]) < 0) {
System.out.println("rotation will go the long way, oh noes");
rotations[i - 1].negate();
rotations[i].negate();
}
}
} else {

@ -307,7 +307,11 @@ public class FbxMaterial extends FbxObject<Material> {
if (useAlphaBlend) {
// No idea if this is a transparent or translucent model, gotta guess..
mat.setTransparent(true);
mat.setFloat("AlphaDiscardThreshold", 0.01f);
// Commenting this out for now. It causes extra shaders to be
// used and is less efficient due to usage of "discard".
// mat.setFloat("AlphaDiscardThreshold", 0.01f);
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}

@ -111,36 +111,36 @@ public final class FbxMesh extends FbxNodeAttribute<IntMap<Mesh>> {
}
public void applyCluster(FbxCluster cluster) {
if (boneIndices == null) {
boneIndices = new ArrayList[positions.length];
boneWeights = new ArrayList[positions.length];
}
FbxLimbNode limb = cluster.getLimb();
Bone bone = limb.getJmeBone();
Skeleton skeleton = limb.getSkeletonHolder().getJmeSkeleton();
int boneIndex = skeleton.getBoneIndex(bone);
int[] positionIndices = cluster.getVertexIndices();
double[] weights = cluster.getWeights();
for (int i = 0; i < positionIndices.length; i++) {
int positionIndex = positionIndices[i];
float boneWeight = (float)weights[i];
ArrayList<Integer> boneIndicesForVertex = boneIndices[positionIndex];
ArrayList<Float> boneWeightsForVertex = boneWeights[positionIndex];
if (boneIndicesForVertex == null) {
boneIndicesForVertex = new ArrayList<Integer>();
boneWeightsForVertex = new ArrayList<Float>();
boneIndices[positionIndex] = boneIndicesForVertex;
boneWeights[positionIndex] = boneWeightsForVertex;
}
boneIndicesForVertex.add(boneIndex);
boneWeightsForVertex.add(boneWeight);
}
// if (boneIndices == null) {
// boneIndices = new ArrayList[positions.length];
// boneWeights = new ArrayList[positions.length];
// }
//
// FbxLimbNode limb = cluster.getLimb();
// Bone bone = limb.getJmeBone();
// Skeleton skeleton = limb.getSkeletonRoot().getJmeSkeleton();
// int boneIndex = skeleton.getBoneIndex(bone);
//
// int[] positionIndices = cluster.getVertexIndices();
// double[] weights = cluster.getWeights();
//
// for (int i = 0; i < positionIndices.length; i++) {
// int positionIndex = positionIndices[i];
// float boneWeight = (float)weights[i];
//
// ArrayList<Integer> boneIndicesForVertex = boneIndices[positionIndex];
// ArrayList<Float> boneWeightsForVertex = boneWeights[positionIndex];
//
// if (boneIndicesForVertex == null) {
// boneIndicesForVertex = new ArrayList<Integer>();
// boneWeightsForVertex = new ArrayList<Float>();
// boneIndices[positionIndex] = boneIndicesForVertex;
// boneWeights[positionIndex] = boneWeightsForVertex;
// }
//
// boneIndicesForVertex.add(boneIndex);
// boneWeightsForVertex.add(boneWeight);
// }
}
@Override
@ -210,7 +210,7 @@ public final class FbxMesh extends FbxNodeAttribute<IntMap<Mesh>> {
protected IntMap<Mesh> toJmeObject() {
// Load clusters from SkinDeformer
if (skinDeformer != null) {
for (FbxCluster cluster : skinDeformer.getJmeObject()) {
for (FbxCluster cluster : skinDeformer.getClusters()) {
applyCluster(cluster);
}
}

@ -53,6 +53,7 @@ import com.jme3.scene.debug.SkeletonDebugger;
import com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode;
import com.jme3.scene.plugins.fbx.anim.FbxCluster;
import com.jme3.scene.plugins.fbx.anim.FbxLimbNode;
import com.jme3.scene.plugins.fbx.anim.FbxSkeleton;
import com.jme3.scene.plugins.fbx.anim.FbxSkinDeformer;
import com.jme3.scene.plugins.fbx.file.FbxElement;
import com.jme3.scene.plugins.fbx.material.FbxImage;
@ -108,7 +109,7 @@ public class FbxNode extends FbxObject<Spatial> {
/**
* For FBX nodes that contain a skeleton (i.e. FBX limbs).
*/
protected Skeleton skeleton;
protected FbxSkeleton skeleton;
protected final Transform jmeWorldNodeTransform = new Transform();
protected final Transform jmeLocalNodeTransform = new Transform();
@ -380,11 +381,11 @@ public class FbxNode extends FbxObject<Spatial> {
FbxNode preferredParent = null;
if (deformer != null) {
for (FbxCluster cluster : deformer.getJmeObject()) {
for (FbxCluster cluster : deformer.getClusters()) {
FbxLimbNode limb = cluster.getLimb();
if (preferredParent == null) {
preferredParent = limb.getSkeletonHolder();
} else if (preferredParent != limb.getSkeletonHolder()) {
preferredParent = limb.getSkeletonRoot();
} else if (preferredParent != limb.getSkeletonRoot()) {
logger.log(Level.WARNING, "A mesh is being deformed by multiple skeletons. "
+ "Only one skeleton will work, ignoring other skeletons.");
}
@ -484,8 +485,8 @@ public class FbxNode extends FbxObject<Spatial> {
if (fbxNode.skeleton != null) {
throw new UnsupportedOperationException();
}
fbxNode.skeleton = FbxLimbNode.createSkeleton(fbxNode);
System.out.println("created skeleton: " + fbxNode.skeleton);
// fbxNode.skeleton = FbxLimbNode.createSkeleton(fbxNode);
// System.out.println("created skeleton: " + fbxNode.skeleton);
}
}
@ -523,19 +524,19 @@ public class FbxNode extends FbxObject<Spatial> {
}
}
if (fbxNode.skeleton != null) {
jmeSpatial.addControl(new AnimControl(fbxNode.skeleton));
jmeSpatial.addControl(new SkeletonControl(fbxNode.skeleton));
SkeletonDebugger sd = new SkeletonDebugger("debug", fbxNode.skeleton);
Material mat = new Material(fbxNode.assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.getAdditionalRenderState().setDepthTest(false);
mat.setColor("Color", ColorRGBA.Green);
sd.setMaterial(mat);
((Node)jmeSpatial).attachChild(sd);
}
// if (fbxNode.skeleton != null) {
// jmeSpatial.addControl(new AnimControl(fbxNode.skeleton));
// jmeSpatial.addControl(new SkeletonControl(fbxNode.skeleton));
//
// SkeletonDebugger sd = new SkeletonDebugger("debug", fbxNode.skeleton);
// Material mat = new Material(fbxNode.assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
// mat.getAdditionalRenderState().setWireframe(true);
// mat.getAdditionalRenderState().setDepthTest(false);
// mat.setColor("Color", ColorRGBA.Green);
// sd.setMaterial(mat);
//
// ((Node)jmeSpatial).attachChild(sd);
// }
return jmeSpatial;
}
@ -548,10 +549,18 @@ public class FbxNode extends FbxObject<Spatial> {
// return limb;
// }
public Skeleton getJmeSkeleton() {
// public Skeleton getJmeSkeleton() {
// return skeleton;
// }
public FbxSkeleton getFbxSkeleton() {
return skeleton;
}
public void setFbxSkeleton(FbxSkeleton skeleton) {
this.skeleton = skeleton;
}
public List<FbxNode> getChildren() {
return children;
}

Loading…
Cancel
Save