chandlerprall / Physijs

Physics plugin for Three.js
MIT License
2.75k stars 455 forks source link

Plane not behaving as expected when objects falling on it (2.0 branch) #283

Closed alkavan closed 7 years ago

alkavan commented 7 years ago

Issue is first 3 boxes seems to be "standing" on the plane, however other boxes created in look ignore it?

image

Plane is created like this:

define(['physi'], function (physi) {

    var Floor = function (options) {

        options = options || {
                position: {x: 0, y: 0, z: 0},
                dim: {width: 4000, height: 4000},
                mass:  0
            };

        var geometry = new THREE.PlaneGeometry(options.dim.width, options.dim.height);
        geometry.applyMatrix( new THREE.Matrix4().makeRotationX( -Math.PI / 2 ) );
        var material = new THREE.MeshPhongMaterial( { color: 0x223322 } );

        var mesh = new physi.Plane(
            geometry,
            material
        );

        var object = new THREE.Object3D();
        object.add( mesh );

        mesh = new physi.CompoundObject( object, { mass: options.mass } );

        mesh.position.x = options.position.x;
        mesh.position.y = options.position.y;
        mesh.position.z = options.position.z;

        return mesh;
    };

    return Floor;
});

Box is created like this:

define(['physi'], function (physi) {

    var Box = function (options) {

        options = options || {
                position: {x: 0, y: 0, z: 0},
                dim: {width: 1, height: 1, depth: 1},
                scale: 1.0,
                mass:  1.0
            };

        var geometry, material;

        geometry = new THREE.BoxGeometry(
            options.scale * options.dim.width,
            options.scale * options.dim.height,
            options.scale * options.dim.depth
        );

        material = new THREE.MeshPhongMaterial({
            specular:     0xff0000,
            shading:      THREE.FlatShading,
            vertexColors: THREE.VertexColors
        });

        var mesh = new physi.Box(
            geometry,
            material
        );

        var object = new THREE.Object3D();
        object.add( mesh );
        mesh = new physi.CompoundObject( object, { mass: options.mass } );

        mesh.position.x = options.position.x;
        mesh.position.y = options.position.y;
        mesh.position.z = options.position.z;

        return mesh;
    };

    return Box;
});

First 3 boxes and floor:

var floor = new Floor();
this.scene.add(floor);

var box = new Box({
    position: { x: 0, y: 500, z: 0 },
    dim: { width: 100, height: 100, depth: 100 },
    scale: 1.0,
    mass: 100
});
this.scene.add(box);

Boxes in loop:

this.boxCreateInterval = setInterval(function () {

    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    var randomX     = getRandomInt(0, 2000);
    var randomY     = getRandomInt(3000, 1000);
    var randomZ     = getRandomInt(0, 2000);
    var randomMass  = getRandomInt(10, 100);
    var randomScale = getRandomInt(1, 2);

    var randomSignX  = Math.random() < 0.5 ? -1 : 1;
    var randomSignZ  = Math.random() < 0.5 ? -1 : 1;

    randomX *= randomSignX;
    randomZ *= randomSignZ;

    var box = new Box({
        position: {
            x: randomX,
            y: randomY,
            z: randomZ
        },
        dim: {
            width:  100,
            height: 100,
            depth:  100
        },
        scale: randomScale,
        mass: randomMass
    });

    this.physicsObjects.add(box);
    this.scene.add(box);
}.bind(this), 1000);
chandlerprall commented 7 years ago

Looking into this; one thing to note is that the physics engine is tuned for the units to be in meters (thus you'd be creating 100x100x100 meters boxes.

That doesn't appear to be what's causing what you've observed to happen, but wanted to point it out. I'll respond with more info as I have it.

chandlerprall commented 7 years ago

Tracked it down. You're rotating the floor's plane geometry directly with

geometry.applyMatrix( new THREE.Matrix4().makeRotationX( -Math.PI / 2 ) );

the physijs.Plane object expects that the geometry passed to it is an unmodified THREE.PlaneGeometry; Physijs expects a plane spanning XY and you're passing an object spanning XZ.

Switching geometry.applyMatrix for

mesh.quaternion.setFromRotationMatrix(new THREE.Matrix4().makeRotationX( -Math.PI / 2 ));

clears up the issue for me. Let me know if you have any questions about this, and thanks for checking out the v2 branch!

alkavan commented 7 years ago

Yes! so that worked nicely! thanks.

image

Thanks for making that branch! just in time for me. I'll try bug report and maybe help if possible.