diff --git a/jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java b/jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java index b1f3d02df..36c8c6e38 100644 --- a/jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java +++ b/jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java @@ -108,8 +108,8 @@ public class SkeletonControl extends AbstractControl implements Cloneable { /** * Material references used for hardware skinning */ - private Set materials = new HashSet(); - + private final HashSet materials = new HashSet(); + /** * 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; } diff --git a/jme3-core/src/main/resources/com/jme3/asset/General.cfg b/jme3-core/src/main/resources/com/jme3/asset/General.cfg index c56b62146..d16b9fc3c 100644 --- a/jme3-core/src/main/resources/com/jme3/asset/General.cfg +++ b/jme3-core/src/main/resources/com/jme3/asset/General.cfg @@ -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 diff --git a/jme3-plugins/build.gradle b/jme3-plugins/build.gradle index dabbe62a0..0ff99d2d3 100644 --- a/jme3-plugins/build.gradle +++ b/jme3-plugins/build.gradle @@ -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' diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/FbxLoader.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/FbxLoader.java index fd157cb48..593d4745e 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/FbxLoader.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/FbxLoader.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); diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxAnimUtil.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxAnimUtil.java index c376757de..20e4a3910 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxAnimUtil.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxAnimUtil.java @@ -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); + } } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxBindPose.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxBindPose.java index 78d37c74e..c0bb3eae0 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxBindPose.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxBindPose.java @@ -56,31 +56,25 @@ public class FbxBindPose extends FbxObject> { } 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)); } } } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxCluster.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxCluster.java index 3065ce88c..290a020b3 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxCluster.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxCluster.java @@ -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); } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxLimbNode.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxLimbNode.java index 4b41b4f47..bd28db457 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxLimbNode.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxLimbNode.java @@ -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 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 FbxNode getSkeletonRoot() { + return skeletonRoot; } - - public static Skeleton createSkeleton(FbxNode skeletonHolderNode) { - if (skeletonHolderNode instanceof FbxLimbNode) { - throw new UnsupportedOperationException("Limb nodes cannot be skeleton holders"); - } - - List bones = new ArrayList(); - - 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 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; } } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkeleton.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkeleton.java new file mode 100755 index 000000000..0113fd0eb --- /dev/null +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkeleton.java @@ -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 limbToIndexMap = new HashMap(); + + 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 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 limbList = new ArrayList(); + List rootList = new ArrayList(); + + 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; + } + +} diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkinDeformer.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkinDeformer.java index 7a831cf7f..0d7e06498 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkinDeformer.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxSkinDeformer.java @@ -31,24 +31,94 @@ */ 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> { +public class FbxSkinDeformer extends FbxObject { + private FbxNode skeletonRoot; private final List clusters = new ArrayList(); 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: + *
+     * Invert(Invert(TransformLinkMatrix) * TransformMatrix * Geometry)
+     * 
+ * + * @return The skeleton as described by this skin deformer. + */ @Override - protected List toJmeObject() { + protected Skeleton toJmeObject() { + throw new UnsupportedOperationException(); + } + + /** + * Get the clusters attached to this skin deformer. + * + * @return The skin deformer's clusters. + */ + public List getClusters() { return clusters; } - + @Override public void connectObject(FbxObject object) { if (object instanceof FbxCluster) { @@ -62,5 +132,5 @@ public class FbxSkinDeformer extends FbxObject> { public void connectObjectProperty(FbxObject object, String property) { unsupportedConnectObjectProperty(object, property); } - + } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxToJmeTrack.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxToJmeTrack.java index 7b7b5ee5b..07d514159 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxToJmeTrack.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/anim/FbxToJmeTrack.java @@ -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 { diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/material/FbxMaterial.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/material/FbxMaterial.java index 9be5bf70c..dd8f06bb9 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/material/FbxMaterial.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/material/FbxMaterial.java @@ -307,7 +307,11 @@ public class FbxMaterial extends FbxObject { 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); } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/mesh/FbxMesh.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/mesh/FbxMesh.java index 2278b1695..8967facef 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/mesh/FbxMesh.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/mesh/FbxMesh.java @@ -111,36 +111,36 @@ public final class FbxMesh extends FbxNodeAttribute> { } 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 boneIndicesForVertex = boneIndices[positionIndex]; - ArrayList boneWeightsForVertex = boneWeights[positionIndex]; - - if (boneIndicesForVertex == null) { - boneIndicesForVertex = new ArrayList(); - boneWeightsForVertex = new ArrayList(); - 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 boneIndicesForVertex = boneIndices[positionIndex]; +// ArrayList boneWeightsForVertex = boneWeights[positionIndex]; +// +// if (boneIndicesForVertex == null) { +// boneIndicesForVertex = new ArrayList(); +// boneWeightsForVertex = new ArrayList(); +// boneIndices[positionIndex] = boneIndicesForVertex; +// boneWeights[positionIndex] = boneWeightsForVertex; +// } +// +// boneIndicesForVertex.add(boneIndex); +// boneWeightsForVertex.add(boneWeight); +// } } @Override @@ -210,7 +210,7 @@ public final class FbxMesh extends FbxNodeAttribute> { protected IntMap toJmeObject() { // Load clusters from SkinDeformer if (skinDeformer != null) { - for (FbxCluster cluster : skinDeformer.getJmeObject()) { + for (FbxCluster cluster : skinDeformer.getClusters()) { applyCluster(cluster); } } diff --git a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/node/FbxNode.java b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/node/FbxNode.java index 05e031328..0aa0fc72e 100644 --- a/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/node/FbxNode.java +++ b/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/node/FbxNode.java @@ -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 { /** * 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 { 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 { 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 { } } - 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 { // 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 getChildren() { return children; }