Package com.bulletphysics.collision.broadphase

Source Code of com.bulletphysics.collision.broadphase.AxisSweep3Internal

/*
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* AxisSweep3
* Copyright (c) 2006 Simon Hobbs
*
* Bullet Continuous Collision Detection and Physics Library
* Copyright (c) 2003-2008 Erwin Coumans  http://www.bulletphysics.com/
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

package com.bulletphysics.collision.broadphase;

import com.bulletphysics.BulletStats;
import com.bulletphysics.collision.broadphase.AxisSweep3Internal.Handle;
import com.bulletphysics.linearmath.MiscUtil;
import com.bulletphysics.linearmath.VectorUtil;
import com.bulletphysics.util.ObjectArrayList;
import cz.advel.stack.Stack;
import javax.vecmath.Vector3f;

/**
* AxisSweep3Internal is an internal base class that implements sweep and prune.
* Use concrete implementation {@link AxisSweep3} or {@link AxisSweep3_32}.
*
* @author jezek2
*/
public abstract class AxisSweep3Internal extends BroadphaseInterface {

  protected int bpHandleMask;
  protected int handleSentinel;
 
  protected final Vector3f worldAabbMin = new Vector3f(); // overall system bounds
  protected final Vector3f worldAabbMax = new Vector3f(); // overall system bounds

  protected final Vector3f quantize = new Vector3f();     // scaling factor for quantization

  protected int numHandles;                               // number of active handles
  protected int maxHandles;                               // max number of handles
  protected Handle[] pHandles;                            // handles pool
  protected int firstFreeHandle;                        // free handles list

  protected EdgeArray[] pEdges = new EdgeArray[3];      // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)

  protected OverlappingPairCache pairCache;
 
  // OverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to OverlappingPairCache.
  protected OverlappingPairCallback userPairCallback = null;
 
  protected boolean ownsPairCache = false;

  protected int invalidPair = 0;
 
  // JAVA NOTE: added
  protected int mask;
 
  AxisSweep3Internal(Vector3f worldAabbMin, Vector3f worldAabbMax, int handleMask, int handleSentinel, int userMaxHandles/* = 16384*/, OverlappingPairCache pairCache/*=0*/) {
    this.bpHandleMask = handleMask;
    this.handleSentinel = handleSentinel;
    this.pairCache = pairCache;

    int maxHandles = userMaxHandles + 1; // need to add one sentinel handle

    if (this.pairCache == null) {
      this.pairCache = new HashedOverlappingPairCache();
      ownsPairCache = true;
    }

    //assert(bounds.HasVolume());

    // init bounds
    this.worldAabbMin.set(worldAabbMin);
    this.worldAabbMax.set(worldAabbMax);

    Vector3f aabbSize = Stack.alloc(Vector3f.class);
    aabbSize.sub(this.worldAabbMax, this.worldAabbMin);

    int maxInt = this.handleSentinel;

    quantize.set(maxInt / aabbSize.x, maxInt / aabbSize.y, maxInt / aabbSize.z);

    // allocate handles buffer and put all handles on free list
    pHandles = new Handle[maxHandles];
    for (int i=0; i<maxHandles; i++) {
      pHandles[i] = createHandle();
    }
    this.maxHandles = maxHandles;
    this.numHandles = 0;

    // handle 0 is reserved as the null index, and is also used as the sentinel
    firstFreeHandle = 1;
    {
      for (int i=firstFreeHandle; i<maxHandles; i++) {
        pHandles[i].setNextFree(i+1);
      }
      pHandles[maxHandles - 1].setNextFree(0);
    }

    {
      // allocate edge buffers
      for (int i=0; i<3; i++) {
        pEdges[i] = createEdgeArray(maxHandles*2);
      }
    }
    //removed overlap management

    // make boundary sentinels

    pHandles[0].clientObject = null;

    for (int axis = 0; axis < 3; axis++) {
      pHandles[0].setMinEdges(axis, 0);
      pHandles[0].setMaxEdges(axis, 1);

      pEdges[axis].setPos(0, 0);
      pEdges[axis].setHandle(0, 0);
      pEdges[axis].setPos(1, handleSentinel);
      pEdges[axis].setHandle(1, 0);
      //#ifdef DEBUG_BROADPHASE
      //debugPrintAxis(axis);
      //#endif //DEBUG_BROADPHASE
    }
   
    // JAVA NOTE: added
    mask = getMask();
  }

  // allocation/deallocation
  protected int allocHandle() {
    assert (firstFreeHandle != 0);

    int handle = firstFreeHandle;
    firstFreeHandle = getHandle(handle).getNextFree();
    numHandles++;

    return handle;
  }
 
  protected void freeHandle(int handle) {
    assert (handle > 0 && handle < maxHandles);

    getHandle(handle).setNextFree(firstFreeHandle);
    firstFreeHandle = handle;

    numHandles--;
  }
 
  protected boolean testOverlap(int ignoreAxis, Handle pHandleA, Handle pHandleB) {
    // optimization 1: check the array index (memory address), instead of the m_pos

    for (int axis=0; axis<3; axis++) {
      if (axis != ignoreAxis) {
        if (pHandleA.getMaxEdges(axis) < pHandleB.getMinEdges(axis) ||
            pHandleB.getMaxEdges(axis) < pHandleA.getMinEdges(axis)) {
          return false;
        }
      }
    }

    //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)

    /*for (int axis = 0; axis < 3; axis++)
    {
    if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
    m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
    {
    return false;
    }
    }
    */

    return true;
  }
 
  //#ifdef DEBUG_BROADPHASE
  //void debugPrintAxis(int axis,bool checkCardinality=true);
  //#endif //DEBUG_BROADPHASE

  protected void quantize(int[] out, Vector3f point, int isMax) {
    Vector3f clampedPoint = Stack.alloc(point);

    VectorUtil.setMax(clampedPoint, worldAabbMin);
    VectorUtil.setMin(clampedPoint, worldAabbMax);

    Vector3f v = Stack.alloc(Vector3f.class);
    v.sub(clampedPoint, worldAabbMin);
    VectorUtil.mul(v, v, quantize);

    out[0] = (((int)v.x & bpHandleMask) | isMax) & mask;
    out[1] = (((int)v.y & bpHandleMask) | isMax) & mask;
    out[2] = (((int)v.z & bpHandleMask) | isMax) & mask;
  }

  // sorting a min edge downwards can only ever *add* overlaps
  protected void sortMinDown(int axis, int edge, Dispatcher dispatcher, boolean updateOverlaps) {
    EdgeArray edgeArray = pEdges[axis];
    int pEdge_idx = edge;
    int pPrev_idx = pEdge_idx - 1;

    Handle pHandleEdge = getHandle(edgeArray.getHandle(pEdge_idx));

    while (edgeArray.getPos(pEdge_idx) < edgeArray.getPos(pPrev_idx)) {
      Handle pHandlePrev = getHandle(edgeArray.getHandle(pPrev_idx));

      if (edgeArray.isMax(pPrev_idx) != 0) {
        // if previous edge is a maximum check the bounds and add an overlap if necessary
        if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandlePrev)) {
          pairCache.addOverlappingPair(pHandleEdge, pHandlePrev);
          if (userPairCallback != null) {
            userPairCallback.addOverlappingPair(pHandleEdge, pHandlePrev);
            //AddOverlap(pEdge->m_handle, pPrev->m_handle);
          }
        }

        // update edge reference in other handle
        pHandlePrev.incMaxEdges(axis);
      }
      else {
        pHandlePrev.incMinEdges(axis);
      }
      pHandleEdge.decMinEdges(axis);

      // swap the edges
      edgeArray.swap(pEdge_idx, pPrev_idx);

      // decrement
      pEdge_idx--;
      pPrev_idx--;
    }

    //#ifdef DEBUG_BROADPHASE
    //debugPrintAxis(axis);
    //#endif //DEBUG_BROADPHASE
  }
 
  // sorting a min edge upwards can only ever *remove* overlaps
  protected void sortMinUp(int axis, int edge, Dispatcher dispatcher, boolean updateOverlaps) {
    EdgeArray edgeArray = pEdges[axis];
    int pEdge_idx = edge;
    int pNext_idx = pEdge_idx + 1;
    Handle pHandleEdge = getHandle(edgeArray.getHandle(pEdge_idx));

    while (edgeArray.getHandle(pNext_idx) != 0 && (edgeArray.getPos(pEdge_idx) >= edgeArray.getPos(pNext_idx))) {
      Handle pHandleNext = getHandle(edgeArray.getHandle(pNext_idx));

      if (edgeArray.isMax(pNext_idx) != 0) {
        // if next edge is maximum remove any overlap between the two handles
        if (updateOverlaps) {
          Handle handle0 = getHandle(edgeArray.getHandle(pEdge_idx));
          Handle handle1 = getHandle(edgeArray.getHandle(pNext_idx));

          pairCache.removeOverlappingPair(handle0, handle1, dispatcher);
          if (userPairCallback != null) {
            userPairCallback.removeOverlappingPair(handle0, handle1, dispatcher);
          }
        }

        // update edge reference in other handle
        pHandleNext.decMaxEdges(axis);
      }
      else {
        pHandleNext.decMinEdges(axis);
      }
      pHandleEdge.incMinEdges(axis);

      // swap the edges
      edgeArray.swap(pEdge_idx, pNext_idx);

      // increment
      pEdge_idx++;
      pNext_idx++;
    }
  }
 
  // sorting a max edge downwards can only ever *remove* overlaps
  protected void sortMaxDown(int axis, int edge, Dispatcher dispatcher, boolean updateOverlaps) {
    EdgeArray edgeArray = pEdges[axis];
    int pEdge_idx = edge;
    int pPrev_idx = pEdge_idx - 1;
    Handle pHandleEdge = getHandle(edgeArray.getHandle(pEdge_idx));

    while (edgeArray.getPos(pEdge_idx) < edgeArray.getPos(pPrev_idx)) {
      Handle pHandlePrev = getHandle(edgeArray.getHandle(pPrev_idx));

      if (edgeArray.isMax(pPrev_idx) == 0) {
        // if previous edge was a minimum remove any overlap between the two handles
        if (updateOverlaps) {
          // this is done during the overlappingpairarray iteration/narrowphase collision
          Handle handle0 = getHandle(edgeArray.getHandle(pEdge_idx));
          Handle handle1 = getHandle(edgeArray.getHandle(pPrev_idx));
          pairCache.removeOverlappingPair(handle0, handle1, dispatcher);
          if (userPairCallback != null) {
            userPairCallback.removeOverlappingPair(handle0, handle1, dispatcher);
          }
        }

        // update edge reference in other handle
        pHandlePrev.incMinEdges(axis);
      }
      else {
        pHandlePrev.incMaxEdges(axis);
      }
      pHandleEdge.decMaxEdges(axis);

      // swap the edges
      edgeArray.swap(pEdge_idx, pPrev_idx);

      // decrement
      pEdge_idx--;
      pPrev_idx--;
    }

    //#ifdef DEBUG_BROADPHASE
    //debugPrintAxis(axis);
    //#endif //DEBUG_BROADPHASE
  }
 
  // sorting a max edge upwards can only ever *add* overlaps
  protected void sortMaxUp(int axis, int edge, Dispatcher dispatcher, boolean updateOverlaps) {
    EdgeArray edgeArray = pEdges[axis];
    int pEdge_idx = edge;
    int pNext_idx = pEdge_idx + 1;
    Handle pHandleEdge = getHandle(edgeArray.getHandle(pEdge_idx));

    while (edgeArray.getHandle(pNext_idx) != 0 && (edgeArray.getPos(pEdge_idx) >= edgeArray.getPos(pNext_idx))) {
      Handle pHandleNext = getHandle(edgeArray.getHandle(pNext_idx));

      if (edgeArray.isMax(pNext_idx) == 0) {
        // if next edge is a minimum check the bounds and add an overlap if necessary
        if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) {
          Handle handle0 = getHandle(edgeArray.getHandle(pEdge_idx));
          Handle handle1 = getHandle(edgeArray.getHandle(pNext_idx));
          pairCache.addOverlappingPair(handle0, handle1);
          if (userPairCallback != null) {
            userPairCallback.addOverlappingPair(handle0, handle1);
          }
        }

        // update edge reference in other handle
        pHandleNext.decMinEdges(axis);
      }
      else {
        pHandleNext.decMaxEdges(axis);
      }
      pHandleEdge.incMaxEdges(axis);

      // swap the edges
      edgeArray.swap(pEdge_idx, pNext_idx);

      // increment
      pEdge_idx++;
      pNext_idx++;
    }
  }
 
  public int getNumHandles() {
    return numHandles;
  }

  public void calculateOverlappingPairs(Dispatcher dispatcher) {
    if (pairCache.hasDeferredRemoval()) {
      ObjectArrayList<BroadphasePair> overlappingPairArray = pairCache.getOverlappingPairArray();

      // perform a sort, to find duplicates and to sort 'invalid' pairs to the end
      MiscUtil.quickSort(overlappingPairArray, BroadphasePair.broadphasePairSortPredicate);

      MiscUtil.resize(overlappingPairArray, overlappingPairArray.size() - invalidPair, BroadphasePair.class);
      invalidPair = 0;

      int i;

      BroadphasePair previousPair = new BroadphasePair();
      previousPair.pProxy0 = null;
      previousPair.pProxy1 = null;
      previousPair.algorithm = null;

      for (i=0; i<overlappingPairArray.size(); i++) {
        BroadphasePair pair = overlappingPairArray.getQuick(i);

        boolean isDuplicate = (pair.equals(previousPair));

        previousPair.set(pair);

        boolean needsRemoval = false;

        if (!isDuplicate) {
          boolean hasOverlap = testAabbOverlap(pair.pProxy0, pair.pProxy1);

          if (hasOverlap) {
            needsRemoval = false;//callback->processOverlap(pair);
          }
          else {
            needsRemoval = true;
          }
        }
        else {
          // remove duplicate
          needsRemoval = true;
          // should have no algorithm
          assert (pair.algorithm == null);
        }

        if (needsRemoval) {
          pairCache.cleanOverlappingPair(pair, dispatcher);

          //    m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
          //    m_overlappingPairArray.pop_back();
          pair.pProxy0 = null;
          pair.pProxy1 = null;
          invalidPair++;
          BulletStats.gOverlappingPairs--;
        }

      }

      // if you don't like to skip the invalid pairs in the array, execute following code:
      //#define CLEAN_INVALID_PAIRS 1
      //#ifdef CLEAN_INVALID_PAIRS

      // perform a sort, to sort 'invalid' pairs to the end
      MiscUtil.quickSort(overlappingPairArray, BroadphasePair.broadphasePairSortPredicate);

      MiscUtil.resize(overlappingPairArray, overlappingPairArray.size() - invalidPair, BroadphasePair.class);
      invalidPair = 0;
      //#endif//CLEAN_INVALID_PAIRS

      //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
    }
  }
 
  public int addHandle(Vector3f aabbMin, Vector3f aabbMax, Object pOwner, short collisionFilterGroup, short collisionFilterMask, Dispatcher dispatcher, Object multiSapProxy) {
    // quantize the bounds
    int[] min = new int[3], max = new int[3];
    quantize(min, aabbMin, 0);
    quantize(max, aabbMax, 1);

    // allocate a handle
    int handle = allocHandle();

    Handle pHandle = getHandle(handle);

    pHandle.uniqueId = handle;
    //pHandle->m_pOverlaps = 0;
    pHandle.clientObject = pOwner;
    pHandle.collisionFilterGroup = collisionFilterGroup;
    pHandle.collisionFilterMask = collisionFilterMask;
    pHandle.multiSapParentProxy = multiSapProxy;

    // compute current limit of edge arrays
    int limit = numHandles * 2;

    // insert new edges just inside the max boundary edge
    for (int axis = 0; axis < 3; axis++) {
      pHandles[0].setMaxEdges(axis, pHandles[0].getMaxEdges(axis) + 2);

      pEdges[axis].set(limit + 1, limit - 1);

      pEdges[axis].setPos(limit - 1, min[axis]);
      pEdges[axis].setHandle(limit - 1, handle);

      pEdges[axis].setPos(limit, max[axis]);
      pEdges[axis].setHandle(limit, handle);

      pHandle.setMinEdges(axis, limit - 1);
      pHandle.setMaxEdges(axis, limit);
    }

    // now sort the new edges to their correct position
    sortMinDown(0, pHandle.getMinEdges(0), dispatcher, false);
    sortMaxDown(0, pHandle.getMaxEdges(0), dispatcher, false);
    sortMinDown(1, pHandle.getMinEdges(1), dispatcher, false);
    sortMaxDown(1, pHandle.getMaxEdges(1), dispatcher, false);
    sortMinDown(2, pHandle.getMinEdges(2), dispatcher, true);
    sortMaxDown(2, pHandle.getMaxEdges(2), dispatcher, true);

    return handle;
  }
 
  public void removeHandle(int handle, Dispatcher dispatcher) {
    Handle pHandle = getHandle(handle);

    // explicitly remove the pairs containing the proxy
    // we could do it also in the sortMinUp (passing true)
    // todo: compare performance
    if (!pairCache.hasDeferredRemoval()) {
      pairCache.removeOverlappingPairsContainingProxy(pHandle, dispatcher);
    }

    // compute current limit of edge arrays
    int limit = numHandles * 2;

    int axis;

    for (axis = 0; axis < 3; axis++) {
      pHandles[0].setMaxEdges(axis, pHandles[0].getMaxEdges(axis) - 2);
    }

    // remove the edges by sorting them up to the end of the list
    for (axis = 0; axis < 3; axis++) {
      EdgeArray pEdges = this.pEdges[axis];
      int max = pHandle.getMaxEdges(axis);
      pEdges.setPos(max, handleSentinel);

      sortMaxUp(axis, max, dispatcher, false);

      int i = pHandle.getMinEdges(axis);
      pEdges.setPos(i, handleSentinel);

      sortMinUp(axis, i, dispatcher, false);

      pEdges.setHandle(limit - 1, 0);
      pEdges.setPos(limit - 1, handleSentinel);

      //#ifdef DEBUG_BROADPHASE
      //debugPrintAxis(axis,false);
      //#endif //DEBUG_BROADPHASE
    }

    // free the handle
    freeHandle(handle);
  }
 
  public void updateHandle(int handle, Vector3f aabbMin, Vector3f aabbMax, Dispatcher dispatcher) {
    Handle pHandle = getHandle(handle);

    // quantize the new bounds
    int[] min = new int[3], max = new int[3];
    quantize(min, aabbMin, 0);
    quantize(max, aabbMax, 1);

    // update changed edges
    for (int axis = 0; axis < 3; axis++) {
      int emin = pHandle.getMinEdges(axis);
      int emax = pHandle.getMaxEdges(axis);

      int dmin = (int) min[axis] - (int) pEdges[axis].getPos(emin);
      int dmax = (int) max[axis] - (int) pEdges[axis].getPos(emax);

      pEdges[axis].setPos(emin, min[axis]);
      pEdges[axis].setPos(emax, max[axis]);

      // expand (only adds overlaps)
      if (dmin < 0) {
        sortMinDown(axis, emin, dispatcher, true);
      }
      if (dmax > 0) {
        sortMaxUp(axis, emax, dispatcher, true); // shrink (only removes overlaps)
      }
      if (dmin > 0) {
        sortMinUp(axis, emin, dispatcher, true);
      }
      if (dmax < 0) {
        sortMaxDown(axis, emax, dispatcher, true);
      }
       
      //#ifdef DEBUG_BROADPHASE
      //debugPrintAxis(axis);
      //#endif //DEBUG_BROADPHASE
    }
  }
 
  public Handle getHandle(int index) {
    return pHandles[index];
  }
 
  //public void processAllOverlappingPairs(OverlapCallback callback) {
  //}
 
  public BroadphaseProxy createProxy(Vector3f aabbMin, Vector3f aabbMax, BroadphaseNativeType shapeType, Object userPtr, short collisionFilterGroup, short collisionFilterMask, Dispatcher dispatcher, Object multiSapProxy) {
    int handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher, multiSapProxy);

    Handle handle = getHandle(handleId);

    return handle;
  }
 
  public void destroyProxy(BroadphaseProxy proxy, Dispatcher dispatcher) {
    Handle handle = (Handle)proxy;
    removeHandle(handle.uniqueId, dispatcher);
  }

  public void setAabb(BroadphaseProxy proxy, Vector3f aabbMin, Vector3f aabbMax, Dispatcher dispatcher) {
    Handle handle = (Handle) proxy;
    updateHandle(handle.uniqueId, aabbMin, aabbMax, dispatcher);
  }
 
  public boolean testAabbOverlap(BroadphaseProxy proxy0, BroadphaseProxy proxy1) {
    Handle pHandleA = (Handle)proxy0;
    Handle pHandleB = (Handle)proxy1;

    // optimization 1: check the array index (memory address), instead of the m_pos

    for (int axis = 0; axis < 3; axis++) {
      if (pHandleA.getMaxEdges(axis) < pHandleB.getMinEdges(axis) ||
          pHandleB.getMaxEdges(axis) < pHandleA.getMinEdges(axis)) {
        return false;
      }
    }
    return true;
  }

  public OverlappingPairCache getOverlappingPairCache() {
    return pairCache;
  }

  public void setOverlappingPairUserCallback(OverlappingPairCallback pairCallback) {
    userPairCallback = pairCallback;
  }
 
  public OverlappingPairCallback getOverlappingPairUserCallback() {
    return userPairCallback;
  }
 
  // getAabb returns the axis aligned bounding box in the 'global' coordinate frame
  // will add some transform later
  public void getBroadphaseAabb(Vector3f aabbMin, Vector3f aabbMax) {
    aabbMin.set(worldAabbMin);
    aabbMax.set(worldAabbMax);
  }

  public void printStats() {
    /*
    printf("btAxisSweep3.h\n");
    printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
    printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
    m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
    */
  }
 
  ////////////////////////////////////////////////////////////////////////////
 
  protected abstract EdgeArray createEdgeArray(int size);
  protected abstract Handle createHandle();
  protected abstract int getMask();
 
  protected static abstract class EdgeArray {
    public abstract void swap(int idx1, int idx2);
    public abstract void set(int dest, int src);
   
    public abstract int getPos(int index);
    public abstract void setPos(int index, int value);

    public abstract int getHandle(int index);
    public abstract void setHandle(int index, int value);
   
    public int isMax(int offset) {
      return (getPos(offset) & 1);
    }
  }
 
  protected static abstract class Handle extends BroadphaseProxy {
    public abstract int getMinEdges(int edgeIndex);
    public abstract void setMinEdges(int edgeIndex, int value);
   
    public abstract int getMaxEdges(int edgeIndex);
    public abstract void setMaxEdges(int edgeIndex, int value);

    public void incMinEdges(int edgeIndex) {
      setMinEdges(edgeIndex, getMinEdges(edgeIndex)+1);
    }

    public void incMaxEdges(int edgeIndex) {
      setMaxEdges(edgeIndex, getMaxEdges(edgeIndex)+1);
    }

    public void decMinEdges(int edgeIndex) {
      setMinEdges(edgeIndex, getMinEdges(edgeIndex)-1);
    }

    public void decMaxEdges(int edgeIndex) {
      setMaxEdges(edgeIndex, getMaxEdges(edgeIndex)-1);
    }
   
    public void setNextFree(int next) {
      setMinEdges(0, next);
    }
   
    public int getNextFree() {
      return getMinEdges(0);
    }
  }
 
}
TOP

Related Classes of com.bulletphysics.collision.broadphase.AxisSweep3Internal

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.