import { c as TmpVectors, V as Vector3, ao as Quaternion, M as Matrix, L as Logger, aG as unregisterGLTFExtension, aH as registerGLTFExtension } from './index-CxR0Yf_7.js';
import { GLTFLoader, ArrayItem } from './glTFLoader-BbG05oe0.js';
import './thinInstanceMesh-Bxr7w30K.js';
import './index-BvBk1Iap.js';
import './bone-C6xIrJX4.js';
import './skeleton-DzANFt7R.js';
import './rawTexture-Bto4WZO2.js';
import './assetContainer-7GPvH2S_.js';
import './objectModelMapping-DnUo8NMz.js';

const NAME = "EXT_mesh_gpu_instancing";
/**
 * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing/README.md)
 * [Playground Sample](https://playground.babylonjs.com/#QFIGLW#9)
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
class EXT_mesh_gpu_instancing {
    /**
     * @internal
     */
    constructor(loader) {
        /**
         * The name of this extension.
         */
        this.name = NAME;
        this._loader = loader;
        this.enabled = this._loader.isExtensionUsed(NAME);
    }
    /** @internal */
    dispose() {
        this._loader = null;
    }
    /**
     * @internal
     */
    // eslint-disable-next-line no-restricted-syntax
    loadNodeAsync(context, node, assign) {
        return GLTFLoader.LoadExtensionAsync(context, node, this.name, async (extensionContext, extension) => {
            this._loader._disableInstancedMesh++;
            const promise = this._loader.loadNodeAsync(`/nodes/${node.index}`, node, assign);
            this._loader._disableInstancedMesh--;
            if (!node._primitiveBabylonMeshes) {
                return await promise;
            }
            const promises = new Array();
            let instanceCount = 0;
            const loadAttribute = (attribute) => {
                if (extension.attributes[attribute] == undefined) {
                    promises.push(Promise.resolve(null));
                    return;
                }
                const accessor = ArrayItem.Get(`${extensionContext}/attributes/${attribute}`, this._loader.gltf.accessors, extension.attributes[attribute]);
                promises.push(this._loader._loadFloatAccessorAsync(`/accessors/${accessor.bufferView}`, accessor));
                if (instanceCount === 0) {
                    instanceCount = accessor.count;
                }
                else if (instanceCount !== accessor.count) {
                    throw new Error(`${extensionContext}/attributes: Instance buffer accessors do not have the same count.`);
                }
            };
            loadAttribute("TRANSLATION");
            loadAttribute("ROTATION");
            loadAttribute("SCALE");
            loadAttribute("_COLOR_0");
            // eslint-disable-next-line github/no-then
            return await promise.then(async (babylonTransformNode) => {
                const [translationBuffer, rotationBuffer, scaleBuffer, colorBuffer] = await Promise.all(promises);
                const matrices = new Float32Array(instanceCount * 16);
                TmpVectors.Vector3[0].copyFromFloats(0, 0, 0); // translation
                TmpVectors.Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation
                TmpVectors.Vector3[1].copyFromFloats(1, 1, 1); // scale
                for (let i = 0; i < instanceCount; ++i) {
                    translationBuffer && Vector3.FromArrayToRef(translationBuffer, i * 3, TmpVectors.Vector3[0]);
                    rotationBuffer && Quaternion.FromArrayToRef(rotationBuffer, i * 4, TmpVectors.Quaternion[0]);
                    scaleBuffer && Vector3.FromArrayToRef(scaleBuffer, i * 3, TmpVectors.Vector3[1]);
                    Matrix.ComposeToRef(TmpVectors.Vector3[1], TmpVectors.Quaternion[0], TmpVectors.Vector3[0], TmpVectors.Matrix[0]);
                    TmpVectors.Matrix[0].copyToArray(matrices, i * 16);
                }
                for (const babylonMesh of node._primitiveBabylonMeshes) {
                    babylonMesh.thinInstanceSetBuffer("matrix", matrices, 16, true);
                    if (colorBuffer) {
                        if (colorBuffer.length === instanceCount * 3) {
                            babylonMesh.thinInstanceSetBuffer("color", colorBuffer, 3, true);
                        }
                        else if (colorBuffer.length === instanceCount * 4) {
                            babylonMesh.thinInstanceSetBuffer("color", colorBuffer, 4, true);
                        }
                        else {
                            Logger.Warn("Unexpected size of _COLOR_0 attribute for mesh " + babylonMesh.name);
                        }
                    }
                }
                return babylonTransformNode;
            });
        });
    }
}
unregisterGLTFExtension(NAME);
registerGLTFExtension(NAME, true, (loader) => new EXT_mesh_gpu_instancing(loader));

export { EXT_mesh_gpu_instancing };
//# sourceMappingURL=EXT_mesh_gpu_instancing-CXbTF9Kl.js.map
