WireframeIndexGenerator.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import defined from "./defined.js";
  2. import IndexDatatype from "./IndexDatatype.js";
  3. import PrimitiveType from "./PrimitiveType.js";
  4. /**
  5. * Functions for generating indices for model wireframes. The indices are
  6. * outputted as typed arrays, which can then be put into buffers for rendering.
  7. *
  8. * @namespace WireframeIndexGenerator
  9. * @private
  10. */
  11. const WireframeIndexGenerator = {};
  12. function createWireframeFromTriangles(vertexCount) {
  13. const wireframeIndices = IndexDatatype.createTypedArray(
  14. vertexCount,
  15. vertexCount * 2
  16. );
  17. const length = vertexCount;
  18. let index = 0;
  19. for (let i = 0; i < length; i += 3) {
  20. wireframeIndices[index++] = i;
  21. wireframeIndices[index++] = i + 1;
  22. wireframeIndices[index++] = i + 1;
  23. wireframeIndices[index++] = i + 2;
  24. wireframeIndices[index++] = i + 2;
  25. wireframeIndices[index++] = i;
  26. }
  27. return wireframeIndices;
  28. }
  29. function createWireframeFromTriangleIndices(vertexCount, originalIndices) {
  30. const originalIndicesCount = originalIndices.length;
  31. const wireframeIndices = IndexDatatype.createTypedArray(
  32. vertexCount,
  33. originalIndicesCount * 2
  34. );
  35. let index = 0;
  36. for (let i = 0; i < originalIndicesCount; i += 3) {
  37. const point0 = originalIndices[i];
  38. const point1 = originalIndices[i + 1];
  39. const point2 = originalIndices[i + 2];
  40. wireframeIndices[index++] = point0;
  41. wireframeIndices[index++] = point1;
  42. wireframeIndices[index++] = point1;
  43. wireframeIndices[index++] = point2;
  44. wireframeIndices[index++] = point2;
  45. wireframeIndices[index++] = point0;
  46. }
  47. return wireframeIndices;
  48. }
  49. function createWireframeFromTriangleStrip(vertexCount) {
  50. const numberOfTriangles = vertexCount - 2;
  51. const wireframeIndicesCount = 2 + numberOfTriangles * 4;
  52. const wireframeIndices = IndexDatatype.createTypedArray(
  53. vertexCount,
  54. wireframeIndicesCount
  55. );
  56. let index = 0;
  57. // Handle the first edge
  58. wireframeIndices[index++] = 0;
  59. wireframeIndices[index++] = 1;
  60. // Add two edges for every triangle in the strip
  61. for (let i = 0; i < numberOfTriangles; i++) {
  62. wireframeIndices[index++] = i + 1;
  63. wireframeIndices[index++] = i + 2;
  64. wireframeIndices[index++] = i + 2;
  65. wireframeIndices[index++] = i;
  66. }
  67. return wireframeIndices;
  68. }
  69. function createWireframeFromTriangleStripIndices(vertexCount, originalIndices) {
  70. const originalIndicesCount = originalIndices.length;
  71. const numberOfTriangles = originalIndicesCount - 2;
  72. const wireframeIndicesCount = 2 + numberOfTriangles * 4;
  73. const wireframeIndices = IndexDatatype.createTypedArray(
  74. vertexCount,
  75. wireframeIndicesCount
  76. );
  77. let index = 0;
  78. // Handle the first edge
  79. wireframeIndices[index++] = originalIndices[0];
  80. wireframeIndices[index++] = originalIndices[1];
  81. // Add two edges for every triangle in the strip
  82. for (let i = 0; i < numberOfTriangles; i++) {
  83. const point0 = originalIndices[i];
  84. const point1 = originalIndices[i + 1];
  85. const point2 = originalIndices[i + 2];
  86. wireframeIndices[index++] = point1;
  87. wireframeIndices[index++] = point2;
  88. wireframeIndices[index++] = point2;
  89. wireframeIndices[index++] = point0;
  90. }
  91. return wireframeIndices;
  92. }
  93. function createWireframeFromTriangleFan(vertexCount) {
  94. const numberOfTriangles = vertexCount - 2;
  95. const wireframeIndicesCount = 2 + numberOfTriangles * 4;
  96. const wireframeIndices = IndexDatatype.createTypedArray(
  97. vertexCount,
  98. wireframeIndicesCount
  99. );
  100. let index = 0;
  101. // Handle the first edge
  102. wireframeIndices[index++] = 0;
  103. wireframeIndices[index++] = 1;
  104. // Add two edges for every triangle in the fan
  105. for (let i = 0; i < numberOfTriangles; i++) {
  106. wireframeIndices[index++] = i + 1;
  107. wireframeIndices[index++] = i + 2;
  108. wireframeIndices[index++] = i + 2;
  109. wireframeIndices[index++] = 0;
  110. }
  111. return wireframeIndices;
  112. }
  113. function createWireframeFromTriangleFanIndices(vertexCount, originalIndices) {
  114. const originalIndicesCount = originalIndices.length;
  115. const numberOfTriangles = originalIndicesCount - 2;
  116. const wireframeIndicesCount = 2 + numberOfTriangles * 4;
  117. const wireframeIndices = IndexDatatype.createTypedArray(
  118. vertexCount,
  119. wireframeIndicesCount
  120. );
  121. let index = 0;
  122. // Handle the first edge
  123. const firstPoint = originalIndices[0];
  124. wireframeIndices[index++] = firstPoint;
  125. wireframeIndices[index++] = originalIndices[1];
  126. // Add two edges for every triangle in the fan
  127. for (let i = 0; i < numberOfTriangles; i++) {
  128. const point1 = originalIndices[i + 1];
  129. const point2 = originalIndices[i + 2];
  130. wireframeIndices[index++] = point1;
  131. wireframeIndices[index++] = point2;
  132. wireframeIndices[index++] = point2;
  133. wireframeIndices[index++] = firstPoint;
  134. }
  135. return wireframeIndices;
  136. }
  137. /**
  138. * Generates a wireframe index buffer for a primitive, either by reindexing the existing indices
  139. * or creating them from scratch if the model had none.
  140. *
  141. * @param {PrimitiveType} primitiveType The primitive type.
  142. * @param {Number} vertexCount The number of vertices in the primitive.
  143. * @param {Uint8Array|Uint16Array|Uint32Array} [originalIndices] A typed array containing the original indices of the primitive.
  144. *
  145. * @return {Uint16Array|Uint32Array} A typed array with the wireframe indices, or undefined if the primitive type does not use triangles.
  146. *
  147. * @private
  148. */
  149. WireframeIndexGenerator.createWireframeIndices = function (
  150. primitiveType,
  151. vertexCount,
  152. originalIndices
  153. ) {
  154. const hasOriginalIndices = defined(originalIndices);
  155. if (primitiveType === PrimitiveType.TRIANGLES) {
  156. return hasOriginalIndices
  157. ? createWireframeFromTriangleIndices(vertexCount, originalIndices)
  158. : createWireframeFromTriangles(vertexCount);
  159. }
  160. if (primitiveType === PrimitiveType.TRIANGLE_STRIP) {
  161. return hasOriginalIndices
  162. ? createWireframeFromTriangleStripIndices(vertexCount, originalIndices)
  163. : createWireframeFromTriangleStrip(vertexCount);
  164. }
  165. if (primitiveType === PrimitiveType.TRIANGLE_FAN) {
  166. return hasOriginalIndices
  167. ? createWireframeFromTriangleFanIndices(vertexCount, originalIndices)
  168. : createWireframeFromTriangleFan(vertexCount);
  169. }
  170. return undefined;
  171. };
  172. /**
  173. * Gets the number of indices in the wireframe index buffer of a primitive type.
  174. *
  175. * @param {PrimitiveType} primitiveType The primitive type.
  176. * @param {Number} originalCount The original number of vertices or indices in the primitive.
  177. * @return {Number} The number of indices in the primitive's wireframe.
  178. *
  179. * @private
  180. */
  181. WireframeIndexGenerator.getWireframeIndicesCount = function (
  182. primitiveType,
  183. originalCount
  184. ) {
  185. // For TRIANGLES, the wireframe takes every triangle (i.e. three of the original
  186. // indices) and turns it into lines. Each triangle has three lines, and each line
  187. // requires two indices, so the final count is twice the original.
  188. if (primitiveType === PrimitiveType.TRIANGLES) {
  189. return originalCount * 2;
  190. }
  191. // For TRIANGLE_STRIP and TRIANGLE_FAN, the number of triangles in the primitive
  192. // is equal to the total number of vertices minus two. This is because after the
  193. // first edge is specified by the first two indices, every point afterwards
  194. // contributes two more edges with two of the previous points, forming a new triangle.
  195. // Each of these edges requires two indices, so each triangle in the primitive
  196. // results in four indices in addition to the first two.
  197. if (
  198. primitiveType === PrimitiveType.TRIANGLE_STRIP ||
  199. primitiveType === PrimitiveType.TRIANGLE_FAN
  200. ) {
  201. const numberOfTriangles = originalCount - 2;
  202. return 2 + numberOfTriangles * 4;
  203. }
  204. return originalCount;
  205. };
  206. export default WireframeIndexGenerator;