【问题标题】:How to constrain objects in a box/cylinder container in Physijs (with Three.js)如何在 Physijs 中约束盒子/圆柱容器中的对象(使用 Three.js)
【发布时间】:2015-04-26 11:28:04
【问题描述】:

我根据 Physijs 的示例 shapes 编写了一个程序来随机生成 ConvexGeometry 对象并将其放入一个盒子容器中。

一切都很顺利,直到太多的物体被放入容器中,物体只是挣扎着飞出盒子。

这里是初始化场景的代码:

initScene = function() {
    TWEEN.start();

    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.shadowMapEnabled = true;
    renderer.shadowMapSoft = true;
    document.getElementById( 'viewport' ).appendChild( renderer.domElement );

    render_stats = new Stats();
    render_stats.domElement.style.position = 'absolute';
    render_stats.domElement.style.top = '0px';
    render_stats.domElement.style.zIndex = 100;
    document.getElementById( 'viewport' ).appendChild( render_stats.domElement );

    physics_stats = new Stats();
    physics_stats.domElement.style.position = 'absolute';
    physics_stats.domElement.style.top = '50px';
    physics_stats.domElement.style.zIndex = 100;
    document.getElementById( 'viewport' ).appendChild( physics_stats.domElement );

    scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 });
    scene.setGravity(new THREE.Vector3( 0, -30, 0 ));
    scene.addEventListener(
        'update',
        function() {
            scene.simulate( undefined, 2 );
            physics_stats.update();
        }
    );

    camera = new THREE.PerspectiveCamera(
        35,
        window.innerWidth / window.innerHeight,
        1,
        1000
    );
    camera.position.set( 150, 120, 150 );
    camera.lookAt( scene.position );
    scene.add( camera );

    // Materials
    wall_material = Physijs.createMaterial(
        new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 1 } )
    );
    ground_material = Physijs.createMaterial(
        new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }),
        .8, // high friction
        .4 // low restitution
    );
    ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping;
    ground_material.map.repeat.set( 2.5, 2.5 );

    // Ground
    ground = new Physijs.BoxMesh(
        new THREE.BoxGeometry(50, 1, 50),
        //new THREE.PlaneGeometry(50, 50),
        ground_material,
        0 // mass
    );

    ground.receiveShadow = true;
    scene.add( ground );

    // Bumpers
    var bumper,
        bumper_geom = new THREE.BoxGeometry(1, 50, 50);

    // Back left
    bumper = new Physijs.BoxMesh( bumper_geom, ground_material, 0, { restitution: .2 } );
    bumper.position.y = 25;
    bumper.position.x = -25;
    bumper.receiveShadow = true;
    bumper.castShadow = true;
    scene.add( bumper );

    // Front right
    bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
    bumper.position.y = 25;
    bumper.position.x = 25;
    bumper.receiveShadow = true;
    bumper.castShadow = true;
    scene.add( bumper );

    // Back right
    bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
    bumper.position.y = 25;
    bumper.position.z = -25;
    bumper.rotation.y = Math.PI / 2;
    bumper.receiveShadow = true;
    bumper.castShadow = true;
    scene.add( bumper );

    // Front left
    bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
    bumper.position.y = 25;
    bumper.position.z = 25;
    bumper.rotation.y = Math.PI / 2;
    bumper.receiveShadow = true;
    bumper.castShadow = true;
    scene.add( bumper );

    // Top
    bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
    bumper.position.y = 50;
    bumper.position.x = 0;
    bumper.position.z = 0;
    bumper.rotation.z = Math.PI / 2;
    bumper.receiveShadow = true;
    bumper.castShadow = true;
    scene.add( bumper );

    requestAnimationFrame( render );
    scene.simulate();

    createShape();
};

创建形状:

createShape = (function() {

    var addshapes = true,
        doCreateShape;

    setTimeout(
        function addListener() {
            var button = document.getElementById( 'stop' );
            if ( button ) {
                button.addEventListener( 'click', function() { addshapes = false; } );
            } else {
                setTimeout( addListener );
            }
        }
    );

    doCreateShape = function() {
        var shape, material = new THREE.MeshLambertMaterial({ opacity: 0, transparent: true });
        var minR = 5, maxR = 10;
        var minVertices = 4, maxVertices = 6;
        var sphere = randomSphereInBox(minR, maxR, {vertex3A: new THREE.Vector3(0, 0, 0), vertex3B: new THREE.Vector3(50, 50, 50)});
        var convex_geometry = randomConvexInSphere(minVertices, maxVertices, sphere);
        shape = new Physijs.BoxMesh(
            convex_geometry,
            material
        );

        shape.material.color.setRGB( Math.random() * 100 / 100, Math.random() * 100 / 100, Math.random() * 100 / 100 );
        shape.castShadow = false;
        shape.receiveShadow = false;

        shape.position.set(
            Math.random() * 30 - 15,
            40,
            Math.random() * 30 - 15   
        );

        if ( addshapes ) {
            shape.addEventListener( 'ready', createShape );
        }

        scene.add( shape );

        new TWEEN.Tween(shape.material).to({opacity: 1}, 500).start();

        document.getElementById( 'shapecount' ).textContent = ( ++shapes ) + ' shapes created';
    };

    return function() {
        setTimeout( doCreateShape, 10 );
    };
})();

有什么方法可以约束容器内的所有对象?

【问题讨论】:

    标签: javascript three.js physijs


    【解决方案1】:

    嗯,物体从盒子里弹出来的事实是因为你将它重载到物体对于容器来说“太大”的程度,从而导致泄漏。我认为没有真正的解决方法,因为这一直是物理引擎中的一个问题,但尝试堵住一个洞并没有什么坏处,对吧?

    您可以尝试使用对象自己的 addEventListener 方法来检查与容器的碰撞,如果是,则将其自身的位置设置为容器的中心,暂时避免任何额外的碰撞:

    doCreateShape = function(){
        // ...
    
        shape.addEventListener('collision', function(collidedWith, lineVel, angleVel){
            if(collidedWith.material == wall_material){ // If it actually collided with a wall
                this.__dirtyPosition = true; // To actively change the object position
                this.position.x = 0;
                this.position.y = 40;
                this.position.z = 0;
            }
        });
    
        scene.add(shape);
    
        // ...
    }
    

    只需确保wall_material 变量是全局变量。

    此外,将 所有对象 的恢复原状设置为 0 将减少容器内的弹跳。

    【讨论】:

      猜你喜欢
      • 2019-05-30
      • 1970-01-01
      • 2012-09-06
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多