示例#1
0
        public bool RayCastStackless(int index)
        {
            LBVHNODE current = NativeNodes[0];

            // Without using stack
            float3 rayDirection = Rays[index].Direction;

            // ----------------------------------------------------------------------------------------------------
            float sA = rayDirection[current.SplitAxis];

            current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
            current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);
            // ----------------------------------------------------------------------------------------------------

            int rootNearID = current.NearNodeID;
            int rootNodeID = current.NodeID;

            current = NativeNodes[rootNearID];

            TraverseSstate state = TraverseSstate.FromParent;

            bool  intersect = false;
            float bestDist  = float.MaxValue;

            while (current.NodeID != rootNodeID)
            {
                switch (state)
                {
                case TraverseSstate.FromChild:
                    int cID = current.NodeID;

                    current = NativeNodes[current.ParentID];

                    // ----------------------------------------------------------------------------------------------------
                    sA = rayDirection[current.SplitAxis];

                    current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                    current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);

                    // ----------------------------------------------------------------------------------------------------

                    if (cID == current.NearNodeID)
                    {
                        current = NativeNodes[current.FarNodeID];
                        state   = TraverseSstate.FromSibling;
                    }
                    else
                    {
                        state = TraverseSstate.FromChild;
                    }

                    break;

                case TraverseSstate.FromSibling:
                    if (!current.IntersectRay(Rays[index]))
                    {
                        current = NativeNodes[current.ParentID];
                        state   = TraverseSstate.FromChild;
                    }
                    else if (current.IsLeaf == 1)
                    {
                        // No need to iterate as we can only have 1 triangle in a leaf node

                        if (NativePrims[current.PrimitivesOffset].IntersectRay(Rays[index], ref TempHi, index))
                        {
                            if (TempHi[index].HitDistance < bestDist)
                            {
                                bestDist        = TempHi[index].HitDistance;
                                HitInfos[index] = TempHi[index];
                                intersect       = true;
                            }
                        }
                        current = NativeNodes[current.ParentID];
                        state   = TraverseSstate.FromChild;
                    }
                    else
                    {
                        // ----------------------------------------------------------------------------------------------------
                        sA = rayDirection[current.SplitAxis];

                        current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                        current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);

                        // ----------------------------------------------------------------------------------------------------

                        current = NativeNodes[current.NearNodeID];
                        state   = TraverseSstate.FromParent;
                    }

                    break;

                case TraverseSstate.FromParent:
                    if (!current.IntersectRay(Rays[index]))
                    {
                        cID     = current.NodeID;
                        current = NativeNodes[current.ParentID];

                        // ----------------------------------------------------------------------------------------------------
                        sA = rayDirection[current.SplitAxis];

                        current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                        current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);

                        current = cID == current.NearNodeID ? NativeNodes[current.FarNodeID] : NativeNodes[current.NearNodeID];
                        state   = TraverseSstate.FromSibling;
                    }
                    else if (current.IsLeaf == 1)
                    {
                        // No need to iterate as we can only have 1 triangle in a leaf node

                        if (NativePrims[current.PrimitivesOffset].IntersectRay(Rays[index], ref TempHi, index))
                        {
                            if (TempHi[index].HitDistance < bestDist)
                            {
                                bestDist        = TempHi[index].HitDistance;
                                HitInfos[index] = TempHi[index];
                                intersect       = true;
                            }
                        }

                        // ----------------------------------------------------------------------------------------------------

                        // ReSharper disable InlineOutVariableDeclaration
                        int lChild, rChild, splitAxis;
                        NativeNodes[current.ParentID].GetChildrenIDsAndSplitAxis(out lChild, out rChild, out splitAxis);

                        sA = rayDirection[splitAxis];
                        int farNodeID = math.@select(rChild, lChild, sA < 0f);
                        current = NativeNodes[farNodeID];
                        state   = TraverseSstate.FromSibling;
                    }
                    else
                    {
                        // ----------------------------------------------------------------------------------------------------

                        sA = rayDirection[current.SplitAxis];

                        current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                        current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);
                        current            = NativeNodes[current.NearNodeID];
                        state = TraverseSstate.FromParent;
                    }
                    break;
                }
            }
            return(intersect);
        }
        public bool RayCastStackless(int index)
        {
            LBVHNODE current      = NativeNodes[0];
            float3   rayDirection = Rays[index].Direction;

            // ----------------------------------------------------------------------------------------------------
            float sA = rayDirection[current.SplitAxis];

            current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
            current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);
            // ----------------------------------------------------------------------------------------------------

            int rootNearID = current.NearNodeID;
            int rootNodeID = current.NodeID;

            current = NativeNodes[rootNearID];

            TraverseState state     = TraverseState.FromParent;
            bool          intersect = false;

            while (current.NodeID != rootNodeID)
            {
                switch (state)
                {
                case TraverseState.FromChild:

                    int cID = current.NodeID;

                    current = NativeNodes[current.ParentID];

                    // ----------------------------------------------------------------------------------------------------
                    sA = rayDirection[current.SplitAxis];
                    current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                    current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);

                    // ----------------------------------------------------------------------------------------------------


                    if (cID == current.NearNodeID)
                    {
                        current = NativeNodes[current.FarNodeID];
                        state   = TraverseState.FromSibling;
                    }
                    else
                    {
                        state = TraverseState.FromChild;
                    }

                    break;

                case TraverseState.FromSibling:

                    // ReSharper disable once NotAccessedVariable
                    float dist;
                    if (!BVHBBox.IntersectRay(Rays[index], current.BMin, current.BMax, out dist))
                    {
                        current = NativeNodes[current.ParentID];
                        state   = TraverseState.FromChild;
                    }
                    else if (current.IsLeaf == 1)
                    {
                        if (NativePrims[current.PrimitivesOffset].IntersectRay(Rays[index], ref TempHi, index))
                        {
                            HitInfos.Add(TempHi[index]);
                            intersect = true;
                        }

                        current = NativeNodes[current.ParentID];
                        state   = TraverseState.FromChild;
                    }
                    else
                    {
                        // ----------------------------------------------------------------------------------------------------
                        sA = rayDirection[current.SplitAxis];
                        current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                        current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);
                        // ----------------------------------------------------------------------------------------------------

                        current = NativeNodes[current.NearNodeID];
                        state   = TraverseState.FromParent;
                    }

                    break;

                case TraverseState.FromParent:
                    if (!BVHBBox.IntersectRay(Rays[index], current.BMin, current.BMax, out dist))
                    {
                        cID     = current.NodeID;
                        current = NativeNodes[current.ParentID];

                        // ----------------------------------------------------------------------------------------------------
                        sA = rayDirection[current.SplitAxis];
                        current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                        current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);
                        // ----------------------------------------------------------------------------------------------------

                        if (cID == current.NearNodeID)
                        {
                            current = NativeNodes[current.FarNodeID];
                            state   = TraverseState.FromSibling;
                        }
                        else
                        {
                            current = NativeNodes[current.NearNodeID];
                            state   = TraverseState.FromSibling;
                        }
                    }
                    else if (current.IsLeaf == 1)
                    {
                        // Test triangle for intersection

                        if (NativePrims[current.PrimitivesOffset].IntersectRay(Rays[index], ref TempHi, index))
                        {
                            HitInfos.Add(TempHi[index]);
                            intersect = true;
                        }

                        // ----------------------------------------------------------------------------------------------------

                        int lChild, rChild, splitAxis;
                        NativeNodes[current.ParentID]
                        .GetChildrenIDsAndSplitAxis(out lChild, out rChild, out splitAxis);
                        sA = rayDirection[splitAxis];

                        //int nearNodeID = math.@select(lChild, rChild, sA < 0f);
                        int farNodeID = math.@select(rChild, lChild, sA < 0f);

                        // ----------------------------------------------------------------------------------------------------

                        current = NativeNodes[farNodeID];
                        state   = TraverseState.FromSibling;
                    }
                    else
                    {
                        // ----------------------------------------------------------------------------------------------------
                        sA = rayDirection[current.SplitAxis];
                        current.NearNodeID = math.@select(current.LChildID, current.RChildID, sA < 0f);
                        current.FarNodeID  = math.@select(current.RChildID, current.LChildID, sA < 0f);
                        // ----------------------------------------------------------------------------------------------------

                        current = NativeNodes[current.NearNodeID];
                        state   = TraverseState.FromParent;
                    }

                    break;
                }
            }

            return(intersect);
        }