Huge constraints refactoring (the computations might yet not be perfect, but models loading should get much less crashes).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9720 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 12 years ago
parent 58bbd2d076
commit 711b8ab9ca
  1. 32
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java
  2. 13
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
  3. 6
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java
  4. 7
      engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java
  5. 142
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/BlenderTrack.java
  6. 168
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/BoneConstraint.java
  7. 149
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java
  8. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintAction.java
  9. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintChildOf.java
  10. 43
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintClampTo.java
  11. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDampTrack.java
  12. 120
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java
  13. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFollowPath.java
  14. 437
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java
  15. 122
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLike.java
  16. 137
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLimit.java
  17. 43
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLockTrack.java
  18. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintMinMax.java
  19. 37
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintNull.java
  20. 43
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPivot.java
  21. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPython.java
  22. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRigidBodyJoint.java
  23. 114
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLike.java
  24. 180
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java
  25. 45
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSameVolume.java
  26. 98
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSizeLike.java
  27. 131
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSizeLimit.java
  28. 43
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSplineInverseKinematic.java
  29. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintStretchTo.java
  30. 45
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTrackTo.java
  31. 45
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransLike.java
  32. 42
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransform.java
  33. 302
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java
  34. 32
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/SkeletonConstraint.java
  35. 146
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/SpatialConstraint.java
  36. 244
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java
  37. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionAction.java
  38. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionChildOf.java
  39. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionClampTo.java
  40. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionDampTrack.java
  41. 59
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionDistLimit.java
  42. 83
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java
  43. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFollowPath.java
  44. 34
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionInverseKinematics.java
  45. 74
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLocLike.java
  46. 87
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLocLimit.java
  47. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLockTrack.java
  48. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionMinMax.java
  49. 19
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionNull.java
  50. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionPivot.java
  51. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionPython.java
  52. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRigidBodyJoint.java
  53. 67
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRotLike.java
  54. 85
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRotLimit.java
  55. 27
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSameVolume.java
  56. 45
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionShrinkWrap.java
  57. 51
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSizeLike.java
  58. 75
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSizeLimit.java
  59. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSplineInverseKinematic.java
  60. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionStretchTo.java
  61. 27
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionTrackTo.java
  62. 27
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionTransLike.java
  63. 26
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionTransform.java
  64. 13
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java
  65. 9
      engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java

@ -31,6 +31,7 @@
*/
package com.jme3.scene.plugins.blender;
import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.asset.AssetManager;
import com.jme3.asset.BlenderKey;
@ -52,6 +53,7 @@ import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -488,6 +490,17 @@ public class BlenderContext {
public List<Constraint> getConstraints(Long objectOMA) {
return objectOMA == null ? null : constraints.get(objectOMA);
}
/**
* @return all available constraints
*/
public List<Constraint> getAllConstraints() {
List<Constraint> result = new ArrayList<Constraint>();
for(Entry<Long, List<Constraint>> entry : constraints.entrySet()) {
result.addAll(entry.getValue());
}
return result;
}
/**
* This method sets the anim data for the specified OMA of its owner.
@ -584,7 +597,24 @@ public class BlenderContext {
public BoneContext getBoneContext(Long boneOMA) {
return boneContexts.get(boneOMA);
}
/**
* Returns bone by given name.
*
* @param name
* the name of the bone
* @return found bone or null if none bone of a given name exists
*/
public BoneContext getBoneByName(String name) {
for(Entry<Long, BoneContext> entry : boneContexts.entrySet()) {
Bone bone = entry.getValue().getBone();
if(bone != null && name.equals(bone.getName())) {
return entry.getValue();
}
}
return null;
}
/**
* This metod returns the default material.
*

@ -79,6 +79,7 @@ public class BlenderLoader extends AbstractBlenderLoader {
try {
this.setup(assetInfo);
List<FileBlockHeader> sceneBlocks = new ArrayList<FileBlockHeader>();
BlenderKey blenderKey = blenderContext.getBlenderKey();
LoadingResults loadingResults = blenderKey.prepareLoadingResults();
WorldData worldData = null;// a set of data used in different scene aspects
@ -104,7 +105,7 @@ public class BlenderLoader extends AbstractBlenderLoader {
// break;
case FileBlockHeader.BLOCK_SC00:// Scene
if ((blenderKey.getFeaturesToLoad() & FeaturesToLoad.SCENES) != 0) {
loadingResults.addScene(this.toScene(block.getStructure(blenderContext)));
sceneBlocks.add(block);
}
break;
case FileBlockHeader.BLOCK_WO00:// World
@ -121,6 +122,16 @@ public class BlenderLoader extends AbstractBlenderLoader {
break;
}
}
//bake constraints after everything is loaded
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
constraintHelper.bakeConstraints(blenderContext);
//load the scene at the very end so that the root nodes have no parent during loading or constraints applying
for(FileBlockHeader sceneBlock : sceneBlocks) {
loadingResults.addScene(this.toScene(sceneBlock.getStructure(blenderContext)));
}
blenderContext.dispose();
return loadingResults;
} catch (BlenderFileException e) {

@ -41,6 +41,7 @@ import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.scene.LightNode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
@ -75,6 +76,11 @@ public class BlenderModelLoader extends BlenderLoader {
}
}
}
//bake constraints after everything is loaded
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
constraintHelper.bakeConstraints(blenderContext);
blenderContext.dispose();
return modelRoot;
} catch (BlenderFileException e) {

@ -200,4 +200,11 @@ public class BoneContext {
public Bone getBone() {
return bone;
}
/**
* @return the old memory address of the bone
*/
public Long getBoneOma() {
return boneStructure.getOldMemoryAddress();
}
}

@ -1,142 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.SpatialTrack;
import com.jme3.animation.Track;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.util.TempVars;
import java.io.IOException;
/**
* This class holds either the bone track or spatial track. Is made to improve
* code readability.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */final class BlenderTrack implements Track {
/** The spatial track. */
private SpatialTrack spatialTrack;
/** The bone track. */
private BoneTrack boneTrack;
/**
* Constructs the object using spatial track (bone track is null).
*
* @param spatialTrack
* the spatial track
*/
public BlenderTrack(SpatialTrack spatialTrack) {
this.spatialTrack = spatialTrack;
}
/**
* Constructs the object using bone track (spatial track is null).
*
* @param spatialTrack
* the spatial track
*/
public BlenderTrack(BoneTrack boneTrack) {
this.boneTrack = boneTrack;
}
/**
* @return the stored track (either bone or spatial)
*/
public Track getTrack() {
return boneTrack != null ? boneTrack : spatialTrack;
}
/**
* @return the array of rotations of this track
*/
public Quaternion[] getRotations() {
if (boneTrack != null) {
return boneTrack.getRotations();
}
return spatialTrack.getRotations();
}
/**
* @return the array of scales for this track
*/
public Vector3f[] getScales() {
if (boneTrack != null) {
return boneTrack.getScales();
}
return spatialTrack.getScales();
}
/**
* @return the arrays of time for this track
*/
public float[] getTimes() {
if (boneTrack != null) {
return boneTrack.getTimes();
}
return spatialTrack.getTimes();
}
/**
* @return the array of translations of this track
*/
public Vector3f[] getTranslations() {
if (boneTrack != null) {
return boneTrack.getTranslations();
}
return spatialTrack.getTranslations();
}
/**
* Set the translations, rotations and scales for this bone track
*
* @param times
* a float array with the time of each frame
* @param translations
* the translation of the bone for each frame
* @param rotations
* the rotation of the bone for each frame
* @param scales
* the scale of the bone for each frame
*/
public void setKeyframes(float[] times, Vector3f[] translations,
Quaternion[] rotations, Vector3f[] scales) {
if (boneTrack != null) {
boneTrack.setKeyframes(times, translations, rotations, scales);
} else {
spatialTrack.setKeyframes(times, translations, rotations, scales);
}
}
public void write(JmeExporter ex) throws IOException {
}
public void read(JmeImporter im) throws IOException {
}
public void setTime(float time, float weight, AnimControl control,
AnimChannel channel, TempVars vars) {
if (boneTrack != null) {
boneTrack.setTime(time, weight, control, channel, vars);
} else {
spatialTrack.setTime(time, weight, control, channel, vars);
}
}
public float getLength() {
return spatialTrack == null ? boneTrack.getLength() : spatialTrack
.getLength();
}
@Override
public BlenderTrack clone() {
if (boneTrack != null) {
return new BlenderTrack(boneTrack.clone());
}
return new BlenderTrack(spatialTrack.clone());
}
}

@ -0,0 +1,168 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.Arrays;
import java.util.logging.Logger;
import com.jme3.animation.Animation;
import com.jme3.animation.Bone;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.Track;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
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.animations.Ipo;
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* Constraint applied on the bone.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class BoneConstraint extends Constraint {
private static final Logger LOGGER = Logger.getLogger(BoneConstraint.class.getName());
/** The OMA of the target armature. */
private Long targetArmatureOMA;
public BoneConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
targetArmatureOMA = targetOMA;
if(targetArmatureOMA != null && targetArmatureOMA <= 0L) {
targetArmatureOMA = null;
}
targetOMA = null;
if(targetArmatureOMA != null && targetArmatureOMA > 0L && (subtargetName == null || subtargetName.length() == 0)) {
invalid = true;
}
}
@Override
public void performBakingOperation() {
Bone owner = blenderContext.getBoneContext(ownerOMA).getBone();
Bone target = null;
if(targetArmatureOMA != null) {//first make sure the target is loaded
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
try {
objectHelper.toObject((Structure) blenderContext.getLoadedFeature(targetArmatureOMA, LoadedFeatureDataType.LOADED_STRUCTURE), blenderContext);
} catch (BlenderFileException e) {
LOGGER.warning("Problems occured during target object loading. The constraint " + name + " will not be applied.");
return ;
}
BoneContext boneContext = blenderContext.getBoneByName(subtargetName);
target = boneContext.getBone();
this.targetOMA = boneContext.getBoneOma();
}
this.prepareTracksForApplyingConstraints();
AnimData animData = blenderContext.getAnimData(ownerOMA);
if(animData != null) {
for(Animation animation : animData.anims) {
Transform ownerTransform = constraintHelper.getBoneTransform(ownerSpace, owner);
Transform targetTransform = target != null ? constraintHelper.getBoneTransform(targetSpace, target) : null;
BoneTrack boneTrack = constraintHelper.getTrack(owner, animData.skeleton, animation);
BoneTrack targetTrack = target != null ? constraintHelper.getTrack(target, animData.skeleton, animation) : null;
constraintDefinition.bake(ownerTransform, targetTransform, boneTrack, targetTrack, this.ipo);
}
}
}
@Override
protected void prepareTracksForApplyingConstraints() {
Long[] bonesOMAs = new Long[] { ownerOMA, targetOMA };
Space[] spaces = new Space[] { ownerSpace, targetSpace };
//creating animations for current objects if at least on of their parents have an animation
for(int i=0;i<bonesOMAs.length;++i) {
Long oma = bonesOMAs[i];
if(this.hasAnimation(oma)) {
Bone currentBone = blenderContext.getBoneContext(oma).getBone();
Bone parent = currentBone.getParent();
boolean foundAnimation = false;
AnimData animData = null;
while(parent != null && !foundAnimation) {
BoneContext boneContext = blenderContext.getBoneByName(parent.getName());
foundAnimation = this.hasAnimation(boneContext.getBoneOma());
animData = blenderContext.getAnimData(boneContext.getBoneOma());
parent = parent.getParent();
}
if(foundAnimation) {
this.applyAnimData(blenderContext.getBoneContext(oma), spaces[i], animData);
}
}
}
//creating animation for owner if it doesn't have one already and if the target has it
if(!this.hasAnimation(ownerOMA) && this.hasAnimation(targetOMA)) {
AnimData targetAnimData = blenderContext.getAnimData(targetOMA);
this.applyAnimData(blenderContext.getBoneContext(ownerOMA), ownerSpace, targetAnimData);
}
}
/**
* The method determines if the bone has animations.
*
* @param boneOMA
* OMA of the bone
* @return <b>true</b> if the bone has animations and <b>false</b> otherwise
*/
private boolean hasAnimation(Long boneOMA) {
AnimData animData = blenderContext.getAnimData(boneOMA);
if(animData != null) {
Bone bone = blenderContext.getBoneContext(boneOMA).getBone();
int boneIndex = animData.skeleton.getBoneIndex(bone);
for(Animation animation : animData.anims) {
for(Track track : animation.getTracks()) {
if(track instanceof BoneTrack && ((BoneTrack) track).getTargetBoneIndex() == boneIndex) {
return true;
}
}
}
}
return false;
}
/**
* The method applies bone's current position to all of the traces of the
* given animations.
*
* @param boneContext
* the bone context
* @param space
* the bone's evaluation space
* @param referenceAnimData
* the object containing the animations
*/
private void applyAnimData(BoneContext boneContext, Space space, AnimData referenceAnimData) {
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
Transform transform = constraintHelper.getBoneTransform(space, boneContext.getBone());
AnimData animData = blenderContext.getAnimData(boneContext.getBoneOma());
for(Animation animation : referenceAnimData.anims) {
BoneTrack parentTrack = (BoneTrack) animation.getTracks()[0];
float[] times = parentTrack.getTimes();
Vector3f[] translations = new Vector3f[times.length];
Quaternion[] rotations = new Quaternion[times.length];
Vector3f[] scales = new Vector3f[times.length];
Arrays.fill(translations, transform.getTranslation());
Arrays.fill(rotations, transform.getRotation());
Arrays.fill(scales, transform.getScale());
for(Animation anim : animData.anims) {
anim.addTrack(new BoneTrack(animData.skeleton.getBoneIndex(boneContext.getBone()), times, translations, rotations, scales));
}
}
blenderContext.setAnimData(boneContext.getBoneOma(), animData);
}
}

@ -1,18 +1,17 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.animation.Bone;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.Skeleton;
import com.jme3.animation.SpatialTrack;
import com.jme3.animation.Track;
import com.jme3.scene.Spatial;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
import com.jme3.scene.plugins.blender.constraints.definitions.ConstraintDefinition;
import com.jme3.scene.plugins.blender.constraints.definitions.ConstraintDefinitionFactory;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
/**
* The implementation of a constraint.
@ -20,18 +19,28 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
* @author Marcin Roguski (Kaelthas)
*/
public abstract class Constraint {
private static final Logger LOGGER = Logger.getLogger(Constraint.class.getName());
/** Indicates if the constraint is invalid. */
protected boolean invalid;
/** The name of this constraint. */
protected final String name;
/** The constraint's owner. */
protected final Feature owner;
/** The constraint's target. */
protected final Feature target;
/** The structure with constraint's data. */
protected final Structure data;
/** Indicates if the constraint is already baked or not. */
protected boolean baked;
protected Space ownerSpace;
protected final ConstraintDefinition constraintDefinition;
protected Long ownerOMA;
protected Long targetOMA;
protected Space targetSpace;
protected String subtargetName;
/** The ipo object defining influence. */
protected final Ipo ipo;
/** The blender context. */
protected final BlenderContext blenderContext;
protected final ConstraintHelper constraintHelper;
/**
* This constructor creates the constraint instance.
@ -48,100 +57,64 @@ public abstract class Constraint {
* this exception is thrown when the blender file is somehow
* corrupted
*/
public Constraint(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
public Constraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
this.blenderContext = blenderContext;
this.name = constraintStructure.getFieldValue("name").toString();
Pointer pData = (Pointer) constraintStructure.getFieldValue("data");
if (pData.isNotNull()) {
data = pData.fetchData(blenderContext.getInputStream()).get(0);
Structure data = pData.fetchData(blenderContext.getInputStream()).get(0);
constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(data, blenderContext);
Pointer pTar = (Pointer)data.getFieldValue("tar");
if(pTar!= null && pTar.isNotNull()) {
Structure targetStructure = pTar.fetchData(blenderContext.getInputStream()).get(0);
Long targetOMA = pTar.getOldMemoryAddress();
Space targetSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("tarspace")).byteValue());
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Spatial target = (Spatial) objectHelper.toObject(targetStructure, blenderContext);
this.target = new Feature(target, targetSpace, targetOMA, blenderContext);
} else {
this.target = null;
this.targetOMA = pTar.getOldMemoryAddress();
this.targetSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("tarspace")).byteValue());
subtargetName = data.getFieldValue("subtarget").toString();
}
} else {
throw new BlenderFileException("The constraint has no data specified!");
//Null constraint has no data, so create it here
constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(null, blenderContext);
}
Space ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue());
this.owner = new Feature(ownerSpace, ownerOMA, blenderContext);
this.ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue());
this.ipo = influenceIpo;
this.ownerOMA = ownerOMA;
this.constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
}
/**
* This method bakes the required sontraints into its owner.
* This method bakes the required sontraints into its owner. It checks if the constraint is invalid
* or if it isn't yet baked. It also performs baking of its target constraints so that the proper baking
* order is kept.
*/
public void bake() {
this.owner.update();
if(this.target != null) {
this.target.update();
if(invalid) {
LOGGER.warning("The constraint " + name + " is invalid and will not be applied.");
} else if(!baked) {
if(targetOMA != null) {
List<Constraint> targetConstraints = blenderContext.getConstraints(targetOMA);
if(targetConstraints != null && targetConstraints.size() > 0) {
LOGGER.log(Level.FINE, "Baking target constraints of constraint: {0}", name);
for(Constraint targetConstraint : targetConstraints) {
targetConstraint.bake();
}
}
}
LOGGER.log(Level.FINE, "Performing baking of constraint: {0}", name);
this.performBakingOperation();
baked = true;
}
this.bakeConstraint();
}
/**
* Bake the animation's constraints into its owner.
* This method should be overwridden and perform the baking opertion.
*/
protected abstract void bakeConstraint();
protected abstract void performBakingOperation();
/**
* This method returns the bone traces for the bone that is affected by the given constraint.
* @param skeleton
* the skeleton containing bones
* @param boneAnimation
* the bone animation that affects the skeleton
* @return the bone track for the bone that is being affected by the constraint
*/
protected BlenderTrack getTrack(Object owner, Skeleton skeleton, Animation animation) {
if(owner instanceof Bone) {
int boneIndex = skeleton.getBoneIndex((Bone) owner);
for (Track track : animation.getTracks()) {
if (((BoneTrack) track).getTargetBoneIndex() == boneIndex) {
return new BlenderTrack(((BoneTrack) track));
}
}
throw new IllegalStateException("Cannot find track for: " + owner);
} else {
return new BlenderTrack((SpatialTrack)animation.getTracks()[0]);
}
}
/**
* The space of target or owner transformation.
*
* @author Marcin Roguski (Kaelthas)
* This method prepares the tracks for both owner and parent. If either owner or parent have no track while its parent has -
* the tracks are created. The tracks will not modify the owner/target movement but will be there ready for applying constraints.
* For example if the owner is a spatial and has no animation but its parent is moving then the track is created for the owner
* that will have non modifying values for translation, rotation and scale and will have the same amount of frames as its parent has.
*/
public static enum Space {
CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID;
/**
* This method returns the enum instance when given the appropriate
* value from the blend file.
*
* @param c
* the blender's value of the space modifier
* @return the scape enum instance
*/
public static Space valueOf(byte c) {
switch (c) {
case 0:
return CONSTRAINT_SPACE_WORLD;
case 1:
return CONSTRAINT_SPACE_LOCAL;
case 2:
return CONSTRAINT_SPACE_POSE;
case 3:
return CONSTRAINT_SPACE_PARLOCAL;
default:
return CONSTRAINT_SPACE_INVALID;
}
}
}
protected abstract void prepareTracksForApplyingConstraints();
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Action' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintAction extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintAction.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintAction(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Action' constraint
LOGGER.log(Level.WARNING, "'Action' constraint NOT implemented!");
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'ChildOf' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintChildOf extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintChildOf.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintChildOf(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement ChildOf constraint
LOGGER.log(Level.WARNING, "ChildOf constraint NOT implemented!");
}
}

@ -1,43 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Clamp to' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintClampTo extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintClampTo.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintClampTo(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
//TODO: implement when curves are implemented
LOGGER.log(Level.INFO, "'Clamp to' not yet implemented! Curves not yet implemented!", name);
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The damp track constraint. Available for blender 2.50+.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDampTrack extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintDampTrack.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintDampTrack(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
// TODO Auto-generated constructor stub
}
@Override
protected void bakeConstraint() {
// TODO Auto-generated method stub
LOGGER.log(Level.WARNING, "'Damp Track' constraint NOT implemented!");
}
}

@ -1,120 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.math.Matrix4f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* This class represents 'Dist limit' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDistLimit extends Constraint {
private static final int LIMITDIST_INSIDE = 0;
private static final int LIMITDIST_OUTSIDE = 1;
private static final int LIMITDIST_ONSURFACE = 2;
protected int mode;
protected float dist;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintDistLimit(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
mode = ((Number) data.getFieldValue("mode")).intValue();
dist = ((Number) data.getFieldValue("dist")).floatValue();
}
@Override
protected void bakeConstraint() {
Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) {
if(owner instanceof Spatial) {
Vector3f targetLocation = ((Spatial) owner).getWorldTranslation();
for(Animation animation : animData.anims) {
BlenderTrack blenderTrack = this.getTrack(owner, animData.skeleton, animation);
int maxFrames = blenderTrack.getTimes().length;
Vector3f[] translations = blenderTrack.getTranslations();
for (int frame = 0; frame < maxFrames; ++frame) {
Vector3f v = translations[frame].subtract(targetLocation);
this.distLimit(v, targetLocation, ipo.calculateValue(frame));
translations[frame].addLocal(v);
}
blenderTrack.setKeyframes(blenderTrack.getTimes(), translations, blenderTrack.getRotations(), blenderTrack.getScales());
}
}
}
// apply static constraint only to spatials
if(owner instanceof Spatial) {
Matrix4f targetWorldMatrix = target.getWorldTransformMatrix();
Vector3f targetLocation = targetWorldMatrix.toTranslationVector();
Matrix4f m = this.owner.getParentWorldTransformMatrix();
m.invertLocal();
Matrix4f ownerWorldMatrix = this.owner.getWorldTransformMatrix();
Vector3f ownerLocation = ownerWorldMatrix.toTranslationVector();
this.distLimit(ownerLocation, targetLocation, ipo.calculateValue(0));
((Spatial) owner).setLocalTranslation(m.mult(ownerLocation));
}
}
/**
*
* @param currentLocation
* @param targetLocation
* @param influence
*/
private void distLimit(Vector3f currentLocation, Vector3f targetLocation, float influence) {
Vector3f v = currentLocation.subtract(targetLocation);
float currentDistance = v.length();
switch (mode) {
case LIMITDIST_INSIDE:
if (currentDistance >= dist) {
v.normalizeLocal();
v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
currentLocation.set(v.addLocal(targetLocation));
}
break;
case LIMITDIST_ONSURFACE:
if (currentDistance > dist) {
v.normalizeLocal();
v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
currentLocation.set(v.addLocal(targetLocation));
} else if(currentDistance < dist) {
v.normalizeLocal().multLocal(dist * influence);
currentLocation.set(targetLocation.add(v));
}
break;
case LIMITDIST_OUTSIDE:
if (currentDistance <= dist) {
v = targetLocation.subtract(currentLocation).normalizeLocal().multLocal(dist * influence);
currentLocation.set(targetLocation.add(v));
}
break;
default:
throw new IllegalStateException("Unknown distance limit constraint mode: " + mode);
}
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Follow path' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintFollowPath extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintFollowPath.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintFollowPath(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
//TODO: implement when curves are implemented
LOGGER.log(Level.INFO, "'Follow path' not implemented! Curves not yet implemented!");
}
}

@ -1,18 +1,31 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.jme3.animation.Animation;
import com.jme3.animation.Bone;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.Skeleton;
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;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.animations.IpoHelper;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.DynamicArray;
import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* This class should be used for constraint calculations.
@ -21,38 +34,6 @@ import java.util.logging.Logger;
public class ConstraintHelper extends AbstractBlenderHelper {
private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName());
private static final Map<String, Class<? extends Constraint>> constraintClasses = new HashMap<String, Class<? extends Constraint>>(22);
static {
constraintClasses.put("bActionConstraint", ConstraintAction.class);
constraintClasses.put("bChildOfConstraint", ConstraintChildOf.class);
constraintClasses.put("bClampToConstraint", ConstraintClampTo.class);
constraintClasses.put("bDistLimitConstraint", ConstraintDistLimit.class);
constraintClasses.put("bFollowPathConstraint", ConstraintFollowPath.class);
constraintClasses.put("bKinematicConstraint", ConstraintInverseKinematics.class);
constraintClasses.put("bLockTrackConstraint", ConstraintLockTrack.class);
constraintClasses.put("bLocateLikeConstraint", ConstraintLocLike.class);
constraintClasses.put("bLocLimitConstraint", ConstraintLocLimit.class);
constraintClasses.put("bMinMaxConstraint", ConstraintMinMax.class);
constraintClasses.put("bNullConstraint", ConstraintNull.class);
constraintClasses.put("bPythonConstraint", ConstraintPython.class);
constraintClasses.put("bRigidBodyJointConstraint", ConstraintRigidBodyJoint.class);
constraintClasses.put("bRotateLikeConstraint", ConstraintRotLike.class);
constraintClasses.put("bShrinkWrapConstraint", ConstraintShrinkWrap.class);
constraintClasses.put("bSizeLikeConstraint", ConstraintSizeLike.class);
constraintClasses.put("bSizeLimitConstraint", ConstraintSizeLimit.class);
constraintClasses.put("bStretchToConstraint", ConstraintStretchTo.class);
constraintClasses.put("bTransformConstraint", ConstraintTransform.class);
constraintClasses.put("bRotLimitConstraint", ConstraintRotLimit.class);
//Blender 2.50+
constraintClasses.put("bSplineIKConstraint", ConstraintSplineInverseKinematic.class);
constraintClasses.put("bDampTrackConstraint", ConstraintDampTrack.class);
constraintClasses.put("bPivotConstraint", ConstraintDampTrack.class);
//Blender 2.56+
constraintClasses.put("bTrackToConstraint", ConstraintTrackTo.class);
constraintClasses.put("bSameVolumeConstraint", ConstraintSameVolume.class);
constraintClasses.put("bTransLikeConstraint", ConstraintTransLike.class);
}
/**
* Helper constructor. It's main task is to generate the affection functions. These functions are common to all
* ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall
@ -125,7 +106,7 @@ public class ConstraintHelper extends AbstractBlenderHelper {
float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
ipo = ipoHelper.fromValue(enforce);
}
constraintsList.add(this.createConstraint(constraint, boneOMA, ipo, blenderContext));
constraintsList.add(new BoneConstraint(constraint, boneOMA, ipo, blenderContext));
}
blenderContext.addConstraints(boneOMA, constraintsList);
}
@ -133,74 +114,362 @@ public class ConstraintHelper extends AbstractBlenderHelper {
//loading constraints connected with the object itself
List<Structure> constraints = ((Structure)objectStructure.getFieldValue("constraints")).evaluateListBase(blenderContext);
List<Constraint> constraintsList = new ArrayList<Constraint>(constraints.size());
for(Structure constraint : constraints) {
String constraintName = constraint.getFieldValue("name").toString();
String objectName = objectStructure.getName();
if(constraints != null && constraints.size() > 0) {
Pointer pData = (Pointer) objectStructure.getFieldValue("data");
String dataType = pData.isNotNull() ? pData.fetchData(blenderContext.getInputStream()).get(0).getType() : null;
List<Constraint> constraintsList = new ArrayList<Constraint>(constraints.size());
Map<String, Ipo> objectConstraintsIpos = constraintsIpos.get(objectName);
Ipo ipo = objectConstraintsIpos!=null ? objectConstraintsIpos.get(constraintName) : null;
if (ipo == null) {
float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
ipo = ipoHelper.fromValue(enforce);
for(Structure constraint : constraints) {
String constraintName = constraint.getFieldValue("name").toString();
String objectName = objectStructure.getName();
Map<String, Ipo> objectConstraintsIpos = constraintsIpos.get(objectName);
Ipo ipo = objectConstraintsIpos!=null ? objectConstraintsIpos.get(constraintName) : null;
if (ipo == null) {
float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
ipo = ipoHelper.fromValue(enforce);
}
constraintsList.add(this.getConstraint(dataType, constraint, objectStructure.getOldMemoryAddress(), ipo, blenderContext));
}
constraintsList.add(this.createConstraint(constraint, objectStructure.getOldMemoryAddress(), ipo, blenderContext));
blenderContext.addConstraints(objectStructure.getOldMemoryAddress(), constraintsList);
}
blenderContext.addConstraints(objectStructure.getOldMemoryAddress(), constraintsList);
}
/**
* This method creates the constraint instance.
* This method creates a proper constraint object depending on the object's
* data type. Supported data types: <li>Mesh <li>Armature <li>Camera <li>
* Lamp Bone constraints are created in a different place.
*
* @param dataType
* the type of the object's data
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* the constraint structure
* @param ownerOMA
* the old memory address of the constraint's owner
* the owner OMA
* @param influenceIpo
* the ipo curve of the influence factor
* the influence interpolation curve
* @param blenderContext
* the blender context
* @return constraint object for the required type
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
* thrown when problems with blender file occured
*/
protected Constraint createConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo,
BlenderContext blenderContext) throws BlenderFileException {
String constraintClassName = this.getConstraintClassName(constraintStructure, blenderContext);
Class<? extends Constraint> constraintClass = constraintClasses.get(constraintClassName);
if(constraintClass != null) {
try {
return (Constraint) constraintClass.getDeclaredConstructors()[0].newInstance(constraintStructure, ownerOMA, influenceIpo,
blenderContext);
} catch (IllegalArgumentException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (SecurityException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (InstantiationException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (IllegalAccessException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (InvocationTargetException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
}
private Constraint getConstraint(String dataType, Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
if(dataType == null || "Mesh".equalsIgnoreCase(dataType) || "Camera".equalsIgnoreCase(dataType) || "Lamp".equalsIgnoreCase(dataType)) {
return new SpatialConstraint(constraintStructure, ownerOMA, influenceIpo, blenderContext);
} else if("Armature".equalsIgnoreCase(dataType)) {
return new SkeletonConstraint(constraintStructure, ownerOMA, influenceIpo, blenderContext);
} else {
throw new BlenderFileException("Unknown constraint type: " + constraintClassName);
throw new IllegalArgumentException("Unsupported data type for applying constraints: " + dataType);
}
}
protected String getConstraintClassName(Structure constraintStructure, BlenderContext blenderContext) throws BlenderFileException {
Pointer pData = (Pointer)constraintStructure.getFieldValue("data");
if(pData.isNotNull()) {
Structure data = pData.fetchData(blenderContext.getInputStream()).get(0);
return data.getType();
/**
* The method bakes all available and valid constraints.
*
* @param blenderContext
* the blender context
*/
public void bakeConstraints(BlenderContext blenderContext) {
for(Constraint constraint : blenderContext.getAllConstraints()) {
constraint.bake();
}
return constraintStructure.getType();
}
/**
* The method returns track for bone.
*
* @param bone
* the bone
* @param skeleton
* the bone's skeleton
* @param animation
* the bone's animation
* @return track for the given bone that was found among the given
* animations or null if none is found
*/
/*package*/ BoneTrack getTrack(Bone bone, Skeleton skeleton, Animation animation) {
int boneIndex = skeleton.getBoneIndex(bone);
for (Track track : animation.getTracks()) {
if (((BoneTrack) track).getTargetBoneIndex() == boneIndex) {
return (BoneTrack) track;
}
}
return null;
}
/**
* The method returns track for spatial.
*
* @param bone
* the spatial
* @param animation
* the spatial's animation
* @return track for the given spatial that was found among the given
* animations or null if none is found
*/
/*package*/ SpatialTrack getTrack(Spatial spatial, Animation animation) {
Track[] tracks = animation.getTracks();
if(tracks != null && tracks.length == 1) {
return (SpatialTrack)tracks[0];
}
return null;
}
/**
* This method returns the transform read directly from the blender
* structure. This can be used to read transforms from one of the object
* types: <li>Spatial <li>Camera <li>Light
*
* @param space
* the space where transform is evaluated
* @param spatialOMA
* the OMA of the object
* @param blenderContext
* the blender context
* @return the object's transform in a given space
*/
@SuppressWarnings("unchecked")
/*package*/ Transform getNodeObjectTransform(Space space, Long spatialOMA, BlenderContext blenderContext) {
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
Structure targetStructure = (Structure) blenderContext.getLoadedFeature(spatialOMA, LoadedFeatureDataType.LOADED_STRUCTURE);
DynamicArray<Number> locArray = ((DynamicArray<Number>) targetStructure.getFieldValue("loc"));
Vector3f loc = new Vector3f(locArray.get(0).floatValue(), locArray.get(1).floatValue(), locArray.get(2).floatValue());
DynamicArray<Number> rotArray = ((DynamicArray<Number>) targetStructure.getFieldValue("rot"));
Quaternion rot = new Quaternion(new float[] { rotArray.get(0).floatValue(), rotArray.get(1).floatValue(), rotArray.get(2).floatValue() });
DynamicArray<Number> sizeArray = ((DynamicArray<Number>) targetStructure.getFieldValue("size"));
Vector3f size = new Vector3f(sizeArray.get(0).floatValue(), sizeArray.get(1).floatValue(), sizeArray.get(2).floatValue());
if (blenderContext.getBlenderKey().isFixUpAxis()) {
float y = loc.y;
loc.y = loc.z;
loc.z = -y;
y = rot.getY();
float z = rot.getZ();
rot.set(rot.getX(), z, -y, rot.getW());
y = size.y;
size.y = size.z;
size.z = y;
}
Transform result = new Transform(loc, rot);
result.setScale(size);
return result;
case CONSTRAINT_SPACE_WORLD://TODO: get it from the object structure ???
Object feature = blenderContext.getLoadedFeature(spatialOMA, LoadedFeatureDataType.LOADED_FEATURE);
if(feature instanceof Spatial) {
return ((Spatial) feature).getWorldTransform();
} else if(feature instanceof Skeleton) {
LOGGER.warning("Trying to get transformation for skeleton. This is not supported. Returning null.");
return null;
} else {
throw new IllegalArgumentException("Given old memory address does not point to a valid object type (spatial, camera or light).");
}
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
/**
* The method returns the transform for the given bone computed in the given
* space.
*
* @param space
* the computation space
* @param bone
* the bone we get the transform from
* @return the transform of the given bone
*/
/*package*/ Transform getBoneTransform(Space space, Bone bone) {
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
Transform localTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
localTransform.setScale(bone.getLocalScale());
return localTransform;
case CONSTRAINT_SPACE_WORLD:
Transform worldTransform = new Transform(bone.getWorldBindPosition(), bone.getWorldBindRotation());
worldTransform.setScale(bone.getWorldBindScale());
return worldTransform;
case CONSTRAINT_SPACE_POSE:
Transform poseTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
poseTransform.setScale(bone.getLocalScale());
return poseTransform;
case CONSTRAINT_SPACE_PARLOCAL:
Transform parentLocalTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
parentLocalTransform.setScale(bone.getLocalScale());
return parentLocalTransform;
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
/**
* The method applies the transform for the given spatial, computed in the
* given space.
*
* @param spatial
* the spatial we apply the transform for
* @param space
* the computation space
* @param transform
* the transform being applied
*/
/*package*/ void applyTransform(Spatial spatial, Space space, Transform transform) {
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
Transform ownerLocalTransform = spatial.getLocalTransform();
ownerLocalTransform.getTranslation().addLocal(transform.getTranslation());
ownerLocalTransform.getRotation().multLocal(transform.getRotation());
ownerLocalTransform.getScale().multLocal(transform.getScale());
break;
case CONSTRAINT_SPACE_WORLD:
Matrix4f m = this.getParentWorldTransformMatrix(spatial);
m.invertLocal();
Matrix4f matrix = this.toMatrix(transform);
m.multLocal(matrix);
float scaleX = (float) Math.sqrt(m.m00 * m.m00 + m.m10 * m.m10 + m.m20 * m.m20);
float scaleY = (float) Math.sqrt(m.m01 * m.m01 + m.m11 * m.m11 + m.m21 * m.m21);
float scaleZ = (float) Math.sqrt(m.m02 * m.m02 + m.m12 * m.m12 + m.m22 * m.m22);
transform.setTranslation(m.toTranslationVector());
transform.setRotation(m.toRotationQuat());
transform.setScale(scaleX, scaleY, scaleZ);
spatial.setLocalTransform(transform);
break;
case CONSTRAINT_SPACE_PARLOCAL:
case CONSTRAINT_SPACE_POSE:
throw new IllegalStateException("Invalid space type (" + space.toString() + ") for owner object.");
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
/**
* The method applies the transform for the given bone, computed in the
* given space.
*
* @param bone
* the bone we apply the transform for
* @param space
* the computation space
* @param transform
* the transform being applied
*/
/*package*/ void applyTransform(Bone bone, Space space, Transform transform) {
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break;
case CONSTRAINT_SPACE_WORLD:
Matrix4f m = this.getParentWorldTransformMatrix(bone);
// m.invertLocal();
transform.setTranslation(m.mult(transform.getTranslation()));
transform.setRotation(m.mult(transform.getRotation(), null));
transform.setScale(transform.getScale());
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
// float x = FastMath.HALF_PI/2;
// float y = -FastMath.HALF_PI;
// float z = -FastMath.HALF_PI/2;
// bone.setBindTransforms(new Vector3f(0,0,0), new Quaternion().fromAngles(x, y, z), new Vector3f(1,1,1));
break;
case CONSTRAINT_SPACE_PARLOCAL:
Vector3f parentLocalTranslation = bone.getLocalPosition().add(transform.getTranslation());
Quaternion parentLocalRotation = bone.getLocalRotation().mult(transform.getRotation());
bone.setBindTransforms(parentLocalTranslation, parentLocalRotation, transform.getScale());
break;
case CONSTRAINT_SPACE_POSE:
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break;
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
/**
* @return world transform matrix of the feature's parent or identity matrix
* if the feature has no parent
*/
private Matrix4f getParentWorldTransformMatrix(Spatial spatial) {
Matrix4f result = new Matrix4f();
if (spatial.getParent() != null) {
Transform t = spatial.getParent().getWorldTransform();
result.setTransform(t.getTranslation(), t.getScale(), t.getRotation().toRotationMatrix());
}
return result;
}
/**
* @return world transform matrix of the feature's parent or identity matrix
* if the feature has no parent
*/
private Matrix4f getParentWorldTransformMatrix(Bone bone) {
Matrix4f result = new Matrix4f();
Bone parent = bone.getParent();
if (parent != null) {
result.setTransform(parent.getWorldBindPosition(), parent.getWorldBindScale(), parent.getWorldBindRotation().toRotationMatrix());
}
return result;
}
/**
* Converts given transform to the matrix.
*
* @param transform
* the transform to be converted
* @return 4x4 matri that represents the given transform
*/
private Matrix4f toMatrix(Transform transform) {
Matrix4f result = Matrix4f.IDENTITY;
if (transform != null) {
result = new Matrix4f();
result.setTranslation(transform.getTranslation());
result.setRotationQuaternion(transform.getRotation());
result.setScale(transform.getScale());
}
return result;
}
@Override
public boolean shouldBeLoaded(Structure structure, BlenderContext blenderContext) {
return true;
}
/**
* The space of target or owner transformation.
*
* @author Marcin Roguski (Kaelthas)
*/
public static enum Space {
CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID;
/**
* This method returns the enum instance when given the appropriate
* value from the blend file.
*
* @param c
* the blender's value of the space modifier
* @return the scape enum instance
*/
public static Space valueOf(byte c) {
switch (c) {
case 0:
return CONSTRAINT_SPACE_WORLD;
case 1:
return CONSTRAINT_SPACE_LOCAL;
case 2:
return CONSTRAINT_SPACE_POSE;
case 3:
return CONSTRAINT_SPACE_PARLOCAL;
default:
return CONSTRAINT_SPACE_INVALID;
}
}
}
}

@ -1,122 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* This class represents 'Loc like' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintLocLike extends Constraint {
private static final int LOCLIKE_X = 0x01;
private static final int LOCLIKE_Y = 0x02;
private static final int LOCLIKE_Z = 0x04;
//protected static final int LOCLIKE_TIP = 0x08;//this is deprecated in blender
private static final int LOCLIKE_X_INVERT = 0x10;
private static final int LOCLIKE_Y_INVERT = 0x20;
private static final int LOCLIKE_Z_INVERT = 0x40;
private static final int LOCLIKE_OFFSET = 0x80;
protected int flag;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintLocLike(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
flag = ((Number) data.getFieldValue("flag")).intValue();
if(blenderContext.getBlenderKey().isFixUpAxis()) {
//swapping Y and X limits flag in the bitwise flag
int y = flag & LOCLIKE_Y;
int invY = flag & LOCLIKE_Y_INVERT;
int z = flag & LOCLIKE_Z;
int invZ = flag & LOCLIKE_Z_INVERT;
flag &= LOCLIKE_X | LOCLIKE_X_INVERT | LOCLIKE_OFFSET;//clear the other flags to swap them
flag |= y << 2;
flag |= invY << 2;
flag |= z >> 2;
flag |= invZ >> 2;
}
}
@Override
protected void bakeConstraint() {
Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) {
Transform targetTransform = this.target.getTransform();
for(Animation animation : animData.anims) {
BlenderTrack blenderTrack = this.getTrack(owner, animData.skeleton, animation);
Vector3f[] translations = blenderTrack.getTranslations();
int maxFrames = translations.length;
for (int frame = 0; frame < maxFrames; ++frame) {
this.locLike(translations[frame], targetTransform.getTranslation(), ipo.calculateValue(frame));
}
blenderTrack.setKeyframes(blenderTrack.getTimes(), translations, blenderTrack.getRotations(), blenderTrack.getScales());
}
}
if(owner instanceof Spatial) {
Transform targetTransform = this.target.getTransform();
Transform ownerTransform = this.owner.getTransform();
Vector3f ownerLocation = ownerTransform.getTranslation();
this.locLike(ownerLocation, targetTransform.getTranslation(), ipo.calculateValue(0));
this.owner.applyTransform(ownerTransform);
}
}
private void locLike(Vector3f ownerLocation, Vector3f targetLocation, float influence) {
Vector3f startLocation = ownerLocation.clone();
Vector3f offset = Vector3f.ZERO;
if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original location to the copied location
offset = startLocation;
}
if ((flag & LOCLIKE_X) != 0) {
ownerLocation.x = targetLocation.x;
if ((flag & LOCLIKE_X_INVERT) != 0) {
ownerLocation.x = -ownerLocation.x;
}
}
if ((flag & LOCLIKE_Y) != 0) {
ownerLocation.y = targetLocation.y;
if ((flag & LOCLIKE_Y_INVERT) != 0) {
ownerLocation.y = -ownerLocation.y;
}
}
if ((flag & LOCLIKE_Z) != 0) {
ownerLocation.z = targetLocation.z;
if ((flag & LOCLIKE_Z_INVERT) != 0) {
ownerLocation.z = -ownerLocation.z;
}
}
ownerLocation.addLocal(offset);
if(influence < 1.0f) {
startLocation.subtractLocal(ownerLocation).normalizeLocal().mult(influence);
ownerLocation.addLocal(startLocation);
}
}
}

@ -1,137 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* This class represents 'Loc limit' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintLocLimit extends Constraint {
private static final int LIMIT_XMIN = 0x01;
private static final int LIMIT_XMAX = 0x02;
private static final int LIMIT_YMIN = 0x04;
private static final int LIMIT_YMAX = 0x08;
private static final int LIMIT_ZMIN = 0x10;
private static final int LIMIT_ZMAX = 0x20;
protected float[][] limits = new float[3][2];
protected int flag;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintLocLimit(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
flag = ((Number) data.getFieldValue("flag")).intValue();
if(blenderContext.getBlenderKey().isFixUpAxis()) {
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 ymin = flag & LIMIT_YMIN;
int ymax = flag & LIMIT_YMAX;
int zmin = flag & LIMIT_ZMIN;
int zmax = flag & LIMIT_ZMAX;
flag &= LIMIT_XMIN | LIMIT_XMAX;//clear the other flags to swap them
flag |= ymin << 2;
flag |= ymax << 2;
flag |= zmin >> 2;
flag |= zmax >> 2;
} 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();
}
}
@Override
protected void bakeConstraint() {
Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) {
for(Animation animation : animData.anims) {
BlenderTrack track = this.getTrack(owner, animData.skeleton, animation);
Vector3f[] translations = track.getTranslations();
int maxFrames = translations.length;
for (int frame = 0; frame < maxFrames; ++frame) {
this.locLimit(translations[frame], ipo.calculateValue(frame));
}
track.setKeyframes(track.getTimes(), translations, track.getRotations(), track.getScales());
}
}
if(owner instanceof Spatial) {
Transform ownerTransform = this.owner.getTransform();
Vector3f ownerLocation = ownerTransform.getTranslation();
this.locLimit(ownerLocation, ipo.calculateValue(0));
this.owner.applyTransform(ownerTransform);
}
}
/**
* This method modifies the given translation.
* @param translation the translation to be modified.
* @param influence the influence value
*/
private void locLimit(Vector3f translation, float influence) {
if ((flag & LIMIT_XMIN) != 0) {
if (translation.x < limits[0][0]) {
translation.x -= (translation.x - limits[0][0]) * influence;
}
}
if ((flag & LIMIT_XMAX) != 0) {
if (translation.x > limits[0][1]) {
translation.x -= (translation.x - limits[0][1]) * influence;
}
}
if ((flag & LIMIT_YMIN) != 0) {
if (translation.y < limits[1][0]) {
translation.y -= (translation.y - limits[1][0]) * influence;
}
}
if ((flag & LIMIT_YMAX) != 0) {
if (translation.y > limits[1][1]) {
translation.y -= (translation.y - limits[1][1]) * influence;
}
}
if ((flag & LIMIT_ZMIN) != 0) {
if (translation.z < limits[2][0]) {
translation.z -= (translation.z - limits[2][0]) * influence;
}
}
if ((flag & LIMIT_ZMAX) != 0) {
if (translation.z > limits[2][1]) {
translation.z -= (translation.z - limits[2][1]) * influence;
}
}
}
}

@ -1,43 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Action' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintLockTrack extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintLockTrack.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintLockTrack(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Lock track' constraint
LOGGER.log(Level.WARNING, "'Lock track' constraint NOT implemented!");
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Min max' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintMinMax extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintMinMax.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintMinMax(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Min max' constraint
LOGGER.log(Level.WARNING, "'Min max' constraint NOT implemented!");
}
}

@ -1,37 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Null' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintNull extends Constraint {
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintNull(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {}
}

@ -1,43 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The pivot constraint. Available for blender 2.50+.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintPivot extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintPivot.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintPivot(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo,
BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
// TODO Auto-generated constructor stub
}
@Override
protected void bakeConstraint() {
// TODO Auto-generated method stub
LOGGER.log(Level.WARNING, "'Pivot' constraint NOT implemented!");
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Python' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintPython extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintPython.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintPython(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Python' constraint
LOGGER.log(Level.WARNING, "'Python' constraint NOT implemented!");
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Rigid body joint' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintRigidBodyJoint extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintRigidBodyJoint.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintRigidBodyJoint(Structure constraintStructure,
Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Rigid body joint' constraint
LOGGER.log(Level.WARNING, "'Rigid body joint' constraint NOT implemented!");
}
}

@ -1,114 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* This class represents 'Rot like' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintRotLike extends Constraint {
private static final int ROTLIKE_X = 0x01;
private static final int ROTLIKE_Y = 0x02;
private static final int ROTLIKE_Z = 0x04;
private static final int ROTLIKE_X_INVERT = 0x10;
private static final int ROTLIKE_Y_INVERT = 0x20;
private static final int ROTLIKE_Z_INVERT = 0x40;
private static final int ROTLIKE_OFFSET = 0x80;
protected int flag;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintRotLike(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
flag = ((Number) data.getFieldValue("flag")).intValue();
}
@Override
protected void bakeConstraint() {
Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) {
Transform targetTransform = this.target.getTransform();
Quaternion targetRotation = targetTransform.getRotation();
for(Animation animation : animData.anims) {
BlenderTrack track = this.getTrack(owner, animData.skeleton, animation);
float[] targetAngles = targetRotation.toAngles(null);
Quaternion[] rotations = track.getRotations();
int maxFrames = rotations.length;
float[] angles = new float[3];
for (int frame = 0; frame < maxFrames; ++frame) {
rotations[frame].toAngles(angles);
this.rotLike(rotations[frame], angles, targetAngles, ipo.calculateValue(frame));
}
track.setKeyframes(track.getTimes(), track.getTranslations(), rotations, track.getScales());
}
}
if(owner instanceof Spatial) {
Transform targetTransform = this.target.getTransform();
Transform ownerTransform = this.owner.getTransform();
Quaternion ownerRotation = ownerTransform.getRotation();
this.rotLike(ownerRotation, ownerRotation.toAngles(null), targetTransform.getRotation().toAngles(null), ipo.calculateValue(0));
this.owner.applyTransform(ownerTransform);
}
}
private void rotLike(Quaternion ownerRotation, float[] ownerAngles, float[] targetAngles, float influence) {
Quaternion startRotation = ownerRotation.clone();
Quaternion offset = Quaternion.IDENTITY;
if ((flag & ROTLIKE_OFFSET) != 0) {//we add the original rotation to the copied rotation
offset = startRotation;
}
if ((flag & ROTLIKE_X) != 0) {
ownerAngles[0] = targetAngles[0];
if ((flag & ROTLIKE_X_INVERT) != 0) {
ownerAngles[0] = -ownerAngles[0];
}
}
if ((flag & ROTLIKE_Y) != 0) {
ownerAngles[1] = targetAngles[1];
if ((flag & ROTLIKE_Y_INVERT) != 0) {
ownerAngles[1] = -ownerAngles[1];
}
}
if ((flag & ROTLIKE_Z) != 0) {
ownerAngles[2] = targetAngles[2];
if ((flag & ROTLIKE_Z_INVERT) != 0) {
ownerAngles[2] = -ownerAngles[2];
}
}
ownerRotation.fromAngles(ownerAngles).multLocal(offset);
if(influence < 1.0f) {
// startLocation.subtractLocal(ownerLocation).normalizeLocal().mult(influence);
// ownerLocation.addLocal(startLocation);
//TODO
}
}
}

@ -1,180 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
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;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
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;
protected boolean updated;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintRotLimit(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
flag = ((Number) data.getFieldValue("flag")).intValue();
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 |= 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) {
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);
this.rotLimit(angles, ipo.calculateValue(frame));
rotations[frame].fromAngles(angles);
}
track.setKeyframes(track.getTimes(), track.getTranslations(), rotations, track.getScales());
}
}
if (owner instanceof Spatial) {
Transform ownerTransform = this.owner.getTransform();
float[] angles = ownerTransform.getRotation().toAngles(null);
this.rotLimit(angles, ipo.calculateValue(0));
ownerTransform.getRotation().fromAngles(angles);
this.owner.applyTransform(ownerTransform);
}
}
/**
* This method computes new constrained angles.
*
* @param angles
* angles to be altered
* @param influence
* the alteration influence
*/
private void rotLimit(float[] angles, float influence) {
if ((flag & LIMIT_XROT) != 0) {
float difference = 0.0f;
if (angles[0] < limits[0][0]) {
difference = (angles[0] - limits[0][0]) * influence;
} else if (angles[0] > limits[0][1]) {
difference = (angles[0] - limits[0][1]) * influence;
}
angles[0] -= difference;
}
if ((flag & LIMIT_YROT) != 0) {
float difference = 0.0f;
if (angles[1] < limits[1][0]) {
difference = (angles[1] - limits[1][0]) * influence;
} else if (angles[1] > limits[1][1]) {
difference = (angles[1] - limits[1][1]) * influence;
}
angles[1] -= difference;
}
if ((flag & LIMIT_ZROT) != 0) {
float difference = 0.0f;
if (angles[2] < limits[2][0]) {
difference = (angles[2] - limits[2][0]) * influence;
} else if (angles[2] > limits[2][1]) {
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;
}
}
}
}
}

@ -1,45 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Same volume' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintSameVolume extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintSameVolume.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintSameVolume(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Same volume' constraint
LOGGER.log(Level.WARNING, "'Same volume' constraint NOT implemented!");
}
}

@ -1,98 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* This class represents 'Size like' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintSizeLike extends Constraint {
private static final int SIZELIKE_X = 0x01;
private static final int SIZELIKE_Y = 0x02;
private static final int SIZELIKE_Z = 0x04;
private static final int LOCLIKE_OFFSET = 0x80;
protected int flag;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintSizeLike(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
flag = ((Number) data.getFieldValue("flag")).intValue();
if(blenderContext.getBlenderKey().isFixUpAxis()) {
//swapping Y and X limits flag in the bitwise flag
int y = flag & SIZELIKE_Y;
int z = flag & SIZELIKE_Z;
flag &= SIZELIKE_X | LOCLIKE_OFFSET;//clear the other flags to swap them
flag |= y << 1;
flag |= z >> 1;
}
}
@Override
protected void bakeConstraint() {
Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) {
Transform targetTransform = this.target.getTransform();
Vector3f targetScale = targetTransform.getScale();
for(Animation animation : animData.anims) {
BlenderTrack track = this.getTrack(owner, animData.skeleton, animation);
Vector3f[] scales = track.getScales();
int maxFrames = scales.length;
for (int frame = 0; frame < maxFrames; ++frame) {
this.sizeLike(scales[frame], targetScale, ipo.calculateValue(frame));
}
track.setKeyframes(track.getTimes(), track.getTranslations(), track.getRotations(), scales);
}
}
if(owner instanceof Spatial) {
Transform targetTransform = this.target.getTransform();
Transform ownerTransform = this.owner.getTransform();
this.sizeLike(ownerTransform.getScale(), targetTransform.getScale(), ipo.calculateValue(0));
this.owner.applyTransform(ownerTransform);
}
}
private void sizeLike(Vector3f ownerScale, Vector3f targetScale, float influence) {
Vector3f offset = Vector3f.ZERO;
if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original scale to the copied scale
offset = ownerScale.clone();
}
if ((flag & SIZELIKE_X) != 0) {
ownerScale.x = targetScale.x * influence + (1.0f - influence) * ownerScale.x;
}
if ((flag & SIZELIKE_Y) != 0) {
ownerScale.y = targetScale.y * influence + (1.0f - influence) * ownerScale.y;
}
if ((flag & SIZELIKE_Z) != 0) {
ownerScale.z = targetScale.z * influence + (1.0f - influence) * ownerScale.z;
}
ownerScale.addLocal(offset);
}
}

@ -1,131 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Animation;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* This class represents 'Size limit' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintSizeLimit extends Constraint {
private static final int LIMIT_XMIN = 0x01;
private static final int LIMIT_XMAX = 0x02;
private static final int LIMIT_YMIN = 0x04;
private static final int LIMIT_YMAX = 0x08;
private static final int LIMIT_ZMIN = 0x10;
private static final int LIMIT_ZMAX = 0x20;
protected float[][] limits = new float[3][2];
protected int flag;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintSizeLimit(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
flag = ((Number) data.getFieldValue("flag")).intValue();
if(blenderContext.getBlenderKey().isFixUpAxis()) {
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 ymin = flag & LIMIT_YMIN;
int ymax = flag & LIMIT_YMAX;
int zmin = flag & LIMIT_ZMIN;
int zmax = flag & LIMIT_ZMAX;
flag &= LIMIT_XMIN | LIMIT_XMAX;//clear the other flags to swap them
flag |= ymin << 2;
flag |= ymax << 2;
flag |= zmin >> 2;
flag |= zmax >> 2;
} 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();
}
}
@Override
protected void bakeConstraint() {
Object owner = this.owner.getObject();
AnimData animData = blenderContext.getAnimData(this.owner.getOma());
if(animData != null) {
for(Animation animation : animData.anims) {
BlenderTrack track = this.getTrack(owner, animData.skeleton, animation);
Vector3f[] scales = track.getScales();
int maxFrames = scales.length;
for (int frame = 0; frame < maxFrames; ++frame) {
this.sizeLimit(scales[frame], ipo.calculateValue(frame));
}
track.setKeyframes(track.getTimes(), track.getTranslations(), track.getRotations(), scales);
}
}
if(owner instanceof Spatial) {
Transform ownerTransform = this.owner.getTransform();
this.sizeLimit(ownerTransform.getScale(), ipo.calculateValue(0));
this.owner.applyTransform(ownerTransform);
}
}
private void sizeLimit(Vector3f scale, float influence) {
if ((flag & LIMIT_XMIN) != 0) {
if (scale.x < limits[0][0]) {
scale.x -= (scale.x - limits[0][0]) * influence;
}
}
if ((flag & LIMIT_XMAX) != 0) {
if (scale.x > limits[0][1]) {
scale.x -= (scale.x - limits[0][1]) * influence;
}
}
if ((flag & LIMIT_YMIN) != 0) {
if (scale.y < limits[1][0]) {
scale.y -= (scale.y - limits[1][0]) * influence;
}
}
if ((flag & LIMIT_YMAX) != 0) {
if (scale.y > limits[1][1]) {
scale.y -= (scale.y - limits[1][1]) * influence;
}
}
if ((flag & LIMIT_ZMIN) != 0) {
if (scale.z < limits[2][0]) {
scale.z -= (scale.z - limits[2][0]) * influence;
}
}
if ((flag & LIMIT_ZMAX) != 0) {
if (scale.z > limits[2][1]) {
scale.z -= (scale.z - limits[2][1]) * influence;
}
}
}
}

@ -1,43 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The spline inverse kinematic constraint. Available for blender 2.50+.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintSplineInverseKinematic extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintSplineInverseKinematic.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintSplineInverseKinematic(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo,
BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
// TODO Auto-generated constructor stub
}
@Override
protected void bakeConstraint() {
// TODO Auto-generated method stub
LOGGER.log(Level.WARNING, "'Splie IK' constraint NOT implemented!");
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Stretch to' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintStretchTo extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintStretchTo.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintStretchTo(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Stretch to' constraint
LOGGER.log(Level.WARNING, "'Stretch to' constraint NOT implemented!");
}
}

@ -1,45 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Track to' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */class ConstraintTrackTo extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintTrackTo.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintTrackTo(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Track to' constraint
LOGGER.log(Level.WARNING, "'Track to' constraint NOT implemented!");
}
}

@ -1,45 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Trans like' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintTransLike extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintTransLike.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintTransLike(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Trans like' constraint
LOGGER.log(Level.WARNING, "'Trans like' constraint NOT implemented!");
}
}

@ -1,42 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class represents 'Transform' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintTransform extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintAction.class.getName());
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintTransform(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
protected void bakeConstraint() {
// TODO: implement 'Transform' constraint
LOGGER.log(Level.WARNING, "'Transform' constraint NOT implemented!");
}
}

@ -1,302 +0,0 @@
package com.jme3.scene.plugins.blender.constraints;
import com.jme3.animation.Bone;
import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
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.constraints.Constraint.Space;
import com.jme3.scene.plugins.blender.file.DynamicArray;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents either owner or target of the constraint. It has the
* common methods that take the evalueation space of the feature.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */class Feature {
/** The evalueation space. */
protected Space space;
/** Old memory address of the feature. */
protected Long oma;
/** The spatial that is hold by the Feature. */
protected Spatial spatial;
/** The bone that is hold by the Feature. */
protected Bone bone;
/** The blender context. */
protected BlenderContext blenderContext;
/**
* Constructs the feature. This object should be loaded later
* when it is read from the blender file.
* The update method should be called before the feature is used.
*
* @param space
* the spatial's evaluation space
* @param oma
* the spatial's old memory address
* @param blenderContext
* the blender context
*/
public Feature(Space space, Long oma, BlenderContext blenderContext) {
this.space = space;
this.oma = oma;
this.blenderContext = blenderContext;
}
/**
* Constructs the feature based on spatial.
*
* @param spatial
* the spatial
* @param space
* the spatial's evaluation space
* @param oma
* the spatial's old memory address
* @param blenderContext
* the blender context
*/
public Feature(Spatial spatial, Space space, Long oma, BlenderContext blenderContext) {
this(space, oma, blenderContext);
this.blenderContext = blenderContext;
}
/**
* Constructs the feature based on bone.
*
* @param bone
* the bone
* @param space
* the bone evaluation space
* @param oma
* the bone old memory address
* @param blenderContext
* the blender context
*/
public Feature(Bone bone, Space space, Long oma, BlenderContext blenderContext) {
this(space, oma, blenderContext);
this.bone = bone;
}
/**
* This method should be called before the feature is used.
* It may happen that the object this feature refers to was not yet loaded from blend file
* when the instance of this class was created.
*/
public void update() {
Object owner = blenderContext.getLoadedFeature(oma, LoadedFeatureDataType.LOADED_FEATURE);
if(owner instanceof Spatial) {
this.spatial = (Spatial) owner;
} else if(owner instanceof Bone) {
this.bone = (Bone) owner;
} else {
throw new IllegalStateException("Unknown type of owner: " + owner.getClass());
}
}
/**
* @return the feature's old memory address
*/
public Long getOma() {
return oma;
}
/**
* @return the object held by the feature (either bone or spatial)
*/
public Object getObject() {
if (spatial != null) {
return spatial;
}
return bone;
}
/**
* @return the feature's transform depending on the evaluation space
*/
@SuppressWarnings("unchecked")
public Transform getTransform() {
if (spatial != null) {
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
Structure targetStructure = (Structure) blenderContext.getLoadedFeature(oma, LoadedFeatureDataType.LOADED_STRUCTURE);
DynamicArray<Number> locArray = ((DynamicArray<Number>) targetStructure.getFieldValue("loc"));
Vector3f loc = new Vector3f(locArray.get(0).floatValue(), locArray.get(1).floatValue(), locArray.get(2).floatValue());
DynamicArray<Number> rotArray = ((DynamicArray<Number>) targetStructure.getFieldValue("rot"));
Quaternion rot = new Quaternion(new float[] { rotArray.get(0).floatValue(), rotArray.get(1).floatValue(), rotArray.get(2).floatValue() });
DynamicArray<Number> sizeArray = ((DynamicArray<Number>) targetStructure.getFieldValue("size"));
Vector3f size = new Vector3f(sizeArray.get(0).floatValue(), sizeArray.get(1).floatValue(), sizeArray.get(2).floatValue());
if (blenderContext.getBlenderKey().isFixUpAxis()) {
float y = loc.y;
loc.y = loc.z;
loc.z = -y;
y = rot.getY();
float z = rot.getZ();
rot.set(rot.getX(), z, -y, rot.getW());
y = size.y;
size.y = size.z;
size.z = y;
}
Transform result = new Transform(loc, rot);
result.setScale(size);
return result;
case CONSTRAINT_SPACE_WORLD:
return spatial.getWorldTransform();
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
// Bone
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
Transform localTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
localTransform.setScale(bone.getLocalScale());
return localTransform;
case CONSTRAINT_SPACE_WORLD:
Transform worldTransform = new Transform(bone.getWorldBindPosition(), bone.getWorldBindRotation());
worldTransform.setScale(bone.getWorldBindScale());
return worldTransform;
case CONSTRAINT_SPACE_POSE:
Transform poseTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
poseTransform.setScale(bone.getLocalScale());
return poseTransform;
case CONSTRAINT_SPACE_PARLOCAL:
Transform parentLocalTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
parentLocalTransform.setScale(bone.getLocalScale());
return parentLocalTransform;
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
/**
* This method applies the given transform to the feature in the proper
* evaluation space.
*
* @param transform
* the transform to be applied
*/
public void applyTransform(Transform transform) {
if (spatial != null) {
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
Transform ownerLocalTransform = spatial.getLocalTransform();
ownerLocalTransform.getTranslation().addLocal(transform.getTranslation());
ownerLocalTransform.getRotation().multLocal(transform.getRotation());
ownerLocalTransform.getScale().multLocal(transform.getScale());
break;
case CONSTRAINT_SPACE_WORLD:
Matrix4f m = this.getParentWorldTransformMatrix();
m.invertLocal();
Matrix4f matrix = this.toMatrix(transform);
m.multLocal(matrix);
float scaleX = (float) Math.sqrt(m.m00 * m.m00 + m.m10 * m.m10 + m.m20 * m.m20);
float scaleY = (float) Math.sqrt(m.m01 * m.m01 + m.m11 * m.m11 + m.m21 * m.m21);
float scaleZ = (float) Math.sqrt(m.m02 * m.m02 + m.m12 * m.m12 + m.m22 * m.m22);
transform.setTranslation(m.toTranslationVector());
transform.setRotation(m.toRotationQuat());
transform.setScale(scaleX, scaleY, scaleZ);
spatial.setLocalTransform(transform);
break;
case CONSTRAINT_SPACE_PARLOCAL:
case CONSTRAINT_SPACE_POSE:
throw new IllegalStateException("Invalid space type (" + space.toString() + ") for owner object.");
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
} else {// Bone
switch (space) {
case CONSTRAINT_SPACE_LOCAL:
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break;
case CONSTRAINT_SPACE_WORLD:
Matrix4f m = this.getParentWorldTransformMatrix();
// m.invertLocal();
transform.setTranslation(m.mult(transform.getTranslation()));
transform.setRotation(m.mult(transform.getRotation(), null));
transform.setScale(transform.getScale());
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
// float x = FastMath.HALF_PI/2;
// float y = -FastMath.HALF_PI;
// float z = -FastMath.HALF_PI/2;
// bone.setBindTransforms(new Vector3f(0,0,0), new Quaternion().fromAngles(x, y, z), new Vector3f(1,1,1));
break;
case CONSTRAINT_SPACE_PARLOCAL:
Vector3f parentLocalTranslation = bone.getLocalPosition().add(transform.getTranslation());
Quaternion parentLocalRotation = bone.getLocalRotation().mult(transform.getRotation());
bone.setBindTransforms(parentLocalTranslation, parentLocalRotation, transform.getScale());
break;
case CONSTRAINT_SPACE_POSE:
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break;
default:
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
}
}
/**
* @return world transform matrix of the feature
*/
public Matrix4f getWorldTransformMatrix() {
if (spatial != null) {
Matrix4f result = new Matrix4f();
Transform t = spatial.getWorldTransform();
result.setTransform(t.getTranslation(), t.getScale(), t.getRotation().toRotationMatrix());
return result;
}
// Bone
Matrix4f result = new Matrix4f();
result.setTransform(bone.getWorldBindPosition(), bone.getWorldBindScale(), bone.getWorldBindRotation().toRotationMatrix());
return result;
}
/**
* @return world transform matrix of the feature's parent or identity matrix
* if the feature has no parent
*/
public Matrix4f getParentWorldTransformMatrix() {
Matrix4f result = new Matrix4f();
if (spatial != null) {
if (spatial.getParent() != null) {
Transform t = spatial.getParent().getWorldTransform();
result.setTransform(t.getTranslation(), t.getScale(), t.getRotation().toRotationMatrix());
}
} else {// Bone
Bone parent = bone.getParent();
if (parent != null) {
result.setTransform(parent.getWorldBindPosition(), parent.getWorldBindScale(), parent.getWorldBindRotation().toRotationMatrix());
}
}
return result;
}
/**
* Converts given transform to the matrix.
*
* @param transform
* the transform to be converted
* @return 4x4 matri that represents the given transform
*/
protected Matrix4f toMatrix(Transform transform) {
Matrix4f result = Matrix4f.IDENTITY;
if (transform != null) {
result = new Matrix4f();
result.setTranslation(transform.getTranslation());
result.setRotationQuaternion(transform.getRotation());
result.setScale(transform.getScale());
}
return result;
}
}

@ -0,0 +1,32 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.logging.Logger;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* Constraint applied on the skeleton. This constraint is here only to make the
* application not crash when loads constraints applied to armature. But
* skeleton movement is not supported by jme so the constraint will never be
* applied.
*
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class SkeletonConstraint extends Constraint {
private static final Logger LOGGER = Logger.getLogger(SkeletonConstraint.class.getName());
public SkeletonConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
public void performBakingOperation() {
LOGGER.warning("Applying constraints to skeleton is not supported.");
}
@Override
protected void prepareTracksForApplyingConstraints() { }
}

@ -0,0 +1,146 @@
package com.jme3.scene.plugins.blender.constraints;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import com.jme3.animation.AnimControl;
import com.jme3.animation.Animation;
import com.jme3.animation.SpatialTrack;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
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.Ipo;
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
/**
* Constraint applied on the spatial objects.
* This includes: nodes, cameras nodes and light nodes.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class SpatialConstraint extends Constraint {
/** The owner of the constraint. */
private Spatial owner;
/** The target of the constraint. */
private Object target;
public SpatialConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext)
throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
}
@Override
public void performBakingOperation() {
this.owner = (Spatial) blenderContext.getLoadedFeature(ownerOMA, LoadedFeatureDataType.LOADED_FEATURE);
this.target = targetOMA != null ? blenderContext.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE) : null;
this.prepareTracksForApplyingConstraints();
//apply static constraint
Transform ownerTransform = constraintHelper.getNodeObjectTransform(ownerSpace, ownerOMA, blenderContext);
Transform targetTransform = targetOMA != null ? constraintHelper.getNodeObjectTransform(targetSpace, targetOMA, blenderContext) : null;
constraintDefinition.bake(ownerTransform, targetTransform, null, null, this.ipo);
constraintHelper.applyTransform(owner, ownerSpace, ownerTransform);
//apply dynamic constraint
AnimData animData = blenderContext.getAnimData(ownerOMA);
if(animData != null) {
for(Animation animation : animData.anims) {
SpatialTrack ownerTrack = constraintHelper.getTrack(owner, animation);
AnimData targetAnimData = blenderContext.getAnimData(targetOMA);
SpatialTrack targetTrack = null;
if(targetAnimData != null) {
targetTrack = constraintHelper.getTrack((Spatial)target, targetAnimData.anims.get(0));
}
constraintDefinition.bake(ownerTransform, targetTransform, ownerTrack, targetTrack, this.ipo);
}
}
}
@Override
protected void prepareTracksForApplyingConstraints() {
Long[] spatialsOMAs = new Long[] { ownerOMA, targetOMA };
Space[] spaces = new Space[] { ownerSpace, targetSpace };
//creating animations for current objects if at least on of their parents have an animation
for (int i = 0; i < spatialsOMAs.length; ++i) {
Long oma = spatialsOMAs[i];
if(oma != null && oma > 0L) {
AnimData animData = blenderContext.getAnimData(oma);
if(animData == null) {
Spatial currentSpatial = (Spatial)blenderContext.getLoadedFeature(oma, LoadedFeatureDataType.LOADED_FEATURE);
Spatial parent = currentSpatial.getParent();
while(parent != null && animData == null) {
Structure parentStructure = (Structure)blenderContext.getLoadedFeature(parent.getName(), LoadedFeatureDataType.LOADED_STRUCTURE);
if(parentStructure == null) {
parent = null;
} else {
Long parentOma = parentStructure.getOldMemoryAddress();
animData = blenderContext.getAnimData(parentOma);
parent = parent.getParent();
}
}
if(animData != null) {//create anim data for the current object
this.applyAnimData(currentSpatial, oma, spaces[i], animData.anims.get(0));
}
}
}
}
//creating animation for owner if it doesn't have one already and if the target has it
AnimData animData = blenderContext.getAnimData(ownerOMA);
if(animData == null) {
AnimData targetAnimData = blenderContext.getAnimData(targetOMA);
if(targetAnimData != null) {
this.applyAnimData(owner, ownerOMA, ownerSpace, targetAnimData.anims.get(0));
}
}
}
/**
* This method applies spatial transform on each frame of the given
* animations.
*
* @param spatial
* the spatial
* @param spatialOma
* the OMA of the given spatial
* @param space
* the space we compute the transform in
* @param referenceAnimation
* the object containing the animations
*/
private void applyAnimData(Spatial spatial, Long spatialOma, Space space, Animation referenceAnimation) {
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
Transform transform = constraintHelper.getNodeObjectTransform(space, spatialOma, blenderContext);
SpatialTrack parentTrack = (SpatialTrack) referenceAnimation.getTracks()[0];
HashMap<String, Animation> anims = new HashMap<String, Animation>(1);
Animation animation = new Animation(spatial.getName(), referenceAnimation.getLength());
anims.put(spatial.getName(), animation);
float[] times = parentTrack.getTimes();
Vector3f[] translations = new Vector3f[times.length];
Quaternion[] rotations = new Quaternion[times.length];
Vector3f[] scales = new Vector3f[times.length];
Arrays.fill(translations, transform.getTranslation());
Arrays.fill(rotations, transform.getRotation());
Arrays.fill(scales, transform.getScale());
animation.addTrack(new SpatialTrack(times, translations, rotations, scales));
AnimControl control = new AnimControl(null);
control.setAnimations(anims);
spatial.addControl(control);
blenderContext.setAnimData(spatialOma, new AnimData(null, new ArrayList<Animation>(anims.values())));
}
}

@ -0,0 +1,244 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.io.IOException;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.SpatialTrack;
import com.jme3.animation.Track;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.util.TempVars;
public abstract class ConstraintDefinition {
protected int flag;
public ConstraintDefinition(Structure constraintData, BlenderContext blenderContext) {
if(constraintData != null) {//Null constraint has no data
Number flag = (Number)constraintData.getFieldValue("flag");
if(flag != null) {
this.flag = flag.intValue();
}
}
}
public void bake(Transform ownerTransform, Transform targetTransform, Track ownerTrack, Track targetTrack, Ipo influenceIpo) {
TrackWrapper ownerWrapperTrack = ownerTrack != null ? new TrackWrapper(ownerTrack) : null;
TrackWrapper targetWrapperTrack = targetTrack != null ? new TrackWrapper(targetTrack) : null;
//uruchamiamy bake dla transformat zale¿nie od tego, które argumenty s¹ nullami, a które - nie
this.bake(ownerTransform, targetTransform, influenceIpo.calculateValue(0));
if(ownerWrapperTrack != null) {
float[] ownerTimes = ownerWrapperTrack.getTimes();
Vector3f[] translations = ownerWrapperTrack.getTranslations();
Quaternion[] rotations = ownerWrapperTrack.getRotations();
Vector3f[] scales = ownerWrapperTrack.getScales();
float[] targetTimes = targetWrapperTrack == null ? null : targetWrapperTrack.getTimes();
Vector3f[] targetTranslations = targetWrapperTrack == null ? null : targetWrapperTrack.getTranslations();
Quaternion[] targetRotations = targetWrapperTrack == null ? null : targetWrapperTrack.getRotations();
Vector3f[] targetScales = targetWrapperTrack == null ? null : targetWrapperTrack.getScales();
Vector3f translation = new Vector3f(), scale = new Vector3f();
Quaternion rotation = new Quaternion();
Transform ownerTemp = new Transform(), targetTemp = new Transform();
for (int i = 0; i <ownerTimes.length; ++i) {
float t = ownerTimes[i];
ownerTemp.setTranslation(translations[i]);
ownerTemp.setRotation(rotations[i]);
ownerTemp.setScale(scales[i]);
if(targetWrapperTrack == null) {
this.bake(ownerTemp, targetTransform, influenceIpo.calculateValue(i));
} else {
//getting the values that are the interpolation of the target track for the time 't'
this.interpolate(targetTranslations, targetTimes, t, translation);
this.interpolate(targetRotations, targetTimes, t, rotation);
this.interpolate(targetScales, targetTimes, t, scale);
targetTemp.setTranslation(translation);
targetTemp.setRotation(rotation);
targetTemp.setScale(scale);
this.bake(ownerTemp, targetTemp, influenceIpo.calculateValue(i));
}
//need to clone here because each of the arrays will reference the same instance if they hold the same value in the compact array
translations[i] = ownerTemp.getTranslation().clone();
rotations[i] = ownerTemp.getRotation().clone();
scales[i] = ownerTemp.getScale().clone();
}
ownerWrapperTrack.setKeyframes(ownerTimes, translations, rotations, scales);
}
}
protected abstract void bake(Transform ownerTransform, Transform targetTransform, float influence);
private void interpolate(Vector3f[] targetVectors, float[] targetTimes, float currentTime, Vector3f result) {
int index = 0;
for (int i = 1; i < targetTimes.length; ++i) {
if(targetTimes[i] < currentTime) {
++index;
} else {
break;
}
}
if(index >= targetTimes.length - 1) {
result.set(targetVectors[targetTimes.length - 1]);
} else {
float delta = targetTimes[index + 1] - targetTimes[index];
if(delta == 0.0f) {
result.set(targetVectors[index + 1]);
} else {
float scale = (currentTime - targetTimes[index])/(targetTimes[index + 1] - targetTimes[index]);
FastMath.interpolateLinear(scale, targetVectors[index], targetVectors[index + 1], result);
}
}
}
private void interpolate(Quaternion[] targetQuaternions, float[] targetTimes, float currentTime, Quaternion result) {
int index = 0;
for (int i = 1; i < targetTimes.length; ++i) {
if(targetTimes[i] < currentTime) {
++index;
} else {
break;
}
}
if(index >= targetTimes.length - 1) {
result.set(targetQuaternions[targetTimes.length - 1]);
} else {
float delta = targetTimes[index + 1] - targetTimes[index];
if(delta == 0.0f) {
result.set(targetQuaternions[index + 1]);
} else {
float scale = (currentTime - targetTimes[index])/(targetTimes[index + 1] - targetTimes[index]);
result.slerp(targetQuaternions[index], targetQuaternions[index + 1], scale);
}
}
}
/**
* This class holds either the bone track or spatial track. Is made to improve
* code readability.
*
* @author Marcin Roguski (Kaelthas)
*/
private static class TrackWrapper implements Track {
/** The spatial track. */
private SpatialTrack spatialTrack;
/** The bone track. */
private BoneTrack boneTrack;
/**
* Constructs the object using the given track. The track must be of one of the types:
* <li> BoneTrack
* <li> SpatialTrack
*
* @param track
* the animation track
*/
public TrackWrapper(Track track) {
if(track instanceof SpatialTrack) {
this.spatialTrack = (SpatialTrack)track;
} else if(track instanceof BoneTrack) {
this.boneTrack = (BoneTrack)track;
} else {
throw new IllegalStateException("Unknown track type!");
}
}
/**
* @return the array of rotations of this track
*/
public Quaternion[] getRotations() {
if (boneTrack != null) {
return boneTrack.getRotations();
}
return spatialTrack.getRotations();
}
/**
* @return the array of scales for this track
*/
public Vector3f[] getScales() {
if (boneTrack != null) {
return boneTrack.getScales();
}
return spatialTrack.getScales();
}
/**
* @return the arrays of time for this track
*/
public float[] getTimes() {
if (boneTrack != null) {
return boneTrack.getTimes();
}
return spatialTrack.getTimes();
}
/**
* @return the array of translations of this track
*/
public Vector3f[] getTranslations() {
if (boneTrack != null) {
return boneTrack.getTranslations();
}
return spatialTrack.getTranslations();
}
/**
* Set the translations, rotations and scales for this bone track
*
* @param times
* a float array with the time of each frame
* @param translations
* the translation of the bone for each frame
* @param rotations
* the rotation of the bone for each frame
* @param scales
* the scale of the bone for each frame
*/
public void setKeyframes(float[] times, Vector3f[] translations,
Quaternion[] rotations, Vector3f[] scales) {
if (boneTrack != null) {
boneTrack.setKeyframes(times, translations, rotations, scales);
} else {
spatialTrack.setKeyframes(times, translations, rotations, scales);
}
}
public void write(JmeExporter ex) throws IOException { }
public void read(JmeImporter im) throws IOException { }
public void setTime(float time, float weight, AnimControl control,
AnimChannel channel, TempVars vars) {
if (boneTrack != null) {
boneTrack.setTime(time, weight, control, channel, vars);
} else {
spatialTrack.setTime(time, weight, control, channel, vars);
}
}
public float getLength() {
return spatialTrack == null ? boneTrack.getLength() : spatialTrack
.getLength();
}
@Override
public TrackWrapper clone() {
if (boneTrack != null) {
return new TrackWrapper(boneTrack.clone());
}
return new TrackWrapper(spatialTrack.clone());
}
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Action' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionAction extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionAction.class.getName());
public ConstraintDefinitionAction(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Action' constraint
LOGGER.log(Level.WARNING, "'Action' constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'ChildOf' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionChildOf extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionChildOf.class.getName());
public ConstraintDefinitionChildOf(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement ChildOf constraint
LOGGER.log(Level.WARNING, "ChildOf constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Clamp to' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionClampTo extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionClampTo.class.getName());
public ConstraintDefinitionClampTo(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
//TODO: implement when curves are implemented
LOGGER.log(Level.INFO, "'Clamp to' not yet implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* The damp track constraint. Available for blender 2.50+.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionDampTrack extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionDampTrack.class.getName());
public ConstraintDefinitionDampTrack(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO Auto-generated method stub
LOGGER.log(Level.WARNING, "'Damp Track' constraint NOT implemented!");
}
}

@ -0,0 +1,59 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Dist limit' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionDistLimit extends ConstraintDefinition {
private static final int LIMITDIST_INSIDE = 0;
private static final int LIMITDIST_OUTSIDE = 1;
private static final int LIMITDIST_ONSURFACE = 2;
protected int mode;
protected float dist;
public ConstraintDefinitionDistLimit(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
mode = ((Number) constraintData.getFieldValue("mode")).intValue();
dist = ((Number) constraintData.getFieldValue("dist")).floatValue();
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
Vector3f v = ownerTransform.getTranslation().subtract(targetTransform.getTranslation());
float currentDistance = v.length();
switch (mode) {
case LIMITDIST_INSIDE:
if (currentDistance >= dist) {
v.normalizeLocal();
v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
ownerTransform.getTranslation().set(v.addLocal(targetTransform.getTranslation()));
}
break;
case LIMITDIST_ONSURFACE:
if (currentDistance > dist) {
v.normalizeLocal();
v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
ownerTransform.getTranslation().set(v.addLocal(targetTransform.getTranslation()));
} else if(currentDistance < dist) {
v.normalizeLocal().multLocal(dist * influence);
ownerTransform.getTranslation().set(targetTransform.getTranslation().add(v));
}
break;
case LIMITDIST_OUTSIDE:
if (currentDistance <= dist) {
v = targetTransform.getTranslation().subtract(ownerTransform.getTranslation()).normalizeLocal().multLocal(dist * influence);
ownerTransform.getTranslation().set(targetTransform.getTranslation().add(v));
}
break;
default:
throw new IllegalStateException("Unknown distance limit constraint mode: " + mode);
}
}
}

@ -0,0 +1,83 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
public class ConstraintDefinitionFactory {
private static final Map<String, Class<? extends ConstraintDefinition>> CONSTRAINT_CLASSES = new HashMap<String, Class<? extends ConstraintDefinition>>();
static {
CONSTRAINT_CLASSES.put("bActionConstraint", ConstraintDefinitionAction.class);
CONSTRAINT_CLASSES.put("bChildOfConstraint", ConstraintDefinitionChildOf.class);
CONSTRAINT_CLASSES.put("bClampToConstraint", ConstraintDefinitionClampTo.class);
CONSTRAINT_CLASSES.put("bDistLimitConstraint", ConstraintDefinitionDistLimit.class);
CONSTRAINT_CLASSES.put("bFollowPathConstraint", ConstraintDefinitionFollowPath.class);
CONSTRAINT_CLASSES.put("bKinematicConstraint", ConstraintDefinitionInverseKinematics.class);
CONSTRAINT_CLASSES.put("bLockTrackConstraint", ConstraintDefinitionLockTrack.class);
CONSTRAINT_CLASSES.put("bLocateLikeConstraint", ConstraintDefinitionLocLike.class);
CONSTRAINT_CLASSES.put("bLocLimitConstraint", ConstraintDefinitionLocLimit.class);
CONSTRAINT_CLASSES.put("bMinMaxConstraint", ConstraintDefinitionMinMax.class);
CONSTRAINT_CLASSES.put("bNullConstraint", ConstraintDefinitionNull.class);
CONSTRAINT_CLASSES.put("bPythonConstraint", ConstraintDefinitionPython.class);
CONSTRAINT_CLASSES.put("bRigidBodyJointConstraint", ConstraintDefinitionRigidBodyJoint.class);
CONSTRAINT_CLASSES.put("bRotateLikeConstraint", ConstraintDefinitionRotLike.class);
CONSTRAINT_CLASSES.put("bShrinkWrapConstraint", ConstraintDefinitionShrinkWrap.class);
CONSTRAINT_CLASSES.put("bSizeLikeConstraint", ConstraintDefinitionSizeLike.class);
CONSTRAINT_CLASSES.put("bSizeLimitConstraint", ConstraintDefinitionSizeLimit.class);
CONSTRAINT_CLASSES.put("bStretchToConstraint", ConstraintDefinitionStretchTo.class);
CONSTRAINT_CLASSES.put("bTransformConstraint", ConstraintDefinitionTransform.class);
CONSTRAINT_CLASSES.put("bRotLimitConstraint", ConstraintDefinitionRotLimit.class);
//Blender 2.50+
CONSTRAINT_CLASSES.put("bSplineIKConstraint", ConstraintDefinitionSplineInverseKinematic.class);
CONSTRAINT_CLASSES.put("bDampTrackConstraint", ConstraintDefinitionDampTrack.class);
CONSTRAINT_CLASSES.put("bPivotConstraint", ConstraintDefinitionDampTrack.class);
//Blender 2.56+
CONSTRAINT_CLASSES.put("bTrackToConstraint", ConstraintDefinitionTrackTo.class);
CONSTRAINT_CLASSES.put("bSameVolumeConstraint", ConstraintDefinitionSameVolume.class);
CONSTRAINT_CLASSES.put("bTransLikeConstraint", ConstraintDefinitionTransLike.class);
}
/**
* This method creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49). If the value is null the NullConstraint is created.
* @param ownerOMA
* the old memory address of the constraint's owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public static ConstraintDefinition createConstraintDefinition(Structure constraintStructure, BlenderContext blenderContext) throws BlenderFileException {
if(constraintStructure == null) {
return new ConstraintDefinitionNull(null, blenderContext);
}
String constraintClassName = constraintStructure.getType();
Class<? extends ConstraintDefinition> constraintDefinitionClass = CONSTRAINT_CLASSES.get(constraintClassName);
if(constraintDefinitionClass != null) {
try {
return (ConstraintDefinition) constraintDefinitionClass.getDeclaredConstructors()[0].newInstance(constraintStructure, blenderContext);
} catch (IllegalArgumentException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (SecurityException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (InstantiationException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (IllegalAccessException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
} catch (InvocationTargetException e) {
throw new BlenderFileException(e.getLocalizedMessage(), e);
}
} else {
throw new BlenderFileException("Unknown constraint type: " + constraintClassName);
}
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Follow path' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionFollowPath extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionFollowPath.class.getName());
public ConstraintDefinitionFollowPath(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
//TODO: implement when curves are implemented
LOGGER.log(Level.INFO, "'Follow path' not implemented! Curves not yet implemented!");
}
}

@ -1,44 +1,26 @@
package com.jme3.scene.plugins.blender.constraints;
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.animation.Animation;
import com.jme3.animation.Skeleton;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.CalculationBone;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import java.util.logging.Logger;
/**
* This class represents 'Inverse kinematics' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintInverseKinematics extends Constraint {
private static final Logger LOGGER = Logger.getLogger(ConstraintInverseKinematics.class.getName());
private static final float IK_SOLVER_ERROR = 0.5f;
/*package*/ class ConstraintDefinitionInverseKinematics extends ConstraintDefinition {
//private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionInverseKinematics.class.getName());
//private static final float IK_SOLVER_ERROR = 0.5f;
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintInverseKinematics(Structure constraintStructure,
Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
public ConstraintDefinitionInverseKinematics(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
protected void bakeConstraint() {
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// try {
// IK solver is only attached to bones
// Bone ownerBone = (Bone) blenderContext.getLoadedFeature(ownerOMA, LoadedFeatureDataType.LOADED_FEATURE);

@ -0,0 +1,74 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Loc like' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionLocLike extends ConstraintDefinition {
private static final int LOCLIKE_X = 0x01;
private static final int LOCLIKE_Y = 0x02;
private static final int LOCLIKE_Z = 0x04;
//protected static final int LOCLIKE_TIP = 0x08;//this is deprecated in blender
private static final int LOCLIKE_X_INVERT = 0x10;
private static final int LOCLIKE_Y_INVERT = 0x20;
private static final int LOCLIKE_Z_INVERT = 0x40;
private static final int LOCLIKE_OFFSET = 0x80;
public ConstraintDefinitionLocLike(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
if(blenderContext.getBlenderKey().isFixUpAxis()) {
//swapping Y and X limits flag in the bitwise flag
int y = flag & LOCLIKE_Y;
int invY = flag & LOCLIKE_Y_INVERT;
int z = flag & LOCLIKE_Z;
int invZ = flag & LOCLIKE_Z_INVERT;
flag &= LOCLIKE_X | LOCLIKE_X_INVERT | LOCLIKE_OFFSET;//clear the other flags to swap them
flag |= y << 1;
flag |= invY << 1;
flag |= z >> 1;
flag |= invZ >> 1;
}
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
Vector3f ownerLocation = ownerTransform.getTranslation();
Vector3f targetLocation = targetTransform.getTranslation();
Vector3f startLocation = ownerTransform.getTranslation().clone();
Vector3f offset = Vector3f.ZERO;
if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original location to the copied location
offset = startLocation;
}
if ((flag & LOCLIKE_X) != 0) {
ownerLocation.x = targetLocation.x;
if ((flag & LOCLIKE_X_INVERT) != 0) {
ownerLocation.x = -ownerLocation.x;
}
}
if ((flag & LOCLIKE_Y) != 0) {
ownerLocation.y = targetLocation.y;
if ((flag & LOCLIKE_Y_INVERT) != 0) {
ownerLocation.y = -ownerLocation.y;
}
}
if ((flag & LOCLIKE_Z) != 0) {
ownerLocation.z = targetLocation.z;
if ((flag & LOCLIKE_Z_INVERT) != 0) {
ownerLocation.z = -ownerLocation.z;
}
}
ownerLocation.addLocal(offset);
if(influence < 1.0f) {
startLocation.subtractLocal(ownerLocation).normalizeLocal().mult(influence);
ownerLocation.addLocal(startLocation);
}
}
}

@ -0,0 +1,87 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Loc limit' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionLocLimit extends ConstraintDefinition {
private static final int LIMIT_XMIN = 0x01;
private static final int LIMIT_XMAX = 0x02;
private static final int LIMIT_YMIN = 0x04;
private static final int LIMIT_YMAX = 0x08;
private static final int LIMIT_ZMIN = 0x10;
private static final int LIMIT_ZMAX = 0x20;
protected float[][] limits = new float[3][2];
public ConstraintDefinitionLocLimit(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
if(blenderContext.getBlenderKey().isFixUpAxis()) {
limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
limits[2][0] = -((Number) constraintData.getFieldValue("ymin")).floatValue();
limits[2][1] = -((Number) constraintData.getFieldValue("ymax")).floatValue();
limits[1][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
limits[1][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
//swapping Y and X limits flag in the bitwise flag
int ymin = flag & LIMIT_YMIN;
int ymax = flag & LIMIT_YMAX;
int zmin = flag & LIMIT_ZMIN;
int zmax = flag & LIMIT_ZMAX;
flag &= LIMIT_XMIN | LIMIT_XMAX;//clear the other flags to swap them
flag |= ymin << 2;
flag |= ymax << 2;
flag |= zmin >> 2;
flag |= zmax >> 2;
} else {
limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
limits[1][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
limits[1][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
limits[2][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
limits[2][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
}
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
Vector3f translation = ownerTransform.getTranslation();
if ((flag & LIMIT_XMIN) != 0) {
if (translation.x < limits[0][0]) {
translation.x -= (translation.x - limits[0][0]) * influence;
}
}
if ((flag & LIMIT_XMAX) != 0) {
if (translation.x > limits[0][1]) {
translation.x -= (translation.x - limits[0][1]) * influence;
}
}
if ((flag & LIMIT_YMIN) != 0) {
if (translation.y < limits[1][0]) {
translation.y -= (translation.y - limits[1][0]) * influence;
}
}
if ((flag & LIMIT_YMAX) != 0) {
if (translation.y > limits[1][1]) {
translation.y -= (translation.y - limits[1][1]) * influence;
}
}
if ((flag & LIMIT_ZMIN) != 0) {
if (translation.z < limits[2][0]) {
translation.z -= (translation.z - limits[2][0]) * influence;
}
}
if ((flag & LIMIT_ZMAX) != 0) {
if (translation.z > limits[2][1]) {
translation.z -= (translation.z - limits[2][1]) * influence;
}
}
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Action' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionLockTrack extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionLockTrack.class.getName());
public ConstraintDefinitionLockTrack(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Lock track' constraint
LOGGER.log(Level.WARNING, "'Lock track' constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Min max' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionMinMax extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionMinMax.class.getName());
public ConstraintDefinitionMinMax(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Min max' constraint
LOGGER.log(Level.WARNING, "'Min max' constraint NOT implemented!");
}
}

@ -0,0 +1,19 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Null' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionNull extends ConstraintDefinition {
public ConstraintDefinitionNull(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) { }
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* The pivot constraint. Available for blender 2.50+.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionPivot extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionPivot.class.getName());
public ConstraintDefinitionPivot(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Pivot' constraint
LOGGER.log(Level.WARNING, "'Pivot' constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Python' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionPython extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionPython.class.getName());
public ConstraintDefinitionPython(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Python' constraint
LOGGER.log(Level.WARNING, "'Python' constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Rigid body joint' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionRigidBodyJoint extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionRigidBodyJoint.class.getName());
public ConstraintDefinitionRigidBodyJoint(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Rigid body joint' constraint
LOGGER.log(Level.WARNING, "'Rigid body joint' constraint NOT implemented!");
}
}

@ -0,0 +1,67 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Rot like' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionRotLike extends ConstraintDefinition {
private static final int ROTLIKE_X = 0x01;
private static final int ROTLIKE_Y = 0x02;
private static final int ROTLIKE_Z = 0x04;
private static final int ROTLIKE_X_INVERT = 0x10;
private static final int ROTLIKE_Y_INVERT = 0x20;
private static final int ROTLIKE_Z_INVERT = 0x40;
private static final int ROTLIKE_OFFSET = 0x80;
private transient float[] ownerAngles = new float[3];
private transient float[] targetAngles = new float[3];
public ConstraintDefinitionRotLike(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
Quaternion ownerRotation = ownerTransform.getRotation();
ownerAngles = ownerRotation.toAngles(ownerAngles);
targetAngles = targetTransform.getRotation().toAngles(targetAngles);
Quaternion startRotation = ownerRotation.clone();
Quaternion offset = Quaternion.IDENTITY;
if ((flag & ROTLIKE_OFFSET) != 0) {//we add the original rotation to the copied rotation
offset = startRotation;
}
if ((flag & ROTLIKE_X) != 0) {
ownerAngles[0] = targetAngles[0];
if ((flag & ROTLIKE_X_INVERT) != 0) {
ownerAngles[0] = -ownerAngles[0];
}
}
if ((flag & ROTLIKE_Y) != 0) {
ownerAngles[1] = targetAngles[1];
if ((flag & ROTLIKE_Y_INVERT) != 0) {
ownerAngles[1] = -ownerAngles[1];
}
}
if ((flag & ROTLIKE_Z) != 0) {
ownerAngles[2] = targetAngles[2];
if ((flag & ROTLIKE_Z_INVERT) != 0) {
ownerAngles[2] = -ownerAngles[2];
}
}
ownerRotation.fromAngles(ownerAngles).multLocal(offset);
if(influence < 1.0f) {
// startLocation.subtractLocal(ownerLocation).normalizeLocal().mult(influence);
// ownerLocation.addLocal(startLocation);
//TODO
}
}
}

@ -0,0 +1,85 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.FastMath;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Rot limit' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */class ConstraintDefinitionRotLimit extends ConstraintDefinition {
private static final int LIMIT_XROT = 0x01;
private static final int LIMIT_YROT = 0x02;
private static final int LIMIT_ZROT = 0x04;
private float[][] limits = new float[3][2];
private transient float[] angles = new float[3];
public ConstraintDefinitionRotLimit(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
if (blenderContext.getBlenderKey().isFixUpAxis()/* && owner.spatial != null*/) {//FIXME: !!!!!!!!
limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
limits[2][0] = -((Number) constraintData.getFieldValue("ymin")).floatValue();
limits[2][1] = -((Number) constraintData.getFieldValue("ymax")).floatValue();
limits[1][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
limits[1][1] = ((Number) constraintData.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 |= limitY << 1;
flag |= limitZ >> 1;
} else {
limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
limits[1][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
limits[1][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
limits[2][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
limits[2][1] = ((Number) constraintData.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
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
if ((flag & LIMIT_XROT) != 0) {
float difference = 0.0f;
if (angles[0] < limits[0][0]) {
difference = (angles[0] - limits[0][0]) * influence;
} else if (angles[0] > limits[0][1]) {
difference = (angles[0] - limits[0][1]) * influence;
}
angles[0] -= difference;
}
if ((flag & LIMIT_YROT) != 0) {
float difference = 0.0f;
if (angles[1] < limits[1][0]) {
difference = (angles[1] - limits[1][0]) * influence;
} else if (angles[1] > limits[1][1]) {
difference = (angles[1] - limits[1][1]) * influence;
}
angles[1] -= difference;
}
if ((flag & LIMIT_ZROT) != 0) {
float difference = 0.0f;
if (angles[2] < limits[2][0]) {
difference = (angles[2] - limits[2][0]) * influence;
} else if (angles[2] > limits[2][1]) {
difference = (angles[2] - limits[2][1]) * influence;
}
angles[2] -= difference;
}
}
}

@ -0,0 +1,27 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Same volume' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionSameVolume extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionSameVolume.class.getName());
public ConstraintDefinitionSameVolume(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Same volume' constraint
LOGGER.log(Level.WARNING, "'Same volume' constraint NOT implemented!");
}
}

@ -1,52 +1,23 @@
package com.jme3.scene.plugins.blender.constraints;
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.animation.Animation;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.ogre.AnimData;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* This class represents 'Shrink wrap' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintShrinkWrap extends Constraint {
/*package*/ class ConstraintDefinitionShrinkWrap extends ConstraintDefinition {
/**
* This constructor creates the constraint instance.
*
* @param constraintStructure
* the constraint's structure (bConstraint clss in blender 2.49).
* @param ownerOMA
* the old memory address of the constraint owner
* @param influenceIpo
* the ipo curve of the influence factor
* @param blenderContext
* the blender context
* @throws BlenderFileException
* this exception is thrown when the blender file is somehow
* corrupted
*/
public ConstraintShrinkWrap(Structure constraintStructure, Long ownerOMA,
Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
public ConstraintDefinitionShrinkWrap(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
protected void bakeConstraint() {
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
//loading mesh points (blender ensures that the target is a mesh-object)
List<Vector3f> pts = new ArrayList<Vector3f>();
/*List<Vector3f> pts = new ArrayList<Vector3f>();
Node target = (Node) this.target.getObject();
for(Spatial spatial : target.getChildren()) {
if(spatial instanceof Geometry) {
@ -84,7 +55,7 @@ import java.util.List;
track.setKeyframes(track.getTimes(), translations, rotations, track.getScales());
}
}
}*/
//TODO: static constraint for spatials
}

@ -0,0 +1,51 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Size like' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionSizeLike extends ConstraintDefinition {
private static final int SIZELIKE_X = 0x01;
private static final int SIZELIKE_Y = 0x02;
private static final int SIZELIKE_Z = 0x04;
private static final int LOCLIKE_OFFSET = 0x80;
public ConstraintDefinitionSizeLike(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
if(blenderContext.getBlenderKey().isFixUpAxis()) {
//swapping Y and X limits flag in the bitwise flag
int y = flag & SIZELIKE_Y;
int z = flag & SIZELIKE_Z;
flag &= SIZELIKE_X | LOCLIKE_OFFSET;//clear the other flags to swap them
flag |= y << 1;
flag |= z >> 1;
}
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
Vector3f ownerScale = ownerTransform.getScale();
Vector3f targetScale = targetTransform.getScale();
Vector3f offset = Vector3f.ZERO;
if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original scale to the copied scale
offset = ownerScale.clone();
}
if ((flag & SIZELIKE_X) != 0) {
ownerScale.x = targetScale.x * influence + (1.0f - influence) * ownerScale.x;
}
if ((flag & SIZELIKE_Y) != 0) {
ownerScale.y = targetScale.y * influence + (1.0f - influence) * ownerScale.y;
}
if ((flag & SIZELIKE_Z) != 0) {
ownerScale.z = targetScale.z * influence + (1.0f - influence) * ownerScale.z;
}
ownerScale.addLocal(offset);
}
}

@ -0,0 +1,75 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Size limit' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionSizeLimit extends ConstraintDefinition {
private static final int LIMIT_XMIN = 0x01;
private static final int LIMIT_XMAX = 0x02;
private static final int LIMIT_YMIN = 0x04;
private static final int LIMIT_YMAX = 0x08;
private static final int LIMIT_ZMIN = 0x10;
private static final int LIMIT_ZMAX = 0x20;
protected float[][] limits = new float[3][2];
public ConstraintDefinitionSizeLimit(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
if(blenderContext.getBlenderKey().isFixUpAxis()) {
limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
limits[2][0] = -((Number) constraintData.getFieldValue("ymin")).floatValue();
limits[2][1] = -((Number) constraintData.getFieldValue("ymax")).floatValue();
limits[1][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
limits[1][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
//swapping Y and X limits flag in the bitwise flag
int ymin = flag & LIMIT_YMIN;
int ymax = flag & LIMIT_YMAX;
int zmin = flag & LIMIT_ZMIN;
int zmax = flag & LIMIT_ZMAX;
flag &= LIMIT_XMIN | LIMIT_XMAX;//clear the other flags to swap them
flag |= ymin << 2;
flag |= ymax << 2;
flag |= zmin >> 2;
flag |= zmax >> 2;
} else {
limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
limits[1][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
limits[1][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
limits[2][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
limits[2][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
}
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
Vector3f scale = ownerTransform.getScale();
if ((flag & LIMIT_XMIN) != 0 && scale.x < limits[0][0]) {
scale.x -= (scale.x - limits[0][0]) * influence;
}
if ((flag & LIMIT_XMAX) != 0 && scale.x > limits[0][1]) {
scale.x -= (scale.x - limits[0][1]) * influence;
}
if ((flag & LIMIT_YMIN) != 0 && scale.y < limits[1][0]) {
scale.y -= (scale.y - limits[1][0]) * influence;
}
if ((flag & LIMIT_YMAX) != 0 && scale.y > limits[1][1]) {
scale.y -= (scale.y - limits[1][1]) * influence;
}
if ((flag & LIMIT_ZMIN) != 0 && scale.z < limits[2][0]) {
scale.z -= (scale.z - limits[2][0]) * influence;
}
if ((flag & LIMIT_ZMAX) != 0 && scale.z > limits[2][1]) {
scale.z -= (scale.z - limits[2][1]) * influence;
}
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* The spline inverse kinematic constraint. Available for blender 2.50+.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionSplineInverseKinematic extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionSplineInverseKinematic.class.getName());
public ConstraintDefinitionSplineInverseKinematic(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO Auto-generated method stub
LOGGER.log(Level.WARNING, "'Splie IK' constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Stretch to' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionStretchTo extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionStretchTo.class.getName());
public ConstraintDefinitionStretchTo(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Stretch to' constraint
LOGGER.log(Level.WARNING, "'Stretch to' constraint NOT implemented!");
}
}

@ -0,0 +1,27 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Track to' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */class ConstraintDefinitionTrackTo extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionTrackTo.class.getName());
public ConstraintDefinitionTrackTo(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Track to' constraint
LOGGER.log(Level.WARNING, "'Track to' constraint NOT implemented!");
}
}

@ -0,0 +1,27 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Trans like' constraint type in blender.
*
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionTransLike extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionTransLike.class.getName());
public ConstraintDefinitionTransLike(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Trans like' constraint
LOGGER.log(Level.WARNING, "'Trans like' constraint NOT implemented!");
}
}

@ -0,0 +1,26 @@
package com.jme3.scene.plugins.blender.constraints.definitions;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Structure;
/**
* This class represents 'Transform' constraint type in blender.
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class ConstraintDefinitionTransform extends ConstraintDefinition {
private static final Logger LOGGER = Logger.getLogger(ConstraintDefinitionAction.class.getName());
public ConstraintDefinitionTransform(Structure constraintData, BlenderContext blenderContext) {
super(constraintData, blenderContext);
}
@Override
public void bake(Transform ownerTransform, Transform targetTransform, float influence) {
// TODO: implement 'Transform' constraint
LOGGER.log(Level.WARNING, "'Transform' constraint NOT implemented!");
}
}

@ -26,7 +26,6 @@ import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType;
import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
import com.jme3.scene.plugins.blender.constraints.Constraint;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
import com.jme3.scene.plugins.blender.file.Pointer;
@ -224,18 +223,6 @@ import com.jme3.util.BufferUtils;
}
}
// applying constraints to Bones
ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class);
for (int i = 0; i < animData.skeleton.getBoneCount(); ++i) {
Long boneOMA = armatureHelper.getBoneOMA(animData.skeleton.getBone(i));
List<Constraint> constraints = blenderContext.getConstraints(boneOMA);
if (constraints != null && constraints.size() > 0) {
for (Constraint constraint : constraints) {
constraint.bake();
}
}
}
// applying animations
AnimControl control = new AnimControl(animData.skeleton);
ArrayList<Animation> animList = animData.anims;

@ -51,7 +51,6 @@ import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType;
import com.jme3.scene.plugins.blender.cameras.CameraHelper;
import com.jme3.scene.plugins.blender.constraints.Constraint;
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
import com.jme3.scene.plugins.blender.curves.CurvesHelper;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
@ -238,14 +237,6 @@ public class ObjectHelper extends AbstractBlenderHelper {
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
constraintHelper.loadConstraints(objectStructure, blenderContext);
//baking constraints
List<Constraint> objectConstraints = blenderContext.getConstraints(objectStructure.getOldMemoryAddress());
if(objectConstraints!=null) {
for(Constraint objectConstraint : objectConstraints) {
objectConstraint.bake();
}
}
//reading custom properties
if(blenderContext.getBlenderKey().isLoadObjectProperties()) {
Properties properties = this.loadProperties(objectStructure, blenderContext);

Loading…
Cancel
Save