Exemplo n.º 1
0
        private void CheckBrush(ref Q3Brush brush, ref Q3CollisionData cd)
        {
            float startFraction = -1.0f;
            float endFraction = 1.0f;
            bool startsOut = false;
            bool endsOut = false;

            for (int i = 0; i < brush.NumSides; i++)
            {
                Q3BrushSide brushSide = m_brushSides[brush.FirstSide + i];
                Q3Plane plane = m_planes[brushSide.PlaneNum];

                float startDistance = 0, endDistance = 0;

                if (cd.type == Q3CollisionType.Ray)
                {
                    startDistance = cd.startPosition.Dot(new Vector3( plane.Normal) ) - plane.Distance;
                    endDistance = cd.endPosition.Dot(new Vector3(plane.Normal) ) - plane.Distance;
                }

                else if (cd.type == Q3CollisionType.Sphere)
                {
                    startDistance = cd.startPosition.Dot(new Vector3( plane.Normal)) - (plane.Distance + cd.sphereRadius);
                    endDistance = cd.endPosition.Dot(new Vector3( plane.Normal)) - (plane.Distance + cd.sphereRadius);
                }

                else if (cd.type == Q3CollisionType.Box)
                {
                    Vector3 offset = new Vector3();
                    if ((new Vector3(plane.Normal)).X < 0)
                        offset.X = cd.boxMaximums.X;
                    else
                        offset.X = cd.boxMinimums.X;

                    if ((new Vector3(plane.Normal)).Y < 0)
                        offset.Y = cd.boxMaximums.Y;
                    else
                        offset.Y = cd.boxMinimums.Y;

                    if ((new Vector3(plane.Normal)).Z < 0)
                        offset.Z = cd.boxMaximums.Z;
                    else
                        offset.Z = cd.boxMinimums.Z;

                    startDistance = (cd.startPosition.X + offset.X) * (new Vector3(plane.Normal)).X +
                                    (cd.startPosition.Y + offset.Y) * (new Vector3(plane.Normal)).Y +
                                    (cd.startPosition.Z + offset.Z) * (new Vector3(plane.Normal)).Z -
                                    plane.Distance;

                    endDistance = (cd.endPosition.X + offset.X) * (new Vector3(plane.Normal)).X +
                                  (cd.endPosition.Y + offset.Y) * (new Vector3(plane.Normal)).Y +
                                  (cd.endPosition.Z + offset.Z) * (new Vector3(plane.Normal)).Z -
                                  plane.Distance;
                }

                if (startDistance > 0)
                    startsOut = true;
                if (endDistance > 0)
                    endsOut = true;

                if (startDistance > 0 && endDistance > 0)
                {
                    return;
                }

                if (startDistance <= 0 && endDistance <= 0)
                {
                    continue;
                }

                if (startDistance > endDistance)
                {
                    float fraction = (startDistance - Q3Constants.Epsilon) / (startDistance - endDistance);
                    if (fraction > startFraction)
                        startFraction = fraction;
                }
                else
                {
                    float fraction = (startDistance + Q3Constants.Epsilon) / (startDistance - endDistance);
                    if (fraction < endFraction)
                        endFraction = fraction;
                }
            }

            if (false == startsOut)
            {
                cd.startOutside = false;
                if (false == endsOut)
                    cd.inSolid = true;

                return;
            }

            if (startFraction < endFraction)
            {
                if (startFraction > -1.0f && startFraction < cd.ratio)
                {
                    if (startFraction < 0)
                        startFraction = 0;
                    cd.ratio = startFraction;
                }
            }
        }
Exemplo n.º 2
0
 public Q3CollisionData TraceSphere(Vector3 startPosition, Vector3 endPosition, float sphereRadius)
 {
     Q3CollisionData collision = new Q3CollisionData();
     collision.type = Q3CollisionType.Sphere;
     collision.sphereRadius = sphereRadius;
     return Trace(startPosition, endPosition, ref collision);
 }
Exemplo n.º 3
0
 public Q3CollisionData TraceRay(Vector3 startPosition, Vector3 endPosition)
 {
     Q3CollisionData collision = new Q3CollisionData();
     collision.type = Q3CollisionType.Ray;
     return Trace(startPosition, endPosition, ref collision);
 }
Exemplo n.º 4
0
        public Q3CollisionData TraceBox(Vector3 startPosition, Vector3 endPosition, AABB bbox)
        {
            Q3CollisionData collision = new Q3CollisionData();
            Vector3 boxMinimums = bbox.Min;
            Vector3 boxMaximums = bbox.Max;

            if (boxMinimums.X == 0 && boxMinimums.Y == 0 && boxMinimums.Z == 0 && boxMaximums.X == 0 && boxMaximums.Y == 0 && boxMaximums.Z == 0)
            {
                collision.type = Q3CollisionType.Ray;
                return Trace(startPosition, endPosition, ref collision);
            }

            if (boxMaximums.X < boxMinimums.X)
            {
                float x = boxMaximums.X;
                boxMaximums.X = boxMinimums.X;
                boxMinimums.X = x;
            }
            if (boxMaximums.Y < boxMinimums.Y)
            {
                float y = boxMaximums.Y;
                boxMaximums.Y = boxMinimums.Y;
                boxMinimums.Y = y;
            }
            if (boxMaximums.Z < boxMinimums.Z)
            {
                float z = boxMaximums.Z;
                boxMaximums.Z = boxMinimums.Z;
                boxMinimums.Z = z;
            }

            Vector3 boxExtents = new Vector3();
            boxExtents.X = Math.Max(Math.Abs(boxMaximums.X), Math.Abs(boxMinimums.X));
            boxExtents.Y = Math.Max(Math.Abs(boxMaximums.Y), Math.Abs(boxMinimums.Y));
            boxExtents.Z = Math.Max(Math.Abs(boxMaximums.Z), Math.Abs(boxMinimums.Z));

            collision.type = Q3CollisionType.Box;
            collision.boxMinimums = boxMinimums;
            collision.boxMaximums = boxMaximums;
            collision.boxExtents = boxExtents;
            return Trace(startPosition, endPosition, ref collision);
        }
Exemplo n.º 5
0
        private void WalkNode(int nodeIndex, float startRatio, float endRatio, Vector3 startPosition, Vector3 endPosition, ref Q3CollisionData cd)
        {
            // Is this a leaf?
            if (0 > nodeIndex)
            {
                Q3Leaf leaf = m_leaves[~nodeIndex];
                for (int i = 0; i < leaf.BrushCount; i++)
                {
                    Q3Brush brush = m_brushes[m_leafBrushes[leaf.BrushStart + i]];
                    if (0 < brush.NumSides &&
                        1 == ((int)m_shaders[brush.ShaderIndex].ContentFlags & 1))
                    {
                        CheckBrush(ref brush, ref cd);
                    }
                }

                return;
            }

            // This is a node
            Q3Node thisNode = m_nodes[nodeIndex];
            Q3Plane thisPlane = m_planes[thisNode.Plane];
            float startDistance = startPosition.Dot( new Vector3(thisPlane.Normal) ) - thisPlane.Distance;
            float endDistance = endPosition.Dot( new Vector3(thisPlane.Normal) ) - thisPlane.Distance;
            float offset = 0;

            // Set offset for sphere-based collision
            if (cd.type == Q3CollisionType.Sphere)
            {
                offset = cd.sphereRadius;
            }

            // Set offest for box-based collision
            if (cd.type == Q3CollisionType.Box)
            {
                offset = Math.Abs(cd.boxExtents.X * (new Vector3(thisPlane.Normal)).X) + Math.Abs(cd.boxExtents.Y * (new Vector3(thisPlane.Normal)).Y) + Math.Abs(cd.boxExtents.Z * (new Vector3(thisPlane.Normal)).Z);
            }

            if (startDistance >= offset && endDistance >= offset)
            {
                // Both points are in front
                WalkNode(thisNode.Front, startRatio, endRatio, startPosition, endPosition, ref cd);
            }
            else if (startDistance < -offset && endDistance < -offset)
            {
                WalkNode(thisNode.Back, startRatio, endRatio, startPosition, endPosition, ref cd);
            }
            else
            {
                // The line spans the splitting plane
                int side = 0;
                float fraction1 = 0.0f;
                float fraction2 = 0.0f;
                float middleFraction = 0.0f;
                Vector3 middlePosition = new Vector3();

                if (startDistance < endDistance)
                {
                    side = 1;
                    float inverseDistance = 1.0f / (startDistance - endDistance);
                    fraction1 = (startDistance - offset + Q3Constants.Epsilon) * inverseDistance;
                    fraction2 = (startDistance + offset + Q3Constants.Epsilon) * inverseDistance;
                }
                else if (endDistance < startDistance)
                {
                    side = 0;
                    float inverseDistance = 1.0f / (startDistance - endDistance);
                    fraction1 = (startDistance + offset + Q3Constants.Epsilon) * inverseDistance;
                    fraction2 = (startDistance - offset - Q3Constants.Epsilon) * inverseDistance;
                }
                else
                {
                    side = 0;
                    fraction1 = 1.0f;
                    fraction2 = 0.0f;
                }

                if (fraction1 < 0.0f) fraction1 = 0.0f;
                else if (fraction1 > 1.0f) fraction1 = 1.0f;
                if (fraction2 < 0.0f) fraction2 = 0.0f;
                else if (fraction2 > 1.0f) fraction2 = 1.0f;

                middleFraction = startRatio + (endRatio - startRatio) * fraction1;
                middlePosition = startPosition + fraction1 * (endPosition - startPosition);

                int side1;
                int side2;
                if (0 == side)
                {
                    side1 = thisNode.Front;
                    side2 = thisNode.Back;
                }
                else
                {
                    side1 = thisNode.Back;
                    side2 = thisNode.Front;
                }

                WalkNode(side1, startRatio, middleFraction, startPosition, middlePosition, ref cd);

                middleFraction = startRatio + (endRatio - startRatio) * fraction2;
                middlePosition = startPosition + fraction2 * (endPosition - startPosition);

                WalkNode(side2, middleFraction, endRatio, middlePosition, endPosition, ref cd);
            }
        }
Exemplo n.º 6
0
        private Q3CollisionData Trace(Vector3 startPosition, Vector3 endPosition, ref Q3CollisionData collision)
        {
            collision.startOutside = true;
            collision.inSolid = false;
            collision.ratio = 1.0f;
            collision.startPosition = startPosition;
            collision.endPosition = endPosition;
            collision.collisionPoint = startPosition;

            WalkNode(0, 0.0f, 1.0f, startPosition, endPosition, ref collision);

            if (1.0f == collision.ratio)
            {
                collision.collisionPoint = endPosition;
            }
            else
            {
                collision.collisionPoint = startPosition + (collision.ratio - 0.002f) * (endPosition - startPosition);
            }

            return collision;
        }