three.js 4 几何体
import * as THREE from 'three'; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; /** * 3d 几何体 * https://threejs.org/docs/index.html#api/zh/geometries/BoxGeometry */ export class ThreeDoc4Geometry { constructor(canvasId) { this.work(canvasId); } work(canvasId) { // 创建 3d 场景 const scene = new THREE.Scene(); scene.background = new THREE.Color(0x9e9e9e); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); // 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。 document.body.appendChild(renderer.domElement); let geo; // 立方缓冲几何体(BoxGeometry) // geo = this.addBox(scene); // 胶囊缓冲几何体(CapsuleGeometry) // geo = this.addCapsule(scene); // 圆形缓冲几何体(CircleGeometry) // geo = this.addCircle(scene); // 圆锥缓冲几何体(ConeGeometry) // geo = this.addCone(scene); // 圆柱缓冲几何体(CylinderGeometry) // geo = this.addCylinder(scene); // 十二面缓冲几何体(DodecahedronGeometry) // geo = this.addDodecahedron(scene); // 添加边缘几何体(EdgesGeometry) // geo = this.addEdges(scene); // 挤压缓冲几何体(ExtrudeGeometry) // geo = this.addExtrude(scene); // 二十面缓冲几何体(IcosahedronGeometry) // geo = this.addIcosahedron(scene); // 车削缓冲几何体(LatheGeometry) // geo = this.addLatheGeometry(scene); // 八面缓冲几何体(OctahedronGeometry) // geo = this.addOctahedronGeometry(scene); // 平面缓冲几何体(PlaneGeometry) // geo = this.addPlane(scene); // 多面缓冲几何体(PolyhedronGeometry) // geo = this.addPolyhedronGeometry(scene); // 圆环缓冲几何体(RingGeometry) // geo = this.addRingGeometry(scene); // 形状缓冲几何体(ShapeGeometry) // geo = this.addShapeGeometry(scene); // 球缓冲几何体(SphereGeometry) // geo = this.addSphere(scene); // 四面缓冲几何体(TetrahedronGeometry) // geo = this.addTetrahedronGeometry(scene); // 圆环缓冲几何体(TorusGeometry) // geo = this.addTorus(scene); // 圆环缓冲扭结几何体(TorusKnotGeometry) // geo = this.addTorusKnotGeometry(scene); // 管道缓冲几何体(TubeGeometry) // geo = this.addTubeGeometry(scene); // 网格几何体(WireframeGeometry) geo = this.addWireframeGeometry(scene); // 边缘辅助线 let edges = new THREE.EdgesHelper(geo, 0x00ff00); scene.add(edges); //在场景中添加光源 let light = new THREE.DirectionalLight(0xffffff, 2); light.position.set(0, 20, 0); scene.add(light); let light2 = new THREE.DirectionalLight(0xffffff, 2); light2.position.set(0, -10, 0); scene.add(light2); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 设置相机位置 camera.position.x = 30; camera.position.y = 20; camera.position.z = 0; camera.lookAt(0, 0, 0); // 添加控制器 let orb = new OrbitControls(camera, document.body); orb.addEventListener('change', function () { console.log(camera.position); }); function animate() { requestAnimationFrame(animate); let step = 0.005; geo.rotation.x += step; geo.rotation.y += step; geo.rotation.z += step; edges.rotation.x += step; edges.rotation.y += step; edges.rotation.z += step; renderer.render(scene, camera); } animate(); } /** * 立方缓冲几何体(BoxGeometry) * BoxGeometry是四边形的原始几何类,它通常使用构造函数所提供的“width”、“height”、“depth”参数来创建立方体或者不规则四边形。 * BoxGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer) * width — X轴上面的宽度,默认值为1。 * height — Y轴上面的高度,默认值为1。 * depth — Z轴上面的深度,默认值为1。 * widthSegments — (可选)宽度的分段数,默认值是1。 * heightSegments — (可选)高度的分段数,默认值是1。 * depthSegments — (可选)深度的分段数,默认值是1。 * @type {BoxGeometry} * @return Object */ addBox(scene) { const geometry = new THREE.BoxGeometry(10, 10, 10); const material = new THREE.MeshPhongMaterial({ color: 0x049EF4 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); return cube; } /** * 胶囊缓冲几何体(CapsuleGeometry) * CapsuleGeometry is a geometry class for a capsule with given radii and height. It is constructed using a lathe. * CapsuleGeometry(radius : Float, length : Float, capSubdivisions : Integer, radialSegments : Integer) * radius — Radius of the capsule. Optional; defaults to 1. * length — Length of the middle section. Optional; defaults to 1. * capSegments — Number of curve segments used to build the caps. Optional; defaults to 4. * radialSegments — Number of segmented faces around the circumference of the capsule. Optional; defaults to 8. * @type {BoxGeometry} * @return Object */ addCapsule(scene) { const geometry = new THREE.CapsuleGeometry( 10, 10, 4, 16 ); const material = new THREE.MeshBasicMaterial( {color: 0x049EF4} ); const capsule = new THREE.Mesh( geometry, material ); scene.add( capsule ); return capsule; } /** * 圆形缓冲几何体(CircleGeometry) * CircleGeometry是欧式几何的一个简单形状,它由围绕着一个中心点的三角分段的数量所构造,由给定的半径来延展。 同时它也可以用于创建规则多边形,其分段数量取决于该规则多边形的边数。 * CircleGeometry(radius : Float, segments : Integer, thetaStart : Float, thetaLength : Float) * radius — 圆形的半径,默认值为1 * segments — 分段(三角面)的数量,最小值为3,默认值为8。 * thetaStart — 第一个分段的起始角度,默认为0。(three o'clock position) * thetaLength — 圆形扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆。 * @return Object */ addCircle(scene) { const geometry = new THREE.CircleGeometry(10, 32); const material = new THREE.MeshBasicMaterial({ color: 0x049EF4 }); const circle = new THREE.Mesh(geometry, material); scene.add(circle); return circle; } /** * 圆锥缓冲几何体(ConeGeometry) * 一个用于生成圆锥几何体的类。 * ConeGeometry(radius : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float) * radius — 圆锥底部的半径,默认值为1。 * height — 圆锥的高度,默认值为1。 * radialSegments — 圆锥侧面周围的分段数,默认为8。 * heightSegments — 圆锥侧面沿着其高度的分段数,默认值为1。 * openEnded — 一个Boolean值,指明该圆锥的底面是开放的还是封顶的。默认值为false,即其底面默认是封顶的。 * thetaStart — 第一个分段的起始角度,默认为0。(three o'clock position) * thetaLength — 圆锥底面圆扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆锥。 * @return Object */ addCone(scene) { const geometry = new THREE.ConeGeometry(10, 10, 16); const material = new THREE.MeshBasicMaterial({ color: 0x049EF4 }); const cone = new THREE.Mesh(geometry, material); scene.add(cone); return cone; } /** * 圆柱缓冲几何体(CylinderGeometry) * 一个用于生成圆柱几何体的类。 * CylinderGeometry(radiusTop : Float, radiusBottom : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float) * radiusTop — 圆柱的顶部半径,默认值是1。 * radiusBottom — 圆柱的底部半径,默认值是1。 * height — 圆柱的高度,默认值是1。 * radialSegments — 圆柱侧面周围的分段数,默认为8。 * heightSegments — 圆柱侧面沿着其高度的分段数,默认值为1。 * openEnded — 一个Boolean值,指明该圆锥的底面是开放的还是封顶的。默认值为false,即其底面默认是封顶的。 * thetaStart — 第一个分段的起始角度,默认为0。(three o'clock position) * thetaLength — 圆柱底面圆扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆柱。 * @return Object */ addCylinder(scene) { const geometry = new THREE.CylinderGeometry(10, 10, 10, 16); const material = new THREE.MeshBasicMaterial({ color: 0x049EF4 }); const cylinder = new THREE.Mesh(geometry, material); scene.add(cylinder); return cylinder; } /** * 十二面缓冲几何体(DodecahedronGeometry) * 一个用于创建十二面几何体的类。 * DodecahedronGeometry(radius : Float, detail : Integer) * radius — 十二面体的半径,默认值为1。 * detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个十二面体。 * @return Object */ addDodecahedron(scene) { const geometry = new THREE.DodecahedronGeometry(10, 0); const material = new THREE.MeshBasicMaterial({ color: 0x049EF4 }); const dodecahedron = new THREE.Mesh(geometry, material); scene.add(dodecahedron); return dodecahedron; } /** * 边缘几何体(EdgesGeometry) * 这可以作为一个辅助对象来查看geometry的边缘。 * EdgesGeometry( geometry : BufferGeometry, thresholdAngle : Integer ) * geometry — 任何一个几何体对象。 * thresholdAngle — 仅当相邻面的法线之间的角度(单位为角度)超过这个值时,才会渲染边缘。默认值为1。 * @return Object */ addEdges(scene) { const geometry = new THREE.BoxGeometry(10, 10, 10); const edges = new THREE.EdgesGeometry(geometry); const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0xffffff })); scene.add(line); return line; } /** * 挤压缓冲几何体(ExtrudeGeometry) * 从一个形状路径中,挤压出一个BufferGeometry。 * ExtrudeGeometry(shapes : Array, options : Object) * shapes — 形状或者一个包含形状的数组。 * options — 一个包含有下列参数的对象: * * curveSegments — int,曲线上点的数量,默认值是12。 * steps — int,用于沿着挤出样条的深度细分的点的数量,默认值为1。 * depth — float,挤出的形状的深度,默认值为1。 * bevelEnabled — bool,对挤出的形状应用是否斜角,默认值为true。 * bevelThickness — float,设置原始形状上斜角的厚度。默认值为0.2。 * bevelSize — float。斜角与原始形状轮廓之间的延伸距离,默认值为bevelThickness-0.1。 * bevelOffset — float. Distance from the shape outline that the bevel starts. Default is 0. * bevelSegments — int。斜角的分段层数,默认值为3。 * extrudePath — THREE.Curve对象。一条沿着被挤出形状的三维样条线。Bevels not supported for path extrusion. * UVGenerator — Object。提供了UV生成器函数的对象。 * 该对象将一个二维形状挤出为一个三维几何体。 * 当使用这个几何体创建Mesh的时候,如果你希望分别对它的表面和它挤出的侧面使用单独的材质,你可以使用一个材质数组。 第一个材质将用于其表面;第二个材质则将用于其挤压出的侧面。 * @return Object */ addExtrude(scene) { const length = 6, width = 4; const shape = new THREE.Shape(); shape.moveTo( 0,0 ); shape.lineTo( 0, width ); shape.lineTo( length, width ); shape.lineTo( length, 0 ); shape.lineTo( 0, 0 ); const extrudeSettings = { steps: 2, depth: 8, bevelEnabled: true, bevelThickness: 1, bevelSize: 1, bevelOffset: 0, bevelSegments: 1 }; const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const mesh = new THREE.Mesh( geometry, material ) ; scene.add( mesh ); return mesh; } /** * 二十面缓冲几何体(IcosahedronGeometry) * 一个用于生成二十面体的类。 * IcosahedronGeometry(radius : Float, detail : Integer) * radius — 二十面体的半径,默认为1。 * detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个二十面体。当这个值大于1的时候,实际上它将变成一个球体。 * @return Object */ addIcosahedron(scene) { const geometry = new THREE.IcosahedronGeometry(10, 0); const material = new THREE.MeshBasicMaterial({ color: 0x049EF4 }); const icosahedron = new THREE.Mesh(geometry, material); scene.add(icosahedron); return icosahedron; } /** * 车削缓冲几何体(LatheGeometry) * 创建具有轴对称性的网格,比如花瓶。车削绕着Y轴来进行旋转。 * @return Object */ addLatheGeometry(scene) { const points = []; for ( let i = 0; i < 10; i ++ ) { points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) ); } const geometry = new THREE.LatheGeometry( points ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const lathe = new THREE.Mesh( geometry, material ); scene.add( lathe ); return lathe; } /** * 八面缓冲几何体(OctahedronGeometry) * 一个用于创建八面体的类。 * OctahedronGeometry(radius : Float, detail : Integer) * radius — 八面体的半径,默认值为1。 * detail — 默认值为0,将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个八面体。 * @return Object */ addOctahedronGeometry(scene) { const geometry = new THREE.OctahedronGeometry( 10, 0); const material = new THREE.MeshBasicMaterial( {color: 0x049EF4, side: THREE.DoubleSide} ); const plane = new THREE.Mesh( geometry, material ); scene.add( plane ); return plane; } /** * 平面缓冲几何体(PlaneGeometry) * 一个用于生成平面几何体的类。 * PlaneGeometry(width : Float, height : Float, widthSegments : Integer, heightSegments : Integer) * width — 平面沿着X轴的宽度。默认值是1。 * height — 平面沿着Y轴的高度。默认值是1。 * widthSegments — (可选)平面的宽度分段数,默认值是1。 * heightSegments — (可选)平面的高度分段数,默认值是1。 * @return Object */ addPlane(scene) { const geometry = new THREE.PlaneGeometry( 10, 10 ); const material = new THREE.MeshBasicMaterial( {color: 0x049EF4, side: THREE.DoubleSide} ); const plane = new THREE.Mesh( geometry, material ); scene.add( plane ); return plane; } /** * 多面缓冲几何体(PolyhedronGeometry) * 多面体在三维空间中具有一些平面的立体图形。这个类将一个顶点数组投射到一个球面上,之后将它们细分为所需的细节级别。 * 这个类由DodecahedronGeometry、IcosahedronGeometry、OctahedronGeometry和TetrahedronGeometry 所使用,以生成它们各自的几何结构。 * PolyhedronGeometry(vertices : Array, indices : Array, radius : Float, detail : Integer) * vertices — 一个顶点Array(数组):[1,1,1, -1,-1,-1, ... ]。 * indices — 一个构成面的索引Array(数组), [0,1,2, 2,3,0, ... ]。 * radius — Float - 最终形状的半径。 * detail — Integer - 将对这个几何体细分多少个级别。细节越多,形状就越平滑。 * @return Object */ addPolyhedronGeometry(scene) { const verticesOfCube = [ -1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1, -1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1, ]; const indicesOfFaces = [ 2,1,0, 0,3,2, 0,4,7, 7,3,0, 0,1,5, 5,4,0, 1,2,6, 6,5,1, 2,3,7, 7,6,2, 4,5,6, 6,7,4 ]; const geometry = new THREE.PolyhedronGeometry( verticesOfCube, indicesOfFaces, 6, 2 ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const plane = new THREE.Mesh( geometry, material ); scene.add( plane ); return plane; } /** * 圆环缓冲几何体(RingGeometry) * 一个用于生成二维圆环几何体的类。 * RingGeometry(innerRadius : Float, outerRadius : Float, thetaSegments : Integer, phiSegments : Integer, thetaStart : Float, thetaLength : Float) * innerRadius — 内部半径,默认值为0.5。 * outerRadius — 外部半径,默认值为1。 * thetaSegments — 圆环的分段数。这个值越大,圆环就越圆。最小值为3,默认值为8。 * phiSegments — 最小值为1,默认值为8。 * thetaStart — 起始角度,默认值为0。 * thetaLength — 圆心角,默认值为Math.PI * 2。 * @return Object */ addRingGeometry(scene) { const geometry = new THREE.RingGeometry( 5, 15, 8 ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4, side: THREE.DoubleSide } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); return mesh; } /** * 形状缓冲几何体(ShapeGeometry) * 从一个或多个路径形状中创建一个单面多边形几何体。 * ShapeGeometry(shapes : Array, curveSegments : Integer) * shapes — 一个单独的shape,或者一个包含形状的Array。Default is a single triangle shape. * curveSegments - Integer - 每一个形状的分段数,默认值为12。 * @return Object */ addShapeGeometry(scene) { const x = 0, y = 0; const heartShape = new THREE.Shape(); heartShape.moveTo( x + 5, y + 5 ); heartShape.bezierCurveTo( x + 5, y + 5, x + 4, y, x, y ); heartShape.bezierCurveTo( x - 6, y, x - 6, y + 7,x - 6, y + 7 ); heartShape.bezierCurveTo( x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19 ); heartShape.bezierCurveTo( x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7 ); heartShape.bezierCurveTo( x + 16, y + 7, x + 16, y, x + 10, y ); heartShape.bezierCurveTo( x + 7, y, x + 5, y + 5, x + 5, y + 5 ); const geometry = new THREE.ShapeGeometry( heartShape ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const mesh = new THREE.Mesh( geometry, material ) ; scene.add( mesh ); return mesh; } /** * 球缓冲几何体(SphereGeometry) * 一个用于生成球体的类。 * SphereGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : * Float, thetaStart : Float, thetaLength : Float) * radius — 球体半径,默认为1。 * widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。 * heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。 * phiStart — 指定水平(经线)起始角度,默认值为0。。 * phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。 * thetaStart — 指定垂直(纬线)起始角度,默认值为0。 * thetaLength — 指定垂直(纬线)扫描角度大小,默认值为 Math.PI。 * 该几何体是通过扫描并计算围绕着Y轴(水平扫描)和X轴(垂直扫描)的顶点来创建的。 因此,不完整的球体(类似球形切片)可以通过为phiStart, * phiLength,thetaStart和thetaLength设置不同的值来创建, 以定义我们开始(或结束)计算这些顶点的起点(或终点)。 * @return Object */ addSphere(scene) { const geometry = new THREE.SphereGeometry( 10, 32, 16 ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const sphere = new THREE.Mesh( geometry, material ); scene.add( sphere ); return sphere; } /** * 四面缓冲几何体(TetrahedronGeometry) * 一个用于生成四面几何体的类。 * TetrahedronGeometry(radius : Float, detail : Integer) * radius — 四面体的半径,默认值为1。 * detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个四面体。 * @return Object */ addTetrahedronGeometry(scene) { const geometry = new THREE.TetrahedronGeometry( 10, 0 ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const sphere = new THREE.Mesh( geometry, material ); scene.add( sphere ); return sphere; } /** * 圆环缓冲几何体(TorusGeometry) * 一个用于生成圆环几何体的类。 * TorusGeometry(radius : Float, tube : Float, radialSegments : Integer, tubularSegments : Integer, arc : Float) * radius - 环面的半径,从环面的中心到管道横截面的中心。默认值是1。 * tube — 管道的半径,默认值为0.4。 * radialSegments — 管道横截面的分段数,默认值为8。 * tubularSegments — 管道的分段数,默认值为6。 * arc — 圆环的圆心角(单位是弧度),默认值为Math.PI * 2。 * @return Object */ addTorus(scene) { const geometry = new THREE.TorusGeometry( 10, 2, 16, 32 ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const torus = new THREE.Mesh( geometry, material ); scene.add( torus ); return torus; } /** * 圆环缓冲扭结几何体(TorusKnotGeometry) * 创建一个圆环扭结,其特殊形状由一对互质的整数,p和q所定义。如果p和q不互质,创建出来的几何体将是一个环面链接。 * TorusKnotGeometry(radius : Float, tube : Float, tubularSegments : Integer, radialSegments : Integer, p : Integer, q : Integer) * radius - 圆环的半径,默认值为1。 * tube — 管道的半径,默认值为0.4。 * tubularSegments — 管道的分段数量,默认值为64。 * radialSegments — 横截面分段数量,默认值为8。 * p — 这个值决定了几何体将绕着其旋转对称轴旋转多少次,默认值是2。 * q — 这个值决定了几何体将绕着其内部圆环旋转多少次,默认值是3。 * @return Object */ addTorusKnotGeometry(scene) { const geometry = new THREE.TorusKnotGeometry( 10, 3, 64, 8 ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const torusKnot = new THREE.Mesh( geometry, material ); scene.add( torusKnot ); return torusKnot; } /** * 管道缓冲几何体(TubeGeometry) * 创建一个沿着三维曲线延伸的管道。 * TubeGeometry(path : Curve, tubularSegments : Integer, radius : Float, radialSegments : Integer, closed : Boolean) * path — Curve - 一个由基类Curve继承而来的3D路径。 Default is a quadratic bezier curve. * tubularSegments — Integer - 组成这一管道的分段数,默认值为64。 * radius — Float - 管道的半径,默认值为1。 * radialSegments — Integer - 管道横截面的分段数目,默认值为8。 * closed — Boolean 管道的两端是否闭合,默认值为false。 * @return Object */ addTubeGeometry(scene) { class CustomSinCurve extends THREE.Curve { constructor( scale = 1 ) { super(); this.scale = scale; } getPoint( t, optionalTarget = new THREE.Vector3() ) { const tx = t * 3 - 1.5; const ty = Math.sin( 2 * Math.PI * t ); const tz = 0; return optionalTarget.set( tx, ty, tz ).multiplyScalar( this.scale ); } } const path = new CustomSinCurve( 10 ); const geometry = new THREE.TubeGeometry( path, 20, 2, 8, false ); const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); return mesh; } /** * 网格几何体(WireframeGeometry) * 这个类可以被用作一个辅助物体,来对一个geometry以线框的形式进行查看。 * WireframeGeometry( geometry : BufferGeometry ) * geometry — 任意几何体对象。 * @return Object */ addWireframeGeometry(scene) { const geometry = new THREE.SphereGeometry( 20, 100, 100 ); const wireframe = new THREE.WireframeGeometry( geometry ); const line = new THREE.LineSegments( wireframe ); line.material.depthTest = false; line.material.opacity = 0.25; line.material.transparent = true; scene.add( line ); return line; } }