159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.bullet;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.app.AppTask;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.AssetManager;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.*;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.shapes.CollisionShape;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.control.PhysicsControl;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.control.RigidBodyControl;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.joints.PhysicsJoint;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsCharacter;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsGhostObject;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsRigidBody;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsVehicle;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Transform;
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Node;
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial;
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Iterator;
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.LinkedList;
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List;
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Map;
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.concurrent.Callable;
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.concurrent.ConcurrentHashMap;
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.concurrent.ConcurrentLinkedQueue;
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.concurrent.Future;
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level;
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger;
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p>PhysicsSpace - The central jbullet-jme physics space</p>
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author normenhansen
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class PhysicsSpace {
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static final int AXIS_X = 0;
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static final int AXIS_Y = 1;
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static final int AXIS_Z = 2;
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private long physicsSpaceId = 0;
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static ThreadLocal<ConcurrentLinkedQueue<AppTask<?>>> pQueueTL =
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            new ThreadLocal<ConcurrentLinkedQueue<AppTask<?>>>() {
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                @Override
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                protected ConcurrentLinkedQueue<AppTask<?>> initialValue() {
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return new ConcurrentLinkedQueue<AppTask<?>>();
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            };
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private ConcurrentLinkedQueue<AppTask<?>> pQueue = new ConcurrentLinkedQueue<AppTask<?>>();
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static ThreadLocal<PhysicsSpace> physicsSpaceTL = new ThreadLocal<PhysicsSpace>();
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private BroadphaseType broadphaseType = BroadphaseType.DBVT;
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private DiscreteDynamicsWorld dynamicsWorld = null;
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private BroadphaseInterface broadphase;
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private CollisionDispatcher dispatcher;
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private ConstraintSolver solver;
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private DefaultCollisionConfiguration collisionConfiguration;
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private Map<GhostObject, PhysicsGhostObject> physicsGhostNodes = new ConcurrentHashMap<GhostObject, PhysicsGhostObject>();
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Map<Long, PhysicsRigidBody> physicsNodes = new ConcurrentHashMap<Long, PhysicsRigidBody>();
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private List<PhysicsJoint> physicsJoints = new LinkedList<PhysicsJoint>();
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private List<PhysicsCollisionListener> collisionListeners = new LinkedList<PhysicsCollisionListener>();
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private List<PhysicsCollisionEvent> collisionEvents = new LinkedList<PhysicsCollisionEvent>();
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Map<Integer, PhysicsCollisionGroupListener> collisionGroupListeners = new ConcurrentHashMap<Integer, PhysicsCollisionGroupListener>();
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private ConcurrentLinkedQueue<PhysicsTickListener> tickListeners = new ConcurrentLinkedQueue<PhysicsTickListener>();
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private PhysicsCollisionEventFactory eventFactory = new PhysicsCollisionEventFactory();
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f worldMax = new Vector3f(10000f, 10000f, 10000f);
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float accuracy = 1f / 60f;
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxSubSteps = 4;
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private AssetManager debugManager;
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    static {
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        System.loadLibrary("bulletjme");
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        initNativePhysics();
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Get the current PhysicsSpace <b>running on this thread</b><br/>
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * For parallel physics, this can also be called from the OpenGL thread to receive the PhysicsSpace
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the PhysicsSpace running on this thread
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static PhysicsSpace getPhysicsSpace() {
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return physicsSpaceTL.get();
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Used internally
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param space
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static void setLocalThreadPhysicsSpace(PhysicsSpace space) {
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsSpaceTL.set(space);
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public PhysicsSpace() {
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), BroadphaseType.DBVT);
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public PhysicsSpace(BroadphaseType broadphaseType) {
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public PhysicsSpace(Vector3f worldMin, Vector3f worldMax) {
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this(worldMin, worldMax, BroadphaseType.AXIS_SWEEP_3);
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public PhysicsSpace(Vector3f worldMin, Vector3f worldMax, BroadphaseType broadphaseType) {
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.worldMin.set(worldMin);
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.worldMax.set(worldMax);
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.broadphaseType = broadphaseType;
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        create();
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Has to be called from the (designated) physics thread
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void create() {
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //TODO: boroadphase!
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsSpaceId = createPhysicsSpace(worldMin.x, worldMin.y, worldMin.z, worldMax.x, worldMax.y, worldMax.z, 3, false);
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        pQueueTL.set(pQueue);
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsSpaceTL.set(this);
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        collisionConfiguration = new DefaultCollisionConfiguration();
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dispatcher = new CollisionDispatcher(collisionConfiguration);
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        switch (broadphaseType) {
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case SIMPLE:
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                broadphase = new SimpleBroadphase();
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                break;
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case AXIS_SWEEP_3:
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                broadphase = new AxisSweep3(Converter.convert(worldMin), Converter.convert(worldMax));
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                break;
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case AXIS_SWEEP_3_32:
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                broadphase = new AxisSweep3_32(Converter.convert(worldMin), Converter.convert(worldMax));
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                break;
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case DBVT:
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                broadphase = new DbvtBroadphase();
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                break;
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        solver = new SequentialImpulseConstraintSolver();
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.setGravity(new javax.vecmath.Vector3f(0, -9.81f, 0));
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        broadphase.getOverlappingPairCache().setInternalGhostPairCallback(new GhostPairCallback());
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        GImpactCollisionAlgorithm.registerAlgorithm(dispatcher);
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        //register filter callback for tick / collision
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        setTickCallback();
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        setContactCallbacks();
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        //register filter callback for collision groups
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        setOverlapFilterCallback();
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native long createPhysicsSpace(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int broadphaseType, boolean threading);
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void preTick_native(float f) {
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        AppTask task = pQueue.poll();
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        task = pQueue.poll();
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        while (task != null) {
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            while (task.isCancelled()) {
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                task = pQueue.poll();
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            try {
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                task.invoke();
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } catch (Exception ex) {
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Logger.getLogger(PhysicsSpace.class.getName()).log(Level.SEVERE, null, ex);
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            task = pQueue.poll();
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Iterator<PhysicsTickListener> it = tickListeners.iterator(); it.hasNext();) {
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            PhysicsTickListener physicsTickCallback = it.next();
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            physicsTickCallback.prePhysicsTick(this, f);
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void postTick_native(float f) {
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Iterator<PhysicsTickListener> it = tickListeners.iterator(); it.hasNext();) {
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            PhysicsTickListener physicsTickCallback = it.next();
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            physicsTickCallback.physicsTick(this, f);
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void addCollision_native() {
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean needCollision_native(PhysicsCollisionObject objectA, PhysicsCollisionObject objectB) {
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return false;
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private void setOverlapFilterCallback() {
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        OverlapFilterCallback callback = new OverlapFilterCallback() {
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            public boolean needBroadphaseCollision(BroadphaseProxy bp, BroadphaseProxy bp1) {
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                boolean collides = (bp.collisionFilterGroup & bp1.collisionFilterMask) != 0;
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                if (collides) {
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    collides = (bp1.collisionFilterGroup & bp.collisionFilterMask) != 0;
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                }
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                if (collides) {
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    assert (bp.clientObject instanceof com.bulletphysics.collision.dispatch.CollisionObject && bp.clientObject instanceof com.bulletphysics.collision.dispatch.CollisionObject);
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    com.bulletphysics.collision.dispatch.CollisionObject colOb = (com.bulletphysics.collision.dispatch.CollisionObject) bp.clientObject;
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    com.bulletphysics.collision.dispatch.CollisionObject colOb1 = (com.bulletphysics.collision.dispatch.CollisionObject) bp1.clientObject;
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    assert (colOb.getUserPointer() != null && colOb1.getUserPointer() != null);
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    PhysicsCollisionObject collisionObject = (PhysicsCollisionObject) colOb.getUserPointer();
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    PhysicsCollisionObject collisionObject1 = (PhysicsCollisionObject) colOb1.getUserPointer();
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    if ((collisionObject.getCollideWithGroups() & collisionObject1.getCollisionGroup()) > 0
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                            || (collisionObject1.getCollideWithGroups() & collisionObject.getCollisionGroup()) > 0) {
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        PhysicsCollisionGroupListener listener = collisionGroupListeners.get(collisionObject.getCollisionGroup());
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        PhysicsCollisionGroupListener listener1 = collisionGroupListeners.get(collisionObject1.getCollisionGroup());
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        if (listener != null) {
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                            return listener.collide(collisionObject, collisionObject1);
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        } else if (listener1 != null) {
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                            return listener1.collide(collisionObject, collisionObject1);
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        }
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        return true;
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    } else {
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        return false;
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    }
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                }
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return collides;
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        };
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.getPairCache().setOverlapFilterCallback(callback);
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private void setTickCallback() {
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        final PhysicsSpace space = this;
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        InternalTickCallback callback2 = new InternalTickCallback() {
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            @Override
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            public void internalTick(DynamicsWorld dw, float f) {
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                //execute task list
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                AppTask task = pQueue.poll();
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                task = pQueue.poll();
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                while (task != null) {
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    while (task.isCancelled()) {
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        task = pQueue.poll();
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    }
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    try {
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        task.invoke();
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    } catch (Exception ex) {
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.SEVERE, null, ex);
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    }
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    task = pQueue.poll();
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                }
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                for (Iterator<PhysicsTickListener> it = tickListeners.iterator(); it.hasNext();) {
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    PhysicsTickListener physicsTickCallback = it.next();
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    physicsTickCallback.prePhysicsTick(space, f);
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                }
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        };
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.setPreTickCallback(callback2);
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        InternalTickCallback callback = new InternalTickCallback() {
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            @Override
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            public void internalTick(DynamicsWorld dw, float f) {
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                for (Iterator<PhysicsTickListener> it = tickListeners.iterator(); it.hasNext();) {
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    PhysicsTickListener physicsTickCallback = it.next();
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    physicsTickCallback.physicsTick(space, f);
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                }
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        };
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.setInternalTickCallback(callback, this);
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private void setContactCallbacks() {
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        BulletGlobals.setContactAddedCallback(new ContactAddedCallback() {
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            public boolean contactAdded(ManifoldPoint cp, com.bulletphysics.collision.dispatch.CollisionObject colObj0,
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    int partId0, int index0, com.bulletphysics.collision.dispatch.CollisionObject colObj1, int partId1,
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    int index1) {
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                System.out.println("contact added");
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return true;
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        });
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        BulletGlobals.setContactProcessedCallback(new ContactProcessedCallback() {
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            public boolean contactProcessed(ManifoldPoint cp, Object body0, Object body1) {
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                if (body0 instanceof CollisionObject && body1 instanceof CollisionObject) {
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    PhysicsCollisionObject node = null, node1 = null;
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    CollisionObject rBody0 = (CollisionObject) body0;
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    CollisionObject rBody1 = (CollisionObject) body1;
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    node = (PhysicsCollisionObject) rBody0.getUserPointer();
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    node1 = (PhysicsCollisionObject) rBody1.getUserPointer();
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    collisionEvents.add(eventFactory.getEvent(PhysicsCollisionEvent.TYPE_PROCESSED, node, node1, cp));
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                }
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return true;
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        });
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        BulletGlobals.setContactDestroyedCallback(new ContactDestroyedCallback() {
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            public boolean contactDestroyed(Object userPersistentData) {
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                System.out.println("contact destroyed");
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return true;
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        });
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void addCollisionEvent_native(PhysicsCollisionObject node, PhysicsCollisionObject node1, long manifoldPointObjectId) {
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        System.out.println("addCollisionEvent:"+node.getObjectId()+" "+ node1.getObjectId());
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        collisionEvents.add(eventFactory.getEvent(PhysicsCollisionEvent.TYPE_PROCESSED, node, node1, manifoldPointObjectId));
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * updates the physics space
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param time the current time value
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void update(float time) {
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        update(time, maxSubSteps);
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * updates the physics space, uses maxSteps<br>
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param time the current time value
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param maxSteps
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void update(float time, int maxSteps) {
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        if (getDynamicsWorld() == null) {
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            return;
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //step simulation
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        stepSimulation(physicsSpaceId, time, maxSteps, accuracy);
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void stepSimulation(long space, float time, int maxSteps, float accuracy);
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void distributeEvents() {
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //add collision callbacks
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        synchronized (collisionEvents) {
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (Iterator<PhysicsCollisionEvent> it = collisionEvents.iterator(); it.hasNext();) {
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                PhysicsCollisionEvent physicsCollisionEvent = it.next();
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                for (PhysicsCollisionListener listener : collisionListeners) {
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    listener.collision(physicsCollisionEvent);
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //recycle events
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                eventFactory.recycle(physicsCollisionEvent);
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                it.remove();
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static <V> Future<V> enqueueOnThisThread(Callable<V> callable) {
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        AppTask<V> task = new AppTask<V>(callable);
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("created apptask");
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        pQueueTL.get().add(task);
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return task;
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * calls the callable on the next physics tick (ensuring e.g. force applying)
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param <V>
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param callable
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public <V> Future<V> enqueue(Callable<V> callable) {
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        AppTask<V> task = new AppTask<V>(callable);
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        pQueue.add(task);
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return task;
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * adds an object to the physics space
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param obj the PhysicsControl or Spatial with PhysicsControl to add
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void add(Object obj) {
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (obj instanceof PhysicsControl) {
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ((PhysicsControl) obj).setPhysicsSpace(this);
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof Spatial) {
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Spatial node = (Spatial) obj;
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            PhysicsControl control = node.getControl(PhysicsControl.class);
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            control.setPhysicsSpace(this);
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsCollisionObject) {
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addCollisionObject((PhysicsCollisionObject) obj);
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsJoint) {
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addJoint((PhysicsJoint) obj);
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw (new UnsupportedOperationException("Cannot add this kind of object to the physics space."));
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void addCollisionObject(PhysicsCollisionObject obj) {
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (obj instanceof PhysicsGhostObject) {
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addGhostObject((PhysicsGhostObject) obj);
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsRigidBody) {
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addRigidBody((PhysicsRigidBody) obj);
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsVehicle) {
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addRigidBody((PhysicsVehicle) obj);
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsCharacter) {
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addCharacter((PhysicsCharacter) obj);
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * removes an object from the physics space
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param obj the PhysicsControl or Spatial with PhysicsControl to remove
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void remove(Object obj) {
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (obj instanceof PhysicsControl) {
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ((PhysicsControl) obj).setPhysicsSpace(null);
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof Spatial) {
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Spatial node = (Spatial) obj;
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            PhysicsControl control = node.getControl(PhysicsControl.class);
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            control.setPhysicsSpace(null);
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsCollisionObject) {
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            removeCollisionObject((PhysicsCollisionObject) obj);
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsJoint) {
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            removeJoint((PhysicsJoint) obj);
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw (new UnsupportedOperationException("Cannot remove this kind of object from the physics space."));
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void removeCollisionObject(PhysicsCollisionObject obj) {
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (obj instanceof PhysicsGhostObject) {
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            removeGhostObject((PhysicsGhostObject) obj);
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsRigidBody) {
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            removeRigidBody((PhysicsRigidBody) obj);
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (obj instanceof PhysicsCharacter) {
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            removeCharacter((PhysicsCharacter) obj);
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * adds all physics controls and joints in the given spatial node to the physics space
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * (e.g. after loading from disk) - recursive if node
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param spatial the rootnode containing the physics objects
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void addAll(Spatial spatial) {
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spatial.getControl(RigidBodyControl.class) != null) {
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            RigidBodyControl physicsNode = spatial.getControl(RigidBodyControl.class);
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!physicsNodes.containsValue(physicsNode)) {
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                physicsNode.setPhysicsSpace(this);
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //add joints
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            List<PhysicsJoint> joints = physicsNode.getJoints();
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (Iterator<PhysicsJoint> it1 = joints.iterator(); it1.hasNext();) {
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                PhysicsJoint physicsJoint = it1.next();
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //add connected physicsnodes if they are not already added
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (!physicsNodes.containsValue(physicsJoint.getBodyA())) {
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (physicsJoint.getBodyA() instanceof PhysicsControl) {
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        add(physicsJoint.getBodyA());
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        addRigidBody(physicsJoint.getBodyA());
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (!physicsNodes.containsValue(physicsJoint.getBodyB())) {
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (physicsJoint.getBodyA() instanceof PhysicsControl) {
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        add(physicsJoint.getBodyB());
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        addRigidBody(physicsJoint.getBodyB());
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (!physicsJoints.contains(physicsJoint)) {
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    addJoint(physicsJoint);
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (spatial.getControl(PhysicsControl.class) != null) {
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            spatial.getControl(PhysicsControl.class).setPhysicsSpace(this);
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //recursion
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spatial instanceof Node) {
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            List<Spatial> children = ((Node) spatial).getChildren();
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (Iterator<Spatial> it = children.iterator(); it.hasNext();) {
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Spatial spat = it.next();
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                addAll(spat);
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Removes all physics controls and joints in the given spatial from the physics space
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * (e.g. before saving to disk) - recursive if node
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param spatial the rootnode containing the physics objects
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void removeAll(Spatial spatial) {
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spatial.getControl(RigidBodyControl.class) != null) {
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            RigidBodyControl physicsNode = spatial.getControl(RigidBodyControl.class);
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (physicsNodes.containsValue(physicsNode)) {
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                physicsNode.setPhysicsSpace(null);
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //remove joints
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            List<PhysicsJoint> joints = physicsNode.getJoints();
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (Iterator<PhysicsJoint> it1 = joints.iterator(); it1.hasNext();) {
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                PhysicsJoint physicsJoint = it1.next();
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //add connected physicsnodes if they are not already added
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (physicsNodes.containsValue(physicsJoint.getBodyA())) {
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (physicsJoint.getBodyA() instanceof PhysicsControl) {
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        remove(physicsJoint.getBodyA());
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        removeRigidBody(physicsJoint.getBodyA());
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (physicsNodes.containsValue(physicsJoint.getBodyB())) {
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (physicsJoint.getBodyA() instanceof PhysicsControl) {
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        remove(physicsJoint.getBodyB());
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        removeRigidBody(physicsJoint.getBodyB());
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (physicsJoints.contains(physicsJoint)) {
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    removeJoint(physicsJoint);
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (spatial.getControl(PhysicsControl.class) != null) {
53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            spatial.getControl(PhysicsControl.class).setPhysicsSpace(null);
53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //recursion
53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spatial instanceof Node) {
53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            List<Spatial> children = ((Node) spatial).getChildren();
53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (Iterator<Spatial> it = children.iterator(); it.hasNext();) {
53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Spatial spat = it.next();
53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                removeAll(spat);
53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void addCollisionObject(long space, long id);
54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void removeCollisionObject(long space, long id);
54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void addRigidBody(long space, long id);
54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void removeRigidBody(long space, long id);
55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void addCharacterObject(long space, long id);
55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void removeCharacterObject(long space, long id);
55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void addAction(long space, long id);
55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void removeAction(long space, long id);
55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void addVehicle(long space, long id);
56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void removeVehicle(long space, long id);
56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void addConstraint(long space, long id);
56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void removeConstraint(long space, long id);
56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void addGhostObject(PhysicsGhostObject node) {
56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding ghost object {0} to physics space.", Long.toHexString(node.getObjectId()));
56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        addCollisionObject(physicsSpaceId, node.getObjectId());
57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void removeGhostObject(PhysicsGhostObject node) {
57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Removing ghost object {0} from physics space.", Long.toHexString(node.getObjectId()));
57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        removeCollisionObject(physicsSpaceId, node.getObjectId());
57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void addCharacter(PhysicsCharacter node) {
57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding character {0} to physics space.", Long.toHexString(node.getObjectId()));
57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        addCharacterObject(physicsSpaceId, node.getObjectId());
58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        addAction(physicsSpaceId, node.getControllerId());
58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.addCollisionObject(node.getObjectId(), CollisionFilterGroups.CHARACTER_FILTER, (short) (CollisionFilterGroups.STATIC_FILTER | CollisionFilterGroups.DEFAULT_FILTER));
58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.addAction(node.getControllerId());
58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void removeCharacter(PhysicsCharacter node) {
58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Removing character {0} from physics space.", Long.toHexString(node.getObjectId()));
58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        removeAction(physicsSpaceId, node.getControllerId());
58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        removeCharacterObject(physicsSpaceId, node.getObjectId());
58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.removeAction(node.getControllerId());
59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.removeCollisionObject(node.getObjectId());
59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void addRigidBody(PhysicsRigidBody node) {
59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsNodes.put(node.getObjectId(), node);
59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //Workaround
59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //It seems that adding a Kinematic RigidBody to the dynamicWorld prevent it from being non kinematic again afterward.
59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //so we add it non kinematic, then set it kinematic again.
59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean kinematic = false;
60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (node.isKinematic()) {
60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            kinematic = true;
60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            node.setKinematic(false);
60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        addRigidBody(physicsSpaceId, node.getObjectId());
60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (kinematic) {
60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            node.setKinematic(true);
60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding RigidBody {0} to physics space.", node.getObjectId());
61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (node instanceof PhysicsVehicle) {
61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding vehicle constraint {0} to physics space.", Long.toHexString(((PhysicsVehicle) node).getVehicleId()));
61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            addVehicle(physicsSpaceId, ((PhysicsVehicle) node).getVehicleId());
61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void removeRigidBody(PhysicsRigidBody node) {
61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (node instanceof PhysicsVehicle) {
61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Removing vehicle constraint {0} from physics space.", Long.toHexString(((PhysicsVehicle) node).getVehicleId()));
61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            removeVehicle(physicsSpaceId, ((PhysicsVehicle) node).getVehicleId());
62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Removing RigidBody {0} from physics space.", Long.toHexString(node.getObjectId()));
62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsNodes.remove(node.getObjectId());
62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        removeRigidBody(physicsSpaceId, node.getObjectId());
62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void addJoint(PhysicsJoint joint) {
62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Adding Joint {0} to physics space.", Long.toHexString(joint.getObjectId()));
62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsJoints.add(joint);
62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        addConstraint(physicsSpaceId, joint.getObjectId());
63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.addConstraint(joint.getObjectId(), !joint.isCollisionBetweenLinkedBodys());
63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
63259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
63359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void removeJoint(PhysicsJoint joint) {
63459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(PhysicsSpace.class.getName()).log(Level.INFO, "Removing Joint {0} from physics space.", Long.toHexString(joint.getObjectId()));
63559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsJoints.remove(joint);
63659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        removeConstraint(physicsSpaceId, joint.getObjectId());
63759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.removeConstraint(joint.getObjectId());
63859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
63959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
64059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
64159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets the gravity of the PhysicsSpace, set before adding physics objects!
64259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param gravity
64359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
64459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setGravity(Vector3f gravity) {
64559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.setGravity(Converter.convert(gravity));
64659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setGravity(physicsSpaceId, gravity);
64759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
64859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
64959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void setGravity(long spaceId, Vector3f gravity);
65059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
65159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    /**
65259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//     * applies gravity value to all objects
65359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//     */
65459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    public void applyGravity() {
65559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta////        dynamicsWorld.applyGravity();
65659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
65759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
65859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    /**
65959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//     * clears forces of all objects
66059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//     */
66159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    public void clearForces() {
66259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta////        dynamicsWorld.clearForces();
66359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
66459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
66559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
66659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Adds the specified listener to the physics tick listeners.
66759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The listeners are called on each physics step, which is not necessarily
66859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * each frame but is determined by the accuracy of the physics space.
66959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param listener
67059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
67159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void addTickListener(PhysicsTickListener listener) {
67259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tickListeners.add(listener);
67359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
67459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
67559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void removeTickListener(PhysicsTickListener listener) {
67659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        tickListeners.remove(listener);
67759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
67859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
67959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
68059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Adds a CollisionListener that will be informed about collision events
68159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param listener the CollisionListener to add
68259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
68359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void addCollisionListener(PhysicsCollisionListener listener) {
68459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        collisionListeners.add(listener);
68559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
68659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
68759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
68859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Removes a CollisionListener from the list
68959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param listener the CollisionListener to remove
69059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
69159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void removeCollisionListener(PhysicsCollisionListener listener) {
69259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        collisionListeners.remove(listener);
69359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
69459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
69559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
69659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Adds a listener for a specific collision group, such a listener can disable collisions when they happen.<br>
69759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * There can be only one listener per collision group.
69859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param listener
69959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param collisionGroup
70059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
70159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void addCollisionGroupListener(PhysicsCollisionGroupListener listener, int collisionGroup) {
70259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        collisionGroupListeners.put(collisionGroup, listener);
70359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
70459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
70559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void removeCollisionGroupListener(int collisionGroup) {
70659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        collisionGroupListeners.remove(collisionGroup);
70759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
70859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
70959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
71059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Performs a ray collision test and returns the results as a list of PhysicsRayTestResults
71159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
71259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public List rayTest(Vector3f from, Vector3f to) {
71359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        List results = new LinkedList();
71459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rayTest(from, to, results);
71559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return (List<PhysicsRayTestResult>) results;
71659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
71759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
71859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
71959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Performs a ray collision test and returns the results as a list of PhysicsRayTestResults
72059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
72159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public List<PhysicsRayTestResult> rayTest(Vector3f from, Vector3f to, List<PhysicsRayTestResult> results) {
72259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        results.clear();
72359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rayTest_native(from, to, physicsSpaceId, results);
72459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return results;
72559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
72659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
72759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public native void rayTest_native(Vector3f from, Vector3f to, long physicsSpaceId, List<PhysicsRayTestResult> results);
72859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
72959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private class InternalRayListener extends CollisionWorld.RayResultCallback {
73059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
73159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        private List<PhysicsRayTestResult> results;
73259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
73359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        public InternalRayListener(List<PhysicsRayTestResult> results) {
73459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            this.results = results;
73559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
73659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
73759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        @Override
73859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        public float addSingleResult(LocalRayResult lrr, boolean bln) {
73959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            PhysicsCollisionObject obj = (PhysicsCollisionObject) lrr.collisionObject.getUserPointer();
74059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            results.add(new PhysicsRayTestResult(obj, Converter.convert(lrr.hitNormalLocal), lrr.hitFraction, bln));
74159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            return lrr.hitFraction;
74259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
74359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
74459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
74559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Performs a sweep collision test and returns the results as a list of PhysicsSweepTestResults<br/>
74659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * You have to use different Transforms for start and end (at least distance > 0.4f).
74759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * SweepTest will not see a collision if it starts INSIDE an object and is moving AWAY from its center.
74859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
74959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end) {
75059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        List<PhysicsSweepTestResult> results = new LinkedList<PhysicsSweepTestResult>();
75159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        if (!(shape.getCShape() instanceof ConvexShape)) {
75259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            Logger.getLogger(PhysicsSpace.class.getName()).log(Level.WARNING, "Trying to sweep test with incompatible mesh shape!");
75359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            return results;
75459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
75559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.convexSweepTest((ConvexShape) shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results));
75659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return results;
75759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
75859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
75959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
76059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
76159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Performs a sweep collision test and returns the results as a list of PhysicsSweepTestResults<br/>
76259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * You have to use different Transforms for start and end (at least distance > 0.4f).
76359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * SweepTest will not see a collision if it starts INSIDE an object and is moving AWAY from its center.
76459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
76559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public List<PhysicsSweepTestResult> sweepTest(CollisionShape shape, Transform start, Transform end, List<PhysicsSweepTestResult> results) {
76659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        results.clear();
76759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        if (!(shape.getCShape() instanceof ConvexShape)) {
76859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            Logger.getLogger(PhysicsSpace.class.getName()).log(Level.WARNING, "Trying to sweep test with incompatible mesh shape!");
76959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            return results;
77059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
77159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.convexSweepTest((ConvexShape) shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results));
77259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return results;
77359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
77459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
77559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    private class InternalSweepListener extends CollisionWorld.ConvexResultCallback {
77659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
77759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        private List<PhysicsSweepTestResult> results;
77859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
77959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        public InternalSweepListener(List<PhysicsSweepTestResult> results) {
78059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            this.results = results;
78159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
78259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
78359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        @Override
78459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        public float addSingleResult(LocalConvexResult lcr, boolean bln) {
78559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            PhysicsCollisionObject obj = (PhysicsCollisionObject) lcr.hitCollisionObject.getUserPointer();
78659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            results.add(new PhysicsSweepTestResult(obj, Converter.convert(lcr.hitNormalLocal), lcr.hitFraction, bln));
78759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            return lcr.hitFraction;
78859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
78959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//    }
79059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
79159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * destroys the current PhysicsSpace so that a new one can be created
79259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
79359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void destroy() {
79459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsNodes.clear();
79559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        physicsJoints.clear();
79659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld.destroy();
79859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        dynamicsWorld = null;
79959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
80059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
80159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
80259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //     * used internally
80359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //     * @return the dynamicsWorld
80459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //     */
80559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public long getSpaceId() {
80659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return physicsSpaceId;
80759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
80859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
80959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BroadphaseType getBroadphaseType() {
81059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return broadphaseType;
81159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
81259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
81359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setBroadphaseType(BroadphaseType broadphaseType) {
81459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.broadphaseType = broadphaseType;
81559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
81659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
81759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
81859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets the maximum amount of extra steps that will be used to step the physics
81959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * when the fps is below the physics fps. Doing this maintains determinism in physics.
82059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * For example a maximum number of 2 can compensate for framerates as low as 30fps
82159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * when the physics has the default accuracy of 60 fps. Note that setting this
82259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * value too high can make the physics drive down its own fps in case its overloaded.
82359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param steps The maximum number of extra steps, default is 4.
82459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
82559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setMaxSubSteps(int steps) {
82659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        maxSubSteps = steps;
82759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
82859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
82959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
83059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * get the current accuracy of the physics computation
83159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the current accuracy
83259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
83359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getAccuracy() {
83459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return accuracy;
83559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
83659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
83759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
83859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * sets the accuracy of the physics computation, default=1/60s<br>
83959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param accuracy
84059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
84159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setAccuracy(float accuracy) {
84259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.accuracy = accuracy;
84359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
84459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
84559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldMin() {
84659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldMin;
84759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
84859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
84959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
85059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * only applies for AXIS_SWEEP broadphase
85159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param worldMin
85259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
85359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setWorldMin(Vector3f worldMin) {
85459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.worldMin.set(worldMin);
85559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
85659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
85759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldMax() {
85859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldMax;
85959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
86059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
86159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
86259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * only applies for AXIS_SWEEP broadphase
86359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param worldMax
86459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
86559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setWorldMax(Vector3f worldMax) {
86659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.worldMax.set(worldMax);
86759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
86859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
86959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
87059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Enable debug display for physics
87159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param manager AssetManager to use to create debug materials
87259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
87359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void enableDebug(AssetManager manager) {
87459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        debugManager = manager;
87559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
87659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
87759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
87859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Disable debug display
87959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
88059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void disableDebug() {
88159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        debugManager = null;
88259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
88359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
88459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public AssetManager getDebugManager() {
88559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return debugManager;
88659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
88759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
88859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public static native void initNativePhysics();
88959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
89059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
89159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * interface with Broadphase types
89259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
89359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public enum BroadphaseType {
89459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
89559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
89659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * basic Broadphase
89759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
89859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        SIMPLE,
89959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
90059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * better Broadphase, needs worldBounds , max Object number = 16384
90159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
90259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        AXIS_SWEEP_3,
90359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
90459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * better Broadphase, needs worldBounds , max Object number = 65536
90559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
90659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        AXIS_SWEEP_3_32,
90759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
90859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * Broadphase allowing quicker adding/removing of physics objects
90959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
91059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        DBVT;
91159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
91259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
91359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
91459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void finalize() throws Throwable {
91559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.finalize();
91659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Finalizing PhysicsSpace {0}", Long.toHexString(physicsSpaceId));
91759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        finalizeNative(physicsSpaceId);
91859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
91959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
92059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private native void finalizeNative(long objectId);
92159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
922