import { uid } from '@luma.gl/core'; import { Geometry } from "../geometry/geometry.js"; // Primitives inspired by TDL http://code.google.com/p/webglsamples/, // copyright 2011 Google Inc. new BSD License // (http://www.opensource.org/licenses/bsd-license.php). export class SphereGeometry extends Geometry { constructor(props = {}) { const { id = uid('sphere-geometry') } = props; const { indices, attributes } = tesselateSphere(props); super({ ...props, id, topology: 'triangle-list', indices, attributes: { ...attributes, ...props.attributes } }); } } /* eslint-disable max-statements, complexity */ function tesselateSphere(props) { const { nlat = 10, nlong = 10 } = props; const startLat = 0; const endLat = Math.PI; const latRange = endLat - startLat; const startLong = 0; const endLong = 2 * Math.PI; const longRange = endLong - startLong; const numVertices = (nlat + 1) * (nlong + 1); const radius = (n1, n2, n3, u, v) => props.radius || 1; const positions = new Float32Array(numVertices * 3); const normals = new Float32Array(numVertices * 3); const texCoords = new Float32Array(numVertices * 2); const IndexType = numVertices > 0xffff ? Uint32Array : Uint16Array; const indices = new IndexType(nlat * nlong * 6); // Create positions, normals and texCoords for (let y = 0; y <= nlat; y++) { for (let x = 0; x <= nlong; x++) { const u = x / nlong; const v = y / nlat; const index = x + y * (nlong + 1); const i2 = index * 2; const i3 = index * 3; const theta = longRange * u; const phi = latRange * v; const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); const sinPhi = Math.sin(phi); const cosPhi = Math.cos(phi); const ux = cosTheta * sinPhi; const uy = cosPhi; const uz = sinTheta * sinPhi; const r = radius(ux, uy, uz, u, v); positions[i3 + 0] = r * ux; positions[i3 + 1] = r * uy; positions[i3 + 2] = r * uz; normals[i3 + 0] = ux; normals[i3 + 1] = uy; normals[i3 + 2] = uz; texCoords[i2 + 0] = u; texCoords[i2 + 1] = 1 - v; } } // Create indices const numVertsAround = nlong + 1; for (let x = 0; x < nlong; x++) { for (let y = 0; y < nlat; y++) { const index = (x * nlat + y) * 6; indices[index + 0] = y * numVertsAround + x; indices[index + 1] = y * numVertsAround + x + 1; indices[index + 2] = (y + 1) * numVertsAround + x; indices[index + 3] = (y + 1) * numVertsAround + x; indices[index + 4] = y * numVertsAround + x + 1; indices[index + 5] = (y + 1) * numVertsAround + x + 1; } } return { indices: { size: 1, value: indices }, attributes: { POSITION: { size: 3, value: positions }, NORMAL: { size: 3, value: normals }, TEXCOORD_0: { size: 2, value: texCoords } } }; }