Commit e686ee26 authored by amandaghassaei's avatar amandaghassaei

starting app

parent ebcfd69c
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&i)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;a(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!==null){define("FileSaver.js",function(){return saveAs})}
This diff is collapsed.
// Written by Paul Kaplan
var geometryToSTLBin = function(geometryArray) {
var writeVector = function(dataview, bufferIndex, vector, offset, orientation, isLittleEndian) {
vector = vector.clone();
if (orientation) vector.applyQuaternion(orientation);
if (offset) vector.add(offset);
bufferIndex = writeFloat(dataview, bufferIndex, vector.x, isLittleEndian);
bufferIndex = writeFloat(dataview, bufferIndex, vector.y, isLittleEndian);
return writeFloat(dataview, bufferIndex, vector.z, isLittleEndian);
};
var writeFloat = function(dataview, bufferIndex, float, isLittleEndian) {
dataview.setFloat32(bufferIndex, float, isLittleEndian);
return bufferIndex + 4;
};
var isLittleEndian = true; // STL files assume little endian, see wikipedia page
var floatData = [];
for (var index = 0;index<geometryArray.length;index++){
var geometry = geometryArray[index].geo;
var orientation = geometryArray[index].orientation;
var offset = geometryArray[index].offset;
if (geometry instanceof THREE.BufferGeometry){
var normals = geometry.attributes.normal.array;
var vertices = geometry.attributes.position.array;
for (var n=0;n<vertices.length;n+=9){
var normal = new THREE.Vector3(normals[n], normals[n+1], normals[n+2]);
var verta = new THREE.Vector3(vertices[n], vertices[n+1], vertices[n+2]);
var vertb = new THREE.Vector3(vertices[n+3], vertices[n+4], vertices[n+5]);
var vertc = new THREE.Vector3(vertices[n+6], vertices[n+7], vertices[n+8]);
floatData.push([normal, verta, vertb, vertc, offset, orientation]);
}
} else {
var tris = geometry.faces;
var verts = geometry.vertices;
for(var n = 0; n < tris.length; n++) {
floatData.push([tris[n].normal, verts[tris[n].a], verts[tris[n].b], verts[tris[n].c], offset, orientation]);
}
}
}
if (floatData.length == 0){
console.warn("no data to write to stl");
return null;
}
//write to DataView
var bufferSize = 84 + (50 * floatData.length);
var buffer = new ArrayBuffer(bufferSize);
var dv = new DataView(buffer);
var bufferIndex = 0;
bufferIndex += 80; // Header is empty
dv.setUint32(bufferIndex, floatData.length, isLittleEndian);
bufferIndex += 4;
for (var i=0;i<floatData.length;i++){
bufferIndex = writeVector(dv, bufferIndex, floatData[i][0], null, floatData[i][5], isLittleEndian);
for (var j=1;j<4;j++){
bufferIndex = writeVector(dv, bufferIndex, floatData[i][j], floatData[i][4], floatData[i][5], isLittleEndian);
}
bufferIndex += 2; // unused 'attribute byte count' is a Uint16
}
return dv;
};
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Origami Simulator</title>
<link href="dependencies/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link rel="stylesheet" type="text/css" href="dependencies/flat-ui.min.css"/>
<link rel="stylesheet" type="text/css" href="dependencies/jquery-ui.min.css"/>
<link rel="stylesheet" type="text/css" href="main.css"/>
<script type="text/javascript" src="dependencies/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="dependencies/jquery-ui.min.js"></script>
<script type="text/javascript" src="dependencies/flat-ui.min.js"></script>
<script type="text/javascript" src="dependencies/three.min.js"></script>
<script type="text/javascript" src="dependencies/binary_stl_writer.js"></script>
<script type="text/javascript" src="dependencies/OrbitControls.js"></script>
<script type="text/javascript" src="dependencies/underscore-min.js"></script>
<script type="text/javascript" src="dependencies/FileSaver.min.js"></script>
<script type="text/javascript" src="js/GLBoilerplate.js"></script>
<script type="text/javascript" src="js/GPUMath.js"></script>
<script type="text/javascript" src="js/controls.js"></script>
<script type="text/javascript" src="js/threeView.js"></script>
<script type="text/javascript" src="js/globals.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div id="threeContainer"></div>
<div id="controlsLeft" class="flipped">
<div>
<a id="logo" target="_blank" href="http://cba.mit.edu/">
<img id="inactiveLogo" src="logo.png"/>
<img id="activeLogo" src="logo-active.png"/>
</a><br/>
3D View:
<div class="indent">
<label class="checkbox" for="dynamic">
<input id="dynamic" data-toggle="checkbox" class="custom-checkbox layersSelector" type="checkbox"><span class="icons"><span class="icon-unchecked"></span><span class="icon-checked"></span></span>
Dynamic Simulation
</label>
<label class="checkbox" for="static">
<input id="static" data-toggle="checkbox" class="custom-checkbox layersSelector" type="checkbox"><span class="icons"><span class="icon-unchecked"></span><span class="icon-checked"></span></span>
Static Simulation
</label>
<label class="checkbox" for="schematic">
<input id="schematic" data-toggle="checkbox" class="custom-checkbox layersSelector" type="checkbox"><span class="icons"><span class="icon-unchecked"></span><span class="icon-checked"></span></span>
Crease Pattern
</label>
</div>
</div>
<br/><br/>
<div class="dynamicSim">
Dynamic Sim Settings:<br/>
<div class="indent">
<div class="sliderContainer">
<span class="label-slider">Damping : </span><div id="damping" class="flat-slider ui-slider ui-corner-all ui-slider-horizontal ui-widget ui-widget-content"></div><br/>
</div>
<a href="#" id="resetDynamicSim" class="btn btn-lg btn-default">Replay Dynamic Simulation</a>
</div>
</div>
<div id="extraSpace"></div>
</div>
<div id="controls">
<a href="#" id="about" class="btn btn-lg btn-default">About</a><br/><br/>
<!--<div class="sliderInput" id="density">-->
<!--<span class="label-slider">Density : </span><div class="flat-slider ui-slider ui-corner-all ui-slider-horizontal ui-widget ui-widget-content"></div>-->
<!--<input value="" placeholder="" class="form-control int" type="text">-->
<!--</div>-->
<!--<div class="sliderInput" id="width">-->
<!--<span class="label-slider">Width (m) : </span><div class="flat-slider ui-slider ui-corner-all ui-slider-horizontal ui-widget ui-widget-content"></div>-->
<!--<input value="" placeholder="" class="form-control int" type="text">-->
<!--</div>-->
<!--<div class="sliderInput" id="length">-->
<!--<span class="label-slider">Length (m) : </span><div class="flat-slider ui-slider ui-corner-all ui-slider-horizontal ui-widget ui-widget-content"></div>-->
<!--<input value="" placeholder="" class="form-control int" type="text">-->
<!--</div>-->
<!--<a href="#" id="addRemoveFixed" class="btn btn-lg btn-default">Add/Remove Fixed Constraint</a>-->
<!--<span class="titleSpan">Available Materials:</span>-->
<!--<div id="materialTypes" class="indent">-->
<!--<label class="radio"><input name="materialTypes" value="none" data-toggle="radio" class="custom-radio" type="radio"><span class="icons"><span class="icon-unchecked"></span><span class="icon-checked"></span></span><span id="noMaterial">No Material Selected</span></label>-->
<!--</div>-->
<!--<a href="#" id="addMaterial" class="btn btn-lg btn-default">+ New Material</a>-->
<!--<div id="extraSpace"></div>-->
</div>
<div class="modal fade" id="aboutModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-body">
<p><b>Origami Simulator</b><br/><br/>
lakfjsdlkfjladskj
<br/>
Built by <a href="http://www.amandaghassaei.com/" target="_blank">Amanda Ghassaei</a> as a homework assignment for <a href="http://courses.csail.mit.edu/6.849/spring17/" target="_blank">Geometric Folding Algorithms</a>.
Code available on <a href="https://github.com/amandaghassaei/OrigamiSimulator" target="_blank">Github</a>.
</p>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</body>
</html>
\ No newline at end of file
//from http://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html
function GLBoilerPlate(){
/**
* Creates and compiles a shader.
*
* @param {!WebGLRenderingContext} gl The WebGL Context.
* @param {string} shaderSource The GLSL source code for the shader.
* @param {number} shaderType The type of shader, VERTEX_SHADER or
* FRAGMENT_SHADER.
* @return {!WebGLShader} The shader.
*/
function compileShader(gl, shaderSource, shaderType) {
// Create the shader object
var shader = gl.createShader(shaderType);
// Set the shader source code.
gl.shaderSource(shader, shaderSource);
// Compile the shader
gl.compileShader(shader);
// Check if it compiled
var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!success) {
// Something went wrong during compilation; get the error
throw "could not compile shader:" + gl.getShaderInfoLog(shader);
}
return shader;
}
/**
* Creates a program from 2 shaders.
*
* @param {!WebGLRenderingContext) gl The WebGL context.
* @param {!WebGLShader} vertexShader A vertex shader.
* @param {!WebGLShader} fragmentShader A fragment shader.
* @return {!WebGLProgram} A program.
*/
function createProgram(gl, vertexShader, fragmentShader) {
// create a program.
var program = gl.createProgram();
// attach the shaders.
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// link the program.
gl.linkProgram(program);
// Check if it linked.
var success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!success) {
// something went wrong with the link
throw ("program filed to link:" + gl.getProgramInfoLog (program));
}
return program;
}
/**
* Creates a shader from the content of a script tag.
*
* @param {!WebGLRenderingContext} gl The WebGL Context.
* @param {string} scriptId The id of the script tag.
* @param {string} opt_shaderType. The type of shader to create.
* If not passed in will use the type attribute from the
* script tag.
* @return {!WebGLShader} A shader.
*/
function createShaderFromSource(gl, shaderSource, shaderType) {
return compileShader(gl, shaderSource, shaderType);
}
/**
* Creates a program from 2 script tags.
*
* @param {!WebGLRenderingContext} gl The WebGL Context.
* @param {string} vertexShaderId The id of the vertex shader script tag.
* @param {string} fragmentShaderId The id of the fragment shader script tag.
* @return {!WebGLProgram} A program
*/
function createProgramFromSource(
gl, vertexShader, fragmentShader) {
var vertexShader = createShaderFromSource(gl, vertexShader, gl.VERTEX_SHADER);
var fragmentShader = createShaderFromSource(gl, fragmentShader, gl.FRAGMENT_SHADER);
return createProgram(gl, vertexShader, fragmentShader);
}
function loadVertexData(gl, program) {
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1,-1, 1,-1, -1, 1, 1, 1]), gl.STATIC_DRAW);
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
}
function makeTexture(gl, width, height, type, data){
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, type, data);
return texture;
}
return {
createProgramFromSource: createProgramFromSource,
loadVertexData: loadVertexData,
makeTexture: makeTexture
}
}
\ No newline at end of file
/**
* Created by ghassaei on 2/24/16.
*/
function initGPUMath(){
var glBoilerplate = GLBoilerPlate();
var canvas = document.getElementById("gpuMathCanvas");
var gl = canvas.getContext("webgl", {antialias:false}) || canvas.getContext("experimental-webgl", {antialias:false});
gl.getExtension('OES_texture_float');
gl.disable(gl.DEPTH_TEST);
var maxTexturesInFragmentShader = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
console.log(maxTexturesInFragmentShader + " textures max");
function GPUMath(){
this.reset();
}
GPUMath.prototype.createProgram = function(programName, vertexShader, fragmentShader){
var programs = this.programs;
var program = programs[name];
if (program) {
console.warn("already a program with the name " + programName);
return;
}
program = glBoilerplate.createProgramFromSource(gl, vertexShader, fragmentShader);
gl.useProgram(program);
glBoilerplate.loadVertexData(gl, program);
programs[programName] = {
program: program,
uniforms: {}
};
};
GPUMath.prototype.initTextureFromData = function(name, width, height, typeName, data, shouldReplace){
var texture = this.textures[name];
if (!shouldReplace && texture) {
console.warn("already a texture with the name " + name);
return;
}
texture = glBoilerplate.makeTexture(gl, width, height, gl[typeName], data);
this.textures[name] = texture;
};
GPUMath.prototype.initFrameBufferForTexture = function(textureName){
var framebuffer = this.frameBuffers[textureName];
if (framebuffer) {
console.warn("framebuffer already exists for texture " + textureName);
return;
}
var texture = this.textures[textureName];
if (!texture){
console.warn("texture " + textureName + " does not exist");
return;
}
framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
this.frameBuffers[textureName] = framebuffer;
};
GPUMath.prototype.setUniformForProgram = function(programName, name, val, type){
if (!this.programs[programName]){
console.warn("no program with name " + programName);
return;
}
var uniforms = this.programs[programName].uniforms;
var location = uniforms[name];
if (!location) {
location = gl.getUniformLocation(this.programs[programName].program, name);
uniforms[name] = location;
}
if (type == "1f") gl.uniform1f(location, val);
else if (type == "2f") gl.uniform2f(location, val[0], val[1]);
else if (type == "3f") gl.uniform3f(location, val[0], val[1], val[2]);
else if (type == "1i") gl.uniform1i(location, val);
else {
console.warn("no uniform for type " + type);
}
};
GPUMath.prototype.setSize = function(width, height){
gl.viewport(0, 0, width, height);
canvas.clientWidth = width;
canvas.clientHeight = height;
};
GPUMath.prototype.setProgram = function(programName){
var program = this.programs[programName];
if (program) gl.useProgram(program.program);
};
GPUMath.prototype.step = function(programName, inputTextures, outputTexture, time){
gl.useProgram(this.programs[programName].program);
if (time) this.setUniformForProgram(programName, "u_time", time, "1f");
gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffers[outputTexture]);
for (var i=0;i<inputTextures.length;i++){
gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, this.textures[inputTextures[i]]);
}
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);//draw to framebuffer
};
GPUMath.prototype.swapTextures = function(texture1Name, texture2Name){
var temp = this.textures[texture1Name];
this.textures[texture1Name] = this.textures[texture2Name];
this.textures[texture2Name] = temp;
temp = this.frameBuffers[texture1Name];
this.frameBuffers[texture1Name] = this.frameBuffers[texture2Name];
this.frameBuffers[texture2Name] = temp;
};
GPUMath.prototype.swap3Textures = function(texture1Name, texture2Name, texture3Name){
var temp = this.textures[texture3Name];
this.textures[texture3Name] = this.textures[texture2Name];
this.textures[texture2Name] = this.textures[texture1Name];
this.textures[texture1Name] = temp;
temp = this.frameBuffers[texture3Name];
this.frameBuffers[texture3Name] = this.frameBuffers[texture2Name];
this.frameBuffers[texture2Name] = this.frameBuffers[texture1Name];
this.frameBuffers[texture1Name] = temp;
};
GPUMath.prototype.readyToRead = function(){
return gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE;
};
GPUMath.prototype.readPixels = function(xMin, yMin, width, height, array){
gl.readPixels(xMin, yMin, width, height, gl.RGBA, gl.UNSIGNED_BYTE, array);
};
GPUMath.prototype.reset = function(){
this.programs = {};
this.frameBuffers = {};
this.textures = {};
this.index = 0;
};
return new GPUMath;
}
\ No newline at end of file
/**
* Created by ghassaei on 10/7/16.
*/
function initControls(globals){
$("#logo").mouseenter(function(){
$("#activeLogo").show();
$("#inactiveLogo").hide();
});
$("#logo").mouseleave(function(){
$("#inactiveLogo").show();
$("#activeLogo").hide();
});
setLink("#about", function(){
$('#aboutModal').modal('show');
});
var dynamicSimVisCallback = function(val){
if (val) $(".dynamicSim").show();
else {
$(".dynamicSim").hide();
}
};
dynamicSimVisCallback(globals.dynamicSimVisible);
setCheckbox("#dynamic", globals.dynamicSimVisible, function(val){
globals.dynamicSimVisible = val;
dynamicSimVisCallback(val);
});
setCheckbox("#static", globals.staticSimVisible, function(val){
globals.staticSimVisible = val;
});
setCheckbox("#schematic", globals.schematicVisible, function(val){
globals.schematicVisible = val;
});
setSlider("#damping", globals.percentDamping, 0.01, 1, 0.01, function(val){
globals.percentDamping = val;
}, function(){
// globals.resetSimFromInitialState();
});
function setButtonGroup(id, callback){
$(id+" a").click(function(e){
e.preventDefault();
var $target = $(e.target);
var val = $target.data("id");
if (val) {
$(id+" span.dropdownLabel").html($target.html());
callback(val);
}
});
}
function setLink(id, callback){
$(id).click(function(e){
e.preventDefault();
callback(e);
});
}
function setRadio(name, val, callback){
$("input[name=" + name + "]").on('change', function() {
var state = $("input[name="+name+"]:checked").val();
callback(state);
});
$(".radio>input[value="+val+"]").prop("checked", true);
}
function setInput(id, val, callback, min, max){
var $input = $(id);
$input.change(function(){
var val = $input.val();
if ($input.hasClass("int")){
if (isNaN(parseInt(val))) return;
val = parseInt(val);
} else {
if (isNaN(parseFloat(val))) return;
val = parseFloat(val);
}
if (min !== undefined && val < min) val = min;
if (max !== undefined && val > max) val = max;
$input.val(val);
callback(val);
});
$input.val(val);
}
function setCheckbox(id, state, callback){
var $input = $(id);
$input.on('change', function () {
if ($input.is(":checked")) callback(true);
else callback(false);
});
$input.prop('checked', state);
}
function setSlider(id, val, min, max, incr, callback, callbackOnStop){
var slider = $(id).slider({
orientation: 'horizontal',
range: false,
value: val,
min: min,
max: max,
step: incr
});
slider.on("slide", function(e, ui){
var val = ui.value;
callback(val);
});
slider.on("slidestop", function(){
var val = slider.slider('value');
if (callbackOnStop) callbackOnStop(val);
})
}
function setLogSliderInput(id, val, min, max, incr, callback){
var scale = (Math.log(max)-Math.log(min)) / (max-min);
var slider = $(id+">div").slider({
orientation: 'horizontal',
range: false,
value: (Math.log(val)-Math.log(min)) / scale + min,
min: min,
max: max,
step: incr
});
var $input = $(id+">input");
$input.change(function(){
var val = $input.val();
if ($input.hasClass("int")){
if (isNaN(parseInt(val))) return;
val = parseInt(val);
} else {
if (isNaN(parseFloat(val))) return;
val = parseFloat(val);
}
var min = slider.slider("option", "min");
if (val < min) val = min;
if (val > max) val = max;
$input.val(val);
slider.slider('value', (Math.log(val)-Math.log(min)) / scale + min);
callback(val, id);
});
$input.val(val);
slider.on("slide", function(e, ui){
var val = ui.value;
val = Math.exp(Math.log(min) + scale*(val-min));
$input.val(val.toFixed(4));
callback(val, id);
});
}
function setSliderInput(id, val, min, max, incr, callback){
var slider = $(id+">div").slider({
orientation: 'horizontal',
range: false,
value: val,
min: min,
max: max,
step: incr
});
var $input = $(id+">input");
$input.change(function(){
var val = $input.val();
if ($input.hasClass("int")){