Example #1
0
        public TraceOutput trace(Vector3 start, Vector3 end, SceneCamera camera, float radius = 0.0f)
        {
            TraceOutput output = new TraceOutput()
            {
                allSolid   = false,
                startSolid = false,
                fraction   = 1.0f,
                endPos     = end,
                plane      = null
            };

            if (this.bsp == null)
            {
                return(output);
            }

            output = this.traceNode(0, 0.0f, 1.0f, start, end, radius, output, camera);

            if (output.fraction != 1.0f)
            {
                // collided with something

                output.endPos = start + output.fraction * (end - start); // interpolate to determine the end position
            }

            return(output);
        }
        public static Vector3?trace(long traceId, Vector3 start, Vector3 end, float radius, bool slide = false)
        {
            if (radius == 0)
            {
                radius = 0.0f;
            }

            if (BspCompiler.brushSides == null)
            {
                return(end);
            }

            TraceOutput output = new TraceOutput()
            {
                startsOut = true,
                allSolid  = false,
                plane     = null,
                fraction  = 1.0f
            };


            traceNode(0, 0, 1, start, end, radius, output);

            if (output.fraction != 1)
            { // collided with something
                if (slide && output.plane != null)
                {
                    float endDist = (float)Math.Abs(Vector3.Dot(end, output.plane.normal) - (output.plane.distance + radius + 0.03125));

                    end.X = end.X + endDist * (output.plane.normal.X);
                    end.Y = end.Y + endDist * (output.plane.normal.Y);
                    end.Z = end.Z + endDist * (output.plane.normal.Z);

                    //for (var i = 0; i< 3; i++) {
                    //    end[i] = end[i] + endDist* (output.plane.normal[i]);
                    //}
                }
                else
                {
                    end.X = start.X + output.fraction * (end.X - start.X);
                    end.Y = start.Y + output.fraction * (end.Y - start.Y);
                    end.Z = start.Z + output.fraction * (end.Z - start.Z);

                    //for (var i = 0; i< 3; i++) {
                    //    end[i] = start[i] + output.fraction * (end[i] - start[i]);
                    //}
                }
            }


            q3bsp.postMessage2(new MessageParams()
            {
                type    = "trace",
                traceId = traceId,
                end     = end
            }, null);

            return(null);
        }
        public static void traceNode(long nodeIdx, float startFraction, float endFraction,
                                     Vector3 start, Vector3 end, float radius, TraceOutput output)
        {
            if (nodeIdx < 0)
            { // Leaf node?
                Leaf leaf = BspCompiler.leaves[(int)-(nodeIdx + 1)];

                for (int i = 0; i < leaf.leafBrushCount; i++)
                {
                    Brush    brush  = BspCompiler.brushes[(int)BspCompiler.leafBrushes[(int)(leaf.leafBrush) + i]];
                    shader_p shader = BspCompiler.shaders[(int)brush.shader];

                    if (brush.brushSideCount > 0 && (shader.contents == 0)) // (shader['contents'] & 1))
                    {
                        traceBrush(brush, start, end, radius, ref output);
                    }
                }
                return;
            }

            // Tree node
            bsp_tree_node node  = BspCompiler.nodes[(int)nodeIdx];
            Plane         plane = BspCompiler.planes[(int)node.plane];

            float startDist = Vector3.Dot(plane.normal, start) - plane.distance;
            float endDist   = Vector3.Dot(plane.normal, end) - plane.distance;

            if (startDist >= radius && endDist >= radius)
            {
                traceNode(node.children[0], startFraction, endFraction, start, end, radius, output);
            }
            else if (startDist < -radius && endDist < -radius)
            {
                traceNode(node.children[1], startFraction, endFraction, start, end, radius, output);
            }
            else
            {
                int     side;
                float   fraction1, fraction2, middleFraction;
                Vector3 middle = Vector3.Zero;

                if (startDist < endDist)
                {
                    side = 1; // back
                    var iDist = 1 / (startDist - endDist);
                    fraction1 = (startDist - radius + 0.03125f) * iDist;
                    fraction2 = (startDist + radius + 0.03125f) * iDist;
                }
                else if (startDist > endDist)
                {
                    side = 0; // front
                    var iDist = 1 / (startDist - endDist);
                    fraction1 = (startDist + radius + 0.03125f) * iDist;
                    fraction2 = (startDist - radius - 0.03125f) * iDist;
                }
                else
                {
                    side      = 0; // front
                    fraction1 = 1.0f;
                    fraction2 = 0.0f;
                }

                if (fraction1 < 0)
                {
                    fraction1 = 0.0f;
                }
                else if (fraction1 > 1)
                {
                    fraction1 = 1.0f;
                }
                if (fraction2 < 0)
                {
                    fraction2 = 0.0f;
                }
                else if (fraction2 > 1)
                {
                    fraction2 = 1.0f;
                }

                middleFraction = startFraction + (endFraction - startFraction) * fraction1;

                middle.X = start.X + fraction1 * (end.X - start.X);
                middle.Y = start.Y + fraction1 * (end.Y - start.Y);
                middle.Z = start.Z + fraction1 * (end.Z - start.Z);
                //for (var i = 0; i < 3; i++)
                //{
                //    middle[i] = start[i] + fraction1 * (end[i] - start[i]);
                //}

                traceNode(node.children[side], startFraction, middleFraction, start, middle, radius, output);

                middleFraction = startFraction + (endFraction - startFraction) * fraction2;

                middle.X = start.X + fraction2 * (end.X - start.X);
                middle.Y = start.Y + fraction2 * (end.Y - start.Y);
                middle.Z = start.Z + fraction2 * (end.Z - start.Z);
                //for (var i = 0; i < 3; i++)
                //{
                //    middle[i] = start[i] + fraction2 * (end[i] - start[i]);
                //}

                traceNode(node.children[side == 0 ? 1 : 0], middleFraction, endFraction, middle, end, radius, output);
            }
        }
        private static void traceBrush(Brush brush, Vector3 start, Vector3 end, float radius, ref TraceOutput output)
        {
            float startFraction  = -1;
            float endFraction    = 1;
            bool  startsOut      = false;
            bool  endsOut        = false;
            Plane collisionPlane = null;

            for (var i = 0; i < brush.brushSideCount; i++)
            {
                BrushSide brushSide = BspCompiler.brushSides[(int)brush.brushSide + i];
                Plane     plane     = BspCompiler.planes[(int)brushSide.plane];

                float startDist = Vector3.Dot(start, plane.normal) - (plane.distance + radius);
                float endDist   = Vector3.Dot(end, plane.normal) - (plane.distance + radius);

                if (startDist > 0)
                {
                    startsOut = true;
                }
                if (endDist > 0)
                {
                    endsOut = true;
                }

                // make sure the trace isn't completely on one side of the brush
                if (startDist > 0 && endDist > 0)
                {
                    return;
                }
                if (startDist <= 0 && endDist <= 0)
                {
                    continue;
                }

                if (startDist > endDist)
                { // line is entering into the brush
                    float fraction = (startDist - 0.03125f) / (startDist - endDist);
                    if (fraction > startFraction)
                    {
                        startFraction  = fraction;
                        collisionPlane = plane;
                    }
                }
                else
                { // line is leaving the brush
                    float fraction = (startDist + 0.03125f) / (startDist - endDist);
                    if (fraction < endFraction)
                    {
                        endFraction = fraction;
                    }
                }
            }

            if (startsOut == false)
            {
                output.startsOut = false;
                if (endsOut == false)
                {
                    output.allSolid = true;
                }
                return;
            }

            if (startFraction < endFraction)
            {
                if (startFraction > -1 && startFraction < output.fraction)
                {
                    output.plane = collisionPlane;
                    if (startFraction < 0)
                    {
                        startFraction = 0;
                    }
                    output.fraction = startFraction;
                }
            }

            return;
        }
Example #5
0
        public TraceOutput traceNode(long nodeIdx, float startFraction, float endFraction,
                                     Vector3 start, Vector3 end, float radius, TraceOutput output, SceneCamera camera)
        {
            if (nodeIdx < 0) // Leaf node?
            {
                Leaf leaf = this.bsp.leaves[(int)(-(nodeIdx + 1))];
                for (var i = 0; i < leaf.leafBrushCount; i++)
                {
                    Brush    brush   = this.bsp.brushes[(int)(this.bsp.leafBrushes[(leaf.leafBrush + i)])];
                    shader_p surface = this.bsp.surfaces[(int)brush.shader];

                    if (brush.brushSideCount > 0 && surface.contents != 0) // surface['contents'] & 1
                    {
                        output = this.traceBrush(brush, start, end, radius, output);
                    }
                }
                return(output);
            }

            // Tree node
            bsp_tree_node node  = this.bsp.nodes[(int)nodeIdx];
            Plane         plane = this.bsp.planes[(int)node.plane];

            float startDist = Vector3.Dot(plane.normal, start) - plane.distance;
            float endDist   = Vector3.Dot(plane.normal, end) - plane.distance;

            if (startDist >= radius && endDist >= radius)
            {
                output = this.traceNode(node.children[0], startFraction, endFraction, start, end, radius, output, camera);
            }
            else if (startDist < -radius && endDist < -radius)
            {
                output = this.traceNode(node.children[1], startFraction, endFraction, start, end, radius, output, camera);
            }
            else
            {
                int   side;
                float fraction1;
                float fraction2;
                float middleFraction;

                Vector3 middle = Vector3.Zero;

                if (startDist < endDist)
                {
                    side = 1; // back
                    var iDist = 1 / (startDist - endDist);
                    fraction1 = (startDist - radius + Config.q3bsptree_trace_offset) * iDist;
                    fraction2 = (startDist + radius + Config.q3bsptree_trace_offset) * iDist;
                }
                else if (startDist > endDist)
                {
                    side = 0; // front
                    var iDist = 1 / (startDist - endDist);
                    fraction1 = (startDist + radius + Config.q3bsptree_trace_offset) * iDist;
                    fraction2 = (startDist - radius - Config.q3bsptree_trace_offset) * iDist;
                }
                else
                {
                    side      = 0; // front
                    fraction1 = 1.0f;
                    fraction2 = 0.0f;
                }

                if (fraction1 < 0)
                {
                    fraction1 = 0.0f;
                }
                else if (fraction1 > 1)
                {
                    fraction1 = 1.0f;
                }
                if (fraction2 < 0)
                {
                    fraction2 = 0.0f;
                }
                else if (fraction2 > 1)
                {
                    fraction2 = 1.0f;
                }

                middleFraction = startFraction + (endFraction - startFraction) * fraction1;

                middle.X = start.X + fraction1 * (end.X - start.X);
                middle.Y = start.Y + fraction1 * (end.Y - start.Y);
                middle.Z = start.Z + fraction1 * (end.Z - start.Z);

                //for (var i = 0; i < 3; i++)
                //{
                //    middle[i] = start[i] + fraction1 * (end[i] - start[i]);
                //}

                output = this.traceNode(node.children[side], startFraction, middleFraction, start, middle, radius, output, camera);

                middleFraction = startFraction + (endFraction - startFraction) * fraction2;

                middle.X = start.X + fraction2 * (end.X - start.X);
                middle.Y = start.Y + fraction2 * (end.Y - start.Y);
                middle.Z = start.Z + fraction2 * (end.Z - start.Z);
                //for (var i = 0; i < 3; i++)
                //{
                //    middle[i] = start[i] + fraction2 * (end[i] - start[i]);
                //}

                output = this.traceNode(node.children[side == 0 ? 1 : 0], middleFraction, endFraction, middle, end, radius, output, camera);
            }

            return(output);
        }
Example #6
0
        public TraceOutput traceBrush(Brush brush, Vector3 start, Vector3 end, float radius, TraceOutput output)
        {
            float startFraction  = -1.0f;
            float endFraction    = 1.0f;
            bool  startsOut      = false;
            bool  endsOut        = false;
            Plane collisionPlane = null;

            for (int i = 0; i < brush.brushSideCount; i++)
            {
                var   brushSide = this.bsp.brushSides[(int)brush.brushSide + i];
                Plane plane     = this.bsp.planes[(int)brushSide.plane];

                //Vector3

                float startDist = Vector3.Dot(start, plane.normal) - (plane.distance + radius);
                float endDist   = Vector3.Dot(end, plane.normal) - (plane.distance + radius);

                if (startDist > 0)
                {
                    startsOut = true;
                }
                if (endDist > 0)
                {
                    endsOut = true;
                }

                // make sure the trace isn't completely on one side of the brush
                if (startDist > 0 && endDist > 0)
                {
                    return(output);
                }
                if (startDist <= 0 && endDist <= 0)
                {
                    continue;
                }

                if (startDist > endDist)
                { // line is entering into the brush
                    float fraction = (startDist - Config.q3bsptree_trace_offset) / (startDist - endDist);

                    if (fraction > startFraction)
                    {
                        startFraction  = fraction;
                        collisionPlane = plane;
                    }
                }
                else
                { // line is leaving the brush
                    float fraction = (startDist + Config.q3bsptree_trace_offset) / (startDist - endDist);
                    if (fraction < endFraction)
                    {
                        endFraction = fraction;
                    }
                }
            }

            if (startsOut == false)
            {
                output.startSolid = true;
                if (endsOut == false)
                {
                    output.allSolid = true;
                }
                return(output);
            }

            if (startFraction < endFraction)
            {
                if (startFraction > -1 && startFraction < output.fraction)
                {
                    output.plane = collisionPlane;
                    if (startFraction < 0)
                    {
                        startFraction = 0.0f;
                    }
                    output.fraction = startFraction;
                }
            }

            return(output);
        }