[Libgdx] Raycasting bug?

Discuss issues specific the Java port of Box2D
Cyraxx
Posts: 3
Joined: Tue Jul 08, 2014 11:53 pm

[Libgdx] Raycasting bug?

Postby Cyraxx » Fri Aug 14, 2015 2:31 am

Hi!

I'm messing around with box2d trying to implement a LoS algorithm by casting a ray (from the mouse for now) to every edge point of the box2d bodies.
If the fraction of the RayCastCallback is 1.0 meaning that the ray hit the target without collision then I'll do another raycast with the starting position as the last raycast's end position and a random distance in the given direction as the end point.
It is working fine mostly but there are a few cases where the ray ignores collision with certain bodies for no reason.

Here is a picture of the problem:
(The yellow circles are the end points after 1 or 2 raycasts, the blue circle is where the bug occoured. If you trace that ray back to the start you'll see that it doesnt register collision with the 1st body)

Image

Eventhough it's messy because it's only a sandbox project I'll provide source code.

Code: Select all

public class RayCast extends ApplicationAdapter {
   public static final float PPM = 64f;

   OrthographicCamera cam, b2;

   SpriteBatch batch;
   Box2DDebugRenderer dr;
   ShapeRenderer sr;

   World world;
   RayCastCallback rccb;

   Vector2 start;
   Vector2 end;
   Array<Vector2> endPoints;
   Array<Vector2> finalEndPoints;

   @Override
   public void create() {
      batch = new SpriteBatch();

      world = new World(new Vector2(0, 0), false);
      dr = new Box2DDebugRenderer();
      sr = new ShapeRenderer();

      b2 = new OrthographicCamera();
      cam = new OrthographicCamera();

      b2.setToOrtho(false, Gdx.graphics.getWidth() / PPM, Gdx.graphics.getHeight() / PPM);
      cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

      endPoints = new Array<Vector2>();
      finalEndPoints = new Array<Vector2>();

      //      float w = Gdx.graphics.getWidth() / PPM;
      //      float h = Gdx.graphics.getHeight() / PPM;
      //
      //      finalEndPoints.add(new Vector2(0, 0));
      //      finalEndPoints.add(new Vector2(0, h));
      //      finalEndPoints.add(new Vector2(w, h));
      //      finalEndPoints.add(new Vector2(w, 0));

      // Left
      createBody(16, Gdx.graphics.getHeight() / 2, 32, Gdx.graphics.getHeight(), false);
      // Right
      createBody(Gdx.graphics.getWidth() - 16, Gdx.graphics.getHeight() / 2, 32, Gdx.graphics.getHeight(), false);
      // Top
      createBody(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() - 16, Gdx.graphics.getWidth() - 66, 32, false);
      // Bottom
      createBody(Gdx.graphics.getWidth() / 2, 16, Gdx.graphics.getWidth() - 66, 32, false);

      //      createBody(800, 400, 64, 64, true);
      //      createBody(500, 300, 128, 64, true);
      //      createBody(150, 200, 64, 64, true);
      //      createBody(450, 500, 64, 64, true);
      //      createBody(200, 100, 256, 64, true);
      //
      //      createBody(200, 600, 64, 64, true);
      //      createBody(274, 600, 64, 64, true);
      createBody(348, 600, 64, 64, true);
      createBody(422, 600, 64, 64, true);
      start = new Vector2(2, 2);
      end = new Vector2(2, 2);
      tmp = new Vector2();

      for(int i = 0; i < finalEndPoints.size; i++) {
         endPoints.add(new Vector2());
      }

      rccb = new RayCastCallback() {
         @Override
         public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
            if(fraction == 1.0f) {
               newCast = true;
            }
            ;
            endPoints.get(index).set(point);
            return fraction;
         }
      };
   }

   int index = 0;
   boolean newCast = false;
   Vector2 tmp;

   @Override
   public void render() {
      if(Gdx.input.isKeyJustPressed(Keys.ESCAPE))
         Gdx.app.exit();

      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

      float mx = Gdx.input.getX() / PPM;
      float my = (Gdx.graphics.getHeight() - Gdx.input.getY()) / PPM;
      start.set(mx, my);

      sr.begin(ShapeType.Line);
      for(index = 0; index < finalEndPoints.size; index++) {
         // First raycast
         world.rayCast(rccb, start, finalEndPoints.get(index));

         tmp.set(endPoints.get(index));
         float angle = (float) (Math.atan2(tmp.y - start.y, tmp.x - start.x));
         angle *= MathUtils.radiansToDegrees;
         if(angle < 0)
            angle += 360;

         // 0, 0
         if(angle > 0 && angle < 90 && index % 4 == 0)
            newCast = false;
         // 0, 1
         else if(angle > 270 && angle < 360 && index % 4 == 1)
            newCast = false;
         // 1, 1
         else if(angle > 180 && angle < 270 && index % 4 == 2)
            newCast = false;
         // 1, 0
         else if(angle > 90 && angle < 180 && index % 4 == 3)
            newCast = false;

         if(!newCast) {
            //            sr.setColor(Color.WHITE);
            //            sr.line(start.x * PPM, start.y * PPM, endPoints.get(index).x * PPM, endPoints.get(index).y * PPM);
         }
         else {
            newCast = false;
            angle *= MathUtils.degreesToRadians;

            // 25 * tileSize distance for the ray cast target
            float x = (float) Math.cos(angle) * 25f;
            float y = (float) Math.sin(angle) * 25f;

            tmp.add(x, y);
            world.rayCast(rccb, finalEndPoints.get(index), tmp);

            sr.setColor(Color.YELLOW);
            sr.line(finalEndPoints.get(index).x * PPM, finalEndPoints.get(index).y * PPM, endPoints.get(index).x * PPM, endPoints.get(index).y * PPM);

         }
      }
      sr.end();

      dr.render(world, b2.combined);

      sr.begin(ShapeType.Line);
      for(int i = 0; i < endPoints.size; i++) {

         // Start -> end
         sr.setColor(Color.RED);
         sr.line(start.x * PPM, start.y * PPM, endPoints.get(i).x * PPM, endPoints.get(i).y * PPM);
         sr.setColor(Color.YELLOW);
         sr.circle(endPoints.get(i).x * PPM, endPoints.get(i).y * PPM, 10);
      }
      sr.end();

   }

   public Body createBody(float x, float y, float w, float h, boolean add) {
      Body body;
      w /= 2;
      w /= PPM;
      h /= 2;
      h /= PPM;
      x /= PPM;
      y /= PPM;

      if(add) {
         finalEndPoints.add(new Vector2(x - w, y - h));
         finalEndPoints.add(new Vector2(x - w, y + h));
         finalEndPoints.add(new Vector2(x + w, y + h));
         finalEndPoints.add(new Vector2(x + w, y - h));
      }

      BodyDef def = new BodyDef();
      def.type = BodyType.DynamicBody;
      def.fixedRotation = false;
      def.gravityScale = 1f;
      def.bullet = true;
      body = world.createBody(def);

      PolygonShape poly = new PolygonShape();
      poly.setAsBox(w, h);
      body.createFixture(poly, 1);

      body.setTransform(x, y, 0);

      return body;
   }
}


Any help would be greatly appriciated!  ;)

Return to “Java”



Who is online

Users browsing this forum: No registered users and 4 guests