예제 #1
0
 public CollisioinTreeNode()
 {
     AABB = new Bounds();
     AABB.Clear();
     LstCDBrush = new List <CDBrush>();
     Children   = new CollisioinTreeNode[8];
 }
예제 #2
0
    private void Remove(CollisioinTreeNode pNode, CDBrush brush)
    {
        for (int i = 0; i < 8; ++i)
        {
            if (pNode.Children.Length > i)
            {
                Split(pNode.Children[i]);
            }
        }

        for (int i = 0; i < pNode.LstCDBrush.Count; ++i)
        {
            if (pNode.LstCDBrush[i] == brush)
            {
                pNode.LstCDBrush.RemoveAt(i);
                break;
            }
        }
    }
예제 #3
0
    public void Build(List <CDBrush> brushs, int minbrushinnode = 16, float minnodesize = 16)
    {
        Release();

        _MinBrushInNode = minbrushinnode;
        _MinNodeSize    = minnodesize;
        _Root           = new CollisioinTreeNode();

        Bounds aabb = _Root.AABB;

        int all = brushs.Count;

        for (int i = 0; i < all; ++i)
        {
            aabb.Merge(brushs[i].BoundAABB);
            _Root.LstCDBrush.Add(brushs[i]);
        }

        Split(_Root);
    }
예제 #4
0
    private void Split(CollisioinTreeNode pNode)
    {
        int nBrushes = pNode.LstCDBrush.Count;

        if (nBrushes < _MinBrushInNode)
        {
            return;
        }
        if (pNode.AABB.extents.x * 2 < _MinNodeSize + 0.1f)
        {
            return;
        }

        Vector3 child_ext = pNode.AABB.extents * 0.5f;

        float[] candidatex = new float[] { pNode.AABB.center.x - child_ext.x, pNode.AABB.center.x + child_ext.x };
        float[] candidatey = new float[] { pNode.AABB.center.y - child_ext.y, pNode.AABB.center.y + child_ext.y };
        float[] candidatez = new float[] { pNode.AABB.center.z - child_ext.z, pNode.AABB.center.z + child_ext.z };

        for (int i = 0; i < 8; ++i)
        {
            pNode.Children[i]              = new CollisioinTreeNode();
            pNode.Children[i].AABB.center  = new Vector3(candidatex[i & 1], candidatey[(i & 2) >> 1], candidatez[(i & 4) >> 2]);
            pNode.Children[i].AABB.extents = child_ext;

            //divide brushes into child node
            for (int j = 0; j < nBrushes; ++j)
            {
                if (BoundsExtansions.AABBAABBOverlap(pNode.LstCDBrush[j].BoundAABB, pNode.Children[i].AABB))
                {
                    pNode.Children[i].LstCDBrush.Add(pNode.LstCDBrush[j]);
                }
            }

            Split(pNode.Children[i]);
        }

        //remove brushes of parent node
        pNode.LstCDBrush.Clear();
    }
예제 #5
0
    public bool _PointInBrush(CollisioinTreeNode pNode, Vector3 p, float offset)
    {
        if (null == pNode)
        {
            return(false);
        }

        if (!pNode.AABB.IsPointIn(p, offset))
        {
            return(false);
        }

        if (pNode.IsLeaf())
        {
            int i;
            for (i = 0; i < (int)pNode.LstCDBrush.Count; ++i)
            {
                CDBrush pBrush = pNode.LstCDBrush[i];

                if (pBrush.PointInBrush(p, offset))
                {
                    return(true);
                }
            }
        }
        else
        {
            for (int j = 0; j < 8; j++)
            {
                if (_PointInBrush(pNode.Children[j], p, offset))
                {
                    return(true);
                }
            }
        }

        return(false);
    }
예제 #6
0
 public CollisionTree()
 {
     _Root = new CollisioinTreeNode();
 }
예제 #7
0
    private bool _CapsuleTraceBrush(CollisioinTreeNode pNode, CapsuleTraceBrushInfo pInfo)
    {
        if (null == pNode || null == pInfo)
        {
            return(false);
        }

        if (!BoundsExtansions.AABBAABBOverlap(pNode.AABB, pInfo.Bound))
        {
            return(false);
        }

        bool bCollide    = false;
        bool bStartSolid = false;

        CDBrush       HitObject = null;
        CollidePoints HitPoints = new CollidePoints();
        Vector3       normal    = Vector3.zero;
        float         fFraction = 100.0f;

        if (pNode.IsLeaf())
        {
            int i;
            for (i = 0; i < (int)pNode.LstCDBrush.Count; ++i)
            {
                CDBrush pBrush = pNode.LstCDBrush[i];

                if (pBrush.CapsuleTraceBrush(pInfo) && (pInfo.Fraction < fFraction))
                {
                    //update the saving info
                    bStartSolid = pInfo.StartSolid;
                    fFraction   = pInfo.Fraction;
                    HitObject   = pInfo.HitObject;
                    HitPoints   = pInfo.HitPoints;
                    normal      = pInfo.Normal;
                    bCollide    = true;

                    //if (pInfo.Fraction == 0.0f)
                    //{
                    //    break;
                    //}
                }
            }
        }
        else
        {
            for (int j = 0; j < 8; j++)
            {
                if (_CapsuleTraceBrush(pNode.Children[j], pInfo) && pInfo.Fraction < fFraction)
                {
                    bStartSolid = pInfo.StartSolid;
                    fFraction   = pInfo.Fraction;
                    HitObject   = pInfo.HitObject;
                    HitPoints   = pInfo.HitPoints;
                    normal      = pInfo.Normal;
                    bCollide    = true;
                    //if (pInfo.Fraction == 0.0f)
                    //{
                    //    break;
                    //}
                }
            }
        }

        if (bCollide)
        {
            //set back
            pInfo.StartSolid = bStartSolid;
            pInfo.Fraction   = fFraction;
            pInfo.HitObject  = HitObject;
            pInfo.HitPoints  = HitPoints;
            pInfo.Normal     = normal;
        }
        return(bCollide);
    }