mesh-builder.ts 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { ValueCell } from 'mol-util/value-cell'
  7. import { Vec3, Mat4 } from 'mol-math/linear-algebra';
  8. import { ChunkedArray } from 'mol-data/util';
  9. import Box, { BoxProps } from '../primitive/box';
  10. import Icosahedron, { IcosahedronProps } from '../primitive/icosahedron';
  11. import { Mesh } from './mesh';
  12. type ElementId = { id?: number }
  13. export interface MeshBuilder {
  14. add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): number
  15. addBox(t: Mat4, props?: BoxProps & ElementId): number
  16. addIcosahedron(t: Mat4, props?: IcosahedronProps & ElementId): number
  17. getMesh(): Mesh
  18. }
  19. const tmpV = Vec3.zero()
  20. // TODO cache primitives based on props
  21. export namespace MeshBuilder {
  22. export function create(initialCount = 2048, chunkSize = 1024): MeshBuilder {
  23. const vertices = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount);
  24. const normals = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount);
  25. const indices = ChunkedArray.create(Uint32Array, 3, chunkSize * 3, initialCount * 3);
  26. // const offsets = ChunkedArray.create<number>(n => new Uint32Array(n), 1, 1000);
  27. // const elementIds = ChunkedArray.create(Uint32Array, 1, chunkSize, initialCount);
  28. ChunkedArray.compact(indices, true)
  29. const add = (t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices: Uint32Array) => {
  30. const { elementCount, elementSize } = vertices
  31. for (let i = 0, il = _vertices.length; i < il; i += 3) {
  32. // position
  33. Vec3.fromArray(tmpV, _vertices, i)
  34. Vec3.transformMat4(tmpV, tmpV, t)
  35. ChunkedArray.add3(vertices, tmpV[0], tmpV[1], tmpV[2]);
  36. // normal
  37. Vec3.fromArray(tmpV, _normals, i)
  38. // Vec3.transformDirection(tmpV, tmpV, n) // TODO
  39. ChunkedArray.add3(normals, tmpV[0], tmpV[1], tmpV[2]);
  40. }
  41. for (let i = 0, il = _indices.length; i < il; i += 3) {
  42. ChunkedArray.add3(indices, _indices[i] + elementCount, _indices[i + 1] + elementCount, _indices[i + 2] + elementCount);
  43. }
  44. return elementCount * elementSize
  45. }
  46. return {
  47. add,
  48. addBox: (t: Mat4, props?: BoxProps & ElementId) => {
  49. const box = Box(props)
  50. return add(t, box.vertices, box.normals, box.indices)
  51. },
  52. addIcosahedron: (t: Mat4, props?: IcosahedronProps & ElementId) => {
  53. const icosahedron = Icosahedron(props)
  54. return add(t, icosahedron.vertices, icosahedron.normals, icosahedron.indices)
  55. },
  56. getMesh: () => {
  57. return {
  58. vertexCount: vertices.elementCount,
  59. triangleCount: indices.elementCount,
  60. vertexBuffer: ValueCell.create(ChunkedArray.compact(vertices, true) as Float32Array),
  61. indexBuffer: ValueCell.create(ChunkedArray.compact(indices, true) as Uint32Array),
  62. normalBuffer: ValueCell.create(ChunkedArray.compact(normals, true) as Float32Array),
  63. normalsComputed: true,
  64. }
  65. }
  66. }
  67. }
  68. }