Skip to content

Instantly share code, notes, and snippets.

@bellbind
Last active July 25, 2023 17:57
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save bellbind/477817982584ac8473ef to your computer and use it in GitHub Desktop.
Save bellbind/477817982584ac8473ef to your computer and use it in GitHub Desktop.
[threejs][html5]STL File Viewer with HTML5 File API
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>STL File Viewer</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r68/three.min.js"
></script>
<script src="https://rawgit.com/mrdoob/three.js/master/examples/js/controls/TrackballControls.js"
></script>
<script src="loader.js"></script>
<script src="stl.js"></script>
</head>
<body>
<div>
select stl file: <input type="file" id="file" /> or drop stl file
</div>
<div id="view"></div>
</body>
</html>
window.addEventListener("load", function () {
"use strict";
var w = 800, h = 800;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(w, h);
var view = document.getElementById("view");
view.appendChild(renderer.domElement);
var camera = new THREE.PerspectiveCamera(45, w / h, 1, 1000);
camera.position.set(0, 0, 50);
var controls = new THREE.TrackballControls(camera, view);
var scene = new THREE.Scene();
scene.add(new THREE.AmbientLight(0x666666));
var light1 = new THREE.DirectionalLight(0xffffff);
light1.position.set(0, 100, 100);
scene.add(light1);
var light2 = new THREE.DirectionalLight(0xffffff);
light2.position.set(0, -100, -100);
scene.add(light2);
var mat = new THREE.MeshPhongMaterial({
color: 0x339900, ambient: 0x339900, specular: 0x030303,
});
var obj = new THREE.Mesh(new THREE.Geometry(), mat);
scene.add(obj);
var loop = function loop() {
requestAnimationFrame(loop);
//obj.rotation.z += 0.05;
controls.update();
renderer.clear();
renderer.render(scene, camera);
};
loop();
// file load
var openFile = function (file) {
var reader = new FileReader();
reader.addEventListener("load", function (ev) {
var buffer = ev.target.result;
var geom = loadStl(buffer);
scene.remove(obj);
obj = new THREE.Mesh(geom, mat);
scene.add(obj);
}, false);
reader.readAsArrayBuffer(file);
};
// file input button
var input = document.getElementById("file");
input.addEventListener("change", function (ev) {
var file = ev.target.files[0];
openFile(file);
}, false);
// dnd
view.addEventListener("dragover", function (ev) {
ev.stopPropagation();
ev.preventDefault();
ev.dataTransfer.dropEffect = "copy";
}, false);
view.addEventListener("drop", function (ev) {
ev.stopPropagation();
ev.preventDefault();
var file = ev.dataTransfer.files[0];
openFile(file);
}, false);
}, false);
var loadStl = (function () {
var binaryVector3 = function (view, offset) {
var v = new THREE.Vector3();
v.x = view.getFloat32(offset + 0, true);
v.y = view.getFloat32(offset + 4, true);
v.z = view.getFloat32(offset + 8, true);
return v;
};
var loadBinaryStl = function (buffer) {
// binary STL
var view = new DataView(buffer);
var size = view.getUint32(80, true);
var geom = new THREE.Geometry();
var offset = 84;
for (var i = 0; i < size; i++) {
var normal = binaryVector3(view, offset);
geom.vertices.push(binaryVector3(view, offset + 12));
geom.vertices.push(binaryVector3(view, offset + 24));
geom.vertices.push(binaryVector3(view, offset + 36));
geom.faces.push(
new THREE.Face3(i * 3, i * 3 + 1, i * 3 + 2, normal));
offset += 4 * 3 * 4 + 2;
}
return geom;
};
var m2vec3 = function (match) {
var v = new THREE.Vector3();
v.x = parseFloat(match[1]);
v.y = parseFloat(match[2]);
v.z = parseFloat(match[3]);
return v;
};
var toLines = function (array) {
var lines = [];
var h = 0;
for (var i = 0; i < array.length; i++) {
if (array[i] === 10) {
var line = String.fromCharCode.apply(
null, array.subarray(h, i));
lines.push(line);
h = i + 1;
}
}
lines.push(String.fromCharCode.apply(null, array.subarray(h)));
return lines;
}
var loadTextStl = function (buffer) {
var lines = toLines(new Uint8Array(buffer));
var index = 0;
var scan = function (regexp) {
while (lines[index].match(/^\s*$/)) index++;
var r = lines[index].match(regexp);
return r;
};
var scanOk = function (regexp) {
var r = scan(regexp);
if (!r) throw new Error(
"not text stl: " + regexp.toString() +
"=> (line " + (index - 1) + ")" +
"[" + lines[index-1] + "]");
index++;
return r;
}
var facetReg = /^\s*facet\s+normal\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/;
var vertexReg = /^\s*vertex\s+([^s]+)\s+([^\s]+)\s+([^\s]+)/;
var geom = new THREE.Geometry();
scanOk(/^\s*solid\s(.*)/);
while (!scan(/^\s*endsolid/)) {
var normal = scanOk(facetReg);
scanOk(/^\s*outer\s+loop/);
var v1 = scanOk(vertexReg);
var v2 = scanOk(vertexReg);
var v3 = scanOk(vertexReg);
scanOk(/\s*endloop/);
scanOk(/\s*endfacet/);
var base = geom.vertices.length;
geom.vertices.push(m2vec3(v1));
geom.vertices.push(m2vec3(v2));
geom.vertices.push(m2vec3(v3));
geom.faces.push(
new THREE.Face3(base, base + 1, base + 2, m2vec3(normal)));
}
return geom;
};
return function (buffer) {
try {
console.log("load as text stl");
return loadTextStl(buffer);
} catch (ex) {
console.log(ex);
console.log("load as binary stl");
return loadBinaryStl(buffer);
}
};
})();
@bellbind
Copy link
Author

@siidorann
Copy link

How can I set a .stl scene before uploading file?
I wanna set stl scene that is in may server.

@SalmanEmenacsoft
Copy link

Nice code, but i have one question, in the above code we have to select the .STL file for the system, but in my case i have the file on my server and i have the link to show that, can you please help me how can i show that please

Thanks

@fenderguitar
Copy link

Any updates on adding our own .stl file? I have one on my server but can't figure out how to modify the code to point to that stl.

@pcasasayas
Copy link

For loading an scene from server side, you have to load the file with THREE.STLloader module provided in three.js website specifing your static path to the file from server, instead of loading the local file with function:(
var openFile = function (file) {
var reader = new FileReader();
reader.addEventListener("load", function (ev) {
var buffer = ev.target.result;
var geom = loadStl(buffer);
scene.remove(obj);
obj = new THREE.Mesh(geom, mat);
scene.add(obj);
}, false);
reader.readAsArrayBuffer(file);
};
)

There is an example on three.js website.

@Pkemarco
Copy link

Hi ! It is very beautiful and helpful. But I want to know please what I have to do to change the background color ? Thank tou.

@AnubhavMadhav
Copy link

Hello! The STL file is not visible on the page after uploading it from system, can someone please help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment