Bugfix: fixed an issue with proper bone orientation in 3D space (as in blender bones have different local coordinates system than other features); this fix caused more models to be loaded properly and made the code more simple
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10840 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
c0f0f0ca9e
commit
32b79324a9
@ -41,7 +41,6 @@ import java.util.logging.Logger;
|
||||
import com.jme3.animation.Bone;
|
||||
import com.jme3.animation.BoneTrack;
|
||||
import com.jme3.animation.Skeleton;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
|
||||
import com.jme3.scene.plugins.blender.BlenderContext;
|
||||
import com.jme3.scene.plugins.blender.curves.BezierCurve;
|
||||
@ -76,21 +75,25 @@ public class ArmatureHelper extends AbstractBlenderHelper {
|
||||
/**
|
||||
* This method builds the object's bones structure.
|
||||
*
|
||||
* @param armatureObjectOMA
|
||||
* the OMa of the armature node
|
||||
* @param boneStructure
|
||||
* the structure containing the bones' data
|
||||
* @param parent
|
||||
* the parent bone
|
||||
* @param result
|
||||
* the list where the newly created bone will be added
|
||||
* @param spatialOMA
|
||||
* the OMA of the spatial that will own the skeleton
|
||||
* @param blenderContext
|
||||
* the blender context
|
||||
* @throws BlenderFileException
|
||||
* an exception is thrown when there is problem with the blender
|
||||
* file
|
||||
*/
|
||||
public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Matrix4f objectToArmatureTransformation, BlenderContext blenderContext) throws BlenderFileException {
|
||||
public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Long spatialOMA, BlenderContext blenderContext) throws BlenderFileException {
|
||||
BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, blenderContext);
|
||||
bc.buildBone(result, objectToArmatureTransformation, blenderContext);
|
||||
bc.buildBone(result, spatialOMA, blenderContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,10 @@ import com.jme3.animation.Skeleton;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.plugins.blender.BlenderContext;
|
||||
import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType;
|
||||
import com.jme3.scene.plugins.blender.constraints.ConstraintHelper;
|
||||
import com.jme3.scene.plugins.blender.file.BlenderFileException;
|
||||
import com.jme3.scene.plugins.blender.file.Structure;
|
||||
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
@ -19,27 +22,36 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
public class BoneContext {
|
||||
private BlenderContext blenderContext;
|
||||
// the flags of the bone
|
||||
private static final int CONNECTED_TO_PARENT = 0x10;
|
||||
|
||||
/**
|
||||
* The bones' matrices have, unlike objects', the coordinate system identical to JME's (Y axis is UP, X to the right and Z toward us).
|
||||
* So in order to have them loaded properly we need to transform their armature matrix (which blender sees as rotated) to make sure we get identical results.
|
||||
*/
|
||||
private static final Matrix4f BONE_ARMATURE_TRANSFORMATION_MATRIX = new Matrix4f(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
|
||||
|
||||
private BlenderContext blenderContext;
|
||||
/** The OMA of the bone's armature object. */
|
||||
private Long armatureObjectOMA;
|
||||
private Long armatureObjectOMA;
|
||||
/** The structure of the bone. */
|
||||
private Structure boneStructure;
|
||||
private Structure boneStructure;
|
||||
/** Bone's name. */
|
||||
private String boneName;
|
||||
/** The bone's armature matrix. */
|
||||
private Matrix4f armatureMatrix;
|
||||
private String boneName;
|
||||
/** The bone's flag. */
|
||||
private int flag;
|
||||
/** The bone's matrix in world space. */
|
||||
private Matrix4f globalBoneMatrix;
|
||||
/** The bone's matrix in the model space. */
|
||||
private Matrix4f boneMatrixInModelSpace;
|
||||
/** The parent context. */
|
||||
private BoneContext parent;
|
||||
private BoneContext parent;
|
||||
/** The children of this context. */
|
||||
private List<BoneContext> children = new ArrayList<BoneContext>();
|
||||
private List<BoneContext> children = new ArrayList<BoneContext>();
|
||||
/** Created bone (available after calling 'buildBone' method). */
|
||||
private Bone bone;
|
||||
/** The bone's rest matrix. */
|
||||
private Matrix4f restMatrix;
|
||||
/** Bone's total inverse transformation. */
|
||||
private Matrix4f inverseTotalTransformation;
|
||||
private Bone bone;
|
||||
/** The length of the bone. */
|
||||
private float length;
|
||||
private float length;
|
||||
|
||||
/**
|
||||
* Constructor. Creates the basic set of bone's data.
|
||||
@ -79,21 +91,26 @@ public class BoneContext {
|
||||
this.boneStructure = boneStructure;
|
||||
this.armatureObjectOMA = armatureObjectOMA;
|
||||
boneName = boneStructure.getFieldValue("name").toString();
|
||||
flag = ((Number) boneStructure.getFieldValue("flag")).intValue();
|
||||
length = ((Number) boneStructure.getFieldValue("length")).floatValue();
|
||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||
armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis());
|
||||
|
||||
// compute the bone's rest matrix
|
||||
restMatrix = armatureMatrix.clone();
|
||||
inverseTotalTransformation = restMatrix.invert();
|
||||
if (parent != null) {
|
||||
restMatrix = parent.inverseTotalTransformation.mult(restMatrix);
|
||||
}
|
||||
// first get the bone matrix in its armature space
|
||||
globalBoneMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis());
|
||||
// then make sure it is rotated in a proper way to fit the jme bone transformation conventions
|
||||
globalBoneMatrix.multLocal(BONE_ARMATURE_TRANSFORMATION_MATRIX);
|
||||
|
||||
Spatial armature = (Spatial) blenderContext.getLoadedFeature(armatureObjectOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
|
||||
Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform());
|
||||
|
||||
// and now compute the final bone matrix in world space
|
||||
globalBoneMatrix = armatureWorldMatrix.mult(globalBoneMatrix);
|
||||
|
||||
// create the children
|
||||
List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext);
|
||||
for (Structure child : childbase) {
|
||||
this.children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext));
|
||||
children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext));
|
||||
}
|
||||
|
||||
blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this);
|
||||
@ -104,31 +121,36 @@ public class BoneContext {
|
||||
*
|
||||
* @param bones
|
||||
* a list of bones where the newly created bone will be added
|
||||
* @param objectToArmatureMatrix
|
||||
* object to armature transformation matrix
|
||||
* @param skeletonOwnerOma
|
||||
* the spatial of the object that will own the skeleton
|
||||
* @param blenderContext
|
||||
* the blender context
|
||||
* @return newly created bone
|
||||
*/
|
||||
public Bone buildBone(List<Bone> bones, Matrix4f objectToArmatureMatrix, BlenderContext blenderContext) {
|
||||
public Bone buildBone(List<Bone> bones, Long skeletonOwnerOma, BlenderContext blenderContext) {
|
||||
Long boneOMA = boneStructure.getOldMemoryAddress();
|
||||
bone = new Bone(boneName);
|
||||
bones.add(bone);
|
||||
blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone);
|
||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||
|
||||
Vector3f poseLocation = restMatrix.toTranslationVector();
|
||||
Quaternion rotation = restMatrix.toRotationQuat().normalizeLocal();
|
||||
Vector3f scale = restMatrix.toScaleVector();
|
||||
if (parent == null) {
|
||||
Quaternion rotationQuaternion = objectToArmatureMatrix.toRotationQuat().normalizeLocal();
|
||||
scale.multLocal(objectToArmatureMatrix.toScaleVector());
|
||||
rotationQuaternion.multLocal(poseLocation.addLocal(objectToArmatureMatrix.toTranslationVector()));
|
||||
rotation.multLocal(rotationQuaternion);
|
||||
Structure skeletonOwnerObjectStructure = (Structure) blenderContext.getLoadedFeature(skeletonOwnerOma, LoadedFeatureDataType.LOADED_STRUCTURE);
|
||||
Matrix4f invertedObjectOwnerGlobalMatrix = objectHelper.getMatrix(skeletonOwnerObjectStructure, "imat", blenderContext.getBlenderKey().isFixUpAxis());
|
||||
if (objectHelper.isParent(skeletonOwnerOma, armatureObjectOMA)) {
|
||||
boneMatrixInModelSpace = globalBoneMatrix.mult(invertedObjectOwnerGlobalMatrix);
|
||||
} else {
|
||||
boneMatrixInModelSpace = invertedObjectOwnerGlobalMatrix.mult(globalBoneMatrix);
|
||||
}
|
||||
|
||||
Matrix4f boneLocalMatrix = parent == null ? boneMatrixInModelSpace : parent.boneMatrixInModelSpace.invert().multLocal(boneMatrixInModelSpace);
|
||||
|
||||
Vector3f poseLocation = parent == null || !this.is(CONNECTED_TO_PARENT) ? boneLocalMatrix.toTranslationVector() : new Vector3f(0, parent.length, 0);
|
||||
Quaternion rotation = boneLocalMatrix.toRotationQuat().normalizeLocal();
|
||||
Vector3f scale = boneLocalMatrix.toScaleVector();
|
||||
|
||||
bone.setBindTransforms(poseLocation, rotation, scale);
|
||||
for (BoneContext child : children) {
|
||||
bone.addChild(child.buildBone(bones, objectToArmatureMatrix, blenderContext));
|
||||
bone.addChild(child.buildBone(bones, skeletonOwnerOma, blenderContext));
|
||||
}
|
||||
|
||||
return bone;
|
||||
@ -168,4 +190,14 @@ public class BoneContext {
|
||||
public Skeleton getSkeleton() {
|
||||
return blenderContext.getSkeleton(armatureObjectOMA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the bone is of specified property defined by its flag.
|
||||
* @param flagMask
|
||||
* the mask of the flag (constants defined in this class)
|
||||
* @return <b>true</b> if the bone IS of specified proeprty and <b>false</b> otherwise
|
||||
*/
|
||||
private boolean is(int flagMask) {
|
||||
return (flag & flagMask) != 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.jme3.scene.plugins.blender.animations;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.jme3.animation.BoneTrack;
|
||||
@ -148,6 +149,11 @@ public class Ipo {
|
||||
if (blenderVersion < 250) {// in blender earlier than 2.50 the values are stored in degrees
|
||||
degreeToRadiansFactor *= FastMath.DEG_TO_RAD * 10;// the values in blender are divided by 10, so we need to mult it here
|
||||
}
|
||||
int yIndex = 1, zIndex = 2;
|
||||
if(spatialTrack && fixUpAxis) {
|
||||
yIndex = 2;
|
||||
zIndex = 1;
|
||||
}
|
||||
|
||||
// calculating track data
|
||||
for (int frame = startFrame; frame <= stopFrame; ++frame) {
|
||||
@ -157,36 +163,30 @@ public class Ipo {
|
||||
for (int j = 0; j < bezierCurves.length; ++j) {
|
||||
double value = bezierCurves[j].evaluate(frame, BezierCurve.Y_VALUE);
|
||||
switch (bezierCurves[j].getType()) {
|
||||
// LOCATION
|
||||
// LOCATION
|
||||
case AC_LOC_X:
|
||||
translation[0] = (float) value;
|
||||
break;
|
||||
case AC_LOC_Y:
|
||||
if (fixUpAxis) {
|
||||
translation[2] = value == 0.0f ? 0 : (float) -value;
|
||||
} else {
|
||||
translation[1] = (float) value;
|
||||
}
|
||||
translation[yIndex] = (float) value;
|
||||
break;
|
||||
case AC_LOC_Z:
|
||||
translation[fixUpAxis ? 1 : 2] = (float) value;
|
||||
translation[zIndex] = (float) value;
|
||||
break;
|
||||
|
||||
// ROTATION (used with object animation)
|
||||
// the value here is in degrees divided by 10 (so in
|
||||
// example: 9 = PI/2)
|
||||
case OB_ROT_X:
|
||||
objectRotation[0] = (float) value * degreeToRadiansFactor;
|
||||
break;
|
||||
case OB_ROT_Y:
|
||||
if (fixUpAxis) {
|
||||
objectRotation[2] = value == 0.0f ? 0 : (float) -value * degreeToRadiansFactor;
|
||||
objectRotation[yIndex] = value == 0.0f ? 0 : (float) -value * degreeToRadiansFactor;
|
||||
} else {
|
||||
objectRotation[1] = (float) value * degreeToRadiansFactor;
|
||||
objectRotation[yIndex] = (float) value * degreeToRadiansFactor;
|
||||
}
|
||||
break;
|
||||
case OB_ROT_Z:
|
||||
objectRotation[fixUpAxis ? 1 : 2] = (float) value * degreeToRadiansFactor;
|
||||
objectRotation[zIndex] = (float) value * degreeToRadiansFactor;
|
||||
break;
|
||||
|
||||
// SIZE
|
||||
@ -200,9 +200,7 @@ public class Ipo {
|
||||
scale[fixUpAxis ? 1 : 2] = (float) value;
|
||||
break;
|
||||
|
||||
// QUATERNION ROTATION (used with bone animation), dunno
|
||||
// why but here we shouldn't check the
|
||||
// spatialTrack flag value
|
||||
// QUATERNION ROTATION (used with bone animation)
|
||||
case AC_QUAT_W:
|
||||
quaternionRotation[3] = (float) value;
|
||||
break;
|
||||
@ -210,17 +208,13 @@ public class Ipo {
|
||||
quaternionRotation[0] = (float) value;
|
||||
break;
|
||||
case AC_QUAT_Y:
|
||||
if (fixUpAxis) {
|
||||
quaternionRotation[2] = value == 0.0f ? 0 : -(float) value;
|
||||
} else {
|
||||
quaternionRotation[1] = (float) value;
|
||||
}
|
||||
break;
|
||||
case AC_QUAT_Z:
|
||||
quaternionRotation[fixUpAxis ? 1 : 2] = (float) value;
|
||||
break;
|
||||
case AC_QUAT_Z:
|
||||
quaternionRotation[fixUpAxis ? 2 : 1] = (float) value;
|
||||
break;
|
||||
default:
|
||||
LOGGER.warning("Unknown ipo curve type: " + bezierCurves[j].getType());
|
||||
LOGGER.log(Level.WARNING, "Unknown ipo curve type: {0}.", bezierCurves[j].getType());
|
||||
}
|
||||
}
|
||||
translations[index] = localQuaternionRotation.multLocal(new Vector3f(translation[0], translation[1], translation[2]));
|
||||
|
@ -17,7 +17,6 @@ import com.jme3.animation.Bone;
|
||||
import com.jme3.animation.BoneTrack;
|
||||
import com.jme3.animation.Skeleton;
|
||||
import com.jme3.animation.SkeletonControl;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
@ -35,7 +34,6 @@ import com.jme3.scene.plugins.blender.file.FileBlockHeader;
|
||||
import com.jme3.scene.plugins.blender.file.Pointer;
|
||||
import com.jme3.scene.plugins.blender.file.Structure;
|
||||
import com.jme3.scene.plugins.blender.meshes.MeshContext;
|
||||
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
import com.jme3.util.BufferUtils;
|
||||
|
||||
/**
|
||||
@ -85,17 +83,10 @@ import com.jme3.util.BufferUtils;
|
||||
|
||||
// load skeleton
|
||||
Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
|
||||
|
||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||
boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
|
||||
Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis);
|
||||
Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis);
|
||||
Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix);
|
||||
|
||||
List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext);
|
||||
List<Bone> bonesList = new ArrayList<Bone>();
|
||||
for (int i = 0; i < bonebase.size(); ++i) {
|
||||
armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, blenderContext);
|
||||
armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectStructure.getOldMemoryAddress(), blenderContext);
|
||||
}
|
||||
bonesList.add(0, new Bone(""));
|
||||
Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
|
||||
@ -105,7 +96,7 @@ import com.jme3.util.BufferUtils;
|
||||
this.meshStructure = meshStructure;
|
||||
|
||||
// read mesh indexes
|
||||
this.meshOMA = meshStructure.getOldMemoryAddress();
|
||||
meshOMA = meshStructure.getOldMemoryAddress();
|
||||
|
||||
// read animations
|
||||
ArrayList<Animation> animations = new ArrayList<Animation>();
|
||||
|
@ -44,6 +44,7 @@ import com.jme3.math.Transform;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.Spatial.CullHint;
|
||||
import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
|
||||
import com.jme3.scene.plugins.blender.BlenderContext;
|
||||
@ -67,9 +68,9 @@ import com.jme3.scene.plugins.blender.modifiers.ModifierHelper;
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
public class ObjectHelper extends AbstractBlenderHelper {
|
||||
private static final Logger LOGGER = Logger.getLogger(ObjectHelper.class.getName());
|
||||
private static final Logger LOGGER = Logger.getLogger(ObjectHelper.class.getName());
|
||||
|
||||
public static final String OMA_MARKER = "oma";
|
||||
public static final String OMA_MARKER = "oma";
|
||||
|
||||
/**
|
||||
* This constructor parses the given blender version and stores the result.
|
||||
@ -98,28 +99,28 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
||||
*/
|
||||
public Object toObject(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
|
||||
LOGGER.fine("Loading blender object.");
|
||||
|
||||
|
||||
int type = ((Number) objectStructure.getFieldValue("type")).intValue();
|
||||
ObjectType objectType = ObjectType.valueOf(type);
|
||||
LOGGER.log(Level.FINE, "Type of the object: {0}.", objectType);
|
||||
if(objectType == ObjectType.LAMP && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.LIGHTS)) {
|
||||
if (objectType == ObjectType.LAMP && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.LIGHTS)) {
|
||||
LOGGER.fine("Lamps are not included in loading.");
|
||||
return null;
|
||||
}
|
||||
if(objectType == ObjectType.CAMERA && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.CAMERAS)) {
|
||||
if (objectType == ObjectType.CAMERA && !blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.CAMERAS)) {
|
||||
LOGGER.fine("Cameras are not included in loading.");
|
||||
return null;
|
||||
}
|
||||
if(!blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.OBJECTS)) {
|
||||
if (!blenderContext.getBlenderKey().shouldLoad(FeaturesToLoad.OBJECTS)) {
|
||||
LOGGER.fine("Objects are not included in loading.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
int lay = ((Number) objectStructure.getFieldValue("lay")).intValue();
|
||||
if((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
|
||||
if ((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
|
||||
LOGGER.fine("The layer this object is located in is not included in loading.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
LOGGER.fine("Checking if the object has not been already loaded.");
|
||||
Object loadedResult = blenderContext.getLoadedFeature(objectStructure.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
|
||||
if (loadedResult != null) {
|
||||
@ -201,29 +202,29 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
||||
|
||||
if (result != null) {
|
||||
blenderContext.addLoadedFeatures(objectStructure.getOldMemoryAddress(), name, objectStructure, result);
|
||||
|
||||
|
||||
result.setLocalTransform(t);
|
||||
result.setCullHint(visible ? CullHint.Always : CullHint.Inherit);
|
||||
if (parent instanceof Node) {
|
||||
((Node) parent).attachChild(result);
|
||||
}
|
||||
|
||||
|
||||
LOGGER.fine("Reading and applying object's modifiers.");
|
||||
ModifierHelper modifierHelper = blenderContext.getHelper(ModifierHelper.class);
|
||||
Collection<Modifier> modifiers = modifierHelper.readModifiers(objectStructure, blenderContext);
|
||||
for (Modifier modifier : modifiers) {
|
||||
modifier.apply(result, blenderContext);
|
||||
}
|
||||
|
||||
|
||||
// I prefer do compute bounding box here than read it from the file
|
||||
result.updateModelBound();
|
||||
|
||||
|
||||
LOGGER.fine("Applying markers (those will be removed before the final result is released).");
|
||||
blenderContext.addMarker(OMA_MARKER, result, objectStructure.getOldMemoryAddress());
|
||||
if(objectType == ObjectType.ARMATURE) {
|
||||
if (objectType == ObjectType.ARMATURE) {
|
||||
blenderContext.addMarker(ArmatureHelper.ARMATURE_NODE_MARKER, result, Boolean.TRUE);
|
||||
}
|
||||
|
||||
|
||||
LOGGER.fine("Loading constraints connected with this object.");
|
||||
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
|
||||
constraintHelper.loadConstraints(objectStructure, blenderContext);
|
||||
@ -241,6 +242,31 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the first given OMA points to a parent of the second one.
|
||||
* The parent need not to be the direct one. This method should be called when we are sure
|
||||
* that both of the features are alred loaded because it does not check it.
|
||||
* The OMA's should point to a spatials, otherwise the function will throw ClassCastException.
|
||||
* @param supposedParentOMA
|
||||
* the OMA of the node that we suppose might be a parent of the second one
|
||||
* @param spatialOMA
|
||||
* the OMA of the scene's node
|
||||
* @return <b>true</b> if the first given OMA points to a parent of the second one and <b>false</b> otherwise
|
||||
*/
|
||||
public boolean isParent(Long supposedParentOMA, Long spatialOMA) {
|
||||
Spatial supposedParent = (Spatial) blenderContext.getLoadedFeature(supposedParentOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||
Spatial spatial = (Spatial) blenderContext.getLoadedFeature(spatialOMA, LoadedFeatureDataType.LOADED_FEATURE);
|
||||
|
||||
Spatial parent = spatial.getParent();
|
||||
while (parent != null) {
|
||||
if (parent.equals(supposedParent)) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calculates local transformation for the object. Parentage is
|
||||
* taken under consideration.
|
||||
@ -320,7 +346,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
||||
public Matrix4f getMatrix(Structure structure, String matrixName, boolean applyFixUpAxis) {
|
||||
Matrix4f result = new Matrix4f();
|
||||
DynamicArray<Number> obmat = (DynamicArray<Number>) structure.getFieldValue(matrixName);
|
||||
//the matrix must be square
|
||||
// the matrix must be square
|
||||
int rowAndColumnSize = Math.abs((int) Math.sqrt(obmat.getTotalSize()));
|
||||
for (int i = 0; i < rowAndColumnSize; ++i) {
|
||||
for (int j = 0; j < rowAndColumnSize; ++j) {
|
||||
@ -361,29 +387,19 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static enum ObjectType {
|
||||
EMPTY(0),
|
||||
MESH(1),
|
||||
CURVE(2),
|
||||
SURF(3),
|
||||
TEXT(4),
|
||||
METABALL(5),
|
||||
LAMP(10),
|
||||
CAMERA(11),
|
||||
WAVE(21),
|
||||
LATTICE(22),
|
||||
ARMATURE(25);
|
||||
|
||||
EMPTY(0), MESH(1), CURVE(2), SURF(3), TEXT(4), METABALL(5), LAMP(10), CAMERA(11), WAVE(21), LATTICE(22), ARMATURE(25);
|
||||
|
||||
private int blenderTypeValue;
|
||||
|
||||
|
||||
private ObjectType(int blenderTypeValue) {
|
||||
this.blenderTypeValue = blenderTypeValue;
|
||||
}
|
||||
|
||||
|
||||
public static ObjectType valueOf(int blenderTypeValue) throws BlenderFileException {
|
||||
for(ObjectType type : ObjectType.values()) {
|
||||
if(type.blenderTypeValue == blenderTypeValue) {
|
||||
for (ObjectType type : ObjectType.values()) {
|
||||
if (type.blenderTypeValue == blenderTypeValue) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user