aboutsummaryrefslogtreecommitdiff
path: root/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java')
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java120
1 files changed, 120 insertions, 0 deletions
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java
new file mode 100644
index 0000000..ff3b99a
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java
@@ -0,0 +1,120 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.Animation;
+import com.jme3.math.Matrix4f;
+import com.jme3.math.Vector3f;
+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.Structure;
+import com.jme3.scene.plugins.ogre.AnimData;
+
+/**
+ * This class represents 'Dist limit' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintDistLimit extends Constraint {
+ private static final int LIMITDIST_INSIDE = 0;
+ private static final int LIMITDIST_OUTSIDE = 1;
+ private static final int LIMITDIST_ONSURFACE = 2;
+
+ protected int mode;
+ protected float dist;
+
+ /**
+ * 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 ConstraintDistLimit(Structure constraintStructure, Long ownerOMA,
+ Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
+ super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
+
+ mode = ((Number) data.getFieldValue("mode")).intValue();
+ dist = ((Number) data.getFieldValue("dist")).floatValue();
+ }
+
+ @Override
+ protected void bakeConstraint() {
+ Object owner = this.owner.getObject();
+ AnimData animData = blenderContext.getAnimData(this.owner.getOma());
+ if(animData != null) {
+ if(owner instanceof Spatial) {
+ Vector3f targetLocation = ((Spatial) owner).getWorldTranslation();
+ for(Animation animation : animData.anims) {
+ BlenderTrack blenderTrack = this.getTrack(owner, animData.skeleton, animation);
+ int maxFrames = blenderTrack.getTimes().length;
+ Vector3f[] translations = blenderTrack.getTranslations();
+ for (int frame = 0; frame < maxFrames; ++frame) {
+ Vector3f v = translations[frame].subtract(targetLocation);
+ this.distLimit(v, targetLocation, ipo.calculateValue(frame));
+ translations[frame].addLocal(v);
+ }
+ blenderTrack.setKeyframes(blenderTrack.getTimes(), translations, blenderTrack.getRotations(), blenderTrack.getScales());
+ }
+ }
+ }
+
+ // apply static constraint only to spatials
+ if(owner instanceof Spatial) {
+ Matrix4f targetWorldMatrix = target.getWorldTransformMatrix();
+ Vector3f targetLocation = targetWorldMatrix.toTranslationVector();
+ Matrix4f m = this.owner.getParentWorldTransformMatrix();
+ m.invertLocal();
+ Matrix4f ownerWorldMatrix = this.owner.getWorldTransformMatrix();
+ Vector3f ownerLocation = ownerWorldMatrix.toTranslationVector();
+ this.distLimit(ownerLocation, targetLocation, ipo.calculateValue(0));
+ ((Spatial) owner).setLocalTranslation(m.mult(ownerLocation));
+ }
+ }
+
+ /**
+ *
+ * @param currentLocation
+ * @param targetLocation
+ * @param influence
+ */
+ private void distLimit(Vector3f currentLocation, Vector3f targetLocation, float influence) {
+ Vector3f v = currentLocation.subtract(targetLocation);
+ float currentDistance = v.length();
+
+ switch (mode) {
+ case LIMITDIST_INSIDE:
+ if (currentDistance >= dist) {
+ v.normalizeLocal();
+ v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
+ currentLocation.set(v.addLocal(targetLocation));
+ }
+ break;
+ case LIMITDIST_ONSURFACE:
+ if (currentDistance > dist) {
+ v.normalizeLocal();
+ v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
+ currentLocation.set(v.addLocal(targetLocation));
+ } else if(currentDistance < dist) {
+ v.normalizeLocal().multLocal(dist * influence);
+ currentLocation.set(targetLocation.add(v));
+ }
+ break;
+ case LIMITDIST_OUTSIDE:
+ if (currentDistance <= dist) {
+ v = targetLocation.subtract(currentLocation).normalizeLocal().multLocal(dist * influence);
+ currentLocation.set(targetLocation.add(v));
+ }
+ break;
+ default:
+ throw new IllegalStateException("Unknown distance limit constraint mode: " + mode);
+ }
+ }
+}