| /* |
| * Copyright (c) 2009-2010 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, 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, btCollisionObject* hitobject) { |
| |
| jobject singleresult = env->AllocObject(jmeClasses::PhysicsRay_Class); |
| jobject hitnormalvec = env->AllocObject(jmeClasses::Vector3f); |
| |
| convert(env, const_cast<btVector3*> (&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->CallVoidMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult); |
| if (env->ExceptionCheck()) { |
| env->Throw(env->ExceptionOccurred()); |
| return; |
| } |
| } |