UNPKG

threepipe

Version:

A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.

133 lines (111 loc) 4.92 kB
import {Vector3} from 'three' import {AGeometryGenerator} from '../AGeometryGenerator' export interface BoxGeometryGeneratorParams { width: number, height: number, depth: number, widthSegments: number, heightSegments: number, depthSegments: number } export class BoxGeometryGenerator extends AGeometryGenerator<BoxGeometryGeneratorParams> { constructor(type = 'box', defaultParams?: Partial<BoxGeometryGeneratorParams>) { super(type) if (defaultParams) Object.assign(this.defaultParams, defaultParams) } defaultParams: BoxGeometryGeneratorParams = { width: 1, height: 1, depth: 1, widthSegments: 1, heightSegments: 1, depthSegments: 1, } // helper variables protected _buildPlane(state: any, u: 'x'|'y'|'z', v: 'x'|'y'|'z', w: 'x'|'y'|'z', udir: number, vdir: number, width: number, height: number, depth: number, gridX: number, gridY: number, materialIndex: number) { const {indices, vertices, normals, uvs, numberOfVertices, groupStart, groups} = state const segmentWidth = width / gridX const segmentHeight = height / gridY const widthHalf = width / 2 const heightHalf = height / 2 const depthHalf = depth / 2 const gridX1 = gridX + 1 const gridY1 = gridY + 1 let vertexCounter = 0 let groupCount = 0 const vector = new Vector3() // generate vertices, normals and uvs for (let iy = 0; iy < gridY1; iy++) { const y = iy * segmentHeight - heightHalf for (let ix = 0; ix < gridX1; ix++) { const x = ix * segmentWidth - widthHalf // set values to correct vector component vector[ u ] = x * udir vector[ v ] = y * vdir vector[ w ] = depthHalf // now apply vector to vertex buffer vertices.push(vector.x, vector.y, vector.z) // set values to correct vector component vector[ u ] = 0 vector[ v ] = 0 vector[ w ] = depth > 0 ? 1 : -1 // now apply vector to normal buffer normals.push(vector.x, vector.y, vector.z) // uvs uvs.push(ix / gridX) uvs.push(1 - iy / gridY) // counters vertexCounter += 1 } } // indices // 1. you need three indices to draw a single face // 2. a single segment consists of two faces // 3. so we need to generate six (2*3) indices per segment for (let iy = 0; iy < gridY; iy++) { for (let ix = 0; ix < gridX; ix++) { const a = numberOfVertices + ix + gridX1 * iy const b = numberOfVertices + ix + gridX1 * (iy + 1) const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1) const d = numberOfVertices + (ix + 1) + gridX1 * iy // faces indices.push(a, b, d) indices.push(b, c, d) // increase counter groupCount += 6 } } // add a group to the geometry. this will ensure multi material support groups.push({start: groupStart, count: groupCount, materialIndex}) // calculate new start value for groups state.groupStart += groupCount // update total number of vertices state.numberOfVertices += vertexCounter } protected _generateData(params: BoxGeometryGeneratorParams) { const {width, height, depth} = params let {widthSegments, heightSegments, depthSegments} = params // segments widthSegments = Math.floor(widthSegments) heightSegments = Math.floor(heightSegments) depthSegments = Math.floor(depthSegments) // buffers const state = { indices: [], vertices: [], normals: [], uvs: [], numberOfVertices: 0, groupStart: 0, groups: [], } // build each side of the box geometry this._buildPlane(state, 'z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0) // px this._buildPlane(state, 'z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1) // nx this._buildPlane(state, 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2) // py this._buildPlane(state, 'x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3) // ny this._buildPlane(state, 'x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4) // pz this._buildPlane(state, 'x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5) // nz return state } }