Skip to content

Commit e0bce36

Browse files
committed
move evaluators to extras; edit curve and surface demos
1 parent a049e02 commit e0bce36

File tree

7 files changed

+296
-209
lines changed

7 files changed

+296
-209
lines changed

demos/curves.html

Lines changed: 4 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<script type="text/javascript" src="../glutil_min.js"></script>
88
<script type="text/javascript" src="../extras/camera.js"></script>
99
<script type="text/javascript" src="../extras/frame.js"></script>
10+
<script type="text/javascript" src="../extras/evaluators.js"></script>
1011
<script type="text/javascript" src="../extras/curvetube.js"></script>
1112
<script type="text/javascript" src="demoutil.js"></script>
1213
</head>
@@ -27,89 +28,6 @@
2728
If you like this, you should donate to Peter O.
2829
at: http://upokecenter.dreamhosters.com/articles/donate-now-2/
2930
*/
30-
function makeMesh(func,resolutionU,resolutionV){
31-
// Default resolution is 50
32-
if(resolutionV==null)resolutionV=resolutionU
33-
if(resolutionU==null)resolutionU=50
34-
if(resolutionV==null)resolutionV=50
35-
// create a new mesh
36-
var mesh=new Mesh();
37-
// define a color gradient evaluator for
38-
// demonstration purposes. Instead of X, Y, and Z,
39-
// generate a Red/Green/Blue color based on
40-
// the same parameters U and V as the surface
41-
// function for 3D points.
42-
var colorGradient={
43-
"evaluate":function(u,v){ return [1-u,v,u]; }
44-
}
45-
// generate the parametric surface.
46-
47-
var ev=new SurfaceEval()
48-
.vertex(func)
49-
// Specify the color gradient evaluator defined above
50-
.color(colorGradient)
51-
// Generate normals for the parametric surface,
52-
// which is required for lighting to work correctly
53-
.setAutoNormal(true)
54-
// Evaluate the surface and generate a triangle
55-
// mesh, using resolution+1 different U-coordinates ranging
56-
// from 0 to 1, and resolution+1
57-
// different V-coordinates ranging from 0 to 1
58-
// Instead of Mesh.TRIANGLES, we could use
59-
// Mesh.LINES to create a wireframe mesh,
60-
// or Mesh.POINTS to create a point mesh.
61-
.evalSurface(mesh,Mesh.TRIANGLES,resolutionU,resolutionV);
62-
// Surface generated, return the mesh
63-
return mesh;
64-
}
65-
function Hypotrochoid(outerRadius, innerRadius, distFromInnerCenter){
66-
this.outer=outerRadius;
67-
this.inner=innerRadius;
68-
this.distFromInner=distFromInnerCenter;
69-
this.evaluate=function(u){
70-
u=u*GLMath.PiTimes2;
71-
var oi=(this.outer-this.inner)
72-
var term=oi*u/this.inner;
73-
// NOTE: prolate hypotrochoid if distFromInner>innerRadius
74-
return [
75-
oi*Math.cos(u)+this.distFromInner*Math.cos(term),
76-
oi*Math.sin(u)-this.distFromInner*Math.sin(term),
77-
0
78-
]
79-
}
80-
}
81-
82-
function Trochoid(radius, distFromCenter){
83-
this.inner=radius;
84-
this.distFromCenter=distFromCenter;
85-
this.evaluate=function(u){
86-
u=u*GLMath.PiTimes2;
87-
var cosu = Math.cos(u);
88-
var sinu = (u>=0 && u<6.283185307179586) ? (u<=3.141592653589793 ? Math.sqrt(1.0-cosu*cosu) : -Math.sqrt(1.0-cosu*cosu)) : Math.sin(u);
89-
return [
90-
this.inner*u-this.distFromCenter*sinu,
91-
this.inner -this.distFromCenter*cosu,
92-
0
93-
]
94-
}
95-
}
96-
97-
function Epitrochoid(outerRadius, innerRadius, distFromInnerCenter){
98-
this.outer=outerRadius;
99-
this.inner=innerRadius;
100-
this.distFromInner=distFromInnerCenter;
101-
this.evaluate=function(u){
102-
u=u*GLMath.PiTimes2;
103-
var oi=(this.outer+this.inner)
104-
var term=oi*u/this.inner;
105-
// NOTE: prolate epitrochoid if distFromInner>innerRadius
106-
return [
107-
oi*Math.cos(u)-this.distFromInner*Math.cos(term),
108-
oi*Math.sin(u)-this.distFromInner*Math.sin(term),
109-
0
110-
]
111-
}
112-
}
11331

11432
var HypocycloidSeal={create:function(radius,points){
11533
return Hypocycloid.create(radius,radius/points);
@@ -155,7 +73,8 @@
15573
}
15674
}
15775
function makeThinCurveMesh(curve){
158-
return makeMesh(new CurveTube(curve,0.025),150,20)
76+
var surface=new CurveTube(curve,0.025);
77+
return makeMesh(surface,150,20)
15978
}
16079

16180
var shapeGroup=new ShapeGroup();
@@ -242,6 +161,7 @@
242161
});
243162
})
244163

164+
245165
// Create the 3D scene; find the HTML canvas and pass it
246166
// to Scene3D.
247167
var scene=new Scene3D(document.getElementById("canvas"));

demos/demoutil.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,44 @@ function pushSettings(updateMeshFunc,settings){
201201
setRanges(ranges);
202202
updateShape(updateMeshFunc);
203203
};
204+
205+
206+
function makeMesh(func,resolutionU,resolutionV){
207+
// Default resolution is 50
208+
if(resolutionV==null)resolutionV=resolutionU
209+
if(resolutionU==null)resolutionU=50
210+
if(resolutionV==null)resolutionV=50
211+
// create a new mesh
212+
var mesh=new Mesh();
213+
// define a color gradient evaluator for
214+
// demonstration purposes. Instead of X, Y, and Z,
215+
// generate a Red/Green/Blue color based on
216+
// the same parameters U and V as the surface
217+
// function for 3D points.
218+
var colorGradient={
219+
"evaluate":function(u,v){ return [1-u,v,u]; }
220+
}
221+
// generate the parametric surface.
222+
223+
var ev=new SurfaceEval()
224+
.vertex(func)
225+
// Specify the color gradient evaluator defined above
226+
.color(colorGradient)
227+
// Generate normals for the parametric surface,
228+
// which is required for lighting to work correctly
229+
.setAutoNormal(true)
230+
// Evaluate the surface and generate a triangle
231+
// mesh, using resolution+1 different U-coordinates ranging
232+
// from 0 to 1, and resolution+1
233+
// different V-coordinates ranging from 0 to 1
234+
// Instead of Mesh.TRIANGLES, we could use
235+
// Mesh.LINES to create a wireframe mesh,
236+
// or Mesh.POINTS to create a point mesh.
237+
.evalSurface(mesh,Mesh.TRIANGLES,resolutionU,resolutionV);
238+
// Surface generated, return the mesh
239+
return mesh;
240+
}
241+
204242
window.addEventListener("load",function(){
205243
var a=document.createElement("a")
206244
a.setAttribute("style","margin-left:2px;margin-top:2px;margin-bottom:2px;position:absolute;left:80%;top:0;"+

demos/surfaces.html

Lines changed: 1 addition & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
canvas { width:100%; height:100%; overflow: hidden; }
66
</style>
77
<script type="text/javascript" src="../glutil_min.js"></script>
8+
<script type="text/javascript" src="../extras/evaluators.js"></script>
89
<script type="text/javascript" src="../extras/camera.js"></script>
910
<script type="text/javascript" src="../extras/frame.js"></script>
1011
<script type="text/javascript" src="extras.js"></script>
@@ -93,87 +94,6 @@
9394
return Math.sign(r)*Math.pow(Math.abs(r),n);
9495
}
9596

96-
/**
97-
* Parametric evaluator for a surface of revolution, which results by revolving
98-
* an X/Y curve around an axis.
99-
* @class
100-
* @alias SurfaceOfRevolution
101-
* @param {Function} curve Curve to rotate about the X-axis.
102-
* The curve function must contain a function
103-
* named "evaluate", which takes the following parameter:<ul>
104-
* <li><code>u</code> - A curve coordinate, generally from 0 to 1.
105-
* </ul>
106-
* The evaluator function returns an array of at least 2 elements: the first
107-
* element is the X coordinate of the curve's position, and the second
108-
* element is the Y coordinate.
109-
* @param {number} minval Smallest U-coordinate.
110-
* @param {number} maxval Largest U-coordinate.
111-
*/
112-
var SurfaceOfRevolution=function(curve,minval,maxval){
113-
this.curve=curve
114-
this.minval=minval
115-
this.maxval=maxval
116-
this.evaluate=function(u,v){
117-
v=1-v;
118-
v*=GLMath.PiTimes2;
119-
u=minval+(maxval-minval)*u;
120-
var cosv = Math.cos(v);
121-
var sinv = (v>=0 && v<6.283185307179586) ? (v<=3.141592653589793 ? Math.sqrt(1.0-cosv*cosv) : -Math.sqrt(1.0-cosv*cosv)) : Math.sin(v);
122-
var curvepos=this.curve.evaluate(u);
123-
return [curvepos[0],curvepos[1]*cosv,curvepos[1]*sinv];
124-
}
125-
}
126-
/**
127-
* Parametric evaluator for a surface of revolution whose curve is the graph of
128-
* a single-variable function.
129-
* @param {Function} func Function whose graph will be
130-
* rotated about the X-axis. The function takes a number
131-
* as a single parameter and returns a number.
132-
* @param {number} minval Smallest parameter of the function.
133-
* @param {number} maxval Largest parameter of the function.
134-
* @return {SurfaceOfRevolution}
135-
*/
136-
SurfaceOfRevolution.fromFunction=function(func,minval,maxval){
137-
return new SurfaceOfRevolution({
138-
"evaluate":function(u){
139-
return [u,func(u),0];
140-
}},minval,maxval);
141-
}
142-
/**
143-
* Parametric evaluator for a torus, a special case of a surface of revolution.
144-
* @param {number} outerRadius Radius from the center to the innermost
145-
* part of the torus.
146-
* @param {number} innerRadius Radius from the inner edge to the innermost
147-
* part of the torus.
148-
* @param {Function|undefined} curve Object describing
149-
* a curve to serve as the cross section of the torus.
150-
* The curve need not be closed; in fact, certain special surfaces can result
151-
* by leaving the ends open.
152-
* The curve function must contain a function
153-
* named "evaluate", which takes the following parameter:<ul>
154-
* <li><code>u</code> - A curve coordinate, generally from 0 to 1.
155-
* </ul>
156-
* The evaluator function returns an array of at least 2 elements: the first
157-
* element is the X coordinate of the curve's position, and the second
158-
* element is the Y coordinate. If null or omitted, uses a circular cross section.
159-
* @return {SurfaceOfRevolution}
160-
*/
161-
SurfaceOfRevolution.torus=function(outerRadius,innerRadius,curve){
162-
if(!curve)curve={
163-
"evaluate":function(u){
164-
u*=GLMath.PiTimes2;
165-
return [Math.sin(u),Math.cos(v)]
166-
}
167-
}
168-
return new SurfaceOfRevolution({
169-
"evaluate":function(u){
170-
var curvept=curve.evaluate(u)
171-
var x=innerRadius*curvept[1];
172-
var y=outerRadius+innerRadius*curvept[0];
173-
return [x,y,0];
174-
}},0,GLMath.PiTimes2);
175-
}
176-
17797
var KleinBottle=function(){
17898
this.evaluate=function(u,v){
17999
var cospi;
@@ -238,39 +158,6 @@
238158
return [x,y,z]
239159
}
240160
}
241-
function makeMesh(func,resolution){
242-
// Default resolution is 50
243-
if(resolution==null)resolution=50
244-
// create a new mesh
245-
var mesh=new Mesh();
246-
// define a color gradient evaluator for
247-
// demonstration purposes. Instead of X, Y, and Z,
248-
// generate a Red/Green/Blue color based on
249-
// the same parameters U and V as the surface
250-
// function for 3D points.
251-
var colorGradient={
252-
"evaluate":function(u,v){ return [1-u,v,u]; }
253-
}
254-
// generate the parametric surface.
255-
256-
var ev=new SurfaceEval()
257-
.vertex(func)
258-
// Specify the color gradient evaluator defined above
259-
.color(colorGradient)
260-
// Generate normals for the parametric surface,
261-
// which is required for lighting to work correctly
262-
.setAutoNormal(true)
263-
// Evaluate the surface and generate a triangle
264-
// mesh, using resolution+1 different U-coordinates ranging
265-
// from 0 to 1, and resolution+1
266-
// different V-coordinates ranging from 0 to 1
267-
// Instead of Mesh.TRIANGLES, we could use
268-
// Mesh.LINES to create a wireframe mesh,
269-
// or Mesh.POINTS to create a point mesh.
270-
.evalSurface(mesh,Mesh.TRIANGLES,resolution,resolution);
271-
// Surface generated, return the mesh
272-
return mesh;
273-
}
274161

275162
var shapeGroup=new ShapeGroup();
276163
var allsettings={}

demos/surfaces2d.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
canvas { width:100%; height:100%; overflow: hidden; }
66
</style>
77
<script type="text/javascript" src="../glutil_min.js"></script>
8+
<script type="text/javascript" src="../extras/evaluators.js"></script>
89
<script type="text/javascript" src="../extras/camera.js"></script>
910
<script type="text/javascript" src="../extras/frame.js"></script>
1011
<script type="text/javascript" src="demoutil.js"></script>

extras/curvetube.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,15 @@ _FrenetFrames.prototype.getSampleAndBasisVectors=function(u){
179179
* @param {number} [thickness] Radius of the
180180
* extruded tube. If this parameter is null or omitted, the default is 0.125.
181181
* @param {Object} [sweptCurve] Object describing
182-
* a curve to serve as the cross section of the extruded shape,
182+
* a two-dimensional curve to serve as the cross section of the extruded shape,
183183
* corresponding to the V coordinate of the CurveTube's
184-
* "evaluate" method. If this parameter is null or omitted, uses a circular cross section
184+
* "evaluate" method.
185+
* If this parameter is null or omitted, uses a circular cross section
185186
* in which the V coordinate ranges from 0 through
186187
* 1. The curve object must contain a function
187-
* named "evaluate", with the same meaning as for the "func" parameter.<p>
188+
* named "evaluate", with the same meaning as for the "func" parameter,
189+
* except the third element, if any, of the return value is ignored.<p>
190+
* The curve need not be closed.<p>
188191
* The cross section will generally have a radius of 1 unit; bigger
189192
* or smaller cross sections will affect the meaning of the "thickness"
190193
* parameter.
@@ -214,16 +217,16 @@ CurveTube.prototype.evaluate=function(u, v){
214217
t1 = vpos[0];
215218
t2 = vpos[1];
216219
var t3=vpos[2];
217-
sx = sampleX+(basisVectors[0]*t2+basisVectors[3]*t1+basisVectors[6]*t3)*this.thickness;
218-
sy = sampleY+(basisVectors[1]*t2+basisVectors[4]*t1+basisVectors[7]*t3)*this.thickness;
219-
sz = sampleZ+(basisVectors[2]*t2+basisVectors[5]*t1+basisVectors[8]*t3)*this.thickness;
220+
sx = sampleX+(-basisVectors[0]*t1+basisVectors[3]*t2)*this.thickness;
221+
sy = sampleY+(-basisVectors[1]*t1+basisVectors[4]*t2)*this.thickness;
222+
sz = sampleZ+(-basisVectors[2]*t1+basisVectors[5]*t2)*this.thickness;
220223
} else {
221224
var vt=GLMath.PiTimes2*v;
222225
t1 = Math.cos(vt);
223226
t2 = (vt>=0 && vt<6.283185307179586) ? (vt<=3.141592653589793 ? Math.sqrt(1.0-t1*t1) : -Math.sqrt(1.0-t1*t1)) : Math.sin(vt);
224-
sx = sampleX+(basisVectors[0]*t2+basisVectors[3]*t1)*this.thickness;
225-
sy = sampleY+(basisVectors[1]*t2+basisVectors[4]*t1)*this.thickness;
226-
sz = sampleZ+(basisVectors[2]*t2+basisVectors[5]*t1)*this.thickness;
227+
sx = sampleX+(-basisVectors[0]*t1+basisVectors[3]*t2)*this.thickness;
228+
sy = sampleY+(-basisVectors[1]*t1+basisVectors[4]*t2)*this.thickness;
229+
sz = sampleZ+(-basisVectors[2]*t1+basisVectors[5]*t2)*this.thickness;
227230
}
228231
return [sx,sy,sz];
229232
}

0 commit comments

Comments
 (0)