Browse Source

Removing the jme3-blender subproject and related references since it now lives in its
own repository: https://github.com/jMonkeyEngine-Contributions/BlenderLoader

pspeed42 5 years ago
parent
commit
221acaadfe
100 changed files with 3 additions and 25369 deletions
  1. 3 3
      README.md
  2. 0 12
      jme3-blender/build.gradle
  3. 0 83
      jme3-blender/examples/src/main/java/jme3test/blender/TestBlenderLoader.java
  4. 0 136
      jme3-blender/examples/src/main/java/jme3test/light/TestTangentGenBadModels.java
  5. 0 95
      jme3-blender/examples/src/main/java/jme3test/model/anim/TestBlenderAnim.java
  6. 0 94
      jme3-blender/examples/src/main/java/jme3test/model/anim/TestBlenderObjectAnim.java
  7. 0 733
      jme3-blender/src/main/java/com/jme3/asset/BlenderKey.java
  8. 0 69
      jme3-blender/src/main/java/com/jme3/asset/GeneratedTextureKey.java
  9. 0 193
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java
  10. 0 767
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderContext.java
  11. 0 419
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderLoader.java
  12. 0 40
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderModelLoader.java
  13. 0 391
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/AnimationHelper.java
  14. 0 134
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/BlenderAction.java
  15. 0 400
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/BoneContext.java
  16. 0 133
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/BoneEnvelope.java
  17. 0 317
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/Ipo.java
  18. 0 148
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/cameras/CameraHelper.java
  19. 0 88
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/BoneConstraint.java
  20. 0 186
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/Constraint.java
  21. 0 476
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java
  22. 0 397
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SimulationNode.java
  23. 0 41
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SkeletonConstraint.java
  24. 0 32
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SpatialConstraint.java
  25. 0 165
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/VirtualTrack.java
  26. 0 162
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java
  27. 0 84
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionDistLimit.java
  28. 0 126
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java
  29. 0 236
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java
  30. 0 107
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLocLike.java
  31. 0 106
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLocLimit.java
  32. 0 61
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionMaintainVolume.java
  33. 0 34
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionNull.java
  34. 0 87
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRotLike.java
  35. 0 129
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRotLimit.java
  36. 0 74
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSizeLike.java
  37. 0 96
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSizeLimit.java
  38. 0 81
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionTransLike.java
  39. 0 40
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/UnsupportedConstraintDefinition.java
  40. 0 172
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/BezierCurve.java
  41. 0 159
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesHelper.java
  42. 0 890
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesTemporalMesh.java
  43. 0 77
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/BlenderFileException.java
  44. 0 371
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/BlenderInputStream.java
  45. 0 203
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/DnaBlockData.java
  46. 0 135
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/DynamicArray.java
  47. 0 327
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/Field.java
  48. 0 213
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/FileBlockHeader.java
  49. 0 189
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/Pointer.java
  50. 0 328
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/Structure.java
  51. 0 214
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/landscape/LandscapeHelper.java
  52. 0 116
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/lights/LightHelper.java
  53. 0 26
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/IAlphaMask.java
  54. 0 366
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java
  55. 0 387
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialHelper.java
  56. 0 583
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DQuaternion.java
  57. 0 190
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DTransform.java
  58. 0 210
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Matrix.java
  59. 0 869
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Vector3d.java
  60. 0 349
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Edge.java
  61. 0 613
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Face.java
  62. 0 305
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/IndexesLoop.java
  63. 0 364
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/MeshBuffers.java
  64. 0 381
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
  65. 0 93
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Point.java
  66. 0 767
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java
  67. 0 113
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java
  68. 0 241
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java
  69. 0 200
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/MaskModifier.java
  70. 0 196
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java
  71. 0 92
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/Modifier.java
  72. 0 117
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ModifierHelper.java
  73. 0 107
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java
  74. 0 642
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java
  75. 0 54
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/TriangulateModifier.java
  76. 0 520
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/objects/ObjectHelper.java
  77. 0 365
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/objects/Properties.java
  78. 0 192
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java
  79. 0 401
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/ColorBand.java
  80. 0 543
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
  81. 0 157
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/DDSTexelData.java
  82. 0 282
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/GeneratedTexture.java
  83. 0 136
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/ImageLoader.java
  84. 0 473
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/ImageUtils.java
  85. 0 691
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  86. 0 392
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TexturePixel.java
  87. 0 662
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java
  88. 0 420
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java
  89. 0 240
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/UVProjectionGenerator.java
  90. 0 86
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/UserUVCollection.java
  91. 0 139
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java
  92. 0 53
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlender.java
  93. 0 275
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
  94. 0 131
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java
  95. 0 117
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderFactory.java
  96. 0 259
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java
  97. 0 814
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/NoiseGenerator.java
  98. 0 128
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/TextureGenerator.java
  99. 0 138
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/TextureGeneratorBlend.java
  100. 0 121
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/TextureGeneratorClouds.java

+ 3 - 3
README.md

@@ -1,4 +1,4 @@
-jMonkeyEngine 
+jMonkeyEngine
 =============
 
 [![Build Status](https://github.com/jMonkeyEngine/jmonkeyengine/workflows/Build%20jMonkeyEngine/badge.svg)](https://github.com/jMonkeyEngine/jmonkeyengine/actions)
@@ -37,8 +37,8 @@ Note: The master branch on GitHub is a development version of the engine and is
  - NetBeans Platform
  - Gradle
 
-Plus a bunch of awesome libraries & tight integrations like Bullet, Blender, NiftyGUI and other goodies.
- 
+Plus a bunch of awesome libraries & tight integrations like Bullet, NiftyGUI and other goodies.
+
 ### Documentation
 
 Did you miss it? Don't sweat it, [here it is again](https://jmonkeyengine.github.io/wiki).

+ 0 - 12
jme3-blender/build.gradle

@@ -1,12 +0,0 @@
-if (!hasProperty('mainClass')) {
-    ext.mainClass = ''
-}
-
-dependencies {
-    compile project(':jme3-core')
-    compile project(':jme3-desktop')
-    compile project(':jme3-effects')
-    compile ('org.ejml:core:0.27')
-    compile ('org.ejml:dense64:0.27')
-    compile ('org.ejml:simple:0.27')
-}

+ 0 - 83
jme3-blender/examples/src/main/java/jme3test/blender/TestBlenderLoader.java

@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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 jme3test.blender;
-
-import com.jme3.app.SimpleApplication;
-import com.jme3.light.DirectionalLight;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Spatial;
-
-public class TestBlenderLoader extends SimpleApplication {
-
-    public static void main(String[] args){
-        TestBlenderLoader app = new TestBlenderLoader();
-        app.start();
-    }
-
-    @Override
-    public void simpleInitApp() {
-        viewPort.setBackgroundColor(ColorRGBA.DarkGray);
-
-        //load model with packed images
-        Spatial ogre = assetManager.loadModel("Blender/2.4x/Sinbad.blend");
-        rootNode.attachChild(ogre);
-
-        //load model with referenced images
-        Spatial track = assetManager.loadModel("Blender/2.4x/MountainValley_Track.blend");
-        rootNode.attachChild(track);
-        
-        // sunset light
-        DirectionalLight dl = new DirectionalLight();
-        dl.setDirection(new Vector3f(-0.1f,-0.7f,1).normalizeLocal());
-        dl.setColor(new ColorRGBA(0.44f, 0.30f, 0.20f, 1.0f));
-        rootNode.addLight(dl);
-
-        // skylight
-        dl = new DirectionalLight();
-        dl.setDirection(new Vector3f(-0.6f,-1,-0.6f).normalizeLocal());
-        dl.setColor(new ColorRGBA(0.10f, 0.22f, 0.44f, 1.0f));
-        rootNode.addLight(dl);
-
-        // white ambient light
-        dl = new DirectionalLight();
-        dl.setDirection(new Vector3f(1, -0.5f,-0.1f).normalizeLocal());
-        dl.setColor(new ColorRGBA(0.80f, 0.70f, 0.80f, 1.0f));
-        rootNode.addLight(dl);
-    }
-
-    @Override
-    public void simpleUpdate(float tpf){
-    }
-    
-}

+ 0 - 136
jme3-blender/examples/src/main/java/jme3test/light/TestTangentGenBadModels.java

@@ -1,136 +0,0 @@
-package jme3test.light;
-
-import com.jme3.app.SimpleApplication;
-import com.jme3.font.BitmapText;
-import com.jme3.input.KeyInput;
-import com.jme3.input.controls.ActionListener;
-import com.jme3.input.controls.KeyTrigger;
-import com.jme3.light.DirectionalLight;
-import com.jme3.light.PointLight;
-import com.jme3.material.Material;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector3f;
-import com.jme3.renderer.queue.RenderQueue.Bucket;
-import com.jme3.scene.*;
-import com.jme3.scene.Spatial.CullHint;
-import com.jme3.scene.shape.Sphere;
-import com.jme3.util.TangentBinormalGenerator;
-
-/**
- *
- * @author Kirusha
- */
-public class TestTangentGenBadModels extends SimpleApplication {
-    
-    float angle;
-    PointLight pl;
-    Geometry lightMdl;
-
-    public static void main(String[] args){
-        TestTangentGenBadModels app = new TestTangentGenBadModels();
-        app.start();
-    }
-
-    @Override
-    public void simpleInitApp() {
-//        assetManager.registerLocator("http://jme-glsl-shaders.googlecode.com/hg/assets/Models/LightBlow/", UrlLocator.class);
-//        assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/", UrlLocator.class);
-        
-        final Spatial badModel = assetManager.loadModel("Models/TangentBugs/test.blend");
-//        badModel.setLocalScale(1f);
-        
-        Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
-        mat.setTexture("NormalMap", assetManager.loadTexture("Models/TangentBugs/test_normal.png"));
-//        Material mat = assetManager.loadMaterial("Textures/BumpMapTest/Tangent.j3m");
-        badModel.setMaterial(mat);
-        rootNode.attachChild(badModel);
-        
-        // TODO: For some reason blender loader fails to load this.
-        // need to check it
-//        Spatial model = assetManager.loadModel("test.blend");
-//        rootNode.attachChild(model);
-        
-        final Node debugTangents = new Node("debug tangents");
-        debugTangents.setCullHint(CullHint.Always);
-        rootNode.attachChild(debugTangents);
-
-        final Material debugMat = assetManager.loadMaterial("Common/Materials/VertexColor.j3m");
-        
-        badModel.depthFirstTraversal(new SceneGraphVisitorAdapter(){
-            @Override
-            public void visit(Geometry g){
-                Mesh m = g.getMesh();
-                Material mat = g.getMaterial();
-                
-//                if (mat.getParam("DiffuseMap") != null){
-//                    mat.setTexture("DiffuseMap", null);
-//                }
-                TangentBinormalGenerator.generate(m);
-                
-                Geometry debug = new Geometry(
-                    "debug tangents geom",
-                    TangentBinormalGenerator.genTbnLines(g.getMesh(), 0.2f)
-                );
-                debug.setMaterial(debugMat);
-                debug.setCullHint(Spatial.CullHint.Never);
-                debug.setLocalTransform(g.getWorldTransform());
-                debugTangents.attachChild(debug);
-            }
-        });
-
-        DirectionalLight dl = new DirectionalLight();
-        dl.setDirection(new Vector3f(-0.8f, -0.6f, -0.08f).normalizeLocal());
-        dl.setColor(new ColorRGBA(1,1,1,1));
-        rootNode.addLight(dl);
-
-        lightMdl = new Geometry("Light", new Sphere(10, 10, 0.1f));
-        lightMdl.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m"));
-        lightMdl.getMesh().setStatic();
-        rootNode.attachChild(lightMdl);
-
-        pl = new PointLight();
-        pl.setColor(ColorRGBA.White);
-//        rootNode.addLight(pl);
-        
-        
-        BitmapText info = new BitmapText(guiFont);
-        info.setText("Press SPACE to switch between lighting and tangent display");
-        info.setQueueBucket(Bucket.Gui);
-        info.move(0, settings.getHeight() - info.getLineHeight(), 0);
-        rootNode.attachChild(info);
-        
-        inputManager.addMapping("space", new KeyTrigger(KeyInput.KEY_SPACE));
-        inputManager.addListener(new ActionListener() {
-            
-            private boolean isLit = true;
-            
-            @Override
-            public void onAction(String name, boolean isPressed, float tpf) {
-                if (isPressed) return;
-                Material mat;
-                if (isLit){
-                    mat = assetManager.loadMaterial("Textures/BumpMapTest/Tangent.j3m");
-                    debugTangents.setCullHint(CullHint.Inherit);
-                }else{
-                    mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
-                    mat.setTexture("NormalMap", assetManager.loadTexture("Models/TangentBugs/test_normal.png"));
-                    debugTangents.setCullHint(CullHint.Always);
-                }
-                isLit = !isLit;
-                badModel.setMaterial(mat);
-            }
-        }, "space");
-    }
-
-    @Override
-    public void simpleUpdate(float tpf){
-        angle += tpf;
-        angle %= FastMath.TWO_PI;
-        
-        pl.setPosition(new Vector3f(FastMath.cos(angle) * 2f, 2f, FastMath.sin(angle) * 2f));
-        lightMdl.setLocalTranslation(pl.getPosition());
-    }
-    
-    
-}

+ 0 - 95
jme3-blender/examples/src/main/java/jme3test/model/anim/TestBlenderAnim.java

@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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 jme3test.model.anim;
-
-import com.jme3.anim.AnimClip;
-import com.jme3.anim.AnimComposer;
-import com.jme3.anim.util.AnimMigrationUtils;
-import com.jme3.app.SimpleApplication;
-import com.jme3.asset.BlenderKey;
-import com.jme3.light.DirectionalLight;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-
-public class TestBlenderAnim extends SimpleApplication {
-
-	public static void main(String[] args) {
-		TestBlenderAnim app = new TestBlenderAnim();
-		app.start();
-	}
-
-	@Override
-	public void simpleInitApp() {
-		flyCam.setMoveSpeed(10f);
-		cam.setLocation(new Vector3f(6.4013605f, 7.488437f, 12.843031f));
-		cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f));
-
-		DirectionalLight dl = new DirectionalLight();
-		dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
-		dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
-		rootNode.addLight(dl);
-
-		BlenderKey blenderKey = new BlenderKey("Blender/2.4x/BaseMesh_249.blend");
-
-		Spatial scene = assetManager.loadModel(blenderKey);
-		rootNode.attachChild(scene);
-
-		Spatial model = this.findNode(rootNode, "BaseMesh_01");
-		AnimMigrationUtils.migrate(model);
-		model.center();
-
-		AnimComposer animComposer = model.getControl(AnimComposer.class);
-		animComposer.getAnimClips().forEach(animClip -> System.out.println("AnimClip name: " + animClip.getName()));
-		AnimClip animClip = animComposer.getAnimClip("run_01"); // run_sideway_left, aim, run_sideway_right, base_stand, run_01, base, jump
-		animComposer.setCurrentAction(animClip.getName());
-	}
-
-	/**
-	 * This method finds a node of a given name.
-	 * 
-	 * @param rootNode
-	 *            the root node to search
-	 * @param name
-	 *            the name of the searched node
-	 * @return the found node or null
-	 */
-	private Spatial findNode(Node rootNode, String name) {
-		if (name.equals(rootNode.getName())) {
-			return rootNode;
-		}
-		return rootNode.getChild(name);
-	}
-}

+ 0 - 94
jme3-blender/examples/src/main/java/jme3test/model/anim/TestBlenderObjectAnim.java

@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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 jme3test.model.anim;
-
-import com.jme3.anim.AnimClip;
-import com.jme3.anim.AnimComposer;
-import com.jme3.anim.util.AnimMigrationUtils;
-import com.jme3.app.SimpleApplication;
-import com.jme3.asset.BlenderKey;
-import com.jme3.light.DirectionalLight;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-
-public class TestBlenderObjectAnim extends SimpleApplication {
-
-    public static void main(String[] args) {
-        TestBlenderObjectAnim app = new TestBlenderObjectAnim();
-        app.start();
-    }
-
-    @Override
-    public void simpleInitApp() {
-        flyCam.setMoveSpeed(10f);
-        cam.setLocation(new Vector3f(6.4013605f, 7.488437f, 12.843031f));
-        cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f));
-
-        DirectionalLight dl = new DirectionalLight();
-        dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
-        dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
-        rootNode.addLight(dl);
-
-        BlenderKey blenderKey = new BlenderKey("Blender/2.4x/animtest.blend");
-        
-        Spatial scene = assetManager.loadModel(blenderKey);
-        rootNode.attachChild(scene);
-        
-        Spatial model = this.findNode(rootNode, "Cube");
-        model.center();
-        
-        // Because it's old .blend file need to migrate object.
-        AnimMigrationUtils.migrate(model);
-
-        AnimComposer animComposer = model.getControl(AnimComposer.class);
-        animComposer.getAnimClips().forEach(animClip -> System.out.println("AnimClip name: " + animClip.getName()));
-        AnimClip animClip = animComposer.getAnimClip("Action"); // Action, Action.001
-        animComposer.setCurrentAction(animClip.getName());
-    }
-    
-    /**
-     * This method finds a node of a given name.
-     * @param rootNode the root node to search
-     * @param name the name of the searched node
-     * @return the found node or null
-     */
-    private Spatial findNode(Node rootNode, String name) {
-        if (name.equals(rootNode.getName())) {
-            return rootNode;
-        }
-        return rootNode.getChild(name);
-    }
-}

+ 0 - 733
jme3-blender/src/main/java/com/jme3/asset/BlenderKey.java

@@ -1,733 +0,0 @@
-/*
- * Copyright (c) 2009-2018 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.asset;
-
-import java.io.IOException;
-
-import com.jme3.export.InputCapsule;
-import com.jme3.export.JmeExporter;
-import com.jme3.export.JmeImporter;
-import com.jme3.export.OutputCapsule;
-import com.jme3.material.Material;
-import com.jme3.material.RenderState.FaceCullMode;
-
-/**
- * Blender key. Contains path of the blender file and its loading properties.
- * @author Marcin Roguski (Kaelthas)
- */
-public class BlenderKey extends ModelKey {
-    protected static final int         DEFAULT_FPS               = 25;
-    /**
-     * FramesPerSecond parameter describe how many frames there are in each second. It allows to calculate the time
-     * between the frames.
-     */
-    protected int                      fps                       = DEFAULT_FPS;
-    /**
-     * This variable is a bitwise flag of FeatureToLoad interface values; By default everything is being loaded.
-     */
-    protected int                      featuresToLoad            = FeaturesToLoad.ALL;
-    /** The variable that tells if content of the file (along with data unlinked to any feature on the scene) should be stored as 'user data' in the result spatial. */
-    protected boolean                  loadUnlinkedAssets;
-    /** The root path for all the assets. */
-    protected String                   assetRootPath;
-    /** This variable indicate if Y axis is UP axis. If not then Z is up. By default set to true. */
-    protected boolean                  fixUpAxis                 = true;
-    /** Generated textures resolution (PPU - Pixels Per Unit). */
-    protected int                      generatedTexturePPU       = 128;
-    /**
-     * The name of world settings that the importer will use. If not set or specified name does not occur in the file
-     * then the first world settings in the file will be used.
-     */
-    protected String                   usedWorld;
-    /**
-     * User's default material that is set for objects that have no material definition in blender. The default value is
-     * null. If the value is null the importer will use its own default material (gray color - like in blender).
-     */
-    protected Material                 defaultMaterial;
-    /** Face cull mode. By default it is disabled. */
-    protected FaceCullMode             faceCullMode              = FaceCullMode.Back;
-    /**
-     * Variable describes which layers will be loaded. N-th bit set means N-th layer will be loaded.
-     * If set to -1 then the current layer will be loaded.
-     */
-    protected int                      layersToLoad              = -1;
-    /** A variable that toggles the object custom properties loading. */
-    protected boolean                  loadObjectProperties      = true;
-    /**
-     * Maximum texture size. Might be dependant on the graphic card.
-     * This value is taken from <b>org.lwjgl.opengl.GL11.GL_MAX_TEXTURE_SIZE</b>.
-     */
-    protected int                      maxTextureSize            = 8192;
-    /** Allows to toggle generated textures loading. Disabled by default because it very often takes too much memory and needs to be used wisely. */
-    protected boolean                  loadGeneratedTextures;
-    /** Tells if the mipmaps will be generated by jme or not. By default generation is dependant on the blender settings. */
-    protected MipmapGenerationMethod   mipmapGenerationMethod    = MipmapGenerationMethod.GENERATE_WHEN_NEEDED;
-    /**
-     * If the sky has only generated textures applied then they will have the following size (both width and height). If 2d textures are used then the generated
-     * textures will get their proper size.
-     */
-    protected int                      skyGeneratedTextureSize   = 1000;
-    /** The radius of a shape that will be used while creating the generated texture for the sky. The higher it is the larger part of the texture will be seen. */
-    protected float                    skyGeneratedTextureRadius = 1;
-    /** The shape against which the generated texture for the sky will be created. */
-    protected SkyGeneratedTextureShape skyGeneratedTextureShape  = SkyGeneratedTextureShape.SPHERE;
-    /**
-     * This field tells if the importer should optimise the use of textures or not. If set to true, then textures of the same mapping type will be merged together
-     * and textures that in the final result will never be visible - will be discarded.
-     */
-    protected boolean                  optimiseTextures;
-    /** The method of matching animations to skeletons. The default value is: AT_LEAST_ONE_NAME_MATCH. */
-    protected AnimationMatchMethod     animationMatchMethod      = AnimationMatchMethod.AT_LEAST_ONE_NAME_MATCH;
-    /** The size of points that are loaded and do not belong to any edge of the mesh. */
-    protected float                    pointsSize                = 1;
-    /** The width of edges that are loaded from the mesh and do not belong to any face. */
-    protected float                    linesWidth                = 1;
-
-    /**
-     * Constructor used by serialization mechanisms.
-     */
-    public BlenderKey() {
-    }
-
-    /**
-     * Constructor. Creates a key for the given file name.
-     * @param name
-     *            the name (path) of a file
-     */
-    public BlenderKey(String name) {
-        super(name);
-    }
-
-    /**
-     * This method returns frames per second amount. The default value is BlenderKey.DEFAULT_FPS = 25.
-     * @return the frames per second amount
-     */
-    public int getFps() {
-        return fps;
-    }
-
-    /**
-     * This method sets frames per second amount.
-     * @param fps
-     *            the frames per second amount
-     */
-    public void setFps(int fps) {
-        this.fps = fps;
-    }
-
-    /**
-     * This method returns the face cull mode.
-     * @return the face cull mode
-     */
-    public FaceCullMode getFaceCullMode() {
-        return faceCullMode;
-    }
-
-    /**
-     * This method sets the face cull mode.
-     * @param faceCullMode
-     *            the face cull mode
-     */
-    public void setFaceCullMode(FaceCullMode faceCullMode) {
-        this.faceCullMode = faceCullMode;
-    }
-
-    /**
-     * This method sets layers to be loaded.
-     * @param layersToLoad
-     *            layers to be loaded
-     */
-    public void setLayersToLoad(int layersToLoad) {
-        this.layersToLoad = layersToLoad;
-    }
-
-    /**
-     * This method returns layers to be loaded.
-     * @return layers to be loaded
-     */
-    public int getLayersToLoad() {
-        return layersToLoad;
-    }
-
-    /**
-     * This method sets the properies loading policy.
-     * By default the value is true.
-     * @param loadObjectProperties
-     *            true to load properties and false to suspend their loading
-     */
-    public void setLoadObjectProperties(boolean loadObjectProperties) {
-        this.loadObjectProperties = loadObjectProperties;
-    }
-
-    /**
-     * @return the current properties loading properties
-     */
-    public boolean isLoadObjectProperties() {
-        return loadObjectProperties;
-    }
-
-    /**
-     * The default value for this parameter is the same as defined by: org.lwjgl.opengl.GL11.GL_MAX_TEXTURE_SIZE.
-     * If by any means this is too large for user's hardware configuration use the 'setMaxTextureSize' method to change that.
-     * @return maximum texture size (width/height)
-     */
-    public int getMaxTextureSize() {
-        return maxTextureSize;
-    }
-
-    /**
-     * This method sets the maximum texture size.
-     * @param maxTextureSize
-     *            the maximum texture size
-     */
-    public void setMaxTextureSize(int maxTextureSize) {
-        this.maxTextureSize = maxTextureSize;
-    }
-
-    /**
-     * This method sets the flag that toggles the generated textures loading.
-     * @param loadGeneratedTextures
-     *            <b>true</b> if generated textures should be loaded and <b>false</b> otherwise
-     */
-    public void setLoadGeneratedTextures(boolean loadGeneratedTextures) {
-        this.loadGeneratedTextures = loadGeneratedTextures;
-    }
-
-    /**
-     * @return tells if the generated textures should be loaded (<b>false</b> is the default value)
-     */
-    public boolean isLoadGeneratedTextures() {
-        return loadGeneratedTextures;
-    }
-
-    /**
-     * Not used any more.
-     * This method sets the asset root path.
-     * @param assetRootPath
-     *            the assets root path
-     */
-    @Deprecated
-    public void setAssetRootPath(String assetRootPath) {
-        this.assetRootPath = assetRootPath;
-    }
-
-    /**
-     * Not used any more.
-     * This method returns the asset root path.
-     * @return the asset root path
-     */
-    @Deprecated
-    public String getAssetRootPath() {
-        return assetRootPath;
-    }
-
-    /**
-     * This method adds features to be loaded.
-     * @param featuresToLoad
-     *            bitwise flag of FeaturesToLoad interface values
-     */
-    @Deprecated
-    public void includeInLoading(int featuresToLoad) {
-        this.featuresToLoad |= featuresToLoad;
-    }
-
-    /**
-     * This method removes features from being loaded.
-     * @param featuresNotToLoad
-     *            bitwise flag of FeaturesToLoad interface values
-     */
-    @Deprecated
-    public void excludeFromLoading(int featuresNotToLoad) {
-        featuresToLoad &= ~featuresNotToLoad;
-    }
-
-    @Deprecated
-    public boolean shouldLoad(int featureToLoad) {
-        return (featuresToLoad & featureToLoad) != 0;
-    }
-
-    /**
-     * This method returns bitwise value of FeaturesToLoad interface value. It describes features that will be loaded by
-     * the blender file loader.
-     * @return features that will be loaded by the blender file loader
-     */
-    @Deprecated
-    public int getFeaturesToLoad() {
-        return featuresToLoad;
-    }
-
-    /**
-     * This method determines if unlinked assets should be loaded.
-     * If not then only objects on selected layers will be loaded and their assets if required.
-     * If yes then all assets will be loaded even if they are on inactive layers or are not linked
-     * to anything.
-     * @return <b>true</b> if unlinked assets should be loaded and <b>false</b> otherwise
-     */
-    public boolean isLoadUnlinkedAssets() {
-        return loadUnlinkedAssets;
-    }
-
-    /**
-     * This method sets if unlinked assets should be loaded.
-     * If not then only objects on selected layers will be loaded and their assets if required.
-     * If yes then all assets will be loaded even if they are on inactive layers or are not linked
-     * to anything.
-     * @param loadUnlinkedAssets
-     *            <b>true</b> if unlinked assets should be loaded and <b>false</b> otherwise
-     */
-    public void setLoadUnlinkedAssets(boolean loadUnlinkedAssets) {
-        this.loadUnlinkedAssets = loadUnlinkedAssets;
-    }
-
-    /**
-     * This method sets the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By default Y
-     * is up axis.
-     * @param fixUpAxis
-     *            the up axis state variable
-     */
-    public void setFixUpAxis(boolean fixUpAxis) {
-        this.fixUpAxis = fixUpAxis;
-    }
-
-    /**
-     * This method returns the fix up axis state. If set to true then Y is up axis. Otherwise the up i Z axis. By
-     * default Y is up axis.
-     * @return the up axis state variable
-     */
-    public boolean isFixUpAxis() {
-        return fixUpAxis;
-    }
-
-    /**
-     * This method sets the generated textures resolution.
-     * @param generatedTexturePPU
-     *            the generated textures resolution
-     */
-    public void setGeneratedTexturePPU(int generatedTexturePPU) {
-        this.generatedTexturePPU = generatedTexturePPU;
-    }
-
-    /**
-     * @return the generated textures resolution
-     */
-    public int getGeneratedTexturePPU() {
-        return generatedTexturePPU;
-    }
-
-    /**
-     * @return mipmaps generation method
-     */
-    public MipmapGenerationMethod getMipmapGenerationMethod() {
-        return mipmapGenerationMethod;
-    }
-
-    /**
-     * @param mipmapGenerationMethod
-     *            mipmaps generation method
-     */
-    public void setMipmapGenerationMethod(MipmapGenerationMethod mipmapGenerationMethod) {
-        this.mipmapGenerationMethod = mipmapGenerationMethod;
-    }
-
-    /**
-     * @return the size of the generated textures for the sky (used if no flat textures are applied)
-     */
-    public int getSkyGeneratedTextureSize() {
-        return skyGeneratedTextureSize;
-    }
-
-    /**
-     * @param skyGeneratedTextureSize
-     *            the size of the generated textures for the sky (used if no flat textures are applied)
-     */
-    public void setSkyGeneratedTextureSize(int skyGeneratedTextureSize) {
-        if (skyGeneratedTextureSize <= 0) {
-            throw new IllegalArgumentException("The texture size must be a positive value (the value given as a parameter: " + skyGeneratedTextureSize + ")!");
-        }
-        this.skyGeneratedTextureSize = skyGeneratedTextureSize;
-    }
-
-    /**
-     * @return the radius of a shape that will be used while creating the generated texture for the sky, the higher it is the larger part of the texture will be seen
-     */
-    public float getSkyGeneratedTextureRadius() {
-        return skyGeneratedTextureRadius;
-    }
-
-    /**
-     * @param skyGeneratedTextureRadius
-     *            the radius of a shape that will be used while creating the generated texture for the sky, the higher it is the larger part of the texture will be seen
-     */
-    public void setSkyGeneratedTextureRadius(float skyGeneratedTextureRadius) {
-        this.skyGeneratedTextureRadius = skyGeneratedTextureRadius;
-    }
-
-    /**
-     * @return the shape against which the generated texture for the sky will be created (by default it is a sphere).
-     */
-    public SkyGeneratedTextureShape getSkyGeneratedTextureShape() {
-        return skyGeneratedTextureShape;
-    }
-
-    /**
-     * @param skyGeneratedTextureShape
-     *            the shape against which the generated texture for the sky will be created
-     */
-    public void setSkyGeneratedTextureShape(SkyGeneratedTextureShape skyGeneratedTextureShape) {
-        if (skyGeneratedTextureShape == null) {
-            throw new IllegalArgumentException("The sky generated shape type cannot be null!");
-        }
-        this.skyGeneratedTextureShape = skyGeneratedTextureShape;
-    }
-
-    /**
-     * If set to true, then textures of the same mapping type will be merged together
-     * and textures that in the final result will never be visible - will be discarded.
-     * @param optimiseTextures
-     *            the variable that tells if the textures should be optimised or not
-     */
-    public void setOptimiseTextures(boolean optimiseTextures) {
-        this.optimiseTextures = optimiseTextures;
-    }
-
-    /**
-     * @return the variable that tells if the textures should be optimised or not (by default the optimisation is disabled)
-     */
-    public boolean isOptimiseTextures() {
-        return optimiseTextures;
-    }
-
-    /**
-     * Sets the way the animations will be matched with skeletons.
-     * 
-     * @param animationMatchMethod
-     *            the way the animations will be matched with skeletons
-     */
-    public void setAnimationMatchMethod(AnimationMatchMethod animationMatchMethod) {
-        this.animationMatchMethod = animationMatchMethod;
-    }
-
-    /**
-     * @return the way the animations will be matched with skeletons
-     */
-    public AnimationMatchMethod getAnimationMatchMethod() {
-        return animationMatchMethod;
-    }
-
-    /**
-     * @return the size of points that are loaded and do not belong to any edge of the mesh
-     */
-    public float getPointsSize() {
-        return pointsSize;
-    }
-
-    /**
-     * Sets the size of points that are loaded and do not belong to any edge of the mesh.
-     * @param pointsSize
-     *            The size of points that are loaded and do not belong to any edge of the mesh
-     */
-    public void setPointsSize(float pointsSize) {
-        this.pointsSize = pointsSize;
-    }
-
-    /**
-     * @return the width of edges that are loaded from the mesh and do not belong to any face
-     */
-    public float getLinesWidth() {
-        return linesWidth;
-    }
-
-    /**
-     * Sets the width of edges that are loaded from the mesh and do not belong to any face.
-     * @param linesWidth
-     *            the width of edges that are loaded from the mesh and do not belong to any face
-     */
-    public void setLinesWidth(float linesWidth) {
-        this.linesWidth = linesWidth;
-    }
-
-    /**
-     * This method sets the name of the WORLD data block that should be used during file loading. By default the name is
-     * not set. If no name is set or the given name does not occur in the file - the first WORLD data block will be used
-     * during loading (assuming any exists in the file).
-     * @param usedWorld
-     *            the name of the WORLD block used during loading
-     */
-    public void setUsedWorld(String usedWorld) {
-        this.usedWorld = usedWorld;
-    }
-
-    /**
-     * This method returns the name of the WORLD data block that should be used during file loading.
-     * @return the name of the WORLD block used during loading
-     */
-    public String getUsedWorld() {
-        return usedWorld;
-    }
-
-    /**
-     * This method sets the default material for objects.
-     * @param defaultMaterial
-     *            the default material
-     */
-    public void setDefaultMaterial(Material defaultMaterial) {
-        this.defaultMaterial = defaultMaterial;
-    }
-
-    /**
-     * This method returns the default material.
-     * @return the default material
-     */
-    public Material getDefaultMaterial() {
-        return defaultMaterial;
-    }
-
-    @Override
-    public void write(JmeExporter e) throws IOException {
-        super.write(e);
-        OutputCapsule oc = e.getCapsule(this);
-        oc.write(fps, "fps", DEFAULT_FPS);
-        oc.write(featuresToLoad, "features-to-load", FeaturesToLoad.ALL);
-        oc.write(loadUnlinkedAssets, "load-unlinked-assets", false);
-        oc.write(assetRootPath, "asset-root-path", null);
-        oc.write(fixUpAxis, "fix-up-axis", true);
-        oc.write(generatedTexturePPU, "generated-texture-ppu", 128);
-        oc.write(usedWorld, "used-world", null);
-        oc.write(defaultMaterial, "default-material", null);
-        oc.write(faceCullMode, "face-cull-mode", FaceCullMode.Off);
-        oc.write(layersToLoad, "layers-to-load", -1);
-        oc.write(mipmapGenerationMethod, "mipmap-generation-method", MipmapGenerationMethod.GENERATE_WHEN_NEEDED);
-        oc.write(skyGeneratedTextureSize, "sky-generated-texture-size", 1000);
-        oc.write(skyGeneratedTextureRadius, "sky-generated-texture-radius", 1f);
-        oc.write(skyGeneratedTextureShape, "sky-generated-texture-shape", SkyGeneratedTextureShape.SPHERE);
-        oc.write(optimiseTextures, "optimise-textures", false);
-        oc.write(animationMatchMethod, "animation-match-method", AnimationMatchMethod.AT_LEAST_ONE_NAME_MATCH);
-        oc.write(pointsSize, "points-size", 1);
-        oc.write(linesWidth, "lines-width", 1);
-    }
-
-    @Override
-    public void read(JmeImporter e) throws IOException {
-        super.read(e);
-        InputCapsule ic = e.getCapsule(this);
-        fps = ic.readInt("fps", DEFAULT_FPS);
-        featuresToLoad = ic.readInt("features-to-load", FeaturesToLoad.ALL);
-        loadUnlinkedAssets = ic.readBoolean("load-unlinked-assets", false);
-        assetRootPath = ic.readString("asset-root-path", null);
-        fixUpAxis = ic.readBoolean("fix-up-axis", true);
-        generatedTexturePPU = ic.readInt("generated-texture-ppu", 128);
-        usedWorld = ic.readString("used-world", null);
-        defaultMaterial = (Material) ic.readSavable("default-material", null);
-        faceCullMode = ic.readEnum("face-cull-mode", FaceCullMode.class, FaceCullMode.Off);
-        layersToLoad = ic.readInt("layers-to=load", -1);
-        mipmapGenerationMethod = ic.readEnum("mipmap-generation-method", MipmapGenerationMethod.class, MipmapGenerationMethod.GENERATE_WHEN_NEEDED);
-        skyGeneratedTextureSize = ic.readInt("sky-generated-texture-size", 1000);
-        skyGeneratedTextureRadius = ic.readFloat("sky-generated-texture-radius", 1f);
-        skyGeneratedTextureShape = ic.readEnum("sky-generated-texture-shape", SkyGeneratedTextureShape.class, SkyGeneratedTextureShape.SPHERE);
-        optimiseTextures = ic.readBoolean("optimise-textures", false);
-        animationMatchMethod = ic.readEnum("animation-match-method", AnimationMatchMethod.class, AnimationMatchMethod.AT_LEAST_ONE_NAME_MATCH);
-        pointsSize = ic.readFloat("points-size", 1);
-        linesWidth = ic.readFloat("lines-width", 1);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + (animationMatchMethod == null ? 0 : animationMatchMethod.hashCode());
-        result = prime * result + (assetRootPath == null ? 0 : assetRootPath.hashCode());
-        result = prime * result + (defaultMaterial == null ? 0 : defaultMaterial.hashCode());
-        result = prime * result + (faceCullMode == null ? 0 : faceCullMode.hashCode());
-        result = prime * result + featuresToLoad;
-        result = prime * result + (fixUpAxis ? 1231 : 1237);
-        result = prime * result + fps;
-        result = prime * result + generatedTexturePPU;
-        result = prime * result + layersToLoad;
-        result = prime * result + (loadGeneratedTextures ? 1231 : 1237);
-        result = prime * result + (loadObjectProperties ? 1231 : 1237);
-        result = prime * result + (loadUnlinkedAssets ? 1231 : 1237);
-        result = prime * result + maxTextureSize;
-        result = prime * result + (mipmapGenerationMethod == null ? 0 : mipmapGenerationMethod.hashCode());
-        result = prime * result + (optimiseTextures ? 1231 : 1237);
-        result = prime * result + Float.floatToIntBits(skyGeneratedTextureRadius);
-        result = prime * result + (skyGeneratedTextureShape == null ? 0 : skyGeneratedTextureShape.hashCode());
-        result = prime * result + skyGeneratedTextureSize;
-        result = prime * result + (usedWorld == null ? 0 : usedWorld.hashCode());
-        result = prime * result + (int) pointsSize;
-        result = prime * result + (int) linesWidth;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof BlenderKey) {
-            return false;
-        }
-        BlenderKey other = (BlenderKey) obj;
-        if (animationMatchMethod != other.animationMatchMethod) {
-            return false;
-        }
-        if (assetRootPath == null) {
-            if (other.assetRootPath != null) {
-                return false;
-            }
-        } else if (!assetRootPath.equals(other.assetRootPath)) {
-            return false;
-        }
-        if (defaultMaterial == null) {
-            if (other.defaultMaterial != null) {
-                return false;
-            }
-        } else if (!defaultMaterial.equals(other.defaultMaterial)) {
-            return false;
-        }
-        if (faceCullMode != other.faceCullMode) {
-            return false;
-        }
-        if (featuresToLoad != other.featuresToLoad) {
-            return false;
-        }
-        if (fixUpAxis != other.fixUpAxis) {
-            return false;
-        }
-        if (fps != other.fps) {
-            return false;
-        }
-        if (generatedTexturePPU != other.generatedTexturePPU) {
-            return false;
-        }
-        if (layersToLoad != other.layersToLoad) {
-            return false;
-        }
-        if (loadGeneratedTextures != other.loadGeneratedTextures) {
-            return false;
-        }
-        if (loadObjectProperties != other.loadObjectProperties) {
-            return false;
-        }
-        if (loadUnlinkedAssets != other.loadUnlinkedAssets) {
-            return false;
-        }
-        if (maxTextureSize != other.maxTextureSize) {
-            return false;
-        }
-        if (mipmapGenerationMethod != other.mipmapGenerationMethod) {
-            return false;
-        }
-        if (optimiseTextures != other.optimiseTextures) {
-            return false;
-        }
-        if (Float.floatToIntBits(skyGeneratedTextureRadius) != Float.floatToIntBits(other.skyGeneratedTextureRadius)) {
-            return false;
-        }
-        if (skyGeneratedTextureShape != other.skyGeneratedTextureShape) {
-            return false;
-        }
-        if (skyGeneratedTextureSize != other.skyGeneratedTextureSize) {
-            return false;
-        }
-        if (usedWorld == null) {
-            if (other.usedWorld != null) {
-                return false;
-            }
-        } else if (!usedWorld.equals(other.usedWorld)) {
-            return false;
-        }
-        if (pointsSize != other.pointsSize) {
-            return false;
-        }
-        if (linesWidth != other.linesWidth) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * This enum tells the importer if the mipmaps for textures will be generated by jme. <li>NEVER_GENERATE and ALWAYS_GENERATE are quite understandable <li>GENERATE_WHEN_NEEDED is an option that checks if the texture had 'Generate mipmaps' option set in blender, mipmaps are generated only when the option is set
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum MipmapGenerationMethod {
-        NEVER_GENERATE, ALWAYS_GENERATE, GENERATE_WHEN_NEEDED;
-    }
-
-    /**
-     * This interface describes the features of the scene that are to be loaded.
-     * @deprecated this interface is deprecated and is not used anymore; to ensure the loading models consistency
-     *             everything must be loaded because in blender one feature might depend on another
-     * @author Marcin Roguski (Kaelthas)
-     */
-    @Deprecated
-    public static interface FeaturesToLoad {
-
-        int SCENES     = 0x0000FFFF;
-        int OBJECTS    = 0x0000000B;
-        int ANIMATIONS = 0x00000004;
-        int MATERIALS  = 0x00000003;
-        int TEXTURES   = 0x00000001;
-        int CAMERAS    = 0x00000020;
-        int LIGHTS     = 0x00000010;
-        int WORLD      = 0x00000040;
-        int ALL        = 0xFFFFFFFF;
-    }
-
-    /**
-     * The shape againts which the sky generated texture will be created.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum SkyGeneratedTextureShape {
-        CUBE, SPHERE;
-    }
-
-    /**
-     * This enum describes which animations should be attached to which armature.
-     * Blender does not store the mapping between action and armature. That is why the importer
-     * will try to match those by comparing bone name of the armature with the channel names
-     * int the actions.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum AnimationMatchMethod {
-        /**
-         * Animation is matched with skeleton when at leas one bone name matches the name of the action channel.
-         * All the bones that do not have their corresponding channel in the animation will not get the proper tracks for
-         * this particulat animation.
-         * Also the channel will not be used for the animation if it does not find the proper bone name.
-         */
-        AT_LEAST_ONE_NAME_MATCH,
-        /**
-         * Animation is matched when all action names are covered by the target names (bone names or the name of the
-         * animated spatial.
-         */
-        ALL_NAMES_MATCH;
-    }
-}

+ 0 - 69
jme3-blender/src/main/java/com/jme3/asset/GeneratedTextureKey.java

@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.asset;
-
-/**
- * This key is mostly used to distinguish between textures that are loaded from
- * the given assets and those being generated automatically. Every generated
- * texture will have this kind of key attached.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class GeneratedTextureKey extends TextureKey {
-
-    /**
-     * Constructor. Stores the name. Extension and folder name are empty
-     * strings.
-     * 
-     * @param name
-     *            the name of the texture
-     */
-    public GeneratedTextureKey(String name) {
-        super(name);
-    }
-
-    @Override
-    public String getExtension() {
-        return "";
-    }
-
-    @Override
-    public String getFolder() {
-        return "";
-    }
-
-    @Override
-    public String toString() {
-        return "Generated texture [" + name + "]";
-    }
-}

+ 0 - 193
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java

@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.asset.AssetNotFoundException;
-import com.jme3.asset.BlenderKey;
-import com.jme3.export.Savable;
-import com.jme3.math.FastMath;
-import com.jme3.math.Quaternion;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.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;
-
-/**
- * A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can
- * hold the state of the calculations.
- * @author Marcin Roguski
- */
-public abstract class AbstractBlenderHelper {
-    private static final Logger LOGGER = Logger.getLogger(AbstractBlenderHelper.class.getName());
-
-    /** The blender context. */
-    protected BlenderContext    blenderContext;
-    /** The version of the blend file. */
-    protected final int         blenderVersion;
-    /** This variable indicates if the Y asxis is the UP axis or not. */
-    protected boolean           fixUpAxis;
-    /** Quaternion used to rotate data when Y is up axis. */
-    protected Quaternion        upAxisRotationQuaternion;
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public AbstractBlenderHelper(String blenderVersion, BlenderContext blenderContext) {
-        this.blenderVersion = Integer.parseInt(blenderVersion);
-        this.blenderContext = blenderContext;
-        fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
-        if (fixUpAxis) {
-            upAxisRotationQuaternion = new Quaternion().fromAngles(-FastMath.HALF_PI, 0, 0);
-        }
-    }
-
-    /**
-     * This method loads the properties if they are available and defined for the structure.
-     * @param structure
-     *            the structure we read the properties from
-     * @param blenderContext
-     *            the blender context
-     * @return loaded properties or null if they are not available
-     * @throws BlenderFileException
-     *             an exception is thrown when the blend file is somehow corrupted
-     */
-    protected Properties loadProperties(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
-        Properties properties = null;
-        Structure id = (Structure) structure.getFieldValue("ID");
-        if (id != null) {
-            Pointer pProperties = (Pointer) id.getFieldValue("properties");
-            if (pProperties.isNotNull()) {
-                Structure propertiesStructure = pProperties.fetchData().get(0);
-                properties = new Properties();
-                properties.load(propertiesStructure, blenderContext);
-            }
-        }
-        return properties;
-    }
-
-    /**
-     * The method applies properties to the given spatial. The Properties
-     * instance cannot be directly applied because the end-user might not have
-     * the blender plugin jar file and thus receive ClassNotFoundException. The
-     * values are set by name instead.
-     * 
-     * @param spatial
-     *            the spatial that is to have properties applied
-     * @param properties
-     *            the properties to be applied
-     */
-    public void applyProperties(Spatial spatial, Properties properties) {
-        List<String> propertyNames = properties.getSubPropertiesNames();
-        if (propertyNames != null && propertyNames.size() > 0) {
-            for (String propertyName : propertyNames) {
-                Object value = properties.findValue(propertyName);
-                if (value instanceof Savable || value instanceof Boolean || value instanceof String || value instanceof Float || value instanceof Integer || value instanceof Long) {
-                    spatial.setUserData(propertyName, value);
-                } else if (value instanceof Double) {
-                    spatial.setUserData(propertyName, ((Double) value).floatValue());
-                } else if (value instanceof int[]) {
-                    spatial.setUserData(propertyName, Arrays.toString((int[]) value));
-                } else if (value instanceof float[]) {
-                    spatial.setUserData(propertyName, Arrays.toString((float[]) value));
-                } else if (value instanceof double[]) {
-                    spatial.setUserData(propertyName, Arrays.toString((double[]) value));
-                }
-            }
-        }
-    }
-
-    /**
-     * The method loads library of a given ID from linked blender file.
-     * @param id
-     *            the ID of the linked feature (it contains its name and blender path)
-     * @return loaded feature or null if none was found
-     * @throws BlenderFileException
-     *             and exception is throw when problems with reading a blend file occur
-     */
-    protected Object loadLibrary(Structure id) throws BlenderFileException {
-        Pointer pLib = (Pointer) id.getFieldValue("lib");
-        if (pLib.isNotNull()) {
-            String fullName = id.getFieldValue("name").toString();// we need full name with the prefix
-            String nameOfFeatureToLoad = id.getName();
-            Structure library = pLib.fetchData().get(0);
-            String path = library.getFieldValue("filepath").toString();
-
-            if (!blenderContext.getLinkedFeatures().keySet().contains(path)) {
-                Spatial loadedAsset = null;
-                BlenderKey blenderKey = new BlenderKey(path);
-                blenderKey.setLoadUnlinkedAssets(true);
-                try {
-                    loadedAsset = blenderContext.getAssetManager().loadAsset(blenderKey);
-                } catch (AssetNotFoundException e) {
-                    LOGGER.log(Level.FINEST, "Cannot locate linked resource at path: {0}.", path);
-                }
-                
-                if (loadedAsset != null) {
-                    Map<String, Map<String, Object>> linkedData = loadedAsset.getUserData("linkedData");
-                    
-                    for (Entry<String, Map<String, Object>> entry : linkedData.entrySet()) {
-                        String linkedDataFilePath = "this".equals(entry.getKey()) ? path : entry.getKey();
-                        blenderContext.getLinkedFeatures().put(linkedDataFilePath, entry.getValue());
-                    }
-                } else {
-                    LOGGER.log(Level.WARNING, "No features loaded from path: {0}.", path);
-                }
-            }
-
-            Object result = blenderContext.getLinkedFeature(path, fullName);
-            if (result == null) {
-                LOGGER.log(Level.WARNING, "Could NOT find asset named {0} in the library of path: {1}.", new Object[] { nameOfFeatureToLoad, path });
-            } else {
-                blenderContext.addLoadedFeatures(id.getOldMemoryAddress(), LoadedDataType.STRUCTURE, id);
-                blenderContext.addLoadedFeatures(id.getOldMemoryAddress(), LoadedDataType.FEATURE, result);
-            }
-            return result;
-        } else {
-            LOGGER.warning("Library link points to nothing!");
-        }
-        return null;
-    }
-}

+ 0 - 767
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderContext.java

@@ -1,767 +0,0 @@
-/*
- * Copyright (c) 2009-2019 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;
-
-import java.util.ArrayList;
-import java.util.EmptyStackException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Stack;
-
-import com.jme3.animation.Animation;
-import com.jme3.animation.Bone;
-import com.jme3.animation.Skeleton;
-import com.jme3.asset.AssetManager;
-import com.jme3.asset.BlenderKey;
-import com.jme3.light.Light;
-import com.jme3.material.Material;
-import com.jme3.math.ColorRGBA;
-import com.jme3.post.Filter;
-import com.jme3.renderer.Camera;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.animations.BlenderAction;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-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.FileBlockHeader.BlockCode;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.materials.MaterialContext;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-import com.jme3.texture.Texture;
-
-/**
- * The class that stores temporary data and manages it during loading the belnd
- * file. This class is intended to be used in a single loading thread. It holds
- * the state of loading operations.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class BlenderContext {
-    /** The blender file version. */
-    private int                                    blenderVersion;
-    /** The blender key. */
-    private BlenderKey                             blenderKey;
-    /** The header of the file block. */
-    private DnaBlockData                           dnaBlockData;
-    /** The scene structure. */
-    private Structure                              sceneStructure;
-    /** The input stream of the blend file. */
-    private BlenderInputStream                     inputStream;
-    /** The asset manager. */
-    private AssetManager                           assetManager;
-    /** The blocks read from the file. */
-    protected List<FileBlockHeader>                blocks                 = new ArrayList<FileBlockHeader>();
-    /**
-     * A map containing the file block headers. The key is the old memory address.
-     */
-    private Map<Long, FileBlockHeader>             fileBlockHeadersByOma  = new HashMap<Long, FileBlockHeader>();
-    /** A map containing the file block headers. The key is the block code. */
-    private Map<BlockCode, List<FileBlockHeader>>  fileBlockHeadersByCode = new HashMap<BlockCode, List<FileBlockHeader>>();
-    /**
-     * This map stores the loaded features by their old memory address. The
-     * first object in the value table is the loaded structure and the second -
-     * the structure already converted into proper data.
-     */
-    private Map<Long, Map<LoadedDataType, Object>> loadedFeatures         = new HashMap<Long, Map<LoadedDataType, Object>>();
-    /** Features loaded from external blender files. The key is the file path and the value is a map between feature name and loaded feature. */
-    private Map<String, Map<String, Object>>       linkedFeatures         = new HashMap<String, Map<String, Object>>();
-    /** A stack that hold the parent structure of currently loaded feature. */
-    private Stack<Structure>                       parentStack            = new Stack<Structure>();
-    /** A list of constraints for the specified object. */
-    protected Map<Long, List<Constraint>>          constraints            = new HashMap<Long, List<Constraint>>();
-    /** Animations loaded for features. */
-    private Map<Long, List<Animation>>             animations             = new HashMap<Long, List<Animation>>();
-    /** Loaded skeletons. */
-    private Map<Long, Skeleton>                    skeletons              = new HashMap<Long, Skeleton>();
-    /** A map between skeleton and node it modifies. */
-    private Map<Skeleton, Node>                    nodesWithSkeletons     = new HashMap<Skeleton, Node>();
-    /** A map of bone contexts. */
-    protected Map<Long, BoneContext>               boneContexts           = new HashMap<Long, BoneContext>();
-    /** A map og helpers that perform loading. */
-    private Map<String, AbstractBlenderHelper>     helpers                = new HashMap<String, AbstractBlenderHelper>();
-    /** Markers used by loading classes to store some custom data. This is made to avoid putting this data into user properties. */
-    private Map<String, Map<Object, Object>>       markers                = new HashMap<String, Map<Object, Object>>();
-    /** A map of blender actions. The key is the action name and the value is the action itself. */
-    private Map<String, BlenderAction>             actions                = new HashMap<String, BlenderAction>();
-
-    /**
-     * This method sets the blender file version.
-     * 
-     * @param blenderVersion
-     *            the blender file version
-     */
-    public void setBlenderVersion(String blenderVersion) {
-        this.blenderVersion = Integer.parseInt(blenderVersion);
-    }
-
-    /**
-     * @return the blender file version
-     */
-    public int getBlenderVersion() {
-        return blenderVersion;
-    }
-
-    /**
-     * This method sets the blender key.
-     * 
-     * @param blenderKey
-     *            the blender key
-     */
-    public void setBlenderKey(BlenderKey blenderKey) {
-        this.blenderKey = blenderKey;
-    }
-
-    /**
-     * This method returns the blender key.
-     * 
-     * @return the blender key
-     */
-    public BlenderKey getBlenderKey() {
-        return blenderKey;
-    }
-
-    /**
-     * This method sets the dna block data.
-     * 
-     * @param dnaBlockData
-     *            the dna block data
-     */
-    public void setBlockData(DnaBlockData dnaBlockData) {
-        this.dnaBlockData = dnaBlockData;
-    }
-
-    /**
-     * This method returns the dna block data.
-     * 
-     * @return the dna block data
-     */
-    public DnaBlockData getDnaBlockData() {
-        return dnaBlockData;
-    }
-
-    /**
-     * This method sets the scene structure data.
-     * 
-     * @param sceneStructure
-     *            the scene structure data
-     */
-    public void setSceneStructure(Structure sceneStructure) {
-        this.sceneStructure = sceneStructure;
-    }
-
-    /**
-     * This method returns the scene structure data.
-     * 
-     * @return the scene structure data
-     */
-    public Structure getSceneStructure() {
-        return sceneStructure;
-    }
-
-    /**
-     * This method returns the asset manager.
-     * 
-     * @return the asset manager
-     */
-    public AssetManager getAssetManager() {
-        return assetManager;
-    }
-
-    /**
-     * This method sets the asset manager.
-     * 
-     * @param assetManager
-     *            the asset manager
-     */
-    public void setAssetManager(AssetManager assetManager) {
-        this.assetManager = assetManager;
-    }
-
-    /**
-     * This method returns the input stream of the blend file.
-     * 
-     * @return the input stream of the blend file
-     */
-    public BlenderInputStream getInputStream() {
-        return inputStream;
-    }
-
-    /**
-     * This method sets the input stream of the blend file.
-     * 
-     * @param inputStream
-     *            the input stream of the blend file
-     */
-    public void setInputStream(BlenderInputStream inputStream) {
-        this.inputStream = inputStream;
-    }
-
-    /**
-     * This method adds a file block header to the map. Its old memory address
-     * is the key.
-     * 
-     * @param oldMemoryAddress
-     *            the address of the block header
-     * @param fileBlockHeader
-     *            the block header to store
-     */
-    public void addFileBlockHeader(Long oldMemoryAddress, FileBlockHeader fileBlockHeader) {
-        blocks.add(fileBlockHeader);
-        fileBlockHeadersByOma.put(oldMemoryAddress, fileBlockHeader);
-        List<FileBlockHeader> headers = fileBlockHeadersByCode.get(fileBlockHeader.getCode());
-        if (headers == null) {
-            headers = new ArrayList<FileBlockHeader>();
-            fileBlockHeadersByCode.put(fileBlockHeader.getCode(), headers);
-        }
-        headers.add(fileBlockHeader);
-    }
-
-    /**
-     * @return the block headers
-     */
-    public List<FileBlockHeader> getBlocks() {
-        return blocks;
-    }
-
-    /**
-     * This method returns the block header of a given memory address. If the
-     * header is not present then null is returned.
-     * 
-     * @param oldMemoryAddress
-     *            the address of the block header
-     * @return loaded header or null if it was not yet loaded
-     */
-    public FileBlockHeader getFileBlock(Long oldMemoryAddress) {
-        return fileBlockHeadersByOma.get(oldMemoryAddress);
-    }
-
-    /**
-     * This method returns a list of file blocks' headers of a specified code.
-     * 
-     * @param code
-     *            the code of file blocks
-     * @return a list of file blocks' headers of a specified code
-     */
-    public List<FileBlockHeader> getFileBlocks(BlockCode code) {
-        return fileBlockHeadersByCode.get(code);
-    }
-
-    /**
-     * This method adds a helper instance to the helpers' map.
-     * 
-     * @param <T>
-     *            the type of the helper
-     * @param clazz
-     *            helper's class definition
-     * @param helper
-     *            the helper instance
-     */
-    public <T> void putHelper(Class<T> clazz, AbstractBlenderHelper helper) {
-        helpers.put(clazz.getSimpleName(), helper);
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T> T getHelper(Class<?> clazz) {
-        return (T) helpers.get(clazz.getSimpleName());
-    }
-
-    /**
-     * This method adds a loaded feature to the map. The key is its unique old
-     * memory address.
-     * 
-     * @param oldMemoryAddress
-     *            the address of the feature
-     * @param featureDataType
-     * @param feature
-     *            the feature we want to store
-     */
-    public void addLoadedFeatures(Long oldMemoryAddress, LoadedDataType featureDataType, Object feature) {
-        if (oldMemoryAddress == null || featureDataType == null || feature == null) {
-            throw new IllegalArgumentException("One of the given arguments is null!");
-        }
-        Map<LoadedDataType, Object> map = loadedFeatures.get(oldMemoryAddress);
-        if (map == null) {
-            map = new HashMap<BlenderContext.LoadedDataType, Object>();
-            loadedFeatures.put(oldMemoryAddress, map);
-        }
-        map.put(featureDataType, feature);
-    }
-
-    /**
-     * This method returns the feature of a given memory address. If the feature
-     * is not yet loaded then null is returned.
-     * 
-     * @param oldMemoryAddress
-     *            the address of the feature
-     * @param loadedFeatureDataType
-     *            the type of data we want to retrieve it can be either filled
-     *            structure or already converted feature
-     * @return loaded feature or null if it was not yet loaded
-     */
-    public Object getLoadedFeature(Long oldMemoryAddress, LoadedDataType loadedFeatureDataType) {
-        Map<LoadedDataType, Object> result = loadedFeatures.get(oldMemoryAddress);
-        if (result != null) {
-            return result.get(loadedFeatureDataType);
-        }
-        return null;
-    }
-
-    /**
-     * The method adds linked content to the blender context.
-     * @param blenderFilePath
-     *            the path of linked blender file
-     * @param featureGroup
-     *            the linked feature group (ie. scenes, materials, meshes, etc.)
-     * @param feature
-     *            the linked feature
-     */
-    @Deprecated
-    public void addLinkedFeature(String blenderFilePath, String featureGroup, Object feature) {
-        // the method is deprecated and empty at the moment
-    }
-
-    /**
-     * The method returns linked feature of a given name from the specified blender path.
-     * @param blenderFilePath
-     *            the blender file path
-     * @param featureName
-     *            the feature name we want to get
-     * @return linked feature or null if none was found
-     */
-    @SuppressWarnings("unchecked")
-    public Object getLinkedFeature(String blenderFilePath, String featureName) {
-        Map<String, Object> linkedFeatures = this.linkedFeatures.get(blenderFilePath);
-        if(linkedFeatures != null) {
-            String namePrefix = (featureName.charAt(0) + "" + featureName.charAt(1)).toUpperCase();
-            featureName = featureName.substring(2);
-            
-            if("SC".equals(namePrefix)) {
-                List<Node> scenes = (List<Node>) linkedFeatures.get("scenes");
-                if(scenes != null) {
-                    for(Node scene : scenes) {
-                        if(featureName.equals(scene.getName())) {
-                            return scene;
-                        }
-                    }
-                }
-            } else if("OB".equals(namePrefix)) {
-                List<Node> features = (List<Node>) linkedFeatures.get("objects");
-                if(features != null) {
-                    for(Node feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("ME".equals(namePrefix)) {
-                List<TemporalMesh> temporalMeshes = (List<TemporalMesh>) linkedFeatures.get("meshes");
-                if(temporalMeshes != null) {
-                    for(TemporalMesh temporalMesh : temporalMeshes) {
-                        if(featureName.equals(temporalMesh.getName())) {
-                            return temporalMesh;
-                        }
-                    }
-                }
-            } else if("MA".equals(namePrefix)) {
-                List<MaterialContext> features = (List<MaterialContext>) linkedFeatures.get("materials");
-                if(features != null) {
-                    for(MaterialContext feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("TX".equals(namePrefix)) {
-                List<Texture> features = (List<Texture>) linkedFeatures.get("textures");
-                if(features != null) {
-                    for(Texture feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("IM".equals(namePrefix)) {
-                List<Texture> features = (List<Texture>) linkedFeatures.get("images");
-                if(features != null) {
-                    for(Texture feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("AC".equals(namePrefix)) {
-                List<Animation> features = (List<Animation>) linkedFeatures.get("animations");
-                if(features != null) {
-                    for(Animation feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("CA".equals(namePrefix)) {
-                List<Camera> features = (List<Camera>) linkedFeatures.get("cameras");
-                if(features != null) {
-                    for(Camera feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("LA".equals(namePrefix)) {
-                List<Light> features = (List<Light>) linkedFeatures.get("lights");
-                if(features != null) {
-                    for(Light feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            } else if("FI".equals(featureName)) {
-                List<Filter> features = (List<Filter>) linkedFeatures.get("lights");
-                if(features != null) {
-                    for(Filter feature : features) {
-                        if(featureName.equals(feature.getName())) {
-                            return feature;
-                        }
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return all linked features for the current blend file
-     */
-    public Map<String, Map<String, Object>> getLinkedFeatures() {
-        return linkedFeatures;
-    }
-
-    /**
-     * This method adds the structure to the parent stack.
-     * 
-     * @param parent
-     *            the structure to be added to the stack
-     */
-    public void pushParent(Structure parent) {
-        parentStack.push(parent);
-    }
-
-    /**
-     * This method removes the structure from the top of the parent's stack.
-     * 
-     * @return the structure that was removed from the stack
-     */
-    public Structure popParent() {
-        try {
-            return parentStack.pop();
-        } catch (EmptyStackException e) {
-            return null;
-        }
-    }
-
-    /**
-     * This method retrieves the structure at the top of the parent's stack but
-     * does not remove it.
-     * 
-     * @return the structure from the top of the stack
-     */
-    public Structure peekParent() {
-        try {
-            return parentStack.peek();
-        } catch (EmptyStackException e) {
-            return null;
-        }
-    }
-
-    /**
-     * 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);
-    }
-
-    /**
-     * Returns constraints applied to the feature of the given OMA.
-     * @param ownerOMA
-     *            the constraints' owner OMA
-     * @return a list of constraints or <b>null</b> if no constraints are applied to the feature
-     */
-    public List<Constraint> getConstraints(Long ownerOMA) {
-        return constraints.get(ownerOMA);
-    }
-
-    /**
-     * @return all available constraints
-     */
-    public List<Constraint> getAllConstraints() {
-        List<Constraint> result = new ArrayList<Constraint>();
-        for (Entry<Long, List<Constraint>> entry : constraints.entrySet()) {
-            result.addAll(entry.getValue());
-        }
-        return result;
-    }
-
-    /**
-     * This method adds the animation for the specified OMA of its owner.
-     * 
-     * @param ownerOMA
-     *            the owner's old memory address
-     * @param animation
-     *            the animation for the feature specified by ownerOMA
-     */
-    public void addAnimation(Long ownerOMA, Animation animation) {
-        List<Animation> animList = animations.get(ownerOMA);
-        if (animList == null) {
-            animList = new ArrayList<Animation>();
-            animations.put(ownerOMA, animList);
-        }
-        animList.add(animation);
-    }
-
-    /**
-     * This method returns the animation data for the specified owner.
-     * 
-     * @param ownerOMA
-     *            the old memory address of the animation data owner
-     * @return the animation or null if none exists
-     */
-    public List<Animation> getAnimations(Long ownerOMA) {
-        return animations.get(ownerOMA);
-    }
-
-    /**
-     * This method sets the skeleton for the specified OMA of its owner.
-     * 
-     * @param skeletonOMA
-     *            the skeleton's old memory address
-     * @param skeleton
-     *            the skeleton specified by the given OMA
-     */
-    public void setSkeleton(Long skeletonOMA, Skeleton skeleton) {
-        skeletons.put(skeletonOMA, skeleton);
-    }
-
-    /**
-     * The method stores a binding between the skeleton and the proper armature
-     * node.
-     * 
-     * @param skeleton
-     *            the skeleton
-     * @param node
-     *            the armature node
-     */
-    public void setNodeForSkeleton(Skeleton skeleton, Node node) {
-        nodesWithSkeletons.put(skeleton, node);
-    }
-
-    /**
-     * This method returns the armature node that is defined for the skeleton.
-     * 
-     * @param skeleton
-     *            the skeleton
-     * @return the armature node that defines the skeleton in blender
-     */
-    public Node getControlledNode(Skeleton skeleton) {
-        return nodesWithSkeletons.get(skeleton);
-    }
-
-    /**
-     * This method returns the skeleton for the specified OMA of its owner.
-     * 
-     * @param skeletonOMA
-     *            the skeleton's old memory address
-     * @return the skeleton specified by the given OMA
-     */
-    public Skeleton getSkeleton(Long skeletonOMA) {
-        return skeletons.get(skeletonOMA);
-    }
-
-    /**
-     * This method sets the bone context for the given bone old memory address.
-     * If the context is already set it will be replaced.
-     * 
-     * @param boneOMA
-     *            the bone's old memory address
-     * @param boneContext
-     *            the bones's context
-     */
-    public void setBoneContext(Long boneOMA, BoneContext boneContext) {
-        boneContexts.put(boneOMA, boneContext);
-    }
-
-    /**
-     * This method returns the bone context for the given bone old memory
-     * address. If no context exists then <b>null</b> is returned.
-     * 
-     * @param boneOMA
-     *            the bone's old memory address
-     * @return bone's context
-     */
-    public BoneContext getBoneContext(Long boneOMA) {
-        return boneContexts.get(boneOMA);
-    }
-
-    /**
-     * Returns bone by given name.
-     * 
-     * @param skeletonOMA
-     *            the OMA of the skeleton where the bone will be searched
-     * @param name
-     *            the name of the bone
-     * @return found bone or null if none bone of a given name exists
-     */
-    public BoneContext getBoneByName(Long skeletonOMA, String name) {
-        for (Entry<Long, BoneContext> entry : boneContexts.entrySet()) {
-            if (entry.getValue().getArmatureObjectOMA().equals(skeletonOMA)) {
-                Bone bone = entry.getValue().getBone();
-                if (bone != null && name.equals(bone.getName())) {
-                    return entry.getValue();
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns bone context for the given bone.
-     * 
-     * @param bone
-     *            the bone
-     * @return the bone's bone context
-     */
-    public BoneContext getBoneContext(Bone bone) {
-        for (Entry<Long, BoneContext> entry : boneContexts.entrySet()) {
-            if (entry.getValue().getBone().getName().equals(bone.getName())) {
-                return entry.getValue();
-            }
-        }
-        throw new IllegalStateException("Cannot find context for bone: " + bone);
-    }
-
-    /**
-     * This metod returns the default material.
-     * 
-     * @return the default material
-     */
-    public synchronized Material getDefaultMaterial() {
-        if (blenderKey.getDefaultMaterial() == null) {
-            Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
-            defaultMaterial.setColor("Color", ColorRGBA.DarkGray);
-            blenderKey.setDefaultMaterial(defaultMaterial);
-        }
-        return blenderKey.getDefaultMaterial();
-    }
-
-    /**
-     * Adds a custom marker for scene's feature.
-     * 
-     * @param marker
-     *            the marker name
-     * @param feature
-     *            te scene's feature (can be node, material or texture or
-     *            anything else)
-     * @param markerValue
-     *            the marker value
-     */
-    public void addMarker(String marker, Object feature, Object markerValue) {
-        if (markerValue == null) {
-            throw new IllegalArgumentException("The marker's value cannot be null.");
-        }
-        Map<Object, Object> markersMap = markers.get(marker);
-        if (markersMap == null) {
-            markersMap = new HashMap<Object, Object>();
-            markers.put(marker, markersMap);
-        }
-        markersMap.put(feature, markerValue);
-    }
-
-    /**
-     * Returns the marker value. The returned value is null if no marker was
-     * defined for the given feature.
-     * 
-     * @param marker
-     *            the marker name
-     * @param feature
-     *            the scene's feature
-     * @return marker value or null if it was not defined
-     */
-    public Object getMarkerValue(String marker, Object feature) {
-        Map<Object, Object> markersMap = markers.get(marker);
-        return markersMap == null ? null : markersMap.get(feature);
-    }
-
-    /**
-     * Adds blender action to the context.
-     * @param action
-     *            the action loaded from the blend file
-     */
-    public void addAction(BlenderAction action) {
-        actions.put(action.getName(), action);
-    }
-
-    /**
-     * @return a map of blender actions; the key is the action name and the value is action itself
-     */
-    public Map<String, BlenderAction> getActions() {
-        return actions;
-    }
-
-    /**
-     * This enum defines what loaded data type user wants to retrieve. It can be
-     * either filled structure or already converted data.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum LoadedDataType {
-        STRUCTURE, FEATURE, TEMPORAL_MESH;
-    }
-    
-    @Override
-    public String toString() {
-        return blenderKey == null ? "BlenderContext [key = null]" : "BlenderContext [ key = " + blenderKey.toString() + " ]";
-    }
-}

+ 0 - 419
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderLoader.java

@@ -1,419 +0,0 @@
-/*
- * Copyright (c) 2009-2019 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;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-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.animation.Animation;
-import com.jme3.asset.AssetInfo;
-import com.jme3.asset.AssetKey;
-import com.jme3.asset.AssetLoader;
-import com.jme3.asset.AssetLocator;
-import com.jme3.asset.AssetManager;
-import com.jme3.asset.BlenderKey;
-import com.jme3.asset.ModelKey;
-import com.jme3.asset.StreamAssetInfo;
-import com.jme3.light.Light;
-import com.jme3.math.ColorRGBA;
-import com.jme3.post.Filter;
-import com.jme3.renderer.Camera;
-import com.jme3.scene.CameraNode;
-import com.jme3.scene.LightNode;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.animations.AnimationHelper;
-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.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.BlenderInputStream;
-import com.jme3.scene.plugins.blender.file.FileBlockHeader;
-import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.landscape.LandscapeHelper;
-import com.jme3.scene.plugins.blender.lights.LightHelper;
-import com.jme3.scene.plugins.blender.materials.MaterialContext;
-import com.jme3.scene.plugins.blender.materials.MaterialHelper;
-import com.jme3.scene.plugins.blender.meshes.MeshHelper;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-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;
-import com.jme3.texture.Texture;
-
-/**
- * This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures.
- * @author Marcin Roguski (Kaelthas)
- */
-public class BlenderLoader implements AssetLoader {
-    private static final Logger     LOGGER = Logger.getLogger(BlenderLoader.class.getName());
-
-    @Override
-    public Spatial load(AssetInfo assetInfo) throws IOException {
-        try {
-            BlenderContext blenderContext = this.setup(assetInfo);
-
-            AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
-            animationHelper.loadAnimations();
-
-            BlenderKey blenderKey = blenderContext.getBlenderKey();
-            LoadedFeatures loadedFeatures = new LoadedFeatures();
-            for (FileBlockHeader block : blenderContext.getBlocks()) {
-                switch (block.getCode()) {
-                    case BLOCK_OB00:
-                        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-                        Node object = (Node) objectHelper.toObject(block.getStructure(blenderContext), blenderContext);
-                        if (LOGGER.isLoggable(Level.FINE)) {
-                            LOGGER.log(Level.FINE, "{0}: {1}--> {2}", new Object[] { object.getName(), object.getLocalTranslation().toString(), object.getParent() == null ? "null" : object.getParent().getName() });
-                        }
-                        if (object.getParent() == null) {
-                            loadedFeatures.objects.add(object);
-                        }
-                        if (object instanceof LightNode && ((LightNode) object).getLight() != null) {
-                            loadedFeatures.lights.add(((LightNode) object).getLight());
-                        } else if (object instanceof CameraNode && ((CameraNode) object).getCamera() != null) {
-                            loadedFeatures.cameras.add(((CameraNode) object).getCamera());
-                        }
-                        break;
-                    case BLOCK_SC00:// Scene
-                        loadedFeatures.sceneBlocks.add(block);
-                        break;
-                    case BLOCK_MA00:// Material
-                        MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
-                        MaterialContext materialContext = materialHelper.toMaterialContext(block.getStructure(blenderContext), blenderContext);
-                        loadedFeatures.materials.add(materialContext);
-                        break;
-                    case BLOCK_ME00:// Mesh
-                        MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-                        TemporalMesh temporalMesh = meshHelper.toTemporalMesh(block.getStructure(blenderContext), blenderContext);
-                        loadedFeatures.meshes.add(temporalMesh);
-                        break;
-                    case BLOCK_IM00:// Image
-                        TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
-                        Texture image = textureHelper.loadImageAsTexture(block.getStructure(blenderContext), 0, blenderContext);
-                        if (image != null && image.getImage() != null) {// render results are stored as images but are not being loaded
-                            loadedFeatures.images.add(image);
-                        }
-                        break;
-                    case BLOCK_TE00:
-                        Structure textureStructure = block.getStructure(blenderContext);
-                        int type = ((Number) textureStructure.getFieldValue("type")).intValue();
-                        if (type == TextureHelper.TEX_IMAGE) {
-                            TextureHelper texHelper = blenderContext.getHelper(TextureHelper.class);
-                            Texture texture = texHelper.getTexture(textureStructure, null, blenderContext);
-                            if (texture != null) {// null is returned when texture has no image
-                                loadedFeatures.textures.add(texture);
-                            }
-                        } else {
-                            LOGGER.fine("Only image textures can be loaded as unlinked assets. Generated textures will be applied to an existing object.");
-                        }
-                        break;
-                    case BLOCK_WO00:// World
-                        LandscapeHelper landscapeHelper = blenderContext.getHelper(LandscapeHelper.class);
-                        Structure worldStructure = block.getStructure(blenderContext);
-
-                        String worldName = worldStructure.getName();
-                        if (blenderKey.getUsedWorld() == null || blenderKey.getUsedWorld().equals(worldName)) {
-
-                            Light ambientLight = landscapeHelper.toAmbientLight(worldStructure);
-                            if (ambientLight != null) {
-                                loadedFeatures.objects.add(new LightNode(null, ambientLight));
-                                loadedFeatures.lights.add(ambientLight);
-                            }
-                            loadedFeatures.sky = landscapeHelper.toSky(worldStructure);
-                            loadedFeatures.backgroundColor = landscapeHelper.toBackgroundColor(worldStructure);
-
-                            Filter fogFilter = landscapeHelper.toFog(worldStructure);
-                            if (fogFilter != null) {
-                                loadedFeatures.filters.add(landscapeHelper.toFog(worldStructure));
-                            }
-                        }
-                        break;
-                    case BLOCK_AC00:
-                        LOGGER.fine("Loading unlinked animations is not yet supported!");
-                        break;
-                    default:
-                        LOGGER.log(Level.FINEST, "Ommiting the block: {0}.", block.getCode());
-                }
-            }
-
-            LOGGER.fine("Baking constraints after every feature is loaded.");
-            ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
-            constraintHelper.bakeConstraints(blenderContext);
-
-            LOGGER.fine("Loading scenes and attaching them to the root object.");
-            for (FileBlockHeader sceneBlock : loadedFeatures.sceneBlocks) {
-                loadedFeatures.scenes.add(this.toScene(sceneBlock.getStructure(blenderContext), blenderContext));
-            }
-
-            LOGGER.fine("Creating the root node of the model and applying loaded nodes of the scene and loaded features to it.");
-            Node modelRoot = new Node(blenderKey.getName());
-            for (Node scene : loadedFeatures.scenes) {
-                modelRoot.attachChild(scene);
-            }
-
-            if (blenderKey.isLoadUnlinkedAssets()) {
-                LOGGER.fine("Setting loaded content as user data in resulting sptaial.");
-                Map<String, Map<String, Object>> linkedData = new HashMap<String, Map<String, Object>>();
-
-                Map<String, Object> thisFileData = new HashMap<String, Object>();
-                thisFileData.put("scenes", loadedFeatures.scenes == null ? new ArrayList<Object>() : loadedFeatures.scenes);
-                thisFileData.put("objects", loadedFeatures.objects == null ? new ArrayList<Object>() : loadedFeatures.objects);
-                thisFileData.put("meshes", loadedFeatures.meshes == null ? new ArrayList<Object>() : loadedFeatures.meshes);
-                thisFileData.put("materials", loadedFeatures.materials == null ? new ArrayList<Object>() : loadedFeatures.materials);
-                thisFileData.put("textures", loadedFeatures.textures == null ? new ArrayList<Object>() : loadedFeatures.textures);
-                thisFileData.put("images", loadedFeatures.images == null ? new ArrayList<Object>() : loadedFeatures.images);
-                thisFileData.put("animations", loadedFeatures.animations == null ? new ArrayList<Object>() : loadedFeatures.animations);
-                thisFileData.put("cameras", loadedFeatures.cameras == null ? new ArrayList<Object>() : loadedFeatures.cameras);
-                thisFileData.put("lights", loadedFeatures.lights == null ? new ArrayList<Object>() : loadedFeatures.lights);
-                thisFileData.put("filters", loadedFeatures.filters == null ? new ArrayList<Object>() : loadedFeatures.filters);
-                thisFileData.put("backgroundColor", loadedFeatures.backgroundColor);
-                thisFileData.put("sky", loadedFeatures.sky);
-
-                linkedData.put("this", thisFileData);
-                linkedData.putAll(blenderContext.getLinkedFeatures());
-
-                modelRoot.setUserData("linkedData", linkedData);
-            }
-
-            return modelRoot;
-        } catch (BlenderFileException e) {
-            throw new IOException(e.getLocalizedMessage(), e);
-        } catch (Exception e) {
-            throw new IOException("Unexpected importer exception occurred: " + e.getLocalizedMessage(), e);
-        } finally {
-            this.clear(assetInfo);
-        }
-    }
-
-    /**
-     * This method converts the given structure to a scene node.
-     * @param structure
-     *            structure of a scene
-     *            @param blenderContext the blender context
-     * @return scene's node
-     * @throws BlenderFileException
-     *             an exception throw when problems with blender file occur
-     */
-    private Node toScene(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
-        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-        Node result = new Node(structure.getName());
-        List<Structure> base = ((Structure) structure.getFieldValue("base")).evaluateListBase();
-        for (Structure b : base) {
-            Pointer pObject = (Pointer) b.getFieldValue("object");
-            if (pObject.isNotNull()) {
-                Structure objectStructure = pObject.fetchData().get(0);
-
-                Object object = objectHelper.toObject(objectStructure, blenderContext);
-                if (object instanceof Node) {
-                    if (LOGGER.isLoggable(Level.FINE)) {
-                        LOGGER.log(Level.FINE, "{0}: {1}--> {2}", new Object[] { ((Node) object).getName(), ((Node) object).getLocalTranslation().toString(), ((Node) object).getParent() == null ? "null" : ((Node) object).getParent().getName() });
-                    }
-
-                    if (((Node) object).getParent() == null) {
-                        result.attachChild((Spatial) object);
-                    }
-
-                    if(object instanceof LightNode) {
-                        result.addLight(((LightNode) object).getLight());
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method sets up the loader.
-     * @param assetInfo
-     *            the asset info
-     * @throws BlenderFileException
-     *             an exception is throw when something wrong happens with blender file
-     */
-    protected BlenderContext setup(AssetInfo assetInfo) throws BlenderFileException {
-        // registering loaders
-        ModelKey modelKey = (ModelKey) assetInfo.getKey();
-        BlenderKey blenderKey;
-        if (modelKey instanceof BlenderKey) {
-            blenderKey = (BlenderKey) modelKey;
-        } else {
-            blenderKey = new BlenderKey(modelKey.getName());
-        }
-
-        // opening stream
-        BlenderInputStream inputStream = new BlenderInputStream(assetInfo.openStream());
-
-        // reading blocks
-        List<FileBlockHeader> blocks = new ArrayList<FileBlockHeader>();
-        FileBlockHeader fileBlock;
-        BlenderContext blenderContext = new BlenderContext();
-        blenderContext.setBlenderVersion(inputStream.getVersionNumber());
-        blenderContext.setAssetManager(assetInfo.getManager());
-        blenderContext.setInputStream(inputStream);
-        blenderContext.setBlenderKey(blenderKey);
-
-        // creating helpers
-        blenderContext.putHelper(AnimationHelper.class, new AnimationHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(TextureHelper.class, new TextureHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(MeshHelper.class, new MeshHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(ObjectHelper.class, new ObjectHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(CurvesHelper.class, new CurvesHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(LightHelper.class, new LightHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(CameraHelper.class, new CameraHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(ModifierHelper.class, new ModifierHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber(), blenderContext));
-        blenderContext.putHelper(LandscapeHelper.class, new LandscapeHelper(inputStream.getVersionNumber(), blenderContext));
-
-        // reading the blocks (dna block is automatically saved in the blender context when found)
-        FileBlockHeader sceneFileBlock = null;
-        do {
-            fileBlock = new FileBlockHeader(inputStream, blenderContext);
-            if (!fileBlock.isDnaBlock()) {
-                blocks.add(fileBlock);
-                // save the scene's file block
-                if (fileBlock.getCode() == BlockCode.BLOCK_SC00) {
-                    sceneFileBlock = fileBlock;
-                }
-            }
-        } while (!fileBlock.isLastBlock());
-        if (sceneFileBlock != null) {
-            blenderContext.setSceneStructure(sceneFileBlock.getStructure(blenderContext));
-        }
-        
-        // adding locator for linked content
-        assetInfo.getManager().registerLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
-        
-        return blenderContext;
-    }
-
-    /**
-     * The internal data is only needed during loading so make it unreachable so that the GC can release
-     * that memory (which can be quite large amount).
-     */
-    protected void clear(AssetInfo assetInfo) {
-        assetInfo.getManager().unregisterLocator(assetInfo.getKey().getName(), LinkedContentLocator.class);
-    }
-
-    /**
-     * This class holds the loading results according to the given loading flag.
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class LoadedFeatures {
-        private List<FileBlockHeader> sceneBlocks     = new ArrayList<FileBlockHeader>();
-        /** The scenes from the file. */
-        private List<Node>            scenes          = new ArrayList<Node>();
-        /** Objects from all scenes. */
-        private List<Node>            objects         = new ArrayList<Node>();
-        /** All meshes. */
-        private List<TemporalMesh>    meshes          = new ArrayList<TemporalMesh>();
-        /** Materials from all objects. */
-        private List<MaterialContext> materials       = new ArrayList<MaterialContext>();
-        /** Textures from all objects. */
-        private List<Texture>         textures        = new ArrayList<Texture>();
-        /** The images stored in the blender file. */
-        private List<Texture>         images          = new ArrayList<Texture>();
-        /** Animations of all objects. */
-        private List<Animation>       animations      = new ArrayList<Animation>();
-        /** All cameras from the file. */
-        private List<Camera>          cameras         = new ArrayList<Camera>();
-        /** All lights from the file. */
-        private List<Light>           lights          = new ArrayList<Light>();
-        /** Loaded sky. */
-        private Spatial               sky;
-        /** Scene filters (ie. FOG). */
-        private List<Filter>          filters         = new ArrayList<Filter>();
-        /**
-         * The background color of the render loaded from the horizon color of the world. If no world is used than the gray color
-         * is set to default (as in blender editor.
-         */
-        private ColorRGBA             backgroundColor = ColorRGBA.Gray;
-    }
-    
-    public static class LinkedContentLocator implements AssetLocator {
-        private File rootFolder;
-        
-        @Override
-        public void setRootPath(String rootPath) {
-            rootFolder = new File(rootPath);
-            if(rootFolder.isFile()) {
-                rootFolder = rootFolder.getParentFile();
-            }
-        }
-
-        @SuppressWarnings("rawtypes")
-        @Override
-        public AssetInfo locate(AssetManager manager, AssetKey key) {
-            if(key instanceof BlenderKey) {
-                File linkedAbsoluteFile = new File(key.getName());
-                if(linkedAbsoluteFile.exists() && linkedAbsoluteFile.isFile()) {
-                    try {
-                        return new StreamAssetInfo(manager, key, new FileInputStream(linkedAbsoluteFile));
-                    } catch (FileNotFoundException e) {
-                        return null;
-                    }
-                }
-                
-                File linkedFileInCurrentAssetFolder = new File(rootFolder, linkedAbsoluteFile.getName());
-                if(linkedFileInCurrentAssetFolder.exists() && linkedFileInCurrentAssetFolder.isFile()) {
-                    try {
-                        return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentAssetFolder));
-                    } catch (FileNotFoundException e) {
-                        return null;
-                    }
-                }
-                
-                File linkedFileInCurrentFolder = new File(".", linkedAbsoluteFile.getName());
-                if(linkedFileInCurrentFolder.exists() && linkedFileInCurrentFolder.isFile()) {
-                    try {
-                        return new StreamAssetInfo(manager, key, new FileInputStream(linkedFileInCurrentFolder));
-                    } catch (FileNotFoundException e) {
-                        return null;
-                    }
-                }
-            }
-            return null;
-        }
-    }
-}

+ 0 - 40
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/BlenderModelLoader.java

@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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;
-
-/**
- * This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures.
- * @deprecated this class is deprecated; use BlenderLoader instead
- * @author Marcin Roguski (Kaelthas)
- */
-public class BlenderModelLoader extends BlenderLoader {
-}

+ 0 - 391
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/AnimationHelper.java

@@ -1,391 +0,0 @@
-package com.jme3.scene.plugins.blender.animations;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-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.Animation;
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.Skeleton;
-import com.jme3.animation.SkeletonControl;
-import com.jme3.animation.SpatialTrack;
-import com.jme3.asset.BlenderKey.AnimationMatchMethod;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.Ipo.ConstIpo;
-import com.jme3.scene.plugins.blender.curves.BezierCurve;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.BlenderInputStream;
-import com.jme3.scene.plugins.blender.file.FileBlockHeader;
-import com.jme3.scene.plugins.blender.file.FileBlockHeader.BlockCode;
-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 helper class that helps in animations loading.
- * @author Marcin Roguski (Kaelthas)
- */
-public class AnimationHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER = Logger.getLogger(AnimationHelper.class.getName());
-
-    public AnimationHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * Loads all animations that are stored in the blender file. The animations are not yet applied to the scene features.
-     * This should be called before objects are loaded.
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with blender file reading occur
-     */
-    public void loadAnimations() throws BlenderFileException {
-        LOGGER.info("Loading animations that will be later applied to scene features.");
-        List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(BlockCode.BLOCK_AC00);
-        if (actionHeaders != null) {
-            for (FileBlockHeader header : actionHeaders) {
-                Structure actionStructure = header.getStructure(blenderContext);
-                LOGGER.log(Level.INFO, "Found animation: {0}.", actionStructure.getName());
-                blenderContext.addAction(this.getTracks(actionStructure, blenderContext));
-            }
-        }
-    }
-
-    /**
-     * The method applies animations to the given node. The names of the animations should be the same as actions names in the blender file.
-     * @param node
-     *            the node to whom the animations will be applied
-     * @param animationMatchMethod
-     *            the way animation should be matched with node
-     */
-    public void applyAnimations(Node node, AnimationMatchMethod animationMatchMethod) {
-        List<BlenderAction> actions = this.getActions(node, animationMatchMethod);
-        if (actions.size() > 0) {
-            List<Animation> animations = new ArrayList<Animation>();
-            for (BlenderAction action : actions) {
-                SpatialTrack[] tracks = action.toTracks(node, blenderContext);
-                if (tracks != null && tracks.length > 0) {
-                    Animation spatialAnimation = new Animation(action.getName(), action.getAnimationTime());
-                    spatialAnimation.setTracks(tracks);
-                    animations.add(spatialAnimation);
-                    blenderContext.addAnimation((Long) node.getUserData(ObjectHelper.OMA_MARKER), spatialAnimation);
-                }
-            }
-
-            if (animations.size() > 0) {
-                AnimControl control = new AnimControl();
-                HashMap<String, Animation> anims = new HashMap<String, Animation>(animations.size());
-                for (int i = 0; i < animations.size(); ++i) {
-                    Animation animation = animations.get(i);
-                    anims.put(animation.getName(), animation);
-                }
-                control.setAnimations(anims);
-                node.addControl(control);
-            }
-        }
-    }
-
-    /**
-     * The method applies skeleton animations to the given node.
-     * @param node
-     *            the node where the animations will be applied
-     * @param skeleton
-     *            the skeleton of the node
-     * @param animationMatchMethod
-     *            the way animation should be matched with skeleton
-     */
-    public void applyAnimations(Node node, Skeleton skeleton, AnimationMatchMethod animationMatchMethod) {
-        node.addControl(new SkeletonControl(skeleton));
-        blenderContext.setNodeForSkeleton(skeleton, node);
-        List<BlenderAction> actions = this.getActions(skeleton, animationMatchMethod);
-
-        if (actions.size() > 0) {
-            List<Animation> animations = new ArrayList<Animation>();
-            for (BlenderAction action : actions) {
-                BoneTrack[] tracks = action.toTracks(skeleton, blenderContext);
-                if (tracks != null && tracks.length > 0) {
-                    Animation boneAnimation = new Animation(action.getName(), action.getAnimationTime());
-                    boneAnimation.setTracks(tracks);
-                    animations.add(boneAnimation);
-                    Long animatedNodeOMA = ((Number) blenderContext.getMarkerValue(ObjectHelper.OMA_MARKER, node)).longValue();
-                    blenderContext.addAnimation(animatedNodeOMA, boneAnimation);
-                }
-            }
-            if (animations.size() > 0) {
-                AnimControl control = new AnimControl(skeleton);
-                HashMap<String, Animation> anims = new HashMap<String, Animation>(animations.size());
-                for (int i = 0; i < animations.size(); ++i) {
-                    Animation animation = animations.get(i);
-                    anims.put(animation.getName(), animation);
-                }
-                control.setAnimations(anims);
-                node.addControl(control);
-
-                // make sure that SkeletonControl is added AFTER the AnimControl
-                SkeletonControl skeletonControl = node.getControl(SkeletonControl.class);
-                if (skeletonControl != null) {
-                    node.removeControl(SkeletonControl.class);
-                    node.addControl(skeletonControl);
-                }
-            }
-        }
-    }
-
-    /**
-     * This method creates an ipo object used for interpolation calculations.
-     * 
-     * @param ipoStructure
-     *            the structure with ipo definition
-     * @param blenderContext
-     *            the blender context
-     * @return the ipo object
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public Ipo fromIpoStructure(Structure ipoStructure, BlenderContext blenderContext) throws BlenderFileException {
-        Structure curvebase = (Structure) ipoStructure.getFieldValue("curve");
-
-        // preparing bezier curves
-        Ipo result = null;
-        List<Structure> curves = curvebase.evaluateListBase();// IpoCurve
-        if (curves.size() > 0) {
-            BezierCurve[] bezierCurves = new BezierCurve[curves.size()];
-            int frame = 0;
-            for (Structure curve : curves) {
-                Pointer pBezTriple = (Pointer) curve.getFieldValue("bezt");
-                List<Structure> bezTriples = pBezTriple.fetchData();
-                int type = ((Number) curve.getFieldValue("adrcode")).intValue();
-                bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2);
-            }
-            curves.clear();
-            result = new Ipo(bezierCurves, fixUpAxis, blenderContext.getBlenderVersion());
-            Long ipoOma = ipoStructure.getOldMemoryAddress();
-            blenderContext.addLoadedFeatures(ipoOma, LoadedDataType.STRUCTURE, ipoStructure);
-            blenderContext.addLoadedFeatures(ipoOma, LoadedDataType.FEATURE, result);
-        }
-        return result;
-    }
-
-    /**
-     * This method creates an ipo with only a single value. No track type is
-     * specified so do not use it for calculating tracks.
-     * 
-     * @param constValue
-     *            the value of this ipo
-     * @return constant ipo
-     */
-    public Ipo fromValue(float constValue) {
-        return new ConstIpo(constValue);
-    }
-
-    /**
-     * This method retuns the bone tracks for animation.
-     * 
-     * @param actionStructure
-     *            the structure containing the tracks
-     * @param blenderContext
-     *            the blender context
-     * @return a list of tracks for the specified animation
-     * @throws BlenderFileException
-     *             an exception is thrown when there are problems with the blend
-     *             file
-     */
-    private BlenderAction getTracks(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
-        if (blenderVersion < 250) {
-            return this.getTracks249(actionStructure, blenderContext);
-        } else {
-            return this.getTracks250(actionStructure, blenderContext);
-        }
-    }
-
-    /**
-     * This method retuns the bone tracks for animation for blender version 2.50
-     * and higher.
-     * 
-     * @param actionStructure
-     *            the structure containing the tracks
-     * @param blenderContext
-     *            the blender context
-     * @return a list of tracks for the specified animation
-     * @throws BlenderFileException
-     *             an exception is thrown when there are problems with the blend
-     *             file
-     */
-    private BlenderAction getTracks250(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Getting tracks!");
-        Structure groups = (Structure) actionStructure.getFieldValue("groups");
-        List<Structure> actionGroups = groups.evaluateListBase();// bActionGroup
-        BlenderAction blenderAction = new BlenderAction(actionStructure.getName(), blenderContext.getBlenderKey().getFps());
-        int lastFrame = 1;
-        for (Structure actionGroup : actionGroups) {
-            String name = actionGroup.getFieldValue("name").toString();
-            List<Structure> channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase();
-            BezierCurve[] bezierCurves = new BezierCurve[channels.size()];
-            int channelCounter = 0;
-            for (Structure c : channels) {
-                int type = this.getCurveType(c, blenderContext);
-                Pointer pBezTriple = (Pointer) c.getFieldValue("bezt");
-                List<Structure> bezTriples = pBezTriple.fetchData();
-                bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2);
-            }
-
-            Ipo ipo = new Ipo(bezierCurves, fixUpAxis, blenderContext.getBlenderVersion());
-            lastFrame = Math.max(lastFrame, ipo.getLastFrame());
-            blenderAction.featuresTracks.put(name, ipo);
-        }
-        blenderAction.stopFrame = lastFrame;
-        return blenderAction;
-    }
-
-    /**
-     * This method retuns the bone tracks for animation for blender version 2.49
-     * (and probably several lower versions too).
-     * 
-     * @param actionStructure
-     *            the structure containing the tracks
-     * @param blenderContext
-     *            the blender context
-     * @return a list of tracks for the specified animation
-     * @throws BlenderFileException
-     *             an exception is thrown when there are problems with the blend
-     *             file
-     */
-    private BlenderAction getTracks249(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Getting tracks!");
-        Structure chanbase = (Structure) actionStructure.getFieldValue("chanbase");
-        List<Structure> actionChannels = chanbase.evaluateListBase();// bActionChannel
-        BlenderAction blenderAction = new BlenderAction(actionStructure.getName(), blenderContext.getBlenderKey().getFps());
-        int lastFrame = 1;
-        for (Structure bActionChannel : actionChannels) {
-            String animatedFeatureName = bActionChannel.getFieldValue("name").toString();
-            Pointer p = (Pointer) bActionChannel.getFieldValue("ipo");
-            if (!p.isNull()) {
-                Structure ipoStructure = p.fetchData().get(0);
-                Ipo ipo = this.fromIpoStructure(ipoStructure, blenderContext);
-                if (ipo != null) {// this can happen when ipo with no curves appear in blender file
-                    lastFrame = Math.max(lastFrame, ipo.getLastFrame());
-                    blenderAction.featuresTracks.put(animatedFeatureName, ipo);
-                }
-            }
-        }
-        blenderAction.stopFrame = lastFrame;
-        return blenderAction;
-    }
-
-    /**
-     * This method returns the type of the ipo curve.
-     * 
-     * @param structure
-     *            the structure must contain the 'rna_path' field and
-     *            'array_index' field (the type is not important here)
-     * @param blenderContext
-     *            the blender context
-     * @return the type of the curve
-     */
-    public int getCurveType(Structure structure, BlenderContext blenderContext) {
-        // reading rna path first
-        BlenderInputStream bis = blenderContext.getInputStream();
-        int currentPosition = bis.getPosition();
-        Pointer pRnaPath = (Pointer) structure.getFieldValue("rna_path");
-        FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pRnaPath.getOldMemoryAddress());
-        bis.setPosition(dataFileBlock.getBlockPosition());
-        String rnaPath = bis.readString();
-        bis.setPosition(currentPosition);
-        int arrayIndex = ((Number) structure.getFieldValue("array_index")).intValue();
-
-        // determining the curve type
-        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;
-        }
-        if (rnaPath.endsWith("rotation") || rnaPath.endsWith("rotation_euler")) {
-            return Ipo.OB_ROT_X + arrayIndex;
-        }
-        LOGGER.log(Level.WARNING, "Unknown curve rna path: {0}", rnaPath);
-        return -1;
-    }
-
-    /**
-     * The method returns the actions for the given skeleton. The actions represent armature animation in blender.
-     * @param skeleton
-     *            the skeleton we fetch the actions for
-     * @param animationMatchMethod
-     *            the method of animation matching
-     * @return a list of animations for the specified skeleton
-     */
-    private List<BlenderAction> getActions(Skeleton skeleton, AnimationMatchMethod animationMatchMethod) {
-        List<BlenderAction> result = new ArrayList<BlenderAction>();
-
-        // first get a set of bone names
-        Set<String> boneNames = new HashSet<String>();
-        for (int i = 0; i < skeleton.getBoneCount(); ++i) {
-            String boneName = skeleton.getBone(i).getName();
-            if (boneName != null && boneName.length() > 0) {
-                boneNames.add(skeleton.getBone(i).getName());
-            }
-        }
-
-        // finding matches
-        Set<String> matchingNames = new HashSet<String>();
-        for (Entry<String, BlenderAction> actionEntry : blenderContext.getActions().entrySet()) {
-            // compute how many action tracks match the skeleton bones' names
-            for (String boneName : boneNames) {
-                if (actionEntry.getValue().hasTrackName(boneName)) {
-                    matchingNames.add(boneName);
-                }
-            }
-
-            BlenderAction action = null;
-            if (animationMatchMethod == AnimationMatchMethod.AT_LEAST_ONE_NAME_MATCH && matchingNames.size() > 0) {
-                action = actionEntry.getValue();
-            } else if (matchingNames.size() == actionEntry.getValue().getTracksCount()) {
-                action = actionEntry.getValue();
-            }
-
-            if (action != null) {
-                // remove the tracks that do not match the bone names if the matching method is different from ALL_NAMES_MATCH
-                if (animationMatchMethod != AnimationMatchMethod.ALL_NAMES_MATCH) {
-                    action = action.clone();
-                    action.removeTracksThatAreNotInTheCollection(matchingNames);
-                }
-                result.add(action);
-            }
-
-            matchingNames.clear();
-        }
-        return result;
-    }
-
-    /**
-     * The method returns the actions for the given node. The actions represent object animation in blender.
-     * @param node
-     *            the node we fetch the actions for
-     * @param animationMatchMethod
-     *            the method of animation matching
-     * @return a list of animations for the specified node
-     */
-    private List<BlenderAction> getActions(Node node, AnimationMatchMethod animationMatchMethod) {
-        List<BlenderAction> result = new ArrayList<BlenderAction>();
-
-        for (Entry<String, BlenderAction> actionEntry : blenderContext.getActions().entrySet()) {
-            if (actionEntry.getValue().hasTrackName(node.getName())) {
-                result.add(actionEntry.getValue());
-            }
-        }
-        return result;
-    }
-}

+ 0 - 134
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/BlenderAction.java

@@ -1,134 +0,0 @@
-package com.jme3.scene.plugins.blender.animations;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.Skeleton;
-import com.jme3.animation.SpatialTrack;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.BlenderContext;
-
-/**
- * An abstract representation of animation. The data stored here is mainly a
- * raw action data loaded from blender. It can later be transformed into
- * bone or spatial animation and applied to the specified node.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class BlenderAction implements Cloneable {
-    /** The action name. */
-    /* package */final String     name;
-    /** Animation speed - frames per second. */
-    /* package */int              fps;
-    /**
-     * The last frame of the animation (the last ipo curve node position is
-     * used as a last frame).
-     */
-    /* package */int              stopFrame;
-    /**
-     * Tracks of the features. In case of bone animation the keys are the
-     * names of the bones. In case of spatial animation - the node's name is
-     * used. A single ipo contains all tracks for location, rotation and
-     * scales.
-     */
-    /* package */Map<String, Ipo> featuresTracks = new HashMap<String, Ipo>();
-
-    public BlenderAction(String name, int fps) {
-        this.name = name;
-        this.fps = fps;
-    }
-
-    public void removeTracksThatAreNotInTheCollection(Collection<String> trackNames) {
-        Map<String, Ipo> newTracks = new HashMap<String, Ipo>();
-        for (String trackName : trackNames) {
-            if (featuresTracks.containsKey(trackName)) {
-                newTracks.put(trackName, featuresTracks.get(trackName));
-            }
-        }
-        featuresTracks = newTracks;
-    }
-
-    @Override
-    public BlenderAction clone() {
-        BlenderAction result = new BlenderAction(name, fps);
-        result.stopFrame = stopFrame;
-        result.featuresTracks = new HashMap<String, Ipo>(featuresTracks);
-        return result;
-    }
-
-    /**
-     * Converts the action into JME spatial animation tracks.
-     * 
-     * @param node
-     *            the node that will be animated
-     * @return the spatial tracks for the node
-     */
-    public SpatialTrack[] toTracks(Node node, BlenderContext blenderContext) {
-        List<SpatialTrack> tracks = new ArrayList<SpatialTrack>(featuresTracks.size());
-        for (Entry<String, Ipo> entry : featuresTracks.entrySet()) {
-            tracks.add((SpatialTrack) entry.getValue().calculateTrack(0, null, node.getLocalTranslation(), node.getLocalRotation(), node.getLocalScale(), 1, stopFrame, fps, true));
-        }
-        return tracks.toArray(new SpatialTrack[tracks.size()]);
-    }
-
-    /**
-     * Converts the action into JME bone animation tracks.
-     * 
-     * @param skeleton
-     *            the skeleton that will be animated
-     * @return the bone tracks for the node
-     */
-    public BoneTrack[] toTracks(Skeleton skeleton, BlenderContext blenderContext) {
-        List<BoneTrack> tracks = new ArrayList<BoneTrack>(featuresTracks.size());
-        for (Entry<String, Ipo> entry : featuresTracks.entrySet()) {
-            int boneIndex = skeleton.getBoneIndex(entry.getKey());
-            BoneContext boneContext = blenderContext.getBoneContext(skeleton.getBone(boneIndex));
-            tracks.add((BoneTrack) entry.getValue().calculateTrack(boneIndex, boneContext, boneContext.getBone().getBindPosition(), boneContext.getBone().getBindRotation(), boneContext.getBone().getBindScale(), 1, stopFrame, fps, false));
-        }
-        return tracks.toArray(new BoneTrack[tracks.size()]);
-    }
-
-    /**
-     * @return the name of the action
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * @return the time of animations (in seconds)
-     */
-    public float getAnimationTime() {
-        return (stopFrame - 1) / (float) fps;
-    }
-
-    /**
-     * Determines if the current action has a track of a given name.
-     * CAUTION! The names are case sensitive.
-     * 
-     * @param name
-     *            the name of the track
-     * @return <B>true</b> if the track of a given name exists for the
-     *         action and <b>false</b> otherwise
-     */
-    public boolean hasTrackName(String name) {
-        return featuresTracks.containsKey(name);
-    }
-
-    /**
-     * @return the amount of tracks in current action
-     */
-    public int getTracksCount() {
-        return featuresTracks.size();
-    }
-
-    @Override
-    public String toString() {
-        return "BlenderTrack [name = " + name + "; tracks = [" + featuresTracks.keySet() + "]]";
-    }
-}

+ 0 - 400
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/BoneContext.java

@@ -1,400 +0,0 @@
-package com.jme3.scene.plugins.blender.animations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.jme3.animation.Bone;
-import com.jme3.animation.Skeleton;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
-import com.jme3.scene.plugins.blender.file.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.objects.ObjectHelper;
-
-/**
- * This class holds the basic data that describes a bone.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class BoneContext {
-    // the flags of the bone
-    public static final int      SELECTED                            = 0x000001;
-    public static final int      CONNECTED_TO_PARENT                 = 0x000010;
-    public static final int      DEFORM                              = 0x001000;
-    public static final int      NO_LOCAL_LOCATION                   = 0x400000;
-    public static final int      NO_INHERIT_SCALE                    = 0x008000;
-    public static final int      NO_INHERIT_ROTATION                 = 0x000200;
-    
-    /**
-     * The bones' matrices have, unlike objects', the coordinate system identical to JME's (Y axis is UP, X to the right and Z toward us).
-     * So in order to have them loaded properly we need to transform their armature matrix (which blender sees as rotated) to make sure we get identical results.
-     */
-    public static final Matrix4f BONE_ARMATURE_TRANSFORMATION_MATRIX = new Matrix4f(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
-
-    private static final int     IKFLAG_LOCK_X                       = 0x01;
-    private static final int     IKFLAG_LOCK_Y                       = 0x02;
-    private static final int     IKFLAG_LOCK_Z                       = 0x04;
-    private static final int     IKFLAG_LIMIT_X                      = 0x08;
-    private static final int     IKFLAG_LIMIT_Y                      = 0x10;
-    private static final int     IKFLAG_LIMIT_Z                      = 0x20;
-
-    private BlenderContext       blenderContext;
-    /** The OMA of the bone's armature object. */
-    private Long                 armatureObjectOMA;
-    /** The OMA of the model that owns the bone's skeleton. */
-    private Long                 skeletonOwnerOma;
-    /** The structure of the bone. */
-    private Structure            boneStructure;
-    /** Bone's name. */
-    private String               boneName;
-    /** The bone's flag. */
-    private int                  flag;
-    /** The bone's matrix in world space. */
-    private Matrix4f             globalBoneMatrix;
-    /** The bone's matrix in the model space. */
-    private Matrix4f             boneMatrixInModelSpace;
-    /** The parent context. */
-    private BoneContext          parent;
-    /** The children of this context. */
-    private List<BoneContext>    children                            = new ArrayList<BoneContext>();
-    /** Created bone (available after calling 'buildBone' method). */
-    private Bone                 bone;
-    /** The length of the bone. */
-    private float                length;
-    /** The bone's deform envelope. */
-    private BoneEnvelope         boneEnvelope;
-
-    // The below data is used only for IK constraint computations.
-
-    /** The bone's stretch value. */
-    private float                ikStretch;
-    /** Bone's rotation minimum values. */
-    private Vector3f             limitMin;
-    /** Bone's rotation maximum values. */
-    private Vector3f             limitMax;
-    /** The bone's stiffness values (how much it rotates during IK computations. */
-    private Vector3f             stiffness;
-    /** Values that indicate if any axis' rotation should be limited by some angle. */
-    private boolean[]            limits;
-    /** Values that indicate if any axis' rotation should be disabled during IK computations. */
-    private boolean[]            locks;
-
-    /**
-     * Constructor. Creates the basic set of bone's data.
-     * 
-     * @param armatureObjectOMA
-     *            the OMA of the bone's armature object
-     * @param boneStructure
-     *            the bone's structure
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is thrown when problem with blender data reading
-     *             occurs
-     */
-    public BoneContext(Long armatureObjectOMA, Structure boneStructure, BlenderContext blenderContext) throws BlenderFileException {
-        this(boneStructure, armatureObjectOMA, null, blenderContext);
-    }
-
-    /**
-     * Constructor. Creates the basic set of bone's data.
-     * 
-     * @param boneStructure
-     *            the bone's structure
-     * @param armatureObjectOMA
-     *            the OMA of the bone's armature object
-     * @param parent
-     *            bone's parent (null if the bone is the root bone)
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is thrown when problem with blender data reading
-     *             occurs
-     */
-    @SuppressWarnings("unchecked")
-    private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext parent, BlenderContext blenderContext) throws BlenderFileException {
-        this.parent = parent;
-        this.blenderContext = blenderContext;
-        this.boneStructure = boneStructure;
-        this.armatureObjectOMA = armatureObjectOMA;
-        boneName = boneStructure.getFieldValue("name").toString();
-        flag = ((Number) boneStructure.getFieldValue("flag")).intValue();
-        length = ((Number) boneStructure.getFieldValue("length")).floatValue();
-        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-
-        // first get the bone matrix in its armature space
-        globalBoneMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis());
-        if (blenderContext.getBlenderKey().isFixUpAxis()) {
-            // then make sure it is rotated in a proper way to fit the jme bone transformation conventions
-            globalBoneMatrix.multLocal(BONE_ARMATURE_TRANSFORMATION_MATRIX);
-        }
-
-        Structure armatureStructure = blenderContext.getFileBlock(armatureObjectOMA).getStructure(blenderContext);
-        Spatial armature = (Spatial) objectHelper.toObject(armatureStructure, blenderContext);
-        ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
-        Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform(), new Matrix4f());
-
-        // and now compute the final bone matrix in world space
-        globalBoneMatrix = armatureWorldMatrix.mult(globalBoneMatrix);
-
-        // load the bone deformation envelope if necessary
-        if ((flag & DEFORM) == 0) {// if the flag is NOT set then the DEFORM is in use
-            boneEnvelope = new BoneEnvelope(boneStructure, armatureWorldMatrix, blenderContext.getBlenderKey().isFixUpAxis());
-        }
-
-        // load bone's pose channel data
-        Pointer pPose = (Pointer) armatureStructure.getFieldValue("pose");
-        if (pPose != null && pPose.isNotNull()) {
-            List<Structure> poseChannels = ((Structure) pPose.fetchData().get(0).getFieldValue("chanbase")).evaluateListBase();
-            for (Structure poseChannel : poseChannels) {
-                Long boneOMA = ((Pointer) poseChannel.getFieldValue("bone")).getOldMemoryAddress();
-                if (boneOMA.equals(this.boneStructure.getOldMemoryAddress())) {
-                    ikStretch = ((Number) poseChannel.getFieldValue("ikstretch")).floatValue();
-                    DynamicArray<Number> limitMin = (DynamicArray<Number>) poseChannel.getFieldValue("limitmin");
-                    this.limitMin = new Vector3f(limitMin.get(0).floatValue(), limitMin.get(1).floatValue(), limitMin.get(2).floatValue());
-
-                    DynamicArray<Number> limitMax = (DynamicArray<Number>) poseChannel.getFieldValue("limitmax");
-                    this.limitMax = new Vector3f(limitMax.get(0).floatValue(), limitMax.get(1).floatValue(), limitMax.get(2).floatValue());
-
-                    DynamicArray<Number> stiffness = (DynamicArray<Number>) poseChannel.getFieldValue("stiffness");
-                    this.stiffness = new Vector3f(stiffness.get(0).floatValue(), stiffness.get(1).floatValue(), stiffness.get(2).floatValue());
-
-                    int ikFlag = ((Number) poseChannel.getFieldValue("ikflag")).intValue();
-                    locks = new boolean[] { (ikFlag & IKFLAG_LOCK_X) != 0, (ikFlag & IKFLAG_LOCK_Y) != 0, (ikFlag & IKFLAG_LOCK_Z) != 0 };
-                    // limits are enabled when locks are disabled, so we ween to take that into account here
-                    limits = new boolean[] { (ikFlag & IKFLAG_LIMIT_X & ~IKFLAG_LOCK_X) != 0, (ikFlag & IKFLAG_LIMIT_Y & ~IKFLAG_LOCK_Y) != 0, (ikFlag & IKFLAG_LIMIT_Z & ~IKFLAG_LOCK_Z) != 0 };
-                    break;// we have found what we need, no need to search further
-                }
-            }
-        }
-
-        // create the children
-        List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase();
-        for (Structure child : childbase) {
-            children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext));
-        }
-
-        blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this);
-    }
-
-    /**
-     * This method builds the bone. It recursively builds the bone's children.
-     * 
-     * @param bones
-     *            a list of bones where the newly created bone will be added
-     * @param skeletonOwnerOma
-     *            the spatial of the object that will own the skeleton
-     * @param blenderContext
-     *            the blender context
-     * @return newly created bone
-     */
-    public Bone buildBone(List<Bone> bones, Long skeletonOwnerOma, BlenderContext blenderContext) {
-        this.skeletonOwnerOma = skeletonOwnerOma;
-        Long boneOMA = boneStructure.getOldMemoryAddress();
-        bone = new Bone(boneName);
-        bones.add(bone);
-        blenderContext.addLoadedFeatures(boneOMA, LoadedDataType.STRUCTURE, boneStructure);
-        blenderContext.addLoadedFeatures(boneOMA, LoadedDataType.FEATURE, bone);
-        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-
-        Structure skeletonOwnerObjectStructure = (Structure) blenderContext.getLoadedFeature(skeletonOwnerOma, LoadedDataType.STRUCTURE);
-        // I could load 'imat' here, but apparently in some older blenders there were bugs or unfinished functionalities that stored ZERO matrix in imat field
-        // loading 'obmat' and inverting it makes us avoid errors in such cases
-        Matrix4f invertedObjectOwnerGlobalMatrix = objectHelper.getMatrix(skeletonOwnerObjectStructure, "obmat", blenderContext.getBlenderKey().isFixUpAxis()).invertLocal();
-        if (objectHelper.isParent(skeletonOwnerOma, armatureObjectOMA)) {
-            boneMatrixInModelSpace = globalBoneMatrix.mult(invertedObjectOwnerGlobalMatrix);
-        } else {
-            boneMatrixInModelSpace = invertedObjectOwnerGlobalMatrix.mult(globalBoneMatrix);
-        }
-
-        Matrix4f boneLocalMatrix = parent == null ? boneMatrixInModelSpace : parent.boneMatrixInModelSpace.invert().multLocal(boneMatrixInModelSpace);
-
-        Vector3f poseLocation = parent == null || !this.is(CONNECTED_TO_PARENT) ? boneLocalMatrix.toTranslationVector() : new Vector3f(0, parent.length, 0);
-        Quaternion rotation = boneLocalMatrix.toRotationQuat().normalizeLocal();
-        Vector3f scale = boneLocalMatrix.toScaleVector();
-
-        bone.setBindTransforms(poseLocation, rotation, scale);
-        for (BoneContext child : children) {
-            bone.addChild(child.buildBone(bones, skeletonOwnerOma, blenderContext));
-        }
-
-        return bone;
-    }
-
-    /**
-     * @return built bone (available after calling 'buildBone' method)
-     */
-    public Bone getBone() {
-        return bone;
-    }
-
-    /**
-     * @return the old memory address of the bone
-     */
-    public Long getBoneOma() {
-        return boneStructure.getOldMemoryAddress();
-    }
-
-    /**
-     * The method returns the length of the bone.
-     * If you want to use it for bone debugger take model space scale into account and do
-     * something like this:
-     * <b>boneContext.getLength() * boneContext.getBone().getModelSpaceScale().y</b>.
-     * Otherwise the bones might not look as they should in the bone debugger.
-     * @return the length of the bone
-     */
-    public float getLength() {
-        return length;
-    }
-
-    /**
-     * @return OMA of the bone's armature object
-     */
-    public Long getArmatureObjectOMA() {
-        return armatureObjectOMA;
-    }
-
-    /**
-     * @return the OMA of the model that owns the bone's skeleton
-     */
-    public Long getSkeletonOwnerOma() {
-        return skeletonOwnerOma;
-    }
-
-    /**
-     * @return the skeleton the bone of this context belongs to
-     */
-    public Skeleton getSkeleton() {
-        return blenderContext.getSkeleton(armatureObjectOMA);
-    }
-
-    /**
-     * @return the initial bone's matrix in model space
-     */
-    public Matrix4f getBoneMatrixInModelSpace() {
-        return boneMatrixInModelSpace;
-    }
-
-    /**
-     * @return the vertex assigning envelope of the bone
-     */
-    public BoneEnvelope getBoneEnvelope() {
-        return boneEnvelope;
-    }
-
-    /**
-     * @return bone's stretch factor
-     */
-    public float getIkStretch() {
-        return ikStretch;
-    }
-
-    /**
-     * @return indicates if the X rotation should be limited
-     */
-    public boolean isLimitX() {
-        return limits != null ? limits[0] : false;
-    }
-
-    /**
-     * @return indicates if the Y rotation should be limited
-     */
-    public boolean isLimitY() {
-        return limits != null ? limits[1] : false;
-    }
-
-    /**
-     * @return indicates if the Z rotation should be limited
-     */
-    public boolean isLimitZ() {
-        return limits != null ? limits[2] : false;
-    }
-
-    /**
-     * @return indicates if the X rotation should be disabled
-     */
-    public boolean isLockX() {
-        return locks != null ? locks[0] : false;
-    }
-
-    /**
-     * @return indicates if the Y rotation should be disabled
-     */
-    public boolean isLockY() {
-        return locks != null ? locks[1] : false;
-    }
-
-    /**
-     * @return indicates if the Z rotation should be disabled
-     */
-    public boolean isLockZ() {
-        return locks != null ? locks[2] : false;
-    }
-
-    /**
-     * @return the minimum values in rotation limitation (if limitation is enabled for specific axis).
-     */
-    public Vector3f getLimitMin() {
-        return limitMin;
-    }
-
-    /**
-     * @return the maximum values in rotation limitation (if limitation is enabled for specific axis).
-     */
-    public Vector3f getLimitMax() {
-        return limitMax;
-    }
-
-    /**
-     * @return the stiffness of the bone
-     */
-    public Vector3f getStiffness() {
-        return stiffness;
-    }
-
-    /**
-     * Tells if the bone is of specified property defined by its flag.
-     * @param flagMask
-     *            the mask of the flag (constants defined in this class)
-     * @return <b>true</b> if the bone IS of specified proeprty and <b>false</b> otherwise
-     */
-    public boolean is(int flagMask) {
-        return (flag & flagMask) != 0;
-    }
-
-    /**
-     * @return the root bone context of this bone context
-     */
-    public BoneContext getRoot() {
-        BoneContext result = this;
-        while (result.parent != null) {
-            result = result.parent;
-        }
-        return result;
-    }
-
-    /**
-     * @return a number of bones from this bone to its root
-     */
-    public int getDistanceFromRoot() {
-        int result = 0;
-        BoneContext boneContext = this;
-        while (boneContext.parent != null) {
-            boneContext = boneContext.parent;
-            ++result;
-        }
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "BoneContext: " + boneName;
-    }
-}

+ 0 - 133
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/BoneEnvelope.java

@@ -1,133 +0,0 @@
-package com.jme3.scene.plugins.blender.animations;
-
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.file.DynamicArray;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * An implementation of bone envelope. Used when assigning bones to the mesh by envelopes.
- * 
- * @author Marcin Roguski
- */
-public class BoneEnvelope {
-    /** A defined distance that will be included in the envelope space. */
-    private float    distance;
-    /** The bone's weight. */
-    private float    weight;
-    /** The radius of the bone's head. */
-    private float    boneHeadRadius;
-    /** The radius of the bone's tail. */
-    private float    boneTailRadius;
-    /** Head position in rest pose in world space. */
-    private Vector3f head;
-    /** Tail position in rest pose in world space. */
-    private Vector3f tail;
-
-    /**
-     * The constructor of bone envelope. It reads all the needed data. Take notice that the positions of head and tail
-     * are computed in the world space and that the points' positions given for computations should be in world space as well.
-     * 
-     * @param boneStructure
-     *            the blender bone structure
-     * @param armatureWorldMatrix
-     *            the world matrix of the armature object
-     * @param fixUpAxis
-     *            a variable that tells if we use the Y-is up axis orientation
-     */
-    @SuppressWarnings("unchecked")
-    public BoneEnvelope(Structure boneStructure, Matrix4f armatureWorldMatrix, boolean fixUpAxis) {
-        distance = ((Number) boneStructure.getFieldValue("dist")).floatValue();
-        weight = ((Number) boneStructure.getFieldValue("weight")).floatValue();
-        boneHeadRadius = ((Number) boneStructure.getFieldValue("rad_head")).floatValue();
-        boneTailRadius = ((Number) boneStructure.getFieldValue("rad_tail")).floatValue();
-
-        DynamicArray<Number> headArray = (DynamicArray<Number>) boneStructure.getFieldValue("arm_head");
-        head = new Vector3f(headArray.get(0).floatValue(), headArray.get(1).floatValue(), headArray.get(2).floatValue());
-        if (fixUpAxis) {
-            float z = head.z;
-            head.z = -head.y;
-            head.y = z;
-        }
-        armatureWorldMatrix.mult(head, head);// move the head point to global space
-
-        DynamicArray<Number> tailArray = (DynamicArray<Number>) boneStructure.getFieldValue("arm_tail");
-        tail = new Vector3f(tailArray.get(0).floatValue(), tailArray.get(1).floatValue(), tailArray.get(2).floatValue());
-        if (fixUpAxis) {
-            float z = tail.z;
-            tail.z = -tail.y;
-            tail.y = z;
-        }
-        armatureWorldMatrix.mult(tail, tail);// move the tail point to global space
-    }
-
-    /**
-     * The method verifies if the given point is inside the envelope.
-     * @param point
-     *            the point in 3D space (MUST be in a world coordinate space)
-     * @return <b>true</b> if the point is inside the envelope and <b>false</b> otherwise
-     */
-    public boolean isInEnvelope(Vector3f point) {
-        Vector3f v = tail.subtract(head);
-        float boneLength = v.length();
-        v.normalizeLocal();
-
-        // computing a plane that contains 'point' and v is its normal vector
-        // the plane's equation is: Ax + By + Cz + D = 0, where v = [A, B, C]
-        float D = -v.dot(point);
-
-        // computing a point where a line that contains head and tail crosses the plane
-        float temp = -(v.dot(head) + D) / v.dot(v);
-        Vector3f p = head.add(v.x * temp, v.y * temp, v.z * temp);
-
-        // determining if the point p is on the same or other side of head than the tail point
-        Vector3f headToPointOnLineVector = p.subtract(head);
-        float headToPointLength = headToPointOnLineVector.length();
-        float cosinus = headToPointOnLineVector.dot(v) / headToPointLength;// the length of v is already = 1; cosinus should be either 1, 0 or -1
-        if (cosinus < 0 && headToPointLength > boneHeadRadius || headToPointLength > boneLength + boneTailRadius) {
-            return false;// the point is outside the anvelope
-        }
-
-        // now check if the point is inside and envelope
-        float pointDistanceFromLine = point.subtract(p).length(), maximumDistance = 0;
-        if (cosinus < 0) {
-            // checking if the distance from p to point is inside the half sphere defined by head envelope
-            // compute the distance from the line to the half sphere border
-            maximumDistance = boneHeadRadius;
-        } else if (headToPointLength < boneLength) {
-            // compute the maximum available distance
-            if (boneTailRadius > boneHeadRadius) {
-                // compute the distance from head to p
-                float headToPDistance = p.subtract(head).length();
-                // from tangens function we have
-                float x = headToPDistance * ((boneTailRadius - boneHeadRadius) / boneLength);
-                maximumDistance = x + boneHeadRadius;
-            } else if (boneTailRadius < boneHeadRadius) {
-                // compute the distance from head to p
-                float tailToPDistance = p.subtract(tail).length();
-                // from tangens function we have
-                float x = tailToPDistance * ((boneHeadRadius - boneTailRadius) / boneLength);
-                maximumDistance = x + boneTailRadius;
-            } else {
-                maximumDistance = boneTailRadius;
-            }
-        } else {
-            // checking if the distance from p to point is inside the half sphere defined by tail envelope
-            maximumDistance = boneTailRadius;
-        }
-
-        return pointDistanceFromLine <= maximumDistance + distance;
-    }
-
-    /**
-     * @return the weight of the bone
-     */
-    public float getWeight() {
-        return weight;
-    }
-
-    @Override
-    public String toString() {
-        return "BoneEnvelope [d=" + distance + ", w=" + weight + ", hr=" + boneHeadRadius + ", tr=" + boneTailRadius + ", (" + head + ") -> (" + tail + ")]";
-    }
-}

+ 0 - 317
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/animations/Ipo.java

@@ -1,317 +0,0 @@
-package com.jme3.scene.plugins.blender.animations;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.SpatialTrack;
-import com.jme3.animation.Track;
-import com.jme3.math.FastMath;
-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 of several b-spline curves (connected 3rd
- * degree bezier curves) of a different type.
- * 
- * @author Marcin Roguski
- */
-public class Ipo {
-    private static final Logger LOGGER    = Logger.getLogger(Ipo.class.getName());
-
-    public static final int     AC_LOC_X  = 1;
-    public static final int     AC_LOC_Y  = 2;
-    public static final int     AC_LOC_Z  = 3;
-    public static final int     OB_ROT_X  = 7;
-    public static final int     OB_ROT_Y  = 8;
-    public static final int     OB_ROT_Z  = 9;
-    public static final int     AC_SIZE_X = 13;
-    public static final int     AC_SIZE_Y = 14;
-    public static final int     AC_SIZE_Z = 15;
-    public static final int     AC_QUAT_W = 25;
-    public static final int     AC_QUAT_X = 26;
-    public static final int     AC_QUAT_Y = 27;
-    public static final int     AC_QUAT_Z = 28;
-
-    /** A list of bezier curves for this interpolation object. */
-    private BezierCurve[]       bezierCurves;
-    /** Each ipo contains one bone track. */
-    private Track               calculatedTrack;
-    /** This variable indicates if the Y asxis is the UP axis or not. */
-    protected boolean           fixUpAxis;
-    /**
-     * Depending on the blender version rotations are stored in degrees or
-     * radians so we need to know the version that is used.
-     */
-    protected final int         blenderVersion;
-
-    /**
-     * Constructor. Stores the bezier curves.
-     * 
-     * @param bezierCurves
-     *            a table of bezier curves
-     * @param fixUpAxis
-     *            indicates if the Y is the up axis or not
-     * @param blenderVersion
-     *            the blender version that is currently used
-     */
-    public Ipo(BezierCurve[] bezierCurves, boolean fixUpAxis, int blenderVersion) {
-        this.bezierCurves = bezierCurves;
-        this.fixUpAxis = fixUpAxis;
-        this.blenderVersion = blenderVersion;
-    }
-
-    /**
-     * This method calculates the ipo value for the first curve.
-     * 
-     * @param frame
-     *            the frame for which the value is calculated
-     * @return calculated ipo value
-     */
-    public double calculateValue(int frame) {
-        return this.calculateValue(frame, 0);
-    }
-
-    /**
-     * This method calculates the ipo value for the curve of the specified
-     * index. Make sure you do not exceed the curves amount. Alway chech the
-     * amount of curves before calling this method.
-     * 
-     * @param frame
-     *            the frame for which the value is calculated
-     * @param curveIndex
-     *            the index of the curve
-     * @return calculated ipo value
-     */
-    public double calculateValue(int frame, int curveIndex) {
-        return bezierCurves[curveIndex].evaluate(frame, BezierCurve.Y_VALUE);
-    }
-
-    /**
-     * This method returns the frame where last bezier triple center point of
-     * the specified bezier curve is located.
-     * 
-     * @return the frame number of the last defined bezier triple point for the
-     *         specified ipo
-     */
-    public int getLastFrame() {
-        int result = 1;
-        for (int i = 0; i < bezierCurves.length; ++i) {
-            int tempResult = bezierCurves[i].getLastFrame();
-            if (tempResult > result) {
-                result = tempResult;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method calculates the value of the curves as a bone track between
-     * the specified frames.
-     * 
-     * @param targetIndex
-     *            the index of the target for which the method calculates the
-     *            tracks IMPORTANT! Aet to -1 (or any negative number) if you
-     *            want to load spatial animation.
-     * @param localTranslation
-     *            the local translation of the object/bone that will be animated by
-     *            the track
-     * @param localRotation
-     *            the local rotation of the object/bone that will be animated by
-     *            the track
-     * @param localScale
-     *            the local scale of the object/bone that will be animated by
-     *            the track
-     * @param startFrame
-     *            the first frame of tracks (inclusive)
-     * @param stopFrame
-     *            the last frame of the tracks (inclusive)
-     * @param fps
-     *            frame rate (frames per second)
-     * @param spatialTrack
-     *            this flag indicates if the track belongs to a spatial or to a
-     *            bone; the difference is important because it appears that bones
-     *            in blender have the same type of coordinate system (Y as UP)
-     *            as jme while other features have different one (Z is UP)
-     * @return bone track for the specified bone
-     */
-    public Track calculateTrack(int targetIndex, BoneContext boneContext, Vector3f localTranslation, Quaternion localRotation, Vector3f localScale, int startFrame, int stopFrame, int fps, boolean spatialTrack) {
-        if (calculatedTrack == null) {
-            // preparing data for track
-            int framesAmount = stopFrame - startFrame;
-            float timeBetweenFrames = 1.0f / fps;
-
-            float[] times = new float[framesAmount + 1];
-            Vector3f[] translations = new Vector3f[framesAmount + 1];
-            float[] translation = new float[3];
-            Quaternion[] rotations = new Quaternion[framesAmount + 1];
-            float[] quaternionRotation = new float[] { localRotation.getX(), localRotation.getY(), localRotation.getZ(), localRotation.getW(), };
-            float[] eulerRotation = localRotation.toAngles(null);
-            Vector3f[] scales = new Vector3f[framesAmount + 1];
-            float[] scale = new float[] { localScale.x, localScale.y, localScale.z };
-            float degreeToRadiansFactor = 1;
-            if (blenderVersion < 250) {// in blender earlier than 2.50 the values are stored in degrees
-                degreeToRadiansFactor *= FastMath.DEG_TO_RAD * 10;// the values in blender are divided by 10, so we need to mult it here
-            }
-            int yIndex = 1, zIndex = 2;
-            boolean swapAxes = spatialTrack && fixUpAxis;
-            if (swapAxes) {
-                yIndex = 2;
-                zIndex = 1;
-            }
-            boolean eulerRotationUsed = false, queternionRotationUsed = false;
-
-            // calculating track data
-            for (int frame = startFrame; frame <= stopFrame; ++frame) {
-                boolean translationSet = false;
-                translation[0] = translation[1] = translation[2] = 0;
-                int index = frame - startFrame;
-                times[index] = index * timeBetweenFrames;// start + (frame - 1) * timeBetweenFrames;
-                for (int j = 0; j < bezierCurves.length; ++j) {
-                    double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
-                    switch (bezierCurves[j].getType()) {
-                        // LOCATION
-                        case AC_LOC_X:
-                            translation[0] = (float) value;
-                            translationSet = true;
-                            break;
-                        case AC_LOC_Y:
-                            if (swapAxes && value != 0) {
-                                value = -value;
-                            }
-                            translation[yIndex] = (float) value;
-                            translationSet = true;
-                            break;
-                        case AC_LOC_Z:
-                            translation[zIndex] = (float) value;
-                            translationSet = true;
-                            break;
-
-                        // EULER ROTATION
-                        case OB_ROT_X:
-                            eulerRotationUsed = true;
-                            eulerRotation[0] = (float) value * degreeToRadiansFactor;
-                            break;
-                        case OB_ROT_Y:
-                            eulerRotationUsed = true;
-                            if (swapAxes && value != 0) {
-                                value = -value;
-                            }
-                            eulerRotation[yIndex] = (float) value * degreeToRadiansFactor;
-                            break;
-                        case OB_ROT_Z:
-                            eulerRotationUsed = true;
-                            eulerRotation[zIndex] = (float) value * degreeToRadiansFactor;
-                            break;
-
-                        // SIZE
-                        case AC_SIZE_X:
-                            scale[0] = (float) value;
-                            break;
-                        case AC_SIZE_Y:
-                            scale[yIndex] = (float) value;
-                            break;
-                        case AC_SIZE_Z:
-                            scale[zIndex] = (float) value;
-                            break;
-
-                        // QUATERNION ROTATION (used with bone animation)
-                        case AC_QUAT_W:
-                            queternionRotationUsed = true;
-                            quaternionRotation[3] = (float) value;
-                            break;
-                        case AC_QUAT_X:
-                            queternionRotationUsed = true;
-                            quaternionRotation[0] = (float) value;
-                            break;
-                        case AC_QUAT_Y:
-                            queternionRotationUsed = true;
-                            if (swapAxes && value != 0) {
-                                value = -value;
-                            }
-                            quaternionRotation[yIndex] = (float) value;
-                            break;
-                        case AC_QUAT_Z:
-                            quaternionRotation[zIndex] = (float) value;
-                            break;
-                        default:
-                            LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType());
-                    }
-                }
-                if(translationSet) {
-                    translations[index] = localRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2]));
-                } else {
-                    translations[index] = new Vector3f();
-                }
-                
-                if(boneContext != null) {
-                    if(boneContext.getBone().getParent() == null && boneContext.is(BoneContext.NO_LOCAL_LOCATION)) {
-                        float temp = translations[index].z;
-                        translations[index].z = -translations[index].y;
-                        translations[index].y = temp;
-                    }
-                }
-                
-                if (queternionRotationUsed) {
-                    rotations[index] = new Quaternion(quaternionRotation[0], quaternionRotation[1], quaternionRotation[2], quaternionRotation[3]);
-                } else {
-                    rotations[index] = new Quaternion().fromAngles(eulerRotation);
-                }
-
-                scales[index] = new Vector3f(scale[0], scale[1], scale[2]);
-            }
-            if (spatialTrack) {
-                calculatedTrack = new SpatialTrack(times, translations, rotations, scales);
-            } else {
-                calculatedTrack = new BoneTrack(targetIndex, times, translations, rotations, scales);
-            }
-
-            if (queternionRotationUsed && eulerRotationUsed) {
-                LOGGER.warning("Animation uses both euler and quaternion tracks for rotations. Quaternion rotation is applied. Make sure that this is what you wanted!");
-            }
-        }
-
-        return calculatedTrack;
-    }
-
-    /**
-     * Ipo constant curve. This is a curve with only one value and no specified
-     * type. This type of ipo cannot be used to calculate tracks. It should only
-     * be used to calculate single value for a given frame.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    /* package */static class ConstIpo extends Ipo {
-
-        /** The constant value of this ipo. */
-        private float constValue;
-
-        /**
-         * Constructor. Stores the constant value of this ipo.
-         * 
-         * @param constValue
-         *            the constant value of this ipo
-         */
-        public ConstIpo(float constValue) {
-            super(null, false, 0);// the version is not important here
-            this.constValue = constValue;
-        }
-
-        @Override
-        public double calculateValue(int frame) {
-            return constValue;
-        }
-
-        @Override
-        public double calculateValue(int frame, int curveIndex) {
-            return constValue;
-        }
-
-        @Override
-        public BoneTrack calculateTrack(int boneIndex, BoneContext boneContext, Vector3f localTranslation, Quaternion localRotation, Vector3f localScale, int startFrame, int stopFrame, int fps, boolean boneTrack) {
-            throw new IllegalStateException("Constatnt ipo object cannot be used for calculating bone tracks!");
-        }
-    }
-}

+ 0 - 148
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/cameras/CameraHelper.java

@@ -1,148 +0,0 @@
-package com.jme3.scene.plugins.blender.cameras;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.math.FastMath;
-import com.jme3.renderer.Camera;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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  = 640;
-    protected static final int  DEFAULT_CAM_HEIGHT = 480;
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public CameraHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * 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, BlenderContext blenderContext) throws BlenderFileException {
-        if (blenderVersion >= 250) {
-            return this.toCamera250(structure, blenderContext.getSceneStructure());
-        } 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
-     * @param sceneStructure
-     *            scene structure
-     * @return jme camera object
-     * @throws BlenderFileException
-     *             an exception is thrown when there are problems with the
-     *             blender file
-     */
-    private Camera toCamera250(Structure structure, Structure sceneStructure) throws BlenderFileException {
-        int width = DEFAULT_CAM_WIDTH;
-        int height = DEFAULT_CAM_HEIGHT;
-        if (sceneStructure != null) {
-            Structure renderData = (Structure) sceneStructure.getFieldValue("r");
-            width = ((Number) renderData.getFieldValue("xsch")).shortValue();
-            height = ((Number) renderData.getFieldValue("ysch")).shortValue();
-        }
-        Camera camera = new Camera(width, 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
-        camera.setParallelProjection(type == 1);
-        float aspect = width / (float) height;
-        float fovY; // Vertical field of view in degrees
-        float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
-        float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
-        if (type == 0) {
-            // Convert lens MM to vertical degrees in fovY, see Blender rna_Camera_angle_get()
-            // Default sensor size prior to 2.60 was 32.
-            float sensor = 32.0f;
-            boolean sensorVertical = false;
-            Number sensorFit = (Number) structure.getFieldValue("sensor_fit");
-            if (sensorFit != null) {
-                // If sensor_fit is vert (2), then sensor_y is used
-                sensorVertical = sensorFit.byteValue() == 2;
-                String sensorName = "sensor_x";
-                if (sensorVertical) {
-                    sensorName = "sensor_y";
-                }
-                sensor = ((Number) structure.getFieldValue(sensorName)).floatValue();
-            }
-            float focalLength = ((Number) structure.getFieldValue("lens")).floatValue();
-            float fov = 2.0f * FastMath.atan(sensor / 2.0f / focalLength);
-            if (sensorVertical) {
-                fovY = fov * FastMath.RAD_TO_DEG;
-            } else {
-                // Convert fov from horizontal to vertical
-                fovY = 2.0f * FastMath.atan(FastMath.tan(fov / 2.0f) / aspect) * FastMath.RAD_TO_DEG;
-            }
-        } else {
-            // This probably is not correct.
-            fovY = ((Number) structure.getFieldValue("ortho_scale")).floatValue();
-        }
-        camera.setFrustumPerspective(fovY, aspect, clipsta, clipend);
-        camera.setName(structure.getName());
-        return camera;
-    }
-
-    /**
-     * 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
-     */
-    private Camera toCamera249(Structure structure) throws BlenderFileException {
-        Camera camera = 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
-        camera.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();
-        }
-        camera.setFrustumPerspective(aspect, camera.getWidth() / camera.getHeight(), clipsta, clipend);
-        camera.setName(structure.getName());
-        return camera;
-    }
-}

+ 0 - 88
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/BoneConstraint.java

@@ -1,88 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.animations.Ipo;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.objects.ObjectHelper;
-
-/**
- * Constraint applied on the bone.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class BoneConstraint extends Constraint {
-    private static final Logger LOGGER = Logger.getLogger(BoneConstraint.class.getName());
-
-    /**
-     * The bone constraint constructor.
-     * 
-     * @param constraintStructure
-     *            the constraint's structure
-     * @param ownerOMA
-     *            the OMA of the bone that owns the constraint
-     * @param influenceIpo
-     *            the influence interpolation curve
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             exception thrown when problems with blender file occur
-     */
-    public BoneConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
-        super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-    }
-
-    @Override
-    public boolean validate() {
-        if (targetOMA != null) {
-            Spatial nodeTarget = (Spatial) blenderContext.getLoadedFeature(targetOMA, LoadedDataType.FEATURE);
-            if (nodeTarget == null) {
-                LOGGER.log(Level.WARNING, "Cannot find target for constraint: {0}.", name);
-                return false;
-            }
-            // the second part of the if expression verifies if the found node
-            // (if any) is an armature node
-            if (blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, nodeTarget) != null) {
-                if (subtargetName.trim().isEmpty()) {
-                    LOGGER.log(Level.WARNING, "No bone target specified for constraint: {0}.", name);
-                    return false;
-                }
-                // if the target is not an object node then it is an Armature,
-                // so make sure the bone is in the current skeleton
-                BoneContext boneContext = blenderContext.getBoneContext(ownerOMA);
-                if (targetOMA.longValue() != boneContext.getArmatureObjectOMA().longValue()) {
-                    LOGGER.log(Level.WARNING, "Bone constraint {0} must target bone in the its own skeleton! Targeting bone in another skeleton is not supported!", name);
-                    return false;
-                }
-            }
-        }
-        return constraintDefinition == null ? true : constraintDefinition.isTargetRequired();
-    }
-
-    @Override
-    public void apply(int frame) {
-        super.apply(frame);
-        blenderContext.getBoneContext(ownerOMA).getBone().updateModelTransforms();
-    }
-    
-    @Override
-    public Long getTargetOMA() {
-        if(targetOMA != null && subtargetName != null && !subtargetName.trim().isEmpty()) {
-            Spatial nodeTarget = (Spatial) blenderContext.getLoadedFeature(targetOMA, LoadedDataType.FEATURE);
-            if(nodeTarget != null) {
-                if(blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, nodeTarget) != null) {
-                    BoneContext boneContext = blenderContext.getBoneByName(targetOMA, subtargetName);
-                    return boneContext != null ? boneContext.getBoneOma() : 0L;
-                }
-                return targetOMA;
-            }
-        }
-        return 0L;
-    }
-}

+ 0 - 186
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/Constraint.java

@@ -1,186 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.Ipo;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.constraints.definitions.ConstraintDefinition;
-import com.jme3.scene.plugins.blender.constraints.definitions.ConstraintDefinitionFactory;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * The implementation of a constraint.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public abstract class Constraint {
-    private static final Logger          LOGGER = Logger.getLogger(Constraint.class.getName());
-
-    /** The name of this constraint. */
-    protected final String               name;
-    /** Indicates if the constraint is already baked or not. */
-    protected boolean                    baked;
-
-    protected Space                      ownerSpace;
-    protected final ConstraintDefinition constraintDefinition;
-    protected Long                       ownerOMA;
-
-    protected Long                       targetOMA;
-    protected Space                      targetSpace;
-    protected String                     subtargetName;
-
-    /** The ipo object defining influence. */
-    protected final Ipo                  ipo;
-    /** The blender context. */
-    protected final BlenderContext       blenderContext;
-    protected final ConstraintHelper     constraintHelper;
-
-    /**
-     * This constructor creates the constraint instance.
-     * 
-     * @param constraintStructure
-     *            the constraint's structure (bConstraint clss in blender 2.49).
-     * @param ownerOMA
-     *            the old memory address of the constraint owner
-     * @param influenceIpo
-     *            the ipo curve of the influence factor
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public Constraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
-        this.blenderContext = blenderContext;
-        name = constraintStructure.getFieldValue("name").toString();
-        Pointer pData = (Pointer) constraintStructure.getFieldValue("data");
-        if (pData.isNotNull()) {
-            Structure data = pData.fetchData().get(0);
-            constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(data, name, ownerOMA, blenderContext);
-            Pointer pTar = (Pointer) data.getFieldValue("tar");
-            if (pTar != null && pTar.isNotNull()) {
-                targetOMA = pTar.getOldMemoryAddress();
-                targetSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("tarspace")).byteValue());
-                Object subtargetValue = data.getFieldValue("subtarget");
-                if (subtargetValue != null) {// not all constraint data have the
-                                             // subtarget field
-                    subtargetName = subtargetValue.toString();
-                }
-            }
-        } else {
-            // Null constraint has no data, so create it here
-            constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(null, name, null, blenderContext);
-        }
-        ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue());
-        ipo = influenceIpo;
-        this.ownerOMA = ownerOMA;
-        constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
-        LOGGER.log(Level.INFO, "Created constraint: {0} with definition: {1}", new Object[] { name, constraintDefinition });
-    }
-
-    /**
-     * @return <b>true</b> if the constraint is implemented and <b>false</b>
-     *         otherwise
-     */
-    public boolean isImplemented() {
-        return constraintDefinition == null ? true : constraintDefinition.isImplemented();
-    }
-
-    /**
-     * @return the name of the constraint type, similar to the constraint name
-     *         used in Blender
-     */
-    public String getConstraintTypeName() {
-        return constraintDefinition.getConstraintTypeName();
-    }
-
-    /**
-     * @return the OMAs of the features whose transform had been altered beside the constraint owner
-     */
-    public Set<Long> getAlteredOmas() {
-        return constraintDefinition.getAlteredOmas();
-    }
-
-    /**
-     * Performs validation before baking. Checks factors that can prevent
-     * constraint from baking that could not be checked during constraint
-     * loading.
-     */
-    public abstract boolean validate();
-
-    /**
-     * @return the OMA of the target or 0 if no target is specified for the constraint
-     */
-    public abstract Long getTargetOMA();
-
-    /**
-     * Applies the constraint to owner (and in some cases can alter other bones of the skeleton).
-     * @param frame
-     *            the frame of the animation
-     */
-    public void apply(int frame) {
-        if (LOGGER.isLoggable(Level.FINEST)) {
-            LOGGER.log(Level.FINEST, "Applying constraint: {0} for frame {1}", new Object[] { name, frame });
-        }
-        Transform targetTransform = targetOMA != null ? constraintHelper.getTransform(targetOMA, subtargetName, targetSpace) : null;
-        constraintDefinition.bake(ownerSpace, targetSpace, targetTransform, (float) ipo.calculateValue(frame));
-    }
-
-    /**
-     * @return determines if the definition of the constraint will change the bone in any way; in most cases
-     *         it is possible to tell that even before the constraint baking simulation is started, so we can discard such bones from constraint
-     *         computing to improve the computation speed and lower the computations complexity
-     */
-    public boolean isTrackToBeChanged() {
-        return constraintDefinition == null ? false : constraintDefinition.isTrackToBeChanged();
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (name == null ? 0 : name.hashCode());
-        result = prime * result + (ownerOMA == null ? 0 : ownerOMA.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (this.getClass() != obj.getClass()) {
-            return false;
-        }
-        Constraint other = (Constraint) obj;
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (ownerOMA == null) {
-            if (other.ownerOMA != null) {
-                return false;
-            }
-        } else if (!ownerOMA.equals(other.ownerOMA)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return "Constraint(name = " + name + ", def = " + constraintDefinition + ")";
-    }
-}

+ 0 - 476
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java

@@ -1,476 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Logger;
-
-import com.jme3.animation.Bone;
-import com.jme3.animation.Skeleton;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.AnimationHelper;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.animations.Ipo;
-import com.jme3.scene.plugins.blender.file.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;
-import com.jme3.util.TempVars;
-
-/**
- * This class should be used for constraint calculations.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class ConstraintHelper extends AbstractBlenderHelper {
-    private static final Logger     LOGGER                      = Logger.getLogger(ConstraintHelper.class.getName());
-
-    /**
-     * Helper constructor.
-     * 
-     * @param blenderVersion
-     *            the version read from the blend file
-     * @param blenderContext
-     *            the blender context
-     */
-    public ConstraintHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * This method reads constraints for for the given structure. The
-     * constraints are loaded only once for object/bone.
-     * 
-     * @param objectStructure
-     *            the structure we read constraint's for
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     */
-    public void loadConstraints(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.fine("Loading constraints.");
-        // reading influence ipos for the constraints
-        AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.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();
-            for (Structure action : actions) {
-                Structure chanbase = (Structure) action.getFieldValue("chanbase");
-                List<Structure> actionChannels = chanbase.evaluateListBase();
-                for (Structure actionChannel : actionChannels) {
-                    Map<String, Ipo> ipos = new HashMap<String, Ipo>();
-                    Structure constChannels = (Structure) actionChannel.getFieldValue("constraintChannels");
-                    List<Structure> constraintChannels = constChannels.evaluateListBase();
-                    for (Structure constraintChannel : constraintChannels) {
-                        Pointer pIpo = (Pointer) constraintChannel.getFieldValue("ipo");
-                        if (pIpo.isNotNull()) {
-                            String constraintName = constraintChannel.getFieldValue("name").toString();
-                            Ipo ipo = animationHelper.fromIpoStructure(pIpo.fetchData().get(0), blenderContext);
-                            ipos.put(constraintName, ipo);
-                        }
-                    }
-                    String actionName = actionChannel.getFieldValue("name").toString();
-                    constraintsIpos.put(actionName, ipos);
-                }
-            }
-        }
-
-        // loading constraints connected with the object's bones
-        Pointer pPose = (Pointer) objectStructure.getFieldValue("pose");
-        if (pPose.isNotNull()) {
-            List<Structure> poseChannels = ((Structure) pPose.fetchData().get(0).getFieldValue("chanbase")).evaluateListBase();
-            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 = blenderContext.getFileBlock(boneOMA).getStructure(blenderContext).getFieldValue("name").toString();
-                List<Structure> constraints = ((Structure) poseChannel.getFieldValue("constraints")).evaluateListBase();
-                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 = animationHelper.fromValue(enforce);
-                    }
-                    constraintsList.add(new BoneConstraint(constraint, boneOMA, ipo, blenderContext));
-                }
-                blenderContext.addConstraints(boneOMA, constraintsList);
-            }
-        }
-
-        // loading constraints connected with the object itself
-        List<Structure> constraints = ((Structure) objectStructure.getFieldValue("constraints")).evaluateListBase();
-        if (constraints != null && constraints.size() > 0) {
-            Pointer pData = (Pointer) objectStructure.getFieldValue("data");
-            String dataType = pData.isNotNull() ? pData.fetchData().get(0).getType() : null;
-            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 = animationHelper.fromValue(enforce);
-                }
-
-                constraintsList.add(this.createConstraint(dataType, constraint, objectStructure.getOldMemoryAddress(), ipo, blenderContext));
-            }
-            blenderContext.addConstraints(objectStructure.getOldMemoryAddress(), constraintsList);
-        }
-    }
-
-    /**
-     * This method creates a proper constraint object depending on the object's
-     * data type. Supported data types: <li>Mesh <li>Armature <li>Camera <li>
-     * Lamp Bone constraints are created in a different place.
-     * 
-     * @param dataType
-     *            the type of the object's data
-     * @param constraintStructure
-     *            the constraint structure
-     * @param ownerOMA
-     *            the owner OMA
-     * @param influenceIpo
-     *            the influence interpolation curve
-     * @param blenderContext
-     *            the blender context
-     * @return constraint object for the required type
-     * @throws BlenderFileException
-     *             thrown when problems with blender file occurred
-     */
-    private Constraint createConstraint(String dataType, Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
-        if (dataType == null || "Mesh".equalsIgnoreCase(dataType) || "Camera".equalsIgnoreCase(dataType) || "Lamp".equalsIgnoreCase(dataType)) {
-            return new SpatialConstraint(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-        } else if ("Armature".equalsIgnoreCase(dataType)) {
-            return new SkeletonConstraint(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-        } else {
-            throw new IllegalArgumentException("Unsupported data type for applying constraints: " + dataType);
-        }
-    }
-
-    /**
-     * The method bakes all available and valid constraints.
-     * 
-     * @param blenderContext
-     *            the blender context
-     */
-    public void bakeConstraints(BlenderContext blenderContext) {
-        Set<Long> owners = new HashSet<Long>();
-        for (Constraint constraint : blenderContext.getAllConstraints()) {
-            if(constraint instanceof BoneConstraint) {
-                BoneContext boneContext = blenderContext.getBoneContext(constraint.ownerOMA);
-                owners.add(boneContext.getArmatureObjectOMA());
-            } else {
-                Spatial spatial = (Spatial) blenderContext.getLoadedFeature(constraint.ownerOMA, LoadedDataType.FEATURE);
-                while (spatial.getParent() != null) {
-                    spatial = spatial.getParent();
-                }
-                owners.add((Long)blenderContext.getMarkerValue(ObjectHelper.OMA_MARKER, spatial));
-            }
-        }
-        
-        List<SimulationNode> simulationRootNodes = new ArrayList<SimulationNode>(owners.size());
-        for(Long ownerOMA : owners) {
-            simulationRootNodes.add(new SimulationNode(ownerOMA, blenderContext));
-        }
-
-        for (SimulationNode node : simulationRootNodes) {
-            node.simulate();
-        }
-    }
-
-    /**
-     * The method retrieves the transform from a feature in a given space.
-     * 
-     * @param oma
-     *            the OMA of the feature (spatial or armature node)
-     * @param subtargetName
-     *            the feature's subtarget (bone in a case of armature's node)
-     * @param space
-     *            the space the transform is evaluated to
-     * @return the transform of a feature in a given space
-     */
-    public Transform getTransform(Long oma, String subtargetName, Space space) {
-        Spatial feature = (Spatial) blenderContext.getLoadedFeature(oma, LoadedDataType.FEATURE);
-        boolean isArmature = blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, feature) != null;
-        if (isArmature) {
-            blenderContext.getSkeleton(oma).updateWorldVectors();
-            BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName);
-            Bone bone = targetBoneContext.getBone();
-
-            if (bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) {
-                space = Space.CONSTRAINT_SPACE_POSE;
-            }
-
-            TempVars tempVars = TempVars.get();// use readable names of the matrices so that the code is more clear
-            Transform result;
-            switch (space) {
-                case CONSTRAINT_SPACE_WORLD:
-                    Spatial model = (Spatial) blenderContext.getLoadedFeature(targetBoneContext.getSkeletonOwnerOma(), LoadedDataType.FEATURE);
-                    Matrix4f boneModelMatrix = this.toMatrix(bone.getModelSpacePosition(), bone.getModelSpaceRotation(), bone.getModelSpaceScale(), tempVars.tempMat4);
-                    Matrix4f modelWorldMatrix = this.toMatrix(model.getWorldTransform(), tempVars.tempMat42);
-                    Matrix4f boneMatrixInWorldSpace = modelWorldMatrix.multLocal(boneModelMatrix);
-                    result = new Transform(boneMatrixInWorldSpace.toTranslationVector(), boneMatrixInWorldSpace.toRotationQuat(), boneMatrixInWorldSpace.toScaleVector());
-                    break;
-                case CONSTRAINT_SPACE_LOCAL:
-                    assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!";
-                    result = new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale());
-                    break;
-                case CONSTRAINT_SPACE_POSE: {
-                    Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
-                    Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
-                    Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
-                    result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
-                    break;
-                }
-                case CONSTRAINT_SPACE_PARLOCAL: {
-                    Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
-                    Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
-                    Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
-                    result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
-                    Bone parent = bone.getParent();
-                    if(parent != null) {
-                        BoneContext parentContext = blenderContext.getBoneContext(parent);
-                        Vector3f head = parent.getModelSpacePosition();
-                        Vector3f tail = head.add(bone.getModelSpaceRotation().mult(Vector3f.UNIT_Y.mult(parentContext.getLength())));
-                        result.getTranslation().subtractLocal(tail);
-                        
-                    }
-                    break;
-                }
-                default:
-                    throw new IllegalStateException("Unknown space type: " + space);
-            }
-            tempVars.release();
-            return result;
-        } else {
-            switch (space) {
-                case CONSTRAINT_SPACE_LOCAL:
-                    return feature.getLocalTransform();
-                case CONSTRAINT_SPACE_WORLD:
-                    return feature.getWorldTransform();
-                case CONSTRAINT_SPACE_PARLOCAL:
-                case CONSTRAINT_SPACE_POSE:
-                    throw new IllegalStateException("Nodes can have only Local and World spaces applied!");
-                default:
-                    throw new IllegalStateException("Unknown space type: " + space);
-            }
-        }
-    }
-
-    /**
-     * Applies transform to a feature (bone or spatial). Computations transform
-     * the given transformation from the given space to the feature's local
-     * space.
-     * 
-     * @param oma
-     *            the OMA of the feature we apply transformation to
-     * @param subtargetName
-     *            the name of the feature's subtarget (bone in case of armature)
-     * @param space
-     *            the space in which the given transform is to be applied
-     * @param transform
-     *            the transform we apply
-     */
-    public void applyTransform(Long oma, String subtargetName, Space space, Transform transform) {
-        Spatial feature = (Spatial) blenderContext.getLoadedFeature(oma, LoadedDataType.FEATURE);
-        boolean isArmature = blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, feature) != null;
-        if (isArmature) {
-            Skeleton skeleton = blenderContext.getSkeleton(oma);
-            BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName);
-            Bone bone = targetBoneContext.getBone();
-
-            if (bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) {
-                space = Space.CONSTRAINT_SPACE_POSE;
-            }
-
-            TempVars tempVars = TempVars.get();
-            switch (space) {
-                case CONSTRAINT_SPACE_LOCAL:
-                    assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!";
-                    bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
-                    break;
-                case CONSTRAINT_SPACE_WORLD: {
-                    Matrix4f boneMatrixInWorldSpace = this.toMatrix(transform, tempVars.tempMat4);
-                    Matrix4f modelWorldMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42);
-                    Matrix4f boneMatrixInModelSpace = modelWorldMatrix.invertLocal().multLocal(boneMatrixInWorldSpace);
-                    Bone parent = bone.getParent();
-                    if (parent != null) {
-                        Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
-                        boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
-                    }
-                    bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
-                    break;
-                }
-                case CONSTRAINT_SPACE_POSE: {
-                    Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
-                    Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
-                    Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
-                    Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
-                    Bone parent = bone.getParent();
-                    if (parent != null) {
-                        Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
-                        boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
-                    }
-                    bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
-                    break;
-                }
-                case CONSTRAINT_SPACE_PARLOCAL:
-                    Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
-                    Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
-                    Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
-                    Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
-                    Bone parent = bone.getParent();
-                    if (parent != null) {
-                        //first add the initial parent matrix to the bone's model matrix
-                        BoneContext parentContext = blenderContext.getBoneContext(parent);
-
-                        Matrix4f initialParentMatrixInModelSpace = parentContext.getBoneMatrixInModelSpace();
-                        Matrix4f currentParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
-                        //the bone will now move with its parent in model space
-
-                        //now we need to subtract the difference between current parent's model matrix and its initial model matrix
-                        boneMatrixInModelSpace = initialParentMatrixInModelSpace.mult(boneMatrixInModelSpace);
-
-                        Matrix4f diffMatrix = initialParentMatrixInModelSpace.mult(currentParentMatrixInModelSpace.invert());
-                        boneMatrixInModelSpace.multLocal(diffMatrix);
-                        //now the bone will have its position in model space with initial parent's model matrix added
-                    }
-                    bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
-                    break;
-                default:
-                    tempVars.release();
-                    throw new IllegalStateException("Invalid space type for target object: " + space.toString());
-            }
-            tempVars.release();
-            skeleton.updateWorldVectors();
-        } else {
-            switch (space) {
-                case CONSTRAINT_SPACE_LOCAL:
-                    feature.getLocalTransform().set(transform);
-                    break;
-                case CONSTRAINT_SPACE_WORLD:
-                    if (feature.getParent() == null) {
-                        feature.setLocalTransform(transform);
-                    } else {
-                        Transform parentWorldTransform = feature.getParent().getWorldTransform();
-
-                        TempVars tempVars = TempVars.get();
-                        Matrix4f parentInverseMatrix = this.toMatrix(parentWorldTransform, tempVars.tempMat4).invertLocal();
-                        Matrix4f m = this.toMatrix(transform, tempVars.tempMat42);
-                        m = m.multLocal(parentInverseMatrix);
-                        tempVars.release();
-
-                        transform.setTranslation(m.toTranslationVector());
-                        transform.setRotation(m.toRotationQuat());
-                        transform.setScale(m.toScaleVector());
-
-                        feature.setLocalTransform(transform);
-                    }
-                    break;
-                default:
-                    throw new IllegalStateException("Invalid space type for spatial object: " + space.toString());
-            }
-        }
-    }
-
-    /**
-     * Converts given transform to the matrix.
-     * 
-     * @param transform
-     *            the transform to be converted
-     * @param store
-     *            the matrix where the result will be stored
-     * @return the store matrix
-     */
-    public Matrix4f toMatrix(Transform transform, Matrix4f store) {
-        if (transform != null) {
-            return this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale(), store);
-        }
-        store.loadIdentity();
-        return store;
-    }
-
-    /**
-     * Converts given transformation parameters into the matrix.
-     * 
-     * @param position
-     *            the position of the feature
-     * @param rotation
-     *            the rotation of the feature
-     * @param scale
-     *            the scale of the feature
-     * @param store
-     *            the matrix where the result will be stored
-     * @return the store matrix
-     */
-    private Matrix4f toMatrix(Vector3f position, Quaternion rotation, Vector3f scale, Matrix4f store) {
-        store.loadIdentity();
-        store.setTranslation(position);
-        store.setRotationQuaternion(rotation);
-        store.setScale(scale);
-        return store;
-    }
-
-    /**
-     * The space of target or owner transformation.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum Space {
-        /** A transformation of the bone or spatial in the world space. */
-        CONSTRAINT_SPACE_WORLD,
-        /**
-         * For spatial it is the transformation in its parent space or in WORLD space if it has no parent.
-         * For bone it is a transformation in its bone parent space or in armature space if it has no parent.
-         */
-        CONSTRAINT_SPACE_LOCAL,
-        /**
-         * This space IS NOT applicable for spatials.
-         * For bone it is a transformation in the blender's armature object space.
-         */
-        CONSTRAINT_SPACE_POSE,
-
-        CONSTRAINT_SPACE_PARLOCAL;
-
-        /**
-         * 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:
-                    throw new IllegalArgumentException("Value: " + c + " cannot be converted to Space enum instance!");
-            }
-        }
-    }
-}

+ 0 - 397
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SimulationNode.java

@@ -1,397 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-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.Stack;
-import java.util.logging.Logger;
-
-import com.jme3.animation.AnimChannel;
-import com.jme3.animation.AnimControl;
-import com.jme3.animation.Animation;
-import com.jme3.animation.Bone;
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.Skeleton;
-import com.jme3.animation.SpatialTrack;
-import com.jme3.animation.Track;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.objects.ObjectHelper;
-import com.jme3.util.TempVars;
-
-/**
- * A node that represents either spatial or bone in constraint simulation. The
- * node is applied its translation, rotation and scale for each frame of its
- * animation. Then the constraints are applied that will eventually alter it.
- * After that the feature's transformation is stored in VirtualTrack which is
- * converted to new bone or spatial track at the very end.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class SimulationNode {
-    private static final Logger LOGGER = Logger.getLogger(SimulationNode.class.getName());
-
-    private Long                 featureOMA;
-    /** The blender context. */
-    private BlenderContext       blenderContext;
-    /** The name of the node (for debugging purposes). */
-    private String               name;
-    /** A list of children for the node (either bones or child spatials). */
-    private List<SimulationNode> children = new ArrayList<SimulationNode>();
-    /** A list of node's animations. */
-    private List<Animation>      animations;
-
-    /** The nodes spatial (if null then the boneContext should be set). */
-    private Spatial     spatial;
-    /** The skeleton of the bone (not null if the node simulated the bone). */
-    private Skeleton    skeleton;
-    /** Animation controller for the node's feature. */
-    private AnimControl animControl;
-
-    /**
-     * The star transform of a spatial. Needed to properly reset the spatial to
-     * its start position.
-     */
-    private Transform            spatialStartTransform;
-    /** Star transformations for bones. Needed to properly reset the bones. */
-    private Map<Bone, Transform> boneStartTransforms;
-
-    /**
-     * Builds the nodes tree for the given feature. The feature (bone or
-     * spatial) is found by its OMA. The feature must be a root bone or a root
-     * spatial.
-     * 
-     * @param featureOMA
-     *            the OMA of either bone or spatial
-     * @param blenderContext
-     *            the blender context
-     */
-    public SimulationNode(Long featureOMA, BlenderContext blenderContext) {
-        this(featureOMA, blenderContext, true);
-    }
-
-    /**
-     * Creates the node for the feature.
-     * 
-     * @param featureOMA
-     *            the OMA of either bone or spatial
-     * @param blenderContext
-     *            the blender context
-     * @param rootNode
-     *            indicates if the feature is a root bone or root spatial or not
-     */
-    private SimulationNode(Long featureOMA, BlenderContext blenderContext, boolean rootNode) {
-        this.featureOMA = featureOMA;
-        this.blenderContext = blenderContext;
-        Node spatial = (Node) blenderContext.getLoadedFeature(featureOMA, LoadedDataType.FEATURE);
-        if (blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, spatial) != null) {
-            skeleton = blenderContext.getSkeleton(featureOMA);
-
-            Node nodeWithAnimationControl = blenderContext.getControlledNode(skeleton);
-            animControl = nodeWithAnimationControl.getControl(AnimControl.class);
-
-            boneStartTransforms = new HashMap<Bone, Transform>();
-            for (int i = 0; i < skeleton.getBoneCount(); ++i) {
-                Bone bone = skeleton.getBone(i);
-                boneStartTransforms.put(bone, new Transform(bone.getBindPosition(), bone.getBindRotation(), bone.getBindScale()));
-            }
-        } else {
-            if (rootNode && spatial.getParent() != null) {
-                throw new IllegalStateException("Given spatial must be a root node!");
-            }
-            this.spatial = spatial;
-            spatialStartTransform = spatial.getLocalTransform().clone();
-        }
-
-        name = '>' + spatial.getName() + '<';
-
-        // add children nodes
-        if (skeleton != null) {
-            Node node = blenderContext.getControlledNode(skeleton);
-            Long animatedNodeOMA = ((Number) blenderContext.getMarkerValue(ObjectHelper.OMA_MARKER, node)).longValue();
-            animations = blenderContext.getAnimations(animatedNodeOMA);
-        } else {
-            animations = blenderContext.getAnimations(featureOMA);
-            for (Spatial child : spatial.getChildren()) {
-                if (child instanceof Node) {
-                    children.add(new SimulationNode((Long) blenderContext.getMarkerValue(ObjectHelper.OMA_MARKER, child), blenderContext, false));
-                }
-            }
-        }
-    }
-
-    /**
-     * Resets the node's feature to its starting transformation.
-     */
-    private void reset() {
-        if (spatial != null) {
-            spatial.setLocalTransform(spatialStartTransform);
-            for (SimulationNode child : children) {
-                child.reset();
-            }
-        } else if (skeleton != null) {
-            for (Entry<Bone, Transform> entry : boneStartTransforms.entrySet()) {
-                Transform t = entry.getValue();
-                entry.getKey().setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale());
-                entry.getKey().updateModelTransforms();
-            }
-            skeleton.reset();
-        }
-    }
-
-    /**
-     * Simulates the spatial node.
-     */
-    private void simulateSpatial() {
-        List<Constraint> constraints = blenderContext.getConstraints(featureOMA);
-        if (constraints != null && constraints.size() > 0) {
-            LOGGER.fine("Simulating spatial.");
-            boolean applyStaticConstraints = true;
-            if (animations != null) {
-                for (Animation animation : animations) {
-                    float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation);
-                    int maxFrame = (int) animationTimeBoundaries[0];
-                    float maxTime = animationTimeBoundaries[1];
-
-                    VirtualTrack vTrack = new VirtualTrack(spatial.getName(), maxFrame, maxTime);
-                    for (Track track : animation.getTracks()) {
-                        for (int frame = 0; frame < maxFrame; ++frame) {
-                            spatial.setLocalTranslation(((SpatialTrack) track).getTranslations()[frame]);
-                            spatial.setLocalRotation(((SpatialTrack) track).getRotations()[frame]);
-                            spatial.setLocalScale(((SpatialTrack) track).getScales()[frame]);
-
-                            for (Constraint constraint : constraints) {
-                                constraint.apply(frame);
-                                vTrack.setTransform(frame, spatial.getLocalTransform());
-                            }
-                        }
-                        Track newTrack = vTrack.getAsSpatialTrack();
-                        if (newTrack != null) {
-                            animation.removeTrack(track);
-                            animation.addTrack(newTrack);
-                        }
-                        applyStaticConstraints = false;
-                    }
-                }
-            }
-
-            // if there are no animations then just constraint the static
-            // object's transformation
-            if (applyStaticConstraints) {
-                for (Constraint constraint : constraints) {
-                    constraint.apply(0);
-                }
-            }
-        }
-
-        for (SimulationNode child : children) {
-            child.simulate();
-        }
-    }
-
-    /**
-     * Simulates the bone node.
-     */
-    private void simulateSkeleton() {
-        LOGGER.fine("Simulating skeleton.");
-        Set<Long> alteredOmas = new HashSet<Long>();
-
-        if (animations != null) {
-            TempVars vars = TempVars.get();
-            AnimChannel animChannel = animControl.createChannel();
-
-            for (Animation animation : animations) {
-                float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation);
-                int maxFrame = (int) animationTimeBoundaries[0];
-                float maxTime = animationTimeBoundaries[1];
-
-                Map<Integer, VirtualTrack> tracks = new HashMap<Integer, VirtualTrack>();
-                for (int frame = 0; frame < maxFrame; ++frame) {
-                    // this MUST be done here, otherwise setting next frame of animation will
-                    // lead to possible errors
-                    this.reset();
-
-                    // first set proper time for all bones in all the tracks ...
-                    for (Track track : animation.getTracks()) {
-                        float time = ((BoneTrack) track).getTimes()[frame];
-                        track.setTime(time, 1, animControl, animChannel, vars);
-                        skeleton.updateWorldVectors();
-                    }
-
-                    // ... and then apply constraints from the root bone to the last child ...
-                    Set<Long> applied = new HashSet<Long>();
-                    for (Bone rootBone : skeleton.getRoots()) {
-                        // ignore the 0-indexed bone
-                        if (skeleton.getBoneIndex(rootBone) > 0) {
-                            this.applyConstraints(rootBone, alteredOmas, applied, frame, new Stack<Bone>());
-                        }
-                    }
-
-                    // ... add virtual tracks if necessary, for bones that were altered but had no tracks before ...
-                    for (Long boneOMA : alteredOmas) {
-                        BoneContext boneContext = blenderContext.getBoneContext(boneOMA);
-                        int boneIndex = skeleton.getBoneIndex(boneContext.getBone());
-                        if (!tracks.containsKey(boneIndex)) {
-                            tracks.put(boneIndex, new VirtualTrack(boneContext.getBone().getName(), maxFrame, maxTime));
-                        }
-                    }
-                    alteredOmas.clear();
-
-                    // ... and fill in another frame in the result track
-                    for (Entry<Integer, VirtualTrack> trackEntry : tracks.entrySet()) {
-                        Bone bone = skeleton.getBone(trackEntry.getKey());
-                        Transform startTransform = boneStartTransforms.get(bone);
-
-                        // track contains differences between the frame position and bind positions of bones/spatials
-                        Vector3f bonePositionDifference = bone.getLocalPosition().subtract(startTransform.getTranslation());
-                        Quaternion boneRotationDifference = startTransform.getRotation().inverse().mult(bone.getLocalRotation()).normalizeLocal();
-                        Vector3f boneScaleDifference = bone.getLocalScale().divide(startTransform.getScale());
-
-                        trackEntry.getValue().setTransform(frame, new Transform(bonePositionDifference, boneRotationDifference, boneScaleDifference));
-                    }
-                }
-
-                for (Entry<Integer, VirtualTrack> trackEntry : tracks.entrySet()) {
-                    Track newTrack = trackEntry.getValue().getAsBoneTrack(trackEntry.getKey());
-                    if (newTrack != null) {
-                        boolean trackReplaced = false;
-                        for (Track track : animation.getTracks()) {
-                            if (((BoneTrack) track).getTargetBoneIndex() == trackEntry.getKey().intValue()) {
-                                animation.removeTrack(track);
-                                animation.addTrack(newTrack);
-                                trackReplaced = true;
-                                break;
-                            }
-                        }
-                        if (!trackReplaced) {
-                            animation.addTrack(newTrack);
-                        }
-                    }
-                }
-            }
-            vars.release();
-            animControl.clearChannels();
-            this.reset();
-        }
-    }
-
-    /**
-     * Applies constraints to the given bone and its children.
-     * The goal is to apply constraint from root bone to the last child.
-     * @param bone
-     *            the bone whose constraints will be applied
-     * @param alteredOmas
-     *            the set of OMAS of the altered bones (is populated if necessary)
-     * @param frame
-     *            the current frame of the animation
-     * @param bonesStack
-     *            the stack of bones used to avoid infinite loops while applying constraints
-     */
-    private void applyConstraints(Bone bone, Set<Long> alteredOmas, Set<Long> applied, int frame, Stack<Bone> bonesStack) {
-        if (!bonesStack.contains(bone)) {
-            bonesStack.push(bone);
-            BoneContext boneContext = blenderContext.getBoneContext(bone);
-            if (!applied.contains(boneContext.getBoneOma())) {
-                List<Constraint> constraints = this.findConstraints(boneContext.getBoneOma(), blenderContext);
-                if (constraints != null && constraints.size() > 0) {
-                    for (Constraint constraint : constraints) {
-                        if (constraint.getTargetOMA() != null && constraint.getTargetOMA() > 0L) {
-                            // first apply constraints of the target bone
-                            BoneContext targetBone = blenderContext.getBoneContext(constraint.getTargetOMA());
-                            this.applyConstraints(targetBone.getBone(), alteredOmas, applied, frame, bonesStack);
-                        }
-                        constraint.apply(frame);
-                        if (constraint.getAlteredOmas() != null) {
-                            alteredOmas.addAll(constraint.getAlteredOmas());
-                        }
-                        alteredOmas.add(boneContext.getBoneOma());
-                    }
-                }
-                applied.add(boneContext.getBoneOma());
-            }
-
-            List<Bone> children = bone.getChildren();
-            if (children != null && children.size() > 0) {
-                for (Bone child : bone.getChildren()) {
-                    this.applyConstraints(child, alteredOmas, applied, frame, bonesStack);
-                }
-            }
-            bonesStack.pop();
-        }
-    }
-
-    /**
-     * Simulates the node.
-     */
-    public void simulate() {
-        this.reset();
-        if (spatial != null) {
-            this.simulateSpatial();
-        } else {
-            this.simulateSkeleton();
-        }
-    }
-
-    /**
-     * Computes the maximum frame and time for the animation. Different tracks
-     * can have different lengths so here the maximum one is being found.
-     * 
-     * @param animation
-     *            the animation
-     * @return maximum frame and time of the animation
-     */
-    private float[] computeAnimationTimeBoundaries(Animation animation) {
-        int maxFrame = Integer.MIN_VALUE;
-        float maxTime = -Float.MAX_VALUE;
-        for (Track track : animation.getTracks()) {
-            if (track instanceof BoneTrack) {
-                maxFrame = Math.max(maxFrame, ((BoneTrack) track).getTranslations().length);
-                maxTime = Math.max(maxTime, ((BoneTrack) track).getTimes()[((BoneTrack) track).getTimes().length - 1]);
-            } else if (track instanceof SpatialTrack) {
-                maxFrame = Math.max(maxFrame, ((SpatialTrack) track).getTranslations().length);
-                maxTime = Math.max(maxTime, ((SpatialTrack) track).getTimes()[((SpatialTrack) track).getTimes().length - 1]);
-            } else {
-                throw new IllegalStateException("Unsupported track type for simuation: " + track);
-            }
-        }
-        return new float[] { maxFrame, maxTime };
-    }
-
-    /**
-     * Finds constraints for the node's features.
-     * 
-     * @param ownerOMA
-     *            the feature's OMA
-     * @param blenderContext
-     *            the blender context
-     * @return a list of feature's constraints or empty list if none were found
-     */
-    private List<Constraint> findConstraints(Long ownerOMA, BlenderContext blenderContext) {
-        List<Constraint> result = new ArrayList<Constraint>();
-        List<Constraint> constraints = blenderContext.getConstraints(ownerOMA);
-        if (constraints != null) {
-            for (Constraint constraint : constraints) {
-                if (constraint.isImplemented() && constraint.validate() && constraint.isTrackToBeChanged()) {
-                    result.add(constraint);
-                }
-                // TODO: add proper warnings to some map or set so that they are not logged on every frame
-            }
-        }
-        return result.size() > 0 ? result : null;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-}

+ 0 - 41
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SkeletonConstraint.java

@@ -1,41 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.Ipo;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * Constraint applied on the skeleton. This constraint is here only to make the
- * application not crash when loads constraints applied to armature. But
- * skeleton movement is not supported by jme so the constraint will never be
- * applied.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class SkeletonConstraint extends Constraint {
-    private static final Logger LOGGER = Logger.getLogger(SkeletonConstraint.class.getName());
-
-    public SkeletonConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
-        super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-    }
-
-    @Override
-    public boolean validate() {
-        LOGGER.warning("Constraints for skeleton are not supported.");
-        return false;
-    }
-
-    @Override
-    public void apply(int frame) {
-        LOGGER.warning("Applying constraints to skeleton is not supported.");
-    }
-    
-    @Override
-    public Long getTargetOMA() {
-        LOGGER.warning("Constraints for skeleton are not supported.");
-        return null;
-    }
-}

+ 0 - 32
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SpatialConstraint.java

@@ -1,32 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.Ipo;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * Constraint applied on the spatial objects. This includes: nodes, cameras
- * nodes and light nodes.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class SpatialConstraint extends Constraint {
-    public SpatialConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
-        super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-    }
-
-    @Override
-    public boolean validate() {
-        if (targetOMA != null) {
-            return blenderContext.getLoadedFeature(targetOMA, LoadedDataType.FEATURE) != null;
-        }
-        return constraintDefinition == null ? true : constraintDefinition.isTargetRequired();
-    }
-    
-    @Override
-    public Long getTargetOMA() {
-        return targetOMA;
-    }
-}

+ 0 - 165
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/VirtualTrack.java

@@ -1,165 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints;
-
-import java.util.ArrayList;
-
-import com.jme3.animation.BoneTrack;
-import com.jme3.animation.SpatialTrack;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-
-/**
- * A virtual track that stores computed frames after constraints are applied.
- * Not all the frames need to be inserted. If there are lacks then the class
- * will fill the gaps.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class VirtualTrack {
-    /** The name of the track (for debugging purposes). */
-    private String               name;
-    /** The last frame for the track. */
-    public int                   maxFrame;
-    /** The max time for the track. */
-    public float                 maxTime;
-    /** Translations of the track. */
-    public ArrayList<Vector3f>   translations;
-    /** Rotations of the track. */
-    public ArrayList<Quaternion> rotations;
-    /** Scales of the track. */
-    public ArrayList<Vector3f>   scales;
-
-    /**
-     * Constructs the object storing the maximum frame and time.
-     * 
-     * @param maxFrame
-     *            the last frame for the track
-     * @param maxTime
-     *            the max time for the track
-     */
-    public VirtualTrack(String name, int maxFrame, float maxTime) {
-        this.name = name;
-        this.maxFrame = maxFrame;
-        this.maxTime = maxTime;
-    }
-
-    /**
-     * Sets the transform for the given frame.
-     * 
-     * @param frameIndex
-     *            the frame for which the transform will be set
-     * @param transform
-     *            the transformation to be set
-     */
-    public void setTransform(int frameIndex, Transform transform) {
-        if (translations == null) {
-            translations = this.createList(Vector3f.ZERO, frameIndex);
-        }
-        this.append(translations, Vector3f.ZERO, frameIndex - translations.size());
-        translations.add(transform.getTranslation().clone());
-
-        if (rotations == null) {
-            rotations = this.createList(Quaternion.IDENTITY, frameIndex);
-        }
-        this.append(rotations, Quaternion.IDENTITY, frameIndex - rotations.size());
-        rotations.add(transform.getRotation().clone());
-
-        if (scales == null) {
-            scales = this.createList(Vector3f.UNIT_XYZ, frameIndex);
-        }
-        this.append(scales, Vector3f.UNIT_XYZ, frameIndex - scales.size());
-        scales.add(transform.getScale().clone());
-    }
-
-    /**
-     * Returns the track as a bone track.
-     * 
-     * @param targetBoneIndex
-     *            the bone index
-     * @return the bone track
-     */
-    public BoneTrack getAsBoneTrack(int targetBoneIndex) {
-        if (translations == null && rotations == null && scales == null) {
-            return null;
-        }
-        return new BoneTrack(targetBoneIndex, this.createTimes(), translations.toArray(new Vector3f[maxFrame]), rotations.toArray(new Quaternion[maxFrame]), scales.toArray(new Vector3f[maxFrame]));
-    }
-
-    /**
-     * Returns the track as a spatial track.
-     * 
-     * @return the spatial track
-     */
-    public SpatialTrack getAsSpatialTrack() {
-        if (translations == null && rotations == null && scales == null) {
-            return null;
-        }
-        return new SpatialTrack(this.createTimes(), translations.toArray(new Vector3f[maxFrame]), rotations.toArray(new Quaternion[maxFrame]), scales.toArray(new Vector3f[maxFrame]));
-    }
-
-    /**
-     * The method creates times for the track based on the given maximum values.
-     * 
-     * @return the times for the track
-     */
-    private float[] createTimes() {
-        float[] times = new float[maxFrame];
-        float dT = maxTime / maxFrame;
-        float t = 0;
-        for (int i = 0; i < maxFrame; ++i) {
-            times[i] = t;
-            t += dT;
-        }
-        return times;
-    }
-
-    /**
-     * Helper method that creates a list of a given size filled with given
-     * elements.
-     * 
-     * @param element
-     *            the element to be put into the list
-     * @param count
-     *            the list size
-     * @return the list
-     */
-    private <T> ArrayList<T> createList(T element, int count) {
-        ArrayList<T> result = new ArrayList<T>(count);
-        for (int i = 0; i < count; ++i) {
-            result.add(element);
-        }
-        return result;
-    }
-
-    /**
-     * Appends the element to the given list.
-     * 
-     * @param list
-     *            the list where the element will be appended
-     * @param element
-     *            the element to be appended
-     * @param count
-     *            how many times the element will be appended
-     */
-    private <T> void append(ArrayList<T> list, T element, int count) {
-        for (int i = 0; i < count; ++i) {
-            list.add(element);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder(2048);
-        result.append("TRACK: ").append(name).append('\n');
-        if (translations != null && translations.size() > 0) {
-            result.append("TRANSLATIONS: ").append(translations.toString()).append('\n');
-        }
-        if (rotations != null && rotations.size() > 0) {
-            result.append("ROTATIONS:    ").append(rotations.toString()).append('\n');
-        }
-        if (scales != null && scales.size() > 0) {
-            result.append("SCALES:       ").append(scales.toString()).append('\n');
-        }
-        return result.toString();
-    }
-}

+ 0 - 162
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java

@@ -1,162 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import java.util.Set;
-
-import com.jme3.animation.Bone;
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * A base class for all constraint definitions.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public abstract class ConstraintDefinition {
-    protected ConstraintHelper constraintHelper;
-    /** Constraints flag. Used to load user's options applied to the constraint. */
-    protected int              flag;
-    /** The constraint's owner. Loaded during runtime. */
-    private Object             owner;
-    /** The blender context. */
-    protected BlenderContext   blenderContext;
-    /** The constraint's owner OMA. */
-    protected Long             ownerOMA;
-    /** Stores the OMA addresses of all features whose transform had been altered beside the constraint owner. */
-    protected Set<Long>        alteredOmas;
-    /** The variable that determines if the constraint will alter the track in any way. */
-    protected boolean          trackToBeChanged = true;
-    /** The name of the constraint. */
-    protected String           constraintName;
-
-    /**
-     * Loads a constraint definition based on the constraint definition
-     * structure.
-     * 
-     * @param constraintData
-     *            the constraint definition structure
-     * @param ownerOMA
-     *            the constraint's owner OMA
-     * @param blenderContext
-     *            the blender context
-     */
-    public ConstraintDefinition(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        if (constraintData != null) {// Null constraint has no data
-            Number flag = (Number) constraintData.getFieldValue("flag");
-            if (flag != null) {
-                this.flag = flag.intValue();
-            }
-        }
-        this.blenderContext = blenderContext;
-        constraintHelper = (ConstraintHelper) (blenderContext == null ? null : blenderContext.getHelper(ConstraintHelper.class));
-        this.ownerOMA = ownerOMA;
-    }
-    
-    public void setConstraintName(String constraintName) {
-        this.constraintName = constraintName;
-    }
-
-    /**
-     * @return determines if the definition of the constraint will change the bone in any way; in most cases
-     *         it is possible to tell that even before the constraint baking simulation is started, so we can discard such bones from constraint
-     *         computing to improve the computation speed and lower the computations complexity
-     */
-    public boolean isTrackToBeChanged() {
-        return trackToBeChanged;
-    }
-
-    /**
-     * @return determines if this constraint definition requires a defined target or not
-     */
-    public abstract boolean isTargetRequired();
-
-    /**
-     * This method is here because we have no guarantee that the owner is loaded
-     * when constraint is being created. So use it to get the owner when it is
-     * needed for computations.
-     * 
-     * @return the owner of the constraint or null if none is set
-     */
-    protected Object getOwner() {
-        if (ownerOMA != null && owner == null) {
-            owner = blenderContext.getLoadedFeature(ownerOMA, LoadedDataType.FEATURE);
-            if (owner == null) {
-                throw new IllegalStateException("Cannot load constraint's owner for constraint type: " + this.getClass().getName());
-            }
-        }
-        return owner;
-    }
-
-    /**
-     * The method gets the owner's transformation. The owner can be either bone or spatial.
-     * @param ownerSpace
-     *            the space in which the computed transformation is given
-     * @return the constraint owner's transformation
-     */
-    protected Transform getOwnerTransform(Space ownerSpace) {
-        if (this.getOwner() instanceof Bone) {
-            BoneContext boneContext = blenderContext.getBoneContext(ownerOMA);
-            return constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), ownerSpace);
-        }
-        return constraintHelper.getTransform(ownerOMA, null, ownerSpace);
-    }
-
-    /**
-     * The method applies the given transformation to the owner.
-     * @param ownerTransform
-     *            the transformation to apply to the owner
-     * @param ownerSpace
-     *            the space that defines which owner's transformation (ie. global, local, etc. will be set)
-     */
-    protected void applyOwnerTransform(Transform ownerTransform, Space ownerSpace) {
-        if (this.getOwner() instanceof Bone) {
-            BoneContext boneContext = blenderContext.getBoneContext(ownerOMA);
-            constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), ownerSpace, ownerTransform);
-        } else {
-            constraintHelper.applyTransform(ownerOMA, null, ownerSpace, ownerTransform);
-        }
-    }
-
-    /**
-     * @return <b>true</b> if the definition is implemented and <b>false</b>
-     *         otherwise
-     */
-    public boolean isImplemented() {
-        return true;
-    }
-
-    /**
-     * @return a list of all OMAs of the features that the constraint had altered beside its owner
-     */
-    public Set<Long> getAlteredOmas() {
-        return alteredOmas;
-    }
-
-    /**
-     * @return the type name of the constraint
-     */
-    public abstract String getConstraintTypeName();
-
-    /**
-     * Bakes the constraint for the current feature (bone or spatial) position.
-     * 
-     * @param ownerSpace
-     *            the space where owner transform will be evaluated in
-     * @param targetSpace
-     *            the space where target transform will be evaluated in
-     * @param targetTransform
-     *            the target transform used by some of the constraints
-     * @param influence
-     *            the influence of the constraint from range [0; 1]
-     */
-    public abstract void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence);
-
-    @Override
-    public String toString() {
-        return this.getConstraintTypeName();
-    }
-}

+ 0 - 84
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionDistLimit.java

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

+ 0 - 126
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java

@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.constraints.definitions;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-public class ConstraintDefinitionFactory {
-    private static final Map<String, Class<? extends ConstraintDefinition>> CONSTRAINT_CLASSES      = new HashMap<String, Class<? extends ConstraintDefinition>>();
-    static {
-        CONSTRAINT_CLASSES.put("bDistLimitConstraint", ConstraintDefinitionDistLimit.class);
-        CONSTRAINT_CLASSES.put("bLocateLikeConstraint", ConstraintDefinitionLocLike.class);
-        CONSTRAINT_CLASSES.put("bLocLimitConstraint", ConstraintDefinitionLocLimit.class);
-        CONSTRAINT_CLASSES.put("bNullConstraint", ConstraintDefinitionNull.class);
-        CONSTRAINT_CLASSES.put("bRotateLikeConstraint", ConstraintDefinitionRotLike.class);
-        CONSTRAINT_CLASSES.put("bRotLimitConstraint", ConstraintDefinitionRotLimit.class);
-        CONSTRAINT_CLASSES.put("bSizeLikeConstraint", ConstraintDefinitionSizeLike.class);
-        CONSTRAINT_CLASSES.put("bSizeLimitConstraint", ConstraintDefinitionSizeLimit.class);
-        CONSTRAINT_CLASSES.put("bKinematicConstraint", ConstraintDefinitionIK.class);
-        CONSTRAINT_CLASSES.put("bTransLikeConstraint", ConstraintDefinitionTransLike.class);// since blender 2.51
-        CONSTRAINT_CLASSES.put("bSameVolumeConstraint", ConstraintDefinitionMaintainVolume.class);// since blender 2.53
-    }
-
-    private static final Map<String, String>                                UNSUPPORTED_CONSTRAINTS = new HashMap<String, String>();
-    static {
-        UNSUPPORTED_CONSTRAINTS.put("bActionConstraint", "Action");
-        UNSUPPORTED_CONSTRAINTS.put("bChildOfConstraint", "Child of");
-        UNSUPPORTED_CONSTRAINTS.put("bClampToConstraint", "Clamp to");
-        UNSUPPORTED_CONSTRAINTS.put("bFollowPathConstraint", "Follow path");
-        UNSUPPORTED_CONSTRAINTS.put("bLockTrackConstraint", "Lock track");
-        UNSUPPORTED_CONSTRAINTS.put("bMinMaxConstraint", "Min max");
-        UNSUPPORTED_CONSTRAINTS.put("bPythonConstraint", "Python/Script");
-        UNSUPPORTED_CONSTRAINTS.put("bRigidBodyJointConstraint", "Rigid body joint");
-        UNSUPPORTED_CONSTRAINTS.put("bShrinkWrapConstraint", "Shrinkwrap");
-        UNSUPPORTED_CONSTRAINTS.put("bStretchToConstraint", "Stretch to");
-        UNSUPPORTED_CONSTRAINTS.put("bTransformConstraint", "Transform");
-        // Blender 2.50+
-        UNSUPPORTED_CONSTRAINTS.put("bSplineIKConstraint", "Spline inverse kinematics");
-        UNSUPPORTED_CONSTRAINTS.put("bDampTrackConstraint", "Damp track");
-        UNSUPPORTED_CONSTRAINTS.put("bPivotConstraint", "Pivot");
-        // Blender 2.56+
-        UNSUPPORTED_CONSTRAINTS.put("bTrackToConstraint", "Track to");
-        // Blender 2.62+
-        UNSUPPORTED_CONSTRAINTS.put("bCameraSolverConstraint", "Camera solver");
-        UNSUPPORTED_CONSTRAINTS.put("bObjectSolverConstraint", "Object solver");
-        UNSUPPORTED_CONSTRAINTS.put("bFollowTrackConstraint", "Follow track");
-    }
-
-    /**
-     * This method creates the constraint instance.
-     * 
-     * @param constraintStructure
-     *            the constraint's structure (bConstraint clss in blender 2.49).
-     *            If the value is null the NullConstraint is created.
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public static ConstraintDefinition createConstraintDefinition(Structure constraintStructure, String constraintName, Long ownerOMA, BlenderContext blenderContext) throws BlenderFileException {
-        if (constraintStructure == null) {
-            return new ConstraintDefinitionNull(null, ownerOMA, blenderContext);
-        }
-        String constraintClassName = constraintStructure.getType();
-        Class<? extends ConstraintDefinition> constraintDefinitionClass = CONSTRAINT_CLASSES.get(constraintClassName);
-        if (constraintDefinitionClass != null) {
-            try {
-                ConstraintDefinition def = (ConstraintDefinition) constraintDefinitionClass.getDeclaredConstructors()[0].newInstance(constraintStructure, ownerOMA, blenderContext);
-                def.setConstraintName(constraintName);
-                return def;
-            } catch (IllegalArgumentException e) {
-                throw new BlenderFileException(e.getLocalizedMessage(), e);
-            } catch (SecurityException e) {
-                throw new BlenderFileException(e.getLocalizedMessage(), e);
-            } catch (InstantiationException e) {
-                throw new BlenderFileException(e.getLocalizedMessage(), e);
-            } catch (IllegalAccessException e) {
-                throw new BlenderFileException(e.getLocalizedMessage(), e);
-            } catch (InvocationTargetException e) {
-                throw new BlenderFileException(e.getLocalizedMessage(), e);
-            }
-        } else {
-            String unsupportedConstraintClassName = UNSUPPORTED_CONSTRAINTS.get(constraintClassName);
-            if (unsupportedConstraintClassName != null) {
-                return new UnsupportedConstraintDefinition(unsupportedConstraintClassName);
-            } else {
-                throw new BlenderFileException("Unknown constraint type: " + constraintClassName);
-            }
-        }
-    }
-}

+ 0 - 236
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java

@@ -1,236 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
-import org.ejml.simple.SimpleMatrix;
-
-import com.jme3.animation.Bone;
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.math.DQuaternion;
-import com.jme3.scene.plugins.blender.math.DTransform;
-import com.jme3.scene.plugins.blender.math.Matrix;
-import com.jme3.scene.plugins.blender.math.Vector3d;
-
-/**
- * A definiotion of a Inverse Kinematics constraint. This implementation uses Jacobian pseudoinverse algorithm.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class ConstraintDefinitionIK extends ConstraintDefinition {
-    private static final float MIN_DISTANCE     = 0.001f;
-    private static final float MIN_ANGLE_CHANGE = 0.001f;
-    private static final int   FLAG_USE_TAIL    = 0x01;
-    private static final int   FLAG_POSITION    = 0x20;
-
-    private BonesChain bones;
-    /** The number of affected bones. Zero means that all parent bones of the current bone should take part in baking. */
-    private int        bonesAffected;
-    /** Indicates if the tail of the bone should be used or not. */
-    private boolean    useTail;
-    /** The amount of iterations of the algorithm. */
-    private int        iterations;
-    /** The count of bones' chain. */
-    private int        bonesCount = -1;
-
-    public ConstraintDefinitionIK(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        bonesAffected = ((Number) constraintData.getFieldValue("rootbone")).intValue();
-        iterations = ((Number) constraintData.getFieldValue("iterations")).intValue();
-        useTail = (flag & FLAG_USE_TAIL) != 0;
-
-        if ((flag & FLAG_POSITION) == 0) {
-            trackToBeChanged = false;
-        }
-
-        if (trackToBeChanged) {
-            alteredOmas = new HashSet<Long>();
-        }
-    }
-
-    /**
-     * Below are the variables that only need to be allocated once for IK constraint instance.
-     */
-    /** Temporal quaternion. */
-    private DQuaternion tempDQuaternion = new DQuaternion();
-    /** Temporal matrix column. */
-    private Vector3d    col             = new Vector3d();
-    /** Effector's position change. */
-    private Matrix      deltaP          = new Matrix(3, 1);
-    /** The current target position. */
-    private Vector3d    target          = new Vector3d();
-    /** Rotation vectors for each joint (allocated when we know the size of a bones' chain. */
-    private Vector3d[]  rotationVectors;
-    /** The Jacobian matrix. Allocated when the bones' chain size is known. */
-    private Matrix      J;
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || !trackToBeChanged || targetTransform == null || bonesCount == 0) {
-            return;// no need to do anything
-        }
-
-        if (bones == null) {
-            bones = new BonesChain((Bone) this.getOwner(), useTail, bonesAffected, alteredOmas, blenderContext);
-        }
-        if (bones.size() == 0) {
-            bonesCount = 0;
-            return;// no need to do anything
-        }
-        double distanceFromTarget = Double.MAX_VALUE;
-        target.set(targetTransform.getTranslation().x, targetTransform.getTranslation().y, targetTransform.getTranslation().z);
-
-        if (bonesCount < 0) {
-            bonesCount = bones.size();
-            rotationVectors = new Vector3d[bonesCount];
-            for (int i = 0; i < bonesCount; ++i) {
-                rotationVectors[i] = new Vector3d();
-            }
-            J = new Matrix(3, bonesCount);
-        }
-
-        BoneContext topBone = bones.get(0);
-        for (int i = 0; i < iterations; ++i) {
-            DTransform topBoneTransform = bones.getWorldTransform(topBone);
-            Vector3d e = topBoneTransform.getTranslation().add(topBoneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(topBone.getLength()));// effector
-            distanceFromTarget = e.distance(target);
-            if (distanceFromTarget <= MIN_DISTANCE) {
-                break;
-            }
-
-            deltaP.setColumn(0, 0, target.x - e.x, target.y - e.y, target.z - e.z);
-            int column = 0;
-            for (BoneContext boneContext : bones) {
-                DTransform boneWorldTransform = bones.getWorldTransform(boneContext);
-                Vector3d j = boneWorldTransform.getTranslation(); // current join position
-                Vector3d vectorFromJointToEffector = e.subtract(j);
-                vectorFromJointToEffector.cross(target.subtract(j), rotationVectors[column]).normalizeLocal();
-                rotationVectors[column].cross(vectorFromJointToEffector, col);
-                J.setColumn(col, column++);
-            }
-            Matrix J_1 = J.pseudoinverse();
-
-            SimpleMatrix deltaThetas = J_1.mult(deltaP);
-            if (deltaThetas.elementMaxAbs() < MIN_ANGLE_CHANGE) {
-                break;
-            }
-            for (int j = 0; j < deltaThetas.numRows(); ++j) {
-                double angle = deltaThetas.get(j, 0);
-                Vector3d rotationVector = rotationVectors[j];
-
-                tempDQuaternion.fromAngleAxis(angle, rotationVector);
-                BoneContext boneContext = bones.get(j);
-                Bone bone = boneContext.getBone();
-                if (bone.equals(this.getOwner())) {
-                    if (boneContext.isLockX()) {
-                        tempDQuaternion.set(0, tempDQuaternion.getY(), tempDQuaternion.getZ(), tempDQuaternion.getW());
-                    }
-                    if (boneContext.isLockY()) {
-                        tempDQuaternion.set(tempDQuaternion.getX(), 0, tempDQuaternion.getZ(), tempDQuaternion.getW());
-                    }
-                    if (boneContext.isLockZ()) {
-                        tempDQuaternion.set(tempDQuaternion.getX(), tempDQuaternion.getY(), 0, tempDQuaternion.getW());
-                    }
-                }
-
-                DTransform boneTransform = bones.getWorldTransform(boneContext);
-                boneTransform.getRotation().set(tempDQuaternion.mult(boneTransform.getRotation()));
-                bones.setWorldTransform(boneContext, boneTransform);
-            }
-        }
-
-        // applying the results
-        for (int i = bonesCount - 1; i >= 0; --i) {
-            BoneContext boneContext = bones.get(i);
-            DTransform transform = bones.getWorldTransform(boneContext);
-            constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD, transform.toTransform());
-        }
-        bones = null;// need to reload them again
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Inverse kinematics";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return true;
-    }
-
-    /**
-     * Loaded bones' chain. This class allows to operate on transform matrices that use double precision in computations.
-     * Only the final result is being transformed to single precision numbers.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class BonesChain extends ArrayList<BoneContext> {
-        private static final long serialVersionUID = -1850524345643600718L;
-
-        private List<Matrix> localBonesMatrices = new ArrayList<Matrix>();
-
-        public BonesChain(Bone bone, boolean useTail, int bonesAffected, Collection<Long> alteredOmas, BlenderContext blenderContext) {
-            if (bone != null) {
-                ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
-                if (!useTail) {
-                    bone = bone.getParent();
-                }
-                while (bone != null && (bonesAffected <= 0 || this.size() < bonesAffected)) {
-                    BoneContext boneContext = blenderContext.getBoneContext(bone);
-                    this.add(boneContext);
-                    alteredOmas.add(boneContext.getBoneOma());
-
-                    Transform transform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD);
-                    localBonesMatrices.add(new DTransform(transform).toMatrix());
-
-                    bone = bone.getParent();
-                }
-                
-                if(localBonesMatrices.size() > 0) {
-                	// making the matrices describe the local transformation
-                    Matrix parentWorldMatrix = localBonesMatrices.get(localBonesMatrices.size() - 1);
-                    for(int i=localBonesMatrices.size() - 2;i>=0;--i) {
-                    	SimpleMatrix m = parentWorldMatrix.invert().mult(localBonesMatrices.get(i));
-                    	parentWorldMatrix = localBonesMatrices.get(i);
-                    	localBonesMatrices.set(i, new Matrix(m));
-                    }
-                }
-            }
-        }
-
-        public DTransform getWorldTransform(BoneContext bone) {
-            int index = this.indexOf(bone);
-            return this.getWorldMatrix(index).toTransform();
-        }
-
-        public void setWorldTransform(BoneContext bone, DTransform transform) {
-            int index = this.indexOf(bone);
-            Matrix boneMatrix = transform.toMatrix();
-
-            if (index < this.size() - 1) {
-                // computing the current bone local transform
-                Matrix parentWorldMatrix = this.getWorldMatrix(index + 1);
-                SimpleMatrix m = parentWorldMatrix.invert().mult(boneMatrix);
-                boneMatrix = new Matrix(m);
-            }
-            localBonesMatrices.set(index, boneMatrix);
-        }
-
-        public Matrix getWorldMatrix(int index) {
-            if (index == this.size() - 1) {
-                return new Matrix(localBonesMatrices.get(this.size() - 1));
-            }
-
-            SimpleMatrix result = this.getWorldMatrix(index + 1);
-            result = result.mult(localBonesMatrices.get(index));
-            return new Matrix(result);
-        }
-    }
-}

+ 0 - 107
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLocLike.java

@@ -1,107 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.animation.Bone;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Loc like' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionLocLike extends ConstraintDefinition {
-    private static final int LOCLIKE_X        = 0x01;
-    private static final int LOCLIKE_Y        = 0x02;
-    private static final int LOCLIKE_Z        = 0x04;
-    // protected static final int LOCLIKE_TIP = 0x08;//this is deprecated in
-    // blender
-    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;
-
-    public ConstraintDefinitionLocLike(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        if (blenderContext.getBlenderKey().isFixUpAxis()) {
-            // swapping Y and X limits flag in the bitwise flag
-            int y = flag & LOCLIKE_Y;
-            int invY = flag & LOCLIKE_Y_INVERT;
-            int z = flag & LOCLIKE_Z;
-            int invZ = flag & LOCLIKE_Z_INVERT;
-            // clear the other flags to swap them
-            flag &= LOCLIKE_X | LOCLIKE_X_INVERT | LOCLIKE_OFFSET;
-
-            flag |= y << 1;
-            flag |= invY << 1;
-            flag |= z >> 1;
-            flag |= invZ >> 1;
-
-            trackToBeChanged = (flag & LOCLIKE_X) != 0 || (flag & LOCLIKE_Y) != 0 || (flag & LOCLIKE_Z) != 0;
-        }
-    }
-
-    @Override
-    public boolean isTrackToBeChanged() {
-        // location copy does not work on bones who are connected to their parent
-        return trackToBeChanged && !(this.getOwner() instanceof Bone && ((Bone) this.getOwner()).getParent() != null && blenderContext.getBoneContext(ownerOMA).is(BoneContext.CONNECTED_TO_PARENT));
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || targetTransform == null || !this.isTrackToBeChanged()) {
-            return;
-        }
-
-        Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-
-        Vector3f ownerLocation = ownerTransform.getTranslation();
-        Vector3f targetLocation = targetTransform.getTranslation();
-
-        Vector3f startLocation = ownerTransform.getTranslation().clone();
-        Vector3f offset = Vector3f.ZERO;
-        if ((flag & LOCLIKE_OFFSET) != 0) {// we add the original location to the copied location
-            offset = startLocation;
-        }
-
-        if ((flag & LOCLIKE_X) != 0) {
-            ownerLocation.x = targetLocation.x;
-            if ((flag & LOCLIKE_X_INVERT) != 0) {
-                ownerLocation.x = -ownerLocation.x;
-            }
-        }
-        if ((flag & LOCLIKE_Y) != 0) {
-            ownerLocation.y = targetLocation.y;
-            if ((flag & LOCLIKE_Y_INVERT) != 0) {
-                ownerLocation.y = -ownerLocation.y;
-            }
-        }
-        if ((flag & LOCLIKE_Z) != 0) {
-            ownerLocation.z = targetLocation.z;
-            if ((flag & LOCLIKE_Z_INVERT) != 0) {
-                ownerLocation.z = -ownerLocation.z;
-            }
-        }
-        ownerLocation.addLocal(offset);
-
-        if (influence < 1.0f) {
-            startLocation.subtractLocal(ownerLocation).normalizeLocal().mult(influence);
-            ownerLocation.addLocal(startLocation);
-        }
-
-        this.applyOwnerTransform(ownerTransform, ownerSpace);
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Copy location";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return true;
-    }
-}

+ 0 - 106
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionLocLimit.java

@@ -1,106 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.animation.Bone;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Loc limit' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionLocLimit extends ConstraintDefinition {
-    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;
-
-    protected float[][]      limits     = new float[3][2];
-
-    public ConstraintDefinitionLocLimit(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        if (blenderContext.getBlenderKey().isFixUpAxis()) {
-            limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
-            limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
-            limits[2][0] = -((Number) constraintData.getFieldValue("ymin")).floatValue();
-            limits[2][1] = -((Number) constraintData.getFieldValue("ymax")).floatValue();
-            limits[1][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
-            limits[1][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
-
-            // swapping Y and X limits flag in the bitwise flag
-            int ymin = flag & LIMIT_YMIN;
-            int ymax = flag & LIMIT_YMAX;
-            int zmin = flag & LIMIT_ZMIN;
-            int zmax = flag & LIMIT_ZMAX;
-            flag &= LIMIT_XMIN | LIMIT_XMAX;// clear the other flags to swap
-                                            // them
-            flag |= ymin << 2;
-            flag |= ymax << 2;
-            flag |= zmin >> 2;
-            flag |= zmax >> 2;
-        } else {
-            limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
-            limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
-            limits[1][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
-            limits[1][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
-            limits[2][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
-            limits[2][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
-        }
-
-        trackToBeChanged = (flag & (LIMIT_XMIN | LIMIT_XMAX | LIMIT_YMIN | LIMIT_YMAX | LIMIT_ZMIN | LIMIT_ZMAX)) != 0;
-    }
-
-    @Override
-    public boolean isTrackToBeChanged() {
-        // location limit does not work on bones who are connected to their parent
-        return trackToBeChanged && !(this.getOwner() instanceof Bone && ((Bone) this.getOwner()).getParent() != null && blenderContext.getBoneContext(ownerOMA).is(BoneContext.CONNECTED_TO_PARENT));
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || !this.isTrackToBeChanged()) {
-            return;// no need to do anything
-        }
-
-        Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-
-        Vector3f translation = ownerTransform.getTranslation();
-
-        if ((flag & LIMIT_XMIN) != 0 && translation.x < limits[0][0]) {
-            translation.x -= (translation.x - limits[0][0]) * influence;
-        }
-        if ((flag & LIMIT_XMAX) != 0 && translation.x > limits[0][1]) {
-            translation.x -= (translation.x - limits[0][1]) * influence;
-        }
-        if ((flag & LIMIT_YMIN) != 0 && translation.y < limits[1][0]) {
-            translation.y -= (translation.y - limits[1][0]) * influence;
-        }
-        if ((flag & LIMIT_YMAX) != 0 && translation.y > limits[1][1]) {
-            translation.y -= (translation.y - limits[1][1]) * influence;
-        }
-        if ((flag & LIMIT_ZMIN) != 0 && translation.z < limits[2][0]) {
-            translation.z -= (translation.z - limits[2][0]) * influence;
-        }
-        if ((flag & LIMIT_ZMAX) != 0 && translation.z > limits[2][1]) {
-            translation.z -= (translation.z - limits[2][1]) * influence;
-        }
-
-        this.applyOwnerTransform(ownerTransform, ownerSpace);
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Limit location";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return false;
-    }
-}

+ 0 - 61
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionMaintainVolume.java

@@ -1,61 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.animation.Bone;
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Maintain volume' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class ConstraintDefinitionMaintainVolume extends ConstraintDefinition {
-    private static final int FLAG_MASK_X = 0;
-    private static final int FLAG_MASK_Y = 1;
-    private static final int FLAG_MASK_Z = 2;
-
-    private float            volume;
-
-    public ConstraintDefinitionMaintainVolume(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        volume = (float) Math.sqrt(((Number) constraintData.getFieldValue("volume")).floatValue());
-        trackToBeChanged = volume != 1 && (flag & (FLAG_MASK_X | FLAG_MASK_Y | FLAG_MASK_Z)) != 0;
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (trackToBeChanged && influence > 0) {
-            // the maintain volume constraint is applied directly to object's scale, so no need to do it again
-            // but in case of bones we need to make computations
-            if (this.getOwner() instanceof Bone) {
-                Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-                switch (flag) {
-                    case FLAG_MASK_X:
-                        ownerTransform.getScale().multLocal(1, volume, volume);
-                        break;
-                    case FLAG_MASK_Y:
-                        ownerTransform.getScale().multLocal(volume, 1, volume);
-                        break;
-                    case FLAG_MASK_Z:
-                        ownerTransform.getScale().multLocal(volume, volume, 1);
-                        break;
-                    default:
-                        throw new IllegalStateException("Unknown flag value: " + flag);
-                }
-                this.applyOwnerTransform(ownerTransform, ownerSpace);
-            }
-        }
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Maintain volume";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return false;
-    }
-}

+ 0 - 34
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionNull.java

@@ -1,34 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Null' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionNull extends ConstraintDefinition {
-
-    public ConstraintDefinitionNull(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        trackToBeChanged = false;
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        // null constraint does nothing so no need to implement this one
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Null";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return false;
-    }
-}

+ 0 - 87
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRotLike.java

@@ -1,87 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.math.Quaternion;
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Rot like' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionRotLike extends ConstraintDefinition {
-    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;
-
-    private transient float[] ownerAngles      = new float[3];
-    private transient float[] targetAngles     = new float[3];
-
-    public ConstraintDefinitionRotLike(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        trackToBeChanged = (flag & (ROTLIKE_X | ROTLIKE_Y | ROTLIKE_Z)) != 0;
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || targetTransform == null || !trackToBeChanged) {
-            return;// no need to do anything
-        }
-        Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-
-        Quaternion ownerRotation = ownerTransform.getRotation();
-        ownerAngles = ownerRotation.toAngles(ownerAngles);
-        targetAngles = targetTransform.getRotation().toAngles(targetAngles);
-
-        Quaternion startRotation = ownerRotation.clone();
-        Quaternion offset = Quaternion.IDENTITY;
-        if ((flag & ROTLIKE_OFFSET) != 0) {// we add the original rotation to
-                                           // the copied rotation
-            offset = startRotation;
-        }
-
-        if ((flag & ROTLIKE_X) != 0) {
-            ownerAngles[0] = targetAngles[0];
-            if ((flag & ROTLIKE_X_INVERT) != 0) {
-                ownerAngles[0] = -ownerAngles[0];
-            }
-        }
-        if ((flag & ROTLIKE_Y) != 0) {
-            ownerAngles[1] = targetAngles[1];
-            if ((flag & ROTLIKE_Y_INVERT) != 0) {
-                ownerAngles[1] = -ownerAngles[1];
-            }
-        }
-        if ((flag & ROTLIKE_Z) != 0) {
-            ownerAngles[2] = targetAngles[2];
-            if ((flag & ROTLIKE_Z_INVERT) != 0) {
-                ownerAngles[2] = -ownerAngles[2];
-            }
-        }
-        ownerRotation.fromAngles(ownerAngles).multLocal(offset);
-
-        if (influence < 1.0f) {
-            // startLocation.subtractLocal(ownerLocation).normalizeLocal().mult(influence);
-            // ownerLocation.addLocal(startLocation);
-            // TODO
-        }
-
-        this.applyOwnerTransform(ownerTransform, ownerSpace);
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Copy rotation";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return true;
-    }
-}

+ 0 - 129
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionRotLimit.java

@@ -1,129 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.math.FastMath;
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Rot limit' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionRotLimit extends ConstraintDefinition {
-    private static final int    LIMIT_XROT = 0x01;
-    private static final int    LIMIT_YROT = 0x02;
-    private static final int    LIMIT_ZROT = 0x04;
-
-    private transient float[][] limits     = new float[3][2];
-    private transient float[]   angles     = new float[3];
-
-    public ConstraintDefinitionRotLimit(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        if (blenderContext.getBlenderKey().isFixUpAxis()) {
-            limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
-            limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
-            limits[2][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
-            limits[2][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
-            limits[1][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
-            limits[1][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
-
-            // swapping Y and X limits flag in the bitwise flag
-            int limitY = flag & LIMIT_YROT;
-            int limitZ = flag & LIMIT_ZROT;
-            flag &= LIMIT_XROT;// clear the other flags to swap them
-            flag |= limitY << 1;
-            flag |= limitZ >> 1;
-        } else {
-            limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
-            limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
-            limits[1][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
-            limits[1][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
-            limits[2][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
-            limits[2][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
-        }
-
-        // until blender 2.49 the rotations values were stored in degrees
-        if (blenderContext.getBlenderVersion() <= 249) {
-            for (int i = 0; i < 3; ++i) {
-                limits[i][0] *= FastMath.DEG_TO_RAD;
-                limits[i][1] *= FastMath.DEG_TO_RAD;
-            }
-        }
-
-        // make sure that the limits are always in range [0, 2PI)
-        // TODO: left it here because it is essential to make sure all cases
-        // work poperly
-        // but will do it a little bit later ;)
-        /*
-         * for (int i = 0; i < 3; ++i) { for (int j = 0; j < 2; ++j) { int
-         * multFactor = (int)Math.abs(limits[i][j] / FastMath.TWO_PI) ; if
-         * (limits[i][j] < 0) { limits[i][j] += FastMath.TWO_PI * (multFactor +
-         * 1); } else { limits[i][j] -= FastMath.TWO_PI * multFactor; } } //make
-         * sure the lower limit is not greater than the upper one
-         * if(limits[i][0] > limits[i][1]) { float temp = limits[i][0];
-         * limits[i][0] = limits[i][1]; limits[i][1] = temp; } }
-         */
-
-        trackToBeChanged = (flag & (LIMIT_XROT | LIMIT_YROT | LIMIT_ZROT)) != 0;
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || !trackToBeChanged) {
-            return;
-        }
-        Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-
-        ownerTransform.getRotation().toAngles(angles);
-        // make sure that the rotations are always in range [0, 2PI)
-        // TODO: same comment as in constructor
-        /*
-         * for (int i = 0; i < 3; ++i) { int multFactor =
-         * (int)Math.abs(angles[i] / FastMath.TWO_PI) ; if(angles[i] < 0) {
-         * angles[i] += FastMath.TWO_PI * (multFactor + 1); } else { angles[i]
-         * -= FastMath.TWO_PI * multFactor; } }
-         */
-        if ((flag & LIMIT_XROT) != 0) {
-            float difference = 0.0f;
-            if (angles[0] < limits[0][0]) {
-                difference = (angles[0] - limits[0][0]) * influence;
-            } else if (angles[0] > limits[0][1]) {
-                difference = (angles[0] - limits[0][1]) * influence;
-            }
-            angles[0] -= difference;
-        }
-        if ((flag & LIMIT_YROT) != 0) {
-            float difference = 0.0f;
-            if (angles[1] < limits[1][0]) {
-                difference = (angles[1] - limits[1][0]) * influence;
-            } else if (angles[1] > limits[1][1]) {
-                difference = (angles[1] - limits[1][1]) * influence;
-            }
-            angles[1] -= difference;
-        }
-        if ((flag & LIMIT_ZROT) != 0) {
-            float difference = 0.0f;
-            if (angles[2] < limits[2][0]) {
-                difference = (angles[2] - limits[2][0]) * influence;
-            } else if (angles[2] > limits[2][1]) {
-                difference = (angles[2] - limits[2][1]) * influence;
-            }
-            angles[2] -= difference;
-        }
-        ownerTransform.getRotation().fromAngles(angles);
-
-        this.applyOwnerTransform(ownerTransform, ownerSpace);
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Limit rotation";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return false;
-    }
-}

+ 0 - 74
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSizeLike.java

@@ -1,74 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Size like' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionSizeLike extends ConstraintDefinition {
-    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;
-
-    public ConstraintDefinitionSizeLike(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        if (blenderContext.getBlenderKey().isFixUpAxis()) {
-            // swapping Y and X limits flag in the bitwise flag
-            int y = flag & SIZELIKE_Y;
-            int z = flag & SIZELIKE_Z;
-            flag &= SIZELIKE_X | LOCLIKE_OFFSET;// clear the other flags to swap
-                                                // them
-            flag |= y << 1;
-            flag |= z >> 1;
-
-            trackToBeChanged = (flag & (SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z)) != 0;
-        }
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || targetTransform == null || !trackToBeChanged) {
-            return;// no need to do anything
-        }
-        Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-
-        Vector3f ownerScale = ownerTransform.getScale();
-        Vector3f targetScale = targetTransform.getScale();
-
-        Vector3f offset = Vector3f.ZERO;
-        if ((flag & LOCLIKE_OFFSET) != 0) {// we add the original scale to the
-                                           // copied scale
-            offset = ownerScale.clone();
-        }
-
-        if ((flag & SIZELIKE_X) != 0) {
-            ownerScale.x = targetScale.x * influence + (1.0f - influence) * ownerScale.x;
-        }
-        if ((flag & SIZELIKE_Y) != 0) {
-            ownerScale.y = targetScale.y * influence + (1.0f - influence) * ownerScale.y;
-        }
-        if ((flag & SIZELIKE_Z) != 0) {
-            ownerScale.z = targetScale.z * influence + (1.0f - influence) * ownerScale.z;
-        }
-        ownerScale.addLocal(offset);
-
-        this.applyOwnerTransform(ownerTransform, ownerSpace);
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Copy scale";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return true;
-    }
-}

+ 0 - 96
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionSizeLimit.java

@@ -1,96 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * This class represents 'Size limit' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ConstraintDefinitionSizeLimit extends ConstraintDefinition {
-    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;
-
-    protected transient float[][] limits     = new float[3][2];
-
-    public ConstraintDefinitionSizeLimit(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        if (blenderContext.getBlenderKey().isFixUpAxis()) {
-            limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
-            limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
-            limits[2][0] = -((Number) constraintData.getFieldValue("ymin")).floatValue();
-            limits[2][1] = -((Number) constraintData.getFieldValue("ymax")).floatValue();
-            limits[1][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
-            limits[1][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
-
-            // swapping Y and X limits flag in the bitwise flag
-            int ymin = flag & LIMIT_YMIN;
-            int ymax = flag & LIMIT_YMAX;
-            int zmin = flag & LIMIT_ZMIN;
-            int zmax = flag & LIMIT_ZMAX;
-            flag &= LIMIT_XMIN | LIMIT_XMAX;// clear the other flags to swap
-                                            // them
-            flag |= ymin << 2;
-            flag |= ymax << 2;
-            flag |= zmin >> 2;
-            flag |= zmax >> 2;
-        } else {
-            limits[0][0] = ((Number) constraintData.getFieldValue("xmin")).floatValue();
-            limits[0][1] = ((Number) constraintData.getFieldValue("xmax")).floatValue();
-            limits[1][0] = ((Number) constraintData.getFieldValue("ymin")).floatValue();
-            limits[1][1] = ((Number) constraintData.getFieldValue("ymax")).floatValue();
-            limits[2][0] = ((Number) constraintData.getFieldValue("zmin")).floatValue();
-            limits[2][1] = ((Number) constraintData.getFieldValue("zmax")).floatValue();
-        }
-
-        trackToBeChanged = (flag & (LIMIT_XMIN | LIMIT_XMAX | LIMIT_YMIN | LIMIT_YMAX | LIMIT_ZMIN | LIMIT_ZMAX)) != 0;
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || !trackToBeChanged) {
-            return;
-        }
-        Transform ownerTransform = this.getOwnerTransform(ownerSpace);
-
-        Vector3f scale = ownerTransform.getScale();
-        if ((flag & LIMIT_XMIN) != 0 && scale.x < limits[0][0]) {
-            scale.x -= (scale.x - limits[0][0]) * influence;
-        }
-        if ((flag & LIMIT_XMAX) != 0 && scale.x > limits[0][1]) {
-            scale.x -= (scale.x - limits[0][1]) * influence;
-        }
-        if ((flag & LIMIT_YMIN) != 0 && scale.y < limits[1][0]) {
-            scale.y -= (scale.y - limits[1][0]) * influence;
-        }
-        if ((flag & LIMIT_YMAX) != 0 && scale.y > limits[1][1]) {
-            scale.y -= (scale.y - limits[1][1]) * influence;
-        }
-        if ((flag & LIMIT_ZMIN) != 0 && scale.z < limits[2][0]) {
-            scale.z -= (scale.z - limits[2][0]) * influence;
-        }
-        if ((flag & LIMIT_ZMAX) != 0 && scale.z > limits[2][1]) {
-            scale.z -= (scale.z - limits[2][1]) * influence;
-        }
-
-        this.applyOwnerTransform(ownerTransform, ownerSpace);
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Limit scale";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return false;
-    }
-}

+ 0 - 81
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionTransLike.java

@@ -1,81 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.animation.Bone;
-import com.jme3.animation.Skeleton;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-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.util.TempVars;
-
-/**
- * This class represents 'Trans like' constraint type in blender.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class ConstraintDefinitionTransLike extends ConstraintDefinition {
-    private Long   targetOMA;
-    private String subtargetName;
-
-    public ConstraintDefinitionTransLike(Structure constraintData, Long ownerOMA, BlenderContext blenderContext) {
-        super(constraintData, ownerOMA, blenderContext);
-        Pointer pTarget = (Pointer) constraintData.getFieldValue("tar");
-        targetOMA = pTarget.getOldMemoryAddress();
-        Object subtarget = constraintData.getFieldValue("subtarget");
-        if (subtarget != null) {
-            subtargetName = subtarget.toString();
-        }
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-        if (influence == 0 || targetTransform == null) {
-            return;// no need to do anything
-        }
-        Object target = this.getTarget();// Bone or Node
-        Object owner = this.getOwner();// Bone or Node
-        if (!target.getClass().equals(owner.getClass())) {
-            ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
-
-            TempVars tempVars = TempVars.get();
-            Matrix4f m = constraintHelper.toMatrix(targetTransform, tempVars.tempMat4);
-            tempVars.tempMat42.set(BoneContext.BONE_ARMATURE_TRANSFORMATION_MATRIX);
-            if (target instanceof Bone) {
-                tempVars.tempMat42.invertLocal();
-            }
-            m = m.multLocal(tempVars.tempMat42);
-            tempVars.release();
-
-            targetTransform = new Transform(m.toTranslationVector(), m.toRotationQuat(), m.toScaleVector());
-        }
-        this.applyOwnerTransform(targetTransform, ownerSpace);
-    }
-
-    /**
-     * @return the target feature; it is either Node or Bone (vertex group subtarger is not yet supported)
-     */
-    private Object getTarget() {
-        Object target = blenderContext.getLoadedFeature(targetOMA, LoadedDataType.FEATURE);
-        if (subtargetName != null && blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, target) != null) {
-            Skeleton skeleton = blenderContext.getSkeleton(targetOMA);
-            target = skeleton.getBone(subtargetName);
-        }
-        return target;
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return "Copy transforms";
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return true;
-    }
-}

+ 0 - 40
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/UnsupportedConstraintDefinition.java

@@ -1,40 +0,0 @@
-package com.jme3.scene.plugins.blender.constraints.definitions;
-
-import com.jme3.math.Transform;
-import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
-
-/**
- * This class represents a constraint that is defined by blender but not
- * supported by either importer ot jme. It only wirtes down a warning when
- * baking is called.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class UnsupportedConstraintDefinition extends ConstraintDefinition {
-    private String typeName;
-
-    public UnsupportedConstraintDefinition(String typeName) {
-        super(null, null, null);
-        this.typeName = typeName;
-        trackToBeChanged = false;
-    }
-
-    @Override
-    public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
-    }
-
-    @Override
-    public boolean isImplemented() {
-        return false;
-    }
-
-    @Override
-    public String getConstraintTypeName() {
-        return typeName;
-    }
-
-    @Override
-    public boolean isTargetRequired() {
-        return false;
-    }
-}

+ 0 - 172
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/BezierCurve.java

@@ -1,172 +0,0 @@
-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.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
- * floating point operations errors.
- * @author Marcin Roguski (Kaelthas)
- */
-public class BezierCurve {
-    private static final int IPO_CONSTANT = 0;
-    private static final int IPO_LINEAR   = 1;
-    private static final int IPO_BEZIER   = 2;
-
-    public static final int  X_VALUE      = 0;
-    public static final int  Y_VALUE      = 1;
-    public static final int  Z_VALUE      = 2;
-    /**
-     * The type of the curve. Describes the data it modifies.
-     * Used in ipos calculations.
-     */
-    private int              type;
-    /** The dimension of the curve. */
-    private int              dimension;
-    /** A table of the bezier points. */
-    private double[][][]     bezierPoints;
-    /** Array that stores a radius for each bezier triple. */
-    private double[]         radiuses;
-    /** Interpolation types of the bezier triples. */
-    private int[]            interpolations;
-
-    public BezierCurve(final int type, final List<Structure> bezTriples, final int dimension) {
-        this(type, bezTriples, dimension, false);
-    }
-
-    @SuppressWarnings("unchecked")
-    public BezierCurve(final int type, final List<Structure> bezTriples, final int dimension, boolean fixUpAxis) {
-        if (dimension != 2 && dimension != 3) {
-            throw new IllegalArgumentException("The dimension of the curve should be 2 or 3!");
-        }
-        this.type = type;
-        this.dimension = dimension;
-        // first index of the bezierPoints table has the length of triples amount
-        // the second index points to a table od three points of a bezier triple (handle, point, handle)
-        // the third index specifies the coordinates of the specific point in a bezier triple
-        bezierPoints = new double[bezTriples.size()][3][dimension];
-        radiuses = new double[bezTriples.size()];
-        interpolations = new int[bezTriples.size()];
-        int i = 0, j, k;
-        for (Structure bezTriple : bezTriples) {
-            DynamicArray<Number> vec = (DynamicArray<Number>) bezTriple.getFieldValue("vec");
-            for (j = 0; j < 3; ++j) {
-                for (k = 0; k < dimension; ++k) {
-                    bezierPoints[i][j][k] = vec.get(j, k).doubleValue();
-                }
-                if (fixUpAxis && dimension == 3) {
-                    double temp = bezierPoints[i][j][2];
-                    bezierPoints[i][j][2] = -bezierPoints[i][j][1];
-                    bezierPoints[i][j][1] = temp;
-                }
-            }
-            radiuses[i] = ((Number) bezTriple.getFieldValue("radius")).floatValue();
-            interpolations[i++] = ((Number) bezTriple.getFieldValue("ipo", IPO_BEZIER)).intValue();
-        }
-    }
-
-    /**
-     * This method evaluates the data for the specified frame. The Y value is returned.
-     * @param frame
-     *            the frame for which the value is being calculated
-     * @param valuePart
-     *            this param specifies wheather we should return the X, Y or Z part of the result value; it should have
-     *            one of the following values: X_VALUE - the X factor of the result Y_VALUE - the Y factor of the result
-     *            Z_VALUE - the Z factor of the result
-     * @return the value of the curve
-     */
-    public double evaluate(int frame, int valuePart) {
-        for (int i = 0; i < bezierPoints.length - 1; ++i) {
-            if (frame >= bezierPoints[i][1][0] && frame <= bezierPoints[i + 1][1][0]) {
-                double t = (frame - bezierPoints[i][1][0]) / (bezierPoints[i + 1][1][0] - bezierPoints[i][1][0]);
-                switch (interpolations[i]) {
-                    case IPO_BEZIER:
-                        double oneMinusT = 1.0f - t;
-                        double oneMinusT2 = oneMinusT * oneMinusT;
-                        double t2 = t * t;
-                        return bezierPoints[i][1][valuePart] * oneMinusT2 * oneMinusT + 3.0f * bezierPoints[i][2][valuePart] * t * oneMinusT2 + 3.0f * bezierPoints[i + 1][0][valuePart] * t2 * oneMinusT + bezierPoints[i + 1][1][valuePart] * t2 * t;
-                    case IPO_LINEAR:
-                        return (1f - t) * bezierPoints[i][1][valuePart] + t * bezierPoints[i + 1][1][valuePart];
-                    case IPO_CONSTANT:
-                        return bezierPoints[i][1][valuePart];
-                    default:
-                        throw new IllegalStateException("Unknown interpolation type for curve: " + interpolations[i]);
-                }
-            }
-        }
-        if (frame < bezierPoints[0][1][0]) {
-            return bezierPoints[0][1][1];
-        } else { // frame>bezierPoints[bezierPoints.length-1][1][0]
-            return bezierPoints[bezierPoints.length - 1][1][1];
-        }
-    }
-
-    /**
-     * This method returns the frame where last bezier triple center point of the bezier curve is located.
-     * @return the frame number of the last defined bezier triple point for the curve
-     */
-    public int getLastFrame() {
-        return (int) bezierPoints[bezierPoints.length - 1][1][0];
-    }
-
-    /**
-     * This method returns the type of the bezier curve. The type describes the parameter that this curve modifies
-     * (ie. LocationX or rotationW of the feature).
-     * @return the type of the bezier curve
-     */
-    public int getType() {
-        return type;
-    }
-
-    /**
-     * The method returns the radius for the required bezier triple.
-     * 
-     * @param bezierTripleIndex
-     *            index of the bezier triple
-     * @return radius of the required bezier triple
-     */
-    public double getRadius(int bezierTripleIndex) {
-        return radiuses[bezierTripleIndex];
-    }
-
-    /**
-     * This method returns a list of control points for this curve.
-     * @return a list of control points for this curve.
-     */
-    public List<Vector3f> getControlPoints() {
-        List<Vector3f> controlPoints = new ArrayList<Vector3f>(bezierPoints.length * 3);
-        for (int i = 0; i < bezierPoints.length; ++i) {
-            controlPoints.add(new Vector3f((float) bezierPoints[i][0][0], (float) bezierPoints[i][0][1], (float) bezierPoints[i][0][2]));
-            controlPoints.add(new Vector3f((float) bezierPoints[i][1][0], (float) bezierPoints[i][1][1], (float) bezierPoints[i][1][2]));
-            controlPoints.add(new Vector3f((float) bezierPoints[i][2][0], (float) bezierPoints[i][2][1], (float) bezierPoints[i][2][2]));
-        }
-        return controlPoints;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("Bezier curve: ").append(type).append('\n');
-        for (int i = 0; i < bezierPoints.length; ++i) {
-            sb.append(this.toStringBezTriple(i)).append('\n');
-        }
-        return sb.toString();
-    }
-
-    /**
-     * This method converts the bezier triple of a specified index into text.
-     * @param tripleIndex
-     *            index of the triple
-     * @return text representation of the triple
-     */
-    private String toStringBezTriple(int tripleIndex) {
-        if (dimension == 2) {
-            return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ") (" + bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ") (" + bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ")]";
-        } else {
-            return "[(" + bezierPoints[tripleIndex][0][0] + ", " + bezierPoints[tripleIndex][0][1] + ", " + bezierPoints[tripleIndex][0][2] + ") (" + bezierPoints[tripleIndex][1][0] + ", " + bezierPoints[tripleIndex][1][1] + ", " + bezierPoints[tripleIndex][1][2] + ") (" + bezierPoints[tripleIndex][2][0] + ", " + bezierPoints[tripleIndex][2][1] + ", " + bezierPoints[tripleIndex][2][2] + ")]";
-        }
-    }
-}

+ 0 - 159
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesHelper.java

@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.curves;
-
-import java.util.logging.Logger;
-
-import com.jme3.math.FastMath;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * A class that is used in mesh calculations.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class CurvesHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER                      = Logger.getLogger(CurvesHelper.class.getName());
-
-    /** Minimum basis U function degree for NURBS curves and surfaces. */
-    protected int               minimumBasisUFunctionDegree = 4;
-    /** Minimum basis V function degree for NURBS curves and surfaces. */
-    protected int               minimumBasisVFunctionDegree = 4;
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public CurvesHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    public CurvesTemporalMesh toCurve(Structure curveStructure, BlenderContext blenderContext) throws BlenderFileException {
-        CurvesTemporalMesh result = new CurvesTemporalMesh(curveStructure, blenderContext);
-
-        if (blenderContext.getBlenderKey().isLoadObjectProperties()) {
-            LOGGER.fine("Reading custom properties.");
-            result.setProperties(this.loadProperties(curveStructure, blenderContext));
-        }
-
-        return result;
-    }
-
-    /**
-     * The method transforms the bevel along the curve.
-     * 
-     * @param bevel
-     *            the bevel to be transformed
-     * @param prevPos
-     *            previous curve point
-     * @param currPos
-     *            current curve point (here the center of the new bevel will be
-     *            set)
-     * @param nextPos
-     *            next curve point
-     * @return points of transformed bevel
-     */
-    protected Vector3f[] transformBevel(Vector3f[] bevel, Vector3f prevPos, Vector3f currPos, Vector3f nextPos) {
-        bevel = bevel.clone();
-
-        // currPos and directionVector define the line in 3D space
-        Vector3f directionVector = prevPos != null ? currPos.subtract(prevPos) : nextPos.subtract(currPos);
-        directionVector.normalizeLocal();
-
-        // plane is described by equation: Ax + By + Cz + D = 0 where planeNormal = [A, B, C] and D = -(Ax + By + Cz)
-        Vector3f planeNormal = null;
-        if (prevPos != null) {
-            planeNormal = currPos.subtract(prevPos).normalizeLocal();
-            if (nextPos != null) {
-                planeNormal.addLocal(nextPos.subtract(currPos).normalizeLocal()).normalizeLocal();
-            }
-        } else {
-            planeNormal = nextPos.subtract(currPos).normalizeLocal();
-        }
-        float D = -planeNormal.dot(currPos);// D = -(Ax + By + Cz)
-
-        // now we need to compute paralell cast of each bevel point on the plane, the leading line is already known
-        // parametric equation of a line: x = px + vx * t; y = py + vy * t; z = pz + vz * t
-        // where p = currPos and v = directionVector
-        // using x, y and z in plane equation we get value of 't' that will allow us to compute the point where plane and line cross
-        float temp = planeNormal.dot(directionVector);
-        for (int i = 0; i < bevel.length; ++i) {
-            float t = -(planeNormal.dot(bevel[i]) + D) / temp;
-            if (fixUpAxis) {
-                bevel[i] = new Vector3f(bevel[i].x + directionVector.x * t, bevel[i].y + directionVector.y * t, bevel[i].z + directionVector.z * t);
-            } else {
-                bevel[i] = new Vector3f(bevel[i].x + directionVector.x * t, -bevel[i].z + directionVector.z * t, bevel[i].y + directionVector.y * t);
-            }
-        }
-        return bevel;
-    }
-
-    /**
-     * This method transforms the first line of the bevel points positioning it
-     * on the first point of the curve.
-     * 
-     * @param startingLinePoints
-     *            the vbevel shape points
-     * @param firstCurvePoint
-     *            the first curve's point
-     * @param secondCurvePoint
-     *            the second curve's point
-     * @return points of transformed bevel
-     */
-    protected Vector3f[] transformToFirstLineOfBevelPoints(Vector3f[] startingLinePoints, Vector3f firstCurvePoint, Vector3f secondCurvePoint) {
-        Vector3f planeNormal = secondCurvePoint.subtract(firstCurvePoint).normalizeLocal();
-
-        float angle = FastMath.acos(planeNormal.dot(Vector3f.UNIT_X));
-        Vector3f rotationVector = Vector3f.UNIT_X.cross(planeNormal).normalizeLocal();
-        
-        Matrix4f m = new Matrix4f();
-        m.setRotationQuaternion(new Quaternion().fromAngleAxis(angle, rotationVector));
-        m.setTranslation(firstCurvePoint);
-
-        Vector3f temp = new Vector3f();
-        Vector3f[] verts = new Vector3f[startingLinePoints.length];
-        for (int i = 0; i < verts.length; ++i) {
-            verts[i] = m.mult(startingLinePoints[i], temp).clone();
-        }
-        return verts;
-    }
-}

+ 0 - 890
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/curves/CurvesTemporalMesh.java

@@ -1,890 +0,0 @@
-package com.jme3.scene.plugins.blender.curves;
-
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-import java.util.logging.Logger;
-
-import com.jme3.material.RenderState.FaceCullMode;
-import com.jme3.math.FastMath;
-import com.jme3.math.Spline;
-import com.jme3.math.Spline.SplineType;
-import com.jme3.math.Vector3f;
-import com.jme3.math.Vector4f;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.mesh.IndexBuffer;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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.MaterialContext;
-import com.jme3.scene.plugins.blender.materials.MaterialHelper;
-import com.jme3.scene.plugins.blender.meshes.Edge;
-import com.jme3.scene.plugins.blender.meshes.Face;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-import com.jme3.scene.shape.Curve;
-import com.jme3.scene.shape.Surface;
-import com.jme3.util.BufferUtils;
-
-/**
- * A temporal mesh for curves and surfaces. It works in similar way as TemporalMesh for meshes.
- * It prepares all necessary lines and faces and allows to apply modifiers just like in regular temporal mesh.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class CurvesTemporalMesh extends TemporalMesh {
-    private static final Logger  LOGGER         = Logger.getLogger(CurvesTemporalMesh.class.getName());
-
-    private static final int     TYPE_BEZIER    = 0x0001;
-    private static final int     TYPE_NURBS     = 0x0004;
-
-    private static final int     FLAG_3D        = 0x0001;
-    private static final int     FLAG_FRONT     = 0x0002;
-    private static final int     FLAG_BACK      = 0x0004;
-    private static final int     FLAG_FILL_CAPS = 0x4000;
-
-    private static final int     FLAG_SMOOTH    = 0x0001;
-
-    protected CurvesHelper       curvesHelper;
-    protected boolean            is2D;
-    protected boolean            isFront;
-    protected boolean            isBack;
-    protected boolean            fillCaps;
-    protected float              bevelStart;
-    protected float              bevelEnd;
-    protected List<BezierLine>   beziers        = new ArrayList<BezierLine>();
-    protected CurvesTemporalMesh bevelObject;
-    protected CurvesTemporalMesh taperObject;
-    /** The scale that is used if the curve is a bevel or taper curve. */
-    protected Vector3f           scale          = new Vector3f(1, 1, 1);
-
-    /**
-     * The constructor creates an empty temporal mesh.
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this will never be thrown here
-     */
-    protected CurvesTemporalMesh(BlenderContext blenderContext) throws BlenderFileException {
-        super(null, blenderContext, false);
-    }
-    
-    /**
-     * Loads the temporal mesh from the given curve structure. The mesh can be either curve or surface.
-     * @param curveStructure
-     *            the structure that contains the curve/surface data
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading occur
-     */
-    public CurvesTemporalMesh(Structure curveStructure, BlenderContext blenderContext) throws BlenderFileException {
-        this(curveStructure, new Vector3f(1, 1, 1), true, blenderContext);
-    }
-
-    /**
-     * Loads the temporal mesh from the given curve structure. The mesh can be either curve or surface.
-     * @param curveStructure
-     *            the structure that contains the curve/surface data
-     * @param scale
-     *            the scale used if the current curve is used as a bevel curve
-     * @param loadBevelAndTaper indicates if bevel and taper should be loaded (this is not needed for curves that are loaded to be used as bevel and taper)
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading occur
-     */
-    @SuppressWarnings("unchecked")
-    private CurvesTemporalMesh(Structure curveStructure, Vector3f scale, boolean loadBevelAndTaper, BlenderContext blenderContext) throws BlenderFileException {
-        super(curveStructure, blenderContext, false);
-        name = curveStructure.getName();
-        curvesHelper = blenderContext.getHelper(CurvesHelper.class);
-        this.scale = scale;
-
-        int flag = ((Number) curveStructure.getFieldValue("flag")).intValue();
-        is2D = (flag & FLAG_3D) == 0;
-        if (is2D) {
-            // TODO: add support for 3D flag
-            LOGGER.warning("2D flag not yet supported for curves!");
-        }
-        isFront = (flag & FLAG_FRONT) != 0;
-        isBack = (flag & FLAG_BACK) != 0;
-        fillCaps = (flag & FLAG_FILL_CAPS) != 0;
-        bevelStart = ((Number) curveStructure.getFieldValue("bevfac1", 0)).floatValue();
-        bevelEnd = ((Number) curveStructure.getFieldValue("bevfac2", 1)).floatValue();
-        if (bevelStart > bevelEnd) {
-            float temp = bevelStart;
-            bevelStart = bevelEnd;
-            bevelEnd = temp;
-        }
-
-        LOGGER.fine("Reading nurbs (and sorting them by material).");
-        Map<Number, List<Structure>> nurbs = new HashMap<Number, List<Structure>>();
-        List<Structure> nurbStructures = ((Structure) curveStructure.getFieldValue("nurb")).evaluateListBase();
-        for (Structure nurb : nurbStructures) {
-            Number matNumber = (Number) nurb.getFieldValue("mat_nr");
-            List<Structure> nurbList = nurbs.get(matNumber);
-            if (nurbList == null) {
-                nurbList = new ArrayList<Structure>();
-                nurbs.put(matNumber, nurbList);
-            }
-            nurbList.add(nurb);
-        }
-
-        LOGGER.fine("Getting materials.");
-        MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
-        materials = materialHelper.getMaterials(curveStructure, blenderContext);
-        if (materials != null) {
-            for (MaterialContext materialContext : materials) {
-                materialContext.setFaceCullMode(FaceCullMode.Off);
-            }
-        }
-
-        LOGGER.fine("Getting or creating bevel object.");
-        bevelObject = loadBevelAndTaper ? this.loadBevelObject(curveStructure) : null;
-
-        LOGGER.fine("Getting taper object.");
-        Pointer pTaperObject = (Pointer) curveStructure.getFieldValue("taperobj");
-        if (bevelObject != null && pTaperObject.isNotNull()) {
-            Structure taperObjectStructure = pTaperObject.fetchData().get(0);
-            DynamicArray<Number> scaleArray = (DynamicArray<Number>) taperObjectStructure.getFieldValue("size");
-            scale = blenderContext.getBlenderKey().isFixUpAxis() ? new Vector3f(scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()) : new Vector3f(scaleArray.get(0).floatValue(), scaleArray.get(2).floatValue(), scaleArray.get(1).floatValue());
-            Pointer pTaperStructure = (Pointer) taperObjectStructure.getFieldValue("data");
-            Structure taperStructure = pTaperStructure.fetchData().get(0);
-            taperObject = new CurvesTemporalMesh(taperStructure, blenderContext);
-        }
-
-        LOGGER.fine("Creating the result curves.");
-        for (Entry<Number, List<Structure>> nurbEntry : nurbs.entrySet()) {
-            for (Structure nurb : nurbEntry.getValue()) {
-                int type = ((Number) nurb.getFieldValue("type")).intValue();
-                if ((type & TYPE_BEZIER) != 0) {
-                    this.loadBezierCurve(nurb, nurbEntry.getKey().intValue());
-                } else if ((type & TYPE_NURBS) != 0) {
-                    this.loadNurbSurface(nurb, nurbEntry.getKey().intValue());
-                } else {
-                    throw new BlenderFileException("Unknown curve type: " + type);
-                }
-            }
-        }
-
-        if (bevelObject != null && beziers.size() > 0) {
-            this.append(this.applyBevelAndTaper(this, bevelObject, taperObject, blenderContext));
-        } else {
-            for (BezierLine bezierLine : beziers) {
-            	int originalVerticesAmount = vertices.size();
-                vertices.add(bezierLine.vertices[0]);
-                Vector3f v = bezierLine.vertices[1].subtract(bezierLine.vertices[0]).normalizeLocal();
-                float temp = v.x;
-                v.x = -v.y;
-                v.y = temp;
-                v.z = 0;
-                normals.add(v);// this will be smoothed in the next iteration
-
-                for (int i = 1; i < bezierLine.vertices.length; ++i) {
-                    vertices.add(bezierLine.vertices[i]);
-                    edges.add(new Edge(originalVerticesAmount + i - 1, originalVerticesAmount + i, 0, false, this));
-
-                    // generating normal for vertex at 'i'
-                    v = bezierLine.vertices[i].subtract(bezierLine.vertices[i - 1]).normalizeLocal();
-                    temp = v.x;
-                    v.x = -v.y;
-                    v.y = temp;
-                    v.z = 0;
-
-                    // make the previous normal smooth
-                    normals.get(i - 1).addLocal(v).multLocal(0.5f).normalizeLocal();
-                    normals.add(v);// this will be smoothed in the next iteration
-                }
-            }
-        }
-    }
-
-    /**
-     * The method computes the value of a point at the certain relational distance from its beginning.
-     * @param alongRatio
-     *            the relative distance along the curve; should be a value between 0 and 1 inclusive;
-     *            if the value exceeds the boundaries it is truncated to them
-     * @return computed value along the curve
-     */
-    private Vector3f getValueAlongCurve(float alongRatio) {
-        alongRatio = FastMath.clamp(alongRatio, 0, 1);
-        Vector3f result = new Vector3f();
-        float probeLength = this.getLength() * alongRatio, length = 0;
-        for (BezierLine bezier : beziers) {
-            float edgeLength = bezier.getLength();
-            if (length + edgeLength >= probeLength) {
-                float ratioAlongEdge = (probeLength - length) / edgeLength;
-                return bezier.getValueAlongCurve(ratioAlongEdge);
-            }
-            length += edgeLength;
-        }
-        return result;
-    }
-
-    /**
-     * @return the length of the curve
-     */
-    private float getLength() {
-        float result = 0;
-        for (BezierLine bezier : beziers) {
-            result += bezier.getLength();
-        }
-        return result;
-    }
-
-    /**
-     * The methods loads the bezier curve from the given structure.
-     * @param nurbStructure
-     *            the structure containing a single curve definition
-     * @param materialIndex
-     *            the index of this segment's material
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading occur
-     */
-    private void loadBezierCurve(Structure nurbStructure, int materialIndex) throws BlenderFileException {
-        Pointer pBezierTriple = (Pointer) nurbStructure.getFieldValue("bezt");
-        if (pBezierTriple.isNotNull()) {
-            int resolution = ((Number) nurbStructure.getFieldValue("resolu")).intValue();
-            boolean cyclic = (((Number) nurbStructure.getFieldValue("flagu")).intValue() & 0x01) != 0;
-            boolean smooth = (((Number) nurbStructure.getFieldValue("flag")).intValue() & FLAG_SMOOTH) != 0;
-
-            // creating the curve object
-            BezierCurve bezierCurve = new BezierCurve(0, pBezierTriple.fetchData(), 3, blenderContext.getBlenderKey().isFixUpAxis());
-            List<Vector3f> controlPoints = bezierCurve.getControlPoints();
-
-            if (cyclic) {
-                // copy the first three points at the end
-                for (int i = 0; i < 3; ++i) {
-                    controlPoints.add(controlPoints.get(i));
-                }
-            }
-            // removing the first and last handles
-            controlPoints.remove(0);
-            controlPoints.remove(controlPoints.size() - 1);
-
-            // creating curve
-            Curve curve = new Curve(new Spline(SplineType.Bezier, controlPoints, 0, false), resolution);
-
-            FloatBuffer vertsBuffer = (FloatBuffer) curve.getBuffer(Type.Position).getData();
-            beziers.add(new BezierLine(BufferUtils.getVector3Array(vertsBuffer), materialIndex, smooth, cyclic));
-        }
-    }
-
-    /**
-     * This method loads the NURBS curve or surface.
-     * @param nurb
-     *            the NURBS data structure
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading occur
-     */
-    @SuppressWarnings("unchecked")
-    private void loadNurbSurface(Structure nurb, int materialIndex) throws BlenderFileException {
-        // loading the knots
-        List<Float>[] knots = new List[2];
-        Pointer[] pKnots = new Pointer[] { (Pointer) nurb.getFieldValue("knotsu"), (Pointer) nurb.getFieldValue("knotsv") };
-        for (int i = 0; i < knots.length; ++i) {
-            if (pKnots[i].isNotNull()) {
-                FileBlockHeader fileBlockHeader = blenderContext.getFileBlock(pKnots[i].getOldMemoryAddress());
-                BlenderInputStream blenderInputStream = blenderContext.getInputStream();
-                blenderInputStream.setPosition(fileBlockHeader.getBlockPosition());
-                int knotsAmount = fileBlockHeader.getCount() * fileBlockHeader.getSize() / 4;
-                knots[i] = new ArrayList<Float>(knotsAmount);
-                for (int j = 0; j < knotsAmount; ++j) {
-                    knots[i].add(Float.valueOf(blenderInputStream.readFloat()));
-                }
-            }
-        }
-
-        // loading the flags and orders (basis functions degrees)
-        int flag = ((Number) nurb.getFieldValue("flag")).intValue();
-        boolean smooth = (flag & FLAG_SMOOTH) != 0;
-        int flagU = ((Number) nurb.getFieldValue("flagu")).intValue();
-        int flagV = ((Number) nurb.getFieldValue("flagv")).intValue();
-        int orderU = ((Number) nurb.getFieldValue("orderu")).intValue();
-        int orderV = ((Number) nurb.getFieldValue("orderv")).intValue();
-
-        // loading control points and their weights
-        int pntsU = ((Number) nurb.getFieldValue("pntsu")).intValue();
-        int pntsV = ((Number) nurb.getFieldValue("pntsv")).intValue();
-        List<Structure> bPoints = ((Pointer) nurb.getFieldValue("bp")).fetchData();
-        List<List<Vector4f>> controlPoints = new ArrayList<List<Vector4f>>(pntsV);
-        for (int i = 0; i < pntsV; ++i) {
-            List<Vector4f> uControlPoints = new ArrayList<Vector4f>(pntsU);
-            for (int j = 0; j < pntsU; ++j) {
-                DynamicArray<Float> vec = (DynamicArray<Float>) bPoints.get(j + i * pntsU).getFieldValue("vec");
-                if (blenderContext.getBlenderKey().isFixUpAxis()) {
-                    uControlPoints.add(new Vector4f(vec.get(0).floatValue(), vec.get(2).floatValue(), -vec.get(1).floatValue(), vec.get(3).floatValue()));
-                } else {
-                    uControlPoints.add(new Vector4f(vec.get(0).floatValue(), vec.get(1).floatValue(), vec.get(2).floatValue(), vec.get(3).floatValue()));
-                }
-            }
-            if ((flagU & 0x01) != 0) {
-                for (int k = 0; k < orderU - 1; ++k) {
-                    uControlPoints.add(uControlPoints.get(k));
-                }
-            }
-            controlPoints.add(uControlPoints);
-        }
-        if ((flagV & 0x01) != 0) {
-            for (int k = 0; k < orderV - 1; ++k) {
-                controlPoints.add(controlPoints.get(k));
-            }
-        }
-
-        int originalVerticesAmount = vertices.size();
-        int resolu = ((Number) nurb.getFieldValue("resolu")).intValue();
-        if (knots[1] == null) {// creating the NURB curve
-            Curve curve = new Curve(new Spline(controlPoints.get(0), knots[0]), resolu);
-            FloatBuffer vertsBuffer = (FloatBuffer) curve.getBuffer(Type.Position).getData();
-            beziers.add(new BezierLine(BufferUtils.getVector3Array(vertsBuffer), materialIndex, smooth, false));
-        } else {// creating the NURB surface
-            int resolv = ((Number) nurb.getFieldValue("resolv")).intValue();
-            int uSegments = resolu * controlPoints.get(0).size() - 1;
-            int vSegments = resolv * controlPoints.size() - 1;
-            Surface nurbSurface = Surface.createNurbsSurface(controlPoints, knots, uSegments, vSegments, orderU, orderV, smooth);
-
-            FloatBuffer vertsBuffer = (FloatBuffer) nurbSurface.getBuffer(Type.Position).getData();
-            vertices.addAll(Arrays.asList(BufferUtils.getVector3Array(vertsBuffer)));
-            FloatBuffer normalsBuffer = (FloatBuffer) nurbSurface.getBuffer(Type.Normal).getData();
-            normals.addAll(Arrays.asList(BufferUtils.getVector3Array(normalsBuffer)));
-
-            IndexBuffer indexBuffer = nurbSurface.getIndexBuffer();
-            for (int i = 0; i < indexBuffer.size(); i += 3) {
-                int index1 = indexBuffer.get(i) + originalVerticesAmount;
-                int index2 = indexBuffer.get(i + 1) + originalVerticesAmount;
-                int index3 = indexBuffer.get(i + 2) + originalVerticesAmount;
-                faces.add(new Face(new Integer[] { index1, index2, index3 }, smooth, materialIndex, null, null, this));
-            }
-        }
-    }
-
-    /**
-     * The method loads the bevel object that should be applied to curve. It can either be another curve or a generated one
-     * based on the bevel generating parameters in blender.
-     * @param curveStructure
-     *            the structure with the curve's data (the curve being loaded, NOT the bevel curve)
-     * @return the curve's bevel object
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading occur
-     */
-    @SuppressWarnings("unchecked")
-    private CurvesTemporalMesh loadBevelObject(Structure curveStructure) throws BlenderFileException {
-        CurvesTemporalMesh bevelObject = null;
-        Pointer pBevelObject = (Pointer) curveStructure.getFieldValue("bevobj");
-        boolean cyclic = false;
-        if (pBevelObject.isNotNull()) {
-            Structure bevelObjectStructure = pBevelObject.fetchData().get(0);
-            DynamicArray<Number> scaleArray = (DynamicArray<Number>) bevelObjectStructure.getFieldValue("size");
-            Vector3f scale = blenderContext.getBlenderKey().isFixUpAxis() ? new Vector3f(scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()) : new Vector3f(scaleArray.get(0).floatValue(), scaleArray.get(2).floatValue(), scaleArray.get(1).floatValue());
-            Pointer pBevelStructure = (Pointer) bevelObjectStructure.getFieldValue("data");
-            Structure bevelStructure = pBevelStructure.fetchData().get(0);
-            bevelObject = new CurvesTemporalMesh(bevelStructure, scale, false, blenderContext);
-
-            // transforming the bezier lines from plane XZ to plane YZ
-            for (BezierLine bl : bevelObject.beziers) {
-                for (Vector3f v : bl.vertices) {
-                    // casting the bezier curve orthogonally on the plane XZ (making Y = 0) and then moving the plane XZ to ZY in a way that:
-                    // -Z => +Y and +X => +Z and +Y => +X (but because casting would make Y = 0, then we simply set X = 0)
-                    v.y = -v.z;
-                    v.z = v.x;
-                    v.x = 0;
-                }
-
-                // bevel curves should not have repeated the first vertex at the end when they are cyclic (this is handled differently)
-                if (bl.isCyclic()) {
-                    bl.removeLastVertex();
-                }
-            }
-        } else {
-            fillCaps = false;// this option is inactive in blender when there is no bevel object applied
-            int bevResol = ((Number) curveStructure.getFieldValue("bevresol")).intValue();
-            float extrude = ((Number) curveStructure.getFieldValue("ext1")).floatValue();
-            float bevelDepth = ((Number) curveStructure.getFieldValue("ext2")).floatValue();
-            float offset = ((Number) curveStructure.getFieldValue("offset", 0)).floatValue();
-            if (offset != 0) {
-                // TODO: add support for offset parameter
-                LOGGER.warning("Offset parameter not yet supported.");
-            }
-            Curve bevelCurve = null;
-            if (bevelDepth > 0.0f) {
-                float handlerLength = bevelDepth / 2.0f;
-                cyclic = !isFront && !isBack;
-                List<Vector3f> conrtolPoints = new ArrayList<Vector3f>();
-
-                // blenders from 2.49 to 2.52 did not pay attention to fron and back faces
-                // so in order to draw the scene exactly as it is in different blender versions the blender version is checked here
-                // when neither fron and back face is selected all version behave the same and draw full bevel around the curve
-                if (cyclic || blenderContext.getBlenderVersion() < 253) {
-                    conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, 0));
-                    conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, -handlerLength));
-
-                    conrtolPoints.add(new Vector3f(0, -extrude - handlerLength, -bevelDepth));
-                    conrtolPoints.add(new Vector3f(0, -extrude, -bevelDepth));
-                    conrtolPoints.add(new Vector3f(0, -extrude + handlerLength, -bevelDepth));
-
-                    if (extrude > 0) {
-                        conrtolPoints.add(new Vector3f(0, extrude - handlerLength, -bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, extrude, -bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, extrude + handlerLength, -bevelDepth));
-                    }
-
-                    conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, -handlerLength));
-                    conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, 0));
-
-                    if (cyclic) {
-                        conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, handlerLength));
-
-                        conrtolPoints.add(new Vector3f(0, extrude + handlerLength, bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, extrude, bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, extrude - handlerLength, bevelDepth));
-
-                        if (extrude > 0) {
-                            conrtolPoints.add(new Vector3f(0, -extrude + handlerLength, bevelDepth));
-                            conrtolPoints.add(new Vector3f(0, -extrude, bevelDepth));
-                            conrtolPoints.add(new Vector3f(0, -extrude - handlerLength, bevelDepth));
-                        }
-
-                        conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, handlerLength));
-                        conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, 0));
-                    }
-                } else {
-                    if (extrude > 0) {
-                        if (isBack) {
-                            conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, 0));
-                            conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, -handlerLength));
-
-                            conrtolPoints.add(new Vector3f(0, -extrude - handlerLength, -bevelDepth));
-                        }
-
-                        conrtolPoints.add(new Vector3f(0, -extrude, -bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, -extrude + handlerLength, -bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, extrude - handlerLength, -bevelDepth));
-                        conrtolPoints.add(new Vector3f(0, extrude, -bevelDepth));
-
-                        if (isFront) {
-                            conrtolPoints.add(new Vector3f(0, extrude + handlerLength, -bevelDepth));
-
-                            conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, -handlerLength));
-                            conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, 0));
-                        }
-                    } else {
-                        if (isFront && isBack) {
-                            conrtolPoints.add(new Vector3f(0, -bevelDepth, 0));
-                            conrtolPoints.add(new Vector3f(0, -bevelDepth, -handlerLength));
-
-                            conrtolPoints.add(new Vector3f(0, -handlerLength, -bevelDepth));
-                            conrtolPoints.add(new Vector3f(0, 0, -bevelDepth));
-                            conrtolPoints.add(new Vector3f(0, handlerLength, -bevelDepth));
-
-                            conrtolPoints.add(new Vector3f(0, bevelDepth, -handlerLength));
-                            conrtolPoints.add(new Vector3f(0, bevelDepth, 0));
-                        } else {
-                            if (isBack) {
-                                conrtolPoints.add(new Vector3f(0, -bevelDepth, 0));
-                                conrtolPoints.add(new Vector3f(0, -bevelDepth, -handlerLength));
-
-                                conrtolPoints.add(new Vector3f(0, -handlerLength, -bevelDepth));
-                                conrtolPoints.add(new Vector3f(0, 0, -bevelDepth));
-                            } else {
-                                conrtolPoints.add(new Vector3f(0, 0, -bevelDepth));
-                                conrtolPoints.add(new Vector3f(0, handlerLength, -bevelDepth));
-
-                                conrtolPoints.add(new Vector3f(0, bevelDepth, -handlerLength));
-                                conrtolPoints.add(new Vector3f(0, bevelDepth, 0));
-                            }
-                        }
-                    }
-                }
-
-                bevelCurve = new Curve(new Spline(SplineType.Bezier, conrtolPoints, 0, false), bevResol);
-            } else if (extrude > 0.0f) {
-                Spline bevelSpline = new Spline(SplineType.Linear, new Vector3f[] { new Vector3f(0, extrude, 0), new Vector3f(0, -extrude, 0) }, 1, false);
-                bevelCurve = new Curve(bevelSpline, bevResol);
-            }
-            if (bevelCurve != null) {
-                bevelObject = new CurvesTemporalMesh(blenderContext);
-                FloatBuffer vertsBuffer = (FloatBuffer) bevelCurve.getBuffer(Type.Position).getData();
-                Vector3f[] verts = BufferUtils.getVector3Array(vertsBuffer);
-                if (cyclic) {// get rid of the last vertex which is identical to the first one
-                    verts = Arrays.copyOf(verts, verts.length - 1);
-                }
-                bevelObject.beziers.add(new BezierLine(verts, 0, false, cyclic));
-            }
-        }
-        return bevelObject;
-    }
-
-    private List<BezierLine> getScaledBeziers() {
-        if (scale.equals(Vector3f.UNIT_XYZ)) {
-            return beziers;
-        }
-        List<BezierLine> result = new ArrayList<BezierLine>();
-        for (BezierLine bezierLine : beziers) {
-            result.add(bezierLine.scale(scale));
-        }
-        return result;
-    }
-
-    /**
-     * This method applies bevel and taper objects to the curve.
-     * @param curve
-     *            the curve we apply the objects to
-     * @param bevelObject
-     *            the bevel object
-     * @param taperObject
-     *            the taper object
-     * @param blenderContext
-     *            the blender context
-     * @return a list of geometries representing the beveled and/or tapered curve
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading occur
-     */
-    private CurvesTemporalMesh applyBevelAndTaper(CurvesTemporalMesh curve, CurvesTemporalMesh bevelObject, CurvesTemporalMesh taperObject, BlenderContext blenderContext) throws BlenderFileException {
-        List<BezierLine> bevelBezierLines = bevelObject.getScaledBeziers();
-        List<BezierLine> curveLines = curve.beziers;
-        if (bevelBezierLines.size() == 0 || curveLines.size() == 0) {
-            return null;
-        }
-
-        CurvesTemporalMesh result = new CurvesTemporalMesh(blenderContext);
-        for (BezierLine curveLine : curveLines) {
-            Vector3f[] curveLineVertices = curveLine.getVertices(bevelStart, bevelEnd);
-
-            for (BezierLine bevelBezierLine : bevelBezierLines) {
-                CurvesTemporalMesh partResult = new CurvesTemporalMesh(blenderContext);
-
-                Vector3f[] bevelLineVertices = bevelBezierLine.getVertices();
-                List<Vector3f[]> bevels = new ArrayList<Vector3f[]>();
-
-                Vector3f[] bevelPoints = curvesHelper.transformToFirstLineOfBevelPoints(bevelLineVertices, curveLineVertices[0], curveLineVertices[1]);
-                bevels.add(bevelPoints);
-                for (int i = 1; i < curveLineVertices.length - 1; ++i) {
-                    bevelPoints = curvesHelper.transformBevel(bevelPoints, curveLineVertices[i - 1], curveLineVertices[i], curveLineVertices[i + 1]);
-                    bevels.add(bevelPoints);
-                }
-                bevelPoints = curvesHelper.transformBevel(bevelPoints, curveLineVertices[curveLineVertices.length - 2], curveLineVertices[curveLineVertices.length - 1], null);
-                bevels.add(bevelPoints);
-
-                Vector3f subtractResult = new Vector3f();
-                if (bevels.size() > 2) {
-                    // changing the first and last bevel so that they are parallel to their neighbours (blender works this way)
-                    // notice this implicates that the distances of every corresponding point in the two bevels must be identical and
-                    // equal to the distance between the points on curve that define the bevel position
-                    // so instead doing complicated rotations on each point we will simply properly translate each of them
-                    int[][] pointIndexes = new int[][] { { 0, 1 }, { curveLineVertices.length - 1, curveLineVertices.length - 2 } };
-                    for (int[] indexes : pointIndexes) {
-                        float distance = curveLineVertices[indexes[1]].subtract(curveLineVertices[indexes[0]], subtractResult).length();
-                        Vector3f[] bevel = bevels.get(indexes[0]);
-                        Vector3f[] nextBevel = bevels.get(indexes[1]);
-                        for (int i = 0; i < bevel.length; ++i) {
-                            float d = bevel[i].subtract(nextBevel[i], subtractResult).length();
-                            subtractResult.normalizeLocal().multLocal(distance - d);
-                            bevel[i].addLocal(subtractResult);
-                        }
-                    }
-                }
-
-                if (taperObject != null) {
-                    float curveLength = curveLine.getLength(), lengthAlongCurve = bevelStart;
-                    for (int i = 0; i < curveLineVertices.length; ++i) {
-                        if (i > 0) {
-                            lengthAlongCurve += curveLineVertices[i].subtract(curveLineVertices[i - 1], subtractResult).length();
-                        }
-                        float taperScale = -taperObject.getValueAlongCurve(lengthAlongCurve / curveLength).z * taperObject.scale.z;
-                        if (taperScale != 1) {
-                            this.applyScale(bevels.get(i), curveLineVertices[i], taperScale);
-                        }
-                    }
-                }
-
-                // adding vertices to the part result
-                for (Vector3f[] bevel : bevels) {
-                    for (Vector3f d : bevel) {
-                        partResult.getVertices().add(d);
-                    }
-                }
-
-                // preparing faces for the part result (each face is a quad)
-                int bevelVertCount = bevelPoints.length;
-                for (int i = 0; i < bevels.size() - 1; ++i) {
-                    for (int j = 0; j < bevelVertCount - 1; ++j) {
-                        Integer[] indexes = new Integer[] { i * bevelVertCount + j + 1, (i + 1) * bevelVertCount + j + 1, (i + 1) * bevelVertCount + j, i * bevelVertCount + j };
-                        partResult.getFaces().add(new Face(indexes, curveLine.isSmooth(), curveLine.getMaterialNumber(), null, null, partResult));
-                        partResult.getEdges().add(new Edge(indexes[0], indexes[1], 0, true, partResult));
-                        partResult.getEdges().add(new Edge(indexes[1], indexes[2], 0, true, partResult));
-                        partResult.getEdges().add(new Edge(indexes[2], indexes[3], 0, true, partResult));
-                        partResult.getEdges().add(new Edge(indexes[3], indexes[0], 0, true, partResult));
-                    }
-                    if (bevelBezierLine.isCyclic()) {
-                        int j = bevelVertCount - 1;
-                        Integer[] indexes = new Integer[] { i * bevelVertCount, (i + 1) * bevelVertCount, (i + 1) * bevelVertCount + j, i * bevelVertCount + j };
-                        partResult.getFaces().add(new Face(indexes, curveLine.isSmooth(), curveLine.getMaterialNumber(), null, null, partResult));
-                        partResult.getEdges().add(new Edge(indexes[0], indexes[1], 0, true, partResult));
-                        partResult.getEdges().add(new Edge(indexes[1], indexes[2], 0, true, partResult));
-                        partResult.getEdges().add(new Edge(indexes[2], indexes[3], 0, true, partResult));
-                        partResult.getEdges().add(new Edge(indexes[3], indexes[0], 0, true, partResult));
-                    }
-                }
-
-                partResult.generateNormals();
-
-                if (fillCaps) {// caps in blender behave as if they weren't affected by the smooth factor
-                    // START CAP
-                    Vector3f[] cap = bevels.get(0);
-                    List<Integer> capIndexes = new ArrayList<Integer>(cap.length);
-                    Vector3f capNormal = curveLineVertices[0].subtract(curveLineVertices[1]).normalizeLocal();
-                    for (int i = 0; i < cap.length; ++i) {
-                        capIndexes.add(partResult.getVertices().size());
-                        partResult.getVertices().add(cap[i]);
-                        partResult.getNormals().add(capNormal);
-                    }
-                    Collections.reverse(capIndexes);// the indexes ned to be reversed for the face to have fron face outside the beveled line
-                    partResult.getFaces().add(new Face(capIndexes.toArray(new Integer[capIndexes.size()]), false, curveLine.getMaterialNumber(), null, null, partResult));
-                    for (int i = 1; i < capIndexes.size(); ++i) {
-                        partResult.getEdges().add(new Edge(capIndexes.get(i - 1), capIndexes.get(i), 0, true, partResult));
-                    }
-
-                    // END CAP
-                    cap = bevels.get(bevels.size() - 1);
-                    capIndexes.clear();
-                    capNormal = curveLineVertices[curveLineVertices.length - 1].subtract(curveLineVertices[curveLineVertices.length - 2]).normalizeLocal();
-                    for (int i = 0; i < cap.length; ++i) {
-                        capIndexes.add(partResult.getVertices().size());
-                        partResult.getVertices().add(cap[i]);
-                        partResult.getNormals().add(capNormal);
-                    }
-                    partResult.getFaces().add(new Face(capIndexes.toArray(new Integer[capIndexes.size()]), false, curveLine.getMaterialNumber(), null, null, partResult));
-                    for (int i = 1; i < capIndexes.size(); ++i) {
-                        partResult.getEdges().add(new Edge(capIndexes.get(i - 1), capIndexes.get(i), 0, true, partResult));
-                    }
-                }
-
-                result.append(partResult);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * The method generates normals for the curve. If any normals were already stored they are discarded.
-     */
-    private void generateNormals() {
-        Map<Integer, Vector3f> normalMap = new TreeMap<Integer, Vector3f>();
-        for (Face face : faces) {
-            // the first 3 verts are enough here (all faces are triangles except for the caps, but those are fully flat anyway)
-            int index1 = face.getIndexes().get(0);
-            int index2 = face.getIndexes().get(1);
-            int index3 = face.getIndexes().get(2);
-
-            Vector3f n = FastMath.computeNormal(vertices.get(index1), vertices.get(index2), vertices.get(index3));
-            for (int index : face.getIndexes()) {
-                Vector3f normal = normalMap.get(index);
-                if (normal == null) {
-                    normalMap.put(index, n.clone());
-                } else {
-                    normal.addLocal(n).normalizeLocal();
-                }
-            }
-        }
-
-        normals.clear();
-        Collections.addAll(normals, new Vector3f[normalMap.size()]);
-        for (Entry<Integer, Vector3f> entry : normalMap.entrySet()) {
-            normals.set(entry.getKey(), entry.getValue());
-        }
-    }
-
-    /**
-     * the method applies scale for the given bevel points. The points table is
-     * being modified so expect your result there.
-     * 
-     * @param points
-     *            the bevel points
-     * @param centerPoint
-     *            the center point of the bevel
-     * @param scale
-     *            the scale to be applied
-     */
-    private void applyScale(Vector3f[] points, Vector3f centerPoint, float scale) {
-        Vector3f taperScaleVector = new Vector3f();
-        for (Vector3f p : points) {
-            taperScaleVector.set(centerPoint).subtractLocal(p).multLocal(1 - scale);
-            p.addLocal(taperScaleVector);
-        }
-    }
-
-    /**
-     * A helper class that represents a single bezier line. It consists of Edge's and allows to
-     * get a subline of a length of the line.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static class BezierLine {
-        /** The edges of the bezier line. */
-        private Vector3f[] vertices;
-        /** The material number of the line. */
-        private int        materialNumber;
-        /** Indicates if the line is smooth of flat. */
-        private boolean    smooth;
-        /** The length of the line. */
-        private float      length;
-        /** Indicates if the current line is cyclic or not. */
-        private boolean    cyclic;
-
-        public BezierLine(Vector3f[] vertices, int materialNumber, boolean smooth, boolean cyclik) {
-            this.vertices = vertices;
-            this.materialNumber = materialNumber;
-            this.smooth = smooth;
-            cyclic = cyclik;
-            this.recomputeLength();
-        }
-
-        public BezierLine scale(Vector3f scale) {
-            BezierLine result = new BezierLine(vertices, materialNumber, smooth, cyclic);
-            result.vertices = new Vector3f[vertices.length];
-            for (int i = 0; i < vertices.length; ++i) {
-                result.vertices[i] = vertices[i].mult(scale);
-            }
-            result.recomputeLength();
-            return result;
-        }
-
-        public void removeLastVertex() {
-            Vector3f[] newVertices = new Vector3f[vertices.length - 1];
-            for (int i = 0; i < vertices.length - 1; ++i) {
-                newVertices[i] = vertices[i];
-            }
-            vertices = newVertices;
-            this.recomputeLength();
-        }
-
-        private void recomputeLength() {
-            length = 0;
-            for (int i = 1; i < vertices.length; ++i) {
-                length += vertices[i - 1].distance(vertices[i]);
-            }
-            if (cyclic) {
-                // if the first vertex is repeated at the end the distance will be = 0 so it won't affect the result, and if it is not repeated
-                // then it is necessary to add the length between the last and the first vertex
-                length += vertices[vertices.length - 1].distance(vertices[0]);
-            }
-        }
-
-        public Vector3f[] getVertices() {
-            return this.getVertices(0, 1);
-        }
-
-        public Vector3f[] getVertices(float startSlice, float endSlice) {
-            if (startSlice == 0 && endSlice == 1) {
-                return vertices;
-            }
-            List<Vector3f> result = new ArrayList<Vector3f>();
-            float length = this.getLength(), temp = 0;
-            float startSliceLength = length * startSlice;
-            float endSliceLength = length * endSlice;
-            int index = 1;
-
-            if (startSlice > 0) {
-                while (temp < startSliceLength) {
-                    Vector3f v1 = vertices[index - 1];
-                    Vector3f v2 = vertices[index++];
-                    float edgeLength = v1.distance(v2);
-                    temp += edgeLength;
-                    if (temp == startSliceLength) {
-                        result.add(v2);
-                    } else if (temp > startSliceLength) {
-                        result.add(v1.subtract(v2).normalizeLocal().multLocal(temp - startSliceLength).addLocal(v2));
-                    }
-                }
-            }
-
-            if (endSlice < 1) {
-                if (index == vertices.length) {
-                    Vector3f v1 = vertices[vertices.length - 2];
-                    Vector3f v2 = vertices[vertices.length - 1];
-                    result.add(v1.subtract(v2).normalizeLocal().multLocal(length - endSliceLength).addLocal(v2));
-                } else {
-                    for (int i = index; i < vertices.length && temp < endSliceLength; ++i) {
-                        Vector3f v1 = vertices[index - 1];
-                        Vector3f v2 = vertices[index++];
-                        temp += v1.distance(v2);
-                        if (temp == endSliceLength) {
-                            result.add(v2);
-                        } else if (temp > endSliceLength) {
-                            result.add(v1.subtract(v2).normalizeLocal().multLocal(temp - startSliceLength).addLocal(v2));
-                        }
-                    }
-                }
-            } else {
-                result.addAll(Arrays.asList(Arrays.copyOfRange(vertices, index, vertices.length)));
-            }
-
-            return result.toArray(new Vector3f[result.size()]);
-        }
-
-        /**
-         * The method computes the value of a point at the certain relational distance from its beginning.
-         * @param alongRatio
-         *            the relative distance along the curve; should be a value between 0 and 1 inclusive;
-         *            if the value exceeds the boundaries it is truncated to them
-         * @return computed value along the curve
-         */
-        public Vector3f getValueAlongCurve(float alongRatio) {
-            alongRatio = FastMath.clamp(alongRatio, 0, 1);
-            Vector3f result = new Vector3f();
-            float probeLength = this.getLength() * alongRatio;
-            float length = 0;
-            for (int i = 1; i < vertices.length; ++i) {
-                float edgeLength = vertices[i].distance(vertices[i - 1]);
-                if (length + edgeLength > probeLength) {
-                    float ratioAlongEdge = (probeLength - length) / edgeLength;
-                    return FastMath.interpolateLinear(ratioAlongEdge, vertices[i - 1], vertices[i]);
-                } else if (length + edgeLength == probeLength) {
-                    return vertices[i];
-                }
-                length += edgeLength;
-            }
-
-            return result;
-        }
-
-        /**
-         * @return the material number of this bezier line
-         */
-        public int getMaterialNumber() {
-            return materialNumber;
-        }
-
-        /**
-         * @return indicates if the line is smooth of flat
-         */
-        public boolean isSmooth() {
-            return smooth;
-        }
-
-        /**
-         * @return the length of this bezier line
-         */
-        public float getLength() {
-            return length;
-        }
-
-        /**
-         * @return indicates if the current line is cyclic or not
-         */
-        public boolean isCyclic() {
-            return cyclic;
-        }
-    }
-}

+ 0 - 77
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/BlenderFileException.java

@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2009-2019 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.file;
-
-/**
- * This exception is thrown when blend file data is somehow invalid.
- * @author Marcin Roguski
- */
-public class BlenderFileException extends Exception {
-
-    private static final long serialVersionUID = 7573482836437866767L;
-
-    /**
-     * Constructor. Creates an exception with no description.
-     */
-    public BlenderFileException() {
-        // this constructor has no message
-    }
-
-    /**
-     * Constructor. Creates an exception containing the given message.
-     * @param message
-     *            the message describing the problem that occurred
-     */
-    public BlenderFileException(String message) {
-        super(message);
-    }
-
-    /**
-     * Constructor. Creates an exception that is based upon other thrown object. It contains the whole stacktrace then.
-     * @param throwable
-     *            an exception/error that occurred
-     */
-    public BlenderFileException(Throwable throwable) {
-        super(throwable);
-    }
-
-    /**
-     * Constructor. Creates an exception with both a message and stacktrace.
-     * @param message
-     *            the message describing the problem that occurred
-     * @param throwable
-     *            an exception/error that occurred
-     */
-    public BlenderFileException(String message, Throwable throwable) {
-        super(message, throwable);
-    }
-}

+ 0 - 371
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/BlenderInputStream.java

@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2009-2019 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.file;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.logging.Logger;
-import java.util.zip.GZIPInputStream;
-
-/**
- * An input stream with random access to data.
- * @author Marcin Roguski
- */
-public class BlenderInputStream extends InputStream {
-
-    private static final Logger LOGGER              = Logger.getLogger(BlenderInputStream.class.getName());
-    /** The default size of the blender buffer. */
-    private static final int    DEFAULT_BUFFER_SIZE = 1048576;                                             // 1MB
-    /**
-     * Size of a pointer; all pointers in the file are stored in this format. '_' means 4 bytes and '-' means 8 bytes.
-     */
-    private int                 pointerSize;
-    /**
-     * Type of byte ordering used; 'v' means little endian and 'V' means big endian.
-     */
-    private char                endianess;
-    /** Version of Blender the file was created in; '248' means version 2.48. */
-    private String              versionNumber;
-    /** The buffer we store the read data to. */
-    protected byte[]            cachedBuffer;
-    /** The total size of the stored data. */
-    protected int               size;
-    /** The current position of the read cursor. */
-    protected int               position;
-
-    /**
-     * Constructor. The input stream is stored and used to read data.
-     * @param inputStream
-     *            the stream we read data from
-     * @throws BlenderFileException
-     *             this exception is thrown if the file header has some invalid data
-     */
-    public BlenderInputStream(InputStream inputStream) throws BlenderFileException {
-        // the size value will canche while reading the file; the available() method cannot be counted on
-        try {
-            size = inputStream.available();
-        } catch (IOException e) {
-            size = 0;
-        }
-        if (size <= 0) {
-            size = BlenderInputStream.DEFAULT_BUFFER_SIZE;
-        }
-
-        // buffered input stream is used here for much faster file reading
-        BufferedInputStream bufferedInputStream;
-        if (inputStream instanceof BufferedInputStream) {
-            bufferedInputStream = (BufferedInputStream) inputStream;
-        } else {
-            bufferedInputStream = new BufferedInputStream(inputStream);
-        }
-
-        try {
-            this.readStreamToCache(bufferedInputStream);
-        } catch (IOException e) {
-            throw new BlenderFileException("Problems occurred while caching the file!", e);
-        } finally {
-            try {
-                inputStream.close();
-            } catch (IOException e) {
-                LOGGER.warning("Unable to close stream with blender file.");
-            }
-        }
-
-        try {
-            this.readFileHeader();
-        } catch (BlenderFileException e) {// the file might be packed, don't panic, try one more time ;)
-            this.decompressFile();
-            position = 0;
-            this.readFileHeader();
-        }
-    }
-
-    /**
-     * This method reads the whole stream into a buffer.
-     * @param inputStream
-     *            the stream to read the file data from
-     * @throws IOException
-     *             an exception is thrown when data read from the stream is invalid or there are problems with i/o
-     *             operations
-     */
-    private void readStreamToCache(InputStream inputStream) throws IOException {
-        int data = inputStream.read();
-        cachedBuffer = new byte[size];
-        size = 0;// this will count the actual size
-        while (data != -1) {
-            if (size >= cachedBuffer.length) {// widen the cached array
-                byte[] newBuffer = new byte[cachedBuffer.length + (cachedBuffer.length >> 1)];
-                System.arraycopy(cachedBuffer, 0, newBuffer, 0, cachedBuffer.length);
-                cachedBuffer = newBuffer;
-            }
-            cachedBuffer[size++] = (byte) data;
-            data = inputStream.read();
-        }
-    }
-
-    /**
-     * This method is used when the blender file is gzipped. It decompresses the data and stores it back into the
-     * cachedBuffer field.
-     */
-    private void decompressFile() {
-        GZIPInputStream gis = null;
-        try {
-            gis = new GZIPInputStream(new ByteArrayInputStream(cachedBuffer));
-            this.readStreamToCache(gis);
-        } catch (IOException e) {
-            throw new IllegalStateException("IO errors occurred where they should NOT! " + "The data is already buffered at this point!", e);
-        } finally {
-            try {
-                if (gis != null) {
-                    gis.close();
-                }
-            } catch (IOException e) {
-                LOGGER.warning(e.getMessage());
-            }
-        }
-    }
-
-    /**
-     * This method loads the header from the given stream during instance creation.
-     * @param inputStream
-     *            the stream we read the header from
-     * @throws BlenderFileException
-     *             this exception is thrown if the file header has some invalid data
-     */
-    private void readFileHeader() throws BlenderFileException {
-        byte[] identifier = new byte[7];
-        int bytesRead = this.readBytes(identifier);
-        if (bytesRead != 7) {
-            throw new BlenderFileException("Error reading header identifier. Only " + bytesRead + " bytes read and there should be 7!");
-        }
-        String strIdentifier = new String(identifier);
-        if (!"BLENDER".equals(strIdentifier)) {
-            throw new BlenderFileException("Wrong file identifier: " + strIdentifier + "! Should be 'BLENDER'!");
-        }
-        char pointerSizeSign = (char) this.readByte();
-        if (pointerSizeSign == '-') {
-            pointerSize = 8;
-        } else if (pointerSizeSign == '_') {
-            pointerSize = 4;
-        } else {
-            throw new BlenderFileException("Invalid pointer size character! Should be '_' or '-' and there is: " + pointerSizeSign);
-        }
-        endianess = (char) this.readByte();
-        if (endianess != 'v' && endianess != 'V') {
-            throw new BlenderFileException("Unknown endianess value! 'v' or 'V' expected and found: " + endianess);
-        }
-        byte[] versionNumber = new byte[3];
-        bytesRead = this.readBytes(versionNumber);
-        if (bytesRead != 3) {
-            throw new BlenderFileException("Error reading version numberr. Only " + bytesRead + " bytes read and there should be 3!");
-        }
-        this.versionNumber = new String(versionNumber);
-    }
-
-    @Override
-    public int read() throws IOException {
-        return this.readByte();
-    }
-
-    /**
-     * This method reads 1 byte from the stream.
-     * It works just in the way the read method does.
-     * It just not throw an exception because at this moment the whole file
-     * is loaded into buffer, so no need for IOException to be thrown.
-     * @return a byte from the stream (1 bytes read)
-     */
-    public int readByte() {
-        return cachedBuffer[position++] & 0xFF;
-    }
-
-    /**
-     * This method reads a bytes number big enough to fill the table.
-     * It does not throw exceptions so it is for internal use only.
-     * @param bytes
-     *            an array to be filled with data
-     * @return number of read bytes (a length of array actually)
-     */
-    private int readBytes(byte[] bytes) {
-        for (int i = 0; i < bytes.length; ++i) {
-            bytes[i] = (byte) this.readByte();
-        }
-        return bytes.length;
-    }
-
-    /**
-     * This method reads 2-byte number from the stream.
-     * @return a number from the stream (2 bytes read)
-     */
-    public int readShort() {
-        int part1 = this.readByte();
-        int part2 = this.readByte();
-        if (endianess == 'v') {
-            return (part2 << 8) + part1;
-        } else {
-            return (part1 << 8) + part2;
-        }
-    }
-
-    /**
-     * This method reads 4-byte number from the stream.
-     * @return a number from the stream (4 bytes read)
-     */
-    public int readInt() {
-        int part1 = this.readByte();
-        int part2 = this.readByte();
-        int part3 = this.readByte();
-        int part4 = this.readByte();
-        if (endianess == 'v') {
-            return (part4 << 24) + (part3 << 16) + (part2 << 8) + part1;
-        } else {
-            return (part1 << 24) + (part2 << 16) + (part3 << 8) + part4;
-        }
-    }
-
-    /**
-     * This method reads 4-byte floating point number (float) from the stream.
-     * @return a number from the stream (4 bytes read)
-     */
-    public float readFloat() {
-        int intValue = this.readInt();
-        return Float.intBitsToFloat(intValue);
-    }
-
-    /**
-     * This method reads 8-byte number from the stream.
-     * @return a number from the stream (8 bytes read)
-     */
-    public long readLong() {
-        long part1 = this.readInt();
-        long part2 = this.readInt();
-        long result = -1;
-        if (endianess == 'v') {
-            result = part2 << 32 | part1;
-        } else {
-            result = part1 << 32 | part2;
-        }
-        return result;
-    }
-
-    /**
-     * This method reads 8-byte floating point number (double) from the stream.
-     * @return a number from the stream (8 bytes read)
-     */
-    public double readDouble() {
-        long longValue = this.readLong();
-        return Double.longBitsToDouble(longValue);
-    }
-
-    /**
-     * This method reads the pointer value. Depending on the pointer size defined in the header, the stream reads either
-     * 4 or 8 bytes of data.
-     * @return the pointer value
-     */
-    public long readPointer() {
-        if (pointerSize == 4) {
-            return this.readInt();
-        }
-        return this.readLong();
-    }
-
-    /**
-     * This method reads the string. It assumes the string is terminated with zero in the stream.
-     * @return the string read from the stream
-     */
-    public String readString() {
-        StringBuilder stringBuilder = new StringBuilder();
-        int data = this.readByte();
-        while (data != 0) {
-            stringBuilder.append((char) data);
-            data = this.readByte();
-        }
-        return stringBuilder.toString();
-    }
-
-    /**
-     * This method sets the current position of the read cursor.
-     * @param position
-     *            the position of the read cursor
-     */
-    public void setPosition(int position) {
-        this.position = position;
-    }
-
-    /**
-     * This method returns the position of the read cursor.
-     * @return the position of the read cursor
-     */
-    public int getPosition() {
-        return position;
-    }
-
-    /**
-     * This method returns the blender version number where the file was created.
-     * @return blender version number
-     */
-    public String getVersionNumber() {
-        return versionNumber;
-    }
-
-    /**
-     * This method returns the size of the pointer.
-     * @return the size of the pointer
-     */
-    public int getPointerSize() {
-        return pointerSize;
-    }
-
-    /**
-     * This method aligns cursor position forward to a given amount of bytes.
-     * @param bytesAmount
-     *            the byte amount to which we aligh the cursor
-     */
-    public void alignPosition(int bytesAmount) {
-        if (bytesAmount <= 0) {
-            throw new IllegalArgumentException("Alignment byte number shoulf be positivbe!");
-        }
-        long move = position % bytesAmount;
-        if (move > 0) {
-            position += bytesAmount - move;
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        // this method is unimplemented because some loaders (ie. TGALoader) tend close the stream given from the outside
-        // because the images can be stored directly in the blender file then this stream is properly positioned and given to the loader
-        // to read the image file, that is why we do not want it to be closed before the reading is done
-        // and anyway this stream is only a cached buffer, so it does not hold any open connection to anything
-    }
-}

+ 0 - 203
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/DnaBlockData.java

@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2009-2018 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.file;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The data block containing the description of the file.
- * @author Marcin Roguski (Kaelthas)
- */
-public class DnaBlockData {
-
-    private static final int             SDNA_ID = 'S' << 24 | 'D' << 16 | 'N' << 8 | 'A'; // SDNA
-    private static final int             NAME_ID = 'N' << 24 | 'A' << 16 | 'M' << 8 | 'E'; // NAME
-    private static final int             TYPE_ID = 'T' << 24 | 'Y' << 16 | 'P' << 8 | 'E'; // TYPE
-    private static final int             TLEN_ID = 'T' << 24 | 'L' << 16 | 'E' << 8 | 'N'; // TLEN
-    private static final int             STRC_ID = 'S' << 24 | 'T' << 16 | 'R' << 8 | 'C'; // STRC
-    /** Structures available inside the file. */
-    private final Structure[]            structures;
-    /** A map that helps finding a structure by type. */
-    private final Map<String, Structure> structuresMap;
-
-    /**
-     * Constructor. Loads the block from the given stream during instance creation.
-     * @param inputStream
-     *            the stream we read the block from
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is throw if the blend file is invalid or somehow corrupted
-     */
-    public DnaBlockData(BlenderInputStream inputStream, BlenderContext blenderContext) throws BlenderFileException {
-        int identifier;
-
-        // reading 'SDNA' identifier
-        identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte();
-
-        if (identifier != SDNA_ID) {
-            throw new BlenderFileException("Invalid identifier! '" + this.toString(SDNA_ID) + "' expected and found: " + this.toString(identifier));
-        }
-
-        // reading names
-        identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte();
-        if (identifier != NAME_ID) {
-            throw new BlenderFileException("Invalid identifier! '" + this.toString(NAME_ID) + "' expected and found: " + this.toString(identifier));
-        }
-        int amount = inputStream.readInt();
-        if (amount <= 0) {
-            throw new BlenderFileException("The names amount number should be positive!");
-        }
-        String[] names = new String[amount];
-        for (int i = 0; i < amount; ++i) {
-            names[i] = inputStream.readString();
-        }
-
-        // reading types
-        inputStream.alignPosition(4);
-        identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte();
-        if (identifier != TYPE_ID) {
-            throw new BlenderFileException("Invalid identifier! '" + this.toString(TYPE_ID) + "' expected and found: " + this.toString(identifier));
-        }
-        amount = inputStream.readInt();
-        if (amount <= 0) {
-            throw new BlenderFileException("The types amount number should be positive!");
-        }
-        String[] types = new String[amount];
-        for (int i = 0; i < amount; ++i) {
-            types[i] = inputStream.readString();
-        }
-
-        // reading lengths
-        inputStream.alignPosition(4);
-        identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte();
-        if (identifier != TLEN_ID) {
-            throw new BlenderFileException("Invalid identifier! '" + this.toString(TLEN_ID) + "' expected and found: " + this.toString(identifier));
-        }
-        int[] lengths = new int[amount];// theamount is the same as int types
-        for (int i = 0; i < amount; ++i) {
-            lengths[i] = inputStream.readShort();
-        }
-
-        // reading structures
-        inputStream.alignPosition(4);
-        identifier = inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte();
-        if (identifier != STRC_ID) {
-            throw new BlenderFileException("Invalid identifier! '" + this.toString(STRC_ID) + "' expected and found: " + this.toString(identifier));
-        }
-        amount = inputStream.readInt();
-        if (amount <= 0) {
-            throw new BlenderFileException("The structures amount number should be positive!");
-        }
-        structures = new Structure[amount];
-        structuresMap = new HashMap<String, Structure>(amount);
-        for (int i = 0; i < amount; ++i) {
-            structures[i] = new Structure(inputStream, names, types, blenderContext);
-            if (structuresMap.containsKey(structures[i].getType())) {
-                throw new BlenderFileException("Blend file seems to be corrupted! The type " + structures[i].getType() + " is defined twice!");
-            }
-            structuresMap.put(structures[i].getType(), structures[i]);
-        }
-    }
-
-    /**
-     * This method returns the amount of the structures.
-     * @return the amount of the structures
-     */
-    public int getStructuresCount() {
-        return structures.length;
-    }
-
-    /**
-     * This method returns the structure of the given index.
-     * @param index
-     *            the index of the structure
-     * @return the structure of the given index
-     */
-    public Structure getStructure(int index) {
-        try {
-            return (Structure) structures[index].clone();
-        } catch (CloneNotSupportedException e) {
-            throw new IllegalStateException("Structure should be clonable!!!", e);
-        }
-    }
-
-    /**
-     * This method returns a structure of the given name. If the name does not exists then null is returned.
-     * @param name
-     *            the name of the structure
-     * @return the required structure or null if the given name is inapropriate
-     */
-    public Structure getStructure(String name) {
-        try {
-            return (Structure) structuresMap.get(name).clone();
-        } catch (CloneNotSupportedException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * This method indicates if the structure of the given name exists.
-     * @param name
-     *            the name of the structure
-     * @return true if the structure exists and false otherwise
-     */
-    public boolean hasStructure(String name) {
-        return structuresMap.containsKey(name);
-    }
-
-    /**
-     * This method converts the given identifier code to string.
-     * @param code
-     *            the code that is to be converted
-     * @return the string value of the identifier
-     */
-    private String toString(int code) {
-        char c1 = (char) ((code & 0xFF000000) >> 24);
-        char c2 = (char) ((code & 0xFF0000) >> 16);
-        char c3 = (char) ((code & 0xFF00) >> 8);
-        char c4 = (char) (code & 0xFF);
-        return String.valueOf(c1) + c2 + c3 + c4;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder stringBuilder = new StringBuilder("=============== ").append(SDNA_ID).append('\n');
-        for (Structure structure : structures) {
-            stringBuilder.append(structure.toString()).append('\n');
-        }
-        return stringBuilder.append("===============").toString();
-    }
-}

+ 0 - 135
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/DynamicArray.java

@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2009-2018 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.file;
-
-/**
- * An array that can be dynamically modified
- * @author Marcin Roguski
- * @param <T>
- *            the type of stored data in the array
- */
-public class DynamicArray<T> implements Cloneable {
-
-    /** An array object that holds the required data. */
-    private T[]   array;
-    /**
-     * This table holds the sizes of dimensions of the dynamic table. Its length specifies the table dimension or a
-     * pointer level. For example: if tableSizes.length == 3 then it either specifies a dynamic table of fixed lengths:
-     * dynTable[a][b][c], where a,b,c are stored in the tableSizes table.
-     */
-    private int[] tableSizes;
-
-    /**
-     * Constructor. Builds an empty array of the specified sizes.
-     * @param tableSizes
-     *            the sizes of the table
-     * @throws IllegalArgumentException
-     *             an exception is thrown if one of the sizes is not a positive number
-     */
-    public DynamicArray(int[] tableSizes, T[] data) {
-        this.tableSizes = tableSizes;
-        int totalSize = 1;
-        for (int size : tableSizes) {
-            if (size <= 0) {
-                throw new IllegalArgumentException("The size of the table must be positive!");
-            }
-            totalSize *= size;
-        }
-        if (totalSize != data.length) {
-            throw new IllegalArgumentException("The size of the table does not match the size of the given data!");
-        }
-        this.array = data;
-    }
-
-    @Override
-    public Object clone() throws CloneNotSupportedException {
-        return super.clone();
-    }
-
-    /**
-     * This method returns a value on the specified position. The dimension of the table is not taken into
-     * consideration.
-     * @param position
-     *            the position of the data
-     * @return required data
-     */
-    public T get(int position) {
-        return array[position];
-    }
-
-    /**
-     * This method returns a value on the specified position in multidimensional array. Be careful not to exceed the
-     * table boundaries. Check the table's dimension first.
-     * @param position
-     *            the position of the data indices of data position
-     * @return required data required data
-     */
-    public T get(int... position) {
-        if (position.length != tableSizes.length) {
-            throw new ArrayIndexOutOfBoundsException("The table accepts " + tableSizes.length + " indexing number(s)!");
-        }
-        int index = 0;
-        for (int i = 0; i < position.length - 1; ++i) {
-            index += position[i] * tableSizes[i + 1];
-        }
-        index += position[position.length - 1];
-        return array[index];
-    }
-
-    /**
-     * This method returns the total amount of data stored in the array.
-     * @return the total amount of data stored in the array
-     */
-    public int getTotalSize() {
-        return array.length;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder();
-        if (array instanceof Character[]) {// in case of character array we convert it to String
-            for (int i = 0; i < array.length && (Character) array[i] != '\0'; ++i) {// strings are terminater with '0'
-                result.append(array[i]);
-            }
-        } else {
-            result.append('[');
-            for (int i = 0; i < array.length; ++i) {
-                result.append(array[i].toString());
-                if (i + 1 < array.length) {
-                    result.append(',');
-                }
-            }
-            result.append(']');
-        }
-        return result.toString();
-    }
-}

+ 0 - 327
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/Field.java

@@ -1,327 +0,0 @@
-package com.jme3.scene.plugins.blender.file;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.Structure.DataType;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class represents a single field in the structure. It can be either a primitive type or a table or a reference to
- * another structure.
- * @author Marcin Roguski
- */
-/* package */
-class Field implements Cloneable {
-
-    private static final int NAME_LENGTH = 24;
-    private static final int TYPE_LENGTH = 16;
-    /** The blender context. */
-    public BlenderContext    blenderContext;
-    /** The type of the field. */
-    public String            type;
-    /** The name of the field. */
-    public String            name;
-    /** The value of the field. Filled during data reading. */
-    public Object            value;
-    /** This variable indicates the level of the pointer. */
-    public int               pointerLevel;
-    /**
-     * This variable determines the sizes of the array. If the value is null then the field is not an array.
-     */
-    public int[]             tableSizes;
-    /** This variable indicates if the field is a function pointer. */
-    public boolean           function;
-
-    /**
-     * Constructor. Saves the field data and parses its name.
-     * @param name
-     *            the name of the field
-     * @param type
-     *            the type of the field
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown if the names contain errors
-     */
-    public Field(String name, String type, BlenderContext blenderContext) throws BlenderFileException {
-        this.type = type;
-        this.blenderContext = blenderContext;
-        this.parseField(new StringBuilder(name));
-    }
-
-    /**
-     * Copy constructor. Used in clone method. Copying is not full. The value in the new object is not set so that we
-     * have a clean empty copy of the field to fill with data.
-     * @param field
-     *            the object that we copy
-     */
-    private Field(Field field) {
-        type = field.type;
-        name = field.name;
-        blenderContext = field.blenderContext;
-        pointerLevel = field.pointerLevel;
-        if (field.tableSizes != null) {
-            tableSizes = field.tableSizes.clone();
-        }
-        function = field.function;
-    }
-
-    @Override
-    public Object clone() throws CloneNotSupportedException {
-        return new Field(this);
-    }
-
-    /**
-     * This method fills the field with data read from the input stream.
-     * @param blenderInputStream
-     *            the stream we read data from
-     * @throws BlenderFileException
-     *             an exception is thrown when the blend file is somehow invalid or corrupted
-     */
-    public void fill(BlenderInputStream blenderInputStream) throws BlenderFileException {
-        int dataToRead = 1;
-        if (tableSizes != null && tableSizes.length > 0) {
-            for (int size : tableSizes) {
-                if (size <= 0) {
-                    throw new BlenderFileException("The field " + name + " has invalid table size: " + size);
-                }
-                dataToRead *= size;
-            }
-        }
-        DataType dataType = pointerLevel == 0 ? DataType.getDataType(type, blenderContext) : DataType.POINTER;
-        switch (dataType) {
-            case POINTER:
-                if (dataToRead == 1) {
-                    Pointer pointer = new Pointer(pointerLevel, function, blenderContext);
-                    pointer.fill(blenderInputStream);
-                    value = pointer;
-                } else {
-                    Pointer[] data = new Pointer[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        Pointer pointer = new Pointer(pointerLevel, function, blenderContext);
-                        pointer.fill(blenderInputStream);
-                        data[i] = pointer;
-                    }
-                    value = new DynamicArray<Pointer>(tableSizes, data);
-                }
-                break;
-            case CHARACTER:
-                // character is also stored as a number, because sometimes the new blender version uses
-                // other number type instead of character as a field type
-                // and characters are very often used as byte number stores instead of real chars
-                if (dataToRead == 1) {
-                    value = Byte.valueOf((byte) blenderInputStream.readByte());
-                } else {
-                    Character[] data = new Character[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        data[i] = Character.valueOf((char) blenderInputStream.readByte());
-                    }
-                    value = new DynamicArray<Character>(tableSizes, data);
-                }
-                break;
-            case SHORT:
-                if (dataToRead == 1) {
-                    value = Integer.valueOf(blenderInputStream.readShort());
-                } else {
-                    Number[] data = new Number[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        data[i] = Integer.valueOf(blenderInputStream.readShort());
-                    }
-                    value = new DynamicArray<Number>(tableSizes, data);
-                }
-                break;
-            case INTEGER:
-                if (dataToRead == 1) {
-                    value = Integer.valueOf(blenderInputStream.readInt());
-                } else {
-                    Number[] data = new Number[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        data[i] = Integer.valueOf(blenderInputStream.readInt());
-                    }
-                    value = new DynamicArray<Number>(tableSizes, data);
-                }
-                break;
-            case LONG:
-                if (dataToRead == 1) {
-                    value = Long.valueOf(blenderInputStream.readLong());
-                } else {
-                    Number[] data = new Number[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        data[i] = Long.valueOf(blenderInputStream.readLong());
-                    }
-                    value = new DynamicArray<Number>(tableSizes, data);
-                }
-                break;
-            case FLOAT:
-                if (dataToRead == 1) {
-                    value = Float.valueOf(blenderInputStream.readFloat());
-                } else {
-                    Number[] data = new Number[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        data[i] = Float.valueOf(blenderInputStream.readFloat());
-                    }
-                    value = new DynamicArray<Number>(tableSizes, data);
-                }
-                break;
-            case DOUBLE:
-                if (dataToRead == 1) {
-                    value = Double.valueOf(blenderInputStream.readDouble());
-                } else {
-                    Number[] data = new Number[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        data[i] = Double.valueOf(blenderInputStream.readDouble());
-                    }
-                    value = new DynamicArray<Number>(tableSizes, data);
-                }
-                break;
-            case VOID:
-                break;
-            case STRUCTURE:
-                if (dataToRead == 1) {
-                    Structure structure = blenderContext.getDnaBlockData().getStructure(type);
-                    structure.fill(blenderContext.getInputStream());
-                    value = structure;
-                } else {
-                    Structure[] data = new Structure[dataToRead];
-                    for (int i = 0; i < dataToRead; ++i) {
-                        Structure structure = blenderContext.getDnaBlockData().getStructure(type);
-                        structure.fill(blenderContext.getInputStream());
-                        data[i] = structure;
-                    }
-                    value = new DynamicArray<Structure>(tableSizes, data);
-                }
-                break;
-            default:
-                throw new IllegalStateException("Unimplemented filling of type: " + type);
-        }
-    }
-
-    /**
-     * This method parses the field name to determine how the field should be used.
-     * @param nameBuilder
-     *            the name of the field (given as StringBuilder)
-     * @throws BlenderFileException
-     *             this exception is thrown if the names contain errors
-     */
-    private void parseField(StringBuilder nameBuilder) throws BlenderFileException {
-        this.removeWhitespaces(nameBuilder);
-        // veryfying if the name is a pointer
-        int pointerIndex = nameBuilder.indexOf("*");
-        while (pointerIndex >= 0) {
-            ++pointerLevel;
-            nameBuilder.deleteCharAt(pointerIndex);
-            pointerIndex = nameBuilder.indexOf("*");
-        }
-        // veryfying if the name is a function pointer
-        if (nameBuilder.indexOf("(") >= 0) {
-            function = true;
-            this.removeCharacter(nameBuilder, '(');
-            this.removeCharacter(nameBuilder, ')');
-        } else {
-            // veryfying if the name is a table
-            int tableStartIndex = 0;
-            List<Integer> lengths = new ArrayList<Integer>(3);// 3 dimensions will be enough in most cases
-            do {
-                tableStartIndex = nameBuilder.indexOf("[");
-                if (tableStartIndex > 0) {
-                    int tableStopIndex = nameBuilder.indexOf("]");
-                    if (tableStopIndex < 0) {
-                        throw new BlenderFileException("Invalid structure name: " + name);
-                    }
-                    try {
-                        lengths.add(Integer.valueOf(nameBuilder.substring(tableStartIndex + 1, tableStopIndex)));
-                    } catch (NumberFormatException e) {
-                        throw new BlenderFileException("Invalid structure name caused by invalid table length: " + name, e);
-                    }
-                    nameBuilder.delete(tableStartIndex, tableStopIndex + 1);
-                }
-            } while (tableStartIndex > 0);
-            if (!lengths.isEmpty()) {
-                tableSizes = new int[lengths.size()];
-                for (int i = 0; i < tableSizes.length; ++i) {
-                    tableSizes[i] = lengths.get(i).intValue();
-                }
-            }
-        }
-        name = nameBuilder.toString();
-    }
-
-    /**
-     * This method removes the required character from the text.
-     * @param text
-     *            the text we remove characters from
-     * @param toRemove
-     *            the character to be removed
-     */
-    private void removeCharacter(StringBuilder text, char toRemove) {
-        for (int i = 0; i < text.length(); ++i) {
-            if (text.charAt(i) == toRemove) {
-                text.deleteCharAt(i);
-                --i;
-            }
-        }
-    }
-
-    /**
-     * This method removes all whitespace from the text.
-     * @param text
-     *            the text we remove whitespace from
-     */
-    private void removeWhitespaces(StringBuilder text) {
-        for (int i = 0; i < text.length(); ++i) {
-            if (Character.isWhitespace(text.charAt(i))) {
-                text.deleteCharAt(i);
-                --i;
-            }
-        }
-    }
-
-    /**
-     * This method builds the full name of the field (with function, pointer and table indications).
-     * @return the full name of the field
-     */
-    /*package*/ String getFullName() {
-        StringBuilder result = new StringBuilder();
-        if (function) {
-            result.append('(');
-        }
-        for (int i = 0; i < pointerLevel; ++i) {
-            result.append('*');
-        }
-        result.append(name);
-        if (tableSizes != null) {
-            for (int i = 0; i < tableSizes.length; ++i) {
-                result.append('[').append(tableSizes[i]).append(']');
-            }
-        }
-        if (function) {
-            result.append(")()");
-        }
-        return result.toString();
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder();
-        result.append(this.getFullName());
-
-        // insert appropriate number of spaces to format the output corrently
-        int nameLength = result.length();
-        result.append(' ');// at least one space is a must
-        for (int i = 1; i < NAME_LENGTH - nameLength; ++i) {// we start from i=1 because one space is already added
-            result.append(' ');
-        }
-        result.append(type);
-        nameLength = result.length();
-        for (int i = 0; i < NAME_LENGTH + TYPE_LENGTH - nameLength; ++i) {
-            result.append(' ');
-        }
-        if (value instanceof Character) {
-            result.append(" = ").append((int) ((Character) value).charValue());
-        } else {
-            result.append(" = ").append(value != null ? value.toString() : "null");
-        }
-        return result.toString();
-    }
-}

+ 0 - 213
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/FileBlockHeader.java

@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.file;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-
-/**
- * A class that holds the header data of a file block. The file block itself is not implemented. This class holds its
- * start position in the stream and using this the structure can fill itself with the proper data.
- * @author Marcin Roguski
- */
-public class FileBlockHeader {
-    private static final Logger LOGGER = Logger.getLogger(FileBlockHeader.class.getName());
-
-    /** Identifier of the file-block [4 bytes]. */
-    private BlockCode           code;
-    /** Total length of the data after the file-block-header [4 bytes]. */
-    private int                 size;
-    /**
-     * Memory address the structure was located when written to disk [4 or 8 bytes (defined in file header as a pointer
-     * size)].
-     */
-    private long                oldMemoryAddress;
-    /** Index of the SDNA structure [4 bytes]. */
-    private int                 sdnaIndex;
-    /** Number of structure located in this file-block [4 bytes]. */
-    private int                 count;
-    /** Start position of the block's data in the stream. */
-    private int                 blockPosition;
-
-    /**
-     * Constructor. Loads the block header from the given stream during instance creation.
-     * @param inputStream
-     *            the stream we read the block header from
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the pointer size is neither 4 nor 8
-     */
-    public FileBlockHeader(BlenderInputStream inputStream, BlenderContext blenderContext) throws BlenderFileException {
-        inputStream.alignPosition(4);
-        code = BlockCode.valueOf(inputStream.readByte() << 24 | inputStream.readByte() << 16 | inputStream.readByte() << 8 | inputStream.readByte());
-        size = inputStream.readInt();
-        oldMemoryAddress = inputStream.readPointer();
-        sdnaIndex = inputStream.readInt();
-        count = inputStream.readInt();
-        blockPosition = inputStream.getPosition();
-        if (BlockCode.BLOCK_DNA1 == code) {
-            blenderContext.setBlockData(new DnaBlockData(inputStream, blenderContext));
-        } else {
-            inputStream.setPosition(blockPosition + size);
-            blenderContext.addFileBlockHeader(Long.valueOf(oldMemoryAddress), this);
-        }
-    }
-
-    /**
-     * This method returns the structure described by the header filled with appropriate data.
-     * @param blenderContext
-     *            the blender context
-     * @return structure filled with data
-     * @throws BlenderFileException
-     */
-    public Structure getStructure(BlenderContext blenderContext) throws BlenderFileException {
-        blenderContext.getInputStream().setPosition(blockPosition);
-        Structure structure = blenderContext.getDnaBlockData().getStructure(sdnaIndex);
-        structure.fill(blenderContext.getInputStream());
-        return structure;
-    }
-
-    /**
-     * This method returns the code of this data block.
-     * @return the code of this data block
-     */
-    public BlockCode getCode() {
-        return code;
-    }
-
-    /**
-     * This method returns the size of the data stored in this block.
-     * @return the size of the data stored in this block
-     */
-    public int getSize() {
-        return size;
-    }
-
-    /**
-     * This method returns the sdna index.
-     * @return the sdna index
-     */
-    public int getSdnaIndex() {
-        return sdnaIndex;
-    }
-
-    /**
-     * This data returns the number of structure stored in the data block after this header.
-     * @return the number of structure stored in the data block after this header
-     */
-    public int getCount() {
-        return count;
-    }
-
-    /**
-     * This method returns the start position of the data block in the blend file stream.
-     * @return the start position of the data block
-     */
-    public int getBlockPosition() {
-        return blockPosition;
-    }
-
-    /**
-     * This method indicates if the block is the last block in the file.
-     * @return true if this block is the last one in the file nad false otherwise
-     */
-    public boolean isLastBlock() {
-        return BlockCode.BLOCK_ENDB == code;
-    }
-
-    /**
-     * This method indicates if the block is the SDNA block.
-     * @return true if this block is the SDNA block and false otherwise
-     */
-    public boolean isDnaBlock() {
-        return BlockCode.BLOCK_DNA1 == code;
-    }
-
-    @Override
-    public String toString() {
-        return "FILE BLOCK HEADER [" + code.toString() + " : " + size + " : " + oldMemoryAddress + " : " + sdnaIndex + " : " + count + "]";
-    }
-
-    public static enum BlockCode {
-        BLOCK_ME00('M' << 24 | 'E' << 16), // mesh
-        BLOCK_CA00('C' << 24 | 'A' << 16), // camera
-        BLOCK_LA00('L' << 24 | 'A' << 16), // lamp
-        BLOCK_OB00('O' << 24 | 'B' << 16), // object
-        BLOCK_MA00('M' << 24 | 'A' << 16), // material
-        BLOCK_SC00('S' << 24 | 'C' << 16), // scene
-        BLOCK_WO00('W' << 24 | 'O' << 16), // world
-        BLOCK_TX00('T' << 24 | 'X' << 16), // texture
-        BLOCK_IP00('I' << 24 | 'P' << 16), // ipo
-        BLOCK_AC00('A' << 24 | 'C' << 16), // action
-        BLOCK_IM00('I' << 24 | 'M' << 16), // image
-        BLOCK_TE00('T' << 24 | 'E' << 16), 
-        BLOCK_WM00('W' << 24 | 'M' << 16), 
-        BLOCK_SR00('S' << 24 | 'R' << 16), 
-        BLOCK_SN00('S' << 24 | 'N' << 16), 
-        BLOCK_BR00('B' << 24 | 'R' << 16), 
-        BLOCK_LS00('L' << 24 | 'S' << 16), 
-        BLOCK_GR00('G' << 24 | 'R' << 16), 
-        BLOCK_AR00('A' << 24 | 'R' << 16), 
-        BLOCK_GLOB('G' << 24 | 'L' << 16 | 'O' << 8 | 'B'), 
-        BLOCK_REND('R' << 24 | 'E' << 16 | 'N' << 8 | 'D'), 
-        BLOCK_DATA('D' << 24 | 'A' << 16 | 'T' << 8 | 'A'), 
-        BLOCK_DNA1('D' << 24 | 'N' << 16 | 'A' << 8 | '1'),
-        BLOCK_ENDB('E' << 24 | 'N' << 16 | 'D' << 8 | 'B'), 
-        BLOCK_TEST('T' << 24 | 'E' << 16 | 'S' << 8 | 'T'), 
-        BLOCK_UNKN(0);
-
-        private int code;
-
-        private BlockCode(int code) {
-            this.code = code;
-        }
-
-        public static BlockCode valueOf(int code) {
-            for (BlockCode blockCode : BlockCode.values()) {
-                if (blockCode.code == code) {
-                    return blockCode;
-                }
-            }
-            byte[] codeBytes = new byte[] { (byte) (code >> 24 & 0xFF), (byte) (code >> 16 & 0xFF), (byte) (code >> 8 & 0xFF), (byte) (code & 0xFF) };
-			for (int i = 0; i < codeBytes.length; ++i) {
-				if (codeBytes[i] == 0) {
-					codeBytes[i] = '0';
-				}
-			}
-			LOGGER.log(Level.WARNING, "Unknown block header: {0}", new String(codeBytes));
-            return BLOCK_UNKN;
-        }
-    }
-}

+ 0 - 189
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/Pointer.java

@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.file;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-
-/**
- * A class that represents a pointer of any level that can be stored in the file.
- * @author Marcin Roguski
- */
-public class Pointer {
-
-    /** The blender context. */
-    private BlenderContext blenderContext;
-    /** The level of the pointer. */
-    private int            pointerLevel;
-    /** The address in file it points to. */
-    private long           oldMemoryAddress;
-    /** This variable indicates if the field is a function pointer. */
-    public boolean         function;
-
-    /**
-     * Constructr. Stores the basic data about the pointer.
-     * @param pointerLevel
-     *            the level of the pointer
-     * @param function
-     *            this variable indicates if the field is a function pointer
-     * @param blenderContext
-     *            the repository f data; used in fetching the value that the pointer points
-     */
-    public Pointer(int pointerLevel, boolean function, BlenderContext blenderContext) {
-        this.pointerLevel = pointerLevel;
-        this.function = function;
-        this.blenderContext = blenderContext;
-    }
-
-    /**
-     * This method fills the pointer with its address value (it doesn't get the actual data yet. Use the 'fetch' method
-     * for this.
-     * @param inputStream
-     *            the stream we read the pointer value from
-     */
-    public void fill(BlenderInputStream inputStream) {
-        oldMemoryAddress = inputStream.readPointer();
-    }
-
-    /**
-     * This method fetches the data stored under the given address.
-     * @return the data read from the file
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is somehow invalid or corrupted
-     */
-    public List<Structure> fetchData() throws BlenderFileException {
-        if (oldMemoryAddress == 0) {
-            throw new NullPointerException("The pointer points to nothing!");
-        }
-        List<Structure> structures = null;
-        FileBlockHeader dataFileBlock = blenderContext.getFileBlock(oldMemoryAddress);
-        if (dataFileBlock == null) {
-            throw new BlenderFileException("No data stored for address: " + oldMemoryAddress + ". Make sure you did not open the newer blender file with older blender version.");
-        }
-        BlenderInputStream inputStream = blenderContext.getInputStream();
-        if (pointerLevel > 1) {
-            int pointersAmount = dataFileBlock.getSize() / inputStream.getPointerSize() * dataFileBlock.getCount();
-            for (int i = 0; i < pointersAmount; ++i) {
-                inputStream.setPosition(dataFileBlock.getBlockPosition() + inputStream.getPointerSize() * i);
-                long oldMemoryAddress = inputStream.readPointer();
-                if (oldMemoryAddress != 0L) {
-                    Pointer p = new Pointer(pointerLevel - 1, function, blenderContext);
-                    p.oldMemoryAddress = oldMemoryAddress;
-                    if (structures == null) {
-                        structures = p.fetchData();
-                    } else {
-                        structures.addAll(p.fetchData());
-                    }
-                } else {
-                    // it is necessary to put null's if the pointer is null, ie. in materials array that is attached to the mesh, the index
-                    // of the material is important, that is why we need null's to indicate that some materials' slots are empty
-                    if (structures == null) {
-                        structures = new ArrayList<Structure>();
-                    }
-                    structures.add(null);
-                }
-            }
-        } else {
-            inputStream.setPosition(dataFileBlock.getBlockPosition());
-            structures = new ArrayList<Structure>(dataFileBlock.getCount());
-            for (int i = 0; i < dataFileBlock.getCount(); ++i) {
-                Structure structure = blenderContext.getDnaBlockData().getStructure(dataFileBlock.getSdnaIndex());
-                structure.fill(blenderContext.getInputStream());
-                structures.add(structure);
-            }
-            return structures;
-        }
-        return structures;
-    }
-
-    /**
-     * This method indicates if this pointer points to a function.
-     * @return <b>true</b> if this is a function pointer and <b>false</b> otherwise
-     */
-    public boolean isFunction() {
-        return function;
-    }
-
-    /**
-     * This method indicates if this is a null-pointer or not.
-     * @return <b>true</b> if the pointer is null and <b>false</b> otherwise
-     */
-    public boolean isNull() {
-        return oldMemoryAddress == 0;
-    }
-
-    /**
-     * This method indicates if this is a null-pointer or not.
-     * @return <b>true</b> if the pointer is not null and <b>false</b> otherwise
-     */
-    public boolean isNotNull() {
-        return oldMemoryAddress != 0;
-    }
-
-    /**
-     * This method returns the old memory address of the structure pointed by the pointer.
-     * @return the old memory address of the structure pointed by the pointer
-     */
-    public long getOldMemoryAddress() {
-        return oldMemoryAddress;
-    }
-
-    @Override
-    public String toString() {
-        return oldMemoryAddress == 0 ? "{$null$}" : "{$" + oldMemoryAddress + "$}";
-    }
-
-    @Override
-    public int hashCode() {
-        return 31 + (int) (oldMemoryAddress ^ oldMemoryAddress >>> 32);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (this.getClass() != obj.getClass()) {
-            return false;
-        }
-        Pointer other = (Pointer) obj;
-        if (oldMemoryAddress != other.oldMemoryAddress) {
-            return false;
-        }
-        return true;
-    }
-}

+ 0 - 328
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/file/Structure.java

@@ -1,328 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.file;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-
-/**
- * A class representing a single structure in the file.
- * @author Marcin Roguski
- */
-public class Structure implements Cloneable {
-
-    /** The address of the block that fills the structure. */
-    private transient Long oldMemoryAddress;
-    /** The type of the structure. */
-    private String         type;
-    /**
-     * The fields of the structure. Each field consists of a pair: name-type.
-     */
-    private Field[]        fields;
-
-    /**
-     * Constructor that copies the data of the structure.
-     * @param structure
-     *            the structure to copy.
-     * @throws CloneNotSupportedException
-     *             this exception should never be thrown
-     */
-    private Structure(Structure structure) throws CloneNotSupportedException {
-        type = structure.type;
-        fields = new Field[structure.fields.length];
-        for (int i = 0; i < fields.length; ++i) {
-            fields[i] = (Field) structure.fields[i].clone();
-        }
-        oldMemoryAddress = structure.oldMemoryAddress;
-    }
-
-    /**
-     * Constructor. Loads the structure from the given stream during instance creation.
-     * @param inputStream
-     *            the stream we read the structure from
-     * @param names
-     *            the names from which the name of structure and its fields will be taken
-     * @param types
-     *            the names of types for the structure
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception occurs if the amount of fields, defined in the file, is negative
-     */
-    public Structure(BlenderInputStream inputStream, String[] names, String[] types, BlenderContext blenderContext) throws BlenderFileException {
-        int nameIndex = inputStream.readShort();
-        type = types[nameIndex];
-        int fieldsAmount = inputStream.readShort();
-        if (fieldsAmount < 0) {
-            throw new BlenderFileException("The amount of fields of " + type + " structure cannot be negative!");
-        }
-        if (fieldsAmount > 0) {
-            fields = new Field[fieldsAmount];
-            for (int i = 0; i < fieldsAmount; ++i) {
-                int typeIndex = inputStream.readShort();
-                nameIndex = inputStream.readShort();
-                fields[i] = new Field(names[nameIndex], types[typeIndex], blenderContext);
-            }
-        }
-        oldMemoryAddress = Long.valueOf(-1L);
-    }
-
-    /**
-     * This method fills the structure with data.
-     * @param inputStream
-     *            the stream we read data from, its read cursor should be placed at the start position of the data for the
-     *            structure
-     * @throws BlenderFileException
-     *             an exception is thrown when the blend file is somehow invalid or corrupted
-     */
-    public void fill(BlenderInputStream inputStream) throws BlenderFileException {
-        int position = inputStream.getPosition();
-        inputStream.setPosition(position - 8 - inputStream.getPointerSize());
-        oldMemoryAddress = Long.valueOf(inputStream.readPointer());
-        inputStream.setPosition(position);
-        for (Field field : fields) {
-            field.fill(inputStream);
-        }
-    }
-
-    /**
-     * This method returns the value of the filed with a given name.
-     * @param fieldName
-     *            the name of the field
-     * @return the value of the field or null if no field with a given name is found
-     */
-    public Object getFieldValue(String fieldName) {
-        return this.getFieldValue(fieldName, null);
-    }
-
-    /**
-     * This method returns the value of the filed with a given name.
-     * @param fieldName
-     *            the name of the field
-     * @param defaultValue
-     *            the value that is being returned when no field of a given name is found
-     * @return the value of the field or the given default value if no field with a given name is found
-     */
-    public Object getFieldValue(String fieldName, Object defaultValue) {
-        for (Field field : fields) {
-            if (field.name.equalsIgnoreCase(fieldName)) {
-                return field.value;
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * This method returns the value of the filed with a given name. The structure is considered to have flat fields
-     * only (no substructures).
-     * @param fieldName
-     *            the name of the field
-     * @return the value of the field or null if no field with a given name is found
-     */
-    public Object getFlatFieldValue(String fieldName) {
-        for (Field field : fields) {
-            Object value = field.value;
-            if (field.name.equalsIgnoreCase(fieldName)) {
-                return value;
-            } else if (value instanceof Structure) {
-                value = ((Structure) value).getFlatFieldValue(fieldName);
-                if (value != null) {// we can compare references here, since we use one static object as a NULL field value
-                    return value;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * This method should be used on structures that are of a 'ListBase' type. It creates a List of structures that are
-     * held by this structure within the blend file.
-     * @return a list of filled structures
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is somehow invalid or corrupted
-     * @throws IllegalArgumentException
-     *             this exception is thrown if the type of the structure is not 'ListBase'
-     */
-    public List<Structure> evaluateListBase() throws BlenderFileException {
-        if (!"ListBase".equals(type)) {
-            throw new IllegalStateException("This structure is not of type: 'ListBase'");
-        }
-        Pointer first = (Pointer) this.getFieldValue("first");
-        Pointer last = (Pointer) this.getFieldValue("last");
-        long currentAddress = 0;
-        long lastAddress = last.getOldMemoryAddress();
-        List<Structure> result = new LinkedList<Structure>();
-        while (currentAddress != lastAddress) {
-            currentAddress = first.getOldMemoryAddress();
-            Structure structure = first.fetchData().get(0);
-            result.add(structure);
-            first = (Pointer) structure.getFlatFieldValue("next");
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the type of the structure.
-     * @return the type of the structure
-     */
-    public String getType() {
-        return type;
-    }
-
-    /**
-     * This method returns the amount of fields for the current structure.
-     * @return the amount of fields for the current structure
-     */
-    public int getFieldsAmount() {
-        return fields.length;
-    }
-
-    /**
-     * This method returns the full field name of the given index.
-     * @param fieldIndex
-     *            the index of the field
-     * @return the full field name of the given index
-     */
-    public String getFieldFullName(int fieldIndex) {
-        return fields[fieldIndex].getFullName();
-    }
-
-    /**
-     * This method returns the field type of the given index.
-     * @param fieldIndex
-     *            the index of the field
-     * @return the field type of the given index
-     */
-    public String getFieldType(int fieldIndex) {
-        return fields[fieldIndex].type;
-    }
-
-    /**
-     * This method returns the address of the structure. The structure should be filled with data otherwise an exception
-     * is thrown.
-     * @return the address of the feature stored in this structure
-     */
-    public Long getOldMemoryAddress() {
-        if (oldMemoryAddress.longValue() == -1L) {
-            throw new IllegalStateException("Call the 'fill' method and fill the structure with data first!");
-        }
-        return oldMemoryAddress;
-    }
-
-    /**
-     * This method returns the name of the structure. If the structure has an ID field then the name is returned.
-     * Otherwise the name does not exists and the method returns null.
-     * @return the name of the structure read from the ID field or null
-     */
-    public String getName() {
-        Object fieldValue = this.getFieldValue("ID");
-        if (fieldValue instanceof Structure) {
-            Structure id = (Structure) fieldValue;
-            return id.getFieldValue("name").toString().substring(2);// blender adds 2-charactes as a name prefix
-        }
-        Object name = this.getFieldValue("name", null);
-        return name == null ? null : name.toString().substring(2);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder("struct ").append(type).append(" {\n");
-        for (int i = 0; i < fields.length; ++i) {
-            result.append(fields[i].toString()).append('\n');
-        }
-        return result.append('}').toString();
-    }
-
-    @Override
-    public Object clone() throws CloneNotSupportedException {
-        return new Structure(this);
-    }
-
-    /**
-     * This enum enumerates all known data types that can be found in the blend file.
-     * @author Marcin Roguski (Kaelthas)
-     */
-    /* package */static enum DataType {
-
-        CHARACTER, SHORT, INTEGER, LONG, FLOAT, DOUBLE, VOID, STRUCTURE, POINTER;
-        /** The map containing the known primary types. */
-        private static final Map<String, DataType> PRIMARY_TYPES = new HashMap<String, DataType>(10);
-
-        static {
-            PRIMARY_TYPES.put("char", CHARACTER);
-            PRIMARY_TYPES.put("uchar", CHARACTER);
-            PRIMARY_TYPES.put("short", SHORT);
-            PRIMARY_TYPES.put("ushort", SHORT);
-            PRIMARY_TYPES.put("int", INTEGER);
-            PRIMARY_TYPES.put("long", LONG);
-            PRIMARY_TYPES.put("ulong", LONG);
-            PRIMARY_TYPES.put("uint64_t", LONG);
-            PRIMARY_TYPES.put("float", FLOAT);
-            PRIMARY_TYPES.put("double", DOUBLE);
-            PRIMARY_TYPES.put("void", VOID);
-        }
-
-        /**
-         * This method returns the data type that is appropriate to the given type name. WARNING! The type recognition
-         * is case sensitive!
-         * @param type
-         *            the type name of the data
-         * @param blenderContext
-         *            the blender context
-         * @return appropriate enum value to the given type name
-         * @throws BlenderFileException
-         *             this exception is thrown if the given type name does not exist in the blend file
-         */
-        public static DataType getDataType(String type, BlenderContext blenderContext) throws BlenderFileException {
-            DataType result = PRIMARY_TYPES.get(type);
-            if (result != null) {
-                return result;
-            }
-            if (blenderContext.getDnaBlockData().hasStructure(type)) {
-                return STRUCTURE;
-            }
-            throw new BlenderFileException("Unknown data type: " + type);
-        }
-
-        /**
-         * @return a collection of known primary types names
-         */
-        /* package */static Collection<String> getKnownPrimaryTypesNames() {
-            return PRIMARY_TYPES.keySet();
-        }
-    }
-}

+ 0 - 214
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/landscape/LandscapeHelper.java

@@ -1,214 +0,0 @@
-package com.jme3.scene.plugins.blender.landscape;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.light.AmbientLight;
-import com.jme3.light.Light;
-import com.jme3.math.ColorRGBA;
-import com.jme3.post.filters.FogFilter;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.textures.ColorBand;
-import com.jme3.scene.plugins.blender.textures.CombinedTexture;
-import com.jme3.scene.plugins.blender.textures.ImageUtils;
-import com.jme3.scene.plugins.blender.textures.TextureHelper;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.TextureCubeMap;
-import com.jme3.util.SkyFactory;
-
-/**
- * The class that allows to load the following: <li>the ambient light of the scene <li>the sky of the scene (with or without texture)
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class LandscapeHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER        = Logger.getLogger(LandscapeHelper.class.getName());
-
-    private static final int    SKYTYPE_BLEND = 1;
-    private static final int    SKYTYPE_REAL  = 2;
-    private static final int    SKYTYPE_PAPER = 4;
-
-    private static final int    MODE_MIST     = 0x01;
-
-    public LandscapeHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * Loads scene ambient light.
-     * @param worldStructure
-     *            the world's blender structure
-     * @return the scene's ambient light
-     */
-    public Light toAmbientLight(Structure worldStructure) {
-        LOGGER.fine("Loading ambient light.");
-        AmbientLight ambientLight = null;
-        float ambr = ((Number) worldStructure.getFieldValue("ambr")).floatValue();
-        float ambg = ((Number) worldStructure.getFieldValue("ambg")).floatValue();
-        float ambb = ((Number) worldStructure.getFieldValue("ambb")).floatValue();
-        if (ambr > 0 || ambg > 0 || ambb > 0) {
-            ambientLight = new AmbientLight();
-            ColorRGBA ambientLightColor = new ColorRGBA(ambr, ambg, ambb, 0.0f);
-            ambientLight.setColor(ambientLightColor);
-            LOGGER.log(Level.FINE, "Loaded ambient light: {0}.", ambientLightColor);
-        } else {
-            LOGGER.finer("Ambient light is set to BLACK which means: no ambient light! The ambient light node will not be included in the result.");
-        }
-        return ambientLight;
-    }
-
-    /**
-     * The method loads fog for the scene.
-     * NOTICE! Remember to manually set the distance and density of the fog.
-     * Unfortunately blender's fog parameters in no way fit to the JME.
-     * @param worldStructure
-     *            the world's structure
-     * @return fog filter or null if scene does not define it
-     */
-    public FogFilter toFog(Structure worldStructure) {
-        FogFilter result = null;
-        int mode = ((Number) worldStructure.getFieldValue("mode")).intValue();
-        if ((mode & MODE_MIST) != 0) {
-            LOGGER.fine("Loading fog.");
-            result = new FogFilter();
-            result.setName("FIfog");
-            result.setFogColor(this.toBackgroundColor(worldStructure));
-        }
-        return result;
-    }
-
-    /**
-     * Loads the background color.
-     * @param worldStructure
-     *            the world's structure
-     * @return the horizon color of the world which is used as a background color.
-     */
-    public ColorRGBA toBackgroundColor(Structure worldStructure) {
-        float horr = ((Number) worldStructure.getFieldValue("horr")).floatValue();
-        float horg = ((Number) worldStructure.getFieldValue("horg")).floatValue();
-        float horb = ((Number) worldStructure.getFieldValue("horb")).floatValue();
-        return new ColorRGBA(horr, horg, horb, 1);
-    }
-
-    /**
-     * Loads scene's sky. Sky can be plain or textured.
-     * If no sky type is selected in blender then no sky is loaded.
-     * @param worldStructure
-     *            the world's structure
-     * @return the scene's sky
-     * @throws BlenderFileException
-     *             blender exception is thrown when problems with blender file occur
-     */
-    public Spatial toSky(Structure worldStructure) throws BlenderFileException {
-        int skytype = ((Number) worldStructure.getFieldValue("skytype")).intValue();
-        if (skytype == 0) {
-            return null;
-        }
-
-        LOGGER.fine("Loading sky.");
-        ColorRGBA horizontalColor = this.toBackgroundColor(worldStructure);
-
-        float zenr = ((Number) worldStructure.getFieldValue("zenr")).floatValue();
-        float zeng = ((Number) worldStructure.getFieldValue("zeng")).floatValue();
-        float zenb = ((Number) worldStructure.getFieldValue("zenb")).floatValue();
-        ColorRGBA zenithColor = new ColorRGBA(zenr, zeng, zenb, 1);
-
-        // jutr for this case load generated textures wheather user had set it or not because those might be needed to properly load the sky
-        boolean loadGeneratedTextures = blenderContext.getBlenderKey().isLoadGeneratedTextures();
-        blenderContext.getBlenderKey().setLoadGeneratedTextures(true);
-
-        TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
-        List<CombinedTexture> loadedTextures = null;
-        try {
-            loadedTextures = textureHelper.readTextureData(worldStructure, new float[] { horizontalColor.r, horizontalColor.g, horizontalColor.b, horizontalColor.a }, true);
-        } finally {
-            blenderContext.getBlenderKey().setLoadGeneratedTextures(loadGeneratedTextures);
-        }
-
-        TextureCubeMap texture = null;
-        if (loadedTextures != null && loadedTextures.size() > 0) {
-            if (loadedTextures.size() > 1) {
-                throw new IllegalStateException("There should be only one combined texture for sky!");
-            }
-            CombinedTexture combinedTexture = loadedTextures.get(0);
-            texture = combinedTexture.generateSkyTexture(horizontalColor, zenithColor, blenderContext);
-        } else {
-            LOGGER.fine("Preparing colors for colorband.");
-            int colorbandType = ColorBand.IPO_CARDINAL;
-            List<ColorRGBA> colorbandColors = new ArrayList<ColorRGBA>(3);
-            colorbandColors.add(horizontalColor);
-            if ((skytype & SKYTYPE_BLEND) != 0) {
-                if ((skytype & SKYTYPE_PAPER) != 0) {
-                    colorbandType = ColorBand.IPO_LINEAR;
-                }
-                if ((skytype & SKYTYPE_REAL) != 0) {
-                    colorbandColors.add(0, zenithColor);
-                }
-                colorbandColors.add(zenithColor);
-            }
-
-            int size = blenderContext.getBlenderKey().getSkyGeneratedTextureSize();
-
-            List<Integer> positions = new ArrayList<Integer>(colorbandColors.size());
-            positions.add(0);
-            if (colorbandColors.size() == 2) {
-                positions.add(size - 1);
-            } else if (colorbandColors.size() == 3) {
-                positions.add(size / 2);
-                positions.add(size - 1);
-            }
-
-            LOGGER.fine("Generating sky texture.");
-            float[][] values = new ColorBand(colorbandType, colorbandColors, positions, size).computeValues();
-
-            Image image = ImageUtils.createEmptyImage(Format.RGB8, size, size, 6);
-            PixelInputOutput pixelIO = PixelIOFactory.getPixelIO(image.getFormat());
-            TexturePixel pixel = new TexturePixel();
-
-            LOGGER.fine("Creating side textures.");
-            int[] sideImagesIndexes = new int[] { 0, 1, 4, 5 };
-            for (int i : sideImagesIndexes) {
-                for (int y = 0; y < size; ++y) {
-                    pixel.red = values[y][0];
-                    pixel.green = values[y][1];
-                    pixel.blue = values[y][2];
-
-                    for (int x = 0; x < size; ++x) {
-                        pixelIO.write(image, i, pixel, x, y);
-                    }
-                }
-            }
-
-            LOGGER.fine("Creating top texture.");
-            pixelIO.read(image, 0, pixel, 0, image.getHeight() - 1);
-            for (int y = 0; y < size; ++y) {
-                for (int x = 0; x < size; ++x) {
-                    pixelIO.write(image, 3, pixel, x, y);
-                }
-            }
-
-            LOGGER.fine("Creating bottom texture.");
-            pixelIO.read(image, 0, pixel, 0, 0);
-            for (int y = 0; y < size; ++y) {
-                for (int x = 0; x < size; ++x) {
-                    pixelIO.write(image, 2, pixel, x, y);
-                }
-            }
-
-            texture = new TextureCubeMap(image);
-        }
-
-        LOGGER.fine("Sky texture created. Creating sky.");
-        return SkyFactory.createSky(blenderContext.getAssetManager(), texture, SkyFactory.EnvMapType.CubeMap);
-    }
-}

+ 0 - 116
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/lights/LightHelper.java

@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.lights;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.light.DirectionalLight;
-import com.jme3.light.Light;
-import com.jme3.light.PointLight;
-import com.jme3.light.SpotLight;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * A class that is used in light calculations.
- * @author Marcin Roguski
- */
-public class LightHelper extends AbstractBlenderHelper {
-
-    private static final Logger LOGGER = Logger.getLogger(LightHelper.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
-     * @param blenderContext
-     *            the blender context
-     */
-    public LightHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    public Light toLight(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
-        Light result = (Light) blenderContext.getLoadedFeature(structure.getOldMemoryAddress(), LoadedDataType.FEATURE);
-        if (result != null) {
-            return result;
-        }
-        Light light = null;
-        int type = ((Number) structure.getFieldValue("type")).intValue();
-        switch (type) {
-            case 0:// Lamp
-                light = new PointLight();
-                float distance = ((Number) structure.getFieldValue("dist")).floatValue();
-                ((PointLight) light).setRadius(distance);
-                break;
-            case 1:// Sun
-                LOGGER.log(Level.WARNING, "'Sun' lamp is not supported in jMonkeyEngine. Using PointLight with radius = Float.MAX_VALUE.");
-                light = new PointLight();
-                ((PointLight) light).setRadius(Float.MAX_VALUE);
-                break;
-            case 2:// Spot
-                light = new SpotLight();
-                // range
-                ((SpotLight) light).setSpotRange(((Number) structure.getFieldValue("dist")).floatValue());
-                // outer angle
-                float outerAngle = ((Number) structure.getFieldValue("spotsize")).floatValue() * FastMath.DEG_TO_RAD * 0.5f;
-                ((SpotLight) light).setSpotOuterAngle(outerAngle);
-
-                // inner angle
-                float spotblend = ((Number) structure.getFieldValue("spotblend")).floatValue();
-                spotblend = FastMath.clamp(spotblend, 0, 1);
-                float innerAngle = outerAngle * (1 - spotblend);
-                ((SpotLight) light).setSpotInnerAngle(innerAngle);
-                break;
-            case 3:// Hemi
-                LOGGER.log(Level.WARNING, "'Hemi' lamp is not supported in jMonkeyEngine. Using DirectionalLight instead.");
-            case 4:// Area
-                light = new DirectionalLight();
-                break;
-            default:
-                throw new BlenderFileException("Unknown light source type: " + type);
-        }
-        float r = ((Number) structure.getFieldValue("r")).floatValue();
-        float g = ((Number) structure.getFieldValue("g")).floatValue();
-        float b = ((Number) structure.getFieldValue("b")).floatValue();
-        light.setColor(new ColorRGBA(r, g, b, 1.0f));
-        light.setName(structure.getName());
-        return light;
-    }
-}

+ 0 - 26
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/IAlphaMask.java

@@ -1,26 +0,0 @@
-package com.jme3.scene.plugins.blender.materials;
-
-/**
- * An interface used in calculating alpha mask during particles' texture calculations.
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */interface IAlphaMask {
-    /**
-     * This method sets the size of the texture's image.
-     * @param width
-     *            the width of the image
-     * @param height
-     *            the height of the image
-     */
-    void setImageSize(int width, int height);
-
-    /**
-     * This method returns the alpha value for the specified texture position.
-     * @param x
-     *            the X coordinate of the texture position
-     * @param y
-     *            the Y coordinate of the texture position
-     * @return the alpha value for the specified texture position
-     */
-    byte getAlpha(float x, float y);
-}

+ 0 - 366
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialContext.java

@@ -1,366 +0,0 @@
-package com.jme3.scene.plugins.blender.materials;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.export.JmeExporter;
-import com.jme3.export.JmeImporter;
-import com.jme3.export.Savable;
-import com.jme3.material.Material;
-import com.jme3.material.RenderState.BlendMode;
-import com.jme3.material.RenderState.FaceCullMode;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Vector2f;
-import com.jme3.renderer.queue.RenderQueue.Bucket;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.VertexBuffer;
-import com.jme3.scene.VertexBuffer.Format;
-import com.jme3.scene.VertexBuffer.Usage;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.materials.MaterialHelper.DiffuseShader;
-import com.jme3.scene.plugins.blender.materials.MaterialHelper.SpecularShader;
-import com.jme3.scene.plugins.blender.textures.CombinedTexture;
-import com.jme3.scene.plugins.blender.textures.TextureHelper;
-import com.jme3.texture.Texture;
-import com.jme3.util.BufferUtils;
-
-/**
- * This class holds the data about the material.
- * @author Marcin Roguski (Kaelthas)
- */
-public final class MaterialContext implements Savable {
-    private static final Logger              LOGGER     = Logger.getLogger(MaterialContext.class.getName());
-
-    // texture mapping types
-    public static final int                  MTEX_COL   = 0x01;
-    public static final int                  MTEX_NOR   = 0x02;
-    public static final int                  MTEX_SPEC  = 0x04;
-    public static final int                  MTEX_EMIT  = 0x40;
-    public static final int                  MTEX_ALPHA = 0x80;
-    public static final int                  MTEX_AMB   = 0x800;
-
-    public static final int                  FLAG_TRANSPARENT   = 0x10000;
-    
-    /* package */final String                name;
-    /* package */final List<CombinedTexture> loadedTextures;
-
-    /* package */final ColorRGBA             diffuseColor;
-    /* package */final DiffuseShader         diffuseShader;
-    /* package */final SpecularShader        specularShader;
-    /* package */final ColorRGBA             specularColor;
-    /* package */final float                 ambientFactor;
-    /* package */final float                 shininess;
-    /* package */final boolean               shadeless;
-    /* package */final boolean               vertexColor;
-    /* package */final boolean               transparent;
-    /* package */final boolean               vTangent;
-    /* package */FaceCullMode                faceCullMode;
-
-    /* package */MaterialContext(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
-        name = structure.getName();
-
-        int mode = ((Number) structure.getFieldValue("mode")).intValue();
-        shadeless = (mode & 0x4) != 0;
-        vertexColor = (mode & 0x80) != 0;
-        vTangent = (mode & 0x4000000) != 0; // NOTE: Requires tangents
-
-        int diff_shader = ((Number) structure.getFieldValue("diff_shader")).intValue();
-        diffuseShader = DiffuseShader.values()[diff_shader];
-        ambientFactor = ((Number) structure.getFieldValue("amb")).floatValue();
-
-        if (shadeless) {
-            float r = ((Number) structure.getFieldValue("r")).floatValue();
-            float g = ((Number) structure.getFieldValue("g")).floatValue();
-            float b = ((Number) structure.getFieldValue("b")).floatValue();
-            float alpha = ((Number) structure.getFieldValue("alpha")).floatValue();
-
-            diffuseColor = new ColorRGBA(r, g, b, alpha);
-            specularShader = null;
-            specularColor = null;
-            shininess = 0.0f;
-        } else {
-            diffuseColor = this.readDiffuseColor(structure, diffuseShader);
-
-            int spec_shader = ((Number) structure.getFieldValue("spec_shader")).intValue();
-            specularShader = SpecularShader.values()[spec_shader];
-            specularColor = this.readSpecularColor(structure);
-            float shininess = ((Number) structure.getFieldValue("har")).floatValue();// this is (probably) the specular hardness in blender
-            this.shininess = shininess > 0.0f ? shininess : MaterialHelper.DEFAULT_SHININESS;
-        }
-
-        TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
-        loadedTextures = textureHelper.readTextureData(structure, new float[] { diffuseColor.r, diffuseColor.g, diffuseColor.b, diffuseColor.a }, false);
-
-        long flag = ((Number)structure.getFieldValue("flag")).longValue();
-        if((flag & FLAG_TRANSPARENT) != 0) {
-            // veryfying if the transparency is present
-            // (in blender transparent mask is 0x10000 but it's better to verify it because blender can indicate transparency when
-            // it is not required
-            boolean transparent = false;
-            if (diffuseColor != null) {
-                transparent = diffuseColor.a < 1.0f;
-                if (loadedTextures.size() > 0) {// texture covers the material color
-                    diffuseColor.set(1, 1, 1, 1);
-                }
-            }
-            if (specularColor != null) {
-                transparent = transparent || specularColor.a < 1.0f;
-            }
-            this.transparent = transparent;
-        } else {
-            transparent = false;
-        }
-    }
-
-    /**
-     * @return the name of the material
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Applies material to a given geometry.
-     * 
-     * @param geometry
-     *            the geometry
-     * @param geometriesOMA
-     *            the geometries OMA
-     * @param userDefinedUVCoordinates
-     *            UV coords defined by user
-     * @param blenderContext
-     *            the blender context
-     */
-    public void applyMaterial(Geometry geometry, Long geometriesOMA, Map<String, List<Vector2f>> userDefinedUVCoordinates, BlenderContext blenderContext) {
-        Material material = null;
-        if (shadeless) {
-            material = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
-
-            if (!transparent) {
-                diffuseColor.a = 1;
-            }
-
-            material.setColor("Color", diffuseColor);
-        } else {
-            material = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
-            material.setBoolean("UseMaterialColors", Boolean.TRUE);
-
-            // setting the colors
-            if (!transparent) {
-                diffuseColor.a = 1;
-            }
-            material.setColor("Diffuse", diffuseColor);
-
-            material.setColor("Specular", specularColor);
-            material.setFloat("Shininess", shininess);
-
-            material.setColor("Ambient", new ColorRGBA(ambientFactor, ambientFactor, ambientFactor, 1f));
-        }
-        
-        // initializing unused "user-defined UV coords" to all available
-        Map<String, List<Vector2f>> unusedUserDefinedUVCoords = Collections.emptyMap();
-        if(userDefinedUVCoordinates != null && !userDefinedUVCoordinates.isEmpty()) {
-            unusedUserDefinedUVCoords = new HashMap<>(userDefinedUVCoordinates);
-        }
-
-        // applying textures
-        int textureIndex = 0;
-        if (loadedTextures != null && loadedTextures.size() > 0) {
-            if (loadedTextures.size() > TextureHelper.TEXCOORD_TYPES.length) {
-                LOGGER.log(Level.WARNING, "The blender file has defined more than {0} different textures. JME supports only {0} UV mappings.", TextureHelper.TEXCOORD_TYPES.length);
-            }
-            for (CombinedTexture combinedTexture : loadedTextures) {
-                if (textureIndex < TextureHelper.TEXCOORD_TYPES.length) {
-                    String usedUserUVSet = combinedTexture.flatten(geometry, geometriesOMA, userDefinedUVCoordinates, blenderContext);
-
-                    this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture());
-                    
-                    if(usedUserUVSet == null || unusedUserDefinedUVCoords.containsKey(usedUserUVSet)) {
-                        List<Vector2f> uvs = combinedTexture.getResultUVS();
-                        if(uvs != null && uvs.size() > 0) {
-                            VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
-                            uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
-                            geometry.getMesh().setBuffer(uvCoordsBuffer);
-                        }//uvs might be null if the user assigned non existing UV coordinates group name to the mesh (this should be fixed in blender file)
-
-                        // Remove used "user-defined UV coords" from the unused collection
-                        if(usedUserUVSet != null) {
-                	       unusedUserDefinedUVCoords.remove(usedUserUVSet);
-                        }
-                    }
-                } else {
-                    LOGGER.log(Level.WARNING, "The texture could not be applied because JME only supports up to {0} different UV's.", TextureHelper.TEXCOORD_TYPES.length);
-                }
-            }
-        }
-
-        if (unusedUserDefinedUVCoords != null && unusedUserDefinedUVCoords.size() > 0) {
-            LOGGER.fine("Storing unused, user defined UV coordinates sets.");
-            if (unusedUserDefinedUVCoords.size() > TextureHelper.TEXCOORD_TYPES.length) {
-                LOGGER.log(Level.WARNING, "The blender file has defined more than {0} different UV coordinates for the mesh. JME supports only {0} UV coordinates buffers.", TextureHelper.TEXCOORD_TYPES.length);
-            }
-            for (Entry<String, List<Vector2f>> entry : unusedUserDefinedUVCoords.entrySet()) {
-                if (textureIndex < TextureHelper.TEXCOORD_TYPES.length) {
-                    List<Vector2f> uvs = entry.getValue();
-                    VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
-                    uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
-                    geometry.getMesh().setBuffer(uvCoordsBuffer);
-                } else {
-                    LOGGER.log(Level.WARNING, "The user's UV set named: '{0}' could not be stored because JME only supports up to {1} different UV's.", new Object[] {
-                		entry.getKey(), TextureHelper.TEXCOORD_TYPES.length
-                    });
-                }
-            }
-        }
-
-        // applying additional data
-        material.setName(name);
-        if (vertexColor) {
-            material.setBoolean(shadeless ? "VertexColor" : "UseVertexColor", true);
-        }
-        material.getAdditionalRenderState().setFaceCullMode(faceCullMode != null ? faceCullMode : blenderContext.getBlenderKey().getFaceCullMode());
-        if (transparent) {
-            material.setTransparent(true);
-            material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
-            geometry.setQueueBucket(Bucket.Transparent);
-        }
-
-        geometry.setMaterial(material);
-    }
-
-    /**
-     * Sets the texture to the given material.
-     * 
-     * @param material
-     *            the material that we add texture to
-     * @param mapTo
-     *            the texture mapping type
-     * @param texture
-     *            the added texture
-     */
-    private void setTexture(Material material, int mapTo, Texture texture) {
-        switch (mapTo) {
-            case MTEX_COL:
-                material.setTexture(shadeless ? MaterialHelper.TEXTURE_TYPE_COLOR : MaterialHelper.TEXTURE_TYPE_DIFFUSE, texture);
-                break;
-            case MTEX_NOR:
-                material.setTexture(MaterialHelper.TEXTURE_TYPE_NORMAL, texture);
-                break;
-            case MTEX_SPEC:
-                material.setTexture(MaterialHelper.TEXTURE_TYPE_SPECULAR, texture);
-                break;
-            case MTEX_EMIT:
-                material.setTexture(MaterialHelper.TEXTURE_TYPE_GLOW, texture);
-                break;
-            case MTEX_ALPHA:
-                if (!shadeless) {
-                    material.setTexture(MaterialHelper.TEXTURE_TYPE_ALPHA, texture);
-                } else {
-                    LOGGER.warning("JME does not support alpha map on unshaded material. Material name is " + name);
-                }
-                break;
-            case MTEX_AMB:
-                material.setTexture(MaterialHelper.TEXTURE_TYPE_LIGHTMAP, texture);
-                break;
-            default:
-                LOGGER.severe("Unknown mapping type: " + mapTo);
-        }
-    }
-
-    /**
-     * @return <b>true</b> if the material has at least one generated texture and <b>false</b> otherwise
-     */
-    public boolean hasGeneratedTextures() {
-        if (loadedTextures != null) {
-            for (CombinedTexture generatedTextures : loadedTextures) {
-                if (generatedTextures.hasGeneratedTextures()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This method sets the face cull mode.
-     * @param faceCullMode
-     *            the face cull mode
-     */
-    public void setFaceCullMode(FaceCullMode faceCullMode) {
-        this.faceCullMode = faceCullMode;
-    }
-
-    /**
-     * This method returns the diffuse color.
-     * 
-     * @param materialStructure
-     *            the material structure
-     * @param diffuseShader
-     *            the diffuse shader
-     * @return the diffuse color
-     */
-    private ColorRGBA readDiffuseColor(Structure materialStructure, DiffuseShader diffuseShader) {
-        // bitwise 'or' of all textures mappings
-        int commonMapto = ((Number) materialStructure.getFieldValue("mapto")).intValue();
-
-        // diffuse color
-        float r = ((Number) materialStructure.getFieldValue("r")).floatValue();
-        float g = ((Number) materialStructure.getFieldValue("g")).floatValue();
-        float b = ((Number) materialStructure.getFieldValue("b")).floatValue();
-        float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue();
-        if ((commonMapto & 0x01) == 0x01) {// Col
-            return new ColorRGBA(r, g, b, alpha);
-        } else {
-            switch (diffuseShader) {
-                case FRESNEL:
-                case ORENNAYAR:
-                case TOON:
-                    break;// TODO: find what is the proper modification
-                case MINNAERT:
-                case LAMBERT:// TODO: check if that is correct
-                    float ref = ((Number) materialStructure.getFieldValue("ref")).floatValue();
-                    r *= ref;
-                    g *= ref;
-                    b *= ref;
-                    break;
-                default:
-                    throw new IllegalStateException("Unknown diffuse shader type: " + diffuseShader.toString());
-            }
-            return new ColorRGBA(r, g, b, alpha);
-        }
-    }
-
-    /**
-     * This method returns a specular color used by the material.
-     * 
-     * @param materialStructure
-     *            the material structure filled with data
-     * @return a specular color used by the material
-     */
-    private ColorRGBA readSpecularColor(Structure materialStructure) {
-        float specularIntensity = ((Number) materialStructure.getFieldValue("spec")).floatValue();
-        float r = ((Number) materialStructure.getFieldValue("specr")).floatValue() * specularIntensity;
-        float g = ((Number) materialStructure.getFieldValue("specg")).floatValue() * specularIntensity;
-        float b = ((Number) materialStructure.getFieldValue("specb")).floatValue() * specularIntensity;
-        float alpha = ((Number) materialStructure.getFieldValue("alpha")).floatValue();
-        return new ColorRGBA(r, g, b, alpha);
-    }
-
-    @Override
-    public void write(JmeExporter e) throws IOException {
-        throw new IOException("Material context is not for saving! It implements savable only to be passed to another blend file as a Savable in user data!");
-    }
-
-    @Override
-    public void read(JmeImporter e) throws IOException {
-        throw new IOException("Material context is not for loading! It implements savable only to be passed to another blend file as a Savable in user data!");
-    }
-}

+ 0 - 387
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/materials/MaterialHelper.java

@@ -1,387 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.materials;
-
-import java.nio.ByteBuffer;
-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.material.MatParam;
-import com.jme3.material.Material;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.shader.VarType;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.texture.Texture;
-import com.jme3.util.BufferUtils;
-
-public class MaterialHelper extends AbstractBlenderHelper {
-    private static final Logger              LOGGER                = Logger.getLogger(MaterialHelper.class.getName());
-    protected static final float             DEFAULT_SHININESS     = 20.0f;
-
-    public static final String               TEXTURE_TYPE_COLOR    = "ColorMap";
-    public static final String               TEXTURE_TYPE_DIFFUSE  = "DiffuseMap";
-    public static final String               TEXTURE_TYPE_NORMAL   = "NormalMap";
-    public static final String               TEXTURE_TYPE_SPECULAR = "SpecularMap";
-    public static final String               TEXTURE_TYPE_GLOW     = "GlowMap";
-    public static final String               TEXTURE_TYPE_ALPHA    = "AlphaMap";
-    public static final String               TEXTURE_TYPE_LIGHTMAP = "LightMap";
-
-    public static final Integer              ALPHA_MASK_NONE       = Integer.valueOf(0);
-    public static final Integer              ALPHA_MASK_CIRCLE     = Integer.valueOf(1);
-    public static final Integer              ALPHA_MASK_CONE       = Integer.valueOf(2);
-    public static final Integer              ALPHA_MASK_HYPERBOLE  = Integer.valueOf(3);
-    protected final Map<Integer, IAlphaMask> alphaMasks            = new HashMap<Integer, IAlphaMask>();
-
-    /**
-     * The type of the material's diffuse shader.
-     */
-    public static enum DiffuseShader {
-        LAMBERT, ORENNAYAR, TOON, MINNAERT, FRESNEL
-    }
-
-    /**
-     * The type of the material's specular shader.
-     */
-    public static enum SpecularShader {
-        COOKTORRENCE, PHONG, BLINN, TOON, WARDISO
-    }
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public MaterialHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-        // setting alpha masks
-        alphaMasks.put(ALPHA_MASK_NONE, new IAlphaMask() {
-            @Override
-            public void setImageSize(int width, int height) {
-            }
-
-            @Override
-            public byte getAlpha(float x, float y) {
-                return (byte) 255;
-            }
-        });
-        alphaMasks.put(ALPHA_MASK_CIRCLE, new IAlphaMask() {
-            private float   r;
-            private float[] center;
-
-            @Override
-            public void setImageSize(int width, int height) {
-                r = Math.min(width, height) * 0.5f;
-                center = new float[] { width * 0.5f, height * 0.5f };
-            }
-
-            @Override
-            public byte getAlpha(float x, float y) {
-                float d = FastMath.abs(FastMath.sqrt((x - center[0]) * (x - center[0]) + (y - center[1]) * (y - center[1])));
-                return (byte) (d >= r ? 0 : 255);
-            }
-        });
-        alphaMasks.put(ALPHA_MASK_CONE, new IAlphaMask() {
-            private float   r;
-            private float[] center;
-
-            @Override
-            public void setImageSize(int width, int height) {
-                r = Math.min(width, height) * 0.5f;
-                center = new float[] { width * 0.5f, height * 0.5f };
-            }
-
-            @Override
-            public byte getAlpha(float x, float y) {
-                float d = FastMath.abs(FastMath.sqrt((x - center[0]) * (x - center[0]) + (y - center[1]) * (y - center[1])));
-                return (byte) (d >= r ? 0 : -255.0f * d / r + 255.0f);
-            }
-        });
-        alphaMasks.put(ALPHA_MASK_HYPERBOLE, new IAlphaMask() {
-            private float   r;
-            private float[] center;
-
-            @Override
-            public void setImageSize(int width, int height) {
-                r = Math.min(width, height) * 0.5f;
-                center = new float[] { width * 0.5f, height * 0.5f };
-            }
-
-            @Override
-            public byte getAlpha(float x, float y) {
-                float d = FastMath.abs(FastMath.sqrt((x - center[0]) * (x - center[0]) + (y - center[1]) * (y - center[1]))) / r;
-                return d >= 1.0f ? 0 : (byte) ((-FastMath.sqrt((2.0f - d) * d) + 1.0f) * 255.0f);
-            }
-        });
-    }
-
-    /**
-     * This method converts the material structure to jme Material.
-     * @param structure
-     *            structure with material data
-     * @param blenderContext
-     *            the blender context
-     * @return jme material
-     * @throws BlenderFileException
-     *             an exception is throw when problems with blend file occur
-     */
-    public MaterialContext toMaterialContext(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
-        MaterialContext result = (MaterialContext) blenderContext.getLoadedFeature(structure.getOldMemoryAddress(), LoadedDataType.FEATURE);
-        if (result != null) {
-            return result;
-        }
-
-        if ("ID".equals(structure.getType())) {
-            LOGGER.fine("Loading material from external blend file.");
-            return (MaterialContext) this.loadLibrary(structure);
-        }
-
-        LOGGER.fine("Loading material.");
-        result = new MaterialContext(structure, blenderContext);
-        LOGGER.log(Level.FINE, "Material''s name: {0}", result.name);
-        Long oma = structure.getOldMemoryAddress();
-        blenderContext.addLoadedFeatures(oma, LoadedDataType.STRUCTURE, structure);
-        blenderContext.addLoadedFeatures(oma, LoadedDataType.FEATURE, result);
-        return result;
-    }
-
-    /**
-     * This method converts the given material into particles-usable material.
-     * The texture and glow color are being copied.
-     * The method assumes it receives the Lighting type of material.
-     * @param material
-     *            the source material
-     * @param blenderContext
-     *            the blender context
-     * @return material converted into particles-usable material
-     */
-    public Material getParticlesMaterial(Material material, Integer alphaMaskIndex, BlenderContext blenderContext) {
-        Material result = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
-
-        // copying texture
-        MatParam diffuseMap = material.getParam("DiffuseMap");
-        if (diffuseMap != null) {
-            Texture texture = ((Texture) diffuseMap.getValue()).clone();
-
-            // applying alpha mask to the texture
-            Image image = texture.getImage();
-            ByteBuffer sourceBB = image.getData(0);
-            sourceBB.rewind();
-            int w = image.getWidth();
-            int h = image.getHeight();
-            ByteBuffer bb = BufferUtils.createByteBuffer(w * h * 4);
-            IAlphaMask iAlphaMask = alphaMasks.get(alphaMaskIndex);
-            iAlphaMask.setImageSize(w, h);
-
-            for (int x = 0; x < w; ++x) {
-                for (int y = 0; y < h; ++y) {
-                    bb.put(sourceBB.get());
-                    bb.put(sourceBB.get());
-                    bb.put(sourceBB.get());
-                    bb.put(iAlphaMask.getAlpha(x, y));
-                }
-            }
-
-            image = new Image(Format.RGBA8, w, h, bb, ColorSpace.Linear);
-            texture.setImage(image);
-
-            result.setTextureParam("Texture", VarType.Texture2D, texture);
-        }
-
-        // copying glow color
-        MatParam glowColor = material.getParam("GlowColor");
-        if (glowColor != null) {
-            ColorRGBA color = (ColorRGBA) glowColor.getValue();
-            result.setParam("GlowColor", VarType.Vector3, color);
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the table of materials connected to the specified structure. The given structure can be of any type (ie. mesh or
-     * curve) but needs to have 'mat' field/
-     * 
-     * @param structureWithMaterials
-     *            the structure containing the mesh data
-     * @param blenderContext
-     *            the blender context
-     * @return a list of vertices colors, each color belongs to a single vertex
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is somehow invalid or corrupted
-     */
-    public MaterialContext[] getMaterials(Structure structureWithMaterials, BlenderContext blenderContext) throws BlenderFileException {
-        Pointer ppMaterials = (Pointer) structureWithMaterials.getFieldValue("mat");
-        MaterialContext[] materials = null;
-        if (ppMaterials.isNotNull()) {
-            List<Structure> materialStructures = ppMaterials.fetchData();
-            if (materialStructures != null && materialStructures.size() > 0) {
-                MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
-                materials = new MaterialContext[materialStructures.size()];
-                int i = 0;
-                for (Structure s : materialStructures) {
-                    materials[i++] = s == null ? null : materialHelper.toMaterialContext(s, blenderContext);
-                }
-            }
-        }
-        return materials;
-    }
-
-    /**
-     * This method converts rgb values to hsv values.
-     * 
-     * @param r
-     *            red value of the color
-     * @param g
-     *            green value of the color
-     * @param b
-     *            blue value of the color
-     * @param hsv
-     *            hsv values of a color (this table contains the result of the transformation)
-     */
-    public void rgbToHsv(float r, float g, float b, float[] hsv) {
-        float cmax = r;
-        float cmin = r;
-        cmax = g > cmax ? g : cmax;
-        cmin = g < cmin ? g : cmin;
-        cmax = b > cmax ? b : cmax;
-        cmin = b < cmin ? b : cmin;
-
-        hsv[2] = cmax; /* value */
-        if (cmax != 0.0) {
-            hsv[1] = (cmax - cmin) / cmax;
-        } else {
-            hsv[1] = 0.0f;
-            hsv[0] = 0.0f;
-        }
-        if (hsv[1] == 0.0) {
-            hsv[0] = -1.0f;
-        } else {
-            float cdelta = cmax - cmin;
-            float rc = (cmax - r) / cdelta;
-            float gc = (cmax - g) / cdelta;
-            float bc = (cmax - b) / cdelta;
-            if (r == cmax) {
-                hsv[0] = bc - gc;
-            } else if (g == cmax) {
-                hsv[0] = 2.0f + rc - bc;
-            } else {
-                hsv[0] = 4.0f + gc - rc;
-            }
-            hsv[0] *= 60.0f;
-            if (hsv[0] < 0.0f) {
-                hsv[0] += 360.0f;
-            }
-        }
-
-        hsv[0] /= 360.0f;
-        if (hsv[0] < 0.0f) {
-            hsv[0] = 0.0f;
-        }
-    }
-
-    /**
-     * This method converts rgb values to hsv values.
-     * 
-     * @param h
-     *            hue
-     * @param s
-     *            saturation
-     * @param v
-     *            value
-     * @param rgb
-     *            rgb result vector (should have 3 elements)
-     */
-    public void hsvToRgb(float h, float s, float v, float[] rgb) {
-        h *= 360.0f;
-        if (s == 0.0) {
-            rgb[0] = rgb[1] = rgb[2] = v;
-        } else {
-            if (h == 360) {
-                h = 0;
-            } else {
-                h /= 60;
-            }
-            int i = (int) Math.floor(h);
-            float f = h - i;
-            float p = v * (1.0f - s);
-            float q = v * (1.0f - s * f);
-            float t = v * (1.0f - s * (1.0f - f));
-            switch (i) {
-                case 0:
-                    rgb[0] = v;
-                    rgb[1] = t;
-                    rgb[2] = p;
-                    break;
-                case 1:
-                    rgb[0] = q;
-                    rgb[1] = v;
-                    rgb[2] = p;
-                    break;
-                case 2:
-                    rgb[0] = p;
-                    rgb[1] = v;
-                    rgb[2] = t;
-                    break;
-                case 3:
-                    rgb[0] = p;
-                    rgb[1] = q;
-                    rgb[2] = v;
-                    break;
-                case 4:
-                    rgb[0] = t;
-                    rgb[1] = p;
-                    rgb[2] = v;
-                    break;
-                case 5:
-                    rgb[0] = v;
-                    rgb[1] = p;
-                    rgb[2] = q;
-                    break;
-            }
-        }
-    }
-}

+ 0 - 583
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DQuaternion.java

@@ -1,583 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.math;
-
-import java.io.IOException;
-
-import com.jme3.export.InputCapsule;
-import com.jme3.export.JmeExporter;
-import com.jme3.export.JmeImporter;
-import com.jme3.export.OutputCapsule;
-import com.jme3.export.Savable;
-import com.jme3.math.Quaternion;
-
-/**
- * <code>DQuaternion</code> defines a single example of a more general class of
- * hypercomplex numbers. DQuaternions extends a rotation in three dimensions to a
- * rotation in four dimensions. This avoids "gimbal lock" and allows for smooth
- * continuous rotation.
- * 
- * <code>DQuaternion</code> is defined by four double point numbers: {x y z w}.
- * 
- * This class's only purpose is to give better accuracy in floating point operations during computations.
- * This is made by copying the original Quaternion class from jme3 core and leaving only required methods and basic computation methods, so that
- * the class is smaller and easier to maintain.
- * Should any other methods be needed, they will be added.
- * 
- * @author Mark Powell
- * @author Joshua Slack
- * @author Marcin Roguski (Kaelthas)
- */
-public final class DQuaternion implements Savable, Cloneable, java.io.Serializable {
-    private static final long       serialVersionUID = 5009180713885017539L;
-
-    /**
-     * Represents the identity quaternion rotation (0, 0, 0, 1).
-     */
-    public static final DQuaternion IDENTITY         = new DQuaternion();
-    public static final DQuaternion DIRECTION_Z      = new DQuaternion();
-    public static final DQuaternion ZERO             = new DQuaternion(0, 0, 0, 0);
-    protected double                x, y, z, w = 1;
-
-    /**
-     * Constructor instantiates a new <code>DQuaternion</code> object
-     * initializing all values to zero, except w which is initialized to 1.
-     *
-     */
-    public DQuaternion() {
-    }
-
-    /**
-     * Constructor instantiates a new <code>DQuaternion</code> object from the
-     * given list of parameters.
-     *
-     * @param x
-     *            the x value of the quaternion.
-     * @param y
-     *            the y value of the quaternion.
-     * @param z
-     *            the z value of the quaternion.
-     * @param w
-     *            the w value of the quaternion.
-     */
-    public DQuaternion(double x, double y, double z, double w) {
-        this.set(x, y, z, w);
-    }
-
-    public DQuaternion(Quaternion q) {
-        this(q.getX(), q.getY(), q.getZ(), q.getW());
-    }
-
-    public Quaternion toQuaternion() {
-        return new Quaternion((float) x, (float) y, (float) z, (float) w);
-    }
-
-    public double getX() {
-        return x;
-    }
-
-    public double getY() {
-        return y;
-    }
-
-    public double getZ() {
-        return z;
-    }
-
-    public double getW() {
-        return w;
-    }
-
-    /**
-     * sets the data in a <code>DQuaternion</code> object from the given list
-     * of parameters.
-     *
-     * @param x
-     *            the x value of the quaternion.
-     * @param y
-     *            the y value of the quaternion.
-     * @param z
-     *            the z value of the quaternion.
-     * @param w
-     *            the w value of the quaternion.
-     * @return this
-     */
-    public DQuaternion set(double x, double y, double z, double w) {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-        this.w = w;
-        return this;
-    }
-
-    /**
-     * Sets the data in this <code>DQuaternion</code> object to be equal to the
-     * passed <code>DQuaternion</code> object. The values are copied producing
-     * a new object.
-     *
-     * @param q
-     *            The DQuaternion to copy values from.
-     * @return this
-     */
-    public DQuaternion set(DQuaternion q) {
-        x = q.x;
-        y = q.y;
-        z = q.z;
-        w = q.w;
-        return this;
-    }
-
-    /**
-     * Sets this DQuaternion to {0, 0, 0, 1}. Same as calling set(0,0,0,1).
-     */
-    public void loadIdentity() {
-        x = y = z = 0;
-        w = 1;
-    }
-
-    /**
-     * <code>norm</code> returns the norm of this quaternion. This is the dot
-     * product of this quaternion with itself.
-     *
-     * @return the norm of the quaternion.
-     */
-    public double norm() {
-        return w * w + x * x + y * y + z * z;
-    }
-    
-    public DQuaternion fromRotationMatrix(double m00, double m01, double m02,
-            double m10, double m11, double m12, double m20, double m21, double m22) {
-        // first normalize the forward (F), up (U) and side (S) vectors of the rotation matrix
-        // so that the scale does not affect the rotation
-        double lengthSquared = m00 * m00 + m10 * m10 + m20 * m20;
-        if (lengthSquared != 1f && lengthSquared != 0f) {
-            lengthSquared = 1.0 / Math.sqrt(lengthSquared);
-            m00 *= lengthSquared;
-            m10 *= lengthSquared;
-            m20 *= lengthSquared;
-        }
-        lengthSquared = m01 * m01 + m11 * m11 + m21 * m21;
-        if (lengthSquared != 1 && lengthSquared != 0f) {
-            lengthSquared = 1.0 / Math.sqrt(lengthSquared);
-            m01 *= lengthSquared;
-            m11 *= lengthSquared;
-            m21 *= lengthSquared;
-        }
-        lengthSquared = m02 * m02 + m12 * m12 + m22 * m22;
-        if (lengthSquared != 1f && lengthSquared != 0f) {
-            lengthSquared = 1.0 / Math.sqrt(lengthSquared);
-            m02 *= lengthSquared;
-            m12 *= lengthSquared;
-            m22 *= lengthSquared;
-        }
-
-        // Use the Graphics Gems code, from 
-        // ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z
-        // *NOT* the "Matrix and Quaternions FAQ", which has errors!
-
-        // the trace is the sum of the diagonal elements; see
-        // http://mathworld.wolfram.com/MatrixTrace.html
-        double t = m00 + m11 + m22;
-
-        // we protect the division by s by ensuring that s>=1
-        if (t >= 0) { // |w| >= .5
-            double s = Math.sqrt(t + 1); // |s|>=1 ...
-            w = 0.5f * s;
-            s = 0.5f / s;                 // so this division isn't bad
-            x = (m21 - m12) * s;
-            y = (m02 - m20) * s;
-            z = (m10 - m01) * s;
-        } else if (m00 > m11 && m00 > m22) {
-            double s = Math.sqrt(1.0 + m00 - m11 - m22); // |s|>=1
-            x = s * 0.5f; // |x| >= .5
-            s = 0.5f / s;
-            y = (m10 + m01) * s;
-            z = (m02 + m20) * s;
-            w = (m21 - m12) * s;
-        } else if (m11 > m22) {
-            double s = Math.sqrt(1.0 + m11 - m00 - m22); // |s|>=1
-            y = s * 0.5f; // |y| >= .5
-            s = 0.5f / s;
-            x = (m10 + m01) * s;
-            z = (m21 + m12) * s;
-            w = (m02 - m20) * s;
-        } else {
-            double s = Math.sqrt(1.0 + m22 - m00 - m11); // |s|>=1
-            z = s * 0.5f; // |z| >= .5
-            s = 0.5f / s;
-            x = (m02 + m20) * s;
-            y = (m21 + m12) * s;
-            w = (m10 - m01) * s;
-        }
-
-        return this;
-    }
-    
-    /**
-     * <code>toRotationMatrix</code> converts this quaternion to a rotational
-     * matrix. The result is stored in result. 4th row and 4th column values are
-     * untouched. Note: the result is created from a normalized version of this quat.
-     * 
-     * @param result
-     *            The Matrix4f to store the result in.
-     * @return the rotation matrix representation of this quaternion.
-     */
-    public Matrix toRotationMatrix(Matrix result) {
-        Vector3d originalScale = new Vector3d();
-        
-        result.toScaleVector(originalScale);
-        result.setScale(1, 1, 1);
-        double norm = this.norm();
-        // we explicitly test norm against one here, saving a division
-        // at the cost of a test and branch.  Is it worth it?
-        double s = norm == 1f ? 2f : norm > 0f ? 2f / norm : 0;
-
-        // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs
-        // will be used 2-4 times each.
-        double xs = x * s;
-        double ys = y * s;
-        double zs = z * s;
-        double xx = x * xs;
-        double xy = x * ys;
-        double xz = x * zs;
-        double xw = w * xs;
-        double yy = y * ys;
-        double yz = y * zs;
-        double yw = w * ys;
-        double zz = z * zs;
-        double zw = w * zs;
-
-        // using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here
-        result.set(0, 0, 1 - (yy + zz));
-        result.set(0, 1, xy - zw);
-        result.set(0, 2, xz + yw);
-        result.set(1, 0, xy + zw);
-        result.set(1, 1, 1 - (xx + zz));
-        result.set(1, 2, yz - xw);
-        result.set(2, 0, xz - yw);
-        result.set(2, 1, yz + xw);
-        result.set(2, 2, 1 - (xx + yy));
-        
-        result.setScale(originalScale);
-        
-        return result;
-    }
-    
-    /**
-     * <code>fromAngleAxis</code> sets this quaternion to the values specified
-     * by an angle and an axis of rotation. This method creates an object, so
-     * use fromAngleNormalAxis if your axis is already normalized.
-     *
-     * @param angle
-     *            the angle to rotate (in radians).
-     * @param axis
-     *            the axis of rotation.
-     * @return this quaternion
-     */
-    public DQuaternion fromAngleAxis(double angle, Vector3d axis) {
-        Vector3d normAxis = axis.normalize();
-        this.fromAngleNormalAxis(angle, normAxis);
-        return this;
-    }
-
-    /**
-     * <code>fromAngleNormalAxis</code> sets this quaternion to the values
-     * specified by an angle and a normalized axis of rotation.
-     *
-     * @param angle
-     *            the angle to rotate (in radians).
-     * @param axis
-     *            the axis of rotation (already normalized).
-     */
-    public DQuaternion fromAngleNormalAxis(double angle, Vector3d axis) {
-        if (axis.x == 0 && axis.y == 0 && axis.z == 0) {
-            this.loadIdentity();
-        } else {
-            double halfAngle = 0.5f * angle;
-            double sin = Math.sin(halfAngle);
-            w = Math.cos(halfAngle);
-            x = sin * axis.x;
-            y = sin * axis.y;
-            z = sin * axis.z;
-        }
-        return this;
-    }
-
-    /**
-     * <code>add</code> adds the values of this quaternion to those of the
-     * parameter quaternion. The result is returned as a new quaternion.
-     *
-     * @param q
-     *            the quaternion to add to this.
-     * @return the new quaternion.
-     */
-    public DQuaternion add(DQuaternion q) {
-        return new DQuaternion(x + q.x, y + q.y, z + q.z, w + q.w);
-    }
-
-    /**
-     * <code>add</code> adds the values of this quaternion to those of the
-     * parameter quaternion. The result is stored in this DQuaternion.
-     *
-     * @param q
-     *            the quaternion to add to this.
-     * @return This DQuaternion after addition.
-     */
-    public DQuaternion addLocal(DQuaternion q) {
-        x += q.x;
-        y += q.y;
-        z += q.z;
-        w += q.w;
-        return this;
-    }
-
-    /**
-     * <code>subtract</code> subtracts the values of the parameter quaternion
-     * from those of this quaternion. The result is returned as a new
-     * quaternion.
-     *
-     * @param q
-     *            the quaternion to subtract from this.
-     * @return the new quaternion.
-     */
-    public DQuaternion subtract(DQuaternion q) {
-        return new DQuaternion(x - q.x, y - q.y, z - q.z, w - q.w);
-    }
-
-    /**
-     * <code>subtract</code> subtracts the values of the parameter quaternion
-     * from those of this quaternion. The result is stored in this DQuaternion.
-     *
-     * @param q
-     *            the quaternion to subtract from this.
-     * @return This DQuaternion after subtraction.
-     */
-    public DQuaternion subtractLocal(DQuaternion q) {
-        x -= q.x;
-        y -= q.y;
-        z -= q.z;
-        w -= q.w;
-        return this;
-    }
-
-    /**
-     * <code>mult</code> multiplies this quaternion by a parameter quaternion.
-     * The result is returned as a new quaternion. It should be noted that
-     * quaternion multiplication is not commutative so q * p != p * q.
-     *
-     * @param q
-     *            the quaternion to multiply this quaternion by.
-     * @return the new quaternion.
-     */
-    public DQuaternion mult(DQuaternion q) {
-        return this.mult(q, null);
-    }
-
-    /**
-     * <code>mult</code> multiplies this quaternion by a parameter quaternion.
-     * The result is returned as a new quaternion. It should be noted that
-     * quaternion multiplication is not commutative so q * p != p * q.
-     *
-     * It IS safe for q and res to be the same object.
-     * It IS NOT safe for this and res to be the same object.
-     *
-     * @param q
-     *            the quaternion to multiply this quaternion by.
-     * @param res
-     *            the quaternion to store the result in.
-     * @return the new quaternion.
-     */
-    public DQuaternion mult(DQuaternion q, DQuaternion res) {
-        if (res == null) {
-            res = new DQuaternion();
-        }
-        double qw = q.w, qx = q.x, qy = q.y, qz = q.z;
-        res.x = x * qw + y * qz - z * qy + w * qx;
-        res.y = -x * qz + y * qw + z * qx + w * qy;
-        res.z = x * qy - y * qx + z * qw + w * qz;
-        res.w = -x * qx - y * qy - z * qz + w * qw;
-        return res;
-    }
-
-    /**
-     * <code>mult</code> multiplies this quaternion by a parameter vector. The
-     * result is returned as a new vector.
-     *
-     * @param v
-     *            the vector to multiply this quaternion by.
-     * @return the new vector.
-     */
-    public Vector3d mult(Vector3d v) {
-        return this.mult(v, null);
-    }
-
-    /**
-     * Multiplies this DQuaternion by the supplied quaternion. The result is
-     * stored in this DQuaternion, which is also returned for chaining. Similar
-     * to this *= q.
-     *
-     * @param q
-     *            The DQuaternion to multiply this one by.
-     * @return This DQuaternion, after multiplication.
-     */
-    public DQuaternion multLocal(DQuaternion q) {
-        double x1 = x * q.w + y * q.z - z * q.y + w * q.x;
-        double y1 = -x * q.z + y * q.w + z * q.x + w * q.y;
-        double z1 = x * q.y - y * q.x + z * q.w + w * q.z;
-        w = -x * q.x - y * q.y - z * q.z + w * q.w;
-        x = x1;
-        y = y1;
-        z = z1;
-        return this;
-    }
-
-    /**
-     * <code>mult</code> multiplies this quaternion by a parameter vector. The
-     * result is returned as a new vector.
-     * 
-     * @param v
-     *            the vector to multiply this quaternion by.
-     * @param store
-     *            the vector to store the result in. It IS safe for v and store
-     *            to be the same object.
-     * @return the result vector.
-     */
-    public Vector3d mult(Vector3d v, Vector3d store) {
-        if (store == null) {
-            store = new Vector3d();
-        }
-        if (v.x == 0 && v.y == 0 && v.z == 0) {
-            store.set(0, 0, 0);
-        } else {
-            double vx = v.x, vy = v.y, vz = v.z;
-            store.x = w * w * vx + 2 * y * w * vz - 2 * z * w * vy + x * x * vx + 2 * y * x * vy + 2 * z * x * vz - z * z * vx - y * y * vx;
-            store.y = 2 * x * y * vx + y * y * vy + 2 * z * y * vz + 2 * w * z * vx - z * z * vy + w * w * vy - 2 * x * w * vz - x * x * vy;
-            store.z = 2 * x * z * vx + 2 * y * z * vy + z * z * vz - 2 * w * y * vx - y * y * vz + 2 * w * x * vy - x * x * vz + w * w * vz;
-        }
-        return store;
-    }
-
-    /**
-     *
-     * <code>toString</code> creates the string representation of this <code>DQuaternion</code>. The values of the quaternion are displaced (x,
-     * y, z, w), in the following manner: <br>
-     * (x, y, z, w)
-     *
-     * @return the string representation of this object.
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "(" + x + ", " + y + ", " + z + ", " + w + ")";
-    }
-
-    /**
-     * <code>equals</code> determines if two quaternions are logically equal,
-     * that is, if the values of (x, y, z, w) are the same for both quaternions.
-     *
-     * @param o
-     *            the object to compare for equality
-     * @return true if they are equal, false otherwise.
-     */
-    @Override
-    public boolean equals(Object o) {
-        if (!(o instanceof DQuaternion)) {
-            return false;
-        }
-
-        if (this == o) {
-            return true;
-        }
-
-        DQuaternion comp = (DQuaternion) o;
-        if (Double.compare(x, comp.x) != 0) {
-            return false;
-        }
-        if (Double.compare(y, comp.y) != 0) {
-            return false;
-        }
-        if (Double.compare(z, comp.z) != 0) {
-            return false;
-        }
-        if (Double.compare(w, comp.w) != 0) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * 
-     * <code>hashCode</code> returns the hash code value as an integer and is
-     * supported for the benefit of hashing based collection classes such as
-     * Hashtable, HashMap, HashSet etc.
-     * 
-     * @return the hashcode for this instance of DQuaternion.
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        long hash = 37;
-        hash = 37 * hash + Double.doubleToLongBits(x);
-        hash = 37 * hash + Double.doubleToLongBits(y);
-        hash = 37 * hash + Double.doubleToLongBits(z);
-        hash = 37 * hash + Double.doubleToLongBits(w);
-        return (int) hash;
-
-    }
-
-    @Override
-    public void write(JmeExporter e) throws IOException {
-        OutputCapsule cap = e.getCapsule(this);
-        cap.write(x, "x", 0);
-        cap.write(y, "y", 0);
-        cap.write(z, "z", 0);
-        cap.write(w, "w", 1);
-    }
-
-    @Override
-    public void read(JmeImporter e) throws IOException {
-        InputCapsule cap = e.getCapsule(this);
-        x = cap.readFloat("x", 0);
-        y = cap.readFloat("y", 0);
-        z = cap.readFloat("z", 0);
-        w = cap.readFloat("w", 1);
-    }
-
-    @Override
-    public DQuaternion clone() {
-        try {
-            return (DQuaternion) super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError(); // can not happen
-        }
-    }
-}

+ 0 - 190
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DTransform.java

@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.math;
-
-import java.io.IOException;
-
-import com.jme3.export.InputCapsule;
-import com.jme3.export.JmeExporter;
-import com.jme3.export.JmeImporter;
-import com.jme3.export.OutputCapsule;
-import com.jme3.export.Savable;
-import com.jme3.math.Transform;
-
-/**
- * Started Date: Jul 16, 2004<br>
- * <br>
- * Represents a translation, rotation and scale in one object.
- * 
- * This class's only purpose is to give better accuracy in floating point operations during computations.
- * This is made by copying the original Transfrom class from jme3 core and removing unnecessary methods so that
- * the class is smaller and easier to maintain.
- * Should any other methods be needed, they will be added.
- * 
- * @author Jack Lindamood
- * @author Joshua Slack
- * @author Marcin Roguski (Kaelthas)
- */
-public final class DTransform implements Savable, Cloneable, java.io.Serializable {
-    private static final long serialVersionUID = 7812915425940606722L;
-
-    private DQuaternion       rotation;
-    private Vector3d          translation;
-    private Vector3d          scale;
-
-    public DTransform() {
-        translation = new Vector3d();
-        rotation = new DQuaternion();
-        scale = new Vector3d();
-    }
-    
-    public DTransform(Transform transform) {
-        translation = new Vector3d(transform.getTranslation());
-        rotation = new DQuaternion(transform.getRotation());
-        scale = new Vector3d(transform.getScale());
-    }
-
-    public Transform toTransform() {
-        return new Transform(translation.toVector3f(), rotation.toQuaternion(), scale.toVector3f());
-    }
-    
-    public Matrix toMatrix() {
-        Matrix m = Matrix.identity(4);
-        m.setTranslation(translation);
-        m.setRotationQuaternion(rotation);
-        m.setScale(scale);
-        return m;
-    }
-    
-    /**
-     * Sets this translation to the given value.
-     * @param trans
-     *            The new translation for this matrix.
-     * @return this
-     */
-    public DTransform setTranslation(Vector3d trans) {
-        translation.set(trans);
-        return this;
-    }
-
-    /**
-     * Sets this rotation to the given DQuaternion value.
-     * @param rot
-     *            The new rotation for this matrix.
-     * @return this
-     */
-    public DTransform setRotation(DQuaternion rot) {
-        rotation.set(rot);
-        return this;
-    }
-
-    /**
-     * Sets this scale to the given value.
-     * @param scale
-     *            The new scale for this matrix.
-     * @return this
-     */
-    public DTransform setScale(Vector3d scale) {
-        this.scale.set(scale);
-        return this;
-    }
-
-    /**
-     * Sets this scale to the given value.
-     * @param scale
-     *            The new scale for this matrix.
-     * @return this
-     */
-    public DTransform setScale(float scale) {
-        this.scale.set(scale, scale, scale);
-        return this;
-    }
-
-    /**
-     * Return the translation vector in this matrix.
-     * @return translation vector.
-     */
-    public Vector3d getTranslation() {
-        return translation;
-    }
-
-    /**
-     * Return the rotation quaternion in this matrix.
-     * @return rotation quaternion.
-     */
-    public DQuaternion getRotation() {
-        return rotation;
-    }
-
-    /**
-     * Return the scale vector in this matrix.
-     * @return scale vector.
-     */
-    public Vector3d getScale() {
-        return scale;
-    }
-
-    @Override
-    public String toString() {
-        return this.getClass().getSimpleName() + "[ " + translation.x + ", " + translation.y + ", " + translation.z + "]\n" + "[ " + rotation.x + ", " + rotation.y + ", " + rotation.z + ", " + rotation.w + "]\n" + "[ " + scale.x + " , " + scale.y + ", " + scale.z + "]";
-    }
-
-    @Override
-    public void write(JmeExporter e) throws IOException {
-        OutputCapsule capsule = e.getCapsule(this);
-        capsule.write(rotation, "rot", new DQuaternion());
-        capsule.write(translation, "translation", Vector3d.ZERO);
-        capsule.write(scale, "scale", Vector3d.UNIT_XYZ);
-    }
-
-    @Override
-    public void read(JmeImporter e) throws IOException {
-        InputCapsule capsule = e.getCapsule(this);
-
-        rotation = (DQuaternion) capsule.readSavable("rot", new DQuaternion());
-        translation = (Vector3d) capsule.readSavable("translation", Vector3d.ZERO);
-        scale = (Vector3d) capsule.readSavable("scale", Vector3d.UNIT_XYZ);
-    }
-
-    @Override
-    public DTransform clone() {
-        try {
-            DTransform tq = (DTransform) super.clone();
-            tq.rotation = rotation.clone();
-            tq.scale = scale.clone();
-            tq.translation = translation.clone();
-            return tq;
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError();
-        }
-    }
-}

+ 0 - 210
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Matrix.java

@@ -1,210 +0,0 @@
-package com.jme3.scene.plugins.blender.math;
-
-import java.text.DecimalFormat;
-
-import org.ejml.ops.CommonOps;
-import org.ejml.simple.SimpleMatrix;
-import org.ejml.simple.SimpleSVD;
-
-import com.jme3.math.FastMath;
-
-/**
- * Encapsulates a 4x4 matrix
- *
- *
- */
-public class Matrix extends SimpleMatrix {
-    private static final long serialVersionUID = 2396600537315902559L;
-
-    public Matrix(int rows, int cols) {
-        super(rows, cols);
-    }
-
-    /**
-     * Copy constructor
-     */
-    public Matrix(SimpleMatrix m) {
-        super(m);
-    }
-    
-    public Matrix(double[][] data) {
-        super(data);
-    }
-    
-    public static Matrix identity(int size) {
-        Matrix result = new Matrix(size, size);
-        CommonOps.setIdentity(result.mat);
-        return result;
-    }
-    
-    public Matrix pseudoinverse() {
-        return this.pseudoinverse(1);
-    }
-    
-    @SuppressWarnings("unchecked")
-    public Matrix pseudoinverse(double lambda) {
-        SimpleSVD<SimpleMatrix> simpleSVD = this.svd();
-        
-        SimpleMatrix U = simpleSVD.getU();
-        SimpleMatrix S = simpleSVD.getW();
-        SimpleMatrix V = simpleSVD.getV();
-        
-        int N = Math.min(this.numRows(),this.numCols());
-        double maxSingular = 0;
-        for( int i = 0; i < N; ++i ) {
-            if( S.get(i, i) > maxSingular ) {
-                maxSingular = S.get(i, i);
-            }
-        }
-        
-        double tolerance = FastMath.DBL_EPSILON * Math.max(this.numRows(),this.numCols()) * maxSingular;
-        for(int i=0;i<Math.min(S.numRows(), S.numCols());++i) {
-            double a = S.get(i, i);
-            if(a <= tolerance) {
-                a = 0;
-            } else {
-                a = a/(a * a + lambda * lambda);
-            }
-            S.set(i, i, a);
-        }
-        return new Matrix(V.mult(S.transpose()).mult(U.transpose()));
-    }
-    
-    public void setColumn(Vector3d col, int column) {
-        this.setColumn(column, 0, col.x, col.y, col.z);
-    }
-    
-    /**
-     * Just for some debug informations in order to compare the results with the scilab computation program.
-     * @param name the name of the matrix
-     * @param m the matrix to print out
-     * @return the String format of the matrix to easily input it to Scilab
-     */
-    public String toScilabString(String name, SimpleMatrix m) {
-        String result = name + " = [";
-        
-        for(int i=0;i<m.numRows();++i) {
-            for(int j=0;j<m.numCols();++j) {
-                result += m.get(i, j) + " ";
-            }
-            result += ";";
-        }
-        
-        return result;
-    }
-    
-    /**
-     * @return a String representation of the matrix
-     */
-    @Override
-    public String toString() {
-        DecimalFormat df = new DecimalFormat("#.0000");
-        StringBuilder buf = new StringBuilder();
-        for (int r = 0; r < this.numRows(); ++r) {
-            buf.append("\n| ");
-            for (int c = 0; c < this.numCols(); ++c) {
-                buf.append(df.format(this.get(r, c))).append(' ');
-            }
-            buf.append('|');
-        }
-        return buf.toString();
-    }
-    
-    public void setTranslation(Vector3d translation) {
-        this.setColumn(translation, 3);
-    }
-    
-    /**
-     * Sets the scale.
-     * 
-     * @param scale
-     *            the scale vector to set
-     */
-    public void setScale(Vector3d scale) {
-        this.setScale(scale.x, scale.y, scale.z);
-    }
-    
-    /**
-     * Sets the scale.
-     * 
-     * @param x
-     *            the X scale
-     * @param y
-     *            the Y scale
-     * @param z
-     *            the Z scale
-     */
-    public void setScale(double x, double y, double z) {
-        Vector3d vect1 = new Vector3d(this.get(0, 0), this.get(1, 0), this.get(2, 0));
-        vect1.normalizeLocal().multLocal(x);
-        this.set(0, 0, vect1.x);
-        this.set(1, 0, vect1.y);
-        this.set(2, 0, vect1.z);
-
-        vect1.set(this.get(0, 1), this.get(1, 1), this.get(2, 1));
-        vect1.normalizeLocal().multLocal(y);
-        this.set(0, 1, vect1.x);
-        this.set(1, 1, vect1.y);
-        this.set(2, 1, vect1.z);
-
-        vect1.set(this.get(0, 2), this.get(1, 2), this.get(2, 2));
-        vect1.normalizeLocal().multLocal(z);
-        this.set(0, 2, vect1.x);
-        this.set(1, 2, vect1.y);
-        this.set(2, 2, vect1.z);
-    }
-    
-    /**
-     * <code>setRotationQuaternion</code> builds a rotation from a
-     * <code>Quaternion</code>.
-     * 
-     * @param quat
-     *            the quaternion to build the rotation from.
-     * @throws NullPointerException
-     *             if quat is null.
-     */
-    public void setRotationQuaternion(DQuaternion quat) {
-        quat.toRotationMatrix(this);
-    }
-    
-    public DTransform toTransform() {
-        DTransform result = new DTransform();
-        result.setTranslation(this.toTranslationVector());
-        result.setRotation(this.toRotationQuat());
-        result.setScale(this.toScaleVector());
-        return result;
-    }
-    
-    public Vector3d toTranslationVector() {
-        return new Vector3d(this.get(0, 3), this.get(1, 3), this.get(2, 3));
-    }
-    
-    public DQuaternion toRotationQuat() {
-        DQuaternion quat = new DQuaternion();
-        quat.fromRotationMatrix(this.get(0, 0), this.get(0, 1), this.get(0, 2), this.get(1, 0), this.get(1, 1), this.get(1, 2), this.get(2, 0), this.get(2, 1), this.get(2, 2));
-        return quat;
-    }
-    
-    /**
-     * Retrieves the scale vector from the matrix and stores it into a given
-     * vector.
-     */
-    public Vector3d toScaleVector() {
-        Vector3d result = new Vector3d();
-        this.toScaleVector(result);
-        return result;
-    }
-    
-    /**
-     * Retrieves the scale vector from the matrix and stores it into a given
-     * vector.
-     * 
-     * @param vector the vector where the scale will be stored
-     */
-    public void toScaleVector(Vector3d vector) {
-        double scaleX = Math.sqrt(this.get(0, 0) * this.get(0, 0) + this.get(1, 0) * this.get(1, 0) + this.get(2, 0) * this.get(2, 0));
-        double scaleY = Math.sqrt(this.get(0, 1) * this.get(0, 1) + this.get(1, 1) * this.get(1, 1) + this.get(2, 1) * this.get(2, 1));
-        double scaleZ = Math.sqrt(this.get(0, 2) * this.get(0, 2) + this.get(1, 2) * this.get(1, 2) + this.get(2, 2) * this.get(2, 2));
-        vector.set(scaleX, scaleY, scaleZ);
-    }
-}

+ 0 - 869
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Vector3d.java

@@ -1,869 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.math;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.logging.Logger;
-
-import com.jme3.export.InputCapsule;
-import com.jme3.export.JmeExporter;
-import com.jme3.export.JmeImporter;
-import com.jme3.export.OutputCapsule;
-import com.jme3.export.Savable;
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector3f;
-
-/*
- * -- Added *Local methods to cut down on object creation - JS
- */
-
-/**
- * <code>Vector3d</code> defines a Vector for a three float value tuple. <code>Vector3d</code> can represent any three dimensional value, such as a
- * vertex, a normal, etc. Utility methods are also included to aid in
- * mathematical calculations.
- *
- * This class's only purpose is to give better accuracy in floating point operations during computations.
- * This is made by copying the original Vector3f class from jme3 core and leaving only required methods and basic computation methods, so that
- * the class is smaller and easier to maintain.
- * Should any other methods be needed, they will be added.
- *
- * @author Mark Powell
- * @author Joshua Slack
- * @author Marcin Roguski (Kaelthas)
- */
-public final class Vector3d implements Savable, Cloneable, Serializable {
-    private static final long    serialVersionUID = 3090477054277293078L;
-
-    private static final Logger  LOGGER           = Logger.getLogger(Vector3d.class.getName());
-
-    public final static Vector3d ZERO             = new Vector3d();
-    public final static Vector3d UNIT_XYZ         = new Vector3d(1, 1, 1);
-    public final static Vector3d UNIT_X           = new Vector3d(1, 0, 0);
-    public final static Vector3d UNIT_Y           = new Vector3d(0, 1, 0);
-    public final static Vector3d UNIT_Z           = new Vector3d(0, 0, 1);
-
-    /**
-     * the x value of the vector.
-     */
-    public double                x;
-
-    /**
-     * the y value of the vector.
-     */
-    public double                y;
-
-    /**
-     * the z value of the vector.
-     */
-    public double                z;
-
-    /**
-     * Constructor instantiates a new <code>Vector3d</code> with default
-     * values of (0,0,0).
-     *
-     */
-    public Vector3d() {
-    }
-
-    /**
-     * Constructor instantiates a new <code>Vector3d</code> with provides
-     * values.
-     *
-     * @param x
-     *            the x value of the vector.
-     * @param y
-     *            the y value of the vector.
-     * @param z
-     *            the z value of the vector.
-     */
-    public Vector3d(double x, double y, double z) {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-    }
-
-    /**
-     * Constructor instantiates a new <code>Vector3d</code> that is a copy
-     * of the provided vector
-     * @param vector3f
-     *            The Vector3f to copy
-     */
-    public Vector3d(Vector3f vector3f) {
-        this(vector3f.x, vector3f.y, vector3f.z);
-    }
-
-    public Vector3f toVector3f() {
-        return new Vector3f((float) x, (float) y, (float) z);
-    }
-
-    /**
-     * <code>set</code> sets the x,y,z values of the vector based on passed
-     * parameters.
-     *
-     * @param x
-     *            the x value of the vector.
-     * @param y
-     *            the y value of the vector.
-     * @param z
-     *            the z value of the vector.
-     * @return this vector
-     */
-    public Vector3d set(double x, double y, double z) {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-        return this;
-    }
-
-    /**
-     * <code>set</code> sets the x,y,z values of the vector by copying the
-     * supplied vector.
-     *
-     * @param vect
-     *            the vector to copy.
-     * @return this vector
-     */
-    public Vector3d set(Vector3d vect) {
-        return this.set(vect.x, vect.y, vect.z);
-    }
-
-    /**
-     *
-     * <code>add</code> adds a provided vector to this vector creating a
-     * resultant vector which is returned. If the provided vector is null, null
-     * is returned.
-     *
-     * @param vec
-     *            the vector to add to this.
-     * @return the resultant vector.
-     */
-    public Vector3d add(Vector3d vec) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, null returned.");
-            return null;
-        }
-        return new Vector3d(x + vec.x, y + vec.y, z + vec.z);
-    }
-
-    /**
-     *
-     * <code>add</code> adds the values of a provided vector storing the
-     * values in the supplied vector.
-     *
-     * @param vec
-     *            the vector to add to this
-     * @param result
-     *            the vector to store the result in
-     * @return result returns the supplied result vector.
-     */
-    public Vector3d add(Vector3d vec, Vector3d result) {
-        result.x = x + vec.x;
-        result.y = y + vec.y;
-        result.z = z + vec.z;
-        return result;
-    }
-
-    /**
-     * <code>addLocal</code> adds a provided vector to this vector internally,
-     * and returns a handle to this vector for easy chaining of calls. If the
-     * provided vector is null, null is returned.
-     *
-     * @param vec
-     *            the vector to add to this vector.
-     * @return this
-     */
-    public Vector3d addLocal(Vector3d vec) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, null returned.");
-            return null;
-        }
-        x += vec.x;
-        y += vec.y;
-        z += vec.z;
-        return this;
-    }
-
-    /**
-     *
-     * <code>add</code> adds the provided values to this vector, creating a
-     * new vector that is then returned.
-     *
-     * @param addX
-     *            the x value to add.
-     * @param addY
-     *            the y value to add.
-     * @param addZ
-     *            the z value to add.
-     * @return the result vector.
-     */
-    public Vector3d add(double addX, double addY, double addZ) {
-        return new Vector3d(x + addX, y + addY, z + addZ);
-    }
-
-    /**
-     * <code>addLocal</code> adds the provided values to this vector
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls.
-     *
-     * @param addX
-     *            value to add to x
-     * @param addY
-     *            value to add to y
-     * @param addZ
-     *            value to add to z
-     * @return this
-     */
-    public Vector3d addLocal(double addX, double addY, double addZ) {
-        x += addX;
-        y += addY;
-        z += addZ;
-        return this;
-    }
-
-    /**
-     *
-     * <code>scaleAdd</code> multiplies this vector by a scalar then adds the
-     * given Vector3d.
-     *
-     * @param scalar
-     *            the value to multiply this vector by.
-     * @param add
-     *            the value to add
-     */
-    public Vector3d scaleAdd(double scalar, Vector3d add) {
-        x = x * scalar + add.x;
-        y = y * scalar + add.y;
-        z = z * scalar + add.z;
-        return this;
-    }
-
-    /**
-     *
-     * <code>scaleAdd</code> multiplies the given vector by a scalar then adds
-     * the given vector.
-     *
-     * @param scalar
-     *            the value to multiply this vector by.
-     * @param mult
-     *            the value to multiply the scalar by
-     * @param add
-     *            the value to add
-     */
-    public Vector3d scaleAdd(double scalar, Vector3d mult, Vector3d add) {
-        x = mult.x * scalar + add.x;
-        y = mult.y * scalar + add.y;
-        z = mult.z * scalar + add.z;
-        return this;
-    }
-
-    /**
-     *
-     * <code>dot</code> calculates the dot product of this vector with a
-     * provided vector. If the provided vector is null, 0 is returned.
-     *
-     * @param vec
-     *            the vector to dot with this vector.
-     * @return the resultant dot product of this vector and a given vector.
-     */
-    public double dot(Vector3d vec) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, 0 returned.");
-            return 0;
-        }
-        return x * vec.x + y * vec.y + z * vec.z;
-    }
-
-    /**
-     * <code>cross</code> calculates the cross product of this vector with a
-     * parameter vector v.
-     *
-     * @param v
-     *            the vector to take the cross product of with this.
-     * @return the cross product vector.
-     */
-    public Vector3d cross(Vector3d v) {
-        return this.cross(v, null);
-    }
-
-    /**
-     * <code>cross</code> calculates the cross product of this vector with a
-     * parameter vector v. The result is stored in <code>result</code>
-     *
-     * @param v
-     *            the vector to take the cross product of with this.
-     * @param result
-     *            the vector to store the cross product result.
-     * @return result, after receiving the cross product vector.
-     */
-    public Vector3d cross(Vector3d v, Vector3d result) {
-        return this.cross(v.x, v.y, v.z, result);
-    }
-
-    /**
-     * <code>cross</code> calculates the cross product of this vector with a
-     * parameter vector v. The result is stored in <code>result</code>
-     *
-     * @param otherX
-     *            x component of the vector to take the cross product of with this.
-     * @param otherY
-     *            y component of the vector to take the cross product of with this.
-     * @param otherZ
-     *            z component of the vector to take the cross product of with this.
-     * @param result
-     *            the vector to store the cross product result.
-     * @return result, after receiving the cross product vector.
-     */
-    public Vector3d cross(double otherX, double otherY, double otherZ, Vector3d result) {
-        if (result == null) {
-            result = new Vector3d();
-        }
-        double resX = y * otherZ - z * otherY;
-        double resY = z * otherX - x * otherZ;
-        double resZ = x * otherY - y * otherX;
-        result.set(resX, resY, resZ);
-        return result;
-    }
-
-    /**
-     * <code>crossLocal</code> calculates the cross product of this vector
-     * with a parameter vector v.
-     *
-     * @param v
-     *            the vector to take the cross product of with this.
-     * @return this.
-     */
-    public Vector3d crossLocal(Vector3d v) {
-        return this.crossLocal(v.x, v.y, v.z);
-    }
-
-    /**
-     * <code>crossLocal</code> calculates the cross product of this vector
-     * with a parameter vector v.
-     *
-     * @param otherX
-     *            x component of the vector to take the cross product of with this.
-     * @param otherY
-     *            y component of the vector to take the cross product of with this.
-     * @param otherZ
-     *            z component of the vector to take the cross product of with this.
-     * @return this.
-     */
-    public Vector3d crossLocal(double otherX, double otherY, double otherZ) {
-        double tempx = y * otherZ - z * otherY;
-        double tempy = z * otherX - x * otherZ;
-        z = x * otherY - y * otherX;
-        x = tempx;
-        y = tempy;
-        return this;
-    }
-
-    /**
-     * <code>length</code> calculates the magnitude of this vector.
-     *
-     * @return the length or magnitude of the vector.
-     */
-    public double length() {
-        return Math.sqrt(this.lengthSquared());
-    }
-
-    /**
-     * <code>lengthSquared</code> calculates the squared value of the
-     * magnitude of the vector.
-     *
-     * @return the magnitude squared of the vector.
-     */
-    public double lengthSquared() {
-        return x * x + y * y + z * z;
-    }
-
-    /**
-     * <code>distanceSquared</code> calculates the distance squared between
-     * this vector and vector v.
-     *
-     * @param v
-     *            the second vector to determine the distance squared.
-     * @return the distance squared between the two vectors.
-     */
-    public double distanceSquared(Vector3d v) {
-        double dx = x - v.x;
-        double dy = y - v.y;
-        double dz = z - v.z;
-        return dx * dx + dy * dy + dz * dz;
-    }
-
-    /**
-     * <code>distance</code> calculates the distance between this vector and
-     * vector v.
-     *
-     * @param v
-     *            the second vector to determine the distance.
-     * @return the distance between the two vectors.
-     */
-    public double distance(Vector3d v) {
-        return Math.sqrt(this.distanceSquared(v));
-    }
-
-    /**
-     *
-     * <code>mult</code> multiplies this vector by a scalar. The resultant
-     * vector is returned.
-     *
-     * @param scalar
-     *            the value to multiply this vector by.
-     * @return the new vector.
-     */
-    public Vector3d mult(double scalar) {
-        return new Vector3d(x * scalar, y * scalar, z * scalar);
-    }
-
-    /**
-     *
-     * <code>mult</code> multiplies this vector by a scalar. The resultant
-     * vector is supplied as the second parameter and returned.
-     *
-     * @param scalar
-     *            the scalar to multiply this vector by.
-     * @param product
-     *            the product to store the result in.
-     * @return product
-     */
-    public Vector3d mult(double scalar, Vector3d product) {
-        if (null == product) {
-            product = new Vector3d();
-        }
-
-        product.x = x * scalar;
-        product.y = y * scalar;
-        product.z = z * scalar;
-        return product;
-    }
-
-    /**
-     * <code>multLocal</code> multiplies this vector by a scalar internally,
-     * and returns a handle to this vector for easy chaining of calls.
-     *
-     * @param scalar
-     *            the value to multiply this vector by.
-     * @return this
-     */
-    public Vector3d multLocal(double scalar) {
-        x *= scalar;
-        y *= scalar;
-        z *= scalar;
-        return this;
-    }
-
-    /**
-     * <code>multLocal</code> multiplies a provided vector by this vector
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls. If the provided vector is null, null is returned.
-     *
-     * @param vec
-     *            the vector to multiply by this vector.
-     * @return this
-     */
-    public Vector3d multLocal(Vector3d vec) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, null returned.");
-            return null;
-        }
-        x *= vec.x;
-        y *= vec.y;
-        z *= vec.z;
-        return this;
-    }
-
-    /**
-     * <code>multLocal</code> multiplies this vector by 3 scalars
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls.
-     *
-     * @param x
-     * @param y
-     * @param z
-     * @return this
-     */
-    public Vector3d multLocal(double x, double y, double z) {
-        this.x *= x;
-        this.y *= y;
-        this.z *= z;
-        return this;
-    }
-
-    /**
-     * <code>multLocal</code> multiplies a provided vector by this vector
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls. If the provided vector is null, null is returned.
-     *
-     * @param vec
-     *            the vector to mult to this vector.
-     * @return this
-     */
-    public Vector3d mult(Vector3d vec) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, null returned.");
-            return null;
-        }
-        return this.mult(vec, null);
-    }
-
-    /**
-     * <code>multLocal</code> multiplies a provided vector by this vector
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls. If the provided vector is null, null is returned.
-     *
-     * @param vec
-     *            the vector to mult to this vector.
-     * @param store
-     *            result vector (null to create a new vector)
-     * @return this
-     */
-    public Vector3d mult(Vector3d vec, Vector3d store) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, null returned.");
-            return null;
-        }
-        if (store == null) {
-            store = new Vector3d();
-        }
-        return store.set(x * vec.x, y * vec.y, z * vec.z);
-    }
-
-    /**
-     * <code>divide</code> divides the values of this vector by a scalar and
-     * returns the result. The values of this vector remain untouched.
-     *
-     * @param scalar
-     *            the value to divide this vectors attributes by.
-     * @return the result <code>Vector</code>.
-     */
-    public Vector3d divide(double scalar) {
-        scalar = 1f / scalar;
-        return new Vector3d(x * scalar, y * scalar, z * scalar);
-    }
-
-    /**
-     * <code>divideLocal</code> divides this vector by a scalar internally,
-     * and returns a handle to this vector for easy chaining of calls. Dividing
-     * by zero will result in an exception.
-     *
-     * @param scalar
-     *            the value to divides this vector by.
-     * @return this
-     */
-    public Vector3d divideLocal(double scalar) {
-        scalar = 1f / scalar;
-        x *= scalar;
-        y *= scalar;
-        z *= scalar;
-        return this;
-    }
-
-    /**
-     * <code>divide</code> divides the values of this vector by a scalar and
-     * returns the result. The values of this vector remain untouched.
-     *
-     * @param scalar
-     *            the value to divide this vectors attributes by.
-     * @return the result <code>Vector</code>.
-     */
-    public Vector3d divide(Vector3d scalar) {
-        return new Vector3d(x / scalar.x, y / scalar.y, z / scalar.z);
-    }
-
-    /**
-     * <code>divideLocal</code> divides this vector by a scalar internally,
-     * and returns a handle to this vector for easy chaining of calls. Dividing
-     * by zero will result in an exception.
-     *
-     * @param scalar
-     *            the value to divides this vector by.
-     * @return this
-     */
-    public Vector3d divideLocal(Vector3d scalar) {
-        x /= scalar.x;
-        y /= scalar.y;
-        z /= scalar.z;
-        return this;
-    }
-
-    /**
-     *
-     * <code>negate</code> returns the negative of this vector. All values are
-     * negated and set to a new vector.
-     *
-     * @return the negated vector.
-     */
-    public Vector3d negate() {
-        return new Vector3d(-x, -y, -z);
-    }
-
-    /**
-     *
-     * <code>negateLocal</code> negates the internal values of this vector.
-     *
-     * @return this.
-     */
-    public Vector3d negateLocal() {
-        x = -x;
-        y = -y;
-        z = -z;
-        return this;
-    }
-
-    /**
-     *
-     * <code>subtract</code> subtracts the values of a given vector from those
-     * of this vector creating a new vector object. If the provided vector is
-     * null, null is returned.
-     *
-     * @param vec
-     *            the vector to subtract from this vector.
-     * @return the result vector.
-     */
-    public Vector3d subtract(Vector3d vec) {
-        return new Vector3d(x - vec.x, y - vec.y, z - vec.z);
-    }
-
-    /**
-     * <code>subtractLocal</code> subtracts a provided vector from this vector
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls. If the provided vector is null, null is returned.
-     *
-     * @param vec
-     *            the vector to subtract
-     * @return this
-     */
-    public Vector3d subtractLocal(Vector3d vec) {
-        if (null == vec) {
-            LOGGER.warning("Provided vector is null, null returned.");
-            return null;
-        }
-        x -= vec.x;
-        y -= vec.y;
-        z -= vec.z;
-        return this;
-    }
-
-    /**
-     *
-     * <code>subtract</code>
-     *
-     * @param vec
-     *            the vector to subtract from this
-     * @param result
-     *            the vector to store the result in
-     * @return result
-     */
-    public Vector3d subtract(Vector3d vec, Vector3d result) {
-        if (result == null) {
-            result = new Vector3d();
-        }
-        result.x = x - vec.x;
-        result.y = y - vec.y;
-        result.z = z - vec.z;
-        return result;
-    }
-
-    /**
-     *
-     * <code>subtract</code> subtracts the provided values from this vector,
-     * creating a new vector that is then returned.
-     *
-     * @param subtractX
-     *            the x value to subtract.
-     * @param subtractY
-     *            the y value to subtract.
-     * @param subtractZ
-     *            the z value to subtract.
-     * @return the result vector.
-     */
-    public Vector3d subtract(double subtractX, double subtractY, double subtractZ) {
-        return new Vector3d(x - subtractX, y - subtractY, z - subtractZ);
-    }
-
-    /**
-     * <code>subtractLocal</code> subtracts the provided values from this vector
-     * internally, and returns a handle to this vector for easy chaining of
-     * calls.
-     *
-     * @param subtractX
-     *            the x value to subtract.
-     * @param subtractY
-     *            the y value to subtract.
-     * @param subtractZ
-     *            the z value to subtract.
-     * @return this
-     */
-    public Vector3d subtractLocal(double subtractX, double subtractY, double subtractZ) {
-        x -= subtractX;
-        y -= subtractY;
-        z -= subtractZ;
-        return this;
-    }
-
-    /**
-     * <code>normalize</code> returns the unit vector of this vector.
-     *
-     * @return unit vector of this vector.
-     */
-    public Vector3d normalize() {
-        double length = x * x + y * y + z * z;
-        if (length != 1f && length != 0f) {
-            length = 1.0f / Math.sqrt(length);
-            return new Vector3d(x * length, y * length, z * length);
-        }
-        return this.clone();
-    }
-
-    /**
-     * <code>normalizeLocal</code> makes this vector into a unit vector of
-     * itself.
-     *
-     * @return this.
-     */
-    public Vector3d normalizeLocal() {
-        // NOTE: this implementation is more optimized
-        // than the old jme normalize as this method
-        // is commonly used.
-        double length = x * x + y * y + z * z;
-        if (length != 1f && length != 0f) {
-            length = 1.0f / Math.sqrt(length);
-            x *= length;
-            y *= length;
-            z *= length;
-        }
-        return this;
-    }
-
-    /**
-     * <code>angleBetween</code> returns (in radians) the angle between two vectors.
-     * It is assumed that both this vector and the given vector are unit vectors (iow, normalized).
-     * 
-     * @param otherVector
-     *            a unit vector to find the angle against
-     * @return the angle in radians.
-     */
-    public double angleBetween(Vector3d otherVector) {
-        double dot = this.dot(otherVector);
-        // the vectors are normalized, but if they are parallel then the dot product migh get a value like: 1.000000000000000002
-        // which is caused by floating point operations; in such case, the acos function will return NaN so we need to clamp this value
-        dot = FastMath.clamp((float) dot, -1, 1);
-        return Math.acos(dot);
-    }
-
-    @Override
-    public Vector3d clone() {
-        try {
-            return (Vector3d) super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError(); // can not happen
-        }
-    }
-
-    /**
-     * are these two vectors the same? they are is they both have the same x,y,
-     * and z values.
-     *
-     * @param o
-     *            the object to compare for equality
-     * @return true if they are equal
-     */
-    @Override
-    public boolean equals(Object o) {
-        if (!(o instanceof Vector3d)) {
-            return false;
-        }
-
-        if (this == o) {
-            return true;
-        }
-
-        Vector3d comp = (Vector3d) o;
-        if (Double.compare(x, comp.x) != 0) {
-            return false;
-        }
-        if (Double.compare(y, comp.y) != 0) {
-            return false;
-        }
-        if (Double.compare(z, comp.z) != 0) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * <code>hashCode</code> returns a unique code for this vector object based
-     * on its values. If two vectors are logically equivalent, they will return
-     * the same hash code value.
-     * @return the hash code value of this vector.
-     */
-    @Override
-    public int hashCode() {
-        long hash = 37;
-        hash += 37 * hash + Double.doubleToLongBits(x);
-        hash += 37 * hash + Double.doubleToLongBits(y);
-        hash += 37 * hash + Double.doubleToLongBits(z);
-        return (int) hash;
-    }
-
-    /**
-     * <code>toString</code> returns the string representation of this vector.
-     * The format is:
-     *
-     * org.jme.math.Vector3d [X=XX.XXXX, Y=YY.YYYY, Z=ZZ.ZZZZ]
-     *
-     * @return the string representation of this vector.
-     */
-    @Override
-    public String toString() {
-        return "(" + x + ", " + y + ", " + z + ")";
-    }
-
-    @Override
-    public void write(JmeExporter e) throws IOException {
-        OutputCapsule capsule = e.getCapsule(this);
-        capsule.write(x, "x", 0);
-        capsule.write(y, "y", 0);
-        capsule.write(z, "z", 0);
-    }
-
-    @Override
-    public void read(JmeImporter e) throws IOException {
-        InputCapsule capsule = e.getCapsule(this);
-        x = capsule.readDouble("x", 0);
-        y = capsule.readDouble("y", 0);
-        z = capsule.readDouble("z", 0);
-    }
-}

+ 0 - 349
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Edge.java

@@ -1,349 +0,0 @@
-package com.jme3.scene.plugins.blender.meshes;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.math.Vector3d;
-import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
-
-/**
- * A class that represents a single edge between two vertices.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class Edge {
-    private static final Logger LOGGER                = Logger.getLogger(Edge.class.getName());
-
-    private static final int    FLAG_EDGE_NOT_IN_FACE = 0x80;
-
-    /** The vertices indexes. */
-    private int                 index1, index2;
-    /** The vertices that can be set if we need and abstract edge outside the mesh (for computations). */
-    private Vector3f 			v1, v2;
-    /** The weight of the edge. */
-    private float               crease;
-    /** A variable that indicates if this edge belongs to any face or not. */
-    private boolean             inFace;
-    /** The mesh that owns the edge. */
-    private TemporalMesh        temporalMesh;
-
-    public Edge(Vector3f v1, Vector3f v2) {
-		this.v1 = v1 == null ? new Vector3f() : v1;
-		this.v2 = v2 == null ? new Vector3f() : v2;
-		index1 = 0;
-		index2 = 1;
-	}
-    
-    /**
-     * This constructor only stores the indexes of the vertices. The position vertices should be stored
-     * outside this class.
-     * @param index1
-     *            the first index of the edge
-     * @param index2
-     *            the second index of the edge
-     * @param crease
-     *            the weight of the face
-     * @param inFace
-     *            a variable that indicates if this edge belongs to any face or not
-     */
-    public Edge(int index1, int index2, float crease, boolean inFace, TemporalMesh temporalMesh) {
-        this.index1 = index1;
-        this.index2 = index2;
-        this.crease = crease;
-        this.inFace = inFace;
-        this.temporalMesh = temporalMesh;
-    }
-
-    @Override
-    public Edge clone() {
-        return new Edge(index1, index2, crease, inFace, temporalMesh);
-    }
-
-    /**
-     * @return the first index of the edge
-     */
-    public int getFirstIndex() {
-        return index1;
-    }
-
-    /**
-     * @return the second index of the edge
-     */
-    public int getSecondIndex() {
-        return index2;
-    }
-
-    /**
-     * @return the first vertex of the edge
-     */
-    public Vector3f getFirstVertex() {
-        return temporalMesh == null ? v1 : temporalMesh.getVertices().get(index1);
-    }
-
-    /**
-     * @return the second vertex of the edge
-     */
-    public Vector3f getSecondVertex() {
-        return temporalMesh == null ? v2 : temporalMesh.getVertices().get(index2);
-    }
-
-    /**
-     * Returns the index other than the given.
-     * @param index
-     *            index of the edge
-     * @return the remaining index number
-     */
-    public int getOtherIndex(int index) {
-        if (index == index1) {
-            return index2;
-        }
-        if (index == index2) {
-            return index1;
-        }
-        throw new IllegalArgumentException("Cannot give the other index for [" + index + "] because this index does not exist in edge: " + this);
-    }
-
-    /**
-     * @return the crease value of the edge (its weight)
-     */
-    public float getCrease() {
-        return crease;
-    }
-
-    /**
-     * @return <b>true</b> if the edge is used by at least one face and <b>false</b> otherwise
-     */
-    public boolean isInFace() {
-        return inFace;
-    }
-
-    /**
-     * @return the length of the edge
-     */
-    public float getLength() {
-        return this.getFirstVertex().distance(this.getSecondVertex());
-    }
-
-    /**
-     * @return the mesh this edge belongs to
-     */
-    public TemporalMesh getTemporalMesh() {
-        return temporalMesh;
-    }
-
-    /**
-     * @return the centroid of the edge
-     */
-    public Vector3f computeCentroid() {
-        return this.getFirstVertex().add(this.getSecondVertex()).divideLocal(2);
-    }
-
-    /**
-     * Shifts indexes by a given amount.
-     * @param shift
-     *            how much the indexes should be shifted
-     * @param predicate
-     *            the predicate that verifies which indexes should be shifted; if null then all will be shifted
-     */
-    public void shiftIndexes(int shift, IndexPredicate predicate) {
-        if (predicate == null) {
-            index1 += shift;
-            index2 += shift;
-        } else {
-            index1 += predicate.execute(index1) ? shift : 0;
-            index2 += predicate.execute(index2) ? shift : 0;
-        }
-    }
-
-    /**
-     * Flips the order of the indexes.
-     */
-    public void flipIndexes() {
-        int temp = index1;
-        index1 = index2;
-        index2 = temp;
-    }
-
-    /**
-     * The crossing method first computes the points on both lines (that contain the edges)
-     * who are closest in distance. If the distance between points is smaller than FastMath.FLT_EPSILON
-     * the we consider them to be the same point (the lines cross).
-     * The second step is to check if both points are contained within the edges.
-     * 
-     * The method of computing the crossing point is as follows:
-     * Let's assume that:
-     * (P0, P1) are the points of the first edge
-     * (Q0, Q1) are the points of the second edge
-     * 
-     * u = P1 - P0
-     * v = Q1 - Q0
-     * 
-     * This gives us the equations of two lines:
-     * L1: (x = P1x + ux*t1; y = P1y + uy*t1; z = P1z + uz*t1)
-     * L2: (x = P2x + vx*t2; y = P2y + vy*t2; z = P2z + vz*t2)
-     * 
-     * Comparing the x and y of the first two equations for each line will allow us to compute t1 and t2
-     * (which is implemented below).
-     * Using t1 and t2 we can compute (x, y, z) of each line and that will give us two points that we need to compare.
-     * 
-     * @param edge
-     *            the edge we check against crossing
-     * @return <b>true</b> if the edges cross and false otherwise
-     */
-    public boolean cross(Edge edge) {
-        return this.getCrossPoint(edge) != null;
-    }
-    
-    /**
-	 * The method computes the crossing pint of this edge and another edge. If
-	 * there is no crossing then null is returned.
-	 * 
-	 * @param edge
-	 *            the edge to compute corss point with
-	 * @return cross point on null if none exist
-	 */
-	public Vector3f getCrossPoint(Edge edge) {
-		return this.getCrossPoint(edge, false, false);
-	}
-    
-	/**
-	 * The method computes the crossing pint of this edge and another edge. If
-	 * there is no crossing then null is returned. Also null is returned if the edges are parallel.
-	 * This method also allows to get the crossing point of the straight lines that contain these edges if
-	 * you set the 'extend' parameter to true.
-	 * 
-	 * @param edge
-	 *            the edge to compute corss point with
-	 * @param extendThisEdge
-	 *            set to <b>true</b> to find a crossing point along the whole
-	 *            straight that contains the current edge
-	 * @param extendSecondEdge
-	 *            set to <b>true</b> to find a crossing point along the whole
-	 *            straight that contains the given edge
-	 * @return cross point on null if none exist or the edges are parallel
-	 */
-	public Vector3f getCrossPoint(Edge edge, boolean extendThisEdge, boolean extendSecondEdge) {
-		Vector3d P1 = new Vector3d(this.getFirstVertex());
-		Vector3d P2 = new Vector3d(edge.getFirstVertex());
-		Vector3d u = new Vector3d(this.getSecondVertex()).subtract(P1).normalizeLocal();
-		Vector3d v = new Vector3d(edge.getSecondVertex()).subtract(P2).normalizeLocal();
-		
-		if(Math.abs(u.dot(v)) >= 1 - FastMath.DBL_EPSILON) {
-			// the edges are parallel; do not care about the crossing point
-			return null;
-		}
-		
-		double t1 = 0, t2 = 0;
-		if(u.x == 0 && v.x == 0) {
-			t2 = (u.z * (P2.y - P1.y) - u.y * (P2.z - P1.z)) / (u.y * v.z - u.z * v.y);
-	        t1 = (P2.z - P1.z + v.z * t2) / u.z;
-		} else if(u.y == 0 && v.y == 0) {
-			t2 = (u.x * (P2.z - P1.z) - u.z * (P2.x - P1.x)) / (u.z * v.x - u.x * v.z);
-	        t1 = (P2.x - P1.x + v.x * t2) / u.x;
-		} else if(u.z == 0 && v.z == 0) {
-			t2 = (u.x * (P2.y - P1.y) - u.y * (P2.x - P1.x)) / (u.y * v.x - u.x * v.y);
-	        t1 = (P2.x - P1.x + v.x * t2) / u.x;
-		} else {
-			t2 = (P1.y * u.x - P1.x * u.y + P2.x * u.y - P2.y * u.x) / (v.y * u.x - u.y * v.x);
-			t1 = (P2.x - P1.x + v.x * t2) / u.x;
-			if(Math.abs(P1.z - P2.z + u.z * t1 - v.z * t2) > FastMath.FLT_EPSILON) {
-				return null;
-			}
-		}
-		Vector3d p1 = P1.add(u.mult(t1));
-        Vector3d p2 = P2.add(v.mult(t2));
-
-		if (p1.distance(p2) <= FastMath.FLT_EPSILON) {
-			if(extendThisEdge && extendSecondEdge) {
-				return p1.toVector3f();
-			}
-			// the lines cross, check if p1 and p2 are within the edges
-            Vector3d p = p1.subtract(P1);
-            double cos = p.dot(u) / p.length();
-            if (extendThisEdge || p.length()<= FastMath.FLT_EPSILON || cos >= 1 - FastMath.FLT_EPSILON && p.length() - this.getLength() <= FastMath.FLT_EPSILON) {
-                // p1 is inside the first edge, lets check the other edge now
-                p = p2.subtract(P2);
-                cos = p.dot(v) / p.length();
-                if(extendSecondEdge || p.length()<= FastMath.FLT_EPSILON || cos >= 1 - FastMath.FLT_EPSILON && p.length() - edge.getLength() <= FastMath.FLT_EPSILON) {
-                	return p1.toVector3f();
-                }
-            }
-        }
-		
-		return null;
-	}
-
-    @Override
-    public String toString() {
-        String result = "Edge [" + index1 + ", " + index2 + "] {" + crease + "}";
-        result += " (" + this.getFirstVertex() + " -> " + this.getSecondVertex() + ")";
-        if (inFace) {
-            result += "[F]";
-        }
-        return result;
-    }
-
-    @Override
-    public int hashCode() {
-        // The hash code must be identical for the same two indexes, no matter their order.
-        final int prime = 31;
-        int result = 1;
-        int lowerIndex = Math.min(index1, index2);
-        int higherIndex = Math.max(index1, index2);
-        result = prime * result + lowerIndex;
-        result = prime * result + higherIndex;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof Edge)) {
-            return false;
-        }
-        if (this == obj) {
-            return true;
-        }
-        Edge other = (Edge) obj;
-        return Math.min(index1, index2) == Math.min(other.index1, other.index2) && Math.max(index1, index2) == Math.max(other.index1, other.index2);
-    }
-
-    /**
-     * The method loads all edges from the given mesh structure that does not belong to any face.
-     * @param meshStructure
-     *            the mesh structure
-     * @param temporalMesh
-     *            the owner of the edges
-     * @return all edges without faces
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with file reading occur
-     */
-    public static List<Edge> loadAll(Structure meshStructure, TemporalMesh temporalMesh) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading all edges that do not belong to any face from mesh: {0}", meshStructure.getName());
-        List<Edge> result = new ArrayList<Edge>();
-
-        Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge");
-
-        if (pMEdge.isNotNull()) {
-            List<Structure> edges = pMEdge.fetchData();
-            for (Structure edge : edges) {
-                int flag = ((Number) edge.getFieldValue("flag")).intValue();
-
-                int v1 = ((Number) edge.getFieldValue("v1")).intValue();
-                int v2 = ((Number) edge.getFieldValue("v2")).intValue();
-                // I do not know why, but blender stores (possibly only sometimes) crease as negative values and shows positive in the editor
-                float crease = Math.abs(((Number) edge.getFieldValue("crease")).floatValue());
-                boolean edgeInFace = (flag & Edge.FLAG_EDGE_NOT_IN_FACE) == 0;
-                result.add(new Edge(v1, v2, crease, edgeInFace, temporalMesh));
-            }
-        }
-        LOGGER.log(Level.FINE, "Loaded {0} edges.", result.size());
-        return result;
-    }
-}

+ 0 - 613
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Face.java

@@ -1,613 +0,0 @@
-package com.jme3.scene.plugins.blender.meshes;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-
-/**
- * A class that represents a single face in the mesh. The face is a polygon. Its minimum count of
- * vertices is = 3.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class Face implements Comparator<Integer> {
-    private static final Logger         LOGGER = Logger.getLogger(Face.class.getName());
-
-    /** The indexes loop of the face. */
-    private IndexesLoop                 indexes;
-
-    private List<IndexesLoop>           triangulatedFaces;
-    /** Indicates if the face is smooth or solid. */
-    private boolean                     smooth;
-    /** The material index of the face. */
-    private int                         materialNumber;
-    /** UV coordinate sets attached to the face. The key is the set name and value are the UV coords. */
-    private Map<String, List<Vector2f>> faceUVCoords;
-    /** The vertex colors of the face. */
-    private List<byte[]>                vertexColors;
-    /** The temporal mesh the face belongs to. */
-    private TemporalMesh                temporalMesh;
-
-    /**
-     * Creates a complete face with all available data.
-     * @param indexes
-     *            the indexes of the face (required)
-     * @param smooth
-     *            indicates if the face is smooth or solid
-     * @param materialNumber
-     *            the material index of the face
-     * @param faceUVCoords
-     *            UV coordinate sets of the face (optional)
-     * @param vertexColors
-     *            the vertex colors of the face (optional)
-     * @param temporalMesh
-     *            the temporal mesh the face belongs to (required)
-     */
-    public Face(Integer[] indexes, boolean smooth, int materialNumber, Map<String, List<Vector2f>> faceUVCoords, List<byte[]> vertexColors, TemporalMesh temporalMesh) {
-        this.setTemporalMesh(temporalMesh);
-        this.indexes = new IndexesLoop(indexes);
-        this.smooth = smooth;
-        this.materialNumber = materialNumber;
-        this.faceUVCoords = faceUVCoords;
-        this.temporalMesh = temporalMesh;
-        this.vertexColors = vertexColors;
-    }
-
-    /**
-     * Default constructor. Used by the clone method.
-     */
-    private Face() {
-    }
-
-    @Override
-    public Face clone() {
-        Face result = new Face();
-        result.indexes = indexes.clone();
-        result.smooth = smooth;
-        result.materialNumber = materialNumber;
-        if (faceUVCoords != null) {
-            result.faceUVCoords = new HashMap<String, List<Vector2f>>(faceUVCoords.size());
-            for (Entry<String, List<Vector2f>> entry : faceUVCoords.entrySet()) {
-                List<Vector2f> uvs = new ArrayList<Vector2f>(entry.getValue().size());
-                for (Vector2f v : entry.getValue()) {
-                    uvs.add(v.clone());
-                }
-                result.faceUVCoords.put(entry.getKey(), uvs);
-            }
-        }
-        if (vertexColors != null) {
-            result.vertexColors = new ArrayList<byte[]>(vertexColors.size());
-            for (byte[] colors : vertexColors) {
-                result.vertexColors.add(colors.clone());
-            }
-        }
-        result.temporalMesh = temporalMesh;
-        return result;
-    }
-
-    /**
-     * Returns the index at the given position in the index loop. If the given position is negative or exceeds
-     * the amount of vertices - it is being looped properly so that it always hits an index.
-     * For example getIndex(-1) will return the index before the 0 - in this case it will be the last one.
-     * @param indexPosition
-     *            the index position
-     * @return index value at the given position
-     */
-    private Integer getIndex(int indexPosition) {
-        if (indexPosition >= indexes.size()) {
-            indexPosition = indexPosition % indexes.size();
-        } else if (indexPosition < 0) {
-            indexPosition = indexes.size() - -indexPosition % indexes.size();
-        }
-        return indexes.get(indexPosition);
-    }
-
-    /**
-     * @return the mesh this face belongs to
-     */
-    public TemporalMesh getTemporalMesh() {
-        return temporalMesh;
-    }
-
-    /**
-     * @return the original indexes of the face
-     */
-    public IndexesLoop getIndexes() {
-        return indexes;
-    }
-
-    /**
-     * @return the centroid of the face
-     */
-    public Vector3f computeCentroid() {
-        Vector3f result = new Vector3f();
-        List<Vector3f> vertices = temporalMesh.getVertices();
-        for (Integer index : indexes) {
-            result.addLocal(vertices.get(index));
-        }
-        return result.divideLocal(indexes.size());
-    }
-
-    /**
-     * @return current indexes of the face (if it is already triangulated then more than one index group will be in the result list)
-     */
-    public List<List<Integer>> getCurrentIndexes() {
-        if (triangulatedFaces == null) {
-            return Arrays.asList(indexes.getAll());
-        }
-        List<List<Integer>> result = new ArrayList<List<Integer>>(triangulatedFaces.size());
-        for (IndexesLoop loop : triangulatedFaces) {
-            result.add(loop.getAll());
-        }
-        return result;
-    }
-
-    /**
-     * The method detaches the triangle from the face. This method keeps the indexes loop normalized - every index
-     * has only two neighbours. So if detaching the triangle causes a vertex to have more than two neighbours - it is
-     * also detached and returned as a result.
-     * The result is an empty list if no such situation happens.
-     * @param triangleIndexes
-     *            the indexes of a triangle to be detached
-     * @return a list of faces that need to be detached as well in order to keep them normalized
-     * @throws BlenderFileException
-     *             an exception is thrown when vertices of a face create more than one loop; this is found during path finding
-     */
-    private List<Face> detachTriangle(Integer[] triangleIndexes) throws BlenderFileException {
-        LOGGER.fine("Detaching triangle.");
-        if (triangleIndexes.length != 3) {
-            throw new IllegalArgumentException("Cannot detach triangle with that does not have 3 indexes!");
-        }
-        MeshHelper meshHelper = temporalMesh.getBlenderContext().getHelper(MeshHelper.class);
-        List<Face> detachedFaces = new ArrayList<Face>();
-        List<Integer> path = new ArrayList<Integer>(indexes.size());
-
-        boolean[] edgeRemoved = new boolean[] { indexes.removeEdge(triangleIndexes[0], triangleIndexes[1]), indexes.removeEdge(triangleIndexes[0], triangleIndexes[2]), indexes.removeEdge(triangleIndexes[1], triangleIndexes[2]) };
-        Integer[][] indexesPairs = new Integer[][] { new Integer[] { triangleIndexes[0], triangleIndexes[1] }, new Integer[] { triangleIndexes[0], triangleIndexes[2] }, new Integer[] { triangleIndexes[1], triangleIndexes[2] } };
-
-        for (int i = 0; i < 3; ++i) {
-            if (!edgeRemoved[i]) {
-                indexes.findPath(indexesPairs[i][0], indexesPairs[i][1], path);
-                if (path.size() == 0) {
-                    indexes.findPath(indexesPairs[i][1], indexesPairs[i][0], path);
-                }
-                if (path.size() == 0) {
-                    throw new IllegalStateException("Triangulation failed. Cannot find path between two indexes. Please apply triangulation in Blender as a workaround.");
-                }
-                if (detachedFaces.size() == 0 && path.size() < indexes.size()) {
-                    Integer[] indexesSublist = path.toArray(new Integer[path.size()]);
-                    detachedFaces.add(new Face(indexesSublist, smooth, materialNumber, meshHelper.selectUVSubset(this, indexesSublist), meshHelper.selectVertexColorSubset(this, indexesSublist), temporalMesh));
-                    for (int j = 0; j < path.size() - 1; ++j) {
-                        indexes.removeEdge(path.get(j), path.get(j + 1));
-                    }
-                    indexes.removeEdge(path.get(path.size() - 1), path.get(0));
-                } else {
-                    indexes.addEdge(path.get(path.size() - 1), path.get(0));
-                }
-            }
-        }
-
-        return detachedFaces;
-    }
-
-    /**
-     * Sets the temporal mesh for the face. The given mesh cannot be null.
-     * @param temporalMesh
-     *            the temporal mesh of the face
-     * @throws IllegalArgumentException
-     *             thrown if given temporal mesh is null
-     */
-    public void setTemporalMesh(TemporalMesh temporalMesh) {
-        if (temporalMesh == null) {
-            throw new IllegalArgumentException("No temporal mesh for the face given!");
-        }
-        this.temporalMesh = temporalMesh;
-    }
-
-    /**
-     * Flips the order of the indexes.
-     */
-    public void flipIndexes() {
-        indexes.reverse();
-        if (faceUVCoords != null) {
-            for (Entry<String, List<Vector2f>> entry : faceUVCoords.entrySet()) {
-                Collections.reverse(entry.getValue());
-            }
-        }
-    }
-
-    /**
-     * Flips UV coordinates.
-     * @param u
-     *            indicates if U coords should be flipped
-     * @param v
-     *            indicates if V coords should be flipped
-     */
-    public void flipUV(boolean u, boolean v) {
-        if (faceUVCoords != null) {
-            for (Entry<String, List<Vector2f>> entry : faceUVCoords.entrySet()) {
-                for (Vector2f uv : entry.getValue()) {
-                    uv.set(u ? 1 - uv.x : uv.x, v ? 1 - uv.y : uv.y);
-                }
-            }
-        }
-    }
-
-    /**
-     * @return the UV sets of the face
-     */
-    public Map<String, List<Vector2f>> getUvSets() {
-        return faceUVCoords;
-    }
-
-    /**
-     * @return current vertex count of the face
-     */
-    public int vertexCount() {
-        return indexes.size();
-    }
-
-    /**
-     * The method triangulates the face.
-     */
-    public TriangulationWarning triangulate() {
-        LOGGER.fine("Triangulating face.");
-        assert indexes.size() >= 3 : "Invalid indexes amount for face. 3 is the required minimum!";
-        triangulatedFaces = new ArrayList<IndexesLoop>(indexes.size() - 2);
-        Integer[] indexes = new Integer[3];
-        TriangulationWarning warning = TriangulationWarning.NONE;
-        
-        try {
-            List<Face> facesToTriangulate = new ArrayList<Face>(Arrays.asList(this.clone()));
-            while (facesToTriangulate.size() > 0 && warning == TriangulationWarning.NONE) {
-                Face face = facesToTriangulate.remove(0);
-                // two special cases will improve the computations speed
-                if(face.getIndexes().size() == 3) {
-                	triangulatedFaces.add(face.getIndexes().clone());
-                } else {
-                	int previousIndex1 = -1, previousIndex2 = -1, previousIndex3 = -1;
-                    while (face.vertexCount() > 0) {
-                        indexes[0] = face.getIndex(0);
-                        indexes[1] = face.findClosestVertex(indexes[0], -1);
-                        indexes[2] = face.findClosestVertex(indexes[0], indexes[1]);
-
-                        LOGGER.finer("Veryfying improper triangulation of the temporal mesh.");
-                        if (indexes[0] < 0 || indexes[1] < 0 || indexes[2] < 0) {
-                            warning = TriangulationWarning.CLOSEST_VERTS;
-                            break;
-                        }
-                        if (previousIndex1 == indexes[0] && previousIndex2 == indexes[1] && previousIndex3 == indexes[2]) {
-                            warning = TriangulationWarning.INFINITE_LOOP;
-                            break;
-                        }
-                        previousIndex1 = indexes[0];
-                        previousIndex2 = indexes[1];
-                        previousIndex3 = indexes[2];
-
-                        Arrays.sort(indexes, this);
-                        facesToTriangulate.addAll(face.detachTriangle(indexes));
-                        triangulatedFaces.add(new IndexesLoop(indexes));
-                    }
-                }
-            }
-        } catch (BlenderFileException e) {
-            LOGGER.log(Level.WARNING, "Errors occurred during face triangulation: {0}. The face will be triangulated with the most direct algorithm, but the results might not be identical to blender.", e.getLocalizedMessage());
-            warning = TriangulationWarning.UNKNOWN;
-        }
-        if(warning != TriangulationWarning.NONE) {
-            LOGGER.finest("Triangulation the face using the most direct algorithm.");
-            indexes[0] = this.getIndex(0);
-            for (int i = 1; i < this.vertexCount() - 1; ++i) {
-                indexes[1] = this.getIndex(i);
-                indexes[2] = this.getIndex(i + 1);
-                triangulatedFaces.add(new IndexesLoop(indexes));
-            }
-        }
-        return warning;
-    }
-    
-    /**
-     * A warning that indicates a problem with face triangulation. The warnings are collected and displayed once for each type for a mesh to
-     * avoid multiple warning loggings during triangulation. The amount of iterations can be really huge and logging every single failure would
-     * really slow down the importing process and make logs unreadable.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum TriangulationWarning {
-        NONE(null), 
-        CLOSEST_VERTS("Unable to find two closest vertices while triangulating face."), 
-        INFINITE_LOOP("Infinite loop detected during triangulation."), 
-        UNKNOWN("There was an unknown problem with face triangulation. Please see log for details.");
-
-        private String description;
-
-        private TriangulationWarning(String description) {
-            this.description = description;
-        }
-
-        @Override
-        public String toString() {
-            return description;
-        }
-    }
-    
-    /**
-     * @return <b>true</b> if the face is smooth and <b>false</b> otherwise
-     */
-    public boolean isSmooth() {
-        return smooth;
-    }
-
-    /**
-     * @return the material index of the face
-     */
-    public int getMaterialNumber() {
-        return materialNumber;
-    }
-
-    /**
-     * @return the vertices colord of the face
-     */
-    public List<byte[]> getVertexColors() {
-        return vertexColors;
-    }
-
-    @Override
-    public String toString() {
-        return "Face " + indexes;
-    }
-
-	/**
-	 * The method finds the closest vertex to the one specified by <b>index</b>.
-	 * If the vertexToIgnore is positive than it will be ignored in the result.
-	 * The closest vertex must be able to create an edge that is fully contained
-	 * within the face and does not cross any other edges. Also if the
-	 * vertexToIgnore is not negative then the condition that the edge between
-	 * the found index and the one to ignore is inside the face must also be
-	 * met.
-	 * 
-	 * @param index
-	 *            the index of the vertex that needs to have found the nearest
-	 *            neighbour
-	 * @param indexToIgnore
-	 *            the index to ignore in the result (pass -1 if none is to be
-	 *            ignored)
-	 * @return the index of the closest vertex to the given one
-	 */
-    private int findClosestVertex(int index, int indexToIgnore) {
-        int result = -1;
-        List<Vector3f> vertices = temporalMesh.getVertices();
-        Vector3f v1 = vertices.get(index);
-        float distance = Float.MAX_VALUE;
-        for (int i : indexes) {
-            if (i != index && i != indexToIgnore) {
-                Vector3f v2 = vertices.get(i);
-                float d = v2.distance(v1);
-                if (d < distance && this.contains(new Edge(index, i, 0, true, temporalMesh)) && (indexToIgnore < 0 || this.contains(new Edge(indexToIgnore, i, 0, true, temporalMesh)))) {
-                    result = i;
-                    distance = d;
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * The method verifies if the edge is contained within the face.
-     * It means it cannot cross any other edge and it must be inside the face and not outside of it.
-     * @param edge
-     *            the edge to be checked
-     * @return <b>true</b> if the given edge is contained within the face and <b>false</b> otherwise
-     */
-    private boolean contains(Edge edge) {
-        int index1 = edge.getFirstIndex();
-        int index2 = edge.getSecondIndex();
-        // check if the line between the vertices is not a border edge of the face
-        if (!indexes.areNeighbours(index1, index2)) {
-            for (int i = 0; i < indexes.size(); ++i) {
-                int i1 = this.getIndex(i - 1);
-                int i2 = this.getIndex(i);
-                // check if the edges have no common verts (because if they do, they cannot cross)
-                if (i1 != index1 && i1 != index2 && i2 != index1 && i2 != index2) {
-                    if (edge.cross(new Edge(i1, i2, 0, false, temporalMesh))) {
-                        return false;
-                    }
-                }
-            }
-
-            // computing the edge's middle point
-            Vector3f edgeMiddlePoint = edge.computeCentroid();
-            // computing the edge that is perpendicular to the given edge and has a length of 1 (length actually does not matter)
-            Vector3f edgeVector = edge.getSecondVertex().subtract(edge.getFirstVertex());
-            Vector3f edgeNormal = temporalMesh.getNormals().get(index1).cross(edgeVector).normalizeLocal();
-            Edge e = new Edge(edgeMiddlePoint, edgeNormal.add(edgeMiddlePoint));
-            // compute the vectors from the middle point to the crossing between the extended edge 'e' and other edges of the face
-            List<Vector3f> crossingVectors = new ArrayList<Vector3f>();
-            for (int i = 0; i < indexes.size(); ++i) {
-                int i1 = this.getIndex(i);
-                int i2 = this.getIndex(i + 1);
-            	Vector3f crossPoint = e.getCrossPoint(new Edge(i1, i2, 0, false, temporalMesh), true, false);
-                if(crossPoint != null) {
-                	crossingVectors.add(crossPoint.subtractLocal(edgeMiddlePoint));
-                }
-            }
-            if(crossingVectors.size() == 0) {
-            	return false;// edges do not cross
-            }
-            
-            // use only distinct vertices (doubles may appear if the crossing point is a vertex)
-            List<Vector3f> distinctCrossingVectors = new ArrayList<Vector3f>();
-            for(Vector3f cv : crossingVectors) {
-        		double minDistance = Double.MAX_VALUE;
-        		for(Vector3f dcv : distinctCrossingVectors) {
-        			minDistance = Math.min(minDistance, dcv.distance(cv));
-        		}
-        		if(minDistance > FastMath.FLT_EPSILON) {
-        			distinctCrossingVectors.add(cv);
-        		}
-            }
-            
-            if(distinctCrossingVectors.size() == 0) {
-            	throw new IllegalStateException("There MUST be at least 2 crossing vertices!");
-            }
-            // checking if all crossing vectors point to the same direction (if yes then the edge is outside the face)
-            float direction = Math.signum(distinctCrossingVectors.get(0).dot(edgeNormal));// if at least one vector has different direction that this - it means that the edge is inside the face
-            for(int i=1;i<distinctCrossingVectors.size();++i) {
-            	if(direction != Math.signum(distinctCrossingVectors.get(i).dot(edgeNormal))) {
-            		return true;
-            	}
-            }
-            return false;
-        }
-        return true;
-    }
-    
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + indexes.hashCode();
-        result = prime * result + temporalMesh.hashCode();
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof Face)) {
-            return false;
-        }
-        Face other = (Face) obj;
-        if (!indexes.equals(other.indexes)) {
-            return false;
-        }
-        return temporalMesh.equals(other.temporalMesh);
-    }
-
-    /**
-     * Loads all faces of a given mesh.
-     * @param meshStructure
-     *            the mesh structure we read the faces from
-     * @param userUVGroups
-     *            UV groups defined by the user
-     * @param verticesColors
-     *            the vertices colors of the mesh
-     * @param temporalMesh
-     *            the temporal mesh the faces will belong to
-     * @param blenderContext
-     *            the blender context
-     * @return list of faces read from the given mesh structure
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with file reading occur
-     */
-    public static List<Face> loadAll(Structure meshStructure, Map<String, List<Vector2f>> userUVGroups, List<byte[]> verticesColors, TemporalMesh temporalMesh, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading all faces from mesh: {0}", meshStructure.getName());
-        List<Face> result = new ArrayList<Face>();
-        MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-        if (meshHelper.isBMeshCompatible(meshStructure)) {
-            LOGGER.fine("Reading BMesh.");
-            Pointer pMLoop = (Pointer) meshStructure.getFieldValue("mloop");
-            Pointer pMPoly = (Pointer) meshStructure.getFieldValue("mpoly");
-
-            if (pMPoly.isNotNull() && pMLoop.isNotNull()) {
-                List<Structure> polys = pMPoly.fetchData();
-                List<Structure> loops = pMLoop.fetchData();
-                for (Structure poly : polys) {
-                    int materialNumber = ((Number) poly.getFieldValue("mat_nr")).intValue();
-                    int loopStart = ((Number) poly.getFieldValue("loopstart")).intValue();
-                    int totLoop = ((Number) poly.getFieldValue("totloop")).intValue();
-                    boolean smooth = (((Number) poly.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
-                    Integer[] vertexIndexes = new Integer[totLoop];
-
-                    for (int i = loopStart; i < loopStart + totLoop; ++i) {
-                        vertexIndexes[i - loopStart] = ((Number) loops.get(i).getFieldValue("v")).intValue();
-                    }
-
-                    // uvs always must be added wheater we have texture or not
-                    Map<String, List<Vector2f>> uvCoords = new HashMap<String, List<Vector2f>>();
-                    for (Entry<String, List<Vector2f>> entry : userUVGroups.entrySet()) {
-                        List<Vector2f> uvs = entry.getValue().subList(loopStart, loopStart + totLoop);
-                        uvCoords.put(entry.getKey(), new ArrayList<Vector2f>(uvs));
-                    }
-
-                    List<byte[]> vertexColors = null;
-                    if (verticesColors != null && verticesColors.size() > 0) {
-                        vertexColors = new ArrayList<byte[]>(totLoop);
-                        for (int i = loopStart; i < loopStart + totLoop; ++i) {
-                            vertexColors.add(verticesColors.get(i));
-                        }
-                    }
-
-                    result.add(new Face(vertexIndexes, smooth, materialNumber, uvCoords, vertexColors, temporalMesh));
-                }
-            }
-        } else {
-            LOGGER.fine("Reading traditional faces.");
-            Pointer pMFace = (Pointer) meshStructure.getFieldValue("mface");
-            List<Structure> mFaces = pMFace.isNotNull() ? pMFace.fetchData() : null;
-            if (mFaces != null && mFaces.size() > 0) {
-                // indicates if the material with the specified number should have a texture attached
-                for (int i = 0; i < mFaces.size(); ++i) {
-                    Structure mFace = mFaces.get(i);
-                    int materialNumber = ((Number) mFace.getFieldValue("mat_nr")).intValue();
-                    boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
-
-                    int v1 = ((Number) mFace.getFieldValue("v1")).intValue();
-                    int v2 = ((Number) mFace.getFieldValue("v2")).intValue();
-                    int v3 = ((Number) mFace.getFieldValue("v3")).intValue();
-                    int v4 = ((Number) mFace.getFieldValue("v4")).intValue();
-
-                    int vertCount = v4 == 0 ? 3 : 4;
-
-                    // uvs always must be added wheater we have texture or not
-                    Map<String, List<Vector2f>> faceUVCoords = new HashMap<String, List<Vector2f>>();
-                    for (Entry<String, List<Vector2f>> entry : userUVGroups.entrySet()) {
-                        List<Vector2f> uvCoordsForASingleFace = new ArrayList<Vector2f>(vertCount);
-                        for (int j = 0; j < vertCount; ++j) {
-                            uvCoordsForASingleFace.add(entry.getValue().get(i * 4 + j));
-                        }
-                        faceUVCoords.put(entry.getKey(), uvCoordsForASingleFace);
-                    }
-
-                    List<byte[]> vertexColors = null;
-                    if (verticesColors != null && verticesColors.size() > 0) {
-                        vertexColors = new ArrayList<byte[]>(vertCount);
-
-                        vertexColors.add(verticesColors.get(v1));
-                        vertexColors.add(verticesColors.get(v2));
-                        vertexColors.add(verticesColors.get(v3));
-                        if (vertCount == 4) {
-                            vertexColors.add(verticesColors.get(v4));
-                        }
-                    }
-
-                    result.add(new Face(vertCount == 4 ? new Integer[] { v1, v2, v3, v4 } : new Integer[] { v1, v2, v3 }, smooth, materialNumber, faceUVCoords, vertexColors, temporalMesh));
-                }
-            }
-        }
-        LOGGER.log(Level.FINE, "Loaded {0} faces.", result.size());
-        return result;
-    }
-
-    @Override
-    public int compare(Integer index1, Integer index2) {
-        return indexes.indexOf(index1) - indexes.indexOf(index2);
-    }
-}

+ 0 - 305
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/IndexesLoop.java

@@ -1,305 +0,0 @@
-package com.jme3.scene.plugins.blender.meshes;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-
-/**
- * This class represents the Face's indexes loop. It is a simplified implementation of directed graph.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class IndexesLoop implements Comparator<Integer>, Iterable<Integer> {
-    public static final IndexPredicate  INDEX_PREDICATE_USE_ALL = new IndexPredicate() {
-                                                                    @Override
-                                                                    public boolean execute(Integer index) {
-                                                                        return true;
-                                                                    }
-                                                                };
-
-    /** The indexes. */
-    private List<Integer>               nodes;
-    /** The edges of the indexes graph. The key is the 'from' index and 'value' is - 'to' index. */
-    private Map<Integer, List<Integer>> edges                   = new HashMap<Integer, List<Integer>>();
-
-    /**
-     * The constructor uses the given nodes in their give order. Each neighbour indexes will form an edge.
-     * @param nodes
-     *            the nodes for the loop
-     */
-    public IndexesLoop(Integer[] nodes) {
-        this.nodes = new ArrayList<Integer>(Arrays.asList(nodes));
-        this.prepareEdges(this.nodes);
-    }
-
-    @Override
-    public IndexesLoop clone() {
-        return new IndexesLoop(nodes.toArray(new Integer[nodes.size()]));
-    }
-
-    /**
-     * The method prepares edges for the given indexes.
-     * @param nodes
-     *            the indexes
-     */
-    private void prepareEdges(List<Integer> nodes) {
-        for (int i = 0; i < nodes.size() - 1; ++i) {
-            if (edges.containsKey(nodes.get(i))) {
-                edges.get(nodes.get(i)).add(nodes.get(i + 1));
-            } else {
-                edges.put(nodes.get(i), new ArrayList<Integer>(Arrays.asList(nodes.get(i + 1))));
-            }
-        }
-        edges.put(nodes.get(nodes.size() - 1), new ArrayList<Integer>(Arrays.asList(nodes.get(0))));
-    }
-
-    /**
-     * @return the count of indexes
-     */
-    public int size() {
-        return nodes.size();
-    }
-
-    /**
-     * Adds edge to the loop.
-     * @param from
-     *            the start index
-     * @param to
-     *            the end index
-     */
-    public void addEdge(Integer from, Integer to) {
-        if (nodes.contains(from) && nodes.contains(to)) {
-            if (edges.containsKey(from) && !edges.get(from).contains(to)) {
-                edges.get(from).add(to);
-            }
-        }
-    }
-
-    /**
-     * Removes edge from the face. The edge is removed if it already exists in the face.
-     * @param node1
-     *            the first index of the edge to be removed
-     * @param node2
-     *            the second index of the edge to be removed
-     * @return <b>true</b> if the edge was removed and <b>false</b> otherwise
-     */
-    public boolean removeEdge(Integer node1, Integer node2) {
-        boolean edgeRemoved = false;
-        if (nodes.contains(node1) && nodes.contains(node2)) {
-            if (edges.containsKey(node1)) {
-                edgeRemoved |= edges.get(node1).remove(node2);
-            }
-            if (edges.containsKey(node2)) {
-                edgeRemoved |= edges.get(node2).remove(node1);
-            }
-            if (edgeRemoved) {
-                if (this.getNeighbourCount(node1) == 0) {
-                    this.removeIndexes(node1);
-                }
-                if (this.getNeighbourCount(node2) == 0) {
-                    this.removeIndexes(node2);
-                }
-            }
-        }
-        return edgeRemoved;
-    }
-
-    /**
-     * Tells if the given indexes are neighbours.
-     * @param index1
-     *            the first index
-     * @param index2
-     *            the second index
-     * @return <b>true</b> if the given indexes are neighbours and <b>false</b> otherwise
-     */
-    public boolean areNeighbours(Integer index1, Integer index2) {
-        if (index1.equals(index2) || !edges.containsKey(index1) || !edges.containsKey(index2)) {
-            return false;
-        }
-        return edges.get(index1).contains(index2) || edges.get(index2).contains(index1);
-    }
-
-    /**
-     * Returns the value of the index located after the given one. Pointint the last index will return the first one.
-     * @param index
-     *            the index value
-     * @return the value of 'next' index
-     */
-    public Integer getNextIndex(Integer index) {
-        int i = nodes.indexOf(index);
-        return i == nodes.size() - 1 ? nodes.get(0) : nodes.get(i + 1);
-    }
-
-    /**
-     * Returns the value of the index located before the given one. Pointint the first index will return the last one.
-     * @param index
-     *            the index value
-     * @return the value of 'previous' index
-     */
-    public Integer getPreviousIndex(Integer index) {
-        int i = nodes.indexOf(index);
-        return i == 0 ? nodes.get(nodes.size() - 1) : nodes.get(i - 1);
-    }
-
-    /**
-     * The method shifts all indexes by a given value.
-     * @param shift
-     *            the value to shift all indexes
-     * @param predicate
-     *            the predicate that verifies which indexes should be shifted; if null then all will be shifted
-     */
-    public void shiftIndexes(int shift, IndexPredicate predicate) {
-        if (predicate == null) {
-            predicate = INDEX_PREDICATE_USE_ALL;
-        }
-        List<Integer> nodes = new ArrayList<Integer>(this.nodes.size());
-        for (Integer node : this.nodes) {
-            nodes.add(node + (predicate.execute(node) ? shift : 0));
-        }
-
-        Map<Integer, List<Integer>> edges = new HashMap<Integer, List<Integer>>();
-        for (Entry<Integer, List<Integer>> entry : this.edges.entrySet()) {
-            List<Integer> neighbours = new ArrayList<Integer>(entry.getValue().size());
-            for (Integer neighbour : entry.getValue()) {
-                neighbours.add(neighbour + (predicate.execute(neighbour) ? shift : 0));
-            }
-            edges.put(entry.getKey() + shift, neighbours);
-        }
-
-        this.nodes = nodes;
-        this.edges = edges;
-    }
-
-    /**
-     * Reverses the order of the indexes.
-     */
-    public void reverse() {
-        Collections.reverse(nodes);
-        edges.clear();
-        this.prepareEdges(nodes);
-    }
-
-    /**
-     * Returns the neighbour count of the given index.
-     * @param index
-     *            the index whose neighbour count will be checked
-     * @return the count of neighbours of the given index
-     */
-    private int getNeighbourCount(Integer index) {
-        int result = 0;
-        if (edges.containsKey(index)) {
-            result = edges.get(index).size();
-            for (List<Integer> neighbours : edges.values()) {
-                if (neighbours.contains(index)) {
-                    ++result;
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns the position of the given index in the loop.
-     * @param index
-     *            the index of the face
-     * @return the indexe's position in the loop
-     */
-    public int indexOf(Integer index) {
-        return nodes.indexOf(index);
-    }
-
-    /**
-     * Returns the index at the given position.
-     * @param indexPosition
-     *            the position of the index
-     * @return the index at a given position
-     */
-    public Integer get(int indexPosition) {
-        return nodes.get(indexPosition);
-    }
-
-    /**
-     * @return all indexes of the face
-     */
-    public List<Integer> getAll() {
-        return new ArrayList<Integer>(nodes);
-    }
-
-    /**
-     * The method removes all given indexes.
-     * @param indexes
-     *            the indexes to be removed
-     */
-    public void removeIndexes(Integer... indexes) {
-        for (Integer index : indexes) {
-            nodes.remove(index);
-            edges.remove(index);
-            for (List<Integer> neighbours : edges.values()) {
-                neighbours.remove(index);
-            }
-        }
-    }
-
-    /**
-     * The method finds the path between the given indexes.
-     * @param start
-     *            the start index
-     * @param end
-     *            the end index
-     * @param result
-     *            a list containing indexes on the path from start to end (inclusive)
-     * @throws IllegalStateException
-     *             an exception is thrown when the loop is not normalized (at least one
-     *             index has more than 2 neighbours)
-     * @throws BlenderFileException
-     *             an exception is thrown if the vertices of a face create more than one loop; this is thrown
-     *             to prevent lack of memory errors during triangulation
-     */
-    public void findPath(Integer start, Integer end, List<Integer> result) throws BlenderFileException {
-        result.clear();
-        Integer node = start;
-        while (!node.equals(end)) {
-            if (result.contains(node)) {
-                throw new BlenderFileException("Indexes of face have infinite loops!");
-            }
-            result.add(node);
-            List<Integer> nextSteps = edges.get(node);
-            if (nextSteps == null || nextSteps.size() == 0) {
-                result.clear();// no directed path from start to end
-                return;
-            } else if (nextSteps.size() == 1) {
-                node = nextSteps.get(0);
-            } else {
-                throw new BlenderFileException("Triangulation failed. Face has ambiguous indexes loop. Please triangulate your model in Blender as a workaround.");
-            }
-        }
-        result.add(end);
-    }
-
-    @Override
-    public String toString() {
-        return "IndexesLoop " + nodes.toString();
-    }
-
-    @Override
-    public int compare(Integer i1, Integer i2) {
-        return nodes.indexOf(i1) - nodes.indexOf(i2);
-    }
-
-    @Override
-    public Iterator<Integer> iterator() {
-        return nodes.iterator();
-    }
-
-    public static interface IndexPredicate {
-        boolean execute(Integer index);
-    }
-}

+ 0 - 364
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/MeshBuffers.java

@@ -1,364 +0,0 @@
-package com.jme3.scene.plugins.blender.meshes;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NavigableMap;
-import java.util.TreeMap;
-
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-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.util.BufferUtils;
-
-/**
- * A class that aggregates the mesh data to prepare proper buffers. The buffers refer only to ONE material.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class MeshBuffers {
-    private static final int              MAXIMUM_WEIGHTS_PER_VERTEX = 4;
-
-    /** The material index. */
-    private final int                     materialIndex;
-    /** The vertices. */
-    private List<Vector3f>                verts                      = new ArrayList<Vector3f>();
-    /** The normals. */
-    private List<Vector3f>                normals                    = new ArrayList<Vector3f>();
-    /** The UV coordinate sets. */
-    private Map<String, List<Vector2f>>   uvCoords                   = new HashMap<String, List<Vector2f>>();
-    /** The vertex colors. */
-    private List<byte[]>                  vertColors                 = new ArrayList<byte[]>();
-    /** The indexes. */
-    private List<Integer>                 indexes                    = new ArrayList<Integer>();
-    /** The maximum weights count assigned to a single vertex. Used during weights normalization. */
-    private int                           maximumWeightsPerVertex;
-    /** A list of mapping between weights and indexes. Each entry for the proper vertex. */
-    private List<TreeMap<Float, Integer>> boneWeightAndIndexes       = new ArrayList<TreeMap<Float, Integer>>();
-
-    /**
-     * Constructor stores only the material index value.
-     * @param materialIndex
-     *            the material index
-     */
-    public MeshBuffers(int materialIndex) {
-        this.materialIndex = materialIndex;
-    }
-
-    /**
-     * @return the material index
-     */
-    public int getMaterialIndex() {
-        return materialIndex;
-    }
-
-    /**
-     * @return indexes buffer
-     */
-    public Buffer getIndexBuffer() {
-        if (indexes.size() <= Short.MAX_VALUE) {
-            short[] indices = new short[indexes.size()];
-            for (int i = 0; i < indexes.size(); ++i) {
-                indices[i] = indexes.get(i).shortValue();
-            }
-            return BufferUtils.createShortBuffer(indices);
-        } else {
-            int[] indices = new int[indexes.size()];
-            for (int i = 0; i < indexes.size(); ++i) {
-                indices[i] = indexes.get(i).intValue();
-            }
-            return BufferUtils.createIntBuffer(indices);
-        }
-    }
-
-    /**
-     * @return positions buffer
-     */
-    public VertexBuffer getPositionsBuffer() {
-        VertexBuffer positionBuffer = new VertexBuffer(Type.Position);
-        Vector3f[] data = verts.toArray(new Vector3f[verts.size()]);
-        positionBuffer.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(data));
-        return positionBuffer;
-    }
-
-    /**
-     * @return normals buffer
-     */
-    public VertexBuffer getNormalsBuffer() {
-        VertexBuffer positionBuffer = new VertexBuffer(Type.Normal);
-        Vector3f[] data = normals.toArray(new Vector3f[normals.size()]);
-        positionBuffer.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(data));
-        return positionBuffer;
-    }
-
-    /**
-     * @return bone buffers
-     */
-    public BoneBuffersData getBoneBuffers() {
-        BoneBuffersData result = null;
-        if (maximumWeightsPerVertex > 0) {
-            this.normalizeBoneBuffers(MAXIMUM_WEIGHTS_PER_VERTEX);
-            maximumWeightsPerVertex = MAXIMUM_WEIGHTS_PER_VERTEX;
-            
-            FloatBuffer weightsFloatData = BufferUtils.createFloatBuffer(boneWeightAndIndexes.size() * MAXIMUM_WEIGHTS_PER_VERTEX);
-            ByteBuffer indicesData = BufferUtils.createByteBuffer(boneWeightAndIndexes.size() * MAXIMUM_WEIGHTS_PER_VERTEX);
-            int index = 0;
-            for (Map<Float, Integer> boneBuffersData : boneWeightAndIndexes) {
-                if (boneBuffersData.size() > 0) {
-                    int count = 0;
-                    for (Entry<Float, Integer> entry : boneBuffersData.entrySet()) {
-                        weightsFloatData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX + count, entry.getKey());
-                        indicesData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX + count, entry.getValue().byteValue());
-                        ++count;
-                    }
-                } else {
-                    // if no bone is assigned to this vertex then attach it to the 0-indexed root bone
-                    weightsFloatData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX, 1.0f);
-                    indicesData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX, (byte) 0);
-                }
-                ++index;
-            }
-            VertexBuffer verticesWeights = new VertexBuffer(Type.BoneWeight);
-            verticesWeights.setupData(Usage.CpuOnly, maximumWeightsPerVertex, Format.Float, weightsFloatData);
-
-            VertexBuffer verticesWeightsIndices = new VertexBuffer(Type.BoneIndex);
-            verticesWeightsIndices.setupData(Usage.CpuOnly, maximumWeightsPerVertex, Format.UnsignedByte, indicesData);
-
-            result = new BoneBuffersData(maximumWeightsPerVertex, verticesWeights, verticesWeightsIndices);
-        }
-
-        return result;
-    }
-
-    /**
-     * @return UV coordinates sets
-     */
-    public Map<String, List<Vector2f>> getUvCoords() {
-        return uvCoords;
-    }
-
-    /**
-     * @return <b>true</b> if vertex colors are used and <b>false</b> otherwise
-     */
-    public boolean areVertexColorsUsed() {
-        return vertColors.size() > 0;
-    }
-
-    /**
-     * @return vertex colors buffer
-     */
-    public ByteBuffer getVertexColorsBuffer() {
-        ByteBuffer result = null;
-        if (vertColors.size() > 0) {
-            result = BufferUtils.createByteBuffer(4 * vertColors.size());
-            for (byte[] v : vertColors) {
-                if (v != null) {
-                    result.put(v[0]).put(v[1]).put(v[2]).put(v[3]);
-                } else {
-                    result.put((byte) 0).put((byte) 0).put((byte) 0).put((byte) 0);
-                }
-            }
-            result.flip();
-        }
-        return result;
-    }
-
-    /**
-     * @return <b>true</b> if indexes can be shorts' and <b>false</b> if they need to be ints'
-     */
-    public boolean isShortIndexBuffer() {
-        return indexes.size() <= Short.MAX_VALUE;
-    }
-
-    /**
-     * Appends a vertex and normal to the buffers.
-     * @param vert
-     *            vertex
-     * @param normal
-     *            normal vector
-     */
-    public void append(Vector3f vert, Vector3f normal) {
-        int index = this.indexOf(vert, normal, null);
-        if (index >= 0) {
-            indexes.add(index);
-        } else {
-            indexes.add(verts.size());
-            verts.add(vert);
-            normals.add(normal);
-        }
-    }
-
-    /**
-     * Appends the face data to the buffers.
-     * @param smooth
-     *            tells if the face is smooth or flat
-     * @param verts
-     *            the vertices
-     * @param normals
-     *            the normals
-     * @param uvCoords
-     *            the UV coordinates
-     * @param vertColors
-     *            the vertex colors
-     * @param vertexGroups
-     *            the vertex groups
-     */
-    public void append(boolean smooth, Vector3f[] verts, Vector3f[] normals, Map<String, List<Vector2f>> uvCoords, byte[][] vertColors, List<Map<Float, Integer>> vertexGroups) {
-        if (verts.length != normals.length) {
-            throw new IllegalArgumentException("The amount of verts and normals MUST be equal!");
-        }
-        if (vertColors != null && vertColors.length != verts.length) {
-            throw new IllegalArgumentException("The amount of vertex colors and vertices MUST be equal!");
-        }
-        if (vertexGroups.size() != 0 && vertexGroups.size() != verts.length) {
-            throw new IllegalArgumentException("The amount of (if given) vertex groups and vertices MUST be equal!");
-        }
-
-        if (!smooth) {
-            // make the normals perpendicular to the face
-            normals[0] = normals[1] = normals[2] = FastMath.computeNormal(verts[0], verts[1], verts[2]);
-        }
-
-        for (int i = 0; i < verts.length; ++i) {
-            int index = -1;
-            Map<String, Vector2f> uvCoordsForVertex = this.getUVsForVertex(i, uvCoords);
-            if (smooth && (index = this.indexOf(verts[i], normals[i], uvCoordsForVertex)) >= 0) {
-                indexes.add(index);
-            } else {
-                indexes.add(this.verts.size());
-                this.verts.add(verts[i]);
-                this.normals.add(normals[i]);
-                this.vertColors.add(vertColors[i]);
-
-                if (uvCoords != null && uvCoords.size() > 0) {
-                    for (Entry<String, List<Vector2f>> entry : uvCoords.entrySet()) {
-                        if (this.uvCoords.containsKey(entry.getKey())) {
-                            this.uvCoords.get(entry.getKey()).add(entry.getValue().get(i));
-                        } else {
-                            List<Vector2f> uvs = new ArrayList<Vector2f>();
-                            uvs.add(entry.getValue().get(i));
-                            this.uvCoords.put(entry.getKey(), uvs);
-                        }
-                    }
-                }
-
-                if (vertexGroups.size() > 0) {
-                    Map<Float, Integer> group = vertexGroups.get(i);
-                    maximumWeightsPerVertex = Math.max(maximumWeightsPerVertex, group.size());
-                    boneWeightAndIndexes.add(new TreeMap<Float, Integer>(group));
-                }
-            }
-        }
-    }
-
-    /**
-     * Returns UV coordinates assigned for the vertex with the proper index.
-     * @param vertexIndex
-     *            the index of the vertex
-     * @param uvs
-     *            all UV coordinates we search in
-     * @return a set of UV coordinates assigned to the given vertex
-     */
-    private Map<String, Vector2f> getUVsForVertex(int vertexIndex, Map<String, List<Vector2f>> uvs) {
-        if (uvs == null || uvs.size() == 0) {
-            return null;
-        }
-        Map<String, Vector2f> result = new HashMap<String, Vector2f>(uvs.size());
-        for (Entry<String, List<Vector2f>> entry : uvs.entrySet()) {
-            result.put(entry.getKey(), entry.getValue().get(vertexIndex));
-        }
-        return result;
-    }
-
-    /**
-     * The method returns an index of a vertex described by the given data.
-     * The method tries to find a vertex that mathes the given data. If it does it means
-     * that such vertex is already used.
-     * @param vert
-     *            the vertex position coordinates
-     * @param normal
-     *            the vertex's normal vector
-     * @param uvCoords
-     *            the UV coords of the vertex
-     * @return index of the found vertex of -1
-     */
-    private int indexOf(Vector3f vert, Vector3f normal, Map<String, Vector2f> uvCoords) {
-        for (int i = 0; i < verts.size(); ++i) {
-            if (verts.get(i).equals(vert) && normals.get(i).equals(normal)) {
-                if (uvCoords != null && uvCoords.size() > 0) {
-                    for (Entry<String, Vector2f> entry : uvCoords.entrySet()) {
-                        List<Vector2f> uvs = this.uvCoords.get(entry.getKey());
-                        if (uvs == null) {
-                            return -1;
-                        }
-                        if (!uvs.get(i).equals(entry.getValue())) {
-                            return -1;
-                        }
-                    }
-                }
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * The method normalizes the weights and bone indexes data.
-     * First it truncates the amount to MAXIMUM_WEIGHTS_PER_VERTEX because this is how many weights JME can handle.
-     * Next it normalizes the weights so that the sum of all verts is 1.
-     * @param maximumSize
-     *            the maximum size that the data will be truncated to (usually: MAXIMUM_WEIGHTS_PER_VERTEX)
-     */
-    private void normalizeBoneBuffers(int maximumSize) {
-        for (TreeMap<Float, Integer> group : boneWeightAndIndexes) {
-            if (group.size() > maximumSize) {
-                NavigableMap<Float, Integer> descendingWeights = group.descendingMap();
-                while (descendingWeights.size() > maximumSize) {
-                    descendingWeights.pollLastEntry();
-                }
-            }
-
-            // normalizing the weights so that the sum of the values is equal to '1'
-            TreeMap<Float, Integer> normalizedGroup = new TreeMap<Float, Integer>();
-            float sum = 0;
-            for (Entry<Float, Integer> entry : group.entrySet()) {
-                sum += entry.getKey();
-            }
-
-            if (sum != 0 && sum != 1) {
-                for (Entry<Float, Integer> entry : group.entrySet()) {
-                    normalizedGroup.put(entry.getKey() / sum, entry.getValue());
-                }
-                group.clear();
-                group.putAll(normalizedGroup);
-            }
-        }
-    }
-
-    /**
-     * A class that gathers the data for mesh bone buffers.
-     * Added to increase code readability.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static class BoneBuffersData {
-        public final int          maximumWeightsPerVertex;
-        public final VertexBuffer verticesWeights;
-        public final VertexBuffer verticesWeightsIndices;
-
-        public BoneBuffersData(int maximumWeightsPerVertex, VertexBuffer verticesWeights, VertexBuffer verticesWeightsIndices) {
-            this.maximumWeightsPerVertex = maximumWeightsPerVertex;
-            this.verticesWeights = verticesWeights;
-            this.verticesWeightsIndices = verticesWeightsIndices;
-        }
-    }
-}

+ 0 - 381
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/MeshHelper.java

@@ -1,381 +0,0 @@
-/*
- * Copyright (c) 2009-2019 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.meshes;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.material.Material;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.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;
-
-/**
- * A class that is used in mesh calculations.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class MeshHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER                   = Logger.getLogger(MeshHelper.class.getName());
-
-    /** A type of UV data layer in traditional faced mesh (triangles or quads). */
-    public static final int     UV_DATA_LAYER_TYPE_FMESH = 5;
-    /** A type of UV data layer in bmesh type. */
-    public static final int     UV_DATA_LAYER_TYPE_BMESH = 16;
-
-    /** A material used for single lines and points. */
-    private Material            blackUnshadedMaterial;
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public MeshHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * Converts the mesh structure into temporal mesh.
-     * The temporal mesh is stored in blender context and here always a clone is being returned because the mesh might
-     * be modified by modifiers.
-     * 
-     * @param meshStructure
-     *            the mesh structure
-     * @param blenderContext
-     *            the blender context
-     * @return temporal mesh read from the given structure
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading blend file occur
-     */
-    public TemporalMesh toTemporalMesh(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading temporal mesh named: {0}.", meshStructure.getName());
-        TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(meshStructure.getOldMemoryAddress(), LoadedDataType.TEMPORAL_MESH);
-        if (temporalMesh != null) {
-            LOGGER.fine("The mesh is already loaded. Returning its clone.");
-            return temporalMesh.clone();
-        }
-
-        if ("ID".equals(meshStructure.getType())) {
-            LOGGER.fine("Loading mesh from external blend file.");
-            return (TemporalMesh) this.loadLibrary(meshStructure);
-        }
-
-        String name = meshStructure.getName();
-        LOGGER.log(Level.FINE, "Reading mesh: {0}.", name);
-        temporalMesh = new TemporalMesh(meshStructure, blenderContext);
-
-        LOGGER.fine("Loading materials.");
-        MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
-        temporalMesh.setMaterials(materialHelper.getMaterials(meshStructure, blenderContext));
-
-        LOGGER.fine("Reading custom properties.");
-        Properties properties = this.loadProperties(meshStructure, blenderContext);
-        temporalMesh.setProperties(properties);
-
-        blenderContext.addLoadedFeatures(meshStructure.getOldMemoryAddress(), LoadedDataType.STRUCTURE, meshStructure);
-        blenderContext.addLoadedFeatures(meshStructure.getOldMemoryAddress(), LoadedDataType.TEMPORAL_MESH, temporalMesh);
-        return temporalMesh.clone();
-    }
-
-    /**
-     * Tells if the given mesh structure supports BMesh.
-     * 
-     * @param meshStructure
-     *            the mesh structure
-     * @return <b>true</b> if BMesh is supported and <b>false</b> otherwise
-     */
-    public boolean isBMeshCompatible(Structure meshStructure) {
-        Pointer pMLoop = (Pointer) meshStructure.getFieldValue("mloop");
-        Pointer pMPoly = (Pointer) meshStructure.getFieldValue("mpoly");
-        return pMLoop != null && pMPoly != null && pMLoop.isNotNull() && pMPoly.isNotNull();
-    }
-
-    /**
-     * This method returns the vertices: a list of vertex positions and a list
-     * of vertex normals.
-     * 
-     * @param meshStructure
-     *            the structure containing the mesh data
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is somehow invalid or corrupted
-     */
-    @SuppressWarnings("unchecked")
-    public void loadVerticesAndNormals(Structure meshStructure, List<Vector3f> vertices, List<Vector3f> normals) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading vertices and normals from mesh: {0}.", meshStructure.getName());
-        int count = ((Number) meshStructure.getFieldValue("totvert")).intValue();
-        if (count > 0) {
-            Pointer pMVert = (Pointer) meshStructure.getFieldValue("mvert");
-            List<Structure> mVerts = pMVert.fetchData();
-            Vector3f co = null, no = null;
-            if (fixUpAxis) {
-                for (int i = 0; i < count; ++i) {
-                    DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue("co");
-                    co = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(2).floatValue(), -coordinates.get(1).floatValue());
-                    vertices.add(co);
-
-                    DynamicArray<Number> norm = (DynamicArray<Number>) mVerts.get(i).getFieldValue("no");
-                    no = new Vector3f(norm.get(0).shortValue() / 32767.0f, norm.get(2).shortValue() / 32767.0f, -norm.get(1).shortValue() / 32767.0f);
-                    normals.add(no);
-                }
-            } else {
-                for (int i = 0; i < count; ++i) {
-                    DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue("co");
-                    co = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(1).floatValue(), coordinates.get(2).floatValue());
-                    vertices.add(co);
-
-                    DynamicArray<Number> norm = (DynamicArray<Number>) mVerts.get(i).getFieldValue("no");
-                    no = new Vector3f(norm.get(0).shortValue() / 32767.0f, norm.get(1).shortValue() / 32767.0f, norm.get(2).shortValue() / 32767.0f);
-                    normals.add(no);
-                }
-            }
-        }
-        LOGGER.log(Level.FINE, "Loaded {0} vertices and normals.", vertices.size());
-    }
-
-    /**
-     * This method returns the vertices colors. Each vertex is stored in byte[4] array.
-     * 
-     * @param meshStructure
-     *            the structure containing the mesh data
-     * @param blenderContext
-     *            the blender context
-     * @return a list of vertices colors, each color belongs to a single vertex or empty list of colors are not specified
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is somehow invalid or corrupted
-     */
-    public List<byte[]> loadVerticesColors(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading vertices colors from mesh: {0}.", meshStructure.getName());
-        MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-        Pointer pMCol = (Pointer) meshStructure.getFieldValue(meshHelper.isBMeshCompatible(meshStructure) ? "mloopcol" : "mcol");
-        List<byte[]> verticesColors = new ArrayList<byte[]>();
-        // it was likely a bug in blender untill version 2.63 (the blue and red factors were misplaced in their structure)
-        // so we need to put them right
-        boolean useBGRA = blenderContext.getBlenderVersion() < 263;
-        if (pMCol.isNotNull()) {
-            List<Structure> mCol = pMCol.fetchData();
-            for (Structure color : mCol) {
-                byte r = ((Number) color.getFieldValue("r")).byteValue();
-                byte g = ((Number) color.getFieldValue("g")).byteValue();
-                byte b = ((Number) color.getFieldValue("b")).byteValue();
-                byte a = ((Number) color.getFieldValue("a")).byteValue();
-                verticesColors.add(useBGRA ? new byte[] { b, g, r, a } : new byte[] { r, g, b, a });
-            }
-        }
-        return verticesColors;
-    }
-
-    /**
-     * The method loads the UV coordinates. The result is a map where the key is the user's UV set name and the values are UV coordinates.
-     * But depending on the mesh type (triangle/quads or bmesh) the lists in the map have different meaning.
-     * For bmesh they are enlisted just like they are stored in the blend file (in loops).
-     * For traditional faces every 4 UV's should be assigned for a single face.
-     * @param meshStructure
-     *            the mesh structure
-     * @return a map that sorts UV coordinates between different UV sets
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with blend file occur
-     */
-    @SuppressWarnings("unchecked")
-    public LinkedHashMap<String, List<Vector2f>> loadUVCoordinates(Structure meshStructure) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading UV coordinates from mesh: {0}.", meshStructure.getName());
-        LinkedHashMap<String, List<Vector2f>> result = new LinkedHashMap<String, List<Vector2f>>();
-        if (this.isBMeshCompatible(meshStructure)) {
-            // in this case the UV's are assigned to vertices (an array is the same length as the vertex array)
-            Structure loopData = (Structure) meshStructure.getFieldValue("ldata");
-            Pointer pLoopDataLayers = (Pointer) loopData.getFieldValue("layers");
-            List<Structure> loopDataLayers = pLoopDataLayers.fetchData();
-            for (Structure structure : loopDataLayers) {
-                Pointer p = (Pointer) structure.getFieldValue("data");
-                if (p.isNotNull() && ((Number) structure.getFieldValue("type")).intValue() == MeshHelper.UV_DATA_LAYER_TYPE_BMESH) {
-                    String uvSetName = structure.getFieldValue("name").toString();
-                    List<Structure> uvsStructures = p.fetchData();
-                    List<Vector2f> uvs = new ArrayList<Vector2f>(uvsStructures.size());
-                    for (Structure uvStructure : uvsStructures) {
-                        DynamicArray<Number> loopUVS = (DynamicArray<Number>) uvStructure.getFieldValue("uv");
-                        uvs.add(new Vector2f(loopUVS.get(0).floatValue(), loopUVS.get(1).floatValue()));
-                    }
-                    result.put(uvSetName, uvs);
-                }
-            }
-        } else {
-            // in this case UV's are assigned to faces (the array has the same length as the faces count)
-            Structure facesData = (Structure) meshStructure.getFieldValue("fdata");
-            Pointer pFacesDataLayers = (Pointer) facesData.getFieldValue("layers");
-            if (pFacesDataLayers.isNotNull()) {
-                List<Structure> facesDataLayers = pFacesDataLayers.fetchData();
-                for (Structure structure : facesDataLayers) {
-                    Pointer p = (Pointer) structure.getFieldValue("data");
-                    if (p.isNotNull() && ((Number) structure.getFieldValue("type")).intValue() == MeshHelper.UV_DATA_LAYER_TYPE_FMESH) {
-                        String uvSetName = structure.getFieldValue("name").toString();
-                        List<Structure> uvsStructures = p.fetchData();
-                        List<Vector2f> uvs = new ArrayList<Vector2f>(uvsStructures.size());
-                        for (Structure uvStructure : uvsStructures) {
-                            DynamicArray<Number> mFaceUVs = (DynamicArray<Number>) uvStructure.getFieldValue("uv");
-                            uvs.add(new Vector2f(mFaceUVs.get(0).floatValue(), mFaceUVs.get(1).floatValue()));
-                            uvs.add(new Vector2f(mFaceUVs.get(2).floatValue(), mFaceUVs.get(3).floatValue()));
-                            uvs.add(new Vector2f(mFaceUVs.get(4).floatValue(), mFaceUVs.get(5).floatValue()));
-                            uvs.add(new Vector2f(mFaceUVs.get(6).floatValue(), mFaceUVs.get(7).floatValue()));
-                        }
-                        result.put(uvSetName, uvs);
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Loads all vertices groups.
-     * @param meshStructure
-     *            the mesh structure
-     * @return a list of vertex groups for every vertex in the mesh
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with blend file occur
-     */
-    public List<Map<String, Float>> loadVerticesGroups(Structure meshStructure) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading vertices groups from mesh: {0}.", meshStructure.getName());
-        List<Map<String, Float>> result = new ArrayList<Map<String, Float>>();
-
-        Structure parent = blenderContext.peekParent();
-        if(parent != null) {
-        	// the mesh might be saved without its parent (it is then unused)
-        	Structure defbase = (Structure) parent.getFieldValue("defbase");
-            List<String> groupNames = new ArrayList<String>();
-            List<Structure> defs = defbase.evaluateListBase();
-            
-            if(!defs.isEmpty()) {
-                for (Structure def : defs) {
-                    groupNames.add(def.getFieldValue("name").toString());
-                }
-
-                Pointer pDvert = (Pointer) meshStructure.getFieldValue("dvert");// dvert = DeformVERTices
-                if (pDvert.isNotNull()) {// assigning weights and bone indices
-                    List<Structure> dverts = pDvert.fetchData();
-                    for (Structure dvert : dverts) {
-                        Map<String, Float> weightsForVertex = new HashMap<String, Float>();
-                        Pointer pDW = (Pointer) dvert.getFieldValue("dw");
-                        if (pDW.isNotNull()) {
-                            List<Structure> dw = pDW.fetchData();
-                            for (Structure deformWeight : dw) {
-                                int groupIndex = ((Number) deformWeight.getFieldValue("def_nr")).intValue();
-                                float weight = ((Number) deformWeight.getFieldValue("weight")).floatValue();
-                                String groupName = groupNames.get(groupIndex);
-
-                                weightsForVertex.put(groupName, weight);
-                            }
-                        }
-                        result.add(weightsForVertex);
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Selects the proper subsets of UV coordinates for the given sublist of indexes.
-     * @param face
-     *            the face with the original UV sets
-     * @param indexesSublist
-     *            the sub list of indexes
-     * @return a map of UV coordinates subsets
-     */
-    public Map<String, List<Vector2f>> selectUVSubset(Face face, Integer... indexesSublist) {
-        Map<String, List<Vector2f>> result = null;
-        if (face.getUvSets() != null) {
-            result = new HashMap<String, List<Vector2f>>();
-            for (Entry<String, List<Vector2f>> entry : face.getUvSets().entrySet()) {
-                List<Vector2f> uvs = new ArrayList<Vector2f>(indexesSublist.length);
-                for (Integer index : indexesSublist) {
-                    uvs.add(entry.getValue().get(face.getIndexes().indexOf(index)));
-                }
-                result.put(entry.getKey(), uvs);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Selects the proper subsets of vertex colors for the given sublist of indexes.
-     * @param face
-     *            the face with the original vertex colors
-     * @param indexesSublist
-     *            the sub list of indexes
-     * @return a sublist of vertex colors
-     */
-    public List<byte[]> selectVertexColorSubset(Face face, Integer... indexesSublist) {
-        List<byte[]> result = null;
-        List<byte[]> vertexColors = face.getVertexColors();
-        if (vertexColors != null) {
-            result = new ArrayList<byte[]>(indexesSublist.length);
-            for (Integer index : indexesSublist) {
-                result.add(vertexColors.get(face.getIndexes().indexOf(index)));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns the black unshaded material. It is used for lines and points because that is how blender
-     * renders it.
-     * @param blenderContext
-     *            the blender context
-     * @return black unshaded material
-     */
-    public synchronized Material getBlackUnshadedMaterial(BlenderContext blenderContext) {
-        if (blackUnshadedMaterial == null) {
-            blackUnshadedMaterial = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
-            blackUnshadedMaterial.setColor("Color", ColorRGBA.Black);
-        }
-        return blackUnshadedMaterial;
-    }
-}

+ 0 - 93
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Point.java

@@ -1,93 +0,0 @@
-package com.jme3.scene.plugins.blender.meshes;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
-
-/**
- * A class that represents a single point on the scene that is not a part of an edge.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class Point {
-    private static final Logger LOGGER = Logger.getLogger(Point.class.getName());
-
-    /** The point's index. */
-    private int                 index;
-
-    /**
-     * Constructs a point for a given index.
-     * @param index
-     *            the index of the point
-     */
-    public Point(int index) {
-        this.index = index;
-    }
-
-    @Override
-    public Point clone() {
-        return new Point(index);
-    }
-
-    /**
-     * @return the index of the point
-     */
-    public int getIndex() {
-        return index;
-    }
-
-    /**
-     * The method shifts the index by a given value.
-     * @param shift
-     *            the value to shift the index
-     * @param predicate
-     *            the predicate that verifies which indexes should be shifted; if null then all will be shifted
-     */
-    public void shiftIndexes(int shift, IndexPredicate predicate) {
-        if (predicate == null || predicate.execute(index)) {
-            index += shift;
-        }
-    }
-
-    /**
-     * Loads all points of the mesh that do not belong to any edge.
-     * @param meshStructure
-     *            the mesh structure
-     * @return a list of points
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with file reading occur
-     */
-    public static List<Point> loadAll(Structure meshStructure) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Loading all points that do not belong to any edge from mesh: {0}", meshStructure.getName());
-        List<Point> result = new ArrayList<Point>();
-
-        Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge");
-        if (pMEdge.isNotNull()) {
-            int count = ((Number) meshStructure.getFieldValue("totvert")).intValue();
-            Set<Integer> unusedVertices = new HashSet<Integer>(count);
-            for (int i = 0; i < count; ++i) {
-                unusedVertices.add(i);
-            }
-
-            List<Structure> edges = pMEdge.fetchData();
-            for (Structure edge : edges) {
-                unusedVertices.remove(((Number) edge.getFieldValue("v1")).intValue());
-                unusedVertices.remove(((Number) edge.getFieldValue("v2")).intValue());
-            }
-
-            for (Integer unusedIndex : unusedVertices) {
-                result.add(new Point(unusedIndex));
-            }
-        }
-        LOGGER.log(Level.FINE, "Loaded {0} points.", result.size());
-        return result;
-    }
-}

+ 0 - 767
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java

@@ -1,767 +0,0 @@
-package com.jme3.scene.plugins.blender.meshes;
-
-import java.nio.IntBuffer;
-import java.nio.ShortBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-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.bounding.BoundingBox;
-import com.jme3.bounding.BoundingVolume;
-import com.jme3.material.Material;
-import com.jme3.material.RenderState.FaceCullMode;
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.Mesh.Mode;
-import com.jme3.scene.Node;
-import com.jme3.scene.VertexBuffer;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.VertexBuffer.Usage;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.materials.MaterialContext;
-import com.jme3.scene.plugins.blender.meshes.Face.TriangulationWarning;
-import com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData;
-import com.jme3.scene.plugins.blender.modifiers.Modifier;
-import com.jme3.scene.plugins.blender.objects.Properties;
-
-/**
- * The class extends Geometry so that it can be temporalily added to the object's node.
- * Later each such node's child will be transformed into a list of geometries.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class TemporalMesh extends Geometry {
-    private static final Logger        LOGGER                    = Logger.getLogger(TemporalMesh.class.getName());
-    /** A minimum weight value. */
-    private static final double 	   MINIMUM_BONE_WEIGHT 		 = FastMath.DBL_EPSILON;
-    
-    /** The blender context. */
-    protected final BlenderContext     blenderContext;
-
-    /** The mesh's structure. */
-    protected final Structure          meshStructure;
-
-    /** Loaded vertices. */
-    protected List<Vector3f>           vertices                  = new ArrayList<Vector3f>();
-    /** Loaded normals. */
-    protected List<Vector3f>           normals                   = new ArrayList<Vector3f>();
-    /** Loaded vertex groups. */
-    protected List<Map<String, Float>> vertexGroups              = new ArrayList<Map<String, Float>>();
-    /** Loaded vertex colors. */
-    protected List<byte[]>             verticesColors            = new ArrayList<byte[]>();
-
-    /** Materials used by the mesh. */
-    protected MaterialContext[]        materials;
-    /** The properties of the mesh. */
-    protected Properties               properties;
-    /** The bone indexes. */
-    protected Map<String, Integer>     boneIndexes               = new HashMap<String, Integer>();
-    /** The modifiers that should be applied after the mesh has been created. */
-    protected List<Modifier>           postMeshCreationModifiers = new ArrayList<Modifier>();
-
-    /** The faces of the mesh. */
-    protected List<Face>               faces                     = new ArrayList<Face>();
-    /** The edges of the mesh. */
-    protected List<Edge>               edges                     = new ArrayList<Edge>();
-    /** The points of the mesh. */
-    protected List<Point>              points                    = new ArrayList<Point>();
-    /** A map between index and faces that contain it (for faster index - face queries). */
-    protected Map<Integer, Set<Face>>  indexToFaceMapping        = new HashMap<Integer, Set<Face>>();
-    /** A map between index and edges that contain it (for faster index - edge queries). */
-    protected Map<Integer, Set<Edge>>  indexToEdgeMapping        = new HashMap<Integer, Set<Edge>>();
-
-    /** The bounding box of the temporal mesh. */
-    protected BoundingBox              boundingBox;
-
-    /**
-     * Creates a temporal mesh based on the given mesh structure.
-     * @param meshStructure
-     *            the mesh structure
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with file reading occur
-     */
-    public TemporalMesh(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
-        this(meshStructure, blenderContext, true);
-    }
-
-    /**
-     * Creates a temporal mesh based on the given mesh structure.
-     * @param meshStructure
-     *            the mesh structure
-     * @param blenderContext
-     *            the blender context
-     * @param loadData
-     *            tells if the data should be loaded from the mesh structure
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with file reading occur
-     */
-    protected TemporalMesh(Structure meshStructure, BlenderContext blenderContext, boolean loadData) throws BlenderFileException {
-        this.blenderContext = blenderContext;
-        this.meshStructure = meshStructure;
-
-        if (loadData) {
-            name = meshStructure.getName();
-
-            MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-
-            meshHelper.loadVerticesAndNormals(meshStructure, vertices, normals);
-            verticesColors = meshHelper.loadVerticesColors(meshStructure, blenderContext);
-            LinkedHashMap<String, List<Vector2f>> userUVGroups = meshHelper.loadUVCoordinates(meshStructure);
-            vertexGroups = meshHelper.loadVerticesGroups(meshStructure);
-
-            faces = Face.loadAll(meshStructure, userUVGroups, verticesColors, this, blenderContext);
-            edges = Edge.loadAll(meshStructure, this);
-            points = Point.loadAll(meshStructure);
-
-            this.rebuildIndexesMappings();
-        }
-    }
-
-    /**
-     * @return the blender context
-     */
-    public BlenderContext getBlenderContext() {
-        return blenderContext;
-    }
-
-    /**
-     * @return the vertices of the mesh
-     */
-    public List<Vector3f> getVertices() {
-        return vertices;
-    }
-
-    /**
-     * @return the normals of the mesh
-     */
-    public List<Vector3f> getNormals() {
-        return normals;
-    }
-
-    /**
-     * @return all faces
-     */
-    public List<Face> getFaces() {
-        return faces;
-    }
-
-    /**
-     * @return all edges
-     */
-    public List<Edge> getEdges() {
-        return edges;
-    }
-
-    /**
-     * @return all points (do not mistake it with vertices)
-     */
-    public List<Point> getPoints() {
-        return points;
-    }
-
-    /**
-     * @return all vertices colors
-     */
-    public List<byte[]> getVerticesColors() {
-        return verticesColors;
-    }
-
-    /**
-     * @return all vertex groups for the vertices (each map has groups for the proper vertex)
-     */
-    public List<Map<String, Float>> getVertexGroups() {
-        return vertexGroups;
-    }
-
-    /**
-     * @return the faces that contain the given index or null if none contain it
-     */
-    public Collection<Face> getAdjacentFaces(Integer index) {
-        return indexToFaceMapping.get(index);
-    }
-
-    /**
-     * @param edge the edge of the mesh
-     * @return a list of faces that contain the given edge or an empty list
-     */
-    public Collection<Face> getAdjacentFaces(Edge edge) {
-        List<Face> result = new ArrayList<Face>(indexToFaceMapping.get(edge.getFirstIndex()));
-        Set<Face> secondIndexAdjacentFaces = indexToFaceMapping.get(edge.getSecondIndex());
-        if (secondIndexAdjacentFaces != null) {
-            result.retainAll(indexToFaceMapping.get(edge.getSecondIndex()));
-        }
-        return result;
-    }
-
-    /**
-     * @param index the index of the mesh
-     * @return a list of edges that contain the index
-     */
-    public Collection<Edge> getAdjacentEdges(Integer index) {
-        return indexToEdgeMapping.get(index);
-    }
-
-    /**
-     * Tells if the given edge is a boundary edge. The boundary edge means that it belongs to a single
-     * face or to none.
-     * @param edge the edge of the mesh
-     * @return <b>true</b> if the edge is a boundary one and <b>false</b> otherwise
-     */
-    public boolean isBoundary(Edge edge) {
-        return this.getAdjacentFaces(edge).size() <= 1;
-    }
-
-    /**
-     * The method tells if the given index is a boundary index. A boundary index belongs to at least
-     * one boundary edge.
-     * @param index
-     *            the index of the mesh
-     * @return <b>true</b> if the index is a boundary one and <b>false</b> otherwise
-     */
-    public boolean isBoundary(Integer index) {
-        Collection<Edge> adjacentEdges = this.getAdjacentEdges(index);
-        for (Edge edge : adjacentEdges) {
-            if (this.isBoundary(edge)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public TemporalMesh clone() {
-        try {
-            TemporalMesh result = new TemporalMesh(meshStructure, blenderContext, false);
-            result.name = name;
-            for (Vector3f v : vertices) {
-                result.vertices.add(v.clone());
-            }
-            for (Vector3f n : normals) {
-                result.normals.add(n.clone());
-            }
-            for (Map<String, Float> group : vertexGroups) {
-                result.vertexGroups.add(new HashMap<String, Float>(group));
-            }
-            for (byte[] vertColor : verticesColors) {
-                result.verticesColors.add(vertColor.clone());
-            }
-            result.materials = materials;
-            result.properties = properties;
-            result.boneIndexes.putAll(boneIndexes);
-            result.postMeshCreationModifiers.addAll(postMeshCreationModifiers);
-            for (Face face : faces) {
-                result.faces.add(face.clone());
-            }
-            for (Edge edge : edges) {
-                result.edges.add(edge.clone());
-            }
-            for (Point point : points) {
-                result.points.add(point.clone());
-            }
-            result.rebuildIndexesMappings();
-            return result;
-        } catch (BlenderFileException e) {
-            LOGGER.log(Level.SEVERE, "Error while cloning the temporal mesh: {0}. Returning null.", e.getLocalizedMessage());
-        }
-        return null;
-    }
-
-    /**
-     * The method rebuilds the mappings between faces and edges. Should be called after
-     * every major change of the temporal mesh done outside it.
-     * <p>
-     * Note: I will remove this method soon and cause the mappings to be done
-     * automatically when the mesh is modified.
-     */
-    public void rebuildIndexesMappings() {
-        indexToEdgeMapping.clear();
-        indexToFaceMapping.clear();
-        for (Face face : faces) {
-            for (Integer index : face.getIndexes()) {
-                Set<Face> faces = indexToFaceMapping.get(index);
-                if (faces == null) {
-                    faces = new HashSet<Face>();
-                    indexToFaceMapping.put(index, faces);
-                }
-                faces.add(face);
-            }
-        }
-        for (Edge edge : edges) {
-            Set<Edge> edges = indexToEdgeMapping.get(edge.getFirstIndex());
-            if (edges == null) {
-                edges = new HashSet<Edge>();
-                indexToEdgeMapping.put(edge.getFirstIndex(), edges);
-            }
-            edges.add(edge);
-            edges = indexToEdgeMapping.get(edge.getSecondIndex());
-            if (edges == null) {
-                edges = new HashSet<Edge>();
-                indexToEdgeMapping.put(edge.getSecondIndex(), edges);
-            }
-            edges.add(edge);
-        }
-    }
-
-    @Override
-    public void updateModelBound() {
-        if (boundingBox == null) {
-            boundingBox = new BoundingBox();
-        }
-        Vector3f min = new Vector3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
-        Vector3f max = new Vector3f(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE);
-        for (Vector3f v : vertices) {
-            min.set(Math.min(min.x, v.x), Math.min(min.y, v.y), Math.min(min.z, v.z));
-            max.set(Math.max(max.x, v.x), Math.max(max.y, v.y), Math.max(max.z, v.z));
-        }
-        boundingBox.setMinMax(min, max);
-    }
-
-    @Override
-    public BoundingVolume getModelBound() {
-        this.updateModelBound();
-        return boundingBox;
-    }
-
-    @Override
-    public BoundingVolume getWorldBound() {
-        this.updateModelBound();
-        Node parent = this.getParent();
-        if (parent != null) {
-            BoundingVolume bv = boundingBox.clone();
-            bv.setCenter(parent.getWorldTranslation());
-            return bv;
-        } else {
-            return boundingBox;
-        }
-    }
-
-    /**
-     * Triangulates the mesh.
-     */
-    public void triangulate() {
-        Set<TriangulationWarning> warnings = new HashSet<>(TriangulationWarning.values().length - 1);
-        LOGGER.fine("Triangulating temporal mesh.");
-        for (Face face : faces) {
-            TriangulationWarning warning = face.triangulate();
-            if(warning != TriangulationWarning.NONE) {
-                warnings.add(warning);
-            }
-        }
-        
-        if(warnings.size() > 0 && LOGGER.isLoggable(Level.WARNING)) {
-            StringBuilder sb = new StringBuilder(512);
-            sb.append("There were problems with triangulating the faces of a mesh: ").append(name);
-            for(TriangulationWarning w : warnings) {
-                sb.append("\n\t").append(w);
-            }
-            LOGGER.warning(sb.toString());
-        }
-    }
-
-    /**
-     * The method appends the given mesh to the current one. New faces and vertices and indexes are added.
-     * @param mesh
-     *            the mesh to be appended
-     */
-    public void append(TemporalMesh mesh) {
-        if (mesh != null) {
-            // we need to shift the indexes in faces, lines and points
-            int shift = vertices.size();
-            if (shift > 0) {
-                for (Face face : mesh.faces) {
-                    face.getIndexes().shiftIndexes(shift, null);
-                    face.setTemporalMesh(this);
-                }
-                for (Edge edge : mesh.edges) {
-                    edge.shiftIndexes(shift, null);
-                }
-                for (Point point : mesh.points) {
-                    point.shiftIndexes(shift, null);
-                }
-            }
-
-            faces.addAll(mesh.faces);
-            edges.addAll(mesh.edges);
-            points.addAll(mesh.points);
-
-            vertices.addAll(mesh.vertices);
-            normals.addAll(mesh.normals);
-            vertexGroups.addAll(mesh.vertexGroups);
-            verticesColors.addAll(mesh.verticesColors);
-            boneIndexes.putAll(mesh.boneIndexes);
-
-            this.rebuildIndexesMappings();
-        }
-    }
-
-    /**
-     * Sets the properties of the mesh.
-     * @param properties
-     *            the properties of the mesh
-     */
-    public void setProperties(Properties properties) {
-        this.properties = properties;
-    }
-
-    /**
-     * Sets the materials of the mesh.
-     * @param materials
-     *            the materials of the mesh
-     */
-    public void setMaterials(MaterialContext[] materials) {
-        this.materials = materials;
-    }
-
-    /**
-     * Adds bone index to the mesh.
-     * @param boneName
-     *            the name of the bone
-     * @param boneIndex
-     *            the index of the bone
-     */
-    public void addBoneIndex(String boneName, Integer boneIndex) {
-        boneIndexes.put(boneName, boneIndex);
-    }
-
-    /**
-     * The modifier to be applied after the geometries are created.
-     * @param modifier
-     *            the modifier to be applied
-     */
-    public void applyAfterMeshCreate(Modifier modifier) {
-        postMeshCreationModifiers.add(modifier);
-    }
-
-    @Override
-    public int getVertexCount() {
-        return vertices.size();
-    }
-
-    /**
-     * Removes all vertices from the mesh.
-     */
-    public void clear() {
-        vertices.clear();
-        normals.clear();
-        vertexGroups.clear();
-        verticesColors.clear();
-        faces.clear();
-        edges.clear();
-        points.clear();
-        indexToEdgeMapping.clear();
-        indexToFaceMapping.clear();
-    }
-
-    /**
-     * The mesh builds geometries from the mesh. The result is stored in the blender context
-     * under the mesh's OMA.
-     */
-    public void toGeometries() {
-        LOGGER.log(Level.FINE, "Converting temporal mesh {0} to jme geometries.", name);
-        List<Geometry> result = new ArrayList<Geometry>();
-        MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-        Node parent = this.getParent();
-        parent.detachChild(this);
-
-        this.prepareFacesGeometry(result, meshHelper);
-        this.prepareLinesGeometry(result, meshHelper);
-        this.preparePointsGeometry(result, meshHelper);
-
-        blenderContext.addLoadedFeatures(meshStructure.getOldMemoryAddress(), LoadedDataType.FEATURE, result);
-
-        for (Geometry geometry : result) {
-            parent.attachChild(geometry);
-        }
-
-        for (Modifier modifier : postMeshCreationModifiers) {
-            modifier.postMeshCreationApply(parent, blenderContext);
-        }
-    }
-
-    /**
-     * The method creates geometries from faces.
-     * @param result
-     *            the list where new geometries will be appended
-     * @param meshHelper
-     *            the mesh helper
-     */
-    protected void prepareFacesGeometry(List<Geometry> result, MeshHelper meshHelper) {
-        LOGGER.fine("Preparing faces geometries.");
-        this.triangulate();
-
-        Vector3f[] tempVerts = new Vector3f[3];
-        Vector3f[] tempNormals = new Vector3f[3];
-        byte[][] tempVertColors = new byte[3][];
-        List<Map<Float, Integer>> boneBuffers = new ArrayList<Map<Float, Integer>>(3);
-
-        LOGGER.log(Level.FINE, "Appending {0} faces to mesh buffers.", faces.size());
-        Map<Integer, MeshBuffers> faceMeshes = new HashMap<Integer, MeshBuffers>();
-        for (Face face : faces) {
-            MeshBuffers meshBuffers = faceMeshes.get(face.getMaterialNumber());
-            if (meshBuffers == null) {
-                meshBuffers = new MeshBuffers(face.getMaterialNumber());
-                faceMeshes.put(face.getMaterialNumber(), meshBuffers);
-            }
-
-            List<List<Integer>> triangulatedIndexes = face.getCurrentIndexes();
-            List<byte[]> vertexColors = face.getVertexColors();
-
-            for (List<Integer> indexes : triangulatedIndexes) {
-                assert indexes.size() == 3 : "The mesh has not been properly triangulated!";
-                
-                Vector3f normal = null;
-                if(!face.isSmooth()) {
-                    normal = FastMath.computeNormal(vertices.get(indexes.get(0)), vertices.get(indexes.get(1)), vertices.get(indexes.get(2)));
-                }
-                
-                boneBuffers.clear();
-                for (int i = 0; i < 3; ++i) {
-                    int vertIndex = indexes.get(i);
-                    tempVerts[i] = vertices.get(vertIndex);
-                    tempNormals[i] = normal != null ? normal : normals.get(vertIndex);
-                    tempVertColors[i] = vertexColors != null ? vertexColors.get(face.getIndexes().indexOf(vertIndex)) : null;
-
-                    if (boneIndexes.size() > 0 && vertexGroups.size() > 0) {
-                        Map<Float, Integer> boneBuffersForVertex = new HashMap<Float, Integer>();
-                        Map<String, Float> vertexGroupsForVertex = vertexGroups.get(vertIndex);
-                        for (Entry<String, Integer> entry : boneIndexes.entrySet()) {
-                            if (vertexGroupsForVertex.containsKey(entry.getKey())) {
-                                float weight = vertexGroupsForVertex.get(entry.getKey());
-                                if (weight > MINIMUM_BONE_WEIGHT) {
-                                	// only values of weight greater than MINIMUM_BONE_WEIGHT are used
-                                	// if all non zero weights were used, and they were samm enough, problems with normalisation would occur
-                                	// because adding a very small value to 1.0 will give 1.0
-                                	// so in order to avoid such errors, which can cause severe animation artifacts we need to use some minimum weight value
-                                    boneBuffersForVertex.put(weight, entry.getValue());
-                                }
-                            }
-                        }
-                        if (boneBuffersForVertex.size() == 0) {// attach the vertex to zero-indexed bone so that it does not collapse to (0, 0, 0)
-                            boneBuffersForVertex.put(1.0f, 0);
-                        }
-                        boneBuffers.add(boneBuffersForVertex);
-                    }
-                }
-
-                Map<String, List<Vector2f>> uvs = meshHelper.selectUVSubset(face, indexes.toArray(new Integer[indexes.size()]));
-                meshBuffers.append(face.isSmooth(), tempVerts, tempNormals, uvs, tempVertColors, boneBuffers);
-            }
-        }
-
-        LOGGER.fine("Converting mesh buffers to geometries.");
-        Map<Geometry, MeshBuffers> geometryToBuffersMap = new HashMap<Geometry, MeshBuffers>();
-        for (Entry<Integer, MeshBuffers> entry : faceMeshes.entrySet()) {
-            MeshBuffers meshBuffers = entry.getValue();
-
-            Mesh mesh = new Mesh();
-
-            if (meshBuffers.isShortIndexBuffer()) {
-                mesh.setBuffer(Type.Index, 1, (ShortBuffer) meshBuffers.getIndexBuffer());
-            } else {
-                mesh.setBuffer(Type.Index, 1, (IntBuffer) meshBuffers.getIndexBuffer());
-            }
-            mesh.setBuffer(meshBuffers.getPositionsBuffer());
-            mesh.setBuffer(meshBuffers.getNormalsBuffer());
-            if (meshBuffers.areVertexColorsUsed()) {
-                mesh.setBuffer(Type.Color, 4, meshBuffers.getVertexColorsBuffer());
-                mesh.getBuffer(Type.Color).setNormalized(true);
-            }
-
-            BoneBuffersData boneBuffersData = meshBuffers.getBoneBuffers();
-            if (boneBuffersData != null) {
-                mesh.setMaxNumWeights(boneBuffersData.maximumWeightsPerVertex);
-                mesh.setBuffer(boneBuffersData.verticesWeights);
-                mesh.setBuffer(boneBuffersData.verticesWeightsIndices);
-
-                LOGGER.fine("Generating bind pose and normal buffers.");
-                mesh.generateBindPose(true);
-
-                // change the usage type of vertex and normal buffers from Static to Stream
-                mesh.getBuffer(Type.Position).setUsage(Usage.Stream);
-                mesh.getBuffer(Type.Normal).setUsage(Usage.Stream);
-
-                // creating empty buffers for HW skinning; the buffers will be setup if ever used
-                VertexBuffer verticesWeightsHW = new VertexBuffer(Type.HWBoneWeight);
-                VertexBuffer verticesWeightsIndicesHW = new VertexBuffer(Type.HWBoneIndex);
-                mesh.setBuffer(verticesWeightsHW);
-                mesh.setBuffer(verticesWeightsIndicesHW);
-            }
-
-            Geometry geometry = new Geometry(name + (result.size() + 1), mesh);
-            if (properties != null && properties.getValue() != null) {
-                meshHelper.applyProperties(geometry, properties);
-            }
-            result.add(geometry);
-
-            geometryToBuffersMap.put(geometry, meshBuffers);
-        }
-
-        LOGGER.fine("Applying materials to geometries.");
-        for (Entry<Geometry, MeshBuffers> entry : geometryToBuffersMap.entrySet()) {
-            int materialIndex = entry.getValue().getMaterialIndex();
-            Geometry geometry = entry.getKey();
-            if (materialIndex >= 0 && materials != null && materials.length > materialIndex && materials[materialIndex] != null) {
-                materials[materialIndex].applyMaterial(geometry, meshStructure.getOldMemoryAddress(), entry.getValue().getUvCoords(), blenderContext);
-            } else {
-                Material defaultMaterial = blenderContext.getDefaultMaterial().clone();
-                defaultMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
-                geometry.setMaterial(defaultMaterial);
-            }
-        }
-    }
-
-    /**
-     * The method creates geometries from lines.
-     * @param result
-     *            the list where new geometries will be appended
-     * @param meshHelper
-     *            the mesh helper
-     */
-    protected void prepareLinesGeometry(List<Geometry> result, MeshHelper meshHelper) {
-        if (edges.size() > 0) {
-            LOGGER.fine("Preparing lines geometries.");
-
-            List<List<Integer>> separateEdges = new ArrayList<List<Integer>>();
-            List<Edge> edges = new ArrayList<Edge>(this.edges.size());
-            for (Edge edge : this.edges) {
-                if (!edge.isInFace()) {
-                    edges.add(edge);
-                }
-            }
-            while (edges.size() > 0) {
-                boolean edgeAppended = false;
-                int edgeIndex = 0;
-                for (List<Integer> list : separateEdges) {
-                    for (edgeIndex = 0; edgeIndex < edges.size() && !edgeAppended; ++edgeIndex) {
-                        Edge edge = edges.get(edgeIndex);
-                        if (list.get(0).equals(edge.getFirstIndex())) {
-                            list.add(0, edge.getSecondIndex());
-                            --edgeIndex;
-                            edgeAppended = true;
-                        } else if (list.get(0).equals(edge.getSecondIndex())) {
-                            list.add(0, edge.getFirstIndex());
-                            --edgeIndex;
-                            edgeAppended = true;
-                        } else if (list.get(list.size() - 1).equals(edge.getFirstIndex())) {
-                            list.add(edge.getSecondIndex());
-                            --edgeIndex;
-                            edgeAppended = true;
-                        } else if (list.get(list.size() - 1).equals(edge.getSecondIndex())) {
-                            list.add(edge.getFirstIndex());
-                            --edgeIndex;
-                            edgeAppended = true;
-                        }
-                    }
-                    if (edgeAppended) {
-                        break;
-                    }
-                }
-                Edge edge = edges.remove(edgeAppended ? edgeIndex : 0);
-                if (!edgeAppended) {
-                    separateEdges.add(new ArrayList<Integer>(Arrays.asList(edge.getFirstIndex(), edge.getSecondIndex())));
-                }
-            }
-
-            for (List<Integer> list : separateEdges) {
-                MeshBuffers meshBuffers = new MeshBuffers(0);
-                for (int index : list) {
-                    meshBuffers.append(vertices.get(index), normals.get(index));
-                }
-                Mesh mesh = new Mesh();
-                mesh.setLineWidth(blenderContext.getBlenderKey().getLinesWidth());
-                mesh.setMode(Mode.LineStrip);
-                if (meshBuffers.isShortIndexBuffer()) {
-                    mesh.setBuffer(Type.Index, 1, (ShortBuffer) meshBuffers.getIndexBuffer());
-                } else {
-                    mesh.setBuffer(Type.Index, 1, (IntBuffer) meshBuffers.getIndexBuffer());
-                }
-                mesh.setBuffer(meshBuffers.getPositionsBuffer());
-                mesh.setBuffer(meshBuffers.getNormalsBuffer());
-
-                Geometry geometry = new Geometry(meshStructure.getName() + (result.size() + 1), mesh);
-                geometry.setMaterial(meshHelper.getBlackUnshadedMaterial(blenderContext));
-                if (properties != null && properties.getValue() != null) {
-                    meshHelper.applyProperties(geometry, properties);
-                }
-                result.add(geometry);
-            }
-        }
-    }
-
-    /**
-     * The method creates geometries from points.
-     * @param result
-     *            the list where new geometries will be appended
-     * @param meshHelper
-     *            the mesh helper
-     */
-    protected void preparePointsGeometry(List<Geometry> result, MeshHelper meshHelper) {
-        if (points.size() > 0) {
-            LOGGER.fine("Preparing point geometries.");
-
-            MeshBuffers pointBuffers = new MeshBuffers(0);
-            for (Point point : points) {
-                pointBuffers.append(vertices.get(point.getIndex()), normals.get(point.getIndex()));
-            }
-            Mesh pointsMesh = new Mesh();
-            pointsMesh.setMode(Mode.Points);
-            pointsMesh.setPointSize(blenderContext.getBlenderKey().getPointsSize());
-            if (pointBuffers.isShortIndexBuffer()) {
-                pointsMesh.setBuffer(Type.Index, 1, (ShortBuffer) pointBuffers.getIndexBuffer());
-            } else {
-                pointsMesh.setBuffer(Type.Index, 1, (IntBuffer) pointBuffers.getIndexBuffer());
-            }
-            pointsMesh.setBuffer(pointBuffers.getPositionsBuffer());
-            pointsMesh.setBuffer(pointBuffers.getNormalsBuffer());
-
-            Geometry pointsGeometry = new Geometry(meshStructure.getName() + (result.size() + 1), pointsMesh);
-            pointsGeometry.setMaterial(meshHelper.getBlackUnshadedMaterial(blenderContext));
-            if (properties != null && properties.getValue() != null) {
-                meshHelper.applyProperties(pointsGeometry, properties);
-            }
-            result.add(pointsGeometry);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "TemporalMesh [name=" + name + ", vertices.size()=" + vertices.size() + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (meshStructure == null ? 0 : meshStructure.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof TemporalMesh)) {
-            return false;
-        }
-        TemporalMesh other = (TemporalMesh) obj;
-        return meshStructure.getOldMemoryAddress().equals(other.meshStructure.getOldMemoryAddress());
-    }
-}

+ 0 - 113
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java

@@ -1,113 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.animation.Bone;
-import com.jme3.animation.Skeleton;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.AnimationHelper;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-
-/**
- * This modifier allows to add bone animation to the object.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ArmatureModifier extends Modifier {
-    private static final Logger LOGGER              = Logger.getLogger(ArmatureModifier.class.getName());
-
-    private static final int    FLAG_VERTEX_GROUPS  = 0x01;
-    private static final int    FLAG_BONE_ENVELOPES = 0x02;
-
-    private Skeleton            skeleton;
-
-    /**
-     * 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 blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public ArmatureModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
-        if (this.validate(modifierStructure, blenderContext)) {
-            Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object");
-            if (pArmatureObject.isNotNull()) {
-                int deformflag = ((Number) modifierStructure.getFieldValue("deformflag")).intValue();
-                boolean useVertexGroups = (deformflag & FLAG_VERTEX_GROUPS) != 0;
-                boolean useBoneEnvelopes = (deformflag & FLAG_BONE_ENVELOPES) != 0;
-                modifying = useBoneEnvelopes || useVertexGroups;
-                if (modifying) {// if neither option is used the modifier will not modify anything anyway
-                    Structure armatureObject = pArmatureObject.fetchData().get(0);
-                    if(blenderContext.getSkeleton(armatureObject.getOldMemoryAddress()) == null) {
-                        LOGGER.fine("Creating new skeleton for armature modifier.");
-                        Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData().get(0);
-                        List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase();
-                        List<Bone> bonesList = new ArrayList<Bone>();
-                        for (int i = 0; i < bonebase.size(); ++i) {
-                            this.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectStructure.getOldMemoryAddress(), blenderContext);
-                        }
-                        bonesList.add(0, new Bone(""));
-                        Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
-                        skeleton = new Skeleton(bones);
-                        blenderContext.setSkeleton(armatureObject.getOldMemoryAddress(), skeleton);
-                    } else {
-                        skeleton = blenderContext.getSkeleton(armatureObject.getOldMemoryAddress());
-                    }                    
-                }
-            } else {
-                modifying = false;
-            }
-        }
-    }
-
-    private void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Long spatialOMA, BlenderContext blenderContext) throws BlenderFileException {
-        BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, blenderContext);
-        bc.buildBone(result, spatialOMA, blenderContext);
-    }
-    
-    @Override
-    public void postMeshCreationApply(Node node, BlenderContext blenderContext) {
-        LOGGER.fine("Applying armature modifier after mesh has been created.");
-        AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
-        animationHelper.applyAnimations(node, skeleton, blenderContext.getBlenderKey().getAnimationMatchMethod());
-        node.updateModelBound();
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Armature modifier is invalid! Cannot be applied to: {0}", node.getName());
-        }
-
-        if (modifying) {
-            TemporalMesh temporalMesh = this.getTemporalMesh(node);
-            if (temporalMesh != null) {
-                LOGGER.log(Level.FINE, "Applying armature modifier to: {0}", temporalMesh);
-                
-                LOGGER.fine("Creating map between bone name and its index.");
-                for (int i = 0; i < skeleton.getBoneCount(); ++i) {
-                    Bone bone = skeleton.getBone(i);
-                    temporalMesh.addBoneIndex(bone.getName(), i);
-                }
-                temporalMesh.applyAfterMeshCreate(this);
-            } else {
-                LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-            }
-        }
-    }
-}

+ 0 - 241
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java

@@ -1,241 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.HashSet;
-import java.util.List;
-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.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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.meshes.MeshHelper;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-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());
-
-    private int                 fittype;
-    private int                 count;
-    private float               length;
-    private float[]             offset;
-    private float[]             scale;
-    private Pointer             pOffsetObject;
-    private Pointer             pStartCap;
-    private Pointer             pEndCap;
-
-    /**
-     * 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 blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    @SuppressWarnings("unchecked")
-    public ArrayModifier(Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
-        if (this.validate(modifierStructure, blenderContext)) {
-            fittype = ((Number) modifierStructure.getFieldValue("fit_type")).intValue();
-            switch (fittype) {
-                case 0:// FIXED COUNT
-                    count = ((Number) modifierStructure.getFieldValue("count")).intValue();
-                    break;
-                case 1:// FIXED LENGTH
-                    length = ((Number) modifierStructure.getFieldValue("length")).floatValue();
-                    break;
-                case 2:// FITCURVE
-                    Pointer pCurveOb = (Pointer) modifierStructure.getFieldValue("curve_ob");
-                    if (pCurveOb.isNotNull()) {
-                        Structure curveStructure = pCurveOb.fetchData().get(0);
-                        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-                        Node curveObject = (Node) objectHelper.toObject(curveStructure, blenderContext);
-                        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);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    fittype = 1;// treat it like FIXED LENGTH
-                    break;
-                default:
-                    assert false : "Unknown array modifier fit type: " + fittype;
-            }
-
-            // offset parameters
-            int offsettype = ((Number) modifierStructure.getFieldValue("offset_type")).intValue();
-            if ((offsettype & 0x01) != 0) {// Constant offset
-                DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifierStructure.getFieldValue("offset");
-                offset = new float[] { offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue() };
-            }
-            if ((offsettype & 0x02) != 0) {// Relative offset
-                DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifierStructure.getFieldValue("scale");
-                scale = new float[] { scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue() };
-            }
-            if ((offsettype & 0x04) != 0) {// Object offset
-                pOffsetObject = (Pointer) modifierStructure.getFieldValue("offset_ob");
-            }
-
-            // start cap and end cap
-            pStartCap = (Pointer) modifierStructure.getFieldValue("start_cap");
-            pEndCap = (Pointer) modifierStructure.getFieldValue("end_cap");
-        }
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Array modifier is invalid! Cannot be applied to: {0}", node.getName());
-        } else {
-            TemporalMesh temporalMesh = this.getTemporalMesh(node);
-            if (temporalMesh != null) {
-                LOGGER.log(Level.FINE, "Applying array modifier to: {0}", temporalMesh);
-                if (offset == null) {// the node will be repeated several times in the same place
-                    offset = new float[] { 0.0f, 0.0f, 0.0f };
-                }
-                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
-                    temporalMesh.updateModelBound();
-                    BoundingVolume boundingVolume = temporalMesh.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 };
-                if (pOffsetObject != null && pOffsetObject.isNotNull()) {
-                    FileBlockHeader offsetObjectBlock = blenderContext.getFileBlock(pOffsetObject.getOldMemoryAddress());
-                    ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-                    try {// we take the structure in case the object was not yet loaded
-                        Structure offsetStructure = offsetObjectBlock.getStructure(blenderContext);
-                        Vector3f translation = objectHelper.getTransformation(offsetStructure, blenderContext).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
-                MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-                TemporalMesh[] caps = new TemporalMesh[] { null, null };
-                Pointer[] pCaps = new Pointer[] { pStartCap, pEndCap };
-                for (int i = 0; i < pCaps.length; ++i) {
-                    if (pCaps[i].isNotNull()) {
-                        FileBlockHeader capBlock = blenderContext.getFileBlock(pCaps[i].getOldMemoryAddress());
-                        try {// we take the structure in case the object was not yet loaded
-                            Structure capStructure = capBlock.getStructure(blenderContext);
-                            Pointer pMesh = (Pointer) capStructure.getFieldValue("data");
-                            List<Structure> meshesArray = pMesh.fetchData();
-                            caps[i] = meshHelper.toTemporalMesh(meshesArray.get(0), blenderContext);
-                        } 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]);
-                if (blenderContext.getBlenderKey().isFixUpAxis()) {
-                    float y = translationVector.y;
-                    translationVector.y = translationVector.z;
-                    translationVector.z = y == 0 ? 0 : -y;
-                }
-
-                // getting/calculating repeats amount
-                int count = 0;
-                if (fittype == 0) {// Fixed count
-                    count = this.count - 1;
-                } else if (fittype == 1) {// Fixed length
-                    float length = this.length;
-                    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
-                Vector3f totalTranslation = new Vector3f(translationVector);
-                if (count > 0) {
-                    TemporalMesh originalMesh = temporalMesh.clone();
-                    for (int i = 0; i < count; ++i) {
-                        TemporalMesh clone = originalMesh.clone();
-                        for (Vector3f v : clone.getVertices()) {
-                            v.addLocal(totalTranslation);
-                        }
-                        temporalMesh.append(clone);
-                        totalTranslation.addLocal(translationVector);
-                    }
-                }
-                if (caps[0] != null) {
-                    translationVector.multLocal(-1);
-                    TemporalMesh capsClone = caps[0].clone();
-                    for (Vector3f v : capsClone.getVertices()) {
-                        v.addLocal(translationVector);
-                    }
-                    temporalMesh.append(capsClone);
-                }
-                if (caps[1] != null) {
-                    TemporalMesh capsClone = caps[1].clone();
-                    for (Vector3f v : capsClone.getVertices()) {
-                        v.addLocal(totalTranslation);
-                    }
-                    temporalMesh.append(capsClone);
-                }
-            } else {
-                LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-            }
-        }
-    }
-}

+ 0 - 200
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/MaskModifier.java

@@ -1,200 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.animations.BoneContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.Edge;
-import com.jme3.scene.plugins.blender.meshes.Face;
-import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
-import com.jme3.scene.plugins.blender.meshes.Point;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-
-/**
- * This modifier allows to use mask modifier on the object.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class MaskModifier extends Modifier {
-    private static final Logger LOGGER            = Logger.getLogger(MaskModifier.class.getName());
-
-    private static final int    FLAG_INVERT_MASK  = 0x01;
-
-    private static final int    MODE_VERTEX_GROUP = 0;
-    private static final int    MODE_ARMATURE     = 1;
-
-    private Pointer             pArmatureObject;
-    private String              vertexGroupName;
-    private boolean             invertMask;
-
-    public MaskModifier(Structure modifierStructure, BlenderContext blenderContext) {
-        if (this.validate(modifierStructure, blenderContext)) {
-            int flag = ((Number) modifierStructure.getFieldValue("flag")).intValue();
-            invertMask = (flag & FLAG_INVERT_MASK) != 0;
-
-            int mode = ((Number) modifierStructure.getFieldValue("mode")).intValue();
-            if (mode == MODE_VERTEX_GROUP) {
-                vertexGroupName = modifierStructure.getFieldValue("vgroup").toString();
-                if (vertexGroupName != null && vertexGroupName.length() == 0) {
-                    vertexGroupName = null;
-                }
-            } else if (mode == MODE_ARMATURE) {
-                pArmatureObject = (Pointer) modifierStructure.getFieldValue("ob_arm");
-            } else {
-                LOGGER.log(Level.SEVERE, "Unknown mode type: {0}. Cannot apply modifier: {1}.", new Object[] { mode, modifierStructure.getName() });
-                invalid = true;
-            }
-        }
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Mirror modifier is invalid! Cannot be applied to: {0}", node.getName());
-        } else {
-            TemporalMesh temporalMesh = this.getTemporalMesh(node);
-            if (temporalMesh != null) {
-                List<String> vertexGroupsToRemove = new ArrayList<String>();
-                if (vertexGroupName != null) {
-                    vertexGroupsToRemove.add(vertexGroupName);
-                } else if (pArmatureObject != null && pArmatureObject.isNotNull()) {
-                    try {
-                        Structure armatureObject = pArmatureObject.fetchData().get(0);
-
-                        Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData().get(0);
-                        List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase();
-                        vertexGroupsToRemove.addAll(this.readBoneNames(bonebase));
-                    } catch (BlenderFileException e) {
-                        LOGGER.log(Level.SEVERE, "Cannot load armature object for the mask modifier. Cause: {0}", e.getLocalizedMessage());
-                        LOGGER.log(Level.SEVERE, "Mask modifier will NOT be applied to node named: {0}", node.getName());
-                    }
-                } else {
-                    // if the mesh has no vertex groups then remove all verts
-                    // if the mesh has at least one vertex group - then do nothing
-                    // I have no idea why we should do that, but blender works this way
-                    Set<String> vertexGroupNames = new HashSet<String>();
-                    for (Map<String, Float> groups : temporalMesh.getVertexGroups()) {
-                        vertexGroupNames.addAll(groups.keySet());
-                    }
-                    if (vertexGroupNames.size() == 0 && !invertMask || vertexGroupNames.size() > 0 && invertMask) {
-                        temporalMesh.clear();
-                    }
-                }
-
-                if (vertexGroupsToRemove.size() > 0) {
-                    List<Integer> vertsToBeRemoved = new ArrayList<Integer>();
-                    for (int i = 0; i < temporalMesh.getVertexCount(); ++i) {
-                        Map<String, Float> vertexGroups = temporalMesh.getVertexGroups().get(i);
-                        boolean hasVertexGroup = false;
-                        if (vertexGroups != null) {
-                            for (String groupName : vertexGroupsToRemove) {
-                                Float weight = vertexGroups.get(groupName);
-                                if (weight != null && weight > 0) {
-                                    hasVertexGroup = true;
-                                    break;
-                                }
-                            }
-                        }
-
-                        if (!hasVertexGroup && !invertMask || hasVertexGroup && invertMask) {
-                            vertsToBeRemoved.add(i);
-                        }
-                    }
-
-                    Collections.reverse(vertsToBeRemoved);
-                    for (Integer vertexIndex : vertsToBeRemoved) {
-                        this.removeVertexAt(vertexIndex, temporalMesh);
-                    }
-                }
-            } else {
-                LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-            }
-        }
-    }
-
-    /**
-     * Every face, edge and point that contains
-     * the vertex will be removed.
-     * @param index
-     *            the index of a vertex to be removed
-     * @throws IndexOutOfBoundsException
-     *             thrown when given index is negative or beyond the count of vertices
-     */
-    private void removeVertexAt(final int index, TemporalMesh temporalMesh) {
-        if (index < 0 || index >= temporalMesh.getVertexCount()) {
-            throw new IndexOutOfBoundsException("The given index is out of bounds: " + index);
-        }
-
-        temporalMesh.getVertices().remove(index);
-        temporalMesh.getNormals().remove(index);
-        if (temporalMesh.getVertexGroups().size() > 0) {
-            temporalMesh.getVertexGroups().remove(index);
-        }
-        if (temporalMesh.getVerticesColors().size() > 0) {
-            temporalMesh.getVerticesColors().remove(index);
-        }
-
-        IndexPredicate shiftPredicate = new IndexPredicate() {
-            @Override
-            public boolean execute(Integer i) {
-                return i > index;
-            }
-        };
-        for (int i = temporalMesh.getFaces().size() - 1; i >= 0; --i) {
-            Face face = temporalMesh.getFaces().get(i);
-            if (face.getIndexes().indexOf(index) >= 0) {
-                temporalMesh.getFaces().remove(i);
-            } else {
-                face.getIndexes().shiftIndexes(-1, shiftPredicate);
-            }
-        }
-        for (int i = temporalMesh.getEdges().size() - 1; i >= 0; --i) {
-            Edge edge = temporalMesh.getEdges().get(i);
-            if (edge.getFirstIndex() == index || edge.getSecondIndex() == index) {
-                temporalMesh.getEdges().remove(i);
-            } else {
-                edge.shiftIndexes(-1, shiftPredicate);
-            }
-        }
-        for (int i = temporalMesh.getPoints().size() - 1; i >= 0; --i) {
-            Point point = temporalMesh.getPoints().get(i);
-            if (point.getIndex() == index) {
-                temporalMesh.getPoints().remove(i);
-            } else {
-                point.shiftIndexes(-1, shiftPredicate);
-            }
-        }
-    }
-
-    /**
-     * Reads the names of the bones from the given bone base.
-     * @param boneBase
-     *            the list of bone base structures
-     * @return a list of bones' names
-     * @throws BlenderFileException
-     *             is thrown if problems with reading the child bones' bases occur
-     */
-    private List<String> readBoneNames(List<Structure> boneBase) throws BlenderFileException {
-        List<String> result = new ArrayList<String>();
-        for (Structure boneStructure : boneBase) {
-            int flag = ((Number) boneStructure.getFieldValue("flag")).intValue();
-            if ((flag & BoneContext.SELECTED) != 0) {
-                result.add(boneStructure.getFieldValue("name").toString());
-            }
-            List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase();
-            result.addAll(this.readBoneNames(childbase));
-        }
-        return result;
-    }
-}

+ 0 - 196
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java

@@ -1,196 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.Collections;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.Edge;
-import com.jme3.scene.plugins.blender.meshes.Face;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-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());
-
-    private static final int    FLAG_MIRROR_X            = 0x08;
-    private static final int    FLAG_MIRROR_Y            = 0x10;
-    private static final int    FLAG_MIRROR_Z            = 0x20;
-    private static final int    FLAG_MIRROR_U            = 0x02;
-    private static final int    FLAG_MIRROR_V            = 0x04;
-    private static final int    FLAG_MIRROR_VERTEX_GROUP = 0x40;
-    private static final int    FLAG_MIRROR_MERGE        = 0x80;
-
-    private boolean[]           isMirrored;
-    private boolean             mirrorU, mirrorV;
-    private boolean             merge;
-    private float               tolerance;
-    private Pointer             pMirrorObject;
-    private boolean             mirrorVGroup;
-
-    /**
-     * 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 blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public MirrorModifier(Structure modifierStructure, BlenderContext blenderContext) {
-        if (this.validate(modifierStructure, blenderContext)) {
-            int flag = ((Number) modifierStructure.getFieldValue("flag")).intValue();
-
-            isMirrored = new boolean[] { (flag & FLAG_MIRROR_X) != 0, (flag & FLAG_MIRROR_Y) != 0, (flag & FLAG_MIRROR_Z) != 0 };
-            if (blenderContext.getBlenderKey().isFixUpAxis()) {
-                boolean temp = isMirrored[1];
-                isMirrored[1] = isMirrored[2];
-                isMirrored[2] = temp;
-            }
-            mirrorU = (flag & FLAG_MIRROR_U) != 0;
-            mirrorV = (flag & FLAG_MIRROR_V) != 0;
-            mirrorVGroup = (flag & FLAG_MIRROR_VERTEX_GROUP) != 0;
-            merge = (flag & FLAG_MIRROR_MERGE) == 0;// in this case we use == instead of != (this is not a mistake)
-
-            tolerance = ((Number) modifierStructure.getFieldValue("tolerance")).floatValue();
-            pMirrorObject = (Pointer) modifierStructure.getFieldValue("mirror_ob");
-
-            if (mirrorVGroup) {
-                LOGGER.warning("Mirroring vertex groups is currently not supported.");
-            }
-        }
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Mirror modifier is invalid! Cannot be applied to: {0}", node.getName());
-        } else {
-            TemporalMesh temporalMesh = this.getTemporalMesh(node);
-            if (temporalMesh != null) {
-                LOGGER.log(Level.FINE, "Applying mirror modifier to: {0}", temporalMesh);
-                Vector3f mirrorPlaneCenter = new Vector3f();
-                if (pMirrorObject.isNotNull()) {
-                    Structure objectStructure;
-                    try {
-                        objectStructure = pMirrorObject.fetchData().get(0);
-                        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-                        Node object = (Node) objectHelper.toObject(objectStructure, blenderContext);
-                        if (object != null) {
-                            // compute the mirror object coordinates in node's local space
-                            mirrorPlaneCenter = this.getWorldMatrix(node).invertLocal().mult(object.getWorldTranslation());
-                        }
-                    } catch (BlenderFileException e) {
-                        LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage());
-                        LOGGER.log(Level.SEVERE, "Mirror modifier will not be applied to node named: {0}", node.getName());
-                        return;
-                    }
-                }
-
-                LOGGER.finest("Allocating temporal variables.");
-                float d;
-                Vector3f mirrorPlaneNormal = new Vector3f();
-                Vector3f shiftVector = new Vector3f();
-
-                LOGGER.fine("Mirroring mesh.");
-                for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) {
-                    if (isMirrored[mirrorIndex]) {
-                        boolean mirrorAtPoint0 = mirrorPlaneCenter.get(mirrorIndex) == 0;
-                        if (!mirrorAtPoint0) {// compute mirror's plane normal vector in node's space
-                            mirrorPlaneNormal.set(0, 0, 0).set(mirrorIndex, Math.signum(mirrorPlaneCenter.get(mirrorIndex)));
-                        }
-
-                        TemporalMesh mirror = temporalMesh.clone();
-                        for (int i = 0; i < mirror.getVertexCount(); ++i) {
-                            Vector3f vertex = mirror.getVertices().get(i);
-                            Vector3f normal = mirror.getNormals().get(i);
-
-                            if (mirrorAtPoint0) {
-                                d = Math.abs(vertex.get(mirrorIndex));
-                                shiftVector.set(0, 0, 0).set(mirrorIndex, -vertex.get(mirrorIndex));
-                            } else {
-                                d = this.computeDistanceFromPlane(vertex, mirrorPlaneCenter, mirrorPlaneNormal);
-                                mirrorPlaneNormal.mult(d, shiftVector);
-                            }
-
-                            if (merge && d <= tolerance) {
-                                vertex.addLocal(shiftVector);
-                                normal.set(mirrorIndex, 0);
-                                temporalMesh.getVertices().get(i).addLocal(shiftVector);
-                                temporalMesh.getNormals().get(i).set(mirrorIndex, 0);
-                            } else {
-                                vertex.addLocal(shiftVector.multLocal(2));
-                                normal.set(mirrorIndex, -normal.get(mirrorIndex));
-                            }
-                        }
-
-                        // flipping the indexes
-                        for (Face face : mirror.getFaces()) {
-                            face.flipIndexes();
-                        }
-                        for (Edge edge : mirror.getEdges()) {
-                            edge.flipIndexes();
-                        }
-                        Collections.reverse(mirror.getPoints());
-
-                        if (mirrorU || mirrorV) {
-                            for (Face face : mirror.getFaces()) {
-                                face.flipUV(mirrorU, mirrorV);
-                            }
-                        }
-
-                        temporalMesh.append(mirror);
-                    }
-                }
-            } else {
-                LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-            }
-        }
-    }
-
-    /**
-     * Fetches the world matrix transformation of the given node.
-     * @param node
-     *            the node
-     * @return the node's world transformation matrix
-     */
-    private Matrix4f getWorldMatrix(Node node) {
-        Matrix4f result = new Matrix4f();
-        result.setTranslation(node.getWorldTranslation());
-        result.setRotationQuaternion(node.getWorldRotation());
-        result.setScale(node.getWorldScale());
-        return result;
-    }
-
-    /**
-     * The method computes the distance between a point and a plane (described by point in space and normal vector).
-     * @param p
-     *            the point in the space
-     * @param c
-     *            mirror's plane center
-     * @param n
-     *            mirror's plane normal (should be normalized)
-     * @return the minimum distance from point to plane
-     */
-    private float computeDistanceFromPlane(Vector3f p, Vector3f c, Vector3f n) {
-        return Math.abs(n.dot(p) - c.dot(n));
-    }
-}

+ 0 - 92
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/Modifier.java

@@ -1,92 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.List;
-
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.Pointer;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-
-/**
- * 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 SUBSURF_MODIFIER_DATA          = "SubsurfModifierData";
-    public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData";
-
-    /** This variable indicates if the modifier is invalid (<b>true</b>) or not (<b>false</b>). */
-    protected boolean          invalid;
-    /**
-     * A variable that tells if the modifier causes modification. Some modifiers like ArmatureModifier might have no
-     * Armature object attached and thus not really modifying the feature. In such cases it is good to know if it is
-     * sense to add the modifier to the list of object's modifiers.
-     */
-    protected boolean          modifying                      = true;
-
-    /**
-     * This method applies the modifier to the given node.
-     * 
-     * @param node
-     *            the node that will have modifier applied
-     * @param blenderContext
-     *            the blender context
-     */
-    public abstract void apply(Node node, BlenderContext blenderContext);
-
-    /**
-     * The method that is called when geometries are already created.
-     * @param node
-     *            the node that will have the modifier applied
-     * @param blenderContext
-     *            the blender context
-     */
-    public void postMeshCreationApply(Node node, BlenderContext blenderContext) {
-    }
-
-    /**
-     * Determines if the modifier can be applied multiple times over one mesh.
-     * At this moment only armature and object animation modifiers cannot be
-     * applied multiple times.
-     * 
-     * @param modifierType
-     *            the type name of the modifier
-     * @return <b>true</b> if the modifier can be applied many times and
-     *         <b>false</b> otherwise
-     */
-    public static boolean canBeAppliedMultipleTimes(String modifierType) {
-        return !(ARMATURE_MODIFIER_DATA.equals(modifierType) || OBJECT_ANIMATION_MODIFIER_DATA.equals(modifierType));
-    }
-
-    protected boolean validate(Structure modifierStructure, BlenderContext blenderContext) {
-        Structure modifierData = (Structure) modifierStructure.getFieldValue("modifier");
-        Pointer pError = (Pointer) modifierData.getFieldValue("error");
-        invalid = pError.isNotNull();
-        return !invalid;
-    }
-
-    /**
-     * @return <b>true</b> if the modifier causes feature's modification or <b>false</b> if not
-     */
-    public boolean isModifying() {
-        return modifying;
-    }
-
-    protected TemporalMesh getTemporalMesh(Node node) {
-        List<Spatial> children = node.getChildren();
-        if (children != null && children.size() == 1 && children.get(0) instanceof TemporalMesh) {
-            return (TemporalMesh) children.get(0);
-        }
-        return null;
-    }
-}

+ 0 - 117
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ModifierHelper.java

@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-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
-     * @param blenderContext
-     *            the blender context
-     */
-    public ModifierHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * This method reads the given object's modifiers.
-     * 
-     * @param objectStructure
-     *            the object structure
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public Collection<Modifier> readModifiers(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
-        Set<String> alreadyReadModifiers = new HashSet<String>();
-        Collection<Modifier> result = new ArrayList<Modifier>();
-        Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers");
-        List<Structure> modifiers = modifiersListBase.evaluateListBase();
-        for (Structure modifierStructure : modifiers) {
-            String modifierType = modifierStructure.getType();
-            if (!Modifier.canBeAppliedMultipleTimes(modifierType) && alreadyReadModifiers.contains(modifierType)) {
-                LOGGER.log(Level.WARNING, "Modifier {0} can only be applied once to object: {1}", new Object[] { modifierType, objectStructure.getName() });
-            } else {
-                Modifier modifier = null;
-                if (Modifier.ARRAY_MODIFIER_DATA.equals(modifierStructure.getType())) {
-                    modifier = new ArrayModifier(modifierStructure, blenderContext);
-                } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifierStructure.getType())) {
-                    modifier = new MirrorModifier(modifierStructure, blenderContext);
-                } else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifierStructure.getType())) {
-                    modifier = new ArmatureModifier(objectStructure, modifierStructure, blenderContext);
-                } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifierStructure.getType())) {
-                    modifier = new ParticlesModifier(modifierStructure, blenderContext);
-                } else if(Modifier.SUBSURF_MODIFIER_DATA.equals(modifierStructure.getType())) {
-                    modifier = new SubdivisionSurfaceModifier(modifierStructure, blenderContext);
-                }
-
-                if (modifier != null) {
-                    if (modifier.isModifying()) {
-                        result.add(modifier);
-                        alreadyReadModifiers.add(modifierType);
-                    } else {
-                        LOGGER.log(Level.WARNING, "The modifier {0} will cause no changes in the model. It will be ignored!", modifierStructure.getName());
-                    }
-                } else {
-                    LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifierStructure.getType());
-                }
-            }
-        }
-        return result;
-    }
-}

+ 0 - 107
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java

@@ -1,107 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-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.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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.meshes.TemporalMesh;
-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 {
-    private static final Logger LOGGER = Logger.getLogger(MirrorModifier.class.getName());
-
-    /** Loaded particles emitter. */
-    private ParticleEmitter     particleEmitter;
-
-    /**
-     * This constructor reads the particles system structure and stores it in
-     * order to apply it later to the node.
-     * 
-     * @param modifierStructure
-     *            the structure of the modifier
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is throw wneh there are problems with the
-     *             blender file
-     */
-    public ParticlesModifier(Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
-        if (this.validate(modifierStructure, blenderContext)) {
-            Pointer pParticleSystem = (Pointer) modifierStructure.getFieldValue("psys");
-            if (pParticleSystem.isNotNull()) {
-                ParticlesHelper particlesHelper = blenderContext.getHelper(ParticlesHelper.class);
-                Structure particleSystem = pParticleSystem.fetchData().get(0);
-                particleEmitter = particlesHelper.toParticleEmitter(particleSystem);
-            }
-        }
-    }
-    
-    @Override
-    public void postMeshCreationApply(Node node, BlenderContext blenderContext) {
-        LOGGER.log(Level.FINE, "Applying particles modifier to: {0}", node);
-        
-        MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
-        ParticleEmitter emitter = particleEmitter.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, blenderContext);
-                    emitter.setMaterial(material);// TODO: divide into several pieces
-                }
-            }
-        }
-        if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) {
-            ((EmitterMeshVertexShape) emitterShape).setMeshes(meshes);
-        }
-
-        node.attachChild(emitter);
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Particles modifier is invalid! Cannot be applied to: {0}", node.getName());
-        } else {
-            TemporalMesh temporalMesh = this.getTemporalMesh(node);
-            if(temporalMesh != null) {
-                temporalMesh.applyAfterMeshCreate(this);
-            } else {
-                LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-            }
-        }
-    }
-}

+ 0 - 642
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java

@@ -1,642 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-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.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.Edge;
-import com.jme3.scene.plugins.blender.meshes.Face;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-
-/**
- * A modifier that subdivides the mesh using either simple or catmull-clark subdivision.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class SubdivisionSurfaceModifier extends Modifier {
-    private static final Logger LOGGER                  = Logger.getLogger(SubdivisionSurfaceModifier.class.getName());
-
-    private static final int    TYPE_CATMULLCLARK       = 0;
-    private static final int    TYPE_SIMPLE             = 1;
-
-    private static final int    FLAG_SUBDIVIDE_UVS      = 0x8;
-
-    /** The subdivision type. */
-    private int                 subdivType;
-    /** The amount of subdivision levels. */
-    private int                 levels;
-    /** Indicates if the UV's should also be subdivided. */
-    private boolean             subdivideUVS;
-    /** Stores the vertices that are located on original edges of the mesh. */
-    private Set<Integer>        verticesOnOriginalEdges = new HashSet<Integer>();
-
-    /**
-     * Constructor loads all necessary modifier data.
-     * @param modifierStructure
-     *            the modifier structure
-     * @param blenderContext
-     *            the blender context
-     */
-    public SubdivisionSurfaceModifier(Structure modifierStructure, BlenderContext blenderContext) {
-        if (this.validate(modifierStructure, blenderContext)) {
-            subdivType = ((Number) modifierStructure.getFieldValue("subdivType")).intValue();
-            levels = ((Number) modifierStructure.getFieldValue("levels")).intValue();
-            int flag = ((Number) modifierStructure.getFieldValue("flags")).intValue();
-            subdivideUVS = (flag & FLAG_SUBDIVIDE_UVS) != 0 && subdivType == TYPE_CATMULLCLARK;
-
-            if (subdivType != TYPE_CATMULLCLARK && subdivType != TYPE_SIMPLE) {
-                LOGGER.log(Level.SEVERE, "Unknown subdivision type: {0}.", subdivType);
-                invalid = true;
-            }
-            if (levels < 0) {
-                LOGGER.severe("The amount of subdivision levels cannot be negative.");
-                invalid = true;
-            }
-        }
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Subdivision surface modifier is invalid! Cannot be applied to: {0}", node.getName());
-        } else if (levels > 0) {// no need to do anything if the levels is set to zero
-            TemporalMesh temporalMesh = this.getTemporalMesh(node);
-            if (temporalMesh != null) {
-                LOGGER.log(Level.FINE, "Applying subdivision surface modifier to: {0}", temporalMesh);
-                verticesOnOriginalEdges.clear();//in case the instance of this class was used more than once
-                
-                for (Edge edge : temporalMesh.getEdges()) {
-                    verticesOnOriginalEdges.add(edge.getFirstIndex());
-                    verticesOnOriginalEdges.add(edge.getSecondIndex());
-                }
-
-                if (subdivType == TYPE_CATMULLCLARK) {
-                    for (int i = 0; i < levels; ++i) {
-                        this.subdivideSimple(temporalMesh);// first do simple subdivision ...
-                        this.subdivideCatmullClark(temporalMesh);// ... and then apply Catmull-Clark algorithm
-                        if (subdivideUVS) {// UV's can be subdivided only for Catmull-Clark subdivision algorithm
-                            this.subdivideUVs(temporalMesh);
-                        }
-                    }
-                } else {
-                    for (int i = 0; i < levels; ++i) {
-                        this.subdivideSimple(temporalMesh);
-                    }
-                }
-            } else {
-                LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-            }
-        }
-    }
-
-    /**
-     * Catmull-Clark subdivision. It assumes that the mesh was already simple-subdivided.
-     * @param temporalMesh
-     *            the mesh whose vertices will be transformed to form Catmull-Clark subdivision
-     */
-    private void subdivideCatmullClark(TemporalMesh temporalMesh) {
-        Set<Integer> boundaryVertices = new HashSet<Integer>();
-        for (Edge edge : temporalMesh.getEdges()) {
-            if (!edge.isInFace()) {
-                boundaryVertices.add(edge.getFirstIndex());
-                boundaryVertices.add(edge.getSecondIndex());
-            } else {
-                if (temporalMesh.isBoundary(edge.getFirstIndex())) {
-                    boundaryVertices.add(edge.getFirstIndex());
-                }
-                if (temporalMesh.isBoundary(edge.getSecondIndex())) {
-                    boundaryVertices.add(edge.getSecondIndex());
-                }
-            }
-        }
-
-        List<CreasePoint> creasePoints = new ArrayList<CreasePoint>(temporalMesh.getVertexCount());
-        for (int i = 0; i < temporalMesh.getVertexCount(); ++i) {
-            // finding adjacent edges that were created by dividing original edges
-            List<Edge> adjacentOriginalEdges = new ArrayList<Edge>();
-            Collection<Edge> adjacentEdges = temporalMesh.getAdjacentEdges(i);
-            if(adjacentEdges != null) {// this can be null if a vertex with index 'i' is not connected to any face nor edge
-                for (Edge edge : temporalMesh.getAdjacentEdges(i)) {
-                    if (verticesOnOriginalEdges.contains(edge.getFirstIndex()) || verticesOnOriginalEdges.contains(edge.getSecondIndex())) {
-                        adjacentOriginalEdges.add(edge);
-                    }
-                }
-                
-                creasePoints.add(new CreasePoint(i, boundaryVertices.contains(i), adjacentOriginalEdges, temporalMesh));
-            } else {
-                creasePoints.add(null);//the count of crease points must be equal to vertex count; otherwise we'll get IndexOutofBoundsException later
-            }
-        }
-
-        Vector3f[] averageVert = new Vector3f[temporalMesh.getVertexCount()];
-        int[] averageCount = new int[temporalMesh.getVertexCount()];
-
-        for (Face face : temporalMesh.getFaces()) {
-            Vector3f centroid = face.computeCentroid();
-
-            for (Integer index : face.getIndexes()) {
-                if (boundaryVertices.contains(index)) {
-                    Edge edge = this.findEdge(temporalMesh, index, face.getIndexes().getNextIndex(index));
-                    if (temporalMesh.isBoundary(edge)) {
-                        averageVert[index] = averageVert[index] == null ? edge.computeCentroid() : averageVert[index].addLocal(edge.computeCentroid());
-                        averageCount[index] += 1;
-                    }
-                    edge = this.findEdge(temporalMesh, face.getIndexes().getPreviousIndex(index), index);
-                    if (temporalMesh.isBoundary(edge)) {
-                        averageVert[index] = averageVert[index] == null ? edge.computeCentroid() : averageVert[index].addLocal(edge.computeCentroid());
-                        averageCount[index] += 1;
-                    }
-                } else {
-                    averageVert[index] = averageVert[index] == null ? centroid.clone() : averageVert[index].addLocal(centroid);
-                    averageCount[index] += 1;
-                }
-            }
-        }
-        for (Edge edge : temporalMesh.getEdges()) {
-            if (!edge.isInFace()) {
-                Vector3f centroid = temporalMesh.getVertices().get(edge.getFirstIndex()).add(temporalMesh.getVertices().get(edge.getSecondIndex())).divideLocal(2);
-
-                averageVert[edge.getFirstIndex()] = averageVert[edge.getFirstIndex()] == null ? centroid.clone() : averageVert[edge.getFirstIndex()].addLocal(centroid);
-                averageVert[edge.getSecondIndex()] = averageVert[edge.getSecondIndex()] == null ? centroid.clone() : averageVert[edge.getSecondIndex()].addLocal(centroid);
-                averageCount[edge.getFirstIndex()] += 1;
-                averageCount[edge.getSecondIndex()] += 1;
-            }
-        }
-
-        for (int i = 0; i < averageVert.length; ++i) {
-            if(averageVert[i] != null && averageCount[i] > 0) {
-                Vector3f v = temporalMesh.getVertices().get(i);
-                averageVert[i].divideLocal(averageCount[i]);
-
-                // computing translation vector
-                Vector3f t = averageVert[i].subtract(v);
-                if (!boundaryVertices.contains(i)) {
-                    t.multLocal(4 / (float) averageCount[i]);
-                }
-
-                // moving the vertex
-                v.addLocal(t);
-
-                // applying crease weight if necessary
-                CreasePoint creasePoint = creasePoints.get(i);
-                if (creasePoint.getTarget() != null && creasePoint.getWeight() != 0) {
-                    t = creasePoint.getTarget().subtractLocal(v).multLocal(creasePoint.getWeight());
-                    v.addLocal(t);
-                }
-            }
-        }
-    }
-
-    /**
-     * The method performs a simple subdivision of the mesh.
-     * 
-     * @param temporalMesh
-     *            the mesh to be subdivided
-     */
-    private void subdivideSimple(TemporalMesh temporalMesh) {
-        Map<Edge, Integer> edgePoints = new HashMap<Edge, Integer>();
-        Map<Face, Integer> facePoints = new HashMap<Face, Integer>();
-        Set<Face> newFaces = new LinkedHashSet<Face>();
-        Set<Edge> newEdges = new LinkedHashSet<Edge>(temporalMesh.getEdges().size() * 4);
-
-        int originalFacesCount = temporalMesh.getFaces().size();
-
-        List<Map<String, Float>> vertexGroups = temporalMesh.getVertexGroups();
-        // the result vertex array will have verts in the following order [[original_verts], [face_verts], [edge_verts]]
-        List<Vector3f> vertices = temporalMesh.getVertices();
-        List<Vector3f> edgeVertices = new ArrayList<Vector3f>();
-        List<Vector3f> faceVertices = new ArrayList<Vector3f>();
-        // the same goes for normals
-        List<Vector3f> normals = temporalMesh.getNormals();
-        List<Vector3f> edgeNormals = new ArrayList<Vector3f>();
-        List<Vector3f> faceNormals = new ArrayList<Vector3f>();
-
-        List<Face> faces = temporalMesh.getFaces();
-        for (Face face : faces) {
-            Map<String, List<Vector2f>> uvSets = face.getUvSets();
-
-            Vector3f facePoint = face.computeCentroid();
-            Integer facePointIndex = vertices.size() + faceVertices.size();
-            facePoints.put(face, facePointIndex);
-            faceVertices.add(facePoint);
-            faceNormals.add(this.computeFaceNormal(face));
-            Map<String, Vector2f> faceUV = this.computeFaceUVs(face);
-            byte[] faceVertexColor = this.computeFaceVertexColor(face);
-            Map<String, Float> faceVertexGroups = this.computeFaceVertexGroups(face);
-            if (vertexGroups.size() > 0) {
-                vertexGroups.add(faceVertexGroups);
-            }
-
-            for (int i = 0; i < face.getIndexes().size(); ++i) {
-                int vIndex = face.getIndexes().get(i);
-                int vPrevIndex = i == 0 ? face.getIndexes().get(face.getIndexes().size() - 1) : face.getIndexes().get(i - 1);
-                int vNextIndex = i == face.getIndexes().size() - 1 ? face.getIndexes().get(0) : face.getIndexes().get(i + 1);
-
-                Edge prevEdge = this.findEdge(temporalMesh, vPrevIndex, vIndex);
-                Edge nextEdge = this.findEdge(temporalMesh, vIndex, vNextIndex);
-                int vPrevEdgeVertIndex = edgePoints.containsKey(prevEdge) ? edgePoints.get(prevEdge) : -1;
-                int vNextEdgeVertIndex = edgePoints.containsKey(nextEdge) ? edgePoints.get(nextEdge) : -1;
-
-                Vector3f v = temporalMesh.getVertices().get(vIndex);
-                if (vPrevEdgeVertIndex < 0) {
-                    vPrevEdgeVertIndex = vertices.size() + originalFacesCount + edgeVertices.size();
-                    verticesOnOriginalEdges.add(vPrevEdgeVertIndex);
-                    edgeVertices.add(vertices.get(vPrevIndex).add(v).divideLocal(2));
-                    edgeNormals.add(normals.get(vPrevIndex).add(normals.get(vIndex)).normalizeLocal());
-                    edgePoints.put(prevEdge, vPrevEdgeVertIndex);
-                    if (vertexGroups.size() > 0) {
-                        vertexGroups.add(this.interpolateVertexGroups(Arrays.asList(vertexGroups.get(vPrevIndex), vertexGroups.get(vIndex))));
-                    }
-                }
-                if (vNextEdgeVertIndex < 0) {
-                    vNextEdgeVertIndex = vertices.size() + originalFacesCount + edgeVertices.size();
-                    verticesOnOriginalEdges.add(vNextEdgeVertIndex);
-                    edgeVertices.add(vertices.get(vNextIndex).add(v).divideLocal(2));
-                    edgeNormals.add(normals.get(vNextIndex).add(normals.get(vIndex)).normalizeLocal());
-                    edgePoints.put(nextEdge, vNextEdgeVertIndex);
-                    if (vertexGroups.size() > 0) {
-                        vertexGroups.add(this.interpolateVertexGroups(Arrays.asList(vertexGroups.get(vNextIndex), vertexGroups.get(vIndex))));
-                    }
-                }
-
-                Integer[] indexes = new Integer[] { vIndex, vNextEdgeVertIndex, facePointIndex, vPrevEdgeVertIndex };
-
-                Map<String, List<Vector2f>> newUVSets = null;
-                if (uvSets != null) {
-                    newUVSets = new HashMap<String, List<Vector2f>>(uvSets.size());
-                    for (Entry<String, List<Vector2f>> uvset : uvSets.entrySet()) {
-                        int indexOfvIndex = i;
-                        int indexOfvPrevIndex = face.getIndexes().indexOf(vPrevIndex);
-                        int indexOfvNextIndex = face.getIndexes().indexOf(vNextIndex);
-
-                        Vector2f uv1 = uvset.getValue().get(indexOfvIndex);
-                        Vector2f uv2 = uvset.getValue().get(indexOfvNextIndex).add(uv1).divideLocal(2);
-                        Vector2f uv3 = faceUV.get(uvset.getKey());
-                        Vector2f uv4 = uvset.getValue().get(indexOfvPrevIndex).add(uv1).divideLocal(2);
-                        List<Vector2f> uvList = Arrays.asList(uv1, uv2, uv3, uv4);
-                        newUVSets.put(uvset.getKey(), new ArrayList<Vector2f>(uvList));
-                    }
-                }
-
-                List<byte[]> vertexColors = null;
-                if (face.getVertexColors() != null) {
-
-                    int indexOfvIndex = i;
-                    int indexOfvPrevIndex = face.getIndexes().indexOf(vPrevIndex);
-                    int indexOfvNextIndex = face.getIndexes().indexOf(vNextIndex);
-
-                    byte[] vCol1 = face.getVertexColors().get(indexOfvIndex);
-                    byte[] vCol2 = this.interpolateVertexColors(face.getVertexColors().get(indexOfvNextIndex), vCol1);
-                    byte[] vCol3 = faceVertexColor;
-                    byte[] vCol4 = this.interpolateVertexColors(face.getVertexColors().get(indexOfvPrevIndex), vCol1);
-                    vertexColors = new ArrayList<byte[]>(Arrays.asList(vCol1, vCol2, vCol3, vCol4));
-                }
-
-                newFaces.add(new Face(indexes, face.isSmooth(), face.getMaterialNumber(), newUVSets, vertexColors, temporalMesh));
-
-                newEdges.add(new Edge(vIndex, vNextEdgeVertIndex, nextEdge.getCrease(), true, temporalMesh));
-                newEdges.add(new Edge(vNextEdgeVertIndex, facePointIndex, 0, true, temporalMesh));
-                newEdges.add(new Edge(facePointIndex, vPrevEdgeVertIndex, 0, true, temporalMesh));
-                newEdges.add(new Edge(vPrevEdgeVertIndex, vIndex, prevEdge.getCrease(), true, temporalMesh));
-            }
-        }
-
-        vertices.addAll(faceVertices);
-        vertices.addAll(edgeVertices);
-        normals.addAll(faceNormals);
-        normals.addAll(edgeNormals);
-
-        for (Edge edge : temporalMesh.getEdges()) {
-            if (!edge.isInFace()) {
-                int newVertexIndex = vertices.size();
-                vertices.add(vertices.get(edge.getFirstIndex()).add(vertices.get(edge.getSecondIndex())).divideLocal(2));
-                normals.add(normals.get(edge.getFirstIndex()).add(normals.get(edge.getSecondIndex())).normalizeLocal());
-
-                newEdges.add(new Edge(edge.getFirstIndex(), newVertexIndex, edge.getCrease(), false, temporalMesh));
-                newEdges.add(new Edge(newVertexIndex, edge.getSecondIndex(), edge.getCrease(), false, temporalMesh));
-                verticesOnOriginalEdges.add(newVertexIndex);
-            }
-        }
-
-        temporalMesh.getFaces().clear();
-        temporalMesh.getFaces().addAll(newFaces);
-        temporalMesh.getEdges().clear();
-        temporalMesh.getEdges().addAll(newEdges);
-
-        temporalMesh.rebuildIndexesMappings();
-    }
-
-    /**
-     * The method subdivides mesh's UV coordinates. It actually performs only Catmull-Clark modifications because if any UV's are present then they are
-     * automatically subdivided by the simple algorithm.
-     * @param temporalMesh
-     *            the mesh whose UV coordinates will be applied Catmull-Clark algorithm
-     */
-    private void subdivideUVs(TemporalMesh temporalMesh) {
-        List<Face> faces = temporalMesh.getFaces();
-        Map<String, UvCoordsSubdivideTemporalMesh> subdividedUVS = new HashMap<String, UvCoordsSubdivideTemporalMesh>();
-        for (Face face : faces) {
-            if (face.getUvSets() != null) {
-                for (Entry<String, List<Vector2f>> uvset : face.getUvSets().entrySet()) {
-                    UvCoordsSubdivideTemporalMesh uvCoordsSubdivideTemporalMesh = subdividedUVS.get(uvset.getKey());
-                    if (uvCoordsSubdivideTemporalMesh == null) {
-                        try {
-                            uvCoordsSubdivideTemporalMesh = new UvCoordsSubdivideTemporalMesh(temporalMesh.getBlenderContext());
-                        } catch (BlenderFileException e) {
-                            assert false : "Something went really wrong! The UvCoordsSubdivideTemporalMesh class should NOT throw exceptions here!";
-                        }
-                        subdividedUVS.put(uvset.getKey(), uvCoordsSubdivideTemporalMesh);
-                    }
-                    uvCoordsSubdivideTemporalMesh.addFace(uvset.getValue());
-                }
-            }
-        }
-
-        for (Entry<String, UvCoordsSubdivideTemporalMesh> entry : subdividedUVS.entrySet()) {
-            entry.getValue().rebuildIndexesMappings();
-            this.subdivideCatmullClark(entry.getValue());
-
-            for (int i = 0; i < faces.size(); ++i) {
-                List<Vector2f> uvs = faces.get(i).getUvSets().get(entry.getKey());
-                if (uvs != null) {
-                    uvs.clear();
-                    uvs.addAll(entry.getValue().faceToUVs(i));
-                }
-            }
-        }
-    }
-
-    /**
-     * The method computes the face's normal vector.
-     * @param face
-     *            the face of the mesh
-     * @return face's normal vector
-     */
-    private Vector3f computeFaceNormal(Face face) {
-        Vector3f result = new Vector3f();
-        for (Integer index : face.getIndexes()) {
-            result.addLocal(face.getTemporalMesh().getNormals().get(index));
-        }
-        result.divideLocal(face.getIndexes().size());
-        return result;
-    }
-
-    /**
-     * The method computes the UV coordinates of the face middle point.
-     * @param face
-     *            the face of the mesh
-     * @return a map whose key is the name of the UV set and value is the UV coordinate of the face's middle point
-     */
-    private Map<String, Vector2f> computeFaceUVs(Face face) {
-        Map<String, Vector2f> result = null;
-
-        Map<String, List<Vector2f>> uvSets = face.getUvSets();
-        if (uvSets != null && uvSets.size() > 0) {
-            result = new HashMap<String, Vector2f>(uvSets.size());
-
-            for (Entry<String, List<Vector2f>> entry : uvSets.entrySet()) {
-                Vector2f faceUV = new Vector2f();
-                for (Vector2f uv : entry.getValue()) {
-                    faceUV.addLocal(uv);
-                }
-                faceUV.divideLocal(entry.getValue().size());
-                result.put(entry.getKey(), faceUV);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * The mesh interpolates the values of vertex groups weights for new vertices.
-     * @param vertexGroups
-     *            the vertex groups
-     * @return interpolated weights of given vertex groups' weights
-     */
-    private Map<String, Float> interpolateVertexGroups(List<Map<String, Float>> vertexGroups) {
-        Map<String, Float> weightSums = new HashMap<String, Float>();
-        if (vertexGroups.size() > 0) {
-            for (Map<String, Float> vGroup : vertexGroups) {
-                for (Entry<String, Float> entry : vGroup.entrySet()) {
-                    if (weightSums.containsKey(entry.getKey())) {
-                        weightSums.put(entry.getKey(), weightSums.get(entry.getKey()) + entry.getValue());
-                    } else {
-                        weightSums.put(entry.getKey(), entry.getValue());
-                    }
-                }
-            }
-        }
-
-        Map<String, Float> result = new HashMap<String, Float>(weightSums.size());
-        for (Entry<String, Float> entry : weightSums.entrySet()) {
-            result.put(entry.getKey(), entry.getValue() / vertexGroups.size());
-        }
-
-        return result;
-    }
-
-    /**
-     * The method computes the vertex groups values for face's middle point.
-     * @param face
-     *            the face of the mesh
-     * @return face's middle point interpolated vertex groups' weights
-     */
-    private Map<String, Float> computeFaceVertexGroups(Face face) {
-        if (face.getTemporalMesh().getVertexGroups().size() > 0) {
-            List<Map<String, Float>> vertexGroups = new ArrayList<Map<String, Float>>(face.getIndexes().size());
-            for (Integer index : face.getIndexes()) {
-                vertexGroups.add(face.getTemporalMesh().getVertexGroups().get(index));
-            }
-            return this.interpolateVertexGroups(vertexGroups);
-        }
-        return new HashMap<String, Float>();
-    }
-
-    /**
-     * The method computes face's middle point vertex color.
-     * @param face
-     *            the face of the mesh
-     * @return face's middle point vertex color
-     */
-    private byte[] computeFaceVertexColor(Face face) {
-        if (face.getVertexColors() != null) {
-            return this.interpolateVertexColors(face.getVertexColors().toArray(new byte[face.getVertexColors().size()][]));
-        }
-        return null;
-    }
-
-    /**
-     * The method computes the average value for the given vertex colors.
-     * @param colors
-     *            the vertex colors
-     * @return vertex colors' average value
-     */
-    private byte[] interpolateVertexColors(byte[]... colors) {
-        TexturePixel pixel = new TexturePixel();
-        TexturePixel temp = new TexturePixel();
-        for (int i = 0; i < colors.length; ++i) {
-            temp.fromARGB8(colors[i][3], colors[i][0], colors[i][1], colors[i][2]);
-            pixel.add(temp);
-        }
-        pixel.divide(colors.length);
-        byte[] result = new byte[4];
-        pixel.toRGBA8(result);
-        return result;
-    }
-
-    /**
-     * The method finds an edge between the given vertices in the mesh.
-     * @param temporalMesh
-     *            the mesh
-     * @param index1
-     *            first index of the edge
-     * @param index2
-     *            second index of the edge
-     * @return found edge or null
-     */
-    private Edge findEdge(TemporalMesh temporalMesh, int index1, int index2) {
-        for (Edge edge : temporalMesh.getEdges()) {
-            if (edge.getFirstIndex() == index1 && edge.getSecondIndex() == index2 || edge.getFirstIndex() == index2 && edge.getSecondIndex() == index1) {
-                return edge;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * This is a helper class for UV coordinates subdivision. UV's form a mesh that is being applied the same algorithms as a regular mesh.
-     * This way one code handles two issues. After applying Catmull-Clark algorithm the UV-mesh is transformed back into UV coordinates.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class UvCoordsSubdivideTemporalMesh extends TemporalMesh {
-        private static final Vector3f NORMAL = new Vector3f(0, 0, 1);
-
-        public UvCoordsSubdivideTemporalMesh(BlenderContext blenderContext) throws BlenderFileException {
-            super(null, blenderContext, false);
-        }
-
-        /**
-         * Adds a UV-face to the mesh.
-         * @param uvs
-         *            the UV coordinates
-         */
-        public void addFace(List<Vector2f> uvs) {
-            Integer[] indexes = new Integer[uvs.size()];
-            int i = 0;
-
-            for (Vector2f uv : uvs) {
-                Vector3f v = new Vector3f(uv.x, uv.y, 0);
-                int index = vertices.indexOf(v);
-                if (index >= 0) {
-                    indexes[i++] = index;
-                } else {
-                    indexes[i++] = vertices.size();
-                    vertices.add(v);
-                    normals.add(NORMAL);
-                }
-            }
-            faces.add(new Face(indexes, false, 0, null, null, this));
-            for (i = 1; i < indexes.length; ++i) {
-                edges.add(new Edge(indexes[i - 1], indexes[i], 0, true, this));
-            }
-            edges.add(new Edge(indexes[indexes.length - 1], indexes[0], 0, true, this));
-        }
-
-        /**
-         * Converts the mesh back into UV coordinates for the given face.
-         * @param faceIndex
-         *            the index of the face
-         * @return UV coordinates
-         */
-        public List<Vector2f> faceToUVs(int faceIndex) {
-            Face face = faces.get(faceIndex);
-            List<Vector2f> result = new ArrayList<Vector2f>(face.getIndexes().size());
-            for (Integer index : face.getIndexes()) {
-                Vector3f v = vertices.get(index);
-                result.add(new Vector2f(v.x, v.y));
-            }
-            return result;
-        }
-    }
-
-    /**
-     * A point computed for each vertex before applying CC subdivision and after simple subdivision.
-     * This class has a target where the vertices will be drawn to with a proper strength (value from 0 to 1).
-     * 
-     * The algorithm of computing the target point was made by observing how blender behaves.
-     * If a vertex has one or less creased edges (means edges that have non zero crease value) the target will not exist.
-     * If a vertex is a border vertex and has two creased edges - the target will be the original simple subdivided vertex.
-     * If a vertex is not a border vertex and have two creased edges - then it will be drawned to the plane defined by those
-     * two edges.
-     * If a vertex has 3 or more creased edges it will be drawn to its original vertex before CC subdivision with average strength
-     * computed from edges' crease values.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class CreasePoint {
-        private Vector3f target = new Vector3f();
-        private float    weight;
-        private int      index;
-
-        public CreasePoint(int index, boolean borderIndex, List<Edge> creaseEdges, TemporalMesh temporalMesh) {
-            this.index = index;
-            if (creaseEdges == null || creaseEdges.size() <= 1) {
-                target = null;// crease is used when vertex belongs to at least 2 creased edges
-            } else {
-                int creasedEdgesCount = 0;
-                for (Edge edge : creaseEdges) {
-                    if (edge.getCrease() > 0) {
-                        ++creasedEdgesCount;
-                        weight += edge.getCrease();
-                        target.addLocal(temporalMesh.getVertices().get(edge.getOtherIndex(index)));
-                    }
-                }
-
-                if (creasedEdgesCount <= 1) {
-                    target = null;// crease is used when vertex belongs to at least 2 creased edges
-                } else if (creasedEdgesCount == 2) {
-                    if (borderIndex) {
-                        target.set(temporalMesh.getVertices().get(index));
-                    } else {
-                        target.addLocal(temporalMesh.getVertices().get(index)).divideLocal(creasedEdgesCount + 1);
-                    }
-                } else {
-                    target.set(temporalMesh.getVertices().get(index));
-                }
-                if (creasedEdgesCount > 0) {
-                    weight /= creasedEdgesCount;
-                }
-            }
-        }
-
-        public Vector3f getTarget() {
-            return target;
-        }
-
-        public float getWeight() {
-            return weight;
-        }
-
-        @Override
-        public String toString() {
-            return "CreasePoint [index = " + index + ", target=" + target + ", weight=" + weight + "]";
-        }
-    }
-}

+ 0 - 54
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/TriangulateModifier.java

@@ -1,54 +0,0 @@
-package com.jme3.scene.plugins.blender.modifiers;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.Node;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.BlenderFileException;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-
-/**
- * The triangulation modifier. It does not take any settings into account so if the result is different than
- * in blender then please apply the modifier before importing.
- * 
- * @author Marcin Roguski
- */
-public class TriangulateModifier extends Modifier {
-    private static final Logger LOGGER = Logger.getLogger(TriangulateModifier.class.getName());
-
-    /**
-     * 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 blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             this exception is thrown when the blender file is somehow
-     *             corrupted
-     */
-    public TriangulateModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
-        if (this.validate(modifierStructure, blenderContext)) {
-            LOGGER.warning("Triangulation modifier does not take modifier options into account. If triangulation result is different" + " than the model in blender please apply the modifier before importing!");
-        }
-    }
-
-    @Override
-    public void apply(Node node, BlenderContext blenderContext) {
-        if (invalid) {
-            LOGGER.log(Level.WARNING, "Triangulate modifier is invalid! Cannot be applied to: {0}", node.getName());
-        }
-        TemporalMesh temporalMesh = this.getTemporalMesh(node);
-        if (temporalMesh != null) {
-            LOGGER.log(Level.FINE, "Applying triangulation modifier to: {0}", temporalMesh);
-            temporalMesh.triangulate();
-        } else {
-            LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
-        }
-    }
-}

+ 0 - 520
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/objects/ObjectHelper.java

@@ -1,520 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.objects;
-
-import java.nio.Buffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.nio.ShortBuffer;
-import java.util.Collection;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.light.Light;
-import com.jme3.math.FastMath;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Transform;
-import com.jme3.math.Vector3f;
-import com.jme3.renderer.Camera;
-import com.jme3.scene.CameraNode;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.LightNode;
-import com.jme3.scene.Mesh.Mode;
-import com.jme3.scene.Node;
-import com.jme3.scene.Spatial;
-import com.jme3.scene.Spatial.CullHint;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.animations.AnimationHelper;
-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.file.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.meshes.TemporalMesh;
-import com.jme3.scene.plugins.blender.modifiers.Modifier;
-import com.jme3.scene.plugins.blender.modifiers.ModifierHelper;
-import com.jme3.util.TempVars;
-
-/**
- * A class that is used in object calculations.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class ObjectHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER               = Logger.getLogger(ObjectHelper.class.getName());
-
-    public static final String  OMA_MARKER           = "oma";
-    public static final String  ARMATURE_NODE_MARKER = "armature-node";
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public ObjectHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * This method reads the given structure and createn an object that
-     * represents the data.
-     * 
-     * @param objectStructure
-     *            the object's structure
-     * @param blenderContext
-     *            the blender context
-     * @return blener's object representation or null if its type is excluded from loading
-     * @throws BlenderFileException
-     *             an exception is thrown when the given data is inapropriate
-     */
-    public Object toObject(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
-        Object loadedResult = blenderContext.getLoadedFeature(objectStructure.getOldMemoryAddress(), LoadedDataType.FEATURE);
-        if (loadedResult != null) {
-            return loadedResult;
-        }
-
-        LOGGER.fine("Loading blender object.");
-        if ("ID".equals(objectStructure.getType())) {
-            Node object = (Node) this.loadLibrary(objectStructure);
-            if (object.getParent() != null) {
-                LOGGER.log(Level.FINEST, "Detaching object {0}, loaded from external file, from its parent.", object);
-                object.getParent().detachChild(object);
-            }
-            return object;
-        }
-        int type = ((Number) objectStructure.getFieldValue("type")).intValue();
-        ObjectType objectType = ObjectType.valueOf(type);
-        LOGGER.log(Level.FINE, "Type of the object: {0}.", objectType);
-
-        int lay = ((Number) objectStructure.getFieldValue("lay")).intValue();
-        if ((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
-            LOGGER.fine("The layer this object is located in is not included in loading.");
-            return null;
-        }
-
-        blenderContext.pushParent(objectStructure);
-        String name = objectStructure.getName();
-        LOGGER.log(Level.FINE, "Loading obejct: {0}", name);
-
-        int restrictflag = ((Number) objectStructure.getFieldValue("restrictflag")).intValue();
-        boolean visible = (restrictflag & 0x01) != 0;
-
-        Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
-        Object parent = blenderContext.getLoadedFeature(pParent.getOldMemoryAddress(), LoadedDataType.FEATURE);
-        if (parent == null && pParent.isNotNull()) {
-            Structure parentStructure = pParent.fetchData().get(0);
-            parent = this.toObject(parentStructure, blenderContext);
-        }
-
-        Transform t = this.getTransformation(objectStructure, blenderContext);
-        LOGGER.log(Level.FINE, "Importing object of type: {0}", objectType);
-        Node result = null;
-        try {
-            switch (objectType) {
-                case LATTICE:
-                case METABALL:
-                case TEXT:
-                case WAVE:
-                    LOGGER.log(Level.WARNING, "{0} type is not supported but the node will be returned in order to keep parent - child relationship.", objectType);
-                case EMPTY:
-                case ARMATURE:
-                    // need to use an empty node to properly create
-                    // parent-children relationships between nodes
-                    result = new Node(name);
-                    break;
-                case MESH:
-                    result = new Node(name);
-                    MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
-                    Pointer pMesh = (Pointer) objectStructure.getFieldValue("data");
-                    List<Structure> meshesArray = pMesh.fetchData();
-                    TemporalMesh temporalMesh = meshHelper.toTemporalMesh(meshesArray.get(0), blenderContext);
-                    if (temporalMesh != null) {
-                        result.attachChild(temporalMesh);
-                    }
-                    break;
-                case SURF:
-                case CURVE:
-                    result = new Node(name);
-                    Pointer pCurve = (Pointer) objectStructure.getFieldValue("data");
-                    if (pCurve.isNotNull()) {
-                        CurvesHelper curvesHelper = blenderContext.getHelper(CurvesHelper.class);
-                        Structure curveData = pCurve.fetchData().get(0);
-                        TemporalMesh curvesTemporalMesh = curvesHelper.toCurve(curveData, blenderContext);
-                        if (curvesTemporalMesh != null) {
-                            result.attachChild(curvesTemporalMesh);
-                        }
-                    }
-                    break;
-                case LAMP:
-                    Pointer pLamp = (Pointer) objectStructure.getFieldValue("data");
-                    if (pLamp.isNotNull()) {
-                        LightHelper lightHelper = blenderContext.getHelper(LightHelper.class);
-                        List<Structure> lampsArray = pLamp.fetchData();
-                        Light light = lightHelper.toLight(lampsArray.get(0), blenderContext);
-                        if (light == null) {
-                            // probably some light type is not supported, just create a node so that we can maintain child-parent relationship for nodes
-                            result = new Node(name);
-                        } else {
-                            result = new LightNode(name, light);
-                        }
-                    }
-                    break;
-                case CAMERA:
-                    Pointer pCamera = (Pointer) objectStructure.getFieldValue("data");
-                    if (pCamera.isNotNull()) {
-                        CameraHelper cameraHelper = blenderContext.getHelper(CameraHelper.class);
-                        List<Structure> camerasArray = pCamera.fetchData();
-                        Camera camera = cameraHelper.toCamera(camerasArray.get(0), blenderContext);
-                        if (camera == null) {
-                            // just create a node so that we can maintain child-parent relationship for nodes
-                            result = new Node(name);
-                        } else {
-                            result = new CameraNode(name, camera);
-                        }
-                    }
-                    break;
-                default:
-                    LOGGER.log(Level.WARNING, "Unsupported object type: {0}", type);
-            }
-
-            if (result != null) {
-                LOGGER.fine("Storing loaded feature in blender context and applying markers (those will be removed before the final result is released).");
-                Long oma = objectStructure.getOldMemoryAddress();
-                blenderContext.addLoadedFeatures(oma, LoadedDataType.STRUCTURE, objectStructure);
-                blenderContext.addLoadedFeatures(oma, LoadedDataType.FEATURE, result);
-
-                blenderContext.addMarker(OMA_MARKER, result, objectStructure.getOldMemoryAddress());
-                if (objectType == ObjectType.ARMATURE) {
-                    blenderContext.addMarker(ARMATURE_NODE_MARKER, result, Boolean.TRUE);
-                }
-
-                result.setLocalTransform(t);
-                result.setCullHint(visible ? CullHint.Always : CullHint.Inherit);
-                if (parent instanceof Node) {
-                    ((Node) parent).attachChild(result);
-                }
-
-                LOGGER.fine("Reading and applying object's modifiers.");
-                ModifierHelper modifierHelper = blenderContext.getHelper(ModifierHelper.class);
-                Collection<Modifier> modifiers = modifierHelper.readModifiers(objectStructure, blenderContext);
-                for (Modifier modifier : modifiers) {
-                    modifier.apply(result, blenderContext);
-                }
-
-                if (result.getChildren() != null && result.getChildren().size() > 0) {
-                    if (result.getChildren().size() == 1 && result.getChild(0) instanceof TemporalMesh) {
-                        LOGGER.fine("Converting temporal mesh into jme geometries.");
-                        ((TemporalMesh) result.getChild(0)).toGeometries();
-                    }
-
-                    LOGGER.fine("Applying proper scale to the geometries.");
-                    for (Spatial child : result.getChildren()) {
-                        if (child instanceof Geometry) {
-                            this.flipMeshIfRequired((Geometry) child, child.getWorldScale());
-                        }
-                    }
-                }
-
-                // I prefer do compute bounding box here than read it from the file
-                result.updateModelBound();
-
-                LOGGER.fine("Applying animations to the object if such are defined.");
-                AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
-                animationHelper.applyAnimations(result, blenderContext.getBlenderKey().getAnimationMatchMethod());
-
-                LOGGER.fine("Loading constraints connected with this object.");
-                ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
-                constraintHelper.loadConstraints(objectStructure, blenderContext);
-
-                LOGGER.fine("Loading custom properties.");
-                if (blenderContext.getBlenderKey().isLoadObjectProperties()) {
-                    Properties properties = this.loadProperties(objectStructure, blenderContext);
-                    // the loaded property is a group property, so we need to get
-                    // each value and set it to Spatial
-                    if (properties != null && properties.getValue() != null) {
-                        this.applyProperties(result, properties);
-                    }
-                }
-            }
-        } finally {
-            blenderContext.popParent();
-        }
-        return result;
-    }
-
-    /**
-     * The method flips the mesh if the scale is mirroring it. Mirroring scale has either 1 or all 3 factors negative.
-     * If two factors are negative then there is no mirroring because a rotation and translation can be found that will
-     * lead to the same transform when all scales are positive.
-     * 
-     * @param geometry
-     *            the geometry that is being flipped if necessary
-     * @param scale
-     *            the scale vector of the given geometry
-     */
-    private void flipMeshIfRequired(Geometry geometry, Vector3f scale) {
-        float s = scale.x * scale.y * scale.z;
-
-        if (s < 0 && geometry.getMesh() != null) {// negative s means that the scale is mirroring the object
-            FloatBuffer normals = geometry.getMesh().getFloatBuffer(Type.Normal);
-            if (normals != null) {
-                for (int i = 0; i < normals.limit(); i += 3) {
-                    if (scale.x < 0) {
-                        normals.put(i, -normals.get(i));
-                    }
-                    if (scale.y < 0) {
-                        normals.put(i + 1, -normals.get(i + 1));
-                    }
-                    if (scale.z < 0) {
-                        normals.put(i + 2, -normals.get(i + 2));
-                    }
-                }
-            }
-
-            if (geometry.getMesh().getMode() == Mode.Triangles) {// there is no need to flip the indexes for lines and points
-                LOGGER.finer("Flipping index order in triangle mesh.");
-                Buffer indexBuffer = geometry.getMesh().getBuffer(Type.Index).getData();
-                for (int i = 0; i < indexBuffer.limit(); i += 3) {
-                    if (indexBuffer instanceof ShortBuffer) {
-                        short index = ((ShortBuffer) indexBuffer).get(i + 1);
-                        ((ShortBuffer) indexBuffer).put(i + 1, ((ShortBuffer) indexBuffer).get(i + 2));
-                        ((ShortBuffer) indexBuffer).put(i + 2, index);
-                    } else {
-                        int index = ((IntBuffer) indexBuffer).get(i + 1);
-                        ((IntBuffer) indexBuffer).put(i + 1, ((IntBuffer) indexBuffer).get(i + 2));
-                        ((IntBuffer) indexBuffer).put(i + 2, index);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if the first given OMA points to a parent of the second one.
-     * The parent need not to be the direct one. This method should be called when we are sure
-     * that both of the features are alred loaded because it does not check it.
-     * The OMA's should point to a spatials, otherwise the function will throw ClassCastException.
-     * @param supposedParentOMA
-     *            the OMA of the node that we suppose might be a parent of the second one
-     * @param spatialOMA
-     *            the OMA of the scene's node
-     * @return <b>true</b> if the first given OMA points to a parent of the second one and <b>false</b> otherwise
-     */
-    public boolean isParent(Long supposedParentOMA, Long spatialOMA) {
-        Spatial supposedParent = (Spatial) blenderContext.getLoadedFeature(supposedParentOMA, LoadedDataType.FEATURE);
-        Spatial spatial = (Spatial) blenderContext.getLoadedFeature(spatialOMA, LoadedDataType.FEATURE);
-
-        Spatial parent = spatial.getParent();
-        while (parent != null) {
-            if (parent.equals(supposedParent)) {
-                return true;
-            }
-            parent = parent.getParent();
-        }
-        return false;
-    }
-
-    /**
-     * This method calculates local transformation for the object. Parentage is
-     * taken under consideration.
-     * 
-     * @param objectStructure
-     *            the object's structure
-     * @return objects transformation relative to its parent
-     */
-    public Transform getTransformation(Structure objectStructure, BlenderContext blenderContext) {
-        TempVars tempVars = TempVars.get();
-
-        Matrix4f parentInv = tempVars.tempMat4;
-        Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
-        if (pParent.isNotNull()) {
-            Structure parentObjectStructure = (Structure) blenderContext.getLoadedFeature(pParent.getOldMemoryAddress(), LoadedDataType.STRUCTURE);
-            this.getMatrix(parentObjectStructure, "obmat", fixUpAxis, parentInv).invertLocal();
-        } else {
-            parentInv.loadIdentity();
-        }
-
-        Matrix4f globalMatrix = this.getMatrix(objectStructure, "obmat", fixUpAxis, tempVars.tempMat42);
-        Matrix4f localMatrix = parentInv.multLocal(globalMatrix);
-
-        this.getSizeSignums(objectStructure, tempVars.vect1);
-
-        localMatrix.toTranslationVector(tempVars.vect2);
-        localMatrix.toRotationQuat(tempVars.quat1);
-        localMatrix.toScaleVector(tempVars.vect3);
-
-        Transform t = new Transform(tempVars.vect2, tempVars.quat1.normalizeLocal(), tempVars.vect3.multLocal(tempVars.vect1));
-        tempVars.release();
-        return t;
-    }
-
-    /**
-     * The method gets the signs of the scale factors and stores them properly in the given vector.
-     * @param objectStructure
-     *            the object's structure
-     * @param store
-     *            the vector where the result will be stored
-     */
-    @SuppressWarnings("unchecked")
-    private void getSizeSignums(Structure objectStructure, Vector3f store) {
-        DynamicArray<Number> size = (DynamicArray<Number>) objectStructure.getFieldValue("size");
-        if (fixUpAxis) {
-            store.x = Math.signum(size.get(0).floatValue());
-            store.y = Math.signum(size.get(2).floatValue());
-            store.z = Math.signum(size.get(1).floatValue());
-        } else {
-            store.x = Math.signum(size.get(0).floatValue());
-            store.y = Math.signum(size.get(1).floatValue());
-            store.z = Math.signum(size.get(2).floatValue());
-        }
-    }
-
-    /**
-     * This method returns the matrix of a given name for the given structure.
-     * It takes up axis into consideration.
-     * 
-     * The method that moves the matrix from Z-up axis to Y-up axis space is as follows:
-     * - load the matrix directly from blender (it has the Z-up axis orientation)
-     * - switch the second and third rows in the matrix
-     * - switch the second and third column in the matrix
-     * - multiply the values in the third row by -1
-     * - multiply the values in the third column by -1
-     * 
-     * The result matrix is now in Y-up axis orientation.
-     * The procedure was discovered by experimenting but it looks like it's working :)
-     * The previous procedure transformet the loaded matrix into component (loc, rot, scale),
-     * switched several values and pu the back into the matrix.
-     * It worked fine until models with negative scale are used.
-     * The current method is not touched by that flaw.
-     * 
-     * @param structure
-     *            the structure with matrix data
-     * @param matrixName
-     *            the name of the matrix
-     * @param fixUpAxis
-     *            tells if the Y axis is a UP axis
-     * @param store
-     *            the matrix where the result will pe placed
-     * @return the required matrix
-     */
-    @SuppressWarnings("unchecked")
-    private Matrix4f getMatrix(Structure structure, String matrixName, boolean fixUpAxis, Matrix4f store) {
-        DynamicArray<Number> obmat = (DynamicArray<Number>) structure.getFieldValue(matrixName);
-        // the matrix must be square
-        int rowAndColumnSize = Math.abs((int) Math.sqrt(obmat.getTotalSize()));
-        for (int i = 0; i < rowAndColumnSize; ++i) {
-            for (int j = 0; j < rowAndColumnSize; ++j) {
-                float value = obmat.get(j, i).floatValue();
-                if (Math.abs(value) <= FastMath.FLT_EPSILON) {
-                    value = 0;
-                }
-                store.set(i, j, value);
-            }
-        }
-        if (fixUpAxis) {
-            // first switch the second and third row
-            for (int i = 0; i < 4; ++i) {
-                float temp = store.get(1, i);
-                store.set(1, i, store.get(2, i));
-                store.set(2, i, temp);
-            }
-
-            // then switch the second and third column
-            for (int i = 0; i < 4; ++i) {
-                float temp = store.get(i, 1);
-                store.set(i, 1, store.get(i, 2));
-                store.set(i, 2, temp);
-            }
-
-            // multiply the values in the third row by -1
-            store.m20 *= -1;
-            store.m21 *= -1;
-            store.m22 *= -1;
-            store.m23 *= -1;
-
-            // multiply the values in the third column by -1
-            store.m02 *= -1;
-            store.m12 *= -1;
-            store.m22 *= -1;
-            store.m32 *= -1;
-        }
-
-        return store;
-    }
-
-    /**
-     * This method returns the matrix of a given name for the given structure.
-     * It takes up axis into consideration.
-     * 
-     * @param structure
-     *            the structure with matrix data
-     * @param matrixName
-     *            the name of the matrix
-     * @param fixUpAxis
-     *            tells if the Y axis is a UP axis
-     * @return the required matrix
-     */
-    public Matrix4f getMatrix(Structure structure, String matrixName, boolean fixUpAxis) {
-        return this.getMatrix(structure, matrixName, fixUpAxis, new Matrix4f());
-    }
-
-    private static enum ObjectType {
-        EMPTY(0), MESH(1), CURVE(2), SURF(3), TEXT(4), METABALL(5), LAMP(10), CAMERA(11), WAVE(21), LATTICE(22), ARMATURE(25);
-
-        private int blenderTypeValue;
-
-        private ObjectType(int blenderTypeValue) {
-            this.blenderTypeValue = blenderTypeValue;
-        }
-
-        public static ObjectType valueOf(int blenderTypeValue) throws BlenderFileException {
-            for (ObjectType type : ObjectType.values()) {
-                if (type.blenderTypeValue == blenderTypeValue) {
-                    return type;
-                }
-            }
-            throw new BlenderFileException("Unknown type value: " + blenderTypeValue);
-        }
-    }
-}

+ 0 - 365
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/objects/Properties.java

@@ -1,365 +0,0 @@
-package com.jme3.scene.plugins.blender.objects;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * The blender object's custom properties.
- * This class is valid for all versions of blender.
- * @author Marcin Roguski (Kaelthas)
- */
-public class Properties implements Cloneable {
-    // property type
-    public static final int       IDP_STRING        = 0;
-    public static final int       IDP_INT           = 1;
-    public static final int       IDP_FLOAT         = 2;
-    public static final int       IDP_ARRAY         = 5;
-    public static final int       IDP_GROUP         = 6;
-    // public static final int IDP_ID = 7;//this is not implemented in blender (yet)
-    public static final int       IDP_DOUBLE        = 8;
-    // the following are valid for blender 2.5x+
-    public static final int       IDP_IDPARRAY      = 9;
-    public static final int       IDP_NUMTYPES      = 10;
-
-    protected static final String RNA_PROPERTY_NAME = "_RNA_UI";
-    /** Default name of the property (used if the name is not specified in blender file). */
-    protected static final String DEFAULT_NAME      = "Unnamed property";
-
-    /** The name of the property. */
-    private String                name;
-    /** The type of the property. */
-    private int                   type;
-    /** The subtype of the property. Defines the type of array's elements. */
-    private int                   subType;
-    /** The value of the property. */
-    private Object                value;
-    /** The description of the property. */
-    private String                description;
-
-    /**
-     * This method loads the property from the belnder file.
-     * @param idPropertyStructure
-     *            the ID structure constining the property
-     * @param blenderContext
-     *            the blender context
-     * @throws BlenderFileException
-     *             an exception is thrown when the belnder file is somehow invalid
-     */
-    public void load(Structure idPropertyStructure, BlenderContext blenderContext) throws BlenderFileException {
-        name = idPropertyStructure.getFieldValue("name").toString();
-        if (name == null || name.length() == 0) {
-            name = DEFAULT_NAME;
-        }
-        subType = ((Number) idPropertyStructure.getFieldValue("subtype")).intValue();
-        type = ((Number) idPropertyStructure.getFieldValue("type")).intValue();
-
-        // reading the data
-        Structure data = (Structure) idPropertyStructure.getFieldValue("data");
-        int len = ((Number) idPropertyStructure.getFieldValue("len")).intValue();
-        switch (type) {
-            case IDP_STRING: {
-                Pointer pointer = (Pointer) data.getFieldValue("pointer");
-                BlenderInputStream bis = blenderContext.getInputStream();
-                FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pointer.getOldMemoryAddress());
-                bis.setPosition(dataFileBlock.getBlockPosition());
-                value = bis.readString();
-                break;
-            }
-            case IDP_INT:
-                int intValue = ((Number) data.getFieldValue("val")).intValue();
-                value = Integer.valueOf(intValue);
-                break;
-            case IDP_FLOAT:
-                int floatValue = ((Number) data.getFieldValue("val")).intValue();
-                value = Float.valueOf(Float.intBitsToFloat(floatValue));
-                break;
-            case IDP_ARRAY: {
-                Pointer pointer = (Pointer) data.getFieldValue("pointer");
-                BlenderInputStream bis = blenderContext.getInputStream();
-                FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pointer.getOldMemoryAddress());
-                bis.setPosition(dataFileBlock.getBlockPosition());
-                int elementAmount = dataFileBlock.getSize();
-                switch (subType) {
-                    case IDP_INT:
-                        elementAmount /= 4;
-                        int[] intList = new int[elementAmount];
-                        for (int i = 0; i < elementAmount; ++i) {
-                            intList[i] = bis.readInt();
-                        }
-                        value = intList;
-                        break;
-                    case IDP_FLOAT:
-                        elementAmount /= 4;
-                        float[] floatList = new float[elementAmount];
-                        for (int i = 0; i < elementAmount; ++i) {
-                            floatList[i] = bis.readFloat();
-                        }
-                        value = floatList;
-                        break;
-                    case IDP_DOUBLE:
-                        elementAmount /= 8;
-                        double[] doubleList = new double[elementAmount];
-                        for (int i = 0; i < elementAmount; ++i) {
-                            doubleList[i] = bis.readDouble();
-                        }
-                        value = doubleList;
-                        break;
-                    default:
-                        throw new IllegalStateException("Invalid array subtype: " + subType);
-                }
-            }
-            case IDP_GROUP:
-                Structure group = (Structure) data.getFieldValue("group");
-                List<Structure> dataList = group.evaluateListBase();
-                List<Properties> subProperties = new ArrayList<Properties>(len);
-                for (Structure d : dataList) {
-                    Properties properties = new Properties();
-                    properties.load(d, blenderContext);
-                    subProperties.add(properties);
-                }
-                value = subProperties;
-                break;
-            case IDP_DOUBLE:
-                int doublePart1 = ((Number) data.getFieldValue("val")).intValue();
-                int doublePart2 = ((Number) data.getFieldValue("val2")).intValue();
-                long doubleVal = (long) doublePart2 << 32 | doublePart1;
-                value = Double.valueOf(Double.longBitsToDouble(doubleVal));
-                break;
-            case IDP_IDPARRAY: {
-                Pointer pointer = (Pointer) data.getFieldValue("pointer");
-                List<Structure> arrays = pointer.fetchData();
-                List<Object> result = new ArrayList<Object>(arrays.size());
-                Properties temp = new Properties();
-                for (Structure array : arrays) {
-                    temp.load(array, blenderContext);
-                    result.add(temp.value);
-                }
-                value = result;
-                break;
-            }
-            case IDP_NUMTYPES:
-                throw new UnsupportedOperationException();
-                // case IDP_ID://not yet implemented in blender
-                // return null;
-            default:
-                throw new IllegalStateException("Unknown custom property type: " + type);
-        }
-        this.completeLoading();
-    }
-
-    /**
-     * This method returns the name of the property.
-     * @return the name of the property
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * This method returns the value of the property.
-     * The type of the value depends on the type of the property.
-     * @return the value of the property
-     */
-    public Object getValue() {
-        return value;
-    }
-
-    /**
-     * @return the names of properties that are stored withing this property
-     *         (assuming this property is of IDP_GROUP type)
-     */
-    @SuppressWarnings("unchecked")
-    public List<String> getSubPropertiesNames() {
-        List<String> result = null;
-        if (type == IDP_GROUP) {
-            List<Properties> properties = (List<Properties>) value;
-            if (properties != null && properties.size() > 0) {
-                result = new ArrayList<String>(properties.size());
-                for (Properties property : properties) {
-                    result.add(property.getName());
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the same as getValue if the current property is of
-     * other type than IDP_GROUP and its name matches 'propertyName' param. If
-     * this property is a group property the method tries to find subproperty
-     * value of the given name. The first found value is returnes os <b>use this
-     * method wisely</b>. If no property of a given name is foung - <b>null</b>
-     * is returned.
-     * 
-     * @param propertyName
-     *            the name of the property
-     * @return found property value or <b>null</b>
-     */
-    @SuppressWarnings("unchecked")
-    public Object findValue(String propertyName) {
-        if (name.equals(propertyName)) {
-            return value;
-        } else {
-            if (type == IDP_GROUP) {
-                List<Properties> props = (List<Properties>) value;
-                for (Properties p : props) {
-                    Object v = p.findValue(propertyName);
-                    if (v != null) {
-                        return v;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        this.append(sb, new StringBuilder());
-        return sb.toString();
-    }
-
-    /**
-     * This method appends the data of the property to the given string buffer.
-     * @param sb
-     *            string buffer
-     * @param indent
-     *            indent buffer
-     */
-    @SuppressWarnings("unchecked")
-    private void append(StringBuilder sb, StringBuilder indent) {
-        sb.append(indent).append("name: ").append(name).append("\n\r");
-        sb.append(indent).append("type: ").append(type).append("\n\r");
-        sb.append(indent).append("subType: ").append(subType).append("\n\r");
-        sb.append(indent).append("description: ").append(description).append("\n\r");
-        indent.append('\t');
-        sb.append(indent).append("value: ");
-        if (value instanceof Properties) {
-            ((Properties) value).append(sb, indent);
-        } else if (value instanceof List) {
-            for (Object v : (List<Object>) value) {
-                if (v instanceof Properties) {
-                    sb.append(indent).append("{\n\r");
-                    indent.append('\t');
-                    ((Properties) v).append(sb, indent);
-                    indent.deleteCharAt(indent.length() - 1);
-                    sb.append(indent).append("}\n\r");
-                } else {
-                    sb.append(v);
-                }
-            }
-        } else {
-            sb.append(value);
-        }
-        sb.append("\n\r");
-        indent.deleteCharAt(indent.length() - 1);
-    }
-
-    /**
-     * This method should be called after the properties loading.
-     * It loads the properties from the _RNA_UI property and removes this property from the
-     * result list.
-     */
-    @SuppressWarnings("unchecked")
-    protected void completeLoading() {
-        if (type == IDP_GROUP) {
-            List<Properties> groupProperties = (List<Properties>) value;
-            Properties rnaUI = null;
-            for (Properties properties : groupProperties) {
-                if (properties.name.equals(RNA_PROPERTY_NAME) && properties.type == IDP_GROUP) {
-                    rnaUI = properties;
-                    break;
-                }
-            }
-            if (rnaUI != null) {
-                // removing the RNA from the result list
-                groupProperties.remove(rnaUI);
-
-                // loading the descriptions
-                Map<String, String> descriptions = new HashMap<String, String>(groupProperties.size());
-                List<Properties> propertiesRNA = (List<Properties>) rnaUI.value;
-                for (Properties properties : propertiesRNA) {
-                    String name = properties.name;
-                    String description = null;
-                    List<Properties> rnaData = (List<Properties>) properties.value;
-                    for (Properties rna : rnaData) {
-                        if ("description".equalsIgnoreCase(rna.name)) {
-                            description = (String) rna.value;
-                            break;
-                        }
-                    }
-                    descriptions.put(name, description);
-                }
-
-                // applying the descriptions
-                for (Properties properties : groupProperties) {
-                    properties.description = descriptions.get(properties.name);
-                }
-            }
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (description == null ? 0 : description.hashCode());
-        result = prime * result + (name == null ? 0 : name.hashCode());
-        result = prime * result + subType;
-        result = prime * result + type;
-        result = prime * result + (value == null ? 0 : value.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (this.getClass() != obj.getClass()) {
-            return false;
-        }
-        Properties other = (Properties) obj;
-        if (description == null) {
-            if (other.description != null) {
-                return false;
-            }
-        } else if (!description.equals(other.description)) {
-            return false;
-        }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (subType != other.subType) {
-            return false;
-        }
-        if (type != other.type) {
-            return false;
-        }
-        if (value == null) {
-            if (other.value != null) {
-                return false;
-            }
-        } else if (!value.equals(other.value)) {
-            return false;
-        }
-        return true;
-    }
-}

+ 0 - 192
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java

@@ -1,192 +0,0 @@
-package com.jme3.scene.plugins.blender.particles;
-
-import com.jme3.effect.ParticleEmitter;
-import com.jme3.effect.ParticleMesh.Type;
-import com.jme3.effect.influencers.EmptyParticleInfluencer;
-import com.jme3.effect.influencers.NewtonianParticleInfluencer;
-import com.jme3.effect.influencers.ParticleInfluencer;
-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.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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 java.util.logging.Logger;
-
-public class ParticlesHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER              = Logger.getLogger(ParticlesHelper.class.getName());
-
-    // part->type
-    public static final int     PART_EMITTER        = 0;
-    public static final int     PART_REACTOR        = 1;
-    public static final int     PART_HAIR           = 2;
-    public static final int     PART_FLUID          = 3;
-
-    // part->flag
-    public static final int     PART_REACT_STA_END  = 1;
-    public static final int     PART_REACT_MULTIPLE = 2;
-    public static final int     PART_LOOP           = 4;
-    // public static final int PART_LOOP_INSTANT =8;
-    public static final int     PART_HAIR_GEOMETRY  = 16;
-    public static final int     PART_UNBORN         = 32;                                               // show unborn particles
-    public static final int     PART_DIED           = 64;                                               // show died particles
-    public static final int     PART_TRAND          = 128;
-    public static final int     PART_EDISTR         = 256;                                              // particle/face from face areas
-    public static final int     PART_STICKY         = 512;                                              // collided particles can stick to collider
-    public static final int     PART_DIE_ON_COL     = 1 << 12;
-    public static final int     PART_SIZE_DEFL      = 1 << 13;                                          // swept sphere deflections
-    public static final int     PART_ROT_DYN        = 1 << 14;                                          // dynamic rotation
-    public static final int     PART_SIZEMASS       = 1 << 16;
-    public static final int     PART_ABS_LENGTH     = 1 << 15;
-    public static final int     PART_ABS_TIME       = 1 << 17;
-    public static final int     PART_GLOB_TIME      = 1 << 18;
-    public static final int     PART_BOIDS_2D       = 1 << 19;
-    public static final int     PART_BRANCHING      = 1 << 20;
-    public static final int     PART_ANIM_BRANCHING = 1 << 21;
-    public static final int     PART_SELF_EFFECT    = 1 << 22;
-    public static final int     PART_SYMM_BRANCHING = 1 << 24;
-    public static final int     PART_HAIR_BSPLINE   = 1024;
-    public static final int     PART_GRID_INVERT    = 1 << 26;
-    public static final int     PART_CHILD_EFFECT   = 1 << 27;
-    public static final int     PART_CHILD_SEAMS    = 1 << 28;
-    public static final int     PART_CHILD_RENDER   = 1 << 29;
-    public static final int     PART_CHILD_GUIDE    = 1 << 30;
-
-    // part->from
-    public static final int     PART_FROM_VERT      = 0;
-    public static final int     PART_FROM_FACE      = 1;
-    public static final int     PART_FROM_VOLUME    = 2;
-    public static final int     PART_FROM_PARTICLE  = 3;
-    public static final int     PART_FROM_CHILD     = 4;
-
-    // part->phystype
-    public static final int     PART_PHYS_NO        = 0;
-    public static final int     PART_PHYS_NEWTON    = 1;
-    public static final int     PART_PHYS_KEYED     = 2;
-    public static final int     PART_PHYS_BOIDS     = 3;
-
-    // part->draw_as
-    public static final int     PART_DRAW_NOT       = 0;
-    public static final int     PART_DRAW_DOT       = 1;
-    public static final int     PART_DRAW_CIRC      = 2;
-    public static final int     PART_DRAW_CROSS     = 3;
-    public static final int     PART_DRAW_AXIS      = 4;
-    public static final int     PART_DRAW_LINE      = 5;
-    public static final int     PART_DRAW_PATH      = 6;
-    public static final int     PART_DRAW_OB        = 7;
-    public static final int     PART_DRAW_GR        = 8;
-    public static final int     PART_DRAW_BB        = 9;
-
-    /**
-     * 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
-     * @param blenderContext
-     *            the blender context
-     */
-    public ParticlesHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    @SuppressWarnings("unchecked")
-    public ParticleEmitter toParticleEmitter(Structure particleSystem) throws BlenderFileException {
-        ParticleEmitter result = null;
-        Pointer pParticleSettings = (Pointer) particleSystem.getFieldValue("part");
-        if (pParticleSettings.isNotNull()) {
-            Structure particleSettings = pParticleSettings.fetchData().get(0);
-
-            int totPart = ((Number) particleSettings.getFieldValue("totpart")).intValue();
-
-            // draw type will be stored temporarily in the name (it is used during modifier applying operation)
-            int drawAs = ((Number) particleSettings.getFieldValue("draw_as")).intValue();
-            char nameSuffix;// P - point, L - line, N - None, B - Bilboard
-            switch (drawAs) {
-                case PART_DRAW_NOT:
-                    nameSuffix = 'N';
-                    totPart = 0;// no need to generate particles in this case
-                    break;
-                case PART_DRAW_BB:
-                    nameSuffix = 'B';
-                    break;
-                case PART_DRAW_OB:
-                case PART_DRAW_GR:
-                    nameSuffix = 'P';
-                    LOGGER.warning("Neither object nor group particles supported yet! Using point representation instead!");// TODO: support groups and aobjects
-                    break;
-                case PART_DRAW_LINE:
-                    nameSuffix = 'L';
-                    LOGGER.warning("Lines not yet supported! Using point representation instead!");// TODO: support lines
-                default:// all others are rendered as points in blender
-                    nameSuffix = 'P';
-            }
-            result = new ParticleEmitter(particleSettings.getName() + nameSuffix, Type.Triangle, totPart);
-            if (nameSuffix == 'N') {
-                return result;// no need to set anything else
-            }
-
-            // setting the emitters shape (the shapes meshes will be set later during modifier applying operation)
-            int from = ((Number) particleSettings.getFieldValue("from")).intValue();
-            switch (from) {
-                case PART_FROM_VERT:
-                    result.setShape(new EmitterMeshVertexShape());
-                    break;
-                case PART_FROM_FACE:
-                    result.setShape(new EmitterMeshFaceShape());
-                    break;
-                case PART_FROM_VOLUME:
-                    result.setShape(new EmitterMeshConvexHullShape());
-                    break;
-                default:
-                    LOGGER.warning("Default shape used! Unknown emitter shape value ('from' parameter: " + from + ')');
-            }
-
-            // reading acceleration
-            DynamicArray<Number> acc = (DynamicArray<Number>) particleSettings.getFieldValue("acc");
-            result.setGravity(-acc.get(0).floatValue(), -acc.get(1).floatValue(), -acc.get(2).floatValue());
-
-            // setting the colors
-            result.setEndColor(new ColorRGBA(1f, 1f, 1f, 1f));
-            result.setStartColor(new ColorRGBA(1f, 1f, 1f, 1f));
-
-            // reading size
-            float sizeFactor = nameSuffix == 'B' ? 1.0f : 0.3f;
-            float size = ((Number) particleSettings.getFieldValue("size")).floatValue() * sizeFactor;
-            result.setStartSize(size);
-            result.setEndSize(size);
-
-            // reading lifetime
-            int fps = blenderContext.getBlenderKey().getFps();
-            float lifetime = ((Number) particleSettings.getFieldValue("lifetime")).floatValue() / fps;
-            float randlife = ((Number) particleSettings.getFieldValue("randlife")).floatValue() / fps;
-            result.setLowLife(lifetime * (1.0f - randlife));
-            result.setHighLife(lifetime);
-
-            // preparing influencer
-            ParticleInfluencer influencer;
-            int phystype = ((Number) particleSettings.getFieldValue("phystype")).intValue();
-            switch (phystype) {
-                case PART_PHYS_NEWTON:
-                    influencer = new NewtonianParticleInfluencer();
-                    ((NewtonianParticleInfluencer) influencer).setNormalVelocity(((Number) particleSettings.getFieldValue("normfac")).floatValue());
-                    ((NewtonianParticleInfluencer) influencer).setVelocityVariation(((Number) particleSettings.getFieldValue("randfac")).floatValue());
-                    ((NewtonianParticleInfluencer) influencer).setSurfaceTangentFactor(((Number) particleSettings.getFieldValue("tanfac")).floatValue());
-                    ((NewtonianParticleInfluencer) influencer).setSurfaceTangentRotation(((Number) particleSettings.getFieldValue("tanphase")).floatValue());
-                    break;
-                case PART_PHYS_BOIDS:
-                case PART_PHYS_KEYED:// TODO: support other influencers
-                    LOGGER.warning("Boids and Keyed particles physic not yet supported! Empty influencer used!");
-                case PART_PHYS_NO:
-                default:
-                    influencer = new EmptyParticleInfluencer();
-            }
-            result.setParticleInfluencer(influencer);
-        }
-        return result;
-    }
-}

+ 0 - 401
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/ColorBand.java

@@ -1,401 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures;
-
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.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 java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * A class constaining the colorband data.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class ColorBand {
-    private static final Logger LOGGER       = Logger.getLogger(ColorBand.class.getName());
-
-    // interpolation types
-    public static final int     IPO_LINEAR   = 0;
-    public static final int     IPO_EASE     = 1;
-    public static final int     IPO_BSPLINE  = 2;
-    public static final int     IPO_CARDINAL = 3;
-    public static final int     IPO_CONSTANT = 4;
-
-    private int                 cursorsAmount, ipoType;
-    /** The default amount of possible cursor positions. */
-    private int                 resultSize   = 1001;
-    private ColorBandData[]     data;
-
-    /**
-     * A constructor used to instantiate color band by hand instead of reading it from the blend file.
-     * @param ipoType
-     *            the interpolation type
-     * @param colors
-     *            the colorband colors
-     * @param positions
-     *            the positions for colors' cursors
-     * @param resultSize
-     *            the size of the result table
-     */
-    public ColorBand(int ipoType, List<ColorRGBA> colors, List<Integer> positions, int resultSize) {
-        if (colors == null || colors.size() < 1) {
-            throw new IllegalArgumentException("The amount of colorband's colors must be at least 1.");
-        }
-        if (ipoType < IPO_LINEAR || ipoType > IPO_CONSTANT) {
-            throw new IllegalArgumentException("Unknown colorband interpolation type: " + ipoType);
-        }
-        if (positions == null || positions.size() != colors.size()) {
-            throw new IllegalArgumentException("The size of positions and colors list should be equal!");
-        }
-        for (Integer position : positions) {
-            if (position.intValue() < 0 || position.intValue() >= resultSize) {
-                throw new IllegalArgumentException("Invalid position value: " + position + "! Should be from range: [0, " + resultSize + "]!");
-            }
-        }
-
-        cursorsAmount = colors.size();
-        this.ipoType = ipoType;
-        this.resultSize = resultSize;
-        data = new ColorBandData[cursorsAmount];
-        for (int i = 0; i < cursorsAmount; ++i) {
-            data[i] = new ColorBandData(colors.get(i), positions.get(i));
-        }
-    }
-
-    /**
-     * Constructor. Loads the data from the given structure.
-     * @param tex
-     * @param blenderContext
-     */
-    @SuppressWarnings("unchecked")
-    public ColorBand(Structure tex, BlenderContext blenderContext) {
-        int flag = ((Number) tex.getFieldValue("flag")).intValue();
-        if ((flag & GeneratedTexture.TEX_COLORBAND) != 0) {
-            Pointer pColorband = (Pointer) tex.getFieldValue("coba");
-            try {
-                Structure colorbandStructure = pColorband.fetchData().get(0);
-                cursorsAmount = ((Number) colorbandStructure.getFieldValue("tot")).intValue();
-                ipoType = ((Number) colorbandStructure.getFieldValue("ipotype")).intValue();
-                data = new ColorBandData[cursorsAmount];
-                DynamicArray<Structure> data = (DynamicArray<Structure>) colorbandStructure.getFieldValue("data");
-                for (int i = 0; i < cursorsAmount; ++i) {
-                    this.data[i] = new ColorBandData(data.get(i));
-                }
-            } catch (BlenderFileException e) {
-                LOGGER.log(Level.WARNING, "Cannot fetch the colorband structure. The reason: {0}", e.getLocalizedMessage());
-            }
-        }
-    }
-
-    /**
-     * This method determines if the colorband has any transparencies or is not
-     * transparent at all.
-     * 
-     * @return <b>true</b> if the colorband has transparencies and <b>false</b>
-     *         otherwise
-     */
-    public boolean hasTransparencies() {
-        if (data != null) {
-            for (ColorBandData colorBandData : data) {
-                if (colorBandData.a < 1.0f) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This method computes the values of the colorband.
-     * 
-     * @return an array of 1001 elements and each element is float[4] object
-     *         containing rgba values
-     */
-    public float[][] computeValues() {
-        float[][] result = null;
-        if (data != null) {
-            result = new float[resultSize][4];// resultSize - amount of possible cursor positions; 4 = [r, g, b, a]
-            if (data.length == 1) {// special case; use only one color for all types of colorband interpolation
-                for (int i = 0; i < result.length; ++i) {
-                    result[i][0] = data[0].r;
-                    result[i][1] = data[0].g;
-                    result[i][2] = data[0].b;
-                    result[i][3] = data[0].a;
-                }
-            } else {
-                int currentCursor = 0;
-                ColorBandData currentData = data[0];
-                ColorBandData nextData = data[0];
-                switch (ipoType) {
-                    case ColorBand.IPO_LINEAR:
-                        float rDiff = 0,
-                        gDiff = 0,
-                        bDiff = 0,
-                        aDiff = 0,
-                        posDiff;
-                        for (int i = 0; i < result.length; ++i) {
-                            posDiff = i - currentData.pos;
-                            result[i][0] = currentData.r + rDiff * posDiff;
-                            result[i][1] = currentData.g + gDiff * posDiff;
-                            result[i][2] = currentData.b + bDiff * posDiff;
-                            result[i][3] = currentData.a + aDiff * posDiff;
-                            if (nextData.pos == i) {
-                                currentData = data[currentCursor++];
-                                if (currentCursor < data.length) {
-                                    nextData = data[currentCursor];
-                                    // calculate differences
-                                    int d = nextData.pos - currentData.pos;
-                                    rDiff = (nextData.r - currentData.r) / d;
-                                    gDiff = (nextData.g - currentData.g) / d;
-                                    bDiff = (nextData.b - currentData.b) / d;
-                                    aDiff = (nextData.a - currentData.a) / d;
-                                } else {
-                                    rDiff = gDiff = bDiff = aDiff = 0;
-                                }
-                            }
-                        }
-                        break;
-                    case ColorBand.IPO_BSPLINE:
-                    case ColorBand.IPO_CARDINAL:
-                        Map<Integer, ColorBandData> cbDataMap = new TreeMap<Integer, ColorBandData>();
-                        for (int i = 0; i < data.length; ++i) {
-                            cbDataMap.put(Integer.valueOf(i), data[i]);
-                        }
-
-                        if (data[0].pos == 0) {
-                            cbDataMap.put(Integer.valueOf(-1), data[0]);
-                        } else {
-                            ColorBandData cbData = new ColorBandData(data[0]);
-                            cbData.pos = 0;
-                            cbDataMap.put(Integer.valueOf(-1), cbData);
-                            cbDataMap.put(Integer.valueOf(-2), cbData);
-                        }
-
-                        if (data[data.length - 1].pos == 1000) {
-                            cbDataMap.put(Integer.valueOf(data.length), data[data.length - 1]);
-                        } else {
-                            ColorBandData cbData = new ColorBandData(data[data.length - 1]);
-                            cbData.pos = 1000;
-                            cbDataMap.put(Integer.valueOf(data.length), cbData);
-                            cbDataMap.put(Integer.valueOf(data.length + 1), cbData);
-                        }
-
-                        float[] ipoFactors = new float[4];
-                        float f;
-
-                        ColorBandData data0 = this.getColorbandData(currentCursor - 2, cbDataMap);
-                        ColorBandData data1 = this.getColorbandData(currentCursor - 1, cbDataMap);
-                        ColorBandData data2 = this.getColorbandData(currentCursor, cbDataMap);
-                        ColorBandData data3 = this.getColorbandData(currentCursor + 1, cbDataMap);
-
-                        for (int i = 0; i < result.length; ++i) {
-                            if (data2.pos != data1.pos) {
-                                f = (i - data2.pos) / (float) (data1.pos - data2.pos);
-                                f = FastMath.clamp(f, 0.0f, 1.0f);
-                            } else {
-                                f = 0.0f;
-                            }
-                            this.getIpoData(f, ipoFactors);
-                            result[i][0] = ipoFactors[3] * data0.r + ipoFactors[2] * data1.r + ipoFactors[1] * data2.r + ipoFactors[0] * data3.r;
-                            result[i][1] = ipoFactors[3] * data0.g + ipoFactors[2] * data1.g + ipoFactors[1] * data2.g + ipoFactors[0] * data3.g;
-                            result[i][2] = ipoFactors[3] * data0.b + ipoFactors[2] * data1.b + ipoFactors[1] * data2.b + ipoFactors[0] * data3.b;
-                            result[i][3] = ipoFactors[3] * data0.a + ipoFactors[2] * data1.a + ipoFactors[1] * data2.a + ipoFactors[0] * data3.a;
-                            result[i][0] = FastMath.clamp(result[i][0], 0.0f, 1.0f);
-                            result[i][1] = FastMath.clamp(result[i][1], 0.0f, 1.0f);
-                            result[i][2] = FastMath.clamp(result[i][2], 0.0f, 1.0f);
-                            result[i][3] = FastMath.clamp(result[i][3], 0.0f, 1.0f);
-
-                            if (nextData.pos == i) {
-                                ++currentCursor;
-                                data0 = cbDataMap.get(currentCursor - 2);
-                                data1 = cbDataMap.get(currentCursor - 1);
-                                data2 = cbDataMap.get(currentCursor);
-                                data3 = cbDataMap.get(currentCursor + 1);
-                            }
-                        }
-                        break;
-                    case ColorBand.IPO_EASE:
-                        float d,
-                        a,
-                        b,
-                        d2;
-                        for (int i = 0; i < result.length; ++i) {
-                            if (nextData.pos != currentData.pos) {
-                                d = (i - currentData.pos) / (float) (nextData.pos - currentData.pos);
-                                d2 = d * d;
-                                a = 3.0f * d2 - 2.0f * d * d2;
-                                b = 1.0f - a;
-                            } else {
-                                d = a = 0.0f;
-                                b = 1.0f;
-                            }
-
-                            result[i][0] = b * currentData.r + a * nextData.r;
-                            result[i][1] = b * currentData.g + a * nextData.g;
-                            result[i][2] = b * currentData.b + a * nextData.b;
-                            result[i][3] = b * currentData.a + a * nextData.a;
-                            if (nextData.pos == i) {
-                                currentData = data[currentCursor++];
-                                if (currentCursor < data.length) {
-                                    nextData = data[currentCursor];
-                                }
-                            }
-                        }
-                        break;
-                    case ColorBand.IPO_CONSTANT:
-                        for (int i = 0; i < result.length; ++i) {
-                            result[i][0] = currentData.r;
-                            result[i][1] = currentData.g;
-                            result[i][2] = currentData.b;
-                            result[i][3] = currentData.a;
-                            if (nextData.pos == i) {
-                                currentData = data[currentCursor++];
-                                if (currentCursor < data.length) {
-                                    nextData = data[currentCursor];
-                                }
-                            }
-                        }
-                        break;
-                    default:
-                        throw new IllegalStateException("Unknown interpolation type: " + ipoType);
-                }
-            }
-        }
-        return result;
-    }
-
-    private ColorBandData getColorbandData(int index, Map<Integer, ColorBandData> cbDataMap) {
-        ColorBandData result = cbDataMap.get(index);
-        if (result == null) {
-            result = new ColorBandData();
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the data for either B-spline of Cardinal
-     * interpolation.
-     * 
-     * @param d
-     *            distance factor for the current intensity
-     * @param ipoFactors
-     *            table to store the results (size of the table must be at least
-     *            4)
-     */
-    private void getIpoData(float d, float[] ipoFactors) {
-        float d2 = d * d;
-        float d3 = d2 * d;
-        if (ipoType == ColorBand.IPO_BSPLINE) {
-            ipoFactors[0] = -0.71f * d3 + 1.42f * d2 - 0.71f * d;
-            ipoFactors[1] = 1.29f * d3 - 2.29f * d2 + 1.0f;
-            ipoFactors[2] = -1.29f * d3 + 1.58f * d2 + 0.71f * d;
-            ipoFactors[3] = 0.71f * d3 - 0.71f * d2;
-        } else if (ipoType == ColorBand.IPO_CARDINAL) {
-            ipoFactors[0] = -0.16666666f * d3 + 0.5f * d2 - 0.5f * d + 0.16666666f;
-            ipoFactors[1] = 0.5f * d3 - d2 + 0.6666666f;
-            ipoFactors[2] = -0.5f * d3 + 0.5f * d2 + 0.5f * d + 0.16666666f;
-            ipoFactors[3] = 0.16666666f * d3;
-        } else {
-            throw new IllegalStateException("Cannot get interpolation data for other colorband types than B-spline and Cardinal!");
-        }
-    }
-
-    /**
-     * Class to store the single colorband cursor data.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class ColorBandData {
-        public final float r, g, b, a;
-        public int         pos;
-
-        public ColorBandData() {
-            r = g = b = 0;
-            a = 1;
-        }
-
-        /**
-         * Constructor that stores the color and position of the cursor.
-         * @param color
-         *            the cursor's color
-         * @param pos
-         *            the cursor's position
-         */
-        public ColorBandData(ColorRGBA color, int pos) {
-            r = color.r;
-            g = color.g;
-            b = color.b;
-            a = color.a;
-            this.pos = pos;
-        }
-
-        /**
-         * Copy constructor.
-         */
-        private ColorBandData(ColorBandData data) {
-            r = data.r;
-            g = data.g;
-            b = data.b;
-            a = data.a;
-            pos = data.pos;
-        }
-
-        /**
-         * Constructor. Loads the data from the given structure.
-         * 
-         * @param cbdataStructure
-         *            the structure containing the CBData object
-         */
-        public ColorBandData(Structure cbdataStructure) {
-            r = ((Number) cbdataStructure.getFieldValue("r")).floatValue();
-            g = ((Number) cbdataStructure.getFieldValue("g")).floatValue();
-            b = ((Number) cbdataStructure.getFieldValue("b")).floatValue();
-            a = ((Number) cbdataStructure.getFieldValue("a")).floatValue();
-            pos = (int) (((Number) cbdataStructure.getFieldValue("pos")).floatValue() * 1000.0f);
-        }
-
-        @Override
-        public String toString() {
-            return "P: " + pos + " [" + r + ", " + g + ", " + b + ", " + a + "]";
-        }
-    }
-}

+ 0 - 543
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/CombinedTexture.java

@@ -1,543 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.image.BufferedImage;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jme3tools.converters.ImageToAwt;
-
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Vector2f;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.materials.MaterialContext;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-import com.jme3.scene.plugins.blender.textures.TriangulatedTexture.TriangleTextureElement;
-import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.UVCoordinatesType;
-import com.jme3.scene.plugins.blender.textures.UVProjectionGenerator.UVProjectionType;
-import com.jme3.scene.plugins.blender.textures.blending.TextureBlender;
-import com.jme3.scene.plugins.blender.textures.blending.TextureBlenderFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Texture;
-import com.jme3.texture.Texture.MagFilter;
-import com.jme3.texture.Texture.MinFilter;
-import com.jme3.texture.Texture.WrapMode;
-import com.jme3.texture.Texture2D;
-import com.jme3.texture.TextureCubeMap;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.util.BufferUtils;
-
-/**
- * This class represents a texture that is defined for the material. It can be
- * made of several textures (both 2D and 3D) that are merged together and
- * returned as a single texture.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class CombinedTexture {
-    private static final Logger LOGGER       = Logger.getLogger(CombinedTexture.class.getName());
-
-    /** The mapping type of the texture. Defined bu MaterialContext.MTEX_COL, MTEX_NOR etc. */
-    private final int           mappingType;
-    /**
-     * If set to true then if a texture without alpha is added then all textures below are discarded because
-     * the new one will cover them anyway. If set to false then all textures are stored.
-     */
-    private boolean             discardCoveredTextures;
-    /** The data for each of the textures. */
-    private List<TextureData>   textureDatas = new ArrayList<TextureData>();
-    /** The result texture. */
-    private Texture             resultTexture;
-    /** The UV values for the result texture. */
-    private List<Vector2f>      resultUVS;
-
-    /**
-     * Constructor. Stores the texture mapping type (ie. color map, normal map).
-     * 
-     * @param mappingType
-     *            texture mapping type
-     * @param discardCoveredTextures
-     *            if set to true then if a texture without alpha is added then all textures below are discarded because
-     *            the new one will cover them anyway, if set to false then all textures are stored
-     */
-    public CombinedTexture(int mappingType, boolean discardCoveredTextures) {
-        this.mappingType = mappingType;
-        this.discardCoveredTextures = discardCoveredTextures;
-    }
-
-    /**
-     * This method adds a texture data to the resulting texture.
-     * 
-     * @param texture
-     *            the source texture
-     * @param textureBlender
-     *            the texture blender (to mix the texture with its material
-     *            color)
-     * @param uvCoordinatesType
-     *            the type of UV coordinates
-     * @param projectionType
-     *            the type of UV coordinates projection (for flat textures)
-     * @param textureStructure
-     *            the texture sructure
-     * @param uvCoordinatesName
-     *            the name of the used user's UV coordinates for this texture
-     * @param blenderContext
-     *            the blender context
-     */
-    public void add(Texture texture, TextureBlender textureBlender, int uvCoordinatesType, int projectionType, Structure textureStructure, String uvCoordinatesName, BlenderContext blenderContext) {
-        if (!(texture instanceof GeneratedTexture) && !(texture instanceof Texture2D)) {
-            throw new IllegalArgumentException("Unsupported texture type: " + (texture == null ? "null" : texture.getClass()));
-        }
-        if (!(texture instanceof GeneratedTexture) || blenderContext.getBlenderKey().isLoadGeneratedTextures()) {
-            if (UVCoordinatesGenerator.isTextureCoordinateTypeSupported(UVCoordinatesType.valueOf(uvCoordinatesType))) {
-                TextureData textureData = new TextureData();
-                textureData.texture = texture;
-                textureData.textureBlender = textureBlender;
-                textureData.uvCoordinatesType = UVCoordinatesType.valueOf(uvCoordinatesType);
-                textureData.projectionType = UVProjectionType.valueOf(projectionType);
-                textureData.textureStructure = textureStructure;
-                textureData.uvCoordinatesName = uvCoordinatesName;
-
-                if (discardCoveredTextures && textureDatas.size() > 0 && this.isWithoutAlpha(textureData, blenderContext)) {
-                    textureDatas.clear();// clear previous textures, they will be covered anyway
-                }
-                textureDatas.add(textureData);
-            } else {
-                LOGGER.warning("The texture coordinates type is not supported: " + UVCoordinatesType.valueOf(uvCoordinatesType) + ". The texture '" + textureStructure.getName() + "'.");
-            }
-        }
-    }
-
-	/**
-	 * This method flattens the texture and creates a single result of Texture2D
-	 * type.
-	 * 
-	 * @param geometry
-	 *            the geometry the texture is created for
-	 * @param geometriesOMA
-	 *            the old memory address of the geometries list that the given
-	 *            geometry belongs to (needed for bounding box creation)
-	 * @param userDefinedUVCoordinates
-	 *            the UV's defined by user (null or zero length table if none
-	 *            were defined)
-	 * @param blenderContext
-	 *            the blender context
-	 * @return the name of the user UV coordinates used (null if the UV's were
-	 *         generated)
-	 */
-    public String flatten(Geometry geometry, Long geometriesOMA, Map<String, List<Vector2f>> userDefinedUVCoordinates, BlenderContext blenderContext) {
-        Mesh mesh = geometry.getMesh();
-        Texture previousTexture = null;
-        UVCoordinatesType masterUVCoordinatesType = null;
-        String masterUserUVSetName = null;
-        for (TextureData textureData : textureDatas) {
-            // decompress compressed textures (all will be merged into one texture anyway)
-            if (textureDatas.size() > 1 && textureData.texture.getImage().getFormat().isCompressed()) {
-                textureData.texture.setImage(ImageUtils.decompress(textureData.texture.getImage()));
-                textureData.textureBlender = TextureBlenderFactory.alterTextureType(textureData.texture.getImage().getFormat(), textureData.textureBlender);
-            }
-
-            if (previousTexture == null) {// the first texture will lead the others to its shape
-                if (textureData.texture instanceof GeneratedTexture) {
-                    resultTexture = ((GeneratedTexture) textureData.texture).triangulate(mesh, geometriesOMA, textureData.uvCoordinatesType, blenderContext);
-                } else if (textureData.texture instanceof Texture2D) {
-                    resultTexture = textureData.texture;
-
-                    if (textureData.uvCoordinatesType == UVCoordinatesType.TEXCO_UV && userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
-                        if (textureData.uvCoordinatesName == null) {
-                            resultUVS = userDefinedUVCoordinates.values().iterator().next();// get the first UV available
-                        } else {
-                            resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
-                        }
-                        if(resultUVS == null && LOGGER.isLoggable(Level.WARNING)) {
-                            LOGGER.warning("The texture " + textureData.texture.getName() + " has assigned non existing UV coordinates group: " + textureData.uvCoordinatesName + ".");
-                        }
-                        masterUserUVSetName = textureData.uvCoordinatesName;
-                    } else {
-                        TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
-                        resultUVS = UVCoordinatesGenerator.generateUVCoordinatesFor2DTexture(mesh, textureData.uvCoordinatesType, textureData.projectionType, temporalMesh);
-                    }
-                }
-                this.blend(resultTexture, textureData.textureBlender, blenderContext);
-
-                previousTexture = resultTexture;
-                masterUVCoordinatesType = textureData.uvCoordinatesType;
-            } else {
-                if (textureData.texture instanceof GeneratedTexture) {
-                    if (!(resultTexture instanceof TriangulatedTexture)) {
-                        resultTexture = new TriangulatedTexture((Texture2D) resultTexture, resultUVS, blenderContext);
-                        resultUVS = null;
-                        previousTexture = resultTexture;
-                    }
-
-                    TriangulatedTexture triangulatedTexture = ((GeneratedTexture) textureData.texture).triangulate(mesh, geometriesOMA, textureData.uvCoordinatesType, blenderContext);
-                    triangulatedTexture.castToUVS((TriangulatedTexture) resultTexture, blenderContext);
-                    triangulatedTexture.blend(textureData.textureBlender, (TriangulatedTexture) resultTexture, blenderContext);
-                    resultTexture = previousTexture = triangulatedTexture;
-                } else if (textureData.texture instanceof Texture2D) {
-                    if (this.isUVTypesMatch(masterUVCoordinatesType, masterUserUVSetName, textureData.uvCoordinatesType, textureData.uvCoordinatesName) && resultTexture instanceof Texture2D) {
-                        this.scale((Texture2D) textureData.texture, resultTexture.getImage().getWidth(), resultTexture.getImage().getHeight());
-                        ImageUtils.merge(resultTexture.getImage(), textureData.texture.getImage());
-                        previousTexture = resultTexture;
-                    } else {
-                        if (!(resultTexture instanceof TriangulatedTexture)) {
-                            resultTexture = new TriangulatedTexture((Texture2D) resultTexture, resultUVS, blenderContext);
-                            resultUVS = null;
-                        }
-                        // first triangulate the current texture
-                        List<Vector2f> textureUVS = null;
-                        if (textureData.uvCoordinatesType == UVCoordinatesType.TEXCO_UV && userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
-                            if (textureData.uvCoordinatesName == null) {
-                                textureUVS = userDefinedUVCoordinates.values().iterator().next();// get the first UV available
-                            } else {
-                                textureUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
-                            }
-                        } else {
-                            TemporalMesh geometries = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
-                            textureUVS = UVCoordinatesGenerator.generateUVCoordinatesFor2DTexture(mesh, textureData.uvCoordinatesType, textureData.projectionType, geometries);
-                        }
-                        TriangulatedTexture triangulatedTexture = new TriangulatedTexture((Texture2D) textureData.texture, textureUVS, blenderContext);
-                        // then move the texture to different UV's
-                        triangulatedTexture.castToUVS((TriangulatedTexture) resultTexture, blenderContext);
-                        // merge triangulated textures
-                        for (int i = 0; i < ((TriangulatedTexture) resultTexture).getFaceTextureCount(); ++i) {
-                            ImageUtils.merge(((TriangulatedTexture) resultTexture).getFaceTextureElement(i).image, triangulatedTexture.getFaceTextureElement(i).image);
-                        }
-                    }
-                }
-            }
-        }
-
-        if (resultTexture instanceof TriangulatedTexture) {
-            if (mappingType == MaterialContext.MTEX_NOR) {
-                for (int i = 0; i < ((TriangulatedTexture) resultTexture).getFaceTextureCount(); ++i) {
-                    TriangleTextureElement triangleTextureElement = ((TriangulatedTexture) resultTexture).getFaceTextureElement(i);
-                    triangleTextureElement.image = ImageUtils.convertToNormalMapTexture(triangleTextureElement.image, 1);// TODO: get proper strength factor
-                }
-            }
-            resultUVS = ((TriangulatedTexture) resultTexture).getResultUVS();
-            resultTexture = ((TriangulatedTexture) resultTexture).getResultTexture();
-            masterUserUVSetName = null;
-        }
-
-        // setting additional data
-        resultTexture.setWrap(WrapMode.Repeat);
-        // the filters are required if generated textures are used because
-        // otherwise ugly lines appear between the mesh faces
-        resultTexture.setMagFilter(MagFilter.Nearest);
-        resultTexture.setMinFilter(MinFilter.NearestNoMipMaps);
-        
-        return masterUserUVSetName;
-    }
-
-    /**
-     * Generates a texture that will be used by the sky spatial.
-     * The result texture has 6 layers. Every image in each layer has equal size and its shape is a square.
-     * The size of each image is the maximum size (width or height) of the textures given.
-     * The default sky generated texture size is used (this value is set in the BlenderKey) if no picture textures
-     * are present or their sizes is lower than the generated texture size.
-     * The textures of lower sizes are properly scaled.
-     * All the textures are mixed into one and put as layers in the result texture.
-     * 
-     * @param horizontalColor
-     *            the horizon color
-     * @param zenithColor
-     *            the zenith color
-     * @param blenderContext
-     *            the blender context
-     * @return texture for the sky
-     */
-    public TextureCubeMap generateSkyTexture(ColorRGBA horizontalColor, ColorRGBA zenithColor, BlenderContext blenderContext) {
-        LOGGER.log(Level.FINE, "Preparing sky texture from {0} applied textures.", textureDatas.size());
-
-        LOGGER.fine("Computing the texture size.");
-        int size = -1;
-        for (TextureData textureData : textureDatas) {
-            if (textureData.texture instanceof Texture2D) {
-                size = Math.max(textureData.texture.getImage().getWidth(), size);
-                size = Math.max(textureData.texture.getImage().getHeight(), size);
-            }
-        }
-        if (size < 0) {
-            size = blenderContext.getBlenderKey().getSkyGeneratedTextureSize();
-        }
-        LOGGER.log(Level.FINE, "The sky texture size will be: {0}x{0}.", size);
-
-        TextureCubeMap result = null;
-        for (TextureData textureData : textureDatas) {
-            TextureCubeMap texture = null;
-            if (textureData.texture instanceof GeneratedTexture) {
-                texture = ((GeneratedTexture) textureData.texture).generateSkyTexture(size, horizontalColor, zenithColor, blenderContext);
-            } else {
-                // first create a grayscale version of the image
-                Image image = textureData.texture.getImage();
-                if (image.getWidth() != image.getHeight() || image.getWidth() != size) {
-                    image = ImageUtils.resizeTo(image, size, size);
-                }
-                Image grayscaleImage = ImageUtils.convertToGrayscaleTexture(image);
-
-                // add the sky colors to the image
-                PixelInputOutput sourcePixelIO = PixelIOFactory.getPixelIO(grayscaleImage.getFormat());
-                PixelInputOutput targetPixelIO = PixelIOFactory.getPixelIO(image.getFormat());
-                TexturePixel texturePixel = new TexturePixel();
-                for (int x = 0; x < image.getWidth(); ++x) {
-                    for (int y = 0; y < image.getHeight(); ++y) {
-                        sourcePixelIO.read(grayscaleImage, 0, texturePixel, x, y);
-                        texturePixel.intensity = texturePixel.red;// no matter which factor we use here, in grayscale they are all equal
-                        ImageUtils.color(texturePixel, horizontalColor, zenithColor);
-                        targetPixelIO.write(image, 0, texturePixel, x, y);
-                    }
-                }
-
-                // create the cubemap texture from the coloured image
-                ByteBuffer sourceData = image.getData(0);
-                ArrayList<ByteBuffer> data = new ArrayList<ByteBuffer>(6);
-                for (int i = 0; i < 6; ++i) {
-                    data.add(BufferUtils.clone(sourceData));
-                }
-                texture = new TextureCubeMap(new Image(image.getFormat(), image.getWidth(), image.getHeight(), 6, data, ColorSpace.Linear));
-            }
-
-            if (result == null) {
-                result = texture;
-            } else {
-                ImageUtils.mix(result.getImage(), texture.getImage());
-            }
-        }
-        return result;
-    }
-
-    /**
-     * The method checks if the texture UV coordinates match.
-     * It the types are equal and different then UVCoordinatesType.TEXCO_UV then we consider them a match.
-     * If they are both UVCoordinatesType.TEXCO_UV then they match only when their UV sets names are equal.
-     * In other cases they are considered NOT a match.
-     * @param type1
-     *            the UV coord type
-     * @param uvSetName1
-     *            the user's UV coords set name (considered only for UVCoordinatesType.TEXCO_UV)
-     * @param type2
-     *            the UV coord type
-     * @param uvSetName2
-     *            the user's UV coords set name (considered only for UVCoordinatesType.TEXCO_UV)
-     * @return <b>true</b> if the types match and <b>false</b> otherwise
-     */
-    private boolean isUVTypesMatch(UVCoordinatesType type1, String uvSetName1, UVCoordinatesType type2, String uvSetName2) {
-        if (type1 == type2) {
-            if (type1 == UVCoordinatesType.TEXCO_UV) {
-                if (uvSetName1 != null && uvSetName2 != null && uvSetName1.equals(uvSetName2)) {
-                    return true;
-                }
-            } else {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This method blends the texture.
-     * 
-     * @param texture
-     *            the texture to be blended
-     * @param textureBlender
-     *            blending definition for the texture
-     * @param blenderContext
-     *            the blender context
-     */
-    private void blend(Texture texture, TextureBlender textureBlender, BlenderContext blenderContext) {
-        if (texture instanceof TriangulatedTexture) {
-            ((TriangulatedTexture) texture).blend(textureBlender, null, blenderContext);
-        } else if (texture instanceof Texture2D) {
-            Image blendedImage = textureBlender.blend(texture.getImage(), null, blenderContext);
-            texture.setImage(blendedImage);
-        } else {
-            throw new IllegalArgumentException("Invalid type for texture to blend!");
-        }
-    }
-
-    /**
-     * @return the result texture
-     */
-    public Texture getResultTexture() {
-        return resultTexture;
-    }
-
-    /**
-     * @return the result UV coordinates
-     */
-    public List<Vector2f> getResultUVS() {
-        return resultUVS;
-    }
-
-    /**
-     * @return the amount of added textures
-     */
-    public int getTexturesCount() {
-        return textureDatas.size();
-    }
-
-    /**
-     * @return the texture's mapping type
-     */
-    public int getMappingType() {
-        return mappingType;
-    }
-
-    /**
-     * @return <b>true</b> if the texture has at least one generated texture component and <b>false</b> otherwise
-     */
-    public boolean hasGeneratedTextures() {
-        if (textureDatas != null) {
-            for (TextureData textureData : textureDatas) {
-                if (textureData.texture instanceof GeneratedTexture) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This method determines if the given texture has no alpha channel.
-     * 
-     * @param texture
-     *            the texture to check for alpha channel
-     * @return <b>true</b> if the texture has no alpha channel and <b>false</b>
-     *         otherwise
-     */
-    private boolean isWithoutAlpha(TextureData textureData, BlenderContext blenderContext) {
-        ColorBand colorBand = new ColorBand(textureData.textureStructure, blenderContext);
-        if (!colorBand.hasTransparencies()) {
-            int type = ((Number) textureData.textureStructure.getFieldValue("type")).intValue();
-            if (type == TextureHelper.TEX_MAGIC) {
-                return true;
-            }
-            if (type == TextureHelper.TEX_VORONOI) {
-                int voronoiColorType = ((Number) textureData.textureStructure.getFieldValue("vn_coltype")).intValue();
-                return voronoiColorType != 0;// voronoiColorType == 0:
-                                             // intensity, voronoiColorType
-                                             // != 0: col1, col2 or col3
-            }
-            if (type == TextureHelper.TEX_CLOUDS) {
-                int sType = ((Number) textureData.textureStructure.getFieldValue("stype")).intValue();
-                return sType == 1;// sType==0: without colors, sType==1: with
-                                  // colors
-            }
-
-            // checking the flat textures for alpha values presence
-            if (type == TextureHelper.TEX_IMAGE) {
-                Image image = textureData.texture.getImage();
-                switch (image.getFormat()) {
-                    case BGR8:
-                    case DXT1:
-                    case Luminance16F:
-                    case Luminance32F:
-                    case Luminance8:
-                    case RGB111110F:
-                    case RGB16F:
-                    case RGB32F:
-                    case RGB565:
-                    case RGB8:
-                        return true;// these types have no alpha by definition
-                    case ABGR8:
-                    case DXT1A:
-                    case DXT3:
-                    case DXT5:
-                    case Luminance16FAlpha16F:
-                    case Luminance8Alpha8:
-                    case RGBA16F:
-                    case RGBA32F:
-                    case RGBA8:
-                    case ARGB8:
-                    case BGRA8:
-                    case RGB5A1:// with these types it is better to make sure if the texture is or is not transparent
-                        PixelInputOutput pixelInputOutput = PixelIOFactory.getPixelIO(image.getFormat());
-                        TexturePixel pixel = new TexturePixel();
-                        int depth = image.getDepth() == 0 ? 1 : image.getDepth();
-                        for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
-                            for (int x = 0; x < image.getWidth(); ++x) {
-                                for (int y = 0; y < image.getHeight(); ++y) {
-                                    pixelInputOutput.read(image, layerIndex, pixel, x, y);
-                                    if (pixel.alpha < 1.0f) {
-                                        return false;
-                                    }
-                                }
-                            }
-                        }
-                        return true;
-                    default:
-                        throw new IllegalStateException("Unknown image format: " + image.getFormat());
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This method scales the given texture to the given size.
-     * 
-     * @param texture
-     *            the texture to be scaled
-     * @param width
-     *            new width of the texture
-     * @param height
-     *            new height of the texture
-     */
-    private void scale(Texture2D texture, int width, int height) {
-        // first determine if scaling is required
-        boolean scaleRequired = texture.getImage().getWidth() != width || texture.getImage().getHeight() != height;
-
-        if (scaleRequired) {
-            Image image = texture.getImage();
-            BufferedImage sourceImage = ImageToAwt.convert(image, false, true, 0);
-
-            int sourceWidth = sourceImage.getWidth();
-            int sourceHeight = sourceImage.getHeight();
-
-            BufferedImage targetImage = new BufferedImage(width, height, sourceImage.getType());
-
-            Graphics2D g = targetImage.createGraphics();
-            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
-            g.drawImage(sourceImage, 0, 0, width, height, 0, 0, sourceWidth, sourceHeight, null);
-            g.dispose();
-
-            Image output = new ImageLoader().load(targetImage, false);
-            image.setWidth(width);
-            image.setHeight(height);
-            image.setData(output.getData(0));
-            image.setFormat(output.getFormat());
-        }
-    }
-
-    /**
-     * A simple class to aggregate the texture data (improves code quality).
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class TextureData {
-        /** The texture. */
-        public Texture           texture;
-        /** The texture blender (to mix the texture with its material color). */
-        public TextureBlender    textureBlender;
-        /** The type of UV coordinates. */
-        public UVCoordinatesType uvCoordinatesType;
-        /** The type of UV coordinates projection (for flat textures). */
-        public UVProjectionType  projectionType;
-        /** The texture sructure. */
-        public Structure         textureStructure;
-        /** The name of the user's UV coordinates that are used for this texture. */
-        public String            uvCoordinatesName;
-    }
-}

+ 0 - 157
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/DDSTexelData.java

@@ -1,157 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import com.jme3.math.FastMath;
-import com.jme3.texture.Image.Format;
-
-/**
- * The data that helps in bytes calculations for the result image.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class DDSTexelData {
-    /** The colors of the texes. */
-    private TexturePixel[][] colors;
-    /** The indexes of the texels. */
-    private long[]           indexes;
-    /** The alphas of the texels (might be null). */
-    private float[][]        alphas;
-    /** The indexels of texels alpha values (might be null). */
-    private long[]           alphaIndexes;
-    /** The counter of texel x column. */
-    private int              xCounter;
-    /** The counter of texel y row. */
-    private int              yCounter;
-    /** The width of the image in pixels. */
-    private int              widthInPixels;
-    /** The height of the image in pixels. */
-    private int              heightInPixels;
-    /** The total texel count. */
-    private int              xTexelCount;
-
-    /**
-     * Constructor. Allocates memory for data structures.
-     * 
-     * @param compressedSize
-     *            the size of compressed image (or its mipmap)
-     * @param widthToHeightRatio
-     *            width/height ratio for the image
-     * @param format
-     *            the format of the image
-     */
-    public DDSTexelData(int compressedSize, float widthToHeightRatio, Format format) {
-        int texelsCount = compressedSize * 8 / format.getBitsPerPixel() / 16;
-        this.colors = new TexturePixel[texelsCount][];
-        this.indexes = new long[texelsCount];
-        this.widthInPixels = (int) (0.5f * (float) Math.sqrt(this.getSizeInBytes() / widthToHeightRatio));
-        this.heightInPixels = (int) (this.widthInPixels / widthToHeightRatio);
-        this.xTexelCount = widthInPixels >> 2;
-        this.yCounter = (heightInPixels >> 2) - 1;// xCounter is 0 for now
-        if (format == Format.DXT3 || format == Format.DXT5) {
-            this.alphas = new float[texelsCount][];
-            this.alphaIndexes = new long[texelsCount];
-        }
-    }
-
-    /**
-     * This method adds a color and indexes for a texel.
-     * 
-     * @param colors
-     *            the colors of the texel
-     * @param indexes
-     *            the indexes of the texel
-     */
-    public void add(TexturePixel[] colors, int indexes) {
-        this.add(colors, indexes, null, 0);
-    }
-
-    /**
-     * This method adds a color, color indexes and alha values (with their
-     * indexes) for a texel.
-     * 
-     * @param colors
-     *            the colors of the texel
-     * @param indexes
-     *            the indexes of the texel
-     * @param alphas
-     *            the alpha values
-     * @param alphaIndexes
-     *            the indexes of the given alpha values
-     */
-    public void add(TexturePixel[] colors, int indexes, float[] alphas, long alphaIndexes) {
-        int index = yCounter * xTexelCount + xCounter;
-        this.colors[index] = colors;
-        this.indexes[index] = indexes;
-        if (alphas != null) {
-            this.alphas[index] = alphas;
-            this.alphaIndexes[index] = alphaIndexes;
-        }
-        ++this.xCounter;
-        if (this.xCounter >= this.xTexelCount) {
-            this.xCounter = 0;
-            --this.yCounter;
-        }
-    }
-
-    /**
-     * This method returns the values of the pixel located on the given
-     * coordinates on the result image.
-     * 
-     * @param x
-     *            the x coordinate of the pixel
-     * @param y
-     *            the y coordinate of the pixel
-     * @param result
-     *            the table where the result is stored
-     * @return <b>true</b> if the pixel was correctly read and <b>false</b> if
-     *         the position was outside the image sizes
-     */
-    public boolean getRGBA8(int x, int y, byte[] result) {
-        int xTexetlIndex = x % widthInPixels / 4;
-        int yTexelIndex = y % heightInPixels / 4;
-
-        int texelIndex = yTexelIndex * xTexelCount + xTexetlIndex;
-        if (texelIndex < colors.length) {
-            TexturePixel[] colors = this.colors[texelIndex];
-
-            // coordinates of the pixel in the selected texel
-            x = x - 4 * xTexetlIndex;// pixels are arranged from left to right
-            y = 3 - y - 4 * yTexelIndex;// pixels are arranged from bottom to top (that is why '3 - ...' is at the start)
-
-            int pixelIndexInTexel = (y * 4 + x) * (int) FastMath.log(colors.length, 2);
-            int alphaIndexInTexel = alphas != null ? (y * 4 + x) * (int) FastMath.log(alphas.length, 2) : 0;
-
-            // getting the pixel
-            int indexMask = colors.length - 1;
-            int colorIndex = (int) (this.indexes[texelIndex] >> pixelIndexInTexel & indexMask);
-            float alpha = this.alphas != null ? this.alphas[texelIndex][(int) (this.alphaIndexes[texelIndex] >> alphaIndexInTexel & 0x07)] : colors[colorIndex].alpha;
-            result[0] = (byte) (colors[colorIndex].red * 255.0f);
-            result[1] = (byte) (colors[colorIndex].green * 255.0f);
-            result[2] = (byte) (colors[colorIndex].blue * 255.0f);
-            result[3] = (byte) (alpha * 255.0f);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @return the size of the decompressed texel (in bytes)
-     */
-    public int getSizeInBytes() {
-        // indexes.length == count of texels
-        return indexes.length * 16 * 4;
-    }
-
-    /**
-     * @return image (mipmap) width
-     */
-    public int getPixelWidth() {
-        return widthInPixels;
-    }
-
-    /**
-     * @return image (mipmap) height
-     */
-    public int getPixelHeight() {
-        return heightInPixels;
-    }
-}

+ 0 - 282
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/GeneratedTexture.java

@@ -1,282 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import com.jme3.bounding.BoundingBox;
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
-import com.jme3.scene.plugins.blender.textures.TriangulatedTexture.TriangleTextureElement;
-import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.UVCoordinatesType;
-import com.jme3.scene.plugins.blender.textures.generating.TextureGenerator;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.Texture;
-import com.jme3.texture.TextureCubeMap;
-import com.jme3.util.TempVars;
-
-/**
- * The generated texture loaded from blender file. The texture is not generated
- * after being read. This class rather stores all required data and can compute
- * a pixel in the required 3D space position.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class GeneratedTexture extends Texture {
-    private static final int            POSITIVE_X       = 0;
-    private static final int            NEGATIVE_X       = 1;
-    private static final int            POSITIVE_Y       = 2;
-    private static final int            NEGATIVE_Y       = 3;
-    private static final int            POSITIVE_Z       = 4;
-    private static final int            NEGATIVE_Z       = 5;
-
-    // flag values
-    public static final int             TEX_COLORBAND    = 1;
-    public static final int             TEX_FLIPBLEND    = 2;
-    public static final int             TEX_NEGALPHA     = 4;
-    public static final int             TEX_CHECKER_ODD  = 8;
-    public static final int             TEX_CHECKER_EVEN = 16;
-    public static final int             TEX_PRV_ALPHA    = 32;
-    public static final int             TEX_PRV_NOR      = 64;
-    public static final int             TEX_REPEAT_XMIR  = 128;
-    public static final int             TEX_REPEAT_YMIR  = 256;
-    public static final int             TEX_FLAG_MASK    = TEX_COLORBAND | TEX_FLIPBLEND | TEX_NEGALPHA | TEX_CHECKER_ODD | TEX_CHECKER_EVEN | TEX_PRV_ALPHA | TEX_PRV_NOR | TEX_REPEAT_XMIR | TEX_REPEAT_YMIR;
-
-    /** Material-texture link structure. */
-    private final Structure             mTex;
-    /** Texture generateo for the specified texture type. */
-    private final TextureGenerator      textureGenerator;
-    /**
-     * The generated texture cast functions. They are used to cas a given point on a plane to a specified shape in 3D space.
-     * The functions should be ordered as the ordinal of a BlenderKey.CastFunction enums.
-     */
-    private final static CastFunction[] CAST_FUNCTIONS    = new CastFunction[] {
-        /**
-         * The cube casting function (does nothing except scaling if needed because the given points are already on a cube).
-         */
-        new CastFunction() {
-            @Override
-            public void cast(Vector3f pointToCast, float radius) {
-                //computed using the Thales' theorem
-                float length = 2 * pointToCast.subtractLocal(0.5f, 0.5f, 0.5f).length() * radius;
-                pointToCast.normalizeLocal().addLocal(0.5f, 0.5f, 0.5f).multLocal(length);
-            }
-        },
-        
-        /**
-         * The sphere casting function.
-         */
-        new CastFunction() {
-            /**
-             * The method casts a point on a plane to a sphere.
-             * The plane is one of the faces of a cube that has a edge of length 1 and center in (0.5 0.5, 0.5). This cube is a basic 3d area where generated texture
-             * is created.
-             * To cast a point on a cube face to a sphere that is inside the cube we perform several easy vector operations.
-             * 1. create a vector from the cube's center to the point
-             * 2. setting its length to 0.5 (the radius of the sphere)
-             * 3. adding the value of the cube's center to get a point on the sphere
-             * 
-             * The result is stored in the given vector.
-             * 
-             * @param pointToCast
-             *            the point on a plane that will be cast to a sphere
-             * @param radius
-             *            the radius of the sphere
-             */
-            @Override
-            public void cast(Vector3f pointToCast, float radius) {
-                pointToCast.subtractLocal(0.5f, 0.5f, 0.5f).normalizeLocal().multLocal(radius).addLocal(0.5f, 0.5f, 0.5f);
-            }
-        }
-    };
-
-    /**
-     * Constructor. Reads the required data from the 'tex' structure.
-     * 
-     * @param tex
-     *            the texture structure
-     * @param mTex
-     *            the material-texture link data structure
-     * @param textureGenerator
-     *            the generator for the required texture type
-     * @param blenderContext
-     *            the blender context
-     */
-    public GeneratedTexture(Structure tex, Structure mTex, TextureGenerator textureGenerator, BlenderContext blenderContext) {
-        this.mTex = mTex;
-        this.textureGenerator = textureGenerator;
-        this.textureGenerator.readData(tex, blenderContext);
-        super.setImage(new GeneratedTextureImage(textureGenerator.getImageFormat()));
-    }
-
-    /**
-     * This method computes the textyre color/intensity at the specified (u, v,
-     * s) position in 3D space.
-     * 
-     * @param pixel
-     *            the pixel where the result is stored
-     * @param u
-     *            the U factor
-     * @param v
-     *            the V factor
-     * @param s
-     *            the S factor
-     */
-    public void getPixel(TexturePixel pixel, float u, float v, float s) {
-        textureGenerator.getPixel(pixel, u, v, s);
-    }
-
-    /**
-     * This method triangulates the texture. In the result we get a set of small
-     * flat textures for each face of the given mesh. This can be later merged
-     * into one flat texture.
-     * 
-     * @param mesh
-     *            the mesh we create the texture for
-     * @param geometriesOMA
-     *            the old memory address of the geometries group that the given
-     *            mesh belongs to (required for bounding box calculations)
-     * @param coordinatesType
-     *            the types of UV coordinates
-     * @param blenderContext
-     *            the blender context
-     * @return triangulated texture
-     */
-    public TriangulatedTexture triangulate(Mesh mesh, Long geometriesOMA, UVCoordinatesType coordinatesType, BlenderContext blenderContext) {
-        TemporalMesh geometries = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
-
-        int[] coordinatesSwappingIndexes = new int[] { ((Number) mTex.getFieldValue("projx")).intValue(), ((Number) mTex.getFieldValue("projy")).intValue(), ((Number) mTex.getFieldValue("projz")).intValue() };
-        List<Vector3f> uvs = UVCoordinatesGenerator.generateUVCoordinatesFor3DTexture(mesh, coordinatesType, coordinatesSwappingIndexes, geometries);
-        Vector3f[] uvsArray = uvs.toArray(new Vector3f[uvs.size()]);
-        BoundingBox boundingBox = UVCoordinatesGenerator.getBoundingBox(geometries);
-        Set<TriangleTextureElement> triangleTextureElements = new TreeSet<TriangleTextureElement>(new Comparator<TriangleTextureElement>() {
-            @Override
-            public int compare(TriangleTextureElement o1, TriangleTextureElement o2) {
-                return o1.faceIndex - o2.faceIndex;
-            }
-        });
-        int[] indices = new int[3];
-        for (int i = 0; i < mesh.getTriangleCount(); ++i) {
-            mesh.getTriangle(i, indices);
-            triangleTextureElements.add(new TriangleTextureElement(i, boundingBox, this, uvsArray, indices, blenderContext));
-        }
-        return new TriangulatedTexture(triangleTextureElements, blenderContext);
-    }
-
-    /**
-     * Creates a texture for the sky. The result texture has 6 layers.
-     * @param size
-     *            the size of the texture (width and height are equal)
-     * @param horizontalColor
-     *            the horizon color
-     * @param zenithColor
-     *            the zenith color
-     * @param blenderContext
-     *            the blender context
-     * @return the sky texture
-     */
-    public TextureCubeMap generateSkyTexture(int size, ColorRGBA horizontalColor, ColorRGBA zenithColor, BlenderContext blenderContext) {
-        Image image = ImageUtils.createEmptyImage(Format.RGB8, size, size, 6);
-        PixelInputOutput pixelIO = PixelIOFactory.getPixelIO(image.getFormat());
-        TexturePixel pixel = new TexturePixel();
-
-        float delta = 1 / (float) (size - 1);
-        float sideV, sideS = 1, forwardU = 1, forwardV, upS;
-        TempVars tempVars = TempVars.get();
-        CastFunction castFunction = CAST_FUNCTIONS[blenderContext.getBlenderKey().getSkyGeneratedTextureShape().ordinal()];
-        float castRadius = blenderContext.getBlenderKey().getSkyGeneratedTextureRadius();
-
-        for (int x = 0; x < size; ++x) {
-            sideV = 1;
-            forwardV = 1;
-            upS = 0;
-            for (int y = 0; y < size; ++y) {
-                castFunction.cast(tempVars.vect1.set(1, sideV, sideS), castRadius);
-                textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
-                pixelIO.write(image, NEGATIVE_X, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// right
-
-                castFunction.cast(tempVars.vect1.set(0, sideV, 1 - sideS), castRadius);
-                textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
-                pixelIO.write(image, POSITIVE_X, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// left
-
-                castFunction.cast(tempVars.vect1.set(forwardU, forwardV, 0), castRadius);
-                textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
-                pixelIO.write(image, POSITIVE_Z, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// front
-
-                castFunction.cast(tempVars.vect1.set(1 - forwardU, forwardV, 1), castRadius);
-                textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
-                pixelIO.write(image, NEGATIVE_Z, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// back
-
-                castFunction.cast(tempVars.vect1.set(forwardU, 0, upS), castRadius);
-                textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
-                pixelIO.write(image, NEGATIVE_Y, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// top
-
-                castFunction.cast(tempVars.vect1.set(forwardU, 1, 1 - upS), castRadius);
-                textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
-                pixelIO.write(image, POSITIVE_Y, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// bottom
-
-                sideV = FastMath.clamp(sideV - delta, 0, 1);
-                forwardV = FastMath.clamp(forwardV - delta, 0, 1);
-                upS = FastMath.clamp(upS + delta, 0, 1);
-            }
-            sideS = FastMath.clamp(sideS - delta, 0, 1);
-            forwardU = FastMath.clamp(forwardU - delta, 0, 1);
-        }
-        tempVars.release();
-
-        return new TextureCubeMap(image);
-    }
-
-    @Override
-    public void setWrap(WrapAxis axis, WrapMode mode) {
-    }
-
-    @Override
-    public void setWrap(WrapMode mode) {
-    }
-
-    @Override
-    public WrapMode getWrap(WrapAxis axis) {
-        return null;
-    }
-
-    @Override
-    public Type getType() {
-        return Type.ThreeDimensional;
-    }
-
-    @Override
-    public Texture createSimpleClone() {
-        return null;
-    }
-
-    /**
-     * Private class to give the format of the 'virtual' 3D texture image.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class GeneratedTextureImage extends Image {
-        public GeneratedTextureImage(Format imageFormat) {
-            super.format = imageFormat;
-        }
-    }
-
-    /**
-     * The casting functions to create a sky generated texture against selected shape of a selected size.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static interface CastFunction {
-        void cast(Vector3f pointToCast, float radius);
-    }
-}

+ 0 - 136
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/ImageLoader.java

@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures;
-
-import com.jme3.asset.AssetManager;
-import com.jme3.asset.TextureKey;
-import com.jme3.scene.plugins.blender.file.BlenderInputStream;
-import com.jme3.texture.Image;
-import com.jme3.texture.Texture;
-import com.jme3.texture.plugins.AWTLoader;
-import com.jme3.texture.plugins.HDRLoader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * An image loader class. It uses three loaders (AWTLoader, TGALoader and DDSLoader) in an attempt to load the image from the given
- * input stream.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class ImageLoader extends AWTLoader {
-    private static final Logger LOGGER    = Logger.getLogger(ImageLoader.class.getName());
-    private static final Logger hdrLogger = Logger.getLogger(HDRLoader.class.getName()); // Used to silence HDR Errors
-    
-    /**
-     * List of Blender-Supported Texture Extensions (we have to guess them, so
-     * the AssetLoader can find them. Not good, but better than nothing.
-     * Source: https://docs.blender.org/manual/en/dev/data_system/files/media/image_formats.html
-     */
-    private static final String[] extensions = new String[]
-        { /* Windows Bitmap */".bmp",
-          /* Iris */ ".sgi", ".rgb", ".bw",
-          /* PNG */ ".png",
-          /* JPEG */ ".jpg", ".jpeg",
-          /* JPEG 2000 */ ".jp2", ".j2c",
-          /* Targa */".tga",
-          /* Cineon & DPX */".cin", ".dpx",
-          /* OpenEXR */ ".exr",
-          /* Radiance HDR */ ".hdr",
-          /* TIFF */ ".tif", ".tiff",
-          /* DDS (Direct X) */ ".dds" };
-
-    /**
-     * This method loads a image which is packed into the blender file.
-     * It makes use of all the registered AssetLoaders
-     * 
-     * @param inputStream
-     *            blender input stream
-     * @param startPosition
-     *            position in the stream where the image data starts
-     * @param flipY
-     *            if the image should be flipped (does not work with DirectX image)
-     * @return loaded image or null if it could not be loaded
-     * @deprecated This method has only been left in for API compability.
-     * Use loadTexture instead
-     */
-    public Image loadImage(AssetManager assetManager, BlenderInputStream inputStream, int startPosition, boolean flipY) {
-        Texture tex = loadTexture(assetManager, inputStream, startPosition, flipY);
-        
-        if (tex == null) {
-            return null;
-        } else {
-            return tex.getImage();
-        }
-    }
-    
-    /**
-     * This method loads a texture which is packed into the blender file.
-     * It makes use of all the registered AssetLoaders
-     * 
-     * @param inputStream
-     *            blender input stream
-     * @param startPosition
-     *            position in the stream where the image data starts
-     * @param flipY
-     *            if the image should be flipped (does not work with DirectX image)
-     * @return loaded texture or null if it could not be loaded
-     */
-    public Texture loadTexture(AssetManager assetManager, BlenderInputStream inputStream, int startPosition, boolean flipY) {
-        inputStream.setPosition(startPosition);
-        TextureKey tKey;
-        Texture result = null;
-        
-        hdrLogger.setLevel(Level.SEVERE); // When we bruteforce try HDR on a non hdr file, it prints unreadable chars
-        
-        for (String ext: extensions) {
-            tKey = new TextureKey("dummy" + ext, flipY);
-            try {
-                result = assetManager.loadAssetFromStream(tKey, inputStream);
-            } catch (Exception e) {
-                continue;
-            }
-            
-            if (result != null) {
-                break; // Could locate a possible asset
-            }
-        }
-        
-        if (result == null) {
-            LOGGER.warning("Texture could not be loaded by any of the available loaders!\n"
-                    + "Since the file has been packed into the blender file, there is no"
-                    + "way for us to tell you which texture it was.");
-        }
-        
-        return result;
-    }
-}

+ 0 - 473
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/ImageUtils.java

@@ -1,473 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import java.awt.color.ColorSpace;
-import java.awt.geom.AffineTransform;
-import java.awt.image.AffineTransformOp;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorConvertOp;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-import jme3tools.converters.ImageToAwt;
-import jme3tools.converters.RGB565;
-
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.util.BufferUtils;
-
-/**
- * This utility class has the methods that deal with images.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public final class ImageUtils {
-    /**
-     * Creates an image of the given size and depth.
-     * @param format
-     *            the image format
-     * @param width
-     *            the image width
-     * @param height
-     *            the image height
-     * @param depth
-     *            the image depth
-     * @return the new image instance
-     */
-    public static Image createEmptyImage(Format format, int width, int height, int depth) {
-        int bufferSize = width * height * (format.getBitsPerPixel() >> 3);
-        if (depth < 2) {
-            return new Image(format, width, height, BufferUtils.createByteBuffer(bufferSize), com.jme3.texture.image.ColorSpace.Linear);
-        }
-        ArrayList<ByteBuffer> data = new ArrayList<ByteBuffer>(depth);
-        for (int i = 0; i < depth; ++i) {
-            data.add(BufferUtils.createByteBuffer(bufferSize));
-        }
-        return new Image(Format.RGB8, width, height, depth, data, com.jme3.texture.image.ColorSpace.Linear);
-    }
-
-    /**
-     * The method sets a color for the given pixel by merging the two given colors.
-     * The lowIntensityColor will be most visible when the pixel has low intensity.
-     * The highIntensityColor will be most visible when the pixel has high intensity.
-     * 
-     * @param pixel
-     *            the pixel that will have the colors altered
-     * @param lowIntensityColor
-     *            the low intensity color
-     * @param highIntensityColor
-     *            the high intensity color
-     * @return the altered pixel (the same instance)
-     */
-    public static TexturePixel color(TexturePixel pixel, ColorRGBA lowIntensityColor, ColorRGBA highIntensityColor) {
-        float intensity = pixel.intensity;
-        pixel.fromColor(lowIntensityColor);
-        pixel.mult(1 - pixel.intensity);
-        pixel.add(highIntensityColor.mult(intensity));
-        return pixel;
-    }
-
-    /**
-     * This method merges two given images. The result is stored in the
-     * 'target' image.
-     * 
-     * @param targetImage
-     *            the target image
-     * @param sourceImage
-     *            the source image
-     */
-    public static void merge(Image targetImage, Image sourceImage) {
-        if (sourceImage.getDepth() != targetImage.getDepth()) {
-            throw new IllegalArgumentException("The given images should have the same depth to merge them!");
-        }
-        if (sourceImage.getWidth() != targetImage.getWidth()) {
-            throw new IllegalArgumentException("The given images should have the same width to merge them!");
-        }
-        if (sourceImage.getHeight() != targetImage.getHeight()) {
-            throw new IllegalArgumentException("The given images should have the same height to merge them!");
-        }
-
-        PixelInputOutput sourceIO = PixelIOFactory.getPixelIO(sourceImage.getFormat());
-        PixelInputOutput targetIO = PixelIOFactory.getPixelIO(targetImage.getFormat());
-        TexturePixel sourcePixel = new TexturePixel();
-        TexturePixel targetPixel = new TexturePixel();
-        int depth = targetImage.getDepth() == 0 ? 1 : targetImage.getDepth();
-
-        for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
-            for (int x = 0; x < sourceImage.getWidth(); ++x) {
-                for (int y = 0; y < sourceImage.getHeight(); ++y) {
-                    sourceIO.read(sourceImage, layerIndex, sourcePixel, x, y);
-                    targetIO.read(targetImage, layerIndex, targetPixel, x, y);
-                    targetPixel.merge(sourcePixel);
-                    targetIO.write(targetImage, layerIndex, targetPixel, x, y);
-                }
-            }
-        }
-    }
-
-    /**
-     * This method merges two given images. The result is stored in the
-     * 'target' image.
-     * 
-     * @param targetImage
-     *            the target image
-     * @param sourceImage
-     *            the source image
-     */
-    public static void mix(Image targetImage, Image sourceImage) {
-        if (sourceImage.getDepth() != targetImage.getDepth()) {
-            throw new IllegalArgumentException("The given images should have the same depth to merge them!");
-        }
-        if (sourceImage.getWidth() != targetImage.getWidth()) {
-            throw new IllegalArgumentException("The given images should have the same width to merge them!");
-        }
-        if (sourceImage.getHeight() != targetImage.getHeight()) {
-            throw new IllegalArgumentException("The given images should have the same height to merge them!");
-        }
-
-        PixelInputOutput sourceIO = PixelIOFactory.getPixelIO(sourceImage.getFormat());
-        PixelInputOutput targetIO = PixelIOFactory.getPixelIO(targetImage.getFormat());
-        TexturePixel sourcePixel = new TexturePixel();
-        TexturePixel targetPixel = new TexturePixel();
-        int depth = targetImage.getDepth() == 0 ? 1 : targetImage.getDepth();
-
-        for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
-            for (int x = 0; x < sourceImage.getWidth(); ++x) {
-                for (int y = 0; y < sourceImage.getHeight(); ++y) {
-                    sourceIO.read(sourceImage, layerIndex, sourcePixel, x, y);
-                    targetIO.read(targetImage, layerIndex, targetPixel, x, y);
-                    targetPixel.mix(sourcePixel);
-                    targetIO.write(targetImage, layerIndex, targetPixel, x, y);
-                }
-            }
-        }
-    }
-
-    /**
-     * Resizes the image to the given width and height.
-     * @param source
-     *            the source image (this remains untouched, the new image instance is created)
-     * @param width
-     *            the target image width
-     * @param height
-     *            the target image height
-     * @return the resized image
-     */
-    public static Image resizeTo(Image source, int width, int height) {
-        BufferedImage sourceImage = ImageToAwt.convert(source, false, false, 0);
-
-        double scaleX = width / (double) sourceImage.getWidth();
-        double scaleY = height / (double) sourceImage.getHeight();
-        AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY);
-        AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR);
-
-        BufferedImage scaledImage = bilinearScaleOp.filter(sourceImage, new BufferedImage(width, height, sourceImage.getType()));
-        return ImageUtils.toJmeImage(scaledImage, source.getFormat());
-    }
-
-    /**
-     * This method converts the given texture into normal-map texture.
-     * 
-     * @param source
-     *            the source texture
-     * @param strengthFactor
-     *            the normal strength factor
-     * @return normal-map texture
-     */
-    public static Image convertToNormalMapTexture(Image source, float strengthFactor) {
-        BufferedImage sourceImage = ImageToAwt.convert(source, false, false, 0);
-
-        BufferedImage heightMap = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
-        BufferedImage bumpMap = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
-        ColorConvertOp gscale = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
-        gscale.filter(sourceImage, heightMap);
-
-        Vector3f S = new Vector3f();
-        Vector3f T = new Vector3f();
-        Vector3f N = new Vector3f();
-
-        for (int x = 0; x < bumpMap.getWidth(); ++x) {
-            for (int y = 0; y < bumpMap.getHeight(); ++y) {
-                // generating bump pixel
-                S.x = 1;
-                S.y = 0;
-                S.z = strengthFactor * ImageUtils.getHeight(heightMap, x + 1, y) - strengthFactor * ImageUtils.getHeight(heightMap, x - 1, y);
-                T.x = 0;
-                T.y = 1;
-                T.z = strengthFactor * ImageUtils.getHeight(heightMap, x, y + 1) - strengthFactor * ImageUtils.getHeight(heightMap, x, y - 1);
-
-                float den = (float) Math.sqrt(S.z * S.z + T.z * T.z + 1);
-                N.x = -S.z;
-                N.y = -T.z;
-                N.z = 1;
-                N.divideLocal(den);
-
-                // setting the pixel in the result image
-                bumpMap.setRGB(x, y, ImageUtils.vectorToColor(N.x, N.y, N.z));
-            }
-        }
-        return ImageUtils.toJmeImage(bumpMap, source.getFormat());
-    }
-
-    /**
-     * This method converts the given texture into black and whit (grayscale) texture.
-     * 
-     * @param source
-     *            the source texture
-     * @return grayscale texture
-     */
-    public static Image convertToGrayscaleTexture(Image source) {
-        BufferedImage sourceImage = ImageToAwt.convert(source, false, false, 0);
-        ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
-        op.filter(sourceImage, sourceImage);
-        return ImageUtils.toJmeImage(sourceImage, source.getFormat());
-    }
-
-    /**
-     * This method decompresses the given image. If the given image is already
-     * decompressed nothing happens and it is simply returned.
-     * 
-     * @param image
-     *            the image to decompress
-     * @return the decompressed image
-     */
-    public static Image decompress(Image image) {
-        Format format = image.getFormat();
-        int depth = image.getDepth();
-        if (depth == 0) {
-            depth = 1;
-        }
-        ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
-        int[] sizes = image.getMipMapSizes() != null ? image.getMipMapSizes() : new int[1];
-        int[] newMipmapSizes = image.getMipMapSizes() != null ? new int[image.getMipMapSizes().length] : null;
-
-        for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
-            ByteBuffer data = image.getData(dataLayerIndex);
-            data.rewind();
-            if (sizes.length == 1) {
-                sizes[0] = data.remaining();
-            }
-            float widthToHeightRatio = image.getWidth() / image.getHeight();// this should always be constant for each mipmap
-            List<DDSTexelData> texelDataList = new ArrayList<DDSTexelData>(sizes.length);
-            int maxPosition = 0, resultSize = 0;
-
-            for (int sizeIndex = 0; sizeIndex < sizes.length; ++sizeIndex) {
-                maxPosition += sizes[sizeIndex];
-                DDSTexelData texelData = new DDSTexelData(sizes[sizeIndex], widthToHeightRatio, format);
-                texelDataList.add(texelData);
-                switch (format) {
-                    case DXT1:// BC1
-                    case DXT1A:
-                        while (data.position() < maxPosition) {
-                            TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
-                            short c0 = data.getShort();
-                            short c1 = data.getShort();
-                            int col0 = RGB565.RGB565_to_ARGB8(c0);
-                            int col1 = RGB565.RGB565_to_ARGB8(c1);
-                            colors[0].fromARGB8(col0);
-                            colors[1].fromARGB8(col1);
-
-                            if (col0 > col1) {
-                                // creating color2 = 2/3color0 + 1/3color1
-                                colors[2].fromPixel(colors[0]);
-                                colors[2].mult(2);
-                                colors[2].add(colors[1]);
-                                colors[2].divide(3);
-
-                                // creating color3 = 1/3color0 + 2/3color1;
-                                colors[3].fromPixel(colors[1]);
-                                colors[3].mult(2);
-                                colors[3].add(colors[0]);
-                                colors[3].divide(3);
-                            } else {
-                                // creating color2 = 1/2color0 + 1/2color1
-                                colors[2].fromPixel(colors[0]);
-                                colors[2].add(colors[1]);
-                                colors[2].mult(0.5f);
-
-                                colors[3].fromARGB8(0);
-                            }
-                            int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
-                            texelData.add(colors, indexes);
-                        }
-                        break;
-                    case DXT3:// BC2
-                        while (data.position() < maxPosition) {
-                            TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
-                            long alpha = data.getLong();
-                            float[] alphas = new float[16];
-                            long alphasIndex = 0;
-                            for (int i = 0; i < 16; ++i) {
-                                alphasIndex |= i << i * 4;
-                                byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
-                                alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
-                            }
-
-                            short c0 = data.getShort();
-                            short c1 = data.getShort();
-                            int col0 = RGB565.RGB565_to_ARGB8(c0);
-                            int col1 = RGB565.RGB565_to_ARGB8(c1);
-                            colors[0].fromARGB8(col0);
-                            colors[1].fromARGB8(col1);
-
-                            // creating color2 = 2/3color0 + 1/3color1
-                            colors[2].fromPixel(colors[0]);
-                            colors[2].mult(2);
-                            colors[2].add(colors[1]);
-                            colors[2].divide(3);
-
-                            // creating color3 = 1/3color0 + 2/3color1;
-                            colors[3].fromPixel(colors[1]);
-                            colors[3].mult(2);
-                            colors[3].add(colors[0]);
-                            colors[3].divide(3);
-
-                            int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
-                            texelData.add(colors, indexes, alphas, alphasIndex);
-                        }
-                        break;
-                    case DXT5:// BC3
-                        float[] alphas = new float[8];
-                        while (data.position() < maxPosition) {
-                            TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
-                            alphas[0] = data.get() * 255.0f;
-                            alphas[1] = data.get() * 255.0f;
-                            //the casts to long must be done here because otherwise 32-bit integers would be shifetd by 32 and 40 bits which would result in improper values
-                            long alphaIndices = data.get() | (long)data.get() << 8 | (long)data.get() << 16 | (long)data.get() << 24 | (long)data.get() << 32 | (long)data.get() << 40;
-                            if (alphas[0] > alphas[1]) {// 6 interpolated alpha values.
-                                alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
-                                alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
-                                alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
-                                alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
-                                alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
-                                alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
-                            } else {
-                                alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
-                                alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
-                                alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
-                                alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
-                                alphas[6] = 0;
-                                alphas[7] = 1;
-                            }
-
-                            short c0 = data.getShort();
-                            short c1 = data.getShort();
-                            int col0 = RGB565.RGB565_to_ARGB8(c0);
-                            int col1 = RGB565.RGB565_to_ARGB8(c1);
-                            colors[0].fromARGB8(col0);
-                            colors[1].fromARGB8(col1);
-
-                            // creating color2 = 2/3color0 + 1/3color1
-                            colors[2].fromPixel(colors[0]);
-                            colors[2].mult(2);
-                            colors[2].add(colors[1]);
-                            colors[2].divide(3);
-
-                            // creating color3 = 1/3color0 + 2/3color1;
-                            colors[3].fromPixel(colors[1]);
-                            colors[3].mult(2);
-                            colors[3].add(colors[0]);
-                            colors[3].divide(3);
-
-                            int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
-                            texelData.add(colors, indexes, alphas, alphaIndices);
-                        }
-                        break;
-                    default:
-                        throw new IllegalStateException("Unknown compressed format: " + format);
-                }
-                newMipmapSizes[sizeIndex] = texelData.getSizeInBytes();
-                resultSize += texelData.getSizeInBytes();
-            }
-            byte[] bytes = new byte[resultSize];
-            int offset = 0;
-            byte[] pixelBytes = new byte[4];
-            for (DDSTexelData texelData : texelDataList) {
-                for (int i = 0; i < texelData.getPixelWidth(); ++i) {
-                    for (int j = 0; j < texelData.getPixelHeight(); ++j) {
-                        if (texelData.getRGBA8(i, j, pixelBytes)) {
-                            bytes[offset + (j * texelData.getPixelWidth() + i) * 4] = pixelBytes[0];
-                            bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 1] = pixelBytes[1];
-                            bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 2] = pixelBytes[2];
-                            bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 3] = pixelBytes[3];
-                        } else {
-                            break;
-                        }
-                    }
-                }
-                offset += texelData.getSizeInBytes();
-            }
-            dataArray.add(BufferUtils.createByteBuffer(bytes));
-        }
-
-        Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray, com.jme3.texture.image.ColorSpace.Linear) : 
-                                   new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0), com.jme3.texture.image.ColorSpace.Linear);
-        if (newMipmapSizes != null) {
-            result.setMipMapSizes(newMipmapSizes);
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the height represented by the specified pixel in the
-     * given texture. The given texture should be a height-map.
-     * 
-     * @param image
-     *            the height-map texture
-     * @param x
-     *            pixel's X coordinate
-     * @param y
-     *            pixel's Y coordinate
-     * @return height represented by the given texture in the specified location
-     */
-    private static int getHeight(BufferedImage image, int x, int y) {
-        if (x < 0) {
-            x = 0;
-        } else if (x >= image.getWidth()) {
-            x = image.getWidth() - 1;
-        }
-        if (y < 0) {
-            y = 0;
-        } else if (y >= image.getHeight()) {
-            y = image.getHeight() - 1;
-        }
-        return image.getRGB(x, y) & 0xff;
-    }
-
-    /**
-     * This method transforms given vector's coordinates into ARGB color (A is
-     * always = 255).
-     * 
-     * @param x
-     *            X factor of the vector
-     * @param y
-     *            Y factor of the vector
-     * @param z
-     *            Z factor of the vector
-     * @return color representation of the given vector
-     */
-    private static int vectorToColor(float x, float y, float z) {
-        int r = Math.round(255 * (x + 1f) / 2f);
-        int g = Math.round(255 * (y + 1f) / 2f);
-        int b = Math.round(255 * (z + 1f) / 2f);
-        return (255 << 24) + (r << 16) + (g << 8) + b;
-    }
-
-    /**
-     * Converts java awt image to jme image.
-     * @param bufferedImage
-     *            the java awt image
-     * @param format
-     *            the result image format
-     * @return the jme image
-     */
-    private static Image toJmeImage(BufferedImage bufferedImage, Format format) {
-        ByteBuffer byteBuffer = BufferUtils.createByteBuffer(bufferedImage.getWidth() * bufferedImage.getHeight() * 3);
-        ImageToAwt.convert(bufferedImage, format, byteBuffer);
-        return new Image(format, bufferedImage.getWidth(), bufferedImage.getHeight(), byteBuffer, com.jme3.texture.image.ColorSpace.Linear);
-    }
-}

+ 0 - 691
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TextureHelper.java

@@ -1,691 +0,0 @@
-/*
- * Copyright (c) 2009-2018 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.textures;
-
-import java.awt.geom.AffineTransform;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.asset.AssetInfo;
-import com.jme3.asset.AssetLoadException;
-import com.jme3.asset.AssetManager;
-import com.jme3.asset.AssetNotFoundException;
-import com.jme3.asset.BlenderKey;
-import com.jme3.asset.GeneratedTextureKey;
-import com.jme3.asset.TextureKey;
-import com.jme3.math.Vector2f;
-import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
-import com.jme3.scene.plugins.blender.file.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.materials.MaterialContext;
-import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.UVCoordinatesType;
-import com.jme3.scene.plugins.blender.textures.blending.TextureBlender;
-import com.jme3.scene.plugins.blender.textures.blending.TextureBlenderFactory;
-import com.jme3.scene.plugins.blender.textures.generating.TextureGeneratorFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Texture;
-import com.jme3.texture.Texture.MinFilter;
-import com.jme3.texture.Texture.WrapMode;
-import com.jme3.texture.Texture2D;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.util.BufferUtils;
-import com.jme3.util.PlaceholderAssets;
-
-/**
- * A class that is used in texture calculations.
- * 
- * @author Marcin Roguski
- */
-public class TextureHelper extends AbstractBlenderHelper {
-    private static final Logger     LOGGER                  = Logger.getLogger(TextureHelper.class.getName());
-
-    // texture types
-    public static final int         TEX_NONE                = 0;
-    public static final int         TEX_CLOUDS              = 1;
-    public static final int         TEX_WOOD                = 2;
-    public static final int         TEX_MARBLE              = 3;
-    public static final int         TEX_MAGIC               = 4;
-    public static final int         TEX_BLEND               = 5;
-    public static final int         TEX_STUCCI              = 6;
-    public static final int         TEX_NOISE               = 7;
-    public static final int         TEX_IMAGE               = 8;
-    public static final int         TEX_PLUGIN              = 9;
-    public static final int         TEX_ENVMAP              = 10;
-    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+
-    public static final int         TEX_OCEAN               = 16;                                                                                                                                          // v. 26+
-
-    public static final Type[]      TEXCOORD_TYPES          = new Type[] { Type.TexCoord, Type.TexCoord2, Type.TexCoord3, Type.TexCoord4, Type.TexCoord5, Type.TexCoord6, Type.TexCoord7, Type.TexCoord8 };
-
-    private TextureGeneratorFactory textureGeneratorFactory = new TextureGeneratorFactory();
-
-    /**
-     * This constructor parses the given blender version and stores the result.
-     * It creates noise generator and texture generators.
-     * 
-     * @param blenderVersion
-     *            the version read from the blend file
-     * @param blenderContext
-     *            the blender context
-     */
-    public TextureHelper(String blenderVersion, BlenderContext blenderContext) {
-        super(blenderVersion, blenderContext);
-    }
-
-    /**
-     * This class returns a texture read from the file or from packed blender
-     * data. The returned texture has the name set to the value of its blender
-     * type.
-     * 
-     * @param textureStructure
-     *            texture structure filled with data
-     * @param blenderContext
-     *            the blender context
-     * @return the texture that can be used by JME engine
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is
-     *             somehow invalid or corrupted
-     */
-    public Texture getTexture(Structure textureStructure, Structure mTex, BlenderContext blenderContext) throws BlenderFileException {
-        Texture result = (Texture) blenderContext.getLoadedFeature(textureStructure.getOldMemoryAddress(), LoadedDataType.FEATURE);
-        if (result != null) {
-            return result;
-        }
-
-        if ("ID".equals(textureStructure.getType())) {
-            LOGGER.fine("Loading texture from external blend file.");
-            return (Texture) this.loadLibrary(textureStructure);
-        }
-
-        int type = ((Number) textureStructure.getFieldValue("type")).intValue();
-        int imaflag = ((Number) textureStructure.getFieldValue("imaflag")).intValue();
-
-        switch (type) {
-            case TEX_IMAGE:// (it is first because probably this will be most commonly used)
-                Pointer pImage = (Pointer) textureStructure.getFieldValue("ima");
-                if (pImage.isNotNull()) {
-                    Structure image = pImage.fetchData().get(0);
-                    Texture loadedTexture = this.loadImageAsTexture(image, imaflag, blenderContext);
-                    if (loadedTexture != null) {
-                        result = loadedTexture;
-                        this.applyColorbandAndColorFactors(textureStructure, result.getImage(), blenderContext);
-                    }
-                }
-                break;
-            case TEX_CLOUDS:
-            case TEX_WOOD:
-            case TEX_MARBLE:
-            case TEX_MAGIC:
-            case TEX_BLEND:
-            case TEX_STUCCI:
-            case TEX_NOISE:
-            case TEX_MUSGRAVE:
-            case TEX_VORONOI:
-            case TEX_DISTNOISE:
-                result = new GeneratedTexture(textureStructure, mTex, textureGeneratorFactory.createTextureGenerator(type), blenderContext);
-                break;
-            case TEX_NONE:// No texture, do nothing
-                break;
-            case TEX_POINTDENSITY:
-            case TEX_VOXELDATA:
-            case TEX_PLUGIN:
-            case TEX_ENVMAP:
-            case TEX_OCEAN:
-                LOGGER.log(Level.WARNING, "Unsupported texture type: {0} for texture: {1}", new Object[] { type, textureStructure.getName() });
-                break;
-            default:
-                throw new BlenderFileException("Unknown texture type: " + type + " for texture: " + textureStructure.getName());
-        }
-        if (result != null) {
-            result.setName(textureStructure.getName());
-            result.setWrap(WrapMode.Repeat);
-
-            // decide if the mipmaps will be generated
-            switch (blenderContext.getBlenderKey().getMipmapGenerationMethod()) {
-                case ALWAYS_GENERATE:
-                    result.setMinFilter(MinFilter.Trilinear);
-                    break;
-                case NEVER_GENERATE:
-                    break;
-                case GENERATE_WHEN_NEEDED:
-                    if ((imaflag & 0x04) != 0) {
-                        result.setMinFilter(MinFilter.Trilinear);
-                    }
-                    break;
-                default:
-                    throw new IllegalStateException("Unknown mipmap generation method: " + blenderContext.getBlenderKey().getMipmapGenerationMethod());
-            }
-
-            if (type != TEX_IMAGE) {// only generated textures should have this key
-                result.setKey(new GeneratedTextureKey(textureStructure.getName()));
-            }
-
-            if (LOGGER.isLoggable(Level.FINE)) {
-                LOGGER.log(Level.FINE, "Adding texture {0} to the loaded features with OMA = {1}", new Object[] { result.getName(), textureStructure.getOldMemoryAddress() });
-            }
-            blenderContext.addLoadedFeatures(textureStructure.getOldMemoryAddress(), LoadedDataType.STRUCTURE, textureStructure);
-            blenderContext.addLoadedFeatures(textureStructure.getOldMemoryAddress(), LoadedDataType.FEATURE, result);
-        }
-        return result;
-    }
-
-    /**
-     * This class returns a texture read from the file or from packed blender
-     * data.
-     * 
-     * @param imageStructure
-     *            image structure filled with data
-     * @param imaflag
-     *            the image flag
-     * @param blenderContext
-     *            the blender context
-     * @return the texture that can be used by JME engine
-     * @throws BlenderFileException
-     *             this exception is thrown when the blend file structure is
-     *             somehow invalid or corrupted
-     */
-    public Texture loadImageAsTexture(Structure imageStructure, int imaflag, BlenderContext blenderContext) throws BlenderFileException {
-        LOGGER.log(Level.FINE, "Fetching texture with OMA = {0}", imageStructure.getOldMemoryAddress());
-        Texture result = null;
-        Image im = (Image) blenderContext.getLoadedFeature(imageStructure.getOldMemoryAddress(), LoadedDataType.FEATURE);
-       // if (im == null) {  HACK force reaload always, as constructor in else case is destroying the TextureKeys!
-            if ("ID".equals(imageStructure.getType())) {
-                LOGGER.fine("Loading texture from external blend file.");
-                result = (Texture) this.loadLibrary(imageStructure);
-            } else {
-                String texturePath = imageStructure.getFieldValue("name").toString();
-                Pointer pPackedFile = (Pointer) imageStructure.getFieldValue("packedfile");
-                if (pPackedFile.isNull()) {
-                    LOGGER.log(Level.FINE, "Reading texture from file: {0}", texturePath);
-                    result = this.loadImageFromFile(texturePath, imaflag, blenderContext);
-                } else {
-                    LOGGER.fine("Packed texture. Reading directly from the blend file!");
-                    Structure packedFile = pPackedFile.fetchData().get(0);
-                    Pointer pData = (Pointer) packedFile.getFieldValue("data");
-                    FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pData.getOldMemoryAddress());
-                    blenderContext.getInputStream().setPosition(dataFileBlock.getBlockPosition());
-
-                    // Should the texture be flipped? It works for sinbad ..
-                    result = new ImageLoader().loadTexture(blenderContext.getAssetManager(), blenderContext.getInputStream(), dataFileBlock.getBlockPosition(), true);
-                    if (result == null) {
-                        result = new Texture2D(PlaceholderAssets.getPlaceholderImage(blenderContext.getAssetManager()));
-                        LOGGER.fine("ImageLoader returned null. It probably failed to load the packed texture, using placeholder asset");
-                    }
-                }
-            }
-        //} else {
-       //     result = new Texture2D(im);
-       // }
-
-        if (result != null) {// render result is not being loaded
-            blenderContext.addLoadedFeatures(imageStructure.getOldMemoryAddress(), LoadedDataType.STRUCTURE, imageStructure);
-            blenderContext.addLoadedFeatures(imageStructure.getOldMemoryAddress(), LoadedDataType.FEATURE, result.getImage());
-            result.setName(imageStructure.getName());
-        }
-        return result;
-    }
-
-    /**
-     * This method creates the affine transform that is used to transform a
-     * triangle defined by one UV coordinates into a triangle defined by
-     * different UV's.
-     * 
-     * @param source
-     *            source UV coordinates
-     * @param dest
-     *            target UV coordinates
-     * @param sourceSize
-     *            the width and height of the source image
-     * @param targetSize
-     *            the width and height of the target image
-     * @return affine transform to transform one triangle to another
-     */
-    public AffineTransform createAffineTransform(Vector2f[] source, Vector2f[] dest, int[] sourceSize, int[] targetSize) {
-        float x11 = source[0].getX() * sourceSize[0];
-        float x12 = source[0].getY() * sourceSize[1];
-        float x21 = source[1].getX() * sourceSize[0];
-        float x22 = source[1].getY() * sourceSize[1];
-        float x31 = source[2].getX() * sourceSize[0];
-        float x32 = source[2].getY() * sourceSize[1];
-        float y11 = dest[0].getX() * targetSize[0];
-        float y12 = dest[0].getY() * targetSize[1];
-        float y21 = dest[1].getX() * targetSize[0];
-        float y22 = dest[1].getY() * targetSize[1];
-        float y31 = dest[2].getX() * targetSize[0];
-        float y32 = dest[2].getY() * targetSize[1];
-
-        float a1 = ((y11 - y21) * (x12 - x32) - (y11 - y31) * (x12 - x22)) / ((x11 - x21) * (x12 - x32) - (x11 - x31) * (x12 - x22));
-        float a2 = ((y11 - y21) * (x11 - x31) - (y11 - y31) * (x11 - x21)) / ((x12 - x22) * (x11 - x31) - (x12 - x32) * (x11 - x21));
-        float a3 = y11 - a1 * x11 - a2 * x12;
-        float a4 = ((y12 - y22) * (x12 - x32) - (y12 - y32) * (x12 - x22)) / ((x11 - x21) * (x12 - x32) - (x11 - x31) * (x12 - x22));
-        float a5 = ((y12 - y22) * (x11 - x31) - (y12 - y32) * (x11 - x21)) / ((x12 - x22) * (x11 - x31) - (x12 - x32) * (x11 - x21));
-        float a6 = y12 - a4 * x11 - a5 * x12;
-        return new AffineTransform(a1, a4, a2, a5, a3, a6);
-    }
-
-    /**
-     * This method returns the proper pixel position on the image.
-     * 
-     * @param pos
-     *            the relative position (value of range [0, 1] (both inclusive))
-     * @param size
-     *            the size of the line the pixel lies on (width, height or
-     *            depth)
-     * @return the integer index of the pixel on the line of the specified width
-     */
-    public int getPixelPosition(float pos, int size) {
-        float pixelWidth = 1 / (float) size;
-        pos *= size;
-        int result = (int) pos;
-        // here is where we repair floating point operations errors :)
-        if (Math.abs(result - pos) > pixelWidth) {
-            ++result;
-        }
-        return result;
-    }
-
-    /**
-     * This method returns subimage of the give image. The subimage is
-     * constrained by the rectangle coordinates. The source image is unchanged.
-     * 
-     * @param image
-     *            the image to be subimaged
-     * @param minX
-     *            minimum X position
-     * @param minY
-     *            minimum Y position
-     * @param maxX
-     *            maximum X position
-     * @param maxY
-     *            maximum Y position
-     * @return a part of the given image
-     */
-    public Image getSubimage(Image image, int minX, int minY, int maxX, int maxY) {
-        if (minY > maxY) {
-            throw new IllegalArgumentException("Minimum Y value is higher than maximum Y value!");
-        }
-        if (minX > maxX) {
-            throw new IllegalArgumentException("Minimum Y value is higher than maximum Y value!");
-        }
-        if (image.getData().size() > 1) {
-            throw new IllegalArgumentException("Only flat images are allowed for subimage operation!");
-        }
-        if (image.getMipMapSizes() != null) {
-            LOGGER.warning("Subimaging image with mipmaps is not yet supported!");
-        }
-
-        int width = maxX - minX;
-        int height = maxY - minY;
-        ByteBuffer data = BufferUtils.createByteBuffer(width * height * (image.getFormat().getBitsPerPixel() >> 3));
-
-        Image result = new Image(image.getFormat(), width, height, data, ColorSpace.sRGB);
-        PixelInputOutput pixelIO = PixelIOFactory.getPixelIO(image.getFormat());
-        TexturePixel pixel = new TexturePixel();
-
-        for (int x = minX; x < maxX; ++x) {
-            for (int y = minY; y < maxY; ++y) {
-                pixelIO.read(image, 0, pixel, x, y);
-                pixelIO.write(result, 0, pixel, x - minX, y - minY);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method applies the colorband and color factors to image type
-     * textures. If there is no colorband defined for the texture or the color
-     * factors are all equal to 1.0f then no changes are made.
-     * 
-     * @param tex
-     *            the texture structure
-     * @param image
-     *            the image that will be altered if necessary
-     * @param blenderContext
-     *            the blender context
-     */
-    private void applyColorbandAndColorFactors(Structure tex, Image image, BlenderContext blenderContext) {
-        float rfac = ((Number) tex.getFieldValue("rfac")).floatValue();
-        float gfac = ((Number) tex.getFieldValue("gfac")).floatValue();
-        float bfac = ((Number) tex.getFieldValue("bfac")).floatValue();
-        float[][] colorBand = new ColorBand(tex, blenderContext).computeValues();
-        int depth = image.getDepth() == 0 ? 1 : image.getDepth();
-
-        if (colorBand != null) {
-            TexturePixel pixel = new TexturePixel();
-            PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat());
-            for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
-                for (int x = 0; x < image.getWidth(); ++x) {
-                    for (int y = 0; y < image.getHeight(); ++y) {
-                        imageIO.read(image, layerIndex, pixel, x, y);
-
-                        int colorbandIndex = (int) (pixel.alpha * 1000.0f);
-                        pixel.red = colorBand[colorbandIndex][0] * rfac;
-                        pixel.green = colorBand[colorbandIndex][1] * gfac;
-                        pixel.blue = colorBand[colorbandIndex][2] * bfac;
-                        pixel.alpha = colorBand[colorbandIndex][3];
-
-                        imageIO.write(image, layerIndex, pixel, x, y);
-                    }
-                }
-            }
-        } else if (rfac != 1.0f || gfac != 1.0f || bfac != 1.0f) {
-            TexturePixel pixel = new TexturePixel();
-            PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat());
-            for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
-                for (int x = 0; x < image.getWidth(); ++x) {
-                    for (int y = 0; y < image.getHeight(); ++y) {
-                        imageIO.read(image, layerIndex, pixel, x, y);
-
-                        pixel.red *= rfac;
-                        pixel.green *= gfac;
-                        pixel.blue *= bfac;
-
-                        imageIO.write(image, layerIndex, pixel, x, y);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * This method loads the texture from outside the blend file using the
-     * AssetManager that the blend file was loaded with. It returns a texture
-     * with a full assetKey that references the original texture so it later
-     * doesn't need to be packed when the model data is serialized. It searches
-     * the AssetManager for the full path if the model file is a relative path
-     * and will attempt to truncate the path if it is an absolute file path
-     * until the path can be found in the AssetManager. If the texture can not
-     * be found, it will issue a load attempt for the initial path anyway so the
-     * failed load can be reported by the AssetManagers callback methods for
-     * failed assets.
-     * 
-     * @param name
-     *            the path to the image
-     * @param imaflag
-     *            the image flag
-     * @param blenderContext
-     *            the blender context
-     * @return the loaded image or null if the image cannot be found
-     */
-    protected Texture loadImageFromFile(String name, int imaflag, BlenderContext blenderContext) {
-        if (!name.contains(".")) {
-            return null; // no extension means not a valid image
-        }
-
-        // decide if the mipmaps will be generated
-        boolean generateMipmaps = false;
-        switch (blenderContext.getBlenderKey().getMipmapGenerationMethod()) {
-            case ALWAYS_GENERATE:
-                generateMipmaps = true;
-                break;
-            case NEVER_GENERATE:
-                break;
-            case GENERATE_WHEN_NEEDED:
-                generateMipmaps = (imaflag & 0x04) != 0;
-                break;
-            default:
-                throw new IllegalStateException("Unknown mipmap generation method: " + blenderContext.getBlenderKey().getMipmapGenerationMethod());
-        }
-
-        AssetManager assetManager = blenderContext.getAssetManager();
-        name = name.replace('\\', '/');
-        Texture result = null;
-
-        if (name.startsWith("//")) {
-            // This is a relative path, so try to find it relative to the .blend file
-            String relativePath = name.substring(2);
-            // Augument the path with blender key path
-            BlenderKey blenderKey = blenderContext.getBlenderKey();
-            int idx = blenderKey.getName().lastIndexOf('/');
-            String blenderAssetFolder = blenderKey.getName().substring(0, idx != -1 ? idx : 0);
-            String absoluteName = blenderAssetFolder + '/' + relativePath;
-            // Directly try to load texture so AssetManager can report missing textures
-            try {
-                TextureKey key = new TextureKey(absoluteName);
-                key.setFlipY(true);
-                key.setGenerateMips(generateMipmaps);
-                result = assetManager.loadTexture(key);
-                result.setKey(key);
-            } catch (AssetNotFoundException | AssetLoadException e) {
-                LOGGER.fine(e.getLocalizedMessage());
-            }
-        } else {
-            // This is a full path, try to truncate it until the file can be found
-            // this works as the assetManager root is most probably a part of the
-            // image path. E.g. AssetManager has a locator at c:/Files/ and the
-            // texture path is c:/Files/Textures/Models/Image.jpg.
-            // For this we create a list with every possible full path name from
-            // the asset name to the root. Image.jpg, Models/Image.jpg,
-            // Textures/Models/Image.jpg (bingo) etc.
-            List<String> assetNames = new ArrayList<String>();
-            String[] paths = name.split("\\/");
-            StringBuilder sb = new StringBuilder(paths[paths.length - 1]);// the asset name
-            assetNames.add(paths[paths.length - 1]);
-
-            for (int i = paths.length - 2; i >= 0; --i) {
-                sb.insert(0, '/');
-                sb.insert(0, paths[i]);
-                assetNames.add(0, sb.toString());
-            }
-            // Now try to locate the asset
-            for (String assetName : assetNames) {
-                try {
-                    TextureKey key = new TextureKey(assetName);
-                    key.setFlipY(true);
-                    key.setGenerateMips(generateMipmaps);
-                    AssetInfo info = assetManager.locateAsset(key);
-                    if (info != null) {
-                        Texture texture = assetManager.loadTexture(key);
-                        result = texture;
-                        // Set key explicitly here if other ways fail
-                        texture.setKey(key);
-                        // If texture is found return it;
-                        return result;
-                    }
-                } catch (AssetNotFoundException | AssetLoadException e) {
-                    LOGGER.fine(e.getLocalizedMessage());
-                }
-            }
-            // The asset was not found in the loop above, call loadTexture with
-            // the original path once anyway so that the AssetManager can report
-            // the missing asset to subsystems.
-            try {
-                TextureKey key = new TextureKey(name);
-                assetManager.loadTexture(key);
-            } catch (AssetNotFoundException | AssetLoadException e) {
-                LOGGER.fine(e.getLocalizedMessage());
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Reads the texture data from the given material or sky structure.
-     * @param structure
-     *            the structure of material or sky
-     * @param diffuseColorArray
-     *            array of diffuse colors
-     * @param skyTexture
-     *            indicates it we're going to read sky texture or not
-     * @return a list of combined textures
-     * @throws BlenderFileException
-     *             an exception is thrown when problems with reading the blend file occur
-     */
-    @SuppressWarnings("unchecked")
-    public List<CombinedTexture> readTextureData(Structure structure, float[] diffuseColorArray, boolean skyTexture) throws BlenderFileException {
-        DynamicArray<Pointer> mtexsArray = (DynamicArray<Pointer>) structure.getFieldValue("mtex");
-        int separatedTextures = skyTexture ? 0 : ((Number) structure.getFieldValue("septex")).intValue();
-        List<TextureData> texturesList = new ArrayList<TextureData>();
-        for (int i = 0; i < mtexsArray.getTotalSize(); ++i) {
-            Pointer p = mtexsArray.get(i);
-            if (p.isNotNull() && (separatedTextures & 1 << i) == 0) {
-                TextureData textureData = new TextureData();
-                textureData.mtex = p.fetchData().get(0);
-                textureData.uvCoordinatesType = skyTexture ? UVCoordinatesType.TEXCO_ORCO.blenderValue : ((Number) textureData.mtex.getFieldValue("texco")).intValue();
-                textureData.projectionType = ((Number) textureData.mtex.getFieldValue("mapping")).intValue();
-                textureData.uvCoordinatesName = textureData.mtex.getFieldValue("uvName").toString();
-                if (textureData.uvCoordinatesName != null && textureData.uvCoordinatesName.trim().length() == 0) {
-                    textureData.uvCoordinatesName = null;
-                }
-
-                Pointer pTex = (Pointer) textureData.mtex.getFieldValue("tex");
-                if (pTex.isNotNull()) {
-                    Structure tex = pTex.fetchData().get(0);
-                    textureData.textureStructure = tex;
-                    texturesList.add(textureData);
-                }
-            }
-        }
-
-        LOGGER.info("Loading model's textures.");
-        List<CombinedTexture> loadedTextures = new ArrayList<CombinedTexture>();
-        if (blenderContext.getBlenderKey().isOptimiseTextures()) {
-            LOGGER.fine("Optimising the useage of model's textures.");
-            Map<Number, List<TextureData>> textureDataMap = this.sortTextures(texturesList);
-            for (Entry<Number, List<TextureData>> entry : textureDataMap.entrySet()) {
-                if (entry.getValue().size() > 0) {
-                    CombinedTexture combinedTexture = new CombinedTexture(entry.getKey().intValue(), !skyTexture);
-                    for (TextureData textureData : entry.getValue()) {
-                        int texflag = ((Number) textureData.mtex.getFieldValue("texflag")).intValue();
-                        boolean negateTexture = (texflag & 0x04) != 0;
-                        Texture texture = this.getTexture(textureData.textureStructure, textureData.mtex, blenderContext);
-                        if (texture != null) {
-                            int blendType = ((Number) textureData.mtex.getFieldValue("blendtype")).intValue();
-                            float[] color = new float[] { ((Number) textureData.mtex.getFieldValue("r")).floatValue(), ((Number) textureData.mtex.getFieldValue("g")).floatValue(), ((Number) textureData.mtex.getFieldValue("b")).floatValue() };
-                            float colfac = ((Number) textureData.mtex.getFieldValue("colfac")).floatValue();
-                            TextureBlender textureBlender = TextureBlenderFactory.createTextureBlender(texture.getImage().getFormat(), texflag, negateTexture, blendType, diffuseColorArray, color, colfac);
-                            combinedTexture.add(texture, textureBlender, textureData.uvCoordinatesType, textureData.projectionType, textureData.textureStructure, textureData.uvCoordinatesName, blenderContext);
-                        }
-                    }
-                    if (combinedTexture.getTexturesCount() > 0) {
-                        loadedTextures.add(combinedTexture);
-                    }
-                }
-            }
-        } else {
-            LOGGER.fine("No textures optimisation applied.");
-            int[] mappings = new int[] { MaterialContext.MTEX_COL, MaterialContext.MTEX_NOR, MaterialContext.MTEX_EMIT, MaterialContext.MTEX_SPEC, MaterialContext.MTEX_ALPHA, MaterialContext.MTEX_AMB };
-            for (TextureData textureData : texturesList) {
-                Texture texture = this.getTexture(textureData.textureStructure, textureData.mtex, blenderContext);
-                if (texture != null) {
-                    Number mapto = (Number) textureData.mtex.getFieldValue("mapto");
-                    int texflag = ((Number) textureData.mtex.getFieldValue("texflag")).intValue();
-                    boolean negateTexture = (texflag & 0x04) != 0;
-
-                    boolean colorSet = false;
-                    for (int i = 0; i < mappings.length; ++i) {
-                        if ((mappings[i] & mapto.intValue()) != 0) {
-                            if(mappings[i] == MaterialContext.MTEX_COL) {
-                                colorSet = true;
-                            } else if(colorSet && mappings[i] == MaterialContext.MTEX_ALPHA) {
-                                continue;
-                            }
-                            
-                            CombinedTexture combinedTexture = new CombinedTexture(mappings[i], !skyTexture);
-                            int blendType = ((Number) textureData.mtex.getFieldValue("blendtype")).intValue();
-                            float[] color = new float[] { ((Number) textureData.mtex.getFieldValue("r")).floatValue(), ((Number) textureData.mtex.getFieldValue("g")).floatValue(), ((Number) textureData.mtex.getFieldValue("b")).floatValue() };
-                            float colfac = ((Number) textureData.mtex.getFieldValue("colfac")).floatValue();
-                            TextureBlender textureBlender = TextureBlenderFactory.createTextureBlender(texture.getImage().getFormat(), texflag, negateTexture, blendType, diffuseColorArray, color, colfac);
-                            combinedTexture.add(texture, textureBlender, textureData.uvCoordinatesType, textureData.projectionType, textureData.textureStructure, textureData.uvCoordinatesName, blenderContext);
-                            if (combinedTexture.getTexturesCount() > 0) {// the added texture might not have been accepted (if for example loading generated textures is disabled)
-                                loadedTextures.add(combinedTexture);
-                            }
-                        }
-                    }
-                }
-
-            }
-        }
-
-        return loadedTextures;
-    }
-
-    /**
-     * This method sorts the textures by their mapping type. In each group only
-     * textures of one type are put (either two- or three-dimensional).
-     * 
-     * @return a map with sorted textures
-     */
-    private Map<Number, List<TextureData>> sortTextures(List<TextureData> textures) {
-        int[] mappings = new int[] { MaterialContext.MTEX_COL, MaterialContext.MTEX_NOR, MaterialContext.MTEX_EMIT, MaterialContext.MTEX_SPEC, MaterialContext.MTEX_ALPHA, MaterialContext.MTEX_AMB };
-        Map<Number, List<TextureData>> result = new HashMap<Number, List<TextureData>>();
-        for (TextureData data : textures) {
-            Number mapto = (Number) data.mtex.getFieldValue("mapto");
-            
-            boolean colorSet = false;
-            for (int i = 0; i < mappings.length; ++i) {
-                if ((mappings[i] & mapto.intValue()) != 0) {
-                    if(mappings[i] == MaterialContext.MTEX_COL) {
-                        colorSet = true;
-                    } else if(colorSet && mappings[i] == MaterialContext.MTEX_ALPHA) {
-                        continue;
-                    }
-                    
-                    List<TextureData> datas = result.get(mappings[i]);
-                    if (datas == null) {
-                        datas = new ArrayList<TextureData>();
-                        result.put(mappings[i], datas);
-                    }
-                    datas.add(data);
-                }
-            }
-        }
-        return result;
-    }
-
-    private static class TextureData {
-        public Structure mtex;
-        public Structure textureStructure;
-        public int       uvCoordinatesType;
-        public int       projectionType;
-        /** The name of the user's UV coordinates that are used for this texture. */
-        public String    uvCoordinatesName;
-    }
-}

+ 0 - 392
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TexturePixel.java

@@ -1,392 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
-
-/**
- * The class that stores the pixel values of a texture.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class TexturePixel implements Cloneable {
-    /** The pixel data. */
-    public float intensity, red, green, blue, alpha;
-
-    /**
-     * Copies the values from the given pixel.
-     * 
-     * @param pixel
-     *            the pixel that we read from
-     */
-    public void fromPixel(TexturePixel pixel) {
-        this.intensity = pixel.intensity;
-        this.red = pixel.red;
-        this.green = pixel.green;
-        this.blue = pixel.blue;
-        this.alpha = pixel.alpha;
-    }
-
-    /**
-     * Copies the values from the given color.
-     * 
-     * @param colorRGBA
-     *            the color that we read from
-     */
-    public void fromColor(ColorRGBA colorRGBA) {
-        this.red = colorRGBA.r;
-        this.green = colorRGBA.g;
-        this.blue = colorRGBA.b;
-        this.alpha = colorRGBA.a;
-    }
-
-    /**
-     * Copies the values from the given values.
-     * 
-     * @param a
-     *            the alpha value
-     * @param r
-     *            the red value
-     * @param g
-     *            the green value
-     * @param b
-     *            the blue value
-     */
-    public void fromARGB(float a, float r, float g, float b) {
-        this.alpha = a;
-        this.red = r;
-        this.green = g;
-        this.blue = b;
-    }
-
-    /**
-     * Copies the values from the given values.
-     * 
-     * @param a
-     *            the alpha value
-     * @param r
-     *            the red value
-     * @param g
-     *            the green value
-     * @param b
-     *            the blue value
-     */
-    public void fromARGB8(byte a, byte r, byte g, byte b) {
-        this.alpha = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
-        this.red = r >= 0 ? r / 255.0f : 1.0f - ~r / 255.0f;
-        this.green = g >= 0 ? g / 255.0f : 1.0f - ~g / 255.0f;
-        this.blue = b >= 0 ? b / 255.0f : 1.0f - ~b / 255.0f;
-    }
-
-    /**
-     * Copies the values from the given values.
-     * 
-     * @param a
-     *            the alpha value
-     * @param r
-     *            the red value
-     * @param g
-     *            the green value
-     * @param b
-     *            the blue value
-     */
-    public void fromARGB16(short a, short r, short g, short b) {
-        this.alpha = a >= 0 ? a / 65535.0f : 1.0f - ~a / 65535.0f;
-        this.red = r >= 0 ? r / 65535.0f : 1.0f - ~r / 65535.0f;
-        this.green = g >= 0 ? g / 65535.0f : 1.0f - ~g / 65535.0f;
-        this.blue = b >= 0 ? b / 65535.0f : 1.0f - ~b / 65535.0f;
-    }
-
-    /**
-     * Copies the intensity from the given value.
-     * 
-     * @param intensity
-     *            the intensity value
-     */
-    public void fromIntensity(byte intensity) {
-        this.intensity = intensity >= 0 ? intensity / 255.0f : 1.0f - ~intensity / 255.0f;
-    }
-
-    /**
-     * Copies the intensity from the given value.
-     * 
-     * @param intensity
-     *            the intensity value
-     */
-    public void fromIntensity(short intensity) {
-        this.intensity = intensity >= 0 ? intensity / 65535.0f : 1.0f - ~intensity / 65535.0f;
-    }
-
-    /**
-     * This method sets the alpha value (converts it to float number from range
-     * [0, 1]).
-     * 
-     * @param alpha
-     *            the alpha value
-     */
-    public void setAlpha(byte alpha) {
-        this.alpha = alpha >= 0 ? alpha / 255.0f : 1.0f - ~alpha / 255.0f;
-    }
-
-    /**
-     * This method sets the alpha value (converts it to float number from range
-     * [0, 1]).
-     * 
-     * @param alpha
-     *            the alpha value
-     */
-    public void setAlpha(short alpha) {
-        this.alpha = alpha >= 0 ? alpha / 65535.0f : 1.0f - ~alpha / 65535.0f;
-    }
-
-    /**
-     * Copies the values from the given integer that stores the ARGB8 data.
-     * 
-     * @param argb8
-     *            the data stored in an integer
-     */
-    public void fromARGB8(int argb8) {
-        byte pixelValue = (byte) ((argb8 & 0xFF000000) >> 24);
-        this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - ~pixelValue / 255.0f;
-        pixelValue = (byte) ((argb8 & 0xFF0000) >> 16);
-        this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - ~pixelValue / 255.0f;
-        pixelValue = (byte) ((argb8 & 0xFF00) >> 8);
-        this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - ~pixelValue / 255.0f;
-        pixelValue = (byte) (argb8 & 0xFF);
-        this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - ~pixelValue / 255.0f;
-    }
-
-    /**
-     * Stores RGBA values in the given array.
-     * 
-     * @param result
-     *            the array to store values
-     */
-    public void toRGBA(float[] result) {
-        result[0] = this.red;
-        result[1] = this.green;
-        result[2] = this.blue;
-        result[3] = this.alpha;
-    }
-
-    /**
-     * Stores the data in the given table.
-     * 
-     * @param result
-     *            the result table
-     */
-    public void toRGBA8(byte[] result) {
-        result[0] = (byte) (this.red * 255.0f);
-        result[1] = (byte) (this.green * 255.0f);
-        result[2] = (byte) (this.blue * 255.0f);
-        result[3] = (byte) (this.alpha * 255.0f);
-    }
-
-    /**
-     * Stores the pixel values in the integer.
-     * 
-     * @return the integer that stores the pixel values
-     */
-    public int toARGB8() {
-        int result = 0;
-        int b = (int) (this.alpha * 255.0f);
-        result |= b << 24;
-        b = (int) (this.red * 255.0f);
-        result |= b << 16;
-        b = (int) (this.green * 255.0f);
-        result |= b << 8;
-        b = (int) (this.blue * 255.0f);
-        result |= b;
-        return result;
-    }
-
-    /**
-     * @return the intensity of the pixel
-     */
-    public byte getInt() {
-        return (byte) (this.intensity * 255.0f);
-    }
-
-    /**
-     * @return the alpha value of the pixel
-     */
-    public byte getA8() {
-        return (byte) (this.alpha * 255.0f);
-    }
-
-    /**
-     * @return the alpha red of the pixel
-     */
-    public byte getR8() {
-        return (byte) (this.red * 255.0f);
-    }
-
-    /**
-     * @return the green value of the pixel
-     */
-    public byte getG8() {
-        return (byte) (this.green * 255.0f);
-    }
-
-    /**
-     * @return the blue value of the pixel
-     */
-    public byte getB8() {
-        return (byte) (this.blue * 255.0f);
-    }
-
-    /**
-     * @return the alpha value of the pixel
-     */
-    public short getA16() {
-        return (byte) (this.alpha * 65535.0f);
-    }
-
-    /**
-     * @return the alpha red of the pixel
-     */
-    public short getR16() {
-        return (byte) (this.red * 65535.0f);
-    }
-
-    /**
-     * @return the green value of the pixel
-     */
-    public short getG16() {
-        return (byte) (this.green * 65535.0f);
-    }
-
-    /**
-     * @return the blue value of the pixel
-     */
-    public short getB16() {
-        return (byte) (this.blue * 65535.0f);
-    }
-
-    /**
-     * Merges two pixels (adds the values of each color).
-     * 
-     * @param pixel
-     *            the pixel we merge with
-     */
-    public void merge(TexturePixel pixel) {
-        float oneMinusAlpha = 1 - pixel.alpha;
-        this.red = oneMinusAlpha * this.red + pixel.alpha * pixel.red;
-        this.green = oneMinusAlpha * this.green + pixel.alpha * pixel.green;
-        this.blue = oneMinusAlpha * this.blue + pixel.alpha * pixel.blue;
-        this.alpha = (this.alpha + pixel.alpha) * 0.5f;
-    }
-    
-    /**
-     * Mixes two pixels.
-     * 
-     * @param pixel
-     *            the pixel we mix with
-     */
-    public void mix(TexturePixel pixel) {
-        this.red = 0.5f * (this.red + pixel.red);
-        this.green = 0.5f * (this.green + pixel.green);
-        this.blue = 0.5f * (this.blue + pixel.blue);
-        this.alpha = 0.5f * (this.alpha + pixel.alpha);
-        this.intensity = 0.5f * (this.intensity + pixel.intensity);
-    }
-
-    /**
-     * This method negates the colors.
-     */
-    public void negate() {
-        this.red = 1.0f - this.red;
-        this.green = 1.0f - this.green;
-        this.blue = 1.0f - this.blue;
-        this.alpha = 1.0f - this.alpha;
-    }
-
-    /**
-     * This method clears the pixel values.
-     */
-    public void clear() {
-        this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f;
-    }
-
-    /**
-     * This method adds the calues of the given pixel to the current pixel.
-     * 
-     * @param pixel
-     *            the pixel we add
-     */
-    public void add(TexturePixel pixel) {
-        this.red += pixel.red;
-        this.green += pixel.green;
-        this.blue += pixel.blue;
-        this.alpha += pixel.alpha;
-        this.intensity += pixel.intensity;
-    }
-    
-    /**
-     * This method adds the calues of the given pixel to the current pixel.
-     * 
-     * @param pixel
-     *            the pixel we add
-     */
-    public void add(ColorRGBA pixel) {
-        this.red += pixel.r;
-        this.green += pixel.g;
-        this.blue += pixel.b;
-        this.alpha += pixel.a;
-    }
-
-    /**
-     * This method multiplies the values of the given pixel by the given value.
-     * 
-     * @param value
-     *            multiplication factor
-     */
-    public void mult(float value) {
-        this.red *= value;
-        this.green *= value;
-        this.blue *= value;
-        this.alpha *= value;
-        this.intensity *= value;
-    }
-
-    /**
-     * This method divides the values of the given pixel by the given value.
-     * ATTENTION! Beware of the zero value. This will cause you NaN's in the
-     * pixel values.
-     * 
-     * @param value
-     *            division factor
-     */
-    public void divide(float value) {
-        this.red /= value;
-        this.green /= value;
-        this.blue /= value;
-        this.alpha /= value;
-        this.intensity /= value;
-    }
-
-    /**
-     * This method clamps the pixel values to the given borders.
-     * 
-     * @param min
-     *            the minimum value
-     * @param max
-     *            the maximum value
-     */
-    public void clamp(float min, float max) {
-        this.red = FastMath.clamp(this.red, min, max);
-        this.green = FastMath.clamp(this.green, min, max);
-        this.blue = FastMath.clamp(this.blue, min, max);
-        this.alpha = FastMath.clamp(this.alpha, min, max);
-        this.intensity = FastMath.clamp(this.intensity, min, max);
-    }
-
-    @Override
-    public Object clone() throws CloneNotSupportedException {
-        return super.clone();
-    }
-
-    @Override
-    public String toString() {
-        return "[" + red + ", " + green + ", " + blue + ", " + alpha + " {" + intensity + "}]";
-    }
-}

+ 0 - 662
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java

@@ -1,662 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-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.TreeSet;
-
-import jme3tools.converters.ImageToAwt;
-
-import com.jme3.bounding.BoundingBox;
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.textures.blending.TextureBlender;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.Texture;
-import com.jme3.texture.Texture2D;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.util.BufferUtils;
-
-/**
- * This texture holds a set of images for each face in the specified mesh. It
- * helps to flatten 3D texture, merge 3D and 2D textures and merge 2D textures
- * with different UV coordinates.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class TriangulatedTexture extends Texture2D {
-    /** The result image format. */
-    private Format                             format;
-    /** The collection of images for each face. */
-    private Collection<TriangleTextureElement> faceTextures;
-    /**
-     * The maximum texture size (width/height). This is taken from the blender
-     * key.
-     */
-    private int                                maxTextureSize;
-    /** A variable that can prevent removing identical textures. */
-    private boolean                            keepIdenticalTextures = false;
-    /** The result texture. */
-    private Texture2D                          resultTexture;
-    /** The result texture's UV coordinates. */
-    private List<Vector2f>                     resultUVS;
-
-    /**
-     * This method triangulates the given flat texture. The given texture is not
-     * changed.
-     * 
-     * @param texture2d
-     *            the texture to be triangulated
-     * @param uvs
-     *            the UV coordinates for each face
-     */
-    public TriangulatedTexture(Texture2D texture2d, List<Vector2f> uvs, BlenderContext blenderContext) {
-        maxTextureSize = blenderContext.getBlenderKey().getMaxTextureSize();
-        faceTextures = new TreeSet<TriangleTextureElement>(new Comparator<TriangleTextureElement>() {
-            @Override
-            public int compare(TriangleTextureElement o1, TriangleTextureElement o2) {
-                return o1.faceIndex - o2.faceIndex;
-            }
-        });
-        int facesCount = uvs.size() / 3;
-        for (int i = 0; i < facesCount; ++i) {
-            faceTextures.add(new TriangleTextureElement(i, texture2d.getImage(), uvs, true, blenderContext));
-        }
-        format = texture2d.getImage().getFormat();
-    }
-
-    /**
-     * Constructor that simply stores precalculated images.
-     * 
-     * @param faceTextures
-     *            a collection of images for the mesh's faces
-     * @param blenderContext
-     *            the blender context
-     */
-    public TriangulatedTexture(Collection<TriangleTextureElement> faceTextures, BlenderContext blenderContext) {
-        maxTextureSize = blenderContext.getBlenderKey().getMaxTextureSize();
-        this.faceTextures = faceTextures;
-        for (TriangleTextureElement faceTextureElement : faceTextures) {
-            if (format == null) {
-                format = faceTextureElement.image.getFormat();
-            } else if (format != faceTextureElement.image.getFormat()) {
-                throw new IllegalArgumentException("Face texture element images MUST have the same image format!");
-            }
-        }
-    }
-
-    /**
-     * This method blends the each image using the given blender and taking base
-     * texture into consideration.
-     * 
-     * @param textureBlender
-     *            the texture blender that holds the blending definition
-     * @param baseTexture
-     *            the texture that is 'below' the current texture (can be null)
-     * @param blenderContext
-     *            the blender context
-     */
-    public void blend(TextureBlender textureBlender, TriangulatedTexture baseTexture, BlenderContext blenderContext) {
-        Format newFormat = null;
-        for (TriangleTextureElement triangleTextureElement : faceTextures) {
-            Image baseImage = baseTexture == null ? null : baseTexture.getFaceTextureElement(triangleTextureElement.faceIndex).image;
-            triangleTextureElement.image = textureBlender.blend(triangleTextureElement.image, baseImage, blenderContext);
-            if (newFormat == null) {
-                newFormat = triangleTextureElement.image.getFormat();
-            } else if (newFormat != triangleTextureElement.image.getFormat()) {
-                throw new IllegalArgumentException("Face texture element images MUST have the same image format!");
-            }
-        }
-        format = newFormat;
-    }
-
-    /**
-     * This method alters the images to fit them into UV coordinates of the
-     * given target texture.
-     * 
-     * @param targetTexture
-     *            the texture to whose UV coordinates we fit current images
-     * @param blenderContext
-     *            the blender context
-     */
-    public void castToUVS(TriangulatedTexture targetTexture, BlenderContext blenderContext) {
-        int[] sourceSize = new int[2], targetSize = new int[2];
-        ImageLoader imageLoader = new ImageLoader();
-        TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
-        for (TriangleTextureElement entry : faceTextures) {
-            TriangleTextureElement targetFaceTextureElement = targetTexture.getFaceTextureElement(entry.faceIndex);
-            Vector2f[] dest = targetFaceTextureElement.uv;
-
-            // get the sizes of the source and target images
-            sourceSize[0] = entry.image.getWidth();
-            sourceSize[1] = entry.image.getHeight();
-            targetSize[0] = targetFaceTextureElement.image.getWidth();
-            targetSize[1] = targetFaceTextureElement.image.getHeight();
-
-            // create triangle transformation
-            AffineTransform affineTransform = textureHelper.createAffineTransform(entry.uv, dest, sourceSize, targetSize);
-
-            // compute the result texture
-            BufferedImage sourceImage = ImageToAwt.convert(entry.image, false, true, 0);
-
-            BufferedImage targetImage = new BufferedImage(targetSize[0], targetSize[1], sourceImage.getType());
-            Graphics2D g = targetImage.createGraphics();
-            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
-            g.drawImage(sourceImage, affineTransform, null);
-            g.dispose();
-
-            Image output = imageLoader.load(targetImage, false);
-            entry.image = output;
-            entry.uv[0].set(dest[0]);
-            entry.uv[1].set(dest[1]);
-            entry.uv[2].set(dest[2]);
-        }
-    }
-
-    /**
-     * This method returns the flat texture. It is calculated if required or if
-     * it was not created before. Images that are identical are discarded to
-     * reduce the texture size.
-     * 
-     * @param rebuild
-     *            a variable that forces texture recomputation (even if it was
-     *            computed vefore)
-     * @return flat result texture (all images merged into one)
-     */
-    public Texture2D getResultTexture(boolean rebuild) {
-        if (resultTexture == null || rebuild) {
-            // sorting the parts by their height (from highest to the lowest)
-            List<TriangleTextureElement> list = new ArrayList<TriangleTextureElement>(faceTextures);
-            Collections.sort(list, new Comparator<TriangleTextureElement>() {
-                @Override
-                public int compare(TriangleTextureElement o1, TriangleTextureElement o2) {
-                    return o2.image.getHeight() - o1.image.getHeight();
-                }
-            });
-
-            // arraging the images on the resulting image (calculating the result image width and height)
-            Set<Integer> duplicatedFaceIndexes = new HashSet<Integer>();
-            int resultImageHeight = list.get(0).image.getHeight();
-            int resultImageWidth = 0;
-            int currentXPos = 0, currentYPos = 0;
-            Map<TriangleTextureElement, Integer[]> imageLayoutData = new HashMap<TriangleTextureElement, Integer[]>(list.size());
-            while (list.size() > 0) {
-                TriangleTextureElement currentElement = list.remove(0);
-                if (currentXPos + currentElement.image.getWidth() > maxTextureSize) {
-                    currentXPos = 0;
-                    currentYPos = resultImageHeight;
-                    resultImageHeight += currentElement.image.getHeight();
-                }
-                Integer[] currentPositions = new Integer[] { currentXPos, currentYPos };
-                imageLayoutData.put(currentElement, currentPositions);
-
-                if (keepIdenticalTextures) {// removing identical images
-                    for (int i = 0; i < list.size(); ++i) {
-                        if (currentElement.image.equals(list.get(i).image)) {
-                            duplicatedFaceIndexes.add(list.get(i).faceIndex);
-                            imageLayoutData.put(list.remove(i--), currentPositions);
-                        }
-                    }
-                }
-
-                currentXPos += currentElement.image.getWidth();
-                resultImageWidth = Math.max(resultImageWidth, currentXPos);
-                // currentYPos += currentElement.image.getHeight();
-
-                // TODO: implement that to compact the result image
-                // try to add smaller images below the current one
-                // int remainingHeight = resultImageHeight -
-                // currentElement.image.getHeight();
-                // while(remainingHeight > 0) {
-                // for(int i=list.size() - 1;i>=0;--i) {
-                //
-                // }
-                // }
-            }
-
-            // computing the result UV coordinates
-            resultUVS = new ArrayList<Vector2f>(imageLayoutData.size() * 3);
-            for (int i = 0; i < imageLayoutData.size() * 3; ++i) {
-                resultUVS.add(null);
-            }
-            Vector2f[] uvs = new Vector2f[3];
-            for (Entry<TriangleTextureElement, Integer[]> entry : imageLayoutData.entrySet()) {
-                Integer[] position = entry.getValue();
-                entry.getKey().computeFinalUVCoordinates(resultImageWidth, resultImageHeight, position[0], position[1], uvs);
-                resultUVS.set(entry.getKey().faceIndex * 3, uvs[0]);
-                resultUVS.set(entry.getKey().faceIndex * 3 + 1, uvs[1]);
-                resultUVS.set(entry.getKey().faceIndex * 3 + 2, uvs[2]);
-            }
-
-            Image resultImage = new Image(format, resultImageWidth, resultImageHeight, BufferUtils.createByteBuffer(resultImageWidth * resultImageHeight * (format.getBitsPerPixel() >> 3)), ColorSpace.Linear);
-            resultTexture = new Texture2D(resultImage);
-            for (Entry<TriangleTextureElement, Integer[]> entry : imageLayoutData.entrySet()) {
-                if (!duplicatedFaceIndexes.contains(entry.getKey().faceIndex)) {
-                    this.draw(resultImage, entry.getKey().image, entry.getValue()[0], entry.getValue()[1]);
-                }
-            }
-
-            // setting additional data
-            resultTexture.setWrap(WrapAxis.S, this.getWrap(WrapAxis.S));
-            resultTexture.setWrap(WrapAxis.T, this.getWrap(WrapAxis.T));
-            resultTexture.setMagFilter(this.getMagFilter());
-            resultTexture.setMinFilter(this.getMinFilter());
-        }
-        return resultTexture;
-    }
-
-    /**
-     * @return the result flat texture
-     */
-    public Texture2D getResultTexture() {
-        return this.getResultTexture(false);
-    }
-
-    /**
-     * @return the result texture's UV coordinates
-     */
-    public List<Vector2f> getResultUVS() {
-        this.getResultTexture();// this is called here to make sure that the result UVS are computed
-        return resultUVS;
-    }
-
-    /**
-     * This method returns a single image element for the given face index.
-     * 
-     * @param faceIndex
-     *            the face index
-     * @return image element for the required face index
-     * @throws IllegalStateException
-     *             this exception is thrown if the current image set does not
-     *             contain an image for the given face index
-     */
-    public TriangleTextureElement getFaceTextureElement(int faceIndex) {
-        for (TriangleTextureElement textureElement : faceTextures) {
-            if (textureElement.faceIndex == faceIndex) {
-                return textureElement;
-            }
-        }
-        throw new IllegalStateException("No face texture element found for index: " + faceIndex);
-    }
-
-    /**
-     * @return the amount of texture faces
-     */
-    public int getFaceTextureCount() {
-        return faceTextures.size();
-    }
-
-    /**
-     * Tells the object wheather to keep or reduce identical face textures.
-     * 
-     * @param keepIdenticalTextures
-     *            keeps or discards identical textures
-     */
-    public void setKeepIdenticalTextures(boolean keepIdenticalTextures) {
-        this.keepIdenticalTextures = keepIdenticalTextures;
-    }
-
-    /**
-     * This method draws the source image on the target image starting with the
-     * specified positions.
-     * 
-     * @param target
-     *            the target image
-     * @param source
-     *            the source image
-     * @param targetXPos
-     *            start X position on the target image
-     * @param targetYPos
-     *            start Y position on the target image
-     */
-    private void draw(Image target, Image source, int targetXPos, int targetYPos) {
-        PixelInputOutput sourceIO = PixelIOFactory.getPixelIO(source.getFormat());
-        PixelInputOutput targetIO = PixelIOFactory.getPixelIO(target.getFormat());
-        TexturePixel pixel = new TexturePixel();
-
-        for (int x = 0; x < source.getWidth(); ++x) {
-            for (int y = 0; y < source.getHeight(); ++y) {
-                sourceIO.read(source, 0, pixel, x, y);
-                targetIO.write(target, 0, pixel, targetXPos + x, targetYPos + y);
-            }
-        }
-    }
-
-    /**
-     * A class that represents an image for a single face of the mesh.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    /* package */static class TriangleTextureElement {
-        /** The image for the face. */
-        public Image            image;
-        /** The UV coordinates for the image. */
-        public final Vector2f[] uv;
-        /** The index of the face this image refers to. */
-        public final int        faceIndex;
-
-        /**
-         * Constructor that creates the image element from the given texture and
-         * UV coordinates (it cuts out the smallest rectasngle possible from the
-         * given image that will hold the triangle defined by the given UV
-         * coordinates). After the image is cut out the UV coordinates are
-         * recalculated to be fit for the new image.
-         * 
-         * @param faceIndex
-         *            the index of mesh's face this image refers to
-         * @param sourceImage
-         *            the source image
-         * @param uvCoordinates
-         *            the UV coordinates that define the image
-         */
-        public TriangleTextureElement(int faceIndex, Image sourceImage, List<Vector2f> uvCoordinates, boolean wholeUVList, BlenderContext blenderContext) {
-            TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
-            this.faceIndex = faceIndex;
-
-            uv = wholeUVList ? new Vector2f[] { uvCoordinates.get(faceIndex * 3).clone(), uvCoordinates.get(faceIndex * 3 + 1).clone(), uvCoordinates.get(faceIndex * 3 + 2).clone() } : new Vector2f[] { uvCoordinates.get(0).clone(), uvCoordinates.get(1).clone(), uvCoordinates.get(2).clone() };
-
-            // be careful here, floating point operations might cause the
-            // texture positions to be inapropriate
-            int[][] texturePosition = new int[3][2];
-            for (int i = 0; i < texturePosition.length; ++i) {
-                texturePosition[i][0] = textureHelper.getPixelPosition(uv[i].x, sourceImage.getWidth());
-                texturePosition[i][1] = textureHelper.getPixelPosition(uv[i].y, sourceImage.getHeight());
-            }
-
-            // calculating the extent of the texture
-            int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE;
-            int maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
-            float minUVX = Float.MAX_VALUE, minUVY = Float.MAX_VALUE;
-            float maxUVX = Float.MIN_VALUE, maxUVY = Float.MIN_VALUE;
-
-            for (int i = 0; i < texturePosition.length; ++i) {
-                minX = Math.min(texturePosition[i][0], minX);
-                minY = Math.min(texturePosition[i][1], minY);
-
-                maxX = Math.max(texturePosition[i][0], maxX);
-                maxY = Math.max(texturePosition[i][1], maxY);
-
-                minUVX = Math.min(uv[i].x, minUVX);
-                minUVY = Math.min(uv[i].y, minUVY);
-                maxUVX = Math.max(uv[i].x, maxUVX);
-                maxUVY = Math.max(uv[i].y, maxUVY);
-            }
-            int width = maxX - minX;
-            int height = maxY - minY;
-
-            if (width == 0) {
-                width = 1;
-            }
-            if (height == 0) {
-                height = 1;
-            }
-
-            // copy the pixel from the texture to the result image
-            PixelInputOutput pixelReader = PixelIOFactory.getPixelIO(sourceImage.getFormat());
-            TexturePixel pixel = new TexturePixel();
-            ByteBuffer data = BufferUtils.createByteBuffer(width * height * 4);
-            for (int y = minY; y < maxY; ++y) {
-                for (int x = minX; x < maxX; ++x) {
-                    int xPos = x >= sourceImage.getWidth() ? x - sourceImage.getWidth() : x;
-                    int yPos = y >= sourceImage.getHeight() ? y - sourceImage.getHeight() : y;
-                    pixelReader.read(sourceImage, 0, pixel, xPos, yPos);
-                    data.put(pixel.getR8());
-                    data.put(pixel.getG8());
-                    data.put(pixel.getB8());
-                    data.put(pixel.getA8());
-                }
-            }
-            image = new Image(Format.RGBA8, width, height, data, ColorSpace.Linear);
-
-            // modify the UV values so that they fit the new image
-            float heightUV = maxUVY - minUVY;
-            float widthUV = maxUVX - minUVX;
-            for (int i = 0; i < uv.length; ++i) {
-                // first translate it to the image borders
-                uv[i].x -= minUVX;
-                uv[i].y -= minUVY;
-                // then scale so that it fills the whole area
-                uv[i].x /= widthUV;
-                uv[i].y /= heightUV;
-            }
-        }
-
-        /**
-         * Constructor that creates an image element from the 3D texture
-         * (generated texture). It computes a flat smallest rectangle that can
-         * hold a (3D) triangle defined by the given UV coordinates. Then it
-         * defines the image pixels for points in 3D space that define the
-         * calculated rectangle.
-         * 
-         * @param faceIndex
-         *            the face index this image refers to
-         * @param boundingBox
-         *            the bounding box of the mesh
-         * @param texture
-         *            the texture that allows to compute a pixel value in 3D
-         *            space
-         * @param uv
-         *            the UV coordinates of the mesh
-         * @param blenderContext
-         *            the blender context
-         */
-        public TriangleTextureElement(int faceIndex, BoundingBox boundingBox, GeneratedTexture texture, Vector3f[] uv, int[] uvIndices, BlenderContext blenderContext) {
-            this.faceIndex = faceIndex;
-
-            // compute the face vertices from the UV coordinates
-            float width = boundingBox.getXExtent() * 2;
-            float height = boundingBox.getYExtent() * 2;
-            float depth = boundingBox.getZExtent() * 2;
-
-            Vector3f min = boundingBox.getMin(null);
-            Vector3f v1 = min.add(uv[uvIndices[0]].x * width, uv[uvIndices[0]].y * height, uv[uvIndices[0]].z * depth);
-            Vector3f v2 = min.add(uv[uvIndices[1]].x * width, uv[uvIndices[1]].y * height, uv[uvIndices[1]].z * depth);
-            Vector3f v3 = min.add(uv[uvIndices[2]].x * width, uv[uvIndices[2]].y * height, uv[uvIndices[2]].z * depth);
-
-            // get the rectangle envelope for the triangle
-            RectangleEnvelope envelope = this.getTriangleEnvelope(v1, v2, v3);
-
-            // create the result image
-            Format imageFormat = texture.getImage().getFormat();
-            int imageWidth = (int) (envelope.width * blenderContext.getBlenderKey().getGeneratedTexturePPU());
-            if (imageWidth == 0) {
-                imageWidth = 1;
-            }
-            int imageHeight = (int) (envelope.height * blenderContext.getBlenderKey().getGeneratedTexturePPU());
-            if (imageHeight == 0) {
-                imageHeight = 1;
-            }
-            ByteBuffer data = BufferUtils.createByteBuffer(imageWidth * imageHeight * (imageFormat.getBitsPerPixel() >> 3));
-            image = new Image(texture.getImage().getFormat(), imageWidth, imageHeight, data, ColorSpace.Linear);
-
-            // computing the pixels
-            PixelInputOutput pixelWriter = PixelIOFactory.getPixelIO(imageFormat);
-            TexturePixel pixel = new TexturePixel();
-            float[] uvs = new float[3];
-            Vector3f point = new Vector3f(envelope.min);
-            Vector3f vecY = new Vector3f();
-            Vector3f wDelta = new Vector3f(envelope.w).multLocal(1.0f / imageWidth);
-            Vector3f hDelta = new Vector3f(envelope.h).multLocal(1.0f / imageHeight);
-            for (int x = 0; x < imageWidth; ++x) {
-                for (int y = 0; y < imageHeight; ++y) {
-                    this.toTextureUV(boundingBox, point, uvs);
-                    texture.getPixel(pixel, uvs[0], uvs[1], uvs[2]);
-                    pixelWriter.write(image, 0, pixel, x, y);
-                    point.addLocal(hDelta);
-                }
-
-                vecY.addLocal(wDelta);
-                point.set(envelope.min).addLocal(vecY);
-            }
-
-            // preparing UV coordinates for the flatted texture
-            this.uv = new Vector2f[3];
-            this.uv[0] = new Vector2f(FastMath.clamp(v1.subtract(envelope.min).length(), 0, Float.MAX_VALUE) / envelope.height, 0);
-            Vector3f heightDropPoint = v2.subtract(envelope.w);// w is directed from the base to v2
-            this.uv[1] = new Vector2f(1, heightDropPoint.subtractLocal(envelope.min).length() / envelope.height);
-            this.uv[2] = new Vector2f(0, 1);
-        }
-
-        /**
-         * This method computes the final UV coordinates for the image (after it
-         * is combined with other images and drawed on the result image).
-         * 
-         * @param totalImageWidth
-         *            the result image width
-         * @param totalImageHeight
-         *            the result image height
-         * @param xPos
-         *            the most left x coordinate of the image
-         * @param yPos
-         *            the most top y coordinate of the image
-         * @param result
-         *            a vector where the result is stored
-         */
-        public void computeFinalUVCoordinates(int totalImageWidth, int totalImageHeight, int xPos, int yPos, Vector2f[] result) {
-            for (int i = 0; i < 3; ++i) {
-                result[i] = new Vector2f();
-                result[i].x = xPos / (float) totalImageWidth + uv[i].x * (image.getWidth() / (float) totalImageWidth);
-                result[i].y = yPos / (float) totalImageHeight + uv[i].y * (image.getHeight() / (float) totalImageHeight);
-            }
-        }
-
-        /**
-         * This method converts the given point into 3D UV coordinates.
-         * 
-         * @param boundingBox
-         *            the bounding box of the mesh
-         * @param point
-         *            the point to be transformed
-         * @param uvs
-         *            the result UV coordinates
-         */
-        private void toTextureUV(BoundingBox boundingBox, Vector3f point, float[] uvs) {
-            uvs[0] = (point.x - boundingBox.getCenter().x) / (boundingBox.getXExtent() == 0 ? 1 : boundingBox.getXExtent());
-            uvs[1] = (point.y - boundingBox.getCenter().y) / (boundingBox.getYExtent() == 0 ? 1 : boundingBox.getYExtent());
-            uvs[2] = (point.z - boundingBox.getCenter().z) / (boundingBox.getZExtent() == 0 ? 1 : boundingBox.getZExtent());
-            // UVS cannot go outside <0, 1> range, but since we are generating texture for triangle envelope it might happen that
-            // some points of the envelope will exceet the bounding box of the mesh thus generating uvs outside the range
-            for (int i = 0; i < 3; ++i) {
-                uvs[i] = FastMath.clamp(uvs[i], 0, 1);
-            }
-        }
-
-        /**
-         * This method returns an envelope of a minimal rectangle, that is set
-         * in 3D space, and contains the given triangle.
-         * 
-         * @param triangle
-         *            the triangle
-         * @return a rectangle minimum and maximum point and height and width
-         */
-        private RectangleEnvelope getTriangleEnvelope(Vector3f v1, Vector3f v2, Vector3f v3) {
-            Vector3f h = v3.subtract(v1);// the height of the resulting rectangle
-            Vector3f temp = v2.subtract(v1);
-
-            float field = 0.5f * h.cross(temp).length();// the field of the rectangle: Field = 0.5 * ||h x temp||
-            if (field <= 0.0f) {
-                return new RectangleEnvelope(v1);// return single point envelope
-            }
-
-            float cosAlpha = h.dot(temp) / (h.length() * temp.length());// the cosinus of angle betweenh and temp
-
-            float triangleHeight = 2 * field / h.length();// the base of the height is the h vector
-            // now calculate the distance between v1 vertex and the point where
-            // the above calculated height 'touches' the base line (it can be
-            // settled outside the h vector)
-            float x = Math.abs((float) Math.sqrt(FastMath.clamp(temp.lengthSquared() - triangleHeight * triangleHeight, 0, Float.MAX_VALUE))) * Math.signum(cosAlpha);
-            // now get the height base point
-            Vector3f xPoint = v1.add(h.normalize().multLocal(x));
-
-            // get the minimum point of the envelope
-            Vector3f min = x < 0 ? xPoint : v1;
-            if (x < 0) {
-                h = v3.subtract(min);
-            } else if (x > h.length()) {
-                h = xPoint.subtract(min);
-            }
-
-            Vector3f envelopeWidth = v2.subtract(xPoint);
-            return new RectangleEnvelope(min, envelopeWidth, h);
-        }
-    }
-
-    /**
-     * A class that represents a flat rectangle in 3D space that is built on a
-     * triangle in 3D space.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    private static class RectangleEnvelope {
-        /** The minimum point of the rectangle. */
-        public final Vector3f min;
-        /** The width vector. */
-        public final Vector3f w;
-        /** The height vector. */
-        public final Vector3f h;
-        /** The width of the rectangle. */
-        public final float    width;
-        /** The height of the rectangle. */
-        public final float    height;
-
-        /**
-         * Constructs a rectangle that actually holds a point, not a triangle.
-         * This is a special case that is sometimes used when generating a
-         * texture where UV coordinates are defined by normals instead of
-         * vertices.
-         * 
-         * @param pointPosition
-         *            a position in 3D space
-         */
-        public RectangleEnvelope(Vector3f pointPosition) {
-            min = pointPosition;
-            h = w = Vector3f.ZERO;
-            width = height = 1;
-        }
-
-        /**
-         * Constructs a rectangle envelope.
-         * 
-         * @param min
-         *            the minimum rectangle point
-         * @param w
-         *            the width vector
-         * @param h
-         *            the height vector
-         */
-        public RectangleEnvelope(Vector3f min, Vector3f w, Vector3f h) {
-            this.min = min;
-            this.h = h;
-            this.w = w;
-            width = w.length();
-            height = h.length();
-        }
-
-        @Override
-        public String toString() {
-            return "Envelope[min = " + min + ", w = " + w + ", h = " + h + "]";
-        }
-    }
-
-    @Override
-    public Texture createSimpleClone() {
-        return null;
-    }
-}

+ 0 - 420
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java

@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-import com.jme3.bounding.BoundingBox;
-import com.jme3.bounding.BoundingSphere;
-import com.jme3.bounding.BoundingVolume;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
-import com.jme3.scene.VertexBuffer;
-import com.jme3.scene.plugins.blender.textures.UVProjectionGenerator.UVProjectionType;
-import com.jme3.util.BufferUtils;
-
-/**
- * This class is used for UV coordinates generation.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class UVCoordinatesGenerator {
-    private static final Logger LOGGER = Logger.getLogger(UVCoordinatesGenerator.class.getName());
-
-    public static enum UVCoordinatesType {
-        TEXCO_ORCO(1), TEXCO_REFL(2), TEXCO_NORM(4), TEXCO_GLOB(8), TEXCO_UV(16), TEXCO_OBJECT(32), TEXCO_LAVECTOR(64), TEXCO_VIEW(128),
-        TEXCO_STICKY(256), TEXCO_OSA(512), TEXCO_WINDOW(1024), NEED_UV(2048), TEXCO_TANGENT(4096),
-        TEXCO_PARTICLE_OR_STRAND(8192), //TEXCO_PARTICLE (since blender 2.6x) has also the value of: 8192 but is used for halo materials instead of normal materials
-        TEXCO_STRESS(16384), TEXCO_SPEED(32768);
-
-        public final int blenderValue;
-
-        private UVCoordinatesType(int blenderValue) {
-            this.blenderValue = blenderValue;
-        }
-
-        public static UVCoordinatesType valueOf(int blenderValue) {
-            for (UVCoordinatesType coordinatesType : UVCoordinatesType.values()) {
-                if (coordinatesType.blenderValue == blenderValue) {
-                    return coordinatesType;
-                }
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Generates a UV coordinates for 2D texture.
-     * 
-     * @param mesh
-     *            the mesh we generate UV's for
-     * @param texco
-     *            UV coordinates type
-     * @param projection
-     *            projection type
-     * @param geometries
-     *            the geometris the given mesh belongs to (required to compute
-     *            bounding box)
-     * @return UV coordinates for the given mesh
-     */
-    public static List<Vector2f> generateUVCoordinatesFor2DTexture(Mesh mesh, UVCoordinatesType texco, UVProjectionType projection, Geometry geometries) {
-        List<Vector2f> result = new ArrayList<Vector2f>();
-        BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometries);
-        float[] inputData = null;// positions, normals, reflection vectors, etc.
-
-        switch (texco) {
-            case TEXCO_ORCO:
-                inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Position));
-                break;
-            case TEXCO_UV:// this should be used if not defined by user explicitly
-                Vector2f[] data = new Vector2f[] { new Vector2f(0, 1), new Vector2f(0, 0), new Vector2f(1, 0) };
-                for (int i = 0; i < mesh.getVertexCount(); ++i) {
-                    result.add(data[i % 3]);
-                }
-                break;
-            case TEXCO_NORM:
-                inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Normal));
-                break;
-            case TEXCO_REFL:
-            case TEXCO_GLOB:
-            case TEXCO_TANGENT:
-            case TEXCO_STRESS:
-            case TEXCO_LAVECTOR:
-            case TEXCO_OBJECT:
-            case TEXCO_OSA:
-            case TEXCO_PARTICLE_OR_STRAND:
-            case TEXCO_SPEED:
-            case TEXCO_STICKY:
-            case TEXCO_VIEW:
-            case TEXCO_WINDOW:
-                LOGGER.warning("Texture coordinates type not currently supported: " + texco);
-                break;
-            default:
-                throw new IllegalStateException("Unknown texture coordinates value: " + texco);
-        }
-
-        if (inputData != null) {// make projection calculations
-            switch (projection) {
-                case PROJECTION_FLAT:
-                    inputData = UVProjectionGenerator.flatProjection(inputData, bb);
-                    break;
-                case PROJECTION_CUBE:
-                    inputData = UVProjectionGenerator.cubeProjection(inputData, bb);
-                    break;
-                case PROJECTION_TUBE:
-                    BoundingTube bt = UVCoordinatesGenerator.getBoundingTube(geometries);
-                    inputData = UVProjectionGenerator.tubeProjection(inputData, bt);
-                    break;
-                case PROJECTION_SPHERE:
-                    BoundingSphere bs = UVCoordinatesGenerator.getBoundingSphere(geometries);
-                    inputData = UVProjectionGenerator.sphereProjection(inputData, bs);
-                    break;
-                default:
-                    throw new IllegalStateException("Unknown projection type: " + projection);
-            }
-            for (int i = 0; i < inputData.length; i += 2) {
-                result.add(new Vector2f(inputData[i], inputData[i + 1]));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Generates a UV coordinates for 3D texture.
-     * 
-     * @param mesh
-     *            the mesh we generate UV's for
-     * @param texco
-     *            UV coordinates type
-     * @param coordinatesSwappingIndexes
-     *            coordinates swapping indexes
-     * @param geometries
-     *            the geometris the given mesh belongs to (required to compute
-     *            bounding box)
-     * @return UV coordinates for the given mesh
-     */
-    public static List<Vector3f> generateUVCoordinatesFor3DTexture(Mesh mesh, UVCoordinatesType texco, int[] coordinatesSwappingIndexes, Geometry... geometries) {
-        List<Vector3f> result = new ArrayList<Vector3f>();
-        BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometries);
-        float[] inputData = null;// positions, normals, reflection vectors, etc.
-
-        switch (texco) {
-            case TEXCO_ORCO:
-                inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Position));
-                break;
-            case TEXCO_UV:
-                Vector2f[] data = new Vector2f[] { new Vector2f(0, 1), new Vector2f(0, 0), new Vector2f(1, 0) };
-                for (int i = 0; i < mesh.getVertexCount(); ++i) {
-                    Vector2f uv = data[i % 3];
-                    result.add(new Vector3f(uv.x, uv.y, 0));
-                }
-                break;
-            case TEXCO_NORM:
-                inputData = BufferUtils.getFloatArray(mesh.getFloatBuffer(VertexBuffer.Type.Normal));
-                break;
-            case TEXCO_REFL:
-            case TEXCO_GLOB:
-            case TEXCO_TANGENT:
-            case TEXCO_STRESS:
-            case TEXCO_LAVECTOR:
-            case TEXCO_OBJECT:
-            case TEXCO_OSA:
-            case TEXCO_PARTICLE_OR_STRAND:
-            case TEXCO_SPEED:
-            case TEXCO_STICKY:
-            case TEXCO_VIEW:
-            case TEXCO_WINDOW:
-                LOGGER.warning("Texture coordinates type not currently supported: " + texco);
-                break;
-            default:
-                throw new IllegalStateException("Unknown texture coordinates value: " + texco);
-        }
-
-        if (inputData != null) {// make calculations
-            Vector3f min = bb.getMin(null);
-            float[] uvCoordsResults = new float[4];// used for coordinates swapping
-            float[] ext = new float[] { bb.getXExtent() * 2, bb.getYExtent() * 2, bb.getZExtent() * 2 };
-            for (int i = 0; i < ext.length; ++i) {
-                if (ext[i] == 0) {
-                    ext[i] = 1;
-                }
-            }
-            // now transform the coordinates so that they are in the range of
-            // <0; 1>
-            for (int i = 0; i < inputData.length; i += 3) {
-                uvCoordsResults[1] = (inputData[i] - min.x) / ext[0];
-                uvCoordsResults[2] = (inputData[i + 1] - min.y) / ext[1];
-                uvCoordsResults[3] = (inputData[i + 2] - min.z) / ext[2];
-                result.add(new Vector3f(uvCoordsResults[coordinatesSwappingIndexes[0]], uvCoordsResults[coordinatesSwappingIndexes[1]], uvCoordsResults[coordinatesSwappingIndexes[2]]));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method should be used to determine if the texture will ever be
-     * computed. If the texture coordinates are not supported then the try of
-     * flattening the texture might result in runtime exceptions occurence.
-     * 
-     * @param texco
-     *            the texture coordinates type
-     * @return <b>true</b> if the type is supported and false otherwise
-     */
-    public static boolean isTextureCoordinateTypeSupported(UVCoordinatesType texco) {
-        switch (texco) {
-            case TEXCO_ORCO:
-            case TEXCO_UV:
-            case TEXCO_NORM:
-                return true;
-            case TEXCO_REFL:
-            case TEXCO_GLOB:
-            case TEXCO_TANGENT:
-            case TEXCO_STRESS:
-            case TEXCO_LAVECTOR:
-            case TEXCO_OBJECT:
-            case TEXCO_OSA:
-            case TEXCO_PARTICLE_OR_STRAND:
-            case TEXCO_SPEED:
-            case TEXCO_STICKY:
-            case TEXCO_VIEW:
-            case TEXCO_WINDOW:
-                return false;
-            default:
-                throw new IllegalStateException("Unknown texture coordinates value: " + texco);
-        }
-    }
-
-    /**
-     * This method returns the bounding box of the given geometries.
-     * 
-     * @param geometries
-     *            the list of geometries
-     * @return bounding box of the given geometries
-     */
-    public static BoundingBox getBoundingBox(Geometry... geometries) {
-        BoundingBox result = null;
-        for (Geometry geometry : geometries) {
-            geometry.updateModelBound();
-            BoundingVolume bv = geometry.getModelBound();
-            if (bv instanceof BoundingBox) {
-                return (BoundingBox) bv;
-            } else if (bv instanceof BoundingSphere) {
-                BoundingSphere bs = (BoundingSphere) bv;
-                float r = bs.getRadius();
-                return new BoundingBox(bs.getCenter(), r, r, r);
-            } else {
-                throw new IllegalStateException("Unknown bounding volume type: " + bv.getClass().getName());
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the bounding sphere of the given geometries.
-     * 
-     * @param geometries
-     *            the list of geometries
-     * @return bounding sphere of the given geometries
-     */
-    /* package */static BoundingSphere getBoundingSphere(Geometry... geometries) {
-        BoundingSphere result = null;
-        for (Geometry geometry : geometries) {
-            geometry.updateModelBound();
-            BoundingVolume bv = geometry.getModelBound();
-            if (bv instanceof BoundingBox) {
-                BoundingBox bb = (BoundingBox) bv;
-                float r = Math.max(bb.getXExtent(), bb.getYExtent());
-                r = Math.max(r, bb.getZExtent());
-                return new BoundingSphere(r, bb.getCenter());
-            } else if (bv instanceof BoundingSphere) {
-                return (BoundingSphere) bv;
-            } else {
-                throw new IllegalStateException("Unknown bounding volume type: " + bv.getClass().getName());
-            }
-        }
-        return result;
-    }
-
-    /**
-     * This method returns the bounding tube of the given geometries.
-     * 
-     * @param geometries
-     *            the list of geometries
-     * @return bounding tube of the given geometries
-     */
-    /* package */static BoundingTube getBoundingTube(Geometry... geometries) {
-        BoundingTube result = null;
-        for (Geometry geometry : geometries) {
-            BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometry);
-            Vector3f max = bb.getMax(null);
-            Vector3f min = bb.getMin(null);
-            float radius = Math.max(max.x - min.x, max.y - min.y) * 0.5f;
-            
-            BoundingTube bt = new BoundingTube(radius, max.z - min.z, bb.getCenter());
-            if (result == null) {
-                result = bt;
-            } else {
-                result.merge(bt);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * A very simple bounding tube. It holds only the basic data bout the
-     * bounding tube and does not provide full functionality of a
-     * BoundingVolume. Should be replaced with a bounding tube that extends the
-     * BoundingVolume if it is ever created.
-     * 
-     * @author Marcin Roguski (Kaelthas)
-     */
-    /* package */static class BoundingTube {
-        private float    radius;
-        private float    height;
-        private Vector3f center;
-
-        /**
-         * Constructor creates the tube with the given params.
-         * 
-         * @param radius
-         *            the radius of the tube
-         * @param height
-         *            the height of the tube
-         * @param center
-         *            the center of the tube
-         */
-        public BoundingTube(float radius, float height, Vector3f center) {
-            this.radius = radius;
-            this.height = height;
-            this.center = center;
-        }
-
-        /**
-         * This method merges two bounding tubes.
-         * 
-         * @param boundingTube
-         *            bounding tube to be merged woth the current one
-         * @return new instance of bounding tube representing the tubes' merge
-         */
-        public BoundingTube merge(BoundingTube boundingTube) {
-            // get tubes (tube1.radius >= tube2.radius)
-            BoundingTube tube1, tube2;
-            if (radius >= boundingTube.radius) {
-                tube1 = this;
-                tube2 = boundingTube;
-            } else {
-                tube1 = boundingTube;
-                tube2 = this;
-            }
-            float r1 = tube1.radius;
-            float r2 = tube2.radius;
-
-            float minZ = Math.min(tube1.center.z - tube1.height * 0.5f, tube2.center.z - tube2.height * 0.5f);
-            float maxZ = Math.max(tube1.center.z + tube1.height * 0.5f, tube2.center.z + tube2.height * 0.5f);
-            float height = maxZ - minZ;
-            Vector3f distance = tube2.center.subtract(tube1.center);
-            Vector3f center = tube1.center.add(distance.mult(0.5f));
-            distance.z = 0;// projecting this vector on XY plane
-            float d = distance.length();
-            // d <= r1 - r2: tube2 is inside tube1 or touches tube1 from the
-            // inside
-            // d > r1 - r2: tube2 is outside or touches tube1 or crosses tube1
-            float radius = d <= r1 - r2 ? tube1.radius : (d + r1 + r2) * 0.5f;
-            return new BoundingTube(radius, height, center);
-        }
-
-        /**
-         * @return the radius of the tube
-         */
-        public float getRadius() {
-            return radius;
-        }
-
-        /**
-         * @return the height of the tube
-         */
-        public float getHeight() {
-            return height;
-        }
-
-        /**
-         * @return the center of the tube
-         */
-        public Vector3f getCenter() {
-            return center;
-        }
-    }
-}

+ 0 - 240
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/UVProjectionGenerator.java

@@ -1,240 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import com.jme3.bounding.BoundingBox;
-import com.jme3.bounding.BoundingSphere;
-import com.jme3.math.FastMath;
-import com.jme3.math.Triangle;
-import com.jme3.math.Vector3f;
-import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTube;
-
-/**
- * This class helps with projection calculations.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class UVProjectionGenerator {
-    /**
-     * 2D texture mapping (projection)
-     * @author Marcin Roguski (Kaelthas)
-     */
-    public static enum UVProjectionType {
-        PROJECTION_FLAT(0), PROJECTION_CUBE(1), PROJECTION_TUBE(2), PROJECTION_SPHERE(3);
-
-        public final int blenderValue;
-
-        private UVProjectionType(int blenderValue) {
-            this.blenderValue = blenderValue;
-        }
-
-        public static UVProjectionType valueOf(int blenderValue) {
-            for (UVProjectionType projectionType : UVProjectionType.values()) {
-                if (projectionType.blenderValue == blenderValue) {
-                    return projectionType;
-                }
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Flat projection for 2D textures.
-     * 
-     * @param mesh
-     *            mesh that is to be projected
-     * @param bb
-     *            the bounding box for projecting
-     * @return UV coordinates after the projection
-     */
-    public static float[] flatProjection(float[] positions, BoundingBox bb) {
-        Vector3f min = bb.getMin(null);
-        float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getZExtent() * 2.0f };
-        float[] uvCoordinates = new float[positions.length / 3 * 2];
-        for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
-            uvCoordinates[j] = (positions[i] - min.x) / ext[0];
-            // skip the Y-coordinate
-            uvCoordinates[j + 1] = (positions[i + 2] - min.z) / ext[1];
-        }
-        return uvCoordinates;
-    }
-
-    /**
-     * Cube projection for 2D textures.
-     * 
-     * @param positions
-     *            points to be projected
-     * @param bb
-     *            the bounding box for projecting
-     * @return UV coordinates after the projection
-     */
-    public static float[] cubeProjection(float[] positions, BoundingBox bb) {
-        Triangle triangle = new Triangle();
-        Vector3f x = new Vector3f(1, 0, 0);
-        Vector3f y = new Vector3f(0, 1, 0);
-        Vector3f z = new Vector3f(0, 0, 1);
-        Vector3f min = bb.getMin(null);
-        float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f, bb.getZExtent() * 2.0f };
-
-        float[] uvCoordinates = new float[positions.length / 3 * 2];
-        float borderAngle = (float) Math.sqrt(2.0f) / 2.0f;
-        for (int i = 0, pointIndex = 0; i < positions.length; i += 9) {
-            triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
-            triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
-            triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
-            Vector3f n = triangle.getNormal();
-            float dotNX = Math.abs(n.dot(x));
-            float dorNY = Math.abs(n.dot(y));
-            float dotNZ = Math.abs(n.dot(z));
-            if (dotNX > borderAngle) {
-                if (dotNZ < borderAngle) {// discard X-coordinate
-                    uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get1().z - min.z) / ext[2];
-                    uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get2().z - min.z) / ext[2];
-                    uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get3().z - min.z) / ext[2];
-                } else {// discard Z-coordinate
-                    uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
-                }
-            } else {
-                if (dorNY > borderAngle) {// discard Y-coordinate
-                    uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get1().z - min.z) / ext[2];
-                    uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get2().z - min.z) / ext[2];
-                    uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get3().z - min.z) / ext[2];
-                } else {// discard Z-coordinate
-                    uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
-                    uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
-                    uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
-                }
-            }
-            triangle.setNormal(null);// clear the previous normal vector
-        }
-        return uvCoordinates;
-    }
-
-    /**
-     * Tube projection for 2D textures.
-     * 
-     * @param positions
-     *            points to be projected
-     * @param bt
-     *            the bounding tube for projecting
-     * @return UV coordinates after the projection
-     */
-    public static float[] tubeProjection(float[] positions, BoundingTube bt) {
-        float[] uvCoordinates = new float[positions.length / 3 * 2];
-        Vector3f v = new Vector3f();
-        float cx = bt.getCenter().x, cz = bt.getCenter().z;
-        Vector3f uBase = new Vector3f(0, 0, -1);
-
-        float vBase = bt.getCenter().y - bt.getHeight() * 0.5f;
-        for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
-            // calculating U
-            v.set(positions[i] - cx, 0, positions[i + 2] - cz);
-            v.normalizeLocal();
-            float angle = v.angleBetween(uBase);// result between [0; PI]
-            if (v.x < 0) {// the angle should be greater than PI, we're on the other part of the image then
-                angle = FastMath.TWO_PI - angle;
-            }
-            uvCoordinates[j] = angle / FastMath.TWO_PI;
-
-            // calculating V
-            float y = positions[i + 1];
-            uvCoordinates[j + 1] = (y - vBase) / bt.getHeight();
-        }
-
-        // looking for splitted triangles
-        Triangle triangle = new Triangle();
-        for (int i = 0; i < positions.length; i += 9) {
-            triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
-            triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
-            triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
-            float sgn1 = Math.signum(triangle.get1().x - cx);
-            float sgn2 = Math.signum(triangle.get2().x - cx);
-            float sgn3 = Math.signum(triangle.get3().x - cx);
-            float xSideFactor = sgn1 + sgn2 + sgn3;
-            float ySideFactor = Math.signum(triangle.get1().z - cz) + Math.signum(triangle.get2().z - cz) + Math.signum(triangle.get3().z - cz);
-            if ((xSideFactor > -3 || xSideFactor < 3) && ySideFactor < 0) {// the triangle is on the splitting plane
-                if (sgn1 == 1.0f) {
-                    uvCoordinates[i / 3 * 2] += 1.0f;
-                }
-                if (sgn2 == 1.0f) {
-                    uvCoordinates[(i / 3 + 1) * 2] += 1.0f;
-                }
-                if (sgn3 == 1.0f) {
-                    uvCoordinates[(i / 3 + 2) * 2] += 1.0f;
-                }
-            }
-        }
-        return uvCoordinates;
-    }
-
-    /**
-     * Sphere projection for 2D textures.
-     * 
-     * @param positions
-     *            points to be projected
-     * @param bb
-     *            the bounding box for projecting
-     * @return UV coordinates after the projection
-     */
-    public static float[] sphereProjection(float[] positions, BoundingSphere bs) {// TODO: rotate it to be vertical
-        float[] uvCoordinates = new float[positions.length / 3 * 2];
-        Vector3f v = new Vector3f();
-        float cx = bs.getCenter().x, cy = bs.getCenter().y, cz = bs.getCenter().z;
-        Vector3f uBase = new Vector3f(0, -1, 0);
-        Vector3f vBase = new Vector3f(0, 0, -1);
-
-        for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
-            // calculating U
-            v.set(positions[i] - cx, positions[i + 1] - cy, 0);
-            v.normalizeLocal();
-            float angle = v.angleBetween(uBase);// result between [0; PI]
-            if (v.x < 0) {// the angle should be greater than PI, we're on the other part of the image then
-                angle = FastMath.TWO_PI - angle;
-            }
-            uvCoordinates[j] = angle / FastMath.TWO_PI;
-
-            // calculating V
-            v.set(positions[i] - cx, positions[i + 1] - cy, positions[i + 2] - cz);
-            v.normalizeLocal();
-            angle = v.angleBetween(vBase);// result between [0; PI]
-            uvCoordinates[j + 1] = angle / FastMath.PI;
-        }
-
-        // looking for splitted triangles
-        Triangle triangle = new Triangle();
-        for (int i = 0; i < positions.length; i += 9) {
-            triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
-            triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
-            triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
-            float sgn1 = Math.signum(triangle.get1().x - cx);
-            float sgn2 = Math.signum(triangle.get2().x - cx);
-            float sgn3 = Math.signum(triangle.get3().x - cx);
-            float xSideFactor = sgn1 + sgn2 + sgn3;
-            float ySideFactor = Math.signum(triangle.get1().y - cy) + Math.signum(triangle.get2().y - cy) + Math.signum(triangle.get3().y - cy);
-            if ((xSideFactor > -3 || xSideFactor < 3) && ySideFactor < 0) {// the triangle is on the splitting plane
-                if (sgn1 == 1.0f) {
-                    uvCoordinates[i / 3 * 2] += 1.0f;
-                }
-                if (sgn2 == 1.0f) {
-                    uvCoordinates[(i / 3 + 1) * 2] += 1.0f;
-                }
-                if (sgn3 == 1.0f) {
-                    uvCoordinates[(i / 3 + 2) * 2] += 1.0f;
-                }
-            }
-        }
-        return uvCoordinates;
-    }
-}

+ 0 - 86
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/UserUVCollection.java

@@ -1,86 +0,0 @@
-package com.jme3.scene.plugins.blender.textures;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.jme3.math.Vector2f;
-
-/**
- * A collection of UV coordinates. The coords are stored in groups defined by the material index and their UV set name.
- * 
- * @author Kaelthas (Marcin Roguski)
- */
-public class UserUVCollection {
-    /** A map between material number and UV coordinates of mesh that has this material applied. */
-    private Map<Integer, LinkedHashMap<String, List<Vector2f>>> uvCoordinates = new HashMap<Integer, LinkedHashMap<String, List<Vector2f>>>();
-    /** A map between vertex index and its UV coordinates. */
-    private Map<String, Map<Integer, Vector2f>>                 uvsMap        = new HashMap<String, Map<Integer, Vector2f>>();
-
-    /**
-     * Adds a single UV coordinates for a specified vertex index.
-     * @param materialIndex
-     *            the material index
-     * @param uvSetName
-     *            the UV set name
-     * @param uv
-     *            the added UV coordinates
-     * @param jmeVertexIndex
-     *            the index of the vertex in result jme mesh
-     */
-    public void addUV(int materialIndex, String uvSetName, Vector2f uv, int jmeVertexIndex) {
-        // first get all UV sets for the specified material ...
-        LinkedHashMap<String, List<Vector2f>> uvsForMaterial = uvCoordinates.get(materialIndex);
-        if (uvsForMaterial == null) {
-            uvsForMaterial = new LinkedHashMap<String, List<Vector2f>>();
-            uvCoordinates.put(materialIndex, uvsForMaterial);
-        }
-
-        // ... then fetch the UVS for the specified UV set name ...
-        List<Vector2f> uvsForName = uvsForMaterial.get(uvSetName);
-        if (uvsForName == null) {
-            uvsForName = new ArrayList<Vector2f>();
-            uvsForMaterial.put(uvSetName, uvsForName);
-        }
-
-        // ... add the UV coordinates to the proper list ...
-        uvsForName.add(uv);
-
-        // ... and add the mapping of the UV coordinates to a vertex index for the specified UV set
-        Map<Integer, Vector2f> uvToVertexIndexMapping = uvsMap.get(uvSetName);
-        if (uvToVertexIndexMapping == null) {
-            uvToVertexIndexMapping = new HashMap<Integer, Vector2f>();
-            uvsMap.put(uvSetName, uvToVertexIndexMapping);
-        }
-        uvToVertexIndexMapping.put(jmeVertexIndex, uv);
-    }
-
-    /**
-     * @param uvSetName
-     *            the name of the UV set
-     * @param vertexIndex
-     *            the vertex index corresponds to the index in jme mesh and not the original one in blender
-     * @return a pre-existing coordinate vector
-     */
-    public Vector2f getUVForVertex(String uvSetName, int vertexIndex) {
-        return uvsMap.get(uvSetName).get(vertexIndex);
-    }
-
-    /**
-     * @param materialNumber
-     *            the material number that is appied to the mesh
-     * @return UV coordinates of vertices that belong to the required mesh part
-     */
-    public LinkedHashMap<String, List<Vector2f>> getUVCoordinates(int materialNumber) {
-        return uvCoordinates.get(materialNumber);
-    }
-
-    /**
-     * @return indicates if the mesh has UV coordinates
-     */
-    public boolean hasUVCoordinates() {
-        return uvCoordinates.size() > 0;
-    }
-}

+ 0 - 139
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java

@@ -1,139 +0,0 @@
-package com.jme3.scene.plugins.blender.textures.blending;
-
-import java.util.logging.Logger;
-
-import jme3tools.converters.MipMapGenerator;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.materials.MaterialHelper;
-import com.jme3.texture.Image;
-
-/**
- * An abstract class that contains the basic methods used by the classes that
- * will derive from it.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */abstract class AbstractTextureBlender implements TextureBlender {
-    private static final Logger LOGGER = Logger.getLogger(AbstractTextureBlender.class.getName());
-
-    protected int               flag;
-    protected boolean           negateTexture;
-    protected int               blendType;
-    protected float[]           materialColor;
-    protected float[]           color;
-    protected float             blendFactor;
-
-    public AbstractTextureBlender(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) {
-        this.flag = flag;
-        this.negateTexture = negateTexture;
-        this.blendType = blendType;
-        this.materialColor = materialColor;
-        this.color = color;
-        this.blendFactor = blendFactor;
-    }
-
-    /**
-     * The method that performs the ramp blending.
-     * 
-     * @param type
-     *            the blend type
-     * @param materialRGB
-     *            the rgb value of the material, here the result is stored too
-     * @param fac
-     *            color affection factor
-     * @param pixelColor
-     *            the texture color
-     * @param blenderContext
-     *            the blender context
-     */
-    protected void blendHSV(int type, float[] materialRGB, float fac, float[] pixelColor, BlenderContext blenderContext) {
-        float oneMinusFactor = 1.0f - fac;
-        MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
-
-        switch (type) {
-            case MTEX_BLEND_HUE: {// FIXME: not working well for image textures (works fine for generated textures)
-                float[] colorTransformResult = new float[3];
-                materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult);
-                if (colorTransformResult[0] != 0.0f) {
-                    float colH = colorTransformResult[0];
-                    materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult);
-                    materialHelper.hsvToRgb(colH, colorTransformResult[1], colorTransformResult[2], colorTransformResult);
-                    materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * colorTransformResult[0];
-                    materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * colorTransformResult[1];
-                    materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * colorTransformResult[2];
-                }
-                break;
-            }
-            case MTEX_BLEND_SAT: {
-                float[] colorTransformResult = new float[3];
-                materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult);
-                float h = colorTransformResult[0];
-                float s = colorTransformResult[1];
-                float v = colorTransformResult[2];
-                if (s != 0.0f) {
-                    materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult);
-                    materialHelper.hsvToRgb(h, oneMinusFactor * s + fac * colorTransformResult[1], v, materialRGB);
-                }
-                break;
-            }
-            case MTEX_BLEND_VAL: {
-                float[] rgbToHsv = new float[3];
-                float[] colToHsv = new float[3];
-                materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv);
-                materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv);
-                materialHelper.hsvToRgb(rgbToHsv[0], rgbToHsv[1], oneMinusFactor * rgbToHsv[2] + fac * colToHsv[2], materialRGB);
-                break;
-            }
-            case MTEX_BLEND_COLOR: {// FIXME: not working well for image textures (works fine for generated textures)
-                float[] rgbToHsv = new float[3];
-                float[] colToHsv = new float[3];
-                materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv);
-                if (colToHsv[2] != 0) {
-                    materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv);
-                    materialHelper.hsvToRgb(colToHsv[0], colToHsv[1], rgbToHsv[2], rgbToHsv);
-                    materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * rgbToHsv[0];
-                    materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * rgbToHsv[1];
-                    materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * rgbToHsv[2];
-                }
-                break;
-            }
-            default:
-                throw new IllegalStateException("Unknown ramp type: " + type);
-        }
-    }
-
-    @Override
-    public void copyBlendingData(TextureBlender textureBlender) {
-        if (textureBlender instanceof AbstractTextureBlender) {
-            flag = ((AbstractTextureBlender) textureBlender).flag;
-            negateTexture = ((AbstractTextureBlender) textureBlender).negateTexture;
-            blendType = ((AbstractTextureBlender) textureBlender).blendType;
-            materialColor = ((AbstractTextureBlender) textureBlender).materialColor.clone();
-            color = ((AbstractTextureBlender) textureBlender).color.clone();
-            blendFactor = ((AbstractTextureBlender) textureBlender).blendFactor;
-        } else {
-            LOGGER.warning("Cannot copy blending data from other types than " + this.getClass());
-        }
-    }
-
-    /**
-     * The method prepares images for blending. It generates mipmaps if one of
-     * the images has them defined and the other one has not.
-     * 
-     * @param target
-     *            the image where the blending result is stored
-     * @param source
-     *            the image that is being read only
-     */
-    protected void prepareImagesForBlending(Image target, Image source) {
-        LOGGER.fine("Generating mipmaps if needed!");
-        boolean targetHasMipmaps = target == null ? false : target.getMipMapSizes() != null && target.getMipMapSizes().length > 0;
-        boolean sourceHasMipmaps = source == null ? false : source.getMipMapSizes() != null && source.getMipMapSizes().length > 0;
-        if (target != null && !targetHasMipmaps && sourceHasMipmaps) {
-            MipMapGenerator.generateMipMaps(target);
-        } else if (source != null && !sourceHasMipmaps && targetHasMipmaps) {
-            MipMapGenerator.generateMipMaps(source);
-        }
-    }
-}

+ 0 - 53
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlender.java

@@ -1,53 +0,0 @@
-package com.jme3.scene.plugins.blender.textures.blending;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.texture.Image;
-
-/**
- * An interface for texture blending classes (the classes that mix the texture
- * pixels with the material colors).
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public interface TextureBlender {
-    // types of blending
-    int MTEX_BLEND          = 0;
-    int MTEX_MUL            = 1;
-    int MTEX_ADD            = 2;
-    int MTEX_SUB            = 3;
-    int MTEX_DIV            = 4;
-    int MTEX_DARK           = 5;
-    int MTEX_DIFF           = 6;
-    int MTEX_LIGHT          = 7;
-    int MTEX_SCREEN         = 8;
-    int MTEX_OVERLAY        = 9;
-    int MTEX_BLEND_HUE      = 10;
-    int MTEX_BLEND_SAT      = 11;
-    int MTEX_BLEND_VAL      = 12;
-    int MTEX_BLEND_COLOR    = 13;
-    int MTEX_NUM_BLENDTYPES = 14;
-
-    /**
-     * This method blends the given texture with material color and the defined
-     * color in 'map to' panel. As a result of this method a new texture is
-     * created. The input texture is NOT.
-     * 
-     * @param image
-     *            the image we use in blending
-     * @param baseImage
-     *            the texture that is underneath the current texture (its pixels
-     *            will be used instead of material color)
-     * @param blenderContext
-     *            the blender context
-     * @return new image that was created after the blending
-     */
-    Image blend(Image image, Image baseImage, BlenderContext blenderContext);
-
-    /**
-     * Copies blending data. Used for blending type format changing.
-     * 
-     * @param textureBlender
-     *            the blend data that should be copied
-     */
-    void copyBlendingData(TextureBlender textureBlender);
-}

+ 0 - 275
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java

@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures.blending;
-
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.util.BufferUtils;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-/**
- * <p>
- * The class that is responsible for blending the following texture types: 
- * </p>
- * <ul>
- * <li>RGBA8</li>
- * <li>ABGR8</li>
- * <li>BGR8</li>
- * <li>RGB8</li>
- * </ul>
- * 
- * <p>
- * Not yet supported (but will be):
- * </p>
- * <ul>
- * <li>ARGB4444</li>
- * <li>RGB10</li>
- * <li>RGB111110F</li>
- * <li>RGB16</li>
- * <li>RGB16F</li>
- * <li>RGB16F_to_RGB111110F</li>
- * <li>RGB16F_to_RGB9E5</li>
- * <li>RGB32F</li>
- * <li>RGB565</li>
- * <li>RGB5A1</li>
- * <li>RGB9E5</li>
- * <li>RGBA16</li>
- * <li>RGBA16F</li>
- * </ul>
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class TextureBlenderAWT extends AbstractTextureBlender {
-    public TextureBlenderAWT(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) {
-        super(flag, negateTexture, blendType, materialColor, color, blendFactor);
-    }
-
-    @Override
-    public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
-        this.prepareImagesForBlending(image, baseImage);
-
-        float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
-        Format format = image.getFormat();
-
-        PixelInputOutput basePixelIO = null, pixelReader = PixelIOFactory.getPixelIO(format);
-        TexturePixel basePixel = null, pixel = new TexturePixel();
-        float[] materialColor = this.materialColor;
-        if (baseImage != null) {
-            basePixelIO = PixelIOFactory.getPixelIO(baseImage.getFormat());
-            materialColor = new float[this.materialColor.length];
-            basePixel = new TexturePixel();
-        }
-
-        int width = image.getWidth();
-        int height = image.getHeight();
-        int depth = image.getDepth();
-        if (depth == 0) {
-            depth = 1;
-        }
-        int bytesPerPixel = image.getFormat().getBitsPerPixel() >> 3;
-        ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
-
-        float[] resultPixel = new float[4];
-        for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
-            ByteBuffer data = image.getData(dataLayerIndex);
-            data.rewind();
-            int imagePixelCount = data.limit() / bytesPerPixel;
-            ByteBuffer newData = BufferUtils.createByteBuffer(imagePixelCount * 4);
-
-            int dataIndex = 0, x = 0, y = 0, index = 0;
-            while (index < data.limit()) {
-                // getting the proper material color if the base texture is applied
-                if (basePixelIO != null) {
-                    basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
-                    basePixel.toRGBA(materialColor);
-                    ++x;
-                    if (x >= width) {
-                        x = 0;
-                        ++y;
-                    }
-                }
-
-                // reading the current texture's pixel
-                pixelReader.read(image, dataLayerIndex, pixel, index);
-                index += bytesPerPixel;
-                pixel.toRGBA(pixelColor);
-                if (negateTexture) {
-                    pixel.negate();
-                }
-
-                this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext);
-                newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
-                newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
-                newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
-                newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f));
-            }
-            dataArray.add(newData);
-        }
-        
-        ColorSpace colorSpace;
-        if (baseImage != null) {
-            colorSpace = baseImage.getColorSpace() != null ? baseImage.getColorSpace() : ColorSpace.Linear;
-        } else {
-            colorSpace = image.getColorSpace();
-        }
-        
-        Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray, colorSpace) : new Image(Format.RGBA8, width, height, dataArray.get(0), colorSpace);
-        if (image.getMipMapSizes() != null) {
-            result.setMipMapSizes(image.getMipMapSizes().clone());
-        }
-        return result;
-    }
-
-    /**
-     * This method blends the single pixel depending on the blending type.
-     * 
-     * @param result
-     *            the result pixel
-     * @param materialColor
-     *            the material color
-     * @param pixelColor
-     *            the pixel color
-     * @param blenderContext
-     *            the blender context
-     */
-    protected void blendPixel(float[] result, float[] materialColor, float[] pixelColor, BlenderContext blenderContext) {
-        // We calculate first the importance of the texture (colFactor * texAlphaValue)
-        float blendFactor = this.blendFactor * pixelColor[3];
-        // Then, we get the object material factor ((1 - texture importance) * matAlphaValue) 
-        float oneMinusFactor = (1f - blendFactor) * materialColor[3];
-        // Finally, we can get the final blendFactor, which is 1 - the material factor.
-        blendFactor = 1f - oneMinusFactor;
-        
-        // --- Compact method ---
-        // float blendFactor = this.blendFactor * (1f - ((1f - pixelColor[3]) * materialColor[3]));
-        // float oneMinusFactor = 1f - blendFactor;
-
-        float col;
-        
-        switch (blendType) {
-            case MTEX_BLEND:
-                result[0] = blendFactor * pixelColor[0] + oneMinusFactor * materialColor[0];
-                result[1] = blendFactor * pixelColor[1] + oneMinusFactor * materialColor[1];
-                result[2] = blendFactor * pixelColor[2] + oneMinusFactor * materialColor[2];
-                break;
-            case MTEX_MUL:
-                result[0] = (oneMinusFactor + blendFactor * materialColor[0]) * pixelColor[0];
-                result[1] = (oneMinusFactor + blendFactor * materialColor[1]) * pixelColor[1];
-                result[2] = (oneMinusFactor + blendFactor * materialColor[2]) * pixelColor[2];
-                break;
-            case MTEX_DIV:
-                if (pixelColor[0] != 0.0) {
-                    result[0] = (oneMinusFactor * materialColor[0] + blendFactor * materialColor[0] / pixelColor[0]) * 0.5f;
-                }
-                if (pixelColor[1] != 0.0) {
-                    result[1] = (oneMinusFactor * materialColor[1] + blendFactor * materialColor[1] / pixelColor[1]) * 0.5f;
-                }
-                if (pixelColor[2] != 0.0) {
-                    result[2] = (oneMinusFactor * materialColor[2] + blendFactor * materialColor[2] / pixelColor[2]) * 0.5f;
-                }
-                break;
-            case MTEX_SCREEN:
-                result[0] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]);
-                result[1] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]);
-                result[2] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]);
-                break;
-            case MTEX_OVERLAY:
-                if (materialColor[0] < 0.5f) {
-                    result[0] = pixelColor[0] * (oneMinusFactor + 2.0f * blendFactor * materialColor[0]);
-                } else {
-                    result[0] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]);
-                }
-                if (materialColor[1] < 0.5f) {
-                    result[1] = pixelColor[1] * (oneMinusFactor + 2.0f * blendFactor * materialColor[1]);
-                } else {
-                    result[1] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]);
-                }
-                if (materialColor[2] < 0.5f) {
-                    result[2] = pixelColor[2] * (oneMinusFactor + 2.0f * blendFactor * materialColor[2]);
-                } else {
-                    result[2] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]);
-                }
-                break;
-            case MTEX_SUB:
-                result[0] = materialColor[0] - blendFactor * pixelColor[0];
-                result[1] = materialColor[1] - blendFactor * pixelColor[1];
-                result[2] = materialColor[2] - blendFactor * pixelColor[2];
-                result[0] = FastMath.clamp(result[0], 0.0f, 1.0f);
-                result[1] = FastMath.clamp(result[1], 0.0f, 1.0f);
-                result[2] = FastMath.clamp(result[2], 0.0f, 1.0f);
-                break;
-            case MTEX_ADD:
-                result[0] = (blendFactor * pixelColor[0] + materialColor[0]) * 0.5f;
-                result[1] = (blendFactor * pixelColor[1] + materialColor[1]) * 0.5f;
-                result[2] = (blendFactor * pixelColor[2] + materialColor[2]) * 0.5f;
-                break;
-            case MTEX_DIFF:
-                result[0] = oneMinusFactor * materialColor[0] + blendFactor * Math.abs(materialColor[0] - pixelColor[0]);
-                result[1] = oneMinusFactor * materialColor[1] + blendFactor * Math.abs(materialColor[1] - pixelColor[1]);
-                result[2] = oneMinusFactor * materialColor[2] + blendFactor * Math.abs(materialColor[2] - pixelColor[2]);
-                break;
-            case MTEX_DARK:
-                col = blendFactor * pixelColor[0];
-                result[0] = col < materialColor[0] ? col : materialColor[0];
-                col = blendFactor * pixelColor[1];
-                result[1] = col < materialColor[1] ? col : materialColor[1];
-                col = blendFactor * pixelColor[2];
-                result[2] = col < materialColor[2] ? col : materialColor[2];
-                break;
-            case MTEX_LIGHT:
-                col = blendFactor * pixelColor[0];
-                result[0] = col > materialColor[0] ? col : materialColor[0];
-                col = blendFactor * pixelColor[1];
-                result[1] = col > materialColor[1] ? col : materialColor[1];
-                col = blendFactor * pixelColor[2];
-                result[2] = col > materialColor[2] ? col : materialColor[2];
-                break;
-            case MTEX_BLEND_HUE:
-            case MTEX_BLEND_SAT:
-            case MTEX_BLEND_VAL:
-            case MTEX_BLEND_COLOR:
-                System.arraycopy(materialColor, 0, result, 0, 3);
-                this.blendHSV(blendType, result, blendFactor, pixelColor, blenderContext);
-                break;
-            default:
-                throw new IllegalStateException("Unknown blend type: " + blendType);
-        }
-    }
-}

+ 0 - 131
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java

@@ -1,131 +0,0 @@
-package com.jme3.scene.plugins.blender.textures.blending;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.util.BufferUtils;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-import jme3tools.converters.RGB565;
-
-/**
- * <p>
- * The class that is responsible for blending the following texture types:
- * </p>
- * <ul>
- * <li>DXT1</li>
- * <li>DXT1A</li>
- * <li>DXT3</li>
- * <li>DXT5</li>
- * </ul>
- * @author Marcin Roguski (Kaelthas)
- */
-public class TextureBlenderDDS extends TextureBlenderAWT {
-    public TextureBlenderDDS(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) {
-        super(flag, negateTexture, blendType, materialColor, color, blendFactor);
-    }
-
-    @Override
-    public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
-        this.prepareImagesForBlending(image, baseImage);
-
-        Format format = image.getFormat();
-        int width = image.getWidth();
-        int height = image.getHeight();
-        int depth = image.getDepth();
-        if (depth == 0) {
-            depth = 1;
-        }
-        ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
-
-        PixelInputOutput basePixelIO = null;
-        float[][] compressedMaterialColor = null;
-        TexturePixel[] baseTextureColors = null;
-        if (baseImage != null) {
-            basePixelIO = PixelIOFactory.getPixelIO(baseImage.getFormat());
-            compressedMaterialColor = new float[2][4];
-            baseTextureColors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
-        }
-
-        float[] resultPixel = new float[4];
-        float[] pixelColor = new float[4];
-        TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
-        int baseXTexelIndex = 0, baseYTexelIndex = 0;
-        float[] alphas = new float[] { 1, 1 };
-        for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
-            ByteBuffer data = image.getData(dataLayerIndex);
-            data.rewind();
-            ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
-            while (data.hasRemaining()) {
-                if (format == Format.DXT3) {
-                    long alpha = data.getLong();
-                    // get alpha for first and last pixel that is compressed in the texel
-                    byte alpha0 = (byte) (alpha << 4 & 0xFF);
-                    byte alpha1 = (byte) (alpha >> 60 & 0xFF);
-                    alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
-                    alphas[1] = alpha1 >= 0 ? alpha1 / 255.0f : 1.0f - ~alpha1 / 255.0f;
-                    newData.putLong(alpha);
-                } else if (format == Format.DXT5) {
-                    byte alpha0 = data.get();
-                    byte alpha1 = data.get();
-                    alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
-                    alphas[1] = alpha1 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
-                    newData.put(alpha0);
-                    newData.put(alpha1);
-                    // only read the next 6 bytes (these are alpha indexes)
-                    newData.putInt(data.getInt());
-                    newData.putShort(data.getShort());
-                }
-                int col0 = RGB565.RGB565_to_ARGB8(data.getShort());
-                int col1 = RGB565.RGB565_to_ARGB8(data.getShort());
-                colors[0].fromARGB8(col0);
-                colors[1].fromARGB8(col1);
-
-                // compressing 16 pixels from the base texture as if they belonged to a texel
-                if (baseImage != null) {
-                    // reading pixels (first and last of the 16 colors array)
-                    basePixelIO.read(baseImage, dataLayerIndex, baseTextureColors[0], baseXTexelIndex << 2, baseYTexelIndex << 2);// first pixel
-                    basePixelIO.read(baseImage, dataLayerIndex, baseTextureColors[1], baseXTexelIndex << 2 + 4, baseYTexelIndex << 2 + 4);// last pixel
-                    baseTextureColors[0].toRGBA(compressedMaterialColor[0]);
-                    baseTextureColors[1].toRGBA(compressedMaterialColor[1]);
-                }
-
-                // blending colors
-                for (int i = 0; i < colors.length; ++i) {
-                    if (negateTexture) {
-                        colors[i].negate();
-                    }
-                    colors[i].toRGBA(pixelColor);
-                    pixelColor[3] = alphas[i];
-                    this.blendPixel(resultPixel, compressedMaterialColor != null ? compressedMaterialColor[i] : materialColor, pixelColor, blenderContext);
-                    colors[i].fromARGB(1, resultPixel[0], resultPixel[1], resultPixel[2]);
-                    int argb8 = colors[i].toARGB8();
-                    short rgb565 = RGB565.ARGB8_to_RGB565(argb8);
-                    newData.putShort(rgb565);
-                }
-
-                // just copy the remaining 4 bytes of the current texel
-                newData.putInt(data.getInt());
-
-                ++baseXTexelIndex;
-                if (baseXTexelIndex > image.getWidth() >> 2) {
-                    baseXTexelIndex = 0;
-                    ++baseYTexelIndex;
-                }
-            }
-            dataArray.add(newData);
-        }
-
-        Image result = dataArray.size() > 1 ? new Image(format, width, height, depth, dataArray, ColorSpace.Linear) : new Image(format, width, height, dataArray.get(0), ColorSpace.Linear);
-        if (image.getMipMapSizes() != null) {
-            result.setMipMapSizes(image.getMipMapSizes().clone());
-        }
-        return result;
-    }
-}

+ 0 - 117
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderFactory.java

@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures.blending;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-
-/**
- * This class creates the texture blending class depending on the texture type.
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class TextureBlenderFactory {
-    private static final Logger LOGGER = Logger.getLogger(TextureBlenderFactory.class.getName());
-
-    /**
-     * A blender that does not change the image. Used for none supported image types.
-     */
-    private static final TextureBlender NON_CHANGING_BLENDER = new TextureBlender() {
-        @Override
-        public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
-            return image;
-        }
-
-        @Override
-        public void copyBlendingData(TextureBlender textureBlender) { }
-    };
-    
-    /**
-     * This method creates the blending class.
-     * 
-     * @param format
-     *            the texture format
-     * @return texture blending class
-     */
-    public static TextureBlender createTextureBlender(Format format, int flag, boolean negate, int blendType, float[] materialColor, float[] color, float colfac) {
-        switch (format) {
-            case Luminance8:
-            case Luminance8Alpha8:
-            case Luminance16F:
-            case Luminance16FAlpha16F:
-            case Luminance32F:
-                return new TextureBlenderLuminance(flag, negate, blendType, materialColor, color, colfac);
-            case RGBA8:
-            case ABGR8:
-            case BGR8:
-            case RGB8:
-            case RGB111110F:
-            case RGB16F:
-            case RGB16F_to_RGB111110F:
-            case RGB16F_to_RGB9E5:
-            case RGB32F:
-            case RGB565:
-            case RGB5A1:
-            case RGB9E5:
-            case RGBA16F:
-            case RGBA32F:
-                return new TextureBlenderAWT(flag, negate, blendType, materialColor, color, colfac);
-            case DXT1:
-            case DXT1A:
-            case DXT3:
-            case DXT5:
-                return new TextureBlenderDDS(flag, negate, blendType, materialColor, color, colfac);
-            default:
-                LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}. Returning a blender that does not change the texture.", format);
-                return NON_CHANGING_BLENDER;
-        }
-    }
-
-    /**
-     * This method changes the image format in the texture blender.
-     * 
-     * @param format
-     *            the new image format
-     * @param textureBlender
-     *            the texture blender that will be altered
-     * @return altered texture blender
-     */
-    public static TextureBlender alterTextureType(Format format, TextureBlender textureBlender) {
-        TextureBlender result = TextureBlenderFactory.createTextureBlender(format, 0, false, 0, null, null, 0);
-        result.copyBlendingData(textureBlender);
-        return result;
-    }
-}

+ 0 - 259
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java

@@ -1,259 +0,0 @@
-package com.jme3.scene.plugins.blender.textures.blending;
-
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
-import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.image.ColorSpace;
-import com.jme3.util.BufferUtils;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * <p>
- * The class that is responsible for blending the following texture types:
- * </p>
- * <ul>
- * <li>Luminance8</li>
- * <li>Luminance8Alpha8</li>
- * </ul>
- * <p>
- * Not yet supported (but will be):
- * </p>
- * <ul>
- * <li>Luminance16</li>
- * <li>Luminance16Alpha16</li>
- * <li>Luminance16F</li>
- * <li>Luminance16FAlpha16F</li>
- * <li>Luminance32F</li>
- * </ul>
- * 
- * @author Marcin Roguski (Kaelthas)
- */
-public class TextureBlenderLuminance extends AbstractTextureBlender {
-    private static final Logger LOGGER = Logger.getLogger(TextureBlenderLuminance.class.getName());
-
-    public TextureBlenderLuminance(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) {
-        super(flag, negateTexture, blendType, materialColor, color, blendFactor);
-    }
-
-    @Override
-    public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
-        this.prepareImagesForBlending(image, baseImage);
-
-        Format format = image.getFormat();
-        PixelInputOutput basePixelIO = null;
-        TexturePixel basePixel = null;
-        float[] materialColor = this.materialColor;
-        if (baseImage != null) {
-            basePixelIO = PixelIOFactory.getPixelIO(baseImage.getFormat());
-            materialColor = new float[this.materialColor.length];
-            basePixel = new TexturePixel();
-        }
-
-        int width = image.getWidth();
-        int height = image.getHeight();
-        int depth = image.getDepth();
-        if (depth == 0) {
-            depth = 1;
-        }
-        ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
-
-        float[] resultPixel = new float[4];
-        float[] tinAndAlpha = new float[2];
-        for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
-            ByteBuffer data = image.getData(dataLayerIndex);
-            data.rewind();
-            ByteBuffer newData = BufferUtils.createByteBuffer(data.limit() * 4);
-
-            int dataIndex = 0, x = 0, y = 0;
-            while (data.hasRemaining()) {
-                // getting the proper material color if the base texture is applied
-                if (basePixelIO != null) {
-                    basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
-                    basePixel.toRGBA(materialColor);
-                    
-                    ++x;
-                    if (x >= width) {
-                        x = 0;
-                        ++y;
-                    }
-                }
-
-                this.getTinAndAlpha(data, format, negateTexture, tinAndAlpha);
-                this.blendPixel(resultPixel, materialColor, color, tinAndAlpha[0], blendFactor, blendType, blenderContext);
-                newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
-                newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
-                newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
-                newData.put(dataIndex++, (byte) (tinAndAlpha[1] * 255.0f));
-            }
-            dataArray.add(newData);
-        }
-
-        Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray, ColorSpace.Linear) : new Image(Format.RGBA8, width, height, dataArray.get(0), ColorSpace.Linear);
-        if (image.getMipMapSizes() != null) {
-            result.setMipMapSizes(image.getMipMapSizes().clone());
-        }
-        return result;
-    }
-
-    /**
-     * This method return texture intensity and alpha value.
-     * 
-     * @param data
-     *            the texture data
-     * @param imageFormat
-     *            the image format
-     * @param neg
-     *            indicates if the texture is negated
-     * @param result
-     *            the table (2 elements) where the result is being stored
-     */
-    protected void getTinAndAlpha(ByteBuffer data, Format imageFormat, boolean neg, float[] result) {
-        byte pixelValue = data.get();// at least one byte is always taken
-        float firstPixelValue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - ~pixelValue / 255.0f;
-        switch (imageFormat) {
-            case Luminance8:
-                result[0] = neg ? 1.0f - firstPixelValue : firstPixelValue;
-                result[1] = 1.0f;
-                break;
-            case Luminance8Alpha8:
-                result[0] = neg ? 1.0f - firstPixelValue : firstPixelValue;
-                pixelValue = data.get();
-                result[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - ~pixelValue / 255.0f;
-                break;
-            case Luminance16F:
-            case Luminance16FAlpha16F:
-            case Luminance32F:
-                LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", imageFormat);
-                break;
-            default:
-                throw new IllegalStateException("Invalid image format type for Luminance texture blender: " + imageFormat);
-        }
-    }
-
-    /**
-     * This method blends the texture with an appropriate color.
-     * 
-     * @param result
-     *            the result color (variable 'in' in blender source code)
-     * @param materialColor
-     *            the texture color (variable 'out' in blender source coude)
-     * @param color
-     *            the previous color (variable 'tex' in blender source code)
-     * @param textureIntensity
-     *            texture intensity (variable 'fact' in blender source code)
-     * @param textureFactor
-     *            texture affection factor (variable 'facg' in blender source
-     *            code)
-     * @param blendtype
-     *            the blend type
-     * @param blenderContext
-     *            the blender context
-     */
-    protected void blendPixel(float[] result, float[] materialColor, float[] color, float textureIntensity, float textureFactor, int blendtype, BlenderContext blenderContext) {
-        float oneMinusFactor, col;
-        textureIntensity *= textureFactor;
-
-        switch (blendtype) {
-            case MTEX_BLEND:
-                oneMinusFactor = 1.0f - textureIntensity;
-                result[0] = textureIntensity * color[0] + oneMinusFactor * materialColor[0];
-                result[1] = textureIntensity * color[1] + oneMinusFactor * materialColor[1];
-                result[2] = textureIntensity * color[2] + oneMinusFactor * materialColor[2];
-                break;
-            case MTEX_MUL:
-                oneMinusFactor = 1.0f - textureFactor;
-                result[0] = (oneMinusFactor + textureIntensity * materialColor[0]) * color[0];
-                result[1] = (oneMinusFactor + textureIntensity * materialColor[1]) * color[1];
-                result[2] = (oneMinusFactor + textureIntensity * materialColor[2]) * color[2];
-                break;
-            case MTEX_DIV:
-                oneMinusFactor = 1.0f - textureIntensity;
-                if (color[0] != 0.0) {
-                    result[0] = (oneMinusFactor * materialColor[0] + textureIntensity * materialColor[0] / color[0]) * 0.5f;
-                }
-                if (color[1] != 0.0) {
-                    result[1] = (oneMinusFactor * materialColor[1] + textureIntensity * materialColor[1] / color[1]) * 0.5f;
-                }
-                if (color[2] != 0.0) {
-                    result[2] = (oneMinusFactor * materialColor[2] + textureIntensity * materialColor[2] / color[2]) * 0.5f;
-                }
-                break;
-            case MTEX_SCREEN:
-                oneMinusFactor = 1.0f - textureFactor;
-                result[0] = 1.0f - (oneMinusFactor + textureIntensity * (1.0f - materialColor[0])) * (1.0f - color[0]);
-                result[1] = 1.0f - (oneMinusFactor + textureIntensity * (1.0f - materialColor[1])) * (1.0f - color[1]);
-                result[2] = 1.0f - (oneMinusFactor + textureIntensity * (1.0f - materialColor[2])) * (1.0f - color[2]);
-                break;
-            case MTEX_OVERLAY:
-                oneMinusFactor = 1.0f - textureFactor;
-                if (materialColor[0] < 0.5f) {
-                    result[0] = color[0] * (oneMinusFactor + 2.0f * textureIntensity * materialColor[0]);
-                } else {
-                    result[0] = 1.0f - (oneMinusFactor + 2.0f * textureIntensity * (1.0f - materialColor[0])) * (1.0f - color[0]);
-                }
-                if (materialColor[1] < 0.5f) {
-                    result[1] = color[1] * (oneMinusFactor + 2.0f * textureIntensity * materialColor[1]);
-                } else {
-                    result[1] = 1.0f - (oneMinusFactor + 2.0f * textureIntensity * (1.0f - materialColor[1])) * (1.0f - color[1]);
-                }
-                if (materialColor[2] < 0.5f) {
-                    result[2] = color[2] * (oneMinusFactor + 2.0f * textureIntensity * materialColor[2]);
-                } else {
-                    result[2] = 1.0f - (oneMinusFactor + 2.0f * textureIntensity * (1.0f - materialColor[2])) * (1.0f - color[2]);
-                }
-                break;
-            case MTEX_SUB:
-                result[0] = materialColor[0] - textureIntensity * color[0];
-                result[1] = materialColor[1] - textureIntensity * color[1];
-                result[2] = materialColor[2] - textureIntensity * color[2];
-                result[0] = FastMath.clamp(result[0], 0.0f, 1.0f);
-                result[1] = FastMath.clamp(result[1], 0.0f, 1.0f);
-                result[2] = FastMath.clamp(result[2], 0.0f, 1.0f);
-                break;
-            case MTEX_ADD:
-                result[0] = (textureIntensity * color[0] + materialColor[0]) * 0.5f;
-                result[1] = (textureIntensity * color[1] + materialColor[1]) * 0.5f;
-                result[2] = (textureIntensity * color[2] + materialColor[2]) * 0.5f;
-                break;
-            case MTEX_DIFF:
-                oneMinusFactor = 1.0f - textureIntensity;
-                result[0] = oneMinusFactor * materialColor[0] + textureIntensity * Math.abs(materialColor[0] - color[0]);
-                result[1] = oneMinusFactor * materialColor[1] + textureIntensity * Math.abs(materialColor[1] - color[1]);
-                result[2] = oneMinusFactor * materialColor[2] + textureIntensity * Math.abs(materialColor[2] - color[2]);
-                break;
-            case MTEX_DARK:
-                col = textureIntensity * color[0];
-                result[0] = col < materialColor[0] ? col : materialColor[0];
-                col = textureIntensity * color[1];
-                result[1] = col < materialColor[1] ? col : materialColor[1];
-                col = textureIntensity * color[2];
-                result[2] = col < materialColor[2] ? col : materialColor[2];
-                break;
-            case MTEX_LIGHT:
-                col = textureIntensity * color[0];
-                result[0] = col > materialColor[0] ? col : materialColor[0];
-                col = textureIntensity * color[1];
-                result[1] = col > materialColor[1] ? col : materialColor[1];
-                col = textureIntensity * color[2];
-                result[2] = col > materialColor[2] ? col : materialColor[2];
-                break;
-            case MTEX_BLEND_HUE:
-            case MTEX_BLEND_SAT:
-            case MTEX_BLEND_VAL:
-            case MTEX_BLEND_COLOR:
-                System.arraycopy(materialColor, 0, result, 0, 3);
-                this.blendHSV(blendtype, result, textureIntensity, color, blenderContext);
-                break;
-            default:
-                throw new IllegalStateException("Unknown blend type: " + blendtype);
-        }
-    }
-}

+ 0 - 814
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/NoiseGenerator.java

@@ -1,814 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.textures.generating;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.textures.generating.TextureGeneratorMusgrave.MusgraveData;
-
-/**
- * This generator is responsible for creating various noises used to create
- * generated textures loaded from blender.
- * It is only used by TextureHelper.
- * Take note that these functions are not thread safe.
- * @author Marcin Roguski (Kaelthas)
- */
-/* package */class NoiseGenerator {
-    private static final Logger LOGGER       = Logger.getLogger(NoiseGenerator.class.getName());
-
-    // tex->stype
-    protected static final int  TEX_PLASTIC  = 0;
-    protected static final int  TEX_WALLIN   = 1;
-    protected static final int  TEX_WALLOUT  = 2;
-
-    // musgrave stype
-    protected static final int  TEX_MFRACTAL = 0;
-    protected static final int  TEX_RIDGEDMF = 1;
-    protected static final int  TEX_HYBRIDMF = 2;
-    protected static final int  TEX_FBM      = 3;
-    protected static final int  TEX_HTERRAIN = 4;
-
-    // keyblock->type
-    protected static final int  KEY_LINEAR   = 0;
-    protected static final int  KEY_CARDINAL = 1;
-    protected static final int  KEY_BSPLINE  = 2;
-
-    // CONSTANTS (read from file)
-    protected static float[]    hashpntf;
-    protected static short[]    hash;
-    protected static float[]    hashvectf;
-    protected static short[]    p;
-    protected static float[][]  g;
-
-    /**
-     * Constructor. Loads the constants needed for computations. They are exactly like the ones the blender uses. Each
-     * deriving class should override this method and load its own constraints.
-     */
-    public NoiseGenerator() {
-        LOGGER.fine("Loading noise constants.");
-        InputStream is = NoiseGenerator.class.getResourceAsStream("noiseconstants.dat");
-        try {
-            ObjectInputStream ois = new ObjectInputStream(is);
-            hashpntf = (float[]) ois.readObject();
-            hash = (short[]) ois.readObject();
-            hashvectf = (float[]) ois.readObject();
-            p = (short[]) ois.readObject();
-            g = (float[][]) ois.readObject();
-        } catch (IOException e) {
-            LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
-        } catch (ClassNotFoundException e) {
-            assert false : "Constants' classes should be arrays of primitive types, so they are ALWAYS known!";
-        } finally {
-            if (is != null) {
-                try {
-                    is.close();
-                } catch (IOException e) {
-                    LOGGER.log(Level.WARNING, e.getLocalizedMessage());
-                }
-            }
-        }
-    }
-
-    protected static Map<Integer, NoiseFunction>    noiseFunctions    = new HashMap<Integer, NoiseFunction>();
-    static {
-        noiseFunctions.put(Integer.valueOf(0), new NoiseFunction() {
-            // originalBlenderNoise
-            @Override
-            public float execute(float x, float y, float z) {
-                return NoiseFunctions.originalBlenderNoise(x, y, z);
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                return 2.0f * NoiseFunctions.originalBlenderNoise(x, y, z) - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(1), new NoiseFunction() {
-            // orgPerlinNoise
-            @Override
-            public float execute(float x, float y, float z) {
-                return 0.5f + 0.5f * NoiseFunctions.noise3Perlin(x, y, z);
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                return NoiseFunctions.noise3Perlin(x, y, z);
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(2), new NoiseFunction() {
-            // newPerlin
-            @Override
-            public float execute(float x, float y, float z) {
-                return 0.5f + 0.5f * NoiseFunctions.newPerlin(x, y, z);
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                return this.execute(x, y, z);
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(3), new NoiseFunction() {
-            private final float[] da = new float[4];
-            private final float[] pa = new float[12];
-
-            // voronoi_F1
-            @Override
-            public float execute(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return da[0];
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return 2.0f * da[0] - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(4), new NoiseFunction() {
-            private final float[] da = new float[4];
-            private final float[] pa = new float[12];
-
-            // voronoi_F2
-            @Override
-            public float execute(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return da[1];
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return 2.0f * da[1] - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(5), new NoiseFunction() {
-            private final float[] da = new float[4];
-            private final float[] pa = new float[12];
-
-            // voronoi_F3
-            @Override
-            public float execute(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return da[2];
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return 2.0f * da[2] - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(6), new NoiseFunction() {
-            private final float[] da = new float[4];
-            private final float[] pa = new float[12];
-
-            // voronoi_F4
-            @Override
-            public float execute(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return da[3];
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return 2.0f * da[3] - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(7), new NoiseFunction() {
-            private final float[] da = new float[4];
-            private final float[] pa = new float[12];
-
-            // voronoi_F1F2
-            @Override
-            public float execute(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return da[1] - da[0];
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                NoiseFunctions.voronoi(x, y, z, da, pa, 1, NATURAL_DISTANCE_FUNCTION);
-                return 2.0f * (da[1] - da[0]) - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(8), new NoiseFunction() {
-            private final NoiseFunction voronoiF1F2NoiseFunction = noiseFunctions.get(Integer.valueOf(7));
-
-            // voronoi_Cr
-            @Override
-            public float execute(float x, float y, float z) {
-                float t = 10 * voronoiF1F2NoiseFunction.execute(x, y, z);
-                return t > 1.0f ? 1.0f : t;
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                float t = 10.0f * voronoiF1F2NoiseFunction.execute(x, y, z);
-                return t > 1.0f ? 1.0f : 2.0f * t - 1.0f;
-            }
-        });
-        noiseFunctions.put(Integer.valueOf(14), new NoiseFunction() {
-            // cellNoise
-            @Override
-            public float execute(float x, float y, float z) {
-                int xi = (int) FastMath.floor(x);
-                int yi = (int) FastMath.floor(y);
-                int zi = (int) FastMath.floor(z);
-                long n = xi + yi * 1301 + zi * 314159;
-                n ^= n << 13;
-                return (n * (n * n * 15731 + 789221) + 1376312589) / 4294967296.0f;
-            }
-
-            @Override
-            public float executeSigned(float x, float y, float z) {
-                return 2.0f * this.execute(x, y, z) - 1.0f;
-            }
-        });
-    }
-    /** Distance metrics for voronoi. e parameter only used in Minkovsky. */
-    protected static Map<Integer, DistanceFunction> distanceFunctions = new HashMap<Integer, NoiseGenerator.DistanceFunction>();
-    private static DistanceFunction                 NATURAL_DISTANCE_FUNCTION;                                                   // often used in noise functions, se I store it here to avoid fetching it every time
-    static {
-        distanceFunctions.put(Integer.valueOf(0), new DistanceFunction() {
-            // real distance
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                return (float) Math.sqrt(x * x + y * y + z * z);
-            }
-        });
-        distanceFunctions.put(Integer.valueOf(1), new DistanceFunction() {
-            // distance squared
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                return x * x + y * y + z * z;
-            }
-        });
-        distanceFunctions.put(Integer.valueOf(2), new DistanceFunction() {
-            // manhattan/taxicab/cityblock distance
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                return FastMath.abs(x) + FastMath.abs(y) + FastMath.abs(z);
-            }
-        });
-        distanceFunctions.put(Integer.valueOf(3), new DistanceFunction() {
-            // Chebychev
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                x = FastMath.abs(x);
-                y = FastMath.abs(y);
-                z = FastMath.abs(z);
-                float t = x > y ? x : y;
-                return z > t ? z : t;
-            }
-        });
-        distanceFunctions.put(Integer.valueOf(4), new DistanceFunction() {
-            // Minkovsky, preset exponent 0.5 (MinkovskyH)
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                float d = (float) (Math.sqrt(FastMath.abs(x)) + Math.sqrt(FastMath.abs(y)) + Math.sqrt(FastMath.abs(z)));
-                return d * d;
-            }
-        });
-        distanceFunctions.put(Integer.valueOf(5), new DistanceFunction() {
-            // Minkovsky, preset exponent 0.25 (Minkovsky4)
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                x *= x;
-                y *= y;
-                z *= z;
-                return (float) Math.sqrt(Math.sqrt(x * x + y * y + z * z));
-            }
-        });
-        distanceFunctions.put(Integer.valueOf(6), new DistanceFunction() {
-            // Minkovsky, general case
-            @Override
-            public float execute(float x, float y, float z, float e) {
-                return (float) Math.pow(Math.pow(FastMath.abs(x), e) + Math.pow(FastMath.abs(y), e) + Math.pow(FastMath.abs(z), e), 1.0f / e);
-            }
-        });
-        NATURAL_DISTANCE_FUNCTION = distanceFunctions.get(Integer.valueOf(0));
-    }
-
-    protected static Map<Integer, MusgraveFunction> musgraveFunctions = new HashMap<Integer, NoiseGenerator.MusgraveFunction>();
-    static {
-        musgraveFunctions.put(Integer.valueOf(TEX_MFRACTAL), new MusgraveFunction() {
-
-            @Override
-            public float execute(MusgraveData musgraveData, float x, float y, float z) {
-                float rmd, value = 1.0f, pwr = 1.0f, pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
-
-                for (int i = 0; i < (int) musgraveData.octaves; ++i) {
-                    value *= pwr * musgraveData.noiseFunction.executeSigned(x, y, z) + 1.0f;
-                    pwr *= pwHL;
-                    x *= musgraveData.lacunarity;
-                    y *= musgraveData.lacunarity;
-                    z *= musgraveData.lacunarity;
-                }
-                rmd = musgraveData.octaves - FastMath.floor(musgraveData.octaves);
-                if (rmd != 0.0f) {
-                    value *= rmd * musgraveData.noiseFunction.executeSigned(x, y, z) * pwr + 1.0f;
-                }
-                return value;
-            }
-        });
-        musgraveFunctions.put(Integer.valueOf(TEX_RIDGEDMF), new MusgraveFunction() {
-
-            @Override
-            public float execute(MusgraveData musgraveData, float x, float y, float z) {
-                float result, signal, weight;
-                float pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
-                float pwr = pwHL;
-
-                signal = musgraveData.offset - FastMath.abs(musgraveData.noiseFunction.executeSigned(x, y, z));
-                signal *= signal;
-                result = signal;
-                weight = 1.0f;
-
-                for (int i = 1; i < (int) musgraveData.octaves; ++i) {
-                    x *= musgraveData.lacunarity;
-                    y *= musgraveData.lacunarity;
-                    z *= musgraveData.lacunarity;
-                    weight = signal * musgraveData.gain;
-                    if (weight > 1.0f) {
-                        weight = 1.0f;
-                    } else if (weight < 0.0) {
-                        weight = 0.0f;
-                    }
-                    signal = musgraveData.offset - FastMath.abs(musgraveData.noiseFunction.executeSigned(x, y, z));
-                    signal *= signal;
-                    signal *= weight;
-                    result += signal * pwr;
-                    pwr *= pwHL;
-                }
-                return result;
-            }
-        });
-        musgraveFunctions.put(Integer.valueOf(TEX_HYBRIDMF), new MusgraveFunction() {
-
-            @Override
-            public float execute(MusgraveData musgraveData, float x, float y, float z) {
-                float result, signal, weight, rmd;
-                float pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
-                float pwr = pwHL;
-
-                result = musgraveData.noiseFunction.executeSigned(x, y, z) + musgraveData.offset;
-                weight = musgraveData.gain * result;
-                x *= musgraveData.lacunarity;
-                y *= musgraveData.lacunarity;
-                z *= musgraveData.lacunarity;
-
-                for (int i = 1; weight > 0.001f && i < (int) musgraveData.octaves; ++i) {
-                    if (weight > 1.0f) {
-                        weight = 1.0f;
-                    }
-                    signal = (musgraveData.noiseFunction.executeSigned(x, y, z) + musgraveData.offset) * pwr;
-                    pwr *= pwHL;
-                    result += weight * signal;
-                    weight *= musgraveData.gain * signal;
-                    x *= musgraveData.lacunarity;
-                    y *= musgraveData.lacunarity;
-                    z *= musgraveData.lacunarity;
-                }
-
-                rmd = musgraveData.octaves - FastMath.floor(musgraveData.octaves);
-                if (rmd != 0.0f) {
-                    result += rmd * (musgraveData.noiseFunction.executeSigned(x, y, z) + musgraveData.offset) * pwr;
-                }
-                return result;
-            }
-        });
-        musgraveFunctions.put(Integer.valueOf(TEX_FBM), new MusgraveFunction() {
-
-            @Override
-            public float execute(MusgraveData musgraveData, float x, float y, float z) {
-                float rmd, value = 0.0f, pwr = 1.0f, pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
-
-                for (int i = 0; i < (int) musgraveData.octaves; ++i) {
-                    value += musgraveData.noiseFunction.executeSigned(x, y, z) * pwr;
-                    pwr *= pwHL;
-                    x *= musgraveData.lacunarity;
-                    y *= musgraveData.lacunarity;
-                    z *= musgraveData.lacunarity;
-                }
-
-                rmd = musgraveData.octaves - FastMath.floor(musgraveData.octaves);
-                if (rmd != 0.f) {
-                    value += rmd * musgraveData.noiseFunction.executeSigned(x, y, z) * pwr;
-                }
-                return value;
-            }
-        });
-        musgraveFunctions.put(Integer.valueOf(TEX_HTERRAIN), new MusgraveFunction() {
-
-            @Override
-            public float execute(MusgraveData musgraveData, float x, float y, float z) {
-                float value, increment, rmd;
-                float pwHL = (float) Math.pow(musgraveData.lacunarity, -musgraveData.h);
-                float pwr = pwHL;
-
-                value = musgraveData.offset + musgraveData.noiseFunction.executeSigned(x, y, z);
-                x *= musgraveData.lacunarity;
-                y *= musgraveData.lacunarity;
-                z *= musgraveData.lacunarity;
-
-                for (int i = 1; i < (int) musgraveData.octaves; ++i) {
-                    increment = (musgraveData.noiseFunction.executeSigned(x, y, z) + musgraveData.offset) * pwr * value;
-                    value += increment;
-                    pwr *= pwHL;
-                    x *= musgraveData.lacunarity;
-                    y *= musgraveData.lacunarity;
-                    z *= musgraveData.lacunarity;
-                }
-
-                rmd = musgraveData.octaves - FastMath.floor(musgraveData.octaves);
-                if (rmd != 0.0) {
-                    increment = (musgraveData.noiseFunction.executeSigned(x, y, z) + musgraveData.offset) * pwr * value;
-                    value += rmd * increment;
-                }
-                return value;
-            }
-        });
-    }
-
-    public static class NoiseFunctions {
-        public static float noise(float x, float y, float z, float noiseSize, int noiseDepth, NoiseFunction noiseFunction, boolean isHard) {
-            if (noiseSize != 0.0) {
-                noiseSize = 1.0f / noiseSize;
-                x *= noiseSize;
-                y *= noiseSize;
-                z *= noiseSize;
-            }
-            float result = noiseFunction.execute(x, y, z);
-            return isHard ? FastMath.abs(2.0f * result - 1.0f) : result;
-        }
-
-        public static float turbulence(float x, float y, float z, float noiseSize, int noiseDepth, NoiseFunction noiseFunction, boolean isHard) {
-            if (noiseSize != 0.0) {
-                noiseSize = 1.0f / noiseSize;
-                x *= noiseSize;
-                y *= noiseSize;
-                z *= noiseSize;
-            }
-
-            float sum = 0, t, amp = 1, fscale = 1;
-            for (int i = 0; i <= noiseDepth; ++i, amp *= 0.5f, fscale *= 2f) {
-                t = noiseFunction.execute(fscale * x, fscale * y, fscale * z);
-                if (isHard) {
-                    t = FastMath.abs(2.0f * t - 1.0f);
-                }
-                sum += t * amp;
-            }
-
-            sum *= (1 << noiseDepth) / (float) ((1 << noiseDepth + 1) - 1);
-            return sum;
-        }
-
-        private static final float[] voronoiP = new float[3];
-
-        public static void voronoi(float x, float y, float z, float[] da, float[] pa, float distanceExponent, DistanceFunction distanceFunction) {
-            float xd, yd, zd, d;
-
-            int xi = (int) FastMath.floor(x);
-            int yi = (int) FastMath.floor(y);
-            int zi = (int) FastMath.floor(z);
-            da[0] = da[1] = da[2] = da[3] = Float.MAX_VALUE;// 1e10f;
-            for (int i = xi - 1; i <= xi + 1; ++i) {
-                for (int j = yi - 1; j <= yi + 1; ++j) {
-                    for (int k = zi - 1; k <= zi + 1; ++k) {
-                        NoiseMath.hash(i, j, k, voronoiP);
-                        xd = x - (voronoiP[0] + i);
-                        yd = y - (voronoiP[1] + j);
-                        zd = z - (voronoiP[2] + k);
-                        d = distanceFunction.execute(xd, yd, zd, distanceExponent);
-                        if (d < da[0]) {
-                            da[3] = da[2];
-                            da[2] = da[1];
-                            da[1] = da[0];
-                            da[0] = d;
-                            pa[9] = pa[6];
-                            pa[10] = pa[7];
-                            pa[11] = pa[8];
-                            pa[6] = pa[3];
-                            pa[7] = pa[4];
-                            pa[8] = pa[5];
-                            pa[3] = pa[0];
-                            pa[4] = pa[1];
-                            pa[5] = pa[2];
-                            pa[0] = voronoiP[0] + i;
-                            pa[1] = voronoiP[1] + j;
-                            pa[2] = voronoiP[2] + k;
-                        } else if (d < da[1]) {
-                            da[3] = da[2];
-                            da[2] = da[1];
-                            da[1] = d;
-                            pa[9] = pa[6];
-                            pa[10] = pa[7];
-                            pa[11] = pa[8];
-                            pa[6] = pa[3];
-                            pa[7] = pa[4];
-                            pa[8] = pa[5];
-                            pa[3] = voronoiP[0] + i;
-                            pa[4] = voronoiP[1] + j;
-                            pa[5] = voronoiP[2] + k;
-                        } else if (d < da[2]) {
-                            da[3] = da[2];
-                            da[2] = d;
-                            pa[9] = pa[6];
-                            pa[10] = pa[7];
-                            pa[11] = pa[8];
-                            pa[6] = voronoiP[0] + i;
-                            pa[7] = voronoiP[1] + j;
-                            pa[8] = voronoiP[2] + k;
-                        } else if (d < da[3]) {
-                            da[3] = d;
-                            pa[9] = voronoiP[0] + i;
-                            pa[10] = voronoiP[1] + j;
-                            pa[11] = voronoiP[2] + k;
-                        }
-                    }
-                }
-            }
-        }
-
-        // instead of adding another permutation array, just use hash table defined above
-        public static float newPerlin(float x, float y, float z) {
-            int A, AA, AB, B, BA, BB;
-            float floorX = FastMath.floor(x), floorY = FastMath.floor(y), floorZ = FastMath.floor(z);
-            int intX = (int) floorX & 0xFF, intY = (int) floorY & 0xFF, intZ = (int) floorZ & 0xFF;
-            x -= floorX;
-            y -= floorY;
-            z -= floorZ;
-            // computing fading curves
-            floorX = NoiseMath.npfade(x);
-            floorY = NoiseMath.npfade(y);
-            floorZ = NoiseMath.npfade(z);
-            A = hash[intX] + intY;
-            AA = hash[A] + intZ;
-            AB = hash[A + 1] + intZ;
-            B = hash[intX + 1] + intY;
-            BA = hash[B] + intZ;
-            BB = hash[B + 1] + intZ;
-            return NoiseMath.lerp(floorZ, NoiseMath.lerp(floorY, NoiseMath.lerp(floorX, NoiseMath.grad(hash[AA], x, y, z), NoiseMath.grad(hash[BA], x - 1, y, z)), NoiseMath.lerp(floorX, NoiseMath.grad(hash[AB], x, y - 1, z), NoiseMath.grad(hash[BB], x - 1, y - 1, z))),
-                    NoiseMath.lerp(floorY, NoiseMath.lerp(floorX, NoiseMath.grad(hash[AA + 1], x, y, z - 1), NoiseMath.grad(hash[BA + 1], x - 1, y, z - 1)), NoiseMath.lerp(floorX, NoiseMath.grad(hash[AB + 1], x, y - 1, z - 1), NoiseMath.grad(hash[BB + 1], x - 1, y - 1, z - 1))));
-        }
-
-        public static float noise3Perlin(float x, float y, float z) {
-            float t = x + 10000.0f;
-            int bx0 = (int) t & 0xFF;
-            int bx1 = bx0 + 1 & 0xFF;
-            float rx0 = t - (int) t;
-            float rx1 = rx0 - 1.0f;
-
-            t = y + 10000.0f;
-            int by0 = (int) t & 0xFF;
-            int by1 = by0 + 1 & 0xFF;
-            float ry0 = t - (int) t;
-            float ry1 = ry0 - 1.0f;
-
-            t = z + 10000.0f;
-            int bz0 = (int) t & 0xFF;
-            int bz1 = bz0 + 1 & 0xFF;
-            float rz0 = t - (int) t;
-            float rz1 = rz0 - 1.0f;
-
-            int i = p[bx0];
-            int j = p[bx1];
-
-            int b00 = p[i + by0];
-            int b10 = p[j + by0];
-            int b01 = p[i + by1];
-            int b11 = p[j + by1];
-
-            float sx = NoiseMath.surve(rx0);
-            float sy = NoiseMath.surve(ry0);
-            float sz = NoiseMath.surve(rz0);
-
-            float[] q = g[b00 + bz0];
-            float u = NoiseMath.at(rx0, ry0, rz0, q);
-            q = g[b10 + bz0];
-            float v = NoiseMath.at(rx1, ry0, rz0, q);
-            float a = NoiseMath.lerp(sx, u, v);
-
-            q = g[b01 + bz0];
-            u = NoiseMath.at(rx0, ry1, rz0, q);
-            q = g[b11 + bz0];
-            v = NoiseMath.at(rx1, ry1, rz0, q);
-            float b = NoiseMath.lerp(sx, u, v);
-
-            float c = NoiseMath.lerp(sy, a, b);
-
-            q = g[b00 + bz1];
-            u = NoiseMath.at(rx0, ry0, rz1, q);
-            q = g[b10 + bz1];
-            v = NoiseMath.at(rx1, ry0, rz1, q);
-            a = NoiseMath.lerp(sx, u, v);
-
-            q = g[b01 + bz1];
-            u = NoiseMath.at(rx0, ry1, rz1, q);
-            q = g[b11 + bz1];
-            v = NoiseMath.at(rx1, ry1, rz1, q);
-            b = NoiseMath.lerp(sx, u, v);
-
-            float d = NoiseMath.lerp(sy, a, b);
-            return 1.5f * NoiseMath.lerp(sz, c, d);
-        }
-
-        private static final float[] cn      = new float[8];
-        private static final int[]   b1      = new int[8];
-        private static final int[]   b2      = new int[2];
-        private static final float[] xFactor = new float[8];
-        private static final float[] yFactor = new float[8];
-        private static final float[] zFactor = new float[8];
-
-        public static float originalBlenderNoise(float x, float y, float z) {
-            float n = 0.5f;
-
-            int ix = (int) FastMath.floor(x);
-            int iy = (int) FastMath.floor(y);
-            int iz = (int) FastMath.floor(z);
-
-            float ox = x - ix;
-            float oy = y - iy;
-            float oz = z - iz;
-
-            float jx = ox - 1;
-            float jy = oy - 1;
-            float jz = oz - 1;
-
-            float cn1 = ox * ox;
-            float cn2 = oy * oy;
-            float cn3 = oz * oz;
-            float cn4 = jx * jx;
-            float cn5 = jy * jy;
-            float cn6 = jz * jz;
-
-            cn1 = 1.0f - 3.0f * cn1 + 2.0f * cn1 * ox;
-            cn2 = 1.0f - 3.0f * cn2 + 2.0f * cn2 * oy;
-            cn3 = 1.0f - 3.0f * cn3 + 2.0f * cn3 * oz;
-            cn4 = 1.0f - 3.0f * cn4 - 2.0f * cn4 * jx;
-            cn5 = 1.0f - 3.0f * cn5 - 2.0f * cn5 * jy;
-            cn6 = 1.0f - 3.0f * cn6 - 2.0f * cn6 * jz;
-
-            cn[0] = cn1 * cn2 * cn3;
-            cn[1] = cn1 * cn2 * cn6;
-            cn[2] = cn1 * cn5 * cn3;
-            cn[3] = cn1 * cn5 * cn6;
-            cn[4] = cn4 * cn2 * cn3;
-            cn[5] = cn4 * cn2 * cn6;
-            cn[6] = cn4 * cn5 * cn3;
-            cn[7] = cn4 * cn5 * cn6;
-
-            b1[0] = b1[1] = hash[hash[ix & 0xFF] + (iy & 0xFF)];
-            b1[2] = b1[3] = hash[hash[ix & 0xFF] + (iy + 1 & 0xFF)];
-            b1[4] = b1[5] = hash[hash[ix + 1 & 0xFF] + (iy & 0xFF)];
-            b1[6] = b1[7] = hash[hash[ix + 1 & 0xFF] + (iy + 1 & 0xFF)];
-
-            b2[0] = iz & 0xFF;
-            b2[1] = iz + 1 & 0xFF;
-
-            xFactor[0] = xFactor[1] = xFactor[2] = xFactor[3] = ox;
-            xFactor[4] = xFactor[5] = xFactor[6] = xFactor[7] = jx;
-            yFactor[0] = yFactor[1] = yFactor[4] = yFactor[5] = oy;
-            yFactor[2] = yFactor[3] = yFactor[6] = yFactor[7] = jy;
-            zFactor[0] = zFactor[2] = zFactor[4] = zFactor[6] = oz;
-            zFactor[1] = zFactor[3] = zFactor[5] = zFactor[7] = jz;
-
-            for (int i = 0; i < cn.length; ++i) {
-                int hIndex = 3 * hash[b1[i] + b2[i % 2]];
-                n += cn[i] * (hashvectf[hIndex] * xFactor[i] + hashvectf[hIndex + 1] * yFactor[i] + hashvectf[hIndex + 2] * zFactor[i]);
-            }
-
-            if (n < 0.0f) {
-                n = 0.0f;
-            } else if (n > 1.0f) {
-                n = 1.0f;
-            }
-            return n;
-        }
-    }
-
-    /**
-     * This class is abstract to the noise functions computations. It has two methods. One calculates the Signed (with
-     * 'S' at the end) and the other Unsigned value.
-     * @author Marcin Roguski (Kaelthas)
-     */
-    interface NoiseFunction {
-
-        /**
-         * This method calculates the unsigned value of the noise.
-         * @param x
-         *            the x texture coordinate
-         * @param y
-         *            the y texture coordinate
-         * @param z
-         *            the z texture coordinate
-         * @return value of the noise
-         */
-        float execute(float x, float y, float z);
-
-        /**
-         * This method calculates the signed value of the noise.
-         * @param x
-         *            the x texture coordinate
-         * @param y
-         *            the y texture coordinate
-         * @param z
-         *            the z texture coordinate
-         * @return value of the noise
-         */
-        float executeSigned(float x, float y, float z);
-    }
-
-    public static class NoiseMath {
-        public static float lerp(float t, float a, float b) {
-            return a + t * (b - a);
-        }
-
-        public static float npfade(float t) {
-            return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
-        }
-
-        public static float grad(int hash, float x, float y, float z) {
-            int h = hash & 0x0F;
-            float u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
-            return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
-        }
-
-        public static float surve(float t) {
-            return t * t * (3.0f - 2.0f * t);
-        }
-
-        public static float at(float x, float y, float z, float[] q) {
-            return x * q[0] + y * q[1] + z * q[2];
-        }
-
-        public static void hash(int x, int y, int z, float[] result) {
-            result[0] = hashpntf[3 * hash[hash[hash[z & 0xFF] + y & 0xFF] + x & 0xFF]];
-            result[1] = hashpntf[3 * hash[hash[hash[z & 0xFF] + y & 0xFF] + x & 0xFF] + 1];
-            result[2] = hashpntf[3 * hash[hash[hash[z & 0xFF] + y & 0xFF] + x & 0xFF] + 2];
-        }
-    }
-
-    /**
-     * This interface is used for distance calculation classes. Distance metrics for voronoi. e parameter only used in
-     * Minkovsky.
-     */
-    interface DistanceFunction {
-
-        /**
-         * This method calculates the distance for voronoi algorithms.
-         * @param x
-         *            the x coordinate
-         * @param y
-         *            the y coordinate
-         * @param z
-         *            the z coordinate
-         * @param e
-         *            this parameter used in Monkovsky (no idea what it really is ;)
-         * @return
-         */
-        float execute(float x, float y, float z, float e);
-    }
-
-    interface MusgraveFunction {
-
-        float execute(MusgraveData musgraveData, float x, float y, float z);
-    }
-}

+ 0 - 128
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/TextureGenerator.java

@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures.generating;
-
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.textures.ColorBand;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.texture.Image.Format;
-
-/**
- * This class is a base class for texture generators.
- * @author Marcin Roguski (Kaelthas)
- */
-public abstract class TextureGenerator {
-    protected NoiseGenerator            noiseGenerator;
-    protected int                       flag;
-    protected float[][]                 colorBand;
-    protected BrightnessAndContrastData bacd;
-    protected Format                    imageFormat;
-
-    public TextureGenerator(NoiseGenerator noiseGenerator, Format imageFormat) {
-        this.noiseGenerator = noiseGenerator;
-        this.imageFormat = imageFormat;
-    }
-
-    public Format getImageFormat() {
-        return imageFormat;
-    }
-
-    public void readData(Structure tex, BlenderContext blenderContext) {
-        flag = ((Number) tex.getFieldValue("flag")).intValue();
-        colorBand = new ColorBand(tex, blenderContext).computeValues();
-        bacd = new BrightnessAndContrastData(tex);
-        if (colorBand != null) {
-            imageFormat = Format.RGBA8;
-        }
-    }
-
-    public abstract void getPixel(TexturePixel pixel, float x, float y, float z);
-
-    /**
-     * This method applies brightness and contrast for RGB textures.
-     */
-    protected void applyBrightnessAndContrast(BrightnessAndContrastData bacd, TexturePixel texres) {
-        texres.red = (texres.red - 0.5f) * bacd.contrast + bacd.brightness;
-        if (texres.red < 0.0f) {
-            texres.red = 0.0f;
-        }
-        texres.green = (texres.green - 0.5f) * bacd.contrast + bacd.brightness;
-        if (texres.green < 0.0f) {
-            texres.green = 0.0f;
-        }
-        texres.blue = (texres.blue - 0.5f) * bacd.contrast + bacd.brightness;
-        if (texres.blue < 0.0f) {
-            texres.blue = 0.0f;
-        }
-    }
-
-    /**
-     * This method applies brightness and contrast for Luminance textures.
-     * @param texres
-     * @param contrast
-     * @param brightness
-     */
-    protected void applyBrightnessAndContrast(TexturePixel texres, float contrast, float brightness) {
-        texres.intensity = (texres.intensity - 0.5f) * contrast + brightness;
-        if (texres.intensity < 0.0f) {
-            texres.intensity = 0.0f;
-        } else if (texres.intensity > 1.0f) {
-            texres.intensity = 1.0f;
-        }
-    }
-
-    /**
-     * This class contains brightness and contrast data.
-     * @author Marcin Roguski (Kaelthas)
-     */
-    protected static class BrightnessAndContrastData {
-        public final float contrast;
-        public final float brightness;
-        public final float rFactor;
-        public final float gFactor;
-        public final float bFactor;
-
-        /**
-         * Constructor reads the required data from the given structure.
-         * @param tex
-         *            texture structure
-         */
-        public BrightnessAndContrastData(Structure tex) {
-            contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
-            brightness = ((Number) tex.getFieldValue("bright")).floatValue() - 0.5f;
-            rFactor = ((Number) tex.getFieldValue("rfac")).floatValue();
-            gFactor = ((Number) tex.getFieldValue("gfac")).floatValue();
-            bFactor = ((Number) tex.getFieldValue("bfac")).floatValue();
-        }
-    }
-}

+ 0 - 138
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/TextureGeneratorBlend.java

@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2009-2020 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.textures.generating;
-
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.texture.Image.Format;
-
-/**
- * This class generates the 'blend' texture.
- * @author Marcin Roguski (Kaelthas)
- */
-public final class TextureGeneratorBlend extends TextureGenerator {
-
-    private static final IntensityFunction INTENSITY_FUNCTION[] = new IntensityFunction[7];
-    static {
-        INTENSITY_FUNCTION[0] = new IntensityFunction() {// Linear: stype = 0 (TEX_LIN)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                return (1.0f + x) * 0.5f;
-            }
-        };
-        INTENSITY_FUNCTION[1] = new IntensityFunction() {// Quad: stype = 1 (TEX_QUAD)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                float result = (1.0f + x) * 0.5f;
-                return result * result;
-            }
-        };
-        INTENSITY_FUNCTION[2] = new IntensityFunction() {// Ease: stype = 2 (TEX_EASE)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                float result = (1.0f + x) * 0.5f;
-                if (result <= 0.0f) {
-                    return 0.0f;
-                } else if (result >= 1.0f) {
-                    return 1.0f;
-                } else {
-                    return result * result * (3.0f - 2.0f * result);
-                }
-            }
-        };
-        INTENSITY_FUNCTION[3] = new IntensityFunction() {// Diagonal: stype = 3 (TEX_DIAG)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                return (2.0f + x + y) * 0.25f;
-            }
-        };
-        INTENSITY_FUNCTION[4] = new IntensityFunction() {// Sphere: stype = 4 (TEX_SPHERE)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                float result = 1.0f - (float) Math.sqrt(x * x + y * y + z * z);
-                return result < 0.0f ? 0.0f : result;
-            }
-        };
-        INTENSITY_FUNCTION[5] = new IntensityFunction() {// Halo: stype = 5 (TEX_HALO)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                float result = 1.0f - (float) Math.sqrt(x * x + y * y + z * z);
-                return result <= 0.0f ? 0.0f : result * result;
-            }
-        };
-        INTENSITY_FUNCTION[6] = new IntensityFunction() {// Radial: stype = 6 (TEX_RAD)
-            @Override
-            public float getIntensity(float x, float y, float z) {
-                return (float) Math.atan2(y, x) * FastMath.INV_TWO_PI + 0.5f;
-            }
-        };
-    }
-
-    /**
-     * Constructor stores the given noise generator.
-     * @param noiseGenerator
-     *            the noise generator
-     */
-    public TextureGeneratorBlend(NoiseGenerator noiseGenerator) {
-        super(noiseGenerator, Format.Luminance8);
-    }
-
-    protected int stype;
-
-    @Override
-    public void readData(Structure tex, BlenderContext blenderContext) {
-        super.readData(tex, blenderContext);
-        stype = ((Number) tex.getFieldValue("stype")).intValue();
-    }
-
-    @Override
-    public void getPixel(TexturePixel pixel, float x, float y, float z) {
-        pixel.intensity = INTENSITY_FUNCTION[stype].getIntensity(x, y, z);
-
-        if (colorBand != null) {
-            int colorbandIndex = (int) (pixel.intensity * 1000.0f);
-            pixel.red = colorBand[colorbandIndex][0];
-            pixel.green = colorBand[colorbandIndex][1];
-            pixel.blue = colorBand[colorbandIndex][2];
-
-            this.applyBrightnessAndContrast(bacd, pixel);
-        } else {
-            this.applyBrightnessAndContrast(pixel, bacd.contrast, bacd.brightness);
-        }
-    }
-
-    private static interface IntensityFunction {
-        float getIntensity(float x, float y, float z);
-    }
-}

+ 0 - 121
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/textures/generating/TextureGeneratorClouds.java

@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.textures.generating;
-
-import com.jme3.math.FastMath;
-import com.jme3.scene.plugins.blender.BlenderContext;
-import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.textures.TexturePixel;
-import com.jme3.scene.plugins.blender.textures.generating.NoiseGenerator.NoiseFunction;
-import com.jme3.texture.Image.Format;
-
-/**
- * This class generates the 'clouds' texture.
- * @author Marcin Roguski (Kaelthas)
- */
-public class TextureGeneratorClouds extends TextureGenerator {
-    // noiseType
-    protected static final int TEX_NOISESOFT = 0;
-    protected static final int TEX_NOISEPERL = 1;
-
-    // sType
-    protected static final int TEX_DEFAULT   = 0;
-    protected static final int TEX_COLOR     = 1;
-
-    protected float            noisesize;
-    protected int              noiseDepth;
-    protected int              noiseBasis;
-    protected NoiseFunction    noiseFunction;
-    protected int              noiseType;
-    protected boolean          isHard;
-    protected int              sType;
-
-    /**
-     * Constructor stores the given noise generator.
-     * @param noiseGenerator
-     *            the noise generator
-     */
-    public TextureGeneratorClouds(NoiseGenerator noiseGenerator) {
-        super(noiseGenerator, Format.Luminance8);
-    }
-
-    @Override
-    public void readData(Structure tex, BlenderContext blenderContext) {
-        super.readData(tex, blenderContext);
-        noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue();
-        noiseDepth = ((Number) tex.getFieldValue("noisedepth")).intValue();
-        noiseBasis = ((Number) tex.getFieldValue("noisebasis")).intValue();
-        noiseType = ((Number) tex.getFieldValue("noisetype")).intValue();
-        isHard = noiseType != TEX_NOISESOFT;
-        sType = ((Number) tex.getFieldValue("stype")).intValue();
-        if (sType == TEX_COLOR) {
-            imageFormat = Format.RGBA8;
-        }
-
-        noiseFunction = NoiseGenerator.noiseFunctions.get(noiseBasis);
-        if (noiseFunction == null) {
-            noiseFunction = NoiseGenerator.noiseFunctions.get(0);
-            noiseBasis = 0;
-        }
-    }
-
-    @Override
-    public void getPixel(TexturePixel pixel, float x, float y, float z) {
-        if (noiseBasis == 0) {
-            ++x;
-            ++y;
-            ++z;
-        }
-        pixel.intensity = NoiseGenerator.NoiseFunctions.turbulence(x, y, z, noisesize, noiseDepth, noiseFunction, isHard);
-        if (colorBand != null) {
-            int colorbandIndex = (int) (pixel.intensity * 1000.0f);
-            pixel.red = colorBand[colorbandIndex][0];
-            pixel.green = colorBand[colorbandIndex][1];
-            pixel.blue = colorBand[colorbandIndex][2];
-            pixel.alpha = colorBand[colorbandIndex][3];
-
-            this.applyBrightnessAndContrast(bacd, pixel);
-        } else if (sType == TEX_COLOR) {
-            pixel.red = pixel.intensity;
-            pixel.green = NoiseGenerator.NoiseFunctions.turbulence(y, x, z, noisesize, noiseDepth, noiseFunction, isHard);
-            pixel.blue = NoiseGenerator.NoiseFunctions.turbulence(y, z, x, noisesize, noiseDepth, noiseFunction, isHard);
-
-            pixel.green = FastMath.clamp(pixel.green, 0.0f, 1.0f);
-            pixel.blue = FastMath.clamp(pixel.blue, 0.0f, 1.0f);
-            pixel.alpha = 1.0f;
-
-            this.applyBrightnessAndContrast(bacd, pixel);
-        } else {
-            this.applyBrightnessAndContrast(pixel, bacd.contrast, bacd.brightness);
-        }
-    }
-}

Some files were not shown because too many files changed in this diff