├── ANGMAP11.jpg
├── LICENSE
├── README.md
├── buttons.css
├── index.html
├── js
├── ImprovedNoise.js
├── Three.SubdivisionModifier.js
└── Three.js
├── matcap.jpg
├── matcap2.jpg
├── matcap3.jpg
├── normal.jpg
└── suzanne-raw.js
/ANGMAP11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spite/spherical-environment-mapping/06789b67cce78e36d54b2779b00d727c706282c8/ANGMAP11.jpg
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Jaume Sanchez
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Spherical Environment Mapping GLSL Shader
2 | =========================================
3 |
4 | Code for the article "Creating a Spherical Reflection/Environment Mapping shader"
5 | http://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader
6 |
7 | License
8 | =======
9 |
10 | MIT licensed
11 |
12 | Copyright (C) 2014 Jaume Sanchez Elias
13 |
14 | http://www.clicktorelease.com
--------------------------------------------------------------------------------
/buttons.css:
--------------------------------------------------------------------------------
1 | .button { display: inline-block; padding: 7px 9px; font-size: inherit; color: #3C3C3D; text-shadow: 1px 1px 0 #FFFFFF; background: #ECECEC; white-space: nowrap; overflow: visible; cursor: pointer; text-decoration: none; border: 1px solid #CACACA; -webkit-border-radius: 2px; -moz-border-radius: 2px; -webkit-background-clip: padding-box; border-radius: 2px; outline: none; position: relative; zoom: 1; *display: inline; }
2 | .button.primary { font-weight: bold }
3 | .button:hover { color: #FFFFFF; border-color: #388AD4; text-decoration: none; text-shadow: -1px -1px 0 rgba(0,0,0,0.3); background-position: 0 -40px; background-color: #2D7DC5; }
4 | .button:active,
5 | .button.active { background-position: 0 -81px; border-color: #347BBA; background-color: #0F5EA2; color: #FFFFFF; text-shadow: none; }
6 | .button:active { top: 1px }
7 | .button.negative:hover { color: #FFFFFF; background-position: 0 -121px; background-color: #D84743; border-color: #911D1B; }
8 | .button.negative:active,
9 | .button.negative.active { background-position: 0 -161px; background-color: #A5211E; border-color: #911D1B; }
10 | .button.pill { -webkit-border-radius: 19px; -moz-border-radius: 19px; border-radius: 19px; padding: 6px 12px; }
11 | .button.left { -webkit-border-bottom-right-radius: 0px; -webkit-border-top-right-radius: 0px; -moz-border-radius-bottomright: 0px; -moz-border-radius-topright: 0px; border-bottom-right-radius: 0px; border-top-right-radius: 0px; margin-right: 0px; }
12 | .button.middle { margin-right: 0px; margin-left: 0px; -webkit-border-radius: 0px; -moz-border-radius: 0px; border-radius: 0px; border-left: none; }
13 | .button.right { -webkit-border-bottom-left-radius: 0px; -webkit-border-top-left-radius: 0px; -moz-border-radius-bottomleft: 0px; -moz-border-radius-topleft: 0px; border-top-left-radius: 0px; border-bottom-left-radius: 0px; margin-left: 0px; border-left: none;}
14 | .button.left:active,
15 | .button.middle:active,
16 | .button.right:active { top: 0px }
17 | .button.big { font-size: 16px; padding: 7px 16px; }
18 | .button span.icon { display: inline-block; width: 14px; height: 12px; margin: auto 7px auto auto; position: relative; top: 1px; background-image: url('/images/css3buttons_icons.png'); background-repeat: no-repeat; }
19 | .big.button span.icon { top: 0px }
20 | .button span.icon.book { background-position: 0 0 }
21 | .button:hover span.icon.book { background-position: 0 -15px }
22 | .button span.icon.calendar { background-position: 0 -30px }
23 | .button:hover span.icon.calendar { background-position: 0 -45px }
24 | .button span.icon.chat { background-position: 0 -60px }
25 | .button:hover span.icon.chat { background-position: 0 -75px }
26 | .button span.icon.check { background-position: 0 -90px }
27 | .button:hover span.icon.check { background-position: 0 -103px }
28 | .button span.icon.clock { background-position: 0 -116px }
29 | .button:hover span.icon.clock { background-position: 0 -131px }
30 | .button span.icon.cog { background-position: 0 -146px }
31 | .button:hover span.icon.cog { background-position: 0 -161px }
32 | .button span.icon.comment { background-position: 0 -176px }
33 | .button:hover span.icon.comment { background-position: 0 -190px }
34 | .button span.icon.cross { background-position: 0 -204px }
35 | .button:hover span.icon.cross { background-position: 0 -219px }
36 | .button span.icon.downarrow { background-position: 0 -234px }
37 | .button:hover span.icon.downarrow { background-position: 0 -249px }
38 | .button span.icon.fork { background-position: 0 -264px }
39 | .button:hover span.icon.fork { background-position: 0 -279px }
40 | .button span.icon.heart { background-position: 0 -294px }
41 | .button:hover span.icon.heart { background-position: 0 -308px }
42 | .button span.icon.home { background-position: 0 -322px }
43 | .button:hover span.icon.home { background-position: 0 -337px }
44 | .button span.icon.key { background-position: 0 -352px }
45 | .button:hover span.icon.key { background-position: 0 -367px }
46 | .button span.icon.leftarrow { background-position: 0 -382px }
47 | .button:hover span.icon.leftarrow { background-position: 0 -397px }
48 | .button span.icon.lock { background-position: 0 -412px }
49 | .button:hover span.icon.lock { background-position: 0 -427px }
50 | .button span.icon.loop { background-position: 0 -442px }
51 | .button:hover span.icon.loop { background-position: 0 -457px }
52 | .button span.icon.magnifier { background-position: 0 -472px }
53 | .button:hover span.icon.magnifier { background-position: 0 -487px }
54 | .button span.icon.mail { background-position: 0 -502px }
55 | .button:hover span.icon.mail { background-position: 0 -514px }
56 | .button span.icon.move { background-position: 0 -526px }
57 | .button:hover span.icon.move { background-position: 0 -541px }
58 | .button span.icon.pen { background-position: 0 -556px }
59 | .button:hover span.icon.pen { background-position: 0 -571px }
60 | .button span.icon.pin { background-position: 0 -586px }
61 | .button:hover span.icon.pin { background-position: 0 -601px }
62 | .button span.icon.plus { background-position: 0 -616px }
63 | .button:hover span.icon.plus { background-position: 0 -631px }
64 | .button span.icon.reload { background-position: 0 -646px }
65 | .button:hover span.icon.reload { background-position: 0 -660px }
66 | .button span.icon.rightarrow { background-position: 0 -674px }
67 | .button:hover span.icon.rightarrow { background-position: 0 -689px }
68 | .button span.icon.rss { background-position: 0 -704px }
69 | .button:hover span.icon.rss { background-position: 0 -719px }
70 | .button span.icon.tag { background-position: 0 -734px }
71 | .button:hover span.icon.tag { background-position: 0 -749px }
72 | .button span.icon.trash { background-position: 0 -764px }
73 | .button:hover span.icon.trash { background-position: 0 -779px }
74 | .button span.icon.unlock { background-position: 0 -794px }
75 | .button:hover span.icon.unlock { background-position: 0 -809px }
76 | .button span.icon.uparrow { background-position: 0 -824px }
77 | .button:hover span.icon.uparrow { background-position: 0 -839px }
78 | .button span.icon.user { background-position: 0 -854px }
79 | .button:hover span.icon.user { background-position: 0 -869px }
80 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Spherical Environment Mapping (MatCap/LitSphere)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
63 |
64 |
65 |
66 |
67 |
74 |
75 |
76 |
84 |
85 |
93 |
94 |
95 |
Enable Phong (per-pixel) shading
96 |
Frame time:
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
124 |
125 |
139 |
140 |
155 |
156 |
177 |
178 |
636 |
637 |
638 |
639 |
--------------------------------------------------------------------------------
/js/ImprovedNoise.js:
--------------------------------------------------------------------------------
1 | // http://mrl.nyu.edu/~perlin/noise/
2 |
3 | var ImprovedNoise = function () {
4 |
5 | var p = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,
6 | 23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,
7 | 174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,
8 | 133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,
9 | 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,
10 | 202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,
11 | 248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,
12 | 178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,
13 | 14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,
14 | 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180];
15 |
16 | for (var i=0; i < 256 ; i++) {
17 |
18 | p[256+i] = p[i];
19 |
20 | }
21 |
22 | function fade(t) {
23 |
24 | return t * t * t * (t * (t * 6 - 15) + 10);
25 |
26 | }
27 |
28 | function lerp(t, a, b) {
29 |
30 | return a + t * (b - a);
31 |
32 | }
33 |
34 | function grad(hash, x, y, z) {
35 |
36 | var h = hash & 15;
37 | var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
38 | return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
39 |
40 | }
41 |
42 | return {
43 |
44 | noise: function (x, y, z) {
45 |
46 | var floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z);
47 |
48 | var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
49 |
50 | x -= floorX;
51 | y -= floorY;
52 | z -= floorZ;
53 |
54 | var xMinus1 = x -1, yMinus1 = y - 1, zMinus1 = z - 1;
55 |
56 | var u = fade(x), v = fade(y), w = fade(z);
57 |
58 | var A = p[X]+Y, AA = p[A]+Z, AB = p[A+1]+Z, B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;
59 |
60 | return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),
61 | grad(p[BA], xMinus1, y, z)),
62 | lerp(u, grad(p[AB], x, yMinus1, z),
63 | grad(p[BB], xMinus1, yMinus1, z))),
64 | lerp(v, lerp(u, grad(p[AA+1], x, y, zMinus1),
65 | grad(p[BA+1], xMinus1, y, z-1)),
66 | lerp(u, grad(p[AB+1], x, yMinus1, zMinus1),
67 | grad(p[BB+1], xMinus1, yMinus1, zMinus1))));
68 |
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/js/Three.SubdivisionModifier.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
3 | *
4 | * Subdivision Geometry Modifier
5 | * using Catmull-Clark Subdivision Surfaces
6 | * for creating smooth geometry meshes
7 | *
8 | * Note: a modifier modifies vertices and faces of geometry,
9 | * so use geometry.clone() if original geometry needs to be retained
10 | *
11 | * Readings:
12 | * http://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
13 | * http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/
14 | * http://xrt.wikidot.com/blog:31
15 | * "Subdivision Surfaces in Character Animation"
16 | *
17 | * (on boundary edges)
18 | * http://rosettacode.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
19 | * https://graphics.stanford.edu/wikis/cs148-09-summer/Assignment3Description
20 | *
21 | * Supports:
22 | * Closed and Open geometries.
23 | *
24 | * TODO:
25 | * crease vertex and "semi-sharp" features
26 | * selective subdivision
27 | */
28 |
29 |
30 | THREE.SubdivisionModifier = function ( subdivisions ) {
31 |
32 | this.subdivisions = (subdivisions === undefined ) ? 1 : subdivisions;
33 |
34 | // Settings
35 | this.useOldVertexColors = false;
36 | this.supportUVs = true;
37 | this.debug = false;
38 |
39 | };
40 |
41 | // Applies the "modify" pattern
42 | THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
43 |
44 | var repeats = this.subdivisions;
45 |
46 | while ( repeats-- > 0 ) {
47 | this.smooth( geometry );
48 | }
49 |
50 | };
51 |
52 | /// REFACTORING THIS OUT
53 |
54 | THREE.GeometryUtils.orderedKey = function ( a, b ) {
55 |
56 | return Math.min( a, b ) + "_" + Math.max( a, b );
57 |
58 | };
59 |
60 |
61 | // Returns a hashmap - of { edge_key: face_index }
62 | THREE.GeometryUtils.computeEdgeFaces = function ( geometry ) {
63 |
64 | var i, il, v1, v2, j, k,
65 | face, faceIndices, faceIndex,
66 | edge,
67 | hash,
68 | edgeFaceMap = {};
69 |
70 | var orderedKey = THREE.GeometryUtils.orderedKey;
71 |
72 | function mapEdgeHash( hash, i ) {
73 |
74 | if ( edgeFaceMap[ hash ] === undefined ) {
75 |
76 | edgeFaceMap[ hash ] = [];
77 |
78 | }
79 |
80 | edgeFaceMap[ hash ].push( i );
81 | }
82 |
83 |
84 | // construct vertex -> face map
85 |
86 | for( i = 0, il = geometry.faces.length; i < il; i ++ ) {
87 |
88 | face = geometry.faces[ i ];
89 |
90 | if ( face instanceof THREE.Face3 ) {
91 |
92 | hash = orderedKey( face.a, face.b );
93 | mapEdgeHash( hash, i );
94 |
95 | hash = orderedKey( face.b, face.c );
96 | mapEdgeHash( hash, i );
97 |
98 | hash = orderedKey( face.c, face.a );
99 | mapEdgeHash( hash, i );
100 |
101 | } else if ( face instanceof THREE.Face4 ) {
102 |
103 | hash = orderedKey( face.a, face.b );
104 | mapEdgeHash( hash, i );
105 |
106 | hash = orderedKey( face.b, face.c );
107 | mapEdgeHash( hash, i );
108 |
109 | hash = orderedKey( face.c, face.d );
110 | mapEdgeHash( hash, i );
111 |
112 | hash = orderedKey( face.d, face.a );
113 | mapEdgeHash( hash, i );
114 |
115 | }
116 |
117 | }
118 |
119 | // extract faces
120 |
121 | // var edges = [];
122 | //
123 | // var numOfEdges = 0;
124 | // for (i in edgeFaceMap) {
125 | // numOfEdges++;
126 | //
127 | // edge = edgeFaceMap[i];
128 | // edges.push(edge);
129 | //
130 | // }
131 |
132 | //debug('edgeFaceMap', edgeFaceMap, 'geometry.edges',geometry.edges, 'numOfEdges', numOfEdges);
133 |
134 | return edgeFaceMap;
135 |
136 | }
137 |
138 | /////////////////////////////
139 |
140 | // Performs an iteration of Catmull-Clark Subdivision
141 | THREE.SubdivisionModifier.prototype.smooth = function ( oldGeometry ) {
142 |
143 | //debug( 'running smooth' );
144 |
145 | // New set of vertices, faces and uvs
146 | var newVertices = [], newFaces = [], newUVs = [];
147 |
148 | function v( x, y, z ) {
149 | newVertices.push( new THREE.Vector3( x, y, z ) );
150 | }
151 |
152 | var scope = this;
153 | var orderedKey = THREE.GeometryUtils.orderedKey;
154 | var computeEdgeFaces = THREE.GeometryUtils.computeEdgeFaces;
155 |
156 | function assert() {
157 |
158 | if (scope.debug && console && console.assert) console.assert.apply(console, arguments);
159 |
160 | }
161 |
162 | function debug() {
163 |
164 | if (scope.debug) console.log.apply(console, arguments);
165 |
166 | }
167 |
168 | function warn() {
169 |
170 | if (console)
171 | console.log.apply(console, arguments);
172 |
173 | }
174 |
175 | function f4( a, b, c, d, oldFace, orders, facei ) {
176 |
177 | // TODO move vertex selection over here!
178 |
179 | var newFace = new THREE.Face4( a, b, c, d, null, oldFace.color, oldFace.materialIndex );
180 |
181 | if (scope.useOldVertexColors) {
182 |
183 | newFace.vertexColors = [];
184 |
185 | var color, tmpColor, order;
186 |
187 | for (var i=0;i<4;i++) {
188 |
189 | order = orders[i];
190 |
191 | color = new THREE.Color(),
192 | color.setRGB(0,0,0);
193 |
194 | for (var j=0, jl=0; j=originalVerticesLength && vertexNo < (originalVerticesLength + originalFaces.length)) {
262 | debug('face pt');
263 | } else {
264 | debug('edge pt');
265 | }
266 |
267 | warn('warning, UV not found for', key);
268 |
269 | return null;
270 | }
271 |
272 | return theUV;
273 |
274 | // Original faces -> Vertex Nos.
275 | // new Facepoint -> Vertex Nos.
276 | // edge Points
277 |
278 | }
279 |
280 | function addUV(vertexNo, oldFaceNo, value) {
281 |
282 | var key = vertexNo+':'+oldFaceNo;
283 | if (!(key in uvForVertices)) {
284 | uvForVertices[key] = value;
285 | } else {
286 | warn('dup vertexNo', vertexNo, 'oldFaceNo', oldFaceNo, 'value', value, 'key', key, uvForVertices[key]);
287 | }
288 | }
289 |
290 | // Step 1
291 | // For each face, add a face point
292 | // Set each face point to be the centroid of all original points for the respective face.
293 | // debug(oldGeometry);
294 | var i, il, j, jl, face;
295 |
296 | // For Uvs
297 | var uvs = oldGeometry.faceVertexUvs[0];
298 | var abcd = 'abcd', vertice;
299 |
300 | debug('originalFaces, uvs, originalVerticesLength', originalFaces.length, uvs.length, originalVerticesLength);
301 |
302 | if (scope.supportUVs)
303 |
304 | for (i=0, il = uvs.length; i Faces Index eg { edge_key: [face_index, face_index2 ]}
366 | var edge, faceIndexA, faceIndexB, avg;
367 |
368 | // debug('edgeFaceMap', edgeFaceMap);
369 |
370 | var edgeCount = 0;
371 |
372 | var edgeVertex, edgeVertexA, edgeVertexB;
373 |
374 | ////
375 |
376 | var vertexEdgeMap = {}; // Gives edges connecting from each vertex
377 | var vertexFaceMap = {}; // Gives faces connecting from each vertex
378 |
379 | function addVertexEdgeMap(vertex, edge) {
380 |
381 | if (vertexEdgeMap[vertex]===undefined) {
382 |
383 | vertexEdgeMap[vertex] = [];
384 |
385 | }
386 |
387 | vertexEdgeMap[vertex].push(edge);
388 | }
389 |
390 | function addVertexFaceMap(vertex, face, edge) {
391 |
392 | if (vertexFaceMap[vertex]===undefined) {
393 |
394 | vertexFaceMap[vertex] = {};
395 |
396 | }
397 |
398 | vertexFaceMap[vertex][face] = edge;
399 | // vertexFaceMap[vertex][face] = null;
400 | }
401 |
402 | // Prepares vertexEdgeMap and vertexFaceMap
403 | for (i in edgeFaceMap) { // This is for every edge
404 | edge = edgeFaceMap[i];
405 |
406 | edgeVertex = i.split('_');
407 | edgeVertexA = edgeVertex[0];
408 | edgeVertexB = edgeVertex[1];
409 |
410 | // Maps an edgeVertex to connecting edges
411 | addVertexEdgeMap(edgeVertexA, [edgeVertexA, edgeVertexB] );
412 | addVertexEdgeMap(edgeVertexB, [edgeVertexA, edgeVertexB] );
413 |
414 | for (j=0,jl=edge.length;j 0, 'an edge without faces?!');
452 |
453 | if (edge.length==1) {
454 |
455 | avg.add( originalPoints[ edgeVertexA ] );
456 | avg.add( originalPoints[ edgeVertexB ] );
457 | avg.multiplyScalar( 0.5 );
458 |
459 | sharpVertices[newPoints.length] = true;
460 |
461 | } else {
462 |
463 | avg.add( facePoints[ faceIndexA ] );
464 | avg.add( facePoints[ faceIndexB ] );
465 |
466 | avg.add( originalPoints[ edgeVertexA ] );
467 | avg.add( originalPoints[ edgeVertexB ] );
468 |
469 | avg.multiplyScalar( 0.25 );
470 |
471 | }
472 |
473 | edgePoints[i] = originalVerticesLength + originalFaces.length + edgeCount;
474 |
475 | newPoints.push( avg );
476 |
477 | edgeCount ++;
478 |
479 | if (!scope.supportUVs) {
480 | continue;
481 | }
482 |
483 | // Prepare subdivided uv
484 |
485 | avgUv = new THREE.Vector2();
486 |
487 | avgUv.x = getUV(edgeVertexA, faceIndexA).x + getUV(edgeVertexB, faceIndexA).x;
488 | avgUv.y = getUV(edgeVertexA, faceIndexA).y + getUV(edgeVertexB, faceIndexA).y;
489 | avgUv.x /= 2;
490 | avgUv.y /= 2;
491 |
492 | addUV(edgePoints[i], faceIndexA, avgUv);
493 |
494 | if (edge.length>=2) {
495 | assert(edge.length == 2, 'did we plan for more than 2 edges?');
496 | avgUv = new THREE.Vector2();
497 |
498 | avgUv.x = getUV(edgeVertexA, faceIndexB).x + getUV(edgeVertexB, faceIndexB).x;
499 | avgUv.y = getUV(edgeVertexA, faceIndexB).y + getUV(edgeVertexB, faceIndexB).y;
500 | avgUv.x /= 2;
501 | avgUv.y /= 2;
502 |
503 | addUV(edgePoints[i], faceIndexB, avgUv);
504 | }
505 |
506 | }
507 |
508 | debug('-- Step 2 done');
509 |
510 | // Step 3
511 | // For each face point, add an edge for every edge of the face,
512 | // connecting the face point to each edge point for the face.
513 |
514 | var facePt, currentVerticeIndex;
515 |
516 | var hashAB, hashBC, hashCD, hashDA, hashCA;
517 |
518 | var abc123 = ['123', '12', '2', '23'];
519 | var bca123 = ['123', '23', '3', '31'];
520 | var cab123 = ['123', '31', '1', '12'];
521 | var abc1234 = ['1234', '12', '2', '23'];
522 | var bcd1234 = ['1234', '23', '3', '34'];
523 | var cda1234 = ['1234', '34', '4', '41'];
524 | var dab1234 = ['1234', '41', '1', '12'];
525 |
526 | for (i=0, il = facePoints.length; i2) {
623 | // TODO
624 | }
625 | */
626 |
627 | F.divideScalar(f);
628 |
629 |
630 | var boundary_edges = 0;
631 |
632 | if (boundary_case) {
633 |
634 | var bb_edge;
635 | for (j=0; j