Several changes to constraints (but may not working well yet).

Fix to Y-up axis issue when parent was present bu not loaded (in different layer for example).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7913 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 14 years ago
parent f182b5d91b
commit 99746c72ec
  1. 11
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ArmatureHelper.java
  2. 7
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CameraHelper.java
  3. 265
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ConstraintHelper.java
  4. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/CurvesHelper.java
  5. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/IpoHelper.java
  6. 6
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/LightHelper.java
  7. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java
  8. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java
  9. 9
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ModifierHelper.java
  10. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/NoiseHelper.java
  11. 38
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ObjectHelper.java
  12. 5
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/ParticlesHelper.java
  13. 6
      engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/TextureHelper.java
  14. 17
      engine/src/blender/com/jme3/scene/plugins/blender/structures/AbstractInfluenceFunction.java
  15. 129
      engine/src/blender/com/jme3/scene/plugins/blender/structures/CalculationBone.java
  16. 11
      engine/src/blender/com/jme3/scene/plugins/blender/utils/AbstractBlenderHelper.java
  17. 41
      engine/src/blender/com/jme3/scene/plugins/blender/utils/JmeConverter.java

@ -267,9 +267,9 @@ public class ArmatureHelper extends AbstractBlenderHelper {
}
/**
* This method returns bone transformation data for the bone of a given name.
* @param boneName
* the name of the bone
* This method returns bone transformation data for the bone of a given index.
* @param index
* the index of the bone
* @return bone's transformation data
*/
public BoneTransformationData getBoneTransformationDataRoot(int index) {
@ -368,4 +368,9 @@ public class ArmatureHelper extends AbstractBlenderHelper {
bonesMap.clear();
boneDataRoots.clear();
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
}

@ -3,10 +3,12 @@ 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.
@ -55,4 +57,9 @@ public class CameraHelper extends AbstractBlenderHelper {
result.setFrustumPerspective(angle, aspect, clipsta, clipend);
return result;
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) != 0;
}
}

@ -2,6 +2,7 @@ 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;
@ -13,6 +14,7 @@ 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;
@ -22,6 +24,7 @@ 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;
@ -146,70 +149,89 @@ public class ConstraintHelper extends AbstractBlenderHelper {
@Override
public void affectAnimation(Skeleton skeleton, BoneAnimation boneAnimation, Constraint constraint) {
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);
pt = transform.getTranslation();
} else {
throw new IllegalStateException("Unknown target object type! Should be Node, Bone or Skeleton and there is: " + targetObject.getClass().getName());
}
//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();
int maxFrames = bones[0].track.getTimes().length;//all tracks should have the same amount of frames
for(int frame = 0; frame < maxFrames; ++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("===============================");
}*/
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());
}
}
/**
@ -226,13 +248,14 @@ public class ConstraintHelper extends AbstractBlenderHelper {
List<CalculationBone> bonesList = new ArrayList<CalculationBone>();
Bone currentBone = bone;
do {
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;
}
}
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
@ -725,101 +748,9 @@ public class ConstraintHelper extends AbstractBlenderHelper {
public void clearState() {
constraints.clear();
}
/**
* The purpose of this class is to imitate bone's movement when calculating inverse kinematics.
* @author Marcin Roguski
*/
private static class CalculationBone extends Node {
/** The name of the bone. Only to be used in toString method. */
private String boneName;
/** The bone's tracks. Will be altered at the end of calculation process. */
private BoneTrack track;
/** The starting position of the bone. */
private Vector3f startTranslation;
/** The starting rotation of the bone. */
private Quaternion startRotation;
/** The starting scale of the bone. */
private Vector3f startScale;
private Vector3f[] translations;
private Quaternion[] rotations;
private Vector3f[] scales;
/**
* Constructor. Stores the track, starting transformation and sets the transformation to the starting positions.
* @param bone
* the bone this class will imitate
* @param track
* the bone's tracks
*/
public CalculationBone(Bone bone, BoneTrack track) {
this.boneName = bone.getName();
this.track = track;
this.startRotation = bone.getModelSpaceRotation().clone();
this.startTranslation = bone.getModelSpacePosition().clone();
this.startScale = bone.getModelSpaceScale().clone();
this.translations = track.getTranslations();
this.rotations = track.getRotations();
this.scales = track.getScales();
this.reset();
}
/**
* This method returns the end point of the bone. If the bone has parent it is calculated from the start point
* of parent to the start point of this bone. If the bone doesn't have a parent the end location is considered
* to be 1 point up along Y axis (scale is applied if set to != 1.0);
* @return the end point of this bone
*/
//TODO: set to Z axis if user defined it this way
public Vector3f getEndPoint() {
if (this.getParent() == null) {
return new Vector3f(0, this.getLocalScale().y, 0);
} else {
Node parent = this.getParent();
return parent.getWorldTranslation().subtract(this.getWorldTranslation()).multLocal(this.getWorldScale());
}
}
/**
* This method resets the calculation bone to the starting position.
*/
public void reset() {
this.setLocalTranslation(startTranslation);
this.setLocalRotation(startRotation);
this.setLocalScale(startScale);
}
@Override
public int attachChild(Spatial child) {
if (this.getChildren() != null && this.getChildren().size() > 1) {
throw new IllegalStateException(this.getClass().getName() + " class instance can only have one child!");
}
return super.attachChild(child);
}
public Spatial rotate(Quaternion rot, int frame) {
Spatial spatial = super.rotate(rot);
this.updateWorldTransforms();
if (this.getChildren() != null && this.getChildren().size() > 0) {
CalculationBone child = (CalculationBone) this.getChild(0);
child.updateWorldTransforms();
}
rotations[frame].set(this.getLocalRotation());
translations[frame].set(this.getLocalTranslation());
if (scales != null) {
scales[frame].set(this.getLocalScale());
}
return spatial;
}
public void applyCalculatedTracks() {
track.setKeyframes(track.getTimes(), translations, rotations);//TODO:scales
}
@Override
public String toString() {
return boneName + ": " + this.getLocalRotation() + " " + this.getLocalTranslation();
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
}

@ -599,4 +599,9 @@ public class CurvesHelper extends AbstractBlenderHelper {
return new Vector3f(locArray.get(0).floatValue(), locArray.get(2).floatValue(), locArray.get(1).floatValue());
}
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
}

@ -71,6 +71,11 @@ public class IpoHelper extends AbstractBlenderHelper {
return new ConstIpo(constValue);
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
/**
* Ipo constant curve. This is a curve with only one value and no specified type. This type of ipo cannot be used to
* calculate tracks. It should only be used to calculate single value for a given frame.

@ -34,6 +34,7 @@ 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.light.DirectionalLight;
import com.jme3.light.Light;
import com.jme3.light.PointLight;
@ -97,4 +98,9 @@ public class LightHelper extends AbstractBlenderHelper {
}
return result;
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.LIGHTS) != 0;
}
}

@ -685,6 +685,11 @@ public class MaterialHelper extends AbstractBlenderHelper {
}
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0;
}
/**
* An interface used in calculating alpha mask during particles' texture calculations.
* @author Marcin Roguski (Kaelthas)

@ -605,4 +605,9 @@ public class MeshHelper extends AbstractBlenderHelper {
// mesh.setMaxNumWeights(maxWeightsPerVert);
return maxWeightsPerVert;
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
}

@ -352,7 +352,7 @@ public class ModifierHelper extends AbstractBlenderHelper {
//preparing the object's bone
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
Transform t = objectHelper.getTransformation(objectStructure);
Transform t = objectHelper.getTransformation(objectStructure, dataRepository);
Bone bone = new Bone(null);
bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale());
@ -545,7 +545,7 @@ public class ModifierHelper extends AbstractBlenderHelper {
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).getTranslation();
Vector3f translation = objectHelper.getTransformation(offsetStructure, dataRepository).getTranslation();
objectOffset[0] = translation.x;
objectOffset[1] = translation.y;
objectOffset[2] = translation.z;
@ -754,4 +754,9 @@ public class ModifierHelper extends AbstractBlenderHelper {
}
return new Skeleton(bones.toArray(new Bone[bones.size()]));
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
}

@ -1529,6 +1529,11 @@ public class NoiseHelper extends AbstractBlenderHelper {
return rx * q[0] + ry * q[1] + rz * q[2];
}
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
/**
* This interface is used for distance calculation classes. Distance metrics for voronoi. e parameter only used in

@ -31,10 +31,13 @@
*/
package com.jme3.scene.plugins.blender.helpers.v249;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.light.DirectionalLight;
import com.jme3.light.Light;
import com.jme3.light.PointLight;
@ -77,6 +80,16 @@ public class ObjectHelper extends AbstractBlenderHelper {
protected static final int OBJECT_TYPE_LATTICE = 22;
protected static final int OBJECT_TYPE_ARMATURE = 25;
/**
* This collection contains types of features that are not visible to the user.
* These will be loaded regardless the layer they reside in.
*/
protected static final Collection<Integer> invisibleTypes = new ArrayList<Integer>();
static {
invisibleTypes.add(OBJECT_TYPE_EMPTY);
invisibleTypes.add(OBJECT_TYPE_ARMATURE);
}
/** This variable indicates if the Y asxis is the UP axis or not. */
protected boolean fixUpAxis;
/** Quaternion used to rotate data when Y is up axis. */
@ -149,7 +162,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
parent = this.toObject(parentStructure, dataRepository);
}
Transform t = objectHelper.getTransformation(objectStructure);
Transform t = objectHelper.getTransformation(objectStructure, dataRepository);
try {
switch(type) {
@ -268,15 +281,23 @@ public class ObjectHelper extends AbstractBlenderHelper {
* @return objects transformation relative to its parent
*/
@SuppressWarnings("unchecked")
public Transform getTransformation(Structure objectStructure) {
public Transform getTransformation(Structure objectStructure, DataRepository dataRepository) {
//these are transformations in global space
DynamicArray<Number> loc = (DynamicArray<Number>)objectStructure.getFieldValue("loc");
DynamicArray<Number> size = (DynamicArray<Number>)objectStructure.getFieldValue("size");
DynamicArray<Number> rot = (DynamicArray<Number>)objectStructure.getFieldValue("rot");
//load parent inverse matrix
Pointer parent = (Pointer) objectStructure.getFieldValue("parent");
Matrix4f parentInv = parent.isNull() ? Matrix4f.IDENTITY : this.getMatrix(objectStructure, "parentinv");
Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
Structure parent = null;
if(pParent.isNotNull()) {
try {
parent = pParent.fetchData(dataRepository.getInputStream()).get(0);
} catch (BlenderFileException e) {
LOGGER.log(Level.WARNING, "Cannot fetch parent for object! Reason: {0}", e.getLocalizedMessage());
}
}
Matrix4f parentInv = pParent.isNull() ? Matrix4f.IDENTITY : this.getMatrix(objectStructure, "parentinv");
//create the global matrix (without the scale)
Matrix4f globalMatrix = new Matrix4f();
@ -296,7 +317,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
size.get(2).floatValue() * scaleZ);
//the root object is transformed if the Y axis is UP
if(parent.isNull() && fixUpAxis) {
if(fixUpAxis && (pParent.isNull() || (parent!=null && !this.shouldBeLoaded(parent, dataRepository)))) {
float y = translation.y;
translation.y = translation.z;
translation.z = -y;
@ -343,4 +364,11 @@ public class ObjectHelper extends AbstractBlenderHelper {
public void clearState() {
fixUpAxis = false;
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
int lay = ((Number) structure.getFieldValue("lay")).intValue();
return ((lay & dataRepository.getBlenderKey().getLayersToLoad()) != 0
&& (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.OBJECTS) != 0);
}
}

@ -187,4 +187,9 @@ public class ParticlesHelper extends AbstractBlenderHelper {
}
return result;
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return true;
}
}

@ -42,6 +42,7 @@ import java.util.logging.Logger;
import com.jme3.asset.AssetNotFoundException;
import com.jme3.asset.TextureKey;
import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.math.FastMath;
import com.jme3.scene.plugins.blender.data.FileBlockHeader;
import com.jme3.scene.plugins.blender.data.Structure;
@ -1779,6 +1780,11 @@ public class TextureHelper extends AbstractBlenderHelper {
return result;
}
}
@Override
public boolean shouldBeLoaded(Structure structure, DataRepository dataRepository) {
return (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.TEXTURES) != 0;
}
/**
* Image types that can be loaded. AWT: png, jpg, jped or bmp TGA: tga DDS: DirectX image files

@ -139,20 +139,21 @@ public abstract class AbstractInfluenceFunction {
* @throws BlenderFileException this exception is thrown if the blend file is somehow corrupted
*/
protected Object getTarget(Constraint constraint, LoadedFeatureDataType loadedFeatureDataType) throws BlenderFileException {
//TODO: load the feature through objectHelper, this way we are certain the object loads and has
//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);
//subtarget goes first
//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) {
//TODO: what if it is not yet loaded ???
return dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
result = dataRepository.getLoadedFeature(subtargetName, loadedFeatureDataType);
}
//and now use the target
Long targetOMA = ((Pointer) constraint.getData().getFieldValue("target")).getOldMemoryAddress();
Structure objectStructure = dataRepository.getFileBlock(targetOMA).getStructure(dataRepository);
return objectHelper.toObject(objectStructure, dataRepository);
return result;
}
/**

@ -0,0 +1,129 @@
package com.jme3.scene.plugins.blender.structures;
import java.util.Arrays;
import com.jme3.animation.Bone;
import com.jme3.animation.BoneTrack;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
/**
* The purpose of this class is to imitate bone's movement when calculating inverse kinematics.
* @author Marcin Roguski
*/
public class CalculationBone extends Node {
private Bone bone;
/** The bone's tracks. Will be altered at the end of calculation process. */
private BoneTrack track;
/** The starting position of the bone. */
private Vector3f startTranslation;
/** The starting rotation of the bone. */
private Quaternion startRotation;
/** The starting scale of the bone. */
private Vector3f startScale;
private Vector3f[] translations;
private Quaternion[] rotations;
private Vector3f[] scales;
public CalculationBone(Bone bone, int boneFramesCount) {
this.bone = bone;
this.startRotation = bone.getModelSpaceRotation().clone();
this.startTranslation = bone.getModelSpacePosition().clone();
this.startScale = bone.getModelSpaceScale().clone();
this.reset();
if(boneFramesCount > 0) {
this.translations = new Vector3f[boneFramesCount];
this.rotations = new Quaternion[boneFramesCount];
this.scales = new Vector3f[boneFramesCount];
Arrays.fill(this.translations, 0, boneFramesCount, this.startTranslation);
Arrays.fill(this.rotations, 0, boneFramesCount, this.startRotation);
Arrays.fill(this.scales, 0, boneFramesCount, this.startScale);
}
}
/**
* Constructor. Stores the track, starting transformation and sets the transformation to the starting positions.
* @param bone
* the bone this class will imitate
* @param track
* the bone's tracks
*/
public CalculationBone(Bone bone, BoneTrack track) {
this(bone, 0);
this.track = track;
this.translations = track.getTranslations();
this.rotations = track.getRotations();
this.scales = track.getScales();
}
public int getBoneFramesCount() {
return this.translations==null ? 0 : this.translations.length;
}
/**
* This method returns the end point of the bone. If the bone has parent it is calculated from the start point
* of parent to the start point of this bone. If the bone doesn't have a parent the end location is considered
* to be 1 point up along Y axis (scale is applied if set to != 1.0);
* @return the end point of this bone
*/
//TODO: set to Z axis if user defined it this way
public Vector3f getEndPoint() {
if (this.getParent() == null) {
return new Vector3f(0, this.getLocalScale().y, 0);
} else {
Node parent = this.getParent();
return parent.getWorldTranslation().subtract(this.getWorldTranslation()).multLocal(this.getWorldScale());
}
}
/**
* This method resets the calculation bone to the starting position.
*/
public void reset() {
this.setLocalTranslation(startTranslation);
this.setLocalRotation(startRotation);
this.setLocalScale(startScale);
}
@Override
public int attachChild(Spatial child) {
if (this.getChildren() != null && this.getChildren().size() > 1) {
throw new IllegalStateException(this.getClass().getName() + " class instance can only have one child!");
}
return super.attachChild(child);
}
public Spatial rotate(Quaternion rot, int frame) {
Spatial spatial = super.rotate(rot);
this.updateWorldTransforms();
if (this.getChildren() != null && this.getChildren().size() > 0) {
CalculationBone child = (CalculationBone) this.getChild(0);
child.updateWorldTransforms();
}
rotations[frame].set(this.getLocalRotation());
translations[frame].set(this.getLocalTranslation());
if (scales != null) {
scales[frame].set(this.getLocalScale());
}
return spatial;
}
public void applyCalculatedTracks() {
if(track != null) {
track.setKeyframes(track.getTimes(), translations, rotations);//TODO:scales
} else {
bone.setUserControl(true);
bone.setUserTransforms(translations[0], rotations[0], scales[0]);
bone.setUserControl(false);
bone.updateWorldVectors();
}
}
@Override
public String toString() {
return bone.getName() + ": " + this.getLocalRotation() + " " + this.getLocalTranslation();
}
}

@ -127,4 +127,15 @@ public abstract class AbstractBlenderHelper {
}
return properties;
}
/**
* This method analyzes the given structure and the data contained within
* data repository and decides if the feature should be loaded.
* @param structure
* structure to be analyzed
* @param dataRepository
* the data repository
* @return <b>true</b> if the feature should be loaded and false otherwise
*/
public abstract boolean shouldBeLoaded(Structure structure, DataRepository dataRepository);
}

@ -32,7 +32,6 @@
package com.jme3.scene.plugins.blender.utils;
import java.util.List;
import java.util.logging.Logger;
import com.jme3.asset.BlenderKey.FeaturesToLoad;
import com.jme3.asset.BlenderKey.WorldData;
@ -57,7 +56,6 @@ import com.jme3.scene.plugins.blender.helpers.ObjectHelper;
*/
public class JmeConverter implements BlenderConverter<Node, Camera, Light, Object, List<Geometry>, Material> {
private static final Logger LOGGER = Logger.getLogger(JmeConverter.class.getName());
private final DataRepository dataRepository;
/**
@ -104,46 +102,47 @@ public class JmeConverter implements BlenderConverter<Node, Camera, Light, Objec
@Override
public Camera toCamera(Structure structure) throws BlenderFileException {
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.CAMERAS) == 0) {
return null;
CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
if (cameraHelper.shouldBeLoaded(structure, dataRepository)) {
return cameraHelper.toCamera(structure);
}
CameraHelper cameraHelper = dataRepository.getHelper(CameraHelper.class);
return cameraHelper.toCamera(structure);
return null;
}
@Override
public Light toLight(Structure structure) throws BlenderFileException {
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.LIGHTS) == 0) {
return null;
LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
if (lightHelper.shouldBeLoaded(structure, dataRepository)) {
return lightHelper.toLight(structure, dataRepository);
}
LightHelper lightHelper = dataRepository.getHelper(LightHelper.class);
return lightHelper.toLight(structure, dataRepository);
return null;
}
@Override
public Object toObject(Structure structure) throws BlenderFileException {
int lay = ((Number) structure.getFieldValue("lay")).intValue();
if ((lay & dataRepository.getBlenderKey().getLayersToLoad()) == 0
|| (dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.OBJECTS) == 0) {
return null;
}
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class);
return objectHelper.toObject(structure, dataRepository);
if(objectHelper.shouldBeLoaded(structure, dataRepository)) {
return objectHelper.toObject(structure, dataRepository);
}
return null;
}
@Override
public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
MeshHelper meshHelper = dataRepository.getHelper(MeshHelper.class);
return meshHelper.toMesh(structure, dataRepository);
if(meshHelper.shouldBeLoaded(structure, dataRepository)) {
return meshHelper.toMesh(structure, dataRepository);
}
return null;
}
@Override
public Material toMaterial(Structure structure) throws BlenderFileException {
if ((dataRepository.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) == 0) {
return null;
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
if (materialHelper.shouldBeLoaded(structure, dataRepository)) {
return materialHelper.toMaterial(structure, dataRepository);
}
MaterialHelper materialHelper = dataRepository.getHelper(MaterialHelper.class);
return materialHelper.toMaterial(structure, dataRepository);
return null;
}
/**

Loading…
Cancel
Save