|
| 1 | +## Introduction |
| 2 | + |
| 3 | +This tip describes parametric surfaces and how to generate them using my |
| 4 | +public-domain [HTML 3D Library](http://peteroupc.github.io/html3dutil). |
| 5 | + |
| 6 | +**Download the latest version of the library at the [HTML 3D Library's Releases page](https://github.com/peteroupc/html3dutil/releases).** |
| 7 | + |
| 8 | +## What Is a Parametric Surface? |
| 9 | + |
| 10 | +A _parametric surface_ is a surface generated by evaluating the results of a _vector function_. This vector function |
| 11 | +takes two numbers, U and V, and returns a 3D point, X, Y, and Z. Each (U, V) point corresponds to an (X, Y, Z) |
| 12 | +point that lies on the surface. |
| 13 | + |
| 14 | +A _vector function_ in 3D is a combination of three functions, one for each axis: |
| 15 | + |
| 16 | +* **F**(u, v) = [ _x_(u, v), _y_(u, v), _z_(u, v) ]; |
| 17 | + |
| 18 | +The _x_ function returns an X coordinate given u and v, and likewise for _y_ and _z_. |
| 19 | +Since the _z_ function returns a Z coordinate, the surface will be in 2D if _z_ always returns |
| 20 | +the same value. |
| 21 | + |
| 22 | +For example, if we have a parametric surface defined by the following functions: |
| 23 | + |
| 24 | +* _x_(u, v) = u * v |
| 25 | +* _y_(u, v) = -u |
| 26 | +* _z_(u, v) = u * sqrt(v) |
| 27 | + |
| 28 | +and we evaluate the UV point (2, 4), then we have: |
| 29 | + |
| 30 | +* **F**(2, 3) = [ 2 * 4, -2, 2 * sqrt(4) ]; |
| 31 | +* **F**(2, 3) = [ 8, -2, 4 ]; |
| 32 | + |
| 33 | +So (8, -2, 4) is one point that lies on this parametric surface, and any other point on the |
| 34 | +surface can be found by evaluating different UV points. By the way, the surface looks like this: |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | +## Parametric Surfaces in the HTML 3D Library |
| 39 | + |
| 40 | +The HTML 3D Library supports parametric surfaces using a class named `SurfaceEval`. It helps |
| 41 | +generate vertex coordinates, texture coordinates, normals, and colors using a parametric surface |
| 42 | +function. The following helper function, `makeMesh`, generates a parametric surface mesh |
| 43 | +that was used to produce the pictures on this page. |
| 44 | + |
| 45 | +The comments explain how `makeMesh` works in detail. |
| 46 | + |
| 47 | + function makeMesh(func){ |
| 48 | + // create a new mesh |
| 49 | + var mesh=new Mesh(); |
| 50 | + // define a color gradient evaluator for |
| 51 | + // demonstration purposes. Instead of X, Y, and Z, |
| 52 | + // generate a Red/Green/Blue color based on |
| 53 | + // the same parameters U and V as the surface |
| 54 | + // function for 3D points. |
| 55 | + var colorGradient={ |
| 56 | + evaluate:function(u,v){ return [1-u,v,u]; } |
| 57 | + } |
| 58 | + // generate the parametric surface. |
| 59 | + // First, create a SurfaceEval object |
| 60 | + var ev=new SurfaceEval() |
| 61 | + // Specify the vertex evaluator passed as _func_ |
| 62 | + .vertex(func) |
| 63 | + // Specify the color gradient evaluator defined above |
| 64 | + .color(colorGradient) |
| 65 | + // Generate normals for the parametric surface, |
| 66 | + // which is required for lighting to work correctly |
| 67 | + .setAutoNormal(true) |
| 68 | + // Evaluate the surface and generate a triangle |
| 69 | + // mesh, using 51 different U-coordinates ranging |
| 70 | + // from 0 to 1 (50 subdivisions plus 1), and 51 |
| 71 | + // different V-coordinates ranging from 0 to 1 |
| 72 | + // Instead of Mesh.TRIANGLES, we could use |
| 73 | + // Mesh.LINES to create a wireframe mesh, |
| 74 | + // or Mesh.POINTS to create a point mesh. |
| 75 | + .evalSurface(mesh,Mesh.TRIANGLES,50,50); |
| 76 | + // Surface generated, return the mesh |
| 77 | + return mesh; |
| 78 | + } |
| 79 | + |
| 80 | +In the HTML 3D Library, parametric surface objects define one method, "evaluate", |
| 81 | +which returns a 3D point given a U parameter and a V parameter. (By default, U and |
| 82 | +V each range from 0 through 1.) |
| 83 | + |
| 84 | +The following code is a very simple surface evaluator. |
| 85 | + |
| 86 | + var evaluator = { |
| 87 | + "evaluate":function(u, v){ |
| 88 | + // Take the U parameter as the X coordinate, |
| 89 | + // the V parameter as the X coordinate, and 0 as |
| 90 | + // coordinate. |
| 91 | + return [u, v, 0]; |
| 92 | + } |
| 93 | + } |
| 94 | + |
| 95 | +That evaluator simply generates a square at the top-right quadrant: |
| 96 | + |
| 97 | + |
| 98 | + |
| 99 | +And the following evaluator generates a circle: |
| 100 | + |
| 101 | + var evaluator = { |
| 102 | + "evaluate":function(u, v){ |
| 103 | + // Extend the range of v |
| 104 | + v*=Math.PI*2; |
| 105 | + // Return circle coordinates. |
| 106 | + return [u*Math.cos(v),u*Math.sin(v),0]; |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | +Now here's the interesting part: This evaluator returns not a circle, |
| 113 | +but a _cone_, whose length runs along the negative z-axis: |
| 114 | + |
| 115 | + var evaluator = { |
| 116 | + "evaluate":function(u, v){ |
| 117 | + // Extend the range of v |
| 118 | + v*=Math.PI*2; |
| 119 | + // Return cone coordinates, using the u |
| 120 | + // parameter as the z-axis. |
| 121 | + return [u*Math.cos(v),u*Math.sin(v),-u]; |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | +The following shape was rotated to show the z-axis; the rotation isn't perfect. |
| 126 | + |
| 127 | + |
| 128 | + |
| 129 | +Note that all three examples above use a value named `evaluator`. To generate |
| 130 | +a mesh with an evaluator and add it to the 3D scene, you then need to do: |
| 131 | + |
| 132 | + // Assumes that a Scene3D object named _scene_ was previously defined. |
| 133 | + // Create a 3D shape using the makeMesh method given earlier on this page |
| 134 | + var shape = scene.makeShape(makeMesh(evaluator)); |
| 135 | + // Add the shape to the 3D scene |
| 136 | + scene.addShape(shape); |
| 137 | + |
| 138 | +The generated 3D mesh from a parametric surface is just like any |
| 139 | +other mesh, and the same functions and methods you use for other meshes |
| 140 | +can be used on this mesh as well. For more information, see the |
| 141 | +[overview page](http://www.codeproject.com/Tips/896839/Public-Domain-HTML-ThreeD-Library) |
| 142 | +and the API references for the [`Mesh`](http://peteroupc.github.io/html3dutil/glutil.Mesh.html) and |
| 143 | +[`Shape`](http://peteroupc.github.io/html3dutil/glutil.Shape.html) classes. |
| 144 | + |
| 145 | +## Demo |
| 146 | + |
| 147 | +* [surfaces.html](https://peteroupc.github.io/html3dutil/demos/surfaces.html) - Demonstrates parametric surfaces. |
| 148 | + |
| 149 | +## Other Pages |
| 150 | + |
| 151 | +The following pages of mine on CodeProject also discuss this library: |
| 152 | + |
| 153 | +* [_Public-Domain HTML 3D Library_](http://www.codeproject.com/Tips/896839/Public-Domain-HTML-ThreeD-Library) |
| 154 | +* [_Creating shapes using the Public Domain HTML 3D Library_](http://www.codeproject.com/Tips/987914/Creating-shapes-using-the-Public-Domain-HTML-D-Lib) |
| 155 | +* [_The "Camera" and the Perspective and View Transforms_](http://www.codeproject.com/Tips/989978/The-Camera-and-the-Projection-and-View-Transforms) |
0 commit comments