You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
15 KiB
417 lines
15 KiB
/*
|
|
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <math.h>
|
|
#include "jmeBulletUtil.h"
|
|
|
|
/**
|
|
* Author: Normen Hansen,Empire Phoenix, Lutherion
|
|
*/
|
|
void jmeBulletUtil::convert(JNIEnv* env, jobject in, btVector3* out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
float x = env->GetFloatField(in, jmeClasses::Vector3f_x); //env->CallFloatMethod(in, jmeClasses::Vector3f_getX);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float y = env->GetFloatField(in, jmeClasses::Vector3f_y); //env->CallFloatMethod(in, jmeClasses::Vector3f_getY);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float z = env->GetFloatField(in, jmeClasses::Vector3f_z); //env->CallFloatMethod(in, jmeClasses::Vector3f_getZ);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
out->setX(x);
|
|
out->setY(y);
|
|
out->setZ(z);
|
|
}
|
|
|
|
void jmeBulletUtil::convert(JNIEnv* env, jobject in, btQuaternion* out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
float x = env->GetFloatField(in, jmeClasses::Quaternion_x);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float y = env->GetFloatField(in, jmeClasses::Quaternion_y); //env->CallFloatMethod(in, jmeClasses::Vector3f_getY);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float z = env->GetFloatField(in, jmeClasses::Quaternion_z); //env->CallFloatMethod(in, jmeClasses::Vector3f_getZ);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
|
|
float w = env->GetFloatField(in, jmeClasses::Quaternion_w); //env->CallFloatMethod(in, jmeClasses::Vector3f_getZ);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
out->setX(x);
|
|
out->setY(y);
|
|
out->setZ(z);
|
|
out->setW(w);
|
|
}
|
|
|
|
|
|
void jmeBulletUtil::convert(JNIEnv* env, const btVector3* in, jobject out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
float x = in->getX();
|
|
float y = in->getY();
|
|
float z = in->getZ();
|
|
env->SetFloatField(out, jmeClasses::Vector3f_x, x);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Vector3f_y, y);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Vector3f_z, z);
|
|
// env->CallObjectMethod(out, jmeClasses::Vector3f_set, x, y, z);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void jmeBulletUtil::convert(JNIEnv* env, jobject in, btMatrix3x3* out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
float m00 = env->GetFloatField(in, jmeClasses::Matrix3f_m00);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m01 = env->GetFloatField(in, jmeClasses::Matrix3f_m01);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m02 = env->GetFloatField(in, jmeClasses::Matrix3f_m02);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m10 = env->GetFloatField(in, jmeClasses::Matrix3f_m10);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m11 = env->GetFloatField(in, jmeClasses::Matrix3f_m11);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m12 = env->GetFloatField(in, jmeClasses::Matrix3f_m12);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m20 = env->GetFloatField(in, jmeClasses::Matrix3f_m20);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m21 = env->GetFloatField(in, jmeClasses::Matrix3f_m21);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float m22 = env->GetFloatField(in, jmeClasses::Matrix3f_m22);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
out->setValue(m00, m01, m02, m10, m11, m12, m20, m21, m22);
|
|
}
|
|
|
|
void jmeBulletUtil::convert(JNIEnv* env, const btMatrix3x3* in, jobject out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
float m00 = in->getRow(0).m_floats[0];
|
|
float m01 = in->getRow(0).m_floats[1];
|
|
float m02 = in->getRow(0).m_floats[2];
|
|
float m10 = in->getRow(1).m_floats[0];
|
|
float m11 = in->getRow(1).m_floats[1];
|
|
float m12 = in->getRow(1).m_floats[2];
|
|
float m20 = in->getRow(2).m_floats[0];
|
|
float m21 = in->getRow(2).m_floats[1];
|
|
float m22 = in->getRow(2).m_floats[2];
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m00, m00);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m01, m01);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m02, m02);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m10, m10);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m11, m11);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m12, m12);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m20, m20);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m21, m21);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Matrix3f_m22, m22);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void jmeBulletUtil::convertQuat(JNIEnv* env, jobject in, btMatrix3x3* out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
float x = env->GetFloatField(in, jmeClasses::Quaternion_x);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float y = env->GetFloatField(in, jmeClasses::Quaternion_y);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float z = env->GetFloatField(in, jmeClasses::Quaternion_z);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
float w = env->GetFloatField(in, jmeClasses::Quaternion_w);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
|
|
float norm = w * w + x * x + y * y + z * z;
|
|
float s = (norm == 1.0) ? 2.0 : (norm > 0.1) ? 2.0 / norm : 0.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
|
|
out->setValue(1.0 - (yy + zz), (xy - zw), (xz + yw),
|
|
(xy + zw), 1 - (xx + zz), (yz - xw),
|
|
(xz - yw), (yz + xw), 1.0 - (xx + yy));
|
|
}
|
|
|
|
void jmeBulletUtil::convertQuat(JNIEnv* env, const btMatrix3x3* in, jobject out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
// the trace is the sum of the diagonal elements; see
|
|
// http://mathworld.wolfram.com/MatrixTrace.html
|
|
float t = in->getRow(0).m_floats[0] + in->getRow(1).m_floats[1] + in->getRow(2).m_floats[2];
|
|
float w, x, y, z;
|
|
// we protect the division by s by ensuring that s>=1
|
|
if (t >= 0) { // |w| >= .5
|
|
float s = sqrt(t + 1); // |s|>=1 ...
|
|
w = 0.5f * s;
|
|
s = 0.5f / s; // so this division isn't bad
|
|
x = (in->getRow(2).m_floats[1] - in->getRow(1).m_floats[2]) * s;
|
|
y = (in->getRow(0).m_floats[2] - in->getRow(2).m_floats[0]) * s;
|
|
z = (in->getRow(1).m_floats[0] - in->getRow(0).m_floats[1]) * s;
|
|
} else if ((in->getRow(0).m_floats[0] > in->getRow(1).m_floats[1]) && (in->getRow(0).m_floats[0] > in->getRow(2).m_floats[2])) {
|
|
float s = sqrt(1.0f + in->getRow(0).m_floats[0] - in->getRow(1).m_floats[1] - in->getRow(2).m_floats[2]); // |s|>=1
|
|
x = s * 0.5f; // |x| >= .5
|
|
s = 0.5f / s;
|
|
y = (in->getRow(1).m_floats[0] + in->getRow(0).m_floats[1]) * s;
|
|
z = (in->getRow(0).m_floats[2] + in->getRow(2).m_floats[0]) * s;
|
|
w = (in->getRow(2).m_floats[1] - in->getRow(1).m_floats[2]) * s;
|
|
} else if (in->getRow(1).m_floats[1] > in->getRow(2).m_floats[2]) {
|
|
float s = sqrt(1.0f + in->getRow(1).m_floats[1] - in->getRow(0).m_floats[0] - in->getRow(2).m_floats[2]); // |s|>=1
|
|
y = s * 0.5f; // |y| >= .5
|
|
s = 0.5f / s;
|
|
x = (in->getRow(1).m_floats[0] + in->getRow(0).m_floats[1]) * s;
|
|
z = (in->getRow(2).m_floats[1] + in->getRow(1).m_floats[2]) * s;
|
|
w = (in->getRow(0).m_floats[2] - in->getRow(2).m_floats[0]) * s;
|
|
} else {
|
|
float s = sqrt(1.0f + in->getRow(2).m_floats[2] - in->getRow(0).m_floats[0] - in->getRow(1).m_floats[1]); // |s|>=1
|
|
z = s * 0.5f; // |z| >= .5
|
|
s = 0.5f / s;
|
|
x = (in->getRow(0).m_floats[2] + in->getRow(2).m_floats[0]) * s;
|
|
y = (in->getRow(2).m_floats[1] + in->getRow(1).m_floats[2]) * s;
|
|
w = (in->getRow(1).m_floats[0] - in->getRow(0).m_floats[1]) * s;
|
|
}
|
|
|
|
env->SetFloatField(out, jmeClasses::Quaternion_x, x);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Quaternion_y, y);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Quaternion_z, z);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
env->SetFloatField(out, jmeClasses::Quaternion_w, w);
|
|
// env->CallObjectMethod(out, jmeClasses::Quaternion_set, x, y, z, w);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void jmeBulletUtil::addResult(JNIEnv* env, jobject resultlist, btVector3* hitnormal, btVector3* m_hitPointWorld, btScalar m_hitFraction, const btCollisionObject* hitobject) {
|
|
|
|
jobject singleresult = env->AllocObject(jmeClasses::PhysicsRay_Class);
|
|
jobject hitnormalvec = env->AllocObject(jmeClasses::Vector3f);
|
|
|
|
convert(env, hitnormal, hitnormalvec);
|
|
jmeUserPointer *up1 = (jmeUserPointer*) hitobject -> getUserPointer();
|
|
|
|
env->SetObjectField(singleresult, jmeClasses::PhysicsRay_normalInWorldSpace, hitnormalvec);
|
|
env->SetFloatField(singleresult, jmeClasses::PhysicsRay_hitfraction, m_hitFraction);
|
|
|
|
env->SetObjectField(singleresult, jmeClasses::PhysicsRay_collisionObject, up1->javaCollisionObject);
|
|
env->CallBooleanMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void jmeBulletUtil::addSweepResult(JNIEnv* env, jobject resultlist, btVector3* hitnormal, btVector3* m_hitPointWorld, btScalar m_hitFraction, const btCollisionObject* hitobject) {
|
|
|
|
jobject singleresult = env->AllocObject(jmeClasses::PhysicsSweep_Class);
|
|
jobject hitnormalvec = env->AllocObject(jmeClasses::Vector3f);
|
|
|
|
convert(env, hitnormal, hitnormalvec);
|
|
jmeUserPointer *up1 = (jmeUserPointer*)hitobject->getUserPointer();
|
|
|
|
env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_normalInWorldSpace, hitnormalvec);
|
|
env->SetFloatField(singleresult, jmeClasses::PhysicsSweep_hitfraction, m_hitFraction);
|
|
|
|
env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_collisionObject, up1->javaCollisionObject);
|
|
env->CallBooleanMethod(resultlist, jmeClasses::PhysicsSweep_addmethod, singleresult);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void jmeBulletUtil::convert(JNIEnv* env, jobject in, btTransform* out) {
|
|
if (in == NULL || out == NULL) {
|
|
jmeClasses::throwNPE(env);
|
|
}
|
|
|
|
jobject translation_vec = env->CallObjectMethod(in, jmeClasses::Transform_translation);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
|
|
jobject rot_quat = env->CallObjectMethod(in, jmeClasses::Transform_rotation);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
|
|
/*
|
|
//Scale currently not supported by bullet
|
|
//@TBD: Create an assertion somewhere to avoid scale values
|
|
jobject scale_vec = env->GetObjectField(in, jmeClasses::Transform_scale);
|
|
if (env->ExceptionCheck()) {
|
|
env->Throw(env->ExceptionOccurred());
|
|
return;
|
|
}
|
|
*/
|
|
btVector3 native_translation_vec = btVector3();
|
|
//btVector3 native_scale_vec = btVector3();
|
|
btQuaternion native_rot_quat = btQuaternion();
|
|
|
|
convert(env, translation_vec, &native_translation_vec);
|
|
//convert(env, scale_vec, native_scale_vec);
|
|
convert(env, rot_quat, &native_rot_quat);
|
|
|
|
out->setRotation(native_rot_quat);
|
|
out->setOrigin(native_translation_vec);
|
|
}
|
|
|