Home | History | Annotate | Download | only in constraints
      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