Cone thread

Started by ubre 9 posts 1,029 views

Reply on sbox.game
  1. #1
    ubre 9,617
    We want DebugOverlay.Cone and Gizmo.Draw.Cone!

    Here is the code:

        /// <summary>
        /// Render a cone for a specific amount of time
        /// </summary>
        /// <param name="origin"></param>
        /// <param name="radius"></param>
        /// <param name="direction"></param>
        /// <param name="angle"></param>
        /// <param name="lines"></param>
        /// <param name="color"></param>
        /// <param name="time"></param>
        public static void Cone(Vector3 origin, float radius, Vector3 direction, float angle, int lines = 12, Color? color = null, float time = 0f)
            => AddToQueue(() =>
            {
                Gizmo.Draw.Color = color ?? Color.White;
                var halfAngle = angle / 2f;
                var normalDir = direction.Normal;
    
                var baseCenter = origin + normalDir * (radius * MathF.Cos(MathX.DegreeToRadian(halfAngle)));
                var baseRadius = radius * MathF.Sin(MathX.DegreeToRadian(halfAngle));
    
                var upDirection = Vector3.Cross(normalDir, Vector3.Up).Normal;
                var rightDirection = Vector3.Cross(normalDir, upDirection).Normal;
    
                Vector3? previousPoint = null;
                var firstPoint = Vector3.Zero;
    
                for (var edge = 0; edge < lines; edge++)
                {
                    var edgeAngle = MathF.PI * edge * 2f / lines;
                    var edgeX = MathF.Cos(edgeAngle) * baseRadius;
                    var edgeY = MathF.Sin(edgeAngle) * baseRadius;
                    var edgePosition = baseCenter + rightDirection * edgeX + upDirection * edgeY;
    
                    Gizmo.Draw.Line(origin, edgePosition);
    
                    if (edge == 0)
                        firstPoint = edgePosition;
    
                    if (previousPoint != null)
                        Gizmo.Draw.Line(previousPoint.Value, edgePosition);
    
                    if (edge + 1 == lines)
                        Gizmo.Draw.Line(edgePosition, firstPoint);
    
                    previousPoint = edgePosition;
                }
            }, time);
        }
    Just add it straight to s&box, free of charge, thank you.

    And if you want to check if a bbox intersects with a cone here you go:

    	/// <summary>
    	/// Is the provided bbox hit by the cone
    	/// </summary>
    	/// <param name="bbox"></param>
    	/// <param name="origin"></param>
    	/// <param name="radius"></param>
    	/// <param name="direction"></param>
    	/// <param name="angle"></param>
    	/// <returns></returns>
    	public static bool IsBBoxHitByCone( BBox bbox, Vector3 origin, float radius, Vector3 direction, float angle )
    	{
    		var normalDir = direction.Normal * (angle > 180f ? -1f : 1f);
    
    		foreach ( var corner in bbox.Corners )
    			if ( IsPointInsideCone( origin, radius, direction, angle, corner ) )
    				return true; // Sometimes it's that easy!
    
    		var coneLine = new Line( origin, origin + normalDir * radius );
    		if ( bbox.Contains( coneLine.ClosestPoint( bbox.Center ) ) ) // Check if the cone's center intersects with the bbox
    			return true; // Hopefully we've got something by now!
    
    		// Now we panic
    
    		var baseCenter = origin + normalDir * radius;
    		var baseRadius = radius * MathF.Tan( MathX.DegreeToRadian( angle ) / 2f );
    		var upDirection = Vector3.Cross( normalDir, Vector3.Up ).Normal;
    		var rightDirection = Vector3.Cross( normalDir, upDirection ).Normal;
    
    		var outerEdges = 12;
    
    		for ( var edge = 0; edge < outerEdges; edge++ )
    		{
    			var edgeAngle = MathF.PI * edge * 2f / outerEdges;
    			var edgeX = MathF.Cos( edgeAngle ) * baseRadius;
    			var edgeY = MathF.Sin( edgeAngle ) * baseRadius;
    			var edgePosition = baseCenter + rightDirection * edgeX + upDirection * edgeY;
    
    			var edgeLine = new Line( origin, edgePosition );
    			if ( bbox.Contains( edgeLine.ClosestPoint( bbox.Center ) ) ) // Check if the cone's outer edge intersects with the bbox
    				return true;
    		}
    
    		return false;
    	}
    It's not perfect but it works, especially if you just need some AOE attacks
  2. #2
    PyroBot11 1,715
     We want DebugOverlay.Cone and Gizmo.Draw.Cone! 
  3. #3
    ubre Started this 9,617
    "I'm right you know"
    I said that
  4. #4
    PyroBot11 1,715
    That was you pointing to the quote!!!
  5. #5
    G Kaf 1,600
    Yeah dude. cones. yeah dude. Thank you ubre. 
  6. edited Feb 2025 #6
    JohnyBro 225
    OMG THANK YOU SO MUCH !
    edited:
    Would be nice to pass length instead of radius
  7. #7
    Asphaltian 1,473
    I'm coning to this
  8. #8
    Unknown
  9. #9
    Unknown