I'm trying to use FileReader to pass a client side ASCII file to loader.load() but it looks like the file never gets there. The file does appear in the 3D scene if I use loader.load('server path to test_file.stl')
instead of loader.load(fileObject)
.
I included an alert() function to display the file's ASCII text and that tells me the JavaScript is grabbing and processing the file and there is no Chrome security barrier but apparently I'm not properly passing the file to loader.load()
.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:#fea47c;
}
div {
position:relative;
left:200px;
top:0px;
background-color: #eeeeee;
border:1px solid black;
width:550px;
height:550px;
}
canvas {
width:550px;
height:550px;
}
</style>
</head>
<body>
<script src=".js/master/build/three.min.js"></script>
<script src=".js/master/examples/js/loaders/STLLoader.js"></script>
<script src=".js/master/examples/js/controls/TrackballControls.js"></script>
<input type="file" id="pickfile"></input>
<script>
document.getElementById('pickfile').addEventListener('change', readFile, false);
function readFile (evt)
{
var fileObject = evt.target.files[0];
var reader = new FileReader();
reader.onload = function() {alert(this.result)}; // verifies ASCII file contents were grabbed
reader.readAsText(fileObject)
}
var container, camera, scene, renderer, controls;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var width = container.clientWidth;
var height = container.clientHeight;
camera = new THREE.PerspectiveCamera( 35, width / height, .1 , 10000);
camera.position.set( 0, 0, 600);
scene = new THREE.Scene();
controls = new THREE.TrackballControls( camera , container);
controls.addEventListener( 'change', render );
// object
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var material = new THREE.MeshLambertMaterial( { ambient: 0xff5533, color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
loader.load(fileObject);
// lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position = camera.position;
scene.add( directionalLight );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width , height );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function addLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
}
function onWindowResize() {
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
I'm trying to use FileReader to pass a client side ASCII file to loader.load() but it looks like the file never gets there. The file does appear in the 3D scene if I use loader.load('server path to test_file.stl')
instead of loader.load(fileObject)
.
I included an alert() function to display the file's ASCII text and that tells me the JavaScript is grabbing and processing the file and there is no Chrome security barrier but apparently I'm not properly passing the file to loader.load()
.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:#fea47c;
}
div {
position:relative;
left:200px;
top:0px;
background-color: #eeeeee;
border:1px solid black;
width:550px;
height:550px;
}
canvas {
width:550px;
height:550px;
}
</style>
</head>
<body>
<script src="https://raw.github./mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://raw.github./mrdoob/three.js/master/examples/js/loaders/STLLoader.js"></script>
<script src="https://raw.github./mrdoob/three.js/master/examples/js/controls/TrackballControls.js"></script>
<input type="file" id="pickfile"></input>
<script>
document.getElementById('pickfile').addEventListener('change', readFile, false);
function readFile (evt)
{
var fileObject = evt.target.files[0];
var reader = new FileReader();
reader.onload = function() {alert(this.result)}; // verifies ASCII file contents were grabbed
reader.readAsText(fileObject)
}
var container, camera, scene, renderer, controls;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var width = container.clientWidth;
var height = container.clientHeight;
camera = new THREE.PerspectiveCamera( 35, width / height, .1 , 10000);
camera.position.set( 0, 0, 600);
scene = new THREE.Scene();
controls = new THREE.TrackballControls( camera , container);
controls.addEventListener( 'change', render );
// object
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var material = new THREE.MeshLambertMaterial( { ambient: 0xff5533, color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
loader.load(fileObject);
// lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position = camera.position;
scene.add( directionalLight );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width , height );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function addLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
}
function onWindowResize() {
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
Share
Improve this question
edited Nov 5, 2017 at 17:24
WestLangley
105k11 gold badges287 silver badges283 bronze badges
asked Dec 13, 2012 at 5:04
ForumLeechForumLeech
4672 gold badges7 silver badges15 bronze badges
2
- For one, it doesn't work that way. I don't know enough about stls to give you a working example but the STLLoader does provide a parse method which returns a geometry from which which you can create a mesh to add to a scene. I tried messing with it, but the stl I have seems to give me some problems. – JayC Commented Dec 13, 2012 at 8:15
- I noticed that you've asked a related question before: stackoverflow./questions/13770297/… . It would be best for the munity if we deleted one of these questions – JayC Commented Dec 13, 2012 at 16:42
2 Answers
Reset to default 5Ok, I tried again this morning, and I think the problem was I was trying to view the loaded results from a bad camera angle or something... anyways, here's an example based on https://raw.github./mrdoob/three.js/master/examples/webgl_loader_stl.html
The essential part:
Like I mentioned above, loader.load does not have any overload that would take the actual contents of the file (and it's kinda silly to think it would). It will only take a location for the file... you needed something that creates your model from the file contents. That would be loader.parse
.
For example, the following handler adds your model to a scene where scene
is in scope of readFile
:
function readFile(evt)
{
var fileObject = evt.target.files[0];
var reader = new FileReader();
reader.onload = function ()
{
var loader = new THREE.STLLoader();
//alert(this.result)
var geometry = loader.parse(this.result);
var material = new THREE.MeshPhongMaterial(
{
ambient: 0xff5533,
color: 0xff5533,
specular: 0x111111,
shininess: 200
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
};
reader.readAsText(fileObject)
}
Whole example:
I'd put this somewhere on the net but as it uses github to host some of the scripts, etc. that's probably not the best idea.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Monospace;
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#pickfile {
color: #fff;
position: absolute;
top: 40px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
a {
color: skyblue
}
</style>
</head>
<body>
<script src="https://raw.github./mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://raw.github./mrdoob/three.js/master/examples/js/loaders/STLLoader.js"></script>
<script src="https://raw.github./mrdoob/three.js/master/examples/js/controls/TrackballControls.js"></script>
<script src="https://raw.github./mrdoob/three.js/master/examples/js/Detector.js"></script>
<script src="https://raw.github./mrdoob/three.js/master/examples/js/libs/stats.min.js"></script>
<input type="file" id="pickfile"></input>
<script>
document.getElementById('pickfile').addEventListener('change', readFile, false);
function readFile(evt)
{
var fileObject = evt.target.files[0];
var reader = new FileReader();
reader.onload = function ()
{
var loader = new THREE.STLLoader();
//alert(this.result)
var geometry = loader.parse(this.result);
var material = new THREE.MeshPhongMaterial(
{
ambient: 0xff5533,
color: 0xff5533,
specular: 0x111111,
shininess: 200
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
};
reader.readAsText(fileObject)
}
if (!Detector.webgl) Detector.addGetWebGLMessage();
var container, stats;
var camera, scene, renderer, objects;
init();
animate();
function init()
{
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 15);
camera.position.set(3, 0.5, 3);
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xffffff, 2, 15);
scene.fog.color.setHSV(0.06, 0.2, 0.45);
// Grid
var size = 20,
step = 0.25;
var geometry = new THREE.Geometry();
var material = new THREE.LineBasicMaterial(
{
color: 0x000000
});
for (var i = -size; i <= size; i += step)
{
geometry.vertices.push(new THREE.Vector3(-size, -0.04, i));
geometry.vertices.push(new THREE.Vector3(size, -0.04, i));
geometry.vertices.push(new THREE.Vector3(i, -0.04, -size));
geometry.vertices.push(new THREE.Vector3(i, -0.04, size));
}
var line = new THREE.Line(geometry, material, THREE.LinePieces);
line.position.y = -0.46;
scene.add(line);
// Ground
var plane = new THREE.Mesh(new THREE.PlaneGeometry(40, 40), new THREE.MeshPhongMaterial(
{
ambient: 0x999999,
color: 0x999999,
specular: 0x101010
}));
plane.rotation.x = -Math.PI / 2;
plane.position.y = -0.5;
scene.add(plane);
plane.receiveShadow = true;
// Object
// Lights
scene.add(new THREE.AmbientLight(0x777777));
addShadowedLight(1, 1, 1, 0xffffff, 1.35);
addShadowedLight(0.5, 1, -1, 0xffaa00, 1);
// renderer
renderer = new THREE.WebGLRenderer(
{
antialias: true,
clearColor: 0x111111,
clearAlpha: 1,
alpha: false
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(scene.fog.color, 1);
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.physicallyBasedShading = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapCullFrontFaces = false;
container.appendChild(renderer.domElement);
// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function addShadowedLight(x, y, z, color, intensity)
{
var directionalLight = new THREE.DirectionalLight(color, intensity);
directionalLight.position.set(x, y, z)
scene.add(directionalLight);
directionalLight.castShadow = true;
//directionalLight.shadowCameraVisible = true;
var d = 1;
directionalLight.shadowCameraLeft = -d;
directionalLight.shadowCameraRight = d;
directionalLight.shadowCameraTop = d;
directionalLight.shadowCameraBottom = -d;
directionalLight.shadowCameraNear = 1;
directionalLight.shadowCameraFar = 4;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = -0.005;
directionalLight.shadowDarkness = 0.15;
}
function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function animate()
{
requestAnimationFrame(animate);
render();
stats.update();
}
function render()
{
var timer = Date.now() * 0.0005;
camera.position.x = Math.cos(timer) * 5;
camera.position.z = Math.sin(timer) * 5;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
</script>
</body>
</html>
Thanks a lot for your snippet, this made my day
Though I had a problem implementing your solution at this line :
reader.readAsText(fileObject) ;
I changed it to :
reader.readAsArrayBuffer(fileObject) ;
and it works like a charm...
So for the plete code :
1) I have a button in my html to load the .stl file :
select your stl file <br>
<input type="file" id="pickFile" />
2) in my js file :
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer, mesh, controls ;
var group ;
var container = document.getElementById('canvas3D');
// Create default material
material = new THREE.MeshPhongMaterial();
init();
animate();
// file input button
document.getElementById('pickFile').addEventListener('change', openFile, false);
// file load
function openFile (evt) {
var fileObject = evt.target.files[0];
// delete previous objects from scene
while(group.children.length > 0){
group.remove(group.children[0]);
}
var reader = new FileReader();
reader.onload = function ()
{
var loader = new THREE.STLLoader();
// parse the .stl file
var geometry = loader.parse(this.result);
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
group.add(mesh);
};
// --> update here
reader.readAsArrayBuffer(fileObject) ;
};
// and the rest of my three.js code there : init() and animate() functions ...