How to Create Bouncing Ball on MouseClick?鼠标点击创建弹跳小球
要实现鼠标点击掉落小弹球,
实际上就是鼠标点击创建小球 和 cannon物理引擎的结合,
需要注意的是,每一个新建的小球都需要绑定一个CANNON.Body,
需要在创建的同时留好数据的访问入口,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| const mouse = new THREE.Vector2() const planeNormal = new THREE.Vector3() const plane = new THREE.Plane() const raycaster = new THREE.Raycaster() const interSectionPointer = new THREE.Vector3() const BallList = []
window.onmousemove = function(e){ mouse.x = e.offsetX/window.innerWidth*2 - 1 mouse.y = 1 - e.offsetY/window.innerHeight*2 planeNormal.copy(camera.position) plane.setFromNormalAndCoplanarPoint(planeNormal, scene.position) raycaster.setFromCamera(mouse,camera) raycaster.ray.intersectPlane(plane, interSectionPointer) } window.onclick = function(e){ const sphereGeo = new THREE.SphereGeometry(0.2) const sphereMat = new THREE.MeshStandardMaterial({ color:0xffffff*Math.random(), metalness:0, roughness:0 }) const sphereMesh = new THREE.Mesh(sphereGeo,sphereMat) sphereMesh.position.copy(interSectionPointer) scene.add(sphereMesh) sphereMesh.castShadow = true const ballBody = new CANNON.Body({ shape:new CANNON.Sphere(0.2), mass:1, position:interSectionPointer, material:ballPhyMat }) world.addBody(ballBody) BallList.push([sphereMesh,ballBody]) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| const world = new CANNON.World({ gravity:new CANNON.Vec3(0,-9.89,0) }) const planePhyMat = new CANNON.Material() const ballPhyMat = new CANNON.Material() const planeBallContactMat = new CANNON.ContactMaterial( planePhyMat, ballPhyMat, { restitution:0.9 } ) world.addContactMaterial(planeBallContactMat)
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| const timeStep = 1/60 function animate() { world.step(timeStep) groundMesh.position.copy(groundBody.position) groundMesh.quaternion.copy(groundBody.quaternion) BallList.forEach(([mesh,body])=>{ mesh.position.copy(body.position) mesh.quaternion.copy(body.quaternion) }) renderer.render(scene, camera); }
renderer.setAnimationLoop(animate);
|
需要注意的是:
如果不做任何处理,此处的球体阴影会因为锯齿变得参差不齐:
渲染器创建时有抗锯齿选项antialias,
设置为true的话抗锯齿效果会好一些:
1
| const renderer = new THREE.WebGLRenderer({antialias: true});
|
看视频作者的操作,是将光源的shadow.mapSize属性进行放大:
1 2
| pointLight.shadow.mapSize.width = 1024 pointLight.shadow.mapSize.height = 1024
|
效果确实好了很多。