Ejemplo n.º 1
0
        public void IntersectPoint(Vector3 point, WorkerCallback intersectCallback)
        {
            Balance();
            MDLCallback callback = new MDLCallback(intersectCallback, m_objects.ToArray(), (uint)m_objects.Count);

            m_tree.IntersectPoint(point, callback);
        }
Ejemplo n.º 2
0
        public void IntersectRay(Ray ray, WorkerCallback intersectCallback, ref float maxDist)
        {
            Balance();
            MDLCallback temp_cb = new MDLCallback(intersectCallback, m_objects.ToArray(), (uint)m_objects.Count);

            m_tree.IntersectRay(ray, temp_cb, ref maxDist, true);
        }
Ejemplo n.º 3
0
        // Optimized verson of intersectRay function for rays with vertical directions
        public void IntersectZAllignedRay(Ray ray, WorkerCallback intersectCallback, ref float max_dist)
        {
            Cell cell = Cell.ComputeCell(ray.Origin.X, ray.Origin.Y);

            if (!cell.IsValid())
            {
                return;
            }

            Node node = nodes[cell.x][cell.y];

            if (node != null)
            {
                node.IntersectRay(ray, intersectCallback, ref max_dist);
            }
        }
Ejemplo n.º 4
0
        public void IntersectPoint(Vector3 point, WorkerCallback intersectCallback)
        {
            Cell cell = Cell.ComputeCell(point.X, point.Y);

            if (!cell.IsValid())
            {
                return;
            }

            Node node = nodes[cell.x][cell.y];

            if (node != null)
            {
                node.IntersectPoint(point, intersectCallback);
            }
        }
Ejemplo n.º 5
0
        public void IntersectRay(Ray ray, WorkerCallback intersectCallback, ref float max_dist, Vector3 end)
        {
            Cell cell = Cell.ComputeCell(ray.Origin.X, ray.Origin.Y);

            if (!cell.IsValid())
            {
                return;
            }

            Cell last_cell = Cell.ComputeCell(end.X, end.Y);

            if (cell == last_cell)
            {
                Node node = nodes[cell.x][cell.y];
                if (node != null)
                {
                    node.IntersectRay(ray, intersectCallback, ref max_dist);
                }
                return;
            }

            float voxel = CELL_SIZE;
            float kx_inv = ray.invDirection().X, bx = ray.Origin.X;
            float ky_inv = ray.invDirection().Y, by = ray.Origin.Y;

            int   stepX, stepY;
            float tMaxX, tMaxY;

            if (kx_inv >= 0)
            {
                stepX = 1;
                float x_border = (cell.x + 1) * voxel;
                tMaxX = (x_border - bx) * kx_inv;
            }
            else
            {
                stepX = -1;
                float x_border = (cell.x - 1) * voxel;
                tMaxX = (x_border - bx) * kx_inv;
            }

            if (ky_inv >= 0)
            {
                stepY = 1;
                float y_border = (cell.y + 1) * voxel;
                tMaxY = (y_border - by) * ky_inv;
            }
            else
            {
                stepY = -1;
                float y_border = (cell.y - 1) * voxel;
                tMaxY = (y_border - by) * ky_inv;
            }

            float tDeltaX = voxel * Math.Abs(kx_inv);
            float tDeltaY = voxel * Math.Abs(ky_inv);

            do
            {
                Node node = nodes[cell.x][cell.y];
                if (node != null)
                {
                    node.IntersectRay(ray, intersectCallback, ref max_dist);
                }
                if (cell == last_cell)
                {
                    break;
                }
                if (tMaxX < tMaxY)
                {
                    tMaxX  += tDeltaX;
                    cell.x += stepX;
                }
                else
                {
                    tMaxY  += tDeltaY;
                    cell.y += stepY;
                }
            } while (cell.IsValid());
        }
Ejemplo n.º 6
0
 public void IntersectRay(Ray ray, WorkerCallback intersectCallback, ref float max_dist)
 {
     IntersectRay(ray, intersectCallback, ref max_dist, ray.Origin + ray.Direction * max_dist);
 }
Ejemplo n.º 7
0
        public void IntersectPoint(Vector3 p, WorkerCallback intersectCallback)
        {
            if (!bounds.contains(p))
            {
                return;
            }

            StackNode[] stack    = new StackNode[64];
            int         stackPos = 0;
            int         node     = 0;

            while (true)
            {
                while (true)
                {
                    uint tn     = tree[node];
                    uint axis   = (uint)(tn & (3 << 30)) >> 30;
                    bool BVH2   = Convert.ToBoolean(tn & (1 << 29));
                    int  offset = (int)(tn & ~(7 << 29));
                    if (!BVH2)
                    {
                        if (axis < 3)
                        {
                            // "normal" interior node
                            float tl = IntBitsToFloat(tree[node + 1]);
                            float tr = IntBitsToFloat(tree[node + 2]);
                            // point is between clip zones
                            if (tl < p[(int)axis] && tr > p[axis])
                            {
                                break;
                            }
                            int right = offset + 3;
                            node = right;
                            // point is in right node only
                            if (tl < p[(int)axis])
                            {
                                continue;
                            }
                            node = offset; // left
                            // point is in left node only
                            if (tr > p[axis])
                            {
                                continue;
                            }
                            // point is in both nodes
                            // push back right node
                            stack[stackPos].node = (uint)right;
                            stackPos++;
                            continue;
                        }
                        else
                        {
                            // leaf - test some objects
                            uint n = tree[node + 1];
                            while (n > 0)
                            {
                                intersectCallback.Invoke(p, objects[offset]); // !!!
                                --n;
                                ++offset;
                            }
                            break;
                        }
                    }
                    else // BVH2 node (empty space cut off left and right)
                    {
                        if (axis > 2)
                        {
                            return; // should not happen
                        }
                        float tl = IntBitsToFloat(tree[node + 1]);
                        float tr = IntBitsToFloat(tree[node + 2]);
                        node = offset;
                        if (tl > p[axis] || tr < p[axis])
                        {
                            break;
                        }
                        continue;
                    }
                } // traversal loop

                // stack is empty?
                if (stackPos == 0)
                {
                    return;
                }
                // move back up the stack
                stackPos--;
                node = (int)stack[stackPos].node;
            }
        }
Ejemplo n.º 8
0
        public void IntersectRay(Ray r, WorkerCallback intersectCallback, ref float maxDist, bool stopAtFirst = false)
        {
            float   intervalMin = -1.0f;
            float   intervalMax = -1.0f;
            Vector3 org         = r.Origin;
            Vector3 dir         = r.Direction;
            Vector3 invDir      = new();

            for (int i = 0; i < 3; ++i)
            {
                invDir[i] = 1.0f / dir[i];
                if (MathFunctions.fuzzyNe(dir[i], 0.0f))
                {
                    float t1 = (bounds.Lo[i] - org[i]) * invDir[i];
                    float t2 = (bounds.Hi[i] - org[i]) * invDir[i];
                    if (t1 > t2)
                    {
                        MathFunctions.Swap <float>(ref t1, ref t2);
                    }
                    if (t1 > intervalMin)
                    {
                        intervalMin = t1;
                    }
                    if (t2 < intervalMax || intervalMax < 0.0f)
                    {
                        intervalMax = t2;
                    }
                    // intervalMax can only become smaller for other axis,
                    //  and intervalMin only larger respectively, so stop early
                    if (intervalMax <= 0 || intervalMin >= maxDist)
                    {
                        return;
                    }
                }
            }

            if (intervalMin > intervalMax)
            {
                return;
            }
            intervalMin = Math.Max(intervalMin, 0.0f);
            intervalMax = Math.Min(intervalMax, maxDist);

            uint[] offsetFront  = new uint[3];
            uint[] offsetBack   = new uint[3];
            uint[] offsetFront3 = new uint[3];
            uint[] offsetBack3  = new uint[3];
            // compute custom offsets from direction sign bit

            for (int i = 0; i < 3; ++i)
            {
                offsetFront[i]  = FloatToRawIntBits(dir[i]) >> 31;
                offsetBack[i]   = offsetFront[i] ^ 1;
                offsetFront3[i] = offsetFront[i] * 3;
                offsetBack3[i]  = offsetBack[i] * 3;

                // avoid always adding 1 during the inner loop
                ++offsetFront[i];
                ++offsetBack[i];
            }

            StackNode[] stack    = new StackNode[64];
            int         stackPos = 0;
            int         node     = 0;

            while (true)
            {
                while (true)
                {
                    uint tn     = tree[node];
                    uint axis   = (uint)(tn & (3 << 30)) >> 30;
                    bool BVH2   = Convert.ToBoolean(tn & (1 << 29));
                    int  offset = (int)(tn & ~(7 << 29));
                    if (!BVH2)
                    {
                        if (axis < 3)
                        {
                            // "normal" interior node
                            float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
                            float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
                            // ray passes between clip zones
                            if (tf < intervalMin && tb > intervalMax)
                            {
                                break;
                            }
                            int back = (int)(offset + offsetBack3[axis]);
                            node = back;
                            // ray passes through far node only
                            if (tf < intervalMin)
                            {
                                intervalMin = (tb >= intervalMin) ? tb : intervalMin;
                                continue;
                            }
                            node = offset + (int)offsetFront3[axis]; // front
                            // ray passes through near node only
                            if (tb > intervalMax)
                            {
                                intervalMax = (tf <= intervalMax) ? tf : intervalMax;
                                continue;
                            }
                            // ray passes through both nodes
                            // push back node
                            stack[stackPos].node  = (uint)back;
                            stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
                            stack[stackPos].tfar  = intervalMax;
                            stackPos++;
                            // update ray interval for front node
                            intervalMax = (tf <= intervalMax) ? tf : intervalMax;
                            continue;
                        }
                        else
                        {
                            // leaf - test some objects
                            int n = (int)tree[node + 1];
                            while (n > 0)
                            {
                                bool hit = intersectCallback.Invoke(r, objects[offset], ref maxDist, stopAtFirst);
                                if (stopAtFirst && hit)
                                {
                                    return;
                                }
                                --n;
                                ++offset;
                            }
                            break;
                        }
                    }
                    else
                    {
                        if (axis > 2)
                        {
                            return; // should not happen
                        }
                        float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
                        float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
                        node        = offset;
                        intervalMin = (tf >= intervalMin) ? tf : intervalMin;
                        intervalMax = (tb <= intervalMax) ? tb : intervalMax;
                        if (intervalMin > intervalMax)
                        {
                            break;
                        }
                        continue;
                    }
                } // traversal loop
                do
                {
                    // stack is empty?
                    if (stackPos == 0)
                    {
                        return;
                    }
                    // move back up the stack
                    stackPos--;
                    intervalMin = stack[stackPos].tnear;
                    if (maxDist < intervalMin)
                    {
                        continue;
                    }
                    node        = (int)stack[stackPos].node;
                    intervalMax = stack[stackPos].tfar;
                    break;
                } while (true);
            }
        }
Ejemplo n.º 9
0
 public MDLCallback(WorkerCallback callback, T[] objects_array, uint size)
 {
     objects      = objects_array;
     _callback    = callback;
     objects_size = size;
 }