Birch-san / box2d-wasm

Box2D physics engine compiled to WebAssembly. Supports TypeScript and ES modules.
263 stars 21 forks source link

Ray casting from fixture doesn't work in my example #58

Open 8Observer8 opened 1 year ago

8Observer8 commented 1 year ago

This code doesn't work:

        // Down ray
        raycaster.drawLine([playerPosition[0], playerPosition[1] - 5],
            [playerPosition[0], playerPosition[1] - 15], [1, 1, 1]);
        const point1 = new b2Vec2(playerPosition[0] / pixelsPerMeter,
            (playerPosition[1] - 5) / pixelsPerMeter);
        const point2 = new b2Vec2(playerPosition[0] / pixelsPerMeter,
            (playerPosition[1] - 15) / pixelsPerMeter);
        // world.RayCast(downRayCallback, point1, point2);

        const input = {
            p1: point1,
            p2: point2,
            maxFraction: 1
        };
        const output = {
            normal: new b2Vec2(0, 0),
            fraction: 1
        };

        grounded = false;
        for (let i = 0; i < fixtures.length; i++) {
            grounded = fixtures[i].RayCast(input, output);
            if (grounded)
                break;
        }
        console.log(`grounded = ${grounded}`);

It prints grounded = false:

Example in Sandboxes:

Run in browser

GitHub Repository with sandboxes and instruction for Rollup.

simple-can-jump-with-ray-box2dwasm-webgl-js

I made this gif-animation to show that point1 and point2 are correct in this example:

// Down ray
        raycaster.drawLine([playerPosition[0], playerPosition[1] - 5],
            [playerPosition[0], playerPosition[1] - 15], [1, 1, 1]);
        const point1 = new b2Vec2(playerPosition[0] / pixelsPerMeter,
            (playerPosition[1] - 5) / pixelsPerMeter);
        const point2 = new b2Vec2(playerPosition[0] / pixelsPerMeter,
            (playerPosition[1] - 15) / pixelsPerMeter);
        world.RayCast(downRayCallback, point1, point2);

world.RayCast works:

point1-and-point2-are-corrent

but fixtures[i].RayCast doesn't work.

8Observer8 commented 1 year ago

The same example works with box2d-core: https://8observer8.github.io/webgl10-js/simple-can-jump-with-ray-box2dcore-webgl-js/ I copied my box2d-wasm example above and replaced box2d-wasm with box2d-core and it works.

simple-can-jump-with-ray-box2dcore-webgl-js

8Observer8 commented 1 year ago

Example using Pixi.js instead of pure WebGL 1.0 as above

When the square intersects the ray, the word "detected" should be printed to the console, but this does not happen.

Sandboxes:

ray-casting-box2dwasm-pixijs-js

        world.Step(dt, 3, 2);
        world.DebugDraw();

        const point1 = new b2Vec2(150 / pixelsPerMeter, 170 / pixelsPerMeter);
        const point2 = new b2Vec2(100 / pixelsPerMeter, 170 / pixelsPerMeter);

        const input = {
            p1: point1,
            p2: point2,
            maxFraction: 1
        };
        const output = {
            normal: new b2Vec2(0, 0),
            fraction: 1
        };

        const ok = boxFixture.RayCast(output, input);
        if (ok) {
            console.log("detected");
        }

        // Render the stage
        renderer.render(stage);
        debugDrawer.clear();

The same example works with box2d-core

I thought maybe it was my mistake, but I replaced box2d-wasm with box2d-core and the example worked. So I think it's a bug. But maybe I did something wrong.

Sandboxes:

ray-casting-box2dcore-pixijs-js

It's exactly the same code:

        world.Step(dt, { velocityIterations: 3, positionIterations: 2 });
        DrawShapes(debugDrawer, world);

        const point1 = new b2Vec2(150 / pixelsPerMeter, 170 / pixelsPerMeter);
        const point2 = new b2Vec2(100 / pixelsPerMeter, 170 / pixelsPerMeter);

        const input = {
            p1: point1,
            p2: point2,
            maxFraction: 1
        };

        const output = {
            normal: new b2Vec2(0, 0),
            fraction: 1
        };

        const ok = boxFixture.RayCast(output, input);
        if (ok) {
            console.log("detected");
        }

        // Render the stage
        renderer.render(stage);
        debugDrawer.clear();
8Observer8 commented 12 months ago

This is an alternative way of using ray casting, It is world.RayCast and it is not a ray casting from the fixture as in the current issue. The example from documentation helped me.

Sandboxes:

GitHub: https://github.com/8Observer8/falling-box-world-ray-casting-contact-listener-box2dwasm-webgl-js

Discussion: https://github.com/Birch-san/box2d-wasm/discussions/64

falling-box-ray-casting-box2dwasm-webgl-js