Now allows STL download on Firefox as well; better error reporting if browser lacks WebGL support
This commit is contained in:
parent
8c3aaac16d
commit
fb5cf38207
3 changed files with 146 additions and 134 deletions
1
csg.js
1
csg.js
|
@ -773,6 +773,7 @@ CSG.roundedCylinder = function(options) {
|
|||
for(var slice2 = 0; slice2 <= qresolution; slice2++)
|
||||
{
|
||||
var pitch = 0.5 * Math.PI * slice2 / qresolution;
|
||||
//var pitch = Math.asin(slice2/qresolution);
|
||||
var cospitch = Math.cos(pitch);
|
||||
var sinpitch = Math.sin(pitch);
|
||||
if(slice2 > 0)
|
||||
|
|
|
@ -110,6 +110,8 @@ without the need to edit the source script. See the <a href="gearsdemo.html">Gea
|
|||
<li>Properties and Connectors (see below) make it very easy to attach objects to each other at predetermined
|
||||
points, even if you don't know the actual orientation or size.</li>
|
||||
<li>Extensive built in <a href="#math">support for 2D and 3D math</a> (classes for Vector2D, Vector3D, Plane, Line3D, Line2D)</li>
|
||||
<li>Debugging support: step through your code, set breakpoints, inspect variables, etc. See the
|
||||
<a href="processfile.html">OpenJsCad parser</a> for details.</li>
|
||||
</ul>
|
||||
<h2>Viewer navigation</h2>
|
||||
Click and drag to rotate the model around the origin.<br>
|
||||
|
@ -278,7 +280,7 @@ var rounded = csg.expand(0.2, 8);
|
|||
</pre>
|
||||
|
||||
<h2>Using Properties</h2>
|
||||
The 'property' property of a solid can be used to store metdata for the object,
|
||||
The 'property' property of a solid can be used to store metadata for the object,
|
||||
for example the coordinate of a specific point of interest of the solid. Whenever
|
||||
the object is transformed (i.e. rotated, scaled or translated), the properties
|
||||
are transformed with it. So the property will keep pointing to the same point
|
||||
|
|
275
openjscad.js
275
openjscad.js
|
@ -4,87 +4,81 @@ OpenJsCad = function() {
|
|||
// A viewer is a WebGL canvas that lets the user view a mesh. The user can
|
||||
// tumble it around by dragging the mouse.
|
||||
OpenJsCad.Viewer = function(containerelement, width, height, initialdepth) {
|
||||
try
|
||||
{
|
||||
var gl = GL.create();
|
||||
this.gl = gl;
|
||||
this.angleX = 0;
|
||||
this.angleY = 0;
|
||||
this.viewpointX = 0;
|
||||
this.viewpointY = 0;
|
||||
this.viewpointZ = initialdepth;
|
||||
var gl = GL.create();
|
||||
this.gl = gl;
|
||||
this.angleX = 0;
|
||||
this.angleY = 0;
|
||||
this.viewpointX = 0;
|
||||
this.viewpointY = 0;
|
||||
this.viewpointZ = initialdepth;
|
||||
|
||||
// Draw triangle lines:
|
||||
this.drawLines = false;
|
||||
// Set to true so lines don't use the depth buffer
|
||||
this.lineOverlay = false;
|
||||
|
||||
// Set up the viewport
|
||||
gl.canvas.width = width;
|
||||
gl.canvas.height = height;
|
||||
gl.viewport(0, 0, width, height);
|
||||
gl.matrixMode(gl.PROJECTION);
|
||||
gl.loadIdentity();
|
||||
gl.perspective(45, width / height, 0.5, 1000);
|
||||
gl.matrixMode(gl.MODELVIEW);
|
||||
|
||||
// Set up WebGL state
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
gl.clearColor(0.93, 0.93, 0.93, 1);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
gl.polygonOffset(1, 1);
|
||||
|
||||
// Black shader for wireframe
|
||||
this.blackShader = new GL.Shader('\
|
||||
void main() {\
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\
|
||||
}\
|
||||
', '\
|
||||
void main() {\
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);\
|
||||
}\
|
||||
');
|
||||
|
||||
// Shader with diffuse and specular lighting
|
||||
this.lightingShader = new GL.Shader('\
|
||||
varying vec3 color;\
|
||||
varying vec3 normal;\
|
||||
varying vec3 light;\
|
||||
void main() {\
|
||||
const vec3 lightDir = vec3(1.0, 2.0, 3.0) / 3.741657386773941;\
|
||||
light = lightDir;\
|
||||
color = gl_Color.rgb;\
|
||||
normal = gl_NormalMatrix * gl_Normal;\
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\
|
||||
}\
|
||||
', '\
|
||||
varying vec3 color;\
|
||||
varying vec3 normal;\
|
||||
varying vec3 light;\
|
||||
void main() {\
|
||||
vec3 n = normalize(normal);\
|
||||
float diffuse = max(0.0, dot(light, n));\
|
||||
float specular = pow(max(0.0, -reflect(light, n).z), 10.0) * sqrt(diffuse);\
|
||||
gl_FragColor = vec4(mix(color * (0.3 + 0.7 * diffuse), vec3(1.0), specular), 1.0);\
|
||||
}\
|
||||
');
|
||||
// Draw triangle lines:
|
||||
this.drawLines = false;
|
||||
// Set to true so lines don't use the depth buffer
|
||||
this.lineOverlay = false;
|
||||
|
||||
containerelement.appendChild(gl.canvas);
|
||||
|
||||
var _this=this;
|
||||
// Set up the viewport
|
||||
gl.canvas.width = width;
|
||||
gl.canvas.height = height;
|
||||
gl.viewport(0, 0, width, height);
|
||||
gl.matrixMode(gl.PROJECTION);
|
||||
gl.loadIdentity();
|
||||
gl.perspective(45, width / height, 0.5, 1000);
|
||||
gl.matrixMode(gl.MODELVIEW);
|
||||
|
||||
gl.onmousemove = function(e) {
|
||||
_this.onMouseMove(e);
|
||||
};
|
||||
gl.ondraw = function() {
|
||||
_this.onDraw();
|
||||
};
|
||||
this.clear();
|
||||
}
|
||||
catch (e) {
|
||||
containerelement.innerHTML = "<b><br><br>Error: "+e.toString()+"</b><br><br>OpenJsCad currently requires Google Chrome with WebGL enabled";
|
||||
}
|
||||
// Set up WebGL state
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
gl.clearColor(0.93, 0.93, 0.93, 1);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
gl.polygonOffset(1, 1);
|
||||
|
||||
// Black shader for wireframe
|
||||
this.blackShader = new GL.Shader('\
|
||||
void main() {\
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\
|
||||
}\
|
||||
', '\
|
||||
void main() {\
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);\
|
||||
}\
|
||||
');
|
||||
|
||||
// Shader with diffuse and specular lighting
|
||||
this.lightingShader = new GL.Shader('\
|
||||
varying vec3 color;\
|
||||
varying vec3 normal;\
|
||||
varying vec3 light;\
|
||||
void main() {\
|
||||
const vec3 lightDir = vec3(1.0, 2.0, 3.0) / 3.741657386773941;\
|
||||
light = lightDir;\
|
||||
color = gl_Color.rgb;\
|
||||
normal = gl_NormalMatrix * gl_Normal;\
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\
|
||||
}\
|
||||
', '\
|
||||
varying vec3 color;\
|
||||
varying vec3 normal;\
|
||||
varying vec3 light;\
|
||||
void main() {\
|
||||
vec3 n = normalize(normal);\
|
||||
float diffuse = max(0.0, dot(light, n));\
|
||||
float specular = pow(max(0.0, -reflect(light, n).z), 10.0) * sqrt(diffuse);\
|
||||
gl_FragColor = vec4(mix(color * (0.3 + 0.7 * diffuse), vec3(1.0), specular), 1.0);\
|
||||
}\
|
||||
');
|
||||
|
||||
containerelement.appendChild(gl.canvas);
|
||||
|
||||
var _this=this;
|
||||
|
||||
gl.onmousemove = function(e) {
|
||||
_this.onMouseMove(e);
|
||||
};
|
||||
gl.ondraw = function() {
|
||||
_this.onDraw();
|
||||
};
|
||||
this.clear();
|
||||
};
|
||||
|
||||
OpenJsCad.Viewer.prototype = {
|
||||
|
@ -470,7 +464,9 @@ OpenJsCad.Processor.prototype = {
|
|||
{
|
||||
this.viewer = new OpenJsCad.Viewer(this.viewerdiv, this.viewerwidth, this.viewerheight, this.initialViewerDistance);
|
||||
} catch (e) {
|
||||
this.viewerdiv.innerHTML = e.toString();
|
||||
// this.viewer = null;
|
||||
this.viewerdiv.innerHTML = "<b><br><br>Error: "+e.toString()+"</b><br><br>OpenJsCad currently requires Google Chrome with WebGL enabled";
|
||||
// this.viewerdiv.innerHTML = e.toString();
|
||||
}
|
||||
this.errordiv = document.createElement("div");
|
||||
this.errorpre = document.createElement("pre");
|
||||
|
@ -728,18 +724,6 @@ OpenJsCad.Processor.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
generateStl1: function() {
|
||||
this.clearStl();
|
||||
if(this.validcsg)
|
||||
{
|
||||
var stltxt = this.solid.toStlString();
|
||||
this.stlBlobUrl = OpenJsCad.textToBlobUrl(stltxt);
|
||||
this.hasstl = true;
|
||||
this.downloadStlLink.href = this.stlBlobUrl;
|
||||
this.enableItems();
|
||||
if(this.onchange) this.onchange();
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
clearStl: function() {
|
||||
|
@ -751,63 +735,88 @@ OpenJsCad.Processor.prototype = {
|
|||
this.stlDirEntry.removeRecursively(function(){});
|
||||
this.stlDirEntry=null;
|
||||
}
|
||||
if(this.stlBlobUrl)
|
||||
{
|
||||
OpenJsCad.revokeBlobUrl(this.stlBlobUrl);
|
||||
this.stlBlobUrl = null;
|
||||
}
|
||||
this.enableItems();
|
||||
if(this.onchange) this.onchange();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
generateStl: function() {
|
||||
this.clearStl();
|
||||
if(this.validcsg)
|
||||
{
|
||||
var stltxt = this.solid.toStlString();
|
||||
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
|
||||
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
|
||||
if(!window.requestFileSystem)
|
||||
try
|
||||
{
|
||||
throw new Error("Your browser does not support the HTML5 FileSystem API. Please try the Chrome browser instead.");
|
||||
this.generateStlFileSystem();
|
||||
}
|
||||
if(!window.BlobBuilder)
|
||||
catch(e)
|
||||
{
|
||||
throw new Error("Your browser does not support the HTML5 BlobBuilder API. Please try the Chrome browser instead.");
|
||||
this.generateStlBlobUrl();
|
||||
}
|
||||
// create a random directory name:
|
||||
var dirname = "OpenJsCadStlOutput1_"+parseInt(Math.random()*1000000000, 10)+".stl";
|
||||
var filename = this.filename+".stl";
|
||||
var that = this;
|
||||
window.requestFileSystem(TEMPORARY, 20*1024*1024, function(fs){
|
||||
fs.root.getDirectory(dirname, {create: true, exclusive: true}, function(dirEntry) {
|
||||
that.stlDirEntry = dirEntry;
|
||||
dirEntry.getFile(filename, {create: true, exclusive: true}, function(fileEntry) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
fileWriter.onwriteend = function(e) {
|
||||
that.hasstl = true;
|
||||
that.downloadStlLink.href = fileEntry.toURL();
|
||||
that.enableItems();
|
||||
if(that.onchange) that.onchange();
|
||||
};
|
||||
fileWriter.onerror = function(e) {
|
||||
throw new Error('Write failed: ' + e.toString());
|
||||
};
|
||||
// Create a new Blob and write it to log.txt.
|
||||
var bb = new window.BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
|
||||
bb.append(stltxt);
|
||||
fileWriter.write(bb.getBlob());
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "createWriter");}
|
||||
);
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "getFile('"+filename+"')");}
|
||||
);
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "getDirectory('"+dirname+"')");}
|
||||
);
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "requestFileSystem");}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
generateStlBlobUrl: function() {
|
||||
var stltxt = this.solid.toStlString();
|
||||
this.stlBlobUrl = OpenJsCad.textToBlobUrl(stltxt);
|
||||
this.hasstl = true;
|
||||
this.downloadStlLink.href = this.stlBlobUrl;
|
||||
this.enableItems();
|
||||
if(this.onchange) this.onchange();
|
||||
},
|
||||
|
||||
generateStlFileSystem: function() {
|
||||
var stltxt = this.solid.toStlString();
|
||||
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
|
||||
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
|
||||
if(!window.requestFileSystem)
|
||||
{
|
||||
throw new Error("Your browser does not support the HTML5 FileSystem API. Please try the Chrome browser instead.");
|
||||
}
|
||||
if(!window.BlobBuilder)
|
||||
{
|
||||
throw new Error("Your browser does not support the HTML5 BlobBuilder API. Please try the Chrome browser instead.");
|
||||
}
|
||||
// create a random directory name:
|
||||
var dirname = "OpenJsCadStlOutput1_"+parseInt(Math.random()*1000000000, 10)+".stl";
|
||||
var filename = this.filename+".stl";
|
||||
var that = this;
|
||||
window.requestFileSystem(TEMPORARY, 20*1024*1024, function(fs){
|
||||
fs.root.getDirectory(dirname, {create: true, exclusive: true}, function(dirEntry) {
|
||||
that.stlDirEntry = dirEntry;
|
||||
dirEntry.getFile(filename, {create: true, exclusive: true}, function(fileEntry) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
fileWriter.onwriteend = function(e) {
|
||||
that.hasstl = true;
|
||||
that.downloadStlLink.href = fileEntry.toURL();
|
||||
that.enableItems();
|
||||
if(that.onchange) that.onchange();
|
||||
};
|
||||
fileWriter.onerror = function(e) {
|
||||
throw new Error('Write failed: ' + e.toString());
|
||||
};
|
||||
// Create a new Blob and write it to log.txt.
|
||||
var bb = new window.BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
|
||||
bb.append(stltxt);
|
||||
fileWriter.write(bb.getBlob());
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "createWriter");}
|
||||
);
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "getFile('"+filename+"')");}
|
||||
);
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "getDirectory('"+dirname+"')");}
|
||||
);
|
||||
},
|
||||
function(fileerror){OpenJsCad.FileSystemApiErrorHandler(fileerror, "requestFileSystem");}
|
||||
);
|
||||
},
|
||||
|
||||
createParamControls: function() {
|
||||
this.parameterstable.innerHTML = "";
|
||||
this.paramControls = [];
|
||||
|
|
Loading…
Add table
Reference in a new issue