Home | History | Annotate | Download | only in bullet-native
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 #include <math.h>
     33 #include "jmeBulletUtil.h"
     34 
     35 /**
     36  * Author: Normen Hansen,Empire Phoenix, Lutherion
     37  */
     38 void jmeBulletUtil::convert(JNIEnv* env, jobject in, btVector3* out) {
     39     if (in == NULL || out == NULL) {
     40         jmeClasses::throwNPE(env);
     41     }
     42     float x = env->GetFloatField(in, jmeClasses::Vector3f_x); //env->CallFloatMethod(in, jmeClasses::Vector3f_getX);
     43     if (env->ExceptionCheck()) {
     44         env->Throw(env->ExceptionOccurred());
     45         return;
     46     }
     47     float y = env->GetFloatField(in, jmeClasses::Vector3f_y); //env->CallFloatMethod(in, jmeClasses::Vector3f_getY);
     48     if (env->ExceptionCheck()) {
     49         env->Throw(env->ExceptionOccurred());
     50         return;
     51     }
     52     float z = env->GetFloatField(in, jmeClasses::Vector3f_z); //env->CallFloatMethod(in, jmeClasses::Vector3f_getZ);
     53     if (env->ExceptionCheck()) {
     54         env->Throw(env->ExceptionOccurred());
     55         return;
     56     }
     57     out->setX(x);
     58     out->setY(y);
     59     out->setZ(z);
     60 }
     61 
     62 void jmeBulletUtil::convert(JNIEnv* env, const btVector3* in, jobject out) {
     63     if (in == NULL || out == NULL) {
     64         jmeClasses::throwNPE(env);
     65     }
     66     float x = in->getX();
     67     float y = in->getY();
     68     float z = in->getZ();
     69     env->SetFloatField(out, jmeClasses::Vector3f_x, x);
     70     if (env->ExceptionCheck()) {
     71         env->Throw(env->ExceptionOccurred());
     72         return;
     73     }
     74     env->SetFloatField(out, jmeClasses::Vector3f_y, y);
     75     if (env->ExceptionCheck()) {
     76         env->Throw(env->ExceptionOccurred());
     77         return;
     78     }
     79     env->SetFloatField(out, jmeClasses::Vector3f_z, z);
     80     //    env->CallObjectMethod(out, jmeClasses::Vector3f_set, x, y, z);
     81     if (env->ExceptionCheck()) {
     82         env->Throw(env->ExceptionOccurred());
     83         return;
     84     }
     85 }
     86 
     87 void jmeBulletUtil::convert(JNIEnv* env, jobject in, btMatrix3x3* out) {
     88     if (in == NULL || out == NULL) {
     89         jmeClasses::throwNPE(env);
     90     }
     91     float m00 = env->GetFloatField(in, jmeClasses::Matrix3f_m00);
     92     if (env->ExceptionCheck()) {
     93         env->Throw(env->ExceptionOccurred());
     94         return;
     95     }
     96     float m01 = env->GetFloatField(in, jmeClasses::Matrix3f_m01);
     97     if (env->ExceptionCheck()) {
     98         env->Throw(env->ExceptionOccurred());
     99         return;
    100     }
    101     float m02 = env->GetFloatField(in, jmeClasses::Matrix3f_m02);
    102     if (env->ExceptionCheck()) {
    103         env->Throw(env->ExceptionOccurred());
    104         return;
    105     }
    106     float m10 = env->GetFloatField(in, jmeClasses::Matrix3f_m10);
    107     if (env->ExceptionCheck()) {
    108         env->Throw(env->ExceptionOccurred());
    109         return;
    110     }
    111     float m11 = env->GetFloatField(in, jmeClasses::Matrix3f_m11);
    112     if (env->ExceptionCheck()) {
    113         env->Throw(env->ExceptionOccurred());
    114         return;
    115     }
    116     float m12 = env->GetFloatField(in, jmeClasses::Matrix3f_m12);
    117     if (env->ExceptionCheck()) {
    118         env->Throw(env->ExceptionOccurred());
    119         return;
    120     }
    121     float m20 = env->GetFloatField(in, jmeClasses::Matrix3f_m20);
    122     if (env->ExceptionCheck()) {
    123         env->Throw(env->ExceptionOccurred());
    124         return;
    125     }
    126     float m21 = env->GetFloatField(in, jmeClasses::Matrix3f_m21);
    127     if (env->ExceptionCheck()) {
    128         env->Throw(env->ExceptionOccurred());
    129         return;
    130     }
    131     float m22 = env->GetFloatField(in, jmeClasses::Matrix3f_m22);
    132     if (env->ExceptionCheck()) {
    133         env->Throw(env->ExceptionOccurred());
    134         return;
    135     }
    136     out->setValue(m00, m01, m02, m10, m11, m12, m20, m21, m22);
    137 }
    138 
    139 void jmeBulletUtil::convert(JNIEnv* env, const btMatrix3x3* in, jobject out) {
    140     if (in == NULL || out == NULL) {
    141         jmeClasses::throwNPE(env);
    142     }
    143     float m00 = in->getRow(0).m_floats[0];
    144     float m01 = in->getRow(0).m_floats[1];
    145     float m02 = in->getRow(0).m_floats[2];
    146     float m10 = in->getRow(1).m_floats[0];
    147     float m11 = in->getRow(1).m_floats[1];
    148     float m12 = in->getRow(1).m_floats[2];
    149     float m20 = in->getRow(2).m_floats[0];
    150     float m21 = in->getRow(2).m_floats[1];
    151     float m22 = in->getRow(2).m_floats[2];
    152     env->SetFloatField(out, jmeClasses::Matrix3f_m00, m00);
    153     if (env->ExceptionCheck()) {
    154         env->Throw(env->ExceptionOccurred());
    155         return;
    156     }
    157     env->SetFloatField(out, jmeClasses::Matrix3f_m01, m01);
    158     if (env->ExceptionCheck()) {
    159         env->Throw(env->ExceptionOccurred());
    160         return;
    161     }
    162     env->SetFloatField(out, jmeClasses::Matrix3f_m02, m02);
    163     if (env->ExceptionCheck()) {
    164         env->Throw(env->ExceptionOccurred());
    165         return;
    166     }
    167     env->SetFloatField(out, jmeClasses::Matrix3f_m10, m10);
    168     if (env->ExceptionCheck()) {
    169         env->Throw(env->ExceptionOccurred());
    170         return;
    171     }
    172     env->SetFloatField(out, jmeClasses::Matrix3f_m11, m11);
    173     if (env->ExceptionCheck()) {
    174         env->Throw(env->ExceptionOccurred());
    175         return;
    176     }
    177     env->SetFloatField(out, jmeClasses::Matrix3f_m12, m12);
    178     if (env->ExceptionCheck()) {
    179         env->Throw(env->ExceptionOccurred());
    180         return;
    181     }
    182     env->SetFloatField(out, jmeClasses::Matrix3f_m20, m20);
    183     if (env->ExceptionCheck()) {
    184         env->Throw(env->ExceptionOccurred());
    185         return;
    186     }
    187     env->SetFloatField(out, jmeClasses::Matrix3f_m21, m21);
    188     if (env->ExceptionCheck()) {
    189         env->Throw(env->ExceptionOccurred());
    190         return;
    191     }
    192     env->SetFloatField(out, jmeClasses::Matrix3f_m22, m22);
    193     if (env->ExceptionCheck()) {
    194         env->Throw(env->ExceptionOccurred());
    195         return;
    196     }
    197 }
    198 
    199 void jmeBulletUtil::convertQuat(JNIEnv* env, jobject in, btMatrix3x3* out) {
    200     if (in == NULL || out == NULL) {
    201         jmeClasses::throwNPE(env);
    202     }
    203     float x = env->GetFloatField(in, jmeClasses::Quaternion_x);
    204     if (env->ExceptionCheck()) {
    205         env->Throw(env->ExceptionOccurred());
    206         return;
    207     }
    208     float y = env->GetFloatField(in, jmeClasses::Quaternion_y);
    209     if (env->ExceptionCheck()) {
    210         env->Throw(env->ExceptionOccurred());
    211         return;
    212     }
    213     float z = env->GetFloatField(in, jmeClasses::Quaternion_z);
    214     if (env->ExceptionCheck()) {
    215         env->Throw(env->ExceptionOccurred());
    216         return;
    217     }
    218     float w = env->GetFloatField(in, jmeClasses::Quaternion_w);
    219     if (env->ExceptionCheck()) {
    220         env->Throw(env->ExceptionOccurred());
    221         return;
    222     }
    223 
    224     float norm = w * w + x * x + y * y + z * z;
    225     float s = (norm == 1.0) ? 2.0 : (norm > 0.1) ? 2.0 / norm : 0.0;
    226 
    227     // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs
    228     // will be used 2-4 times each.
    229     float xs = x * s;
    230     float ys = y * s;
    231     float zs = z * s;
    232     float xx = x * xs;
    233     float xy = x * ys;
    234     float xz = x * zs;
    235     float xw = w * xs;
    236     float yy = y * ys;
    237     float yz = y * zs;
    238     float yw = w * ys;
    239     float zz = z * zs;
    240     float zw = w * zs;
    241 
    242     // using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here
    243     out->setValue(1.0 - (yy + zz), (xy - zw), (xz + yw),
    244             (xy + zw), 1 - (xx + zz), (yz - xw),
    245             (xz - yw), (yz + xw), 1.0 - (xx + yy));
    246 }
    247 
    248 void jmeBulletUtil::convertQuat(JNIEnv* env, const btMatrix3x3* in, jobject out) {
    249     if (in == NULL || out == NULL) {
    250         jmeClasses::throwNPE(env);
    251     }
    252     // the trace is the sum of the diagonal elements; see
    253     // http://mathworld.wolfram.com/MatrixTrace.html
    254     float t = in->getRow(0).m_floats[0] + in->getRow(1).m_floats[1] + in->getRow(2).m_floats[2];
    255     float w, x, y, z;
    256     // we protect the division by s by ensuring that s>=1
    257     if (t >= 0) { // |w| >= .5
    258         float s = sqrt(t + 1); // |s|>=1 ...
    259         w = 0.5f * s;
    260         s = 0.5f / s; // so this division isn't bad
    261         x = (in->getRow(2).m_floats[1] - in->getRow(1).m_floats[2]) * s;
    262         y = (in->getRow(0).m_floats[2] - in->getRow(2).m_floats[0]) * s;
    263         z = (in->getRow(1).m_floats[0] - in->getRow(0).m_floats[1]) * s;
    264     } 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])) {
    265         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
    266         x = s * 0.5f; // |x| >= .5
    267         s = 0.5f / s;
    268         y = (in->getRow(1).m_floats[0] + in->getRow(0).m_floats[1]) * s;
    269         z = (in->getRow(0).m_floats[2] + in->getRow(2).m_floats[0]) * s;
    270         w = (in->getRow(2).m_floats[1] - in->getRow(1).m_floats[2]) * s;
    271     } else if (in->getRow(1).m_floats[1] > in->getRow(2).m_floats[2]) {
    272         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
    273         y = s * 0.5f; // |y| >= .5
    274         s = 0.5f / s;
    275         x = (in->getRow(1).m_floats[0] + in->getRow(0).m_floats[1]) * s;
    276         z = (in->getRow(2).m_floats[1] + in->getRow(1).m_floats[2]) * s;
    277         w = (in->getRow(0).m_floats[2] - in->getRow(2).m_floats[0]) * s;
    278     } else {
    279         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
    280         z = s * 0.5f; // |z| >= .5
    281         s = 0.5f / s;
    282         x = (in->getRow(0).m_floats[2] + in->getRow(2).m_floats[0]) * s;
    283         y = (in->getRow(2).m_floats[1] + in->getRow(1).m_floats[2]) * s;
    284         w = (in->getRow(1).m_floats[0] - in->getRow(0).m_floats[1]) * s;
    285     }
    286 
    287     env->SetFloatField(out, jmeClasses::Quaternion_x, x);
    288     if (env->ExceptionCheck()) {
    289         env->Throw(env->ExceptionOccurred());
    290         return;
    291     }
    292     env->SetFloatField(out, jmeClasses::Quaternion_y, y);
    293     if (env->ExceptionCheck()) {
    294         env->Throw(env->ExceptionOccurred());
    295         return;
    296     }
    297     env->SetFloatField(out, jmeClasses::Quaternion_z, z);
    298     if (env->ExceptionCheck()) {
    299         env->Throw(env->ExceptionOccurred());
    300         return;
    301     }
    302     env->SetFloatField(out, jmeClasses::Quaternion_w, w);
    303     //    env->CallObjectMethod(out, jmeClasses::Quaternion_set, x, y, z, w);
    304     if (env->ExceptionCheck()) {
    305         env->Throw(env->ExceptionOccurred());
    306         return;
    307     }
    308 }
    309 
    310 void jmeBulletUtil::addResult(JNIEnv* env, jobject resultlist, btVector3 hitnormal, btVector3 m_hitPointWorld, btScalar m_hitFraction, btCollisionObject* hitobject) {
    311 
    312     jobject singleresult = env->AllocObject(jmeClasses::PhysicsRay_Class);
    313     jobject hitnormalvec = env->AllocObject(jmeClasses::Vector3f);
    314 
    315     convert(env, const_cast<btVector3*> (&hitnormal), hitnormalvec);
    316     jmeUserPointer *up1 = (jmeUserPointer*) hitobject -> getUserPointer();
    317 
    318     env->SetObjectField(singleresult, jmeClasses::PhysicsRay_normalInWorldSpace, hitnormalvec);
    319     env->SetFloatField(singleresult, jmeClasses::PhysicsRay_hitfraction, m_hitFraction);
    320 
    321     env->SetObjectField(singleresult, jmeClasses::PhysicsRay_collisionObject, up1->javaCollisionObject);
    322     env->CallVoidMethod(resultlist, jmeClasses::PhysicsRay_addmethod, singleresult);
    323     if (env->ExceptionCheck()) {
    324         env->Throw(env->ExceptionOccurred());
    325         return;
    326     }
    327 }
    328