1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354 |
- import BoundingSphere from "../Core/BoundingSphere.js";
- import Cartesian2 from "../Core/Cartesian2.js";
- import Cartesian3 from "../Core/Cartesian3.js";
- import Cartesian4 from "../Core/Cartesian4.js";
- import clone from "../Core/clone.js";
- import defined from "../Core/defined.js";
- import Matrix2 from "../Core/Matrix2.js";
- import Matrix3 from "../Core/Matrix3.js";
- import Matrix4 from "../Core/Matrix4.js";
- import Quaternion from "../Core/Quaternion.js";
- import RuntimeError from "../Core/RuntimeError.js";
- import WebGLConstants from "../Core/WebGLConstants.js";
- import ShaderSource from "../Renderer/ShaderSource.js";
- import addToArray from "../ThirdParty/GltfPipeline/addToArray.js";
- import ForEach from "../ThirdParty/GltfPipeline/ForEach.js";
- import hasExtension from "../ThirdParty/GltfPipeline/hasExtension.js";
- import AttributeType from "./AttributeType.js";
- import Axis from "./Axis.js";
- /**
- * @private
- */
- var ModelUtility = {};
- /**
- * Updates the model's forward axis if the model is not a 2.0 model.
- *
- * @param {Object} model The model to update.
- */
- ModelUtility.updateForwardAxis = function (model) {
- var cachedSourceVersion = model.gltf.extras.sourceVersion;
- if (
- (defined(cachedSourceVersion) && cachedSourceVersion !== "2.0") ||
- ModelUtility.getAssetVersion(model.gltf) !== "2.0"
- ) {
- model._gltfForwardAxis = Axis.X;
- }
- };
- /**
- * Gets the string representing the glTF asset version.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {String} The glTF asset version string.
- */
- ModelUtility.getAssetVersion = function (gltf) {
- // In glTF 1.0 it was valid to omit the version number.
- if (!defined(gltf.asset) || !defined(gltf.asset.version)) {
- return "1.0";
- }
- return gltf.asset.version;
- };
- /**
- * Splits primitive materials with values incompatible for generating techniques.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The glTF asset with modified materials.
- */
- ModelUtility.splitIncompatibleMaterials = function (gltf) {
- var accessors = gltf.accessors;
- var materials = gltf.materials;
- var primitiveInfoByMaterial = {};
- ForEach.mesh(gltf, function (mesh) {
- ForEach.meshPrimitive(mesh, function (primitive) {
- var materialIndex = primitive.material;
- var material = materials[materialIndex];
- var jointAccessorId = primitive.attributes.JOINTS_0;
- var componentType;
- var accessorType;
- if (defined(jointAccessorId)) {
- var jointAccessor = accessors[jointAccessorId];
- componentType = jointAccessor.componentType;
- accessorType = jointAccessor.type;
- }
- var isSkinned = defined(jointAccessorId) && accessorType === "VEC4";
- var hasVertexColors = defined(primitive.attributes.COLOR_0);
- var hasMorphTargets = defined(primitive.targets);
- var hasNormals = defined(primitive.attributes.NORMAL);
- var hasTangents = defined(primitive.attributes.TANGENT);
- var hasTexCoords = defined(primitive.attributes.TEXCOORD_0);
- var hasTexCoord1 =
- hasTexCoords && defined(primitive.attributes.TEXCOORD_1);
- var hasOutline =
- defined(primitive.extensions) &&
- defined(primitive.extensions.CESIUM_primitive_outline);
- var primitiveInfo = primitiveInfoByMaterial[materialIndex];
- if (!defined(primitiveInfo)) {
- primitiveInfoByMaterial[materialIndex] = {
- skinning: {
- skinned: isSkinned,
- componentType: componentType,
- },
- hasVertexColors: hasVertexColors,
- hasMorphTargets: hasMorphTargets,
- hasNormals: hasNormals,
- hasTangents: hasTangents,
- hasTexCoords: hasTexCoords,
- hasTexCoord1: hasTexCoord1,
- hasOutline: hasOutline,
- };
- } else if (
- primitiveInfo.skinning.skinned !== isSkinned ||
- primitiveInfo.hasVertexColors !== hasVertexColors ||
- primitiveInfo.hasMorphTargets !== hasMorphTargets ||
- primitiveInfo.hasNormals !== hasNormals ||
- primitiveInfo.hasTangents !== hasTangents ||
- primitiveInfo.hasTexCoords !== hasTexCoords ||
- primitiveInfo.hasTexCoord1 !== hasTexCoord1 ||
- primitiveInfo.hasOutline !== hasOutline
- ) {
- // This primitive uses the same material as another one that either:
- // * Isn't skinned
- // * Uses a different type to store joints and weights
- // * Doesn't have vertex colors, morph targets, normals, tangents, or texCoords
- // * Doesn't have a CESIUM_primitive_outline extension.
- var clonedMaterial = clone(material, true);
- // Split this off as a separate material
- materialIndex = addToArray(materials, clonedMaterial);
- primitive.material = materialIndex;
- primitiveInfoByMaterial[materialIndex] = {
- skinning: {
- skinned: isSkinned,
- componentType: componentType,
- },
- hasVertexColors: hasVertexColors,
- hasMorphTargets: hasMorphTargets,
- hasNormals: hasNormals,
- hasTangents: hasTangents,
- hasTexCoords: hasTexCoords,
- hasTexCoord1: hasTexCoord1,
- hasOutline: hasOutline,
- };
- }
- });
- });
- return primitiveInfoByMaterial;
- };
- ModelUtility.getShaderVariable = function (type) {
- if (type === "SCALAR") {
- return "float";
- }
- return type.toLowerCase();
- };
- ModelUtility.ModelState = {
- NEEDS_LOAD: 0,
- LOADING: 1,
- LOADED: 2, // Renderable, but textures can still be pending when incrementallyLoadTextures is true.
- FAILED: 3,
- };
- ModelUtility.getFailedLoadFunction = function (model, type, path) {
- return function (error) {
- model._state = ModelUtility.ModelState.FAILED;
- var message = "Failed to load " + type + ": " + path;
- if (defined(error)) {
- message += "\n" + error.message;
- }
- model._readyPromise.reject(new RuntimeError(message));
- };
- };
- ModelUtility.parseBuffers = function (model, bufferLoad) {
- var loadResources = model._loadResources;
- ForEach.buffer(model.gltf, function (buffer, bufferViewId) {
- if (defined(buffer.extras._pipeline.source)) {
- loadResources.buffers[bufferViewId] = buffer.extras._pipeline.source;
- } else if (defined(bufferLoad)) {
- var bufferResource = model._resource.getDerivedResource({
- url: buffer.uri,
- });
- ++loadResources.pendingBufferLoads;
- bufferResource
- .fetchArrayBuffer()
- .then(bufferLoad(model, bufferViewId))
- .otherwise(
- ModelUtility.getFailedLoadFunction(
- model,
- "buffer",
- bufferResource.url
- )
- );
- }
- });
- };
- var aMinScratch = new Cartesian3();
- var aMaxScratch = new Cartesian3();
- ModelUtility.computeBoundingSphere = function (model) {
- var gltf = model.gltf;
- var gltfNodes = gltf.nodes;
- var gltfMeshes = gltf.meshes;
- var rootNodes = gltf.scenes[gltf.scene].nodes;
- var rootNodesLength = rootNodes.length;
- var nodeStack = [];
- var min = new Cartesian3(
- Number.MAX_VALUE,
- Number.MAX_VALUE,
- Number.MAX_VALUE
- );
- var max = new Cartesian3(
- -Number.MAX_VALUE,
- -Number.MAX_VALUE,
- -Number.MAX_VALUE
- );
- for (var i = 0; i < rootNodesLength; ++i) {
- var n = gltfNodes[rootNodes[i]];
- n._transformToRoot = ModelUtility.getTransform(n);
- nodeStack.push(n);
- while (nodeStack.length > 0) {
- n = nodeStack.pop();
- var transformToRoot = n._transformToRoot;
- var meshId = n.mesh;
- if (defined(meshId)) {
- var mesh = gltfMeshes[meshId];
- var primitives = mesh.primitives;
- var primitivesLength = primitives.length;
- for (var m = 0; m < primitivesLength; ++m) {
- var positionAccessor = primitives[m].attributes.POSITION;
- if (defined(positionAccessor)) {
- var minMax = ModelUtility.getAccessorMinMax(gltf, positionAccessor);
- if (defined(minMax.min) && defined(minMax.max)) {
- var aMin = Cartesian3.fromArray(minMax.min, 0, aMinScratch);
- var aMax = Cartesian3.fromArray(minMax.max, 0, aMaxScratch);
- Matrix4.multiplyByPoint(transformToRoot, aMin, aMin);
- Matrix4.multiplyByPoint(transformToRoot, aMax, aMax);
- Cartesian3.minimumByComponent(min, aMin, min);
- Cartesian3.maximumByComponent(max, aMax, max);
- }
- }
- }
- }
- var children = n.children;
- if (defined(children)) {
- var childrenLength = children.length;
- for (var k = 0; k < childrenLength; ++k) {
- var child = gltfNodes[children[k]];
- child._transformToRoot = ModelUtility.getTransform(child);
- Matrix4.multiplyTransformation(
- transformToRoot,
- child._transformToRoot,
- child._transformToRoot
- );
- nodeStack.push(child);
- }
- }
- delete n._transformToRoot;
- }
- }
- var boundingSphere = BoundingSphere.fromCornerPoints(min, max);
- if (model._forwardAxis === Axis.Z) {
- // glTF 2.0 has a Z-forward convention that must be adapted here to X-forward.
- BoundingSphere.transformWithoutScale(
- boundingSphere,
- Axis.Z_UP_TO_X_UP,
- boundingSphere
- );
- }
- if (model._upAxis === Axis.Y) {
- BoundingSphere.transformWithoutScale(
- boundingSphere,
- Axis.Y_UP_TO_Z_UP,
- boundingSphere
- );
- } else if (model._upAxis === Axis.X) {
- BoundingSphere.transformWithoutScale(
- boundingSphere,
- Axis.X_UP_TO_Z_UP,
- boundingSphere
- );
- }
- return boundingSphere;
- };
- function techniqueAttributeForSemantic(technique, semantic) {
- return ForEach.techniqueAttribute(technique, function (
- attribute,
- attributeName
- ) {
- if (attribute.semantic === semantic) {
- return attributeName;
- }
- });
- }
- function ensureSemanticExistenceForPrimitive(gltf, primitive) {
- var accessors = gltf.accessors;
- var materials = gltf.materials;
- var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;
- var techniques = techniquesWebgl.techniques;
- var programs = techniquesWebgl.programs;
- var shaders = techniquesWebgl.shaders;
- var targets = primitive.targets;
- var attributes = primitive.attributes;
- for (var target in targets) {
- if (targets.hasOwnProperty(target)) {
- var targetAttributes = targets[target];
- for (var attribute in targetAttributes) {
- if (attribute !== "extras") {
- attributes[attribute + "_" + target] = targetAttributes[attribute];
- }
- }
- }
- }
- var material = materials[primitive.material];
- var technique =
- techniques[material.extensions.KHR_techniques_webgl.technique];
- var program = programs[technique.program];
- var vertexShader = shaders[program.vertexShader];
- for (var semantic in attributes) {
- if (attributes.hasOwnProperty(semantic)) {
- if (!defined(techniqueAttributeForSemantic(technique, semantic))) {
- var accessorId = attributes[semantic];
- var accessor = accessors[accessorId];
- var lowerCase = semantic.toLowerCase();
- if (lowerCase.charAt(0) === "_") {
- lowerCase = lowerCase.slice(1);
- }
- var attributeName = "a_" + lowerCase;
- technique.attributes[attributeName] = {
- semantic: semantic,
- type: accessor.componentType,
- };
- var pipelineExtras = vertexShader.extras._pipeline;
- var shaderText = pipelineExtras.source;
- shaderText =
- "attribute " +
- ModelUtility.getShaderVariable(accessor.type) +
- " " +
- attributeName +
- ";\n" +
- shaderText;
- pipelineExtras.source = shaderText;
- }
- }
- }
- }
- /**
- * Ensures all attributes present on the primitive are present in the technique and
- * vertex shader.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The glTF asset, including any additional attributes.
- */
- ModelUtility.ensureSemanticExistence = function (gltf) {
- ForEach.mesh(gltf, function (mesh) {
- ForEach.meshPrimitive(mesh, function (primitive) {
- ensureSemanticExistenceForPrimitive(gltf, primitive);
- });
- });
- return gltf;
- };
- /**
- * Creates attribute location for all attributes required by a technique.
- *
- * @param {Object} technique A glTF KHR_techniques_webgl technique object.
- * @param {Object} precreatedAttributes A dictionary object of pre-created attributes for which to also create locations.
- * @returns {Object} A dictionary object containing attribute names and their locations.
- */
- ModelUtility.createAttributeLocations = function (
- technique,
- precreatedAttributes
- ) {
- var attributeLocations = {};
- var hasIndex0 = false;
- var i = 1;
- ForEach.techniqueAttribute(technique, function (attribute, attributeName) {
- // Set the position attribute to the 0th index. In some WebGL implementations the shader
- // will not work correctly if the 0th attribute is not active. For example, some glTF models
- // list the normal attribute first but derived shaders like the cast-shadows shader do not use
- // the normal attribute.
- if (/pos/i.test(attributeName) && !hasIndex0) {
- attributeLocations[attributeName] = 0;
- hasIndex0 = true;
- } else {
- attributeLocations[attributeName] = i++;
- }
- });
- if (defined(precreatedAttributes)) {
- for (var attributeName in precreatedAttributes) {
- if (precreatedAttributes.hasOwnProperty(attributeName)) {
- attributeLocations[attributeName] = i++;
- }
- }
- }
- return attributeLocations;
- };
- ModelUtility.getAccessorMinMax = function (gltf, accessorId) {
- var accessor = gltf.accessors[accessorId];
- var extensions = accessor.extensions;
- var accessorMin = accessor.min;
- var accessorMax = accessor.max;
- // If this accessor is quantized, we should use the decoded min and max
- if (defined(extensions)) {
- var quantizedAttributes = extensions.WEB3D_quantized_attributes;
- if (defined(quantizedAttributes)) {
- accessorMin = quantizedAttributes.decodedMin;
- accessorMax = quantizedAttributes.decodedMax;
- }
- }
- return {
- min: accessorMin,
- max: accessorMax,
- };
- };
- function getTechniqueAttributeOrUniformFunction(
- gltf,
- technique,
- semantic,
- ignoreNodes
- ) {
- if (hasExtension(gltf, "KHR_techniques_webgl")) {
- return function (attributeOrUniform, attributeOrUniformName) {
- if (
- attributeOrUniform.semantic === semantic &&
- (!ignoreNodes || !defined(attributeOrUniform.node))
- ) {
- return attributeOrUniformName;
- }
- };
- }
- return function (parameterName, attributeOrUniformName) {
- var attributeOrUniform = technique.parameters[parameterName];
- if (
- attributeOrUniform.semantic === semantic &&
- (!ignoreNodes || !defined(attributeOrUniform.node))
- ) {
- return attributeOrUniformName;
- }
- };
- }
- ModelUtility.getAttributeOrUniformBySemantic = function (
- gltf,
- semantic,
- programId,
- ignoreNodes
- ) {
- return ForEach.technique(gltf, function (technique) {
- if (defined(programId) && technique.program !== programId) {
- return;
- }
- var value = ForEach.techniqueAttribute(
- technique,
- getTechniqueAttributeOrUniformFunction(
- gltf,
- technique,
- semantic,
- ignoreNodes
- )
- );
- if (defined(value)) {
- return value;
- }
- return ForEach.techniqueUniform(
- technique,
- getTechniqueAttributeOrUniformFunction(
- gltf,
- technique,
- semantic,
- ignoreNodes
- )
- );
- });
- };
- ModelUtility.getDiffuseAttributeOrUniform = function (gltf, programId) {
- var diffuseUniformName = ModelUtility.getAttributeOrUniformBySemantic(
- gltf,
- "COLOR_0",
- programId
- );
- if (!defined(diffuseUniformName)) {
- diffuseUniformName = ModelUtility.getAttributeOrUniformBySemantic(
- gltf,
- "_3DTILESDIFFUSE",
- programId
- );
- }
- return diffuseUniformName;
- };
- var nodeTranslationScratch = new Cartesian3();
- var nodeQuaternionScratch = new Quaternion();
- var nodeScaleScratch = new Cartesian3();
- ModelUtility.getTransform = function (node, result) {
- if (defined(node.matrix)) {
- return Matrix4.fromColumnMajorArray(node.matrix, result);
- }
- return Matrix4.fromTranslationQuaternionRotationScale(
- Cartesian3.fromArray(node.translation, 0, nodeTranslationScratch),
- Quaternion.unpack(node.rotation, 0, nodeQuaternionScratch),
- Cartesian3.fromArray(node.scale, 0, nodeScaleScratch),
- result
- );
- };
- ModelUtility.getUsedExtensions = function (gltf) {
- var extensionsUsed = gltf.extensionsUsed;
- var cachedExtensionsUsed = {};
- if (defined(extensionsUsed)) {
- var extensionsUsedLength = extensionsUsed.length;
- for (var i = 0; i < extensionsUsedLength; i++) {
- var extension = extensionsUsed[i];
- cachedExtensionsUsed[extension] = true;
- }
- }
- return cachedExtensionsUsed;
- };
- ModelUtility.getRequiredExtensions = function (gltf) {
- var extensionsRequired = gltf.extensionsRequired;
- var cachedExtensionsRequired = {};
- if (defined(extensionsRequired)) {
- var extensionsRequiredLength = extensionsRequired.length;
- for (var i = 0; i < extensionsRequiredLength; i++) {
- var extension = extensionsRequired[i];
- cachedExtensionsRequired[extension] = true;
- }
- }
- return cachedExtensionsRequired;
- };
- ModelUtility.supportedExtensions = {
- AGI_articulations: true,
- CESIUM_RTC: true,
- EXT_texture_webp: true,
- KHR_blend: true,
- KHR_binary_glTF: true,
- KHR_draco_mesh_compression: true,
- KHR_materials_common: true,
- KHR_techniques_webgl: true,
- KHR_materials_unlit: true,
- KHR_materials_pbrSpecularGlossiness: true,
- KHR_texture_transform: true,
- WEB3D_quantized_attributes: true,
- };
- ModelUtility.checkSupportedExtensions = function (
- extensionsRequired,
- browserSupportsWebp
- ) {
- for (var extension in extensionsRequired) {
- if (extensionsRequired.hasOwnProperty(extension)) {
- if (!ModelUtility.supportedExtensions[extension]) {
- throw new RuntimeError("Unsupported glTF Extension: " + extension);
- }
- if (extension === "EXT_texture_webp" && browserSupportsWebp === false) {
- throw new RuntimeError(
- "Loaded model requires WebP but browser does not support it."
- );
- }
- }
- }
- };
- ModelUtility.checkSupportedGlExtensions = function (extensionsUsed, context) {
- if (defined(extensionsUsed)) {
- var glExtensionsUsedLength = extensionsUsed.length;
- for (var i = 0; i < glExtensionsUsedLength; i++) {
- var extension = extensionsUsed[i];
- if (extension !== "OES_element_index_uint") {
- throw new RuntimeError("Unsupported WebGL Extension: " + extension);
- } else if (!context.elementIndexUint) {
- throw new RuntimeError(
- "OES_element_index_uint WebGL extension is not enabled."
- );
- }
- }
- }
- };
- function replaceAllButFirstInString(string, find, replace) {
- // Limit search to strings that are not a subset of other tokens.
- find += "(?!\\w)";
- find = new RegExp(find, "g");
- var index = string.search(find);
- return string.replace(find, function (match, offset) {
- return index === offset ? match : replace;
- });
- }
- function getQuantizedAttributes(gltf, accessorId) {
- var accessor = gltf.accessors[accessorId];
- var extensions = accessor.extensions;
- if (defined(extensions)) {
- return extensions.WEB3D_quantized_attributes;
- }
- return undefined;
- }
- function getAttributeVariableName(gltf, primitive, attributeSemantic) {
- var materialId = primitive.material;
- var material = gltf.materials[materialId];
- if (
- !hasExtension(gltf, "KHR_techniques_webgl") ||
- !defined(material.extensions) ||
- !defined(material.extensions.KHR_techniques_webgl)
- ) {
- return;
- }
- var techniqueId = material.extensions.KHR_techniques_webgl.technique;
- var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;
- var technique = techniquesWebgl.techniques[techniqueId];
- return ForEach.techniqueAttribute(technique, function (
- attribute,
- attributeName
- ) {
- var semantic = attribute.semantic;
- if (semantic === attributeSemantic) {
- return attributeName;
- }
- });
- }
- ModelUtility.modifyShaderForDracoQuantizedAttributes = function (
- gltf,
- primitive,
- shader,
- decodedAttributes
- ) {
- var quantizedUniforms = {};
- for (var attributeSemantic in decodedAttributes) {
- if (decodedAttributes.hasOwnProperty(attributeSemantic)) {
- var attribute = decodedAttributes[attributeSemantic];
- var quantization = attribute.quantization;
- if (!defined(quantization)) {
- continue;
- }
- var attributeVarName = getAttributeVariableName(
- gltf,
- primitive,
- attributeSemantic
- );
- if (attributeSemantic.charAt(0) === "_") {
- attributeSemantic = attributeSemantic.substring(1);
- }
- var decodeUniformVarName =
- "gltf_u_dec_" + attributeSemantic.toLowerCase();
- if (!defined(quantizedUniforms[decodeUniformVarName])) {
- var newMain = "gltf_decoded_" + attributeSemantic;
- var decodedAttributeVarName = attributeVarName.replace(
- "a_",
- "gltf_a_dec_"
- );
- var size = attribute.componentsPerAttribute;
- // replace usages of the original attribute with the decoded version, but not the declaration
- shader = replaceAllButFirstInString(
- shader,
- attributeVarName,
- decodedAttributeVarName
- );
- // declare decoded attribute
- var variableType;
- if (quantization.octEncoded) {
- variableType = "vec3";
- } else if (size > 1) {
- variableType = "vec" + size;
- } else {
- variableType = "float";
- }
- shader = variableType + " " + decodedAttributeVarName + ";\n" + shader;
- // The gltf 2.0 COLOR_0 vertex attribute can be VEC4 or VEC3
- var vec3Color = size === 3 && attributeSemantic === "COLOR_0";
- if (vec3Color) {
- shader = replaceAllButFirstInString(
- shader,
- decodedAttributeVarName,
- "vec4(" + decodedAttributeVarName + ", 1.0)"
- );
- }
- // splice decode function into the shader
- var decode = "";
- if (quantization.octEncoded) {
- var decodeUniformVarNameRangeConstant =
- decodeUniformVarName + "_rangeConstant";
- shader =
- "uniform float " +
- decodeUniformVarNameRangeConstant +
- ";\n" +
- shader;
- decode =
- "\n" +
- "void main() {\n" +
- // Draco oct-encoding decodes to zxy order
- " " +
- decodedAttributeVarName +
- " = czm_octDecode(" +
- attributeVarName +
- ".xy, " +
- decodeUniformVarNameRangeConstant +
- ").zxy;\n" +
- " " +
- newMain +
- "();\n" +
- "}\n";
- } else {
- var decodeUniformVarNameNormConstant =
- decodeUniformVarName + "_normConstant";
- var decodeUniformVarNameMin = decodeUniformVarName + "_min";
- shader =
- "uniform float " +
- decodeUniformVarNameNormConstant +
- ";\n" +
- "uniform " +
- variableType +
- " " +
- decodeUniformVarNameMin +
- ";\n" +
- shader;
- var attributeVarAccess = vec3Color ? ".xyz" : "";
- decode =
- "\n" +
- "void main() {\n" +
- " " +
- decodedAttributeVarName +
- " = " +
- decodeUniformVarNameMin +
- " + " +
- attributeVarName +
- attributeVarAccess +
- " * " +
- decodeUniformVarNameNormConstant +
- ";\n" +
- " " +
- newMain +
- "();\n" +
- "}\n";
- }
- shader = ShaderSource.replaceMain(shader, newMain);
- shader += decode;
- }
- }
- }
- return {
- shader: shader,
- };
- };
- ModelUtility.modifyShaderForQuantizedAttributes = function (
- gltf,
- primitive,
- shader
- ) {
- var quantizedUniforms = {};
- var attributes = primitive.attributes;
- for (var attributeSemantic in attributes) {
- if (attributes.hasOwnProperty(attributeSemantic)) {
- var attributeVarName = getAttributeVariableName(
- gltf,
- primitive,
- attributeSemantic
- );
- var accessorId = primitive.attributes[attributeSemantic];
- if (attributeSemantic.charAt(0) === "_") {
- attributeSemantic = attributeSemantic.substring(1);
- }
- var decodeUniformVarName =
- "gltf_u_dec_" + attributeSemantic.toLowerCase();
- var decodeUniformVarNameScale = decodeUniformVarName + "_scale";
- var decodeUniformVarNameTranslate = decodeUniformVarName + "_translate";
- if (
- !defined(quantizedUniforms[decodeUniformVarName]) &&
- !defined(quantizedUniforms[decodeUniformVarNameScale])
- ) {
- var quantizedAttributes = getQuantizedAttributes(gltf, accessorId);
- if (defined(quantizedAttributes)) {
- var decodeMatrix = quantizedAttributes.decodeMatrix;
- var newMain = "gltf_decoded_" + attributeSemantic;
- var decodedAttributeVarName = attributeVarName.replace(
- "a_",
- "gltf_a_dec_"
- );
- var size = Math.floor(Math.sqrt(decodeMatrix.length));
- // replace usages of the original attribute with the decoded version, but not the declaration
- shader = replaceAllButFirstInString(
- shader,
- attributeVarName,
- decodedAttributeVarName
- );
- // declare decoded attribute
- var variableType;
- if (size > 2) {
- variableType = "vec" + (size - 1);
- } else {
- variableType = "float";
- }
- shader =
- variableType + " " + decodedAttributeVarName + ";\n" + shader;
- // splice decode function into the shader - attributes are pre-multiplied with the decode matrix
- // uniform in the shader (32-bit floating point)
- var decode = "";
- if (size === 5) {
- // separate scale and translate since glsl doesn't have mat5
- shader =
- "uniform mat4 " + decodeUniformVarNameScale + ";\n" + shader;
- shader =
- "uniform vec4 " + decodeUniformVarNameTranslate + ";\n" + shader;
- decode =
- "\n" +
- "void main() {\n" +
- " " +
- decodedAttributeVarName +
- " = " +
- decodeUniformVarNameScale +
- " * " +
- attributeVarName +
- " + " +
- decodeUniformVarNameTranslate +
- ";\n" +
- " " +
- newMain +
- "();\n" +
- "}\n";
- quantizedUniforms[decodeUniformVarNameScale] = { mat: 4 };
- quantizedUniforms[decodeUniformVarNameTranslate] = { vec: 4 };
- } else {
- shader =
- "uniform mat" +
- size +
- " " +
- decodeUniformVarName +
- ";\n" +
- shader;
- decode =
- "\n" +
- "void main() {\n" +
- " " +
- decodedAttributeVarName +
- " = " +
- variableType +
- "(" +
- decodeUniformVarName +
- " * vec" +
- size +
- "(" +
- attributeVarName +
- ",1.0));\n" +
- " " +
- newMain +
- "();\n" +
- "}\n";
- quantizedUniforms[decodeUniformVarName] = { mat: size };
- }
- shader = ShaderSource.replaceMain(shader, newMain);
- shader += decode;
- }
- }
- }
- }
- return {
- shader: shader,
- uniforms: quantizedUniforms,
- };
- };
- function getScalarUniformFunction(value) {
- var that = {
- value: value,
- clone: function (source, result) {
- return source;
- },
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- function getVec2UniformFunction(value) {
- var that = {
- value: Cartesian2.fromArray(value),
- clone: Cartesian2.clone,
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- function getVec3UniformFunction(value) {
- var that = {
- value: Cartesian3.fromArray(value),
- clone: Cartesian3.clone,
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- function getVec4UniformFunction(value) {
- var that = {
- value: Cartesian4.fromArray(value),
- clone: Cartesian4.clone,
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- function getMat2UniformFunction(value) {
- var that = {
- value: Matrix2.fromColumnMajorArray(value),
- clone: Matrix2.clone,
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- function getMat3UniformFunction(value) {
- var that = {
- value: Matrix3.fromColumnMajorArray(value),
- clone: Matrix3.clone,
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- function getMat4UniformFunction(value) {
- var that = {
- value: Matrix4.fromColumnMajorArray(value),
- clone: Matrix4.clone,
- func: function () {
- return that.value;
- },
- };
- return that;
- }
- ///////////////////////////////////////////////////////////////////////////
- function DelayLoadedTextureUniform(value, textures, defaultTexture) {
- this._value = undefined;
- this._textureId = value.index;
- this._textures = textures;
- this._defaultTexture = defaultTexture;
- }
- Object.defineProperties(DelayLoadedTextureUniform.prototype, {
- value: {
- get: function () {
- // Use the default texture (1x1 white) until the model's texture is loaded
- if (!defined(this._value)) {
- var texture = this._textures[this._textureId];
- if (defined(texture)) {
- this._value = texture;
- } else {
- return this._defaultTexture;
- }
- }
- return this._value;
- },
- set: function (value) {
- this._value = value;
- },
- },
- });
- DelayLoadedTextureUniform.prototype.clone = function (source) {
- return source;
- };
- DelayLoadedTextureUniform.prototype.func = undefined;
- ///////////////////////////////////////////////////////////////////////////
- function getTextureUniformFunction(value, textures, defaultTexture) {
- var uniform = new DelayLoadedTextureUniform(value, textures, defaultTexture);
- // Define function here to access closure since 'this' can't be
- // used when the Renderer sets uniforms.
- uniform.func = function () {
- return uniform.value;
- };
- return uniform;
- }
- var gltfUniformFunctions = {};
- gltfUniformFunctions[WebGLConstants.FLOAT] = getScalarUniformFunction;
- gltfUniformFunctions[WebGLConstants.FLOAT_VEC2] = getVec2UniformFunction;
- gltfUniformFunctions[WebGLConstants.FLOAT_VEC3] = getVec3UniformFunction;
- gltfUniformFunctions[WebGLConstants.FLOAT_VEC4] = getVec4UniformFunction;
- gltfUniformFunctions[WebGLConstants.INT] = getScalarUniformFunction;
- gltfUniformFunctions[WebGLConstants.INT_VEC2] = getVec2UniformFunction;
- gltfUniformFunctions[WebGLConstants.INT_VEC3] = getVec3UniformFunction;
- gltfUniformFunctions[WebGLConstants.INT_VEC4] = getVec4UniformFunction;
- gltfUniformFunctions[WebGLConstants.BOOL] = getScalarUniformFunction;
- gltfUniformFunctions[WebGLConstants.BOOL_VEC2] = getVec2UniformFunction;
- gltfUniformFunctions[WebGLConstants.BOOL_VEC3] = getVec3UniformFunction;
- gltfUniformFunctions[WebGLConstants.BOOL_VEC4] = getVec4UniformFunction;
- gltfUniformFunctions[WebGLConstants.FLOAT_MAT2] = getMat2UniformFunction;
- gltfUniformFunctions[WebGLConstants.FLOAT_MAT3] = getMat3UniformFunction;
- gltfUniformFunctions[WebGLConstants.FLOAT_MAT4] = getMat4UniformFunction;
- gltfUniformFunctions[WebGLConstants.SAMPLER_2D] = getTextureUniformFunction;
- // GLTF_SPEC: Support SAMPLER_CUBE. https://github.com/KhronosGroup/glTF/issues/40
- ModelUtility.createUniformFunction = function (
- type,
- value,
- textures,
- defaultTexture
- ) {
- return gltfUniformFunctions[type](value, textures, defaultTexture);
- };
- function scaleFromMatrix5Array(matrix) {
- return [
- matrix[0],
- matrix[1],
- matrix[2],
- matrix[3],
- matrix[5],
- matrix[6],
- matrix[7],
- matrix[8],
- matrix[10],
- matrix[11],
- matrix[12],
- matrix[13],
- matrix[15],
- matrix[16],
- matrix[17],
- matrix[18],
- ];
- }
- function translateFromMatrix5Array(matrix) {
- return [matrix[20], matrix[21], matrix[22], matrix[23]];
- }
- ModelUtility.createUniformsForDracoQuantizedAttributes = function (
- decodedAttributes
- ) {
- var uniformMap = {};
- for (var attribute in decodedAttributes) {
- if (decodedAttributes.hasOwnProperty(attribute)) {
- var decodedData = decodedAttributes[attribute];
- var quantization = decodedData.quantization;
- if (!defined(quantization)) {
- continue;
- }
- if (attribute.charAt(0) === "_") {
- attribute = attribute.substring(1);
- }
- var uniformVarName = "gltf_u_dec_" + attribute.toLowerCase();
- if (quantization.octEncoded) {
- var uniformVarNameRangeConstant = uniformVarName + "_rangeConstant";
- var rangeConstant = (1 << quantization.quantizationBits) - 1.0;
- uniformMap[uniformVarNameRangeConstant] = getScalarUniformFunction(
- rangeConstant
- ).func;
- continue;
- }
- var uniformVarNameNormConstant = uniformVarName + "_normConstant";
- var normConstant =
- quantization.range / (1 << quantization.quantizationBits);
- uniformMap[uniformVarNameNormConstant] = getScalarUniformFunction(
- normConstant
- ).func;
- var uniformVarNameMin = uniformVarName + "_min";
- switch (decodedData.componentsPerAttribute) {
- case 1:
- uniformMap[uniformVarNameMin] = getScalarUniformFunction(
- quantization.minValues
- ).func;
- break;
- case 2:
- uniformMap[uniformVarNameMin] = getVec2UniformFunction(
- quantization.minValues
- ).func;
- break;
- case 3:
- uniformMap[uniformVarNameMin] = getVec3UniformFunction(
- quantization.minValues
- ).func;
- break;
- case 4:
- uniformMap[uniformVarNameMin] = getVec4UniformFunction(
- quantization.minValues
- ).func;
- break;
- }
- }
- }
- return uniformMap;
- };
- ModelUtility.createUniformsForQuantizedAttributes = function (
- gltf,
- primitive,
- quantizedUniforms
- ) {
- var accessors = gltf.accessors;
- var setUniforms = {};
- var uniformMap = {};
- var attributes = primitive.attributes;
- for (var attribute in attributes) {
- if (attributes.hasOwnProperty(attribute)) {
- var accessorId = attributes[attribute];
- var a = accessors[accessorId];
- var extensions = a.extensions;
- if (attribute.charAt(0) === "_") {
- attribute = attribute.substring(1);
- }
- if (defined(extensions)) {
- var quantizedAttributes = extensions.WEB3D_quantized_attributes;
- if (defined(quantizedAttributes)) {
- var decodeMatrix = quantizedAttributes.decodeMatrix;
- var uniformVariable = "gltf_u_dec_" + attribute.toLowerCase();
- switch (a.type) {
- case AttributeType.SCALAR:
- uniformMap[uniformVariable] = getMat2UniformFunction(
- decodeMatrix
- ).func;
- setUniforms[uniformVariable] = true;
- break;
- case AttributeType.VEC2:
- uniformMap[uniformVariable] = getMat3UniformFunction(
- decodeMatrix
- ).func;
- setUniforms[uniformVariable] = true;
- break;
- case AttributeType.VEC3:
- uniformMap[uniformVariable] = getMat4UniformFunction(
- decodeMatrix
- ).func;
- setUniforms[uniformVariable] = true;
- break;
- case AttributeType.VEC4:
- // VEC4 attributes are split into scale and translate because there is no mat5 in GLSL
- var uniformVariableScale = uniformVariable + "_scale";
- var uniformVariableTranslate = uniformVariable + "_translate";
- uniformMap[uniformVariableScale] = getMat4UniformFunction(
- scaleFromMatrix5Array(decodeMatrix)
- ).func;
- uniformMap[uniformVariableTranslate] = getVec4UniformFunction(
- translateFromMatrix5Array(decodeMatrix)
- ).func;
- setUniforms[uniformVariableScale] = true;
- setUniforms[uniformVariableTranslate] = true;
- break;
- }
- }
- }
- }
- }
- // If there are any unset quantized uniforms in this program, they should be set to the identity
- for (var quantizedUniform in quantizedUniforms) {
- if (quantizedUniforms.hasOwnProperty(quantizedUniform)) {
- if (!setUniforms[quantizedUniform]) {
- var properties = quantizedUniforms[quantizedUniform];
- if (defined(properties.mat)) {
- if (properties.mat === 2) {
- uniformMap[quantizedUniform] = getMat2UniformFunction(
- Matrix2.IDENTITY
- ).func;
- } else if (properties.mat === 3) {
- uniformMap[quantizedUniform] = getMat3UniformFunction(
- Matrix3.IDENTITY
- ).func;
- } else if (properties.mat === 4) {
- uniformMap[quantizedUniform] = getMat4UniformFunction(
- Matrix4.IDENTITY
- ).func;
- }
- }
- if (defined(properties.vec)) {
- if (properties.vec === 4) {
- uniformMap[quantizedUniform] = getVec4UniformFunction([
- 0,
- 0,
- 0,
- 0,
- ]).func;
- }
- }
- }
- }
- }
- return uniformMap;
- };
- // This doesn't support LOCAL, which we could add if it is ever used.
- var scratchTranslationRtc = new Cartesian3();
- var gltfSemanticUniforms = {
- MODEL: function (uniformState, model) {
- return function () {
- return uniformState.model;
- };
- },
- VIEW: function (uniformState, model) {
- return function () {
- return uniformState.view;
- };
- },
- PROJECTION: function (uniformState, model) {
- return function () {
- return uniformState.projection;
- };
- },
- MODELVIEW: function (uniformState, model) {
- return function () {
- return uniformState.modelView;
- };
- },
- CESIUM_RTC_MODELVIEW: function (uniformState, model) {
- // CESIUM_RTC extension
- var mvRtc = new Matrix4();
- return function () {
- if (defined(model._rtcCenter)) {
- Matrix4.getTranslation(uniformState.model, scratchTranslationRtc);
- Cartesian3.add(
- scratchTranslationRtc,
- model._rtcCenter,
- scratchTranslationRtc
- );
- Matrix4.multiplyByPoint(
- uniformState.view,
- scratchTranslationRtc,
- scratchTranslationRtc
- );
- return Matrix4.setTranslation(
- uniformState.modelView,
- scratchTranslationRtc,
- mvRtc
- );
- }
- return uniformState.modelView;
- };
- },
- MODELVIEWPROJECTION: function (uniformState, model) {
- return function () {
- return uniformState.modelViewProjection;
- };
- },
- MODELINVERSE: function (uniformState, model) {
- return function () {
- return uniformState.inverseModel;
- };
- },
- VIEWINVERSE: function (uniformState, model) {
- return function () {
- return uniformState.inverseView;
- };
- },
- PROJECTIONINVERSE: function (uniformState, model) {
- return function () {
- return uniformState.inverseProjection;
- };
- },
- MODELVIEWINVERSE: function (uniformState, model) {
- return function () {
- return uniformState.inverseModelView;
- };
- },
- MODELVIEWPROJECTIONINVERSE: function (uniformState, model) {
- return function () {
- return uniformState.inverseModelViewProjection;
- };
- },
- MODELINVERSETRANSPOSE: function (uniformState, model) {
- return function () {
- return uniformState.inverseTransposeModel;
- };
- },
- MODELVIEWINVERSETRANSPOSE: function (uniformState, model) {
- return function () {
- return uniformState.normal;
- };
- },
- VIEWPORT: function (uniformState, model) {
- return function () {
- return uniformState.viewportCartesian4;
- };
- },
- // JOINTMATRIX created in createCommand()
- };
- ModelUtility.getGltfSemanticUniforms = function () {
- return gltfSemanticUniforms;
- };
- export default ModelUtility;
|