sheet.ts 7.0 KB

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