Package com.bulletphysics.extras.gimpact

Source Code of com.bulletphysics.extras.gimpact.BvhTree

/*
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* This source file is part of GIMPACT Library.
*
* For the latest info, see http://gimpact.sourceforge.net/
*
* Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
* email: projectileman@yahoo.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.extras.gimpact;

import com.bulletphysics.extras.gimpact.BoxCollision.AABB;
import com.bulletphysics.linearmath.VectorUtil;
import cz.advel.stack.Stack;
import javax.vecmath.Vector3f;

/**
*
* @author jezek2
*/
class BvhTree {

  protected int num_nodes = 0;
  protected BvhTreeNodeArray node_array = new BvhTreeNodeArray();
 
  protected int _calc_splitting_axis(BvhDataArray primitive_boxes, int startIndex, int endIndex) {
    Vector3f means = Stack.alloc(Vector3f.class);
    means.set(0f, 0f, 0f);
    Vector3f variance = Stack.alloc(Vector3f.class);
    variance.set(0f, 0f, 0f);

    int numIndices = endIndex - startIndex;

    Vector3f center = Stack.alloc(Vector3f.class);
    Vector3f diff2 = Stack.alloc(Vector3f.class);

    Vector3f tmp1 = Stack.alloc(Vector3f.class);
    Vector3f tmp2 = Stack.alloc(Vector3f.class);

    for (int i=startIndex; i<endIndex; i++) {
      primitive_boxes.getBoundMax(i, tmp1);
      primitive_boxes.getBoundMin(i, tmp2);
      center.add(tmp1, tmp2);
      center.scale(0.5f);
      means.add(center);
    }
    means.scale(1f / (float)numIndices);

    for (int i=startIndex; i<endIndex; i++) {
      primitive_boxes.getBoundMax(i, tmp1);
      primitive_boxes.getBoundMin(i, tmp2);
      center.add(tmp1, tmp2);
      center.scale(0.5f);
      diff2.sub(center, means);
      VectorUtil.mul(diff2, diff2, diff2);
      variance.add(diff2);
    }
    variance.scale(1f / (float)(numIndices - 1));

    return VectorUtil.maxAxis(variance);
  }

  protected int _sort_and_calc_splitting_index(BvhDataArray primitive_boxes, int startIndex, int endIndex, int splitAxis) {
    int splitIndex = startIndex;
    int numIndices = endIndex - startIndex;

    // average of centers
    float splitValue = 0.0f;

    Vector3f means = Stack.alloc(Vector3f.class);
    means.set(0f, 0f, 0f);

    Vector3f center = Stack.alloc(Vector3f.class);

    Vector3f tmp1 = Stack.alloc(Vector3f.class);
    Vector3f tmp2 = Stack.alloc(Vector3f.class);

    for (int i = startIndex; i < endIndex; i++) {
      primitive_boxes.getBoundMax(i, tmp1);
      primitive_boxes.getBoundMin(i, tmp2);
      center.add(tmp1, tmp2);
      center.scale(0.5f);
      means.add(center);
    }
    means.scale(1f / (float) numIndices);

    splitValue = VectorUtil.getCoord(means, splitAxis);

    // sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
    for (int i = startIndex; i < endIndex; i++) {
      primitive_boxes.getBoundMax(i, tmp1);
      primitive_boxes.getBoundMin(i, tmp2);
      center.add(tmp1, tmp2);
      center.scale(0.5f);

      if (VectorUtil.getCoord(center, splitAxis) > splitValue) {
        // swap
        primitive_boxes.swap(i, splitIndex);
        //swapLeafNodes(i,splitIndex);
        splitIndex++;
      }
    }

    // if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
    // otherwise the tree-building might fail due to stack-overflows in certain cases.
    // unbalanced1 is unsafe: it can cause stack overflows
    //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));

    // unbalanced2 should work too: always use center (perfect balanced trees)
    //bool unbalanced2 = true;

    // this should be safe too:
    int rangeBalancedIndices = numIndices / 3;
    boolean unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));

    if (unbalanced) {
      splitIndex = startIndex + (numIndices >> 1);
    }

    boolean unbal = (splitIndex == startIndex) || (splitIndex == (endIndex));
    assert (!unbal);

    return splitIndex;
  }

  protected void _build_sub_tree(BvhDataArray primitive_boxes, int startIndex, int endIndex) {
    int curIndex = num_nodes;
    num_nodes++;

    assert ((endIndex - startIndex) > 0);

    if ((endIndex - startIndex) == 1) {
      // We have a leaf node
      //setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
      //m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
      node_array.set(curIndex, primitive_boxes, startIndex);

      return;
    }
    // calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.

    // split axis
    int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);

    splitIndex = _sort_and_calc_splitting_index(primitive_boxes, startIndex, endIndex, splitIndex);

    //calc this node bounding box

    AABB node_bound = Stack.alloc(AABB.class);
    AABB tmpAABB = Stack.alloc(AABB.class);

    node_bound.invalidate();

    for (int i=startIndex; i<endIndex; i++) {
      primitive_boxes.getBound(i, tmpAABB);
      node_bound.merge(tmpAABB);
    }

    setNodeBound(curIndex, node_bound);

    // build left branch
    _build_sub_tree(primitive_boxes, startIndex, splitIndex);

    // build right branch
    _build_sub_tree(primitive_boxes, splitIndex, endIndex);

    node_array.setEscapeIndex(curIndex, num_nodes - curIndex);
  }
 
  public void build_tree(BvhDataArray primitive_boxes) {
    // initialize node count to 0
    num_nodes = 0;
    // allocate nodes
    node_array.resize(primitive_boxes.size()*2);

    _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
  }

  public void clearNodes() {
    node_array.clear();
    num_nodes = 0;
  }

  public int getNodeCount() {
    return num_nodes;
  }

  /**
   * Tells if the node is a leaf.
   */
  public boolean isLeafNode(int nodeindex) {
    return node_array.isLeafNode(nodeindex);
  }

  public int getNodeData(int nodeindex) {
    return node_array.getDataIndex(nodeindex);
  }

  public void getNodeBound(int nodeindex, AABB bound) {
    node_array.getBound(nodeindex, bound);
  }

  public void setNodeBound(int nodeindex, AABB bound) {
    node_array.setBound(nodeindex, bound);
  }

  public int getLeftNode(int nodeindex) {
    return nodeindex + 1;
  }

  public int getRightNode(int nodeindex) {
    if (node_array.isLeafNode(nodeindex + 1)) {
      return nodeindex + 2;
    }
    return nodeindex + 1 + node_array.getEscapeIndex(nodeindex + 1);
  }

  public int getEscapeNodeIndex(int nodeindex) {
    return node_array.getEscapeIndex(nodeindex);
  }

  public BvhTreeNodeArray get_node_pointer() {
    return node_array;
  }
 
}
TOP

Related Classes of com.bulletphysics.extras.gimpact.BvhTree

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.