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
3.0
Kae..pl 13 years ago
parent ba57377795
commit 0775b93088
  1. 90
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java
  2. 142
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java
  3. 21
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java
  4. 12
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java
  5. 18
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java
  6. 27
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.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);
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();
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<Structure> 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 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<Structure> 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 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<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName);
if (animationNames != null && animationNames.size() > 0) {
ArrayList<Animation> animations = new ArrayList<Animation>();
List<FileBlockHeader> 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);
//read animations
String objectName = objectStructure.getName();
Set<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName);
if (animationNames != null && animationNames.size() > 0) {
ArrayList<Animation> animations = new ArrayList<Animation>();
List<FileBlockHeader> 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;
}

@ -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<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);
}
}
}
}
}
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;
}
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<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);
}
}
}
}
}
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<Number> offsetArray = (DynamicArray<Number>) 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<Number> scaleArray = (DynamicArray<Number>) 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);
}
}
// offset parameters
int offsettype = ((Number) modifierStructure.getFieldValue("offset_type")).intValue();
if ((offsettype & 0x01) != 0) {// Constant offset
DynamicArray<Number> offsetArray = (DynamicArray<Number>) 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<Number> scaleArray = (DynamicArray<Number>) 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) 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);
}
// 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

@ -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,

@ -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 (<b>true</b>) or not (<b>false</b>). */
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;
}
}

@ -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

@ -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();

Loading…
Cancel
Save