CannonJS地板。让球粘在地上

CannonJS floor. Make a ball stick to the ground

新手问题:我正在尝试将一个球丢到地板上并让它粘在那里甚至滚过一个平面。现在它穿过飞机。我不确定我在哪里犯了错误或者我做错了什么。

var world, timeStep=1/60, scene, renderer, camera,
      icosahedronBody, sphereShape, groundShape,
      ground, groundBody, groundShape;
  // CONSTANTS
  var GRID_HELPER_SIZE = 40,
      GRID_HELPER_STEP = 2,
      MASS             = 5;

  initThree();
  initCannon();
  animate();

  function initCannon() {
    world                   = new CANNON.World();
    world.broadphase        = new CANNON.NaiveBroadphase();
    sphereShape             = new CANNON.Sphere();
    groundShape             = new CANNON.Plane();

    icosahedronBody         = new CANNON.Body({
                                    mass: MASS,
                                  });
    groundBody              = new CANNON.Body({
                                    mass: 0, // mass == 0 makes the body static
                                  });

    world.solver.iterations = 10;
    world.gravity.set(0,-9.8,0);
    world.defaultContactMaterial.contactEquationStiffness = 1e9;
    world.defaultContactMaterial.contactEquationRegularizationTime = 4;

    icosahedronBody.addShape(sphereShape);
    icosahedronBody.position.set(0,50,0)
    icosahedronBody.linearDamping     = 0.5;
    world.addBody(icosahedronBody);

    groundBody.addShape(groundShape);
    groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(0,1,0),-Math.PI/2);
    world.addBody(groundBody);

    var ballContact         = new CANNON.ContactMaterial( groundBody, icosahedronBody, 0.0, 0.0);

    world.addContactMaterial(ballContact);
  }

  function initThree(){
    // INITIALIZE CANVAS
    scene                 = new THREE.Scene();
    renderer              = new THREE.WebGLRenderer();
    camera                = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
    var light             = new THREE.AmbientLight( 0x404040 ),
        directionalLight  = new THREE.DirectionalLight( 0xffffff ),
        gridHelper        = new THREE.GridHelper( GRID_HELPER_SIZE, GRID_HELPER_STEP );

    renderer.setSize( window.innerWidth - 100 , window.innerHeight - 100 );
    renderer.setClearColor( 0x757575 );
    document.body.appendChild( renderer.domElement );
    camera.position.set(1,25,100); // camera position to x , y , z
    camera.lookAt( new THREE.Vector3() )
    directionalLight.position.set( 1, 0.75, 0.5 ).normalize();

    // INITIAL CANVAS
    scene.add( directionalLight );  
    scene.add( light );
    scene.add( camera );
    scene.add( gridHelper );

    // MATERIALS
    var icoGeometry = new THREE.IcosahedronGeometry(10, 1),
        icoMaterial = new THREE.MeshLambertMaterial( {color: 0xff0000} );
    icosahedron     = new THREE.Mesh( icoGeometry, icoMaterial );

    var groundGeometry = new THREE.BoxGeometry(100 , 1, 100),
        groundMaterial = new THREE.MeshLambertMaterial( {color: 0xcccccc} );
    ground             = new THREE.Mesh( groundGeometry, groundMaterial );
    ground.receiveShadow = true;

    // ADD OBJECTS TO SCENE
    scene.add( icosahedron );
    scene.add( ground );
  }    

  function animate() {
      requestAnimationFrame( animate );
      updatePhysics();
      render();
  }
  function updatePhysics() {
      // Step the physics world
      world.step(timeStep);
      // Copy coordinates from Cannon.js to Three.js
      icosahedron.position.copy(icosahedronBody.position);
      icosahedron.quaternion.copy(icosahedronBody.quaternion);

      ground.position.copy(groundBody.position);
      ground.quaternion.copy(groundBody.quaternion);
  }
  function render() {
      renderer.render( scene, camera );
  }

您的 CANNON.Plane 方向似乎有误。默认情况下,它的法线指向Z方向,所以你需要将它沿正X轴旋转-90度,使其法线指向正Y方向(使用right hand rule):

groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2);

其次,您必须使 BoxGeometry 匹配。确保它沿 Z 轴变薄。

var groundGeometry = new THREE.BoxGeometry(100, 100, 1),

我还注意到 THREE.IcosahedronGeometry 的半径是 10,而 CANNON.Sphere 的半径是 1 (the default)。将其半径设置为 10 以匹配 three.js 几何形状:

sphereShape             = new CANNON.Sphere(10);

替换这三行,您的模拟看起来应该是这样。祝你好运!