use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class ObjectHelper method getMatrix.
/**
* This method returns the matrix of a given name for the given structure.
* It takes up axis into consideration.
*
* The method that moves the matrix from Z-up axis to Y-up axis space is as follows:
* - load the matrix directly from blender (it has the Z-up axis orientation)
* - switch the second and third rows in the matrix
* - switch the second and third column in the matrix
* - multiply the values in the third row by -1
* - multiply the values in the third column by -1
*
* The result matrix is now in Y-up axis orientation.
* The procedure was discovered by experimenting but it looks like it's working :)
* The previous procedure transformet the loaded matrix into component (loc, rot, scale),
* switched several values and pu the back into the matrix.
* It worked fine until models with negative scale are used.
* The current method is not touched by that flaw.
*
* @param structure
* the structure with matrix data
* @param matrixName
* the name of the matrix
* @param fixUpAxis
* tells if the Y axis is a UP axis
* @param store
* the matrix where the result will pe placed
* @return the required matrix
*/
@SuppressWarnings("unchecked")
private Matrix4f getMatrix(Structure structure, String matrixName, boolean fixUpAxis, Matrix4f store) {
DynamicArray<Number> obmat = (DynamicArray<Number>) structure.getFieldValue(matrixName);
// 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) {
float value = obmat.get(j, i).floatValue();
if (Math.abs(value) <= FastMath.FLT_EPSILON) {
value = 0;
}
store.set(i, j, value);
}
}
if (fixUpAxis) {
// first switch the second and third row
for (int i = 0; i < 4; ++i) {
float temp = store.get(1, i);
store.set(1, i, store.get(2, i));
store.set(2, i, temp);
}
// then switch the second and third column
for (int i = 0; i < 4; ++i) {
float temp = store.get(i, 1);
store.set(i, 1, store.get(i, 2));
store.set(i, 2, temp);
}
// multiply the values in the third row by -1
store.m20 *= -1;
store.m21 *= -1;
store.m22 *= -1;
store.m23 *= -1;
// multiply the values in the third column by -1
store.m02 *= -1;
store.m12 *= -1;
store.m22 *= -1;
store.m32 *= -1;
}
return store;
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class ShadowUtil method updateShadowCamera.
/**
* Updates the shadow camera to properly contain the given points (which
* contain the eye camera frustum corners)
*
* @param shadowCam
* @param points
*/
public static void updateShadowCamera(Camera shadowCam, Vector3f[] points) {
boolean ortho = shadowCam.isParallelProjection();
shadowCam.setProjectionMatrix(null);
if (ortho) {
shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
} else {
shadowCam.setFrustumPerspective(45, 1, 1, 150);
}
Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
Matrix4f projMatrix = shadowCam.getProjectionMatrix();
BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
TempVars vars = TempVars.get();
Vector3f splitMin = splitBB.getMin(vars.vect1);
Vector3f splitMax = splitBB.getMax(vars.vect2);
// splitMin.z = 0;
// Create the crop matrix.
float scaleX, scaleY, scaleZ;
float offsetX, offsetY, offsetZ;
scaleX = 2.0f / (splitMax.x - splitMin.x);
scaleY = 2.0f / (splitMax.y - splitMin.y);
offsetX = -0.5f * (splitMax.x + splitMin.x) * scaleX;
offsetY = -0.5f * (splitMax.y + splitMin.y) * scaleY;
scaleZ = 1.0f / (splitMax.z - splitMin.z);
offsetZ = -splitMin.z * scaleZ;
Matrix4f cropMatrix = vars.tempMat4;
cropMatrix.set(scaleX, 0f, 0f, offsetX, 0f, scaleY, 0f, offsetY, 0f, 0f, scaleZ, offsetZ, 0f, 0f, 0f, 1f);
Matrix4f result = new Matrix4f();
result.set(cropMatrix);
result.multLocal(projMatrix);
vars.release();
shadowCam.setProjectionMatrix(result);
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class BillboardControl method rotateCameraAligned.
/**
* Aligns this Billboard so that it points to the camera position.
*
* @param camera
* Camera
*/
private void rotateCameraAligned(Camera camera) {
look.set(camera.getLocation()).subtractLocal(spatial.getWorldTranslation());
// coopt left for our own purposes.
Vector3f xzp = left;
// The xzp vector is the projection of the look vector on the xz plane
xzp.set(look.x, 0, look.z);
// check for undefined rotation...
if (xzp.equals(Vector3f.ZERO)) {
return;
}
look.normalizeLocal();
xzp.normalizeLocal();
float cosp = look.dot(xzp);
// compute the local orientation matrix for the billboard
orient.set(0, 0, xzp.z);
orient.set(0, 1, xzp.x * -look.y);
orient.set(0, 2, xzp.x * cosp);
orient.set(1, 0, 0);
orient.set(1, 1, cosp);
orient.set(1, 2, look.y);
orient.set(2, 0, -xzp.x);
orient.set(2, 1, xzp.z * -look.y);
orient.set(2, 2, xzp.z * cosp);
// The billboard must be oriented to face the camera before it is
// transformed into the world.
spatial.setLocalRotation(orient);
fixRefreshFlags();
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class AndroidBufferImageLoader method load.
public Object load(AssetInfo assetInfo) throws IOException {
Bitmap bitmap = null;
Image.Format format;
InputStream in = null;
int bpp;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferQualityOverSpeed = false;
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inTempStorage = tempData;
options.inScaled = false;
options.inDither = false;
options.inInputShareable = true;
options.inPurgeable = true;
options.inSampleSize = 1;
try {
in = assetInfo.openStream();
bitmap = BitmapFactory.decodeStream(in, null, options);
if (bitmap == null) {
throw new IOException("Failed to load image: " + assetInfo.getKey().getName());
}
} finally {
if (in != null) {
in.close();
}
}
switch(bitmap.getConfig()) {
case ALPHA_8:
format = Image.Format.Alpha8;
bpp = 1;
break;
case ARGB_8888:
format = Image.Format.RGBA8;
bpp = 4;
break;
case RGB_565:
format = Image.Format.RGB565;
bpp = 2;
break;
default:
throw new UnsupportedOperationException("Unrecognized Android bitmap format: " + bitmap.getConfig());
}
TextureKey texKey = (TextureKey) assetInfo.getKey();
int width = bitmap.getWidth();
int height = bitmap.getHeight();
ByteBuffer data = BufferUtils.createByteBuffer(bitmap.getWidth() * bitmap.getHeight() * bpp);
if (format == Image.Format.RGBA8) {
int[] pixelData = new int[width * height];
bitmap.getPixels(pixelData, 0, width, 0, 0, width, height);
if (texKey.isFlipY()) {
int[] sln = new int[width];
int y2;
for (int y1 = 0; y1 < height / 2; y1++) {
y2 = height - y1 - 1;
convertARGBtoABGR(pixelData, y1 * width, sln, 0, width);
convertARGBtoABGR(pixelData, y2 * width, pixelData, y1 * width, width);
System.arraycopy(sln, 0, pixelData, y2 * width, width);
}
} else {
convertARGBtoABGR(pixelData, 0, pixelData, 0, pixelData.length);
}
data.asIntBuffer().put(pixelData);
} else {
if (texKey.isFlipY()) {
// Flip the image, then delete the old one.
Matrix flipMat = new Matrix();
flipMat.preScale(1.0f, -1.0f);
Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
bitmap.recycle();
bitmap = newBitmap;
if (bitmap == null) {
throw new IOException("Failed to flip image: " + texKey);
}
}
bitmap.copyPixelsToBuffer(data);
}
data.flip();
bitmap.recycle();
Image image = new Image(format, width, height, data, ColorSpace.sRGB);
return image;
}
use of com.jme3.scene.plugins.blender.math.Matrix in project jmonkeyengine by jMonkeyEngine.
the class ConstraintDefinitionIK method bake.
@Override
public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
if (influence == 0 || !trackToBeChanged || targetTransform == null || bonesCount == 0) {
// no need to do anything
return;
}
if (bones == null) {
bones = new BonesChain((Bone) this.getOwner(), useTail, bonesAffected, alteredOmas, blenderContext);
}
if (bones.size() == 0) {
bonesCount = 0;
// no need to do anything
return;
}
double distanceFromTarget = Double.MAX_VALUE;
target.set(targetTransform.getTranslation().x, targetTransform.getTranslation().y, targetTransform.getTranslation().z);
if (bonesCount < 0) {
bonesCount = bones.size();
rotationVectors = new Vector3d[bonesCount];
for (int i = 0; i < bonesCount; ++i) {
rotationVectors[i] = new Vector3d();
}
J = new Matrix(3, bonesCount);
}
BoneContext topBone = bones.get(0);
for (int i = 0; i < iterations; ++i) {
DTransform topBoneTransform = bones.getWorldTransform(topBone);
// effector
Vector3d e = topBoneTransform.getTranslation().add(topBoneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(topBone.getLength()));
distanceFromTarget = e.distance(target);
if (distanceFromTarget <= MIN_DISTANCE) {
break;
}
deltaP.setColumn(0, 0, target.x - e.x, target.y - e.y, target.z - e.z);
int column = 0;
for (BoneContext boneContext : bones) {
DTransform boneWorldTransform = bones.getWorldTransform(boneContext);
// current join position
Vector3d j = boneWorldTransform.getTranslation();
Vector3d vectorFromJointToEffector = e.subtract(j);
vectorFromJointToEffector.cross(target.subtract(j), rotationVectors[column]).normalizeLocal();
rotationVectors[column].cross(vectorFromJointToEffector, col);
J.setColumn(col, column++);
}
Matrix J_1 = J.pseudoinverse();
SimpleMatrix deltaThetas = J_1.mult(deltaP);
if (deltaThetas.elementMaxAbs() < MIN_ANGLE_CHANGE) {
break;
}
for (int j = 0; j < deltaThetas.numRows(); ++j) {
double angle = deltaThetas.get(j, 0);
Vector3d rotationVector = rotationVectors[j];
tempDQuaternion.fromAngleAxis(angle, rotationVector);
BoneContext boneContext = bones.get(j);
Bone bone = boneContext.getBone();
if (bone.equals(this.getOwner())) {
if (boneContext.isLockX()) {
tempDQuaternion.set(0, tempDQuaternion.getY(), tempDQuaternion.getZ(), tempDQuaternion.getW());
}
if (boneContext.isLockY()) {
tempDQuaternion.set(tempDQuaternion.getX(), 0, tempDQuaternion.getZ(), tempDQuaternion.getW());
}
if (boneContext.isLockZ()) {
tempDQuaternion.set(tempDQuaternion.getX(), tempDQuaternion.getY(), 0, tempDQuaternion.getW());
}
}
DTransform boneTransform = bones.getWorldTransform(boneContext);
boneTransform.getRotation().set(tempDQuaternion.mult(boneTransform.getRotation()));
bones.setWorldTransform(boneContext, boneTransform);
}
}
// applying the results
for (int i = bonesCount - 1; i >= 0; --i) {
BoneContext boneContext = bones.get(i);
DTransform transform = bones.getWorldTransform(boneContext);
constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD, transform.toTransform());
}
// need to reload them again
bones = null;
}
Aggregations