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 "jmePhysicsSpace.h"
     33 #include "jmeBulletUtil.h"
     34 #include <stdio.h>
     35 
     36 /**
     37  * Author: Normen Hansen
     38  */
     39 jmePhysicsSpace::jmePhysicsSpace(JNIEnv* env, jobject javaSpace) {
     40     //TODO: global ref? maybe not -> cleaning, rather callback class?
     41     this->javaPhysicsSpace = env->NewWeakGlobalRef(javaSpace);
     42     this->env = env;
     43     env->GetJavaVM(&vm);
     44     if (env->ExceptionCheck()) {
     45         env->Throw(env->ExceptionOccurred());
     46         return;
     47     }
     48 }
     49 
     50 void jmePhysicsSpace::attachThread() {
     51 #ifdef ANDROID
     52     vm->AttachCurrentThread((JNIEnv**) &env, NULL);
     53 #elif defined (JNI_VERSION_1_2)
     54     vm->AttachCurrentThread((void**) &env, NULL);
     55 #else
     56     vm->AttachCurrentThread(&env, NULL);
     57 #endif
     58 }
     59 
     60 JNIEnv* jmePhysicsSpace::getEnv() {
     61     attachThread();
     62     return this->env;
     63 }
     64 
     65 void jmePhysicsSpace::stepSimulation(jfloat tpf, jint maxSteps, jfloat accuracy) {
     66     dynamicsWorld->stepSimulation(tpf, maxSteps, accuracy);
     67 }
     68 
     69 btThreadSupportInterface* jmePhysicsSpace::createSolverThreadSupport(int maxNumThreads) {
     70 #ifdef _WIN32
     71     Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("solverThreads", SolverThreadFunc, SolverlsMemoryFunc, maxNumThreads);
     72     Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo);
     73     threadSupport->startSPU();
     74 #elif defined (USE_PTHREADS)
     75     PosixThreadSupport::ThreadConstructionInfo constructionInfo("collision", SolverThreadFunc,
     76             SolverlsMemoryFunc, maxNumThreads);
     77     PosixThreadSupport* threadSupport = new PosixThreadSupport(constructionInfo);
     78     threadSupport->startSPU();
     79 #else
     80     SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads", SolverThreadFunc, SolverlsMemoryFunc);
     81     SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci);
     82     threadSupport->startSPU();
     83 #endif
     84     return threadSupport;
     85 }
     86 
     87 btThreadSupportInterface* jmePhysicsSpace::createDispatchThreadSupport(int maxNumThreads) {
     88 #ifdef _WIN32
     89     Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("solverThreads", processCollisionTask, createCollisionLocalStoreMemory, maxNumThreads);
     90     Win32ThreadSupport* threadSupport = new Win32ThreadSupport(threadConstructionInfo);
     91     threadSupport->startSPU();
     92 #elif defined (USE_PTHREADS)
     93     PosixThreadSupport::ThreadConstructionInfo solverConstructionInfo("solver", processCollisionTask,
     94             createCollisionLocalStoreMemory, maxNumThreads);
     95     PosixThreadSupport* threadSupport = new PosixThreadSupport(solverConstructionInfo);
     96     threadSupport->startSPU();
     97 #else
     98     SequentialThreadSupport::SequentialThreadConstructionInfo tci("solverThreads", processCollisionTask, createCollisionLocalStoreMemory);
     99     SequentialThreadSupport* threadSupport = new SequentialThreadSupport(tci);
    100     threadSupport->startSPU();
    101 #endif
    102     return threadSupport;
    103 }
    104 
    105 void jmePhysicsSpace::createPhysicsSpace(jfloat minX, jfloat minY, jfloat minZ, jfloat maxX, jfloat maxY, jfloat maxZ, jint broadphaseId, jboolean threading) {
    106     // collision configuration contains default setup for memory, collision setup
    107     btDefaultCollisionConstructionInfo cci;
    108     //    if(threading){
    109     //        cci.m_defaultMaxPersistentManifoldPoolSize = 32768;
    110     //    }
    111     btCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration(cci);
    112 
    113     btVector3 min = btVector3(minX, minY, minZ);
    114     btVector3 max = btVector3(maxX, maxY, maxZ);
    115 
    116     btBroadphaseInterface* broadphase;
    117 
    118     switch (broadphaseId) {
    119         case 0:
    120             broadphase = new btSimpleBroadphase();
    121             break;
    122         case 1:
    123             broadphase = new btAxisSweep3(min, max);
    124             break;
    125         case 2:
    126             //TODO: 32bit!
    127             broadphase = new btAxisSweep3(min, max);
    128             break;
    129         case 3:
    130             broadphase = new btDbvtBroadphase();
    131             break;
    132         case 4:
    133             //            broadphase = new btGpu3DGridBroadphase(
    134             //                    min, max,
    135             //                    20, 20, 20,
    136             //                    10000, 1000, 25);
    137             break;
    138     }
    139 
    140     btCollisionDispatcher* dispatcher;
    141     btConstraintSolver* solver;
    142     // use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
    143     if (threading) {
    144         btThreadSupportInterface* dispatchThreads = createDispatchThreadSupport(4);
    145         dispatcher = new SpuGatheringCollisionDispatcher(dispatchThreads, 4, collisionConfiguration);
    146         dispatcher->setDispatcherFlags(btCollisionDispatcher::CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
    147     } else {
    148         dispatcher = new btCollisionDispatcher(collisionConfiguration);
    149     }
    150 
    151     // the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
    152     if (threading) {
    153         btThreadSupportInterface* solverThreads = createSolverThreadSupport(4);
    154         solver = new btParallelConstraintSolver(solverThreads);
    155     } else {
    156         solver = new btSequentialImpulseConstraintSolver;
    157     }
    158 
    159     //create dynamics world
    160     btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
    161     dynamicsWorld = world;
    162     dynamicsWorld->setWorldUserInfo(this);
    163 
    164     //parallel solver requires the contacts to be in a contiguous pool, so avoid dynamic allocation
    165     if (threading) {
    166         world->getSimulationIslandManager()->setSplitIslands(false);
    167         world->getSolverInfo().m_numIterations = 4;
    168         world->getSolverInfo().m_solverMode = SOLVER_SIMD + SOLVER_USE_WARMSTARTING; //+SOLVER_RANDMIZE_ORDER;
    169         world->getDispatchInfo().m_enableSPU = true;
    170     }
    171 
    172     broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
    173 
    174     dynamicsWorld->setGravity(btVector3(0, -9.81f, 0));
    175 
    176     struct jmeFilterCallback : public btOverlapFilterCallback {
    177         // return true when pairs need collision
    178 
    179         virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy * proxy1) const {
    180             //            bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
    181             //            collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
    182             bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
    183             collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
    184             if (collides) {
    185                 btCollisionObject* co0 = (btCollisionObject*) proxy0->m_clientObject;
    186                 btCollisionObject* co1 = (btCollisionObject*) proxy1->m_clientObject;
    187                 jmeUserPointer *up0 = (jmeUserPointer*) co0 -> getUserPointer();
    188                 jmeUserPointer *up1 = (jmeUserPointer*) co1 -> getUserPointer();
    189                 if (up0 != NULL && up1 != NULL) {
    190                     collides = (up0->group & up1->groups) != 0;
    191                     collides = collides && (up1->group & up0->groups);
    192 
    193                     //add some additional logic here that modified 'collides'
    194                     return collides;
    195                 }
    196                 return false;
    197             }
    198             return collides;
    199         }
    200     };
    201     dynamicsWorld->getPairCache()->setOverlapFilterCallback(new jmeFilterCallback());
    202     dynamicsWorld->setInternalTickCallback(&jmePhysicsSpace::preTickCallback, static_cast<void *> (this), true);
    203     dynamicsWorld->setInternalTickCallback(&jmePhysicsSpace::postTickCallback, static_cast<void *> (this));
    204     if (gContactProcessedCallback == NULL) {
    205         gContactProcessedCallback = &jmePhysicsSpace::contactProcessedCallback;
    206     }
    207 }
    208 
    209 void jmePhysicsSpace::preTickCallback(btDynamicsWorld *world, btScalar timeStep) {
    210     jmePhysicsSpace* dynamicsWorld = (jmePhysicsSpace*) world->getWorldUserInfo();
    211     JNIEnv* env = dynamicsWorld->getEnv();
    212     jobject javaPhysicsSpace = env->NewLocalRef(dynamicsWorld->getJavaPhysicsSpace());
    213     if (javaPhysicsSpace != NULL) {
    214         env->CallVoidMethod(javaPhysicsSpace, jmeClasses::PhysicsSpace_preTick, timeStep);
    215         env->DeleteLocalRef(javaPhysicsSpace);
    216         if (env->ExceptionCheck()) {
    217             env->Throw(env->ExceptionOccurred());
    218             return;
    219         }
    220     }
    221 }
    222 
    223 void jmePhysicsSpace::postTickCallback(btDynamicsWorld *world, btScalar timeStep) {
    224     jmePhysicsSpace* dynamicsWorld = (jmePhysicsSpace*) world->getWorldUserInfo();
    225     JNIEnv* env = dynamicsWorld->getEnv();
    226     jobject javaPhysicsSpace = env->NewLocalRef(dynamicsWorld->getJavaPhysicsSpace());
    227     if (javaPhysicsSpace != NULL) {
    228         env->CallVoidMethod(javaPhysicsSpace, jmeClasses::PhysicsSpace_postTick, timeStep);
    229         env->DeleteLocalRef(javaPhysicsSpace);
    230         if (env->ExceptionCheck()) {
    231             env->Throw(env->ExceptionOccurred());
    232             return;
    233         }
    234     }
    235 }
    236 
    237 bool jmePhysicsSpace::contactProcessedCallback(btManifoldPoint &cp, void *body0, void *body1) {
    238     //    printf("contactProcessedCallback %d %dn", body0, body1);
    239     btCollisionObject* co0 = (btCollisionObject*) body0;
    240     jmeUserPointer *up0 = (jmeUserPointer*) co0 -> getUserPointer();
    241     btCollisionObject* co1 = (btCollisionObject*) body1;
    242     jmeUserPointer *up1 = (jmeUserPointer*) co1 -> getUserPointer();
    243     if (up0 != NULL) {
    244         jmePhysicsSpace *dynamicsWorld = (jmePhysicsSpace *)up0->space;
    245         if (dynamicsWorld != NULL) {
    246             JNIEnv* env = dynamicsWorld->getEnv();
    247             jobject javaPhysicsSpace = env->NewLocalRef(dynamicsWorld->getJavaPhysicsSpace());
    248             if (javaPhysicsSpace != NULL) {
    249                 jobject javaCollisionObject0 = env->NewLocalRef(up0->javaCollisionObject);
    250                 jobject javaCollisionObject1 = env->NewLocalRef(up1->javaCollisionObject);
    251                 env->CallVoidMethod(javaPhysicsSpace, jmeClasses::PhysicsSpace_addCollisionEvent, javaCollisionObject0, javaCollisionObject1, (jlong) & cp);
    252                 env->DeleteLocalRef(javaPhysicsSpace);
    253                 env->DeleteLocalRef(javaCollisionObject0);
    254                 env->DeleteLocalRef(javaCollisionObject1);
    255                 if (env->ExceptionCheck()) {
    256                     env->Throw(env->ExceptionOccurred());
    257                     return true;
    258                 }
    259             }
    260         }
    261     }
    262     return true;
    263 }
    264 
    265 btDynamicsWorld* jmePhysicsSpace::getDynamicsWorld() {
    266     return dynamicsWorld;
    267 }
    268 
    269 jobject jmePhysicsSpace::getJavaPhysicsSpace() {
    270     return javaPhysicsSpace;
    271 }
    272 
    273 jmePhysicsSpace::~jmePhysicsSpace() {
    274     delete(dynamicsWorld);
    275 }