• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	 */
ConstraintDistLimit(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext)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
bakeConstraint()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 	 */
distLimit(Vector3f currentLocation, Vector3f targetLocation, float influence)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