159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene.plugins.blender.constraints; 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.animation.Animation; 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Matrix4f; 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial; 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.BlenderContext; 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.animations.Ipo; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Structure; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.ogre.AnimData; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This class represents 'Dist limit' constraint type in blender. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski (Kaelthas) 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*package*/ class ConstraintDistLimit extends Constraint { 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final int LIMITDIST_INSIDE = 0; 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final int LIMITDIST_OUTSIDE = 1; 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final int LIMITDIST_ONSURFACE = 2; 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int mode; 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected float dist; 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This constructor creates the constraint instance. 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param constraintStructure 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the constraint's structure (bConstraint clss in blender 2.49). 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param ownerOMA 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the old memory address of the constraint owner 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param influenceIpo 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the ipo curve of the influence factor 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderContext 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the blender context 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws BlenderFileException 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this exception is thrown when the blender file is somehow 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * corrupted 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public ConstraintDistLimit(Structure constraintStructure, Long ownerOMA, 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(constraintStructure, ownerOMA, influenceIpo, blenderContext); 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mode = ((Number) data.getFieldValue("mode")).intValue(); 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dist = ((Number) data.getFieldValue("dist")).floatValue(); 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void bakeConstraint() { 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Object owner = this.owner.getObject(); 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AnimData animData = blenderContext.getAnimData(this.owner.getOma()); 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(animData != null) { 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(owner instanceof Spatial) { 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f targetLocation = ((Spatial) owner).getWorldTranslation(); 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for(Animation animation : animData.anims) { 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BlenderTrack blenderTrack = this.getTrack(owner, animData.skeleton, animation); 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int maxFrames = blenderTrack.getTimes().length; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f[] translations = blenderTrack.getTranslations(); 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int frame = 0; frame < maxFrames; ++frame) { 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v = translations[frame].subtract(targetLocation); 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.distLimit(v, targetLocation, ipo.calculateValue(frame)); 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta translations[frame].addLocal(v); 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blenderTrack.setKeyframes(blenderTrack.getTimes(), translations, blenderTrack.getRotations(), blenderTrack.getScales()); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // apply static constraint only to spatials 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(owner instanceof Spatial) { 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Matrix4f targetWorldMatrix = target.getWorldTransformMatrix(); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f targetLocation = targetWorldMatrix.toTranslationVector(); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Matrix4f m = this.owner.getParentWorldTransformMatrix(); 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.invertLocal(); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Matrix4f ownerWorldMatrix = this.owner.getWorldTransformMatrix(); 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f ownerLocation = ownerWorldMatrix.toTranslationVector(); 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.distLimit(ownerLocation, targetLocation, ipo.calculateValue(0)); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ((Spatial) owner).setLocalTranslation(m.mult(ownerLocation)); 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param currentLocation 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param targetLocation 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param influence 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void distLimit(Vector3f currentLocation, Vector3f targetLocation, float influence) { 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v = currentLocation.subtract(targetLocation); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float currentDistance = v.length(); 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (mode) { 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case LIMITDIST_INSIDE: 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (currentDistance >= dist) { 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.normalizeLocal(); 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.multLocal(dist + (currentDistance - dist) * (1.0f - influence)); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentLocation.set(v.addLocal(targetLocation)); 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case LIMITDIST_ONSURFACE: 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (currentDistance > dist) { 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.normalizeLocal(); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.multLocal(dist + (currentDistance - dist) * (1.0f - influence)); 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentLocation.set(v.addLocal(targetLocation)); 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if(currentDistance < dist) { 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.normalizeLocal().multLocal(dist * influence); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentLocation.set(targetLocation.add(v)); 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case LIMITDIST_OUTSIDE: 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (currentDistance <= dist) { 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = targetLocation.subtract(currentLocation).normalizeLocal().multLocal(dist * influence); 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentLocation.set(targetLocation.add(v)); 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Unknown distance limit constraint mode: " + mode); 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 121