Three.js - 多面体几何
多面体是一种只有平面和直边的几何体。您可以通过指定顶点和索引来绘制不同类型的多面体。
vertices 顶点 − 构成多面体的点的数组。
indices 索引 − 从顶点组成面的索引数组。
radius 半径 − 最终形状的半径。默认为 1。
detail 细节 − 将几何体细分为多少级。细节越多,形状越平滑。
以下代码创建一个有四个面的多面体。
const vertices = [ 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1 ] const indices = [ 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 ] const geometry = new THREE.PolyhedronGeometry(vertices, indices, radius, detail)
示例
查看以下示例。
polyhedron.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Three.js - Polyhedron</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: -applesystem, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } html, body { height: 100vh; width: 100vw; } #threejs-container { position: block; width: 100%; height: 100%; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.js"></script> </head> <body> <div id="threejs-container"></div> <script type="module"> // Creating a tetrahedron using Polyhedron geometry in Three.js // GUI const gui = new dat.GUI() // 尺寸 let width = window.innerWidth let height = window.innerHeight // 场景 const scene = new THREE.Scene() scene.background = new THREE.Color(0x262626) const axesHepler = new THREE.AxesHelper(10) scene.add(axesHepler) // 相机 const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 100) camera.position.set(0, 0, 10) const camFolder = gui.addFolder('Camera') camFolder.add(camera.position, 'z').min(10).max(60).step(10) camFolder.open() // prettier-ignore const vertices = [ 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1 ] // prettier-ignore const indices = [ 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 ] const geometry = new THREE.PolyhedronGeometry(vertices, indices) const material = new THREE.MeshNormalMaterial({ color: 0xffffff }) const materialFolder = gui.addFolder('Material') materialFolder.add(material, 'wireframe') materialFolder.open() const plane = new THREE.Mesh(geometry, material) scene.add(plane) // experimenting plane properties const planeProps = { radius: 1, detail: 1 } const props = gui.addFolder('Properties') props .add(planeProps, 'radius', 1, 30) .step(1) .onChange(redraw) .onFinishChange(() => console.dir(plane.geometry)) props.add(planeProps, 'detail', 1, 30).step(1).onChange(redraw) props.open() function redraw() { let newGeometry = new THREE.PolyhedronGeometry( verticesOfCube, indicesOfFaces, planeProps.radius, planeProps.detail ) plane.geometry.dispose() plane.geometry = newGeometry } // 响应性 window.addEventListener('resize', () => { width = window.innerWidth height = window.innerHlet camera.aspect = width / height camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) renderer.render(scene, camera) }) // 渲染器 const renderer = new THREE.WebGL1Renderer() renderer.setSize(width, height) renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) // 动画 function animate() { requestAnimationFrame(animate) plane.rotation.x += 0.005 plane.rotation.y += 0.01 renderer.render(scene, camera) } // 渲染场景 const container = document.querySelector('#threejs-container') container.append(renderer.domElement) renderer.render(scene, camera) animate() </script> </body> </html>
输出
Three.js 还具有一些常见多面体的几何形状。
多面体 | No. of faces | Code |
---|---|---|
四面体 | 4 | THREE.TetrahedronGeometry |
八面体 | 12 | THREE.OctahedronGeometry |
十二面体 | 12 | THREE.DodecahedronGeometry |
二十面体 | 20 | THREE.IcosahedronGeometry |
示例
查看以下示例。
polyhedrons.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Three.js - Polyhedrons</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: -applesystem, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } html, body { height: 100vh; width: 100vw; } #threejs-container { position: block; width: 100%; height: 100%; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.js"></script> </head> <body> <div id="threejs-container"></div> <script type="module"> // Various built-in polyhedron geometries in Three.js // Tetrahedron, Octahedron, Dodecahedron, Icosahedron // GUI const gui = new dat.GUI() // 尺寸 let width = window.innerWidth let height = window.innerHeight // 场景 const scene = new THREE.Scene() scene.background = new THREE.Color(0x262626) // 相机 const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100) camera.position.set(0, 0, 10) const camFolder = gui.addFolder('Camera') camFolder.add(camera.position, 'z').min(10).max(60).step(10) camFolder.open() // tetrahedron const geometry = new THREE.TetrahedronGeometry() const material = new THREE.MeshNormalMaterial() const materialFolder = gui.addFolder('Material') materialFolder.add(material, 'wireframe') materialFolder.open() const tetrahedron = new THREE.Mesh(geometry, material) tetrahedron.position.set(-5, 0, 0) scene.add(tetrahedron) const tetrahedronProps = { radius: 1, detail: 1 } const tetraProps = gui.addFolder('Tetrahedron') tetraProps .add(tetrahedronProps, 'radius', 1, 50) .step(1) .onChange(redrawTetrahedron) .onFinishChange(() => console.dir(tetrahedron.geometry)) tetraProps.add(tetrahedronProps, 'detail', 1, 50, 1).onChange(redrawTetrahedron) tetraProps.open() function redrawTetrahedron() { let newGeometry = new THREE.TetrahedronGeometry( tetrahedronProps.radius, tetrahedronProps.detail ) tetrahedron.geometry.dispose() tetrahedron.geometry = newGeometry } // octahedron const geometry1 = new THREE.OctahedronGeometry() const octahedron = new THREE.Mesh(geometry1, material) octahedron.position.set(-2.5, 0, 0) scene.add(octahedron) const octahedronProps = { radius: 1, detail: 1 } const octaProps = gui.addFolder('Octahedron') octaProps .add(octahedronProps, 'radius', 1, 50) .step(1) .onChange(redrawOctahedron) .onFinishChange(() => console.dir(octahedron.geometry)) octaProps.add(octahedronProps, 'detail', 1, 50, 1).onChange(redrawOctahedron) octaProps.open() function redrawOctahedron() { let newGeometry = new THREE.OctahedronGeometry( octahedronProps.radius, octahedronProps.detail ) octahedron.geometry.dispose() octahedron.geometry = newGeometry } // dodecahedron const geometry2 = new THREE.DodecahedronGeometry() const dodecahedron = new THREE.Mesh(geometry2, material) dodecahedron.position.set(0, 0, 0) scene.add(dodecahedron) const dodecahedronProps = { radius: 1, detail: 1 } const dodecaProps = gui.addFolder('Dodecahedron') dodecaProps .add(dodecahedronProps, 'radius', 1, 50) .step(1) .onChange(redrawDodecahedron) .onFinishChange(() => console.dir(dodecahedron.geometry)) dodecaProps.add(dodecahedronProps, 'detail', 1, 50, 1).onChange(redrawDodecahedron) dodecaProps.open() function redrawDodecahedron() { let newGeometry = new THREE.DodecahedronGeometry( dodecahedronProps.radius, dodecahedronProps.detail ) dodecahedron.geometry.dispose() dodecahedron.geometry = newGeometry } // icosahedron const geometry3 = new THREE.IcosahedronGeometry() const icosahedron = new THREE.Mesh(geometry3, material) icosahedron.position.set(2.5, 0, 0) scene.add(icosahedron) const icosahedronProps = { radius: 1, detail: 1 } const icosaProps = gui.addFolder('Icosahedron') icosaProps .add(icosahedronProps, 'radius', 1, 50) .step(1) .onChange(redrawIcosahedron) .onFinishChange(() => console.dir(icosahedron.geometry)) icosaProps.add(icosahedronProps, 'detail', 1, 50, 1).onChange(redrawIcosahedron) icosaProps.open() function redrawIcosahedron() { let newGeometry = new THREE.IcosahedronGeometry( icosahedronProps.radius, icosahedronProps.detail ) icosahedron.geometry.dispose() icosahedron.geometry = newGeometry } // 响应性 window.addEventListener('resize', () => { width = window.innerWidth height = window.innerHeight camera.aspect = width / height camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) renderer.render(scene, camera) }) // 渲染器 const renderer = new THREE.WebGL1Renderer() renderer.setSize(width, height) renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) // 动画 function animate() { requestAnimationFrame(animate) const polyhedrons = [tetrahedron, octahedron, dodecahedron, icosahedron] polyhedrons.forEach((hedron) => { hedron.rotation.x += 0.005 hedron.rotation.y += 0.01 }) renderer.render(scene, camera) } // 重新组合场景 const container = document.querySelector('#threejs-container') container.append(renderer.domElement) renderer.render(scene, camera) animate() </script> </body> </html>