cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
164 lines (163 loc) • 6.19 kB
JavaScript
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 };