primitive.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /**
  2. * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Vec3, Mat4, Mat3 } from '../../mol-math/linear-algebra';
  7. import { getNormalMatrix } from '../util';
  8. import { NumberArray } from '../../mol-util/type-helpers';
  9. export interface Primitive {
  10. vertices: ArrayLike<number>
  11. normals: ArrayLike<number>
  12. indices: ArrayLike<number>
  13. }
  14. const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero()
  15. /** Create primitive with face normals from vertices and indices */
  16. export function createPrimitive(vertices: ArrayLike<number>, indices: ArrayLike<number>): Primitive {
  17. const count = indices.length
  18. const builder = PrimitiveBuilder(count / 3)
  19. for (let i = 0; i < count; i += 3) {
  20. Vec3.fromArray(a, vertices, indices[i] * 3)
  21. Vec3.fromArray(b, vertices, indices[i + 1] * 3)
  22. Vec3.fromArray(c, vertices, indices[i + 2] * 3)
  23. builder.add(a, b, c)
  24. }
  25. return builder.getPrimitive()
  26. }
  27. export function copyPrimitive(primitive: Primitive): Primitive {
  28. return {
  29. vertices: new Float32Array(primitive.vertices),
  30. normals: new Float32Array(primitive.normals),
  31. indices: new Uint32Array(primitive.indices)
  32. }
  33. }
  34. export interface PrimitiveBuilder {
  35. add(a: Vec3, b: Vec3, c: Vec3): void
  36. getPrimitive(): Primitive
  37. }
  38. const vn = Vec3.zero()
  39. /** Builder to create primitive with face normals */
  40. export function PrimitiveBuilder(triangleCount: number): PrimitiveBuilder {
  41. const vertices = new Float32Array(triangleCount * 3 * 3)
  42. const normals = new Float32Array(triangleCount * 3 * 3)
  43. const indices = new Uint32Array(triangleCount * 3)
  44. let offset = 0
  45. return {
  46. add: (a: Vec3, b: Vec3, c: Vec3) => {
  47. Vec3.toArray(a, vertices, offset)
  48. Vec3.toArray(b, vertices, offset + 3)
  49. Vec3.toArray(c, vertices, offset + 6)
  50. Vec3.triangleNormal(vn, a, b, c)
  51. for (let j = 0; j < 3; ++j) {
  52. Vec3.toArray(vn, normals, offset + 3 * j)
  53. indices[offset / 3 + j] = offset / 3 + j
  54. }
  55. offset += 9
  56. },
  57. getPrimitive: () => ({ vertices, normals, indices })
  58. }
  59. }
  60. const tmpV = Vec3.zero()
  61. const tmpMat3 = Mat3.zero()
  62. /** Transform primitive in-place */
  63. export function transformPrimitive(primitive: Primitive, t: Mat4) {
  64. const { vertices, normals } = primitive
  65. const n = getNormalMatrix(tmpMat3, t)
  66. for (let i = 0, il = vertices.length; i < il; i += 3) {
  67. // position
  68. Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, vertices, i), t)
  69. Vec3.toArray(tmpV, vertices as NumberArray, i)
  70. // normal
  71. Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, normals, i), n)
  72. Vec3.toArray(tmpV, normals as NumberArray, i)
  73. }
  74. return primitive
  75. }