<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.5" />
<title>Mesh Viewer based on three.js</title>
<style>
body { margin: 0; }
</style>
<!--https://threejs.org/docs/index.html#manual/en/introduction/Installation-->
<script type="importmap">
{
"imports": {
"three": "/.cdn/three/0.164.0/build/three.module.min.js",
"three/addons/": "/.cdn/three/0.164.0/examples/jsm/"
}
}
</script>
</head>
<body>
<!--https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene-->
<!--https://threejs.org/docs/index.html#examples/en/loaders/OBJLoader-->
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
import { STLLoader } from 'three/addons/loaders/STLLoader.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
const scene = new THREE.Scene();
scene.background = new THREE.Color(1,1,1);
scene.add(new THREE.AxesHelper(10));
if (window.matchMedia) {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
scene.background.set(0,0,0);
}
}
const gui = new GUI();
gui.addColor(scene, 'background');
const camera = new THREE.PerspectiveCamera(
60,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(100, -100, 100);
camera.up.set(0, 0, 1);
const light = new THREE.PointLight();
camera.add(light);
scene.add(camera);
// https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733
const renderer = new THREE.WebGLRenderer();
renderer.useLegacyLights = true;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
function addOptions(folder, obj, material) {
folder.add(obj, 'visible');
folder.addColor(material, 'color');
folder.add(material, 'wireframe');
}
function loadOBJ(filename) {
const basename = filename.substring(filename.lastIndexOf('/') + 1);
const folder = gui.addFolder(basename);
const objloader = new OBJLoader();
objloader.load(
filename,
function (obj) {
const material = new THREE.MeshStandardMaterial();
material.color = new THREE.Color(0.5, 0.5, 0.5);
obj.traverse(
function (child) {
if (child instanceof THREE.Mesh) {
child.material = material;
}
}
);
scene.add(obj);
addOptions(folder, obj, material);
}
);
}
function loadSTL(filename) {
const basename = filename.substring(filename.lastIndexOf('/') + 1);
const folder = gui.addFolder(basename);
const stlloader = new STLLoader();
stlloader.load(
filename,
function (geometry) {
const material = new THREE.MeshStandardMaterial();
material.color = new THREE.Color(0.5, 0.5, 0.5);
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
addOptions(folder, mesh, material);
}
);
}
function loadMesh(filename) {
if (filename.endsWith('.obj')) {
loadOBJ(filename);
} else if (filename.endsWith('.stl')) {
loadSTL(filename);
}
}
function createCube() {
const folder = gui.addFolder('Cube');
const geometry = new THREE.BoxGeometry(10, 10, 10);
const material = new THREE.MeshStandardMaterial();
material.color = new THREE.Color(0.5, 0.5, 0.5);
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
addOptions(folder, mesh, material);
}
const params = new URLSearchParams(window.location.search);
if (params.has('filename')) {
loadMesh(params.get('filename'));
} else if (params.has('filenames[]')) {
const filenames = params.getAll('filenames[]');
if (Array.isArray(filenames) && filenames.length) {
for (let i = 0; i < filenames.length; i++) {
loadMesh(filenames[i]);
}
}
} else {
createCube();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
window.addEventListener('resize', onWindowResize);
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>