use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class Quaternion method toRotationMatrix.
/**
* <code>toRotationMatrix</code> converts this quaternion to a rotational
* matrix. The result is stored in result. 4th row and 4th column values are
* untouched. Note: the result is created from a normalized version of this quat.
*
* @param result
* The Matrix4f to store the result in.
* @return the rotation matrix representation of this quaternion.
*/
public Matrix4f toRotationMatrix(Matrix4f result) {
TempVars tempv = TempVars.get();
Vector3f originalScale = tempv.vect1;
result.toScaleVector(originalScale);
result.setScale(1, 1, 1);
float norm = norm();
// we explicitly test norm against one here, saving a division
// at the cost of a test and branch. Is it worth it?
float s = (norm == 1f) ? 2f : (norm > 0f) ? 2f / norm : 0;
// compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs
// will be used 2-4 times each.
float xs = x * s;
float ys = y * s;
float zs = z * s;
float xx = x * xs;
float xy = x * ys;
float xz = x * zs;
float xw = w * xs;
float yy = y * ys;
float yz = y * zs;
float yw = w * ys;
float zz = z * zs;
float zw = w * zs;
// using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here
result.m00 = 1 - (yy + zz);
result.m01 = (xy - zw);
result.m02 = (xz + yw);
result.m10 = (xy + zw);
result.m11 = 1 - (xx + zz);
result.m12 = (yz - xw);
result.m20 = (xz - yw);
result.m21 = (yz + xw);
result.m22 = 1 - (xx + yy);
result.setScale(originalScale);
tempv.release();
return result;
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class FbxBindPose method buildTransform.
private static Matrix4f buildTransform(double[] transform) {
float[] m = new float[transform.length];
for (int i = 0; i < transform.length; ++i) m[i] = (float) transform[i];
Matrix4f matrix = new Matrix4f();
matrix.set(m, false);
return matrix;
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class BoneContext method buildBone.
/**
* This method builds the bone. It recursively builds the bone's children.
*
* @param bones
* a list of bones where the newly created bone will be added
* @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, Long skeletonOwnerOma, BlenderContext blenderContext) {
this.skeletonOwnerOma = skeletonOwnerOma;
Long boneOMA = boneStructure.getOldMemoryAddress();
bone = new Bone(boneName);
bones.add(bone);
blenderContext.addLoadedFeatures(boneOMA, LoadedDataType.STRUCTURE, boneStructure);
blenderContext.addLoadedFeatures(boneOMA, LoadedDataType.FEATURE, bone);
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Structure skeletonOwnerObjectStructure = (Structure) blenderContext.getLoadedFeature(skeletonOwnerOma, LoadedDataType.STRUCTURE);
// I could load 'imat' here, but apparently in some older blenders there were bugs or unfinished functionalities that stored ZERO matrix in imat field
// loading 'obmat' and inverting it makes us avoid errors in such cases
Matrix4f invertedObjectOwnerGlobalMatrix = objectHelper.getMatrix(skeletonOwnerObjectStructure, "obmat", blenderContext.getBlenderKey().isFixUpAxis()).invertLocal();
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, skeletonOwnerOma, blenderContext));
}
return bone;
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class ConstraintHelper method applyTransform.
/**
* Applies transform to a feature (bone or spatial). Computations transform
* the given transformation from the given space to the feature's local
* space.
*
* @param oma
* the OMA of the feature we apply transformation to
* @param subtargetName
* the name of the feature's subtarget (bone in case of armature)
* @param space
* the space in which the given transform is to be applied
* @param transform
* the transform we apply
*/
public void applyTransform(Long oma, String subtargetName, Space space, Transform transform) {
Spatial feature = (Spatial) blenderContext.getLoadedFeature(oma, LoadedDataType.FEATURE);
boolean isArmature = blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, feature) != null;
if (isArmature) {
Skeleton skeleton = blenderContext.getSkeleton(oma);
BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName);
Bone bone = targetBoneContext.getBone();
if (bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) {
space = Space.CONSTRAINT_SPACE_POSE;
}
TempVars tempVars = TempVars.get();
switch(space) {
case CONSTRAINT_SPACE_LOCAL:
assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!";
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break;
case CONSTRAINT_SPACE_WORLD:
{
Matrix4f boneMatrixInWorldSpace = this.toMatrix(transform, tempVars.tempMat4);
Matrix4f modelWorldMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42);
Matrix4f boneMatrixInModelSpace = modelWorldMatrix.invertLocal().multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent();
if (parent != null) {
Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
}
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break;
}
case CONSTRAINT_SPACE_POSE:
{
Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent();
if (parent != null) {
Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
}
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break;
}
case CONSTRAINT_SPACE_PARLOCAL:
Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent();
if (parent != null) {
//first add the initial parent matrix to the bone's model matrix
BoneContext parentContext = blenderContext.getBoneContext(parent);
Matrix4f initialParentMatrixInModelSpace = parentContext.getBoneMatrixInModelSpace();
Matrix4f currentParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
//the bone will now move with its parent in model space
//now we need to subtract the difference between current parent's model matrix and its initial model matrix
boneMatrixInModelSpace = initialParentMatrixInModelSpace.mult(boneMatrixInModelSpace);
Matrix4f diffMatrix = initialParentMatrixInModelSpace.mult(currentParentMatrixInModelSpace.invert());
boneMatrixInModelSpace.multLocal(diffMatrix);
//now the bone will have its position in model space with initial parent's model matrix added
}
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break;
default:
tempVars.release();
throw new IllegalStateException("Invalid space type for target object: " + space.toString());
}
tempVars.release();
skeleton.updateWorldVectors();
} else {
switch(space) {
case CONSTRAINT_SPACE_LOCAL:
feature.getLocalTransform().set(transform);
break;
case CONSTRAINT_SPACE_WORLD:
if (feature.getParent() == null) {
feature.setLocalTransform(transform);
} else {
Transform parentWorldTransform = feature.getParent().getWorldTransform();
TempVars tempVars = TempVars.get();
Matrix4f parentInverseMatrix = this.toMatrix(parentWorldTransform, tempVars.tempMat4).invertLocal();
Matrix4f m = this.toMatrix(transform, tempVars.tempMat42);
m = m.multLocal(parentInverseMatrix);
tempVars.release();
transform.setTranslation(m.toTranslationVector());
transform.setRotation(m.toRotationQuat());
transform.setScale(m.toScaleVector());
feature.setLocalTransform(transform);
}
break;
default:
throw new IllegalStateException("Invalid space type for spatial object: " + space.toString());
}
}
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class AndroidSensorJoyInput method updateOrientation.
/**
* Calculates the device orientation based off the data recieved from the
* Acceleration Sensor and Mangetic Field sensor
* Values are returned relative to the Earth.
*
* From the Android Doc
*
* Computes the device's orientation based on the rotation matrix. When it returns, the array values is filled with the result:
* values[0]: azimuth, rotation around the Z axis.
* values[1]: pitch, rotation around the X axis.
* values[2]: roll, rotation around the Y axis.
*
* The reference coordinate-system used is different from the world
* coordinate-system defined for the rotation matrix:
* X is defined as the vector product Y.Z (It is tangential to the ground at the device's current location and roughly points West).
* Y is tangential to the ground at the device's current location and points towards the magnetic North Pole.
* Z points towards the center of the Earth and is perpendicular to the ground.
*
* @return True if Orientation was calculated
*/
private boolean updateOrientation() {
SensorData sensorData;
AndroidSensorJoystickAxis axis;
final float[] curInclinationMat = new float[16];
final float[] curRotationMat = new float[16];
final float[] rotatedRotationMat = new float[16];
final float[] accValues = new float[3];
final float[] magValues = new float[3];
final float[] orderedOrientation = new float[3];
// if the Gravity Sensor is available, use it for orientation, if not
// use the accelerometer
// NOTE: Seemed to work worse, so just using accelerometer
// sensorData = sensors.get(Sensor.TYPE_GRAVITY);
// if (sensorData == null) {
sensorData = sensors.get(Sensor.TYPE_ACCELEROMETER);
if (sensorData == null || !sensorData.enabled || !sensorData.haveData) {
return false;
}
if (sensorData.sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
return false;
}
synchronized (sensorData.valuesLock) {
accValues[0] = sensorData.lastValues[0];
accValues[1] = sensorData.lastValues[1];
accValues[2] = sensorData.lastValues[2];
}
sensorData = sensors.get(Sensor.TYPE_MAGNETIC_FIELD);
if (sensorData == null || !sensorData.enabled || !sensorData.haveData) {
return false;
}
if (sensorData.sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
return false;
}
synchronized (sensorData.valuesLock) {
magValues[0] = sensorData.lastValues[0];
magValues[1] = sensorData.lastValues[1];
magValues[2] = sensorData.lastValues[2];
}
if (SensorManager.getRotationMatrix(curRotationMat, curInclinationMat, accValues, magValues)) {
final float[] orientValues = new float[3];
if (remapCoordinates(curRotationMat, rotatedRotationMat)) {
SensorManager.getOrientation(rotatedRotationMat, orientValues);
// logger.log(Level.FINE, "Orientation Values: {0}, {1}, {2}",
// new Object[]{orientValues[0], orientValues[1], orientValues[2]});
// need to reorder to make it x, y, z order instead of z, x, y order
orderedOrientation[0] = orientValues[1];
orderedOrientation[1] = orientValues[2];
orderedOrientation[2] = orientValues[0];
sensorData = sensors.get(Sensor.TYPE_ORIENTATION);
if (sensorData != null && sensorData.axes.size() > 0) {
for (int i = 0; i < orderedOrientation.length; i++) {
axis = sensorData.axes.get(i);
if (axis != null) {
axis.setCurRawValue(orderedOrientation[i]);
if (!sensorData.haveData) {
sensorData.haveData = true;
} else {
if (axis.isChanged()) {
joyInput.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
}
}
}
}
} else if (sensorData != null) {
if (!sensorData.haveData) {
sensorData.haveData = true;
}
}
return true;
} else {
logger.log(Level.FINE, "remapCoordinateSystem failed");
}
} else {
logger.log(Level.FINE, "getRotationMatrix returned false");
}
return false;
}
Aggregations