Fixes to limit rotation constraint.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9125 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent c576a12f83
commit 0e9f7ea22f
  1. 27
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java
  2. 1
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
  3. 122
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java
  4. 10
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java

@ -68,6 +68,8 @@ import com.jme3.scene.plugins.ogre.AnimData;
public class BlenderContext { public class BlenderContext {
private static final Logger LOGGER = Logger.getLogger(BlenderContext.class.getName()); private static final Logger LOGGER = Logger.getLogger(BlenderContext.class.getName());
/** The blender file version. */
private int blenderVersion;
/** The blender key. */ /** The blender key. */
private BlenderKey blenderKey; private BlenderKey blenderKey;
/** The header of the file block. */ /** The header of the file block. */
@ -120,6 +122,23 @@ public class BlenderContext {
/** A map og helpers that perform loading. */ /** A map og helpers that perform loading. */
private Map<String, AbstractBlenderHelper> helpers = new HashMap<String, AbstractBlenderHelper>(); private Map<String, AbstractBlenderHelper> helpers = new HashMap<String, AbstractBlenderHelper>();
/**
* 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. * This method sets the blender key.
* *
@ -496,7 +515,7 @@ public class BlenderContext {
public AnimData getAnimData(Long ownerOMA) { public AnimData getAnimData(Long ownerOMA) {
return this.animData.get(ownerOMA); return this.animData.get(ownerOMA);
} }
/** /**
* This method sets the skeleton for the specified OMA of its owner. * 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) { public void setSkeleton(Long skeletonOMA, Skeleton skeleton) {
this.skeletons.put(skeletonOMA, skeleton); this.skeletons.put(skeletonOMA, skeleton);
} }
/** /**
* This method returns the skeleton for the specified OMA of its owner. * This method returns the skeleton for the specified OMA of its owner.
* *
@ -544,7 +563,7 @@ public class BlenderContext {
public MeshContext getMeshContext(Long meshOMA) { public MeshContext getMeshContext(Long meshOMA) {
return this.meshContexts.get(meshOMA); return this.meshContexts.get(meshOMA);
} }
/** /**
* This method sets the bone context for the given bone old memory address. * This method sets the bone context for the given bone old memory address.
* If the context is already set it will be replaced. * If the context is already set it will be replaced.
@ -569,7 +588,7 @@ public class BlenderContext {
public BoneContext getBoneContext(Long boneOMA) { public BoneContext getBoneContext(Long boneOMA) {
return boneContexts.get(boneOMA); return boneContexts.get(boneOMA);
} }
/** /**
* This method sets the material context for the given material. If the * This method sets the material context for the given material. If the
* context is already set it will be replaced. * context is already set it will be replaced.

@ -184,6 +184,7 @@ public class BlenderLoader extends AbstractBlenderLoader {
blocks = new ArrayList<FileBlockHeader>(); blocks = new ArrayList<FileBlockHeader>();
FileBlockHeader fileBlock; FileBlockHeader fileBlock;
blenderContext = new BlenderContext(); blenderContext = new BlenderContext();
blenderContext.setBlenderVersion(inputStream.getVersionNumber());
blenderContext.setAssetManager(assetInfo.getManager()); blenderContext.setAssetManager(assetInfo.getManager());
blenderContext.setInputStream(inputStream); blenderContext.setInputStream(inputStream);
blenderContext.setBlenderKey(blenderKey); blenderContext.setBlenderKey(blenderKey);

@ -1,8 +1,7 @@
package com.jme3.scene.plugins.blender.constraints; package com.jme3.scene.plugins.blender.constraints;
import java.util.Arrays;
import com.jme3.animation.Animation; import com.jme3.animation.Animation;
import com.jme3.animation.Bone;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Transform; 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. * This class represents 'Rot limit' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
/*package*/ class ConstraintRotLimit extends Constraint { /* package */class ConstraintRotLimit extends Constraint {
private static final int LIMIT_XROT = 0x01; private static final int LIMIT_XROT = 0x01;
private static final int LIMIT_YROT = 0x02; private static final int LIMIT_YROT = 0x02;
private static final int LIMIT_ZROT = 0x04; private static final int LIMIT_ZROT = 0x04;
protected float[][] limits = new float[3][2]; protected float[][] limits = new float[3][2];
protected int flag; protected int flag;
protected boolean updated;
/** /**
* This constructor creates the constraint instance. * 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 * this exception is thrown when the blender file is somehow
* corrupted * corrupted
*/ */
public ConstraintRotLimit(Structure constraintStructure, Long ownerOMA, public ConstraintRotLimit(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext); 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(); flag = ((Number) data.getFieldValue("flag")).intValue();
if(blenderContext.getBlenderKey().isFixUpAxis()) { if (blenderContext.getBlenderKey().isFixUpAxis() && owner.spatial != null) {
//swapping Y and X limits flag in the bitwise flag 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 limitY = flag & LIMIT_YROT;
int limitZ = flag & LIMIT_ZROT; 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 |= limitY << 1;
flag |= limitZ >> 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 @Override
protected void bakeConstraint() { protected void bakeConstraint() {
this.update();
Object owner = this.owner.getObject(); Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma()); AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) { if (animData != null) {
for(Animation animation : animData.anims) { for (Animation animation : animData.anims) {
BlenderTrack track = this.getTrack(owner, animData.skeleton, animation); BlenderTrack track = this.getTrack(owner, animData.skeleton, animation);
Quaternion[] rotations = track.getRotations(); Quaternion[] rotations = track.getRotations();
float[] angles = new float[3]; float[] angles = new float[3];
int maxFrames = rotations.length; int maxFrames = rotations.length;
for (int frame = 0; frame < maxFrames; ++frame) { for (int frame = 0; frame < maxFrames; ++frame) {
rotations[frame].toAngles(angles); rotations[frame].toAngles(angles);
System.out.print(Arrays.toString(angles) + "\t\t");
this.rotLimit(angles, ipo.calculateValue(frame)); this.rotLimit(angles, ipo.calculateValue(frame));
System.out.println(Arrays.toString(angles));
rotations[frame].fromAngles(angles); rotations[frame].fromAngles(angles);
} }
track.setKeyframes(track.getTimes(), track.getTranslations(), rotations, track.getScales()); track.setKeyframes(track.getTimes(), track.getTranslations(), rotations, track.getScales());
} }
} }
if(owner instanceof Spatial) { if (owner instanceof Spatial) {
Transform ownerTransform = this.owner.getTransform(); Transform ownerTransform = this.owner.getTransform();
float[] angles = ownerTransform.getRotation().toAngles(null); float[] angles = ownerTransform.getRotation().toAngles(null);
this.rotLimit(angles, ipo.calculateValue(0)); this.rotLimit(angles, ipo.calculateValue(0));
@ -99,7 +105,7 @@ import com.jme3.scene.plugins.ogre.AnimData;
this.owner.applyTransform(ownerTransform); this.owner.applyTransform(ownerTransform);
} }
} }
/** /**
* This method computes new constrained angles. * This method computes new constrained angles.
* *
@ -118,7 +124,7 @@ import com.jme3.scene.plugins.ogre.AnimData;
} }
angles[0] -= difference; angles[0] -= difference;
} }
if ((flag & LIMIT_ZROT) != 0) { if ((flag & LIMIT_YROT) != 0) {
float difference = 0.0f; float difference = 0.0f;
if (angles[1] < limits[1][0]) { if (angles[1] < limits[1][0]) {
difference = (angles[1] - limits[1][0]) * influence; difference = (angles[1] - limits[1][0]) * influence;
@ -127,7 +133,7 @@ import com.jme3.scene.plugins.ogre.AnimData;
} }
angles[1] -= difference; angles[1] -= difference;
} }
/*if ((flag & LIMIT_ZROT) != 0) { if ((flag & LIMIT_ZROT) != 0) {
float difference = 0.0f; float difference = 0.0f;
if (angles[2] < limits[2][0]) { if (angles[2] < limits[2][0]) {
difference = (angles[2] - limits[2][0]) * influence; 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; difference = (angles[2] - limits[2][1]) * influence;
} }
angles[2] -= difference; 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;
}
}
}
} }
} }

@ -1,7 +1,6 @@
package com.jme3.scene.plugins.blender.constraints; package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Bone; import com.jme3.animation.Bone;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Transform; import com.jme3.math.Transform;
@ -9,7 +8,6 @@ import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType; 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.constraints.Constraint.Space;
import com.jme3.scene.plugins.blender.file.DynamicArray; import com.jme3.scene.plugins.blender.file.DynamicArray;
import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.file.Structure;
@ -158,20 +156,12 @@ import com.jme3.scene.plugins.blender.file.Structure;
} }
} }
// Bone // Bone
BoneContext boneContext = blenderContext.getBoneContext(oma);
switch (space) { switch (space) {
case CONSTRAINT_SPACE_LOCAL: case CONSTRAINT_SPACE_LOCAL:
Transform localTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation()); Transform localTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
localTransform.setScale(bone.getLocalScale()); localTransform.setScale(bone.getLocalScale());
return localTransform; return localTransform;
case CONSTRAINT_SPACE_WORLD: 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()); Transform worldTransform = new Transform(bone.getWorldBindPosition(), bone.getWorldBindRotation());
worldTransform.setScale(bone.getWorldBindScale()); worldTransform.setScale(bone.getWorldBindScale());
return worldTransform; return worldTransform;

Loading…
Cancel
Save