import type { Material } from "@babylonjs/core/Materials/material"; import type { Mesh } from "@babylonjs/core/Meshes/mesh"; import type { MorphTarget } from "@babylonjs/core/Morph/morphTarget"; import type { MorphTargetManager } from "@babylonjs/core/Morph/morphTargetManager"; import type { DeepImmutable, Nullable } from "@babylonjs/core/types"; import type { MmdModelMetadata } from "../Loader/mmdModelMetadata"; import type { Vec3, Vec4 } from "../Loader/Parser/mmdTypes"; import { PmxObject } from "../Loader/Parser/pmxObject"; import type { IMmdMaterialProxyConstructor } from "./IMmdMaterialProxy"; import type { MmdRuntimeBone } from "./mmdRuntimeBone"; /** * Represents a material morph element in MMD runtime * * This information is used to induce material recompilation */ export interface IRuntimeMaterialMorphElement { index: number; type: PmxObject.Morph.MaterialMorph.Type; diffuse: Nullable; specular: Nullable; shininess: Nullable; ambient: Nullable; edgeColor: Nullable; edgeSize: Nullable; textureColor: Nullable; sphereTextureColor: Nullable; toonTextureColor: Nullable; } /** * @internal * Represents a morph in MMD runtime */ export interface IRuntimeMorph { readonly name: string; readonly type: PmxObject.Morph.Type; readonly materialElements: Nullable; readonly elements: Nullable; readonly elements2: Nullable; readonly elements3: Nullable; } /** * Morph information exposed to the user * * Only material morphs data are exposed */ export interface IReadonlyRuntimeMorph { /** * Name of the morph */ readonly name: string; /** * Type of the morph */ readonly type: PmxObject.Morph.Type; /** * Material morph elements */ readonly materialElements: Nullable[]>; /** * Group morph / bone morph / uv morph / vertex morph bindings */ readonly elements: Nullable | readonly MorphTarget[]>; } /** * The MmdMorphControllerBase uses `MorphTargetManager` to handle position uv morphs, while the material, bone, and group morphs are handled by CPU bound * * As a result, it reproduces the behavior of the MMD morph system */ export declare abstract class MmdMorphControllerBase { protected readonly _runtimeBones: readonly MmdRuntimeBone[]; private readonly _materials; protected readonly _morphs: readonly IRuntimeMorph[]; protected readonly _morphIndexMap: Map; protected readonly _morphWeights: Float32Array; protected readonly _activeMorphs: Set; /** * MorphTargetManagers used to handle position uv morphs */ readonly morphTargetManagers: readonly MorphTargetManager[]; /** * Creates a new MmdMorphController * @param runtimeBones MMD runtime bones which are original order * @param materials MMD materials which are order of mmd metadata * @param meshes MMD meshes which are order of mmd metadata * @param materialProxyConstructor The constructor of `IMmdMaterialProxy` * @param morphsMetadata Morphs metadata * @param morphTargetManagers MorphTargetManagers * @param logger Logger */ constructor(runtimeBones: Nullable, materials: readonly Material[], meshes: readonly Mesh[], materialProxyConstructor: Nullable>, morphsMetadata: readonly MmdModelMetadata.Morph[], morphTargetManagers: MorphTargetManager[]); /** * Sets the weight of the morph * * If there are multiple morphs with the same name, all of them will be set to the same weight, this is the behavior of MMD * @param morphName Name of the morph * @param weight Weight of the morph */ abstract setMorphWeight(morphName: string, weight: number): void; /** * Gets the weight of the morph * * If there are multiple morphs with the same name, the weight of the first one will be returned * @param morphName Name of the morph * @returns Weight of the morph */ getMorphWeight(morphName: string): number; /** * Gets the indices of the morph with the given name * * The index array is returned because multiple morphs can have the same name * @param morphName Name of the morph * @returns Indices of the morph */ getMorphIndices(morphName: string): readonly number[] | undefined; /** * Sets the weight of the morph from the index * * This method is faster than `setMorphWeight` because it does not need to search the morphs with the given name * @param morphIndex Index of the morph * @param weight Weight of the morph */ abstract setMorphWeightFromIndex(morphIndex: number, weight: number): void; /** * Gets the weight of the morph from the index * @param morphIndex Index of the morph * @returns Weight of the morph */ getMorphWeightFromIndex(morphIndex: number): number; /** * Gets the weights of all morphs * @returns Weights of all morphs */ getMorphWeights(): Readonly>; /** * Set the weights of all morphs to 0 */ resetMorphWeights(): void; private readonly _updatedMaterials; /** * Apply the morphs to mesh */ update(): void; /** * Gets the morph data */ get morphs(): readonly IReadonlyRuntimeMorph[]; private _createRuntimeMorphData; private _groupMorphForeach; private _resetMorph; protected abstract _resetBoneMorph(morph: IRuntimeMorph): void; private _applyMorph; protected abstract _applyBoneMorph(morph: IRuntimeMorph, weight: number): void; private _applyMaterialMorph; }