package com.jme3.scene.plugins.blender.constraints.definitions; import com.jme3.animation.Bone; import com.jme3.math.Transform; import com.jme3.math.Vector3f; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.animations.BoneContext; import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space; import com.jme3.scene.plugins.blender.file.Structure; /** * This class represents 'Dist limit' constraint type in blender. * * @author Marcin Roguski (Kaelthas) */ /* package */class ConstraintDefinitionDistLimit extends ConstraintDefinition { 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; public ConstraintDefinitionDistLimit(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) { super(constraintData, ownerOMA, blenderContext); mode = ((Number) constraintData.getFieldValue("mode")).intValue(); dist = ((Number) constraintData.getFieldValue("dist")).floatValue(); } @Override public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) { if (this.getOwner() instanceof Bone && ((Bone) this.getOwner()).getParent() != null && blenderContext.getBoneContext(ownerOMA).is(BoneContext.CONNECTED_TO_PARENT)) { // distance limit does not work on bones who are connected to their parent return; } if (influence == 0 || targetTransform == null) { return;// no need to do anything } Transform ownerTransform = this.getOwnerTransform(ownerSpace); Vector3f v = ownerTransform.getTranslation().subtract(targetTransform.getTranslation()); float currentDistance = v.length(); switch (mode) { case LIMITDIST_INSIDE: if (currentDistance >= dist) { v.normalizeLocal(); v.multLocal(dist + (currentDistance - dist) * (1.0f - influence)); ownerTransform.getTranslation().set(v.addLocal(targetTransform.getTranslation())); } break; case LIMITDIST_ONSURFACE: if (currentDistance > dist) { v.normalizeLocal(); v.multLocal(dist + (currentDistance - dist) * (1.0f - influence)); ownerTransform.getTranslation().set(v.addLocal(targetTransform.getTranslation())); } else if (currentDistance < dist) { v.normalizeLocal().multLocal(dist * influence); ownerTransform.getTranslation().set(targetTransform.getTranslation().add(v)); } break; case LIMITDIST_OUTSIDE: if (currentDistance <= dist) { v = targetTransform.getTranslation().subtract(ownerTransform.getTranslation()).normalizeLocal().multLocal(dist * influence); ownerTransform.getTranslation().set(targetTransform.getTranslation().add(v)); } break; default: throw new IllegalStateException("Unknown distance limit constraint mode: " + mode); } this.applyOwnerTransform(ownerTransform, ownerSpace); } @Override public boolean isTargetRequired() { return true; } @Override public String getConstraintTypeName() { return "Limit distance"; } }