sheet.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import { Vec3 } from 'mol-math/linear-algebra';
  8. import { ChunkedArray } from 'mol-data/util';
  9. import { MeshBuilderState } from './mesh-builder';
  10. const tA = Vec3.zero()
  11. const tB = Vec3.zero()
  12. const tV = Vec3.zero()
  13. const horizontalVector = Vec3.zero()
  14. const verticalVector = Vec3.zero()
  15. const normalOffset = Vec3.zero()
  16. const positionVector = Vec3.zero()
  17. const normalVector = Vec3.zero()
  18. const torsionVector = Vec3.zero()
  19. const p1 = Vec3.zero()
  20. const p2 = Vec3.zero()
  21. const p3 = Vec3.zero()
  22. const p4 = Vec3.zero()
  23. export function addSheet(controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
  24. const { vertices, normals, indices } = state
  25. let vertexCount = vertices.elementCount
  26. let offsetLength = 0
  27. if (arrowHeight > 0) {
  28. Vec3.fromArray(tA, controlPoints, 0)
  29. Vec3.fromArray(tB, controlPoints, linearSegments * 3)
  30. offsetLength = arrowHeight / Vec3.magnitude(Vec3.sub(tV, tB, tA))
  31. }
  32. for (let i = 0; i <= linearSegments; ++i) {
  33. const actualHeight = arrowHeight === 0 ? height : arrowHeight * (1 - i / linearSegments);
  34. const i3 = i * 3
  35. Vec3.fromArray(verticalVector, normalVectors, i3)
  36. Vec3.scale(verticalVector, verticalVector, actualHeight);
  37. Vec3.fromArray(horizontalVector, binormalVectors, i3)
  38. Vec3.scale(horizontalVector, horizontalVector, width);
  39. if (arrowHeight > 0) {
  40. Vec3.fromArray(tA, normalVectors, i3)
  41. Vec3.fromArray(tB, binormalVectors, i3)
  42. Vec3.scale(normalOffset, Vec3.cross(normalOffset, tA, tB), offsetLength)
  43. }
  44. Vec3.fromArray(positionVector, controlPoints, i3)
  45. Vec3.fromArray(normalVector, normalVectors, i3)
  46. Vec3.fromArray(torsionVector, binormalVectors, i3)
  47. Vec3.add(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector)
  48. Vec3.copy(tB, normalVector)
  49. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  50. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  51. Vec3.add(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector)
  52. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  53. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  54. // Vec3.add(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector) // reuse tA
  55. Vec3.add(tB, Vec3.negate(tB, torsionVector), normalOffset)
  56. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  57. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  58. Vec3.sub(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector)
  59. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  60. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  61. // Vec3.sub(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector) // reuse tA
  62. Vec3.negate(tB, normalVector)
  63. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  64. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  65. Vec3.sub(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector)
  66. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  67. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  68. // Vec3.sub(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector) // reuse tA
  69. Vec3.add(tB, torsionVector, normalOffset)
  70. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  71. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  72. Vec3.add(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector)
  73. ChunkedArray.add3(vertices, tA[0], tA[1], tA[2])
  74. ChunkedArray.add3(normals, tB[0], tB[1], tB[2])
  75. }
  76. for (let i = 0; i < linearSegments; ++i) {
  77. for (let j = 0; j < 4; j++) {
  78. ChunkedArray.add3(
  79. indices,
  80. vertexCount + i * 8 + 2 * j,
  81. vertexCount + (i + 1) * 8 + 2 * j + 1,
  82. vertexCount + i * 8 + 2 * j + 1
  83. );
  84. ChunkedArray.add3(
  85. indices,
  86. vertexCount + i * 8 + 2 * j,
  87. vertexCount + (i + 1) * 8 + 2 * j,
  88. vertexCount + (i + 1) * 8 + 2 * j + 1
  89. );
  90. }
  91. }
  92. if (startCap) {
  93. const offset = 0
  94. vertexCount = vertices.elementCount
  95. Vec3.fromArray(verticalVector, normalVectors, offset)
  96. Vec3.scale(verticalVector, verticalVector, arrowHeight === 0 ? height : arrowHeight);
  97. Vec3.fromArray(horizontalVector, binormalVectors, offset)
  98. Vec3.scale(horizontalVector, horizontalVector, width);
  99. Vec3.fromArray(positionVector, controlPoints, offset)
  100. Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalVector)
  101. Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalVector)
  102. Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalVector)
  103. Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalVector)
  104. ChunkedArray.add3(vertices, p1[0], p1[1], p1[2])
  105. ChunkedArray.add3(vertices, p2[0], p2[1], p2[2])
  106. ChunkedArray.add3(vertices, p3[0], p3[1], p3[2])
  107. ChunkedArray.add3(vertices, p4[0], p4[1], p4[2])
  108. Vec3.cross(normalVector, horizontalVector, verticalVector)
  109. for (let i = 0; i < 4; ++i) {
  110. ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2])
  111. }
  112. ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount);
  113. ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2);
  114. }
  115. if (endCap && arrowHeight === 0) {
  116. const offset = linearSegments * 3
  117. vertexCount = vertices.elementCount
  118. Vec3.fromArray(verticalVector, normalVectors, offset)
  119. Vec3.scale(verticalVector, verticalVector, height);
  120. Vec3.fromArray(horizontalVector, binormalVectors, offset)
  121. Vec3.scale(horizontalVector, horizontalVector, width);
  122. Vec3.fromArray(positionVector, controlPoints, offset)
  123. Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalVector)
  124. Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalVector)
  125. Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalVector)
  126. Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalVector)
  127. ChunkedArray.add3(vertices, p1[0], p1[1], p1[2])
  128. ChunkedArray.add3(vertices, p2[0], p2[1], p2[2])
  129. ChunkedArray.add3(vertices, p3[0], p3[1], p3[2])
  130. ChunkedArray.add3(vertices, p4[0], p4[1], p4[2])
  131. Vec3.cross(normalVector, horizontalVector, verticalVector)
  132. for (let i = 0; i < 4; ++i) {
  133. ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2])
  134. }
  135. ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount);
  136. ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2);
  137. }
  138. return (linearSegments + 1) * 8 + (startCap ? 4 : 0) + (endCap && arrowHeight === 0 ? 4 : 0)
  139. }