UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

164 lines (163 loc) 6.19 kB
import { $variantIndices, $getLoadedMaterial } from "../material.mjs"; import { $correlatedObjects } from "../three-dom-element.mjs"; class Node { constructor(name) { this.name = ""; this.children = new Array(); this.name = name; } } class PrimitiveNode extends Node { constructor(mesh, mvMaterials, modelVariants, correlatedSceneGraph) { super(mesh.name); this.materials = /* @__PURE__ */ new Map(); this.variantToMaterialMap = /* @__PURE__ */ new Map(); this.initialMaterialIdx = 0; this.activeMaterialIdx = 0; this.mesh = mesh; const { gltf, threeGLTF, threeObjectMap } = correlatedSceneGraph; this.modelVariants = modelVariants; this.mesh.userData.variantData = modelVariants; const materialMappings = threeObjectMap.get(mesh.material); if (materialMappings.materials != null) { this.initialMaterialIdx = this.activeMaterialIdx = materialMappings.materials; } else { console.error(`Primitive (${mesh.name}) missing initial material reference.`); } const associations = mesh.userData.associations || {}; if (associations.meshes == null) { console.error("Mesh is missing primitive index association"); return; } const meshElementArray = gltf["meshes"] || []; const gltfPrimitives = meshElementArray[associations.meshes].primitives || []; const gltfPrimitive = gltfPrimitives[associations.primitives]; if (gltfPrimitive == null) { console.error("Mesh primitive definition is missing."); return; } if (gltfPrimitive.material != null) { this.materials.set(gltfPrimitive.material, mvMaterials[gltfPrimitive.material]); } else { const defaultIdx = mvMaterials.findIndex((mat) => { return mat.name === "Default"; }); if (defaultIdx >= 0) { this.materials.set(defaultIdx, mvMaterials[defaultIdx]); } else { console.warn("gltfPrimitive has no material!"); } } if (gltfPrimitive.extensions && gltfPrimitive.extensions["KHR_materials_variants"]) { const variantsExtension = gltfPrimitive.extensions["KHR_materials_variants"]; const extensions = threeGLTF.parser.json.extensions; const variantNames = extensions["KHR_materials_variants"].variants; for (const mapping of variantsExtension.mappings) { const mvMaterial = mvMaterials[mapping.material]; this.materials.set(mapping.material, mvMaterial); for (const variant of mapping.variants) { const { name } = variantNames[variant]; this.variantToMaterialMap.set(variant, mvMaterial); mvMaterial[$variantIndices]().add(variant); if (!modelVariants.has(name)) { modelVariants.set(name, { name, index: variant }); } } } } } async setActiveMaterial(material) { const mvMaterial = this.materials.get(material); if (mvMaterial != null) { this.mesh.material = await mvMaterial[$getLoadedMaterial](); this.activeMaterialIdx = material; } return this.mesh.material; } getActiveMaterial() { return this.materials.get(this.activeMaterialIdx); } getMaterial(index) { return this.materials.get(index); } async enableVariant(name) { if (name == null) { return this.setActiveMaterial(this.initialMaterialIdx); } if (this.variantToMaterialMap != null && this.modelVariants.has(name)) { const modelVariants = this.modelVariants.get(name); return this.enableVariantHelper(modelVariants.index); } return null; } async enableVariantHelper(index) { if (this.variantToMaterialMap != null && index != null) { const material = this.variantToMaterialMap.get(index); if (material != null) { return this.setActiveMaterial(material.index); } } return null; } async instantiateVariants() { if (this.variantToMaterialMap == null) { return; } for (const index of this.variantToMaterialMap.keys()) { const variantMaterial = this.mesh.userData.variantMaterials.get(index); if (variantMaterial.material != null) { continue; } const threeMaterial = await this.enableVariantHelper(index); if (threeMaterial != null) { variantMaterial.material = threeMaterial; } } } get variantInfo() { return this.variantToMaterialMap; } addVariant(materialVariant, variantName) { if (!this.ensureVariantIsUnused(variantName)) { return false; } if (!this.modelVariants.has(variantName)) { this.modelVariants.set(variantName, { name: variantName, index: this.modelVariants.size }); } const modelVariantData = this.modelVariants.get(variantName); const variantIndex = modelVariantData.index; materialVariant[$variantIndices]().add(variantIndex); this.variantToMaterialMap.set(variantIndex, materialVariant); this.materials.set(materialVariant.index, materialVariant); this.updateVariantUserData(variantIndex, materialVariant); return true; } deleteVariant(variantIndex) { if (this.variantInfo.has(variantIndex)) { this.variantInfo.delete(variantIndex); const userDataMap = this.mesh.userData.variantMaterials; if (userDataMap != null) { userDataMap.delete(variantIndex); } } } updateVariantUserData(variantIndex, materialVariant) { materialVariant[$variantIndices]().add(variantIndex); this.mesh.userData.variantData = this.modelVariants; this.mesh.userData.variantMaterials = this.mesh.userData.variantMaterials || /* @__PURE__ */ new Map(); const map = this.mesh.userData.variantMaterials; map.set(variantIndex, { material: materialVariant[$correlatedObjects].values().next().value, gltfMaterialIndex: materialVariant.index }); } ensureVariantIsUnused(variantName) { const modelVariants = this.modelVariants.get(variantName); if (modelVariants != null && this.variantInfo.has(modelVariants.index)) { console.warn(`Primitive cannot add variant '${variantName}' for this material, it already exists.`); return false; } return true; } } export { Node, PrimitiveNode };