UNPKG

cesium

Version:

CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.

923 lines (883 loc) 39.1 kB
define([ './addExtensionsRequired', './addToArray', './ForEach', './getAccessorByteStride', './numberOfComponentsForType', '../../Core/Cartesian3', '../../Core/Math', '../../Core/clone', '../../Core/ComponentDatatype', '../../Core/defaultValue', '../../Core/defined', '../../Core/Quaternion', '../../Core/WebGLConstants' ], function( addExtensionsRequired, addToArray, ForEach, getAccessorByteStride, numberOfComponentsForType, Cartesian3, CesiumMath, clone, ComponentDatatype, defaultValue, defined, Quaternion, WebGLConstants) { 'use strict'; var updateFunctions = { '0.8' : glTF08to10, '1.0' : glTF10to20, '2.0' : undefined }; /** * Update the glTF version to the latest version (2.0), or targetVersion if specified. * Applies changes made to the glTF spec between revisions so that the core library * only has to handle the latest version. * * @param {Object} gltf A javascript object containing a glTF asset. * @param {Object} [options] Options for updating the glTF. * @param {String} [options.targetVersion] The glTF will be upgraded until it hits the specified version. * @returns {Object} The updated glTF asset. */ function updateVersion(gltf, options) { options = defaultValue(options, {}); var targetVersion = options.targetVersion; var version = gltf.version; gltf.asset = defaultValue(gltf.asset, { version: '1.0' }); version = defaultValue(version, gltf.asset.version); // invalid version if (!updateFunctions.hasOwnProperty(version)) { // try truncating trailing version numbers, could be a number as well if it is 0.8 if (defined(version)) { version = ('' + version).substring(0, 3); } // default to 1.0 if it cannot be determined if (!updateFunctions.hasOwnProperty(version)) { version = '1.0'; } } var updateFunction = updateFunctions[version]; while (defined(updateFunction)) { if (version === targetVersion) { break; } updateFunction(gltf); version = gltf.asset.version; updateFunction = updateFunctions[version]; } return gltf; } function updateInstanceTechniques(gltf) { var materials = gltf.materials; for (var materialId in materials) { if (materials.hasOwnProperty(materialId)) { var material = materials[materialId]; var instanceTechnique = material.instanceTechnique; if (defined(instanceTechnique)) { material.technique = instanceTechnique.technique; material.values = instanceTechnique.values; delete material.instanceTechnique; } } } } function setPrimitiveModes(gltf) { var meshes = gltf.meshes; for (var meshId in meshes) { if (meshes.hasOwnProperty(meshId)) { var mesh = meshes[meshId]; var primitives = mesh.primitives; if (defined(primitives)) { var primitivesLength = primitives.length; for (var i = 0; i < primitivesLength; i++) { var primitive = primitives[i]; var defaultMode = defaultValue(primitive.primitive, WebGLConstants.TRIANGLES); primitive.mode = defaultValue(primitive.mode, defaultMode); delete primitive.primitive; } } } } } function updateNodes(gltf) { var nodes = gltf.nodes; var axis = new Cartesian3(); var quat = new Quaternion(); for (var nodeId in nodes) { if (nodes.hasOwnProperty(nodeId)) { var node = nodes[nodeId]; if (defined(node.rotation)) { var rotation = node.rotation; Cartesian3.fromArray(rotation, 0, axis); Quaternion.fromAxisAngle(axis, rotation[3], quat); node.rotation = [quat.x, quat.y, quat.z, quat.w]; } var instanceSkin = node.instanceSkin; if (defined(instanceSkin)) { node.skeletons = instanceSkin.skeletons; node.skin = instanceSkin.skin; node.meshes = instanceSkin.meshes; delete node.instanceSkin; } } } } function updateAnimations(gltf) { var animations = gltf.animations; var accessors = gltf.accessors; var bufferViews = gltf.bufferViews; var buffers = gltf.buffers; var updatedAccessors = {}; var axis = new Cartesian3(); var quat = new Quaternion(); for (var animationId in animations) { if (animations.hasOwnProperty(animationId)) { var animation = animations[animationId]; var channels = animation.channels; var parameters = animation.parameters; var samplers = animation.samplers; if (defined(channels)) { var channelsLength = channels.length; for (var i = 0; i < channelsLength; ++i) { var channel = channels[i]; if (channel.target.path === 'rotation') { var accessorId = parameters[samplers[channel.sampler].output]; if (defined(updatedAccessors[accessorId])) { continue; } updatedAccessors[accessorId] = true; var accessor = accessors[accessorId]; var bufferView = bufferViews[accessor.bufferView]; var buffer = buffers[bufferView.buffer]; var source = buffer.extras._pipeline.source; var byteOffset = source.byteOffset + bufferView.byteOffset + accessor.byteOffset; var componentType = accessor.componentType; var count = accessor.count; var componentsLength = numberOfComponentsForType(accessor.type); var length = accessor.count * componentsLength; var typedArray = ComponentDatatype.createArrayBufferView(componentType, source.buffer, byteOffset, length); for (var j = 0; j < count; j++) { var offset = j * componentsLength; Cartesian3.unpack(typedArray, offset, axis); var angle = typedArray[offset + 3]; Quaternion.fromAxisAngle(axis, angle, quat); Quaternion.pack(quat, typedArray, offset); } } } } } } } function removeTechniquePasses(gltf) { var techniques = gltf.techniques; for (var techniqueId in techniques) { if (techniques.hasOwnProperty(techniqueId)) { var technique = techniques[techniqueId]; var passes = technique.passes; if (defined(passes)) { var passName = defaultValue(technique.pass, 'defaultPass'); if (passes.hasOwnProperty(passName)) { var pass = passes[passName]; var instanceProgram = pass.instanceProgram; technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes); technique.program = defaultValue(technique.program, instanceProgram.program); technique.uniforms = defaultValue(technique.uniforms, instanceProgram.uniforms); technique.states = defaultValue(technique.states, pass.states); } delete technique.passes; delete technique.pass; } } } } function glTF08to10(gltf) { if (!defined(gltf.asset)) { gltf.asset = {}; } var asset = gltf.asset; asset.version = '1.0'; // profile should be an object, not a string if (!defined(asset.profile) || (typeof asset.profile === 'string')) { asset.profile = {}; } // version property should be in asset, not on the root element if (defined(gltf.version)) { delete gltf.version; } // material.instanceTechnique properties should be directly on the material updateInstanceTechniques(gltf); // primitive.primitive should be primitive.mode setPrimitiveModes(gltf); // node rotation should be quaternion, not axis-angle // node.instanceSkin is deprecated updateNodes(gltf); // animations that target rotations should be quaternion, not axis-angle updateAnimations(gltf); // technique.pass and techniques.passes are deprecated removeTechniquePasses(gltf); // gltf.lights -> khrMaterialsCommon.lights if (defined(gltf.lights)) { var extensions = defaultValue(gltf.extensions, {}); gltf.extensions = extensions; var materialsCommon = defaultValue(extensions.KHR_materials_common, {}); extensions.KHR_materials_common = materialsCommon; materialsCommon.lights = gltf.lights; delete gltf.lights; } // gltf.allExtensions -> extensionsUsed if (defined(gltf.allExtensions)) { gltf.extensionsUsed = gltf.allExtensions; gltf.allExtensions = undefined; } } function removeAnimationSamplersIndirection(gltf) { var animations = gltf.animations; for (var animationId in animations) { if (animations.hasOwnProperty(animationId)) { var animation = animations[animationId]; var parameters = animation.parameters; if (defined(parameters)) { var samplers = animation.samplers; for (var samplerId in samplers) { if (samplers.hasOwnProperty(samplerId)) { var sampler = samplers[samplerId]; sampler.input = parameters[sampler.input]; sampler.output = parameters[sampler.output]; } } delete animation.parameters; } } } } function objectToArray(object, mapping) { var array = []; for (var id in object) { if (object.hasOwnProperty(id)) { var value = object[id]; mapping[id] = array.length; array.push(value); if (!defined(value.name) && typeof(value) === 'object') { value.name = id; } } } return array; } function objectsToArrays(gltf) { var i; var globalMapping = { accessors: {}, animations: {}, bufferViews: {}, buffers: {}, cameras: {}, materials: {}, meshes: {}, nodes: {}, programs: {}, shaders: {}, skins: {}, techniques: {} }; // Map joint names to id names var jointName; var jointNameToId = {}; var nodes = gltf.nodes; for (var id in nodes) { if (nodes.hasOwnProperty(id)) { jointName = nodes[id].jointName; if (defined(jointName)) { jointNameToId[jointName] = id; } } } // Convert top level objects to arrays for (var topLevelId in gltf) { if (gltf.hasOwnProperty(topLevelId) && topLevelId !== 'extras' && topLevelId !== 'asset' && topLevelId !== 'extensions') { var objectMapping = {}; var object = gltf[topLevelId]; if (typeof(object) === 'object' && !Array.isArray(object)) { gltf[topLevelId] = objectToArray(object, objectMapping); globalMapping[topLevelId] = objectMapping; if (topLevelId === 'animations') { objectMapping = {}; object.samplers = objectToArray(object.samplers, objectMapping); globalMapping[topLevelId].samplers = objectMapping; } } } } // Remap joint names to array indexes for (jointName in jointNameToId) { if (jointNameToId.hasOwnProperty(jointName)) { jointNameToId[jointName] = globalMapping.nodes[jointNameToId[jointName]]; } } // Fix references if (defined(gltf.scene)) { gltf.scene = globalMapping.scenes[gltf.scene]; } ForEach.bufferView(gltf, function(bufferView) { if (defined(bufferView.buffer)) { bufferView.buffer = globalMapping.buffers[bufferView.buffer]; } }); ForEach.accessor(gltf, function(accessor) { if (defined(accessor.bufferView)) { accessor.bufferView = globalMapping.bufferViews[accessor.bufferView]; } }); ForEach.shader(gltf, function(shader) { var extensions = shader.extensions; if (defined(extensions)) { var binaryGltf = extensions.KHR_binary_glTF; if (defined(binaryGltf)) { shader.bufferView = globalMapping.bufferViews[binaryGltf.bufferView]; delete extensions.KHR_binary_glTF; } if (Object.keys(extensions).length === 0) { delete shader.extensions; } } }); ForEach.program(gltf, function(program) { if (defined(program.vertexShader)) { program.vertexShader = globalMapping.shaders[program.vertexShader]; } if (defined(program.fragmentShader)) { program.fragmentShader = globalMapping.shaders[program.fragmentShader]; } }); ForEach.technique(gltf, function(technique) { if (defined(technique.program)) { technique.program = globalMapping.programs[technique.program]; } ForEach.techniqueParameter(technique, function(parameter) { if (defined(parameter.node)) { parameter.node = globalMapping.nodes[parameter.node]; } var value = parameter.value; if (defined(value)) { if (Array.isArray(value)) { if (value.length === 1) { var textureId = value[0]; if (typeof textureId === 'string') { value[0] = globalMapping.textures[textureId]; } } } else if (typeof value === 'string') { parameter.value = [globalMapping.textures[value]]; } } }); }); ForEach.mesh(gltf, function(mesh) { ForEach.meshPrimitive(mesh, function(primitive) { if (defined(primitive.indices)) { primitive.indices = globalMapping.accessors[primitive.indices]; } ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { primitive.attributes[semantic] = globalMapping.accessors[accessorId]; }); if (defined(primitive.material)) { primitive.material = globalMapping.materials[primitive.material]; } }); }); ForEach.node(gltf, function(node) { var children = node.children; if (defined(children)) { var childrenLength = children.length; for (i = 0; i < childrenLength; i++) { children[i] = globalMapping.nodes[children[i]]; } } if (defined(node.meshes)) { // Split out meshes on nodes var meshes = node.meshes; var meshesLength = meshes.length; if (meshesLength > 0) { node.mesh = globalMapping.meshes[meshes[0]]; for (i = 1; i < meshesLength; i++) { var meshNode = { mesh: globalMapping.meshes[meshes[i]], extras: { _pipeline: {} } }; var meshNodeId = addToArray(gltf.nodes, meshNode); if (!defined(children)) { children = []; node.children = children; } children.push(meshNodeId); } } delete node.meshes; } if (defined(node.camera)) { node.camera = globalMapping.cameras[node.camera]; } if (defined(node.skeletons)) { // Assign skeletons to skins var skeletons = node.skeletons; var skeletonsLength = skeletons.length; if ((skeletonsLength > 0) && defined(node.skin)) { var skin = gltf.skins[globalMapping.skins[node.skin]]; skin.skeleton = globalMapping.nodes[skeletons[0]]; } delete node.skeletons; } if (defined(node.skin)) { node.skin = globalMapping.skins[node.skin]; } if (defined(node.jointName)) { delete(node.jointName); } }); ForEach.skin(gltf, function(skin) { if (defined(skin.inverseBindMatrices)) { skin.inverseBindMatrices = globalMapping.accessors[skin.inverseBindMatrices]; } var joints = []; var jointNames = skin.jointNames; if (defined(jointNames)) { for (i = 0; i < jointNames.length; i++) { joints[i] = jointNameToId[jointNames[i]]; } skin.joints = joints; delete skin.jointNames; } }); ForEach.scene(gltf, function(scene) { var sceneNodes = scene.nodes; if (defined(sceneNodes)) { var sceneNodesLength = sceneNodes.length; for (i = 0; i < sceneNodesLength; i++) { sceneNodes[i] = globalMapping.nodes[sceneNodes[i]]; } } }); ForEach.animation(gltf, function(animation) { var samplerMapping = {}; animation.samplers = objectToArray(animation.samplers, samplerMapping); ForEach.animationSampler(animation, function(sampler) { sampler.input = globalMapping.accessors[sampler.input]; sampler.output = globalMapping.accessors[sampler.output]; }); var channels = animation.channels; if (defined(channels)) { var channelsLength = channels.length; for (i = 0; i < channelsLength; i++) { var channel = channels[i]; channel.sampler = samplerMapping[channel.sampler]; var target = channel.target; if (defined(target)) { target.node = globalMapping.nodes[target.id]; delete target.id; } } } }); ForEach.material(gltf, function(material) { if (defined(material.technique)) { material.technique = globalMapping.techniques[material.technique]; } ForEach.materialValue(material, function(value, name) { if (Array.isArray(value)) { if (value.length === 1) { var textureId = value[0]; if (typeof textureId === 'string') { value[0] = globalMapping.textures[textureId]; } } } else if (typeof value === 'string') { material.values[name] = { index : globalMapping.textures[value] }; } }); var extensions = material.extensions; if (defined(extensions)) { var materialsCommon = extensions.KHR_materials_common; if (defined(materialsCommon)) { ForEach.materialValue(materialsCommon, function(value, name) { if (Array.isArray(value)) { if (value.length === 1) { var textureId = value[0]; if (typeof textureId === 'string') { value[0] = globalMapping.textures[textureId]; } } } else if (typeof value === 'string') { materialsCommon.values[name] = { index: globalMapping.textures[value] }; } }); } } }); ForEach.image(gltf, function(image) { var extensions = image.extensions; if (defined(extensions)) { var binaryGltf = extensions.KHR_binary_glTF; if (defined(binaryGltf)) { image.bufferView = globalMapping.bufferViews[binaryGltf.bufferView]; image.mimeType = binaryGltf.mimeType; delete extensions.KHR_binary_glTF; } if (Object.keys(extensions).length === 0) { delete image.extensions; } } if (defined(image.extras)) { var compressedImages = image.extras.compressedImage3DTiles; for (var type in compressedImages) { if (compressedImages.hasOwnProperty(type)) { var compressedImage = compressedImages[type]; var compressedExtensions = compressedImage.extensions; if (defined(compressedExtensions)) { var compressedBinaryGltf = compressedExtensions.KHR_binary_glTF; if (defined(compressedBinaryGltf)) { compressedImage.bufferView = globalMapping.bufferViews[compressedBinaryGltf.bufferView]; compressedImage.mimeType = compressedBinaryGltf.mimeType; delete compressedExtensions.KHR_binary_glTF; } if (Object.keys(compressedExtensions).length === 0) { delete compressedImage.extensions; } } } } } }); ForEach.texture(gltf, function(texture) { if (defined(texture.sampler)) { texture.sampler = globalMapping.samplers[texture.sampler]; } if (defined(texture.source)) { texture.source = globalMapping.images[texture.source]; } }); } function stripProfile(gltf) { var asset = gltf.asset; delete asset.profile; } var knownExtensions = { CESIUM_RTC : true, KHR_materials_common : true, WEB3D_quantized_attributes : true }; function requireKnownExtensions(gltf) { var extensionsUsed = gltf.extensionsUsed; gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []); if (defined(extensionsUsed)) { var extensionsUsedLength = extensionsUsed.length; for (var i = 0; i < extensionsUsedLength; i++) { var extension = extensionsUsed[i]; if (defined(knownExtensions[extension])) { gltf.extensionsRequired.push(extension); } } } } function removeBufferType(gltf) { ForEach.buffer(gltf, function(buffer) { delete buffer.type; }); } function requireAttributeSetIndex(gltf) { ForEach.mesh(gltf, function(mesh) { ForEach.meshPrimitive(mesh, function(primitive) { ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { if (semantic === 'TEXCOORD') { primitive.attributes.TEXCOORD_0 = accessorId; } else if (semantic === 'COLOR') { primitive.attributes.COLOR_0 = accessorId; } }); delete primitive.attributes.TEXCOORD; delete primitive.attributes.COLOR; }); }); ForEach.technique(gltf, function(technique) { ForEach.techniqueParameter(technique, function(parameter) { var semantic = parameter.semantic; if (defined(semantic)) { if (semantic === 'TEXCOORD') { parameter.semantic = 'TEXCOORD_0'; } else if (semantic === 'COLOR') { parameter.semantic = 'COLOR_0'; } } }); }); } var knownSemantics = { POSITION: true, NORMAL: true, TEXCOORD: true, COLOR: true, JOINT: true, WEIGHT: true }; function underscoreApplicationSpecificSemantics(gltf) { var mappedSemantics = {}; ForEach.mesh(gltf, function(mesh) { ForEach.meshPrimitive(mesh, function(primitive) { /* jshint unused:vars */ ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) { if (semantic.charAt(0) !== '_') { var setIndex = semantic.search(/_[0-9]+/g); var strippedSemantic = semantic; if (setIndex >= 0) { strippedSemantic = semantic.substring(0, setIndex); } if (!defined(knownSemantics[strippedSemantic])) { var newSemantic = '_' + semantic; mappedSemantics[semantic] = newSemantic; } } }); for (var semantic in mappedSemantics) { if (mappedSemantics.hasOwnProperty(semantic)) { var mappedSemantic = mappedSemantics[semantic]; var accessorId = primitive.attributes[semantic]; if (defined(accessorId)) { delete primitive.attributes[semantic]; primitive.attributes[mappedSemantic] = accessorId; } } } }); }); ForEach.technique(gltf, function(technique) { ForEach.techniqueParameter(technique, function(parameter) { var mappedSemantic = mappedSemantics[parameter.semantic]; if (defined(mappedSemantic)) { parameter.semantic = mappedSemantic; } }); }); } function removeScissorFromTechniques(gltf) { ForEach.technique(gltf, function(technique) { var techniqueStates = technique.states; if (defined(techniqueStates)) { var techniqueFunctions = techniqueStates.functions; if (defined(techniqueFunctions)) { delete techniqueFunctions.scissor; } var enableStates = techniqueStates.enable; if (defined(enableStates)) { var scissorIndex = enableStates.indexOf(WebGLConstants.SCISSOR_TEST); if (scissorIndex >= 0) { enableStates.splice(scissorIndex, 1); } } } }); } function clampTechniqueFunctionStates(gltf) { ForEach.technique(gltf, function(technique) { var techniqueStates = technique.states; if (defined(techniqueStates)) { var functions = techniqueStates.functions; if (defined(functions)) { var blendColor = functions.blendColor; if (defined(blendColor)) { for (var i = 0; i < 4; i++) { blendColor[i] = CesiumMath.clamp(blendColor[i], 0.0, 1.0); } } var depthRange = functions.depthRange; if (defined(depthRange)) { depthRange[1] = CesiumMath.clamp(depthRange[1], 0.0, 1.0); depthRange[0] = CesiumMath.clamp(depthRange[0], 0.0, depthRange[1]); } } } }); } function clampCameraParameters(gltf) { ForEach.camera(gltf, function(camera) { var perspective = camera.perspective; if (defined(perspective)) { var aspectRatio = perspective.aspectRatio; if (defined(aspectRatio) && aspectRatio === 0.0) { delete perspective.aspectRatio; } var yfov = perspective.yfov; if (defined(yfov) && yfov === 0.0) { perspective.yfov = 1.0; } } }); } function requireByteLength(gltf) { ForEach.buffer(gltf, function(buffer) { if (!defined(buffer.byteLength)) { buffer.byteLength = buffer.extras._pipeline.source.length; } }); ForEach.bufferView(gltf, function(bufferView) { if (!defined(bufferView.byteLength)) { var bufferViewBufferId = bufferView.buffer; var bufferViewBuffer = gltf.buffers[bufferViewBufferId]; bufferView.byteLength = bufferViewBuffer.byteLength; } }); } function moveByteStrideToBufferView(gltf) { var bufferViews = gltf.bufferViews; var bufferViewsToDelete = {}; ForEach.accessor(gltf, function(accessor) { var oldBufferViewId = accessor.bufferView; if (defined(oldBufferViewId)) { if (!defined(bufferViewsToDelete[oldBufferViewId])) { bufferViewsToDelete[oldBufferViewId] = true; } var bufferView = clone(bufferViews[oldBufferViewId]); var accessorByteStride = (defined(accessor.byteStride) && accessor.byteStride !== 0) ? accessor.byteStride : getAccessorByteStride(gltf, accessor); if (defined(accessorByteStride)) { bufferView.byteStride = accessorByteStride; if (bufferView.byteStride !== 0) { bufferView.byteLength = accessor.count * accessorByteStride; } bufferView.byteOffset += accessor.byteOffset; accessor.byteOffset = 0; delete accessor.byteStride; } accessor.bufferView = addToArray(bufferViews, bufferView); } }); var bufferViewShiftMap = {}; var bufferViewRemovalCount = 0; /* jshint unused:vars */ ForEach.bufferView(gltf, function(bufferView, bufferViewId) { if (defined(bufferViewsToDelete[bufferViewId])) { bufferViewRemovalCount++; } else { bufferViewShiftMap[bufferViewId] = bufferViewId - bufferViewRemovalCount; } }); var removedCount = 0; for (var bufferViewId in bufferViewsToDelete) { if (defined(bufferViewId)) { var index = parseInt(bufferViewId) - removedCount; bufferViews.splice(index, 1); removedCount++; } } ForEach.accessor(gltf, function(accessor) { var accessorBufferView = accessor.bufferView; if (defined(accessorBufferView)) { accessor.bufferView = bufferViewShiftMap[accessorBufferView]; } }); ForEach.shader(gltf, function(shader) { var shaderBufferView = shader.bufferView; if (defined(shaderBufferView)) { shader.bufferView = bufferViewShiftMap[shaderBufferView]; } }); ForEach.image(gltf, function(image) { var imageBufferView = image.bufferView; if (defined(imageBufferView)) { image.bufferView = bufferViewShiftMap[imageBufferView]; } if (defined(image.extras)) { var compressedImages = image.extras.compressedImage3DTiles; for (var type in compressedImages) { if (compressedImages.hasOwnProperty(type)) { var compressedImage = compressedImages[type]; var compressedImageBufferView = compressedImage.bufferView; if (defined(compressedImageBufferView)) { compressedImage.bufferView = bufferViewShiftMap[compressedImageBufferView]; } } } } }); } function stripTechniqueAttributeValues(gltf) { ForEach.technique(gltf, function(technique) { ForEach.techniqueAttribute(technique, function(attribute) { var parameter = technique.parameters[attribute]; if (defined(parameter.value)) { delete parameter.value; } }); }); } function stripTechniqueParameterCount(gltf) { ForEach.technique(gltf, function(technique) { ForEach.techniqueParameter(technique, function(parameter) { if (defined(parameter.count)) { var semantic = parameter.semantic; if (!defined(semantic) || (semantic !== 'JOINTMATRIX' && semantic.indexOf('_') !== 0)) { delete parameter.count; } } }); }); } function addKHRTechniqueExtension(gltf) { var techniques = gltf.techniques; if (defined(techniques) && techniques.length > 0) { addExtensionsRequired(gltf, 'KHR_technique_webgl'); } } function glTF10to20(gltf) { if (!defined(gltf.asset)) { gltf.asset = {}; } var asset = gltf.asset; asset.version = '2.0'; // material.instanceTechnique properties should be directly on the material. instanceTechnique is a gltf 0.8 property but is seen in some 1.0 models. updateInstanceTechniques(gltf); // animation.samplers now refers directly to accessors and animation.parameters should be removed removeAnimationSamplersIndirection(gltf); // top-level objects are now arrays referenced by index instead of id objectsToArrays(gltf); // asset.profile no longer exists stripProfile(gltf); // move known extensions from extensionsUsed to extensionsRequired requireKnownExtensions(gltf); // bufferView.byteLength and buffer.byteLength are required requireByteLength(gltf); // byteStride moved from accessor to bufferView moveByteStrideToBufferView(gltf); // buffer.type is unnecessary and should be removed removeBufferType(gltf); // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#) requireAttributeSetIndex(gltf); // Add underscores to application-specific parameters underscoreApplicationSpecificSemantics(gltf); // remove scissor from techniques removeScissorFromTechniques(gltf); // clamp technique function states to min/max clampTechniqueFunctionStates(gltf); // clamp camera parameters clampCameraParameters(gltf); // a technique parameter specified as an attribute cannot have a value stripTechniqueAttributeValues(gltf); // only techniques with a JOINTMATRIX or application specific semantic may have a defined count property stripTechniqueParameterCount(gltf); // add KHR_technique_webgl extension addKHRTechniqueExtension(gltf); } return updateVersion; });