Browse Source

Several changes to constraints (but may not working well yet).
Fix to Y-up axis issue when parent was present bu not loaded (in different layer for example).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7913 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

Kae..pl 14 years ago
parent
commit
99746c72ec
17 changed files with 364 additions and 206 deletions
  1. 8 3
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ArmatureHelper.java
  2. 7 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java
  3. 98 167
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java
  4. 5 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java
  5. 5 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java
  6. 6 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/LightHelper.java
  7. 5 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java
  8. 5 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java
  9. 7 2
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java
  10. 5 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java
  11. 33 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java
  12. 5 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java
  13. 6 0
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java
  14. 9 8
      engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java
  15. 129 0
      engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java
  16. 11 0
      engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java
  17. 20 21
      engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java

+ 8 - 3
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ArmatureHelper.java

@@ -267,9 +267,9 @@ public class ArmatureHelper extends AbstractBlenderHelper {
     }
     }
 
 
     /**
     /**
-     * This method returns bone transformation data for the bone of a given name.
-     * @param boneName
-     *        the name of the bone
+     * This method returns bone transformation data for the bone of a given index.
+     * @param index
+     *        the index of the bone
      * @return bone's transformation data
      * @return bone's transformation data
      */
      */
     public BoneTransformationData getBoneTransformationDataRoot(int index) {
     public BoneTransformationData getBoneTransformationDataRoot(int index) {
@@ -368,4 +368,9 @@ public class ArmatureHelper extends AbstractBlenderHelper {
         bonesMap.clear();
         bonesMap.clear();
         boneDataRoots.clear();
         boneDataRoots.clear();
     }
     }
+    
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return true;
+    }
 }
 }

+ 7 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java

@@ -3,10 +3,12 @@ package com.jme3.scene.plugins.blender.helpers.v249;
 import java.util.logging.Level;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
+import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.renderer.Camera;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.plugins.blender.data.Structure;
 import com.jme3.scene.plugins.blender.data.Structure;
 import com.jme3.scene.plugins.blender.exception.BlenderFileException;
 import com.jme3.scene.plugins.blender.exception.BlenderFileException;
 import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
 import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.utils.DataRepository;
 
 
 /**
 /**
  * A class that is used in light calculations.
  * A class that is used in light calculations.
@@ -55,4 +57,9 @@ public class CameraHelper extends AbstractBlenderHelper {
         result.setFrustumPerspective(angle, aspect, clipsta, clipend);
         result.setFrustumPerspective(angle, aspect, clipsta, clipend);
         return result;
         return result;
     }
     }
+    
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0;
+    }
 }
 }

+ 98 - 167
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java

@@ -2,6 +2,7 @@ package com.jme3.scene.plugins.blender.helpers.v249;
 
 
 import java.nio.FloatBuffer;
 import java.nio.FloatBuffer;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -13,6 +14,7 @@ import com.jme3.animation.BoneTrack;
 import com.jme3.animation.Skeleton;
 import com.jme3.animation.Skeleton;
 import com.jme3.math.FastMath;
 import com.jme3.math.FastMath;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Quaternion;
+import com.jme3.math.Transform;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.Mesh;
@@ -22,6 +24,7 @@ import com.jme3.scene.VertexBuffer.Type;
 import com.jme3.scene.plugins.blender.data.Structure;
 import com.jme3.scene.plugins.blender.data.Structure;
 import com.jme3.scene.plugins.blender.exception.BlenderFileException;
 import com.jme3.scene.plugins.blender.exception.BlenderFileException;
 import com.jme3.scene.plugins.blender.structures.AbstractInfluenceFunction;
 import com.jme3.scene.plugins.blender.structures.AbstractInfluenceFunction;
+import com.jme3.scene.plugins.blender.structures.CalculationBone;
 import com.jme3.scene.plugins.blender.structures.Constraint;
 import com.jme3.scene.plugins.blender.structures.Constraint;
 import com.jme3.scene.plugins.blender.structures.Constraint.Space;
 import com.jme3.scene.plugins.blender.structures.Constraint.Space;
 import com.jme3.scene.plugins.blender.structures.ConstraintType;
 import com.jme3.scene.plugins.blender.structures.ConstraintType;
@@ -146,70 +149,89 @@ public class ConstraintHelper extends AbstractBlenderHelper {
 
 
 				@Override
 				@Override
 				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
 				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintStructure = constraint.getData();
-					this.validateConstraintType(constraintStructure);
-					/*Long boneOMA = constraint.getBoneOMA();
-                    //IK solver is only attached to bones
-                    Bone ownerBone = (Bone)dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
-
-                    //get the target point
-                    Object targetObject = this.getTarget(constraint, LoadedFeatureDataType.LOADED_FEATURE);
-                    Vector3f pt = null;//Point Target
-                    if(targetObject instanceof Bone) {
-                    pt = ((Bone)targetObject).getModelSpacePosition();
-                    } else if(targetObject instanceof Node) {
-                    pt = ((Node)targetObject).getWorldTranslation();
-                    } else if(targetObject instanceof Skeleton) {
-                    Structure armatureNodeStructure = (Structure)this.getTarget(constraint, LoadedFeatureDataType.LOADED_STRUCTURE);
-                    ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-                    Transform transform = objectHelper.getTransformation(armatureNodeStructure);
-                    pt = transform.getTranslation();
-                    } else {
-                    throw new IllegalStateException("Unknown target object type! Should be Node, Bone or Skeleton and there is: " + targetObject.getClass().getName());
-                    }
-                    //preparing data
-                    int maxIterations = ((Number)constraintStructure.getFieldValue("iterations")).intValue();
-                    CalculationBone[] bones = this.getBonesToCalculate(ownerBone, skeleton, boneAnimation);
-                    for(int i=0;i<bones.length;++i) {
-                    System.out.println(Arrays.toString(bones[i].track.getTranslations()));
-                    System.out.println(Arrays.toString(bones[i].track.getRotations()));
-                    System.out.println("===============================");
-                    }
-                    Quaternion rotation = new Quaternion();
-                    int maxFrames = bones[0].track.getTimes().length;//all tracks should have the same amount of frames
-
-                    for(int frame = 0; frame < maxFrames; ++frame) {
-                    float error = IK_SOLVER_ERROR;
-                    int iteration = 0;
-                    while(error >= IK_SOLVER_ERROR && iteration <= maxIterations) {
-                    //rotating the bones
-                    for(int i = 0; i < bones.length - 1; ++i) {
-                    Vector3f pe = bones[i].getEndPoint();
-                    Vector3f pc = bones[i + 1].getWorldTranslation().clone();
-
-                    Vector3f peSUBpc = pe.subtract(pc).normalizeLocal();
-                    Vector3f ptSUBpc = pt.subtract(pc).normalizeLocal();
-
-                    float theta = FastMath.acos(peSUBpc.dot(ptSUBpc));
-                    Vector3f direction = peSUBpc.cross(ptSUBpc).normalizeLocal();
-                    bones[i].rotate(rotation.fromAngleAxis(theta, direction), frame);
-                    }
-                    error = pt.subtract(bones[0].getEndPoint()).length();
-                    ++iteration;
-                    }
-                    System.out.println("error = " + error + "   iterations = " + iteration);
-                    }
-
-                    for(CalculationBone bone : bones) {
-                    bone.applyCalculatedTracks();
-                    }
-
-                    System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
-                    for(int i=0;i<bones.length;++i) {
-                    System.out.println(Arrays.toString(bones[i].track.getTranslations()));
-                    System.out.println(Arrays.toString(bones[i].track.getRotations()));
-                    System.out.println("===============================");
-                    }*/
+					try {
+						Structure constraintStructure = constraint.getData();
+						this.validateConstraintType(constraintStructure);
+						Long boneOMA = constraint.getBoneOMA();
+						// IK solver is only attached to bones
+						Bone ownerBone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
+
+						// get the target point
+						Object targetObject = this.getTarget(constraint, LoadedFeatureDataType.LOADED_FEATURE);
+						Vector3f pt = null;// Point Target
+						if (targetObject instanceof Bone) {
+							pt = ((Bone) targetObject).getModelSpacePosition();
+						} else if (targetObject instanceof Node) {
+							pt = ((Node) targetObject).getWorldTranslation();
+						} else if (targetObject instanceof Skeleton) {
+							Structure armatureNodeStructure = (Structure) this.getTarget(constraint, LoadedFeatureDataType.LOADED_STRUCTURE);
+							ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+							Transform transform = objectHelper.getTransformation(armatureNodeStructure, dataRepository);
+							pt = transform.getTranslation();
+						} else {
+							throw new IllegalStateException(
+									"Unknown target object type! Should be Node, Bone or Skeleton and there is: "
+									+ targetObject.getClass().getName());
+						}
+						
+						//fetching the owner's bone track
+//						BoneTrack ownerBoneTrack = null;
+//						int boneIndex = skeleton.getBoneIndex(ownerBone);
+//						for (int i = 0; i < boneAnimation.getTracks().length; ++i) {
+//							if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) {
+//								ownerBoneTrack = boneAnimation.getTracks()[i];
+//								break;
+//							}
+//						}
+//						int ownerBoneFramesCount = ownerBoneTrack==null ? 0 : ownerBoneTrack.getTimes().length;
+						
+						// preparing data
+						int maxIterations = ((Number) constraintStructure.getFieldValue("iterations")).intValue();
+						CalculationBone[] bones = this.getBonesToCalculate(ownerBone, skeleton, boneAnimation);
+//						for (int i = 0; i < bones.length; ++i) {
+//							System.out.println(Arrays.toString(bones[i].track.getTranslations()));
+//							System.out.println(Arrays.toString(bones[i].track.getRotations()));
+//							System.out.println("===============================");
+//						}
+						Quaternion rotation = new Quaternion();
+						//all tracks should have the same amount of frames
+						int framesCount = bones[0].getBoneFramesCount();
+						assert framesCount >=1;
+						for (int frame = 0; frame < framesCount; ++frame) {
+							float error = IK_SOLVER_ERROR;
+							int iteration = 0;
+							while (error >= IK_SOLVER_ERROR && iteration <= maxIterations) {
+								// rotating the bones
+								for (int i = 0; i < bones.length - 1; ++i) {
+									Vector3f pe = bones[i].getEndPoint();
+									Vector3f pc = bones[i + 1].getWorldTranslation().clone();
+
+									Vector3f peSUBpc = pe.subtract(pc).normalizeLocal();
+									Vector3f ptSUBpc = pt.subtract(pc).normalizeLocal();
+
+									float theta = FastMath.acos(peSUBpc.dot(ptSUBpc));
+									Vector3f direction = peSUBpc.cross(ptSUBpc).normalizeLocal();
+									bones[i].rotate(rotation.fromAngleAxis(theta, direction), frame);
+								}
+								error = pt.subtract(bones[0].getEndPoint()).length();
+								++iteration;
+							}
+							System.out.println("error = " + error + "   iterations = " + iteration);
+						}
+
+						for (CalculationBone bone : bones) {
+							bone.applyCalculatedTracks();
+						}
+
+//						System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+//						for (int i = 0; i < bones.length; ++i) {
+//							System.out.println(Arrays.toString(bones[i].track.getTranslations()));
+//							System.out.println(Arrays.toString(bones[i].track.getRotations()));
+//							System.out.println("===============================");
+//						}
+					} catch(BlenderFileException e) {
+						LOGGER.severe(e.getLocalizedMessage());
+					}
 				}
 				}
 
 
 				/**
 				/**
@@ -226,13 +248,14 @@ public class ConstraintHelper extends AbstractBlenderHelper {
 					List<CalculationBone> bonesList = new ArrayList<CalculationBone>();
 					List<CalculationBone> bonesList = new ArrayList<CalculationBone>();
 					Bone currentBone = bone;
 					Bone currentBone = bone;
 					do {
 					do {
-						int boneIndex = skeleton.getBoneIndex(currentBone);
-						for (int i = 0; i < boneAnimation.getTracks().length; ++i) {
-							if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) {
-								bonesList.add(new CalculationBone(currentBone, boneAnimation.getTracks()[i]));
-								break;
-							}
-						}
+						bonesList.add(new CalculationBone(currentBone, 1));
+//						int boneIndex = skeleton.getBoneIndex(currentBone);
+//						for (int i = 0; i < boneAnimation.getTracks().length; ++i) {
+//							if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) {
+//								bonesList.add(new CalculationBone(currentBone, boneAnimation.getTracks()[i]));
+//								break;
+//							}
+//						}
 						currentBone = currentBone.getParent();
 						currentBone = currentBone.getParent();
 					} while (currentBone != null);
 					} while (currentBone != null);
 					//attaching children
 					//attaching children
@@ -725,101 +748,9 @@ public class ConstraintHelper extends AbstractBlenderHelper {
 	public void clearState() {
 	public void clearState() {
 		constraints.clear();
 		constraints.clear();
 	}
 	}
-
-	/**
-	 * The purpose of this class is to imitate bone's movement when calculating inverse kinematics.
-	 * @author Marcin Roguski
-	 */
-	private static class CalculationBone extends Node {
-
-		/** The name of the bone. Only to be used in toString method. */
-		private String boneName;
-		/** The bone's tracks. Will be altered at the end of calculation process. */
-		private BoneTrack track;
-		/** The starting position of the bone. */
-		private Vector3f startTranslation;
-		/** The starting rotation of the bone. */
-		private Quaternion startRotation;
-		/** The starting scale of the bone. */
-		private Vector3f startScale;
-		private Vector3f[] translations;
-		private Quaternion[] rotations;
-		private Vector3f[] scales;
-
-		/**
-		 * Constructor. Stores the track, starting transformation and sets the transformation to the starting positions.
-		 * @param bone
-		 *        the bone this class will imitate
-		 * @param track
-		 *        the bone's tracks
-		 */
-		public CalculationBone(Bone bone, BoneTrack track) {
-			this.boneName = bone.getName();
-			this.track = track;
-			this.startRotation = bone.getModelSpaceRotation().clone();
-			this.startTranslation = bone.getModelSpacePosition().clone();
-			this.startScale = bone.getModelSpaceScale().clone();
-			this.translations = track.getTranslations();
-			this.rotations = track.getRotations();
-			this.scales = track.getScales();
-			this.reset();
-		}
-
-		/**
-		 * This method returns the end point of the bone. If the bone has parent it is calculated from the start point
-		 * of parent to the start point of this bone. If the bone doesn't have a parent the end location is considered
-		 * to be 1 point up along Y axis (scale is applied if set to != 1.0);
-		 * @return the end point of this bone
-		 */
-		//TODO: set to Z axis if user defined it this way
-		public Vector3f getEndPoint() {
-			if (this.getParent() == null) {
-				return new Vector3f(0, this.getLocalScale().y, 0);
-			} else {
-				Node parent = this.getParent();
-				return parent.getWorldTranslation().subtract(this.getWorldTranslation()).multLocal(this.getWorldScale());
-			}
-		}
-
-		/**
-		 * This method resets the calculation bone to the starting position.
-		 */
-		public void reset() {
-			this.setLocalTranslation(startTranslation);
-			this.setLocalRotation(startRotation);
-			this.setLocalScale(startScale);
-		}
-
-		@Override
-		public int attachChild(Spatial child) {
-			if (this.getChildren() != null && this.getChildren().size() > 1) {
-				throw new IllegalStateException(this.getClass().getName() + " class instance can only have one child!");
-			}
-			return super.attachChild(child);
-		}
-
-		public Spatial rotate(Quaternion rot, int frame) {
-			Spatial spatial = super.rotate(rot);
-			this.updateWorldTransforms();
-			if (this.getChildren() != null && this.getChildren().size() > 0) {
-				CalculationBone child = (CalculationBone) this.getChild(0);
-				child.updateWorldTransforms();
-			}
-			rotations[frame].set(this.getLocalRotation());
-			translations[frame].set(this.getLocalTranslation());
-			if (scales != null) {
-				scales[frame].set(this.getLocalScale());
-			}
-			return spatial;
-		}
-
-		public void applyCalculatedTracks() {
-			track.setKeyframes(track.getTimes(), translations, rotations);//TODO:scales
-		}
-
-		@Override
-		public String toString() {
-			return boneName + ": " + this.getLocalRotation() + " " + this.getLocalTranslation();
-		}
+	
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return true;
 	}
 	}
 }
 }

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java

@@ -599,4 +599,9 @@ public class CurvesHelper extends AbstractBlenderHelper {
             return new Vector3f(locArray.get(0).floatValue(), locArray.get(2).floatValue(), locArray.get(1).floatValue());
             return new Vector3f(locArray.get(0).floatValue(), locArray.get(2).floatValue(), locArray.get(1).floatValue());
         }
         }
     }
     }
+    
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return true;
+    }
 }
 }

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java

@@ -71,6 +71,11 @@ public class IpoHelper extends AbstractBlenderHelper {
         return new ConstIpo(constValue);
         return new ConstIpo(constValue);
     }
     }
 
 
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return true;
+    }
+    
     /**
     /**
      * Ipo constant curve. This is a curve with only one value and no specified type. This type of ipo cannot be used to
      * Ipo constant curve. This is a curve with only one value and no specified type. This type of ipo cannot be used to
      * calculate tracks. It should only be used to calculate single value for a given frame.
      * calculate tracks. It should only be used to calculate single value for a given frame.

+ 6 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/LightHelper.java

@@ -34,6 +34,7 @@ package com.jme3.scene.plugins.blender.helpers.v249;
 import java.util.logging.Level;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
+import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.light.DirectionalLight;
 import com.jme3.light.DirectionalLight;
 import com.jme3.light.Light;
 import com.jme3.light.Light;
 import com.jme3.light.PointLight;
 import com.jme3.light.PointLight;
@@ -97,4 +98,9 @@ public class LightHelper extends AbstractBlenderHelper {
         }
         }
         return result;
         return result;
     }
     }
+    
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0;
+    }
 }
 }

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java

@@ -685,6 +685,11 @@ public class MaterialHelper extends AbstractBlenderHelper {
 		}
 		}
 	}
 	}
 
 
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0;
+	}
+	
 	/**
 	/**
 	 * An interface used in calculating alpha mask during particles' texture calculations.
 	 * An interface used in calculating alpha mask during particles' texture calculations.
 	 * @author Marcin Roguski (Kaelthas)
 	 * @author Marcin Roguski (Kaelthas)

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java

@@ -605,4 +605,9 @@ public class MeshHelper extends AbstractBlenderHelper {
 		// mesh.setMaxNumWeights(maxWeightsPerVert);
 		// mesh.setMaxNumWeights(maxWeightsPerVert);
 		return maxWeightsPerVert;
 		return maxWeightsPerVert;
 	}
 	}
+	
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return true;
+	}
 }
 }

+ 7 - 2
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java

@@ -352,7 +352,7 @@ public class ModifierHelper extends AbstractBlenderHelper {
 
 
             //preparing the object's bone
             //preparing the object's bone
             ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
             ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-            Transform t = objectHelper.getTransformation(objectStructure);
+            Transform t = objectHelper.getTransformation(objectStructure, dataRepository);
             Bone bone = new Bone(null);
             Bone bone = new Bone(null);
             bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale());
             bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale());
 
 
@@ -545,7 +545,7 @@ public class ModifierHelper extends AbstractBlenderHelper {
             ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
             ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
             try {// we take the structure in case the object was not yet loaded
             try {// we take the structure in case the object was not yet loaded
                 Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository);
                 Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository);
-                Vector3f translation = objectHelper.getTransformation(offsetStructure).getTranslation();
+                Vector3f translation = objectHelper.getTransformation(offsetStructure, dataRepository).getTranslation();
                 objectOffset[0] = translation.x;
                 objectOffset[0] = translation.x;
                 objectOffset[1] = translation.y;
                 objectOffset[1] = translation.y;
                 objectOffset[2] = translation.z;
                 objectOffset[2] = translation.z;
@@ -754,4 +754,9 @@ public class ModifierHelper extends AbstractBlenderHelper {
         }
         }
         return new Skeleton(bones.toArray(new Bone[bones.size()]));
         return new Skeleton(bones.toArray(new Bone[bones.size()]));
     }
     }
+    
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return true;
+    }
 }
 }

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java

@@ -1529,6 +1529,11 @@ public class NoiseHelper extends AbstractBlenderHelper {
             return rx * q[0] + ry * q[1] + rz * q[2];
             return rx * q[0] + ry * q[1] + rz * q[2];
         }
         }
     }
     }
+    
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return true;
+    }
 
 
     /**
     /**
      * This interface is used for distance calculation classes. Distance metrics for voronoi. e parameter only used in
      * This interface is used for distance calculation classes. Distance metrics for voronoi. e parameter only used in

+ 33 - 5
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java

@@ -31,10 +31,13 @@
  */
  */
 package com.jme3.scene.plugins.blender.helpers.v249;
 package com.jme3.scene.plugins.blender.helpers.v249;
 
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 
 
+import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.light.DirectionalLight;
 import com.jme3.light.DirectionalLight;
 import com.jme3.light.Light;
 import com.jme3.light.Light;
 import com.jme3.light.PointLight;
 import com.jme3.light.PointLight;
@@ -77,6 +80,16 @@ public class ObjectHelper extends AbstractBlenderHelper {
 	protected static final int		OBJECT_TYPE_LATTICE			= 22;
 	protected static final int		OBJECT_TYPE_LATTICE			= 22;
 	protected static final int		OBJECT_TYPE_ARMATURE		= 25;
 	protected static final int		OBJECT_TYPE_ARMATURE		= 25;
 	
 	
+	/**
+	 * This collection contains types of features that are not visible to the user.
+	 * These will be loaded regardless the layer they reside in.
+	 */
+	protected static final Collection<Integer> invisibleTypes = new ArrayList<Integer>();
+	static {
+		invisibleTypes.add(OBJECT_TYPE_EMPTY);
+		invisibleTypes.add(OBJECT_TYPE_ARMATURE);
+	}
+	
 	/** This variable indicates if the Y asxis is the UP axis or not. */
 	/** This variable indicates if the Y asxis is the UP axis or not. */
 	protected boolean						fixUpAxis;
 	protected boolean						fixUpAxis;
 	/** Quaternion used to rotate data when Y is up axis. */
 	/** Quaternion used to rotate data when Y is up axis. */
@@ -149,7 +162,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
 			parent = this.toObject(parentStructure, dataRepository);
 			parent = this.toObject(parentStructure, dataRepository);
 		}
 		}
 
 
-		Transform t = objectHelper.getTransformation(objectStructure);
+		Transform t = objectHelper.getTransformation(objectStructure, dataRepository);
 		
 		
 		try {
 		try {
 			switch(type) {
 			switch(type) {
@@ -268,15 +281,23 @@ public class ObjectHelper extends AbstractBlenderHelper {
 	 * @return objects transformation relative to its parent
 	 * @return objects transformation relative to its parent
 	 */
 	 */
 	@SuppressWarnings("unchecked")
 	@SuppressWarnings("unchecked")
-	public Transform getTransformation(Structure objectStructure) {
+	public Transform getTransformation(Structure objectStructure, DataRepository dataRepository) {
 		//these are transformations in global space
 		//these are transformations in global space
 		DynamicArray<Number> loc = (DynamicArray<Number>)objectStructure.getFieldValue("loc");
 		DynamicArray<Number> loc = (DynamicArray<Number>)objectStructure.getFieldValue("loc");
 		DynamicArray<Number> size = (DynamicArray<Number>)objectStructure.getFieldValue("size");
 		DynamicArray<Number> size = (DynamicArray<Number>)objectStructure.getFieldValue("size");
 		DynamicArray<Number> rot = (DynamicArray<Number>)objectStructure.getFieldValue("rot");
 		DynamicArray<Number> rot = (DynamicArray<Number>)objectStructure.getFieldValue("rot");
 
 
 		//load parent inverse matrix
 		//load parent inverse matrix
-		Pointer parent = (Pointer) objectStructure.getFieldValue("parent");
-		Matrix4f parentInv = parent.isNull() ? Matrix4f.IDENTITY : this.getMatrix(objectStructure, "parentinv");
+		Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
+		Structure parent = null;
+		if(pParent.isNotNull()) {
+			try {
+				parent = pParent.fetchData(dataRepository.getInputStream()).get(0);
+			} catch (BlenderFileException e) {
+				LOGGER.log(Level.WARNING, "Cannot fetch parent for object! Reason: {0}", e.getLocalizedMessage());
+			}
+		}
+		Matrix4f parentInv = pParent.isNull() ? Matrix4f.IDENTITY : this.getMatrix(objectStructure, "parentinv");
 		
 		
 		//create the global matrix (without the scale)
 		//create the global matrix (without the scale)
 		Matrix4f globalMatrix = new Matrix4f();
 		Matrix4f globalMatrix = new Matrix4f();
@@ -296,7 +317,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
 									  size.get(2).floatValue() * scaleZ);
 									  size.get(2).floatValue() * scaleZ);
 		
 		
 		//the root object is transformed if the Y axis is UP
 		//the root object is transformed if the Y axis is UP
-		if(parent.isNull() && fixUpAxis) {
+		if(fixUpAxis && (pParent.isNull() || (parent!=null && !this.shouldBeLoaded(parent, dataRepository)))) {
 			float y = translation.y;
 			float y = translation.y;
 			translation.y = translation.z;
 			translation.y = translation.z;
 			translation.z = -y;
 			translation.z = -y;
@@ -343,4 +364,11 @@ public class ObjectHelper extends AbstractBlenderHelper {
 	public void clearState() {
 	public void clearState() {
 		fixUpAxis = false;
 		fixUpAxis = false;
 	}
 	}
+	
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		int lay = ((Number) structure.getFieldValue("lay")).intValue();
+        return ((lay & dataRepository.getBlenderKey().getLayersToLoad()) != 0
+                && (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.OBJECTS) != 0);
+	}
 }
 }

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java

@@ -187,4 +187,9 @@ public class ParticlesHelper extends AbstractBlenderHelper {
 		}
 		}
 		return result;
 		return result;
 	}
 	}
+	
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return true;
+	}
 }
 }

+ 6 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java

@@ -42,6 +42,7 @@ import java.util.logging.Logger;
 
 
 import com.jme3.asset.AssetNotFoundException;
 import com.jme3.asset.AssetNotFoundException;
 import com.jme3.asset.TextureKey;
 import com.jme3.asset.TextureKey;
+import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.math.FastMath;
 import com.jme3.math.FastMath;
 import com.jme3.scene.plugins.blender.data.FileBlockHeader;
 import com.jme3.scene.plugins.blender.data.FileBlockHeader;
 import com.jme3.scene.plugins.blender.data.Structure;
 import com.jme3.scene.plugins.blender.data.Structure;
@@ -1779,6 +1780,11 @@ public class TextureHelper extends AbstractBlenderHelper {
 			return result;
 			return result;
 		}
 		}
 	}
 	}
+	
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.TEXTURES) != 0;
+	}
 
 
 	/**
 	/**
 	 * Image types that can be loaded. AWT: png, jpg, jped or bmp TGA: tga DDS: DirectX image files
 	 * Image types that can be loaded. AWT: png, jpg, jped or bmp TGA: tga DDS: DirectX image files

+ 9 - 8
engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java

@@ -139,20 +139,21 @@ public abstract class AbstractInfluenceFunction {
      * @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted
      * @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted
      */
      */
     protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException {
     protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException {
-    	//TODO: load the feature through objectHelper, this way we are certain the object loads and has
+    	//load the feature through objectHelper, this way we are certain the object loads and has
     	//his own constraints applied to traces
     	//his own constraints applied to traces
     	ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
     	ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-    	//subtarget goes first
+    	//always load the target first
+    	Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
+        Structure objectStructure = dataRepository.getFileBlock(targetOMA).getStructure(dataRepository);
+        Object result = objectHelper.toObject(objectStructure, dataRepository);
+    	
+    	//subtarget should be loaded alogn with target
     	Object subtarget = constraint.getData().getFieldValue("subtarget");
     	Object subtarget = constraint.getData().getFieldValue("subtarget");
     	String subtargetName = subtarget==null ? null : subtarget.toString();
     	String subtargetName = subtarget==null ? null : subtarget.toString();
         if (subtargetName!=null && subtargetName.length() > 0) {
         if (subtargetName!=null && subtargetName.length() > 0) {
-        	//TODO: what if it is not yet loaded ???
-            return dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
+            result = dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
         }
         }
-        //and now use the target
-        Long targetOMA = ((Pointer) constraint.getData().getFieldValue("target")).getOldMemoryAddress();
-        Structure objectStructure = dataRepository.getFileBlock(targetOMA).getStructure(dataRepository);
-        return objectHelper.toObject(objectStructure, dataRepository);
+        return result;
     }
     }
 
 
     /**
     /**

+ 129 - 0
engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java

@@ -0,0 +1,129 @@
+package com.jme3.scene.plugins.blender.structures;
+
+import java.util.Arrays;
+
+import com.jme3.animation.Bone;
+import com.jme3.animation.BoneTrack;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+
+/**
+ * The purpose of this class is to imitate bone's movement when calculating inverse kinematics.
+ * @author Marcin Roguski
+ */
+public class CalculationBone extends Node {
+	private Bone bone;
+	/** The bone's tracks. Will be altered at the end of calculation process. */
+	private BoneTrack track;
+	/** The starting position of the bone. */
+	private Vector3f startTranslation;
+	/** The starting rotation of the bone. */
+	private Quaternion startRotation;
+	/** The starting scale of the bone. */
+	private Vector3f startScale;
+	private Vector3f[] translations;
+	private Quaternion[] rotations;
+	private Vector3f[] scales;
+
+	public CalculationBone(Bone bone, int boneFramesCount) {
+		this.bone = bone;
+		this.startRotation = bone.getModelSpaceRotation().clone();
+		this.startTranslation = bone.getModelSpacePosition().clone();
+		this.startScale = bone.getModelSpaceScale().clone();
+		this.reset();
+		if(boneFramesCount > 0) {
+			this.translations = new Vector3f[boneFramesCount];
+			this.rotations = new Quaternion[boneFramesCount];
+			this.scales = new Vector3f[boneFramesCount];
+			
+			Arrays.fill(this.translations, 0, boneFramesCount, this.startTranslation);
+			Arrays.fill(this.rotations, 0, boneFramesCount, this.startRotation);
+			Arrays.fill(this.scales, 0, boneFramesCount, this.startScale);
+		}
+	}
+	
+	/**
+	 * Constructor. Stores the track, starting transformation and sets the transformation to the starting positions.
+	 * @param bone
+	 *        the bone this class will imitate
+	 * @param track
+	 *        the bone's tracks
+	 */
+	public CalculationBone(Bone bone, BoneTrack track) {
+		this(bone, 0);
+		this.track = track;
+		this.translations = track.getTranslations();
+		this.rotations = track.getRotations();
+		this.scales = track.getScales();
+	}
+
+	public int getBoneFramesCount() {
+		return this.translations==null ? 0 : this.translations.length;
+	}
+	
+	/**
+	 * This method returns the end point of the bone. If the bone has parent it is calculated from the start point
+	 * of parent to the start point of this bone. If the bone doesn't have a parent the end location is considered
+	 * to be 1 point up along Y axis (scale is applied if set to != 1.0);
+	 * @return the end point of this bone
+	 */
+	//TODO: set to Z axis if user defined it this way
+	public Vector3f getEndPoint() {
+		if (this.getParent() == null) {
+			return new Vector3f(0, this.getLocalScale().y, 0);
+		} else {
+			Node parent = this.getParent();
+			return parent.getWorldTranslation().subtract(this.getWorldTranslation()).multLocal(this.getWorldScale());
+		}
+	}
+
+	/**
+	 * This method resets the calculation bone to the starting position.
+	 */
+	public void reset() {
+		this.setLocalTranslation(startTranslation);
+		this.setLocalRotation(startRotation);
+		this.setLocalScale(startScale);
+	}
+
+	@Override
+	public int attachChild(Spatial child) {
+		if (this.getChildren() != null && this.getChildren().size() > 1) {
+			throw new IllegalStateException(this.getClass().getName() + " class instance can only have one child!");
+		}
+		return super.attachChild(child);
+	}
+
+	public Spatial rotate(Quaternion rot, int frame) {
+		Spatial spatial = super.rotate(rot);
+		this.updateWorldTransforms();
+		if (this.getChildren() != null && this.getChildren().size() > 0) {
+			CalculationBone child = (CalculationBone) this.getChild(0);
+			child.updateWorldTransforms();
+		}
+		rotations[frame].set(this.getLocalRotation());
+		translations[frame].set(this.getLocalTranslation());
+		if (scales != null) {
+			scales[frame].set(this.getLocalScale());
+		}
+		return spatial;
+	}
+
+	public void applyCalculatedTracks() {
+		if(track != null) {
+			track.setKeyframes(track.getTimes(), translations, rotations);//TODO:scales
+		} else {
+			bone.setUserControl(true);
+			bone.setUserTransforms(translations[0], rotations[0], scales[0]);
+			bone.setUserControl(false);
+			bone.updateWorldVectors();
+		}
+	}
+
+	@Override
+	public String toString() {
+		return bone.getName() + ": " + this.getLocalRotation() + " " + this.getLocalTranslation();
+	}
+}

+ 11 - 0
engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java

@@ -127,4 +127,15 @@ public abstract class AbstractBlenderHelper {
 		}
 		}
 		return properties;
 		return properties;
 	}
 	}
+	
+	/**
+	 * This method analyzes the given structure and the data contained within
+	 * data repository and decides if the feature should be loaded.
+	 * @param structure
+	 *        structure to be analyzed
+	 * @param dataRepository
+	 *        the data repository
+	 * @return <b>true</b> if the feature should be loaded and false otherwise
+	 */
+	public abstract boolean shouldBeLoaded(Structure structure, DataRepository dataRepository);
 }
 }

+ 20 - 21
engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java

@@ -32,7 +32,6 @@
 package com.jme3.scene.plugins.blender.utils;
 package com.jme3.scene.plugins.blender.utils;
 
 
 import java.util.List;
 import java.util.List;
-import java.util.logging.Logger;
 
 
 import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.asset.BlenderKey.WorldData;
 import com.jme3.asset.BlenderKey.WorldData;
@@ -57,7 +56,6 @@ import com.jme3.scene.plugins.blender.helpers.ObjectHelper;
  */
  */
 public class JmeConverter implements BlenderConverter<Node, Camera, Light, Object, List<Geometry>, Material> {
 public class JmeConverter implements BlenderConverter<Node, Camera, Light, Object, List<Geometry>, Material> {
 
 
-    private static final Logger LOGGER = Logger.getLogger(JmeConverter.class.getName());
     private final DataRepository dataRepository;
     private final DataRepository dataRepository;
 
 
     /**
     /**
@@ -104,46 +102,47 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
 
 
     @Override
     @Override
     public Camera toCamera(Structure structure) throws BlenderFileException {
     public Camera toCamera(Structure structure) throws BlenderFileException {
-        if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) == 0) {
-            return null;
+    	CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
+        if (cameraHelper.shouldBeLoaded(structure, dataRepository)) {
+        	return cameraHelper.toCamera(structure);
         }
         }
-        CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
-        return cameraHelper.toCamera(structure);
+        return null;
     }
     }
 
 
     @Override
     @Override
     public Light toLight(Structure structure) throws BlenderFileException {
     public Light toLight(Structure structure) throws BlenderFileException {
-        if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.LIGHTS) == 0) {
-            return null;
+    	LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
+        if (lightHelper.shouldBeLoaded(structure, dataRepository)) {
+            return lightHelper.toLight(structure, dataRepository);
         }
         }
-        LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
-        return lightHelper.toLight(structure, dataRepository);
+        return null;
     }
     }
 
 
     @Override
     @Override
     public Object toObject(Structure structure) throws BlenderFileException {
     public Object toObject(Structure structure) throws BlenderFileException {
-        int lay = ((Number) structure.getFieldValue("lay")).intValue();
-        if ((lay & dataRepository.getBlenderKey().getLayersToLoad()) == 0
-                || (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.OBJECTS) == 0) {
-            return null;
-        }
         ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
         ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-        return objectHelper.toObject(structure, dataRepository);
+        if(objectHelper.shouldBeLoaded(structure, dataRepository)) {
+        	return objectHelper.toObject(structure, dataRepository);
+        }
+        return null;
     }
     }
 
 
     @Override
     @Override
     public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
     public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
         MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class);
         MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class);
-        return meshHelper.toMesh(structure, dataRepository);
+        if(meshHelper.shouldBeLoaded(structure, dataRepository)) {
+        	return meshHelper.toMesh(structure, dataRepository);
+        }
+        return null;
     }
     }
 
 
     @Override
     @Override
     public Material toMaterial(Structure structure) throws BlenderFileException {
     public Material toMaterial(Structure structure) throws BlenderFileException {
-        if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) == 0) {
-            return null;
+    	MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
+        if (materialHelper.shouldBeLoaded(structure, dataRepository)) {
+            return materialHelper.toMaterial(structure, dataRepository);
         }
         }
-        MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
-        return materialHelper.toMaterial(structure, dataRepository);
+        return null;
     }
     }
 
 
     /**
     /**