123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776 |
- import defined from "../Core/defined.js";
- import PixelFormat from "../Core/PixelFormat.js";
- import ContextLimits from "../Renderer/ContextLimits.js";
- import Sampler from "../Renderer/Sampler.js";
- import Texture from "../Renderer/Texture.js";
- import TextureMagnificationFilter from "../Renderer/TextureMagnificationFilter.js";
- import TextureMinificationFilter from "../Renderer/TextureMinificationFilter.js";
- import TextureWrap from "../Renderer/TextureWrap.js";
- import ForEach from "./GltfPipeline/ForEach.js";
- // glTF does not allow an index value of 65535 because this is the primitive
- // restart value in some APIs.
- const MAX_GLTF_UINT16_INDEX = 65534;
- /**
- * Creates face outlines for glTF primitives with the `CESIUM_primitive_outline` extension.
- * @private
- */
- function ModelOutlineLoader() {}
- /**
- * Returns true if the model uses or requires CESIUM_primitive_outline.
- * @private
- */
- ModelOutlineLoader.hasExtension = function (model) {
- return (
- defined(model.extensionsRequired.CESIUM_primitive_outline) ||
- defined(model.extensionsUsed.CESIUM_primitive_outline)
- );
- };
- /**
- * Arranges to outline any primitives with the CESIUM_primitive_outline extension.
- * It is expected that all buffer data is loaded and available in
- * `extras._pipeline.source` before this function is called, and that vertex
- * and index WebGL buffers are not yet created.
- * @private
- */
- ModelOutlineLoader.outlinePrimitives = function (model) {
- if (!ModelOutlineLoader.hasExtension(model)) {
- return;
- }
- const gltf = model.gltf;
- // Assumption: A single bufferView contains a single zero-indexed range of vertices.
- // No trickery with using large accessor byteOffsets to store multiple zero-based
- // ranges of vertices in a single bufferView. Use separate bufferViews for that,
- // you monster.
- // Note that interleaved vertex attributes (e.g. position0, normal0, uv0,
- // position1, normal1, uv1, ...) _are_ supported and should not be confused with
- // the above.
- const vertexNumberingScopes = [];
- ForEach.mesh(gltf, function (mesh, meshId) {
- ForEach.meshPrimitive(mesh, function (primitive, primitiveId) {
- if (!defined(primitive.extensions)) {
- return;
- }
- const outlineData = primitive.extensions.CESIUM_primitive_outline;
- if (!defined(outlineData)) {
- return;
- }
- const vertexNumberingScope = getVertexNumberingScope(model, primitive);
- if (vertexNumberingScope === undefined) {
- return;
- }
- if (vertexNumberingScopes.indexOf(vertexNumberingScope) < 0) {
- vertexNumberingScopes.push(vertexNumberingScope);
- }
- // Add the outline to this primitive
- addOutline(
- model,
- meshId,
- primitiveId,
- outlineData.indices,
- vertexNumberingScope
- );
- });
- });
- // Update all relevant bufferViews to include the duplicate vertices that are
- // needed for outlining.
- for (let i = 0; i < vertexNumberingScopes.length; ++i) {
- updateBufferViewsWithNewVertices(
- model,
- vertexNumberingScopes[i].bufferViews
- );
- }
- // Remove data not referenced by any bufferViews anymore.
- compactBuffers(model);
- };
- ModelOutlineLoader.createTexture = function (model, context) {
- let cache = context.cache.modelOutliningCache;
- if (!defined(cache)) {
- cache = context.cache.modelOutliningCache = {};
- }
- if (defined(cache.outlineTexture)) {
- return cache.outlineTexture;
- }
- const maxSize = Math.min(4096, ContextLimits.maximumTextureSize);
- let size = maxSize;
- const levelZero = createTexture(size);
- const mipLevels = [];
- while (size > 1) {
- size >>= 1;
- mipLevels.push(createTexture(size));
- }
- const texture = new Texture({
- context: context,
- source: {
- arrayBufferView: levelZero,
- mipLevels: mipLevels,
- },
- width: maxSize,
- height: 1,
- pixelFormat: PixelFormat.LUMINANCE,
- sampler: new Sampler({
- wrapS: TextureWrap.CLAMP_TO_EDGE,
- wrapT: TextureWrap.CLAMP_TO_EDGE,
- minificationFilter: TextureMinificationFilter.LINEAR_MIPMAP_LINEAR,
- magnificationFilter: TextureMagnificationFilter.LINEAR,
- }),
- });
- cache.outlineTexture = texture;
- return texture;
- };
- function addOutline(
- model,
- meshId,
- primitiveId,
- edgeIndicesAccessorId,
- vertexNumberingScope
- ) {
- const vertexCopies = vertexNumberingScope.vertexCopies;
- const extraVertices = vertexNumberingScope.extraVertices;
- const outlineCoordinates = vertexNumberingScope.outlineCoordinates;
- const gltf = model.gltf;
- const mesh = gltf.meshes[meshId];
- const primitive = mesh.primitives[primitiveId];
- const accessors = gltf.accessors;
- const bufferViews = gltf.bufferViews;
- // Find the number of vertices in this primitive by looking at
- // the first attribute. Others are required to be the same.
- let numVertices;
- for (const semantic in primitive.attributes) {
- if (primitive.attributes.hasOwnProperty(semantic)) {
- const attributeId = primitive.attributes[semantic];
- const accessor = accessors[attributeId];
- if (defined(accessor)) {
- numVertices = accessor.count;
- break;
- }
- }
- }
- if (!defined(numVertices)) {
- return undefined;
- }
- const triangleIndexAccessorGltf = accessors[primitive.indices];
- const triangleIndexBufferViewGltf =
- bufferViews[triangleIndexAccessorGltf.bufferView];
- const edgeIndexAccessorGltf = accessors[edgeIndicesAccessorId];
- const edgeIndexBufferViewGltf = bufferViews[edgeIndexAccessorGltf.bufferView];
- const loadResources = model._loadResources;
- const triangleIndexBufferView = loadResources.getBuffer(
- triangleIndexBufferViewGltf
- );
- const edgeIndexBufferView = loadResources.getBuffer(edgeIndexBufferViewGltf);
- let triangleIndices =
- triangleIndexAccessorGltf.componentType === 5123
- ? new Uint16Array(
- triangleIndexBufferView.buffer,
- triangleIndexBufferView.byteOffset +
- triangleIndexAccessorGltf.byteOffset,
- triangleIndexAccessorGltf.count
- )
- : new Uint32Array(
- triangleIndexBufferView.buffer,
- triangleIndexBufferView.byteOffset +
- triangleIndexAccessorGltf.byteOffset,
- triangleIndexAccessorGltf.count
- );
- const edgeIndices =
- edgeIndexAccessorGltf.componentType === 5123
- ? new Uint16Array(
- edgeIndexBufferView.buffer,
- edgeIndexBufferView.byteOffset + edgeIndexAccessorGltf.byteOffset,
- edgeIndexAccessorGltf.count
- )
- : new Uint32Array(
- edgeIndexBufferView.buffer,
- edgeIndexBufferView.byteOffset + edgeIndexAccessorGltf.byteOffset,
- edgeIndexAccessorGltf.count
- );
- // Make a hash table for quick lookups of whether an edge exists between two
- // vertices. The hash is a sparse array indexed by
- // `smallerVertexIndex * totalNumberOfVertices + biggerVertexIndex`
- // A value of 1 indicates an edge exists between the two vertex indices; any
- // other value indicates that it does not. We store the
- // `edgeSmallMultipler` - that is, the number of vertices in the equation
- // above - at index 0 for easy access to it later.
- const edgeSmallMultiplier = numVertices;
- const edges = [edgeSmallMultiplier];
- let i;
- for (i = 0; i < edgeIndices.length; i += 2) {
- const a = edgeIndices[i];
- const b = edgeIndices[i + 1];
- const small = Math.min(a, b);
- const big = Math.max(a, b);
- edges[small * edgeSmallMultiplier + big] = 1;
- }
- // For each triangle, adjust vertex data so that the correct edges are outlined.
- for (i = 0; i < triangleIndices.length; i += 3) {
- let i0 = triangleIndices[i];
- let i1 = triangleIndices[i + 1];
- let i2 = triangleIndices[i + 2];
- const all = false; // set this to true to draw a full wireframe.
- const has01 = all || isHighlighted(edges, i0, i1);
- const has12 = all || isHighlighted(edges, i1, i2);
- const has20 = all || isHighlighted(edges, i2, i0);
- let unmatchableVertexIndex = matchAndStoreCoordinates(
- outlineCoordinates,
- i0,
- i1,
- i2,
- has01,
- has12,
- has20
- );
- while (unmatchableVertexIndex >= 0) {
- // Copy the unmatchable index and try again.
- let copy;
- if (unmatchableVertexIndex === i0) {
- copy = vertexCopies[i0];
- } else if (unmatchableVertexIndex === i1) {
- copy = vertexCopies[i1];
- } else {
- copy = vertexCopies[i2];
- }
- if (copy === undefined) {
- copy = numVertices + extraVertices.length;
- let original = unmatchableVertexIndex;
- while (original >= numVertices) {
- original = extraVertices[original - numVertices];
- }
- extraVertices.push(original);
- vertexCopies[unmatchableVertexIndex] = copy;
- }
- if (
- copy > MAX_GLTF_UINT16_INDEX &&
- triangleIndices instanceof Uint16Array
- ) {
- // We outgrew a 16-bit index buffer, switch to 32-bit.
- triangleIndices = new Uint32Array(triangleIndices);
- triangleIndexAccessorGltf.componentType = 5125; // UNSIGNED_INT
- triangleIndexBufferViewGltf.buffer =
- gltf.buffers.push({
- byteLength: triangleIndices.byteLength,
- extras: {
- _pipeline: {
- source: triangleIndices.buffer,
- },
- },
- }) - 1;
- triangleIndexBufferViewGltf.byteLength = triangleIndices.byteLength;
- triangleIndexBufferViewGltf.byteOffset = 0;
- model._loadResources.buffers[
- triangleIndexBufferViewGltf.buffer
- ] = new Uint8Array(
- triangleIndices.buffer,
- 0,
- triangleIndices.byteLength
- );
- // The index componentType is also squirreled away in ModelLoadResources.
- // Hackily update it, or else we'll end up creating the wrong type
- // of index buffer later.
- loadResources.indexBuffersToCreate._array.forEach(function (toCreate) {
- if (toCreate.id === triangleIndexAccessorGltf.bufferView) {
- toCreate.componentType = triangleIndexAccessorGltf.componentType;
- }
- });
- }
- if (unmatchableVertexIndex === i0) {
- i0 = copy;
- triangleIndices[i] = copy;
- } else if (unmatchableVertexIndex === i1) {
- i1 = copy;
- triangleIndices[i + 1] = copy;
- } else {
- i2 = copy;
- triangleIndices[i + 2] = copy;
- }
- if (defined(triangleIndexAccessorGltf.max)) {
- triangleIndexAccessorGltf.max[0] = Math.max(
- triangleIndexAccessorGltf.max[0],
- copy
- );
- }
- unmatchableVertexIndex = matchAndStoreCoordinates(
- outlineCoordinates,
- i0,
- i1,
- i2,
- has01,
- has12,
- has20
- );
- }
- }
- }
- // Each vertex has three coordinates, a, b, and c.
- // a is the coordinate that applies to edge 2-0 for the vertex.
- // b is the coordinate that applies to edge 0-1 for the vertex.
- // c is the coordinate that applies to edge 1-2 for the vertex.
- // A single triangle with all edges highlighted:
- //
- // | a | b | c |
- // | 1 | 1 | 0 |
- // 0
- // / \
- // / \
- // edge 0-1 / \ edge 2-0
- // / \
- // / \
- // | a | b | c | 1-----------2 | a | b | c |
- // | 0 | 1 | 1 | edge 1-2 | 1 | 0 | 1 |
- //
- // There are 6 possible orderings of coordinates a, b, and c:
- // 0 - abc
- // 1 - acb
- // 2 - bac
- // 3 - bca
- // 4 - cab
- // 5 - cba
- // All vertices must use the _same ordering_ for the edges to be rendered
- // correctly. So we compute a bitmask for each vertex, where the bit at
- // each position indicates whether that ordering works (i.e. doesn't
- // conflict with already-assigned coordinates) for that vertex.
- // Then we can find an ordering that works for all three vertices with a
- // bitwise AND.
- function computeOrderMask(outlineCoordinates, vertexIndex, a, b, c) {
- const startIndex = vertexIndex * 3;
- const first = outlineCoordinates[startIndex];
- const second = outlineCoordinates[startIndex + 1];
- const third = outlineCoordinates[startIndex + 2];
- if (first === undefined) {
- // If one coordinate is undefined, they all are, and all orderings are fine.
- return 63; // 0b111111;
- }
- return (
- ((first === a && second === b && third === c) << 0) +
- ((first === a && second === c && third === b) << 1) +
- ((first === b && second === a && third === c) << 2) +
- ((first === b && second === c && third === a) << 3) +
- ((first === c && second === a && third === b) << 4) +
- ((first === c && second === b && third === a) << 5)
- );
- }
- // popcount for integers 0-63, inclusive.
- // i.e. how many 1s are in the binary representation of the integer.
- function popcount0to63(value) {
- return (
- (value & 1) +
- ((value >> 1) & 1) +
- ((value >> 2) & 1) +
- ((value >> 3) & 1) +
- ((value >> 4) & 1) +
- ((value >> 5) & 1)
- );
- }
- function matchAndStoreCoordinates(
- outlineCoordinates,
- i0,
- i1,
- i2,
- has01,
- has12,
- has20
- ) {
- const a0 = has20 ? 1.0 : 0.0;
- const b0 = has01 ? 1.0 : 0.0;
- const c0 = 0.0;
- const i0Mask = computeOrderMask(outlineCoordinates, i0, a0, b0, c0);
- if (i0Mask === 0) {
- return i0;
- }
- const a1 = 0.0;
- const b1 = has01 ? 1.0 : 0.0;
- const c1 = has12 ? 1.0 : 0.0;
- const i1Mask = computeOrderMask(outlineCoordinates, i1, a1, b1, c1);
- if (i1Mask === 0) {
- return i1;
- }
- const a2 = has20 ? 1.0 : 0.0;
- const b2 = 0.0;
- const c2 = has12 ? 1.0 : 0.0;
- const i2Mask = computeOrderMask(outlineCoordinates, i2, a2, b2, c2);
- if (i2Mask === 0) {
- return i2;
- }
- const workingOrders = i0Mask & i1Mask & i2Mask;
- let a, b, c;
- if (workingOrders & (1 << 0)) {
- // 0 - abc
- a = 0;
- b = 1;
- c = 2;
- } else if (workingOrders & (1 << 1)) {
- // 1 - acb
- a = 0;
- c = 1;
- b = 2;
- } else if (workingOrders & (1 << 2)) {
- // 2 - bac
- b = 0;
- a = 1;
- c = 2;
- } else if (workingOrders & (1 << 3)) {
- // 3 - bca
- b = 0;
- c = 1;
- a = 2;
- } else if (workingOrders & (1 << 4)) {
- // 4 - cab
- c = 0;
- a = 1;
- b = 2;
- } else if (workingOrders & (1 << 5)) {
- // 5 - cba
- c = 0;
- b = 1;
- a = 2;
- } else {
- // No ordering works.
- // Report the most constrained vertex as unmatched so we copy that one.
- const i0Popcount = popcount0to63(i0Mask);
- const i1Popcount = popcount0to63(i1Mask);
- const i2Popcount = popcount0to63(i2Mask);
- if (i0Popcount < i1Popcount && i0Popcount < i2Popcount) {
- return i0;
- } else if (i1Popcount < i2Popcount) {
- return i1;
- }
- return i2;
- }
- const i0Start = i0 * 3;
- outlineCoordinates[i0Start + a] = a0;
- outlineCoordinates[i0Start + b] = b0;
- outlineCoordinates[i0Start + c] = c0;
- const i1Start = i1 * 3;
- outlineCoordinates[i1Start + a] = a1;
- outlineCoordinates[i1Start + b] = b1;
- outlineCoordinates[i1Start + c] = c1;
- const i2Start = i2 * 3;
- outlineCoordinates[i2Start + a] = a2;
- outlineCoordinates[i2Start + b] = b2;
- outlineCoordinates[i2Start + c] = c2;
- return -1;
- }
- function isHighlighted(edges, i0, i1) {
- const edgeSmallMultiplier = edges[0];
- const index = Math.min(i0, i1) * edgeSmallMultiplier + Math.max(i0, i1);
- // If i0 and i1 are both 0, then our index will be 0 and we'll end up
- // accessing the edgeSmallMultiplier that we've sneakily squirreled away
- // in index 0. But it makes no sense to have an edge between vertex 0 and
- // itself, so for any edgeSmallMultiplier other than 1 we'll return the
- // correct answer: false. If edgeSmallMultiplier is 1, that means there is
- // only a single vertex, so no danger of forming a meaningful triangle
- // with that.
- return edges[index] === 1;
- }
- function createTexture(size) {
- const texture = new Uint8Array(size);
- texture[size - 1] = 192;
- if (size === 8) {
- texture[size - 1] = 96;
- } else if (size === 4) {
- texture[size - 1] = 48;
- } else if (size === 2) {
- texture[size - 1] = 24;
- } else if (size === 1) {
- texture[size - 1] = 12;
- }
- return texture;
- }
- function updateBufferViewsWithNewVertices(model, bufferViews) {
- const gltf = model.gltf;
- const loadResources = model._loadResources;
- let i, j;
- for (i = 0; i < bufferViews.length; ++i) {
- const bufferView = bufferViews[i];
- const vertexNumberingScope =
- bufferView.extras._pipeline.vertexNumberingScope;
- // Let the temporary data be garbage collected.
- bufferView.extras._pipeline.vertexNumberingScope = undefined;
- const newVertices = vertexNumberingScope.extraVertices;
- const sourceData = loadResources.getBuffer(bufferView);
- const byteStride = bufferView.byteStride || 4;
- const newVerticesLength = newVertices.length;
- const destData = new Uint8Array(
- sourceData.byteLength + newVerticesLength * byteStride
- );
- // Copy the original vertices
- destData.set(sourceData);
- // Copy the vertices added for outlining
- for (j = 0; j < newVerticesLength; ++j) {
- const sourceIndex = newVertices[j] * byteStride;
- const destIndex = sourceData.length + j * byteStride;
- for (let k = 0; k < byteStride; ++k) {
- destData[destIndex + k] = destData[sourceIndex + k];
- }
- }
- // This bufferView is an independent buffer now. Update the model accordingly.
- bufferView.byteOffset = 0;
- bufferView.byteLength = destData.byteLength;
- const bufferId =
- gltf.buffers.push({
- byteLength: destData.byteLength,
- extras: {
- _pipeline: {
- source: destData.buffer,
- },
- },
- }) - 1;
- bufferView.buffer = bufferId;
- loadResources.buffers[bufferId] = destData;
- // Update the accessors to reflect the added vertices.
- const accessors = vertexNumberingScope.accessors;
- for (j = 0; j < accessors.length; ++j) {
- const accessorId = accessors[j];
- gltf.accessors[accessorId].count += newVerticesLength;
- }
- if (!vertexNumberingScope.createdOutlines) {
- // Create the buffers, views, and accessors for the outline texture coordinates.
- const outlineCoordinates = vertexNumberingScope.outlineCoordinates;
- const outlineCoordinateBuffer = new Float32Array(outlineCoordinates);
- const bufferIndex =
- model.gltf.buffers.push({
- byteLength: outlineCoordinateBuffer.byteLength,
- extras: {
- _pipeline: {
- source: outlineCoordinateBuffer.buffer,
- },
- },
- }) - 1;
- loadResources.buffers[bufferIndex] = new Uint8Array(
- outlineCoordinateBuffer.buffer,
- 0,
- outlineCoordinateBuffer.byteLength
- );
- const bufferViewIndex =
- model.gltf.bufferViews.push({
- buffer: bufferIndex,
- byteLength: outlineCoordinateBuffer.byteLength,
- byteOffset: 0,
- byteStride: 3 * Float32Array.BYTES_PER_ELEMENT,
- target: 34962,
- }) - 1;
- const accessorIndex =
- model.gltf.accessors.push({
- bufferView: bufferViewIndex,
- byteOffset: 0,
- componentType: 5126,
- count: outlineCoordinateBuffer.length / 3,
- type: "VEC3",
- min: [0.0, 0.0, 0.0],
- max: [1.0, 1.0, 1.0],
- }) - 1;
- const primitives = vertexNumberingScope.primitives;
- for (j = 0; j < primitives.length; ++j) {
- primitives[j].attributes._OUTLINE_COORDINATES = accessorIndex;
- }
- loadResources.vertexBuffersToCreate.enqueue(bufferViewIndex);
- vertexNumberingScope.createdOutlines = true;
- }
- }
- }
- function compactBuffers(model) {
- const gltf = model.gltf;
- const loadResources = model._loadResources;
- let i;
- for (i = 0; i < gltf.buffers.length; ++i) {
- const buffer = gltf.buffers[i];
- const bufferViewsUsingThisBuffer = gltf.bufferViews.filter(
- usesBuffer.bind(undefined, i)
- );
- const newLength = bufferViewsUsingThisBuffer.reduce(function (
- previous,
- current
- ) {
- return previous + current.byteLength;
- },
- 0);
- if (newLength === buffer.byteLength) {
- continue;
- }
- const newBuffer = new Uint8Array(newLength);
- let offset = 0;
- for (let j = 0; j < bufferViewsUsingThisBuffer.length; ++j) {
- const bufferView = bufferViewsUsingThisBuffer[j];
- const sourceData = loadResources.getBuffer(bufferView);
- newBuffer.set(sourceData, offset);
- bufferView.byteOffset = offset;
- offset += sourceData.byteLength;
- }
- loadResources.buffers[i] = newBuffer;
- buffer.extras._pipeline.source = newBuffer.buffer;
- buffer.byteLength = newLength;
- }
- }
- function usesBuffer(bufferId, bufferView) {
- return bufferView.buffer === bufferId;
- }
- function getVertexNumberingScope(model, primitive) {
- const attributes = primitive.attributes;
- if (attributes === undefined) {
- return undefined;
- }
- const gltf = model.gltf;
- let vertexNumberingScope;
- // Initialize common details for all bufferViews used by this primitive's vertices.
- // All bufferViews used by this primitive must use a common vertex numbering scheme.
- for (const semantic in attributes) {
- if (!attributes.hasOwnProperty(semantic)) {
- continue;
- }
- const accessorId = attributes[semantic];
- const accessor = gltf.accessors[accessorId];
- const bufferViewId = accessor.bufferView;
- const bufferView = gltf.bufferViews[bufferViewId];
- if (!defined(bufferView.extras)) {
- bufferView.extras = {};
- }
- if (!defined(bufferView.extras._pipeline)) {
- bufferView.extras._pipeline = {};
- }
- if (!defined(bufferView.extras._pipeline.vertexNumberingScope)) {
- bufferView.extras._pipeline.vertexNumberingScope = vertexNumberingScope || {
- // Each element in this array is:
- // a) undefined, if the vertex at this index has no copies
- // b) the index of the copy.
- vertexCopies: [],
- // Extra vertices appended after the ones originally included in the model.
- // Each element is the index of the vertex that this one is a copy of.
- extraVertices: [],
- // The texture coordinates used for outlining, three floats per vertex.
- outlineCoordinates: [],
- // The IDs of accessors that use this vertex numbering.
- accessors: [],
- // The IDs of bufferViews that use this vertex numbering.
- bufferViews: [],
- // The primitives that use this vertex numbering.
- primitives: [],
- // True if the buffer for the outlines has already been created.
- createdOutlines: false,
- };
- } else if (
- vertexNumberingScope !== undefined &&
- bufferView.extras._pipeline.vertexNumberingScope !== vertexNumberingScope
- ) {
- // Conflicting vertex numbering, let's give up.
- return undefined;
- }
- vertexNumberingScope = bufferView.extras._pipeline.vertexNumberingScope;
- if (vertexNumberingScope.bufferViews.indexOf(bufferView) < 0) {
- vertexNumberingScope.bufferViews.push(bufferView);
- }
- if (vertexNumberingScope.accessors.indexOf(accessorId) < 0) {
- vertexNumberingScope.accessors.push(accessorId);
- }
- }
- vertexNumberingScope.primitives.push(primitive);
- return vertexNumberingScope;
- }
- export default ModelOutlineLoader;
|