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); }