فهرست منبع

Bugfix: fixed an issue with proper bone orientation in 3D space (as in blender bones have different local coordinates system than other features); this fix caused more models to be loaded properly and made the code more simple

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10840 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 12 سال پیش
والد
کامیت
32b79324a9

+ 6 - 3
engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java

@@ -41,7 +41,6 @@ import java.util.logging.Logger;
 import com.jme3.animation.Bone;
 import com.jme3.animation.BoneTrack;
 import com.jme3.animation.Skeleton;
-import com.jme3.math.Matrix4f;
 import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
 import com.jme3.scene.plugins.blender.BlenderContext;
 import com.jme3.scene.plugins.blender.curves.BezierCurve;
@@ -76,21 +75,25 @@ public class ArmatureHelper extends AbstractBlenderHelper {
     /**
      * This method builds the object's bones structure.
      * 
+     * @param armatureObjectOMA
+     *            the OMa of the armature node
      * @param boneStructure
      *            the structure containing the bones' data
      * @param parent
      *            the parent bone
      * @param result
      *            the list where the newly created bone will be added
+     * @param spatialOMA
+     *            the OMA of the spatial that will own the skeleton
      * @param blenderContext
      *            the blender context
      * @throws BlenderFileException
      *             an exception is thrown when there is problem with the blender
      *             file
      */
-    public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Matrix4f objectToArmatureTransformation, BlenderContext blenderContext) throws BlenderFileException {
+    public 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, objectToArmatureTransformation, blenderContext);
+        bc.buildBone(result, spatialOMA, blenderContext);
     }
 
     /**

+ 66 - 34
engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java

@@ -8,7 +8,10 @@ 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.LoadedFeatureDataType;
+import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
 import com.jme3.scene.plugins.blender.file.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.Structure;
 import com.jme3.scene.plugins.blender.objects.ObjectHelper;
@@ -19,27 +22,36 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
  * @author Marcin Roguski (Kaelthas)
  */
 public class BoneContext {
-    private BlenderContext    blenderContext;
+    // the flags of the bone
+    private static final int      CONNECTED_TO_PARENT                 = 0x10;
+
+    /**
+     * 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.
+     */
+    private 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 BlenderContext        blenderContext;
     /** The OMA of the bone's armature object. */
-    private Long              armatureObjectOMA;
+    private Long                  armatureObjectOMA;
     /** The structure of the bone. */
-    private Structure         boneStructure;
+    private Structure             boneStructure;
     /** Bone's name. */
-    private String            boneName;
-    /** The bone's armature matrix. */
-    private Matrix4f          armatureMatrix;
+    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;
+    private BoneContext           parent;
     /** The children of this context. */
-    private List<BoneContext> children = new ArrayList<BoneContext>();
+    private List<BoneContext>     children                            = new ArrayList<BoneContext>();
     /** Created bone (available after calling 'buildBone' method). */
-    private Bone              bone;
-    /** The bone's rest matrix. */
-    private Matrix4f          restMatrix;
-    /** Bone's total inverse transformation. */
-    private Matrix4f          inverseTotalTransformation;
+    private Bone                  bone;
     /** The length of the bone. */
-    private float             length;
+    private float                 length;
 
     /**
      * Constructor. Creates the basic set of bone's data.
@@ -79,21 +91,26 @@ public class BoneContext {
         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);
-        armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis());
 
-        // compute the bone's rest matrix
-        restMatrix = armatureMatrix.clone();
-        inverseTotalTransformation = restMatrix.invert();
-        if (parent != null) {
-            restMatrix = parent.inverseTotalTransformation.mult(restMatrix);
-        }
+        // first get the bone matrix in its armature space
+        globalBoneMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", 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);
+
+        Spatial armature = (Spatial) blenderContext.getLoadedFeature(armatureObjectOMA, LoadedFeatureDataType.LOADED_FEATURE);
+        ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
+        Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform());
+
+        // and now compute the final bone matrix in world space
+        globalBoneMatrix = armatureWorldMatrix.mult(globalBoneMatrix);
 
         // create the children
         List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext);
         for (Structure child : childbase) {
-            this.children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext));
+            children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext));
         }
 
         blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this);
@@ -104,31 +121,36 @@ public class BoneContext {
      * 
      * @param bones
      *            a list of bones where the newly created bone will be added
-     * @param objectToArmatureMatrix
-     *            object to armature transformation matrix
+     * @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, Matrix4f objectToArmatureMatrix, BlenderContext blenderContext) {
+    public Bone buildBone(List<Bone> bones, Long skeletonOwnerOma, BlenderContext blenderContext) {
         Long boneOMA = boneStructure.getOldMemoryAddress();
         bone = new Bone(boneName);
         bones.add(bone);
         blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone);
+        ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
 
-        Vector3f poseLocation = restMatrix.toTranslationVector();
-        Quaternion rotation = restMatrix.toRotationQuat().normalizeLocal();
-        Vector3f scale = restMatrix.toScaleVector();
-        if (parent == null) {
-            Quaternion rotationQuaternion = objectToArmatureMatrix.toRotationQuat().normalizeLocal();
-            scale.multLocal(objectToArmatureMatrix.toScaleVector());
-            rotationQuaternion.multLocal(poseLocation.addLocal(objectToArmatureMatrix.toTranslationVector()));
-            rotation.multLocal(rotationQuaternion);
+        Structure skeletonOwnerObjectStructure = (Structure) blenderContext.getLoadedFeature(skeletonOwnerOma, LoadedFeatureDataType.LOADED_STRUCTURE);
+        Matrix4f invertedObjectOwnerGlobalMatrix = objectHelper.getMatrix(skeletonOwnerObjectStructure, "imat", blenderContext.getBlenderKey().isFixUpAxis());
+        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, objectToArmatureMatrix, blenderContext));
+            bone.addChild(child.buildBone(bones, skeletonOwnerOma, blenderContext));
         }
 
         return bone;
@@ -168,4 +190,14 @@ public class BoneContext {
     public Skeleton getSkeleton() {
         return blenderContext.getSkeleton(armatureObjectOMA);
     }
+
+    /**
+     * 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
+     */
+    private boolean is(int flagMask) {
+        return (flag & flagMask) != 0;
+    }
 }

+ 16 - 22
engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java

@@ -1,5 +1,6 @@
 package com.jme3.scene.plugins.blender.animations;
 
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.jme3.animation.BoneTrack;
@@ -148,6 +149,11 @@ public class Ipo {
             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;
+            if(spatialTrack && fixUpAxis) {
+                yIndex = 2;
+                zIndex = 1;
+            }
 
             // calculating track data
             for (int frame = startFrame; frame <= stopFrame; ++frame) {
@@ -157,36 +163,30 @@ public class Ipo {
                 for (int j = 0; j < bezierCurves.length; ++j) {
                     double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
                     switch (bezierCurves[j].getType()) {
-                    // LOCATION
+                        // LOCATION
                         case AC_LOC_X:
                             translation[0] = (float) value;
                             break;
                         case AC_LOC_Y:
-                            if (fixUpAxis) {
-                                translation[2] = value == 0.0f ? 0 : (float) -value;
-                            } else {
-                                translation[1] = (float) value;
-                            }
+                            translation[yIndex] = (float) value;
                             break;
                         case AC_LOC_Z:
-                            translation[fixUpAxis ? 1 : 2] = (float) value;
+                            translation[zIndex] = (float) value;
                             break;
 
                         // ROTATION (used with object animation)
-                        // the value here is in degrees divided by 10 (so in
-                        // example: 9 = PI/2)
                         case OB_ROT_X:
                             objectRotation[0] = (float) value * degreeToRadiansFactor;
                             break;
                         case OB_ROT_Y:
                             if (fixUpAxis) {
-                                objectRotation[2] = value == 0.0f ? 0 : (float) -value * degreeToRadiansFactor;
+                                objectRotation[yIndex] = value == 0.0f ? 0 : (float) -value * degreeToRadiansFactor;
                             } else {
-                                objectRotation[1] = (float) value * degreeToRadiansFactor;
+                                objectRotation[yIndex] = (float) value * degreeToRadiansFactor;
                             }
                             break;
                         case OB_ROT_Z:
-                            objectRotation[fixUpAxis ? 1 : 2] = (float) value * degreeToRadiansFactor;
+                            objectRotation[zIndex] = (float) value * degreeToRadiansFactor;
                             break;
 
                         // SIZE
@@ -200,9 +200,7 @@ public class Ipo {
                             scale[fixUpAxis ? 1 : 2] = (float) value;
                             break;
 
-                        // QUATERNION ROTATION (used with bone animation), dunno
-                        // why but here we shouldn't check the
-                        // spatialTrack flag value
+                        // QUATERNION ROTATION (used with bone animation)
                         case AC_QUAT_W:
                             quaternionRotation[3] = (float) value;
                             break;
@@ -210,17 +208,13 @@ public class Ipo {
                             quaternionRotation[0] = (float) value;
                             break;
                         case AC_QUAT_Y:
-                            if (fixUpAxis) {
-                                quaternionRotation[2] = value == 0.0f ? 0 : -(float) value;
-                            } else {
-                                quaternionRotation[1] = (float) value;
-                            }
+                            quaternionRotation[fixUpAxis ? 1 : 2] = (float) value;
                             break;
                         case AC_QUAT_Z:
-                            quaternionRotation[fixUpAxis ? 1 : 2] = (float) value;
+                            quaternionRotation[fixUpAxis ? 2 : 1] = (float) value;
                             break;
                         default:
-                            LOGGER.warning("Unknown ipo curve type: " + bezierCurves[j].getType());
+                            LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType());
                     }
                 }
                 translations[index] = localQuaternionRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2]));

+ 2 - 11
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java

@@ -17,7 +17,6 @@ import com.jme3.animation.Bone;
 import com.jme3.animation.BoneTrack;
 import com.jme3.animation.Skeleton;
 import com.jme3.animation.SkeletonControl;
-import com.jme3.math.Matrix4f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.Node;
@@ -35,7 +34,6 @@ 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.MeshContext;
-import com.jme3.scene.plugins.blender.objects.ObjectHelper;
 import com.jme3.util.BufferUtils;
 
 /**
@@ -85,17 +83,10 @@ import com.jme3.util.BufferUtils;
 
                 // load skeleton
                 Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
-
-                ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-                boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
-                Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis);
-                Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis);
-                Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix);
-
                 List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext);
                 List<Bone> bonesList = new ArrayList<Bone>();
                 for (int i = 0; i < bonebase.size(); ++i) {
-                    armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, blenderContext);
+                    armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectStructure.getOldMemoryAddress(), blenderContext);
                 }
                 bonesList.add(0, new Bone(""));
                 Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
@@ -105,7 +96,7 @@ import com.jme3.util.BufferUtils;
                 this.meshStructure = meshStructure;
 
                 // read mesh indexes
-                this.meshOMA = meshStructure.getOldMemoryAddress();
+                meshOMA = meshStructure.getOldMemoryAddress();
 
                 // read animations
                 ArrayList<Animation> animations = new ArrayList<Animation>();

+ 49 - 33
engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java

@@ -44,6 +44,7 @@ import com.jme3.math.Transform;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
 import com.jme3.scene.Spatial.CullHint;
 import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
 import com.jme3.scene.plugins.blender.BlenderContext;
@@ -67,9 +68,9 @@ import com.jme3.scene.plugins.blender.modifiers.ModifierHelper;
  * @author Marcin Roguski (Kaelthas)
  */
 public class ObjectHelper extends AbstractBlenderHelper {
-    private static final Logger LOGGER               = Logger.getLogger(ObjectHelper.class.getName());
+    private static final Logger LOGGER     = Logger.getLogger(ObjectHelper.class.getName());
 
-    public static final String OMA_MARKER = "oma";
+    public static final String  OMA_MARKER = "oma";
 
     /**
      * This constructor parses the given blender version and stores the result.
@@ -98,28 +99,28 @@ public class ObjectHelper extends AbstractBlenderHelper {
      */
     public Object toObject(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
         LOGGER.fine("Loading blender object.");
-        
+
         int type = ((Number) objectStructure.getFieldValue("type")).intValue();
         ObjectType objectType = ObjectType.valueOf(type);
         LOGGER.log(Level.FINE, "Type of the object: {0}.", objectType);
-        if(objectType == ObjectType.LAMP && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.LIGHTS)) {
+        if (objectType == ObjectType.LAMP && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.LIGHTS)) {
             LOGGER.fine("Lamps are not included in loading.");
             return null;
         }
-        if(objectType == ObjectType.CAMERA && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.CAMERAS)) {
+        if (objectType == ObjectType.CAMERA && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.CAMERAS)) {
             LOGGER.fine("Cameras are not included in loading.");
             return null;
         }
-        if(!blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.OBJECTS)) {
+        if (!blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.OBJECTS)) {
             LOGGER.fine("Objects are not included in loading.");
             return null;
-        }        
+        }
         int lay = ((Number) objectStructure.getFieldValue("lay")).intValue();
-        if((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
+        if ((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
             LOGGER.fine("The layer this object is located in is not included in loading.");
             return null;
         }
-        
+
         LOGGER.fine("Checking if the object has not been already loaded.");
         Object loadedResult = blenderContext.getLoadedFeature(objectStructure.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
         if (loadedResult != null) {
@@ -201,29 +202,29 @@ public class ObjectHelper extends AbstractBlenderHelper {
 
         if (result != null) {
             blenderContext.addLoadedFeatures(objectStructure.getOldMemoryAddress(), name, objectStructure, result);
-            
+
             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);
             }
-            
+
             // I prefer do compute bounding box here than read it from the file
             result.updateModelBound();
-            
+
             LOGGER.fine("Applying markers (those will be removed before the final result is released).");
             blenderContext.addMarker(OMA_MARKER, result, objectStructure.getOldMemoryAddress());
-            if(objectType == ObjectType.ARMATURE) {
+            if (objectType == ObjectType.ARMATURE) {
                 blenderContext.addMarker(ArmatureHelper.ARMATURE_NODE_MARKER, result, Boolean.TRUE);
             }
-            
+
             LOGGER.fine("Loading constraints connected with this object.");
             ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
             constraintHelper.loadConstraints(objectStructure, blenderContext);
@@ -241,6 +242,31 @@ public class ObjectHelper extends AbstractBlenderHelper {
         return result;
     }
 
+    /**
+     * 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, LoadedFeatureDataType.LOADED_FEATURE);
+        Spatial spatial = (Spatial) blenderContext.getLoadedFeature(spatialOMA, LoadedFeatureDataType.LOADED_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.
@@ -320,7 +346,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
     public Matrix4f getMatrix(Structure structure, String matrixName, boolean applyFixUpAxis) {
         Matrix4f result = new Matrix4f();
         DynamicArray<Number> obmat = (DynamicArray<Number>) structure.getFieldValue(matrixName);
-        //the matrix must be square
+        // 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) {
@@ -361,29 +387,19 @@ public class ObjectHelper extends AbstractBlenderHelper {
 
         return result;
     }
-    
+
     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);
-        
+        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) {
+            for (ObjectType type : ObjectType.values()) {
+                if (type.blenderTypeValue == blenderTypeValue) {
                     return type;
                 }
             }