import defined from "./defined.js"; import IndexDatatype from "./IndexDatatype.js"; import PrimitiveType from "./PrimitiveType.js"; /** * Functions for generating indices for model wireframes. The indices are * outputted as typed arrays, which can then be put into buffers for rendering. * * @namespace WireframeIndexGenerator * @private */ const WireframeIndexGenerator = {}; function createWireframeFromTriangles(vertexCount) { const wireframeIndices = IndexDatatype.createTypedArray( vertexCount, vertexCount * 2 ); const length = vertexCount; let index = 0; for (let i = 0; i < length; i += 3) { wireframeIndices[index++] = i; wireframeIndices[index++] = i + 1; wireframeIndices[index++] = i + 1; wireframeIndices[index++] = i + 2; wireframeIndices[index++] = i + 2; wireframeIndices[index++] = i; } return wireframeIndices; } function createWireframeFromTriangleIndices(vertexCount, originalIndices) { const originalIndicesCount = originalIndices.length; const wireframeIndices = IndexDatatype.createTypedArray( vertexCount, originalIndicesCount * 2 ); let index = 0; for (let i = 0; i < originalIndicesCount; i += 3) { const point0 = originalIndices[i]; const point1 = originalIndices[i + 1]; const point2 = originalIndices[i + 2]; wireframeIndices[index++] = point0; wireframeIndices[index++] = point1; wireframeIndices[index++] = point1; wireframeIndices[index++] = point2; wireframeIndices[index++] = point2; wireframeIndices[index++] = point0; } return wireframeIndices; } function createWireframeFromTriangleStrip(vertexCount) { const numberOfTriangles = vertexCount - 2; const wireframeIndicesCount = 2 + numberOfTriangles * 4; const wireframeIndices = IndexDatatype.createTypedArray( vertexCount, wireframeIndicesCount ); let index = 0; // Handle the first edge wireframeIndices[index++] = 0; wireframeIndices[index++] = 1; // Add two edges for every triangle in the strip for (let i = 0; i < numberOfTriangles; i++) { wireframeIndices[index++] = i + 1; wireframeIndices[index++] = i + 2; wireframeIndices[index++] = i + 2; wireframeIndices[index++] = i; } return wireframeIndices; } function createWireframeFromTriangleStripIndices(vertexCount, originalIndices) { const originalIndicesCount = originalIndices.length; const numberOfTriangles = originalIndicesCount - 2; const wireframeIndicesCount = 2 + numberOfTriangles * 4; const wireframeIndices = IndexDatatype.createTypedArray( vertexCount, wireframeIndicesCount ); let index = 0; // Handle the first edge wireframeIndices[index++] = originalIndices[0]; wireframeIndices[index++] = originalIndices[1]; // Add two edges for every triangle in the strip for (let i = 0; i < numberOfTriangles; i++) { const point0 = originalIndices[i]; const point1 = originalIndices[i + 1]; const point2 = originalIndices[i + 2]; wireframeIndices[index++] = point1; wireframeIndices[index++] = point2; wireframeIndices[index++] = point2; wireframeIndices[index++] = point0; } return wireframeIndices; } function createWireframeFromTriangleFan(vertexCount) { const numberOfTriangles = vertexCount - 2; const wireframeIndicesCount = 2 + numberOfTriangles * 4; const wireframeIndices = IndexDatatype.createTypedArray( vertexCount, wireframeIndicesCount ); let index = 0; // Handle the first edge wireframeIndices[index++] = 0; wireframeIndices[index++] = 1; // Add two edges for every triangle in the fan for (let i = 0; i < numberOfTriangles; i++) { wireframeIndices[index++] = i + 1; wireframeIndices[index++] = i + 2; wireframeIndices[index++] = i + 2; wireframeIndices[index++] = 0; } return wireframeIndices; } function createWireframeFromTriangleFanIndices(vertexCount, originalIndices) { const originalIndicesCount = originalIndices.length; const numberOfTriangles = originalIndicesCount - 2; const wireframeIndicesCount = 2 + numberOfTriangles * 4; const wireframeIndices = IndexDatatype.createTypedArray( vertexCount, wireframeIndicesCount ); let index = 0; // Handle the first edge const firstPoint = originalIndices[0]; wireframeIndices[index++] = firstPoint; wireframeIndices[index++] = originalIndices[1]; // Add two edges for every triangle in the fan for (let i = 0; i < numberOfTriangles; i++) { const point1 = originalIndices[i + 1]; const point2 = originalIndices[i + 2]; wireframeIndices[index++] = point1; wireframeIndices[index++] = point2; wireframeIndices[index++] = point2; wireframeIndices[index++] = firstPoint; } return wireframeIndices; } /** * Generates a wireframe index buffer for a primitive, either by reindexing the existing indices * or creating them from scratch if the model had none. * * @param {PrimitiveType} primitiveType The primitive type. * @param {Number} vertexCount The number of vertices in the primitive. * @param {Uint8Array|Uint16Array|Uint32Array} [originalIndices] A typed array containing the original indices of the primitive. * * @return {Uint16Array|Uint32Array} A typed array with the wireframe indices, or undefined if the primitive type does not use triangles. * * @private */ WireframeIndexGenerator.createWireframeIndices = function ( primitiveType, vertexCount, originalIndices ) { const hasOriginalIndices = defined(originalIndices); if (primitiveType === PrimitiveType.TRIANGLES) { return hasOriginalIndices ? createWireframeFromTriangleIndices(vertexCount, originalIndices) : createWireframeFromTriangles(vertexCount); } if (primitiveType === PrimitiveType.TRIANGLE_STRIP) { return hasOriginalIndices ? createWireframeFromTriangleStripIndices(vertexCount, originalIndices) : createWireframeFromTriangleStrip(vertexCount); } if (primitiveType === PrimitiveType.TRIANGLE_FAN) { return hasOriginalIndices ? createWireframeFromTriangleFanIndices(vertexCount, originalIndices) : createWireframeFromTriangleFan(vertexCount); } return undefined; }; /** * Gets the number of indices in the wireframe index buffer of a primitive type. * * @param {PrimitiveType} primitiveType The primitive type. * @param {Number} originalCount The original number of vertices or indices in the primitive. * @return {Number} The number of indices in the primitive's wireframe. * * @private */ WireframeIndexGenerator.getWireframeIndicesCount = function ( primitiveType, originalCount ) { // For TRIANGLES, the wireframe takes every triangle (i.e. three of the original // indices) and turns it into lines. Each triangle has three lines, and each line // requires two indices, so the final count is twice the original. if (primitiveType === PrimitiveType.TRIANGLES) { return originalCount * 2; } // For TRIANGLE_STRIP and TRIANGLE_FAN, the number of triangles in the primitive // is equal to the total number of vertices minus two. This is because after the // first edge is specified by the first two indices, every point afterwards // contributes two more edges with two of the previous points, forming a new triangle. // Each of these edges requires two indices, so each triangle in the primitive // results in four indices in addition to the first two. if ( primitiveType === PrimitiveType.TRIANGLE_STRIP || primitiveType === PrimitiveType.TRIANGLE_FAN ) { const numberOfTriangles = originalCount - 2; return 2 + numberOfTriangles * 4; } return originalCount; }; export default WireframeIndexGenerator;