UNPKG

gpu-curtains

Version:

gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.

92 lines (89 loc) 3.05 kB
import { IndexedGeometry } from '../../core/geometries/IndexedGeometry.mjs'; import { Vec3 } from '../../math/Vec3.mjs'; class SphereGeometry extends IndexedGeometry { constructor({ topology, instancesCount = 1, vertexBuffers = [], mapBuffersAtCreation = true, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI } = {}) { super({ verticesOrder: "ccw", topology, instancesCount, vertexBuffers, mapBuffersAtCreation }); this.type = "SphereGeometry"; widthSegments = Math.max(3, Math.floor(widthSegments)); heightSegments = Math.max(2, Math.floor(heightSegments)); const radius = 1; const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI); let index = 0; const grid = []; const vertex = new Vec3(); const normal = new Vec3(); const indices = []; const vertices = []; const normals = []; const uvs = []; for (let iy = 0; iy <= heightSegments; iy++) { const verticesRow = []; const v = iy / heightSegments; let uOffset = 0; if (iy === 0 && thetaStart === 0) { uOffset = 0.5 / widthSegments; } else if (iy === heightSegments && thetaEnd === Math.PI) { uOffset = -0.5 / widthSegments; } for (let ix = 0; ix <= widthSegments; ix++) { const u = ix / widthSegments; vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); vertex.y = radius * Math.cos(thetaStart + v * thetaLength); vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); vertices.push(vertex.x, vertex.y, vertex.z); normal.copy(vertex).normalize(); normals.push(normal.x, normal.y, normal.z); uvs.push(u + uOffset, v); verticesRow.push(index++); } grid.push(verticesRow); } for (let iy = 0; iy < heightSegments; iy++) { for (let ix = 0; ix < widthSegments; ix++) { const a = grid[iy][ix + 1]; const b = grid[iy][ix]; const c = grid[iy + 1][ix]; const d = grid[iy + 1][ix + 1]; if (iy !== 0 || thetaStart > 0) indices.push(a, b, d); if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d); } } this.setAttribute({ name: "position", type: "vec3f", bufferFormat: "float32x3", size: 3, array: new Float32Array(vertices) }); this.setAttribute({ name: "uv", type: "vec2f", bufferFormat: "float32x2", size: 2, array: new Float32Array(uvs) }); this.setAttribute({ name: "normal", type: "vec3f", bufferFormat: "float32x3", size: 3, array: new Float32Array(normals) }); this.setIndexBuffer({ array: this.useUint16IndexArray ? new Uint16Array(indices) : new Uint32Array(indices), bufferFormat: this.useUint16IndexArray ? "uint16" : "uint32" }); } } export { SphereGeometry };