From 0e9f7ea22f3a530188746f91ef056a599f9d44e2 Mon Sep 17 00:00:00 2001 From: "Kae..pl" Date: Wed, 1 Feb 2012 18:45:45 +0000 Subject: [PATCH] Fixes to limit rotation constraint. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9125 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../scene/plugins/blender/BlenderContext.java | 27 +++- .../scene/plugins/blender/BlenderLoader.java | 1 + .../constraints/ConstraintRotLimit.java | 122 ++++++++++++------ .../plugins/blender/constraints/Feature.java | 10 -- 4 files changed, 105 insertions(+), 55 deletions(-) diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java index 8884c321e..1ed1c1cff 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java @@ -68,6 +68,8 @@ import com.jme3.scene.plugins.ogre.AnimData; public class BlenderContext { private static final Logger LOGGER = Logger.getLogger(BlenderContext.class.getName()); + /** The blender file version. */ + private int blenderVersion; /** The blender key. */ private BlenderKey blenderKey; /** The header of the file block. */ @@ -120,6 +122,23 @@ public class BlenderContext { /** A map og helpers that perform loading. */ private Map helpers = new HashMap(); + /** + * This method sets the blender file version. + * + * @param blenderVersion + * the blender file version + */ + public void setBlenderVersion(String blenderVersion) { + this.blenderVersion = Integer.parseInt(blenderVersion); + } + + /** + * @return the blender file version + */ + public int getBlenderVersion() { + return blenderVersion; + } + /** * This method sets the blender key. * @@ -496,7 +515,7 @@ public class BlenderContext { public AnimData getAnimData(Long ownerOMA) { return this.animData.get(ownerOMA); } - + /** * This method sets the skeleton for the specified OMA of its owner. * @@ -508,7 +527,7 @@ public class BlenderContext { public void setSkeleton(Long skeletonOMA, Skeleton skeleton) { this.skeletons.put(skeletonOMA, skeleton); } - + /** * This method returns the skeleton for the specified OMA of its owner. * @@ -544,7 +563,7 @@ public class BlenderContext { public MeshContext getMeshContext(Long meshOMA) { return this.meshContexts.get(meshOMA); } - + /** * This method sets the bone context for the given bone old memory address. * If the context is already set it will be replaced. @@ -569,7 +588,7 @@ public class BlenderContext { public BoneContext getBoneContext(Long boneOMA) { return boneContexts.get(boneOMA); } - + /** * This method sets the material context for the given material. If the * context is already set it will be replaced. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java index a89e668fa..3c81ba6d8 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java @@ -184,6 +184,7 @@ public class BlenderLoader extends AbstractBlenderLoader { blocks = new ArrayList(); FileBlockHeader fileBlock; blenderContext = new BlenderContext(); + blenderContext.setBlenderVersion(inputStream.getVersionNumber()); blenderContext.setAssetManager(assetInfo.getManager()); blenderContext.setInputStream(inputStream); blenderContext.setBlenderKey(blenderKey); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java index 358b1e735..d63f342de 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java @@ -1,8 +1,7 @@ package com.jme3.scene.plugins.blender.constraints; -import java.util.Arrays; - import com.jme3.animation.Animation; +import com.jme3.animation.Bone; import com.jme3.math.FastMath; import com.jme3.math.Quaternion; import com.jme3.math.Transform; @@ -15,16 +14,18 @@ import com.jme3.scene.plugins.ogre.AnimData; /** * This class represents 'Rot limit' constraint type in blender. + * * @author Marcin Roguski (Kaelthas) */ -/*package*/ class ConstraintRotLimit extends Constraint { - private static final int LIMIT_XROT = 0x01; - private static final int LIMIT_YROT = 0x02; - private static final int LIMIT_ZROT = 0x04; - - protected float[][] limits = new float[3][2]; - protected int flag; - +/* package */class ConstraintRotLimit extends Constraint { + private static final int LIMIT_XROT = 0x01; + private static final int LIMIT_YROT = 0x02; + private static final int LIMIT_ZROT = 0x04; + + protected float[][] limits = new float[3][2]; + protected int flag; + protected boolean updated; + /** * This constructor creates the constraint instance. * @@ -40,58 +41,63 @@ import com.jme3.scene.plugins.ogre.AnimData; * this exception is thrown when the blender file is somehow * corrupted */ - public ConstraintRotLimit(Structure constraintStructure, Long ownerOMA, - Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { + public ConstraintRotLimit(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { super(constraintStructure, ownerOMA, influenceIpo, blenderContext); - - if(blenderContext.getBlenderKey().isFixUpAxis()) { - limits[0][0] = ((Number) data.getFieldValue("xmin")).floatValue() * FastMath.DEG_TO_RAD; - limits[0][1] = ((Number) data.getFieldValue("xmax")).floatValue() * FastMath.DEG_TO_RAD; - limits[2][0] = -((Number) data.getFieldValue("ymin")).floatValue() * FastMath.DEG_TO_RAD; - limits[2][1] = -((Number) data.getFieldValue("ymax")).floatValue() * FastMath.DEG_TO_RAD; - limits[1][0] = ((Number) data.getFieldValue("zmin")).floatValue() * FastMath.DEG_TO_RAD; - limits[1][1] = ((Number) data.getFieldValue("zmax")).floatValue() * FastMath.DEG_TO_RAD; - } else { - limits[0][0] = ((Number) data.getFieldValue("xmin")).floatValue() * FastMath.DEG_TO_RAD; - limits[0][1] = ((Number) data.getFieldValue("xmax")).floatValue() * FastMath.DEG_TO_RAD; - limits[1][0] = ((Number) data.getFieldValue("ymin")).floatValue() * FastMath.DEG_TO_RAD; - limits[1][1] = ((Number) data.getFieldValue("ymax")).floatValue() * FastMath.DEG_TO_RAD; - limits[2][0] = ((Number) data.getFieldValue("zmin")).floatValue() * FastMath.DEG_TO_RAD; - limits[2][1] = ((Number) data.getFieldValue("zmax")).floatValue() * FastMath.DEG_TO_RAD; - } + flag = ((Number) data.getFieldValue("flag")).intValue(); - if(blenderContext.getBlenderKey().isFixUpAxis()) { - //swapping Y and X limits flag in the bitwise flag + if (blenderContext.getBlenderKey().isFixUpAxis() && owner.spatial != null) { + limits[0][0] = ((Number) data.getFieldValue("xmin")).floatValue(); + limits[0][1] = ((Number) data.getFieldValue("xmax")).floatValue(); + limits[2][0] = -((Number) data.getFieldValue("ymin")).floatValue(); + limits[2][1] = -((Number) data.getFieldValue("ymax")).floatValue(); + limits[1][0] = ((Number) data.getFieldValue("zmin")).floatValue(); + limits[1][1] = ((Number) data.getFieldValue("zmax")).floatValue(); + + // swapping Y and X limits flag in the bitwise flag int limitY = flag & LIMIT_YROT; int limitZ = flag & LIMIT_ZROT; - flag &= LIMIT_XROT;//clear the other flags to swap them + flag &= LIMIT_XROT;// clear the other flags to swap them flag |= limitY << 1; flag |= limitZ >> 1; + } else { + limits[0][0] = ((Number) data.getFieldValue("xmin")).floatValue(); + limits[0][1] = ((Number) data.getFieldValue("xmax")).floatValue(); + limits[1][0] = ((Number) data.getFieldValue("ymin")).floatValue(); + limits[1][1] = ((Number) data.getFieldValue("ymax")).floatValue(); + limits[2][0] = ((Number) data.getFieldValue("zmin")).floatValue(); + limits[2][1] = ((Number) data.getFieldValue("zmax")).floatValue(); + } + + // until blender 2.49 the rotations values were stored in degrees + if (blenderContext.getBlenderVersion() <= 249) { + for (int i = 0; i < limits.length; ++i) { + limits[i][0] *= FastMath.DEG_TO_RAD; + limits[i][1] *= FastMath.DEG_TO_RAD; + } } } @Override protected void bakeConstraint() { + this.update(); Object owner = this.owner.getObject(); AnimData animData = blenderContext.getAnimData(this.owner.getOma()); - if(animData != null) { - for(Animation animation : animData.anims) { + if (animData != null) { + for (Animation animation : animData.anims) { BlenderTrack track = this.getTrack(owner, animData.skeleton, animation); Quaternion[] rotations = track.getRotations(); float[] angles = new float[3]; int maxFrames = rotations.length; for (int frame = 0; frame < maxFrames; ++frame) { rotations[frame].toAngles(angles); - System.out.print(Arrays.toString(angles) + "\t\t"); this.rotLimit(angles, ipo.calculateValue(frame)); - System.out.println(Arrays.toString(angles)); rotations[frame].fromAngles(angles); } track.setKeyframes(track.getTimes(), track.getTranslations(), rotations, track.getScales()); } } - - if(owner instanceof Spatial) { + + if (owner instanceof Spatial) { Transform ownerTransform = this.owner.getTransform(); float[] angles = ownerTransform.getRotation().toAngles(null); this.rotLimit(angles, ipo.calculateValue(0)); @@ -99,7 +105,7 @@ import com.jme3.scene.plugins.ogre.AnimData; this.owner.applyTransform(ownerTransform); } } - + /** * This method computes new constrained angles. * @@ -118,7 +124,7 @@ import com.jme3.scene.plugins.ogre.AnimData; } angles[0] -= difference; } - if ((flag & LIMIT_ZROT) != 0) { + if ((flag & LIMIT_YROT) != 0) { float difference = 0.0f; if (angles[1] < limits[1][0]) { difference = (angles[1] - limits[1][0]) * influence; @@ -127,7 +133,7 @@ import com.jme3.scene.plugins.ogre.AnimData; } angles[1] -= difference; } - /*if ((flag & LIMIT_ZROT) != 0) { + if ((flag & LIMIT_ZROT) != 0) { float difference = 0.0f; if (angles[2] < limits[2][0]) { difference = (angles[2] - limits[2][0]) * influence; @@ -135,6 +141,40 @@ import com.jme3.scene.plugins.ogre.AnimData; difference = (angles[2] - limits[2][1]) * influence; } angles[2] -= difference; - }*/ + } + } + + /** + * This method is called before baking (performes its operations only once). + * It is important to update the state of the limits and owner/target before + * baking the constraint. + */ + private void update() { + if (!updated) { + updated = true; + if (owner != null) { + owner.update(); + } + if (target != null) { + target.update(); + } + if (this.owner.getObject() instanceof Bone) {// for bones we need to + // change the sign + // of the limits + for (int i = 0; i < limits.length; ++i) { + limits[i][0] *= -1; + limits[i][1] *= -1; + } + } + + // sorting the limits (lower is always first) + for (int i = 0; i < limits.length; ++i) { + if (limits[i][0] > limits[i][1]) { + float temp = limits[i][0]; + limits[i][0] = limits[i][1]; + limits[i][1] = temp; + } + } + } } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java index ec51dfa34..b08a20c0c 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java @@ -1,7 +1,6 @@ package com.jme3.scene.plugins.blender.constraints; import com.jme3.animation.Bone; -import com.jme3.math.FastMath; import com.jme3.math.Matrix4f; import com.jme3.math.Quaternion; import com.jme3.math.Transform; @@ -9,7 +8,6 @@ import com.jme3.math.Vector3f; import com.jme3.scene.Spatial; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.animations.BoneContext; import com.jme3.scene.plugins.blender.constraints.Constraint.Space; import com.jme3.scene.plugins.blender.file.DynamicArray; import com.jme3.scene.plugins.blender.file.Structure; @@ -158,20 +156,12 @@ import com.jme3.scene.plugins.blender.file.Structure; } } // Bone - BoneContext boneContext = blenderContext.getBoneContext(oma); switch (space) { case CONSTRAINT_SPACE_LOCAL: Transform localTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation()); localTransform.setScale(bone.getLocalScale()); return localTransform; case CONSTRAINT_SPACE_WORLD: - if(bone.getParent()!=null) { - System.out.println(bone.getParent().getLocalRotation()); - System.out.println(bone.getParent().getWorldBindRotation()); - System.out.println(bone.getParent().getModelSpaceRotation()); - System.out.println(bone.getParent().getWorldBindInverseRotation()); - } - Transform worldTransform = new Transform(bone.getWorldBindPosition(), bone.getWorldBindRotation()); worldTransform.setScale(bone.getWorldBindScale()); return worldTransform;