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
This commit is contained in:
parent
58bbd2d076
commit
711b8ab9ca
@ -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();
|
||||
}
|
||||
this.bakeConstraint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bake the animation's constraints into its owner.
|
||||
*/
|
||||
protected abstract void bakeConstraint();
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
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;
|
||||
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 method should be overwridden and perform the baking opertion.
|
||||
*/
|
||||
protected abstract void performBakingOperation();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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,19 +1,32 @@
|
||||
package com.jme3.scene.plugins.blender.constraints;
|
||||
|
||||
import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
|
||||
import com.jme3.scene.plugins.blender.BlenderContext;
|
||||
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.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;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* This class should be used for constraint calculations.
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
@ -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…
x
Reference in New Issue
Block a user