sheet.ts 7.4 KB

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