Laplacian smoothing
Interactive example using Three.js and three-mesh-halfedge.
by mvgician
HTML
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/",
"three-mesh-halfedge": "https://cdn.jsdelivr.net/npm/[email protected]/build/index.esm.js"
}
}
</script>
CSS
body {
padding: 0;
margin: 0;
}
#wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: auto;
overflow: hidden;
}
.primary{
color: #ddc000;
}
.secondary{
color: #f78e20;
}
.tertiary{
color: #e21;
}
JavaScript
import * as THREE from 'three'
import { HalfedgeDS, Vertex } from 'three-mesh-halfedge'
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { mergeVertices } from 'three/addons/utils/BufferGeometryUtils.js'
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js'
// renderer
const width = window.innerWidth
const height = window.innerHeight
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(3) // smoother (and thinner) lines
renderer.setSize(width, height)
document.body.appendChild(renderer.domElement)
// camera
const camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 20)
camera.position.set(3, 2, 4)
const controls = new OrbitControls(camera, renderer.domElement)
controls.enablePan = false
controls.enableZoom = true
controls.maxDistance = 10
controls.minDistance = 1
// scene
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xffffff)
// gui
const gui = new GUI() // create gui
const shapes = {
Box: merge(new THREE.BoxGeometry(350, 350, 350, 5, 5, 5)),
Cylinder: merge(new THREE.CylinderGeometry(200, 200, 350, 32, 8)),
Bunny: await loadStanfordBunny()
}
// loader
function loadStanfordBunny () {
return new Promise((resolve, reject) => {
const loader = new FBXLoader()
loader.load('https://threejs.org/examples/models/fbx/stanford-bunny.fbx', function (object) {
const model = object.children[0]
resolve(merge(model.geometry))
},
undefined,
function (error) {
reject(error)
})
})
}
const parameters = {
shape: 'Box',
smooth,
reset
}
gui.add(parameters, 'shape', Object.keys(shapes)).onChange(initializeMesh)
gui.add(parameters, 'smooth')
gui.add(parameters, 'reset')
// utils
let mesh, wireframe
const struct = new HalfedgeDS()
const vector = new THREE.Vector3()
const material = new THREE.MeshNormalMaterial()
const wireframeMaterial = new...