Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
422 lines (348 sloc) 11.2 KB
// -----------------------------------------------------------------------------
// Variables
// -----------------------------------------------------------------------------
//window.localStorage.clear();
var settings = new SLAcer.Settings({
file: {
panel: {
collapsed: false,
position : 0
}
},
mesh: {
color: 0x333333,
panel: {
collapsed: false,
position : 1
}
},
slicer: {
layers: {
height: 100 // μm
},
panel: {
collapsed: false,
position : 2
}
},
buildVolume: {
size : { x: 100, y: 100, z: 100 }, // mm
unit : 'mm', // mm or in
color : 0xcccccc,
opacity : 0.1,
panel : {
collapsed: false,
position : 3
}
},
resin: {
density : 1.1, // g/cm3
price : 50, // $
panel : {
collapsed: false,
position : 4
}
},
screen: {
width : 1680,
height : 1050,
diagonal : { size: 22, unit: 'in' },
panel : {
collapsed: false,
position : 5
}
},
viewer3d: {
color: 0xffffff
}
});
// -----------------------------------------------------------------------------
// Error handler
// -----------------------------------------------------------------------------
function errorHandler(error) {
console.error(error);
}
// -----------------------------------------------------------------------------
// Slicer
// -----------------------------------------------------------------------------
var slicer = new SLAcer.Slicer();
var shapes;
function removeShapes() {
if (shapes && shapes.length) {
for (var i = 0, il = shapes.length; i < il; i++) {
viewer3d.removeObject(shapes[i]);
}
}
}
function slice(layerNumber) {
// remove old shapes
removeShapes();
if (layerNumber < 1) {
viewer3d.render();
return;
}
// get slice
var layerHeight = settings.get('slicer.layers.height') / 1000;
var zPosition = layerNumber * layerHeight;
var slice = slicer.getFaces(zPosition);
//console.log('layer number:', layerNumber);
//console.log('z position :', zPosition);
// get new shapes list
shapes = slice.shapes;
zPosition -= settings.get('buildVolume.size.z') / 2;
// add new shapes
for (var i = 0, il = shapes.length; i < il; i++) {
shapes[i].position.z = zPosition;
shapes[i].material.depthTest = false;
viewer3d.scene.add(shapes[i]);
}
// render
viewer3d.render();
}
// -----------------------------------------------------------------------------
// UI
// -----------------------------------------------------------------------------
// Main container
var $main = $('#main');
// Viewer 3D
var $viewer3d = $('#viewer3d');
var viewer3d = new SLAcer.Viewer3D({
color : settings.get('viewer3d.color'),
buildVolume: settings.get('buildVolume'),
target : $viewer3d[0]
});
// Triangulation algorithm
//THREE.Triangulation.setTimer(true);
THREE.Triangulation.setLibrary('earcut');
//THREE.Triangulation.setLibrary('libtess');
//THREE.Triangulation.setLibrary('poly2tri');
// Slider
var $sliderInput = $('#slider input');
$sliderInput.slider({ reversed : true }).on('change', function(e) {
slice(e.value.newValue);
});
var $sliderElement = $('#slider .slider');
var $sliderMinValue = $('#slider .min');
var $sliderMaxValue = $('#slider .max');
// Sidebar
var $sidebar = $('#sidebar');
var $panels = $sidebar.find('.panel');
$sidebar.sortable({
axis : 'y',
handle : '.panel-heading',
cancel : '.panel-toggle',
placeholder: 'panel-placeholder', forcePlaceholderSize: true,
// update panel position
stop: function(e, ui) {
$sidebar.find('.panel').each(function(i, element) {
settings.set(_.camelCase(element.id) + '.panel.position', i);
});
}
});
// Sort panels
var panels = [];
var panel;
_.forEach(settings.settings, function(item, namespace) {
if (item && item.panel) {
panels[item.panel.position] = $('#' + _.kebabCase(namespace));
}
});
for (var i in panels) {
$sidebar.append(panels[i]);
}
// Init panel
function initPanel(name) {
var id = _.kebabCase(name);
var name = _.camelCase(name);
var $body = $('#' + id + '-body');
$body.on('hidden.bs.collapse', function () {
settings.set(name + '.panel.collapsed', true);
});
$body.on('shown.bs.collapse', function () {
settings.set(name + '.panel.collapsed', false);
});
if (settings.get(name + '.panel.collapsed')) {
$body.collapse('hide');
}
return $body;
}
// Unit converter
function parseUnit(value, unit) {
return parseFloat(unit == 'in' ? (value / 25.4) : (value * 25.4));
}
// File panel
var $fileBody = initPanel('file');
// Mesh panel
var $meshBody = initPanel('mesh');
var $meshFaces = $meshBody.find('#mesh-faces');
var $meshVolume = $meshBody.find('#mesh-volume');
var $meshWeight = $meshBody.find('#mesh-weight');
var $meshSizeX = $meshBody.find('#mesh-size-x');
var $meshSizeY = $meshBody.find('#mesh-size-y');
var $meshSizeZ = $meshBody.find('#mesh-size-z');
var $meshSizeUnit = $meshBody.find('.mesh-size-unit');
function updateMeshInfoUI(mesh) {
var size = mesh.getSize();
var unit = settings.get('buildVolume.unit');
var layersHeight = settings.get('slicer.layers.height') / 1000;
var layersNumber = Math.ceil(size.z / layersHeight);
$sliderInput.slider('setAttribute', 'max', layersNumber);
$sliderMaxValue.html(layersNumber);
$meshSizeUnit.html(unit);
if (unit == 'in') {
size.x = parseUnit(size.x, 'in');
size.y = parseUnit(size.y, 'in');
size.z = parseUnit(size.z, 'in');
}
$meshSizeX.html(size.x.toFixed(2));
$meshSizeY.html(size.y.toFixed(2));
$meshSizeZ.html(size.z.toFixed(2));
$meshFaces.html(mesh.geometry.faces.length);
$meshVolume.html(parseInt(mesh.getVolume() / 1000)); // cm3/ml
$meshWeight.html(0);
}
// Slicer panel
var $slicerBody = initPanel('slicer');
// Build volume panel
var $buildVolumeBody = initPanel('buildVolume');
var $buildVolumeX = $buildVolumeBody.find('#build-volume-x');
var $buildVolumeY = $buildVolumeBody.find('#build-volume-y');
var $buildVolumeZ = $buildVolumeBody.find('#build-volume-z');
function updateBuildVolumeUI() {
var buildVolume = settings.get('buildVolume');
$buildVolumeX.val(buildVolume.size.x);
$buildVolumeY.val(buildVolume.size.y);
$buildVolumeZ.val(buildVolume.size.z);
}
function updateBuildVolumeSettings() {
var unit = $('#build-volume input[type=radio]:checked').val();
if (unit != settings.get('buildVolume.diagonal.unit')) {
var size = settings.get('buildVolume.size');
$buildVolumeX.val(parseUnit(size.x, unit));
$buildVolumeY.val(parseUnit(size.y, unit));
$buildVolumeZ.val(parseUnit(size.z, unit));
}
settings.set('buildVolume', {
size: {
x: $buildVolumeX.val(),
y: $buildVolumeY.val(),
z: $buildVolumeZ.val()
},
unit: unit
});
if (size) {
updateMeshInfoUI(slicer.mesh);
}
}
$('#build-volume-unit-' + settings.get('buildVolume.unit')).prop('checked', true);
$('#build-volume input[type=radio]').on('change', updateBuildVolumeSettings);
$('#build-volume input').on('input', updateBuildVolumeSettings);
updateBuildVolumeUI();
// Resin panel
var $resinBody = initPanel('resin');
var $resinPrice = $resinBody.find('#resin-price');
var $resinDensity = $resinBody.find('#resin-density');
function updateResinUI() {
var resin = settings.get('resin');
$resinDensity.val(resin.density);
$resinPrice.val(resin.price);
}
function updateResinSettings() {
settings.set('resin.price' , $resinPrice.val());
settings.set('resin.density', $resinDensity.val());
}
$('#resin input').on('input', updateResinSettings);
updateResinUI();
// Screen
var $screenBody = initPanel('screen');
var $screenWidth = $screenBody.find('#screen-width');
var $screenHeight = $screenBody.find('#screen-height');
var $screenDiagonalSize = $screenBody.find('#screen-diagonal-size');
function updateScreenUI() {
var screen = settings.get('screen');
$screenWidth.val(screen.width);
$screenHeight.val(screen.height);
$screenDiagonalSize.val(screen.diagonal.size);
}
function updateScreenSettings() {
var unit = $('#screen input[type=radio]:checked').val();
if (unit != settings.get('screen.diagonal.unit')) {
$screenDiagonalSize.val(
parseUnit(settings.get('screen.diagonal.size'), unit)
);
}
settings.set('screen', {
width : $screenWidth.val(),
height : $screenHeight.val(),
diagonal: {
size: $screenDiagonalSize.val(),
unit: unit
}
});
}
$('#screen-diagonal-unit-' + settings.get('screen.diagonal.unit')).prop('checked', true);
$('#screen input[type=radio]').on('change', updateScreenSettings);
$('#screen input').on('input', updateScreenSettings);
updateScreenUI();
// UI resize
function resizeUI() {
var width = $main.width();
var height = $main.height();
$sliderElement.height(height - 80);
viewer3d.setSize({ width : width, height: height });
viewer3d.render();
}
$(window).resize(resizeUI);
resizeUI();
// -----------------------------------------------------------------------------
// STL loader
// -----------------------------------------------------------------------------
// Loader instance
var loader = new MeshesJS.STLLoader($main[0]); // drop target
// On Geometry loaded
loader.onGeometry = function(geometry) {
try {
// remove old mesh and plane
slicer.mesh && viewer3d.removeObject(slicer.mesh);
// remove old shapes
removeShapes();
// load new mesh in slicer
slicer.loadMesh(new SLAcer.Mesh(geometry, new THREE.MeshPhongMaterial({
color: settings.get('mesh.color')
})));
// add new mesh and render view
viewer3d.addObject(slicer.mesh);
viewer3d.render();
// update mesh info
updateMeshInfoUI(slicer.mesh);
// get first slice
//slice(1);
}
catch(e) {
errorHandler(e);
}
};
// On loading error
loader.onError = errorHandler;
// -----------------------------------------------------------------------------
// load example
// -----------------------------------------------------------------------------
// example STL file
//var stl = 'stl/Octocat-v2.stl';
var stl = 'stl/StressTest.stl';
// File url
var url = 'http://' + window.location.hostname + window.location.pathname + stl;
// Create http request object
var xmlhttp = new XMLHttpRequest();
// Get the file contents
xmlhttp.open("GET", url);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if(xmlhttp.status == 200){
loader.loadString(xmlhttp.responseText);
}else{
errorHandler('xmlhttp: ' + xmlhttp.statusText);
}
}
}
xmlhttp.send();