1 package com.jme3.scene.plugins.blender.constraints; 2 3 import com.jme3.animation.Animation; 4 import com.jme3.animation.Bone; 5 import com.jme3.animation.BoneTrack; 6 import com.jme3.animation.Skeleton; 7 import com.jme3.animation.SpatialTrack; 8 import com.jme3.animation.Track; 9 import com.jme3.scene.Spatial; 10 import com.jme3.scene.plugins.blender.BlenderContext; 11 import com.jme3.scene.plugins.blender.animations.Ipo; 12 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 13 import com.jme3.scene.plugins.blender.file.Pointer; 14 import com.jme3.scene.plugins.blender.file.Structure; 15 import com.jme3.scene.plugins.blender.objects.ObjectHelper; 16 17 /** 18 * The implementation of a constraint. 19 * 20 * @author Marcin Roguski (Kaelthas) 21 */ 22 public abstract class Constraint { 23 /** The name of this constraint. */ 24 protected final String name; 25 /** The constraint's owner. */ 26 protected final Feature owner; 27 /** The constraint's target. */ 28 protected final Feature target; 29 /** The structure with constraint's data. */ 30 protected final Structure data; 31 /** The ipo object defining influence. */ 32 protected final Ipo ipo; 33 /** The blender context. */ 34 protected final BlenderContext blenderContext; 35 36 /** 37 * This constructor creates the constraint instance. 38 * 39 * @param constraintStructure 40 * the constraint's structure (bConstraint clss in blender 2.49). 41 * @param ownerOMA 42 * the old memory address of the constraint owner 43 * @param influenceIpo 44 * the ipo curve of the influence factor 45 * @param blenderContext 46 * the blender context 47 * @throws BlenderFileException 48 * this exception is thrown when the blender file is somehow 49 * corrupted 50 */ 51 public Constraint(Structure constraintStructure, Long ownerOMA, 52 Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { 53 this.blenderContext = blenderContext; 54 this.name = constraintStructure.getFieldValue("name").toString(); 55 Pointer pData = (Pointer) constraintStructure.getFieldValue("data"); 56 if (pData.isNotNull()) { 57 data = pData.fetchData(blenderContext.getInputStream()).get(0); 58 Pointer pTar = (Pointer)data.getFieldValue("tar"); 59 if(pTar!= null && pTar.isNotNull()) { 60 Structure targetStructure = pTar.fetchData(blenderContext.getInputStream()).get(0); 61 Long targetOMA = pTar.getOldMemoryAddress(); 62 Space targetSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("tarspace")).byteValue()); 63 ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); 64 Spatial target = (Spatial) objectHelper.toObject(targetStructure, blenderContext); 65 this.target = new Feature(target, targetSpace, targetOMA, blenderContext); 66 } else { 67 this.target = null; 68 } 69 } else { 70 throw new BlenderFileException("The constraint has no data specified!"); 71 } 72 Space ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue()); 73 this.owner = new Feature(ownerSpace, ownerOMA, blenderContext); 74 this.ipo = influenceIpo; 75 } 76 77 /** 78 * This method bakes the required sontraints into its owner. 79 */ 80 public void bake() { 81 this.owner.update(); 82 if(this.target != null) { 83 this.target.update(); 84 } 85 this.bakeConstraint(); 86 } 87 88 /** 89 * Bake the animation's constraints into its owner. 90 */ 91 protected abstract void bakeConstraint(); 92 93 /** 94 * This method returns the bone traces for the bone that is affected by the given constraint. 95 * @param skeleton 96 * the skeleton containing bones 97 * @param boneAnimation 98 * the bone animation that affects the skeleton 99 * @return the bone track for the bone that is being affected by the constraint 100 */ 101 protected BlenderTrack getTrack(Object owner, Skeleton skeleton, Animation animation) { 102 if(owner instanceof Bone) { 103 int boneIndex = skeleton.getBoneIndex((Bone) owner); 104 for (Track track : animation.getTracks()) { 105 if (((BoneTrack) track).getTargetBoneIndex() == boneIndex) { 106 return new BlenderTrack(((BoneTrack) track)); 107 } 108 } 109 throw new IllegalStateException("Cannot find track for: " + owner); 110 } else { 111 return new BlenderTrack((SpatialTrack)animation.getTracks()[0]); 112 } 113 } 114 115 /** 116 * The space of target or owner transformation. 117 * 118 * @author Marcin Roguski (Kaelthas) 119 */ 120 public static enum Space { 121 122 CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID; 123 124 /** 125 * This method returns the enum instance when given the appropriate 126 * value from the blend file. 127 * 128 * @param c 129 * the blender's value of the space modifier 130 * @return the scape enum instance 131 */ 132 public static Space valueOf(byte c) { 133 switch (c) { 134 case 0: 135 return CONSTRAINT_SPACE_WORLD; 136 case 1: 137 return CONSTRAINT_SPACE_LOCAL; 138 case 2: 139 return CONSTRAINT_SPACE_POSE; 140 case 3: 141 return CONSTRAINT_SPACE_PARLOCAL; 142 default: 143 return CONSTRAINT_SPACE_INVALID; 144 } 145 } 146 } 147 }