threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
106 lines • 4.9 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var MeshOptSimplifyModifierPlugin_1;
import { BufferAttribute } from 'three';
import { iGeometryCommons } from '../../core';
import { toIndexedGeometry } from '../../three';
import { SimplifyModifierPlugin } from './SimplifyModifierPlugin';
import { uiFolderContainer, uiNumber, uiToggle } from 'uiconfig.js';
/**
* Simplify modifier using [meshoptimizer](https://github.com/zeux/meshoptimizer) library.
* Loads the library at runtime from a customisable cdn url.
*/
let MeshOptSimplifyModifierPlugin = MeshOptSimplifyModifierPlugin_1 = class MeshOptSimplifyModifierPlugin extends SimplifyModifierPlugin {
constructor(initialize = true, rootNode = document.head) {
super();
this.rootNode = rootNode;
this._initializing = undefined;
this.errorThreshold = 0.5;
this.lockBorder = false;
// todo: check if compatible?
if (initialize)
this.initialize();
}
get initialized() {
return !!window.MeshoptSimplifier;
}
onAdded(viewer) {
super.onAdded(viewer);
}
async initialize() {
if (this.initialized)
return;
if (this._initializing)
return await this._initializing;
const s = document.createElement('script');
s.type = 'module';
const ev = Math.random().toString(36).substring(7);
s.innerHTML = `
import { MeshoptSimplifier } from ${JSON.stringify(MeshOptSimplifyModifierPlugin_1.SIMPLIFIER_URL)};
MeshoptSimplifier.ready.then(() => {
window.MeshoptSimplifier = MeshoptSimplifier;
window.dispatchEvent(new CustomEvent('${ev}'))
});
`;
this._initializing = new Promise((res) => {
window.addEventListener(ev, () => res(), { once: true });
this.rootNode.appendChild(s);
this._script = s;
});
return await this._initializing;
}
dispose() {
if (this._script) {
this._script.remove();
delete window.MeshoptSimplifier;
}
this._script = undefined;
}
_simplify(geometry, count) {
if (!this.initialized)
throw new Error('MeshOptSimplifyModifierPlugin not initialized');
if (!geometry.index) {
geometry = toIndexedGeometry(geometry);
}
else {
geometry = geometry.clone();
}
const srcIndexArray = geometry.index.array;
const srcPositionArray = geometry.attributes.position.array;
const factor = count / geometry.attributes.position.count;
// console.log(factor)
// const targetCount = count * 3
const targetCount = 3 * Math.floor(factor * srcIndexArray.length / 3);
// console.log('srcCount', srcIndexArray.length / 3, 'targetCount', targetCount / 3)
// const errorThresh = 1e-2
const [dstIndexArray, error] = window.MeshoptSimplifier.simplify(srcIndexArray, srcPositionArray, 3, targetCount, this.errorThreshold, this.lockBorder ? ['LockBorder'] : []);
console.log('srcCount', srcIndexArray.length / 3, 'destCount', dstIndexArray.length / 3);
if (error) {
console.warn('Simplify error', error);
// return geometry // todo
}
// (geometry.index!.array as Uint32Array).set(dstIndexArray)
geometry.setIndex(new BufferAttribute(new Uint32Array(dstIndexArray), 1));
// geometry.index!.needsUpdate = true
// geometry.setDrawRange(0, dstIndexArray.length)
return iGeometryCommons.upgradeGeometry.call(geometry.toNonIndexed());
}
};
MeshOptSimplifyModifierPlugin.PluginType = 'MeshOptSimplifyModifierPlugin';
// static SIMPLIFIER_URL = 'https://cdn.jsdelivr.net/gh/zeux/meshoptimizer@master/js/meshopt_simplifier.module.js'
MeshOptSimplifyModifierPlugin.SIMPLIFIER_URL = 'https://unpkg.com/meshoptimizer@0.20.0/meshopt_simplifier.module.js';
__decorate([
uiNumber()
], MeshOptSimplifyModifierPlugin.prototype, "errorThreshold", void 0);
__decorate([
uiToggle()
], MeshOptSimplifyModifierPlugin.prototype, "lockBorder", void 0);
MeshOptSimplifyModifierPlugin = MeshOptSimplifyModifierPlugin_1 = __decorate([
uiFolderContainer('Simplify Modifier (meshopt)')
], MeshOptSimplifyModifierPlugin);
export { MeshOptSimplifyModifierPlugin };
//# sourceMappingURL=MeshOptSimplifyModifierPlugin.js.map