This class holds the various distance field primitives inside an AABBTree Each primitive is encompassed in an AABB, primitive groups are formed and stored in a larger encompassing AABB until all groups have been stored in the root AABB Implementation was shamelessly stolen from box2D since I don't want to lose time with this awful structure...
Exemple #1
0
        /// <summary>
        /// Builds the octree from the AABB tree of distance field primitives
        /// </summary>
        /// <param name="_Tree"></param>
        /// <param name="_MinCellSize"></param>
        public void             Build(AABBTree _Tree, float _MinCellSize)
        {
            if (_Tree.m_Root == null)
            {
                throw new Exception("Invalid AABB tree to build octree from!");
            }

            Cell.MIN_CELL_SIZE = _MinCellSize;

            // Compute maximum extent for our octree from root AABB
            AABBTree.AABB RootAABB     = _Tree.m_Root.m_AABB;
            float         MaxDimension = (RootAABB.m_Max - RootAABB.m_Min).Max();

            MaxDimension *= 1.1f;               // Always a bit larger

            // Build center & min corner
            float3 Center = 0.5f * (RootAABB.m_Max - RootAABB.m_Min);
            float3 Min    = Center - 0.5f * MaxDimension * float3.One;

            // Build root cell
            m_Root        = new Cell();
            m_Root.m_Min  = Min;
            m_Root.m_Size = MaxDimension;

            // Insert each primitive in turn to pre-build important cells
            foreach (IDistanceFieldPrimitive Prim in _Tree.m_Primitives)
            {
                m_Root.InsertAABB(Prim.Min, Prim.Max);
            }

            // Now, build actual cells by querying the distance field
            float3 P;             // = new float3();

            for (int Z = 0; Z < 1; Z++)
            {
                P.z = Min.z + Z * MaxDimension;
                for (int Y = 0; Y < 1; Y++)
                {
                    P.y = Min.y + Y * MaxDimension;
                    for (int X = 0; X < 1; X++)
                    {
                        P.x = Min.x + X * MaxDimension;
                        m_Root.m_Corners[X, Y, Z] = _Tree.EvalDistance(P);
                    }
                }
            }
            m_Root.BuildDistanceFieldCells(_Tree);
        }
Exemple #2
0
        /// <summary>
        /// Builds the octree from the AABB tree of distance field primitives
        /// </summary>
        /// <param name="_Tree"></param>
        /// <param name="_MinCellSize"></param>
        public void Build( AABBTree _Tree, float _MinCellSize )
        {
            if ( _Tree.m_Root == null )
                throw new Exception( "Invalid AABB tree to build octree from!" );

            Cell.MIN_CELL_SIZE = _MinCellSize;

            // Compute maximum extent for our octree from root AABB
            AABBTree.AABB	RootAABB = _Tree.m_Root.m_AABB;
            float			MaxDimension = (RootAABB.m_Max - RootAABB.m_Min).Max();
            MaxDimension *= 1.1f;	// Always a bit larger

            // Build center & min corner
            float3			Center = 0.5f * (RootAABB.m_Max - RootAABB.m_Min);
            float3			Min = Center - 0.5f * MaxDimension * float3.One;

            // Build root cell
            m_Root = new Cell();
            m_Root.m_Min = Min;
            m_Root.m_Size = MaxDimension;

            // Insert each primitive in turn to pre-build important cells
            foreach ( IDistanceFieldPrimitive Prim in _Tree.m_Primitives )
                m_Root.InsertAABB( Prim.Min, Prim.Max );

            // Now, build actual cells by querying the distance field
            float3	P;// = new float3();
            for ( int Z=0; Z < 1; Z++ )
            {
                P.z = Min.z + Z * MaxDimension;
                for ( int Y=0; Y < 1; Y++ )
                {
                    P.y = Min.y + Y * MaxDimension;
                    for ( int X=0; X < 1; X++ )
                    {
                        P.x = Min.x + X * MaxDimension;
                        m_Root.m_Corners[X,Y,Z] = _Tree.EvalDistance( P );
                    }
                }
            }
            m_Root.BuildDistanceFieldCells( _Tree );
        }
Exemple #3
0
            /// <summary>
            /// Builds the final tree cells using the pre-built cells and the distance field
            /// This method expects the current cell's corner distances to be already computed
            /// </summary>
            /// <param name="_Tree"></param>
            internal void   BuildDistanceFieldCells(AABBTree _Tree)
            {
                float ChildSize = 0.5f * m_Size;

                if (ChildSize <= MIN_CELL_SIZE)
                {
                    return;                     // This cell's children will be too small...
                }
                // Build corner distances for all children
                float[,,]       ChildCorners = new float[3, 3, 3];
                ChildCorners[0, 0, 0]        = m_Corners[0, 0, 0];
                ChildCorners[2, 0, 0]        = m_Corners[1, 0, 0];
                ChildCorners[0, 2, 0]        = m_Corners[0, 1, 0];
                ChildCorners[2, 2, 0]        = m_Corners[1, 1, 0];
                ChildCorners[0, 0, 2]        = m_Corners[0, 0, 1];
                ChildCorners[2, 0, 2]        = m_Corners[1, 0, 1];
                ChildCorners[0, 2, 2]        = m_Corners[0, 1, 1];
                ChildCorners[2, 2, 2]        = m_Corners[1, 1, 1];
                float3 P;

                for (int Z = 0; Z < 3; Z++)
                {
                    P.z = m_Min.z + Z * ChildSize;
                    for (int Y = 0; Y < 3; Y++)
                    {
                        P.y = m_Min.y + Y * ChildSize;
                        for (int X = 0; X < 3; X++)
                        {
                            P.x = m_Min.x + X * ChildSize;
                            if (ChildCorners[X, Y, Z] == 0.0f)
                            {
                                ChildCorners[X, Y, Z] = _Tree.EvalDistance(P);
                            }
                        }
                    }
                }

                // Recurse through children that are either:
                //	_ non null (i.e. already created by the first pass)
                //	_ have corners with non-consistent signs (i.e. boundary child)
                for (int Z = 0; Z < 2; Z++)
                {
                    P.z = m_Min.z + Z * ChildSize;
                    float nz = P.z + ChildSize;

                    for (int Y = 0; Y < 2; Y++)
                    {
                        P.y = m_Min.y + Y * ChildSize;
                        float ny = P.y + ChildSize;

                        for (int X = 0; X < 2; X++)
                        {
                            P.x = m_Min.x + X * ChildSize;
                            float nx = P.x + ChildSize;

                            // Grab the child node
                            bool ForceRecurse = false;
                            Cell Child        = m_Children[X, Y, Z];
                            if (Child == null)
                            {                                   // Create missing child
                                Child = new Cell()
                                {
                                    m_Parent = this,
                                    m_Min    = P,
                                    m_Size   = ChildSize
                                };
                                m_Children[X, Y, Z] = Child;
                            }
                            else
                            {
                                ForceRecurse = true;                                    // Was already created by first pass, we need to recurse through it...
                            }
                            // Assign child's corner distances
                            int PositiveCornersCount = 0;
                            int NegativeCornersCount = 0;
                            for (int CZ = 0; CZ < 2; CZ++)
                            {
                                for (int CY = 0; CY < 2; CY++)
                                {
                                    for (int CX = 0; CX < 2; CX++)
                                    {
                                        Child.m_Corners[CX, CY, CZ] = ChildCorners[X + CX, Y + CY, Z + CZ];
                                        if (Child.m_Corners[CX, CY, CZ] > 0.0f)
                                        {
                                            PositiveCornersCount++;
                                        }
                                        else
                                        {
                                            NegativeCornersCount++;
                                        }
                                    }
                                }
                            }

                            // Recurse through child if corners' signs mismatch
                            if (ForceRecurse || (PositiveCornersCount > 0 && NegativeCornersCount > 0))
                            {
                                BuildDistanceFieldCells(_Tree);
                            }
                        }
                    }
                }
            }
Exemple #4
0
            /// <summary>
            /// Builds the final tree cells using the pre-built cells and the distance field
            /// This method expects the current cell's corner distances to be already computed
            /// </summary>
            /// <param name="_Tree"></param>
            internal void BuildDistanceFieldCells( AABBTree _Tree )
            {
                float	ChildSize = 0.5f * m_Size;
                if ( ChildSize <= MIN_CELL_SIZE )
                    return;	// This cell's children will be too small...

                // Build corner distances for all children
                float[,,]	ChildCorners = new float[3,3,3];
                ChildCorners[0,0,0] = m_Corners[0,0,0];
                ChildCorners[2,0,0] = m_Corners[1,0,0];
                ChildCorners[0,2,0] = m_Corners[0,1,0];
                ChildCorners[2,2,0] = m_Corners[1,1,0];
                ChildCorners[0,0,2] = m_Corners[0,0,1];
                ChildCorners[2,0,2] = m_Corners[1,0,1];
                ChildCorners[0,2,2] = m_Corners[0,1,1];
                ChildCorners[2,2,2] = m_Corners[1,1,1];
                float3	P;
                for ( int Z=0; Z < 3; Z++ )
                {
                    P.z = m_Min.z + Z * ChildSize;
                    for ( int Y=0; Y < 3; Y++ )
                    {
                        P.y = m_Min.y + Y * ChildSize;
                        for ( int X=0; X < 3; X++ )
                        {
                            P.x = m_Min.x + X * ChildSize;
                            if ( ChildCorners[X,Y,Z] == 0.0f )
                                ChildCorners[X,Y,Z] = _Tree.EvalDistance( P );
                        }
                    }
                }

                // Recurse through children that are either:
                //	_ non null (i.e. already created by the first pass)
                //	_ have corners with non-consistent signs (i.e. boundary child)
                for ( int Z=0; Z < 2; Z++ )
                {
                    P.z = m_Min.z + Z * ChildSize;
                    float	nz = P.z + ChildSize;

                    for ( int Y=0; Y < 2; Y++ )
                    {
                        P.y = m_Min.y + Y * ChildSize;
                        float	ny = P.y + ChildSize;

                        for ( int X=0; X < 2; X++ )
                        {
                            P.x = m_Min.x + X * ChildSize;
                            float	nx = P.x + ChildSize;

                            // Grab the child node
                            bool	ForceRecurse = false;
                            Cell	Child = m_Children[X,Y,Z];
                            if ( Child == null )
                            {	// Create missing child
                                Child = new Cell() {
                                    m_Parent = this,
                                    m_Min = P,
                                    m_Size = ChildSize
                                };
                                m_Children[X,Y,Z] = Child;
                            }
                            else
                                ForceRecurse = true;	// Was already created by first pass, we need to recurse through it...

                            // Assign child's corner distances
                            int	PositiveCornersCount = 0;
                            int	NegativeCornersCount = 0;
                            for ( int CZ=0; CZ < 2; CZ++ )
                                for ( int CY=0; CY < 2; CY++ )
                                    for ( int CX=0; CX < 2; CX++ )
                                    {
                                        Child.m_Corners[CX,CY,CZ] = ChildCorners[X+CX,Y+CY,Z+CZ];
                                        if ( Child.m_Corners[CX,CY,CZ] > 0.0f )
                                            PositiveCornersCount++;
                                        else
                                            NegativeCornersCount++;
                                    }

                            // Recurse through child if corners' signs mismatch
                            if ( ForceRecurse || (PositiveCornersCount > 0 && NegativeCornersCount > 0) )
                                BuildDistanceFieldCells( _Tree );
                        }
                    }
                }
            }