0

我编写了一个程序,根据 Physijs 的示例形状随机生成 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 );
    };
})();

有没有办法限制容器内的所有对象?

4

1 回答 1

0

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

您可以尝试使用对象自己的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将减少容器内的弹跳。

于 2015-11-05T22:37:47.577 回答