three+cannon模拟三维小球搅拌物理反应动画效果代码
代码语言:html
所属分类:三维
代码描述:three+cannon模拟三维小球搅拌物理反应动画效果代码,按住空格键,鼠标点击增加小球。
代码标签: three cannon 模拟 三维 小球 搅拌 物理 反应 动画
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="https://fonts.googleapis.com/css?family=Ropa+Sans&display=swap" rel="stylesheet"> <!-- PRELOAD IMAGES --> <link rel="preload" as="image" href="//repo.bfw.wiki/bfwrepo/images/threecaizhi/ambientOcclusion.avif" crossorigin> <link rel="preload" as="image" href="//repo.bfw.wiki/bfwrepo/images/threecaizhi/height.avif" crossorigin> <link rel="preload" as="image" href="//repo.bfw.wiki/bfwrepo/images/threecaizhi/roughness.avif" crossorigin> <link rel="preload" as="image" href="//repo.bfw.wiki/bfwrepo/images/threecaizhi/normal.avif" crossorigin> <link rel="preload" as="image" href="//repo.bfw.wiki/bfwrepo/images/threecaizhi/basecolor.avif" crossorigin> <style> html { font-family: "Ropa Sans", Arial, sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; font-size: 16px; } *, *::after, *::before { box-sizing: border-box; } h1 { margin: 0; padding: 0; } body { padding: 0; margin: 0; background-color: #341472; overflow: hidden; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } a { font-size: 16px; color: #fff; text-decoration: none; padding: 10px; transition: background-color 0.3s, color 0.3s; } a:hover { color: #341472; background-color: #fff; } #credits { margin: 0; position: absolute; z-index: 1; bottom: 10px; width: 100%; left: 20px; } #instructions { position: absolute; color: #fff; z-index: 1; top: 0; left: 100px; } .stats { position: absolute; top: 0; z-index: 0; pointer-events: none; } </style> </head> <body> <div class="stats"> </div> <p id="instructions"> 按住空格键,鼠标点击增加小球</p> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/Stats-16.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.144.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/OrbitControls.144.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/TransformControls.js"></script> <script type="module"> import { Pane } from "//repo.bfw.wiki/bfwrepo/js/module/tweakpane.3.0.2.js"; import * as CANNON from "//repo.bfw.wiki/bfwrepo/js/module/cannon-es.0.20.0.js"; const radians = degrees => { return degrees * Math.PI / 180; }; const hexToRgb = hex => { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16) / 255, g: parseInt(result[2], 16) / 255, b: parseInt(result[3], 16) / 255 } : null; }; const rgbToHex = (s) => s.match(/[0-9]+/g).reduce((a, b) => a + (b | 256).toString(16).slice(1), "#"); const rInterval = function (callback, delay) { const dateNow = Date.now; const requestAnimation = window.requestAnimationFrame; let start = dateNow(); let stop; const intervalFunc = function () { dateNow() - start < delay || (start += delay, callback()); stop || requestAnimation(intervalFunc); }; requestAnimation(intervalFunc); return { clear: function () { stop = 1; } }; }; class App { init() { this.setup(); this.createScene(); this.createCamera(); this.addCameraControls(); this.addAmbientLight(); this.addDirectionalLight(); this.addPhysicsWorld(); this.addPointLight(); this.addPointerDebugger(); this.addFloor(); this.addFloorGrid(); this.addPropeller(); this.addInnerBoudaries(); this.addAxisHelper(); this.addStatsMonitor(); this.addWindowListeners(); this.addGuiControls(); this.addInitialSpheres(); this.animate(); } addGuiControls() { this.pane = new Pane(); this.guiSettings = this.pane.addFolder({ title: "Settings", expanded: false }); this.guiSettings.addInput(this.colors, "background").on("change", evt => { this.floor.material.color = hexToRgb(evt.value); document.body.style.backgroundColor = evt.value; this.scene.background = new Color(evt.value); }); this.guiSettings.addInput(this.colors, "ring").on("change", evt => { this.ringMesh.material.color = hexToRgb(evt.value); }); this.guiSettings.addInput(this.colors, "propeller").on("change", evt => { this.meshes.propeller.material.color = hexToRgb(evt.value); }); this.guiSettings. addInput(this.colors, "leftSideSphere"). on("change", evt => { this.meshes.sphereLeftSideMaterial.color = hexToRgb(evt.value); }); this.guiSettings. addInput(this.colors, "rightSideSphere"). on("change", evt => { this.meshes.sphereRightSideMaterial.color = hexToRgb(evt.value); }); this.guiSettings. addInput(this.colors, "displayGrid"). on("change", evt => { if (evt.value) { this.scene.add(this.grid); } else { this.scene.remove(this.grid); } }); } addPointerDebugger() { const material = new THREE.MeshStandardMaterial({ color: 0xff0000 }); const geometry = new THREE.SphereGeometry(0.01, 16, 16); this.pointerDebugger = new THREE.Mesh(geometry, material); this.scene.add(this.pointerDebugger); } addPhysicsWorld() { this.world = new CANNON.World(); this.world.gravity.set(0, -40, 0.5); this.world.broadphase = new CANNON.NaiveBroadphase(); this.world.solver.iterations = 20; this.world.defaultContactMaterial.contactEquationStiffness = 1e6; this.world.defaultContactMaterial.contactEquationRelaxation = 10; this.world.allowSleep = true; } setup() { this.velocity = 0.015; this.raycaster = new THREE.Raycaster(); this.mouse3D = new THREE.Vector2(); this.width = window.innerWidth; this.height = window.innerHeight; this.debug = false; this.colors = { background: rgbToHex( window.getComputedStyle(document.body).backgroundColor), floor: rgbToHex(window.getComputedStyle(document.body).backgroundColor), box: "#ffffff", leftSideSphere: "#ff0f40", rightSideSphere: "#ffffff", ambientLight: "#ffffff", directionalLight: "#ffffff", ring: "#ffaf00", propeller: "#faecec", displayGrid: true }; this.sphereConfig = { radius: 0.18, width: 32, height: 32 }; this.meshes = { container: new THREE.Object3D(), spheres: [], propeller: null, material: new THREE.MeshStandardMaterial({ color: this.colors.propeller, metalness: 0.1, roughness: 0.1 }), sphereBaseMaterial: new THREE.MeshPhysicalMaterial({ color: "#ff00ff" }), sphereLeftSideMaterial: new THREE.MeshPhysicalMaterial({ color: this.colors.leftSideSphere, metalness: 0.1, emissive: 0x0, roughness: 0.1 }), sphereRightSideMaterial: new THREE.MeshPhysicalMaterial({ color: this.colors.rightSideSphere, metalness: 0.1, emissive: 0x0, roughness: 0.2 }), sphereConfig: { geometry: new THREE.SphereGeometry( this.sphereConfig.radius, this.sphereConfig.width, this.sphereConfig.height), halfsphere: new THREE.SphereGeometry( this.sphereConfig.radius, 16, 16, 0, 3.15) } }; this.meshes.sphereLeftSideMaterial.clearcoatRoughness = 0; this.meshes.sphereLeftSideMaterial.clearcoat = 0; this.meshes.sphereLeftSideMaterial.reflectivity = 1; this.meshes.sphereRightSideMaterial.clearcoatRoughness = 0; this.meshes.sphereRightSideMaterial.clearcoat = 0; this.meshes.sphereRightSideMaterial.reflectivity = 1; window.addEventListener("mousemove", this.onMouseMove.bind(this), { passive: true }); window.addEventListener("keydown", this.onKeydown.bind(this), { passive: true }); window.addEventListener("keyup", this.onKeyup.bind(this), { passive: true }); } createScene() { this.scene = new THREE.Scene(); this.scene.background = new THREE.Color(this.colors.background); this.renderer = new THREE.WebGLRenderer({ antialias: true }); this.renderer.setSize(this.width, this.height); this.renderer.shadowMap.enabled = true; this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; document.body.appendChild(this.renderer.domElement); } addAxisHelper() { const axesHelper = new THREE.AxesHelper(5); this.debug && this.scene.add(axesHelper); } createCamera() { this.camera = new THREE.PerspectiveCamera( 20, this.width / this.height, 1, 1000); this.camera.position.set(0, 25, 20); this.scene.add(this.camera); } addCameraControls() { this.orbitControl = new THREE.OrbitControls( this.camera, this.renderer.domElement); this.orbitControl.enableDamping = true; this.orbitControl.dampingFactor = 0.02; this.orbitControl.maxDistance = 60; this.orbitControl.minDistance = 30; this.orbitControl.minPolarAngle = THREE.MathUtils.degToRad(0); this.orbitControl.maxPolarAngle = THREE.MathUtils.degToRad(70); this.orbitControl.enablePan = !this.cameraAutoAnimate; this.orbitControl.enableRotate = !this.cameraAutoAnimate; this.orbitControl.enableZoom = !this.cameraAutoAnimate; this.orbitControl.saveState(); document.body.style.cursor = "-moz-grabg"; document.body.style.cursor = "-webkit-grab"; this.orbitControl.addEventListener("start", () => { requestAnimationFrame(() => { document.body.style.cursor = "-moz-grabbing"; document.body.style.cursor = "-webkit-grabbing"; }); }); this.orbitControl.addEventListener("end", () => { requestAnimationFrame(() => { document.body.style.cursor = "-moz-grab"; document.body.style.cursor = "-webkit-grab"; }); }); } addAmbientLight() { const light = new THREE.AmbientLight( { color: this.colors.ambientLight }, 0.5); this.scene.add(light); } addDirectionalLight() { const target = new THREE.Object3D(); this.directionalLight = new THREE.DirectionalLi.........完整代码请登录后点击上方下载按钮下载查看
网友评论0