Files
viewstl/src/load_stl.js
T
omrips 6fbc2cc36a Add files via upload
//New in 1.12 => improve auto_zoom algorithm by Michal Jirku (https://wejn.org/2020/12/cracking-the-threejs-object-fitting-nut/)
//New in 1.12 => "dispose" function
//New in 1.12 => fixed memory leak on "clean" function (thanks to Anthony https://github.com/antho1404)
//New in 1.12 => use 'fetch' instead for xhr when possible (thanks to Anthony https://github.com/antho1404)
//New in 1.12 => added get_vsb_blob (returns vsb file as binary)
//New in 1.12 => set viewstl to take all of the container (and not 5px margin)
//New in 1.12 => fixed bug in json_without_nulls function
2021-02-09 18:12:03 +02:00

229 lines
5.0 KiB
JavaScript

//1.12
//load STL file info geometry and returns it
importScripts("parser.min.js");
MSG_DATA=0;
MSG_LOAD=1;
MSG_ERROR=2;
MSG_STL_LOADED=3;
MSG_LOAD_IN_PROGRESS=4;
var filename=null;
var local_file=null;
var load_from_blob_or_ab=null; //from ArrayBuffer
var x=0;
var y=0;
var z=0;
var model_id=-1;
var get_progress=false;
self.addEventListener("message", function(e)
{
switch (e.data.msg_type)
{
case MSG_DATA:
if (!e.data.data) {send_error("no data");break;}
if ((!e.data.data.filename)&&(!e.data.data.local_file)) {send_error("no file");break;}
if (e.data.data.local_file)
{
filename=e.data.data.local_file.name?e.data.data.local_file.name:e.data.data.filename; //filename property is usefull for blob files, 10x Fraser
local_file=e.data.data.local_file?e.data.data.local_file:null;
}
else if (e.data.data.filename)
filename=e.data.data.filename;
if (e.data.data.x) if (isNumeric(e.data.data.x)) x=e.data.data.x;
if (e.data.data.y) if (isNumeric(e.data.data.y)) y=e.data.data.y;
if (e.data.data.y) if (isNumeric(e.data.data.z)) z=e.data.data.z;
load_from_blob_or_ab=null;
if (e.data.load_from_blob_or_ab)
load_from_blob_or_ab=e.data.load_from_blob_or_ab;
model_id=e.data.data.id?e.data.data.id:-1;
get_progress=e.data.get_progress?e.data.get_progress:false;
break;
case MSG_LOAD:
if (load_from_blob_or_ab)
{
//blob/arraybuffer ready to be parsed
if (load_from_blob_or_ab instanceof ArrayBuffer) after_file_load(load_from_blob_or_ab); //arraybuffer
else read_file(load_from_blob_or_ab); //blob
}
else if (local_file)
//local server file (not to confuse with local computer file)
read_file(local_file);
else if (filename)
//url file (assuming accessible for this domain (if NOT, get help here - https://www.viewstl.com/local_url/)
download_from_local(filename);
break;
default:
console.log("invalid msg: "+e.data.msg_type);
}
});
function isNumeric(n)
{
return !isNaN(parseFloat(n)) && isFinite(n);
}
function send_error(s)
{
postMessage({msg_type:MSG_ERROR, data:s});
}
function download_from_local(filename)
{
if (fetch)
{
download_from_local_fetch(filename);
}
else
{
download_from_local_xhr(filename);
}
}
function download_from_local_xhr(filename)
{
var xhr = new XMLHttpRequest();
if (get_progress)
{
xhr.onprogress =
function(e)
{
postMessage({msg_type:MSG_LOAD_IN_PROGRESS, id:model_id, loaded:e.loaded, total:e.total});
}
}
xhr.onreadystatechange =
function(e)
{
if (xhr.readyState == 4)
{
//console.log('status: '+xhr.status);
if (xhr.status==200)
{
//console.log('done');
after_file_load(xhr.response);
}
}
}
xhr.open("GET", filename, true);
//xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.responseType = "arraybuffer";
xhr.send(null);
}
async function download_from_local_fetch(filename)
{
const response = await fetch(filename);
const reader = response.body.getReader();
const total = Number(response.headers.get('content-length'));
const chunksAll = new Uint8Array(total);
let position = 0
while (true)
{
const { done, value } = await reader.read()
if (done) break;
if (!value) continue;
chunksAll.set(value, position);
position += value.length;
if (get_progress)
{
postMessage({ msg_type: MSG_LOAD_IN_PROGRESS, id: model_id, loaded: position, total: total });
}
}
after_file_load(chunksAll.buffer)
}
function after_file_load(s)
{
var vf_data;
if (!s)
{
send_error("no data");
return;
}
try
{
vf_data=parse_3d_file(filename, s);
}
catch(err)
{
vf_data="Error parsing the file";
}
if (typeof vf_data === 'string')
{
send_error(vf_data);
return;
}
postMessage({msg_type:MSG_STL_LOADED, vertices:vf_data.vertices, faces:vf_data.faces, colors:vf_data.colors});
}
function read_file(f)
{
var reader = new FileReader();
reader.onerror = function(e)
{
var error_str="";
switch(e.target.error.code)
{
case e.target.error.NOT_FOUND_ERR:
error_str="File not found";
break;
case e.target.error.NOT_READABLE_ERR:
error_str="Can't read file - too large?";
break;
case e.target.error.ABORT_ERR:
error_str="Read operation aborted";
break;
case e.target.error.SECURITY_ERR:
error_str="File is locked";
break;
case e.target.error.ENCODING_ERR:
error_str="File too large";
break;
default:
error_str="Error reading file";
}
send_error(error_str);
}
reader.onprogress = function(e)
{
postMessage({msg_type:MSG_LOAD_IN_PROGRESS, id:model_id, loaded:e.loaded, total:e.total});
};
reader.onload = function(e)
{
after_file_load(e.target.result);
};
reader.readAsArrayBuffer(f);
}