123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775 |
- 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 "../ThirdParty/GltfPipeline/ForEach.js";
- var MAX_GLTF_UINT16_INDEX = 65534;
- function ModelOutlineLoader() {}
- ModelOutlineLoader.hasExtension = function (model) {
- return (
- defined(model.extensionsRequired.CESIUM_primitive_outline) ||
- defined(model.extensionsUsed.CESIUM_primitive_outline)
- );
- };
- ModelOutlineLoader.outlinePrimitives = function (model) {
- if (!ModelOutlineLoader.hasExtension(model)) {
- return;
- }
- var gltf = model.gltf;
-
-
-
-
-
-
-
- var vertexNumberingScopes = [];
- ForEach.mesh(gltf, function (mesh, meshId) {
- ForEach.meshPrimitive(mesh, function (primitive, primitiveId) {
- if (!defined(primitive.extensions)) {
- return;
- }
- var outlineData = primitive.extensions.CESIUM_primitive_outline;
- if (!defined(outlineData)) {
- return;
- }
- var vertexNumberingScope = getVertexNumberingScope(model, primitive);
- if (vertexNumberingScope === undefined) {
- return;
- }
- if (vertexNumberingScopes.indexOf(vertexNumberingScope) < 0) {
- vertexNumberingScopes.push(vertexNumberingScope);
- }
-
- addOutline(
- model,
- meshId,
- primitiveId,
- outlineData.indices,
- vertexNumberingScope
- );
- });
- });
-
-
- for (var i = 0; i < vertexNumberingScopes.length; ++i) {
- updateBufferViewsWithNewVertices(
- model,
- vertexNumberingScopes[i].bufferViews
- );
- }
-
- compactBuffers(model);
- };
- ModelOutlineLoader.createTexture = function (model, context) {
- var cache = context.cache.modelOutliningCache;
- if (!defined(cache)) {
- cache = context.cache.modelOutliningCache = {};
- }
- if (defined(cache.outlineTexture)) {
- return cache.outlineTexture;
- }
- var maxSize = Math.min(4096, ContextLimits.maximumTextureSize);
- var size = maxSize;
- var levelZero = createTexture(size);
- var mipLevels = [];
- while (size > 1) {
- size >>= 1;
- mipLevels.push(createTexture(size));
- }
- var 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
- ) {
- var vertexCopies = vertexNumberingScope.vertexCopies;
- var extraVertices = vertexNumberingScope.extraVertices;
- var outlineCoordinates = vertexNumberingScope.outlineCoordinates;
- var gltf = model.gltf;
- var mesh = gltf.meshes[meshId];
- var primitive = mesh.primitives[primitiveId];
- var accessors = gltf.accessors;
- var bufferViews = gltf.bufferViews;
-
-
- var numVertices;
- for (var semantic in primitive.attributes) {
- if (primitive.attributes.hasOwnProperty(semantic)) {
- var attributeId = primitive.attributes[semantic];
- var accessor = accessors[attributeId];
- if (defined(accessor)) {
- numVertices = accessor.count;
- break;
- }
- }
- }
- if (!defined(numVertices)) {
- return undefined;
- }
- var triangleIndexAccessorGltf = accessors[primitive.indices];
- var triangleIndexBufferViewGltf =
- bufferViews[triangleIndexAccessorGltf.bufferView];
- var edgeIndexAccessorGltf = accessors[edgeIndicesAccessorId];
- var edgeIndexBufferViewGltf = bufferViews[edgeIndexAccessorGltf.bufferView];
- var loadResources = model._loadResources;
- var triangleIndexBufferView = loadResources.getBuffer(
- triangleIndexBufferViewGltf
- );
- var edgeIndexBufferView = loadResources.getBuffer(edgeIndexBufferViewGltf);
- var triangleIndices =
- triangleIndexAccessorGltf.componentType === 5123
- ? new Uint16Array(
- triangleIndexBufferView.buffer,
- triangleIndexBufferView.byteOffset +
- triangleIndexAccessorGltf.byteOffset,
- triangleIndexAccessorGltf.count
- )
- : new Uint32Array(
- triangleIndexBufferView.buffer,
- triangleIndexBufferView.byteOffset +
- triangleIndexAccessorGltf.byteOffset,
- triangleIndexAccessorGltf.count
- );
- var edgeIndices =
- edgeIndexAccessorGltf.componentType === 5123
- ? new Uint16Array(
- edgeIndexBufferView.buffer,
- edgeIndexBufferView.byteOffset + edgeIndexAccessorGltf.byteOffset,
- edgeIndexAccessorGltf.count
- )
- : new Uint32Array(
- edgeIndexBufferView.buffer,
- edgeIndexBufferView.byteOffset + edgeIndexAccessorGltf.byteOffset,
- edgeIndexAccessorGltf.count
- );
-
-
-
-
-
-
-
- var edgeSmallMultiplier = numVertices;
- var edges = [edgeSmallMultiplier];
- var i;
- for (i = 0; i < edgeIndices.length; i += 2) {
- var a = edgeIndices[i];
- var b = edgeIndices[i + 1];
- var small = Math.min(a, b);
- var big = Math.max(a, b);
- edges[small * edgeSmallMultiplier + big] = 1;
- }
-
- for (i = 0; i < triangleIndices.length; i += 3) {
- var i0 = triangleIndices[i];
- var i1 = triangleIndices[i + 1];
- var i2 = triangleIndices[i + 2];
- var all = false;
- var has01 = all || isHighlighted(edges, i0, i1);
- var has12 = all || isHighlighted(edges, i1, i2);
- var has20 = all || isHighlighted(edges, i2, i0);
- var unmatchableVertexIndex = matchAndStoreCoordinates(
- outlineCoordinates,
- i0,
- i1,
- i2,
- has01,
- has12,
- has20
- );
- while (unmatchableVertexIndex >= 0) {
-
- var 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;
- var original = unmatchableVertexIndex;
- while (original >= numVertices) {
- original = extraVertices[original - numVertices];
- }
- extraVertices.push(original);
- vertexCopies[unmatchableVertexIndex] = copy;
- }
- if (
- copy > MAX_GLTF_UINT16_INDEX &&
- triangleIndices instanceof Uint16Array
- ) {
-
- triangleIndices = new Uint32Array(triangleIndices);
- triangleIndexAccessorGltf.componentType = 5125;
- 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
- );
-
-
-
- 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
- );
- }
- }
- }
- function computeOrderMask(outlineCoordinates, vertexIndex, a, b, c) {
- var startIndex = vertexIndex * 3;
- var first = outlineCoordinates[startIndex];
- var second = outlineCoordinates[startIndex + 1];
- var third = outlineCoordinates[startIndex + 2];
- if (first === undefined) {
-
- return 63;
- }
- 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)
- );
- }
- 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
- ) {
- var a0 = has20 ? 1.0 : 0.0;
- var b0 = has01 ? 1.0 : 0.0;
- var c0 = 0.0;
- var i0Mask = computeOrderMask(outlineCoordinates, i0, a0, b0, c0);
- if (i0Mask === 0) {
- return i0;
- }
- var a1 = 0.0;
- var b1 = has01 ? 1.0 : 0.0;
- var c1 = has12 ? 1.0 : 0.0;
- var i1Mask = computeOrderMask(outlineCoordinates, i1, a1, b1, c1);
- if (i1Mask === 0) {
- return i1;
- }
- var a2 = has20 ? 1.0 : 0.0;
- var b2 = 0.0;
- var c2 = has12 ? 1.0 : 0.0;
- var i2Mask = computeOrderMask(outlineCoordinates, i2, a2, b2, c2);
- if (i2Mask === 0) {
- return i2;
- }
- var workingOrders = i0Mask & i1Mask & i2Mask;
- var a, b, c;
- if (workingOrders & (1 << 0)) {
-
- a = 0;
- b = 1;
- c = 2;
- } else if (workingOrders & (1 << 1)) {
-
- a = 0;
- c = 1;
- b = 2;
- } else if (workingOrders & (1 << 2)) {
-
- b = 0;
- a = 1;
- c = 2;
- } else if (workingOrders & (1 << 3)) {
-
- b = 0;
- c = 1;
- a = 2;
- } else if (workingOrders & (1 << 4)) {
-
- c = 0;
- a = 1;
- b = 2;
- } else if (workingOrders & (1 << 5)) {
-
- c = 0;
- b = 1;
- a = 2;
- } else {
-
-
- var i0Popcount = popcount0to63(i0Mask);
- var i1Popcount = popcount0to63(i1Mask);
- var i2Popcount = popcount0to63(i2Mask);
- if (i0Popcount < i1Popcount && i0Popcount < i2Popcount) {
- return i0;
- } else if (i1Popcount < i2Popcount) {
- return i1;
- }
- return i2;
- }
- var i0Start = i0 * 3;
- outlineCoordinates[i0Start + a] = a0;
- outlineCoordinates[i0Start + b] = b0;
- outlineCoordinates[i0Start + c] = c0;
- var i1Start = i1 * 3;
- outlineCoordinates[i1Start + a] = a1;
- outlineCoordinates[i1Start + b] = b1;
- outlineCoordinates[i1Start + c] = c1;
- var i2Start = i2 * 3;
- outlineCoordinates[i2Start + a] = a2;
- outlineCoordinates[i2Start + b] = b2;
- outlineCoordinates[i2Start + c] = c2;
- return -1;
- }
- function isHighlighted(edges, i0, i1) {
- var edgeSmallMultiplier = edges[0];
- var index = Math.min(i0, i1) * edgeSmallMultiplier + Math.max(i0, i1);
-
-
-
-
-
-
-
- return edges[index] === 1;
- }
- function createTexture(size) {
- var 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) {
- var gltf = model.gltf;
- var loadResources = model._loadResources;
- var i, j;
- for (i = 0; i < bufferViews.length; ++i) {
- var bufferView = bufferViews[i];
- var vertexNumberingScope = bufferView.extras._pipeline.vertexNumberingScope;
-
- bufferView.extras._pipeline.vertexNumberingScope = undefined;
- var newVertices = vertexNumberingScope.extraVertices;
- var sourceData = loadResources.getBuffer(bufferView);
- var byteStride = bufferView.byteStride || 4;
- var newVerticesLength = newVertices.length;
- var destData = new Uint8Array(
- sourceData.byteLength + newVerticesLength * byteStride
- );
-
- destData.set(sourceData);
-
- for (j = 0; j < newVerticesLength; ++j) {
- var sourceIndex = newVertices[j] * byteStride;
- var destIndex = sourceData.length + j * byteStride;
- for (var k = 0; k < byteStride; ++k) {
- destData[destIndex + k] = destData[sourceIndex + k];
- }
- }
-
- bufferView.byteOffset = 0;
- bufferView.byteLength = destData.byteLength;
- var bufferId =
- gltf.buffers.push({
- byteLength: destData.byteLength,
- extras: {
- _pipeline: {
- source: destData.buffer,
- },
- },
- }) - 1;
- bufferView.buffer = bufferId;
- loadResources.buffers[bufferId] = destData;
-
- var accessors = vertexNumberingScope.accessors;
- for (j = 0; j < accessors.length; ++j) {
- var accessorId = accessors[j];
- gltf.accessors[accessorId].count += newVerticesLength;
- }
- if (!vertexNumberingScope.createdOutlines) {
-
- var outlineCoordinates = vertexNumberingScope.outlineCoordinates;
- var outlineCoordinateBuffer = new Float32Array(outlineCoordinates);
- var bufferIndex =
- model.gltf.buffers.push({
- byteLength: outlineCoordinateBuffer.byteLength,
- extras: {
- _pipeline: {
- source: outlineCoordinateBuffer.buffer,
- },
- },
- }) - 1;
- loadResources.buffers[bufferIndex] = new Uint8Array(
- outlineCoordinateBuffer.buffer,
- 0,
- outlineCoordinateBuffer.byteLength
- );
- var bufferViewIndex =
- model.gltf.bufferViews.push({
- buffer: bufferIndex,
- byteLength: outlineCoordinateBuffer.byteLength,
- byteOffset: 0,
- byteStride: 3 * Float32Array.BYTES_PER_ELEMENT,
- target: 34962,
- }) - 1;
- var 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;
- var 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) {
- var gltf = model.gltf;
- var loadResources = model._loadResources;
- var i;
- for (i = 0; i < gltf.buffers.length; ++i) {
- var buffer = gltf.buffers[i];
- var bufferViewsUsingThisBuffer = gltf.bufferViews.filter(
- usesBuffer.bind(undefined, i)
- );
- var newLength = bufferViewsUsingThisBuffer.reduce(function (
- previous,
- current
- ) {
- return previous + current.byteLength;
- },
- 0);
- if (newLength === buffer.byteLength) {
- continue;
- }
- var newBuffer = new Uint8Array(newLength);
- var offset = 0;
- for (var j = 0; j < bufferViewsUsingThisBuffer.length; ++j) {
- var bufferView = bufferViewsUsingThisBuffer[j];
- var 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) {
- var attributes = primitive.attributes;
- if (attributes === undefined) {
- return undefined;
- }
- var gltf = model.gltf;
- var vertexNumberingScope;
-
-
- for (var semantic in attributes) {
- if (!attributes.hasOwnProperty(semantic)) {
- continue;
- }
- var accessorId = attributes[semantic];
- var accessor = gltf.accessors[accessorId];
- var bufferViewId = accessor.bufferView;
- var 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 || {
-
-
-
- vertexCopies: [],
-
-
- extraVertices: [],
-
- outlineCoordinates: [],
-
- accessors: [],
-
- bufferViews: [],
-
- primitives: [],
-
- createdOutlines: false,
- };
- } else if (
- vertexNumberingScope !== undefined &&
- bufferView.extras._pipeline.vertexNumberingScope !== vertexNumberingScope
- ) {
-
- 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;
|