diff --git a/demo/simplify.html b/demo/simplify.html
index 2a345752..0baf3c3f 100644
--- a/demo/simplify.html
+++ b/demo/simplify.html
@@ -71,6 +71,8 @@
normalWeight: 0.5,
colorWeight: 1.0,
textureWeight: 0.0,
+ autoLod: false,
+ autoLodFactor: 1.0,
stats: {
triangles: 0,
@@ -116,6 +118,10 @@
guiAttributes.push(guiSimplify.add(settings, 'colorWeight', 0, 2, 0.01).onChange(simplify));
guiAttributes.push(guiSimplify.add(settings, 'textureWeight', 0, 100, 0.1).onChange(simplify));
+ var guiLod = gui.addFolder('LOD');
+ guiLod.add(settings, 'autoLod').onChange(simplify);
+ guiLod.add(settings, 'autoLodFactor', 0, 10, 0.01).onChange(simplify);
+
var guiLoad = gui.addFolder('Load');
guiLoad.add(settings, 'loadFile');
guiLoad.add(settings, 'updateModule');
@@ -138,7 +144,7 @@
}
}
- function simplifyMesh(geo) {
+ function simplifyMesh(geo, threshold) {
if (settings.weldVertices) {
// pre-welding is important for some meshes that have very close normals in adjacent face corners
// for now we use the welder from three.js; this is not as performant as it could be
@@ -149,7 +155,7 @@
var positions = new Float32Array(geo.attributes.position.array);
var indices = new Uint32Array(geo.index.array); // needed for _InternalDebug to work
- var target = Math.floor((indices.length * settings.ratio) / 3) * 3;
+ var target = settings.autoLod ? 0 : Math.floor((indices.length * settings.ratio) / 3) * 3;
if (settings.useAttributes) {
var attrib = new Float32Array(geo.attributes.position.count * attributes);
@@ -190,7 +196,6 @@
flags.push('LockBorder');
}
- var threshold = Math.pow(10, -settings.errorThresholdLog10);
var stride = geo.attributes.position instanceof THREE.InterleavedBufferAttribute ? geo.attributes.position.data.stride : 3;
console.time('simplify');
@@ -297,6 +302,21 @@
var vertices = 0;
var error = 0;
+ var threshold = Math.pow(10, -settings.errorThresholdLog10);
+
+ if (settings.autoLod) {
+ // subtract 1 because we assume model radius is 1.0, so this is a distance-to-sphere
+ // ideally this should actually use the real radius :) but we rescale the model to fit a unit box
+ var distance = Math.max(camera.position.distanceTo(model.position) - 1, 0);
+ var loderrortarget = 1e-3; // ~1 pixel at 1k x 1k
+
+ // note: we are currently cutting corners wrt handling the actual mesh scale
+ // since we rescale the entire scene to fit a unit box, we can directly feed the threshold
+ // this works correctly if there's just one mesh or scales match; ideally we tweak this to compute
+ // threshold per mesh based on relative scale between mesh and scene.
+ threshold = distance * loderrortarget * settings.autoLodFactor;
+ }
+
scene.traverse(function (object) {
if (object.isMesh) {
if (!object.original) {
@@ -316,7 +336,7 @@
];
}
- var [geo, tri, err] = simplifyMesh(object.original);
+ var [geo, tri, err] = simplifyMesh(object.original, threshold);
object.geometry = geo;
@@ -405,11 +425,11 @@
model = gltf.scene;
var bbox = new THREE.Box3().setFromObject(model);
- var scale = 2 / (bbox.max.y - bbox.min.y);
- var offset = (-(bbox.min.y + bbox.max.y) / 2) * scale;
+ var scale = 2 / Math.max(bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y, bbox.max.z - bbox.min.z);
+ var offset = new THREE.Vector3().addVectors(bbox.max, bbox.min).multiplyScalar(scale / 2);
model.scale.set(scale, scale, scale);
- model.position.set(0, offset, 0);
+ model.position.set(-offset.x, -offset.y, -offset.z);
scene.add(model);
@@ -435,11 +455,12 @@
window.addEventListener('resize', onWindowResize, false);
- camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 100);
+ camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.y = 1.0;
camera.position.z = 3.0;
controls = new OrbitControls(camera, renderer.domElement);
+ controls.addEventListener('change', simplify);
scene = new THREE.Scene();
scene.background = new THREE.Color(0x300a24);