1 /**
2 * @author zz85 / http://www.lab4games.net/zz85/blog
3 *
4 * Creates extruded geometry from a path shape.
5 *
6 * parameters = {
7 *
8 * size: <float>, // size of the text
9 * height: <float>, // thickness to extrude text
10 * curveSegments: <int>, // number of points on the curves
11 * steps: <int>, // number of points for z-side extrusions / used for subdividing segements of extrude spline too
12 * amount: <int>, // Amount
13 *
14 * bevelEnabled: <bool>, // turn on bevel
15 * bevelThickness: <float>, // how deep into text bevel goes
16 * bevelSize: <float>, // how far from text outline is bevel
17 * bevelSegments: <int>, // number of bevel layers
18 *
19 * extrudePath: <THREE.CurvePath> // 3d spline path to extrude shape along. (creates Frames if .frames aren't defined)
20 * frames: <THREE.TubeGeometry.FrenetFrames> // containing arrays of tangents, normals, binormals
21 *
22 * material: <int> // material index for front and back faces
23 * extrudeMaterial: <int> // material index for extrusion and beveled faces
24 * uvGenerator: <Object> // object that provides UV generator functions
25 *
26 * }
27 **/
28
29 /**@constructor*/
30 THREE.ExtrudeGeometry = function ( shapes, options ) {
31
32 if ( typeof( shapes ) === "undefined" ) {
33 shapes = [];
34 return;
35 }
36
37 THREE.Geometry.call( this );
38
39 shapes = shapes instanceof Array ? shapes : [ shapes ];
40
41 this.shapebb = shapes[ shapes.length - 1 ].getBoundingBox();
42
43 this.addShapeList( shapes, options );
44
45 this.computeCentroids();
46 this.computeFaceNormals();
47
48 // can't really use automatic vertex normals
49 // as then front and back sides get smoothed too
50 // should do separate smoothing just for sides
51
52 //this.computeVertexNormals();
53
54 //console.log( "took", ( Date.now() - startTime ) );
55
56 };
57
58 THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype );
59
60 THREE.ExtrudeGeometry.prototype.addShapeList = function ( shapes, options ) {
61 var sl = shapes.length;
62
63 for ( var s = 0; s < sl; s ++ ) {
64 var shape = shapes[ s ];
65 this.addShape( shape, options );
66 }
67 };
68
69 THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
70
71 var amount = options.amount !== undefined ? options.amount : 100;
72
73 var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
74 var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
75 var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
76
77 var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
78
79 var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
80
81 var steps = options.steps !== undefined ? options.steps : 1;
82
83 var extrudePath = options.extrudePath;
84 var extrudePts, extrudeByPath = false;
85
86 var material = options.material;
87 var extrudeMaterial = options.extrudeMaterial;
88
89 // Use default WorldUVGenerator if no UV generators are specified.
90 var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
91
92 var shapebb = this.shapebb;
93 //shapebb = shape.getBoundingBox();
94
95
96
97 var splineTube, binormal, normal, position2;
98 if ( extrudePath ) {
99
100 extrudePts = extrudePath.getSpacedPoints( steps );
101
102 extrudeByPath = true;
103 bevelEnabled = false; // bevels not supported for path extrusion
104
105 // SETUP TNB variables
106
107 // Reuse TNB from TubeGeomtry for now.
108 // TODO1 - have a .isClosed in spline?
109
110 splineTube = options.frames !== undefined ? options.frames : new THREE.TubeGeometry.FrenetFrames(extrudePath, steps, false);
111
112 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
113
114 binormal = new THREE.Vector3();
115 normal = new THREE.Vector3();
116 position2 = new THREE.Vector3();
117
118 }
119
120 // Safeguards if bevels are not enabled
121
122 if ( ! bevelEnabled ) {
123
124 bevelSegments = 0;
125 bevelThickness = 0;
126 bevelSize = 0;
127
128 }
129
130 // Variables initalization
131
132 var ahole, h, hl; // looping of holes
133 var scope = this;
134 var bevelPoints = [];
135
136 var shapesOffset = this.vertices.length;
137
138 var shapePoints = shape.extractPoints();
139
140 var vertices = shapePoints.shape;
141 var holes = shapePoints.holes;
142
143 var reverse = !THREE.Shape.Utils.isClockWise( vertices ) ;
144
145 if ( reverse ) {
146
147 vertices = vertices.reverse();
148
149 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
150
151 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
152
153 ahole = holes[ h ];
154
155 if ( THREE.Shape.Utils.isClockWise( ahole ) ) {
156
157 holes[ h ] = ahole.reverse();
158
159 }
160
161 }
162
163 reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
164
165 }
166
167
168 var faces = THREE.Shape.Utils.triangulateShape ( vertices, holes );
169
170 /* Vertices */
171
172 var contour = vertices; // vertices has all points but contour has only points of circumference
173
174 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
175
176 ahole = holes[ h ];
177
178 vertices = vertices.concat( ahole );
179
180 }
181
182
183 function scalePt2 ( pt, vec, size ) {
184
185 if ( !vec ) console.log( "die" );
186
187 return vec.clone().multiplyScalar( size ).addSelf( pt );
188
189 }
190
191 var b, bs, t, z,
192 vert, vlen = vertices.length,
193 face, flen = faces.length,
194 cont, clen = contour.length;
195
196
197 // Find directions for point movement
198
199 var RAD_TO_DEGREES = 180 / Math.PI;
200
201
202 function getBevelVec( pt_i, pt_j, pt_k ) {
203
204 // Algorithm 2
205
206 return getBevelVec2( pt_i, pt_j, pt_k );
207
208 }
209
210 function getBevelVec1( pt_i, pt_j, pt_k ) {
211
212 var anglea = Math.atan2( pt_j.y - pt_i.y, pt_j.x - pt_i.x );
213 var angleb = Math.atan2( pt_k.y - pt_i.y, pt_k.x - pt_i.x );
214
215 if ( anglea > angleb ) {
216
217 angleb += Math.PI * 2;
218
219 }
220
221 var anglec = ( anglea + angleb ) / 2;
222
223
224 //console.log('angle1', anglea * RAD_TO_DEGREES,'angle2', angleb * RAD_TO_DEGREES, 'anglec', anglec *RAD_TO_DEGREES);
225
226 var x = - Math.cos( anglec );
227 var y = - Math.sin( anglec );
228
229 var vec = new THREE.Vector2( x, y ); //.normalize();
230
231 return vec;
232
233 }
234
235 function getBevelVec2( pt_i, pt_j, pt_k ) {
236
237 var a = THREE.ExtrudeGeometry.__v1,
238 b = THREE.ExtrudeGeometry.__v2,
239 v_hat = THREE.ExtrudeGeometry.__v3,
240 w_hat = THREE.ExtrudeGeometry.__v4,
241 p = THREE.ExtrudeGeometry.__v5,
242 q = THREE.ExtrudeGeometry.__v6,
243 v, w,
244 v_dot_w_hat, q_sub_p_dot_w_hat,
245 s, intersection;
246
247 // good reading for line-line intersection
248 // http://sputsoft.com/blog/2010/03/line-line-intersection.html
249
250 // define a as vector j->i
251 // define b as vectot k->i
252
253 a.set( pt_i.x - pt_j.x, pt_i.y - pt_j.y );
254 b.set( pt_i.x - pt_k.x, pt_i.y - pt_k.y );
255
256 // get unit vectors
257
258 v = a.normalize();
259 w = b.normalize();
260
261 // normals from pt i
262
263 v_hat.set( -v.y, v.x );
264 w_hat.set( w.y, -w.x );
265
266 // pts from i
267
268 p.copy( pt_i ).addSelf( v_hat );
269 q.copy( pt_i ).addSelf( w_hat );
270
271 if ( p.equals( q ) ) {
272
273 //console.log("Warning: lines are straight");
274 return w_hat.clone();
275
276 }
277
278 // Points from j, k. helps prevents points cross overover most of the time
279
280 p.copy( pt_j ).addSelf( v_hat );
281 q.copy( pt_k ).addSelf( w_hat );
282
283 v_dot_w_hat = v.dot( w_hat );
284 q_sub_p_dot_w_hat = q.subSelf( p ).dot( w_hat );
285
286 // We should not reach these conditions
287
288 if ( v_dot_w_hat === 0 ) {
289
290 console.log( "Either infinite or no solutions!" );
291
292 if ( q_sub_p_dot_w_hat === 0 ) {
293
294 console.log( "Its finite solutions." );
295
296 } else {
297
298 console.log( "Too bad, no solutions." );
299
300 }
301
302 }
303
304 s = q_sub_p_dot_w_hat / v_dot_w_hat;
305
306 if ( s < 0 ) {
307
308 // in case of emergecy, revert to algorithm 1.
309
310 return getBevelVec1( pt_i, pt_j, pt_k );
311
312 }
313
314 intersection = v.multiplyScalar( s ).addSelf( p );
315
316 return intersection.subSelf( pt_i ).clone(); // Don't normalize!, otherwise sharp corners become ugly
317
318 }
319
320 var contourMovements = [];
321
322 for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
323
324 if ( j === il ) j = 0;
325 if ( k === il ) k = 0;
326
327 // (j)---(i)---(k)
328 // console.log('i,j,k', i, j , k)
329
330 var pt_i = contour[ i ];
331 var pt_j = contour[ j ];
332 var pt_k = contour[ k ];
333
334 contourMovements[ i ]= getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
335
336 }
337
338 var holesMovements = [], oneHoleMovements, verticesMovements = contourMovements.concat();
339
340 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
341
342 ahole = holes[ h ];
343
344 oneHoleMovements = [];
345
346 for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
347
348 if ( j === il ) j = 0;
349 if ( k === il ) k = 0;
350
351 // (j)---(i)---(k)
352 oneHoleMovements[ i ]= getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
353
354 }
355
356 holesMovements.push( oneHoleMovements );
357 verticesMovements = verticesMovements.concat( oneHoleMovements );
358
359 }
360
361
362 // Loop bevelSegments, 1 for the front, 1 for the back
363
364 for ( b = 0; b < bevelSegments; b ++ ) {
365 //for ( b = bevelSegments; b > 0; b -- ) {
366
367 t = b / bevelSegments;
368 z = bevelThickness * ( 1 - t );
369
370 //z = bevelThickness * t;
371 bs = bevelSize * ( Math.sin ( t * Math.PI/2 ) ) ; // curved
372 //bs = bevelSize * t ; // linear
373
374 // contract shape
375
376 for ( i = 0, il = contour.length; i < il; i ++ ) {
377
378 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
379 //vert = scalePt( contour[ i ], contourCentroid, bs, false );
380 v( vert.x, vert.y, - z );
381
382 }
383
384 // expand holes
385
386 for ( h = 0, hl = holes.length; h < hl; h++ ) {
387
388 ahole = holes[ h ];
389 oneHoleMovements = holesMovements[ h ];
390
391 for ( i = 0, il = ahole.length; i < il; i++ ) {
392
393 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
394 //vert = scalePt( ahole[ i ], holesCentroids[ h ], bs, true );
395
396 v( vert.x, vert.y, -z );
397
398 }
399
400 }
401
402 }
403
404 bs = bevelSize;
405
406 // Back facing vertices
407
408 for ( i = 0; i < vlen; i ++ ) {
409
410 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
411
412 if ( !extrudeByPath ) {
413
414 v( vert.x, vert.y, 0 );
415
416 } else {
417
418 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
419
420 normal.copy( splineTube.normals[0] ).multiplyScalar(vert.x);
421 binormal.copy( splineTube.binormals[0] ).multiplyScalar(vert.y);
422
423 position2.copy( extrudePts[0] ).addSelf(normal).addSelf(binormal);
424
425 v( position2.x, position2.y, position2.z );
426
427 }
428
429 }
430
431 // Add stepped vertices...
432 // Including front facing vertices
433
434 var s;
435
436 for ( s = 1; s <= steps; s ++ ) {
437
438 for ( i = 0; i < vlen; i ++ ) {
439
440 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
441
442 if ( !extrudeByPath ) {
443
444 v( vert.x, vert.y, amount / steps * s );
445
446 } else {
447
448 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
449
450 normal.copy( splineTube.normals[s] ).multiplyScalar( vert.x );
451 binormal.copy( splineTube.binormals[s] ).multiplyScalar( vert.y );
452
453 position2.copy( extrudePts[s] ).addSelf( normal ).addSelf( binormal );
454
455 v( position2.x, position2.y, position2.z );
456
457 }
458
459 }
460
461 }
462
463
464 // Add bevel segments planes
465
466 //for ( b = 1; b <= bevelSegments; b ++ ) {
467 for ( b = bevelSegments - 1; b >= 0; b -- ) {
468
469 t = b / bevelSegments;
470 z = bevelThickness * ( 1 - t );
471 //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) );
472 bs = bevelSize * Math.sin ( t * Math.PI/2 ) ;
473
474 // contract shape
475
476 for ( i = 0, il = contour.length; i < il; i ++ ) {
477
478 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
479 v( vert.x, vert.y, amount + z );
480
481 }
482
483 // expand holes
484
485 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
486
487 ahole = holes[ h ];
488 oneHoleMovements = holesMovements[ h ];
489
490 for ( i = 0, il = ahole.length; i < il; i ++ ) {
491
492 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
493
494 if ( !extrudeByPath ) {
495
496 v( vert.x, vert.y, amount + z );
497
498 } else {
499
500 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
501
502 }
503
504 }
505
506 }
507
508 }
509
510 /* Faces */
511
512 // Top and bottom faces
513
514 buildLidFaces();
515
516 // Sides faces
517
518 buildSideFaces();
519
520
521 ///// Internal functions
522
523 function buildLidFaces() {
524
525 if ( bevelEnabled ) {
526
527 var layer = 0 ; // steps + 1
528 var offset = vlen * layer;
529
530 // Bottom faces
531
532 for ( i = 0; i < flen; i ++ ) {
533
534 face = faces[ i ];
535 f3( face[ 2 ]+ offset, face[ 1 ]+ offset, face[ 0 ] + offset, true );
536
537 }
538
539 layer = steps + bevelSegments * 2;
540 offset = vlen * layer;
541
542 // Top faces
543
544 for ( i = 0; i < flen; i ++ ) {
545
546 face = faces[ i ];
547 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset, false );
548
549 }
550
551 } else {
552
553 // Bottom faces
554
555 for ( i = 0; i < flen; i++ ) {
556
557 face = faces[ i ];
558 f3( face[ 2 ], face[ 1 ], face[ 0 ], true );
559
560 }
561
562 // Top faces
563
564 for ( i = 0; i < flen; i ++ ) {
565
566 face = faces[ i ];
567 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps, false );
568
569 }
570 }
571
572 }
573
574 // Create faces for the z-sides of the shape
575
576 function buildSideFaces() {
577
578 var layeroffset = 0;
579 sidewalls( contour, layeroffset );
580 layeroffset += contour.length;
581
582 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
583
584 ahole = holes[ h ];
585 sidewalls( ahole, layeroffset );
586
587 //, true
588 layeroffset += ahole.length;
589
590 }
591
592 }
593
594 function sidewalls( contour, layeroffset ) {
595
596 var j, k;
597 i = contour.length;
598
599 while ( --i >= 0 ) {
600
601 j = i;
602 k = i - 1;
603 if ( k < 0 ) k = contour.length - 1;
604
605 //console.log('b', i,j, i-1, k,vertices.length);
606
607 var s = 0, sl = steps + bevelSegments * 2;
608
609 for ( s = 0; s < sl; s ++ ) {
610
611 var slen1 = vlen * s;
612 var slen2 = vlen * ( s + 1 );
613
614 var a = layeroffset + j + slen1,
615 b = layeroffset + k + slen1,
616 c = layeroffset + k + slen2,
617 d = layeroffset + j + slen2;
618
619 f4( a, b, c, d, contour, s, sl, j, k );
620
621 }
622 }
623
624 }
625
626
627 function v( x, y, z ) {
628
629 scope.vertices.push( new THREE.Vector3( x, y, z ) );
630
631 }
632
633 function f3( a, b, c, isBottom ) {
634
635 a += shapesOffset;
636 b += shapesOffset;
637 c += shapesOffset;
638
639 // normal, color, material
640 scope.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
641
642 var uvs = isBottom ? uvgen.generateBottomUV( scope, shape, options, a, b, c ) : uvgen.generateTopUV( scope, shape, options, a, b, c );
643
644 scope.faceVertexUvs[ 0 ].push( uvs );
645
646 }
647
648 function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
649
650 a += shapesOffset;
651 b += shapesOffset;
652 c += shapesOffset;
653 d += shapesOffset;
654
655 scope.faces.push( new THREE.Face4( a, b, c, d, null, null, extrudeMaterial ) );
656
657 var uvs = uvgen.generateSideWallUV( scope, shape, wallContour, options, a, b, c, d,
658 stepIndex, stepsLength, contourIndex1, contourIndex2 );
659 scope.faceVertexUvs[ 0 ].push( uvs );
660
661 }
662
663 };
664
665 THREE.ExtrudeGeometry.WorldUVGenerator = {
666
667 generateTopUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC ) {
668 var ax = geometry.vertices[ indexA ].x,
669 ay = geometry.vertices[ indexA ].y,
670
671 bx = geometry.vertices[ indexB ].x,
672 by = geometry.vertices[ indexB ].y,
673
674 cx = geometry.vertices[ indexC ].x,
675 cy = geometry.vertices[ indexC ].y;
676
677 return [
678 new THREE.UV( ax, ay ),
679 new THREE.UV( bx, by ),
680 new THREE.UV( cx, cy )
681 ];
682
683 },
684
685 generateBottomUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC ) {
686
687 return this.generateTopUV( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC );
688
689 },
690
691 generateSideWallUV: function( geometry, extrudedShape, wallContour, extrudeOptions,
692 indexA, indexB, indexC, indexD, stepIndex, stepsLength,
693 contourIndex1, contourIndex2 ) {
694
695 var ax = geometry.vertices[ indexA ].x,
696 ay = geometry.vertices[ indexA ].y,
697 az = geometry.vertices[ indexA ].z,
698
699 bx = geometry.vertices[ indexB ].x,
700 by = geometry.vertices[ indexB ].y,
701 bz = geometry.vertices[ indexB ].z,
702
703 cx = geometry.vertices[ indexC ].x,
704 cy = geometry.vertices[ indexC ].y,
705 cz = geometry.vertices[ indexC ].z,
706
707 dx = geometry.vertices[ indexD ].x,
708 dy = geometry.vertices[ indexD ].y,
709 dz = geometry.vertices[ indexD ].z;
710
711 if ( Math.abs( ay - by ) < 0.01 ) {
712 return [
713 new THREE.UV( ax, 1 - az ),
714 new THREE.UV( bx, 1 - bz ),
715 new THREE.UV( cx, 1 - cz ),
716 new THREE.UV( dx, 1 - dz )
717 ];
718 } else {
719 return [
720 new THREE.UV( ay, 1 - az ),
721 new THREE.UV( by, 1 - bz ),
722 new THREE.UV( cy, 1 - cz ),
723 new THREE.UV( dy, 1 - dz )
724 ];
725 }
726 }
727 };
728
729 THREE.ExtrudeGeometry.__v1 = new THREE.Vector2();
730 THREE.ExtrudeGeometry.__v2 = new THREE.Vector2();
731 THREE.ExtrudeGeometry.__v3 = new THREE.Vector2();
732 THREE.ExtrudeGeometry.__v4 = new THREE.Vector2();
733 THREE.ExtrudeGeometry.__v5 = new THREE.Vector2();
734 THREE.ExtrudeGeometry.__v6 = new THREE.Vector2();
735
nike free rn
new balance hombre baratas
cinturones gucci
ugg rebajas
cinturon gucci
ray ban baratas
nike cortez
peuterey mujer
christian louboutin madrid
mbt zapatos
gafas ray ban baratas
mbt ofertas
air max blancas
mbt barcelona
nike air max 90
woolrich barcelona
nike mujer
botas ugg
gafas de sol carrera aratas
air max 2016 baratas
oakley baratas
nike air max 2016