|
|
@ -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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|