jquery, coffeescript added. simple.html for a simple editor, which should look and work like openscad.
parent
c6a95b7de4
commit
6bb529834f
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,693 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="lightgl.js"></script>
|
||||
<script src="csg.js"></script>
|
||||
<script src="openjscad.js"></script>
|
||||
<script src="jquery.js"></script>
|
||||
<script src="coffee-script.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font: 14px/20px 'Helvetica Neue Light', HelveticaNeue-Light, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
pre, code, textarea {
|
||||
font: 12px/20px Monaco, monospace;
|
||||
border: 1px solid #CCC;
|
||||
border-radius: 3px;
|
||||
background: #F9F9F9;
|
||||
padding: 0 3px;
|
||||
color: #555;
|
||||
}
|
||||
pre, textarea {
|
||||
padding: 10px;
|
||||
}
|
||||
pre {
|
||||
width: 100%;
|
||||
}
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
canvas {
|
||||
cursor: move;
|
||||
}
|
||||
header > *{
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="openjscad.css" type="text/css">
|
||||
<script>
|
||||
|
||||
var gProcessor=null;
|
||||
|
||||
// Show all exceptions to the user:
|
||||
OpenJsCad.AlertUserOfUncaughtExceptions();
|
||||
|
||||
function onload() {
|
||||
gProcessor = new OpenJsCad.Processor(document.getElementById("viewer"));
|
||||
updateSolid();
|
||||
}
|
||||
|
||||
function getCode() {
|
||||
var code = document.getElementById('code').value;
|
||||
var lang = document.getElementById('lang').value;
|
||||
if( 'CoffeeScript' === lang)
|
||||
code = CoffeeScript.compile( code, { bare: 'on'});
|
||||
return code;
|
||||
}
|
||||
|
||||
function updateSolid() {
|
||||
gProcessor.setJsCad( getCode());
|
||||
}
|
||||
|
||||
/* http://pallieter.org/Projects/insertTab/ */
|
||||
function insertTab(o, e) {
|
||||
var kC = e.keyCode ? e.keyCode : e.charCode ? e.charCode : e.which;
|
||||
if (kC == 9 && !e.shiftKey && !e.ctrlKey && !e.altKey) {
|
||||
var oS = o.scrollTop;
|
||||
if (o.setSelectionRange) {
|
||||
var sS = o.selectionStart;
|
||||
var sE = o.selectionEnd;
|
||||
o.value = o.value.substring(0, sS) + "\t" + o.value.substr(sE);
|
||||
o.setSelectionRange(sS + 1, sS + 1);
|
||||
o.focus();
|
||||
}
|
||||
else if (o.createTextRange) {
|
||||
document.selection.createRange().text = "\t";
|
||||
e.returnValue = false;
|
||||
}
|
||||
o.scrollTop = oS;
|
||||
if (e.preventDefault)
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
hist = [];
|
||||
function edit_history(event) {
|
||||
}
|
||||
</script>
|
||||
<title>OpenJsCad</title>
|
||||
</head>
|
||||
|
||||
<body onload="onload()">
|
||||
<header>
|
||||
<h1>OpenJsCad</h1>
|
||||
[<a href='#' onclick="updateSolid(); return false;">Update</a>]
|
||||
</header>
|
||||
|
||||
<div id="viewer" style="float:right;"></div>
|
||||
|
||||
<div id="editor">
|
||||
<textarea id="code" name="code" onkeydown="r=insertTab(this, event);edit_history(event);return r">main = ->
|
||||
resolution = 24; # increase to get smoother corners (will get slow!)
|
||||
|
||||
cube1 = CSG.roundedCube center: [0,0,0], radius: [10,10,10], roundradius: 2, resolution: resolution
|
||||
sphere1 = CSG.sphere center: [5, 5, 5], radius: 10, resolution: resolution
|
||||
sphere2 = sphere1.translate [12, 5, 0]
|
||||
sphere3 = CSG.sphere center: [20, 0, 0], radius: 30, resolution: resolution
|
||||
|
||||
result = cube1
|
||||
result = result.union sphere1
|
||||
result = result.subtract sphere2
|
||||
result = result.intersect sphere3
|
||||
result</textarea>
|
||||
<br>
|
||||
<select id="lang" name="lang">
|
||||
<option>JavaScript</option>
|
||||
<option selected>CoffeeScript</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="help" style="display:none">
|
||||
<h2>Primitive solids</h2>
|
||||
Currently the following solids are supported. The parameters are passed in an object; most
|
||||
parameters are optional. 3D vectors can be passed in an array. If a scalar is passed
|
||||
for a parameter which expects a 3D vector, it is used for the x, y and z value.
|
||||
In other words: <code>radius: 1</code> will give <code>radius: [1,1,1]</code>.
|
||||
<br><br>
|
||||
All rounded solids have a 'resolution' parameter which controls tesselation. If resolution
|
||||
is set to 8, then 8 polygons per 360 degree of revolution are used. Beware that rendering
|
||||
time will increase dramatically when increasing the resolution. For a sphere the number of polygons
|
||||
increases quadratically with the resolution used.
|
||||
<br><br>
|
||||
<pre>
|
||||
// a cube:
|
||||
var cube = CSG.cube({
|
||||
center: [0, 0, 0],
|
||||
radius: [1, 1, 1]
|
||||
});
|
||||
|
||||
// a sphere:
|
||||
var sphere = CSG.sphere({
|
||||
center: [0, 0, 0],
|
||||
radius: 2, // must be scalar
|
||||
resolution: 32
|
||||
});
|
||||
|
||||
// a cylinder:
|
||||
var cylinder = CSG.cylinder({
|
||||
start: [0, -1, 0],
|
||||
end: [0, 1, 0],
|
||||
radius: 1,
|
||||
resolution: 16
|
||||
});
|
||||
|
||||
// like a cylinder, but with spherical endpoints:
|
||||
var roundedCylinder = CSG.roundedCylinder({
|
||||
start: [0, -1, 0],
|
||||
end: [0, 1, 0],
|
||||
radius: 1,
|
||||
resolution: 16
|
||||
});
|
||||
|
||||
// a rounded cube:
|
||||
var cube = CSG.roundedCube({
|
||||
center: [0, 0, 0],
|
||||
radius: 1,
|
||||
roundradius: 0.2,
|
||||
resolution: 8,
|
||||
});
|
||||
</pre>
|
||||
|
||||
<h2>CSG operations</h2>
|
||||
The 3 standard CSG operations are supported. All CSG operations return a new solid; the source solids
|
||||
are not modified:
|
||||
<pre>
|
||||
var csg1 = cube.union(sphere);
|
||||
var csg2 = cube.intersect(sphere);
|
||||
var csg3 = cube.subtract(sphere);
|
||||
</pre>
|
||||
|
||||
<h2>Transformations</h2>
|
||||
Solids can be translated, scaled and rotated. Multiple transforms can be combined into a single matrix transform.
|
||||
For <a href="#math">matrix and vector math see below</a>.
|
||||
<pre>
|
||||
var cube = CSG.cube();
|
||||
|
||||
// translation:
|
||||
var cube2 = cube.translate([1, 2, 3]);
|
||||
|
||||
// scaling:
|
||||
var largecube = cube.scale(2.0);
|
||||
var stretchedcube = cube.scale([1.5, 1, 0.5]);
|
||||
|
||||
// rotation:
|
||||
var rotated1 = cube.rotateX(-45); // rotate around the X axis
|
||||
var rotated2 = cube.rotateY(90); // rotate around the Y axis
|
||||
var rotated3 = cube.rotateZ(20); // rotate around the Z axis
|
||||
|
||||
// combine multiple transforms into a single matrix transform:
|
||||
var m = new CSG.Matrix4x4();
|
||||
m = m.multiply(CSG.Matrix4x4.rotationX(40));
|
||||
m = m.multiply(CSG.Matrix4x4.rotationZ(40));
|
||||
m = m.multiply(CSG.Matrix4x4.translation([-.5, 0, 0]));
|
||||
m = m.multiply(CSG.Matrix4x4.scaling([1.1, 1.2, 1.3]));
|
||||
|
||||
// and apply the transform:
|
||||
var cube3 = cube.transform(m);
|
||||
</pre>
|
||||
|
||||
<h2>Mirroring</h2>
|
||||
Solids can be mirrored in any plane in 3D space. For <a href="#math">plane math see below</a>.
|
||||
<pre>
|
||||
var cube = CSG.cube().translate([1,0,0]);
|
||||
|
||||
var cube2 = cube.mirroredX(); // mirrored in the x=0 plane
|
||||
var cube3 = cube.mirroredY(); // mirrored in the y=0 plane
|
||||
var cube4 = cube.mirroredZ(); // mirrored in the z=0 plane
|
||||
|
||||
// create a plane by specifying 3 points:
|
||||
var plane = CSG.Plane.fromPoints([5,0,0], [5, 1, 0], [3, 1, 7]);
|
||||
|
||||
// and mirror in that plane:
|
||||
var cube5 = cube.mirrored(plane);
|
||||
</pre>
|
||||
|
||||
<h2>Cutting by a plane</h2>
|
||||
A solid can be cut by a plane; only the part on the back side is kept:
|
||||
|
||||
<pre>
|
||||
var cube = CSG.cube({radius: 10});
|
||||
|
||||
// create a plane by specifying 3 points:
|
||||
var plane1 = CSG.Plane.fromPoints([5,0,0], [7, 1, 0], [3, 1, 7]);
|
||||
|
||||
// or by specifying a normal and a point on the plane:
|
||||
var plane2 = CSG.Plane.fromNormalAndPoint([3, 1, 2], [5, 0, 0]);
|
||||
|
||||
// and cut by the plane:
|
||||
var part1 = cube.cutByPlane(plane2);
|
||||
|
||||
// or if we need the other half of the cube:
|
||||
var part2 = cube.cutByPlane(plane2.flipped());
|
||||
</pre>
|
||||
|
||||
|
||||
<h2>Expansion and contraction</h2>
|
||||
Expansion can be seen
|
||||
as the 3D convolution of an object with a sphere. Contraction is the reverse: the area outside the solid
|
||||
is expanded, and this is then subtracted from the solid.
|
||||
<br><br>
|
||||
Expansion and contraction are very powerful ways to get an object with nice smooth corners. For example
|
||||
a rounded cube can be created by expanding a normal cube.
|
||||
<br><br>
|
||||
Note that these are expensive operations: spheroids are created around every corner and edge in the original
|
||||
object, so the number of polygons quickly increases. Expansion and contraction therefore are only practical for simple
|
||||
non-curved objects.
|
||||
<br><br>
|
||||
expand() and contract() take two parameters: the first is the radius of expansion or contraction; the second
|
||||
parameter is optional and specififies the resolution (number of polygons on spherical surfaces, per 360 degree revolution).
|
||||
<pre>
|
||||
var cube1 = CSG.cube({radius: 1.0});
|
||||
var cube2 = CSG.cube({radius: 1.0}).translate([-0.3, -0.3, -0.3]);
|
||||
var csg = cube1.subtract(cube2);
|
||||
var rounded = csg.expand(0.2, 8);
|
||||
</pre>
|
||||
|
||||
<h2>Using Properties</h2>
|
||||
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
|
||||
of interest even after several transformations have been applied to the solid.
|
||||
<br><br>
|
||||
Properties can have any type, but only the properties of classes supporting
|
||||
a 'transform' method will actually be transformed. This includes CSG.Vector3D,
|
||||
CSG.Plane and CSG.Connector. In particular CSG.Connector properties (see below)
|
||||
can be very useful: these can
|
||||
be used to attach a solid to another solid at a predetermined location regardless of the
|
||||
current orientation.
|
||||
<br><br>
|
||||
It's even possible to include a CSG solid as a property of another solid. This could
|
||||
be used for example
|
||||
to define the cutout cylinders to create matching screw holes for an object. Those 'solid properties'
|
||||
get the same transformations as the owning solid but they will not be visible in the result
|
||||
of CSG operations such as union().
|
||||
<br><br>
|
||||
Other kind of properties (for
|
||||
example, strings) will still be included in the properties of the transformed
|
||||
solid, but the properties will not get any transformation when the owning solid is transformed. <br><br>
|
||||
All primitive solids have some predefined properties, such as the center point
|
||||
of a sphere (TODO: document).
|
||||
<br><br>
|
||||
The solid resulting from CSG operations (union(), subtract(), intersect()) will get
|
||||
the merged properties of both source solids. If identically named properties exist, only
|
||||
one of them will be kept.
|
||||
<pre>
|
||||
var cube = CSG.cube({radius: 1.0});
|
||||
cube.properties.aCorner = new CSG.Vector3D([1, 1, 1]);
|
||||
cube = cube.translate([5, 0, 0]);
|
||||
cube = cube.scale(2);
|
||||
// cube.properties.aCorner will now point to [12, 2, 2],
|
||||
// which is still the same corner point
|
||||
|
||||
// Properties can be stored in arrays; all properties in the array
|
||||
// will be transformed if the solid is transformed:
|
||||
cube.properties.otherCorners = [
|
||||
new CSG.Vector3D([-1, 1, 1]),
|
||||
new CSG.Vector3D([-1, -1, 1])
|
||||
];
|
||||
|
||||
// and we can create sub-property objects; these must be of the
|
||||
// CSG.Properties class. All sub properties will be transformed with
|
||||
// the solid:
|
||||
cube.properties.myProperties = new CSG.Properties();
|
||||
cube.properties.myProperties.someProperty = new CSG.Vector3D([-1, -1, -1]);
|
||||
</pre>
|
||||
For an example see the <a href="servodemo.html">Servo motor</a> demo.
|
||||
|
||||
<h2>Connectors</h2>
|
||||
The CSG.Connector class is intended to facilitate
|
||||
attaching two solids to each other at a predetermined
|
||||
location and orientation.
|
||||
For example suppose we have a CSG solid depicting a servo motor
|
||||
and a solid of a servo arm: by defining a Connector property for each of them, we
|
||||
can easily attach the servo arm to the servo motor at the correct position
|
||||
(i.e. the motor shaft) and orientation (i.e. arm perpendicular to the shaft)
|
||||
even if we don't know their current position and orientation
|
||||
in 3D space.<br><br>
|
||||
In other words Connector give us the freedom to rotate and translate objects at will without the need
|
||||
to keep track of their positions and boundaries. And if a third party library exposes connectors for
|
||||
its solids, the user of the library does not have to know the actual dimensions or
|
||||
shapes, only the names of the connector properties.
|
||||
<br><br>
|
||||
A CSG.Connector consist of 3 properties:<br>
|
||||
<b>point</b>: a CSG.Vector3D defining the connection point in 3D space<br>
|
||||
<b>axis</b>: a CSG.Vector3D defining the direction vector of the connection
|
||||
(in the case of the servo motor example it would point in the direction of the shaft)<br>
|
||||
<b>normal</b>: a CSG.Vector3D direction vector somewhat perpendicular to axis; this
|
||||
defines the "12 o'clock" orientation of the connection.
|
||||
<br><br>
|
||||
When connecting two connectors, the solid is transformed such that the <b>point</b>
|
||||
properties will be identical, the <b>axis</b> properties will have the same direction
|
||||
(or opposite direction if mirror == true), and the <b>normal</b>s match as much as possible.
|
||||
<br><br>
|
||||
Connectors can be connected by means of two methods:<br>
|
||||
A CSG solid's <b>connectTo()</b> function transforms a solid such that two connectors
|
||||
become connected.<br>
|
||||
Alternatively we can use a connector's <b>getTransformationTo()</b> method to obtain
|
||||
a transformation matrix which would connect the connectors. This can be used if we
|
||||
need to apply the same transform to multiple solids.
|
||||
|
||||
<pre>
|
||||
var cube1 = CSG.cube({radius: 10});
|
||||
var cube2 = CSG.cube({radius: 4});
|
||||
|
||||
// define a connector on the center of one face of cube1
|
||||
// The connector's axis points outwards and its normal points
|
||||
// towards the positive z axis:
|
||||
cube1.properties.myConnector = new CSG.Connector([10, 0, 0], [1, 0, 0], [0, 0, 1]);
|
||||
|
||||
// define a similar connector for cube 2:
|
||||
cube2.properties.myConnector = new CSG.Connector([0, -4, 0], [0, -1, 0], [0, 0, 1]);
|
||||
|
||||
// do some random transformations on cube 1:
|
||||
cube1 = cube1.rotateX(30);
|
||||
cube1 = cube1.translate([3.1, 2, 0]);
|
||||
|
||||
// Now attach cube2 to cube 1:
|
||||
cube2 = cube2.connectTo(
|
||||
cube2.properties.myConnector,
|
||||
cube1.properties.myConnector,
|
||||
true, // mirror
|
||||
0 // normalrotation
|
||||
);
|
||||
|
||||
// Or alternatively:
|
||||
var matrix = cube2.properties.myConnector.getTransformationTo(
|
||||
cube1.properties.myConnector,
|
||||
true, // mirror
|
||||
0 // normalrotation
|
||||
);
|
||||
cube2 = cube2.transform(matrix);
|
||||
|
||||
var result = cube2.union(cube1);
|
||||
|
||||
</pre>
|
||||
For a more complete example see the <a href="servodemo.html">Servo motor</a> demo.
|
||||
|
||||
<h2>Determining the bounds of an object</h2>
|
||||
The getBounds() function can be used to retrieve the bounding box of an object.
|
||||
getBounds() returns
|
||||
an array with two elements specifying the minimum x,y,z coordinate and the maximum x,y,z coordinate:
|
||||
|
||||
<pre>
|
||||
var cube1 = CSG.cube({radius: 10});
|
||||
var cube2 = CSG.cube({radius: 5});
|
||||
|
||||
// get the right bound of cube1 and the left bound of cube2:
|
||||
var deltax = cube1.getBounds()[1].x - cube2.getBounds()[0].x;
|
||||
|
||||
// align cube2 so it touches cube1:
|
||||
cube2 = cube2.translate([deltax, 0, 0]);
|
||||
|
||||
return cube1.union(cube2);
|
||||
</pre>
|
||||
|
||||
<h2>2D shapes</h2>
|
||||
Two dimensional shapes can be defined through the Polygon2D class. Currently this requires the polygon to be convex
|
||||
(i.e. all corners less than 180 degrees). Shapes can be transformed (rotation, translation, scaling).
|
||||
To actually use the shape it needs to be extruded into a 3D CSG object through the extrude() function. extrude()
|
||||
places the 2D solid onto the z=0 plane, and extrudes in the specified direction. Extrusion can be done with an optional
|
||||
twist. This rotates the solid around the z axis (and not necessariy around the extrusion axis) during extrusion.
|
||||
The total degrees of rotation is specified in the twistangle parameter, and twiststeps determine the number of steps
|
||||
between the bottom and top surface.
|
||||
<pre>
|
||||
// Create a shape; argument is an array of 2D coordinates
|
||||
// The shape must be convex, can be specified in clockwise or in counterclockwise direction
|
||||
var shape2d=new CSG.Polygon2D([[0,0], [5,0], [3,5], [0,5]]);
|
||||
|
||||
// Do some transformations:
|
||||
shape2d=shape2d.translate([-2, -2]);
|
||||
shape2d=shape2d.rotate(20);
|
||||
shape2d=shape2d.scale([0.2, 0.2]);
|
||||
|
||||
// And extrude. This creates a CSG solid:
|
||||
var extruded=shape2d.extrude({
|
||||
offset: [0.5, 0, 2], // direction for extrusion
|
||||
twistangle: 180, // top surface is rotated 180 degrees
|
||||
twiststeps: 100 // create 100 slices
|
||||
});
|
||||
</pre>
|
||||
For an example of 2D shapes see the <a href="hookdemo.html">Parametric S hook</a> demo.
|
||||
|
||||
<h2>2D Paths</h2>
|
||||
A path is simply a series of points, connected by lines. A path can be open or closed (an additional line
|
||||
is drawn between the first and last point). 2D paths are supported through the CSG.Path2D class.
|
||||
<br><br>
|
||||
Paths can be contructed either by giving a series of 2D coordinates, or through the CSG.Path2D.arc() function,
|
||||
which creates a circular curved path. Paths can be concatenated, the result is a new path.
|
||||
<br><br>
|
||||
Creating a 3D solid is currently supported by the rectangularExtrude() function. This creates a 3D shape
|
||||
by following the path with a 2D rectangle (upright, perpendicular to the path direction).
|
||||
<pre>
|
||||
var path = new CSG.Path2D([[10,10], [-10,10]], /* closed = */ false);
|
||||
var anotherpath = new CSG.Path2D([[-10,-10]]);
|
||||
path = path.concat(anotherpath);
|
||||
path = path.appendPoint([10,-10]);
|
||||
path = path.close(); // close the path
|
||||
|
||||
// of course we could simply have done:
|
||||
// var path = new CSG.Path2D([[10,10], [-10,10], [-10,-10], [10,-10]], /* closed = */ true);
|
||||
|
||||
// We can make arcs and circles:
|
||||
var curvedpath = CSG.Path2D.arc({
|
||||
center: [0,0,0],
|
||||
radius: 10,
|
||||
startangle: 0,
|
||||
endangle: 180,
|
||||
resolution: 16,
|
||||
});
|
||||
|
||||
// Extrude the path by following it with a rectangle (upright, perpendicular to the path direction)
|
||||
// Returns a CSG solid
|
||||
// width: width of the extrusion, in the z=0 plane
|
||||
// height: height of the extrusion in the z direction
|
||||
// resolution: number of segments per 360 degrees for the curve in a corner
|
||||
// roundEnds: if true, the ends of the polygon will be rounded, otherwise they will be flat
|
||||
var csg = path.rectangularExtrude(3, 4, 16, true);
|
||||
return csg;
|
||||
</pre>
|
||||
|
||||
<h2>Interactive parametric models</h2>
|
||||
It is possible to make certain parameters
|
||||
editable in the browser. This allows users not familiar with JavaScript to create customized STL files.
|
||||
<br><br>
|
||||
To do so, add a function getParameterDefinitions() to your .jscad source. This function should return
|
||||
an array with parameter definitions. Currently 4 parameters types are supported: float, int, text and choice.
|
||||
The user edited values of the parameters will be supplied as an object parameter to the main() function of your .jscad file.
|
||||
<br><br>
|
||||
A float, int or text parameter is created by including the following object in the array returned by getParameterDefinitions():
|
||||
<pre>{
|
||||
name: 'width',
|
||||
type: 'float', // or 'text' or 'int'
|
||||
default: 1.23, // optional, sets the initial value
|
||||
caption: 'Width of the thingy:', // optional, displayed left of the input field
|
||||
// if omitted, the 'name' is displayed (i.e. 'width')
|
||||
}</pre>
|
||||
A 'choice' parameter is created using the following object:
|
||||
<pre>{
|
||||
name: 'shape',
|
||||
type: 'choice',
|
||||
values: ["TRI", "SQU", "CIR"], // these are the values that will be supplied to your script
|
||||
captions: ["Triangle", "Square", "Circle"], // optional, these values are shown in the listbox
|
||||
// if omitted, the items in the 'values' array are used
|
||||
caption: 'Shape:', // optional, displayed left of the input field
|
||||
default: "SQU", // optional, default selected value
|
||||
// if omitted, the first item is selected by default
|
||||
}</pre>
|
||||
To use the values add an argument to your main() function. This argument will be supplied an object
|
||||
with the user edited parameter values:
|
||||
<pre>
|
||||
function main(params)
|
||||
{
|
||||
// custom error checking:
|
||||
if(params.width <= 0) throw new Error("Width should be positive!");
|
||||
|
||||
if(params.shape == "TRI")
|
||||
{
|
||||
// do something
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
A complete example. Copy/paste it into the Playground at the top of this page to see how it works:
|
||||
<pre>
|
||||
function getParameterDefinitions() {
|
||||
return [
|
||||
{
|
||||
name: 'width',
|
||||
type: 'float',
|
||||
default: 10,
|
||||
caption: "Width of the cube:",
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'float',
|
||||
default: 14,
|
||||
caption: "Height of the cube:",
|
||||
},
|
||||
{
|
||||
name: 'depth',
|
||||
type: 'float',
|
||||
default: 7,
|
||||
caption: "Depth of the cube:",
|
||||
},
|
||||
{
|
||||
name: 'rounded',
|
||||
type: 'choice',
|
||||
caption: 'Round the corners?',
|
||||
values: [0, 1],
|
||||
captions: ["No thanks", "Yes please"],
|
||||
default: 1,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function main(params) {
|
||||
var result;
|
||||
if(params.rounded == 1)
|
||||
{
|
||||
result = CSG.roundedCube({radius: [params.width, params.height, params.depth], roundradius: 2, resolution: 32});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CSG.cube({radius: [params.width, params.height, params.depth]});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
</pre>
|
||||
Or see the <a href="gearsdemo.html">Gears demo</a> for another example of interactive parameters.
|
||||
|
||||
<h2>Miscellaneous</h2>
|
||||
Solids can be given a color using the setColor(r, g, b) function. Beware: this returns a new solid,
|
||||
the original solid is not modified! Faces of the solid will keep their original color when doing
|
||||
CSG operations (union() etc). Colors values range between 0.0 and 1.0 (not 255).
|
||||
<pre>
|
||||
var cube1 = CSG.cube({radius: 10});
|
||||
cube1 = cube1.setColor(0.5, 0, 0);
|
||||
|
||||
var cube2 = CSG.cube({radius: 10});
|
||||
cube2 = cube2.setColor(0, 0.5, 0);
|
||||
cube2 = cube2.translate([5,1,4]);
|
||||
|
||||
var result = cube1.subtract(cube2);
|
||||
// the resulting solid will have faces with 2 different colors
|
||||
</pre>
|
||||
|
||||
<h2><a name="math"></a>2D and 3D Math</h2>
|
||||
There are utility classes for many 2D and 3D operations. Below is a quick summary, for details
|
||||
view the source of csg.js:
|
||||
<pre>
|
||||
// --------- Vector3D ---------------------
|
||||
var vec1 = new CSG.Vector3D(1,2,3); // 3 arguments
|
||||
var vec2 = new CSG.Vector3D( [1,2,3] ); // 1 array argument
|
||||
var vec3 = new CSG.Vector3D(vec2); // cloning a vector
|
||||
// get the values as: vec1.x, vec.y, vec1.z
|
||||
// vector math. All operations return a new vector, the original is unmodified!
|
||||
// vectors cannot be modified. Instead you should create a new vector.
|
||||
vec.negated()
|
||||
vec.abs()
|
||||
vec.plus(othervector)
|
||||
vec.minus(othervector)
|
||||
vec.times(3.0)
|
||||
vec.dividedBy(-5)
|
||||
vec.dot(othervector)
|
||||
vec.lerp(othervector, t) // linear interpolation (0 <= t <= 1)
|
||||
vec.length()
|
||||
vec.lengthSquared() // == vec.length()^2
|
||||
vec.unit()
|
||||
vec.cross(othervector) // cross product: returns a vector perpendicular to both
|
||||
vec.distanceTo(othervector)
|
||||
vec.distanceToSquared(othervector) // == vec.distanceTo(othervector)^2
|
||||
vec.equals(othervector)
|
||||
vec.multiply4x4(matrix4x4) // right multiply by a 4x4 matrix
|
||||
vec.min(othervector) // returns a new vector with the minimum x,y and z values
|
||||
vec.max(othervector) // returns a new vector with the maximum x,y and z values
|
||||
|
||||
// --------- Vector2D ---------------------
|
||||
var vec1 = new CSG.Vector2D(1,2); // 2 arguments
|
||||
var vec2 = new CSG.Vector2D( [1,2] ); // 1 array argument
|
||||
var vec3 = new CSG.Vector2D(vec2); // cloning a vector
|
||||
// vector math. All operations return a new vector, the original is unmodified!
|
||||
vec.negated()
|
||||
vec.abs()
|
||||
vec.plus(othervector)
|
||||
vec.minus(othervector)
|
||||
vec.times(3.0)
|
||||
vec.dividedBy(-5)
|
||||
vec.dot(othervector)
|
||||
vec.lerp(othervector, t) // linear interpolation (0 <= t <= 1)
|
||||
vec.length()
|
||||
vec.unit()
|
||||
vec.normal() // returns a 90 degree clockwise rotated vector
|
||||
vec.distanceTo(othervector)
|
||||
vec.equals(othervector)
|
||||
vec.multiply4x4(matrix4x4) // right multiply by a 4x4 matrix
|
||||
vec.toVector3D(z) // convert to a vector3D by adding a z coordinate
|
||||
vec.angleDegrees() // returns the angle of the vector: [1,0] = 0 degrees, [0, 1] = 90 degrees, etc
|
||||
vec.angleRadians() // ditto in radians
|
||||
var vec = CSG.Vector2D.fromAngleDegrees(degrees); // returns a vector at the specified angle
|
||||
var vec = CSG.Vector2D.fromAngleRadians(radians); // returns a vector at the specified angle
|
||||
|
||||
// --------- Matrix4x4 ---------------------
|
||||
var m1 = new CSG.Matrix4x4(); // unity matrix
|
||||
var m2 = new CSG.Matrix4x4( [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] );
|
||||
// elements are passed in row order
|
||||
var result = m1.plus(m2);
|
||||
var result = m1.minus(m2);
|
||||
var result = m1.multiply(m2);
|
||||
// matrix vector multiplication (vectors are padded with zeroes to get a 4x1 vector):
|
||||
var vec3d = m1.rightMultiply1x3Vector(vec3d); // matrix * vector
|
||||
var vec3d = m1.leftMultiply1x3Vector(vec3d); // vector * matrix
|
||||
var vec2d = m1.rightMultiply1x2Vector(vec2d); // matrix * vector
|
||||
var vec2d = m1.leftMultiply1x2Vector(vec2d); // vector * matrix
|
||||
// common transformation matrices:
|
||||
var m = CSG.Matrix4x4.rotationX(degrees); // matrix for rotation about X axis
|
||||
var m = CSG.Matrix4x4.rotationY(degrees); // matrix for rotation about Y axis
|
||||
var m = CSG.Matrix4x4.rotationZ(degrees); // matrix for rotation about Z axis
|
||||
var m = CSG.Matrix4x4.rotation(rotationCenter, rotationAxis, degrees); // rotation about arbitrary point and axis
|
||||
var m = CSG.Matrix4x4.translation(vec3d); // translation
|
||||
var m = CSG.Matrix4x4.scaling(vec3d); // scale
|
||||
var m = CSG.Matrix4x4.mirroring(plane); // mirroring in a plane; the argument must be a CSG.Plane
|
||||
// matrix transformations can be concatenated:
|
||||
var transform = CSG.Matrix4x4.rotationX(20).multiply(CSG.Matrix4x4.rotationY(30));
|
||||
// Use a CSG solid's transform() method to apply the transformation to a CSG solid
|
||||
|
||||
// ------------ Plane --------------------------
|
||||
// a 3D plane is represented by a normal vector (should have unit length) and a distance from the origin w
|
||||
// the plane passes through normal.times(w)
|
||||
var plane1 = new CSG.Plane(normal, w);
|
||||
// Or we can construct a plane from 3 points:
|
||||
var plane2 = CSG.Plane.fromPoints(p1, p2, p3);
|
||||
// Or from a normal vector and 1 point:
|
||||
var plane3 = CSG.Plane.fromNormalAndPoint(normal, point);
|
||||
// Flip a plane (front side becomes back side):
|
||||
var plane4 = plane3.flipped();
|
||||
// Apply transformations (rotation, scaling, translation):
|
||||
var transformed = plane3.transformed(matrix4x4); // argument is a CSG.Matrix4x4
|
||||
// Intersection of plane and 3d line:
|
||||
var point = plane3.intersectWithLine(line); // argument is CSG.Line3D, returns a CSG.Vector3D
|
||||
// Intersection of 2 planes:
|
||||
var line = plane3.intersectWithPlane(plane); // argument is another CSG.Plane, returns a CSG.Line3D
|
||||
// Distance to point:
|
||||
var w = signedDistanceToPoint(point); // argument is CSG.Vector3D, returns a float (positive
|
||||
// if in front of plane, negative if in back)
|
||||
|
||||
// ------------ Line3D --------------------------
|
||||
// A line in 3d space is represented by a point and a direction vector.
|
||||
// Direction should be a unit vector. Point can be any point on the line:
|
||||
var line = new CSG.Line3D(point, direction); // argumenst are CSG.Vector3D
|
||||
// or by giving two points:
|
||||
var line = CSG.Line3D.fromPoints(p1, p2); // argumenst are CSG.Vector3D
|
||||
var point = intersectWithPlane(plane); // == plane.intersectWithLine(this)
|
||||
var line2 = line.reverse(); // same line but reverse direction
|
||||
var line2 = line.transform(matrix4x4); // for rotation, scaling, etc
|
||||
var p = line.closestPointOnLine(point); // project point onto the line
|
||||
var d = line.distanceToPoint(point);
|
||||
</pre>
|
||||
|
||||
</div> <!-- help -->
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue