示例#1
0
        private static bool OnCircleIntersection(RayComponent ray, ColliderComponent col, TransformComponent tr,
                                                 out float2 hitPoint)
        {
            hitPoint = float2.zero;
            float2 source = ray.Source;
            float2 target = ray.Target;
            float2 pos    = tr.Position;
            float  r      = col.Size.x;

            float t;
            float dx = target.x - source.x;
            float dy = target.y - source.y;

            float a    = dx * dx + dy * dy;
            float spDx = source.x - pos.x;
            float spDy = source.y - pos.y;
            float b    = 2 * (dx * spDx + dy * spDy);
            float c    = spDx * spDx + spDy * spDy - r * r;

            float det = b * b - 4 * a * c;

            if (a <= MathHelper.EPSILON || det < 0)
            {
                return(false);
            }

            if (MathHelper.Equal(det, 0))
            {
                t        = -b / (2 * a);
                hitPoint = new float2(source.x + t * dx, source.y + t * dy);
                return(true);
            }

            float sqrtDet = math.sqrt(det);

            t = (-b + sqrtDet) / (2 * a);
            float2 p1 = new float2(source.x + t * dx, source.y + t * dy);

            t = (-b - sqrtDet) / (2 * a);
            float2 p2 = new float2(source.x + t * dx, source.y + t * dy);

            hitPoint = math.distancesq(ray.Source, p1) < math.distancesq(ray.Source, p2) ? p1 : p2;
            return(true);
        }
示例#2
0
        public override bool Hit(RayComponent ray, float min, float max, ref HitInfo result)
        {
            AABB aabb = Value.aabb;
            IHitableComponent left  = Value.left;
            IHitableComponent right = Value.right;

            HitInfo centerHitInfo = new HitInfo();

            if (MathUtility.Hit(ray, min, max, aabb, ref centerHitInfo))
            {
                HitInfo leftHitInfo  = new HitInfo();
                bool    hitLeft      = left.Hit(ray, min, max, ref leftHitInfo);
                HitInfo rightHitInfo = new HitInfo();
                bool    hitRight     = right.Hit(ray, min, max, ref rightHitInfo);

                if (hitLeft && hitRight)
                {
                    if (leftHitInfo.t < rightHitInfo.t)
                    {
                        result = leftHitInfo;
                    }
                    else
                    {
                        result = rightHitInfo;
                    }
                    return(true);
                }

                if (hitLeft)
                {
                    result = leftHitInfo;
                    return(true);
                }

                if (hitRight)
                {
                    result = rightHitInfo;
                    return(true);
                }

                // miss
            }
            return(false);
        }
示例#3
0
        private static void RayTrace(RayComponent ray, ref int[] chunks, ref float2[] points, out int length)
        {
            const float cellSize = BroadphaseHelper.ChunkSize;
            const float offset   = ushort.MaxValue * cellSize;

            float2 source = ray.Source + offset;
            float2 target = ray.Target + offset;

            float x0 = source.x / cellSize;
            float y0 = source.y / cellSize;
            float x1 = target.x / cellSize;
            float y1 = target.y / cellSize;
            float dx = math.abs(x1 - x0);
            float dy = math.abs(y1 - y0);

            int x = (int)math.abs(x0);
            int y = (int)math.abs(y0);

            float dtDx = 1.0f / dx;
            float dtDy = 1.0f / dy;
            float t    = 0.0f;

            int   n = 1;
            int   xInc, yInc;
            float tnv, tnh;

            if (math.abs(dx) < MathHelper.EPSILON)
            {
                xInc = 0;
                tnh  = dtDx;
            }
            else if (x1 > x0)
            {
                xInc = 1;
                n   += (int)math.floor(x1) - x;
                tnh  = (math.floor(x0) + 1 - x0) * dtDx;
            }
            else
            {
                xInc = -1;
                n   += x - (int)math.floor(x1);
                tnh  = (x0 - math.floor(x0)) * dtDx;
            }

            if (math.abs(dy) < MathHelper.EPSILON)
            {
                yInc = 0;
                tnv  = dtDy;
            }
            else if (y1 > y0)
            {
                yInc = 1;
                n   += (int)math.floor(y1) - y;
                tnv  = (math.floor(y0) + 1 - y0) * dtDy;
            }
            else
            {
                yInc = -1;
                n   += y - (int)math.floor(y1);
                tnv  = (y0 - math.floor(y0)) * dtDy;
            }

            length = n + 1;
            for (int i = 0; n > 0; n--, i++)
            {
                float  xPos = t * (x1 - x0) * cellSize;
                float  yPos = t * (y1 - y0) * cellSize;
                float2 pos  = new float2(xPos, yPos);
                points[i] = source + pos - offset;

                short xChunk = (short)(x - ushort.MaxValue);
                short yChunk = (short)(y - ushort.MaxValue);
                chunks[i] = (xChunk << 16) | (ushort)yChunk;

                if (tnv < tnh)
                {
                    y   += yInc;
                    t    = tnv;
                    tnv += dtDy;
                }
                else
                {
                    x   += xInc;
                    t    = tnh;
                    tnh += dtDx;
                }
            }

            points[length - 1] = target - offset;
        }
示例#4
0
        private static bool OnRectIntersection(RayComponent ray, ColliderComponent col, TransformComponent tr,
                                               out float2 hitPoint)
        {
            hitPoint = float2.zero;
            float minDist = float.MaxValue;

            float2x2 rotate   = float2x2.Rotate(tr.Rotation);
            float2x4 vertices = float2x4.zero;

            for (int i = 0; i < 4; i++)
            {
                vertices[i] = MathHelper.Mul(rotate, col.Vertices[i]) + tr.Position;
            }

            for (int i = 0; i < 4; i++)
            {
                int j = i + 1;
                if (j == 4)
                {
                    j = 0;
                }

                float2 p1 = vertices[i];
                float2 p2 = vertices[j];

                float2 b = ray.Target - ray.Source;
                float2 d = p2 - p1;

                float cross = b.x * d.y - b.y * d.x;
                if (MathHelper.Equal(cross, 0))
                {
                    continue;
                }

                float2 c = p1 - ray.Source;
                float  t = (c.x * d.y - c.y * d.x) / cross;
                if (t < 0 || t > 1)
                {
                    continue;
                }

                float u = (c.x * b.y - c.y * b.x) / cross;
                if (u < 0 || u > 1)
                {
                    continue;
                }

                float2 p = ray.Source + t * b;

                float dist = math.distancesq(ray.Source, p);
                if (!(dist < minDist))
                {
                    continue;
                }

                minDist  = dist;
                hitPoint = p;
            }

            return(minDist < float.MaxValue);
        }