1 package com.jme3.scene.plugins.blender.constraints; 2 3 import com.jme3.animation.Animation; 4 import com.jme3.animation.Skeleton; 5 import com.jme3.scene.plugins.blender.BlenderContext; 6 import com.jme3.scene.plugins.blender.animations.CalculationBone; 7 import com.jme3.scene.plugins.blender.animations.Ipo; 8 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 9 import com.jme3.scene.plugins.blender.file.Structure; 10 import java.util.logging.Logger; 11 12 /** 13 * This class represents 'Inverse kinematics' constraint type in blender. 14 * @author Marcin Roguski (Kaelthas) 15 */ 16 /*package*/ class ConstraintInverseKinematics extends Constraint { 17 private static final Logger LOGGER = Logger.getLogger(ConstraintInverseKinematics.class.getName()); 18 private static final float IK_SOLVER_ERROR = 0.5f; 19 20 /** 21 * This constructor creates the constraint instance. 22 * 23 * @param constraintStructure 24 * the constraint's structure (bConstraint clss in blender 2.49). 25 * @param ownerOMA 26 * the old memory address of the constraint owner 27 * @param influenceIpo 28 * the ipo curve of the influence factor 29 * @param blenderContext 30 * the blender context 31 * @throws BlenderFileException 32 * this exception is thrown when the blender file is somehow 33 * corrupted 34 */ 35 public ConstraintInverseKinematics(Structure constraintStructure, 36 Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { 37 super(constraintStructure, ownerOMA, influenceIpo, blenderContext); 38 } 39 40 @Override 41 protected void bakeConstraint() { 42 // try { 43 // IK solver is only attached to bones 44 // Bone ownerBone = (Bone) blenderContext.getLoadedFeature(ownerOMA, LoadedFeatureDataType.LOADED_FEATURE); 45 // AnimData animData = blenderContext.getAnimData(ownerOMA); 46 // if(animData == null) { 47 //TODO: to nie moxe byx null, utworzyx dane bez ruchu, w zalexnoxci czy target six rusza 48 // } 49 50 //prepare a list of all parents of this bone 51 // CalculationBone[] bones = this.getBonesToCalculate(skeleton, boneAnimation); 52 53 // get the target point 54 // Object targetObject = this.getTarget(LoadedFeatureDataType.LOADED_FEATURE); 55 // Vector3f pt = null;// Point Target 56 // if (targetObject instanceof Bone) { 57 // pt = ((Bone) targetObject).getModelSpacePosition(); 58 // } else if (targetObject instanceof Spatial) { 59 // pt = ((Spatial) targetObject).getWorldTranslation(); 60 // } else if (targetObject instanceof Skeleton) { 61 // Structure armatureNodeStructure = (Structure) this.getTarget(LoadedFeatureDataType.LOADED_STRUCTURE); 62 // ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); 63 // Transform transform = objectHelper.getTransformation(armatureNodeStructure, blenderContext); 64 // pt = transform.getTranslation(); 65 // } else { 66 // throw new IllegalStateException( 67 // "Unknown target object type! Should be Node, Bone or Skeleton and there is: " 68 // + targetObject.getClass().getName()); 69 // } 70 71 //fetching the owner's bone track 72 // BoneTrack ownerBoneTrack = null; 73 // int boneIndex = skeleton.getBoneIndex(ownerBone); 74 // for (int i = 0; i < boneAnimation.getTracks().length; ++i) { 75 // if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) { 76 // ownerBoneTrack = boneAnimation.getTracks()[i]; 77 // break; 78 // } 79 // } 80 // int ownerBoneFramesCount = ownerBoneTrack==null ? 0 : ownerBoneTrack.getTimes().length; 81 // 82 // // preparing data 83 // int maxIterations = ((Number) data.getFieldValue("iterations")).intValue(); 84 // CalculationBone[] bones = this.getBonesToCalculate(ownerBone, skeleton, boneAnimation); 85 // for (int i = 0; i < bones.length; ++i) { 86 // System.out.println(Arrays.toString(bones[i].track.getTranslations())); 87 // System.out.println(Arrays.toString(bones[i].track.getRotations())); 88 // System.out.println("==============================="); 89 // } 90 // Quaternion rotation = new Quaternion(); 91 // //all tracks should have the same amount of frames 92 // int framesCount = bones[0].getBoneFramesCount(); 93 // assert framesCount >=1; 94 // for (int frame = 0; frame < framesCount; ++frame) { 95 // float error = IK_SOLVER_ERROR; 96 // int iteration = 0; 97 // while (error >= IK_SOLVER_ERROR && iteration <= maxIterations) { 98 // // rotating the bones 99 // for (int i = 0; i < bones.length - 1; ++i) { 100 // Vector3f pe = bones[i].getEndPoint(); 101 // Vector3f pc = bones[i + 1].getWorldTranslation().clone(); 102 // 103 // Vector3f peSUBpc = pe.subtract(pc).normalizeLocal(); 104 // Vector3f ptSUBpc = pt.subtract(pc).normalizeLocal(); 105 // 106 // float theta = FastMath.acos(peSUBpc.dot(ptSUBpc)); 107 // Vector3f direction = peSUBpc.cross(ptSUBpc).normalizeLocal(); 108 // bones[i].rotate(rotation.fromAngleAxis(theta, direction), frame); 109 // } 110 // error = pt.subtract(bones[0].getEndPoint()).length(); 111 // ++iteration; 112 // } 113 // } 114 // 115 // for (CalculationBone bone : bones) { 116 // bone.applyCalculatedTracks(); 117 // } 118 // 119 // System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); 120 // for (int i = 0; i < bones.length; ++i) { 121 // System.out.println(Arrays.toString(bones[i].track.getTranslations())); 122 // System.out.println(Arrays.toString(bones[i].track.getRotations())); 123 // System.out.println("==============================="); 124 // } 125 // } catch(BlenderFileException e) { 126 // LOGGER.severe(e.getLocalizedMessage()); 127 // } 128 } 129 130 /** 131 * This method returns bones used for rotation calculations. 132 * @param bone 133 * the bone to which the constraint is applied 134 * @param skeleton 135 * the skeleton owning the bone and its ancestors 136 * @param boneAnimation 137 * the bone animation data that stores the traces for the skeleton's bones 138 * @return a list of bones to imitate the bone's movement during IK solving 139 */ 140 private CalculationBone[] getBonesToCalculate(Skeleton skeleton, Animation boneAnimation) { 141 // Bone ownerBone = (Bone) blenderContext.getLoadedFeature(ownerOMA, LoadedFeatureDataType.LOADED_FEATURE); 142 // List<CalculationBone> bonesList = new ArrayList<CalculationBone>(); 143 // do { 144 // bonesList.add(new CalculationBone(ownerBone, 1)); 145 // int boneIndex = skeleton.getBoneIndex(ownerBone); 146 // for (int i = 0; i < boneAnimation.getTracks().length; ++i) { 147 // if (((BoneTrack[])boneAnimation.getTracks())[i].getTargetBoneIndex() == boneIndex) { 148 // bonesList.add(new CalculationBone(ownerBone, (BoneTrack)boneAnimation.getTracks()[i])); 149 // break; 150 // } 151 // } 152 // ownerBone = ownerBone.getParent(); 153 // } while (ownerBone != null); 154 // //attaching children 155 // CalculationBone[] result = bonesList.toArray(new CalculationBone[bonesList.size()]); 156 // for (int i = result.length - 1; i > 0; --i) { 157 // result[i].attachChild(result[i - 1]); 158 // } 159 // return result; 160 return null; 161 } 162 } 163