diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java similarity index 92% rename from engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java index 0acf7bd11..e14bf4a27 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java @@ -29,14 +29,15 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.utils; +package com.jme3.scene.plugins.blender; import java.nio.FloatBuffer; import java.util.List; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.Properties; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.Properties; import com.jme3.util.BufferUtils; /** diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java index e8dee730e..6ed96351f 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java @@ -47,25 +47,22 @@ import com.jme3.asset.ModelKey; import com.jme3.light.Light; import com.jme3.renderer.Camera; import com.jme3.scene.Node; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.helpers.ArmatureHelper; -import com.jme3.scene.plugins.blender.helpers.CameraHelper; -import com.jme3.scene.plugins.blender.helpers.ConstraintHelper; -import com.jme3.scene.plugins.blender.helpers.CurvesHelper; -import com.jme3.scene.plugins.blender.helpers.IpoHelper; -import com.jme3.scene.plugins.blender.helpers.LightHelper; -import com.jme3.scene.plugins.blender.helpers.MaterialHelper; -import com.jme3.scene.plugins.blender.helpers.MeshHelper; -import com.jme3.scene.plugins.blender.helpers.ModifierHelper; -import com.jme3.scene.plugins.blender.helpers.NoiseHelper; -import com.jme3.scene.plugins.blender.helpers.ObjectHelper; -import com.jme3.scene.plugins.blender.helpers.ParticlesHelper; -import com.jme3.scene.plugins.blender.helpers.TextureHelper; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.JmeConverter; +import com.jme3.scene.plugins.blender.animations.ArmatureHelper; +import com.jme3.scene.plugins.blender.animations.IpoHelper; +import com.jme3.scene.plugins.blender.cameras.CameraHelper; +import com.jme3.scene.plugins.blender.constraints.ConstraintHelper; +import com.jme3.scene.plugins.blender.curves.CurvesHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.BlenderInputStream; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.lights.LightHelper; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; +import com.jme3.scene.plugins.blender.meshes.MeshHelper; +import com.jme3.scene.plugins.blender.modifiers.ModifierHelper; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; +import com.jme3.scene.plugins.blender.particles.ParticlesHelper; +import com.jme3.scene.plugins.blender.textures.TextureHelper; /** * This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures. @@ -111,7 +108,6 @@ public class BlenderLoader implements AssetLoader { dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber())); dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository)); dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber())); - dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber())); dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber())); //setting additional data to helpers diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java index a6e0a0304..7e400c727 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderModelLoader.java @@ -45,24 +45,21 @@ import com.jme3.asset.BlenderKey.LoadingResults; import com.jme3.asset.ModelKey; import com.jme3.scene.Node; import com.jme3.scene.Spatial; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.helpers.ArmatureHelper; -import com.jme3.scene.plugins.blender.helpers.CameraHelper; -import com.jme3.scene.plugins.blender.helpers.ConstraintHelper; -import com.jme3.scene.plugins.blender.helpers.CurvesHelper; -import com.jme3.scene.plugins.blender.helpers.IpoHelper; -import com.jme3.scene.plugins.blender.helpers.LightHelper; -import com.jme3.scene.plugins.blender.helpers.MaterialHelper; -import com.jme3.scene.plugins.blender.helpers.MeshHelper; -import com.jme3.scene.plugins.blender.helpers.ModifierHelper; -import com.jme3.scene.plugins.blender.helpers.NoiseHelper; -import com.jme3.scene.plugins.blender.helpers.ObjectHelper; -import com.jme3.scene.plugins.blender.helpers.ParticlesHelper; -import com.jme3.scene.plugins.blender.helpers.TextureHelper; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.JmeConverter; +import com.jme3.scene.plugins.blender.animations.ArmatureHelper; +import com.jme3.scene.plugins.blender.animations.IpoHelper; +import com.jme3.scene.plugins.blender.cameras.CameraHelper; +import com.jme3.scene.plugins.blender.constraints.ConstraintHelper; +import com.jme3.scene.plugins.blender.curves.CurvesHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.BlenderInputStream; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.lights.LightHelper; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; +import com.jme3.scene.plugins.blender.meshes.MeshHelper; +import com.jme3.scene.plugins.blender.modifiers.ModifierHelper; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; +import com.jme3.scene.plugins.blender.particles.ParticlesHelper; +import com.jme3.scene.plugins.blender.textures.TextureHelper; /** * This is the main loading class. Have in notice that asset manager needs to have loaders for resources like textures. @@ -104,7 +101,6 @@ public class BlenderModelLoader implements AssetLoader { dataRepository.putHelper(MaterialHelper.class, new MaterialHelper(inputStream.getVersionNumber())); dataRepository.putHelper(ConstraintHelper.class, new ConstraintHelper(inputStream.getVersionNumber(), dataRepository)); dataRepository.putHelper(IpoHelper.class, new IpoHelper(inputStream.getVersionNumber())); - dataRepository.putHelper(NoiseHelper.class, new NoiseHelper(inputStream.getVersionNumber())); dataRepository.putHelper(ParticlesHelper.class, new ParticlesHelper(inputStream.getVersionNumber())); //setting additional data to helpers diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/DataRepository.java b/engine/src/blender/com/jme3/scene/plugins/blender/DataRepository.java similarity index 86% rename from engine/src/blender/com/jme3/scene/plugins/blender/utils/DataRepository.java rename to engine/src/blender/com/jme3/scene/plugins/blender/DataRepository.java index 31db11fe6..68dc1875f 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/DataRepository.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/DataRepository.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.utils; +package com.jme3.scene.plugins.blender; import java.util.ArrayList; import java.util.EmptyStackException; @@ -42,11 +42,13 @@ import com.jme3.asset.AssetManager; import com.jme3.asset.BlenderKey; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; -import com.jme3.scene.plugins.blender.data.DnaBlockData; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.structures.Ipo; -import com.jme3.scene.plugins.blender.structures.Modifier; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.constraints.Constraint; +import com.jme3.scene.plugins.blender.file.BlenderInputStream; +import com.jme3.scene.plugins.blender.file.DnaBlockData; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.modifiers.Modifier; /** * The class that stores temporary data and manages it during loading the belnd file. This class is intended to be used @@ -84,6 +86,8 @@ public class DataRepository { private Map loadedIpos = new HashMap(); /** A list of modifiers for the specified object. */ protected Map> modifiers = new HashMap>(); + /** A list of constraints for the specified object. */ + protected Map> constraints = new HashMap>(); /** A map og helpers that perform loading. */ private Map helpers = new HashMap(); @@ -330,18 +334,16 @@ public class DataRepository { * This method adds a new modifier to the list. * @param ownerOMA * the owner's old memory address - * @param modifierType - * the type of the modifier - * @param loadedModifier - * the loaded modifier object + * @param modifier + * the object's modifier */ - public void addModifier(Long ownerOMA, String modifierType, Object loadedModifier, Object additionalModifierData) { + public void addModifier(Long ownerOMA, Modifier modifier) { List objectModifiers = this.modifiers.get(ownerOMA); if (objectModifiers == null) { objectModifiers = new ArrayList(); this.modifiers.put(ownerOMA, objectModifiers); } - objectModifiers.add(new Modifier(modifierType, loadedModifier, additionalModifierData)); + objectModifiers.add(modifier); } /** @@ -365,6 +367,33 @@ public class DataRepository { } return result; } + + /** + * This method adds a new modifier to the list. + * @param ownerOMA + * the owner's old memory address + * @param constraints + * the object's constraints + */ + public void addConstraints(Long ownerOMA, List constraints) { + List objectConstraints = this.constraints.get(ownerOMA); + if (objectConstraints == null) { + objectConstraints = new ArrayList(); + this.constraints.put(ownerOMA, objectConstraints); + } + objectConstraints.addAll(constraints); + } + + /** + * This method returns constraints for the object specified by its old memory address. If no + * modifiers are found - null is returned. + * @param objectOMA + * object's old memory address + * @return the list of object's modifiers or null + */ + public List getConstraints(Long objectOMA) { + return constraints.get(objectOMA); + } /** * This metod returns the default material. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java b/engine/src/blender/com/jme3/scene/plugins/blender/JmeConverter.java similarity index 88% rename from engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java rename to engine/src/blender/com/jme3/scene/plugins/blender/JmeConverter.java index 0fc42277d..5d037b499 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/JmeConverter.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.utils; +package com.jme3.scene.plugins.blender; import java.util.List; @@ -42,19 +42,19 @@ import com.jme3.math.ColorRGBA; import com.jme3.renderer.Camera; import com.jme3.scene.Geometry; import com.jme3.scene.Node; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.helpers.CameraHelper; -import com.jme3.scene.plugins.blender.helpers.LightHelper; -import com.jme3.scene.plugins.blender.helpers.MaterialHelper; -import com.jme3.scene.plugins.blender.helpers.MeshHelper; -import com.jme3.scene.plugins.blender.helpers.ObjectHelper; +import com.jme3.scene.plugins.blender.cameras.CameraHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.lights.LightHelper; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; +import com.jme3.scene.plugins.blender.meshes.MeshHelper; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; /** * This class converts blender file blocks into jMonkeyEngine data structures. * @author Marcin Roguski */ -public class JmeConverter implements BlenderConverter, Material> { +/*package*/ class JmeConverter { private final DataRepository dataRepository; @@ -84,7 +84,6 @@ public class JmeConverter implements BlenderConverter toMesh(Structure structure) throws BlenderFileException { MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class); if(meshHelper.shouldBeLoaded(structure, dataRepository)) { @@ -136,7 +131,6 @@ public class JmeConverter implements BlenderConverter bonesMap = new HashMap(); - /** A map of bones and their old memory addresses. */ - protected Map bonesOMAs = new HashMap(); - /** This list contains bones hierarchy and their matrices. It is later converted into jme bones. */ - protected List boneDataRoots = new ArrayList(); /** * This constructor parses the given blender version and stores the result. Some functionalities may differ in @@ -82,6 +75,16 @@ public class ArmatureHelper extends AbstractBlenderHelper { super(blenderVersion); } + /** + * The map of the bones. Maps a bone name to its index in the armature. Should be cleared after the object had been + * read. TODO: probably bones can have identical names in different armatures + */ + protected Map bonesMap = new HashMap(); + /** A map of bones and their old memory addresses. */ + protected Map bonesOMAs = new HashMap(); + /** This list contains bones hierarchy and their matrices. It is later converted into jme bones. */ + protected List boneDataRoots = new ArrayList(); + /** * This method returns the old memory address of a bone. If the bone does not exist in the blend file - zero is * returned. @@ -145,45 +148,6 @@ public class ArmatureHelper extends AbstractBlenderHelper { return result; } - /** - * This method reads the tracks of the armature object. - * @param actionStructure - * @param dataRepository - * the data repository - * @param objectName - * the name of animation owner - * @param animationName - * the name of the animation - * @return a list of tracks for the armature - * @throws BlenderFileException - * this exception is thrown when the blender file is somehow corrupted - */ - public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException { - LOGGER.log(Level.INFO, "Getting tracks!"); - IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class); - int fps = dataRepository.getBlenderKey().getFps(); - int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName); - Structure chanbase = (Structure) actionStructure.getFieldValue("chanbase"); - List actionChannels = chanbase.evaluateListBase(dataRepository);//bActionChannel - if (actionChannels != null && actionChannels.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) { - throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!"); - } - List tracks = new ArrayList(); - for (Structure bActionChannel : actionChannels) { - String name = bActionChannel.getFieldValue("name").toString(); - Integer boneIndex = bonesMap.get(name); - if (boneIndex != null) { - Pointer p = (Pointer) bActionChannel.getFieldValue("ipo"); - if (p.isNotNull()) { - Structure ipoStructure = p.fetchData(dataRepository.getInputStream()).get(0); - Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository); - tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps)); - } - } - } - return tracks.toArray(new BoneTrack[tracks.size()]); - } - /** * This bone returns transformation matrix of the bone that is relative to * its armature object. @@ -373,4 +337,116 @@ public class ArmatureHelper extends AbstractBlenderHelper { public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { return true; } + + public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException { + if (blenderVersion < 250) { + return this.getTracks250(actionStructure, dataRepository, objectName, animationName); + } else { + return this.getTracks249(actionStructure, dataRepository, objectName, animationName); + } + } + + private BoneTrack[] getTracks250(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException { + LOGGER.log(Level.INFO, "Getting tracks!"); + int fps = dataRepository.getBlenderKey().getFps(); + int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName); + Structure groups = (Structure) actionStructure.getFieldValue("groups"); + List actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup + if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) { + throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!"); + } + + List tracks = new ArrayList(); + for (Structure actionGroup : actionGroups) { + String name = actionGroup.getFieldValue("name").toString(); + Integer boneIndex = bonesMap.get(name); + if (boneIndex != null) { + List channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository); + BezierCurve[] bezierCurves = new BezierCurve[channels.size()]; + int channelCounter = 0; + for (Structure c : channels) { + //reading rna path first + BlenderInputStream bis = dataRepository.getInputStream(); + int currentPosition = bis.getPosition(); + Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path"); + FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress()); + bis.setPosition(dataFileBlock.getBlockPosition()); + String rnaPath = bis.readString(); + bis.setPosition(currentPosition); + int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue(); + int type = this.getCurveType(rnaPath, arrayIndex); + + Pointer pBezTriple = (Pointer) c.getFieldValue("bezt"); + List bezTriples = pBezTriple.fetchData(dataRepository.getInputStream()); + bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2); + } + + Ipo ipo = new Ipo(bezierCurves); + tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps)); + } + } + return tracks.toArray(new BoneTrack[tracks.size()]); + } + + private BoneTrack[] getTracks249(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException { + LOGGER.log(Level.INFO, "Getting tracks!"); + int fps = dataRepository.getBlenderKey().getFps(); + int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName); + Structure groups = (Structure) actionStructure.getFieldValue("groups"); + List actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup + if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) { + throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!"); + } + + List tracks = new ArrayList(); + for (Structure actionGroup : actionGroups) { + String name = actionGroup.getFieldValue("name").toString(); + Integer boneIndex = bonesMap.get(name); + if (boneIndex != null) { + List channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository); + BezierCurve[] bezierCurves = new BezierCurve[channels.size()]; + int channelCounter = 0; + for (Structure c : channels) { + //reading rna path first + BlenderInputStream bis = dataRepository.getInputStream(); + int currentPosition = bis.getPosition(); + Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path"); + FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress()); + bis.setPosition(dataFileBlock.getBlockPosition()); + String rnaPath = bis.readString(); + bis.setPosition(currentPosition); + int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue(); + int type = this.getCurveType(rnaPath, arrayIndex); + + Pointer pBezTriple = (Pointer) c.getFieldValue("bezt"); + List bezTriples = pBezTriple.fetchData(dataRepository.getInputStream()); + bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2); + } + + Ipo ipo = new Ipo(bezierCurves); + tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps)); + } + } + return tracks.toArray(new BoneTrack[tracks.size()]); + } + + /** + * This method parses the information stored inside the curve rna path and returns the proper type + * of the curve. + * @param rnaPath the curve's rna path + * @param arrayIndex the array index of the stored data + * @return the type of the curve + */ + protected int getCurveType(String rnaPath, int arrayIndex) { + if (rnaPath.endsWith(".location")) { + return Ipo.AC_LOC_X + arrayIndex; + } + if (rnaPath.endsWith(".rotation_quaternion")) { + return Ipo.AC_QUAT_W + arrayIndex; + } + if (rnaPath.endsWith(".scale")) { + return Ipo.AC_SIZE_X + arrayIndex; + } + throw new IllegalStateException("Unknown curve rna path: " + rnaPath); + } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java b/engine/src/blender/com/jme3/scene/plugins/blender/animations/CalculationBone.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java rename to engine/src/blender/com/jme3/scene/plugins/blender/animations/CalculationBone.java index cc0abd33c..53067e685 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/animations/CalculationBone.java @@ -1,4 +1,4 @@ -package com.jme3.scene.plugins.blender.structures; +package com.jme3.scene.plugins.blender.animations; import java.util.Arrays; @@ -11,7 +11,7 @@ import com.jme3.scene.Spatial; /** * The purpose of this class is to imitate bone's movement when calculating inverse kinematics. - * @author Marcin Roguski + * @author Marcin Roguski (Kaelthas) */ public class CalculationBone extends Node { private Bone bone; diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Ipo.java b/engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/structures/Ipo.java rename to engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java index d098774d1..8c9360d1e 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Ipo.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/animations/Ipo.java @@ -1,8 +1,9 @@ -package com.jme3.scene.plugins.blender.structures; +package com.jme3.scene.plugins.blender.animations; import com.jme3.animation.BoneTrack; import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; +import com.jme3.scene.plugins.blender.curves.BezierCurve; /** * This class is used to calculate bezier curves value for the given frames. The Ipo (interpolation object) consists diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/animations/IpoHelper.java similarity index 86% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/animations/IpoHelper.java index 7712bcd0a..b46d48b7a 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/animations/IpoHelper.java @@ -1,15 +1,14 @@ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.animations; import java.util.List; import com.jme3.animation.BoneTrack; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.BezierCurve; -import com.jme3.scene.plugins.blender.structures.Ipo; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.curves.BezierCurve; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; /** * This class helps to compute values from interpolation curves for features like animation or constraint influence. The @@ -18,7 +17,7 @@ import com.jme3.scene.plugins.blender.utils.Pointer; */ public class IpoHelper extends AbstractBlenderHelper { - /** + /** * This constructor parses the given blender version and stores the result. Some functionalities may differ in * different blender versions. * @param blenderVersion diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java new file mode 100644 index 000000000..ee90e7aad --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java @@ -0,0 +1,118 @@ +package com.jme3.scene.plugins.blender.cameras; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.asset.BlenderKey.FeaturesToLoad; +import com.jme3.renderer.Camera; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * A class that is used to load cameras into the scene. + * @author Marcin Roguski + */ +public class CameraHelper extends AbstractBlenderHelper { + + private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName()); + protected static final int DEFAULT_CAM_WIDTH = 100; + protected static final int DEFAULT_CAM_HEIGHT = 100; + + /** + * This constructor parses the given blender version and stores the result. Some functionalities may differ in + * different blender versions. + * @param blenderVersion + * the version read from the blend file + */ + public CameraHelper(String blenderVersion) { + super(blenderVersion); + } + + /** + * This method converts the given structure to jme camera. + * + * @param structure + * camera structure + * @return jme camera object + * @throws BlenderFileException + * an exception is thrown when there are problems with the + * blender file + */ + public Camera toCamera(Structure structure) throws BlenderFileException { + if (blenderVersion >= 250) { + return this.toCamera250(structure); + } else { + return this.toCamera249(structure); + } + } + + /** + * This method converts the given structure to jme camera. Should be used form blender 2.5+. + * + * @param structure + * camera structure + * @return jme camera object + * @throws BlenderFileException + * an exception is thrown when there are problems with the + * blender file + */ + public Camera toCamera250(Structure structure) throws BlenderFileException { + Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT); + int type = ((Number) structure.getFieldValue("type")).intValue(); + if (type != 0 && type != 1) { + LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type); + type = 0; + } + //type==0 - perspective; type==1 - orthographic; perspective is used as default + result.setParallelProjection(type == 1); + float aspect = 0; + float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); + float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); + if (type == 0) { + aspect = ((Number) structure.getFieldValue("lens")).floatValue(); + } else { + aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); + } + result.setFrustumPerspective(45, aspect, clipsta, clipend); + return result; + } + + /** + * This method converts the given structure to jme camera. Should be used form blender 2.49. + * + * @param structure + * camera structure + * @return jme camera object + * @throws BlenderFileException + * an exception is thrown when there are problems with the + * blender file + */ + public Camera toCamera249(Structure structure) throws BlenderFileException { + Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT); + int type = ((Number) structure.getFieldValue("type")).intValue(); + if (type != 0 && type != 1) { + LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type); + type = 0; + } + //type==0 - perspective; type==1 - orthographic; perspective is used as default + result.setParallelProjection(type == 1); + float angle = ((Number) structure.getFieldValue("angle")).floatValue(); + float aspect = 0; + float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); + float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); + if (type == 0) { + aspect = ((Number) structure.getFieldValue("lens")).floatValue(); + } else { + aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); + } + result.setFrustumPerspective(angle, aspect, clipsta, clipend); + return result; + } + + @Override + public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { + return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java new file mode 100644 index 000000000..37a06fd8d --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java @@ -0,0 +1,247 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.Bone; +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; + +/** + * The implementation of a constraint. + * + * @author Marcin Roguski + */ +public abstract class Constraint { + + /** The name of this constraint. */ + protected final String name; + /** The old memory address of the constraint's owner. */ + protected final Long boneOMA; + protected final Space ownerSpace; + protected final Space targetSpace; + /** The structure with constraint's data. */ + protected final Structure data; + /** The ipo object defining influence. */ + protected final Ipo ipo; + protected DataRepository dataRepository; + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public Constraint(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + this.name = constraintStructure.getFieldValue("name").toString(); + ConstraintType constraintType = ConstraintType.valueOf(((Number)constraintStructure.getFieldValue("type")).intValue()); + if(constraintType != this.getType()) { + throw new IllegalStateException("Constraint structure does not match its type for constraint: " + name); + } + Pointer pData = (Pointer) constraintStructure.getFieldValue("data"); + if (pData.isNotNull()) { + data = pData.fetchData(dataRepository.getInputStream()).get(0); + } else { + throw new BlenderFileException("The constraint has no data specified!"); + } + this.boneOMA = boneOMA; + this.ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue()); + this.targetSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("tarspace")).byteValue()); + this.ipo = influenceIpo; + } + + /** + * This method returns the name of the constraint. + * + * @return the name of the constraint + */ + public String getName() { + return name; + } + + /** + * This method returns the old memoty address of the bone this constraint + * affects. + * + * @return the old memory address of the bone this constraint affects + */ + public Long getBoneOMA() { + return boneOMA; + } + + /** + * This method returns the type of the constraint. + * + * @return the type of the constraint + */ + public abstract ConstraintType getType(); + + /** + * This method returns the bone traces for the bone that is affected by the given constraint. + * @param skeleton + * the skeleton containing bones + * @param boneAnimation + * the bone animation that affects the skeleton + * @return the bone track for the bone that is being affected by the constraint + */ + protected BoneTrack getBoneTrack(Skeleton skeleton, BoneAnimation boneAnimation) { + Bone bone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE); + int boneIndex = bone==null ? 0 : skeleton.getBoneIndex(bone);//bone==null may mean the object animation + if (boneIndex != -1) { + //searching for track for this bone + for (BoneTrack boneTrack : boneAnimation.getTracks()) { + if (boneTrack.getTargetBoneIndex() == boneIndex) { + return boneTrack; + } + } + } + return null; + } + + /** + * This method returns the target or subtarget object (if specified). + * @param loadedFeatureDataType + * @return target or subtarget feature + * @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted + */ + protected Object getTarget(LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException { + //load the feature through objectHelper, this way we are certain the object loads and has + //his own constraints applied to traces + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + //always load the target first + Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress(); + Structure objectStructure = dataRepository.getFileBlock(targetOMA).getStructure(dataRepository); + Object result = objectHelper.toObject(objectStructure, dataRepository); + + //subtarget should be loaded alogn with target + Object subtarget = data.getFieldValue("subtarget"); + String subtargetName = subtarget==null ? null : subtarget.toString(); + if (subtargetName!=null && subtargetName.length() > 0) { + result = dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType); + } + return result; + } + + /** + * This method returns target's object location. + * @return target's object location + */ + protected Vector3f getTargetLocation() { + Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress(); + Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE); + switch (targetSpace) { + case CONSTRAINT_SPACE_LOCAL: + return targetObject.getLocalTranslation(); + case CONSTRAINT_SPACE_WORLD: + return targetObject.getWorldTranslation(); + default: + throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString()); + } + } + + /** + * This method returns target's object location in the specified frame. + * @param frame + * the frame number + * @return target's object location + */ + protected Vector3f getTargetLocation(int frame) { + return this.getTargetLocation();//TODO: implement getting location in a specified frame + } + + /** + * This method returns target's object rotation. + * @return target's object rotation + */ + protected Quaternion getTargetRotation() { + Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress(); + Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE); + switch (targetSpace) { + case CONSTRAINT_SPACE_LOCAL: + return targetObject.getLocalRotation(); + case CONSTRAINT_SPACE_WORLD: + return targetObject.getWorldRotation(); + default: + throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString()); + } + } + + /** + * This method returns target's object scale. + * @return target's object scale + */ + protected Vector3f getTargetScale() { + Long targetOMA = ((Pointer) data.getFieldValue("tar")).getOldMemoryAddress(); + Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE); + switch (targetSpace) { + case CONSTRAINT_SPACE_LOCAL: + return targetObject.getLocalScale(); + case CONSTRAINT_SPACE_WORLD: + return targetObject.getWorldScale(); + default: + throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString()); + } + } + + /** + * This method affects the bone animation tracks for the given skeleton. + * + * @param skeleton + * the skeleton containing the affected bones by constraint + * @param boneAnimation + * the bone animation baked traces + * @param constraint + * the constraint + */ + public abstract void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation); + + /** + * The space of target or owner transformation. + * + * @author Marcin Roguski + */ + public static enum Space { + + CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID; + + /** + * This method returns the enum instance when given the appropriate + * value from the blend file. + * + * @param c + * the blender's value of the space modifier + * @return the scape enum instance + */ + public static Space valueOf(byte c) { + switch (c) { + case 0: + return CONSTRAINT_SPACE_WORLD; + case 1: + return CONSTRAINT_SPACE_LOCAL; + case 2: + return CONSTRAINT_SPACE_POSE; + case 3: + return CONSTRAINT_SPACE_PARLOCAL; + default: + return CONSTRAINT_SPACE_INVALID; + } + } + } +} \ No newline at end of file diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintAction.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintAction.java new file mode 100644 index 000000000..9bf3f715c --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintAction.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Action' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintAction extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintAction.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintAction(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Action' constraint + LOGGER.log(Level.WARNING, "'Action' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_ACTION; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintChildOf.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintChildOf.java new file mode 100644 index 000000000..516ec45f3 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintChildOf.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'ChildOf' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintChildOf extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintChildOf.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintChildOf(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement ChildOf constraint + LOGGER.log(Level.WARNING, "ChildOf constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_CHILDOF; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintClampTo.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintClampTo.java new file mode 100644 index 000000000..92cc0b88a --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintClampTo.java @@ -0,0 +1,51 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Clamp to' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintClampTo extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintClampTo.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintClampTo(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) + throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + //TODO: implement when curves are implemented + LOGGER.log(Level.INFO, "'Clamp to' not yet implemented! Curves not yet implemented!", this.getName()); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_CLAMPTO; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java new file mode 100644 index 000000000..43eba271e --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintDistLimit.java @@ -0,0 +1,84 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Vector3f; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Dist limit' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintDistLimit extends Constraint { + private static final int LIMITDIST_INSIDE = 0; + private static final int LIMITDIST_OUTSIDE = 1; + private static final int LIMITDIST_ONSURFACE = 2; + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintDistLimit(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + Vector3f targetLocation = this.getTargetLocation(); + BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation); + if (boneTrack != null) { + //TODO: target vertex group !!! + float dist = ((Number) data.getFieldValue("dist")).floatValue(); + int mode = ((Number) data.getFieldValue("mode")).intValue(); + + int maxFrames = boneTrack.getTimes().length; + Vector3f[] translations = boneTrack.getTranslations(); + for (int frame = 0; frame < maxFrames; ++frame) { + Vector3f v = translations[frame].subtract(targetLocation); + float currentDistance = v.length(); + float influence = ipo.calculateValue(frame); + float modifier = 0.0f; + switch (mode) { + case LIMITDIST_INSIDE: + if (currentDistance >= dist) { + modifier = (dist - currentDistance) / currentDistance; + } + break; + case LIMITDIST_ONSURFACE: + modifier = (dist - currentDistance) / currentDistance; + break; + case LIMITDIST_OUTSIDE: + if (currentDistance <= dist) { + modifier = (dist - currentDistance) / currentDistance; + } + break; + default: + throw new IllegalStateException("Unknown distance limit constraint mode: " + mode); + } + translations[frame].addLocal(v.multLocal(modifier * influence)); + } + boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales()); + } + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_DISTLIMIT; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFactory.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFactory.java new file mode 100644 index 000000000..2b36c55bd --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFactory.java @@ -0,0 +1,78 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * A factory class to create new instances of constraints depending on the type from the constraint's structure. + * This class has a package scope. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ final class ConstraintFactory { + + /** + * This method creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public static Constraint createConstraint(Structure constraintStructure, Long boneOMA, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + int type = ((Number)constraintStructure.getFieldValue("type")).intValue(); + ConstraintType constraintType = ConstraintType.valueOf(type); + switch(constraintType) { + case CONSTRAINT_TYPE_ACTION: + return new ConstraintAction(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_CHILDOF: + return new ConstraintChildOf(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_CLAMPTO: + return new ConstraintClampTo(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_DISTLIMIT: + return new ConstraintDistLimit(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_FOLLOWPATH: + return new ConstraintFollowPath(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_KINEMATIC: + return new ConstraintInverseKinematics(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_LOCKTRACK: + return new ConstraintLockTrack(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_LOCLIKE: + return new ConstraintLocLike(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_LOCLIMIT: + return new ConstraintLocLimit(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_MINMAX: + return new ConstraintMinMax(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_NULL: + return new ConstraintNull(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_PYTHON: + return new ConstraintPython(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_RIGIDBODYJOINT: + return new ConstraintRigidBodyJoint(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_ROTLIKE: + return new ConstraintRotLike(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_ROTLIMIT: + return new ConstraintRotLimit(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_SHRINKWRAP: + return new ConstraintShrinkWrap(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_SIZELIKE: + return new ConstraintSizeLike(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_SIZELIMIT: + return new ConstraintSizeLimit(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_STRETCHTO: + return new ConstraintStretchTo(constraintStructure, boneOMA, influenceIpo, dataRepository); + case CONSTRAINT_TYPE_TRANSFORM: + return new ConstraintTransform(constraintStructure, boneOMA, influenceIpo, dataRepository); + default: + throw new IllegalStateException("Unknown constraint type: " + constraintType); + } + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFollowPath.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFollowPath.java new file mode 100644 index 000000000..c0975030d --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintFollowPath.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Follow path' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintFollowPath extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintFollowPath.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintFollowPath(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + //TODO: implement when curves are implemented + LOGGER.log(Level.INFO, "'Follow path' not implemented! Curves not yet implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_FOLLOWPATH; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java new file mode 100644 index 000000000..0b496ed9c --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintHelper.java @@ -0,0 +1,140 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.animations.IpoHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class should be used for constraint calculations. + * @author Marcin Roguski + */ +public class ConstraintHelper extends AbstractBlenderHelper { + private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName()); + + /** + * Helper constructor. It's main task is to generate the affection functions. These functions are common to all + * ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall + * consider refactoring. The constructor parses the given blender version and stores the result. Some + * functionalities may differ in different blender versions. + * @param blenderVersion + * the version read from the blend file + */ + public ConstraintHelper(String blenderVersion, DataRepository dataRepository) { + super(blenderVersion); + } + + /** + * This method reads constraints for for the given structure. The constraints are loaded only once for object/bone. + * @param ownerOMA + * the owner's old memory address + * @param objectStructure + * the structure we read constraint's for + * @param dataRepository + * the data repository + * @throws BlenderFileException + */ + public Map> loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { + if (blenderVersion < 250) {//TODO + LOGGER.warning("Loading of constraints not yet implemented for version 2.5x !"); + return new HashMap>(0); + } + + // reading influence ipos for the constraints + IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class); + Map> constraintsIpos = new HashMap>(); + Pointer pActions = (Pointer) objectStructure.getFieldValue("action"); + if (pActions.isNotNull()) { + List actions = pActions.fetchData(dataRepository.getInputStream()); + for (Structure action : actions) { + Structure chanbase = (Structure) action.getFieldValue("chanbase"); + List actionChannels = chanbase.evaluateListBase(dataRepository); + for (Structure actionChannel : actionChannels) { + Map ipos = new HashMap(); + Structure constChannels = (Structure) actionChannel.getFieldValue("constraintChannels"); + List constraintChannels = constChannels.evaluateListBase(dataRepository); + for (Structure constraintChannel : constraintChannels) { + Pointer pIpo = (Pointer) constraintChannel.getFieldValue("ipo"); + if (pIpo.isNotNull()) { + String constraintName = constraintChannel.getFieldValue("name").toString(); + Ipo ipo = ipoHelper.createIpo(pIpo.fetchData(dataRepository.getInputStream()).get(0), dataRepository); + ipos.put(constraintName, ipo); + } + } + String actionName = actionChannel.getFieldValue("name").toString(); + constraintsIpos.put(actionName, ipos); + } + } + } + + Map> result = new HashMap>(); + + //loading constraints connected with the object's bones + Pointer pPose = (Pointer) objectStructure.getFieldValue("pose");//TODO: what if the object has two armatures ???? + if (pPose.isNotNull()) { + List poseChannels = ((Structure) pPose.fetchData(dataRepository.getInputStream()).get(0).getFieldValue("chanbase")).evaluateListBase(dataRepository); + for (Structure poseChannel : poseChannels) { + List constraintsList = new ArrayList(); + Long boneOMA = Long.valueOf(((Pointer) poseChannel.getFieldValue("bone")).getOldMemoryAddress()); + + //the name is read directly from structure because bone might not yet be loaded + String name = dataRepository.getFileBlock(boneOMA).getStructure(dataRepository).getFieldValue("name").toString(); + List constraints = ((Structure) poseChannel.getFieldValue("constraints")).evaluateListBase(dataRepository); + for (Structure constraint : constraints) { + String constraintName = constraint.getFieldValue("name").toString(); + Map ipoMap = constraintsIpos.get(name); + Ipo ipo = ipoMap==null ? null : ipoMap.get(constraintName); + if (ipo == null) { + float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue(); + ipo = ipoHelper.createIpo(enforce); + } + constraintsList.add(ConstraintFactory.createConstraint(constraint, boneOMA, ipo, dataRepository)); + } + + result.put(boneOMA, constraintsList); + dataRepository.addConstraints(boneOMA, constraintsList); + } + } + // TODO: reading constraints for objects (implement when object's animation will be available) + List constraintChannels = ((Structure)objectStructure.getFieldValue("constraintChannels")).evaluateListBase(dataRepository); + for(Structure constraintChannel : constraintChannels) { + System.out.println(constraintChannel); + } + + //loading constraints connected with the object itself (TODO: test this) + if(!result.containsKey(objectStructure.getOldMemoryAddress())) { + List constraints = ((Structure)objectStructure.getFieldValue("constraints")).evaluateListBase(dataRepository); + List constraintsList = new ArrayList(constraints.size()); + + for(Structure constraint : constraints) { + String constraintName = constraint.getFieldValue("name").toString(); + String objectName = objectStructure.getName(); + + Map objectConstraintsIpos = constraintsIpos.get(objectName); + Ipo ipo = objectConstraintsIpos!=null ? objectConstraintsIpos.get(constraintName) : null; + if (ipo == null) { + float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue(); + ipo = ipoHelper.createIpo(enforce); + } + constraintsList.add(ConstraintFactory.createConstraint(constraint, null, ipo, dataRepository)); + } + result.put(objectStructure.getOldMemoryAddress(), constraintsList); + dataRepository.addConstraints(objectStructure.getOldMemoryAddress(), constraintsList); + } + return result; + } + + @Override + public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { + return true; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintInverseKinematics.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintInverseKinematics.java new file mode 100644 index 000000000..bb3f36ff7 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintInverseKinematics.java @@ -0,0 +1,170 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import com.jme3.animation.Bone; +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.math.FastMath; +import com.jme3.math.Quaternion; +import com.jme3.math.Transform; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.CalculationBone; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; + +/** + * This class represents 'Inverse kinematics' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintInverseKinematics extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintInverseKinematics.class.getName()); + private static final float IK_SOLVER_ERROR = 0.5f; + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintInverseKinematics(Structure constraintStructure, + Long boneOMA, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + try { + // IK solver is only attached to bones + Bone ownerBone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE); + + // get the target point + Object targetObject = this.getTarget(LoadedFeatureDataType.LOADED_FEATURE); + Vector3f pt = null;// Point Target + if (targetObject instanceof Bone) { + pt = ((Bone) targetObject).getModelSpacePosition(); + } else if (targetObject instanceof Node) { + pt = ((Node) targetObject).getWorldTranslation(); + } else if (targetObject instanceof Skeleton) { + Structure armatureNodeStructure = (Structure) this.getTarget(LoadedFeatureDataType.LOADED_STRUCTURE); + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + Transform transform = objectHelper.getTransformation(armatureNodeStructure, dataRepository); + pt = transform.getTranslation(); + } else { + throw new IllegalStateException( + "Unknown target object type! Should be Node, Bone or Skeleton and there is: " + + targetObject.getClass().getName()); + } + + //fetching the owner's bone track +// BoneTrack ownerBoneTrack = null; +// int boneIndex = skeleton.getBoneIndex(ownerBone); +// for (int i = 0; i < boneAnimation.getTracks().length; ++i) { +// if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) { +// ownerBoneTrack = boneAnimation.getTracks()[i]; +// break; +// } +// } +// int ownerBoneFramesCount = ownerBoneTrack==null ? 0 : ownerBoneTrack.getTimes().length; + + // preparing data + int maxIterations = ((Number) data.getFieldValue("iterations")).intValue(); + CalculationBone[] bones = this.getBonesToCalculate(ownerBone, skeleton, boneAnimation); +// for (int i = 0; i < bones.length; ++i) { +// System.out.println(Arrays.toString(bones[i].track.getTranslations())); +// System.out.println(Arrays.toString(bones[i].track.getRotations())); +// System.out.println("==============================="); +// } + Quaternion rotation = new Quaternion(); + //all tracks should have the same amount of frames + int framesCount = bones[0].getBoneFramesCount(); + assert framesCount >=1; + for (int frame = 0; frame < framesCount; ++frame) { + float error = IK_SOLVER_ERROR; + int iteration = 0; + while (error >= IK_SOLVER_ERROR && iteration <= maxIterations) { + // rotating the bones + for (int i = 0; i < bones.length - 1; ++i) { + Vector3f pe = bones[i].getEndPoint(); + Vector3f pc = bones[i + 1].getWorldTranslation().clone(); + + Vector3f peSUBpc = pe.subtract(pc).normalizeLocal(); + Vector3f ptSUBpc = pt.subtract(pc).normalizeLocal(); + + float theta = FastMath.acos(peSUBpc.dot(ptSUBpc)); + Vector3f direction = peSUBpc.cross(ptSUBpc).normalizeLocal(); + bones[i].rotate(rotation.fromAngleAxis(theta, direction), frame); + } + error = pt.subtract(bones[0].getEndPoint()).length(); + ++iteration; + } + } + + for (CalculationBone bone : bones) { + bone.applyCalculatedTracks(); + } + +// System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); +// for (int i = 0; i < bones.length; ++i) { +// System.out.println(Arrays.toString(bones[i].track.getTranslations())); +// System.out.println(Arrays.toString(bones[i].track.getRotations())); +// System.out.println("==============================="); +// } + } catch(BlenderFileException e) { + LOGGER.severe(e.getLocalizedMessage()); + } + } + + /** + * This method returns bones used for rotation calculations. + * @param bone + * the bone to which the constraint is applied + * @param skeleton + * the skeleton owning the bone and its ancestors + * @param boneAnimation + * the bone animation data that stores the traces for the skeleton's bones + * @return a list of bones to imitate the bone's movement during IK solving + */ + private CalculationBone[] getBonesToCalculate(Bone bone, Skeleton skeleton, BoneAnimation boneAnimation) { + List bonesList = new ArrayList(); + Bone currentBone = bone; + do { + bonesList.add(new CalculationBone(currentBone, 1)); +// int boneIndex = skeleton.getBoneIndex(currentBone); +// for (int i = 0; i < boneAnimation.getTracks().length; ++i) { +// if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) { +// bonesList.add(new CalculationBone(currentBone, boneAnimation.getTracks()[i])); +// break; +// } +// } + currentBone = currentBone.getParent(); + } while (currentBone != null); + //attaching children + CalculationBone[] result = bonesList.toArray(new CalculationBone[bonesList.size()]); + for (int i = result.length - 1; i > 0; --i) { + result[i].attachChild(result[i - 1]); + } + return result; + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_KINEMATIC; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLike.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLike.java new file mode 100644 index 000000000..15a9c4d6d --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLike.java @@ -0,0 +1,87 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Vector3f; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Loc like' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintLocLike extends Constraint { + private static final int LOCLIKE_X = 0x01; + private static final int LOCLIKE_Y = 0x02; + private static final int LOCLIKE_Z = 0x04; + /* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */ + //protected static final int LOCLIKE_TIP = 0x08; + private static final int LOCLIKE_X_INVERT = 0x10; + private static final int LOCLIKE_Y_INVERT = 0x20; + private static final int LOCLIKE_Z_INVERT = 0x40; + private static final int LOCLIKE_OFFSET = 0x80; + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintLocLike(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation); + if (boneTrack != null) { + Vector3f targetLocation = this.getTargetLocation(); + int flag = ((Number) data.getFieldValue("flag")).intValue(); + Vector3f[] translations = boneTrack.getTranslations(); + int maxFrames = translations.length; + for (int frame = 0; frame < maxFrames; ++frame) { + Vector3f offset = Vector3f.ZERO; + if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original location to the copied location + offset = translations[frame].clone(); + } + + if ((flag & LOCLIKE_X) != 0) { + translations[frame].x = targetLocation.x; + if ((flag & LOCLIKE_X_INVERT) != 0) { + translations[frame].x = -translations[frame].x; + } + } else if ((flag & LOCLIKE_Y) != 0) { + translations[frame].y = targetLocation.y; + if ((flag & LOCLIKE_Y_INVERT) != 0) { + translations[frame].y = -translations[frame].y; + } + } else if ((flag & LOCLIKE_Z) != 0) { + translations[frame].z = targetLocation.z; + if ((flag & LOCLIKE_Z_INVERT) != 0) { + translations[frame].z = -translations[frame].z; + } + } + translations[frame].addLocal(offset);//TODO: ipo influence + } + boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales()); + } + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_LOCLIKE; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLimit.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLimit.java new file mode 100644 index 000000000..081e1bb51 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLocLimit.java @@ -0,0 +1,98 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Vector3f; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Loc limit' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintLocLimit extends Constraint { + private static final int LIMIT_XMIN = 0x01; + private static final int LIMIT_XMAX = 0x02; + private static final int LIMIT_YMIN = 0x04; + private static final int LIMIT_YMAX = 0x08; + private static final int LIMIT_ZMIN = 0x10; + private static final int LIMIT_ZMAX = 0x20; + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintLocLimit(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation); + if (boneTrack != null) { + int flag = ((Number) data.getFieldValue("flag")).intValue(); + Vector3f[] translations = boneTrack.getTranslations(); + int maxFrames = translations.length; + for (int frame = 0; frame < maxFrames; ++frame) { + float influence = ipo.calculateValue(frame); + if ((flag & LIMIT_XMIN) != 0) { + float xmin = ((Number) data.getFieldValue("xmin")).floatValue(); + if (translations[frame].x < xmin) { + translations[frame].x -= (translations[frame].x - xmin) * influence; + } + } + if ((flag & LIMIT_XMAX) != 0) { + float xmax = ((Number) data.getFieldValue("xmax")).floatValue(); + if (translations[frame].x > xmax) { + translations[frame].x -= (translations[frame].x - xmax) * influence; + } + } + if ((flag & LIMIT_YMIN) != 0) { + float ymin = ((Number) data.getFieldValue("ymin")).floatValue(); + if (translations[frame].y < ymin) { + translations[frame].y -= (translations[frame].y - ymin) * influence; + } + } + if ((flag & LIMIT_YMAX) != 0) { + float ymax = ((Number) data.getFieldValue("ymax")).floatValue(); + if (translations[frame].y > ymax) { + translations[frame].y -= (translations[frame].y - ymax) * influence; + } + } + if ((flag & LIMIT_ZMIN) != 0) { + float zmin = ((Number) data.getFieldValue("zmin")).floatValue(); + if (translations[frame].z < zmin) { + translations[frame].z -= (translations[frame].z - zmin) * influence; + } + } + if ((flag & LIMIT_ZMAX) != 0) { + float zmax = ((Number) data.getFieldValue("zmax")).floatValue(); + if (translations[frame].z > zmax) { + translations[frame].z -= (translations[frame].z - zmax) * influence; + } + }//TODO: consider constraint space !!! + } + boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales()); + } + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_LOCLIMIT; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLockTrack.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLockTrack.java new file mode 100644 index 000000000..89cec67c1 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintLockTrack.java @@ -0,0 +1,51 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Action' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintLockTrack extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintLockTrack.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintLockTrack(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) + throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Lock track' constraint + LOGGER.log(Level.WARNING, "'Lock track' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_LOCKTRACK; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintMinMax.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintMinMax.java new file mode 100644 index 000000000..699d0abf4 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintMinMax.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Min max' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintMinMax extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintMinMax.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintMinMax(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Min max' constraint + LOGGER.log(Level.WARNING, "'Min max' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_MINMAX; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintNull.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintNull.java new file mode 100644 index 000000000..cbe584fee --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintNull.java @@ -0,0 +1,44 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Null' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintNull extends Constraint { + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintNull(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) + throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) {} + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_NULL; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPython.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPython.java new file mode 100644 index 000000000..df90eb33b --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintPython.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Python' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintPython extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintPython.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintPython(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Python' constraint + LOGGER.log(Level.WARNING, "'Python' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_PYTHON; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRigidBodyJoint.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRigidBodyJoint.java new file mode 100644 index 000000000..bbb843a99 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRigidBodyJoint.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Rigid body joint' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintRigidBodyJoint extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintRigidBodyJoint.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintRigidBodyJoint(Structure constraintStructure, + Long boneOMA, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Rigid body joint' constraint + LOGGER.log(Level.WARNING, "'Rigid body joint' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_RIGIDBODYJOINT; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLike.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLike.java new file mode 100644 index 000000000..b77133123 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLike.java @@ -0,0 +1,88 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Quaternion; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Rot like' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintRotLike extends Constraint { + private static final int ROTLIKE_X = 0x01; + private static final int ROTLIKE_Y = 0x02; + private static final int ROTLIKE_Z = 0x04; + private static final int ROTLIKE_X_INVERT = 0x10; + private static final int ROTLIKE_Y_INVERT = 0x20; + private static final int ROTLIKE_Z_INVERT = 0x40; + private static final int ROTLIKE_OFFSET = 0x80; + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintRotLike(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation); + if (boneTrack != null) { + Quaternion targetRotation = this.getTargetRotation(); + int flag = ((Number) data.getFieldValue("flag")).intValue(); + float[] targetAngles = targetRotation.toAngles(null); + Quaternion[] rotations = boneTrack.getRotations(); + int maxFrames = rotations.length; + for (int frame = 0; frame < maxFrames; ++frame) { + float[] angles = rotations[frame].toAngles(null); + + Quaternion offset = Quaternion.IDENTITY; + if ((flag & ROTLIKE_OFFSET) != 0) {//we add the original rotation to the copied rotation + offset = rotations[frame].clone(); + } + + if ((flag & ROTLIKE_X) != 0) { + angles[0] = targetAngles[0]; + if ((flag & ROTLIKE_X_INVERT) != 0) { + angles[0] = -angles[0]; + } + } else if ((flag & ROTLIKE_Y) != 0) { + angles[1] = targetAngles[1]; + if ((flag & ROTLIKE_Y_INVERT) != 0) { + angles[1] = -angles[1]; + } + } else if ((flag & ROTLIKE_Z) != 0) { + angles[2] = targetAngles[2]; + if ((flag & ROTLIKE_Z_INVERT) != 0) { + angles[2] = -angles[2]; + } + } + rotations[frame].fromAngles(angles).multLocal(offset);//TODO: ipo influence + } + boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales()); + } + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_ROTLIKE; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java new file mode 100644 index 000000000..4df401d3e --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintRotLimit.java @@ -0,0 +1,95 @@ +package com.jme3.scene.plugins.blender.constraints; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.FastMath; +import com.jme3.math.Quaternion; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Rot limit' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintRotLimit extends Constraint { + private static final int LIMIT_XROT = 0x01; + private static final int LIMIT_YROT = 0x02; + private static final int LIMIT_ZROT = 0x04; + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintRotLimit(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation); + if (boneTrack != null) { + int flag = ((Number) data.getFieldValue("flag")).intValue(); + Quaternion[] rotations = boneTrack.getRotations(); + int maxFrames = rotations.length; + for (int frame = 0; frame < maxFrames; ++frame) { + float[] angles = rotations[frame].toAngles(null); + float influence = ipo.calculateValue(frame); + if ((flag & LIMIT_XROT) != 0) { + float xmin = ((Number) data.getFieldValue("xmin")).floatValue() * FastMath.DEG_TO_RAD; + float xmax = ((Number) data.getFieldValue("xmax")).floatValue() * FastMath.DEG_TO_RAD; + float difference = 0.0f; + if (angles[0] < xmin) { + difference = (angles[0] - xmin) * influence; + } else if (angles[0] > xmax) { + difference = (angles[0] - xmax) * influence; + } + angles[0] -= difference; + } + if ((flag & LIMIT_YROT) != 0) { + float ymin = ((Number) data.getFieldValue("ymin")).floatValue() * FastMath.DEG_TO_RAD; + float ymax = ((Number) data.getFieldValue("ymax")).floatValue() * FastMath.DEG_TO_RAD; + float difference = 0.0f; + if (angles[1] < ymin) { + difference = (angles[1] - ymin) * influence; + } else if (angles[1] > ymax) { + difference = (angles[1] - ymax) * influence; + } + angles[1] -= difference; + } + if ((flag & LIMIT_ZROT) != 0) { + float zmin = ((Number) data.getFieldValue("zmin")).floatValue() * FastMath.DEG_TO_RAD; + float zmax = ((Number) data.getFieldValue("zmax")).floatValue() * FastMath.DEG_TO_RAD; + float difference = 0.0f; + if (angles[2] < zmin) { + difference = (angles[2] - zmin) * influence; + } else if (angles[2] > zmax) { + difference = (angles[2] - zmax) * influence; + } + angles[2] -= difference; + } + rotations[frame].fromAngles(angles);//TODO: consider constraint space !!! + } + boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales()); + } + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_ROTLIMIT; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintShrinkWrap.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintShrinkWrap.java new file mode 100644 index 000000000..5b6dccdfe --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintShrinkWrap.java @@ -0,0 +1,100 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Shrink wrap' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintShrinkWrap extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintShrinkWrap.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintShrinkWrap(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + //loading mesh points (blender ensures that the target is a mesh-object) + List pts = new ArrayList(); + try { + Node node = (Node)this.getTarget(LoadedFeatureDataType.LOADED_FEATURE); + for(Spatial spatial : node.getChildren()) { + if(spatial instanceof Geometry) { + Mesh mesh = ((Geometry) spatial).getMesh(); + FloatBuffer floatBuffer = mesh.getFloatBuffer(Type.Position); + for(int i=0;i xmax) { + scales[frame].x -= (scales[frame].x - xmax) * influence; + } + } + if ((flag & LIMIT_YMIN) != 0) { + float ymin = ((Number) data.getFieldValue("ymin")).floatValue(); + if (scales[frame].y < ymin) { + scales[frame].y -= (scales[frame].y - ymin) * influence; + } + } + if ((flag & LIMIT_YMAX) != 0) { + float ymax = ((Number) data.getFieldValue("ymax")).floatValue(); + if (scales[frame].y > ymax) { + scales[frame].y -= (scales[frame].y - ymax) * influence; + } + } + if ((flag & LIMIT_ZMIN) != 0) { + float zmin = ((Number) data.getFieldValue("zmin")).floatValue(); + if (scales[frame].z < zmin) { + scales[frame].z -= (scales[frame].z - zmin) * influence; + } + } + if ((flag & LIMIT_ZMAX) != 0) { + float zmax = ((Number) data.getFieldValue("zmax")).floatValue(); + if (scales[frame].z > zmax) { + scales[frame].z -= (scales[frame].z - zmax) * influence; + } + }//TODO: consider constraint space !!! + } + boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), boneTrack.getRotations(), scales); + } + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_SIZELIMIT; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintStretchTo.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintStretchTo.java new file mode 100644 index 000000000..4c5825f3c --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintStretchTo.java @@ -0,0 +1,51 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Stretch to' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintStretchTo extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintStretchTo.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintStretchTo(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) + throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Stretch to' constraint + LOGGER.log(Level.WARNING, "'Stretch to' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_STRETCHTO; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransform.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransform.java new file mode 100644 index 000000000..5de071e01 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintTransform.java @@ -0,0 +1,50 @@ +package com.jme3.scene.plugins.blender.constraints; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.Skeleton; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; + +/** + * This class represents 'Transform' constraint type in blender. + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ConstraintTransform extends Constraint { + private static final Logger LOGGER = Logger.getLogger(ConstraintAction.class.getName()); + + /** + * This constructor creates the constraint instance. + * + * @param constraintStructure + * the constraint's structure (bConstraint clss in blender 2.49). + * @param boneOMA + * the old memory address of the constraint owner + * @param influenceIpo + * the ipo curve of the influence factor + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ConstraintTransform(Structure constraintStructure, Long boneOMA, + Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { + super(constraintStructure, boneOMA, influenceIpo, dataRepository); + } + + @Override + public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { + // TODO: implement 'Transform' constraint + LOGGER.log(Level.WARNING, "'Transform' constraint NOT implemented!"); + } + + @Override + public ConstraintType getType() { + return ConstraintType.CONSTRAINT_TYPE_TRANSFORM; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/ConstraintType.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintType.java similarity index 97% rename from engine/src/blender/com/jme3/scene/plugins/blender/structures/ConstraintType.java rename to engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintType.java index db486b52e..35c161bb6 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/ConstraintType.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/ConstraintType.java @@ -1,4 +1,4 @@ -package com.jme3.scene.plugins.blender.structures; +package com.jme3.scene.plugins.blender.constraints; import java.util.HashMap; import java.util.Map; diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/BezierCurve.java b/engine/src/blender/com/jme3/scene/plugins/blender/curves/BezierCurve.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/structures/BezierCurve.java rename to engine/src/blender/com/jme3/scene/plugins/blender/curves/BezierCurve.java index 9826d9a32..e4df671cb 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/BezierCurve.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/curves/BezierCurve.java @@ -1,11 +1,11 @@ -package com.jme3.scene.plugins.blender.structures; +package com.jme3.scene.plugins.blender.curves; import java.util.ArrayList; import java.util.List; import com.jme3.math.Vector3f; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.utils.DynamicArray; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.Structure; /** * A class that helps to calculate the bezier curves calues. It uses doubles for performing calculations to minimize diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/curves/CurvesHelper.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/curves/CurvesHelper.java index a331d5303..56347963d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/curves/CurvesHelper.java @@ -1,4 +1,4 @@ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.curves; import java.nio.FloatBuffer; import java.nio.IntBuffer; @@ -21,16 +21,17 @@ import com.jme3.math.Vector4f; import com.jme3.scene.Geometry; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer.Type; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.BezierCurve; -import com.jme3.scene.plugins.blender.structures.Properties; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.BlenderInputStream; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; +import com.jme3.scene.plugins.blender.meshes.MeshHelper; +import com.jme3.scene.plugins.blender.objects.Properties; import com.jme3.scene.shape.Curve; import com.jme3.scene.shape.Surface; import com.jme3.util.BufferUtils; @@ -604,4 +605,4 @@ public class CurvesHelper extends AbstractBlenderHelper { public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { return true; } -} +} \ No newline at end of file diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/exception/BlenderFileException.java b/engine/src/blender/com/jme3/scene/plugins/blender/exceptions/BlenderFileException.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/exception/BlenderFileException.java rename to engine/src/blender/com/jme3/scene/plugins/blender/exceptions/BlenderFileException.java index 378cedd1e..e0b40b3d6 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/exception/BlenderFileException.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/exceptions/BlenderFileException.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.exception; +package com.jme3.scene.plugins.blender.exceptions; /** * This exception is thrown when blend file data is somehow invalid. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderInputStream.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/BlenderInputStream.java similarity index 96% rename from engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderInputStream.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/BlenderInputStream.java index 71aa28dc6..e9660789d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderInputStream.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/BlenderInputStream.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.utils; +package com.jme3.scene.plugins.blender.file; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -39,7 +39,7 @@ import java.util.logging.Logger; import java.util.zip.GZIPInputStream; import com.jme3.asset.AssetManager; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; /** * An input stream with random access to data. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/data/DnaBlockData.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/DnaBlockData.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/data/DnaBlockData.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/DnaBlockData.java index 8f72f6d9f..ecb224cd7 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/data/DnaBlockData.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/DnaBlockData.java @@ -29,14 +29,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.data; +package com.jme3.scene.plugins.blender.file; import java.util.HashMap; import java.util.Map; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; /** * The data block containing the description of the file. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/DynamicArray.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/DynamicArray.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/utils/DynamicArray.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/DynamicArray.java index 20ed7e38d..3fff5a825 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/DynamicArray.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/DynamicArray.java @@ -29,9 +29,9 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.utils; +package com.jme3.scene.plugins.blender.file; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; /** * An array that can be dynamically modified/ diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/data/Field.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/Field.java similarity index 94% rename from engine/src/blender/com/jme3/scene/plugins/blender/data/Field.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/Field.java index 4823af7cd..a744b1520 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/data/Field.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/Field.java @@ -1,14 +1,11 @@ -package com.jme3.scene.plugins.blender.data; +package com.jme3.scene.plugins.blender.file; import java.util.ArrayList; import java.util.List; -import com.jme3.scene.plugins.blender.data.Structure.DataType; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure.DataType; /** * This class represents a single field in the structure. It can be either a primitive type or a table or a reference to diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/data/FileBlockHeader.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/FileBlockHeader.java similarity index 94% rename from engine/src/blender/com/jme3/scene/plugins/blender/data/FileBlockHeader.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/FileBlockHeader.java index cf6e5672c..91aa0b793 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/data/FileBlockHeader.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/FileBlockHeader.java @@ -29,11 +29,10 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.data; +package com.jme3.scene.plugins.blender.file; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; /** * A class that holds the header data of a file block. The file block itself is not implemented. This class holds its diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/Pointer.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/Pointer.java similarity index 94% rename from engine/src/blender/com/jme3/scene/plugins/blender/utils/Pointer.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/Pointer.java index 92d359555..1e718340d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/Pointer.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/Pointer.java @@ -29,14 +29,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.utils; +package com.jme3.scene.plugins.blender.file; import java.util.ArrayList; import java.util.List; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; /** * A class that represents a pointer of any level that can be stored in the file. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/data/Structure.java b/engine/src/blender/com/jme3/scene/plugins/blender/file/Structure.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/data/Structure.java rename to engine/src/blender/com/jme3/scene/plugins/blender/file/Structure.java index 070ac9e4b..ac8ebc815 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/data/Structure.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/file/Structure.java @@ -29,17 +29,15 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.data; +package com.jme3.scene.plugins.blender.file; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; /** * A class representing a single structure in the file. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ArmatureHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ArmatureHelper.java deleted file mode 100644 index ec01a5126..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ArmatureHelper.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.jme3.animation.BoneTrack; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.BezierCurve; -import com.jme3.scene.plugins.blender.structures.Ipo; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.Pointer; - -/** - * This class defines the methods to calculate certain aspects of animation and armature functionalities. - * @author Marcin Roguski - */ -public class ArmatureHelper extends com.jme3.scene.plugins.blender.helpers.v249.ArmatureHelper { - - private static final Logger LOGGER = Logger.getLogger(ArmatureHelper.class.getName()); - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ArmatureHelper(String blenderVersion) { - super(blenderVersion); - } - - @Override - public BoneTrack[] getTracks(Structure actionStructure, DataRepository dataRepository, String objectName, String animationName) throws BlenderFileException { - if (blenderVersion < 250) { - return super.getTracks(actionStructure, dataRepository, objectName, animationName); - } - LOGGER.log(Level.INFO, "Getting tracks!"); - int fps = dataRepository.getBlenderKey().getFps(); - int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, animationName); - Structure groups = (Structure) actionStructure.getFieldValue("groups"); - List actionGroups = groups.evaluateListBase(dataRepository);//bActionGroup - if (actionGroups != null && actionGroups.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) { - throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!"); - } - - List tracks = new ArrayList(); - for (Structure actionGroup : actionGroups) { - String name = actionGroup.getFieldValue("name").toString(); - Integer boneIndex = bonesMap.get(name); - if (boneIndex != null) { - List channels = ((Structure) actionGroup.getFieldValue("channels")).evaluateListBase(dataRepository); - BezierCurve[] bezierCurves = new BezierCurve[channels.size()]; - int channelCounter = 0; - for (Structure c : channels) { - //reading rna path first - BlenderInputStream bis = dataRepository.getInputStream(); - int currentPosition = bis.getPosition(); - Pointer pRnaPath = (Pointer) c.getFieldValue("rna_path"); - FileBlockHeader dataFileBlock = dataRepository.getFileBlock(pRnaPath.getOldMemoryAddress()); - bis.setPosition(dataFileBlock.getBlockPosition()); - String rnaPath = bis.readString(); - bis.setPosition(currentPosition); - int arrayIndex = ((Number) c.getFieldValue("array_index")).intValue(); - int type = this.getCurveType(rnaPath, arrayIndex); - - Pointer pBezTriple = (Pointer) c.getFieldValue("bezt"); - List bezTriples = pBezTriple.fetchData(dataRepository.getInputStream()); - bezierCurves[channelCounter++] = new BezierCurve(type, bezTriples, 2); - } - - Ipo ipo = new Ipo(bezierCurves); - tracks.add(ipo.calculateTrack(boneIndex.intValue(), animationFrames[0], animationFrames[1], fps)); - } - } - return tracks.toArray(new BoneTrack[tracks.size()]); - } - - /** - * This method parses the information stored inside the curve rna path and returns the proper type - * of the curve. - * @param rnaPath the curve's rna path - * @param arrayIndex the array index of the stored data - * @return the type of the curve - */ - protected int getCurveType(String rnaPath, int arrayIndex) { - if (rnaPath.endsWith(".location")) { - return Ipo.AC_LOC_X + arrayIndex; - } - if (rnaPath.endsWith(".rotation_quaternion")) { - return Ipo.AC_QUAT_W + arrayIndex; - } - if (rnaPath.endsWith(".scale")) { - return Ipo.AC_SIZE_X + arrayIndex; - } - throw new IllegalStateException("Unknown curve rna path: " + rnaPath); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/CameraHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/CameraHelper.java deleted file mode 100644 index 30829b079..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/CameraHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.jme3.renderer.Camera; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; - -/** - * A class that is used in light calculations. - * @author Marcin Roguski - */ -public class CameraHelper extends com.jme3.scene.plugins.blender.helpers.v249.CameraHelper { - - private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName()); - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public CameraHelper(String blenderVersion) { - super(blenderVersion); - } - - @Override - public Camera toCamera(Structure structure) throws BlenderFileException { - if (blenderVersion < 250) { - return super.toCamera(structure); - } - Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT); - int type = ((Number) structure.getFieldValue("type")).intValue(); - if (type != 0 && type != 1) { - LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type); - type = 0; - } - //type==0 - perspective; type==1 - orthographic; perspective is used as default - result.setParallelProjection(type == 1); - float aspect = 0; - float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); - float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); - if (type == 0) { - aspect = ((Number) structure.getFieldValue("lens")).floatValue(); - } else { - aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); - } - result.setFrustumPerspective(45, aspect, clipsta, clipend); - return result; - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ConstraintHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ConstraintHelper.java deleted file mode 100644 index d60da53ff..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ConstraintHelper.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers; - -import java.util.logging.Logger; - -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.DataRepository; - -/** - * This class should be used for constraint calculations. - * @author Marcin Roguski - */ -public class ConstraintHelper extends com.jme3.scene.plugins.blender.helpers.v249.ConstraintHelper { - - private static final Logger LOGGER = Logger.getLogger(ConstraintHelper.class.getName()); - - /** - * Helper constructor. It's main task is to generate the affection functions. These functions are common to all - * ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall - * consider refactoring. The constructor parses the given blender version and stores the result. Some - * functionalities may differ in different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ConstraintHelper(String blenderVersion, DataRepository dataRepository) { - super(blenderVersion, dataRepository); - } - - @Override - public void loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { - if (blenderVersion < 250) { - super.loadConstraints(objectStructure, dataRepository); - } else { - LOGGER.warning("Loading of constraints not yet implemented for version 2.5x !"); - //TODO: to implement - } - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/CurvesHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/CurvesHelper.java deleted file mode 100644 index cb4f42de9..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/CurvesHelper.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers; - -/** - * A class that is used in mesh calculations. - * @author Marcin Roguski - */ -public class CurvesHelper extends com.jme3.scene.plugins.blender.helpers.v249.CurvesHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public CurvesHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/IpoHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/IpoHelper.java deleted file mode 100644 index 96ab48aa3..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/IpoHelper.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers; - -/** - * This class helps to compute values from interpolation curves for features like animation or constraint influence. The - * curves are 3rd degree bezier curves. - * @author Marcin Roguski - */ -public class IpoHelper extends com.jme3.scene.plugins.blender.helpers.v249.IpoHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public IpoHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/LightHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/LightHelper.java deleted file mode 100644 index 8cdcf5bdd..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/LightHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -/** - * A class that is used in light calculations. - * @author Marcin Roguski - */ -public class LightHelper extends com.jme3.scene.plugins.blender.helpers.v249.LightHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public LightHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/MaterialHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/MaterialHelper.java deleted file mode 100644 index b2b117754..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/MaterialHelper.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -public class MaterialHelper extends com.jme3.scene.plugins.blender.helpers.v249.MaterialHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public MaterialHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/MeshHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/MeshHelper.java deleted file mode 100644 index 58b2e04b7..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/MeshHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -/** - * A class that is used in mesh calculations. - * @author Marcin Roguski - */ -public class MeshHelper extends com.jme3.scene.plugins.blender.helpers.v249.MeshHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public MeshHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ModifierHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ModifierHelper.java deleted file mode 100644 index 821c90790..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ModifierHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -/** - * A class that is used in modifiers calculations. - * @author Marcin Roguski - */ -public class ModifierHelper extends com.jme3.scene.plugins.blender.helpers.v249.ModifierHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ModifierHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/NoiseHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/NoiseHelper.java deleted file mode 100644 index babd416a6..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/NoiseHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * $Id: noise.c 14611 2008-04-29 08:24:33Z campbellbarton $ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - * - */ -package com.jme3.scene.plugins.blender.helpers; - -/** - * Methods of this class are copied from blender 2.49 source code and modified so that they can be used in java. They are mostly NOT - * documented because they are not documented in blender's source code. If I find a proper description or discover what they actually do and - * what parameters mean - I shall describe such methods :) If anyone have some hint what these methods are doing please rite the proper - * javadoc documentation. These methods should be used to create generated textures. - * - * @author Marcin Roguski (Kaelthas) - */ -public class NoiseHelper extends com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper { - - /** - * Constructor. Stores the blender version number and loads the constants needed for computations. - * - * @param blenderVersion - * the number of blender version - */ - public NoiseHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ObjectHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ObjectHelper.java deleted file mode 100644 index a735067c2..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ObjectHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -/** - * A class that is used in object calculations. - * @author Marcin Roguski - */ -public class ObjectHelper extends com.jme3.scene.plugins.blender.helpers.v249.ObjectHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ObjectHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ParticlesHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ParticlesHelper.java deleted file mode 100644 index 9993d757e..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/ParticlesHelper.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers; - -/** - * This class helps to import the special effects from blender file. - * @author Marcin Roguski (Kaelthas) - */ -public class ParticlesHelper extends com.jme3.scene.plugins.blender.helpers.v249.ParticlesHelper { - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ParticlesHelper(String blenderVersion) { - super(blenderVersion); - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/TextureHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/TextureHelper.java deleted file mode 100644 index a29801bd9..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/TextureHelper.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers; - -import java.util.logging.Logger; - -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.texture.Texture; - -/** - * A class that is used in texture calculations. - * @author Marcin Roguski - */ -public class TextureHelper extends com.jme3.scene.plugins.blender.helpers.v249.TextureHelper { - - private static final Logger LOGGER = Logger.getLogger(TextureHelper.class.getName()); - public static final int TEX_POINTDENSITY = 14; - public static final int TEX_VOXELDATA = 15; - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public TextureHelper(String blenderVersion) { - super(blenderVersion); - } - - @Override - public Texture getTexture(Structure tex, DataRepository dataRepository) throws BlenderFileException { - if (blenderVersion < 250) { - return super.getTexture(tex, dataRepository); - } - Texture result = (Texture) dataRepository.getLoadedFeature(tex.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE); - if (result != null) { - return result; - } - int type = ((Number) tex.getFieldValue("type")).intValue(); - switch (type) { - case TEX_POINTDENSITY: - LOGGER.warning("Point density texture loading currently not supported!"); - break; - case TEX_VOXELDATA: - LOGGER.warning("Voxel data texture loading currently not supported!"); - break; - default: - result = super.getTexture(tex, dataRepository); - } - return result; - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java deleted file mode 100644 index 1446bac63..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers.v249; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.jme3.asset.BlenderKey.FeaturesToLoad; -import com.jme3.renderer.Camera; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; - -/** - * A class that is used in light calculations. - * @author Marcin Roguski - */ -public class CameraHelper extends AbstractBlenderHelper { - - private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName()); - protected static final int DEFAULT_CAM_WIDTH = 100; - protected static final int DEFAULT_CAM_HEIGHT = 100; - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public CameraHelper(String blenderVersion) { - super(blenderVersion); - } - - /** - * This method reads the camera object. - * @param structure the structure containing the camera data - * @return the camera object - * @throws BlenderFileException - */ - public Camera toCamera(Structure structure) throws BlenderFileException { - Camera result = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT); - int type = ((Number) structure.getFieldValue("type")).intValue(); - if (type != 0 && type != 1) { - LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type); - type = 0; - } - //type==0 - perspective; type==1 - orthographic; perspective is used as default - result.setParallelProjection(type == 1); - float angle = ((Number) structure.getFieldValue("angle")).floatValue(); - float aspect = 0; - float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); - float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); - if (type == 0) { - aspect = ((Number) structure.getFieldValue("lens")).floatValue(); - } else { - aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); - } - result.setFrustumPerspective(angle, aspect, clipsta, clipend); - return result; - } - - @Override - public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { - return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0; - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java deleted file mode 100644 index 491d6161d..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java +++ /dev/null @@ -1,756 +0,0 @@ -package com.jme3.scene.plugins.blender.helpers.v249; - -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -import com.jme3.animation.Bone; -import com.jme3.animation.BoneAnimation; -import com.jme3.animation.BoneTrack; -import com.jme3.animation.Skeleton; -import com.jme3.math.FastMath; -import com.jme3.math.Quaternion; -import com.jme3.math.Transform; -import com.jme3.math.Vector3f; -import com.jme3.scene.Geometry; -import com.jme3.scene.Mesh; -import com.jme3.scene.Node; -import com.jme3.scene.Spatial; -import com.jme3.scene.VertexBuffer.Type; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.AbstractInfluenceFunction; -import com.jme3.scene.plugins.blender.structures.CalculationBone; -import com.jme3.scene.plugins.blender.structures.Constraint; -import com.jme3.scene.plugins.blender.structures.Constraint.Space; -import com.jme3.scene.plugins.blender.structures.ConstraintType; -import com.jme3.scene.plugins.blender.structures.Ipo; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.Pointer; - -/** - * This class should be used for constraint calculations. - * @author Marcin Roguski - */ -public class ConstraintHelper extends AbstractBlenderHelper { - - /** - * A table containing implementations of influence functions for constraints. It should contain functions for - * blender at least 249 and higher. - */ - protected static AbstractInfluenceFunction[] influenceFunctions; - /** - * Constraints stored for object with the given old memory address. - */ - protected Map constraints = new HashMap(); - - /** - * Helper constructor. It's main task is to generate the affection functions. These functions are common to all - * ConstraintHelper instances. Unfortunately this constructor might grow large. If it becomes too large - I shall - * consider refactoring. The constructor parses the given blender version and stores the result. Some - * functionalities may differ in different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ConstraintHelper(String blenderVersion, DataRepository dataRepository) { - super(blenderVersion); - this.initializeConstraintFunctions(dataRepository); - } - - /** - * This method initializes constraint functions for Blender 2.49. - * @param dataRepository - * the data repository - */ - private synchronized void initializeConstraintFunctions(DataRepository dataRepository) { - if (influenceFunctions == null) { - influenceFunctions = new AbstractInfluenceFunction[ConstraintType.getLastDefinedTypeValue() + 1]; - //ACTION constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_ACTION.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_ACTION, dataRepository) { - }; - - //CHILDOF constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_CHILDOF.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_CHILDOF, dataRepository) { - }; - - //CLAMPTO constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_CLAMPTO.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_CLAMPTO, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - this.validateConstraintType(constraint.getData()); - LOGGER.log(Level.INFO, "{0} not active! Curves not yet implemented!", constraint.getName());//TODO: implement when curves are implemented - } - }; - - //DISTLIMIT constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_DISTLIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_DISTLIMIT, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Structure constraintStructure = constraint.getData(); - this.validateConstraintType(constraintStructure); - Vector3f targetLocation = this.getTargetLocation(constraint); - BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint); - if (boneTrack != null) { - //TODO: target vertex group !!! - float dist = ((Number) constraintStructure.getFieldValue("dist")).floatValue(); - int mode = ((Number) constraintStructure.getFieldValue("mode")).intValue(); - - int maxFrames = boneTrack.getTimes().length; - Vector3f[] translations = boneTrack.getTranslations(); - for (int frame = 0; frame < maxFrames; ++frame) { - Vector3f v = translations[frame].subtract(targetLocation); - float currentDistance = v.length(); - float influence = constraint.getIpo().calculateValue(frame); - float modifier = 0.0f; - switch (mode) { - case LIMITDIST_INSIDE: - if (currentDistance >= dist) { - modifier = (dist - currentDistance) / currentDistance; - } - break; - case LIMITDIST_ONSURFACE: - modifier = (dist - currentDistance) / currentDistance; - break; - case LIMITDIST_OUTSIDE: - if (currentDistance <= dist) { - modifier = (dist - currentDistance) / currentDistance; - } - break; - default: - throw new IllegalStateException("Unknown distance limit constraint mode: " + mode); - } - translations[frame].addLocal(v.multLocal(modifier * influence)); - } - boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales()); - } - } - }; - - //FOLLOWPATH constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_FOLLOWPATH.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_FOLLOWPATH, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - this.validateConstraintType(constraint.getData()); - LOGGER.log(Level.INFO, "{0} not active! Curves not yet implemented!", constraint.getName());//TODO: implement when curves are implemented - } - }; - - //KINEMATIC constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_KINEMATIC.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_KINEMATIC, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - try { - Structure constraintStructure = constraint.getData(); - this.validateConstraintType(constraintStructure); - Long boneOMA = constraint.getBoneOMA(); - // IK solver is only attached to bones - Bone ownerBone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE); - - // get the target point - Object targetObject = this.getTarget(constraint, LoadedFeatureDataType.LOADED_FEATURE); - Vector3f pt = null;// Point Target - if (targetObject instanceof Bone) { - pt = ((Bone) targetObject).getModelSpacePosition(); - } else if (targetObject instanceof Node) { - pt = ((Node) targetObject).getWorldTranslation(); - } else if (targetObject instanceof Skeleton) { - Structure armatureNodeStructure = (Structure) this.getTarget(constraint, LoadedFeatureDataType.LOADED_STRUCTURE); - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - Transform transform = objectHelper.getTransformation(armatureNodeStructure, dataRepository); - pt = transform.getTranslation(); - } else { - throw new IllegalStateException( - "Unknown target object type! Should be Node, Bone or Skeleton and there is: " - + targetObject.getClass().getName()); - } - - //fetching the owner's bone track -// BoneTrack ownerBoneTrack = null; -// int boneIndex = skeleton.getBoneIndex(ownerBone); -// for (int i = 0; i < boneAnimation.getTracks().length; ++i) { -// if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) { -// ownerBoneTrack = boneAnimation.getTracks()[i]; -// break; -// } -// } -// int ownerBoneFramesCount = ownerBoneTrack==null ? 0 : ownerBoneTrack.getTimes().length; - - // preparing data - int maxIterations = ((Number) constraintStructure.getFieldValue("iterations")).intValue(); - CalculationBone[] bones = this.getBonesToCalculate(ownerBone, skeleton, boneAnimation); -// for (int i = 0; i < bones.length; ++i) { -// System.out.println(Arrays.toString(bones[i].track.getTranslations())); -// System.out.println(Arrays.toString(bones[i].track.getRotations())); -// System.out.println("==============================="); -// } - Quaternion rotation = new Quaternion(); - //all tracks should have the same amount of frames - int framesCount = bones[0].getBoneFramesCount(); - assert framesCount >=1; - for (int frame = 0; frame < framesCount; ++frame) { - float error = IK_SOLVER_ERROR; - int iteration = 0; - while (error >= IK_SOLVER_ERROR && iteration <= maxIterations) { - // rotating the bones - for (int i = 0; i < bones.length - 1; ++i) { - Vector3f pe = bones[i].getEndPoint(); - Vector3f pc = bones[i + 1].getWorldTranslation().clone(); - - Vector3f peSUBpc = pe.subtract(pc).normalizeLocal(); - Vector3f ptSUBpc = pt.subtract(pc).normalizeLocal(); - - float theta = FastMath.acos(peSUBpc.dot(ptSUBpc)); - Vector3f direction = peSUBpc.cross(ptSUBpc).normalizeLocal(); - bones[i].rotate(rotation.fromAngleAxis(theta, direction), frame); - } - error = pt.subtract(bones[0].getEndPoint()).length(); - ++iteration; - } - System.out.println("error = " + error + " iterations = " + iteration); - } - - for (CalculationBone bone : bones) { - bone.applyCalculatedTracks(); - } - -// System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); -// for (int i = 0; i < bones.length; ++i) { -// System.out.println(Arrays.toString(bones[i].track.getTranslations())); -// System.out.println(Arrays.toString(bones[i].track.getRotations())); -// System.out.println("==============================="); -// } - } catch(BlenderFileException e) { - LOGGER.severe(e.getLocalizedMessage()); - } - } - - /** - * This method returns bones used for rotation calculations. - * @param bone - * the bone to which the constraint is applied - * @param skeleton - * the skeleton owning the bone and its ancestors - * @param boneAnimation - * the bone animation data that stores the traces for the skeleton's bones - * @return a list of bones to imitate the bone's movement during IK solving - */ - private CalculationBone[] getBonesToCalculate(Bone bone, Skeleton skeleton, BoneAnimation boneAnimation) { - List bonesList = new ArrayList(); - Bone currentBone = bone; - do { - bonesList.add(new CalculationBone(currentBone, 1)); -// int boneIndex = skeleton.getBoneIndex(currentBone); -// for (int i = 0; i < boneAnimation.getTracks().length; ++i) { -// if (boneAnimation.getTracks()[i].getTargetBoneIndex() == boneIndex) { -// bonesList.add(new CalculationBone(currentBone, boneAnimation.getTracks()[i])); -// break; -// } -// } - currentBone = currentBone.getParent(); - } while (currentBone != null); - //attaching children - CalculationBone[] result = bonesList.toArray(new CalculationBone[bonesList.size()]); - for (int i = result.length - 1; i > 0; --i) { - result[i].attachChild(result[i - 1]); - } - return result; - } - }; - - //LOCKTRACK constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_LOCKTRACK.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_LOCKTRACK, dataRepository) { - }; - - //LOCLIKE constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_LOCLIKE.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_LOCLIKE, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Structure constraintData = constraint.getData(); - this.validateConstraintType(constraintData); - BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint); - if (boneTrack != null) { - Vector3f targetLocation = this.getTargetLocation(constraint); - int flag = ((Number) constraintData.getFieldValue("flag")).intValue(); - Vector3f[] translations = boneTrack.getTranslations(); - int maxFrames = translations.length; - for (int frame = 0; frame < maxFrames; ++frame) { - Vector3f offset = Vector3f.ZERO; - if ((flag & LOCLIKE_OFFSET) != 0) {//we add the original location to the copied location - offset = translations[frame].clone(); - } - - if ((flag & LOCLIKE_X) != 0) { - translations[frame].x = targetLocation.x; - if ((flag & LOCLIKE_X_INVERT) != 0) { - translations[frame].x = -translations[frame].x; - } - } else if ((flag & LOCLIKE_Y) != 0) { - translations[frame].y = targetLocation.y; - if ((flag & LOCLIKE_Y_INVERT) != 0) { - translations[frame].y = -translations[frame].y; - } - } else if ((flag & LOCLIKE_Z) != 0) { - translations[frame].z = targetLocation.z; - if ((flag & LOCLIKE_Z_INVERT) != 0) { - translations[frame].z = -translations[frame].z; - } - } - translations[frame].addLocal(offset);//TODO: ipo influence - } - boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales()); - } - } - }; - - //LOCLIMIT constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_LOCLIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_LOCLIMIT, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Structure constraintStructure = constraint.getData(); - this.validateConstraintType(constraintStructure); - BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint); - if (boneTrack != null) { - int flag = ((Number) constraintStructure.getFieldValue("flag")).intValue(); - Vector3f[] translations = boneTrack.getTranslations(); - int maxFrames = translations.length; - for (int frame = 0; frame < maxFrames; ++frame) { - float influence = constraint.getIpo().calculateValue(frame); - if ((flag & LIMIT_XMIN) != 0) { - float xmin = ((Number) constraintStructure.getFieldValue("xmin")).floatValue(); - if (translations[frame].x < xmin) { - translations[frame].x -= (translations[frame].x - xmin) * influence; - } - } - if ((flag & LIMIT_XMAX) != 0) { - float xmax = ((Number) constraintStructure.getFieldValue("xmax")).floatValue(); - if (translations[frame].x > xmax) { - translations[frame].x -= (translations[frame].x - xmax) * influence; - } - } - if ((flag & LIMIT_YMIN) != 0) { - float ymin = ((Number) constraintStructure.getFieldValue("ymin")).floatValue(); - if (translations[frame].y < ymin) { - translations[frame].y -= (translations[frame].y - ymin) * influence; - } - } - if ((flag & LIMIT_YMAX) != 0) { - float ymax = ((Number) constraintStructure.getFieldValue("ymax")).floatValue(); - if (translations[frame].y > ymax) { - translations[frame].y -= (translations[frame].y - ymax) * influence; - } - } - if ((flag & LIMIT_ZMIN) != 0) { - float zmin = ((Number) constraintStructure.getFieldValue("zmin")).floatValue(); - if (translations[frame].z < zmin) { - translations[frame].z -= (translations[frame].z - zmin) * influence; - } - } - if ((flag & LIMIT_ZMAX) != 0) { - float zmax = ((Number) constraintStructure.getFieldValue("zmax")).floatValue(); - if (translations[frame].z > zmax) { - translations[frame].z -= (translations[frame].z - zmax) * influence; - } - }//TODO: consider constraint space !!! - } - boneTrack.setKeyframes(boneTrack.getTimes(), translations, boneTrack.getRotations(), boneTrack.getScales()); - } - } - }; - - //MINMAX constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_MINMAX.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_MINMAX, dataRepository) { - }; - - //NULL constraint - does nothing - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_NULL.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_NULL, dataRepository) { - }; - - //PYTHON constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_PYTHON.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_PYTHON, dataRepository) { - }; - - //RIGIDBODYJOINT constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_RIGIDBODYJOINT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_RIGIDBODYJOINT, dataRepository) { - }; - - //ROTLIKE constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_ROTLIKE.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_ROTLIKE, dataRepository) { - - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Structure constraintData = constraint.getData(); - this.validateConstraintType(constraintData); - BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint); - if (boneTrack != null) { - Quaternion targetRotation = this.getTargetRotation(constraint); - int flag = ((Number) constraintData.getFieldValue("flag")).intValue(); - float[] targetAngles = targetRotation.toAngles(null); - Quaternion[] rotations = boneTrack.getRotations(); - int maxFrames = rotations.length; - for (int frame = 0; frame < maxFrames; ++frame) { - float[] angles = rotations[frame].toAngles(null); - - Quaternion offset = Quaternion.IDENTITY; - if ((flag & ROTLIKE_OFFSET) != 0) {//we add the original rotation to the copied rotation - offset = rotations[frame].clone(); - } - - if ((flag & ROTLIKE_X) != 0) { - angles[0] = targetAngles[0]; - if ((flag & ROTLIKE_X_INVERT) != 0) { - angles[0] = -angles[0]; - } - } else if ((flag & ROTLIKE_Y) != 0) { - angles[1] = targetAngles[1]; - if ((flag & ROTLIKE_Y_INVERT) != 0) { - angles[1] = -angles[1]; - } - } else if ((flag & ROTLIKE_Z) != 0) { - angles[2] = targetAngles[2]; - if ((flag & ROTLIKE_Z_INVERT) != 0) { - angles[2] = -angles[2]; - } - } - rotations[frame].fromAngles(angles).multLocal(offset);//TODO: ipo influence - } - boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales()); - } - } - }; - - //ROTLIMIT constraint - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_ROTLIMIT.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_ROTLIMIT, dataRepository) { - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Structure constraintStructure = constraint.getData(); - this.validateConstraintType(constraintStructure); - BoneTrack boneTrack = this.getBoneTrack(skeleton, boneAnimation, constraint); - if (boneTrack != null) { - int flag = ((Number) constraintStructure.getFieldValue("flag")).intValue(); - Quaternion[] rotations = boneTrack.getRotations(); - int maxFrames = rotations.length; - for (int frame = 0; frame < maxFrames; ++frame) { - float[] angles = rotations[frame].toAngles(null); - float influence = constraint.getIpo().calculateValue(frame); - if ((flag & LIMIT_XROT) != 0) { - float xmin = ((Number) constraintStructure.getFieldValue("xmin")).floatValue() * FastMath.DEG_TO_RAD; - float xmax = ((Number) constraintStructure.getFieldValue("xmax")).floatValue() * FastMath.DEG_TO_RAD; - float difference = 0.0f; - if (angles[0] < xmin) { - difference = (angles[0] - xmin) * influence; - } else if (angles[0] > xmax) { - difference = (angles[0] - xmax) * influence; - } - angles[0] -= difference; - } - if ((flag & LIMIT_YROT) != 0) { - float ymin = ((Number) constraintStructure.getFieldValue("ymin")).floatValue() * FastMath.DEG_TO_RAD; - float ymax = ((Number) constraintStructure.getFieldValue("ymax")).floatValue() * FastMath.DEG_TO_RAD; - float difference = 0.0f; - if (angles[1] < ymin) { - difference = (angles[1] - ymin) * influence; - } else if (angles[1] > ymax) { - difference = (angles[1] - ymax) * influence; - } - angles[1] -= difference; - } - if ((flag & LIMIT_ZROT) != 0) { - float zmin = ((Number) constraintStructure.getFieldValue("zmin")).floatValue() * FastMath.DEG_TO_RAD; - float zmax = ((Number) constraintStructure.getFieldValue("zmax")).floatValue() * FastMath.DEG_TO_RAD; - float difference = 0.0f; - if (angles[2] < zmin) { - difference = (angles[2] - zmin) * influence; - } else if (angles[2] > zmax) { - difference = (angles[2] - zmax) * influence; - } - angles[2] -= difference; - } - rotations[frame].fromAngles(angles);//TODO: consider constraint space !!! - } - boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), rotations, boneTrack.getScales()); - } - } - }; - - //SHRINKWRAP constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_SHRINKWRAP.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_SHRINKWRAP, dataRepository) { - @Override - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Structure constraintStructure = constraint.getData(); - this.validateConstraintType(constraintStructure); - - //loading mesh points (blender ensures that the target is a mesh-object) - List pts = new ArrayList(); - try { - Node node = (Node)this.getTarget(constraint, LoadedFeatureDataType.LOADED_FEATURE); - for(Spatial spatial : node.getChildren()) { - if(spatial instanceof Geometry) { - Mesh mesh = ((Geometry) spatial).getMesh(); - FloatBuffer floatBuffer = mesh.getFloatBuffer(Type.Position); - for(int i=0;i xmax) { - scales[frame].x -= (scales[frame].x - xmax) * influence; - } - } - if ((flag & LIMIT_YMIN) != 0) { - float ymin = ((Number) constraintStructure.getFieldValue("ymin")).floatValue(); - if (scales[frame].y < ymin) { - scales[frame].y -= (scales[frame].y - ymin) * influence; - } - } - if ((flag & LIMIT_YMAX) != 0) { - float ymax = ((Number) constraintStructure.getFieldValue("ymax")).floatValue(); - if (scales[frame].y > ymax) { - scales[frame].y -= (scales[frame].y - ymax) * influence; - } - } - if ((flag & LIMIT_ZMIN) != 0) { - float zmin = ((Number) constraintStructure.getFieldValue("zmin")).floatValue(); - if (scales[frame].z < zmin) { - scales[frame].z -= (scales[frame].z - zmin) * influence; - } - } - if ((flag & LIMIT_ZMAX) != 0) { - float zmax = ((Number) constraintStructure.getFieldValue("zmax")).floatValue(); - if (scales[frame].z > zmax) { - scales[frame].z -= (scales[frame].z - zmax) * influence; - } - }//TODO: consider constraint space !!! - } - boneTrack.setKeyframes(boneTrack.getTimes(), boneTrack.getTranslations(), boneTrack.getRotations(), scales); - } - } - }; - - //STRETCHTO constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_STRETCHTO.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_STRETCHTO, dataRepository) { - }; - - //TRANSFORM constraint (TODO: to implement) - influenceFunctions[ConstraintType.CONSTRAINT_TYPE_TRANSFORM.getConstraintId()] = new AbstractInfluenceFunction(ConstraintType.CONSTRAINT_TYPE_TRANSFORM, dataRepository) { - }; - } - } - - /** - * This method reads constraints for for the given structure. The constraints are loaded only once for object/bone. - * @param ownerOMA - * the owner's old memory address - * @param objectStructure - * the structure we read constraint's for - * @param dataRepository - * the data repository - * @throws BlenderFileException - */ - public void loadConstraints(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { - // reading influence ipos for the constraints - IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class); - Map> constraintsIpos = new HashMap>(); - Pointer pActions = (Pointer) objectStructure.getFieldValue("action"); - if (pActions.isNotNull()) { - List actions = pActions.fetchData(dataRepository.getInputStream()); - for (Structure action : actions) { - Structure chanbase = (Structure) action.getFieldValue("chanbase"); - List actionChannels = chanbase.evaluateListBase(dataRepository); - for (Structure actionChannel : actionChannels) { - Map ipos = new HashMap(); - Structure constChannels = (Structure) actionChannel.getFieldValue("constraintChannels"); - List constraintChannels = constChannels.evaluateListBase(dataRepository); - for (Structure constraintChannel : constraintChannels) { - Pointer pIpo = (Pointer) constraintChannel.getFieldValue("ipo"); - if (pIpo.isNotNull()) { - String constraintName = constraintChannel.getFieldValue("name").toString(); - Ipo ipo = ipoHelper.createIpo(pIpo.fetchData(dataRepository.getInputStream()).get(0), dataRepository); - ipos.put(constraintName, ipo); - } - } - String actionName = actionChannel.getFieldValue("name").toString(); - constraintsIpos.put(actionName, ipos); - } - } - } - - //loading constraints connected with the object's bones - List constraintsList = new ArrayList(); - Pointer pPose = (Pointer) objectStructure.getFieldValue("pose");//TODO: what if the object has two armatures ???? - if (pPose.isNotNull()) { - //getting pose channels - List poseChannels = ((Structure) pPose.fetchData(dataRepository.getInputStream()).get(0).getFieldValue("chanbase")).evaluateListBase(dataRepository); - for (Structure poseChannel : poseChannels) { - Long boneOMA = Long.valueOf(((Pointer) poseChannel.getFieldValue("bone")).getOldMemoryAddress()); - //the name is read directly from structure because bone might not yet be loaded - String name = dataRepository.getFileBlock(boneOMA).getStructure(dataRepository).getFieldValue("name").toString(); - List constraints = ((Structure) poseChannel.getFieldValue("constraints")).evaluateListBase(dataRepository); - for (Structure constraint : constraints) { - int type = ((Number) constraint.getFieldValue("type")).intValue(); - String constraintName = constraint.getFieldValue("name").toString(); - Map ipoMap = constraintsIpos.get(name); - Ipo ipo = ipoMap==null ? null : ipoMap.get(constraintName); - if (ipo == null) { - float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue(); - ipo = ipoHelper.createIpo(enforce); - } - Space ownerSpace = Space.valueOf(((Number) constraint.getFieldValue("ownspace")).byteValue()); - Space targetSpace = Space.valueOf(((Number) constraint.getFieldValue("tarspace")).byteValue()); - Constraint c = new Constraint(constraint, influenceFunctions[type], boneOMA, ownerSpace, targetSpace, ipo, dataRepository); - constraintsList.add(c); - } - } - } - // TODO: reading constraints for objects (implement when object's animation will be available) - List constraintChannels = ((Structure)objectStructure.getFieldValue("constraintChannels")).evaluateListBase(dataRepository); - for(Structure constraintChannel : constraintChannels) { - System.out.println(constraintChannel); - } - - //loading constraints connected with the object itself (TODO: test this) - if(!this.constraints.containsKey(objectStructure.getOldMemoryAddress())) { - List constraints = ((Structure)objectStructure.getFieldValue("constraints")).evaluateListBase(dataRepository); - Constraint[] result = new Constraint[constraints.size()]; - int i = 0; - - for(Structure constraint : constraints) { - int type = ((Number)constraint.getFieldValue("type")).intValue(); - String constraintName = constraint.getFieldValue("name").toString(); - String objectName = objectStructure.getName(); - - Map objectConstraintsIpos = constraintsIpos.get(objectName); - Ipo ipo = objectConstraintsIpos!=null ? objectConstraintsIpos.get(constraintName) : null; - if (ipo == null) { - float enforce = ((Number) constraint.getFieldValue("enforce")).floatValue(); - ipo = ipoHelper.createIpo(enforce); - } - Space ownerSpace = Space.valueOf(((Number) constraint.getFieldValue("ownspace")).byteValue()); - Space targetSpace = Space.valueOf(((Number) constraint.getFieldValue("tarspace")).byteValue()); - result[i++] = new Constraint(constraint, influenceFunctions[type], null, - ownerSpace, targetSpace, ipo, dataRepository);//TODO: influence ipos for object animation - } - this.constraints.put(objectStructure.getOldMemoryAddress(), result); - } - - if (constraintsList.size() > 0) { - this.constraints.put(objectStructure.getOldMemoryAddress(), constraintsList.toArray(new Constraint[constraintsList.size()])); - } - } - - /** - * This method returns a list of constraints of the feature's constraints. The order of constraints is important. - * @param ownerOMA - * the owner's old memory address - * @return a table of constraints for the feature specified by old memory address - */ - public Constraint[] getConstraints(Long ownerOMA) { - return constraints.get(ownerOMA); - } - - @Override - public void clearState() { - constraints.clear(); - } - - @Override - public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { - return true; - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java deleted file mode 100644 index e05e22da7..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.helpers.v249; - -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.jme3.animation.AnimControl; -import com.jme3.animation.Bone; -import com.jme3.animation.BoneAnimation; -import com.jme3.animation.BoneTrack; -import com.jme3.animation.Skeleton; -import com.jme3.animation.SkeletonControl; -import com.jme3.bounding.BoundingBox; -import com.jme3.bounding.BoundingSphere; -import com.jme3.bounding.BoundingVolume; -import com.jme3.effect.ParticleEmitter; -import com.jme3.effect.shapes.EmitterMeshVertexShape; -import com.jme3.effect.shapes.EmitterShape; -import com.jme3.material.Material; -import com.jme3.math.Matrix4f; -import com.jme3.math.Transform; -import com.jme3.math.Vector3f; -import com.jme3.scene.Geometry; -import com.jme3.scene.Mesh; -import com.jme3.scene.Node; -import com.jme3.scene.Spatial; -import com.jme3.scene.VertexBuffer.Type; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.helpers.ParticlesHelper; -import com.jme3.scene.plugins.blender.structures.Constraint; -import com.jme3.scene.plugins.blender.structures.Ipo; -import com.jme3.scene.plugins.blender.structures.Modifier; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; -import com.jme3.scene.plugins.ogre.AnimData; -import com.jme3.scene.shape.Curve; - -/** - * A class that is used in modifiers calculations. - * @author Marcin Roguski - */ -public class ModifierHelper extends AbstractBlenderHelper { - - private static final Logger LOGGER = Logger.getLogger(ModifierHelper.class.getName()); - - /** - * This constructor parses the given blender version and stores the result. Some functionalities may differ in - * different blender versions. - * @param blenderVersion - * the version read from the blend file - */ - public ModifierHelper(String blenderVersion) { - super(blenderVersion); - } - - /** - * This method applies modifier to the object. - * @param node - * the loaded object - * @param modifier - * the modifier to apply - * @param dataRepository - * the data repository - * @return the node to whom the modifier was applied - */ - public Node applyModifier(Node node, Modifier modifier, DataRepository dataRepository) { - if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) { - return this.applyArmatureModifierData(node, modifier, dataRepository); - } else if (Modifier.OBJECT_ANIMATION_MODIFIER_DATA.equals(modifier.getType())) { - return this.applyObjectAnimationModifier(node, modifier, dataRepository); - } else if (Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) { - return this.applyArrayModifierData(node, modifier, dataRepository); - } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) { - return this.applyParticleSystemModifierData(node, modifier, dataRepository); - } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifier.getType())) { - return this.applyMirrorModifierData(node, modifier, dataRepository); - } else { - LOGGER.log(Level.WARNING, "Modifier: {0} not yet implemented!!!", modifier.getType()); - return node; - } - } - - /** - * This method reads the given object's modifiers. - * @param objectStructure - * the object structure - * @param dataRepository - * the data repository - * @param converter - * the converter object (in some cases we need to read an object first before loading the modifier) - * @throws BlenderFileException - * this exception is thrown when the blender file is somehow corrupted - */ - @SuppressWarnings("unchecked") - public void readModifiers(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { - Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers"); - List modifiers = modifiersListBase.evaluateListBase(dataRepository); - for (Structure modifier : modifiers) { - Object loadedModifier = null; - Object modifierAdditionalData = null; - if (Modifier.ARRAY_MODIFIER_DATA.equals(modifier.getType())) {// ****************ARRAY MODIFIER - Map params = new HashMap(); - - Number fittype = (Number) modifier.getFieldValue("fit_type"); - params.put("fittype", fittype); - switch (fittype.intValue()) { - case 0:// FIXED COUNT - params.put("count", modifier.getFieldValue("count")); - break; - case 1:// FIXED LENGTH - params.put("length", modifier.getFieldValue("length")); - break; - case 2:// FITCURVE - Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob"); - float length = 0; - if (pCurveOb.isNotNull()) { - Structure curveStructure = pCurveOb.fetchData(dataRepository.getInputStream()).get(0); - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - Node curveObject = (Node) objectHelper.toObject(curveStructure, dataRepository); - Set 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); - } - } - } - } - } - params.put("length", Float.valueOf(length)); - params.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH - break; - default: - assert false : "Unknown array modifier fit type: " + fittype; - } - - // offset parameters - int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue(); - if ((offsettype & 0x01) != 0) {// Constant offset - DynamicArray offsetArray = (DynamicArray) modifier.getFieldValue("offset"); - float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()}; - params.put("offset", offset); - } - if ((offsettype & 0x02) != 0) {// Relative offset - DynamicArray scaleArray = (DynamicArray) modifier.getFieldValue("scale"); - float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()}; - params.put("scale", scale); - } - if ((offsettype & 0x04) != 0) {// Object offset - Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob"); - if (pOffsetObject.isNotNull()) { - params.put("offsetob", pOffsetObject); - } - } - - // start cap and end cap - Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap"); - if (pStartCap.isNotNull()) { - params.put("startcap", pStartCap); - } - Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap"); - if (pEndCap.isNotNull()) { - params.put("endcap", pEndCap); - } - loadedModifier = params; - } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifier.getType())) {// ****************MIRROR MODIFIER - Map params = new HashMap(); - - params.put("flag", modifier.getFieldValue("flag")); - params.put("tolerance", modifier.getFieldValue("tolerance")); - Pointer pMirrorOb = (Pointer) modifier.getFieldValue("mirror_ob"); - if (pMirrorOb.isNotNull()) { - params.put("mirrorob", pMirrorOb); - } - loadedModifier = params; - } else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifier.getType())) {// ****************ARMATURE MODIFIER - Pointer pArmatureObject = (Pointer) modifier.getFieldValue("object"); - if (pArmatureObject.isNotNull()) { - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - Structure armatureObject = (Structure) dataRepository.getLoadedFeature(pArmatureObject.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_STRUCTURE); - if (armatureObject == null) {// we check this first not to fetch the structure unnecessary - armatureObject = pArmatureObject.fetchData(dataRepository.getInputStream()).get(0); - objectHelper.toObject(armatureObject, dataRepository); - } - modifierAdditionalData = armatureObject.getOldMemoryAddress(); - ArmatureHelper armatureHelper = dataRepository.getHelper(ArmatureHelper.class); - - // changing bones matrices so that they fit the current object (that is why we need a copy of a skeleton) - Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); - Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); - Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); - Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); - - //setting the bones structure inside the skeleton (thus completing its loading) - Skeleton skeleton = new Skeleton(bones); - dataRepository.addLoadedFeatures(armatureObject.getOldMemoryAddress(), armatureObject.getName(), armatureObject, skeleton); - - String objectName = objectStructure.getName(); - Set animationNames = dataRepository.getBlenderKey().getAnimationNames(objectName); - if (animationNames != null && animationNames.size() > 0) { - ArrayList animations = new ArrayList(); - List actionHeaders = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); - for (FileBlockHeader header : actionHeaders) { - Structure actionStructure = header.getStructure(dataRepository); - String actionName = actionStructure.getName(); - if (animationNames.contains(actionName)) { - int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, actionName); - int fps = dataRepository.getBlenderKey().getFps(); - float start = (float) animationFrames[0] / (float) fps; - float stop = (float) animationFrames[1] / (float) fps; - BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); - boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, dataRepository, objectName, actionName)); - animations.add(boneAnimation); - } - } - loadedModifier = new AnimData(new Skeleton(bones), animations); - } - } else { - LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifier.getType()); - } - } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {// ****************PARTICLES MODIFIER - Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys"); - if (pParticleSystem.isNotNull()) { - ParticlesHelper particlesHelper = dataRepository.getHelper(ParticlesHelper.class); - Structure particleSystem = pParticleSystem.fetchData(dataRepository.getInputStream()).get(0); - loadedModifier = particlesHelper.toParticleEmitter(particleSystem, dataRepository); - } - } - // adding modifier to the modifier's lists - if (loadedModifier != null) { - dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier.getType(), loadedModifier, modifierAdditionalData); - modifierAdditionalData = null; - } - } - - //at the end read object's animation modifier - Modifier objectAnimationModifier = this.readObjectAnimation(objectStructure, dataRepository); - if (objectAnimationModifier != null) { - dataRepository.addModifier(objectStructure.getOldMemoryAddress(), - objectAnimationModifier.getType(), - objectAnimationModifier.getJmeModifierRepresentation(), - objectAnimationModifier.getAdditionalData()); - } - } - - /** - * This method reads animation of the object itself (without bones) and stores it as an ArmatureModifierData - * modifier. The animation is returned as a modifier. It should be later applied regardless other modifiers. The - * reason for this is that object may not have modifiers added but it's animation should be working. - * @param objectStructure - * the structure of the object - * @param dataRepository - * the data repository - * @return animation modifier is returned, it should be separately applied when the object is loaded - * @throws BlenderFileException - * this exception is thrown when the blender file is somehow corrupted - */ - protected Modifier readObjectAnimation(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { - Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo"); - if (pIpo.isNotNull()) { - //check if there is an action name connected with this ipo - String objectAnimationName = null; - List actionBlocks = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); - for (FileBlockHeader actionBlock : actionBlocks) { - Structure action = actionBlock.getStructure(dataRepository); - List actionChannels = ((Structure) action.getFieldValue("chanbase")).evaluateListBase(dataRepository); - if (actionChannels.size() == 1) {//object's animtion action has only one channel - Pointer pChannelIpo = (Pointer) actionChannels.get(0).getFieldValue("ipo"); - if (pChannelIpo.equals(pIpo)) { - objectAnimationName = action.getName(); - break; - } - } - } - - String objectName = objectStructure.getName(); - if (objectAnimationName == null) {//set the object's animation name to object's name - objectAnimationName = objectName; - } - - IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class); - Structure ipoStructure = pIpo.fetchData(dataRepository.getInputStream()).get(0); - Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository); - int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, objectAnimationName); - if (animationFrames == null) {//if the name was created here there are no frames set for the animation - animationFrames = new int[]{1, ipo.getLastFrame()}; - } - int fps = dataRepository.getBlenderKey().getFps(); - float start = (float) animationFrames[0] / (float) fps; - float stop = (float) animationFrames[1] / (float) fps; - - //calculating track for the only bone in this skeleton - BoneTrack[] tracks = new BoneTrack[1]; - tracks[0] = ipo.calculateTrack(0, animationFrames[0], animationFrames[1], fps); - - BoneAnimation boneAnimation = new BoneAnimation(objectAnimationName, stop - start); - boneAnimation.setTracks(tracks); - ArrayList animations = new ArrayList(1); - animations.add(boneAnimation); - - //preparing the object's bone - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - Transform t = objectHelper.getTransformation(objectStructure, dataRepository); - Bone bone = new Bone(null); - bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale()); - - return new Modifier(Modifier.OBJECT_ANIMATION_MODIFIER_DATA, new AnimData(new Skeleton(new Bone[]{bone}), animations), objectStructure.getOldMemoryAddress()); - } - return null; - } - - /** - * This method applies particles emitter to the given node. - * @param node - * the particles emitter node - * @param modifier - * the modifier containing the emitter data - * @param dataRepository - * the data repository - * @return node with particles' emitter applied - */ - protected Node applyParticleSystemModifierData(Node node, Modifier modifier, DataRepository dataRepository) { - MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class); - ParticleEmitter emitter = (ParticleEmitter) modifier.getJmeModifierRepresentation(); - emitter = emitter.clone(); - - // veryfying the alpha function for particles' texture - Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE; - char nameSuffix = emitter.getName().charAt(emitter.getName().length() - 1); - if (nameSuffix == 'B' || nameSuffix == 'N') { - alphaFunction = MaterialHelper.ALPHA_MASK_NONE; - } - // removing the type suffix from the name - emitter.setName(emitter.getName().substring(0, emitter.getName().length() - 1)); - - // applying emitter shape - EmitterShape emitterShape = emitter.getShape(); - List meshes = new ArrayList(); - for (Spatial spatial : node.getChildren()) { - if (spatial instanceof Geometry) { - Mesh mesh = ((Geometry) spatial).getMesh(); - if (mesh != null) { - meshes.add(mesh); - Material material = materialHelper.getParticlesMaterial(((Geometry) spatial).getMaterial(), alphaFunction, dataRepository); - emitter.setMaterial(material);// TODO: divide into several pieces - } - } - } - if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) { - ((EmitterMeshVertexShape) emitterShape).setMeshes(meshes); - } - - node.attachChild(emitter); - return node; - } - - /** - * This method applies ArmatureModifierData to the loaded object. - * @param node - * the loaded object - * @param modifier - * the modifier to apply - * @param dataRepository - * the data repository - * @return the node to whom the modifier was applied - */ - protected Node applyArmatureModifierData(Node node, Modifier modifier, DataRepository dataRepository) { - AnimData ad = (AnimData) modifier.getJmeModifierRepresentation(); - ArrayList animList = ad.anims; - Long modifierArmatureObject = (Long) modifier.getAdditionalData(); - if (animList != null && animList.size() > 0) { - ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class); - Constraint[] constraints = constraintHelper.getConstraints(modifierArmatureObject); - HashMap anims = new HashMap(); - for (int i = 0; i < animList.size(); ++i) { - BoneAnimation boneAnimation = animList.get(i).clone(); - - // baking constraints into animations - if (constraints != null && constraints.length > 0) { - for (Constraint constraint : constraints) { - constraint.affectAnimation(ad.skeleton, boneAnimation); - } - } - - anims.put(boneAnimation.getName(), boneAnimation); - } - - // getting meshes - Mesh[] meshes = null; - List meshesList = new ArrayList(); - List children = node.getChildren(); - for (Spatial child : children) { - if (child instanceof Geometry) { - meshesList.add(((Geometry) child).getMesh()); - } - } - if (meshesList.size() > 0) { - meshes = meshesList.toArray(new Mesh[meshesList.size()]); - } - - // applying the control to the node - SkeletonControl skeletonControl = new SkeletonControl(meshes, ad.skeleton); - AnimControl control = node.getControl(AnimControl.class); - - if (control == null) { - control = new AnimControl(ad.skeleton); - } else { - // merging skeletons - Skeleton controlSkeleton = control.getSkeleton(); - int boneIndexIncrease = controlSkeleton.getBoneCount(); - Skeleton skeleton = this.merge(controlSkeleton, ad.skeleton); - - // merging animations - HashMap animations = new HashMap(); - for (String animationName : control.getAnimationNames()) { - animations.put(animationName, control.getAnim(animationName)); - } - for (Entry animEntry : anims.entrySet()) { - BoneAnimation ba = animEntry.getValue(); - for (int i = 0; i < ba.getTracks().length; ++i) { - BoneTrack bt = ba.getTracks()[i]; - int newBoneIndex = bt.getTargetBoneIndex() + boneIndexIncrease; - ba.getTracks()[i] = new BoneTrack(newBoneIndex, bt.getTimes(), bt.getTranslations(), bt.getRotations(), bt.getScales()); - } - animations.put(animEntry.getKey(), animEntry.getValue()); - } - - // replacing the control - node.removeControl(control); - control = new AnimControl(skeleton); - } - control.setAnimations(anims); - node.addControl(control); - node.addControl(skeletonControl); - } - return node; - } - - protected Node applyObjectAnimationModifier(Node node, Modifier modifier, DataRepository dataRepository) { - AnimData ad = (AnimData) modifier.getJmeModifierRepresentation(); - - // TODO: Why is this line here? Why is this needed? - // Remove if necessary. - //ad.skeleton.getBone(0).setAttachNode(node); - - return this.applyArmatureModifierData(node, modifier, dataRepository); - } - - /** - * This method applies the array modifier to the node. - * @param node - * the object the modifier will be applied to - * @param modifier - * the modifier to be applied - * @param dataRepository - * the data repository - * @return object node with array modifier applied - */ - @SuppressWarnings("unchecked") - protected Node applyArrayModifierData(Node node, Modifier modifier, DataRepository dataRepository) { - Map modifierData = (Map) modifier.getJmeModifierRepresentation(); - int fittype = ((Number) modifierData.get("fittype")).intValue(); - float[] offset = (float[]) modifierData.get("offset"); - if (offset == null) {// the node will be repeated several times in the same place - offset = new float[]{0.0f, 0.0f, 0.0f}; - } - float[] scale = (float[]) modifierData.get("scale"); - if (scale == null) {// the node will be repeated several times in the same place - scale = new float[]{0.0f, 0.0f, 0.0f}; - } else { - // getting bounding box - node.updateModelBound(); - BoundingVolume boundingVolume = node.getWorldBound(); - if (boundingVolume instanceof BoundingBox) { - scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f; - scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f; - scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f; - } else if (boundingVolume instanceof BoundingSphere) { - float radius = ((BoundingSphere) boundingVolume).getRadius(); - scale[0] *= radius * 2.0f; - scale[1] *= radius * 2.0f; - scale[2] *= radius * 2.0f; - } else { - throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName()); - } - } - - // adding object's offset - float[] objectOffset = new float[]{0.0f, 0.0f, 0.0f}; - Pointer pOffsetObject = (Pointer) modifierData.get("offsetob"); - if (pOffsetObject != null) { - FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress()); - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - try {// we take the structure in case the object was not yet loaded - Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository); - Vector3f translation = objectHelper.getTransformation(offsetStructure, dataRepository).getTranslation(); - objectOffset[0] = translation.x; - objectOffset[1] = translation.y; - objectOffset[2] = translation.z; - } catch (BlenderFileException e) { - LOGGER.log(Level.WARNING, "Problems in blender file structure! Object offset cannot be applied! The problem: {0}", e.getMessage()); - } - } - - // getting start and end caps - Node[] caps = new Node[]{null, null}; - Pointer[] pCaps = new Pointer[]{(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")}; - for (int i = 0; i < pCaps.length; ++i) { - if (pCaps[i] != null) { - caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE); - if (caps[i] != null) { - caps[i] = (Node) caps[i].clone(); - } else { - FileBlockHeader capBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress()); - try {// we take the structure in case the object was not yet loaded - Structure capStructure = capBlock.getStructure(dataRepository); - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository); - if (caps[i] == null) { - LOGGER.log(Level.WARNING, "Cap object ''{0}'' couldn''t be loaded!", capStructure.getName()); - } - } catch (BlenderFileException e) { - LOGGER.log(Level.WARNING, "Problems in blender file structure! Cap object cannot be applied! The problem: {0}", e.getMessage()); - } - } - } - } - - Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0], offset[1] + scale[1] + objectOffset[1], offset[2] + scale[2] + objectOffset[2]); - - // getting/calculating repeats amount - int count = 0; - if (fittype == 0) {// Fixed count - count = ((Number) modifierData.get("count")).intValue() - 1; - } else if (fittype == 1) {// Fixed length - float length = ((Number) modifierData.get("length")).floatValue(); - if (translationVector.length() > 0.0f) { - count = (int) (length / translationVector.length()) - 1; - } - } else if (fittype == 2) {// Fit curve - throw new IllegalStateException("Fit curve should be transformed to Fixed Length array type!"); - } else { - throw new IllegalStateException("Unknown fit type: " + fittype); - } - - // adding translated nodes and caps - if (count > 0) { - Node[] arrayNodes = new Node[count]; - Vector3f newTranslation = new Vector3f(); - for (int i = 0; i < count; ++i) { - newTranslation.addLocal(translationVector); - Node nodeClone = (Node) node.clone(); - nodeClone.setLocalTranslation(newTranslation); - arrayNodes[i] = nodeClone; - } - for (Node nodeClone : arrayNodes) { - node.attachChild(nodeClone); - } - if (caps[0] != null) { - caps[0].getLocalTranslation().set(node.getLocalTranslation()).subtractLocal(translationVector); - node.attachChild(caps[0]); - } - if (caps[1] != null) { - caps[1].getLocalTranslation().set(newTranslation).addLocal(translationVector); - node.attachChild(caps[1]); - } - } - return node; - } - - /** - * This method applies the mirror modifier to the node. - * @param node - * the object the modifier will be applied to - * @param modifier - * the modifier to be applied - * @param dataRepository - * the data repository - * @return object node with mirror modifier applied - */ - @SuppressWarnings("unchecked") - protected Node applyMirrorModifierData(Node node, Modifier modifier, DataRepository dataRepository) { - Map modifierData = (Map) modifier.getJmeModifierRepresentation(); - int flag = ((Number) modifierData.get("flag")).intValue(); - float[] mirrorFactor = new float[]{ - (flag & 0x08) != 0 ? -1.0f : 1.0f, - (flag & 0x10) != 0 ? -1.0f : 1.0f, - (flag & 0x20) != 0 ? -1.0f : 1.0f - }; - float[] center = new float[]{0.0f, 0.0f, 0.0f}; - Pointer pObject = (Pointer) modifierData.get("mirrorob"); - if (pObject != null) { - Structure objectStructure; - try { - objectStructure = pObject.fetchData(dataRepository.getInputStream()).get(0); - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - Node object = (Node) objectHelper.toObject(objectStructure, dataRepository); - if (object != null) { - Vector3f translation = object.getWorldTranslation(); - center[0] = translation.x; - center[1] = translation.y; - center[2] = translation.z; - } - } catch (BlenderFileException e) { - LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage()); - } - } - float tolerance = ((Number) modifierData.get("tolerance")).floatValue(); - boolean mirrorU = (flag & 0x01) != 0; - boolean mirrorV = (flag & 0x02) != 0; -// boolean mirrorVGroup = (flag & 0x20) != 0; - - List geometriesToAdd = new ArrayList(); - for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) { - if (mirrorFactor[mirrorIndex] == -1.0f) { - for (Spatial spatial : node.getChildren()) { - if (spatial instanceof Geometry) { - Mesh mesh = ((Geometry) spatial).getMesh(); - Mesh clone = mesh.deepClone(); - - // getting buffers - FloatBuffer position = mesh.getFloatBuffer(Type.Position); - FloatBuffer bindPosePosition = mesh.getFloatBuffer(Type.BindPosePosition); - - FloatBuffer clonePosition = clone.getFloatBuffer(Type.Position); - FloatBuffer cloneBindPosePosition = clone.getFloatBuffer(Type.BindPosePosition); - FloatBuffer cloneNormals = clone.getFloatBuffer(Type.Normal); - FloatBuffer cloneBindPoseNormals = clone.getFloatBuffer(Type.BindPoseNormal); - IntBuffer cloneIndexes = (IntBuffer) clone.getBuffer(Type.Index).getData(); - - // modyfying data - for (int i = mirrorIndex; i < clonePosition.limit(); i += 3) { - float value = clonePosition.get(i); - float d = center[mirrorIndex] - value; - - if (Math.abs(d) <= tolerance) { - clonePosition.put(i, center[mirrorIndex]); - cloneBindPosePosition.put(i, center[mirrorIndex]); - position.put(i, center[mirrorIndex]); - bindPosePosition.put(i, center[mirrorIndex]); - } else { - clonePosition.put(i, value + 2.0f * d); - cloneBindPosePosition.put(i, value + 2.0f * d); - } - cloneNormals.put(i, -cloneNormals.get(i)); - cloneBindPoseNormals.put(i, -cloneNormals.get(i)); - - //modifying clone indexes - int vertexIndex = (i - mirrorIndex) / 3; - if (vertexIndex % 3 == 0 && vertexIndex bones = new ArrayList(s1.getBoneCount() + s2.getBoneCount()); - for (int i = 0; i < s1.getBoneCount(); ++i) { - bones.add(s1.getBone(i)); - } - for (int i = 1; i < s2.getBoneCount(); ++i) {// ommit objectAnimationBone - bones.add(s2.getBone(i)); - } - return new Skeleton(bones.toArray(new Bone[bones.size()])); - } - - @Override - public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { - return true; - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/LightHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/lights/LightHelper.java similarity index 89% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/LightHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/lights/LightHelper.java index a02b2abbe..de456779d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/LightHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/lights/LightHelper.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.lights; import java.util.logging.Level; import java.util.logging.Logger; @@ -39,11 +39,11 @@ import com.jme3.light.DirectionalLight; import com.jme3.light.Light; import com.jme3.light.PointLight; import com.jme3.math.ColorRGBA; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Structure; /** * A class that is used in light calculations. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java index 26d898f54..aad4aebdd 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.materials; import java.nio.ByteBuffer; import java.util.HashMap; @@ -48,13 +48,14 @@ import com.jme3.material.RenderState.BlendMode; import com.jme3.material.RenderState.FaceCullMode; import com.jme3.math.ColorRGBA; import com.jme3.math.FastMath; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.textures.TextureHelper; import com.jme3.shader.VarType; import com.jme3.texture.Image; import com.jme3.texture.Image.Format; diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java index 7029b999b..46ce3dd9c 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.meshes; import java.nio.ByteBuffer; import java.nio.FloatBuffer; @@ -57,14 +57,17 @@ import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer.Format; import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Usage; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.Properties; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.ArmatureHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; +import com.jme3.scene.plugins.blender.objects.Properties; +import com.jme3.scene.plugins.blender.textures.TextureHelper; import com.jme3.texture.Texture; import com.jme3.util.BufferUtils; @@ -465,7 +468,7 @@ public class MeshHelper extends AbstractBlenderHelper { * @param vertices * a list of vertices read from the blender file */ - protected void addNormal(Vector3f normalToAdd, Map normalMap, boolean smooth, Vector3f... vertices) { + public void addNormal(Vector3f normalToAdd, Map normalMap, boolean smooth, Vector3f... vertices) { for (Vector3f v : vertices) { Vector3f n = normalMap.get(v); if (!smooth || n == null) { 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 new file mode 100644 index 000000000..1d6ed472a --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java @@ -0,0 +1,216 @@ +package com.jme3.scene.plugins.blender.modifiers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import com.jme3.animation.AnimControl; +import com.jme3.animation.Bone; +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.animation.SkeletonControl; +import com.jme3.math.Matrix4f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.ArmatureHelper; +import com.jme3.scene.plugins.blender.constraints.Constraint; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; +import com.jme3.scene.plugins.ogre.AnimData; + +/** + * This modifier allows to add bone animation to the object. + * + * @author Marcin Roguski (Kaelthas) + */ +/* package */class ArmatureModifier extends Modifier { + + /** + * This constructor is only temporary. It will be removed when object + * animation is implemented in jme. TODO!!!!!!! + */ + /* package */ArmatureModifier() { + } + + /** + * This constructor reads animation data from the object structore. The + * stored data is the AnimData and additional data is armature's OMA. + * + * @param objectStructure + * the structure of the object + * @param modifierStructure + * the structure of the modifier + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ArmatureModifier(Structure objectStructure, Structure modifierStructure, DataRepository dataRepository) throws BlenderFileException { + Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); + if (pArmatureObject.isNotNull()) { + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + Structure armatureObject = (Structure) dataRepository.getLoadedFeature(pArmatureObject.getOldMemoryAddress(), + LoadedFeatureDataType.LOADED_STRUCTURE); + if (armatureObject == null) {// we check this first not to fetch the + // structure unnecessary + armatureObject = pArmatureObject.fetchData(dataRepository.getInputStream()).get(0); + objectHelper.toObject(armatureObject, dataRepository); + } + additionalData = armatureObject.getOldMemoryAddress(); + ArmatureHelper armatureHelper = dataRepository + .getHelper(ArmatureHelper.class); + + // changing bones matrices so that they fit the current object (that + // is why we need a copy of a skeleton) + Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); + Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); + Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); + Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); + + // setting the bones structure inside the skeleton (thus completing + // its loading) + Skeleton skeleton = new Skeleton(bones); + dataRepository.addLoadedFeatures(armatureObject.getOldMemoryAddress(), armatureObject.getName(), armatureObject, skeleton); + + String objectName = objectStructure.getName(); + Set animationNames = dataRepository.getBlenderKey().getAnimationNames(objectName); + if (animationNames != null && animationNames.size() > 0) { + ArrayList animations = new ArrayList(); + List actionHeaders = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); + for (FileBlockHeader header : actionHeaders) { + Structure actionStructure = header.getStructure(dataRepository); + String actionName = actionStructure.getName(); + if (animationNames.contains(actionName)) { + int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, actionName); + int fps = dataRepository.getBlenderKey().getFps(); + float start = (float) animationFrames[0] / (float) fps; + float stop = (float) animationFrames[1] / (float) fps; + BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); + boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, dataRepository, objectName, actionName)); + animations.add(boneAnimation); + } + } + jmeModifierRepresentation = new AnimData(new Skeleton(bones), animations); + } + } + } + + @Override + public Node apply(Node node, DataRepository dataRepository) { + if(jmeModifierRepresentation == null) { + return node; + } + AnimData ad = (AnimData) jmeModifierRepresentation; + ArrayList animList = ad.anims; + Long modifierArmatureObject = (Long) additionalData; + if (animList != null && animList.size() > 0) { + List constraints = dataRepository.getConstraints(modifierArmatureObject); + HashMap anims = new HashMap(); + for (int i = 0; i < animList.size(); ++i) { + BoneAnimation boneAnimation = animList.get(i).clone(); + + // baking constraints into animations + if (constraints != null && constraints.size() > 0) { + for (Constraint constraint : constraints) { + constraint.affectAnimation(ad.skeleton, boneAnimation); + } + } + + anims.put(boneAnimation.getName(), boneAnimation); + } + + // getting meshes + Mesh[] meshes = null; + List meshesList = new ArrayList(); + List children = node.getChildren(); + for (Spatial child : children) { + if (child instanceof Geometry) { + meshesList.add(((Geometry) child).getMesh()); + } + } + if (meshesList.size() > 0) { + meshes = meshesList.toArray(new Mesh[meshesList.size()]); + } + + // applying the control to the node + SkeletonControl skeletonControl = new SkeletonControl(meshes, ad.skeleton); + AnimControl control = node.getControl(AnimControl.class); + + if (control == null) { + control = new AnimControl(ad.skeleton); + } else { + // merging skeletons + Skeleton controlSkeleton = control.getSkeleton(); + int boneIndexIncrease = controlSkeleton.getBoneCount(); + Skeleton skeleton = this.merge(controlSkeleton, ad.skeleton); + + // merging animations + HashMap animations = new HashMap(); + for (String animationName : control.getAnimationNames()) { + animations.put(animationName, + control.getAnim(animationName)); + } + for (Entry animEntry : anims.entrySet()) { + BoneAnimation ba = animEntry.getValue(); + for (int i = 0; i < ba.getTracks().length; ++i) { + BoneTrack bt = ba.getTracks()[i]; + int newBoneIndex = bt.getTargetBoneIndex() + + boneIndexIncrease; + ba.getTracks()[i] = new BoneTrack(newBoneIndex, + bt.getTimes(), bt.getTranslations(), + bt.getRotations(), bt.getScales()); + } + animations.put(animEntry.getKey(), animEntry.getValue()); + } + + // replacing the control + node.removeControl(control); + control = new AnimControl(skeleton); + } + control.setAnimations(anims); + node.addControl(control); + node.addControl(skeletonControl); + } + return node; + } + + @Override + public String getType() { + return Modifier.ARMATURE_MODIFIER_DATA; + } + + /** + * This method merges two skeletons into one. I assume that each skeleton's + * 0-indexed bone is objectAnimationBone so only one such bone should be + * placed in the result + * + * @param s1 + * first skeleton + * @param s2 + * second skeleton + * @return merged skeleton + */ + protected Skeleton merge(Skeleton s1, Skeleton s2) { + List bones = new ArrayList(s1.getBoneCount() + + s2.getBoneCount()); + for (int i = 0; i < s1.getBoneCount(); ++i) { + bones.add(s1.getBone(i)); + } + for (int i = 1; i < s2.getBoneCount(); ++i) {// ommit + // objectAnimationBone + bones.add(s2.getBone(i)); + } + return new Skeleton(bones.toArray(new Bone[bones.size()])); + } +} 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 new file mode 100644 index 000000000..0f285a0e6 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java @@ -0,0 +1,244 @@ +package com.jme3.scene.plugins.blender.modifiers; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; +import com.jme3.bounding.BoundingVolume; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; +import com.jme3.scene.shape.Curve; + +/** + * This modifier allows to array modifier to the object. + * + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class ArrayModifier extends Modifier { + private static final Logger LOGGER = Logger.getLogger(ArrayModifier.class.getName()); + + /** + * This constructor reads array data from the modifier structure. The + * stored data is a map of parameters for array modifier. No additional data + * is loaded. + * + * @param objectStructure + * the structure of the object + * @param modifierStructure + * the structure of the modifier + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + @SuppressWarnings("unchecked") + public ArrayModifier(Structure modifier, DataRepository dataRepository) throws BlenderFileException { + Map params = new HashMap(); + + Number fittype = (Number) modifier.getFieldValue("fit_type"); + params.put("fittype", fittype); + switch (fittype.intValue()) { + case 0:// FIXED COUNT + params.put("count", modifier.getFieldValue("count")); + break; + case 1:// FIXED LENGTH + params.put("length", modifier.getFieldValue("length")); + break; + case 2:// FITCURVE + Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob"); + float length = 0; + if (pCurveOb.isNotNull()) { + Structure curveStructure = pCurveOb.fetchData(dataRepository.getInputStream()).get(0); + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + Node curveObject = (Node) objectHelper.toObject(curveStructure, dataRepository); + Set 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); + } + } + } + } + } + params.put("length", Float.valueOf(length)); + params.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH + break; + default: + assert false : "Unknown array modifier fit type: " + fittype; + } + + // offset parameters + int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue(); + if ((offsettype & 0x01) != 0) {// Constant offset + DynamicArray offsetArray = (DynamicArray) modifier.getFieldValue("offset"); + float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()}; + params.put("offset", offset); + } + if ((offsettype & 0x02) != 0) {// Relative offset + DynamicArray scaleArray = (DynamicArray) modifier.getFieldValue("scale"); + float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()}; + params.put("scale", scale); + } + if ((offsettype & 0x04) != 0) {// Object offset + Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob"); + if (pOffsetObject.isNotNull()) { + params.put("offsetob", pOffsetObject); + } + } + + // start cap and end cap + Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap"); + if (pStartCap.isNotNull()) { + params.put("startcap", pStartCap); + } + Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap"); + if (pEndCap.isNotNull()) { + params.put("endcap", pEndCap); + } + jmeModifierRepresentation = params; + } + + @Override + @SuppressWarnings("unchecked") + public Node apply(Node node, DataRepository dataRepository) { + Map modifierData = (Map) jmeModifierRepresentation; + int fittype = ((Number) modifierData.get("fittype")).intValue(); + float[] offset = (float[]) modifierData.get("offset"); + if (offset == null) {// the node will be repeated several times in the same place + offset = new float[]{0.0f, 0.0f, 0.0f}; + } + float[] scale = (float[]) modifierData.get("scale"); + if (scale == null) {// the node will be repeated several times in the same place + scale = new float[]{0.0f, 0.0f, 0.0f}; + } else { + // getting bounding box + node.updateModelBound(); + BoundingVolume boundingVolume = node.getWorldBound(); + if (boundingVolume instanceof BoundingBox) { + scale[0] *= ((BoundingBox) boundingVolume).getXExtent() * 2.0f; + scale[1] *= ((BoundingBox) boundingVolume).getYExtent() * 2.0f; + scale[2] *= ((BoundingBox) boundingVolume).getZExtent() * 2.0f; + } else if (boundingVolume instanceof BoundingSphere) { + float radius = ((BoundingSphere) boundingVolume).getRadius(); + scale[0] *= radius * 2.0f; + scale[1] *= radius * 2.0f; + scale[2] *= radius * 2.0f; + } else { + throw new IllegalStateException("Unknown bounding volume type: " + boundingVolume.getClass().getName()); + } + } + + // adding object's offset + float[] objectOffset = new float[]{0.0f, 0.0f, 0.0f}; + Pointer pOffsetObject = (Pointer) modifierData.get("offsetob"); + if (pOffsetObject != null) { + FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress()); + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + try {// we take the structure in case the object was not yet loaded + Structure offsetStructure = offsetObjectBlock.getStructure(dataRepository); + Vector3f translation = objectHelper.getTransformation(offsetStructure, dataRepository).getTranslation(); + objectOffset[0] = translation.x; + objectOffset[1] = translation.y; + objectOffset[2] = translation.z; + } catch (BlenderFileException e) { + LOGGER.log(Level.WARNING, "Problems in blender file structure! Object offset cannot be applied! The problem: {0}", e.getMessage()); + } + } + + // getting start and end caps + Node[] caps = new Node[]{null, null}; + Pointer[] pCaps = new Pointer[]{(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")}; + for (int i = 0; i < pCaps.length; ++i) { + if (pCaps[i] != null) { + caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE); + if (caps[i] != null) { + caps[i] = (Node) caps[i].clone(); + } else { + FileBlockHeader capBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress()); + try {// we take the structure in case the object was not yet loaded + Structure capStructure = capBlock.getStructure(dataRepository); + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository); + if (caps[i] == null) { + LOGGER.log(Level.WARNING, "Cap object ''{0}'' couldn''t be loaded!", capStructure.getName()); + } + } catch (BlenderFileException e) { + LOGGER.log(Level.WARNING, "Problems in blender file structure! Cap object cannot be applied! The problem: {0}", e.getMessage()); + } + } + } + } + + Vector3f translationVector = new Vector3f(offset[0] + scale[0] + objectOffset[0], offset[1] + scale[1] + objectOffset[1], offset[2] + scale[2] + objectOffset[2]); + + // getting/calculating repeats amount + int count = 0; + if (fittype == 0) {// Fixed count + count = ((Number) modifierData.get("count")).intValue() - 1; + } else if (fittype == 1) {// Fixed length + float length = ((Number) modifierData.get("length")).floatValue(); + if (translationVector.length() > 0.0f) { + count = (int) (length / translationVector.length()) - 1; + } + } else if (fittype == 2) {// Fit curve + throw new IllegalStateException("Fit curve should be transformed to Fixed Length array type!"); + } else { + throw new IllegalStateException("Unknown fit type: " + fittype); + } + + // adding translated nodes and caps + if (count > 0) { + Node[] arrayNodes = new Node[count]; + Vector3f newTranslation = new Vector3f(); + for (int i = 0; i < count; ++i) { + newTranslation.addLocal(translationVector); + Node nodeClone = (Node) node.clone(); + nodeClone.setLocalTranslation(newTranslation); + arrayNodes[i] = nodeClone; + } + for (Node nodeClone : arrayNodes) { + node.attachChild(nodeClone); + } + if (caps[0] != null) { + caps[0].getLocalTranslation().set(node.getLocalTranslation()).subtractLocal(translationVector); + node.attachChild(caps[0]); + } + if (caps[1] != null) { + caps[1].getLocalTranslation().set(newTranslation).addLocal(translationVector); + node.attachChild(caps[1]); + } + } + return node; + } + + @Override + public String getType() { + return ARRAY_MODIFIER_DATA; + } +} 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 new file mode 100644 index 000000000..0107cb8a5 --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java @@ -0,0 +1,170 @@ +package com.jme3.scene.plugins.blender.modifiers; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; + +/** + * This modifier allows to array modifier to the object. + * + * @author Marcin Roguski (Kaelthas) + */ +/*package*/ class MirrorModifier extends Modifier { + private static final Logger LOGGER = Logger.getLogger(MirrorModifier.class.getName()); + + /** + * This constructor reads mirror data from the modifier structure. The + * stored data is a map of parameters for mirror modifier. No additional data + * is loaded. + * When the modifier is applied it is necessary to get the newly created node. + * + * @param objectStructure + * the structure of the object + * @param modifierStructure + * the structure of the modifier + * @param dataRepository + * the data repository + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public MirrorModifier(Structure modifier, DataRepository dataRepository) { + Map params = new HashMap(); + + params.put("flag", modifier.getFieldValue("flag")); + params.put("tolerance", modifier.getFieldValue("tolerance")); + Pointer pMirrorOb = (Pointer) modifier.getFieldValue("mirror_ob"); + if (pMirrorOb.isNotNull()) { + params.put("mirrorob", pMirrorOb); + } + jmeModifierRepresentation = params; + } + + @Override + @SuppressWarnings("unchecked") + public Node apply(Node node, DataRepository dataRepository) { + Map modifierData = (Map) jmeModifierRepresentation; + int flag = ((Number) modifierData.get("flag")).intValue(); + float[] mirrorFactor = new float[]{ + (flag & 0x08) != 0 ? -1.0f : 1.0f, + (flag & 0x10) != 0 ? -1.0f : 1.0f, + (flag & 0x20) != 0 ? -1.0f : 1.0f + }; + float[] center = new float[]{0.0f, 0.0f, 0.0f}; + Pointer pObject = (Pointer) modifierData.get("mirrorob"); + if (pObject != null) { + Structure objectStructure; + try { + objectStructure = pObject.fetchData(dataRepository.getInputStream()).get(0); + ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); + Node object = (Node) objectHelper.toObject(objectStructure, dataRepository); + if (object != null) { + Vector3f translation = object.getWorldTranslation(); + center[0] = translation.x; + center[1] = translation.y; + center[2] = translation.z; + } + } catch (BlenderFileException e) { + LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage()); + } + } + float tolerance = ((Number) modifierData.get("tolerance")).floatValue(); + boolean mirrorU = (flag & 0x01) != 0; + boolean mirrorV = (flag & 0x02) != 0; +// boolean mirrorVGroup = (flag & 0x20) != 0; + + List geometriesToAdd = new ArrayList(); + for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) { + if (mirrorFactor[mirrorIndex] == -1.0f) { + for (Spatial spatial : node.getChildren()) { + if (spatial instanceof Geometry) { + Mesh mesh = ((Geometry) spatial).getMesh(); + Mesh clone = mesh.deepClone(); + + // getting buffers + FloatBuffer position = mesh.getFloatBuffer(Type.Position); + FloatBuffer bindPosePosition = mesh.getFloatBuffer(Type.BindPosePosition); + + FloatBuffer clonePosition = clone.getFloatBuffer(Type.Position); + FloatBuffer cloneBindPosePosition = clone.getFloatBuffer(Type.BindPosePosition); + FloatBuffer cloneNormals = clone.getFloatBuffer(Type.Normal); + FloatBuffer cloneBindPoseNormals = clone.getFloatBuffer(Type.BindPoseNormal); + IntBuffer cloneIndexes = (IntBuffer) clone.getBuffer(Type.Index).getData(); + + // modyfying data + for (int i = mirrorIndex; i < clonePosition.limit(); i += 3) { + float value = clonePosition.get(i); + float d = center[mirrorIndex] - value; + + if (Math.abs(d) <= tolerance) { + clonePosition.put(i, center[mirrorIndex]); + cloneBindPosePosition.put(i, center[mirrorIndex]); + position.put(i, center[mirrorIndex]); + bindPosePosition.put(i, center[mirrorIndex]); + } else { + clonePosition.put(i, value + 2.0f * d); + cloneBindPosePosition.put(i, value + 2.0f * d); + } + cloneNormals.put(i, -cloneNormals.get(i)); + cloneBindPoseNormals.put(i, -cloneNormals.get(i)); + + //modifying clone indexes + int vertexIndex = (i - mirrorIndex) / 3; + if (vertexIndex % 3 == 0 && vertexIndex readModifiers(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { + Collection result = new ArrayList(); + Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers"); + List modifiers = modifiersListBase.evaluateListBase(dataRepository); + for (Structure modifierStructure : modifiers) { + Modifier modifier = null; + if (Modifier.ARRAY_MODIFIER_DATA.equals(modifierStructure.getType())) { + modifier = new ArrayModifier(modifierStructure, dataRepository); + } else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifierStructure.getType())) { + modifier = new MirrorModifier(modifierStructure, dataRepository); + } else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifierStructure.getType())) { + modifier = new ArmatureModifier(objectStructure, modifierStructure, dataRepository); + } else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifierStructure.getType())) { + modifier = new ParticlesModifier(modifierStructure, dataRepository); + } + + if(modifier != null) { + result.add(modifier); + dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier); + } else { + LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifierStructure.getType()); + } + } + + //at the end read object's animation modifier + Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo"); + if (pIpo.isNotNull()) { + Modifier modifier = new ObjectAnimationModifier(objectStructure, dataRepository); + result.add(modifier); + dataRepository.addModifier(objectStructure.getOldMemoryAddress(), modifier); + } + return result; + } + + @Override + public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) { + return true; + } +} 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 new file mode 100644 index 000000000..75c64510d --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java @@ -0,0 +1,122 @@ +package com.jme3.scene.plugins.blender.modifiers; + +import java.util.ArrayList; +import java.util.List; + +import com.jme3.animation.Bone; +import com.jme3.animation.BoneAnimation; +import com.jme3.animation.BoneTrack; +import com.jme3.animation.Skeleton; +import com.jme3.math.Transform; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.animations.Ipo; +import com.jme3.scene.plugins.blender.animations.IpoHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.objects.ObjectHelper; +import com.jme3.scene.plugins.ogre.AnimData; + +/** + * This modifier allows to add animation to the object. + * + * @author Marcin Roguski (Kaelthas) + */ +/* package */class ObjectAnimationModifier extends ArmatureModifier { + + /** + * This constructor reads animation of the object itself (without bones) and + * stores it as an ArmatureModifierData modifier. The animation is returned + * as a modifier. It should be later applied regardless other modifiers. The + * reason for this is that object may not have modifiers added but it's + * animation should be working. The stored modifier is an anim data and + * additional data is given object's OMA. + * + * @param objectStructure + * the structure of the object + * @param dataRepository + * the data repository + * @return animation modifier is returned, it should be separately applied + * when the object is loaded + * @throws BlenderFileException + * this exception is thrown when the blender file is somehow + * corrupted + */ + public ObjectAnimationModifier(Structure objectStructure, + DataRepository dataRepository) throws BlenderFileException { + Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo"); + if (pIpo.isNotNull()) { + // check if there is an action name connected with this ipo + String objectAnimationName = null; + List actionBlocks = dataRepository + .getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); + for (FileBlockHeader actionBlock : actionBlocks) { + Structure action = actionBlock.getStructure(dataRepository); + List actionChannels = ((Structure) action + .getFieldValue("chanbase")) + .evaluateListBase(dataRepository); + if (actionChannels.size() == 1) {// object's animtion action has + // only one channel + Pointer pChannelIpo = (Pointer) actionChannels.get(0) + .getFieldValue("ipo"); + if (pChannelIpo.equals(pIpo)) { + objectAnimationName = action.getName(); + break; + } + } + } + + String objectName = objectStructure.getName(); + if (objectAnimationName == null) {// set the object's animation name + // to object's name + objectAnimationName = objectName; + } + + IpoHelper ipoHelper = dataRepository.getHelper(IpoHelper.class); + Structure ipoStructure = pIpo.fetchData( + dataRepository.getInputStream()).get(0); + Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository); + int[] animationFrames = dataRepository.getBlenderKey() + .getAnimationFrames(objectName, objectAnimationName); + if (animationFrames == null) {// if the name was created here there + // are no frames set for the + // animation + animationFrames = new int[] { 1, ipo.getLastFrame() }; + } + int fps = dataRepository.getBlenderKey().getFps(); + float start = (float) animationFrames[0] / (float) fps; + float stop = (float) animationFrames[1] / (float) fps; + + // calculating track for the only bone in this skeleton + BoneTrack[] tracks = new BoneTrack[1]; + tracks[0] = ipo.calculateTrack(0, animationFrames[0], + animationFrames[1], fps); + + BoneAnimation boneAnimation = new BoneAnimation( + objectAnimationName, stop - start); + boneAnimation.setTracks(tracks); + ArrayList animations = new ArrayList( + 1); + animations.add(boneAnimation); + + // preparing the object's bone + ObjectHelper objectHelper = dataRepository + .getHelper(ObjectHelper.class); + Transform t = objectHelper.getTransformation(objectStructure, + dataRepository); + Bone bone = new Bone(null); + bone.setBindTransforms(t.getTranslation(), t.getRotation(), + t.getScale()); + + jmeModifierRepresentation = new AnimData(new Skeleton( + new Bone[] { bone }), animations); + additionalData = objectStructure.getOldMemoryAddress(); + } + } + + @Override + public String getType() { + return Modifier.OBJECT_ANIMATION_MODIFIER_DATA; + } +} 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 new file mode 100644 index 000000000..e0f417b1e --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java @@ -0,0 +1,99 @@ +package com.jme3.scene.plugins.blender.modifiers; + +import java.util.ArrayList; +import java.util.List; + +import com.jme3.effect.ParticleEmitter; +import com.jme3.effect.shapes.EmitterMeshVertexShape; +import com.jme3.effect.shapes.EmitterShape; +import com.jme3.material.Material; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; +import com.jme3.scene.plugins.blender.particles.ParticlesHelper; + +/** + * This modifier allows to add particles to the object. + * + * @author Marcin Roguski (Kaelthas) + */ +/* package */class ParticlesModifier extends Modifier { + + /** + * This constructor reads the particles system structure and stores it in + * order to apply it later to the node. + * + * @param modifier + * the structure of the modifier + * @param dataRepository + * the data repository + * @throws BlenderFileException + * an exception is throw wneh there are problems with the + * blender file + */ + public ParticlesModifier(Structure modifier, DataRepository dataRepository) + throws BlenderFileException { + Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys"); + if (pParticleSystem.isNotNull()) { + ParticlesHelper particlesHelper = dataRepository + .getHelper(ParticlesHelper.class); + Structure particleSystem = pParticleSystem.fetchData( + dataRepository.getInputStream()).get(0); + jmeModifierRepresentation = particlesHelper.toParticleEmitter( + particleSystem, dataRepository); + } + } + + @Override + public Node apply(Node node, DataRepository dataRepository) { + MaterialHelper materialHelper = dataRepository + .getHelper(MaterialHelper.class); + ParticleEmitter emitter = (ParticleEmitter) jmeModifierRepresentation; + emitter = emitter.clone(); + + // veryfying the alpha function for particles' texture + Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE; + char nameSuffix = emitter.getName().charAt( + emitter.getName().length() - 1); + if (nameSuffix == 'B' || nameSuffix == 'N') { + alphaFunction = MaterialHelper.ALPHA_MASK_NONE; + } + // removing the type suffix from the name + emitter.setName(emitter.getName().substring(0, + emitter.getName().length() - 1)); + + // applying emitter shape + EmitterShape emitterShape = emitter.getShape(); + List meshes = new ArrayList(); + for (Spatial spatial : node.getChildren()) { + if (spatial instanceof Geometry) { + Mesh mesh = ((Geometry) spatial).getMesh(); + if (mesh != null) { + meshes.add(mesh); + Material material = materialHelper.getParticlesMaterial( + ((Geometry) spatial).getMaterial(), alphaFunction, + dataRepository); + emitter.setMaterial(material);// TODO: divide into several + // pieces + } + } + } + if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) { + ((EmitterMeshVertexShape) emitterShape).setMeshes(meshes); + } + + node.attachChild(emitter); + return node; + } + + @Override + public String getType() { + return Modifier.PARTICLE_MODIFIER_DATA; + } +} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java similarity index 90% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java index daca5c6ae..5d9f916a1 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.objects; import java.util.ArrayList; import java.util.Collection; @@ -51,15 +51,21 @@ import com.jme3.scene.Geometry; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.scene.Spatial.CullHint; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.structures.Modifier; -import com.jme3.scene.plugins.blender.structures.Properties; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.ArmatureHelper; +import com.jme3.scene.plugins.blender.cameras.CameraHelper; +import com.jme3.scene.plugins.blender.constraints.ConstraintHelper; +import com.jme3.scene.plugins.blender.curves.CurvesHelper; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.lights.LightHelper; +import com.jme3.scene.plugins.blender.meshes.MeshHelper; +import com.jme3.scene.plugins.blender.modifiers.Modifier; +import com.jme3.scene.plugins.blender.modifiers.ModifierHelper; /** * A class that is used in object calculations. @@ -136,19 +142,15 @@ public class ObjectHelper extends AbstractBlenderHelper { dataRepository.pushParent(objectStructure); ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - ModifierHelper modifierHelper = dataRepository.getHelper(ModifierHelper.class); ArmatureHelper armatureHelper = dataRepository.getHelper(ArmatureHelper.class); - ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class); //get object data int type = ((Number)objectStructure.getFieldValue("type")).intValue(); String name = objectStructure.getName(); LOGGER.log(Level.INFO, "Loading obejct: {0}", name); - //reading modifiers - modifierHelper.readModifiers(objectStructure, dataRepository); - //loading constraints connected with this object + ConstraintHelper constraintHelper = dataRepository.getHelper(ConstraintHelper.class); constraintHelper.loadConstraints(objectStructure, dataRepository); int restrictflag = ((Number)objectStructure.getFieldValue("restrictflag")).intValue(); @@ -187,10 +189,11 @@ public class ObjectHelper extends AbstractBlenderHelper { } node.setLocalTransform(t); - //applying all modifiers - List modifiers = dataRepository.getModifiers(objectStructure.getOldMemoryAddress(), null); + //reading and applying all modifiers + ModifierHelper modifierHelper = dataRepository.getHelper(ModifierHelper.class); + Collection modifiers = modifierHelper.readModifiers(objectStructure, dataRepository); for(Modifier modifier : modifiers) { - modifierHelper.applyModifier(node, modifier, dataRepository); + modifier.apply(node, dataRepository); } //setting the parent diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Properties.java b/engine/src/blender/com/jme3/scene/plugins/blender/objects/Properties.java similarity index 97% rename from engine/src/blender/com/jme3/scene/plugins/blender/structures/Properties.java rename to engine/src/blender/com/jme3/scene/plugins/blender/objects/Properties.java index 0eaa633d3..229313c12 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Properties.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/objects/Properties.java @@ -1,4 +1,4 @@ -package com.jme3.scene.plugins.blender.structures; +package com.jme3.scene.plugins.blender.objects; import java.io.IOException; import java.util.ArrayList; @@ -11,12 +11,12 @@ import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.export.Savable; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.BlenderInputStream; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; /** * The blender object's custom properties. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java similarity index 92% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java index 682b1d05c..dd3a9eb48 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/particles/ParticlesHelper.java @@ -1,4 +1,4 @@ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.particles; import java.util.logging.Logger; @@ -11,12 +11,12 @@ import com.jme3.effect.shapes.EmitterMeshConvexHullShape; import com.jme3.effect.shapes.EmitterMeshFaceShape; import com.jme3.effect.shapes.EmitterMeshVertexShape; import com.jme3.math.ColorRGBA; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; public class ParticlesHelper extends AbstractBlenderHelper { private static final Logger LOGGER = Logger.getLogger(ParticlesHelper.class.getName()); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java b/engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java deleted file mode 100644 index 8e2b4234b..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.jme3.scene.plugins.blender.structures; - -import java.util.logging.Logger; - -import com.jme3.animation.Bone; -import com.jme3.animation.BoneAnimation; -import com.jme3.animation.BoneTrack; -import com.jme3.animation.Skeleton; -import com.jme3.math.Quaternion; -import com.jme3.math.Vector3f; -import com.jme3.scene.Node; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.helpers.v249.ObjectHelper; -import com.jme3.scene.plugins.blender.structures.Constraint.Space; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.Pointer; - -/** - * This class is used to calculate the constraint. The following methods should be implemented: affectLocation, - * affectRotation and affectScale. This class also defines all constants required by known deriving classes. - * @author Marcin Roguski - */ -public abstract class AbstractInfluenceFunction { - - protected static final Logger LOGGER = Logger.getLogger(AbstractInfluenceFunction.class.getName()); - protected static final float IK_SOLVER_ERROR = 0.5f; - //DISTLIMIT - protected static final int LIMITDIST_INSIDE = 0; - protected static final int LIMITDIST_OUTSIDE = 1; - protected static final int LIMITDIST_ONSURFACE = 2; - //CONSTRAINT_TYPE_LOCLIKE - protected static final int LOCLIKE_X = 0x01; - protected static final int LOCLIKE_Y = 0x02; - protected static final int LOCLIKE_Z = 0x04; - //ROTLIKE - protected static final int ROTLIKE_X = 0x01; - protected static final int ROTLIKE_Y = 0x02; - protected static final int ROTLIKE_Z = 0x04; - protected static final int ROTLIKE_X_INVERT = 0x10; - protected static final int ROTLIKE_Y_INVERT = 0x20; - protected static final int ROTLIKE_Z_INVERT = 0x40; - protected static final int ROTLIKE_OFFSET = 0x80; - //SIZELIKE - protected static final int SIZELIKE_X = 0x01; - protected static final int SIZELIKE_Y = 0x02; - protected static final int SIZELIKE_Z = 0x04; - protected static final int SIZELIKE_OFFSET = 0x80; - - /* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */ - //protected static final int LOCLIKE_TIP = 0x08; - protected static final int LOCLIKE_X_INVERT = 0x10; - protected static final int LOCLIKE_Y_INVERT = 0x20; - protected static final int LOCLIKE_Z_INVERT = 0x40; - protected static final int LOCLIKE_OFFSET = 0x80; - //LOCLIMIT, SIZELIMIT - protected static final int LIMIT_XMIN = 0x01; - protected static final int LIMIT_XMAX = 0x02; - protected static final int LIMIT_YMIN = 0x04; - protected static final int LIMIT_YMAX = 0x08; - protected static final int LIMIT_ZMIN = 0x10; - protected static final int LIMIT_ZMAX = 0x20; - //ROTLIMIT - protected static final int LIMIT_XROT = 0x01; - protected static final int LIMIT_YROT = 0x02; - protected static final int LIMIT_ZROT = 0x04; - /** The type of the constraint. */ - protected ConstraintType constraintType; - /** The data repository. */ - protected DataRepository dataRepository; - - /** - * Constructor. - * @param constraintType - * the type of the current constraint - * @param dataRepository - * the data repository - */ - public AbstractInfluenceFunction(ConstraintType constraintType, DataRepository dataRepository) { - this.constraintType = constraintType; - this.dataRepository = dataRepository; - } - - /** - * This method validates the constraint type. It throws an IllegalArgumentException if the constraint type of the - * given structure is invalid. - * @param constraintStructure - * the structure with constraint data - */ - protected void validateConstraintType(Structure constraintStructure) { - if (!constraintType.getClassName().equalsIgnoreCase(constraintStructure.getType())) { - throw new IllegalArgumentException("Invalud structure type (" + constraintStructure.getType() + ") for the constraint: " + constraintType.getClassName() + '!'); - } - } - - /** - * This method affects the bone animation tracks for the given skeleton. - * @param skeleton - * the skeleton containing the affected bones by constraint - * @param boneAnimation - * the bone animation baked traces - * @param constraint - * the constraint - */ - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - } - - /** - * This method returns the bone traces for the bone that is affected by the given constraint. - * @param skeleton - * the skeleton containing bones - * @param boneAnimation - * the bone animation that affects the skeleton - * @param constraint - * the affecting constraint - * @return the bone track for the bone that is being affected by the constraint - */ - protected BoneTrack getBoneTrack(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) { - Long boneOMA = constraint.getBoneOMA(); - Bone bone = (Bone) dataRepository.getLoadedFeature(boneOMA, LoadedFeatureDataType.LOADED_FEATURE); - int boneIndex = bone==null ? 0 : skeleton.getBoneIndex(bone);//bone==null may mean the object animation - if (boneIndex != -1) { - //searching for track for this bone - for (BoneTrack boneTrack : boneAnimation.getTracks()) { - if (boneTrack.getTargetBoneIndex() == boneIndex) { - return boneTrack; - } - } - } - return null; - } - - /** - * This method returns the target or subtarget object (if specified). - * @param constraint - * the constraint instance - * @return target or subtarget feature - * @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted - */ - protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException { - //load the feature through objectHelper, this way we are certain the object loads and has - //his own constraints applied to traces - ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); - //always load the target first - Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress(); - Structure objectStructure = dataRepository.getFileBlock(targetOMA).getStructure(dataRepository); - Object result = objectHelper.toObject(objectStructure, dataRepository); - - //subtarget should be loaded alogn with target - Object subtarget = constraint.getData().getFieldValue("subtarget"); - String subtargetName = subtarget==null ? null : subtarget.toString(); - if (subtargetName!=null && subtargetName.length() > 0) { - result = dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType); - } - return result; - } - - /** - * This method returns target's object location. - * @param constraint - * the constraint instance - * @return target's object location - */ - protected Vector3f getTargetLocation(Constraint constraint) { - Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress(); - Space targetSpace = constraint.getTargetSpace(); - Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE); - switch (targetSpace) { - case CONSTRAINT_SPACE_LOCAL: - return targetObject.getLocalTranslation(); - case CONSTRAINT_SPACE_WORLD: - return targetObject.getWorldTranslation(); - default: - throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString()); - } - } - - /** - * This method returns target's object location in the specified frame. - * @param constraint - * the constraint instance - * @param frame - * the frame number - * @return target's object location - */ - protected Vector3f getTargetLocation(Constraint constraint, int frame) { - return this.getTargetLocation(constraint);//TODO: implement getting location in a specified frame - } - - /** - * This method returns target's object rotation. - * @param constraint - * the constraint instance - * @return target's object rotation - */ - protected Quaternion getTargetRotation(Constraint constraint) { - Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress(); - Space targetSpace = constraint.getTargetSpace(); - Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE); - switch (targetSpace) { - case CONSTRAINT_SPACE_LOCAL: - return targetObject.getLocalRotation(); - case CONSTRAINT_SPACE_WORLD: - return targetObject.getWorldRotation(); - default: - throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString()); - } - } - - /** - * This method returns target's object scale. - * @param constraint - * the constraint instance - * @return target's object scale - */ - protected Vector3f getTargetScale(Constraint constraint) { - Long targetOMA = ((Pointer) constraint.getData().getFieldValue("tar")).getOldMemoryAddress(); - Space targetSpace = constraint.getTargetSpace(); - Node targetObject = (Node) dataRepository.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE); - switch (targetSpace) { - case CONSTRAINT_SPACE_LOCAL: - return targetObject.getLocalScale(); - case CONSTRAINT_SPACE_WORLD: - return targetObject.getWorldScale(); - default: - throw new IllegalStateException("Invalid space type for target object: " + targetSpace.toString()); - } - } -} diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Constraint.java b/engine/src/blender/com/jme3/scene/plugins/blender/structures/Constraint.java deleted file mode 100644 index 7467c0aca..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Constraint.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.jme3.scene.plugins.blender.structures; - -import com.jme3.animation.BoneAnimation; -import com.jme3.animation.Skeleton; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.Pointer; - -/** - * The implementation of a constraint. - * @author Marcin Roguski - */ -public class Constraint { - - /** The type of this constraint. */ - private final ConstraintType type; - /** The name of this constraint. */ - private final String name; - /** The old memory address of the constraint's owner. */ - private final Long boneOMA; - private final Space ownerSpace; - private final Space targetSpace; - /** The structure with constraint's data. */ - private final Structure data; - /** The ipo object defining influence. */ - private final Ipo ipo; - /** The influence function of this constraint. */ - private final AbstractInfluenceFunction influenceFunction; - - /** - * This constructor creates the constraint instance. - * @param constraintStructure - * the constraint's structure (bConstraint clss in blender 2.49). - * @param influenceFunction - * the constraint's influence function (taken from ConstraintHelper) - * @param boneOMA - * the old memory address of the constraint owner - * @param influenceIpo - * the ipo curve of the influence factor - * @param dataRepository - * the data repository - * @throws BlenderFileException - */ - public Constraint(Structure constraintStructure, AbstractInfluenceFunction influenceFunction, Long boneOMA, Space ownerSpace, Space targetSpace, Ipo influenceIpo, DataRepository dataRepository) throws BlenderFileException { - if (influenceFunction == null) { - throw new IllegalArgumentException("Influence function is not defined!"); - } - Pointer pData = (Pointer) constraintStructure.getFieldValue("data"); - if (pData.isNotNull()) { - data = pData.fetchData(dataRepository.getInputStream()).get(0); - } else { - throw new BlenderFileException("The constraint has no data specified!"); - } - this.boneOMA = boneOMA; - this.type = ConstraintType.valueOf(((Number) constraintStructure.getFieldValue("type")).intValue()); - this.name = constraintStructure.getFieldValue("name").toString(); - this.ownerSpace = ownerSpace; - this.targetSpace = targetSpace; - this.ipo = influenceIpo; - this.influenceFunction = influenceFunction; - } - - /** - * This method returns the name of the constraint. - * @return the name of the constraint - */ - public String getName() { - return name; - } - - /** - * This method returns the old memoty address of the bone this constraint affects. - * @return the old memory address of the bone this constraint affects - */ - public Long getBoneOMA() { - return boneOMA; - } - - /** - * This method returns owner's transform space. - * @return owner's transform space - */ - public Space getOwnerSpace() { - return ownerSpace; - } - - /** - * This method returns target's transform space. - * @return target's transform space - */ - public Space getTargetSpace() { - return targetSpace; - } - - /** - * This method returns the type of the constraint. - * @return the type of the constraint - */ - public ConstraintType getType() { - return type; - } - - /** - * This method returns the constraint's data structure. - * @return the constraint's data structure - */ - public Structure getData() { - return data; - } - - /** - * This method returns the constraint's influcence curve. - * @return the constraint's influcence curve - */ - public Ipo getIpo() { - return ipo; - } - - /** - * This method affects the bone animation tracks for the given skeleton. - * @param skeleton - * the skeleton containing the affected bones by constraint - * @param boneAnimation - * the bone animation baked traces - * @param constraint - * the constraint - */ - public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation) { - influenceFunction.affectAnimation(skeleton, boneAnimation, this); - } - - /** - * The space of target or owner transformation. - * @author Marcin Roguski - */ - public static enum Space { - - CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_INVALID; - - /** - * This method returns the enum instance when given the appropriate value from the blend file. - * @param c - * the blender's value of the space modifier - * @return the scape enum instance - */ - public static Space valueOf(byte c) { - switch (c) { - case 0: - return CONSTRAINT_SPACE_WORLD; - case 1: - return CONSTRAINT_SPACE_LOCAL; - case 2: - return CONSTRAINT_SPACE_POSE; - case 3: - return CONSTRAINT_SPACE_PARLOCAL; - default: - return CONSTRAINT_SPACE_INVALID; - } - } - } -} \ No newline at end of file diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Modifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/structures/Modifier.java deleted file mode 100644 index f66fe0e96..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/structures/Modifier.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.jme3.scene.plugins.blender.structures; - -/** - * This class represents an object's modifier. The modifier object can be varied and the user needs to know what is - * the type of it for the specified type name. For example "ArmatureModifierData" type specified in blender is - * represented by AnimData object from jMonkeyEngine. - * @author Marcin Roguski (Kaelthas) - */ -public class Modifier { - - public static final String ARRAY_MODIFIER_DATA = "ArrayModifierData"; - public static final String ARMATURE_MODIFIER_DATA = "ArmatureModifierData"; - public static final String PARTICLE_MODIFIER_DATA = "ParticleSystemModifierData"; - public static final String MIRROR_MODIFIER_DATA = "MirrorModifierData"; - public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData"; - - /** - * Blender's type of modifier. - */ - private String type; - - /** - * JME modifier representation object. - */ - private Object jmeModifierRepresentation; - - /** - * Various additional data used by modifiers. - */ - private Object additionalData; - - /** - * Constructor. Creates modifier object. - * @param type - * blender's type of modifier - * @param modifier - * JME modifier representation object - */ - public Modifier(String type, Object modifier, Object additionalData) { - this.type = type; - this.jmeModifierRepresentation = modifier; - this.additionalData = additionalData; - } - - /** - * This method returns JME modifier representation object. - * @return JME modifier representation object - */ - public Object getJmeModifierRepresentation() { - return jmeModifierRepresentation; - } - - /** - * This method returns blender's type of modifier. - * @return blender's type of modifier - */ - public String getType() { - return type; - } - - /** - * This method returns additional data stored in the modifier. - * @return the additional data stored in the modifier - */ - public Object getAdditionalData() { - return additionalData; - } -} \ No newline at end of file diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/NoiseGenerator.java similarity index 95% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/textures/NoiseGenerator.java index b85b42b6f..8b3def74d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/NoiseGenerator.java @@ -28,7 +28,7 @@ * ***** END GPL LICENSE BLOCK ***** * */ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.textures; import java.io.IOException; import java.io.InputStream; @@ -39,24 +39,23 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.jme3.math.FastMath; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.helpers.v249.TextureHelper.CBData; -import com.jme3.scene.plugins.blender.helpers.v249.TextureHelper.ColorBand; -import com.jme3.scene.plugins.blender.helpers.v249.TextureHelper.TexResult; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.DataRepository; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.textures.TextureHelper.CBData; +import com.jme3.scene.plugins.blender.textures.TextureHelper.ColorBand; +import com.jme3.scene.plugins.blender.textures.TextureHelper.TexResult; /** - * Methods of this class are copied from blender 2.49 source code and modified so that they can be used in java. They - * are mostly NOT documented because they are not documented in blender's source code. If I find a proper description or - * discover what they actually do and what parameters mean - I shall describe such methods :) If anyone have some hint - * what these methods are doing please rite the proper javadoc documentation. These methods should be used to create - * generated textures. + * This generator is responsible for creating various noises used to create + * generated textures loaded from blender. + * It derives from AbstractBlenderHelper but is not stored in data repository. + * It is only used by TextureHelper. * @author Marcin Roguski (Kaelthas) */ -public class NoiseHelper extends AbstractBlenderHelper { +/*package*/ class NoiseGenerator extends AbstractBlenderHelper { - private static final Logger LOGGER = Logger.getLogger(NoiseHelper.class.getName()); + private static final Logger LOGGER = Logger.getLogger(NoiseGenerator.class.getName()); /* return value */ protected static final int TEX_INT = 0; @@ -137,7 +136,7 @@ public class NoiseHelper extends AbstractBlenderHelper { * @param blenderVersion * the number of blender version */ - public NoiseHelper(String blenderVersion) { + public NoiseGenerator(String blenderVersion) { super(blenderVersion); this.loadConstants(); } @@ -148,7 +147,7 @@ public class NoiseHelper extends AbstractBlenderHelper { * an exception will be thrown the class will not be instantiated. */ protected void loadConstants() { - InputStream is = NoiseHelper.class.getResourceAsStream("noiseconstants.dat"); + InputStream is = NoiseGenerator.class.getResourceAsStream("noiseconstants.dat"); try { ObjectInputStream ois = new ObjectInputStream(is); hashpntf = (float[]) ois.readObject(); @@ -332,7 +331,7 @@ public class NoiseHelper extends AbstractBlenderHelper { }); } /** Distance metrics for voronoi. e parameter only used in Minkovsky. */ - protected static Map distanceFunctions = new HashMap(); + protected static Map distanceFunctions = new HashMap(); static { // real distance @@ -400,7 +399,7 @@ public class NoiseHelper extends AbstractBlenderHelper { } }); } - protected static Map musgraveFunctions = new HashMap(); + protected static Map musgraveFunctions = new HashMap(); static { musgraveFunctions.put(Integer.valueOf(TEX_MFRACTAL), new MusgraveFunction() { @@ -895,7 +894,7 @@ public class NoiseHelper extends AbstractBlenderHelper { float n = 5.0f * (x + y + z); float mi = n + turbul * this.bliGTurbulence(noisesize, x, y, z, noisedepth, noisetype != TEX_NOISESOFT, noisebasis); - if (stype >= NoiseHelper.TEX_SOFT) { /* TEX_SOFT always true */ + if (stype >= NoiseGenerator.TEX_SOFT) { /* TEX_SOFT always true */ mi = waveformFunctions[waveform].execute(mi); if (stype == TEX_SHARP) { mi = (float) Math.sqrt(mi); diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java similarity index 92% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java rename to engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java index d138dcf4b..fc9276ed8 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.scene.plugins.blender.helpers.v249; +package com.jme3.scene.plugins.blender.textures; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; @@ -52,16 +52,16 @@ import com.jme3.asset.GeneratedTextureKey; import com.jme3.asset.TextureKey; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; -import com.jme3.scene.plugins.blender.data.FileBlockHeader; -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; -import com.jme3.scene.plugins.blender.helpers.NoiseHelper; -import com.jme3.scene.plugins.blender.utils.AbstractBlenderHelper; -import com.jme3.scene.plugins.blender.utils.BlenderInputStream; -import com.jme3.scene.plugins.blender.utils.DataRepository; -import com.jme3.scene.plugins.blender.utils.DataRepository.LoadedFeatureDataType; -import com.jme3.scene.plugins.blender.utils.DynamicArray; -import com.jme3.scene.plugins.blender.utils.Pointer; +import com.jme3.scene.plugins.blender.AbstractBlenderHelper; +import com.jme3.scene.plugins.blender.DataRepository; +import com.jme3.scene.plugins.blender.DataRepository.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; +import com.jme3.scene.plugins.blender.file.BlenderInputStream; +import com.jme3.scene.plugins.blender.file.DynamicArray; +import com.jme3.scene.plugins.blender.file.FileBlockHeader; +import com.jme3.scene.plugins.blender.file.Pointer; +import com.jme3.scene.plugins.blender.file.Structure; +import com.jme3.scene.plugins.blender.materials.MaterialHelper; import com.jme3.texture.Image; import com.jme3.texture.Image.Format; import com.jme3.texture.Texture; @@ -95,7 +95,9 @@ public class TextureHelper extends AbstractBlenderHelper { public static final int TEX_MUSGRAVE = 11; public static final int TEX_VORONOI = 12; public static final int TEX_DISTNOISE = 13; - + public static final int TEX_POINTDENSITY = 14;//v. 25+ + public static final int TEX_VOXELDATA = 15;//v. 25+ + // mapto public static final int MAP_COL = 1; public static final int MAP_NORM = 2; @@ -149,6 +151,8 @@ public class TextureHelper extends AbstractBlenderHelper { public static final int MA_RAMP_VAL = 14; public static final int MA_RAMP_COLOR = 15; + protected NoiseGenerator noiseHelper; + /** * This constructor parses the given blender version and stores the result. Some functionalities may differ in different blender * versions. @@ -158,6 +162,7 @@ public class TextureHelper extends AbstractBlenderHelper { */ public TextureHelper(String blenderVersion) { super(blenderVersion); + noiseHelper = new NoiseGenerator(blenderVersion); } /** @@ -221,6 +226,12 @@ public class TextureHelper extends AbstractBlenderHelper { break; case TEX_NONE:// No texture, do nothing break; + case TEX_POINTDENSITY: + LOGGER.warning("Point density texture loading currently not supported!"); + break; + case TEX_VOXELDATA: + LOGGER.warning("Voxel data texture loading currently not supported!"); + break; case TEX_PLUGIN: case TEX_ENVMAP:// TODO: implement envmap texture LOGGER.log(Level.WARNING, "Unsupported texture type: {0} for texture: {1}", new Object[]{type, tex.getName()}); @@ -253,7 +264,6 @@ public class TextureHelper extends AbstractBlenderHelper { */ protected Texture clouds(Structure tex, int width, int height, DataRepository dataRepository) { // preparing the proper data - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float wDelta = 1.0f / width, hDelta = 1.0f / height; float[] texvec = new float[] { 0, 0, 0 }; TexResult texres = new TexResult(); @@ -265,14 +275,14 @@ public class TextureHelper extends AbstractBlenderHelper { int noiseType = ((Number) tex.getFieldValue("noisetype")).intValue(); float contrast = ((Number) tex.getFieldValue("contrast")).floatValue(); float bright = ((Number) tex.getFieldValue("bright")).floatValue(); - boolean isHard = noiseType != com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_NOISESOFT; + boolean isHard = noiseType != NoiseGenerator.TEX_NOISESOFT; int sType = ((Number) tex.getFieldValue("stype")).intValue(); int halfW = width, halfH = height; width <<= 1; height <<= 1; ColorBand colorBand = this.readColorband(tex, dataRepository); - Format format = sType == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8; - int bytesPerPixel = sType == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLOR || colorBand != null ? 3 : 1; + Format format = sType == NoiseGenerator.TEX_COLOR || colorBand != null ? Format.RGB8 : Format.Luminance8; + int bytesPerPixel = sType == NoiseGenerator.TEX_COLOR || colorBand != null ? 3 : 1; ByteBuffer data = BufferUtils.createByteBuffer(width * height * bytesPerPixel); for (int i = -halfW; i < halfW; ++i) { @@ -295,7 +305,7 @@ public class TextureHelper extends AbstractBlenderHelper { data.put((byte) (texres.tr * 255.0f)); data.put((byte) (texres.tg * 255.0f)); data.put((byte) (texres.tb * 255.0f)); - } else if (sType == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLOR) { + } else if (sType == NoiseGenerator.TEX_COLOR) { // in this case, int. value should really be computed from color, // and bumpnormal from that, would be too slow, looks ok as is texres.tr = texres.tin; @@ -329,7 +339,6 @@ public class TextureHelper extends AbstractBlenderHelper { */ protected Texture wood(Structure tex, int width, int height, DataRepository dataRepository) { // preparing the proper data - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float contrast = ((Number) tex.getFieldValue("contrast")).floatValue(); float bright = ((Number) tex.getFieldValue("bright")).floatValue(); float nabla = ((Number) tex.getFieldValue("nabla")).floatValue(); @@ -386,7 +395,6 @@ public class TextureHelper extends AbstractBlenderHelper { */ protected Texture marble(Structure tex, int width, int height, DataRepository dataRepository) { // preparing the proper data - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float contrast = ((Number) tex.getFieldValue("contrast")).floatValue(); float bright = ((Number) tex.getFieldValue("bright")).floatValue(); float nabla = ((Number) tex.getFieldValue("nabla")).floatValue(); @@ -442,7 +450,6 @@ public class TextureHelper extends AbstractBlenderHelper { * @return the generated texture */ protected Texture magic(Structure tex, int width, int height, DataRepository dataRepository) { - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float x, y, z, turb; int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue(); float turbul = ((Number) tex.getFieldValue("turbul")).floatValue() / 5.0f; @@ -536,7 +543,6 @@ public class TextureHelper extends AbstractBlenderHelper { * @return the generated texture */ protected Texture blend(Structure tex, int width, int height, DataRepository dataRepository) { - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); int flag = ((Number) tex.getFieldValue("flag")).intValue(); int stype = ((Number) tex.getFieldValue("stype")).intValue(); float contrast = ((Number) tex.getFieldValue("contrast")).floatValue(); @@ -556,7 +562,7 @@ public class TextureHelper extends AbstractBlenderHelper { texvec[0] = wDelta * i; for (int j = -halfH; j < halfH; ++j) { texvec[1] = hDelta * j; - if ((flag & com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_FLIPBLEND) != 0) { + if ((flag & NoiseGenerator.TEX_FLIPBLEND) != 0) { x = texvec[1]; y = texvec[0]; } else { @@ -564,16 +570,16 @@ public class TextureHelper extends AbstractBlenderHelper { y = texvec[1]; } - if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_LIN) { /* lin */ + if (stype == NoiseGenerator.TEX_LIN) { /* lin */ texres.tin = (1.0f + x) / 2.0f; - } else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_QUAD) { /* quad */ + } else if (stype == NoiseGenerator.TEX_QUAD) { /* quad */ texres.tin = (1.0f + x) / 2.0f; if (texres.tin < 0.0f) { texres.tin = 0.0f; } else { texres.tin *= texres.tin; } - } else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_EASE) { /* ease */ + } else if (stype == NoiseGenerator.TEX_EASE) { /* ease */ texres.tin = (1.0f + x) / 2.0f; if (texres.tin <= 0.0f) { texres.tin = 0.0f; @@ -583,16 +589,16 @@ public class TextureHelper extends AbstractBlenderHelper { t = texres.tin * texres.tin; texres.tin = 3.0f * t - 2.0f * t * texres.tin; } - } else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_DIAG) { /* diag */ + } else if (stype == NoiseGenerator.TEX_DIAG) { /* diag */ texres.tin = (2.0f + x + y) / 4.0f; - } else if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_RAD) { /* radial */ + } else if (stype == NoiseGenerator.TEX_RAD) { /* radial */ texres.tin = (float) Math.atan2(y, x) / FastMath.TWO_PI + 0.5f; } else { /* sphere TEX_SPHERE */ texres.tin = 1.0f - (float) Math.sqrt(x * x + y * y + texvec[2] * texvec[2]); if (texres.tin < 0.0f) { texres.tin = 0.0f; } - if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_HALO) { + if (stype == NoiseGenerator.TEX_HALO) { texres.tin *= texres.tin; } /* halo */ } @@ -629,10 +635,9 @@ public class TextureHelper extends AbstractBlenderHelper { int noisebasis = ((Number) tex.getFieldValue("noisebasis")).intValue(); int noisetype = ((Number) tex.getFieldValue("noisetype")).intValue(); float turbul = ((Number) tex.getFieldValue("turbul")).floatValue(); - boolean isHard = noisetype != com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_NOISESOFT; + boolean isHard = noisetype != NoiseGenerator.TEX_NOISESOFT; int stype = ((Number) tex.getFieldValue("stype")).intValue(); - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float[] texvec = new float[] { 0, 0, 0 }; TexResult texres = new TexResult(); float wDelta = 1.0f / width, hDelta = 1.0f / height, b2, ofs; @@ -665,7 +670,7 @@ public class TextureHelper extends AbstractBlenderHelper { texres.nor[2] = texres.tin; noiseHelper.texNormalDerivate(colorBand, texres, dataRepository); - if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_WALLOUT) { + if (stype == NoiseGenerator.TEX_WALLOUT) { texres.nor[0] = -texres.nor[0]; texres.nor[1] = -texres.nor[1]; texres.nor[2] = -texres.nor[2]; @@ -673,7 +678,7 @@ public class TextureHelper extends AbstractBlenderHelper { } } - if (stype == com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_WALLOUT) { + if (stype == NoiseGenerator.TEX_WALLOUT) { texres.tin = 1.0f - texres.tin; } if (texres.tin < 0.0f) { @@ -706,7 +711,6 @@ public class TextureHelper extends AbstractBlenderHelper { */ // TODO: correct this one, so it looks more like the texture generated by blender protected Texture texnoise(Structure tex, int width, int height, DataRepository dataRepository) { - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float div = 3.0f; int val, ran, loop; int noisedepth = ((Number) tex.getFieldValue("noisedepth")).intValue(); @@ -762,7 +766,6 @@ public class TextureHelper extends AbstractBlenderHelper { * @return the generated texture */ protected Texture musgrave(Structure tex, int width, int height, DataRepository dataRepository) { - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); int stype = ((Number) tex.getFieldValue("stype")).intValue(); float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue(); TexResult texres = new TexResult(); @@ -781,15 +784,15 @@ public class TextureHelper extends AbstractBlenderHelper { for (int j = -halfH; j < halfH; ++j) { texvec[1] = hDelta * j / noisesize; switch (stype) { - case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_MFRACTAL: - case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_FBM: + case NoiseGenerator.TEX_MFRACTAL: + case NoiseGenerator.TEX_FBM: noiseHelper.mgMFractalOrfBmTex(tex, texvec, colorBand, texres, dataRepository); break; - case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_RIDGEDMF: - case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_HYBRIDMF: + case NoiseGenerator.TEX_RIDGEDMF: + case NoiseGenerator.TEX_HYBRIDMF: noiseHelper.mgRidgedOrHybridMFTex(tex, texvec, colorBand, texres, dataRepository); break; - case com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_HTERRAIN: + case NoiseGenerator.TEX_HTERRAIN: noiseHelper.mgHTerrainTex(tex, texvec, colorBand, texres, dataRepository); break; default: @@ -822,7 +825,6 @@ public class TextureHelper extends AbstractBlenderHelper { * @return the generated texture */ protected Texture voronoi(Structure tex, int width, int height, DataRepository dataRepository) { - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float vn_w1 = ((Number) tex.getFieldValue("vn_w1")).floatValue(); float vn_w2 = ((Number) tex.getFieldValue("vn_w2")).floatValue(); float vn_w3 = ((Number) tex.getFieldValue("vn_w3")).floatValue(); @@ -944,7 +946,6 @@ public class TextureHelper extends AbstractBlenderHelper { * @return the generated texture */ protected Texture distnoise(Structure tex, int width, int height, DataRepository dataRepository) { - NoiseHelper noiseHelper = dataRepository.getHelper(NoiseHelper.class); float noisesize = ((Number) tex.getFieldValue("noisesize")).floatValue(); float nabla = ((Number) tex.getFieldValue("nabla")).floatValue(); float distAmount = ((Number) tex.getFieldValue("dist_amount")).floatValue(); @@ -1006,7 +1007,7 @@ public class TextureHelper extends AbstractBlenderHelper { protected ColorBand readColorband(Structure tex, DataRepository dataRepository) { ColorBand result = null; int flag = ((Number) tex.getFieldValue("flag")).intValue(); - if ((flag & com.jme3.scene.plugins.blender.helpers.v249.NoiseHelper.TEX_COLORBAND) != 0) { + if ((flag & NoiseGenerator.TEX_COLORBAND) != 0) { Pointer pColorband = (Pointer) tex.getFieldValue("coba"); Structure colorbandStructure; try { @@ -1965,4 +1966,4 @@ public class TextureHelper extends AbstractBlenderHelper { return super.clone(); } } -} +} \ No newline at end of file diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/noiseconstants.dat b/engine/src/blender/com/jme3/scene/plugins/blender/textures/noiseconstants.dat similarity index 100% rename from engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/noiseconstants.dat rename to engine/src/blender/com/jme3/scene/plugins/blender/textures/noiseconstants.dat diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderConverter.java b/engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderConverter.java deleted file mode 100644 index 0c3180b86..000000000 --- a/engine/src/blender/com/jme3/scene/plugins/blender/utils/BlenderConverter.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2009-2010 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.jme3.scene.plugins.blender.utils; - -import com.jme3.scene.plugins.blender.data.Structure; -import com.jme3.scene.plugins.blender.exception.BlenderFileException; - -/** - * This interface provides an abstraction to converting loaded blender structures into data structures. The data - * structures can vary and therefore one can use the loader for different kind of engines. - * @author Marcin Roguski - * @param - * the type of the scene node element - * @param - * the type of camera element - * @param - * the type of light element - * @param - * the type of object element - * @param - * the type of mesh element - * @param - * the type of material element - */ -//TODO: ujednolicić wyrzucane wyjątki -public interface BlenderConverter { - - /** - * This method reads converts the given structure into scene. The given structure needs to be filled with the - * appropriate data. - * @param structure - * the structure we read the scene from - * @return the scene feature - */ - NodeType toScene(Structure structure); - - /** - * This method reads converts the given structure into camera. The given structure needs to be filled with the - * appropriate data. - * @param structure - * the structure we read the camera from - * @return the camera feature - */ - CameraType toCamera(Structure structure) throws BlenderFileException; - - /** - * This method reads converts the given structure into light. The given structure needs to be filled with the - * appropriate data. - * @param structure - * the structure we read the light from - * @return the light feature - */ - LightType toLight(Structure structure) throws BlenderFileException; - - /** - * This method reads converts the given structure into objct. The given structure needs to be filled with the - * appropriate data. - * @param structure - * the structure we read the object from - * @return the object feature - */ - ObjectType toObject(Structure structure) throws BlenderFileException; - - /** - * This method reads converts the given structure into mesh. The given structure needs to be filled with the - * appropriate data. - * @param structure - * the structure we read the mesh from - * @return the mesh feature - */ - MeshType toMesh(Structure structure) throws BlenderFileException; - - /** - * This method reads converts the given structure into material. The given structure needs to be filled with the - * appropriate data. - * @param structure - * the structure we read the material from - * @return the material feature - */ - MaterialType toMaterial(Structure structure) throws BlenderFileException; -} \ No newline at end of file