Ver Fonte

Large blender importer refactoring:
- bleder features separated between different packages
- refactoring of modifier system (each modifier now in a separate class)
- refactoring of constraints system (each constraint now in a separate class)
- no converter interface
- every helper supports versions 2.49 and 2.5+.

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

Kae..pl há 14 anos atrás
pai
commit
1e7b7860fe
80 ficheiros alterados com 3448 adições e 3108 exclusões
  1. 5 4
      engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java
  2. 16 20
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
  3. 15 19
      engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java
  4. 41 12
      engine/src/blender/com/jme3/scene/plugins/blender/DataRepository.java
  5. 9 15
      engine/src/blender/com/jme3/scene/plugins/blender/JmeConverter.java
  6. 132 56
      engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java
  7. 2 2
      engine/src/blender/com/jme3/scene/plugins/blender/animations/CalculationBone.java
  8. 2 1
      engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java
  9. 8 9
      engine/src/blender/com/jme3/scene/plugins/blender/animations/IpoHelper.java
  10. 118 0
      engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java
  11. 247 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java
  12. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintAction.java
  13. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintChildOf.java
  14. 51 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintClampTo.java
  15. 84 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java
  16. 78 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFactory.java
  17. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFollowPath.java
  18. 140 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java
  19. 170 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintInverseKinematics.java
  20. 87 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLike.java
  21. 98 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLimit.java
  22. 51 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLockTrack.java
  23. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintMinMax.java
  24. 44 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintNull.java
  25. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPython.java
  26. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRigidBodyJoint.java
  27. 88 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLike.java
  28. 95 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java
  29. 100 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintShrinkWrap.java
  30. 74 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSizeLike.java
  31. 98 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSizeLimit.java
  32. 51 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintStretchTo.java
  33. 50 0
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransform.java
  34. 1 1
      engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintType.java
  35. 3 3
      engine/src/blender/com/jme3/scene/plugins/blender/curves/BezierCurve.java
  36. 13 12
      engine/src/blender/com/jme3/scene/plugins/blender/curves/CurvesHelper.java
  37. 1 1
      engine/src/blender/com/jme3/scene/plugins/blender/exceptions/BlenderFileException.java
  38. 2 2
      engine/src/blender/com/jme3/scene/plugins/blender/file/BlenderInputStream.java
  39. 3 4
      engine/src/blender/com/jme3/scene/plugins/blender/file/DnaBlockData.java
  40. 2 2
      engine/src/blender/com/jme3/scene/plugins/blender/file/DynamicArray.java
  41. 4 7
      engine/src/blender/com/jme3/scene/plugins/blender/file/Field.java
  42. 3 4
      engine/src/blender/com/jme3/scene/plugins/blender/file/FileBlockHeader.java
  43. 3 4
      engine/src/blender/com/jme3/scene/plugins/blender/file/Pointer.java
  44. 3 5
      engine/src/blender/com/jme3/scene/plugins/blender/file/Structure.java
  45. 0 132
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/ArmatureHelper.java
  46. 0 52
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/CameraHelper.java
  47. 0 38
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/ConstraintHelper.java
  48. 0 18
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/CurvesHelper.java
  49. 0 19
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/IpoHelper.java
  50. 0 49
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/LightHelper.java
  51. 0 45
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/MaterialHelper.java
  52. 0 49
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/MeshHelper.java
  53. 0 49
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/ModifierHelper.java
  54. 0 52
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/NoiseHelper.java
  55. 0 49
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/ObjectHelper.java
  56. 0 18
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/ParticlesHelper.java
  57. 0 84
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/TextureHelper.java
  58. 0 65
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java
  59. 0 756
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java
  60. 0 762
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java
  61. 6 6
      engine/src/blender/com/jme3/scene/plugins/blender/lights/LightHelper.java
  62. 9 8
      engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java
  63. 13 10
      engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
  64. 216 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java
  65. 244 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java
  66. 170 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java
  67. 67 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java
  68. 113 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ModifierHelper.java
  69. 122 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java
  70. 99 0
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java
  71. 21 18
      engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java
  72. 7 7
      engine/src/blender/com/jme3/scene/plugins/blender/objects/Properties.java
  73. 7 7
      engine/src/blender/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java
  74. 0 230
      engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java
  75. 0 162
      engine/src/blender/com/jme3/scene/plugins/blender/structures/Constraint.java
  76. 0 68
      engine/src/blender/com/jme3/scene/plugins/blender/structures/Modifier.java
  77. 18 19
      engine/src/blender/com/jme3/scene/plugins/blender/textures/NoiseGenerator.java
  78. 44 43
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  79. 0 0
      engine/src/blender/com/jme3/scene/plugins/blender/textures/noiseconstants.dat
  80. 0 110
      engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderConverter.java

+ 5 - 4
engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java

@@ -29,14 +29,15 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.utils;
+package com.jme3.scene.plugins.blender;
 
 import java.nio.FloatBuffer;
 import java.util.List;
 
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.Properties;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.objects.Properties;
 import com.jme3.util.BufferUtils;
 
 /**

+ 16 - 20
engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java

@@ -47,25 +47,22 @@ import com.jme3.asset.ModelKey;
 import com.jme3.light.Light;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.helpers.ArmatureHelper;
-import com.jme3.scene.plugins.blender.helpers.CameraHelper;
-import com.jme3.scene.plugins.blender.helpers.ConstraintHelper;
-import com.jme3.scene.plugins.blender.helpers.CurvesHelper;
-import com.jme3.scene.plugins.blender.helpers.IpoHelper;
-import com.jme3.scene.plugins.blender.helpers.LightHelper;
-import com.jme3.scene.plugins.blender.helpers.MaterialHelper;
-import com.jme3.scene.plugins.blender.helpers.MeshHelper;
-import com.jme3.scene.plugins.blender.helpers.ModifierHelper;
-import com.jme3.scene.plugins.blender.helpers.NoiseHelper;
-import com.jme3.scene.plugins.blender.helpers.ObjectHelper;
-import com.jme3.scene.plugins.blender.helpers.ParticlesHelper;
-import com.jme3.scene.plugins.blender.helpers.TextureHelper;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.JmeConverter;
+import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
+import com.jme3.scene.plugins.blender.animations.IpoHelper;
+import com.jme3.scene.plugins.blender.cameras.CameraHelper;
+import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
+import com.jme3.scene.plugins.blender.curves.CurvesHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.lights.LightHelper;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.scene.plugins.blender.meshes.MeshHelper;
+import com.jme3.scene.plugins.blender.modifiers.ModifierHelper;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+import com.jme3.scene.plugins.blender.particles.ParticlesHelper;
+import com.jme3.scene.plugins.blender.textures.TextureHelper;
 
 /**
  * This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures.
@@ -111,7 +108,6 @@ public class BlenderLoader implements AssetLoader {
             dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber()));
             dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository));
             dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber()));
-            dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber()));
             dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber()));
 
             //setting additional data to helpers

+ 15 - 19
engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java

@@ -45,24 +45,21 @@ import com.jme3.asset.BlenderKey.LoadingResults;
 import com.jme3.asset.ModelKey;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.helpers.ArmatureHelper;
-import com.jme3.scene.plugins.blender.helpers.CameraHelper;
-import com.jme3.scene.plugins.blender.helpers.ConstraintHelper;
-import com.jme3.scene.plugins.blender.helpers.CurvesHelper;
-import com.jme3.scene.plugins.blender.helpers.IpoHelper;
-import com.jme3.scene.plugins.blender.helpers.LightHelper;
-import com.jme3.scene.plugins.blender.helpers.MaterialHelper;
-import com.jme3.scene.plugins.blender.helpers.MeshHelper;
-import com.jme3.scene.plugins.blender.helpers.ModifierHelper;
-import com.jme3.scene.plugins.blender.helpers.NoiseHelper;
-import com.jme3.scene.plugins.blender.helpers.ObjectHelper;
-import com.jme3.scene.plugins.blender.helpers.ParticlesHelper;
-import com.jme3.scene.plugins.blender.helpers.TextureHelper;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.JmeConverter;
+import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
+import com.jme3.scene.plugins.blender.animations.IpoHelper;
+import com.jme3.scene.plugins.blender.cameras.CameraHelper;
+import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
+import com.jme3.scene.plugins.blender.curves.CurvesHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.lights.LightHelper;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.scene.plugins.blender.meshes.MeshHelper;
+import com.jme3.scene.plugins.blender.modifiers.ModifierHelper;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+import com.jme3.scene.plugins.blender.particles.ParticlesHelper;
+import com.jme3.scene.plugins.blender.textures.TextureHelper;
 
 /**
  * This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures.
@@ -104,7 +101,6 @@ public class BlenderModelLoader implements AssetLoader {
             dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber()));
             dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository));
             dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber()));
-            dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber()));
             dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber()));
 
             //setting additional data to helpers

+ 41 - 12
engine/src/blender/com/jme3/scene/plugins/blender/utils/DataRepository.java → engine/src/blender/com/jme3/scene/plugins/blender/DataRepository.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.utils;
+package com.jme3.scene.plugins.blender;
 
 import java.util.ArrayList;
 import java.util.EmptyStackException;
@@ -42,11 +42,13 @@ import com.jme3.asset.AssetManager;
 import com.jme3.asset.BlenderKey;
 import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
-import com.jme3.scene.plugins.blender.data.DnaBlockData;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.structures.Ipo;
-import com.jme3.scene.plugins.blender.structures.Modifier;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.constraints.Constraint;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.DnaBlockData;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.modifiers.Modifier;
 
 /**
  * The class that stores temporary data and manages it during loading the belnd file. This class is intended to be used
@@ -84,6 +86,8 @@ public class DataRepository {
     private Map<Long, Ipo> loadedIpos = new HashMap<Long, Ipo>();
     /** A list of modifiers for the specified object. */
     protected Map<Long, List<Modifier>> modifiers = new HashMap<Long, List<Modifier>>();
+    /** A list of constraints for the specified object. */
+    protected Map<Long, List<Constraint>> constraints = new HashMap<Long, List<Constraint>>();
     /** A map og helpers that perform loading. */
     private Map<String, AbstractBlenderHelper> helpers = new HashMap<String, AbstractBlenderHelper>();
 
@@ -330,18 +334,16 @@ public class DataRepository {
      * This method adds a new modifier to the list.
      * @param ownerOMA
      *        the owner's old memory address
-     * @param modifierType
-     *        the type of the modifier
-     * @param loadedModifier
-     *        the loaded modifier object
+     * @param modifier
+     * 		  the object's modifier
      */
-    public void addModifier(Long ownerOMA, String modifierType, Object loadedModifier, Object additionalModifierData) {
+    public void addModifier(Long ownerOMA, Modifier modifier) {
         List<Modifier> objectModifiers = this.modifiers.get(ownerOMA);
         if (objectModifiers == null) {
             objectModifiers = new ArrayList<Modifier>();
             this.modifiers.put(ownerOMA, objectModifiers);
         }
-        objectModifiers.add(new Modifier(modifierType, loadedModifier, additionalModifierData));
+        objectModifiers.add(modifier);
     }
 
     /**
@@ -365,6 +367,33 @@ public class DataRepository {
         }
         return result;
     }
+    
+    /**
+     * This method adds a new modifier to the list.
+     * @param ownerOMA
+     *        the owner's old memory address
+     * @param constraints
+     * 		  the object's constraints
+     */
+    public void addConstraints(Long ownerOMA, List<Constraint> constraints) {
+        List<Constraint> objectConstraints = this.constraints.get(ownerOMA);
+        if (objectConstraints == null) {
+            objectConstraints = new ArrayList<Constraint>();
+            this.constraints.put(ownerOMA, objectConstraints);
+        }
+        objectConstraints.addAll(constraints);
+    }
+
+    /**
+     * This method returns constraints for the object specified by its old memory address. If no
+     * modifiers are found - <b>null</b> is returned.
+     * @param objectOMA
+     *        object's old memory address
+     * @return the list of object's modifiers or null
+     */
+    public List<Constraint> getConstraints(Long objectOMA) {
+    	return constraints.get(objectOMA);
+    }
 
     /**
      * This metod returns the default material.

+ 9 - 15
engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java → engine/src/blender/com/jme3/scene/plugins/blender/JmeConverter.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.utils;
+package com.jme3.scene.plugins.blender;
 
 import java.util.List;
 
@@ -42,19 +42,19 @@ import com.jme3.math.ColorRGBA;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.helpers.CameraHelper;
-import com.jme3.scene.plugins.blender.helpers.LightHelper;
-import com.jme3.scene.plugins.blender.helpers.MaterialHelper;
-import com.jme3.scene.plugins.blender.helpers.MeshHelper;
-import com.jme3.scene.plugins.blender.helpers.ObjectHelper;
+import com.jme3.scene.plugins.blender.cameras.CameraHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.lights.LightHelper;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.scene.plugins.blender.meshes.MeshHelper;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
 
 /**
  * This class converts blender file blocks into jMonkeyEngine data structures.
  * @author Marcin Roguski
  */
-public class JmeConverter implements BlenderConverter<Node, Camera, Light, Object, List<Geometry>, Material> {
+/*package*/ class JmeConverter {
 
     private final DataRepository dataRepository;
 
@@ -84,7 +84,6 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
         this.dataRepository = dataRepository;
     }
 
-    @Override
     public Node toScene(Structure structure) {//TODO: poprawny import sceny
         if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.SCENES) == 0) {
             return null;
@@ -100,7 +99,6 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
         return new Node(sceneName);
     }
 
-    @Override
     public Camera toCamera(Structure structure) throws BlenderFileException {
     	CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
         if (cameraHelper.shouldBeLoaded(structure, dataRepository)) {
@@ -109,7 +107,6 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
         return null;
     }
 
-    @Override
     public Light toLight(Structure structure) throws BlenderFileException {
     	LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
         if (lightHelper.shouldBeLoaded(structure, dataRepository)) {
@@ -118,7 +115,6 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
         return null;
     }
 
-    @Override
     public Object toObject(Structure structure) throws BlenderFileException {
         ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
         if(objectHelper.shouldBeLoaded(structure, dataRepository)) {
@@ -127,7 +123,6 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
         return null;
     }
 
-    @Override
     public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
         MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class);
         if(meshHelper.shouldBeLoaded(structure, dataRepository)) {
@@ -136,7 +131,6 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
         return null;
     }
 
-    @Override
     public Material toMaterial(Structure structure) throws BlenderFileException {
     	MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
         if (materialHelper.shouldBeLoaded(structure, dataRepository)) {

+ 132 - 56
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ArmatureHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.animations;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -47,13 +47,15 @@ import com.jme3.math.Vector3f;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.Ipo;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.curves.BezierCurve;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
 
 /**
  * This class defines the methods to calculate certain aspects of animation and armature functionalities.
@@ -62,15 +64,6 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
 public class ArmatureHelper extends AbstractBlenderHelper {
 
     private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName());
-    /**
-     * The map of the bones. Maps a bone name to its index in the armature. Should be cleared after the object had been
-     * read. TODO: probably bones can have identical names in different armatures
-     */
-    protected Map<String, Integer> bonesMap = new HashMap<String, Integer>();
-    /** A map of bones and their old memory addresses. */
-    protected Map<Bone, Long> bonesOMAs = new HashMap<Bone, Long>();
-    /** This list contains bones hierarchy and their matrices. It is later converted into jme bones. */
-    protected List<BoneTransformationData> boneDataRoots = new ArrayList<BoneTransformationData>();
 
     /**
      * This constructor parses the given blender version and stores the result. Some functionalities may differ in
@@ -82,6 +75,16 @@ public class ArmatureHelper extends AbstractBlenderHelper {
         super(blenderVersion);
     }
 
+    /**
+     * The map of the bones. Maps a bone name to its index in the armature. Should be cleared after the object had been
+     * read. TODO: probably bones can have identical names in different armatures
+     */
+    protected Map<String, Integer> bonesMap = new HashMap<String, Integer>();
+    /** A map of bones and their old memory addresses. */
+    protected Map<Bone, Long> bonesOMAs = new HashMap<Bone, Long>();
+    /** This list contains bones hierarchy and their matrices. It is later converted into jme bones. */
+    protected List<BoneTransformationData> boneDataRoots = new ArrayList<BoneTransformationData>();
+
     /**
      * This method returns the old memory address of a bone. If the bone does not exist in the blend file - zero is
      * returned.
@@ -145,45 +148,6 @@ public class ArmatureHelper extends AbstractBlenderHelper {
         return result;
     }
 
-    /**
-     * This method reads the tracks of the armature object.
-     * @param actionStructure
-     * @param dataRepository
-     *        the data repository
-     * @param objectName
-     *        the name of animation owner
-     * @param animationName
-     *        the name of the animation
-     * @return a list of tracks for the armature
-     * @throws BlenderFileException
-     *         this exception is thrown when the blender file is somehow corrupted
-     */
-    public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
-        LOGGER.log(Level.INFO, "Getting tracks!");
-        IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
-        int fps = dataRepository.getBlenderKey().getFps();
-        int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
-        Structure chanbase = (Structure) actionStructure.getFieldValue("chanbase");
-        List<Structure> actionChannels = chanbase.evaluateListBase(dataRepository);//bActionChannel
-        if (actionChannels != null && actionChannels.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
-            throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
-        }
-        List<BoneTrack> tracks = new ArrayList<BoneTrack>();
-        for (Structure bActionChannel : actionChannels) {
-            String name = bActionChannel.getFieldValue("name").toString();
-            Integer boneIndex = bonesMap.get(name);
-            if (boneIndex != null) {
-                Pointer p = (Pointer) bActionChannel.getFieldValue("ipo");
-                if (p.isNotNull()) {
-                    Structure ipoStructure = p.fetchData(dataRepository.getInputStream()).get(0);
-                    Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository);
-                    tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
-                }
-            }
-        }
-        return tracks.toArray(new BoneTrack[tracks.size()]);
-    }
-
     /**
      * This bone returns transformation matrix of the bone that is relative to
      * its armature object.
@@ -373,4 +337,116 @@ public class ArmatureHelper extends AbstractBlenderHelper {
     public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
     	return true;
     }
+    
+    public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
+    	if (blenderVersion < 250) {
+            return this.getTracks250(actionStructure, dataRepository, objectName, animationName);
+        } else {
+        	return this.getTracks249(actionStructure, dataRepository, objectName, animationName);
+        }
+    }
+    
+    private BoneTrack[] getTracks250(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
+        LOGGER.log(Level.INFO, "Getting tracks!");
+        int fps = dataRepository.getBlenderKey().getFps();
+        int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
+        Structure groups = (Structure) actionStructure.getFieldValue("groups");
+        List<Structure> actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup
+        if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
+            throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
+        }
+
+        List<BoneTrack> tracks = new ArrayList<BoneTrack>();
+        for (Structure actionGroup : actionGroups) {
+            String name = actionGroup.getFieldValue("name").toString();
+            Integer boneIndex = bonesMap.get(name);
+            if (boneIndex != null) {
+                List<Structure> channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository);
+                BezierCurve[] bezierCurves = new BezierCurve[channels.size()];
+                int channelCounter = 0;
+                for (Structure c : channels) {
+                    //reading rna path first
+                    BlenderInputStream bis = dataRepository.getInputStream();
+                    int currentPosition = bis.getPosition();
+                    Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path");
+                    FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress());
+                    bis.setPosition(dataFileBlock.getBlockPosition());
+                    String rnaPath = bis.readString();
+                    bis.setPosition(currentPosition);
+                    int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue();
+                    int type = this.getCurveType(rnaPath, arrayIndex);
+
+                    Pointer pBezTriple = (Pointer) c.getFieldValue("bezt");
+                    List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
+                    bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2);
+                }
+
+                Ipo ipo = new Ipo(bezierCurves);
+                tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
+            }
+        }
+        return tracks.toArray(new BoneTrack[tracks.size()]);
+    }
+    
+    private BoneTrack[] getTracks249(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
+        LOGGER.log(Level.INFO, "Getting tracks!");
+        int fps = dataRepository.getBlenderKey().getFps();
+        int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
+        Structure groups = (Structure) actionStructure.getFieldValue("groups");
+        List<Structure> actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup
+        if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
+            throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
+        }
+
+        List<BoneTrack> tracks = new ArrayList<BoneTrack>();
+        for (Structure actionGroup : actionGroups) {
+            String name = actionGroup.getFieldValue("name").toString();
+            Integer boneIndex = bonesMap.get(name);
+            if (boneIndex != null) {
+                List<Structure> channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository);
+                BezierCurve[] bezierCurves = new BezierCurve[channels.size()];
+                int channelCounter = 0;
+                for (Structure c : channels) {
+                    //reading rna path first
+                    BlenderInputStream bis = dataRepository.getInputStream();
+                    int currentPosition = bis.getPosition();
+                    Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path");
+                    FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress());
+                    bis.setPosition(dataFileBlock.getBlockPosition());
+                    String rnaPath = bis.readString();
+                    bis.setPosition(currentPosition);
+                    int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue();
+                    int type = this.getCurveType(rnaPath, arrayIndex);
+
+                    Pointer pBezTriple = (Pointer) c.getFieldValue("bezt");
+                    List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
+                    bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2);
+                }
+
+                Ipo ipo = new Ipo(bezierCurves);
+                tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
+            }
+        }
+        return tracks.toArray(new BoneTrack[tracks.size()]);
+    }
+
+    /**
+     * This method parses the information stored inside the curve rna path and returns the proper type
+     * of the curve.
+     * @param rnaPath the curve's rna path
+     * @param arrayIndex the array index of the stored data
+     * @return the type of the curve
+     */
+    protected int getCurveType(String rnaPath, int arrayIndex) {
+        if (rnaPath.endsWith(".location")) {
+            return Ipo.AC_LOC_X + arrayIndex;
+        }
+        if (rnaPath.endsWith(".rotation_quaternion")) {
+            return Ipo.AC_QUAT_W + arrayIndex;
+        }
+        if (rnaPath.endsWith(".scale")) {
+            return Ipo.AC_SIZE_X + arrayIndex;
+        }
+        throw new IllegalStateException("Unknown curve rna path: " + rnaPath);
+    }
 }

+ 2 - 2
engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java → engine/src/blender/com/jme3/scene/plugins/blender/animations/CalculationBone.java

@@ -1,4 +1,4 @@
-package com.jme3.scene.plugins.blender.structures;
+package com.jme3.scene.plugins.blender.animations;
 
 import java.util.Arrays;
 
@@ -11,7 +11,7 @@ import com.jme3.scene.Spatial;
 
 /**
  * The purpose of this class is to imitate bone's movement when calculating inverse kinematics.
- * @author Marcin Roguski
+ * @author Marcin Roguski (Kaelthas)
  */
 public class CalculationBone extends Node {
 	private Bone bone;

+ 2 - 1
engine/src/blender/com/jme3/scene/plugins/blender/structures/Ipo.java → engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java

@@ -1,8 +1,9 @@
-package com.jme3.scene.plugins.blender.structures;
+package com.jme3.scene.plugins.blender.animations;
 
 import com.jme3.animation.BoneTrack;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
+import com.jme3.scene.plugins.blender.curves.BezierCurve;
 
 /**
  * This class is used to calculate bezier curves value for the given frames. The Ipo (interpolation object) consists

+ 8 - 9
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/animations/IpoHelper.java

@@ -1,15 +1,14 @@
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.animations;
 
 import java.util.List;
 
 import com.jme3.animation.BoneTrack;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.BezierCurve;
-import com.jme3.scene.plugins.blender.structures.Ipo;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.curves.BezierCurve;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
 
 /**
  * This class helps to compute values from interpolation curves for features like animation or constraint influence. The
@@ -18,7 +17,7 @@ import com.jme3.scene.plugins.blender.utils.Pointer;
  */
 public class IpoHelper extends AbstractBlenderHelper {
 
-    /**
+	/**
      * This constructor parses the given blender version and stores the result. Some functionalities may differ in
      * different blender versions.
      * @param blenderVersion

+ 118 - 0
engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java

@@ -0,0 +1,118 @@
+package com.jme3.scene.plugins.blender.cameras;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.asset.BlenderKey.FeaturesToLoad;
+import com.jme3.renderer.Camera;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * A class that is used to load cameras into the scene.
+ * @author Marcin Roguski
+ */
+public class CameraHelper extends AbstractBlenderHelper {
+
+    private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
+    protected static final int DEFAULT_CAM_WIDTH = 100;
+    protected static final int DEFAULT_CAM_HEIGHT = 100;
+    
+    /**
+     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
+     * different blender versions.
+     * @param blenderVersion
+     *        the version read from the blend file
+     */
+    public CameraHelper(String blenderVersion) {
+        super(blenderVersion);
+    }
+    
+	/**
+	 * This method converts the given structure to jme camera.
+	 * 
+	 * @param structure
+	 *            camera structure
+	 * @return jme camera object
+	 * @throws BlenderFileException
+	 *             an exception is thrown when there are problems with the
+	 *             blender file
+	 */
+    public Camera toCamera(Structure structure) throws BlenderFileException {
+    	if (blenderVersion >= 250) {
+            return this.toCamera250(structure);
+        } else {
+        	return this.toCamera249(structure);
+        }
+    }
+
+	/**
+	 * This method converts the given structure to jme camera. Should be used form blender 2.5+.
+	 * 
+	 * @param structure
+	 *            camera structure
+	 * @return jme camera object
+	 * @throws BlenderFileException
+	 *             an exception is thrown when there are problems with the
+	 *             blender file
+	 */
+    public Camera toCamera250(Structure structure) throws BlenderFileException {
+        Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
+        int type = ((Number) structure.getFieldValue("type")).intValue();
+        if (type != 0 && type != 1) {
+            LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
+            type = 0;
+        }
+        //type==0 - perspective; type==1 - orthographic; perspective is used as default
+        result.setParallelProjection(type == 1);
+        float aspect = 0;
+        float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
+        float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
+        if (type == 0) {
+            aspect = ((Number) structure.getFieldValue("lens")).floatValue();
+        } else {
+            aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
+        }
+        result.setFrustumPerspective(45, aspect, clipsta, clipend);
+        return result;
+    }
+    
+    /**
+	 * This method converts the given structure to jme camera. Should be used form blender 2.49.
+	 * 
+	 * @param structure
+	 *            camera structure
+	 * @return jme camera object
+	 * @throws BlenderFileException
+	 *             an exception is thrown when there are problems with the
+	 *             blender file
+	 */
+    public Camera toCamera249(Structure structure) throws BlenderFileException {
+        Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
+        int type = ((Number) structure.getFieldValue("type")).intValue();
+        if (type != 0 && type != 1) {
+            LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
+            type = 0;
+        }
+        //type==0 - perspective; type==1 - orthographic; perspective is used as default
+        result.setParallelProjection(type == 1);
+        float angle = ((Number) structure.getFieldValue("angle")).floatValue();
+        float aspect = 0;
+        float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
+        float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
+        if (type == 0) {
+            aspect = ((Number) structure.getFieldValue("lens")).floatValue();
+        } else {
+            aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
+        }
+        result.setFrustumPerspective(angle, aspect, clipsta, clipend);
+        return result;
+    }
+
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0;
+	}
+}

+ 247 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java

@@ -0,0 +1,247 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.Bone;
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Node;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+
+/**
+ * The implementation of a constraint.
+ * 
+ * @author Marcin Roguski
+ */
+public abstract class Constraint {
+
+	/** The name of this constraint. */
+	protected final String name;
+	/** The old memory address of the constraint's owner. */
+	protected final Long boneOMA;
+	protected final Space ownerSpace;
+	protected final Space targetSpace;
+	/** The structure with constraint's data. */
+	protected final Structure data;
+	/** The ipo object defining influence. */
+	protected final Ipo ipo;
+	protected DataRepository dataRepository;
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public Constraint(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		this.name = constraintStructure.getFieldValue("name").toString();
+		ConstraintType constraintType = ConstraintType.valueOf(((Number)constraintStructure.getFieldValue("type")).intValue());
+		if(constraintType != this.getType()) {
+			throw new IllegalStateException("Constraint structure does not match its type for constraint: " + name);
+		}
+		Pointer pData = (Pointer) constraintStructure.getFieldValue("data");
+		if (pData.isNotNull()) {
+			data = pData.fetchData(dataRepository.getInputStream()).get(0);
+		} else {
+			throw new BlenderFileException("The constraint has no data specified!");
+		}
+		this.boneOMA = boneOMA;
+		this.ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue());
+		this.targetSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("tarspace")).byteValue());
+		this.ipo = influenceIpo;
+	}
+
+	/**
+	 * This method returns the name of the constraint.
+	 * 
+	 * @return the name of the constraint
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * This method returns the old memoty address of the bone this constraint
+	 * affects.
+	 * 
+	 * @return the old memory address of the bone this constraint affects
+	 */
+	public Long getBoneOMA() {
+		return boneOMA;
+	}
+
+	/**
+	 * This method returns the type of the constraint.
+	 * 
+	 * @return the type of the constraint
+	 */
+	public abstract ConstraintType getType();
+
+	/**
+     * This method returns the bone traces for the bone that is affected by the given constraint.
+     * @param skeleton
+     *        the skeleton containing bones
+     * @param boneAnimation
+     *        the bone animation that affects the skeleton
+     * @return the bone track for the bone that is being affected by the constraint
+     */
+    protected BoneTrack getBoneTrack(Skeleton skeleton, BoneAnimation boneAnimation) {
+        Bone bone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
+        int boneIndex = bone==null ? 0 : skeleton.getBoneIndex(bone);//bone==null may mean the object animation
+        if (boneIndex != -1) {
+            //searching for track for this bone
+            for (BoneTrack boneTrack : boneAnimation.getTracks()) {
+                if (boneTrack.getTargetBoneIndex() == boneIndex) {
+                    return boneTrack;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * This method returns the target or subtarget object (if specified).
+     * @param loadedFeatureDataType
+     * @return target or subtarget feature
+     * @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted
+     */
+    protected Object getTarget(LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException {
+    	//load the feature through objectHelper, this way we are certain the object loads and has
+    	//his own constraints applied to traces
+    	ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+    	//always load the target first
+    	Long targetOMA = ((Pointer) data.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 = data.getFieldValue("subtarget");
+    	String subtargetName = subtarget==null ? null : subtarget.toString();
+        if (subtargetName!=null && subtargetName.length() > 0) {
+            result = dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
+        }
+        return result;
+    }
+	
+	/**
+     * This method returns target's object location.
+     * @return target's object location
+     */
+    protected Vector3f getTargetLocation() {
+        Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress();
+        Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
+        switch (targetSpace) {
+            case CONSTRAINT_SPACE_LOCAL:
+                return targetObject.getLocalTranslation();
+            case CONSTRAINT_SPACE_WORLD:
+                return targetObject.getWorldTranslation();
+            default:
+                throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
+        }
+    }
+
+    /**
+     * This method returns target's object location in the specified frame.
+     * @param frame
+     *        the frame number
+     * @return target's object location
+     */
+    protected Vector3f getTargetLocation(int frame) {
+        return this.getTargetLocation();//TODO: implement getting location in a specified frame
+    }
+
+    /**
+     * This method returns target's object rotation.
+     * @return target's object rotation
+     */
+    protected Quaternion getTargetRotation() {
+        Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress();
+        Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
+        switch (targetSpace) {
+            case CONSTRAINT_SPACE_LOCAL:
+                return targetObject.getLocalRotation();
+            case CONSTRAINT_SPACE_WORLD:
+                return targetObject.getWorldRotation();
+            default:
+                throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
+        }
+    }
+
+    /**
+     * This method returns target's object scale.
+     * @return target's object scale
+     */
+    protected Vector3f getTargetScale() {
+        Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress();
+        Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
+        switch (targetSpace) {
+            case CONSTRAINT_SPACE_LOCAL:
+                return targetObject.getLocalScale();
+            case CONSTRAINT_SPACE_WORLD:
+                return targetObject.getWorldScale();
+            default:
+                throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
+        }
+    }
+    
+	/**
+	 * This method affects the bone animation tracks for the given skeleton.
+	 * 
+	 * @param skeleton
+	 *            the skeleton containing the affected bones by constraint
+	 * @param boneAnimation
+	 *            the bone animation baked traces
+	 * @param constraint
+	 *            the constraint
+	 */
+	public abstract void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation);
+
+	/**
+	 * The space of target or owner transformation.
+	 * 
+	 * @author Marcin Roguski
+	 */
+	public static enum Space {
+
+		CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID;
+
+		/**
+		 * This method returns the enum instance when given the appropriate
+		 * value from the blend file.
+		 * 
+		 * @param c
+		 *            the blender's value of the space modifier
+		 * @return the scape enum instance
+		 */
+		public static Space valueOf(byte c) {
+			switch (c) {
+			case 0:
+				return CONSTRAINT_SPACE_WORLD;
+			case 1:
+				return CONSTRAINT_SPACE_LOCAL;
+			case 2:
+				return CONSTRAINT_SPACE_POSE;
+			case 3:
+				return CONSTRAINT_SPACE_PARLOCAL;
+			default:
+				return CONSTRAINT_SPACE_INVALID;
+			}
+		}
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintAction.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Action' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintAction extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintAction.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintAction(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Action' constraint
+		LOGGER.log(Level.WARNING, "'Action' constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_ACTION;
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintChildOf.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'ChildOf' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintChildOf extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintChildOf.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintChildOf(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement ChildOf constraint
+		LOGGER.log(Level.WARNING, "ChildOf constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_CHILDOF;
+	}
+}

+ 51 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintClampTo.java

@@ -0,0 +1,51 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Clamp to' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintClampTo extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintClampTo.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintClampTo(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository)
+			throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		//TODO: implement when curves are implemented
+		LOGGER.log(Level.INFO, "'Clamp to' not yet implemented! Curves not yet implemented!", this.getName());
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_CLAMPTO;
+	}
+}

+ 84 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java

@@ -0,0 +1,84 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * 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;
+    
+    /**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintDistLimit(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		Vector3f targetLocation = this.getTargetLocation();
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			//TODO: target vertex group !!!
+			float dist = ((Number) data.getFieldValue("dist")).floatValue();
+			int mode = ((Number) data.getFieldValue("mode")).intValue();
+
+			int maxFrames = boneTrack.getTimes().length;
+			Vector3f[] translations = boneTrack.getTranslations();
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				Vector3f v = translations[frame].subtract(targetLocation);
+				float currentDistance = v.length();
+				float influence = ipo.calculateValue(frame);
+				float modifier = 0.0f;
+				switch (mode) {
+					case LIMITDIST_INSIDE:
+						if (currentDistance >= dist) {
+							modifier = (dist - currentDistance) / currentDistance;
+						}
+						break;
+					case LIMITDIST_ONSURFACE:
+						modifier = (dist - currentDistance) / currentDistance;
+						break;
+					case LIMITDIST_OUTSIDE:
+						if (currentDistance <= dist) {
+							modifier = (dist - currentDistance) / currentDistance;
+						}
+						break;
+					default:
+						throw new IllegalStateException("Unknown distance limit constraint mode: " + mode);
+				}
+				translations[frame].addLocal(v.multLocal(modifier * influence));
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales());
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_DISTLIMIT;
+	}
+}

+ 78 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFactory.java

@@ -0,0 +1,78 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * A factory class to create new instances of constraints depending on the type from the constraint's structure.
+ * This class has a package scope.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ final class ConstraintFactory {
+	
+	/**
+	 * This method creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public static Constraint createConstraint(Structure constraintStructure, Long boneOMA, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		int type = ((Number)constraintStructure.getFieldValue("type")).intValue();
+		ConstraintType constraintType = ConstraintType.valueOf(type);
+			switch(constraintType) {
+				case CONSTRAINT_TYPE_ACTION:
+					return new ConstraintAction(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_CHILDOF:
+					return new ConstraintChildOf(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_CLAMPTO:
+					return new ConstraintClampTo(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_DISTLIMIT:
+					return new ConstraintDistLimit(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_FOLLOWPATH:
+					return new ConstraintFollowPath(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_KINEMATIC:
+					return new ConstraintInverseKinematics(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_LOCKTRACK:
+					return new ConstraintLockTrack(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_LOCLIKE:
+					return new ConstraintLocLike(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_LOCLIMIT:
+					return new ConstraintLocLimit(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_MINMAX:
+					return new ConstraintMinMax(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_NULL:
+					return new ConstraintNull(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_PYTHON:
+					return new ConstraintPython(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+					return new ConstraintRigidBodyJoint(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_ROTLIKE:
+					return new ConstraintRotLike(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_ROTLIMIT:
+					return new ConstraintRotLimit(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_SHRINKWRAP:
+					return new ConstraintShrinkWrap(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_SIZELIKE:
+					return new ConstraintSizeLike(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_SIZELIMIT:
+					return new ConstraintSizeLimit(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_STRETCHTO:
+					return new ConstraintStretchTo(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				case CONSTRAINT_TYPE_TRANSFORM:
+					return new ConstraintTransform(constraintStructure, boneOMA, influenceIpo, dataRepository);
+				default:
+					throw new IllegalStateException("Unknown constraint type: " + constraintType);
+		}
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFollowPath.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Follow path' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintFollowPath extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintFollowPath.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintFollowPath(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		//TODO: implement when curves are implemented
+		LOGGER.log(Level.INFO, "'Follow path' not implemented! Curves not yet implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_FOLLOWPATH;
+	}
+}

+ 140 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java

@@ -0,0 +1,140 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.animations.IpoHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class should be used for constraint calculations.
+ * @author Marcin Roguski
+ */
+public class ConstraintHelper extends AbstractBlenderHelper {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName());
+	
+	/**
+	 * Helper constructor. It's main task is to generate the affection functions. These functions are common to all
+	 * ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall
+	 * consider refactoring. The constructor parses the given blender version and stores the result. Some
+	 * functionalities may differ in different blender versions.
+	 * @param blenderVersion
+	 *        the version read from the blend file
+	 */
+	public ConstraintHelper(String blenderVersion, DataRepository dataRepository) {
+		super(blenderVersion);
+	}
+
+	/**
+	 * This method reads constraints for for the given structure. The constraints are loaded only once for object/bone.
+	 * @param ownerOMA
+	 *        the owner's old memory address
+	 * @param objectStructure
+	 *        the structure we read constraint's for
+	 * @param dataRepository
+	 *        the data repository
+	 * @throws BlenderFileException
+	 */
+	public Map<Long, List<Constraint>> loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
+		if (blenderVersion < 250) {//TODO
+			LOGGER.warning("Loading of constraints not yet implemented for version 2.5x !");
+			return new HashMap<Long, List<Constraint>>(0);
+		}
+		
+		// reading influence ipos for the constraints
+		IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
+		Map<String, Map<String, Ipo>> constraintsIpos = new HashMap<String, Map<String, Ipo>>();
+		Pointer pActions = (Pointer) objectStructure.getFieldValue("action");
+		if (pActions.isNotNull()) {
+			List<Structure> actions = pActions.fetchData(dataRepository.getInputStream());
+			for (Structure action : actions) {
+				Structure chanbase = (Structure) action.getFieldValue("chanbase");
+				List<Structure> actionChannels = chanbase.evaluateListBase(dataRepository);
+				for (Structure actionChannel : actionChannels) {
+					Map<String, Ipo> ipos = new HashMap<String, Ipo>();
+					Structure constChannels = (Structure) actionChannel.getFieldValue("constraintChannels");
+					List<Structure> constraintChannels = constChannels.evaluateListBase(dataRepository);
+					for (Structure constraintChannel : constraintChannels) {
+						Pointer pIpo = (Pointer) constraintChannel.getFieldValue("ipo");
+						if (pIpo.isNotNull()) {
+							String constraintName = constraintChannel.getFieldValue("name").toString();
+							Ipo ipo = ipoHelper.createIpo(pIpo.fetchData(dataRepository.getInputStream()).get(0), dataRepository);
+							ipos.put(constraintName, ipo);
+						}
+					}
+					String actionName = actionChannel.getFieldValue("name").toString();
+					constraintsIpos.put(actionName, ipos);
+				}
+			}
+		}
+
+		Map<Long, List<Constraint>> result = new HashMap<Long, List<Constraint>>();
+		
+		//loading constraints connected with the object's bones
+		Pointer pPose = (Pointer) objectStructure.getFieldValue("pose");//TODO: what if the object has two armatures ????
+		if (pPose.isNotNull()) {
+			List<Structure> poseChannels = ((Structure) pPose.fetchData(dataRepository.getInputStream()).get(0).getFieldValue("chanbase")).evaluateListBase(dataRepository);
+			for (Structure poseChannel : poseChannels) {
+				List<Constraint> constraintsList = new ArrayList<Constraint>();
+				Long boneOMA = Long.valueOf(((Pointer) poseChannel.getFieldValue("bone")).getOldMemoryAddress());
+				
+				//the name is read directly from structure because bone might not yet be loaded
+				String name = dataRepository.getFileBlock(boneOMA).getStructure(dataRepository).getFieldValue("name").toString();
+				List<Structure> constraints = ((Structure) poseChannel.getFieldValue("constraints")).evaluateListBase(dataRepository);
+				for (Structure constraint : constraints) {
+					String constraintName = constraint.getFieldValue("name").toString();
+					Map<String, Ipo> ipoMap = constraintsIpos.get(name);
+					Ipo ipo = ipoMap==null ? null : ipoMap.get(constraintName);
+					if (ipo == null) {
+						float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
+						ipo = ipoHelper.createIpo(enforce);
+					}
+					constraintsList.add(ConstraintFactory.createConstraint(constraint, boneOMA, ipo, dataRepository));
+				}
+				
+				result.put(boneOMA, constraintsList);
+				dataRepository.addConstraints(boneOMA, constraintsList);
+			}
+		}
+		// TODO: reading constraints for objects (implement when object's animation will be available)
+		List<Structure> constraintChannels = ((Structure)objectStructure.getFieldValue("constraintChannels")).evaluateListBase(dataRepository);
+		for(Structure constraintChannel : constraintChannels) {
+			System.out.println(constraintChannel);
+		}
+
+		//loading constraints connected with the object itself (TODO: test this)
+		if(!result.containsKey(objectStructure.getOldMemoryAddress())) {
+			List<Structure> constraints = ((Structure)objectStructure.getFieldValue("constraints")).evaluateListBase(dataRepository);
+			List<Constraint> constraintsList = new ArrayList<Constraint>(constraints.size());
+			
+			for(Structure constraint : constraints) {
+				String constraintName = constraint.getFieldValue("name").toString();
+				String objectName = objectStructure.getName();
+				
+				Map<String, Ipo> objectConstraintsIpos = constraintsIpos.get(objectName);
+				Ipo ipo = objectConstraintsIpos!=null ? objectConstraintsIpos.get(constraintName) : null;
+				if (ipo == null) {
+					float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
+					ipo = ipoHelper.createIpo(enforce);
+				}
+				constraintsList.add(ConstraintFactory.createConstraint(constraint, null, ipo, dataRepository));
+			}
+			result.put(objectStructure.getOldMemoryAddress(), constraintsList);
+			dataRepository.addConstraints(objectStructure.getOldMemoryAddress(), constraintsList);
+		}
+		return result;
+	}
+	
+	@Override
+	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+		return true;
+	}
+}

+ 170 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintInverseKinematics.java

@@ -0,0 +1,170 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.jme3.animation.Bone;
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Transform;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Node;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.animations.CalculationBone;
+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.blender.objects.ObjectHelper;
+
+/**
+ * This class represents 'Inverse kinematics' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintInverseKinematics extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintInverseKinematics.class.getName());
+	private static final float IK_SOLVER_ERROR = 0.5f;
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintInverseKinematics(Structure constraintStructure,
+			Long boneOMA, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		try {
+			// IK solver is only attached to bones
+			Bone ownerBone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
+
+			// get the target point
+			Object targetObject = this.getTarget(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(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) data.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;
+				}
+			}
+
+			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());
+		}
+	}
+	
+	/**
+	 * This method returns bones used for rotation calculations.
+	 * @param bone
+	 *        the bone to which the constraint is applied
+	 * @param skeleton
+	 *        the skeleton owning the bone and its ancestors
+	 * @param boneAnimation
+	 *        the bone animation data that stores the traces for the skeleton's bones
+	 * @return a list of bones to imitate the bone's movement during IK solving
+	 */
+	private CalculationBone[] getBonesToCalculate(Bone bone, Skeleton skeleton, BoneAnimation boneAnimation) {
+		List<CalculationBone> bonesList = new ArrayList<CalculationBone>();
+		Bone currentBone = bone;
+		do {
+			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();
+		} while (currentBone != null);
+		//attaching children
+		CalculationBone[] result = bonesList.toArray(new CalculationBone[bonesList.size()]);
+		for (int i = result.length - 1; i > 0; --i) {
+			result[i].attachChild(result[i - 1]);
+		}
+		return result;
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_KINEMATIC;
+	}
+}

+ 87 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLike.java

@@ -0,0 +1,87 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Loc like' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintLocLike extends Constraint {
+	private static final int LOCLIKE_X = 0x01;
+	private static final int LOCLIKE_Y = 0x02;
+	private static final int LOCLIKE_Z = 0x04;
+	/* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */
+    //protected static final int LOCLIKE_TIP = 0x08;
+    private static final int LOCLIKE_X_INVERT = 0x10;
+    private static final int LOCLIKE_Y_INVERT = 0x20;
+    private static final int LOCLIKE_Z_INVERT = 0x40;
+    private static final int LOCLIKE_OFFSET = 0x80;
+    
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintLocLike(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			Vector3f targetLocation = this.getTargetLocation();
+			int flag = ((Number) data.getFieldValue("flag")).intValue();
+			Vector3f[] translations = boneTrack.getTranslations();
+			int maxFrames = translations.length;
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				Vector3f offset = Vector3f.ZERO;
+				if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original location to the copied location
+					offset = translations[frame].clone();
+				}
+
+				if ((flag & LOCLIKE_X) != 0) {
+					translations[frame].x = targetLocation.x;
+					if ((flag & LOCLIKE_X_INVERT) != 0) {
+						translations[frame].x = -translations[frame].x;
+					}
+				} else if ((flag & LOCLIKE_Y) != 0) {
+					translations[frame].y = targetLocation.y;
+					if ((flag & LOCLIKE_Y_INVERT) != 0) {
+						translations[frame].y = -translations[frame].y;
+					}
+				} else if ((flag & LOCLIKE_Z) != 0) {
+					translations[frame].z = targetLocation.z;
+					if ((flag & LOCLIKE_Z_INVERT) != 0) {
+						translations[frame].z = -translations[frame].z;
+					}
+				}
+				translations[frame].addLocal(offset);//TODO: ipo influence
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales());
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_LOCLIKE;
+	}
+}

+ 98 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLimit.java

@@ -0,0 +1,98 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Loc limit' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintLocLimit extends Constraint {
+    private static final int LIMIT_XMIN = 0x01;
+    private static final int LIMIT_XMAX = 0x02;
+    private static final int LIMIT_YMIN = 0x04;
+    private static final int LIMIT_YMAX = 0x08;
+    private static final int LIMIT_ZMIN = 0x10;
+    private static final int LIMIT_ZMAX = 0x20;
+    
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintLocLimit(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			int flag = ((Number) data.getFieldValue("flag")).intValue();
+			Vector3f[] translations = boneTrack.getTranslations();
+			int maxFrames = translations.length;
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				float influence = ipo.calculateValue(frame);
+				if ((flag & LIMIT_XMIN) != 0) {
+					float xmin = ((Number) data.getFieldValue("xmin")).floatValue();
+					if (translations[frame].x < xmin) {
+						translations[frame].x -= (translations[frame].x - xmin) * influence;
+					}
+				}
+				if ((flag & LIMIT_XMAX) != 0) {
+					float xmax = ((Number) data.getFieldValue("xmax")).floatValue();
+					if (translations[frame].x > xmax) {
+						translations[frame].x -= (translations[frame].x - xmax) * influence;
+					}
+				}
+				if ((flag & LIMIT_YMIN) != 0) {
+					float ymin = ((Number) data.getFieldValue("ymin")).floatValue();
+					if (translations[frame].y < ymin) {
+						translations[frame].y -= (translations[frame].y - ymin) * influence;
+					}
+				}
+				if ((flag & LIMIT_YMAX) != 0) {
+					float ymax = ((Number) data.getFieldValue("ymax")).floatValue();
+					if (translations[frame].y > ymax) {
+						translations[frame].y -= (translations[frame].y - ymax) * influence;
+					}
+				}
+				if ((flag & LIMIT_ZMIN) != 0) {
+					float zmin = ((Number) data.getFieldValue("zmin")).floatValue();
+					if (translations[frame].z < zmin) {
+						translations[frame].z -= (translations[frame].z - zmin) * influence;
+					}
+				}
+				if ((flag & LIMIT_ZMAX) != 0) {
+					float zmax = ((Number) data.getFieldValue("zmax")).floatValue();
+					if (translations[frame].z > zmax) {
+						translations[frame].z -= (translations[frame].z - zmax) * influence;
+					}
+				}//TODO: consider constraint space !!!
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales());
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_LOCLIMIT;
+	}
+}

+ 51 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLockTrack.java

@@ -0,0 +1,51 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Action' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintLockTrack extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintLockTrack.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintLockTrack(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository)
+			throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Lock track' constraint
+		LOGGER.log(Level.WARNING, "'Lock track' constraint NOT implemented!");
+	}
+
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_LOCKTRACK;
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintMinMax.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Min max' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintMinMax extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintMinMax.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintMinMax(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Min max' constraint
+		LOGGER.log(Level.WARNING, "'Min max' constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_MINMAX;
+	}
+}

+ 44 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintNull.java

@@ -0,0 +1,44 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Null' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintNull extends Constraint {
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintNull(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository)
+			throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_NULL;
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPython.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Python' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintPython extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintPython.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintPython(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Python' constraint
+		LOGGER.log(Level.WARNING, "'Python' constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_PYTHON;
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRigidBodyJoint.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Rigid body joint' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintRigidBodyJoint extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintRigidBodyJoint.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintRigidBodyJoint(Structure constraintStructure,
+			Long boneOMA, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Rigid body joint' constraint
+		LOGGER.log(Level.WARNING, "'Rigid body joint' constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_RIGIDBODYJOINT;
+	}
+}

+ 88 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLike.java

@@ -0,0 +1,88 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Quaternion;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Rot like' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintRotLike extends Constraint {
+	private static final int ROTLIKE_X = 0x01;
+	private static final int ROTLIKE_Y = 0x02;
+	private static final int ROTLIKE_Z = 0x04;
+	private static final int ROTLIKE_X_INVERT = 0x10;
+    private static final int ROTLIKE_Y_INVERT = 0x20;
+    private static final int ROTLIKE_Z_INVERT = 0x40;
+    private static final int ROTLIKE_OFFSET = 0x80;
+    
+    /**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintRotLike(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			Quaternion targetRotation = this.getTargetRotation();
+			int flag = ((Number) data.getFieldValue("flag")).intValue();
+			float[] targetAngles = targetRotation.toAngles(null);
+			Quaternion[] rotations = boneTrack.getRotations();
+			int maxFrames = rotations.length;
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				float[] angles = rotations[frame].toAngles(null);
+
+				Quaternion offset = Quaternion.IDENTITY;
+				if ((flag & ROTLIKE_OFFSET) != 0) {//we add the original rotation to the copied rotation
+					offset = rotations[frame].clone();
+				}
+
+				if ((flag & ROTLIKE_X) != 0) {
+					angles[0] = targetAngles[0];
+					if ((flag & ROTLIKE_X_INVERT) != 0) {
+						angles[0] = -angles[0];
+					}
+				} else if ((flag & ROTLIKE_Y) != 0) {
+					angles[1] = targetAngles[1];
+					if ((flag & ROTLIKE_Y_INVERT) != 0) {
+						angles[1] = -angles[1];
+					}
+				} else if ((flag & ROTLIKE_Z) != 0) {
+					angles[2] = targetAngles[2];
+					if ((flag & ROTLIKE_Z_INVERT) != 0) {
+						angles[2] = -angles[2];
+					}
+				}
+				rotations[frame].fromAngles(angles).multLocal(offset);//TODO: ipo influence
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales());
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_ROTLIKE;
+	}
+}

+ 95 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java

@@ -0,0 +1,95 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Rot limit' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintRotLimit extends Constraint {
+	private static final int LIMIT_XROT = 0x01;
+	private static final int LIMIT_YROT = 0x02;
+	private static final int LIMIT_ZROT = 0x04;
+    
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintRotLimit(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			int flag = ((Number) data.getFieldValue("flag")).intValue();
+			Quaternion[] rotations = boneTrack.getRotations();
+			int maxFrames = rotations.length;
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				float[] angles = rotations[frame].toAngles(null);
+				float influence = ipo.calculateValue(frame);
+				if ((flag & LIMIT_XROT) != 0) {
+					float xmin = ((Number) data.getFieldValue("xmin")).floatValue() * FastMath.DEG_TO_RAD;
+					float xmax = ((Number) data.getFieldValue("xmax")).floatValue() * FastMath.DEG_TO_RAD;
+					float difference = 0.0f;
+					if (angles[0] < xmin) {
+						difference = (angles[0] - xmin) * influence;
+					} else if (angles[0] > xmax) {
+						difference = (angles[0] - xmax) * influence;
+					}
+					angles[0] -= difference;
+				}
+				if ((flag & LIMIT_YROT) != 0) {
+					float ymin = ((Number) data.getFieldValue("ymin")).floatValue() * FastMath.DEG_TO_RAD;
+					float ymax = ((Number) data.getFieldValue("ymax")).floatValue() * FastMath.DEG_TO_RAD;
+					float difference = 0.0f;
+					if (angles[1] < ymin) {
+						difference = (angles[1] - ymin) * influence;
+					} else if (angles[1] > ymax) {
+						difference = (angles[1] - ymax) * influence;
+					}
+					angles[1] -= difference;
+				}
+				if ((flag & LIMIT_ZROT) != 0) {
+					float zmin = ((Number) data.getFieldValue("zmin")).floatValue() * FastMath.DEG_TO_RAD;
+					float zmax = ((Number) data.getFieldValue("zmax")).floatValue() * FastMath.DEG_TO_RAD;
+					float difference = 0.0f;
+					if (angles[2] < zmin) {
+						difference = (angles[2] - zmin) * influence;
+					} else if (angles[2] > zmax) {
+						difference = (angles[2] - zmax) * influence;
+					}
+					angles[2] -= difference;
+				}
+				rotations[frame].fromAngles(angles);//TODO: consider constraint space !!!
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales());
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_ROTLIMIT;
+	}
+}

+ 100 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintShrinkWrap.java

@@ -0,0 +1,100 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.VertexBuffer.Type;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Shrink wrap' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintShrinkWrap extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintShrinkWrap.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintShrinkWrap(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		//loading mesh points (blender ensures that the target is a mesh-object)
+		List<Vector3f> pts = new ArrayList<Vector3f>();
+		try {
+			Node node = (Node)this.getTarget(LoadedFeatureDataType.LOADED_FEATURE);
+			for(Spatial spatial : node.getChildren()) {
+				if(spatial instanceof Geometry) {
+					Mesh mesh = ((Geometry) spatial).getMesh();
+					FloatBuffer floatBuffer = mesh.getFloatBuffer(Type.Position);
+					for(int i=0;i<floatBuffer.limit();i+=3) {
+						pts.add(new Vector3f(floatBuffer.get(i), floatBuffer.get(i + 1), floatBuffer.get(i + 2)));
+					}
+				}
+			}
+			
+			//modifying traces
+			BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+			if (boneTrack != null) {
+				Vector3f[] translations = boneTrack.getTranslations();
+				Quaternion[] rotations = boneTrack.getRotations();
+				int maxFrames = translations.length;
+				for (int frame = 0; frame < maxFrames; ++frame) {
+					Vector3f currentTranslation = translations[frame];
+					
+					//looking for minimum distanced point
+					Vector3f minDistancePoint = null;
+					float distance = Float.MAX_VALUE;
+					for(Vector3f p : pts) {
+						float temp = currentTranslation.distance(p);
+						if(temp < distance) {
+							distance = temp;
+							minDistancePoint = p;
+						}
+					}
+					translations[frame] = minDistancePoint.clone();
+				}
+				
+				boneTrack.setKeyframes(boneTrack.getTimes(), translations, rotations, boneTrack.getScales());
+			}
+		} catch (BlenderFileException e) {
+			LOGGER.severe(e.getLocalizedMessage());
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_SHRINKWRAP;
+	}
+}

+ 74 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSizeLike.java

@@ -0,0 +1,74 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Size like' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintSizeLike extends Constraint {
+	private static final int SIZELIKE_X = 0x01;
+	private static final int SIZELIKE_Y = 0x02;
+	private static final int SIZELIKE_Z = 0x04;
+	private static final int LOCLIKE_OFFSET = 0x80;
+    
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintSizeLike(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		Vector3f targetScale = this.getTargetLocation();
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			int flag = ((Number) data.getFieldValue("flag")).intValue();
+			Vector3f[] scales = boneTrack.getScales();
+			int maxFrames = scales.length;
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				Vector3f offset = Vector3f.ZERO;
+				if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original scale to the copied scale
+					offset = scales[frame].clone();
+				}
+
+				if ((flag & SIZELIKE_X) != 0) {
+					scales[frame].x = targetScale.x;
+				} else if ((flag & SIZELIKE_Y) != 0) {
+					scales[frame].y = targetScale.y;
+				} else if ((flag & SIZELIKE_Z) != 0) {
+					scales[frame].z = targetScale.z;
+				}
+				scales[frame].addLocal(offset);//TODO: ipo influence
+				//TODO: add or multiply???
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), boneTrack.getRotations(), scales);
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_SIZELIKE;
+	}
+}

+ 98 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintSizeLimit.java

@@ -0,0 +1,98 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Size limit' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintSizeLimit extends Constraint {
+	private static final int LIMIT_XMIN = 0x01;
+	private static final int LIMIT_XMAX = 0x02;
+	private static final int LIMIT_YMIN = 0x04;
+	private static final int LIMIT_YMAX = 0x08;
+	private static final int LIMIT_ZMIN = 0x10;
+	private static final int LIMIT_ZMAX = 0x20;
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintSizeLimit(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation);
+		if (boneTrack != null) {
+			int flag = ((Number) data.getFieldValue("flag")).intValue();
+			Vector3f[] scales = boneTrack.getScales();
+			int maxFrames = scales.length;
+			for (int frame = 0; frame < maxFrames; ++frame) {
+				float influence = ipo.calculateValue(frame);
+				if ((flag & LIMIT_XMIN) != 0) {
+					float xmin = ((Number) data.getFieldValue("xmin")).floatValue();
+					if (scales[frame].x < xmin) {
+						scales[frame].x -= (scales[frame].x - xmin) * influence;
+					}
+				}
+				if ((flag & LIMIT_XMAX) != 0) {
+					float xmax = ((Number) data.getFieldValue("xmax")).floatValue();
+					if (scales[frame].x > xmax) {
+						scales[frame].x -= (scales[frame].x - xmax) * influence;
+					}
+				}
+				if ((flag & LIMIT_YMIN) != 0) {
+					float ymin = ((Number) data.getFieldValue("ymin")).floatValue();
+					if (scales[frame].y < ymin) {
+						scales[frame].y -= (scales[frame].y - ymin) * influence;
+					}
+				}
+				if ((flag & LIMIT_YMAX) != 0) {
+					float ymax = ((Number) data.getFieldValue("ymax")).floatValue();
+					if (scales[frame].y > ymax) {
+						scales[frame].y -= (scales[frame].y - ymax) * influence;
+					}
+				}
+				if ((flag & LIMIT_ZMIN) != 0) {
+					float zmin = ((Number) data.getFieldValue("zmin")).floatValue();
+					if (scales[frame].z < zmin) {
+						scales[frame].z -= (scales[frame].z - zmin) * influence;
+					}
+				}
+				if ((flag & LIMIT_ZMAX) != 0) {
+					float zmax = ((Number) data.getFieldValue("zmax")).floatValue();
+					if (scales[frame].z > zmax) {
+						scales[frame].z -= (scales[frame].z - zmax) * influence;
+					}
+				}//TODO: consider constraint space !!!
+			}
+			boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), boneTrack.getRotations(), scales);
+		}
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_SIZELIMIT;
+	}
+}

+ 51 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintStretchTo.java

@@ -0,0 +1,51 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Stretch to' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintStretchTo extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintStretchTo.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintStretchTo(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository)
+			throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Stretch to' constraint
+		LOGGER.log(Level.WARNING, "'Stretch to' constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_STRETCHTO;
+	}
+}

+ 50 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransform.java

@@ -0,0 +1,50 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.Skeleton;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents 'Transform' constraint type in blender.
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ConstraintTransform extends Constraint {
+	private static final Logger LOGGER = Logger.getLogger(ConstraintAction.class.getName());
+	
+	/**
+	 * This constructor creates the constraint instance.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure (bConstraint clss in blender 2.49).
+	 * @param boneOMA
+	 *            the old memory address of the constraint owner
+	 * @param influenceIpo
+	 *            the ipo curve of the influence factor
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ConstraintTransform(Structure constraintStructure, Long boneOMA,
+			Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
+		super(constraintStructure, boneOMA, influenceIpo, dataRepository);
+	}
+
+	@Override
+	public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
+		// TODO: implement 'Transform' constraint
+		LOGGER.log(Level.WARNING, "'Transform' constraint NOT implemented!");
+	}
+	
+	@Override
+	public ConstraintType getType() {
+		return ConstraintType.CONSTRAINT_TYPE_TRANSFORM;
+	}
+}

+ 1 - 1
engine/src/blender/com/jme3/scene/plugins/blender/structures/ConstraintType.java → engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintType.java

@@ -1,4 +1,4 @@
-package com.jme3.scene.plugins.blender.structures;
+package com.jme3.scene.plugins.blender.constraints;
 
 import java.util.HashMap;
 import java.util.Map;

+ 3 - 3
engine/src/blender/com/jme3/scene/plugins/blender/structures/BezierCurve.java → engine/src/blender/com/jme3/scene/plugins/blender/curves/BezierCurve.java

@@ -1,11 +1,11 @@
-package com.jme3.scene.plugins.blender.structures;
+package com.jme3.scene.plugins.blender.curves;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.Structure;
 
 /**
  * A class that helps to calculate the bezier curves calues. It uses doubles for performing calculations to minimize

+ 13 - 12
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/curves/CurvesHelper.java

@@ -1,4 +1,4 @@
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.curves;
 
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
@@ -21,16 +21,17 @@ import com.jme3.math.Vector4f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.BezierCurve;
-import com.jme3.scene.plugins.blender.structures.Properties;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.scene.plugins.blender.meshes.MeshHelper;
+import com.jme3.scene.plugins.blender.objects.Properties;
 import com.jme3.scene.shape.Curve;
 import com.jme3.scene.shape.Surface;
 import com.jme3.util.BufferUtils;
@@ -604,4 +605,4 @@ public class CurvesHelper extends AbstractBlenderHelper {
     public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
     	return true;
     }
-}
+}

+ 1 - 1
engine/src/blender/com/jme3/scene/plugins/blender/exception/BlenderFileException.java → engine/src/blender/com/jme3/scene/plugins/blender/exceptions/BlenderFileException.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.exception;
+package com.jme3.scene.plugins.blender.exceptions;
 
 /**
  * This exception is thrown when blend file data is somehow invalid.

+ 2 - 2
engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderInputStream.java → engine/src/blender/com/jme3/scene/plugins/blender/file/BlenderInputStream.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.utils;
+package com.jme3.scene.plugins.blender.file;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
@@ -39,7 +39,7 @@ import java.util.logging.Logger;
 import java.util.zip.GZIPInputStream;
 
 import com.jme3.asset.AssetManager;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 
 /**
  * An input stream with random access to data.

+ 3 - 4
engine/src/blender/com/jme3/scene/plugins/blender/data/DnaBlockData.java → engine/src/blender/com/jme3/scene/plugins/blender/file/DnaBlockData.java

@@ -29,14 +29,13 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.data;
+package com.jme3.scene.plugins.blender.file;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 
 /**
  * The data block containing the description of the file.

+ 2 - 2
engine/src/blender/com/jme3/scene/plugins/blender/utils/DynamicArray.java → engine/src/blender/com/jme3/scene/plugins/blender/file/DynamicArray.java

@@ -29,9 +29,9 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.utils;
+package com.jme3.scene.plugins.blender.file;
 
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 
 /**
  * An array that can be dynamically modified/

+ 4 - 7
engine/src/blender/com/jme3/scene/plugins/blender/data/Field.java → engine/src/blender/com/jme3/scene/plugins/blender/file/Field.java

@@ -1,14 +1,11 @@
-package com.jme3.scene.plugins.blender.data;
+package com.jme3.scene.plugins.blender.file;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import com.jme3.scene.plugins.blender.data.Structure.DataType;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure.DataType;
 
 /**
  * This class represents a single field in the structure. It can be either a primitive type or a table or a reference to

+ 3 - 4
engine/src/blender/com/jme3/scene/plugins/blender/data/FileBlockHeader.java → engine/src/blender/com/jme3/scene/plugins/blender/file/FileBlockHeader.java

@@ -29,11 +29,10 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.data;
+package com.jme3.scene.plugins.blender.file;
 
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 
 /**
  * A class that holds the header data of a file block. The file block itself is not implemented. This class holds its

+ 3 - 4
engine/src/blender/com/jme3/scene/plugins/blender/utils/Pointer.java → engine/src/blender/com/jme3/scene/plugins/blender/file/Pointer.java

@@ -29,14 +29,13 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.utils;
+package com.jme3.scene.plugins.blender.file;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 
 /**
  * A class that represents a pointer of any level that can be stored in the file.

+ 3 - 5
engine/src/blender/com/jme3/scene/plugins/blender/data/Structure.java → engine/src/blender/com/jme3/scene/plugins/blender/file/Structure.java

@@ -29,17 +29,15 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.data;
+package com.jme3.scene.plugins.blender.file;
 
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 
 /**
  * A class representing a single structure in the file.

+ 0 - 132
engine/src/blender/com/jme3/scene/plugins/blender/helpers/ArmatureHelper.java

@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.animation.BoneTrack;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.BezierCurve;
-import com.jme3.scene.plugins.blender.structures.Ipo;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.Pointer;
-
-/**
- * This class defines the methods to calculate certain aspects of animation and armature functionalities.
- * @author Marcin Roguski
- */
-public class ArmatureHelper extends com.jme3.scene.plugins.blender.helpers.v249.ArmatureHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName());
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public ArmatureHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-
-    @Override
-    public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException {
-        if (blenderVersion < 250) {
-            return super.getTracks(actionStructure, dataRepository, objectName, animationName);
-        }
-        LOGGER.log(Level.INFO, "Getting tracks!");
-        int fps = dataRepository.getBlenderKey().getFps();
-        int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName);
-        Structure groups = (Structure) actionStructure.getFieldValue("groups");
-        List<Structure> actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup
-        if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {
-            throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");
-        }
-
-        List<BoneTrack> tracks = new ArrayList<BoneTrack>();
-        for (Structure actionGroup : actionGroups) {
-            String name = actionGroup.getFieldValue("name").toString();
-            Integer boneIndex = bonesMap.get(name);
-            if (boneIndex != null) {
-                List<Structure> channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository);
-                BezierCurve[] bezierCurves = new BezierCurve[channels.size()];
-                int channelCounter = 0;
-                for (Structure c : channels) {
-                    //reading rna path first
-                    BlenderInputStream bis = dataRepository.getInputStream();
-                    int currentPosition = bis.getPosition();
-                    Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path");
-                    FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress());
-                    bis.setPosition(dataFileBlock.getBlockPosition());
-                    String rnaPath = bis.readString();
-                    bis.setPosition(currentPosition);
-                    int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue();
-                    int type = this.getCurveType(rnaPath, arrayIndex);
-
-                    Pointer pBezTriple = (Pointer) c.getFieldValue("bezt");
-                    List<Structure> bezTriples = pBezTriple.fetchData(dataRepository.getInputStream());
-                    bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2);
-                }
-
-                Ipo ipo = new Ipo(bezierCurves);
-                tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps));
-            }
-        }
-        return tracks.toArray(new BoneTrack[tracks.size()]);
-    }
-
-    /**
-     * This method parses the information stored inside the curve rna path and returns the proper type
-     * of the curve.
-     * @param rnaPath the curve's rna path
-     * @param arrayIndex the array index of the stored data
-     * @return the type of the curve
-     */
-    protected int getCurveType(String rnaPath, int arrayIndex) {
-        if (rnaPath.endsWith(".location")) {
-            return Ipo.AC_LOC_X + arrayIndex;
-        }
-        if (rnaPath.endsWith(".rotation_quaternion")) {
-            return Ipo.AC_QUAT_W + arrayIndex;
-        }
-        if (rnaPath.endsWith(".scale")) {
-            return Ipo.AC_SIZE_X + arrayIndex;
-        }
-        throw new IllegalStateException("Unknown curve rna path: " + rnaPath);
-    }
-}

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

@@ -1,52 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.renderer.Camera;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-
-/**
- * A class that is used in light calculations.
- * @author Marcin Roguski
- */
-public class CameraHelper extends com.jme3.scene.plugins.blender.helpers.v249.CameraHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public CameraHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-
-    @Override
-    public Camera toCamera(Structure structure) throws BlenderFileException {
-        if (blenderVersion < 250) {
-            return super.toCamera(structure);
-        }
-        Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
-        int type = ((Number) structure.getFieldValue("type")).intValue();
-        if (type != 0 && type != 1) {
-            LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
-            type = 0;
-        }
-        //type==0 - perspective; type==1 - orthographic; perspective is used as default
-        result.setParallelProjection(type == 1);
-        float aspect = 0;
-        float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
-        float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
-        if (type == 0) {
-            aspect = ((Number) structure.getFieldValue("lens")).floatValue();
-        } else {
-            aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
-        }
-        result.setFrustumPerspective(45, aspect, clipsta, clipend);
-        return result;
-    }
-}

+ 0 - 38
engine/src/blender/com/jme3/scene/plugins/blender/helpers/ConstraintHelper.java

@@ -1,38 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers;
-
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-
-/**
- * This class should be used for constraint calculations.
- * @author Marcin Roguski
- */
-public class ConstraintHelper extends com.jme3.scene.plugins.blender.helpers.v249.ConstraintHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName());
-
-    /**
-     * Helper constructor. It's main task is to generate the affection functions. These functions are common to all
-     * ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall
-     * consider refactoring. The constructor parses the given blender version and stores the result. Some
-     * functionalities may differ in different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public ConstraintHelper(String blenderVersion, DataRepository dataRepository) {
-        super(blenderVersion, dataRepository);
-    }
-
-    @Override
-    public void loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
-        if (blenderVersion < 250) {
-            super.loadConstraints(objectStructure, dataRepository);
-        } else {
-            LOGGER.warning("Loading of constraints not yet implemented for version 2.5x !");
-            //TODO: to implement
-        }
-    }
-}

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

@@ -1,18 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * A class that is used in mesh calculations.
- * @author Marcin Roguski
- */
-public class CurvesHelper extends com.jme3.scene.plugins.blender.helpers.v249.CurvesHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public CurvesHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,19 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * This class helps to compute values from interpolation curves for features like animation or constraint influence. The
- * curves are 3rd degree bezier curves.
- * @author Marcin Roguski
- */
-public class IpoHelper extends com.jme3.scene.plugins.blender.helpers.v249.IpoHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public IpoHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * A class that is used in light calculations.
- * @author Marcin Roguski
- */
-public class LightHelper extends com.jme3.scene.plugins.blender.helpers.v249.LightHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public LightHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-public class MaterialHelper extends com.jme3.scene.plugins.blender.helpers.v249.MaterialHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public MaterialHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * A class that is used in mesh calculations.
- * @author Marcin Roguski
- */
-public class MeshHelper extends com.jme3.scene.plugins.blender.helpers.v249.MeshHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public MeshHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

+ 0 - 49
engine/src/blender/com/jme3/scene/plugins/blender/helpers/ModifierHelper.java

@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * A class that is used in modifiers calculations.
- * @author Marcin Roguski
- */
-public class ModifierHelper extends com.jme3.scene.plugins.blender.helpers.v249.ModifierHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public ModifierHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,52 +0,0 @@
-/*
- *
- * $Id: noise.c 14611 2008-04-29 08:24:33Z campbellbarton $
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * Methods of this class are copied from blender 2.49 source code and modified so that they can be used in java. They are mostly NOT
- * documented because they are not documented in blender's source code. If I find a proper description or discover what they actually do and
- * what parameters mean - I shall describe such methods :) If anyone have some hint what these methods are doing please rite the proper
- * javadoc documentation. These methods should be used to create generated textures.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class NoiseHelper extends com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper {
-
-    /**
-     * Constructor. Stores the blender version number and loads the constants needed for computations.
-     * 
-     * @param blenderVersion
-     *            the number of blender version
-     */
-    public NoiseHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

+ 0 - 49
engine/src/blender/com/jme3/scene/plugins/blender/helpers/ObjectHelper.java

@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * A class that is used in object calculations.
- * @author Marcin Roguski
- */
-public class ObjectHelper extends com.jme3.scene.plugins.blender.helpers.v249.ObjectHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public ObjectHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,18 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers;
-
-/**
- * This class helps to import the special effects from blender file.
- * @author Marcin Roguski (Kaelthas)
- */
-public class ParticlesHelper extends com.jme3.scene.plugins.blender.helpers.v249.ParticlesHelper {
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public ParticlesHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-}

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

@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers;
-
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.texture.Texture;
-
-/**
- * A class that is used in texture calculations.
- * @author Marcin Roguski
- */
-public class TextureHelper extends com.jme3.scene.plugins.blender.helpers.v249.TextureHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(TextureHelper.class.getName());
-    public static final int TEX_POINTDENSITY = 14;
-    public static final int TEX_VOXELDATA = 15;
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public TextureHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-
-    @Override
-    public Texture getTexture(Structure tex, DataRepository dataRepository) throws BlenderFileException {
-        if (blenderVersion < 250) {
-            return super.getTexture(tex, dataRepository);
-        }
-        Texture result = (Texture) dataRepository.getLoadedFeature(tex.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
-        if (result != null) {
-            return result;
-        }
-        int type = ((Number) tex.getFieldValue("type")).intValue();
-        switch (type) {
-            case TEX_POINTDENSITY:
-                LOGGER.warning("Point density texture loading currently not supported!");
-                break;
-            case TEX_VOXELDATA:
-                LOGGER.warning("Voxel data texture loading currently not supported!");
-                break;
-            default:
-                result = super.getTexture(tex, dataRepository);
-        }
-        return result;
-    }
-}

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

@@ -1,65 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers.v249;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.asset.BlenderKey.FeaturesToLoad;
-import com.jme3.renderer.Camera;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-
-/**
- * A class that is used in light calculations.
- * @author Marcin Roguski
- */
-public class CameraHelper extends AbstractBlenderHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName());
-    protected static final int DEFAULT_CAM_WIDTH = 100;
-    protected static final int DEFAULT_CAM_HEIGHT = 100;
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public CameraHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-
-    /**
-     * This method reads the camera object.
-     * @param structure the structure containing the camera data
-     * @return the camera object
-     * @throws BlenderFileException
-     */
-    public Camera toCamera(Structure structure) throws BlenderFileException {
-        Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);
-        int type = ((Number) structure.getFieldValue("type")).intValue();
-        if (type != 0 && type != 1) {
-            LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
-            type = 0;
-        }
-        //type==0 - perspective; type==1 - orthographic; perspective is used as default
-        result.setParallelProjection(type == 1);
-        float angle = ((Number) structure.getFieldValue("angle")).floatValue();
-        float aspect = 0;
-        float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
-        float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
-        if (type == 0) {
-            aspect = ((Number) structure.getFieldValue("lens")).floatValue();
-        } else {
-            aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
-        }
-        result.setFrustumPerspective(angle, aspect, clipsta, clipend);
-        return result;
-    }
-    
-    @Override
-    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
-    	return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0;
-    }
-}

+ 0 - 756
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java

@@ -1,756 +0,0 @@
-package com.jme3.scene.plugins.blender.helpers.v249;
-
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-
-import com.jme3.animation.Bone;
-import com.jme3.animation.BoneAnimation;
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.Skeleton;
-import com.jme3.math.FastMath;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-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.Space;
-import com.jme3.scene.plugins.blender.structures.ConstraintType;
-import com.jme3.scene.plugins.blender.structures.Ipo;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.Pointer;
-
-/**
- * This class should be used for constraint calculations.
- * @author Marcin Roguski
- */
-public class ConstraintHelper extends AbstractBlenderHelper {
-
-	/**
-	 * A table containing implementations of influence functions for constraints. It should contain functions for
-	 * blender at least 249 and higher.
-	 */
-	protected static AbstractInfluenceFunction[] influenceFunctions;
-	/**
-	 * Constraints stored for object with the given old memory address.
-	 */
-	protected Map<Long, Constraint[]> constraints = new HashMap<Long, Constraint[]>();
-
-	/**
-	 * Helper constructor. It's main task is to generate the affection functions. These functions are common to all
-	 * ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall
-	 * consider refactoring. The constructor parses the given blender version and stores the result. Some
-	 * functionalities may differ in different blender versions.
-	 * @param blenderVersion
-	 *        the version read from the blend file
-	 */
-	public ConstraintHelper(String blenderVersion, DataRepository dataRepository) {
-		super(blenderVersion);
-		this.initializeConstraintFunctions(dataRepository);
-	}
-
-	/**
-	 * This method initializes constraint functions for Blender 2.49.
-	 * @param dataRepository
-	 *           			the data repository
-	 */
-	private synchronized void initializeConstraintFunctions(DataRepository dataRepository) {
-		if (influenceFunctions == null) {
-			influenceFunctions = new AbstractInfluenceFunction[ConstraintType.getLastDefinedTypeValue() + 1];
-			//ACTION constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_ACTION.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_ACTION, dataRepository) {
-			};
-
-			//CHILDOF constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_CHILDOF.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_CHILDOF, dataRepository) {
-			};
-
-			//CLAMPTO constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_CLAMPTO.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_CLAMPTO, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					this.validateConstraintType(constraint.getData());
-					LOGGER.log(Level.INFO, "{0} not active! Curves not yet implemented!", constraint.getName());//TODO: implement when curves are implemented
-				}
-			};
-
-			//DISTLIMIT constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_DISTLIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_DISTLIMIT, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintStructure = constraint.getData();
-					this.validateConstraintType(constraintStructure);
-					Vector3f targetLocation = this.getTargetLocation(constraint);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						//TODO: target vertex group !!!
-						float dist = ((Number) constraintStructure.getFieldValue("dist")).floatValue();
-						int mode = ((Number) constraintStructure.getFieldValue("mode")).intValue();
-
-						int maxFrames = boneTrack.getTimes().length;
-						Vector3f[] translations = boneTrack.getTranslations();
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							Vector3f v = translations[frame].subtract(targetLocation);
-							float currentDistance = v.length();
-							float influence = constraint.getIpo().calculateValue(frame);
-							float modifier = 0.0f;
-							switch (mode) {
-								case LIMITDIST_INSIDE:
-									if (currentDistance >= dist) {
-										modifier = (dist - currentDistance) / currentDistance;
-									}
-									break;
-								case LIMITDIST_ONSURFACE:
-									modifier = (dist - currentDistance) / currentDistance;
-									break;
-								case LIMITDIST_OUTSIDE:
-									if (currentDistance <= dist) {
-										modifier = (dist - currentDistance) / currentDistance;
-									}
-									break;
-								default:
-									throw new IllegalStateException("Unknown distance limit constraint mode: " + mode);
-							}
-							translations[frame].addLocal(v.multLocal(modifier * influence));
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales());
-					}
-				}
-			};
-
-			//FOLLOWPATH constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_FOLLOWPATH.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_FOLLOWPATH, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					this.validateConstraintType(constraint.getData());
-					LOGGER.log(Level.INFO, "{0} not active! Curves not yet implemented!", constraint.getName());//TODO: implement when curves are implemented
-				}
-			};
-
-			//KINEMATIC constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_KINEMATIC.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_KINEMATIC, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					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());
-					}
-				}
-
-				/**
-				 * This method returns bones used for rotation calculations.
-				 * @param bone
-				 *        the bone to which the constraint is applied
-				 * @param skeleton
-				 *        the skeleton owning the bone and its ancestors
-				 * @param boneAnimation
-				 *        the bone animation data that stores the traces for the skeleton's bones
-				 * @return a list of bones to imitate the bone's movement during IK solving
-				 */
-				private CalculationBone[] getBonesToCalculate(Bone bone, Skeleton skeleton, BoneAnimation boneAnimation) {
-					List<CalculationBone> bonesList = new ArrayList<CalculationBone>();
-					Bone currentBone = bone;
-					do {
-						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();
-					} while (currentBone != null);
-					//attaching children
-					CalculationBone[] result = bonesList.toArray(new CalculationBone[bonesList.size()]);
-					for (int i = result.length - 1; i > 0; --i) {
-						result[i].attachChild(result[i - 1]);
-					}
-					return result;
-				}
-			};
-
-			//LOCKTRACK constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_LOCKTRACK.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_LOCKTRACK, dataRepository) {
-			};
-
-			//LOCLIKE constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_LOCLIKE.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_LOCLIKE, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintData = constraint.getData();
-					this.validateConstraintType(constraintData);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						Vector3f targetLocation = this.getTargetLocation(constraint);
-						int flag = ((Number) constraintData.getFieldValue("flag")).intValue();
-						Vector3f[] translations = boneTrack.getTranslations();
-						int maxFrames = translations.length;
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							Vector3f offset = Vector3f.ZERO;
-							if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original location to the copied location
-								offset = translations[frame].clone();
-							}
-
-							if ((flag & LOCLIKE_X) != 0) {
-								translations[frame].x = targetLocation.x;
-								if ((flag & LOCLIKE_X_INVERT) != 0) {
-									translations[frame].x = -translations[frame].x;
-								}
-							} else if ((flag & LOCLIKE_Y) != 0) {
-								translations[frame].y = targetLocation.y;
-								if ((flag & LOCLIKE_Y_INVERT) != 0) {
-									translations[frame].y = -translations[frame].y;
-								}
-							} else if ((flag & LOCLIKE_Z) != 0) {
-								translations[frame].z = targetLocation.z;
-								if ((flag & LOCLIKE_Z_INVERT) != 0) {
-									translations[frame].z = -translations[frame].z;
-								}
-							}
-							translations[frame].addLocal(offset);//TODO: ipo influence
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales());
-					}
-				}
-			};
-
-			//LOCLIMIT constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_LOCLIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_LOCLIMIT, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintStructure = constraint.getData();
-					this.validateConstraintType(constraintStructure);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						int flag = ((Number) constraintStructure.getFieldValue("flag")).intValue();
-						Vector3f[] translations = boneTrack.getTranslations();
-						int maxFrames = translations.length;
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							float influence = constraint.getIpo().calculateValue(frame);
-							if ((flag & LIMIT_XMIN) != 0) {
-								float xmin = ((Number) constraintStructure.getFieldValue("xmin")).floatValue();
-								if (translations[frame].x < xmin) {
-									translations[frame].x -= (translations[frame].x - xmin) * influence;
-								}
-							}
-							if ((flag & LIMIT_XMAX) != 0) {
-								float xmax = ((Number) constraintStructure.getFieldValue("xmax")).floatValue();
-								if (translations[frame].x > xmax) {
-									translations[frame].x -= (translations[frame].x - xmax) * influence;
-								}
-							}
-							if ((flag & LIMIT_YMIN) != 0) {
-								float ymin = ((Number) constraintStructure.getFieldValue("ymin")).floatValue();
-								if (translations[frame].y < ymin) {
-									translations[frame].y -= (translations[frame].y - ymin) * influence;
-								}
-							}
-							if ((flag & LIMIT_YMAX) != 0) {
-								float ymax = ((Number) constraintStructure.getFieldValue("ymax")).floatValue();
-								if (translations[frame].y > ymax) {
-									translations[frame].y -= (translations[frame].y - ymax) * influence;
-								}
-							}
-							if ((flag & LIMIT_ZMIN) != 0) {
-								float zmin = ((Number) constraintStructure.getFieldValue("zmin")).floatValue();
-								if (translations[frame].z < zmin) {
-									translations[frame].z -= (translations[frame].z - zmin) * influence;
-								}
-							}
-							if ((flag & LIMIT_ZMAX) != 0) {
-								float zmax = ((Number) constraintStructure.getFieldValue("zmax")).floatValue();
-								if (translations[frame].z > zmax) {
-									translations[frame].z -= (translations[frame].z - zmax) * influence;
-								}
-							}//TODO: consider constraint space !!!
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales());
-					}
-				}
-			};
-
-			//MINMAX constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_MINMAX.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_MINMAX, dataRepository) {
-			};
-
-			//NULL constraint - does nothing
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_NULL.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_NULL, dataRepository) {
-			};
-
-			//PYTHON constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_PYTHON.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_PYTHON, dataRepository) {
-			};
-
-			//RIGIDBODYJOINT constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_RIGIDBODYJOINT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_RIGIDBODYJOINT, dataRepository) {
-			};
-
-			//ROTLIKE constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_ROTLIKE.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_ROTLIKE, dataRepository) {
-
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintData = constraint.getData();
-					this.validateConstraintType(constraintData);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						Quaternion targetRotation = this.getTargetRotation(constraint);
-						int flag = ((Number) constraintData.getFieldValue("flag")).intValue();
-						float[] targetAngles = targetRotation.toAngles(null);
-						Quaternion[] rotations = boneTrack.getRotations();
-						int maxFrames = rotations.length;
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							float[] angles = rotations[frame].toAngles(null);
-
-							Quaternion offset = Quaternion.IDENTITY;
-							if ((flag & ROTLIKE_OFFSET) != 0) {//we add the original rotation to the copied rotation
-								offset = rotations[frame].clone();
-							}
-
-							if ((flag & ROTLIKE_X) != 0) {
-								angles[0] = targetAngles[0];
-								if ((flag & ROTLIKE_X_INVERT) != 0) {
-									angles[0] = -angles[0];
-								}
-							} else if ((flag & ROTLIKE_Y) != 0) {
-								angles[1] = targetAngles[1];
-								if ((flag & ROTLIKE_Y_INVERT) != 0) {
-									angles[1] = -angles[1];
-								}
-							} else if ((flag & ROTLIKE_Z) != 0) {
-								angles[2] = targetAngles[2];
-								if ((flag & ROTLIKE_Z_INVERT) != 0) {
-									angles[2] = -angles[2];
-								}
-							}
-							rotations[frame].fromAngles(angles).multLocal(offset);//TODO: ipo influence
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales());
-					}
-				}
-			};
-
-			//ROTLIMIT constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_ROTLIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_ROTLIMIT, dataRepository) {
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintStructure = constraint.getData();
-					this.validateConstraintType(constraintStructure);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						int flag = ((Number) constraintStructure.getFieldValue("flag")).intValue();
-						Quaternion[] rotations = boneTrack.getRotations();
-						int maxFrames = rotations.length;
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							float[] angles = rotations[frame].toAngles(null);
-							float influence = constraint.getIpo().calculateValue(frame);
-							if ((flag & LIMIT_XROT) != 0) {
-								float xmin = ((Number) constraintStructure.getFieldValue("xmin")).floatValue() * FastMath.DEG_TO_RAD;
-								float xmax = ((Number) constraintStructure.getFieldValue("xmax")).floatValue() * FastMath.DEG_TO_RAD;
-								float difference = 0.0f;
-								if (angles[0] < xmin) {
-									difference = (angles[0] - xmin) * influence;
-								} else if (angles[0] > xmax) {
-									difference = (angles[0] - xmax) * influence;
-								}
-								angles[0] -= difference;
-							}
-							if ((flag & LIMIT_YROT) != 0) {
-								float ymin = ((Number) constraintStructure.getFieldValue("ymin")).floatValue() * FastMath.DEG_TO_RAD;
-								float ymax = ((Number) constraintStructure.getFieldValue("ymax")).floatValue() * FastMath.DEG_TO_RAD;
-								float difference = 0.0f;
-								if (angles[1] < ymin) {
-									difference = (angles[1] - ymin) * influence;
-								} else if (angles[1] > ymax) {
-									difference = (angles[1] - ymax) * influence;
-								}
-								angles[1] -= difference;
-							}
-							if ((flag & LIMIT_ZROT) != 0) {
-								float zmin = ((Number) constraintStructure.getFieldValue("zmin")).floatValue() * FastMath.DEG_TO_RAD;
-								float zmax = ((Number) constraintStructure.getFieldValue("zmax")).floatValue() * FastMath.DEG_TO_RAD;
-								float difference = 0.0f;
-								if (angles[2] < zmin) {
-									difference = (angles[2] - zmin) * influence;
-								} else if (angles[2] > zmax) {
-									difference = (angles[2] - zmax) * influence;
-								}
-								angles[2] -= difference;
-							}
-							rotations[frame].fromAngles(angles);//TODO: consider constraint space !!!
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales());
-					}
-				}
-			};
-
-			//SHRINKWRAP constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_SHRINKWRAP.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_SHRINKWRAP, dataRepository) {
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintStructure = constraint.getData();
-					this.validateConstraintType(constraintStructure);
-					
-					//loading mesh points (blender ensures that the target is a mesh-object)
-					List<Vector3f> pts = new ArrayList<Vector3f>();
-					try {
-						Node node = (Node)this.getTarget(constraint, LoadedFeatureDataType.LOADED_FEATURE);
-						for(Spatial spatial : node.getChildren()) {
-							if(spatial instanceof Geometry) {
-								Mesh mesh = ((Geometry) spatial).getMesh();
-								FloatBuffer floatBuffer = mesh.getFloatBuffer(Type.Position);
-								for(int i=0;i<floatBuffer.limit();i+=3) {
-									pts.add(new Vector3f(floatBuffer.get(i), floatBuffer.get(i + 1), floatBuffer.get(i + 2)));
-								}
-							}
-						}
-						
-						//modifying traces
-						BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-						if (boneTrack != null) {
-							Vector3f[] translations = boneTrack.getTranslations();
-							Quaternion[] rotations = boneTrack.getRotations();
-							int maxFrames = translations.length;
-							for (int frame = 0; frame < maxFrames; ++frame) {
-								Vector3f currentTranslation = translations[frame];
-								
-								//looking for minimum distanced point
-								Vector3f minDistancePoint = null;
-								float distance = Float.MAX_VALUE;
-								for(Vector3f p : pts) {
-									float temp = currentTranslation.distance(p);
-									if(temp < distance) {
-										distance = temp;
-										minDistancePoint = p;
-									}
-								}
-								translations[frame] = minDistancePoint.clone();
-							}
-							
-							boneTrack.setKeyframes(boneTrack.getTimes(), translations, rotations, boneTrack.getScales());
-						}
-					} catch (BlenderFileException e) {
-						LOGGER.severe(e.getLocalizedMessage());
-					}
-				}
-			};
-
-			//SIZELIKE constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_SIZELIKE.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_SIZELIKE, dataRepository) {
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintData = constraint.getData();
-					this.validateConstraintType(constraintData);
-					Vector3f targetScale = this.getTargetLocation(constraint);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						int flag = ((Number) constraintData.getFieldValue("flag")).intValue();
-						Vector3f[] scales = boneTrack.getScales();
-						int maxFrames = scales.length;
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							Vector3f offset = Vector3f.ZERO;
-							if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original scale to the copied scale
-								offset = scales[frame].clone();
-							}
-
-							if ((flag & SIZELIKE_X) != 0) {
-								scales[frame].x = targetScale.x;
-							} else if ((flag & SIZELIKE_Y) != 0) {
-								scales[frame].y = targetScale.y;
-							} else if ((flag & SIZELIKE_Z) != 0) {
-								scales[frame].z = targetScale.z;
-							}
-							scales[frame].addLocal(offset);//TODO: ipo influence
-							//TODO: add or multiply???
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), boneTrack.getRotations(), scales);
-					}
-				}
-			};
-
-			//SIZELIMIT constraint
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_SIZELIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_SIZELIMIT, dataRepository) {
-				@Override
-				public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-					Structure constraintStructure = constraint.getData();
-					this.validateConstraintType(constraintStructure);
-					BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint);
-					if (boneTrack != null) {
-						int flag = ((Number) constraintStructure.getFieldValue("flag")).intValue();
-						Vector3f[] scales = boneTrack.getScales();
-						int maxFrames = scales.length;
-						for (int frame = 0; frame < maxFrames; ++frame) {
-							float influence = constraint.getIpo().calculateValue(frame);
-							if ((flag & LIMIT_XMIN) != 0) {
-								float xmin = ((Number) constraintStructure.getFieldValue("xmin")).floatValue();
-								if (scales[frame].x < xmin) {
-									scales[frame].x -= (scales[frame].x - xmin) * influence;
-								}
-							}
-							if ((flag & LIMIT_XMAX) != 0) {
-								float xmax = ((Number) constraintStructure.getFieldValue("xmax")).floatValue();
-								if (scales[frame].x > xmax) {
-									scales[frame].x -= (scales[frame].x - xmax) * influence;
-								}
-							}
-							if ((flag & LIMIT_YMIN) != 0) {
-								float ymin = ((Number) constraintStructure.getFieldValue("ymin")).floatValue();
-								if (scales[frame].y < ymin) {
-									scales[frame].y -= (scales[frame].y - ymin) * influence;
-								}
-							}
-							if ((flag & LIMIT_YMAX) != 0) {
-								float ymax = ((Number) constraintStructure.getFieldValue("ymax")).floatValue();
-								if (scales[frame].y > ymax) {
-									scales[frame].y -= (scales[frame].y - ymax) * influence;
-								}
-							}
-							if ((flag & LIMIT_ZMIN) != 0) {
-								float zmin = ((Number) constraintStructure.getFieldValue("zmin")).floatValue();
-								if (scales[frame].z < zmin) {
-									scales[frame].z -= (scales[frame].z - zmin) * influence;
-								}
-							}
-							if ((flag & LIMIT_ZMAX) != 0) {
-								float zmax = ((Number) constraintStructure.getFieldValue("zmax")).floatValue();
-								if (scales[frame].z > zmax) {
-									scales[frame].z -= (scales[frame].z - zmax) * influence;
-								}
-							}//TODO: consider constraint space !!!
-						}
-						boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), boneTrack.getRotations(), scales);
-					}
-				}
-			};
-
-			//STRETCHTO constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_STRETCHTO.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_STRETCHTO, dataRepository) {
-			};
-
-			//TRANSFORM constraint (TODO: to implement)
-			influenceFunctions[ConstraintType.CONSTRAINT_TYPE_TRANSFORM.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_TRANSFORM, dataRepository) {
-			};
-		}
-	}
-
-	/**
-	 * This method reads constraints for for the given structure. The constraints are loaded only once for object/bone.
-	 * @param ownerOMA
-	 *        the owner's old memory address
-	 * @param objectStructure
-	 *        the structure we read constraint's for
-	 * @param dataRepository
-	 *        the data repository
-	 * @throws BlenderFileException
-	 */
-	public void loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
-		// reading influence ipos for the constraints
-		IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
-		Map<String, Map<String, Ipo>> constraintsIpos = new HashMap<String, Map<String, Ipo>>();
-		Pointer pActions = (Pointer) objectStructure.getFieldValue("action");
-		if (pActions.isNotNull()) {
-			List<Structure> actions = pActions.fetchData(dataRepository.getInputStream());
-			for (Structure action : actions) {
-				Structure chanbase = (Structure) action.getFieldValue("chanbase");
-				List<Structure> actionChannels = chanbase.evaluateListBase(dataRepository);
-				for (Structure actionChannel : actionChannels) {
-					Map<String, Ipo> ipos = new HashMap<String, Ipo>();
-					Structure constChannels = (Structure) actionChannel.getFieldValue("constraintChannels");
-					List<Structure> constraintChannels = constChannels.evaluateListBase(dataRepository);
-					for (Structure constraintChannel : constraintChannels) {
-						Pointer pIpo = (Pointer) constraintChannel.getFieldValue("ipo");
-						if (pIpo.isNotNull()) {
-							String constraintName = constraintChannel.getFieldValue("name").toString();
-							Ipo ipo = ipoHelper.createIpo(pIpo.fetchData(dataRepository.getInputStream()).get(0), dataRepository);
-							ipos.put(constraintName, ipo);
-						}
-					}
-					String actionName = actionChannel.getFieldValue("name").toString();
-					constraintsIpos.put(actionName, ipos);
-				}
-			}
-		}
-
-		//loading constraints connected with the object's bones
-		List<Constraint> constraintsList = new ArrayList<Constraint>();
-		Pointer pPose = (Pointer) objectStructure.getFieldValue("pose");//TODO: what if the object has two armatures ????
-		if (pPose.isNotNull()) {
-			//getting pose channels
-			List<Structure> poseChannels = ((Structure) pPose.fetchData(dataRepository.getInputStream()).get(0).getFieldValue("chanbase")).evaluateListBase(dataRepository);
-			for (Structure poseChannel : poseChannels) {
-				Long boneOMA = Long.valueOf(((Pointer) poseChannel.getFieldValue("bone")).getOldMemoryAddress());
-				//the name is read directly from structure because bone might not yet be loaded
-				String name = dataRepository.getFileBlock(boneOMA).getStructure(dataRepository).getFieldValue("name").toString();
-				List<Structure> constraints = ((Structure) poseChannel.getFieldValue("constraints")).evaluateListBase(dataRepository);
-				for (Structure constraint : constraints) {
-					int type = ((Number) constraint.getFieldValue("type")).intValue();
-					String constraintName = constraint.getFieldValue("name").toString();
-					Map<String, Ipo> ipoMap = constraintsIpos.get(name);
-					Ipo ipo = ipoMap==null ? null : ipoMap.get(constraintName);
-					if (ipo == null) {
-						float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
-						ipo = ipoHelper.createIpo(enforce);
-					}
-					Space ownerSpace = Space.valueOf(((Number) constraint.getFieldValue("ownspace")).byteValue());
-					Space targetSpace = Space.valueOf(((Number) constraint.getFieldValue("tarspace")).byteValue());
-					Constraint c = new Constraint(constraint, influenceFunctions[type], boneOMA, ownerSpace, targetSpace, ipo, dataRepository);
-					constraintsList.add(c);
-				}
-			}
-		}
-		// TODO: reading constraints for objects (implement when object's animation will be available)
-		List<Structure> constraintChannels = ((Structure)objectStructure.getFieldValue("constraintChannels")).evaluateListBase(dataRepository);
-		for(Structure constraintChannel : constraintChannels) {
-			System.out.println(constraintChannel);
-		}
-
-		//loading constraints connected with the object itself (TODO: test this)
-		if(!this.constraints.containsKey(objectStructure.getOldMemoryAddress())) {
-			List<Structure> constraints = ((Structure)objectStructure.getFieldValue("constraints")).evaluateListBase(dataRepository);
-			Constraint[] result = new Constraint[constraints.size()];
-			int i = 0;
-			
-			for(Structure constraint : constraints) {
-				int type = ((Number)constraint.getFieldValue("type")).intValue();
-				String constraintName = constraint.getFieldValue("name").toString();
-				String objectName = objectStructure.getName();
-				
-				Map<String, Ipo> objectConstraintsIpos = constraintsIpos.get(objectName);
-				Ipo ipo = objectConstraintsIpos!=null ? objectConstraintsIpos.get(constraintName) : null;
-				if (ipo == null) {
-					float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue();
-					ipo = ipoHelper.createIpo(enforce);
-				}
-				Space ownerSpace = Space.valueOf(((Number) constraint.getFieldValue("ownspace")).byteValue());
-				Space targetSpace = Space.valueOf(((Number) constraint.getFieldValue("tarspace")).byteValue());
-				result[i++] = new Constraint(constraint, influenceFunctions[type], null, 
-											 ownerSpace, targetSpace, ipo, dataRepository);//TODO: influence ipos for object animation
-			}
-			this.constraints.put(objectStructure.getOldMemoryAddress(), result);
-		}
-		
-		if (constraintsList.size() > 0) {
-			this.constraints.put(objectStructure.getOldMemoryAddress(), constraintsList.toArray(new Constraint[constraintsList.size()]));
-		}
-	}
-
-	/**
-	 * This method returns a list of constraints of the feature's constraints. The order of constraints is important.
-	 * @param ownerOMA
-	 *        the owner's old memory address
-	 * @return a table of constraints for the feature specified by old memory address
-	 */
-	public Constraint[] getConstraints(Long ownerOMA) {
-		return constraints.get(ownerOMA);
-	}
-
-	@Override
-	public void clearState() {
-		constraints.clear();
-	}
-	
-	@Override
-	public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
-		return true;
-	}
-}

+ 0 - 762
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java

@@ -1,762 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.helpers.v249;
-
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.animation.AnimControl;
-import com.jme3.animation.Bone;
-import com.jme3.animation.BoneAnimation;
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.Skeleton;
-import com.jme3.animation.SkeletonControl;
-import com.jme3.bounding.BoundingBox;
-import com.jme3.bounding.BoundingSphere;
-import com.jme3.bounding.BoundingVolume;
-import com.jme3.effect.ParticleEmitter;
-import com.jme3.effect.shapes.EmitterMeshVertexShape;
-import com.jme3.effect.shapes.EmitterShape;
-import com.jme3.material.Material;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.helpers.ParticlesHelper;
-import com.jme3.scene.plugins.blender.structures.Constraint;
-import com.jme3.scene.plugins.blender.structures.Ipo;
-import com.jme3.scene.plugins.blender.structures.Modifier;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
-import com.jme3.scene.plugins.ogre.AnimData;
-import com.jme3.scene.shape.Curve;
-
-/**
- * A class that is used in modifiers calculations.
- * @author Marcin Roguski
- */
-public class ModifierHelper extends AbstractBlenderHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(ModifierHelper.class.getName());
-
-    /**
-     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
-     * different blender versions.
-     * @param blenderVersion
-     *        the version read from the blend file
-     */
-    public ModifierHelper(String blenderVersion) {
-        super(blenderVersion);
-    }
-
-    /**
-     * This method applies modifier to the object.
-     * @param node
-     *        the loaded object
-     * @param modifier
-     *        the modifier to apply
-     * @param dataRepository
-     *        the data repository
-     * @return the node to whom the modifier was applied
-     */
-    public Node applyModifier(Node node, Modifier modifier, DataRepository dataRepository) {
-        if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {
-            return this.applyArmatureModifierData(node, modifier, dataRepository);
-        } else if (Modifier.OBJECT_ANIMATION_MODIFIER_DATA.equals(modifier.getType())) {
-            return this.applyObjectAnimationModifier(node, modifier, dataRepository);
-        } else if (Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {
-            return this.applyArrayModifierData(node, modifier, dataRepository);
-        } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {
-            return this.applyParticleSystemModifierData(node, modifier, dataRepository);
-        } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifier.getType())) {
-            return this.applyMirrorModifierData(node, modifier, dataRepository);
-        } else {
-            LOGGER.log(Level.WARNING, "Modifier: {0} not yet implemented!!!", modifier.getType());
-            return node;
-        }
-    }
-
-    /**
-     * This method reads the given object's modifiers.
-     * @param objectStructure
-     *        the object structure
-     * @param dataRepository
-     *        the data repository
-     * @param converter
-     *        the converter object (in some cases we need to read an object first before loading the modifier)
-     * @throws BlenderFileException
-     *         this exception is thrown when the blender file is somehow corrupted
-     */
-    @SuppressWarnings("unchecked")
-    public void readModifiers(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
-        Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers");
-        List<Structure> modifiers = modifiersListBase.evaluateListBase(dataRepository);
-        for (Structure modifier : modifiers) {
-            Object loadedModifier = null;
-            Object modifierAdditionalData = null;
-            if (Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {// ****************ARRAY MODIFIER
-                Map<String, Object> params = new HashMap<String, Object>();
-
-                Number fittype = (Number) modifier.getFieldValue("fit_type");
-                params.put("fittype", fittype);
-                switch (fittype.intValue()) {
-                    case 0:// FIXED COUNT
-                        params.put("count", modifier.getFieldValue("count"));
-                        break;
-                    case 1:// FIXED LENGTH
-                        params.put("length", modifier.getFieldValue("length"));
-                        break;
-                    case 2:// FITCURVE
-                        Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob");
-                        float length = 0;
-                        if (pCurveOb.isNotNull()) {
-                            Structure curveStructure = pCurveOb.fetchData(dataRepository.getInputStream()).get(0);
-                            ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-                            Node curveObject = (Node) objectHelper.toObject(curveStructure, dataRepository);
-                            Set<Number> referencesToCurveLengths = new HashSet<Number>(curveObject.getChildren().size());
-                            for (Spatial spatial : curveObject.getChildren()) {
-                                if (spatial instanceof Geometry) {
-                                    Mesh mesh = ((Geometry) spatial).getMesh();
-                                    if (mesh instanceof Curve) {
-                                        length += ((Curve) mesh).getLength();
-                                    } else {
-                                        //if bevel object has several parts then each mesh will have the same reference
-                                        //to length value (and we should use only one)
-                                        Number curveLength = spatial.getUserData("curveLength");
-                                        if (curveLength != null && !referencesToCurveLengths.contains(curveLength)) {
-                                            length += curveLength.floatValue();
-                                            referencesToCurveLengths.add(curveLength);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        params.put("length", Float.valueOf(length));
-                        params.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH
-                        break;
-                    default:
-                        assert false : "Unknown array modifier fit type: " + fittype;
-                }
-
-                // offset parameters
-                int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue();
-                if ((offsettype & 0x01) != 0) {// Constant offset
-                    DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifier.getFieldValue("offset");
-                    float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()};
-                    params.put("offset", offset);
-                }
-                if ((offsettype & 0x02) != 0) {// Relative offset
-                    DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifier.getFieldValue("scale");
-                    float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()};
-                    params.put("scale", scale);
-                }
-                if ((offsettype & 0x04) != 0) {// Object offset
-                    Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob");
-                    if (pOffsetObject.isNotNull()) {
-                        params.put("offsetob", pOffsetObject);
-                    }
-                }
-
-                // start cap and end cap
-                Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap");
-                if (pStartCap.isNotNull()) {
-                    params.put("startcap", pStartCap);
-                }
-                Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap");
-                if (pEndCap.isNotNull()) {
-                    params.put("endcap", pEndCap);
-                }
-                loadedModifier = params;
-            } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifier.getType())) {// ****************MIRROR MODIFIER
-                Map<String, Object> params = new HashMap<String, Object>();
-
-                params.put("flag", modifier.getFieldValue("flag"));
-                params.put("tolerance", modifier.getFieldValue("tolerance"));
-                Pointer pMirrorOb = (Pointer) modifier.getFieldValue("mirror_ob");
-                if (pMirrorOb.isNotNull()) {
-                    params.put("mirrorob", pMirrorOb);
-                }
-                loadedModifier = params;
-            } else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {// ****************ARMATURE MODIFIER
-                Pointer pArmatureObject = (Pointer) modifier.getFieldValue("object");
-                if (pArmatureObject.isNotNull()) {
-                    ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-                    Structure armatureObject = (Structure) dataRepository.getLoadedFeature(pArmatureObject.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_STRUCTURE);
-                    if (armatureObject == null) {// we check this first not to fetch the structure unnecessary
-                        armatureObject = pArmatureObject.fetchData(dataRepository.getInputStream()).get(0);
-                        objectHelper.toObject(armatureObject, dataRepository);
-                    }
-                    modifierAdditionalData = armatureObject.getOldMemoryAddress();
-                    ArmatureHelper armatureHelper = dataRepository.getHelper(ArmatureHelper.class);
-
-                    // changing bones matrices so that they fit the current object (that is why we need a copy of a skeleton)
-                    Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject);
-                    Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert();
-                    Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix);
-                    Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation);
-
-                    //setting the bones structure inside the skeleton (thus completing its loading)
-                    Skeleton skeleton = new Skeleton(bones);
-                    dataRepository.addLoadedFeatures(armatureObject.getOldMemoryAddress(), armatureObject.getName(), armatureObject, skeleton);
-
-                    String objectName = objectStructure.getName();
-                    Set<String> animationNames = dataRepository.getBlenderKey().getAnimationNames(objectName);
-                    if (animationNames != null && animationNames.size() > 0) {
-                        ArrayList<BoneAnimation> animations = new ArrayList<BoneAnimation>();
-                        List<FileBlockHeader> actionHeaders = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
-                        for (FileBlockHeader header : actionHeaders) {
-                            Structure actionStructure = header.getStructure(dataRepository);
-                            String actionName = actionStructure.getName();
-                            if (animationNames.contains(actionName)) {
-                                int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, actionName);
-                                int fps = dataRepository.getBlenderKey().getFps();
-                                float start = (float) animationFrames[0] / (float) fps;
-                                float stop = (float) animationFrames[1] / (float) fps;
-                                BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start);
-                                boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, dataRepository, objectName, actionName));
-                                animations.add(boneAnimation);
-                            }
-                        }
-                        loadedModifier = new AnimData(new Skeleton(bones), animations);
-                    }
-                } else {
-                    LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifier.getType());
-                }
-            } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {// ****************PARTICLES MODIFIER
-                Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys");
-                if (pParticleSystem.isNotNull()) {
-                    ParticlesHelper particlesHelper = dataRepository.getHelper(ParticlesHelper.class);
-                    Structure particleSystem = pParticleSystem.fetchData(dataRepository.getInputStream()).get(0);
-                    loadedModifier = particlesHelper.toParticleEmitter(particleSystem, dataRepository);
-                }
-            }
-            // adding modifier to the modifier's lists
-            if (loadedModifier != null) {
-                dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier.getType(), loadedModifier, modifierAdditionalData);
-                modifierAdditionalData = null;
-            }
-        }
-
-        //at the end read object's animation modifier
-        Modifier objectAnimationModifier = this.readObjectAnimation(objectStructure, dataRepository);
-        if (objectAnimationModifier != null) {
-            dataRepository.addModifier(objectStructure.getOldMemoryAddress(),
-                    objectAnimationModifier.getType(),
-                    objectAnimationModifier.getJmeModifierRepresentation(),
-                    objectAnimationModifier.getAdditionalData());
-        }
-    }
-
-    /**
-     * This method reads animation of the object itself (without bones) and stores it as an ArmatureModifierData
-     * modifier. The animation is returned as a modifier. It should be later applied regardless other modifiers. The
-     * reason for this is that object may not have modifiers added but it's animation should be working.
-     * @param objectStructure
-     *        the structure of the object
-     * @param dataRepository
-     *        the data repository
-     * @return animation modifier is returned, it should be separately applied when the object is loaded
-     * @throws BlenderFileException
-     *         this exception is thrown when the blender file is somehow corrupted
-     */
-    protected Modifier readObjectAnimation(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
-        Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo");
-        if (pIpo.isNotNull()) {
-            //check if there is an action name connected with this ipo
-            String objectAnimationName = null;
-            List<FileBlockHeader> actionBlocks = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
-            for (FileBlockHeader actionBlock : actionBlocks) {
-                Structure action = actionBlock.getStructure(dataRepository);
-                List<Structure> actionChannels = ((Structure) action.getFieldValue("chanbase")).evaluateListBase(dataRepository);
-                if (actionChannels.size() == 1) {//object's animtion action has only one channel
-                    Pointer pChannelIpo = (Pointer) actionChannels.get(0).getFieldValue("ipo");
-                    if (pChannelIpo.equals(pIpo)) {
-                        objectAnimationName = action.getName();
-                        break;
-                    }
-                }
-            }
-
-            String objectName = objectStructure.getName();
-            if (objectAnimationName == null) {//set the object's animation name to object's name
-                objectAnimationName = objectName;
-            }
-
-            IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
-            Structure ipoStructure = pIpo.fetchData(dataRepository.getInputStream()).get(0);
-            Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository);
-            int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, objectAnimationName);
-            if (animationFrames == null) {//if the name was created here there are no frames set for the animation
-                animationFrames = new int[]{1, ipo.getLastFrame()};
-            }
-            int fps = dataRepository.getBlenderKey().getFps();
-            float start = (float) animationFrames[0] / (float) fps;
-            float stop = (float) animationFrames[1] / (float) fps;
-
-            //calculating track for the only bone in this skeleton
-            BoneTrack[] tracks = new BoneTrack[1];
-            tracks[0] = ipo.calculateTrack(0, animationFrames[0], animationFrames[1], fps);
-
-            BoneAnimation boneAnimation = new BoneAnimation(objectAnimationName, stop - start);
-            boneAnimation.setTracks(tracks);
-            ArrayList<BoneAnimation> animations = new ArrayList<BoneAnimation>(1);
-            animations.add(boneAnimation);
-
-            //preparing the object's bone
-            ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-            Transform t = objectHelper.getTransformation(objectStructure, dataRepository);
-            Bone bone = new Bone(null);
-            bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale());
-
-            return new Modifier(Modifier.OBJECT_ANIMATION_MODIFIER_DATA, new AnimData(new Skeleton(new Bone[]{bone}), animations), objectStructure.getOldMemoryAddress());
-        }
-        return null;
-    }
-
-    /**
-     * This method applies particles emitter to the given node.
-     * @param node
-     *        the particles emitter node
-     * @param modifier
-     *        the modifier containing the emitter data
-     * @param dataRepository
-     *        the data repository
-     * @return node with particles' emitter applied
-     */
-    protected Node applyParticleSystemModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
-        MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
-        ParticleEmitter emitter = (ParticleEmitter) modifier.getJmeModifierRepresentation();
-        emitter = emitter.clone();
-
-        // veryfying the alpha function for particles' texture
-        Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE;
-        char nameSuffix = emitter.getName().charAt(emitter.getName().length() - 1);
-        if (nameSuffix == 'B' || nameSuffix == 'N') {
-            alphaFunction = MaterialHelper.ALPHA_MASK_NONE;
-        }
-        // removing the type suffix from the name
-        emitter.setName(emitter.getName().substring(0, emitter.getName().length() - 1));
-
-        // applying emitter shape
-        EmitterShape emitterShape = emitter.getShape();
-        List<Mesh> meshes = new ArrayList<Mesh>();
-        for (Spatial spatial : node.getChildren()) {
-            if (spatial instanceof Geometry) {
-                Mesh mesh = ((Geometry) spatial).getMesh();
-                if (mesh != null) {
-                    meshes.add(mesh);
-                    Material material = materialHelper.getParticlesMaterial(((Geometry) spatial).getMaterial(), alphaFunction, dataRepository);
-                    emitter.setMaterial(material);// TODO: divide into several pieces
-                }
-            }
-        }
-        if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) {
-            ((EmitterMeshVertexShape) emitterShape).setMeshes(meshes);
-        }
-
-        node.attachChild(emitter);
-        return node;
-    }
-
-    /**
-     * This method applies ArmatureModifierData to the loaded object.
-     * @param node
-     *        the loaded object
-     * @param modifier
-     *        the modifier to apply
-     * @param dataRepository
-     *        the data repository
-     * @return the node to whom the modifier was applied
-     */
-    protected Node applyArmatureModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
-        AnimData ad = (AnimData) modifier.getJmeModifierRepresentation();
-        ArrayList<BoneAnimation> animList = ad.anims;
-        Long modifierArmatureObject = (Long) modifier.getAdditionalData();
-        if (animList != null && animList.size() > 0) {
-            ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class);
-            Constraint[] constraints = constraintHelper.getConstraints(modifierArmatureObject);
-            HashMap<String, BoneAnimation> anims = new HashMap<String, BoneAnimation>();
-            for (int i = 0; i < animList.size(); ++i) {
-                BoneAnimation boneAnimation = animList.get(i).clone();
-
-                // baking constraints into animations
-                if (constraints != null && constraints.length > 0) {
-                    for (Constraint constraint : constraints) {
-                        constraint.affectAnimation(ad.skeleton, boneAnimation);
-                    }
-                }
-
-                anims.put(boneAnimation.getName(), boneAnimation);
-            }
-
-            // getting meshes
-            Mesh[] meshes = null;
-            List<Mesh> meshesList = new ArrayList<Mesh>();
-            List<Spatial> children = node.getChildren();
-            for (Spatial child : children) {
-                if (child instanceof Geometry) {
-                    meshesList.add(((Geometry) child).getMesh());
-                }
-            }
-            if (meshesList.size() > 0) {
-                meshes = meshesList.toArray(new Mesh[meshesList.size()]);
-            }
-
-            // applying the control to the node
-            SkeletonControl skeletonControl = new SkeletonControl(meshes, ad.skeleton);
-            AnimControl control = node.getControl(AnimControl.class);
-
-            if (control == null) {
-                control = new AnimControl(ad.skeleton);
-            } else {
-                // merging skeletons
-                Skeleton controlSkeleton = control.getSkeleton();
-                int boneIndexIncrease = controlSkeleton.getBoneCount();
-                Skeleton skeleton = this.merge(controlSkeleton, ad.skeleton);
-
-                // merging animations
-                HashMap<String, BoneAnimation> animations = new HashMap<String, BoneAnimation>();
-                for (String animationName : control.getAnimationNames()) {
-                    animations.put(animationName, control.getAnim(animationName));
-                }
-                for (Entry<String, BoneAnimation> animEntry : anims.entrySet()) {
-                    BoneAnimation ba = animEntry.getValue();
-                    for (int i = 0; i < ba.getTracks().length; ++i) {
-                        BoneTrack bt = ba.getTracks()[i];
-                        int newBoneIndex = bt.getTargetBoneIndex() + boneIndexIncrease;
-                        ba.getTracks()[i] = new BoneTrack(newBoneIndex, bt.getTimes(), bt.getTranslations(), bt.getRotations(), bt.getScales());
-                    }
-                    animations.put(animEntry.getKey(), animEntry.getValue());
-                }
-
-                // replacing the control
-                node.removeControl(control);
-                control = new AnimControl(skeleton);
-            }
-            control.setAnimations(anims);
-            node.addControl(control);
-            node.addControl(skeletonControl);
-        }
-        return node;
-    }
-
-    protected Node applyObjectAnimationModifier(Node node, Modifier modifier, DataRepository dataRepository) {
-        AnimData ad = (AnimData) modifier.getJmeModifierRepresentation();
-        
-        // TODO: Why is this line here? Why is this needed? 
-        // Remove if necessary.
-        //ad.skeleton.getBone(0).setAttachNode(node);
-        
-        return this.applyArmatureModifierData(node, modifier, dataRepository);
-    }
-
-    /**
-     * This method applies the array modifier to the node.
-     * @param node
-     *        the object the modifier will be applied to
-     * @param modifier
-     *        the modifier to be applied
-     * @param dataRepository
-     *        the data repository
-     * @return object node with array modifier applied
-     */
-    @SuppressWarnings("unchecked")
-    protected Node applyArrayModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
-        Map<String, Object> modifierData = (Map<String, Object>) modifier.getJmeModifierRepresentation();
-        int fittype = ((Number) modifierData.get("fittype")).intValue();
-        float[] offset = (float[]) modifierData.get("offset");
-        if (offset == null) {// the node will be repeated several times in the same place
-            offset = new float[]{0.0f, 0.0f, 0.0f};
-        }
-        float[] scale = (float[]) modifierData.get("scale");
-        if (scale == null) {// the node will be repeated several times in the same place
-            scale = new float[]{0.0f, 0.0f, 0.0f};
-        } else {
-            // getting bounding box
-            node.updateModelBound();
-            BoundingVolume boundingVolume = node.getWorldBound();
-            if (boundingVolume instanceof BoundingBox) {
-                scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f;
-                scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f;
-                scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f;
-            } else if (boundingVolume instanceof BoundingSphere) {
-                float radius = ((BoundingSphere) boundingVolume).getRadius();
-                scale[0] *= radius * 2.0f;
-                scale[1] *= radius * 2.0f;
-                scale[2] *= radius * 2.0f;
-            } else {
-                throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName());
-            }
-        }
-
-        // adding object's offset
-        float[] objectOffset = new float[]{0.0f, 0.0f, 0.0f};
-        Pointer pOffsetObject = (Pointer) modifierData.get("offsetob");
-        if (pOffsetObject != null) {
-            FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
-            ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-            try {// we take the structure in case the object was not yet loaded
-                Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository);
-                Vector3f translation = objectHelper.getTransformation(offsetStructure, dataRepository).getTranslation();
-                objectOffset[0] = translation.x;
-                objectOffset[1] = translation.y;
-                objectOffset[2] = translation.z;
-            } catch (BlenderFileException e) {
-                LOGGER.log(Level.WARNING, "Problems in blender file structure! Object offset cannot be applied! The problem: {0}", e.getMessage());
-            }
-        }
-
-        // getting start and end caps
-        Node[] caps = new Node[]{null, null};
-        Pointer[] pCaps = new Pointer[]{(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")};
-        for (int i = 0; i < pCaps.length; ++i) {
-            if (pCaps[i] != null) {
-                caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
-                if (caps[i] != null) {
-                    caps[i] = (Node) caps[i].clone();
-                } else {
-                    FileBlockHeader capBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
-                    try {// we take the structure in case the object was not yet loaded
-                        Structure capStructure = capBlock.getStructure(dataRepository);
-                        ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-                        caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository);
-                        if (caps[i] == null) {
-                            LOGGER.log(Level.WARNING, "Cap object ''{0}'' couldn''t be loaded!", capStructure.getName());
-                        }
-                    } catch (BlenderFileException e) {
-                        LOGGER.log(Level.WARNING, "Problems in blender file structure! Cap object cannot be applied! The problem: {0}", e.getMessage());
-                    }
-                }
-            }
-        }
-
-        Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0], offset[1] + scale[1] + objectOffset[1], offset[2] + scale[2] + objectOffset[2]);
-
-        // getting/calculating repeats amount
-        int count = 0;
-        if (fittype == 0) {// Fixed count
-            count = ((Number) modifierData.get("count")).intValue() - 1;
-        } else if (fittype == 1) {// Fixed length
-            float length = ((Number) modifierData.get("length")).floatValue();
-            if (translationVector.length() > 0.0f) {
-                count = (int) (length / translationVector.length()) - 1;
-            }
-        } else if (fittype == 2) {// Fit curve
-            throw new IllegalStateException("Fit curve should be transformed to Fixed Length array type!");
-        } else {
-            throw new IllegalStateException("Unknown fit type: " + fittype);
-        }
-
-        // adding translated nodes and caps
-        if (count > 0) {
-            Node[] arrayNodes = new Node[count];
-            Vector3f newTranslation = new Vector3f();
-            for (int i = 0; i < count; ++i) {
-                newTranslation.addLocal(translationVector);
-                Node nodeClone = (Node) node.clone();
-                nodeClone.setLocalTranslation(newTranslation);
-                arrayNodes[i] = nodeClone;
-            }
-            for (Node nodeClone : arrayNodes) {
-                node.attachChild(nodeClone);
-            }
-            if (caps[0] != null) {
-                caps[0].getLocalTranslation().set(node.getLocalTranslation()).subtractLocal(translationVector);
-                node.attachChild(caps[0]);
-            }
-            if (caps[1] != null) {
-                caps[1].getLocalTranslation().set(newTranslation).addLocal(translationVector);
-                node.attachChild(caps[1]);
-            }
-        }
-        return node;
-    }
-
-    /**
-     * This method applies the mirror modifier to the node.
-     * @param node
-     *        the object the modifier will be applied to
-     * @param modifier
-     *        the modifier to be applied
-     * @param dataRepository
-     *        the data repository
-     * @return object node with mirror modifier applied
-     */
-    @SuppressWarnings("unchecked")
-    protected Node applyMirrorModifierData(Node node, Modifier modifier, DataRepository dataRepository) {
-        Map<String, Object> modifierData = (Map<String, Object>) modifier.getJmeModifierRepresentation();
-        int flag = ((Number) modifierData.get("flag")).intValue();
-        float[] mirrorFactor = new float[]{
-            (flag & 0x08) != 0 ? -1.0f : 1.0f,
-            (flag & 0x10) != 0 ? -1.0f : 1.0f,
-            (flag & 0x20) != 0 ? -1.0f : 1.0f
-        };
-        float[] center = new float[]{0.0f, 0.0f, 0.0f};
-        Pointer pObject = (Pointer) modifierData.get("mirrorob");
-        if (pObject != null) {
-            Structure objectStructure;
-            try {
-                objectStructure = pObject.fetchData(dataRepository.getInputStream()).get(0);
-                ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-                Node object = (Node) objectHelper.toObject(objectStructure, dataRepository);
-                if (object != null) {
-                    Vector3f translation = object.getWorldTranslation();
-                    center[0] = translation.x;
-                    center[1] = translation.y;
-                    center[2] = translation.z;
-                }
-            } catch (BlenderFileException e) {
-                LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage());
-            }
-        }
-        float tolerance = ((Number) modifierData.get("tolerance")).floatValue();
-        boolean mirrorU = (flag & 0x01) != 0;
-        boolean mirrorV = (flag & 0x02) != 0;
-//		boolean mirrorVGroup = (flag & 0x20) != 0;
-
-        List<Geometry> geometriesToAdd = new ArrayList<Geometry>();
-        for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) {
-            if (mirrorFactor[mirrorIndex] == -1.0f) {
-                for (Spatial spatial : node.getChildren()) {
-                    if (spatial instanceof Geometry) {
-                        Mesh mesh = ((Geometry) spatial).getMesh();
-                        Mesh clone = mesh.deepClone();
-
-                        // getting buffers
-                        FloatBuffer position = mesh.getFloatBuffer(Type.Position);
-                        FloatBuffer bindPosePosition = mesh.getFloatBuffer(Type.BindPosePosition);
-
-                        FloatBuffer clonePosition = clone.getFloatBuffer(Type.Position);
-                        FloatBuffer cloneBindPosePosition = clone.getFloatBuffer(Type.BindPosePosition);
-                        FloatBuffer cloneNormals = clone.getFloatBuffer(Type.Normal);
-                        FloatBuffer cloneBindPoseNormals = clone.getFloatBuffer(Type.BindPoseNormal);
-                        IntBuffer cloneIndexes = (IntBuffer) clone.getBuffer(Type.Index).getData();
-
-                        // modyfying data
-                        for (int i = mirrorIndex; i < clonePosition.limit(); i += 3) {
-                            float value = clonePosition.get(i);
-                            float d = center[mirrorIndex] - value;
-
-                            if (Math.abs(d) <= tolerance) {
-                                clonePosition.put(i, center[mirrorIndex]);
-                                cloneBindPosePosition.put(i, center[mirrorIndex]);
-                                position.put(i, center[mirrorIndex]);
-                                bindPosePosition.put(i, center[mirrorIndex]);
-                            } else {
-                                clonePosition.put(i, value + 2.0f * d);
-                                cloneBindPosePosition.put(i, value + 2.0f * d);
-                            }
-                            cloneNormals.put(i, -cloneNormals.get(i));
-                            cloneBindPoseNormals.put(i, -cloneNormals.get(i));
-
-                            //modifying clone indexes
-                            int vertexIndex = (i - mirrorIndex) / 3;
-                            if (vertexIndex % 3 == 0 && vertexIndex<cloneIndexes.limit()) {
-                                int index = cloneIndexes.get(vertexIndex + 2);
-                                cloneIndexes.put(vertexIndex + 2, cloneIndexes.get(vertexIndex + 1));
-                                cloneIndexes.put(vertexIndex + 1, index);
-                            }
-                        }
-
-                        if (mirrorU) {
-                            FloatBuffer cloneUVs = (FloatBuffer) clone.getBuffer(Type.TexCoord).getData();
-                            for (int i = 0; i < cloneUVs.limit(); i += 2) {
-                                cloneUVs.put(i, 1.0f - cloneUVs.get(i));
-                            }
-                        }
-                        if (mirrorV) {
-                            FloatBuffer cloneUVs = (FloatBuffer) clone.getBuffer(Type.TexCoord).getData();
-                            for (int i = 1; i < cloneUVs.limit(); i += 2) {
-                                cloneUVs.put(i, 1.0f - cloneUVs.get(i));
-                            }
-                        }
-
-                        Geometry geometry = new Geometry(null, clone);
-                        geometry.setMaterial(((Geometry) spatial).getMaterial());
-                        geometriesToAdd.add(geometry);
-                    }
-                }
-
-                // adding meshes to node
-                for (Geometry geometry : geometriesToAdd) {
-                    node.attachChild(geometry);
-                }
-                geometriesToAdd.clear();
-            }
-        }
-        return node;
-    }
-
-    /**
-     * This method merges two skeletons into one. I assume that each skeleton's 0-indexed bone is objectAnimationBone so
-     * only one such bone should be placed in the result
-     * @param s1
-     *        first skeleton
-     * @param s2
-     *        second skeleton
-     * @return merged skeleton
-     */
-    protected Skeleton merge(Skeleton s1, Skeleton s2) {
-        List<Bone> bones = new ArrayList<Bone>(s1.getBoneCount() + s2.getBoneCount());
-        for (int i = 0; i < s1.getBoneCount(); ++i) {
-            bones.add(s1.getBone(i));
-        }
-        for (int i = 1; i < s2.getBoneCount(); ++i) {// ommit objectAnimationBone
-            bones.add(s2.getBone(i));
-        }
-        return new Skeleton(bones.toArray(new Bone[bones.size()]));
-    }
-    
-    @Override
-    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
-    	return true;
-    }
-}

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

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.lights;
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -39,11 +39,11 @@ import com.jme3.light.DirectionalLight;
 import com.jme3.light.Light;
 import com.jme3.light.PointLight;
 import com.jme3.math.ColorRGBA;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Structure;
 
 /**
  * A class that is used in light calculations.

+ 9 - 8
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.materials;
 
 import java.nio.ByteBuffer;
 import java.util.HashMap;
@@ -48,13 +48,14 @@ import com.jme3.material.RenderState.BlendMode;
 import com.jme3.material.RenderState.FaceCullMode;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.textures.TextureHelper;
 import com.jme3.shader.VarType;
 import com.jme3.texture.Image;
 import com.jme3.texture.Image.Format;

+ 13 - 10
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.meshes;
 
 import java.nio.ByteBuffer;
 import java.nio.FloatBuffer;
@@ -57,14 +57,17 @@ import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.VertexBuffer.Format;
 import com.jme3.scene.VertexBuffer.Type;
 import com.jme3.scene.VertexBuffer.Usage;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.Properties;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.scene.plugins.blender.objects.Properties;
+import com.jme3.scene.plugins.blender.textures.TextureHelper;
 import com.jme3.texture.Texture;
 import com.jme3.util.BufferUtils;
 
@@ -465,7 +468,7 @@ public class MeshHelper extends AbstractBlenderHelper {
 	 * @param vertices
 	 *            a list of vertices read from the blender file
 	 */
-	protected void addNormal(Vector3f normalToAdd, Map<Vector3f, Vector3f> normalMap, boolean smooth, Vector3f... vertices) {
+	public void addNormal(Vector3f normalToAdd, Map<Vector3f, Vector3f> normalMap, boolean smooth, Vector3f... vertices) {
 		for (Vector3f v : vertices) {
 			Vector3f n = normalMap.get(v);
 			if (!smooth || n == null) {

+ 216 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java

@@ -0,0 +1,216 @@
+package com.jme3.scene.plugins.blender.modifiers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.jme3.animation.AnimControl;
+import com.jme3.animation.Bone;
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.animation.SkeletonControl;
+import com.jme3.math.Matrix4f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
+import com.jme3.scene.plugins.blender.constraints.Constraint;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+import com.jme3.scene.plugins.ogre.AnimData;
+
+/**
+ * This modifier allows to add bone animation to the object.
+ * 
+ * @author Marcin Roguski (Kaelthas)
+ */
+/* package */class ArmatureModifier extends Modifier {
+
+	/**
+	 * This constructor is only temporary. It will be removed when object
+	 * animation is implemented in jme. TODO!!!!!!!
+	 */
+	/* package */ArmatureModifier() {
+	}
+
+	/**
+	 * This constructor reads animation data from the object structore. The
+	 * stored data is the AnimData and additional data is armature's OMA.
+	 * 
+	 * @param objectStructure
+	 *            the structure of the object
+	 * @param modifierStructure
+	 *            the structure of the modifier
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ArmatureModifier(Structure objectStructure, Structure modifierStructure, DataRepository dataRepository) throws BlenderFileException {
+		Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object");
+		if (pArmatureObject.isNotNull()) {
+			ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+			Structure armatureObject = (Structure) dataRepository.getLoadedFeature(pArmatureObject.getOldMemoryAddress(),
+							LoadedFeatureDataType.LOADED_STRUCTURE);
+			if (armatureObject == null) {// we check this first not to fetch the
+											// structure unnecessary
+				armatureObject = pArmatureObject.fetchData(dataRepository.getInputStream()).get(0);
+				objectHelper.toObject(armatureObject, dataRepository);
+			}
+			additionalData = armatureObject.getOldMemoryAddress();
+			ArmatureHelper armatureHelper = dataRepository
+					.getHelper(ArmatureHelper.class);
+
+			// changing bones matrices so that they fit the current object (that
+			// is why we need a copy of a skeleton)
+			Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject);
+			Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert();
+			Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix);
+			Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation);
+
+			// setting the bones structure inside the skeleton (thus completing
+			// its loading)
+			Skeleton skeleton = new Skeleton(bones);
+			dataRepository.addLoadedFeatures(armatureObject.getOldMemoryAddress(), armatureObject.getName(), armatureObject, skeleton);
+
+			String objectName = objectStructure.getName();
+			Set<String> animationNames = dataRepository.getBlenderKey().getAnimationNames(objectName);
+			if (animationNames != null && animationNames.size() > 0) {
+				ArrayList<BoneAnimation> animations = new ArrayList<BoneAnimation>();
+				List<FileBlockHeader> actionHeaders = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
+				for (FileBlockHeader header : actionHeaders) {
+					Structure actionStructure = header.getStructure(dataRepository);
+					String actionName = actionStructure.getName();
+					if (animationNames.contains(actionName)) {
+						int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, actionName);
+						int fps = dataRepository.getBlenderKey().getFps();
+						float start = (float) animationFrames[0] / (float) fps;
+						float stop = (float) animationFrames[1] / (float) fps;
+						BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start);
+						boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, dataRepository, objectName, actionName));
+						animations.add(boneAnimation);
+					}
+				}
+				jmeModifierRepresentation = new AnimData(new Skeleton(bones), animations);
+			}
+		}
+	}
+
+	@Override
+	public Node apply(Node node, DataRepository dataRepository) {
+		if(jmeModifierRepresentation == null) {
+			return node;
+		}
+		AnimData ad = (AnimData) jmeModifierRepresentation;
+		ArrayList<BoneAnimation> animList = ad.anims;
+		Long modifierArmatureObject = (Long) additionalData;
+		if (animList != null && animList.size() > 0) {
+			List<Constraint> constraints = dataRepository.getConstraints(modifierArmatureObject);
+			HashMap<String, BoneAnimation> anims = new HashMap<String, BoneAnimation>();
+			for (int i = 0; i < animList.size(); ++i) {
+				BoneAnimation boneAnimation = animList.get(i).clone();
+
+				// baking constraints into animations
+				if (constraints != null && constraints.size() > 0) {
+					for (Constraint constraint : constraints) {
+						constraint.affectAnimation(ad.skeleton, boneAnimation);
+					}
+				}
+
+				anims.put(boneAnimation.getName(), boneAnimation);
+			}
+
+			// getting meshes
+			Mesh[] meshes = null;
+			List<Mesh> meshesList = new ArrayList<Mesh>();
+			List<Spatial> children = node.getChildren();
+			for (Spatial child : children) {
+				if (child instanceof Geometry) {
+					meshesList.add(((Geometry) child).getMesh());
+				}
+			}
+			if (meshesList.size() > 0) {
+				meshes = meshesList.toArray(new Mesh[meshesList.size()]);
+			}
+
+			// applying the control to the node
+			SkeletonControl skeletonControl = new SkeletonControl(meshes, ad.skeleton);
+			AnimControl control = node.getControl(AnimControl.class);
+
+			if (control == null) {
+				control = new AnimControl(ad.skeleton);
+			} else {
+				// merging skeletons
+				Skeleton controlSkeleton = control.getSkeleton();
+				int boneIndexIncrease = controlSkeleton.getBoneCount();
+				Skeleton skeleton = this.merge(controlSkeleton, ad.skeleton);
+
+				// merging animations
+				HashMap<String, BoneAnimation> animations = new HashMap<String, BoneAnimation>();
+				for (String animationName : control.getAnimationNames()) {
+					animations.put(animationName,
+							control.getAnim(animationName));
+				}
+				for (Entry<String, BoneAnimation> animEntry : anims.entrySet()) {
+					BoneAnimation ba = animEntry.getValue();
+					for (int i = 0; i < ba.getTracks().length; ++i) {
+						BoneTrack bt = ba.getTracks()[i];
+						int newBoneIndex = bt.getTargetBoneIndex()
+								+ boneIndexIncrease;
+						ba.getTracks()[i] = new BoneTrack(newBoneIndex,
+								bt.getTimes(), bt.getTranslations(),
+								bt.getRotations(), bt.getScales());
+					}
+					animations.put(animEntry.getKey(), animEntry.getValue());
+				}
+
+				// replacing the control
+				node.removeControl(control);
+				control = new AnimControl(skeleton);
+			}
+			control.setAnimations(anims);
+			node.addControl(control);
+			node.addControl(skeletonControl);
+		}
+		return node;
+	}
+
+	@Override
+	public String getType() {
+		return Modifier.ARMATURE_MODIFIER_DATA;
+	}
+
+	/**
+	 * This method merges two skeletons into one. I assume that each skeleton's
+	 * 0-indexed bone is objectAnimationBone so only one such bone should be
+	 * placed in the result
+	 * 
+	 * @param s1
+	 *            first skeleton
+	 * @param s2
+	 *            second skeleton
+	 * @return merged skeleton
+	 */
+	protected Skeleton merge(Skeleton s1, Skeleton s2) {
+		List<Bone> bones = new ArrayList<Bone>(s1.getBoneCount()
+				+ s2.getBoneCount());
+		for (int i = 0; i < s1.getBoneCount(); ++i) {
+			bones.add(s1.getBone(i));
+		}
+		for (int i = 1; i < s2.getBoneCount(); ++i) {// ommit
+														// objectAnimationBone
+			bones.add(s2.getBone(i));
+		}
+		return new Skeleton(bones.toArray(new Bone[bones.size()]));
+	}
+}

+ 244 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java

@@ -0,0 +1,244 @@
+package com.jme3.scene.plugins.blender.modifiers;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
+import com.jme3.bounding.BoundingVolume;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+import com.jme3.scene.shape.Curve;
+
+/**
+ * This modifier allows to array modifier to the object.
+ * 
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class ArrayModifier extends Modifier {
+	private static final Logger LOGGER = Logger.getLogger(ArrayModifier.class.getName());
+	
+	/**
+	 * This constructor reads array data from the modifier structure. The
+	 * stored data is a map of parameters for array modifier. No additional data
+	 * is loaded.
+	 * 
+	 * @param objectStructure
+	 *            the structure of the object
+	 * @param modifierStructure
+	 *            the structure of the modifier
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	@SuppressWarnings("unchecked")
+	public ArrayModifier(Structure modifier, DataRepository dataRepository) throws BlenderFileException {
+		Map<String, Object> params = new HashMap<String, Object>();
+
+        Number fittype = (Number) modifier.getFieldValue("fit_type");
+        params.put("fittype", fittype);
+        switch (fittype.intValue()) {
+            case 0:// FIXED COUNT
+                params.put("count", modifier.getFieldValue("count"));
+                break;
+            case 1:// FIXED LENGTH
+                params.put("length", modifier.getFieldValue("length"));
+                break;
+            case 2:// FITCURVE
+                Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob");
+                float length = 0;
+                if (pCurveOb.isNotNull()) {
+                    Structure curveStructure = pCurveOb.fetchData(dataRepository.getInputStream()).get(0);
+                    ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+                    Node curveObject = (Node) objectHelper.toObject(curveStructure, dataRepository);
+                    Set<Number> referencesToCurveLengths = new HashSet<Number>(curveObject.getChildren().size());
+                    for (Spatial spatial : curveObject.getChildren()) {
+                        if (spatial instanceof Geometry) {
+                            Mesh mesh = ((Geometry) spatial).getMesh();
+                            if (mesh instanceof Curve) {
+                                length += ((Curve) mesh).getLength();
+                            } else {
+                                //if bevel object has several parts then each mesh will have the same reference
+                                //to length value (and we should use only one)
+                                Number curveLength = spatial.getUserData("curveLength");
+                                if (curveLength != null && !referencesToCurveLengths.contains(curveLength)) {
+                                    length += curveLength.floatValue();
+                                    referencesToCurveLengths.add(curveLength);
+                                }
+                            }
+                        }
+                    }
+                }
+                params.put("length", Float.valueOf(length));
+                params.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH
+                break;
+            default:
+                assert false : "Unknown array modifier fit type: " + fittype;
+        }
+
+        // offset parameters
+        int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue();
+        if ((offsettype & 0x01) != 0) {// Constant offset
+            DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifier.getFieldValue("offset");
+            float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()};
+            params.put("offset", offset);
+        }
+        if ((offsettype & 0x02) != 0) {// Relative offset
+            DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifier.getFieldValue("scale");
+            float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()};
+            params.put("scale", scale);
+        }
+        if ((offsettype & 0x04) != 0) {// Object offset
+            Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob");
+            if (pOffsetObject.isNotNull()) {
+                params.put("offsetob", pOffsetObject);
+            }
+        }
+
+        // start cap and end cap
+        Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap");
+        if (pStartCap.isNotNull()) {
+            params.put("startcap", pStartCap);
+        }
+        Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap");
+        if (pEndCap.isNotNull()) {
+            params.put("endcap", pEndCap);
+        }
+        jmeModifierRepresentation = params;
+	}
+	
+	@Override
+	@SuppressWarnings("unchecked")
+	public Node apply(Node node, DataRepository dataRepository) {
+		Map<String, Object> modifierData = (Map<String, Object>) jmeModifierRepresentation;
+        int fittype = ((Number) modifierData.get("fittype")).intValue();
+        float[] offset = (float[]) modifierData.get("offset");
+        if (offset == null) {// the node will be repeated several times in the same place
+            offset = new float[]{0.0f, 0.0f, 0.0f};
+        }
+        float[] scale = (float[]) modifierData.get("scale");
+        if (scale == null) {// the node will be repeated several times in the same place
+            scale = new float[]{0.0f, 0.0f, 0.0f};
+        } else {
+            // getting bounding box
+            node.updateModelBound();
+            BoundingVolume boundingVolume = node.getWorldBound();
+            if (boundingVolume instanceof BoundingBox) {
+                scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f;
+                scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f;
+                scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f;
+            } else if (boundingVolume instanceof BoundingSphere) {
+                float radius = ((BoundingSphere) boundingVolume).getRadius();
+                scale[0] *= radius * 2.0f;
+                scale[1] *= radius * 2.0f;
+                scale[2] *= radius * 2.0f;
+            } else {
+                throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName());
+            }
+        }
+
+        // adding object's offset
+        float[] objectOffset = new float[]{0.0f, 0.0f, 0.0f};
+        Pointer pOffsetObject = (Pointer) modifierData.get("offsetob");
+        if (pOffsetObject != null) {
+            FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
+            ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+            try {// we take the structure in case the object was not yet loaded
+                Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository);
+                Vector3f translation = objectHelper.getTransformation(offsetStructure, dataRepository).getTranslation();
+                objectOffset[0] = translation.x;
+                objectOffset[1] = translation.y;
+                objectOffset[2] = translation.z;
+            } catch (BlenderFileException e) {
+                LOGGER.log(Level.WARNING, "Problems in blender file structure! Object offset cannot be applied! The problem: {0}", e.getMessage());
+            }
+        }
+
+        // getting start and end caps
+        Node[] caps = new Node[]{null, null};
+        Pointer[] pCaps = new Pointer[]{(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")};
+        for (int i = 0; i < pCaps.length; ++i) {
+            if (pCaps[i] != null) {
+                caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
+                if (caps[i] != null) {
+                    caps[i] = (Node) caps[i].clone();
+                } else {
+                    FileBlockHeader capBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress());
+                    try {// we take the structure in case the object was not yet loaded
+                        Structure capStructure = capBlock.getStructure(dataRepository);
+                        ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+                        caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository);
+                        if (caps[i] == null) {
+                            LOGGER.log(Level.WARNING, "Cap object ''{0}'' couldn''t be loaded!", capStructure.getName());
+                        }
+                    } catch (BlenderFileException e) {
+                        LOGGER.log(Level.WARNING, "Problems in blender file structure! Cap object cannot be applied! The problem: {0}", e.getMessage());
+                    }
+                }
+            }
+        }
+
+        Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0], offset[1] + scale[1] + objectOffset[1], offset[2] + scale[2] + objectOffset[2]);
+
+        // getting/calculating repeats amount
+        int count = 0;
+        if (fittype == 0) {// Fixed count
+            count = ((Number) modifierData.get("count")).intValue() - 1;
+        } else if (fittype == 1) {// Fixed length
+            float length = ((Number) modifierData.get("length")).floatValue();
+            if (translationVector.length() > 0.0f) {
+                count = (int) (length / translationVector.length()) - 1;
+            }
+        } else if (fittype == 2) {// Fit curve
+            throw new IllegalStateException("Fit curve should be transformed to Fixed Length array type!");
+        } else {
+            throw new IllegalStateException("Unknown fit type: " + fittype);
+        }
+
+        // adding translated nodes and caps
+        if (count > 0) {
+            Node[] arrayNodes = new Node[count];
+            Vector3f newTranslation = new Vector3f();
+            for (int i = 0; i < count; ++i) {
+                newTranslation.addLocal(translationVector);
+                Node nodeClone = (Node) node.clone();
+                nodeClone.setLocalTranslation(newTranslation);
+                arrayNodes[i] = nodeClone;
+            }
+            for (Node nodeClone : arrayNodes) {
+                node.attachChild(nodeClone);
+            }
+            if (caps[0] != null) {
+                caps[0].getLocalTranslation().set(node.getLocalTranslation()).subtractLocal(translationVector);
+                node.attachChild(caps[0]);
+            }
+            if (caps[1] != null) {
+                caps[1].getLocalTranslation().set(newTranslation).addLocal(translationVector);
+                node.attachChild(caps[1]);
+            }
+        }
+        return node;
+	}
+	
+	@Override
+	public String getType() {
+		return ARRAY_MODIFIER_DATA;
+	}
+}

+ 170 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java

@@ -0,0 +1,170 @@
+package com.jme3.scene.plugins.blender.modifiers;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.VertexBuffer.Type;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+
+/**
+ * This modifier allows to array modifier to the object.
+ * 
+ * @author Marcin Roguski (Kaelthas)
+ */
+/*package*/ class MirrorModifier extends Modifier {
+	private static final Logger LOGGER = Logger.getLogger(MirrorModifier.class.getName());
+	
+	/**
+	 * This constructor reads mirror data from the modifier structure. The
+	 * stored data is a map of parameters for mirror modifier. No additional data
+	 * is loaded.
+	 * When the modifier is applied it is necessary to get the newly created node.
+	 * 
+	 * @param objectStructure
+	 *            the structure of the object
+	 * @param modifierStructure
+	 *            the structure of the modifier
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public MirrorModifier(Structure modifier, DataRepository dataRepository) {
+		Map<String, Object> params = new HashMap<String, Object>();
+
+        params.put("flag", modifier.getFieldValue("flag"));
+        params.put("tolerance", modifier.getFieldValue("tolerance"));
+        Pointer pMirrorOb = (Pointer) modifier.getFieldValue("mirror_ob");
+        if (pMirrorOb.isNotNull()) {
+            params.put("mirrorob", pMirrorOb);
+        }
+        jmeModifierRepresentation = params;
+	}
+	
+	@Override
+	@SuppressWarnings("unchecked")
+	public Node apply(Node node, DataRepository dataRepository) {
+		Map<String, Object> modifierData = (Map<String, Object>) jmeModifierRepresentation;
+        int flag = ((Number) modifierData.get("flag")).intValue();
+        float[] mirrorFactor = new float[]{
+            (flag & 0x08) != 0 ? -1.0f : 1.0f,
+            (flag & 0x10) != 0 ? -1.0f : 1.0f,
+            (flag & 0x20) != 0 ? -1.0f : 1.0f
+        };
+        float[] center = new float[]{0.0f, 0.0f, 0.0f};
+        Pointer pObject = (Pointer) modifierData.get("mirrorob");
+        if (pObject != null) {
+            Structure objectStructure;
+            try {
+                objectStructure = pObject.fetchData(dataRepository.getInputStream()).get(0);
+                ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
+                Node object = (Node) objectHelper.toObject(objectStructure, dataRepository);
+                if (object != null) {
+                    Vector3f translation = object.getWorldTranslation();
+                    center[0] = translation.x;
+                    center[1] = translation.y;
+                    center[2] = translation.z;
+                }
+            } catch (BlenderFileException e) {
+                LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage());
+            }
+        }
+        float tolerance = ((Number) modifierData.get("tolerance")).floatValue();
+        boolean mirrorU = (flag & 0x01) != 0;
+        boolean mirrorV = (flag & 0x02) != 0;
+//		boolean mirrorVGroup = (flag & 0x20) != 0;
+
+        List<Geometry> geometriesToAdd = new ArrayList<Geometry>();
+        for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) {
+            if (mirrorFactor[mirrorIndex] == -1.0f) {
+                for (Spatial spatial : node.getChildren()) {
+                    if (spatial instanceof Geometry) {
+                        Mesh mesh = ((Geometry) spatial).getMesh();
+                        Mesh clone = mesh.deepClone();
+
+                        // getting buffers
+                        FloatBuffer position = mesh.getFloatBuffer(Type.Position);
+                        FloatBuffer bindPosePosition = mesh.getFloatBuffer(Type.BindPosePosition);
+
+                        FloatBuffer clonePosition = clone.getFloatBuffer(Type.Position);
+                        FloatBuffer cloneBindPosePosition = clone.getFloatBuffer(Type.BindPosePosition);
+                        FloatBuffer cloneNormals = clone.getFloatBuffer(Type.Normal);
+                        FloatBuffer cloneBindPoseNormals = clone.getFloatBuffer(Type.BindPoseNormal);
+                        IntBuffer cloneIndexes = (IntBuffer) clone.getBuffer(Type.Index).getData();
+
+                        // modyfying data
+                        for (int i = mirrorIndex; i < clonePosition.limit(); i += 3) {
+                            float value = clonePosition.get(i);
+                            float d = center[mirrorIndex] - value;
+
+                            if (Math.abs(d) <= tolerance) {
+                                clonePosition.put(i, center[mirrorIndex]);
+                                cloneBindPosePosition.put(i, center[mirrorIndex]);
+                                position.put(i, center[mirrorIndex]);
+                                bindPosePosition.put(i, center[mirrorIndex]);
+                            } else {
+                                clonePosition.put(i, value + 2.0f * d);
+                                cloneBindPosePosition.put(i, value + 2.0f * d);
+                            }
+                            cloneNormals.put(i, -cloneNormals.get(i));
+                            cloneBindPoseNormals.put(i, -cloneNormals.get(i));
+
+                            //modifying clone indexes
+                            int vertexIndex = (i - mirrorIndex) / 3;
+                            if (vertexIndex % 3 == 0 && vertexIndex<cloneIndexes.limit()) {
+                                int index = cloneIndexes.get(vertexIndex + 2);
+                                cloneIndexes.put(vertexIndex + 2, cloneIndexes.get(vertexIndex + 1));
+                                cloneIndexes.put(vertexIndex + 1, index);
+                            }
+                        }
+
+                        if (mirrorU) {
+                            FloatBuffer cloneUVs = (FloatBuffer) clone.getBuffer(Type.TexCoord).getData();
+                            for (int i = 0; i < cloneUVs.limit(); i += 2) {
+                                cloneUVs.put(i, 1.0f - cloneUVs.get(i));
+                            }
+                        }
+                        if (mirrorV) {
+                            FloatBuffer cloneUVs = (FloatBuffer) clone.getBuffer(Type.TexCoord).getData();
+                            for (int i = 1; i < cloneUVs.limit(); i += 2) {
+                                cloneUVs.put(i, 1.0f - cloneUVs.get(i));
+                            }
+                        }
+
+                        Geometry geometry = new Geometry(null, clone);
+                        geometry.setMaterial(((Geometry) spatial).getMaterial());
+                        geometriesToAdd.add(geometry);
+                    }
+                }
+
+                // adding meshes to node
+                for (Geometry geometry : geometriesToAdd) {
+                    node.attachChild(geometry);
+                }
+                geometriesToAdd.clear();
+            }
+        }
+        return node;
+	}
+	
+	@Override
+	public String getType() {
+		return Modifier.MIRROR_MODIFIER_DATA;
+	}
+}

+ 67 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java

@@ -0,0 +1,67 @@
+package com.jme3.scene.plugins.blender.modifiers;
+
+import com.jme3.scene.Node;
+import com.jme3.scene.plugins.blender.DataRepository;
+
+/**
+ * This class represents an object's modifier. The modifier object can be varied
+ * and the user needs to know what is the type of it for the specified type
+ * name. For example "ArmatureModifierData" type specified in blender is
+ * represented by AnimData object from jMonkeyEngine.
+ * 
+ * @author Marcin Roguski (Kaelthas)
+ */
+public abstract class Modifier {
+
+	public static final String ARRAY_MODIFIER_DATA = "ArrayModifierData";
+	public static final String ARMATURE_MODIFIER_DATA = "ArmatureModifierData";
+	public static final String PARTICLE_MODIFIER_DATA = "ParticleSystemModifierData";
+	public static final String MIRROR_MODIFIER_DATA = "MirrorModifierData";
+	public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData";
+
+	/**
+	 * JME modifier representation object.
+	 */
+	protected Object jmeModifierRepresentation;
+
+	/**
+	 * Various additional data used by modifiers.
+	 */
+	protected Object additionalData;
+
+	/**
+	 * This method returns JME modifier representation object.
+	 * 
+	 * @return JME modifier representation object
+	 */
+	public Object getJmeModifierRepresentation() {
+		return jmeModifierRepresentation;
+	}
+
+	/**
+	 * This method returns additional data stored in the modifier.
+	 * 
+	 * @return the additional data stored in the modifier
+	 */
+	public Object getAdditionalData() {
+		return additionalData;
+	}
+
+	/**
+	 * This method applies the modifier to the given node.
+	 * 
+	 * @param node
+	 *            the node that will have modifier applied
+	 * @param dataRepository
+	 *            the data repository
+	 * @return the node with applied modifier
+	 */
+	public abstract Node apply(Node node, DataRepository dataRepository);
+
+	/**
+	 * This method returns blender's type of modifier.
+	 * 
+	 * @return blender's type of modifier
+	 */
+	public abstract String getType();
+}

+ 113 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ModifierHelper.java

@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.scene.plugins.blender.modifiers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * A class that is used in modifiers calculations.
+ * @author Marcin Roguski
+ */
+public class ModifierHelper extends AbstractBlenderHelper {
+
+    private static final Logger LOGGER = Logger.getLogger(ModifierHelper.class.getName());
+
+    /**
+     * This constructor parses the given blender version and stores the result. Some functionalities may differ in
+     * different blender versions.
+     * @param blenderVersion
+     *        the version read from the blend file
+     */
+    public ModifierHelper(String blenderVersion) {
+        super(blenderVersion);
+    }
+
+    /**
+     * This method reads the given object's modifiers.
+     * @param objectStructure
+     *        the object structure
+     * @param dataRepository
+     *        the data repository
+     * @param converter
+     *        the converter object (in some cases we need to read an object first before loading the modifier)
+     * @throws BlenderFileException
+     *         this exception is thrown when the blender file is somehow corrupted
+     */
+    public Collection<Modifier> readModifiers(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException {
+    	Collection<Modifier> result = new ArrayList<Modifier>();
+    	Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers");
+        List<Structure> modifiers = modifiersListBase.evaluateListBase(dataRepository);
+        for (Structure modifierStructure : modifiers) {
+            Modifier modifier = null;
+            if (Modifier.ARRAY_MODIFIER_DATA.equals(modifierStructure.getType())) {
+            	modifier = new ArrayModifier(modifierStructure, dataRepository);
+            } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifierStructure.getType())) {
+            	modifier = new MirrorModifier(modifierStructure, dataRepository);
+            } else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifierStructure.getType())) {
+            	modifier = new ArmatureModifier(objectStructure, modifierStructure, dataRepository);
+            } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifierStructure.getType())) {
+            	modifier = new ParticlesModifier(modifierStructure, dataRepository);
+            }
+            
+            if(modifier != null) {
+            	result.add(modifier);
+            	dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier);
+            } else {
+            	LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifierStructure.getType());
+            }
+        }
+
+        //at the end read object's animation modifier
+        Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo");
+        if (pIpo.isNotNull()) {
+        	Modifier modifier = new ObjectAnimationModifier(objectStructure, dataRepository);
+        	result.add(modifier);
+        	dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
+    	return true;
+    }
+}

+ 122 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java

@@ -0,0 +1,122 @@
+package com.jme3.scene.plugins.blender.modifiers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jme3.animation.Bone;
+import com.jme3.animation.BoneAnimation;
+import com.jme3.animation.BoneTrack;
+import com.jme3.animation.Skeleton;
+import com.jme3.math.Transform;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.animations.Ipo;
+import com.jme3.scene.plugins.blender.animations.IpoHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.objects.ObjectHelper;
+import com.jme3.scene.plugins.ogre.AnimData;
+
+/**
+ * This modifier allows to add animation to the object.
+ * 
+ * @author Marcin Roguski (Kaelthas)
+ */
+/* package */class ObjectAnimationModifier extends ArmatureModifier {
+
+	/**
+	 * This constructor reads animation of the object itself (without bones) and
+	 * stores it as an ArmatureModifierData modifier. The animation is returned
+	 * as a modifier. It should be later applied regardless other modifiers. The
+	 * reason for this is that object may not have modifiers added but it's
+	 * animation should be working. The stored modifier is an anim data and
+	 * additional data is given object's OMA.
+	 * 
+	 * @param objectStructure
+	 *            the structure of the object
+	 * @param dataRepository
+	 *            the data repository
+	 * @return animation modifier is returned, it should be separately applied
+	 *         when the object is loaded
+	 * @throws BlenderFileException
+	 *             this exception is thrown when the blender file is somehow
+	 *             corrupted
+	 */
+	public ObjectAnimationModifier(Structure objectStructure,
+			DataRepository dataRepository) throws BlenderFileException {
+		Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo");
+		if (pIpo.isNotNull()) {
+			// check if there is an action name connected with this ipo
+			String objectAnimationName = null;
+			List<FileBlockHeader> actionBlocks = dataRepository
+					.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
+			for (FileBlockHeader actionBlock : actionBlocks) {
+				Structure action = actionBlock.getStructure(dataRepository);
+				List<Structure> actionChannels = ((Structure) action
+						.getFieldValue("chanbase"))
+						.evaluateListBase(dataRepository);
+				if (actionChannels.size() == 1) {// object's animtion action has
+													// only one channel
+					Pointer pChannelIpo = (Pointer) actionChannels.get(0)
+							.getFieldValue("ipo");
+					if (pChannelIpo.equals(pIpo)) {
+						objectAnimationName = action.getName();
+						break;
+					}
+				}
+			}
+
+			String objectName = objectStructure.getName();
+			if (objectAnimationName == null) {// set the object's animation name
+												// to object's name
+				objectAnimationName = objectName;
+			}
+
+			IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class);
+			Structure ipoStructure = pIpo.fetchData(
+					dataRepository.getInputStream()).get(0);
+			Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository);
+			int[] animationFrames = dataRepository.getBlenderKey()
+					.getAnimationFrames(objectName, objectAnimationName);
+			if (animationFrames == null) {// if the name was created here there
+											// are no frames set for the
+											// animation
+				animationFrames = new int[] { 1, ipo.getLastFrame() };
+			}
+			int fps = dataRepository.getBlenderKey().getFps();
+			float start = (float) animationFrames[0] / (float) fps;
+			float stop = (float) animationFrames[1] / (float) fps;
+
+			// calculating track for the only bone in this skeleton
+			BoneTrack[] tracks = new BoneTrack[1];
+			tracks[0] = ipo.calculateTrack(0, animationFrames[0],
+					animationFrames[1], fps);
+
+			BoneAnimation boneAnimation = new BoneAnimation(
+					objectAnimationName, stop - start);
+			boneAnimation.setTracks(tracks);
+			ArrayList<BoneAnimation> animations = new ArrayList<BoneAnimation>(
+					1);
+			animations.add(boneAnimation);
+
+			// preparing the object's bone
+			ObjectHelper objectHelper = dataRepository
+					.getHelper(ObjectHelper.class);
+			Transform t = objectHelper.getTransformation(objectStructure,
+					dataRepository);
+			Bone bone = new Bone(null);
+			bone.setBindTransforms(t.getTranslation(), t.getRotation(),
+					t.getScale());
+
+			jmeModifierRepresentation = new AnimData(new Skeleton(
+					new Bone[] { bone }), animations);
+			additionalData = objectStructure.getOldMemoryAddress();
+		}
+	}
+
+	@Override
+	public String getType() {
+		return Modifier.OBJECT_ANIMATION_MODIFIER_DATA;
+	}
+}

+ 99 - 0
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java

@@ -0,0 +1,99 @@
+package com.jme3.scene.plugins.blender.modifiers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jme3.effect.ParticleEmitter;
+import com.jme3.effect.shapes.EmitterMeshVertexShape;
+import com.jme3.effect.shapes.EmitterShape;
+import com.jme3.material.Material;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.scene.plugins.blender.particles.ParticlesHelper;
+
+/**
+ * This modifier allows to add particles to the object.
+ * 
+ * @author Marcin Roguski (Kaelthas)
+ */
+/* package */class ParticlesModifier extends Modifier {
+
+	/**
+	 * This constructor reads the particles system structure and stores it in
+	 * order to apply it later to the node.
+	 * 
+	 * @param modifier
+	 *            the structure of the modifier
+	 * @param dataRepository
+	 *            the data repository
+	 * @throws BlenderFileException
+	 *             an exception is throw wneh there are problems with the
+	 *             blender file
+	 */
+	public ParticlesModifier(Structure modifier, DataRepository dataRepository)
+			throws BlenderFileException {
+		Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys");
+		if (pParticleSystem.isNotNull()) {
+			ParticlesHelper particlesHelper = dataRepository
+					.getHelper(ParticlesHelper.class);
+			Structure particleSystem = pParticleSystem.fetchData(
+					dataRepository.getInputStream()).get(0);
+			jmeModifierRepresentation = particlesHelper.toParticleEmitter(
+					particleSystem, dataRepository);
+		}
+	}
+
+	@Override
+	public Node apply(Node node, DataRepository dataRepository) {
+		MaterialHelper materialHelper = dataRepository
+				.getHelper(MaterialHelper.class);
+		ParticleEmitter emitter = (ParticleEmitter) jmeModifierRepresentation;
+		emitter = emitter.clone();
+
+		// veryfying the alpha function for particles' texture
+		Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE;
+		char nameSuffix = emitter.getName().charAt(
+				emitter.getName().length() - 1);
+		if (nameSuffix == 'B' || nameSuffix == 'N') {
+			alphaFunction = MaterialHelper.ALPHA_MASK_NONE;
+		}
+		// removing the type suffix from the name
+		emitter.setName(emitter.getName().substring(0,
+				emitter.getName().length() - 1));
+
+		// applying emitter shape
+		EmitterShape emitterShape = emitter.getShape();
+		List<Mesh> meshes = new ArrayList<Mesh>();
+		for (Spatial spatial : node.getChildren()) {
+			if (spatial instanceof Geometry) {
+				Mesh mesh = ((Geometry) spatial).getMesh();
+				if (mesh != null) {
+					meshes.add(mesh);
+					Material material = materialHelper.getParticlesMaterial(
+							((Geometry) spatial).getMaterial(), alphaFunction,
+							dataRepository);
+					emitter.setMaterial(material);// TODO: divide into several
+													// pieces
+				}
+			}
+		}
+		if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) {
+			((EmitterMeshVertexShape) emitterShape).setMeshes(meshes);
+		}
+
+		node.attachChild(emitter);
+		return node;
+	}
+
+	@Override
+	public String getType() {
+		return Modifier.PARTICLE_MODIFIER_DATA;
+	}
+}

+ 21 - 18
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.objects;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -51,15 +51,21 @@ import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.scene.Spatial.CullHint;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.structures.Modifier;
-import com.jme3.scene.plugins.blender.structures.Properties;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.animations.ArmatureHelper;
+import com.jme3.scene.plugins.blender.cameras.CameraHelper;
+import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
+import com.jme3.scene.plugins.blender.curves.CurvesHelper;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.lights.LightHelper;
+import com.jme3.scene.plugins.blender.meshes.MeshHelper;
+import com.jme3.scene.plugins.blender.modifiers.Modifier;
+import com.jme3.scene.plugins.blender.modifiers.ModifierHelper;
 
 /**
  * A class that is used in object calculations.
@@ -136,19 +142,15 @@ public class ObjectHelper extends AbstractBlenderHelper {
 		dataRepository.pushParent(objectStructure);
 
 		ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-		ModifierHelper modifierHelper = dataRepository.getHelper(ModifierHelper.class);
 		ArmatureHelper armatureHelper = dataRepository.getHelper(ArmatureHelper.class);
-		ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class);
 
 		//get object data
 		int type = ((Number)objectStructure.getFieldValue("type")).intValue();
 		String name = objectStructure.getName();
 		LOGGER.log(Level.INFO, "Loading obejct: {0}", name);
 
-		//reading modifiers
-		modifierHelper.readModifiers(objectStructure, dataRepository);
-
 		//loading constraints connected with this object
+		ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class);
 		constraintHelper.loadConstraints(objectStructure, dataRepository);
 
 		int restrictflag = ((Number)objectStructure.getFieldValue("restrictflag")).intValue();
@@ -187,10 +189,11 @@ public class ObjectHelper extends AbstractBlenderHelper {
 					}
 					node.setLocalTransform(t);
 
-					//applying all modifiers
-					List<Modifier> modifiers = dataRepository.getModifiers(objectStructure.getOldMemoryAddress(), null);
+					//reading and applying all modifiers
+					ModifierHelper modifierHelper = dataRepository.getHelper(ModifierHelper.class);
+					Collection<Modifier> modifiers = modifierHelper.readModifiers(objectStructure, dataRepository);
 					for(Modifier modifier : modifiers) {
-						modifierHelper.applyModifier(node, modifier, dataRepository);
+						modifier.apply(node, dataRepository);
 					}
 
 					//setting the parent

+ 7 - 7
engine/src/blender/com/jme3/scene/plugins/blender/structures/Properties.java → engine/src/blender/com/jme3/scene/plugins/blender/objects/Properties.java

@@ -1,4 +1,4 @@
-package com.jme3.scene.plugins.blender.structures;
+package com.jme3.scene.plugins.blender.objects;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -11,12 +11,12 @@ import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
 import com.jme3.export.Savable;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
 
 /**
  * The blender object's custom properties.

+ 7 - 7
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java

@@ -1,4 +1,4 @@
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.particles;
 
 import java.util.logging.Logger;
 
@@ -11,12 +11,12 @@ import com.jme3.effect.shapes.EmitterMeshConvexHullShape;
 import com.jme3.effect.shapes.EmitterMeshFaceShape;
 import com.jme3.effect.shapes.EmitterMeshVertexShape;
 import com.jme3.math.ColorRGBA;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
 
 public class ParticlesHelper extends AbstractBlenderHelper {
 	private static final Logger			LOGGER		= Logger.getLogger(ParticlesHelper.class.getName());

+ 0 - 230
engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java

@@ -1,230 +0,0 @@
-package com.jme3.scene.plugins.blender.structures;
-
-import java.util.logging.Logger;
-
-import com.jme3.animation.Bone;
-import com.jme3.animation.BoneAnimation;
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.Skeleton;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.helpers.v249.ObjectHelper;
-import com.jme3.scene.plugins.blender.structures.Constraint.Space;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.Pointer;
-
-/**
- * This class is used to calculate the constraint. The following methods should be implemented: affectLocation,
- * affectRotation and affectScale. This class also defines all constants required by known deriving classes.
- * @author Marcin Roguski
- */
-public abstract class AbstractInfluenceFunction {
-
-    protected static final Logger LOGGER = Logger.getLogger(AbstractInfluenceFunction.class.getName());
-    protected static final float IK_SOLVER_ERROR = 0.5f;
-    //DISTLIMIT
-    protected static final int LIMITDIST_INSIDE = 0;
-    protected static final int LIMITDIST_OUTSIDE = 1;
-    protected static final int LIMITDIST_ONSURFACE = 2;
-    //CONSTRAINT_TYPE_LOCLIKE
-    protected static final int LOCLIKE_X = 0x01;
-    protected static final int LOCLIKE_Y = 0x02;
-    protected static final int LOCLIKE_Z = 0x04;
-    //ROTLIKE
-    protected static final int ROTLIKE_X = 0x01;
-    protected static final int ROTLIKE_Y = 0x02;
-    protected static final int ROTLIKE_Z = 0x04;
-    protected static final int ROTLIKE_X_INVERT = 0x10;
-    protected static final int ROTLIKE_Y_INVERT = 0x20;
-    protected static final int ROTLIKE_Z_INVERT = 0x40;
-    protected static final int ROTLIKE_OFFSET = 0x80;
-    //SIZELIKE
-    protected static final int SIZELIKE_X = 0x01;
-    protected static final int SIZELIKE_Y = 0x02;
-    protected static final int SIZELIKE_Z = 0x04;
-    protected static final int SIZELIKE_OFFSET = 0x80;
-
-    /* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */
-    //protected static final int LOCLIKE_TIP = 0x08;
-    protected static final int LOCLIKE_X_INVERT = 0x10;
-    protected static final int LOCLIKE_Y_INVERT = 0x20;
-    protected static final int LOCLIKE_Z_INVERT = 0x40;
-    protected static final int LOCLIKE_OFFSET = 0x80;
-    //LOCLIMIT, SIZELIMIT
-    protected static final int LIMIT_XMIN = 0x01;
-    protected static final int LIMIT_XMAX = 0x02;
-    protected static final int LIMIT_YMIN = 0x04;
-    protected static final int LIMIT_YMAX = 0x08;
-    protected static final int LIMIT_ZMIN = 0x10;
-    protected static final int LIMIT_ZMAX = 0x20;
-    //ROTLIMIT
-    protected static final int LIMIT_XROT = 0x01;
-    protected static final int LIMIT_YROT = 0x02;
-    protected static final int LIMIT_ZROT = 0x04;
-    /** The type of the constraint. */
-    protected ConstraintType constraintType;
-    /** The data repository. */
-    protected DataRepository dataRepository;
-
-    /**
-     * Constructor.
-     * @param constraintType
-     *        the type of the current constraint
-     * @param dataRepository
-     *        the data repository
-     */
-    public AbstractInfluenceFunction(ConstraintType constraintType, DataRepository dataRepository) {
-        this.constraintType = constraintType;
-        this.dataRepository = dataRepository;
-    }
-
-    /**
-     * This method validates the constraint type. It throws an IllegalArgumentException if the constraint type of the
-     * given structure is invalid.
-     * @param constraintStructure
-     *        the structure with constraint data
-     */
-    protected void validateConstraintType(Structure constraintStructure) {
-        if (!constraintType.getClassName().equalsIgnoreCase(constraintStructure.getType())) {
-            throw new IllegalArgumentException("Invalud structure type (" + constraintStructure.getType() + ") for the constraint: " + constraintType.getClassName() + '!');
-        }
-    }
-
-    /**
-     * This method affects the bone animation tracks for the given skeleton.
-     * @param skeleton
-     *        the skeleton containing the affected bones by constraint
-     * @param boneAnimation
-     *        the bone animation baked traces
-     * @param constraint
-     *        the constraint
-     */
-    public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-    }
-
-    /**
-     * This method returns the bone traces for the bone that is affected by the given constraint.
-     * @param skeleton
-     *        the skeleton containing bones
-     * @param boneAnimation
-     *        the bone animation that affects the skeleton
-     * @param constraint
-     *        the affecting constraint
-     * @return the bone track for the bone that is being affected by the constraint
-     */
-    protected BoneTrack getBoneTrack(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
-        Long boneOMA = constraint.getBoneOMA();
-        Bone bone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE);
-        int boneIndex = bone==null ? 0 : skeleton.getBoneIndex(bone);//bone==null may mean the object animation
-        if (boneIndex != -1) {
-            //searching for track for this bone
-            for (BoneTrack boneTrack : boneAnimation.getTracks()) {
-                if (boneTrack.getTargetBoneIndex() == boneIndex) {
-                    return boneTrack;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * This method returns the target or subtarget object (if specified).
-     * @param constraint
-     *        the constraint instance
-     * @return target or subtarget feature
-     * @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted
-     */
-    protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException {
-    	//load the feature through objectHelper, this way we are certain the object loads and has
-    	//his own constraints applied to traces
-    	ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
-    	//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");
-    	String subtargetName = subtarget==null ? null : subtarget.toString();
-        if (subtargetName!=null && subtargetName.length() > 0) {
-            result = dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
-        }
-        return result;
-    }
-
-    /**
-     * This method returns target's object location.
-     * @param constraint
-     *        the constraint instance
-     * @return target's object location
-     */
-    protected Vector3f getTargetLocation(Constraint constraint) {
-        Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
-        Space targetSpace = constraint.getTargetSpace();
-        Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
-        switch (targetSpace) {
-            case CONSTRAINT_SPACE_LOCAL:
-                return targetObject.getLocalTranslation();
-            case CONSTRAINT_SPACE_WORLD:
-                return targetObject.getWorldTranslation();
-            default:
-                throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
-        }
-    }
-
-    /**
-     * This method returns target's object location in the specified frame.
-     * @param constraint
-     *        the constraint instance
-     * @param frame
-     *        the frame number
-     * @return target's object location
-     */
-    protected Vector3f getTargetLocation(Constraint constraint, int frame) {
-        return this.getTargetLocation(constraint);//TODO: implement getting location in a specified frame
-    }
-
-    /**
-     * This method returns target's object rotation.
-     * @param constraint
-     *        the constraint instance
-     * @return target's object rotation
-     */
-    protected Quaternion getTargetRotation(Constraint constraint) {
-        Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
-        Space targetSpace = constraint.getTargetSpace();
-        Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
-        switch (targetSpace) {
-            case CONSTRAINT_SPACE_LOCAL:
-                return targetObject.getLocalRotation();
-            case CONSTRAINT_SPACE_WORLD:
-                return targetObject.getWorldRotation();
-            default:
-                throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
-        }
-    }
-
-    /**
-     * This method returns target's object scale.
-     * @param constraint
-     *        the constraint instance
-     * @return target's object scale
-     */
-    protected Vector3f getTargetScale(Constraint constraint) {
-        Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress();
-        Space targetSpace = constraint.getTargetSpace();
-        Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
-        switch (targetSpace) {
-            case CONSTRAINT_SPACE_LOCAL:
-                return targetObject.getLocalScale();
-            case CONSTRAINT_SPACE_WORLD:
-                return targetObject.getWorldScale();
-            default:
-                throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString());
-        }
-    }
-}

+ 0 - 162
engine/src/blender/com/jme3/scene/plugins/blender/structures/Constraint.java

@@ -1,162 +0,0 @@
-package com.jme3.scene.plugins.blender.structures;
-
-import com.jme3.animation.BoneAnimation;
-import com.jme3.animation.Skeleton;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.Pointer;
-
-/**
- * The implementation of a constraint.
- * @author Marcin Roguski
- */
-public class Constraint {
-
-    /** The type of this constraint. */
-    private final ConstraintType type;
-    /** The name of this constraint. */
-    private final String name;
-    /** The old memory address of the constraint's owner. */
-    private final Long boneOMA;
-    private final Space ownerSpace;
-    private final Space targetSpace;
-    /** The structure with constraint's data. */
-    private final Structure data;
-    /** The ipo object defining influence. */
-    private final Ipo ipo;
-    /** The influence function of this constraint. */
-    private final AbstractInfluenceFunction influenceFunction;
-
-    /**
-     * This constructor creates the constraint instance.
-     * @param constraintStructure
-     *        the constraint's structure (bConstraint clss in blender 2.49).
-     * @param influenceFunction
-     *        the constraint's influence function (taken from ConstraintHelper)
-     * @param boneOMA
-     *        the old memory address of the constraint owner
-     * @param influenceIpo
-     *        the ipo curve of the influence factor
-     * @param dataRepository
-     *        the data repository
-     * @throws BlenderFileException
-     */
-    public Constraint(Structure constraintStructure, AbstractInfluenceFunction influenceFunction, Long boneOMA, Space ownerSpace, Space targetSpace, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException {
-        if (influenceFunction == null) {
-            throw new IllegalArgumentException("Influence function is not defined!");
-        }
-        Pointer pData = (Pointer) constraintStructure.getFieldValue("data");
-        if (pData.isNotNull()) {
-            data = pData.fetchData(dataRepository.getInputStream()).get(0);
-        } else {
-            throw new BlenderFileException("The constraint has no data specified!");
-        }
-        this.boneOMA = boneOMA;
-        this.type = ConstraintType.valueOf(((Number) constraintStructure.getFieldValue("type")).intValue());
-        this.name = constraintStructure.getFieldValue("name").toString();
-        this.ownerSpace = ownerSpace;
-        this.targetSpace = targetSpace;
-        this.ipo = influenceIpo;
-        this.influenceFunction = influenceFunction;
-    }
-
-    /**
-     * This method returns the name of the constraint.
-     * @return the name of the constraint
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * This method returns the old memoty address of the bone this constraint affects.
-     * @return the old memory address of the bone this constraint affects
-     */
-    public Long getBoneOMA() {
-        return boneOMA;
-    }
-
-    /**
-     * This method returns owner's transform space.
-     * @return owner's transform space
-     */
-    public Space getOwnerSpace() {
-        return ownerSpace;
-    }
-
-    /**
-     * This method returns target's transform space.
-     * @return target's transform space
-     */
-    public Space getTargetSpace() {
-        return targetSpace;
-    }
-
-    /**
-     * This method returns the type of the constraint.
-     * @return the type of the constraint
-     */
-    public ConstraintType getType() {
-        return type;
-    }
-
-    /**
-     * This method returns the constraint's data structure.
-     * @return the constraint's data structure
-     */
-    public Structure getData() {
-        return data;
-    }
-
-    /**
-     * This method returns the constraint's influcence curve.
-     * @return the constraint's influcence curve
-     */
-    public Ipo getIpo() {
-        return ipo;
-    }
-
-    /**
-     * This method affects the bone animation tracks for the given skeleton.
-     * @param skeleton
-     *        the skeleton containing the affected bones by constraint
-     * @param boneAnimation
-     *        the bone animation baked traces
-     * @param constraint
-     *        the constraint
-     */
-    public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {
-        influenceFunction.affectAnimation(skeleton, boneAnimation, this);
-    }
-
-    /**
-     * The space of target or owner transformation.
-     * @author Marcin Roguski
-     */
-    public static enum Space {
-
-        CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID;
-
-        /**
-         * This method returns the enum instance when given the appropriate value from the blend file.
-         * @param c
-         *        the blender's value of the space modifier
-         * @return the scape enum instance
-         */
-        public static Space valueOf(byte c) {
-            switch (c) {
-                case 0:
-                    return CONSTRAINT_SPACE_WORLD;
-                case 1:
-                    return CONSTRAINT_SPACE_LOCAL;
-                case 2:
-                    return CONSTRAINT_SPACE_POSE;
-                case 3:
-                    return CONSTRAINT_SPACE_PARLOCAL;
-                default:
-                    return CONSTRAINT_SPACE_INVALID;
-            }
-        }
-    }
-}

+ 0 - 68
engine/src/blender/com/jme3/scene/plugins/blender/structures/Modifier.java

@@ -1,68 +0,0 @@
-package com.jme3.scene.plugins.blender.structures;
-
-/**
- * This class represents an object's modifier. The modifier object can be varied and the user needs to know what is
- * the type of it for the specified type name. For example "ArmatureModifierData" type specified in blender is
- * represented by AnimData object from jMonkeyEngine.
- * @author Marcin Roguski (Kaelthas)
- */
-public class Modifier {
-
-    public static final String ARRAY_MODIFIER_DATA = "ArrayModifierData";
-    public static final String ARMATURE_MODIFIER_DATA = "ArmatureModifierData";
-    public static final String PARTICLE_MODIFIER_DATA = "ParticleSystemModifierData";
-    public static final String MIRROR_MODIFIER_DATA = "MirrorModifierData";
-    public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData";
-    
-    /** 
-     * Blender's type of modifier. 
-     */
-    private String type;
-    
-    /** 
-     * JME modifier representation object. 
-     */
-    private Object jmeModifierRepresentation;
-    
-    /** 
-     * Various additional data used by modifiers.
-     */
-    private Object additionalData;
-
-    /**
-     * Constructor. Creates modifier object.
-     * @param type
-     *        blender's type of modifier
-     * @param modifier
-     *        JME modifier representation object
-     */
-    public Modifier(String type, Object modifier, Object additionalData) {
-        this.type = type;
-        this.jmeModifierRepresentation = modifier;
-        this.additionalData = additionalData;
-    }
-
-    /**
-     * This method returns JME modifier representation object.
-     * @return JME modifier representation object
-     */
-    public Object getJmeModifierRepresentation() {
-        return jmeModifierRepresentation;
-    }
-
-    /**
-     * This method returns blender's type of modifier.
-     * @return blender's type of modifier
-     */
-    public String getType() {
-        return type;
-    }
-
-    /**
-     * This method returns additional data stored in the modifier.
-     * @return the additional data stored in the modifier
-     */
-    public Object getAdditionalData() {
-        return additionalData;
-    }
-}

+ 18 - 19
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/textures/NoiseGenerator.java

@@ -28,7 +28,7 @@
  * ***** END GPL LICENSE BLOCK *****
  *
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.textures;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -39,24 +39,23 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.helpers.v249.TextureHelper.CBData;
-import com.jme3.scene.plugins.blender.helpers.v249.TextureHelper.ColorBand;
-import com.jme3.scene.plugins.blender.helpers.v249.TextureHelper.TexResult;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.textures.TextureHelper.CBData;
+import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand;
+import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult;
 
 /**
- * Methods of this class are copied from blender 2.49 source code and modified so that they can be used in java. They
- * are mostly NOT documented because they are not documented in blender's source code. If I find a proper description or
- * discover what they actually do and what parameters mean - I shall describe such methods :) If anyone have some hint
- * what these methods are doing please rite the proper javadoc documentation. These methods should be used to create
- * generated textures.
+ * This generator is responsible for creating various noises used to create
+ * generated textures loaded from blender.
+ * It derives from AbstractBlenderHelper but is not stored in data repository.
+ * It is only used by TextureHelper.
  * @author Marcin Roguski (Kaelthas)
  */
-public class NoiseHelper extends AbstractBlenderHelper {
+/*package*/ class NoiseGenerator extends AbstractBlenderHelper {
 
-    private static final Logger LOGGER = Logger.getLogger(NoiseHelper.class.getName());
+    private static final Logger LOGGER = Logger.getLogger(NoiseGenerator.class.getName());
 
     /* return value */
     protected static final int TEX_INT = 0;
@@ -137,7 +136,7 @@ public class NoiseHelper extends AbstractBlenderHelper {
      * @param blenderVersion
      *        the number of blender version
      */
-    public NoiseHelper(String blenderVersion) {
+    public NoiseGenerator(String blenderVersion) {
         super(blenderVersion);
         this.loadConstants();
     }
@@ -148,7 +147,7 @@ public class NoiseHelper extends AbstractBlenderHelper {
      * an exception will be thrown the class will not be instantiated.
      */
     protected void loadConstants() {
-        InputStream is = NoiseHelper.class.getResourceAsStream("noiseconstants.dat");
+        InputStream is = NoiseGenerator.class.getResourceAsStream("noiseconstants.dat");
         try {
             ObjectInputStream ois = new ObjectInputStream(is);
             hashpntf = (float[]) ois.readObject();
@@ -332,7 +331,7 @@ public class NoiseHelper extends AbstractBlenderHelper {
         });
     }
     /** Distance metrics for voronoi. e parameter only used in Minkovsky. */
-    protected static Map<Integer, DistanceFunc> distanceFunctions = new HashMap<Integer, NoiseHelper.DistanceFunc>();
+    protected static Map<Integer, DistanceFunc> distanceFunctions = new HashMap<Integer, NoiseGenerator.DistanceFunc>();
 
     static {
         // real distance
@@ -400,7 +399,7 @@ public class NoiseHelper extends AbstractBlenderHelper {
             }
         });
     }
-    protected static Map<Integer, MusgraveFunction> musgraveFunctions = new HashMap<Integer, NoiseHelper.MusgraveFunction>();
+    protected static Map<Integer, MusgraveFunction> musgraveFunctions = new HashMap<Integer, NoiseGenerator.MusgraveFunction>();
 
     static {
         musgraveFunctions.put(Integer.valueOf(TEX_MFRACTAL), new MusgraveFunction() {
@@ -895,7 +894,7 @@ public class NoiseHelper extends AbstractBlenderHelper {
         float n = 5.0f * (x + y + z);
         float mi = n + turbul * this.bliGTurbulence(noisesize, x, y, z, noisedepth, noisetype != TEX_NOISESOFT, noisebasis);
 
-        if (stype >= NoiseHelper.TEX_SOFT) { /* TEX_SOFT always true */
+        if (stype >= NoiseGenerator.TEX_SOFT) { /* TEX_SOFT always true */
             mi = waveformFunctions[waveform].execute(mi);
             if (stype == TEX_SHARP) {
                 mi = (float) Math.sqrt(mi);

+ 44 - 43
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java → engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java

@@ -29,7 +29,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-package com.jme3.scene.plugins.blender.helpers.v249;
+package com.jme3.scene.plugins.blender.textures;
 
 import java.awt.color.ColorSpace;
 import java.awt.image.BufferedImage;
@@ -52,16 +52,16 @@ import com.jme3.asset.GeneratedTextureKey;
 import com.jme3.asset.TextureKey;
 import com.jme3.math.FastMath;
 import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.data.FileBlockHeader;
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-import com.jme3.scene.plugins.blender.helpers.NoiseHelper;
-import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.utils.BlenderInputStream;
-import com.jme3.scene.plugins.blender.utils.DataRepository;
-import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType;
-import com.jme3.scene.plugins.blender.utils.DynamicArray;
-import com.jme3.scene.plugins.blender.utils.Pointer;
+import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
+import com.jme3.scene.plugins.blender.DataRepository;
+import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
+import com.jme3.scene.plugins.blender.file.BlenderInputStream;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.FileBlockHeader;
+import com.jme3.scene.plugins.blender.file.Pointer;
+import com.jme3.scene.plugins.blender.file.Structure;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
 import com.jme3.texture.Image;
 import com.jme3.texture.Image.Format;
 import com.jme3.texture.Texture;
@@ -95,7 +95,9 @@ public class TextureHelper extends AbstractBlenderHelper {
 	public static final int		TEX_MUSGRAVE		= 11;
 	public static final int		TEX_VORONOI			= 12;
 	public static final int		TEX_DISTNOISE		= 13;
-
+	public static final int 	TEX_POINTDENSITY 	= 14;//v. 25+
+    public static final int 	TEX_VOXELDATA 		= 15;//v. 25+
+    
 	// mapto
 	public static final int		MAP_COL				= 1;
 	public static final int		MAP_NORM			= 2;
@@ -149,6 +151,8 @@ public class TextureHelper extends AbstractBlenderHelper {
 	public static final int		MA_RAMP_VAL			= 14;
 	public static final int		MA_RAMP_COLOR		= 15;
 
+	protected NoiseGenerator noiseHelper;
+	
 	/**
 	 * This constructor parses the given blender version and stores the result. Some functionalities may differ in different blender
 	 * versions.
@@ -158,6 +162,7 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 */
 	public TextureHelper(String blenderVersion) {
 		super(blenderVersion);
+		noiseHelper = new NoiseGenerator(blenderVersion);
 	}
 
 	/**
@@ -221,6 +226,12 @@ public class TextureHelper extends AbstractBlenderHelper {
 				break;
 			case TEX_NONE:// No texture, do nothing
 				break;
+			case TEX_POINTDENSITY:
+                LOGGER.warning("Point density texture loading currently not supported!");
+                break;
+            case TEX_VOXELDATA:
+                LOGGER.warning("Voxel data texture loading currently not supported!");
+                break;
 			case TEX_PLUGIN:
 			case TEX_ENVMAP:// TODO: implement envmap texture
 				LOGGER.log(Level.WARNING, "Unsupported texture type: {0} for texture: {1}", new Object[]{type, tex.getName()});
@@ -253,7 +264,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 */
 	protected Texture clouds(Structure tex, int width, int height, DataRepository dataRepository) {
 		// preparing the proper data
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float wDelta = 1.0f / width, hDelta = 1.0f / height;
 		float[] texvec = new float[] { 0, 0, 0 };
 		TexResult texres = new TexResult();
@@ -265,14 +275,14 @@ public class TextureHelper extends AbstractBlenderHelper {
 		int noiseType = ((Number) tex.getFieldValue("noisetype")).intValue();
 		float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
 		float bright = ((Number) tex.getFieldValue("bright")).floatValue();
-		boolean isHard = noiseType != com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_NOISESOFT;
+		boolean isHard = noiseType != NoiseGenerator.TEX_NOISESOFT;
 		int sType = ((Number) tex.getFieldValue("stype")).intValue();
 		int halfW = width, halfH = height;
 		width <<= 1;
 		height <<= 1;
 		ColorBand colorBand = this.readColorband(tex, dataRepository);
-		Format format = sType == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8;
-		int bytesPerPixel = sType == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLOR || colorBand != null ? 3 : 1;
+		Format format = sType == NoiseGenerator.TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8;
+		int bytesPerPixel = sType == NoiseGenerator.TEX_COLOR || colorBand != null ? 3 : 1;
 
 		ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
 		for (int i = -halfW; i < halfW; ++i) {
@@ -295,7 +305,7 @@ public class TextureHelper extends AbstractBlenderHelper {
 					data.put((byte) (texres.tr * 255.0f));
 					data.put((byte) (texres.tg * 255.0f));
 					data.put((byte) (texres.tb * 255.0f));
-				} else if (sType == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLOR) {
+				} else if (sType == NoiseGenerator.TEX_COLOR) {
 					// in this case, int. value should really be computed from color,
 					// and bumpnormal from that, would be too slow, looks ok as is
 					texres.tr = texres.tin;
@@ -329,7 +339,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 */
 	protected Texture wood(Structure tex, int width, int height, DataRepository dataRepository) {
 		// preparing the proper data
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
 		float bright = ((Number) tex.getFieldValue("bright")).floatValue();
 		float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
@@ -386,7 +395,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 */
 	protected Texture marble(Structure tex, int width, int height, DataRepository dataRepository) {
 		// preparing the proper data
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
 		float bright = ((Number) tex.getFieldValue("bright")).floatValue();
 		float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
@@ -442,7 +450,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 * @return the generated texture
 	 */
 	protected Texture magic(Structure tex, int width, int height, DataRepository dataRepository) {
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float x, y, z, turb;
 		int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue();
 		float turbul = ((Number) tex.getFieldValue("turbul")).floatValue() / 5.0f;
@@ -536,7 +543,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 * @return the generated texture
 	 */
 	protected Texture blend(Structure tex, int width, int height, DataRepository dataRepository) {
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		int flag = ((Number) tex.getFieldValue("flag")).intValue();
 		int stype = ((Number) tex.getFieldValue("stype")).intValue();
 		float contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
@@ -556,7 +562,7 @@ public class TextureHelper extends AbstractBlenderHelper {
 			texvec[0] = wDelta * i;
 			for (int j = -halfH; j < halfH; ++j) {
 				texvec[1] = hDelta * j;
-				if ((flag & com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_FLIPBLEND) != 0) {
+				if ((flag & NoiseGenerator.TEX_FLIPBLEND) != 0) {
 					x = texvec[1];
 					y = texvec[0];
 				} else {
@@ -564,16 +570,16 @@ public class TextureHelper extends AbstractBlenderHelper {
 					y = texvec[1];
 				}
 
-				if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_LIN) { /* lin */
+				if (stype == NoiseGenerator.TEX_LIN) { /* lin */
 					texres.tin = (1.0f + x) / 2.0f;
-				} else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_QUAD) { /* quad */
+				} else if (stype == NoiseGenerator.TEX_QUAD) { /* quad */
 					texres.tin = (1.0f + x) / 2.0f;
 					if (texres.tin < 0.0f) {
 						texres.tin = 0.0f;
 					} else {
 						texres.tin *= texres.tin;
 					}
-				} else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_EASE) { /* ease */
+				} else if (stype == NoiseGenerator.TEX_EASE) { /* ease */
 					texres.tin = (1.0f + x) / 2.0f;
 					if (texres.tin <= 0.0f) {
 						texres.tin = 0.0f;
@@ -583,16 +589,16 @@ public class TextureHelper extends AbstractBlenderHelper {
 						t = texres.tin * texres.tin;
 						texres.tin = 3.0f * t - 2.0f * t * texres.tin;
 					}
-				} else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_DIAG) { /* diag */
+				} else if (stype == NoiseGenerator.TEX_DIAG) { /* diag */
 					texres.tin = (2.0f + x + y) / 4.0f;
-				} else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_RAD) { /* radial */
+				} else if (stype == NoiseGenerator.TEX_RAD) { /* radial */
 					texres.tin = (float) Math.atan2(y, x) / FastMath.TWO_PI + 0.5f;
 				} else { /* sphere TEX_SPHERE */
 					texres.tin = 1.0f - (float) Math.sqrt(x * x + y * y + texvec[2] * texvec[2]);
 					if (texres.tin < 0.0f) {
 						texres.tin = 0.0f;
 					}
-					if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_HALO) {
+					if (stype == NoiseGenerator.TEX_HALO) {
 						texres.tin *= texres.tin;
 					} /* halo */
 				}
@@ -629,10 +635,9 @@ public class TextureHelper extends AbstractBlenderHelper {
 		int noisebasis = ((Number) tex.getFieldValue("noisebasis")).intValue();
 		int noisetype = ((Number) tex.getFieldValue("noisetype")).intValue();
 		float turbul = ((Number) tex.getFieldValue("turbul")).floatValue();
-		boolean isHard = noisetype != com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_NOISESOFT;
+		boolean isHard = noisetype != NoiseGenerator.TEX_NOISESOFT;
 		int stype = ((Number) tex.getFieldValue("stype")).intValue();
 
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float[] texvec = new float[] { 0, 0, 0 };
 		TexResult texres = new TexResult();
 		float wDelta = 1.0f / width, hDelta = 1.0f / height, b2, ofs;
@@ -665,7 +670,7 @@ public class TextureHelper extends AbstractBlenderHelper {
 						texres.nor[2] = texres.tin;
 						noiseHelper.texNormalDerivate(colorBand, texres, dataRepository);
 
-						if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_WALLOUT) {
+						if (stype == NoiseGenerator.TEX_WALLOUT) {
 							texres.nor[0] = -texres.nor[0];
 							texres.nor[1] = -texres.nor[1];
 							texres.nor[2] = -texres.nor[2];
@@ -673,7 +678,7 @@ public class TextureHelper extends AbstractBlenderHelper {
 					}
 				}
 
-				if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_WALLOUT) {
+				if (stype == NoiseGenerator.TEX_WALLOUT) {
 					texres.tin = 1.0f - texres.tin;
 				}
 				if (texres.tin < 0.0f) {
@@ -706,7 +711,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 */
 	// TODO: correct this one, so it looks more like the texture generated by blender
 	protected Texture texnoise(Structure tex, int width, int height, DataRepository dataRepository) {
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float div = 3.0f;
 		int val, ran, loop;
 		int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue();
@@ -762,7 +766,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 * @return the generated texture
 	 */
 	protected Texture musgrave(Structure tex, int width, int height, DataRepository dataRepository) {
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		int stype = ((Number) tex.getFieldValue("stype")).intValue();
 		float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
 		TexResult texres = new TexResult();
@@ -781,15 +784,15 @@ public class TextureHelper extends AbstractBlenderHelper {
 			for (int j = -halfH; j < halfH; ++j) {
 				texvec[1] = hDelta * j / noisesize;
 				switch (stype) {
-					case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_MFRACTAL:
-					case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_FBM:
+					case NoiseGenerator.TEX_MFRACTAL:
+					case NoiseGenerator.TEX_FBM:
 						noiseHelper.mgMFractalOrfBmTex(tex, texvec, colorBand, texres, dataRepository);
 						break;
-					case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_RIDGEDMF:
-					case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_HYBRIDMF:
+					case NoiseGenerator.TEX_RIDGEDMF:
+					case NoiseGenerator.TEX_HYBRIDMF:
 						noiseHelper.mgRidgedOrHybridMFTex(tex, texvec, colorBand, texres, dataRepository);
 						break;
-					case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_HTERRAIN:
+					case NoiseGenerator.TEX_HTERRAIN:
 						noiseHelper.mgHTerrainTex(tex, texvec, colorBand, texres, dataRepository);
 						break;
 					default:
@@ -822,7 +825,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 * @return the generated texture
 	 */
 	protected Texture voronoi(Structure tex, int width, int height, DataRepository dataRepository) {
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float vn_w1 = ((Number) tex.getFieldValue("vn_w1")).floatValue();
 		float vn_w2 = ((Number) tex.getFieldValue("vn_w2")).floatValue();
 		float vn_w3 = ((Number) tex.getFieldValue("vn_w3")).floatValue();
@@ -944,7 +946,6 @@ public class TextureHelper extends AbstractBlenderHelper {
 	 * @return the generated texture
 	 */
 	protected Texture distnoise(Structure tex, int width, int height, DataRepository dataRepository) {
-		NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class);
 		float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
 		float nabla = ((Number) tex.getFieldValue("nabla")).floatValue();
 		float distAmount = ((Number) tex.getFieldValue("dist_amount")).floatValue();
@@ -1006,7 +1007,7 @@ public class TextureHelper extends AbstractBlenderHelper {
 	protected ColorBand readColorband(Structure tex, DataRepository dataRepository) {
 		ColorBand result = null;
 		int flag = ((Number) tex.getFieldValue("flag")).intValue();
-		if ((flag & com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLORBAND) != 0) {
+		if ((flag & NoiseGenerator.TEX_COLORBAND) != 0) {
 			Pointer pColorband = (Pointer) tex.getFieldValue("coba");
 			Structure colorbandStructure;
 			try {
@@ -1965,4 +1966,4 @@ public class TextureHelper extends AbstractBlenderHelper {
 			return super.clone();
 		}
 	}
-}
+}

+ 0 - 0
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/noiseconstants.dat → engine/src/blender/com/jme3/scene/plugins/blender/textures/noiseconstants.dat


+ 0 - 110
engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderConverter.java

@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.scene.plugins.blender.utils;
-
-import com.jme3.scene.plugins.blender.data.Structure;
-import com.jme3.scene.plugins.blender.exception.BlenderFileException;
-
-/**
- * This interface provides an abstraction to converting loaded blender structures into data structures. The data
- * structures can vary and therefore one can use the loader for different kind of engines.
- * @author Marcin Roguski
- * @param <NodeType>
- *        the type of the scene node element
- * @param <CameraType>
- *        the type of camera element
- * @param <LightType>
- *        the type of light element
- * @param <ObjectType>
- *        the type of object element
- * @param <MeshType>
- *        the type of mesh element
- * @param <MaterialType>
- *        the type of material element
- */
-//TODO: ujednolicić wyrzucane wyjątki
-public interface BlenderConverter<NodeType, CameraType, LightType, ObjectType, MeshType, MaterialType> {
-
-    /**
-     * This method reads converts the given structure into scene. The given structure needs to be filled with the
-     * appropriate data.
-     * @param structure
-     *        the structure we read the scene from
-     * @return the scene feature
-     */
-    NodeType toScene(Structure structure);
-
-    /**
-     * This method reads converts the given structure into camera. The given structure needs to be filled with the
-     * appropriate data.
-     * @param structure
-     *        the structure we read the camera from
-     * @return the camera feature
-     */
-    CameraType toCamera(Structure structure) throws BlenderFileException;
-
-    /**
-     * This method reads converts the given structure into light. The given structure needs to be filled with the
-     * appropriate data.
-     * @param structure
-     *        the structure we read the light from
-     * @return the light feature
-     */
-    LightType toLight(Structure structure) throws BlenderFileException;
-
-    /**
-     * This method reads converts the given structure into objct. The given structure needs to be filled with the
-     * appropriate data.
-     * @param structure
-     *        the structure we read the object from
-     * @return the object feature
-     */
-    ObjectType toObject(Structure structure) throws BlenderFileException;
-
-    /**
-     * This method reads converts the given structure into mesh. The given structure needs to be filled with the
-     * appropriate data.
-     * @param structure
-     *        the structure we read the mesh from
-     * @return the mesh feature
-     */
-    MeshType toMesh(Structure structure) throws BlenderFileException;
-
-    /**
-     * This method reads converts the given structure into material. The given structure needs to be filled with the
-     * appropriate data.
-     * @param structure
-     *        the structure we read the material from
-     * @return the material feature
-     */
-    MaterialType toMaterial(Structure structure) throws BlenderFileException;
-}