private void BuildSubTree(GIM_BVH_DATA_ARRAY primitive_boxes, int startIndex, int endIndex)
        {
            int curIndex = m_num_nodes;

            m_num_nodes++;

            Debug.Assert((endIndex - startIndex) > 0);

            if ((endIndex - startIndex) <= MAX_INDICES_PER_NODE)
            {
                //We have a leaf node
                int   count   = endIndex - startIndex;
                int[] indices = new int[count];
                AABB  bounds  = new AABB();
                bounds.Invalidate();

                for (int i = 0; i < count; i++)
                {
                    indices[i] = primitive_boxes[startIndex + i].m_data;
                    bounds.Merge(primitive_boxes.GetRawArray()[startIndex + i].m_bound);
                }
                SetNodeBound(curIndex, ref bounds);
                m_node_array[curIndex].SetDataIndices(indices);

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

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

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


            //calc this node bounding box

            AABB node_bound = new AABB();

            node_bound.Invalidate();

            for (int i = startIndex; i < endIndex; i++)
            {
                node_bound.Merge(ref primitive_boxes.GetRawArray()[i].m_bound);
            }

            SetNodeBound(curIndex, ref node_bound);


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


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

            m_node_array.GetRawArray()[curIndex].SetEscapeIndex(m_num_nodes - curIndex);
        }
Beispiel #2
0
        protected int CalcSplittingAxis(GIM_BVH_DATA_ARRAY primitive_boxes, int startIndex, int endIndex)
        {
            int i;

            IndexedVector3 means      = IndexedVector3.Zero;
            IndexedVector3 variance   = IndexedVector3.Zero;
            int            numIndices = endIndex - startIndex;

            for (i = startIndex; i < endIndex; i++)
            {
                IndexedVector3 center = 0.5f * (primitive_boxes[i].m_bound.m_max +
                                                primitive_boxes[i].m_bound.m_min);
                means += center;
            }
            means *= (1.0f / (float)numIndices);

            for (i = startIndex; i < endIndex; i++)
            {
                IndexedVector3 center = 0.5f * (primitive_boxes[i].m_bound.m_max +
                                                primitive_boxes[i].m_bound.m_min);
                IndexedVector3 diff2 = center - means;
                diff2     = diff2 * diff2;
                variance += diff2;
            }
            variance *= (1.0f) / ((float)numIndices - 1);

            return(MathUtil.MaxAxis(ref variance));
        }
Beispiel #3
0
        protected int SortAndCalcSplittingIndex(
            GIM_BVH_DATA_ARRAY primitive_boxes,
            int startIndex, int endIndex, int splitAxis)
        {
            int i;
            int splitIndex = startIndex;
            int numIndices = endIndex - startIndex;

            // average of centers
            float splitValue = 0.0f;

            IndexedVector3 means = IndexedVector3.Zero;

            for (i = startIndex; i < endIndex; i++)
            {
                IndexedVector3 center = 0.5f * (primitive_boxes[i].m_bound.m_max +
                                                primitive_boxes[i].m_bound.m_min);
                means += center;
            }
            means *= (1.0f) / (float)numIndices;

            splitValue = means[splitAxis];


            //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
            for (i = startIndex; i < endIndex; i++)
            {
                IndexedVector3 center = 0.5f * (primitive_boxes[i].m_bound.m_max +
                                                primitive_boxes[i].m_bound.m_min);
                if (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;
            bool unbalanced           = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));

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

            Debug.Assert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));

            return(splitIndex);
        }
        //! prototype functions for box tree management
        //!@{
        internal void BuildTree(GIM_BVH_DATA_ARRAY primitive_boxes)
        {
            CalcQuantization(primitive_boxes);
            // initialize node count to 0
            m_num_nodes = 0;
            // allocate nodes
            m_node_array.Resize(primitive_boxes.Count * 2);

            BuildSubTree(primitive_boxes, 0, primitive_boxes.Count);
        }
Beispiel #5
0
        //! prototype functions for box tree management
        //!@{
        public void BuildTree(GIM_BVH_DATA_ARRAY primitive_boxes)
        {
            // initialize node count to 0
            m_num_nodes = 0;
            // allocate nodes
            m_node_array.Capacity = (primitive_boxes.Count * 2);

            // check this- should be capacity or count??
            BuildSubTree(primitive_boxes, 0, primitive_boxes.Count);
        }
Beispiel #6
0
        //! this rebuild the entire set
        public void BuildSet()
        {
            //obtain primitive boxes
            GIM_BVH_DATA_ARRAY primitive_boxes = new GIM_BVH_DATA_ARRAY();

            //primitive_boxes.resize(m_primitive_manager.get_primitive_count());
            primitive_boxes.Capacity = m_primitive_manager.GetPrimitiveCount();
            for (int i = 0; i < primitive_boxes.Count; i++)
            {
                m_primitive_manager.GetPrimitiveBox(i, out primitive_boxes.GetRawArray()[i].m_bound);
                primitive_boxes.GetRawArray()[i].m_data = i;
            }

            m_box_tree.BuildTree(primitive_boxes);
        }
Beispiel #7
0
        protected void CalcQuantization(GIM_BVH_DATA_ARRAY primitive_boxes, float boundMargin)
        {
            //calc globa box
            AABB global_bound = new AABB();

            global_bound.Invalidate();

            int count = primitive_boxes.Count;

            for (int i = 0; i < count; i++)
            {
                global_bound.Merge(ref primitive_boxes.GetRawArray()[i].m_bound);
            }

            GImpactQuantization.CalcQuantizationParameters(out m_global_bound.m_min, out m_global_bound.m_max, out m_bvhQuantization, ref global_bound.m_min, ref global_bound.m_max, boundMargin);
        }
Beispiel #8
0
        //! this rebuild the entire set
        public void BuildSet()
        {
            //obtain primitive boxes
            int listSize = m_primitive_manager.GetPrimitiveCount();
            GIM_BVH_DATA_ARRAY primitive_boxes = new GIM_BVH_DATA_ARRAY(listSize);

            // forces boxes to be allocated
            primitive_boxes.Resize(listSize);

            GIM_BVH_DATA[] rawArray = primitive_boxes.GetRawArray();
            for (int i = 0; i < listSize; i++)
            {
                m_primitive_manager.GetPrimitiveBox(i, out rawArray[i].m_bound);
                rawArray[i].m_data = i;
            }

            m_box_tree.BuildTree(primitive_boxes);
        }
Beispiel #9
0
        protected void BuildSubTree(GIM_BVH_DATA_ARRAY primitive_boxes, int startIndex, int endIndex)
        {
            int curIndex = m_num_nodes;

            m_num_nodes++;

            Debug.Assert((endIndex - startIndex) > 0);

            if ((endIndex - startIndex) == 1)
            {
                //We have a leaf node
                SetNodeBound(curIndex, ref primitive_boxes.GetRawArray()[startIndex].m_bound);
                m_node_array[curIndex].SetDataIndex(primitive_boxes[startIndex].m_data);
#if DEBUG
                if (BulletGlobals.g_streamWriter != null && BulletGlobals.debugGimpactBVH)
                {
                    BulletGlobals.g_streamWriter.WriteLine("bst curIndex[{0}] dataIndex[{1}]", curIndex, primitive_boxes[startIndex].m_data);
                    MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "bst min", primitive_boxes[startIndex].m_bound.m_min);
                    MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "bst max", primitive_boxes[startIndex].m_bound.m_max);
                }
#endif

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

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

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


            //calc this node bounding box

            AABB node_bound = new AABB();
            node_bound.Invalidate();

            for (int i = startIndex; i < endIndex; i++)
            {
                node_bound.Merge(ref primitive_boxes.GetRawArray()[i].m_bound);
            }

            SetNodeBound(curIndex, ref node_bound);


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


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

            m_node_array.GetRawArray()[curIndex].SetEscapeIndex(m_num_nodes - curIndex);
#if DEBUG
            if (BulletGlobals.g_streamWriter != null && BulletGlobals.debugGimpactBVH)
            {
                BulletGlobals.g_streamWriter.WriteLine("bst curIndex[{0}] escapeIndex[{1}]", curIndex, m_node_array.GetRawArray()[curIndex].GetEscapeIndex());
                MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "bst node min", node_bound.m_min);
                MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "bst node max", node_bound.m_max);
            }
#endif
        }
Beispiel #10
0
 protected void CalcQuantization(GIM_BVH_DATA_ARRAY primitive_boxes)
 {
     CalcQuantization(primitive_boxes, 1.0f);
 }