blob: 6846d14bb835df26a6f5e85e8f8861ab0bb4a943 [file] [log] [blame]
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 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.Pointer;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
/**
* The implementation of a constraint.
*
* @author Marcin Roguski (Kaelthas)
*/
public abstract class Constraint {
/** 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;
/** The ipo object defining influence. */
protected final Ipo ipo;
/** The blender context. */
protected final BlenderContext blenderContext;
/**
* 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 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);
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;
}
} else {
throw new BlenderFileException("The constraint has no data specified!");
}
Space ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue());
this.owner = new Feature(ownerSpace, ownerOMA, blenderContext);
this.ipo = influenceIpo;
}
/**
* This method bakes the required sontraints into its owner.
*/
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;
}
}
}
}