1 package com.jme3.scene.plugins.blender.constraints; 2 3 import com.jme3.animation.Animation; 4 import com.jme3.math.Matrix4f; 5 import com.jme3.math.Vector3f; 6 import com.jme3.scene.Spatial; 7 import com.jme3.scene.plugins.blender.BlenderContext; 8 import com.jme3.scene.plugins.blender.animations.Ipo; 9 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 10 import com.jme3.scene.plugins.blender.file.Structure; 11 import com.jme3.scene.plugins.ogre.AnimData; 12 13 /** 14 * This class represents 'Dist limit' constraint type in blender. 15 * @author Marcin Roguski (Kaelthas) 16 */ 17 /*package*/ class ConstraintDistLimit extends Constraint { 18 private static final int LIMITDIST_INSIDE = 0; 19 private static final int LIMITDIST_OUTSIDE = 1; 20 private static final int LIMITDIST_ONSURFACE = 2; 21 22 protected int mode; 23 protected float dist; 24 25 /** 26 * This constructor creates the constraint instance. 27 * 28 * @param constraintStructure 29 * the constraint's structure (bConstraint clss in blender 2.49). 30 * @param ownerOMA 31 * the old memory address of the constraint owner 32 * @param influenceIpo 33 * the ipo curve of the influence factor 34 * @param blenderContext 35 * the blender context 36 * @throws BlenderFileException 37 * this exception is thrown when the blender file is somehow 38 * corrupted 39 */ 40 public ConstraintDistLimit(Structure constraintStructure, Long ownerOMA, 41 Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { 42 super(constraintStructure, ownerOMA, influenceIpo, blenderContext); 43 44 mode = ((Number) data.getFieldValue("mode")).intValue(); 45 dist = ((Number) data.getFieldValue("dist")).floatValue(); 46 } 47 48 @Override 49 protected void bakeConstraint() { 50 Object owner = this.owner.getObject(); 51 AnimData animData = blenderContext.getAnimData(this.owner.getOma()); 52 if(animData != null) { 53 if(owner instanceof Spatial) { 54 Vector3f targetLocation = ((Spatial) owner).getWorldTranslation(); 55 for(Animation animation : animData.anims) { 56 BlenderTrack blenderTrack = this.getTrack(owner, animData.skeleton, animation); 57 int maxFrames = blenderTrack.getTimes().length; 58 Vector3f[] translations = blenderTrack.getTranslations(); 59 for (int frame = 0; frame < maxFrames; ++frame) { 60 Vector3f v = translations[frame].subtract(targetLocation); 61 this.distLimit(v, targetLocation, ipo.calculateValue(frame)); 62 translations[frame].addLocal(v); 63 } 64 blenderTrack.setKeyframes(blenderTrack.getTimes(), translations, blenderTrack.getRotations(), blenderTrack.getScales()); 65 } 66 } 67 } 68 69 // apply static constraint only to spatials 70 if(owner instanceof Spatial) { 71 Matrix4f targetWorldMatrix = target.getWorldTransformMatrix(); 72 Vector3f targetLocation = targetWorldMatrix.toTranslationVector(); 73 Matrix4f m = this.owner.getParentWorldTransformMatrix(); 74 m.invertLocal(); 75 Matrix4f ownerWorldMatrix = this.owner.getWorldTransformMatrix(); 76 Vector3f ownerLocation = ownerWorldMatrix.toTranslationVector(); 77 this.distLimit(ownerLocation, targetLocation, ipo.calculateValue(0)); 78 ((Spatial) owner).setLocalTranslation(m.mult(ownerLocation)); 79 } 80 } 81 82 /** 83 * 84 * @param currentLocation 85 * @param targetLocation 86 * @param influence 87 */ 88 private void distLimit(Vector3f currentLocation, Vector3f targetLocation, float influence) { 89 Vector3f v = currentLocation.subtract(targetLocation); 90 float currentDistance = v.length(); 91 92 switch (mode) { 93 case LIMITDIST_INSIDE: 94 if (currentDistance >= dist) { 95 v.normalizeLocal(); 96 v.multLocal(dist + (currentDistance - dist) * (1.0f - influence)); 97 currentLocation.set(v.addLocal(targetLocation)); 98 } 99 break; 100 case LIMITDIST_ONSURFACE: 101 if (currentDistance > dist) { 102 v.normalizeLocal(); 103 v.multLocal(dist + (currentDistance - dist) * (1.0f - influence)); 104 currentLocation.set(v.addLocal(targetLocation)); 105 } else if(currentDistance < dist) { 106 v.normalizeLocal().multLocal(dist * influence); 107 currentLocation.set(targetLocation.add(v)); 108 } 109 break; 110 case LIMITDIST_OUTSIDE: 111 if (currentDistance <= dist) { 112 v = targetLocation.subtract(currentLocation).normalizeLocal().multLocal(dist * influence); 113 currentLocation.set(targetLocation.add(v)); 114 } 115 break; 116 default: 117 throw new IllegalStateException("Unknown distance limit constraint mode: " + mode); 118 } 119 } 120 } 121