From 0775b93088363c2a4aac54fee24860d9dd2706f9 Mon Sep 17 00:00:00 2001 From: "Kae..pl" Date: Sun, 11 Sep 2011 22:13:40 +0000 Subject: [PATCH] Added support for modifiers validating. Now modifiers that are invalid will not be loaded. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8245 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../blender/modifiers/ArmatureModifier.java | 98 ++++++------ .../blender/modifiers/ArrayModifier.java | 146 +++++++++--------- .../blender/modifiers/MirrorModifier.java | 21 ++- .../plugins/blender/modifiers/Modifier.java | 12 ++ .../modifiers/ObjectAnimationModifier.java | 18 +-- .../blender/modifiers/ParticlesModifier.java | 27 +++- 6 files changed, 178 insertions(+), 144 deletions(-) diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java index 89fcff60a..08d5da1cd 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java @@ -7,6 +7,8 @@ import java.util.HashMap; 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.animation.AnimControl; import com.jme3.animation.Animation; @@ -43,6 +45,7 @@ import com.jme3.util.BufferUtils; * @author Marcin Roguski (Kaelthas) */ /* package */class ArmatureModifier extends Modifier { + private static final Logger LOGGER = Logger.getLogger(ArmatureModifier.class.getName()); private static final int MAXIMUM_WEIGHTS_PER_VERTEX = 4; // have no idea why 4, could someone please explain ? /** Loaded animation data. */ @@ -80,53 +83,55 @@ import com.jme3.util.BufferUtils; * corrupted */ public ArmatureModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException { - Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); - if (pArmatureObject.isNotNull()) { - ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); - ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); - - Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0); - this.armatureObjectOMA = armatureObject.getOldMemoryAddress(); - - //read skeleton - // changing bones matrices so that they fit the current object - Structure armatureStructure = ((Pointer)armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); - Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase"); - List bonesStructures = bonebase.evaluateListBase(blenderContext); - for (Structure boneStructure : bonesStructures) { - BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext); - armatureHelper.addBoneDataRoot(rootBoneTransformationData); - } - Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); - Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); - Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); - Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); - - //read mesh indexes - Structure meshStructure = ((Pointer)objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); - this.meshOMA = meshStructure.getOldMemoryAddress(); - this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext); - - //read animations - String objectName = objectStructure.getName(); - Set animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName); - if (animationNames != null && animationNames.size() > 0) { - ArrayList animations = new ArrayList(); - List actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); - for (FileBlockHeader header : actionHeaders) { - Structure actionStructure = header.getStructure(blenderContext); - String actionName = actionStructure.getName(); - if (animationNames.contains(actionName)) { - int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName); - int fps = blenderContext.getBlenderKey().getFps(); - float start = (float) animationFrames[0] / (float) fps; - float stop = (float) animationFrames[1] / (float) fps; - BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); - boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName)); - animations.add(boneAnimation); + if(this.validate(modifierStructure, blenderContext)) { + Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); + if (pArmatureObject.isNotNull()) { + ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); + ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); + + Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0); + this.armatureObjectOMA = armatureObject.getOldMemoryAddress(); + + //read skeleton + // changing bones matrices so that they fit the current object + Structure armatureStructure = ((Pointer)armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); + Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase"); + List bonesStructures = bonebase.evaluateListBase(blenderContext); + for (Structure boneStructure : bonesStructures) { + BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext); + armatureHelper.addBoneDataRoot(rootBoneTransformationData); + } + Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); + Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); + Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); + Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); + + //read mesh indexes + Structure meshStructure = ((Pointer)objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); + this.meshOMA = meshStructure.getOldMemoryAddress(); + this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext); + + //read animations + String objectName = objectStructure.getName(); + Set animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName); + if (animationNames != null && animationNames.size() > 0) { + ArrayList animations = new ArrayList(); + List actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); + for (FileBlockHeader header : actionHeaders) { + Structure actionStructure = header.getStructure(blenderContext); + String actionName = actionStructure.getName(); + if (animationNames.contains(actionName)) { + int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName); + int fps = blenderContext.getBlenderKey().getFps(); + float start = (float) animationFrames[0] / (float) fps; + float stop = (float) animationFrames[1] / (float) fps; + BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); + boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName)); + animations.add(boneAnimation); + } } + animData = new AnimData(new Skeleton(bones), animations); } - animData = new AnimData(new Skeleton(bones), animations); } } } @@ -134,6 +139,9 @@ import com.jme3.util.BufferUtils; @Override @SuppressWarnings("unchecked") public Node apply(Node node, BlenderContext blenderContext) { + if(invalid) { + LOGGER.log(Level.WARNING, "Armature modifier is invalid! Cannot be applied to: {0}", node.getName()); + }//if invalid, animData will be null if(animData == null) { return node; } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java index 3b1542287..bfa5e0e73 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java @@ -52,80 +52,86 @@ import com.jme3.scene.shape.Curve; * corrupted */ @SuppressWarnings("unchecked") - public ArrayModifier(Structure modifier, BlenderContext blenderContext) throws BlenderFileException { - Number fittype = (Number) modifier.getFieldValue("fit_type"); - modifierData.put("fittype", fittype); - switch (fittype.intValue()) { - case 0:// FIXED COUNT - modifierData.put("count", modifier.getFieldValue("count")); - break; - case 1:// FIXED LENGTH - modifierData.put("length", modifier.getFieldValue("length")); - break; - case 2:// FITCURVE - Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob"); - float length = 0; - if (pCurveOb.isNotNull()) { - Structure curveStructure = pCurveOb.fetchData(blenderContext.getInputStream()).get(0); - ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); - Node curveObject = (Node) objectHelper.toObject(curveStructure, blenderContext); - Set referencesToCurveLengths = new HashSet(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); - } - } - } - } - } - modifierData.put("length", Float.valueOf(length)); - modifierData.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH - break; - default: - assert false : "Unknown array modifier fit type: " + fittype; - } - - // offset parameters - int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue(); - if ((offsettype & 0x01) != 0) {// Constant offset - DynamicArray offsetArray = (DynamicArray) modifier.getFieldValue("offset"); - float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()}; - modifierData.put("offset", offset); - } - if ((offsettype & 0x02) != 0) {// Relative offset - DynamicArray scaleArray = (DynamicArray) modifier.getFieldValue("scale"); - float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()}; - modifierData.put("scale", scale); - } - if ((offsettype & 0x04) != 0) {// Object offset - Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob"); - if (pOffsetObject.isNotNull()) { - modifierData.put("offsetob", pOffsetObject); - } - } - - // start cap and end cap - Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap"); - if (pStartCap.isNotNull()) { - modifierData.put("startcap", pStartCap); - } - Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap"); - if (pEndCap.isNotNull()) { - modifierData.put("endcap", pEndCap); - } + public ArrayModifier(Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException { + if(this.validate(modifierStructure, blenderContext)) { + Number fittype = (Number) modifierStructure.getFieldValue("fit_type"); + modifierData.put("fittype", fittype); + switch (fittype.intValue()) { + case 0:// FIXED COUNT + modifierData.put("count", modifierStructure.getFieldValue("count")); + break; + case 1:// FIXED LENGTH + modifierData.put("length", modifierStructure.getFieldValue("length")); + break; + case 2:// FITCURVE + Pointer pCurveOb = (Pointer) modifierStructure.getFieldValue("curve_ob"); + float length = 0; + if (pCurveOb.isNotNull()) { + Structure curveStructure = pCurveOb.fetchData(blenderContext.getInputStream()).get(0); + ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); + Node curveObject = (Node) objectHelper.toObject(curveStructure, blenderContext); + Set referencesToCurveLengths = new HashSet(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); + } + } + } + } + } + modifierData.put("length", Float.valueOf(length)); + modifierData.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH + break; + default: + assert false : "Unknown array modifier fit type: " + fittype; + } + + // offset parameters + int offsettype = ((Number) modifierStructure.getFieldValue("offset_type")).intValue(); + if ((offsettype & 0x01) != 0) {// Constant offset + DynamicArray offsetArray = (DynamicArray) modifierStructure.getFieldValue("offset"); + float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()}; + modifierData.put("offset", offset); + } + if ((offsettype & 0x02) != 0) {// Relative offset + DynamicArray scaleArray = (DynamicArray) modifierStructure.getFieldValue("scale"); + float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()}; + modifierData.put("scale", scale); + } + if ((offsettype & 0x04) != 0) {// Object offset + Pointer pOffsetObject = (Pointer) modifierStructure.getFieldValue("offset_ob"); + if (pOffsetObject.isNotNull()) { + modifierData.put("offsetob", pOffsetObject); + } + } + + // start cap and end cap + Pointer pStartCap = (Pointer) modifierStructure.getFieldValue("start_cap"); + if (pStartCap.isNotNull()) { + modifierData.put("startcap", pStartCap); + } + Pointer pEndCap = (Pointer) modifierStructure.getFieldValue("end_cap"); + if (pEndCap.isNotNull()) { + modifierData.put("endcap", pEndCap); + } + } } @Override public Node apply(Node node, BlenderContext blenderContext) { + if(invalid) { + LOGGER.log(Level.WARNING, "Array modifier is invalid! Cannot be applied to: {0}", node.getName()); + return node; + } int fittype = ((Number) modifierData.get("fittype")).intValue(); float[] offset = (float[]) modifierData.get("offset"); if (offset == null) {// the node will be repeated several times in the same place diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java index b64a95dfe..ef06eff92 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java @@ -48,17 +48,24 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper; * this exception is thrown when the blender file is somehow * corrupted */ - public MirrorModifier(Structure modifier, BlenderContext blenderContext) { - modifierData.put("flag", modifier.getFieldValue("flag")); - modifierData.put("tolerance", modifier.getFieldValue("tolerance")); - Pointer pMirrorOb = (Pointer) modifier.getFieldValue("mirror_ob"); - if (pMirrorOb.isNotNull()) { - modifierData.put("mirrorob", pMirrorOb); - } + public MirrorModifier(Structure modifierStructure, BlenderContext blenderContext) { + if(this.validate(modifierStructure, blenderContext)) { + modifierData.put("flag", modifierStructure.getFieldValue("flag")); + modifierData.put("tolerance", modifierStructure.getFieldValue("tolerance")); + Pointer pMirrorOb = (Pointer) modifierStructure.getFieldValue("mirror_ob"); + if (pMirrorOb.isNotNull()) { + modifierData.put("mirrorob", pMirrorOb); + } + } } @Override public Node apply(Node node, BlenderContext blenderContext) { + if(invalid) { + LOGGER.log(Level.WARNING, "Mirror modifier is invalid! Cannot be applied to: {0}", node.getName()); + return node; + } + int flag = ((Number) modifierData.get("flag")).intValue(); float[] mirrorFactor = new float[]{ (flag & 0x08) != 0 ? -1.0f : 1.0f, diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java index ceac97600..f1190f630 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java @@ -2,6 +2,8 @@ package com.jme3.scene.plugins.blender.modifiers; import com.jme3.scene.Node; import com.jme3.scene.plugins.blender.BlenderContext; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; /** * This class represents an object's modifier. The modifier object can be varied @@ -19,6 +21,9 @@ public abstract class Modifier { public static final String MIRROR_MODIFIER_DATA = "MirrorModifierData"; public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData"; + /** This variable indicates if the modifier is invalid (true) or not (false). */ + protected boolean invalid; + /** * This method applies the modifier to the given node. * @@ -36,4 +41,11 @@ public abstract class Modifier { * @return blender's type of modifier */ public abstract String getType(); + + protected boolean validate(Structure modifierStructure, BlenderContext blenderContext) { + Structure modifierData = (Structure)modifierStructure.getFieldValue("modifier"); + Pointer pError = (Pointer) modifierData.getFieldValue("error"); + invalid = pError.isNotNull(); + return !invalid; + } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java index fe39688e8..22ab79f89 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java @@ -1,24 +1,11 @@ package com.jme3.scene.plugins.blender.modifiers; -import com.jme3.animation.Animation; -import java.util.ArrayList; -import java.util.List; import java.util.logging.Logger; -import com.jme3.animation.Bone; -import com.jme3.animation.BoneAnimation; -import com.jme3.animation.BoneTrack; -import com.jme3.animation.Skeleton; -import com.jme3.math.Transform; import com.jme3.scene.Node; import com.jme3.scene.plugins.blender.BlenderContext; -import com.jme3.scene.plugins.blender.animations.Ipo; -import com.jme3.scene.plugins.blender.animations.IpoHelper; import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; -import com.jme3.scene.plugins.blender.file.FileBlockHeader; -import com.jme3.scene.plugins.blender.file.Pointer; import com.jme3.scene.plugins.blender.file.Structure; -import com.jme3.scene.plugins.blender.objects.ObjectHelper; import com.jme3.scene.plugins.ogre.AnimData; /** @@ -53,6 +40,8 @@ import com.jme3.scene.plugins.ogre.AnimData; * corrupted */ public ObjectAnimationModifier(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException { + LOGGER.warning("Object animation modifier not yet implemented!"); + /* Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo"); if (pIpo.isNotNull()) { // check if there is an action name connected with this ipo @@ -105,12 +94,13 @@ import com.jme3.scene.plugins.ogre.AnimData; animData = new AnimData(new Skeleton(new Bone[] { bone }), animations); objectOMA = objectStructure.getOldMemoryAddress(); } + */ } @Override public Node apply(Node node, BlenderContext blenderContext) { LOGGER.warning("Object animation modifier not yet implemented!"); - return null; + return node; } @Override diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java index 4a04b42d9..4a5134d67 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java @@ -2,6 +2,8 @@ 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; @@ -24,13 +26,16 @@ import com.jme3.scene.plugins.blender.particles.ParticlesHelper; * @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 modifier + * @param modifierStructure * the structure of the modifier * @param blenderContext * the blender context @@ -38,18 +43,24 @@ import com.jme3.scene.plugins.blender.particles.ParticlesHelper; * an exception is throw wneh there are problems with the * blender file */ - public ParticlesModifier(Structure modifier, BlenderContext blenderContext) - throws BlenderFileException { - Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys"); - if (pParticleSystem.isNotNull()) { - ParticlesHelper particlesHelper = blenderContext.getHelper(ParticlesHelper.class); - Structure particleSystem = pParticleSystem.fetchData(blenderContext.getInputStream()).get(0); - particleEmitter = particlesHelper.toParticleEmitter(particleSystem, blenderContext); + 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(blenderContext.getInputStream()).get(0); + particleEmitter = particlesHelper.toParticleEmitter(particleSystem, blenderContext); + } } } @Override public Node apply(Node node, BlenderContext blenderContext) { + if(invalid) { + LOGGER.log(Level.WARNING, "Particles modifier is invalid! Cannot be applied to: {0}", node.getName()); + return node; + } + MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class); ParticleEmitter emitter = particleEmitter.clone();