aboutsummaryrefslogtreecommitdiff
path: root/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java')
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java302
1 files changed, 302 insertions, 0 deletions
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java
new file mode 100644
index 0000000..b08a20c
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/constraints/Feature.java
@@ -0,0 +1,302 @@
+package com.jme3.scene.plugins.blender.constraints;
+
+import com.jme3.animation.Bone;
+import com.jme3.math.Matrix4f;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Transform;
+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.Constraint.Space;
+import com.jme3.scene.plugins.blender.file.DynamicArray;
+import com.jme3.scene.plugins.blender.file.Structure;
+
+/**
+ * This class represents either owner or target of the constraint. It has the
+ * common methods that take the evalueation space of the feature.
+ *
+ * @author Marcin Roguski (Kaelthas)
+ */
+/* package */class Feature {
+ /** The evalueation space. */
+ protected Space space;
+ /** Old memory address of the feature. */
+ protected Long oma;
+ /** The spatial that is hold by the Feature. */
+ protected Spatial spatial;
+ /** The bone that is hold by the Feature. */
+ protected Bone bone;
+ /** The blender context. */
+ protected BlenderContext blenderContext;
+
+ /**
+ * Constructs the feature. This object should be loaded later
+ * when it is read from the blender file.
+ * The update method should be called before the feature is used.
+ *
+ * @param space
+ * the spatial's evaluation space
+ * @param oma
+ * the spatial's old memory address
+ * @param blenderContext
+ * the blender context
+ */
+ public Feature(Space space, Long oma, BlenderContext blenderContext) {
+ this.space = space;
+ this.oma = oma;
+ this.blenderContext = blenderContext;
+ }
+
+ /**
+ * Constructs the feature based on spatial.
+ *
+ * @param spatial
+ * the spatial
+ * @param space
+ * the spatial's evaluation space
+ * @param oma
+ * the spatial's old memory address
+ * @param blenderContext
+ * the blender context
+ */
+ public Feature(Spatial spatial, Space space, Long oma, BlenderContext blenderContext) {
+ this(space, oma, blenderContext);
+ this.blenderContext = blenderContext;
+ }
+
+ /**
+ * Constructs the feature based on bone.
+ *
+ * @param bone
+ * the bone
+ * @param space
+ * the bone evaluation space
+ * @param oma
+ * the bone old memory address
+ * @param blenderContext
+ * the blender context
+ */
+ public Feature(Bone bone, Space space, Long oma, BlenderContext blenderContext) {
+ this(space, oma, blenderContext);
+ this.bone = bone;
+ }
+
+ /**
+ * This method should be called before the feature is used.
+ * It may happen that the object this feature refers to was not yet loaded from blend file
+ * when the instance of this class was created.
+ */
+ public void update() {
+ Object owner = blenderContext.getLoadedFeature(oma, LoadedFeatureDataType.LOADED_FEATURE);
+ if(owner instanceof Spatial) {
+ this.spatial = (Spatial) owner;
+ } else if(owner instanceof Bone) {
+ this.bone = (Bone) owner;
+ } else {
+ throw new IllegalStateException("Unknown type of owner: " + owner.getClass());
+ }
+ }
+
+ /**
+ * @return the feature's old memory address
+ */
+ public Long getOma() {
+ return oma;
+ }
+
+ /**
+ * @return the object held by the feature (either bone or spatial)
+ */
+ public Object getObject() {
+ if (spatial != null) {
+ return spatial;
+ }
+ return bone;
+ }
+
+ /**
+ * @return the feature's transform depending on the evaluation space
+ */
+ @SuppressWarnings("unchecked")
+ public Transform getTransform() {
+ if (spatial != null) {
+ switch (space) {
+ case CONSTRAINT_SPACE_LOCAL:
+ Structure targetStructure = (Structure) blenderContext.getLoadedFeature(oma, LoadedFeatureDataType.LOADED_STRUCTURE);
+
+ DynamicArray<Number> locArray = ((DynamicArray<Number>) targetStructure.getFieldValue("loc"));
+ Vector3f loc = new Vector3f(locArray.get(0).floatValue(), locArray.get(1).floatValue(), locArray.get(2).floatValue());
+ DynamicArray<Number> rotArray = ((DynamicArray<Number>) targetStructure.getFieldValue("rot"));
+ Quaternion rot = new Quaternion(new float[] { rotArray.get(0).floatValue(), rotArray.get(1).floatValue(), rotArray.get(2).floatValue() });
+ DynamicArray<Number> sizeArray = ((DynamicArray<Number>) targetStructure.getFieldValue("size"));
+ Vector3f size = new Vector3f(sizeArray.get(0).floatValue(), sizeArray.get(1).floatValue(), sizeArray.get(2).floatValue());
+
+ if (blenderContext.getBlenderKey().isFixUpAxis()) {
+ float y = loc.y;
+ loc.y = loc.z;
+ loc.z = -y;
+
+ y = rot.getY();
+ float z = rot.getZ();
+ rot.set(rot.getX(), z, -y, rot.getW());
+
+ y = size.y;
+ size.y = size.z;
+ size.z = y;
+ }
+
+ Transform result = new Transform(loc, rot);
+ result.setScale(size);
+ return result;
+ case CONSTRAINT_SPACE_WORLD:
+ return spatial.getWorldTransform();
+ default:
+ throw new IllegalStateException("Invalid space type for target object: " + space.toString());
+ }
+ }
+ // Bone
+ switch (space) {
+ case CONSTRAINT_SPACE_LOCAL:
+ Transform localTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
+ localTransform.setScale(bone.getLocalScale());
+ return localTransform;
+ case CONSTRAINT_SPACE_WORLD:
+ Transform worldTransform = new Transform(bone.getWorldBindPosition(), bone.getWorldBindRotation());
+ worldTransform.setScale(bone.getWorldBindScale());
+ return worldTransform;
+ case CONSTRAINT_SPACE_POSE:
+ Transform poseTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
+ poseTransform.setScale(bone.getLocalScale());
+ return poseTransform;
+ case CONSTRAINT_SPACE_PARLOCAL:
+ Transform parentLocalTransform = new Transform(bone.getLocalPosition(), bone.getLocalRotation());
+ parentLocalTransform.setScale(bone.getLocalScale());
+ return parentLocalTransform;
+ default:
+ throw new IllegalStateException("Invalid space type for target object: " + space.toString());
+ }
+ }
+
+ /**
+ * This method applies the given transform to the feature in the proper
+ * evaluation space.
+ *
+ * @param transform
+ * the transform to be applied
+ */
+ public void applyTransform(Transform transform) {
+ if (spatial != null) {
+ switch (space) {
+ case CONSTRAINT_SPACE_LOCAL:
+ Transform ownerLocalTransform = spatial.getLocalTransform();
+ ownerLocalTransform.getTranslation().addLocal(transform.getTranslation());
+ ownerLocalTransform.getRotation().multLocal(transform.getRotation());
+ ownerLocalTransform.getScale().multLocal(transform.getScale());
+ break;
+ case CONSTRAINT_SPACE_WORLD:
+ Matrix4f m = this.getParentWorldTransformMatrix();
+ m.invertLocal();
+ Matrix4f matrix = this.toMatrix(transform);
+ m.multLocal(matrix);
+
+ float scaleX = (float) Math.sqrt(m.m00 * m.m00 + m.m10 * m.m10 + m.m20 * m.m20);
+ float scaleY = (float) Math.sqrt(m.m01 * m.m01 + m.m11 * m.m11 + m.m21 * m.m21);
+ float scaleZ = (float) Math.sqrt(m.m02 * m.m02 + m.m12 * m.m12 + m.m22 * m.m22);
+
+ transform.setTranslation(m.toTranslationVector());
+ transform.setRotation(m.toRotationQuat());
+ transform.setScale(scaleX, scaleY, scaleZ);
+ spatial.setLocalTransform(transform);
+ break;
+ case CONSTRAINT_SPACE_PARLOCAL:
+ case CONSTRAINT_SPACE_POSE:
+ throw new IllegalStateException("Invalid space type (" + space.toString() + ") for owner object.");
+ default:
+ throw new IllegalStateException("Invalid space type for target object: " + space.toString());
+ }
+ } else {// Bone
+ switch (space) {
+ case CONSTRAINT_SPACE_LOCAL:
+ bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
+ break;
+ case CONSTRAINT_SPACE_WORLD:
+ Matrix4f m = this.getParentWorldTransformMatrix();
+// m.invertLocal();
+ transform.setTranslation(m.mult(transform.getTranslation()));
+ transform.setRotation(m.mult(transform.getRotation(), null));
+ transform.setScale(transform.getScale());
+ bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
+// float x = FastMath.HALF_PI/2;
+// float y = -FastMath.HALF_PI;
+// float z = -FastMath.HALF_PI/2;
+// bone.setBindTransforms(new Vector3f(0,0,0), new Quaternion().fromAngles(x, y, z), new Vector3f(1,1,1));
+ break;
+ case CONSTRAINT_SPACE_PARLOCAL:
+ Vector3f parentLocalTranslation = bone.getLocalPosition().add(transform.getTranslation());
+ Quaternion parentLocalRotation = bone.getLocalRotation().mult(transform.getRotation());
+ bone.setBindTransforms(parentLocalTranslation, parentLocalRotation, transform.getScale());
+ break;
+ case CONSTRAINT_SPACE_POSE:
+ bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
+ break;
+ default:
+ throw new IllegalStateException("Invalid space type for target object: " + space.toString());
+ }
+ }
+ }
+
+ /**
+ * @return world transform matrix of the feature
+ */
+ public Matrix4f getWorldTransformMatrix() {
+ if (spatial != null) {
+ Matrix4f result = new Matrix4f();
+ Transform t = spatial.getWorldTransform();
+ result.setTransform(t.getTranslation(), t.getScale(), t.getRotation().toRotationMatrix());
+ return result;
+ }
+ // Bone
+ Matrix4f result = new Matrix4f();
+ result.setTransform(bone.getWorldBindPosition(), bone.getWorldBindScale(), bone.getWorldBindRotation().toRotationMatrix());
+ return result;
+ }
+
+ /**
+ * @return world transform matrix of the feature's parent or identity matrix
+ * if the feature has no parent
+ */
+ public Matrix4f getParentWorldTransformMatrix() {
+ Matrix4f result = new Matrix4f();
+ if (spatial != null) {
+ if (spatial.getParent() != null) {
+ Transform t = spatial.getParent().getWorldTransform();
+ result.setTransform(t.getTranslation(), t.getScale(), t.getRotation().toRotationMatrix());
+ }
+ } else {// Bone
+ Bone parent = bone.getParent();
+ if (parent != null) {
+ result.setTransform(parent.getWorldBindPosition(), parent.getWorldBindScale(), parent.getWorldBindRotation().toRotationMatrix());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts given transform to the matrix.
+ *
+ * @param transform
+ * the transform to be converted
+ * @return 4x4 matri that represents the given transform
+ */
+ protected Matrix4f toMatrix(Transform transform) {
+ Matrix4f result = Matrix4f.IDENTITY;
+ if (transform != null) {
+ result = new Matrix4f();
+ result.setTranslation(transform.getTranslation());
+ result.setRotationQuaternion(transform.getRotation());
+ result.setScale(transform.getScale());
+ }
+ return result;
+ }
+}