Cannon.js是一个Web的轻量级3D物理引擎,包括简单的碰撞检测,各种体形,接触,摩擦和约束。可用于游戏的刚体模拟。用JavaScript编写的,可以与任何支持浏览器的渲染或游戏引擎一起使用。
cannonjs官网:http://schteppe.github.io/cannon.js/
cannonjs分支:https://github.com/pmndrs/cannon-es/
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
<canvas id="canvas"/> <script> let head = document.getElementsByTagName("head")[0]; let cannon_script = document.createElement("script"); cannon_script.src = "https://github.com/schteppe/cannon.js/releases/download/v0.6.2/cannon.min.js"; head.appendChild(cannon_script); let three_script = document.createElement("script"); three_script.src = "https://github.com/mrdoob/three.js/blob/dev/build/three_r132_min.js"; head.appendChild(three_script); three_script.onload = function () { new Cinema().render(); }; class Cinema { constructor() { let canvas = document.getElementById("canvas"); canvas.width = 800; canvas.height = 350; this.camera = new THREE.PerspectiveCamera(55, canvas.width / canvas.height, 1, 1000); this.camera.position.x = 200; this.camera.position.y = 80; this.camera.position.z = 180; this.camera.lookAt(0, 5, 0); let controls_right = new THREE.OrbitControls(this.camera, canvas); controls_right.target.set(0, 5, 0); controls_right.update(); this.renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true}); this.renderer.setSize(canvas.width, canvas.height); this.renderer.shadowMap.enabled = true; this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; this.cannonWorld = new CANNON.World(); // 创建物理世界 this.cannonWorld.gravity.set(0, -1, 0); // 重力加速度。负数为沿y轴向下,绝对值太大会穿过地面 this.cannonWorld.solver.iterations = 5; // 解算器的迭代次数,更高的迭代次数意味着更加精确同时性能将会降低 this.cannonWorld.broadphase = new CANNON.NaiveBroadphase();// NaiveBroadphase是默认碰撞检测方式,检测速度较高 this.scene = new THREE.Scene(); this.scene.add(this.camera); this.scene.add(new MyDirectionalLight("#ffffff")); this.scene.add(new THREE.AmbientLight("#cccccc")); let ground = new CannonGround(this.scene, this.cannonWorld); ground.intoSceneAndWorld(); setInterval(() => { // "下雨" let cannonBox = new CannonBox(this.scene, this.cannonWorld); cannonBox.intoSceneAndWorld(); }, 10); } updatePhysics() { this.cannonWorld.step(0.2); // 降落速度 this.scene.children.forEach(obj => { // 遍历场景中的对象 if (obj.isMesh == true) { obj.position.copy(obj.userData.position); obj.quaternion.copy(obj.userData.quaternion); } }); } render() { this.updatePhysics(); this.renderer.render(this.scene, this.camera); requestAnimationFrame(this.render.bind(this)); } } class MyDirectionalLight { constructor(color) { let directionalLight = new THREE.DirectionalLight(color, 1); directionalLight.position.set(60, 300, 100); directionalLight.target.position.set(35, 0, 65); directionalLight.castShadow = true; directionalLight.shadow.camera.visible = true; let d = 160; directionalLight.shadow.camera.left = -d; directionalLight.shadow.camera.right = d; directionalLight.shadow.camera.top = d; directionalLight.shadow.camera.bottom = -d; directionalLight.shadow.camera.far = 1000; directionalLight.shadow.bias = -0.01; directionalLight.shadow.mapSize.width = 2048; directionalLight.shadow.mapSize.height = 2048; return directionalLight; } } class CannonGround { constructor(scene, cannonWorld) { this.scene = scene; this.cannonWorld = cannonWorld; } intoSceneAndWorld() { let width = 300; let depth = 300; let height = 0.2; let pos_x = 0; let pos_y = -0.1; let pos_z = 0; let shape = new CANNON.Box(new CANNON.Vec3(width / 2, height / 2, depth / 2)); var cannonBody = new CANNON.Body({ //创建一个刚体(物理世界的刚体数据) mass: 0, // 刚体质量kg。大于0就会掉落 position: new CANNON.Vec3(pos_x, pos_y, pos_z), // 刚体位置,单位是米 shape: shape, // 刚体的形状 material: new CANNON.Material({ friction: 0.5, // 材质摩擦系数 restitution: 0.5 // 材质弹性系数 }) }); this.cannonWorld.addBody(cannonBody); // 物理世界添加刚体 let color = "#cdccdc"; let geometry = new THREE.BoxGeometry(width, height, depth); let material = new THREE.MeshPhongMaterial({ color: color, side: THREE.DoubleSide }); let mesh = new THREE.Mesh(geometry, material); mesh.position.x = pos_x; mesh.position.y = pos_y; mesh.position.z = pos_z; mesh.castShdow = true; mesh.receiveShadow = true; mesh.userData = cannonBody; // 将刚体赋值给网格的userData属性 this.scene.add(mesh); // 场景添加网格 } } class CannonBox { constructor(scene, cannonWorld) { this.scene = scene; this.cannonWorld = cannonWorld; } intoSceneAndWorld() { let width = 10; let depth = 10; let height = 10; let x = (0.5 - Math.random()) * 250; let y = 100; let z = (0.5 - Math.random()) * 250; let cannonBody = new CANNON.Body({ mass: 1, // 质量为1kg position: new CANNON.Vec3(x, y, z), // 位置 shape: new CANNON.Box(new CANNON.Vec3(width / 2, height / 2, depth / 2)), // 形状 material: new CANNON.Material({ friction: 0.4, // 摩擦系数 restitution: 0.8 // 弹性系数。数值越大弹性越好 }) }); this.cannonWorld.addBody(cannonBody);//在物理世界中添加该刚体 var color = "#"; // 随机色 for (let k = 0; k < 6; k++) color += parseInt(Math.random() * 16).toString(16); let material = new THREE.MeshPhongMaterial({ color: color, side: THREE.DoubleSide, }); let geometry = new THREE.BoxGeometry(width, height, depth); let mesh = new THREE.Mesh(geometry, material); mesh.position.set(x, y, z); mesh.castShadow = true; mesh.receiveShadow = true; mesh.userData = cannonBody; // 给box的userData属性添加刚体数据 this.scene.add(mesh); // 添加到场景 setTimeout(() => { // 自动移除 this.cannonWorld.removeBody(cannonBody); this.scene.remove(mesh); mesh.material.dispose(); mesh.geometry.dispose(); }, 8000); } } </script> |
- end
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/3134.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设