提交 23e315cb 编写于 作者: A alteredq

Merged zz85's Path / Shape / Extrude geometry. Cleaned up and refactored it a bit.

All three classes are now in separate files.
Updated build script.
Fixed runaway globals.
Optimized loops ("in" should be used just for iterating over object properties, for arrays it's slow and also traversal order is not guaranteed).
Cleaned whitespace.
Bit more polished example.
Fixed inverted side faces for fish shape.
上级 3ba8cc4d
因为 它太大了无法显示 source diff 。你可以改为 查看blob
此差异已折叠。
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js canvas/webgl - geometry - text</title>
<title>three.js canvas - geometry - shapes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<style type="text/css">
......@@ -20,10 +20,7 @@
<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<!-- load the font file from canvas-text -->
<script type="text/javascript" src="../src/extras/geometries/Path.js"></script>
<script type="text/javascript">
......@@ -55,7 +52,7 @@
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Simple Dynamic 3D Shapes Example by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br/>Drag to spin the text';
info.innerHTML = 'Simple procedurally generated 3D shapes example by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br/>Drag to spin';
container.appendChild( info );
camera = new THREE.Camera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
......@@ -65,153 +62,163 @@
scene = new THREE.Scene();
var californiaPts=[];
californiaPts.push( new THREE.Vector2 (610, 320) );
californiaPts.push( new THREE.Vector2 (450, 300) );
californiaPts.push( new THREE.Vector2 (392, 392) );
californiaPts.push( new THREE.Vector2 (266, 438) );
californiaPts.push( new THREE.Vector2 (190, 570) );
californiaPts.push( new THREE.Vector2 (190, 600) );
californiaPts.push( new THREE.Vector2 (160, 620) );
californiaPts.push( new THREE.Vector2 (160, 650) );
californiaPts.push( new THREE.Vector2 (180, 640) );
californiaPts.push( new THREE.Vector2 (165, 680) );
californiaPts.push( new THREE.Vector2 (150, 670) );
californiaPts.push( new THREE.Vector2 (90, 737) );
californiaPts.push( new THREE.Vector2 (80, 795) );
californiaPts.push( new THREE.Vector2 (50, 835) );
californiaPts.push( new THREE.Vector2 (64, 870) );
californiaPts.push( new THREE.Vector2 (60, 945) );
californiaPts.push( new THREE.Vector2 (300, 945) );
californiaPts.push( new THREE.Vector2 (300, 743) );
californiaPts.push( new THREE.Vector2 (600, 473) );
californiaPts.push( new THREE.Vector2 (626, 425) );
californiaPts.push( new THREE.Vector2 (600, 370) );
californiaPts.push( new THREE.Vector2 (610, 320) );
var californiaShape = new THREE.Shape(californiaPts);
var california3d = new THREE.ExtrudeGeometry( californiaShape, {
amount: 20
});
var extrudeSettings = {
amount: 30
};
parent = new THREE.Object3D();
parent.position.y = 50;
scene.addChild( parent );
function addGeometry( geometry, color, x, y, z, rx, ry, rz, s ) {
var mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { color: color } ), new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true } ) ] );
mesh.position.set( x, y, z );
mesh.rotation.set( rx, ry, rz );
mesh.scale.set( s, s, s );
parent.addChild( mesh );
}
var extrudeSettings = { amount: 20 };
// California
var californiaPts = [];
californiaPts.push( new THREE.Vector2 ( 610, 320 ) );
californiaPts.push( new THREE.Vector2 ( 450, 300 ) );
californiaPts.push( new THREE.Vector2 ( 392, 392 ) );
californiaPts.push( new THREE.Vector2 ( 266, 438 ) );
californiaPts.push( new THREE.Vector2 ( 190, 570 ) );
californiaPts.push( new THREE.Vector2 ( 190, 600 ) );
californiaPts.push( new THREE.Vector2 ( 160, 620 ) );
californiaPts.push( new THREE.Vector2 ( 160, 650 ) );
californiaPts.push( new THREE.Vector2 ( 180, 640 ) );
californiaPts.push( new THREE.Vector2 ( 165, 680 ) );
californiaPts.push( new THREE.Vector2 ( 150, 670 ) );
californiaPts.push( new THREE.Vector2 ( 90, 737 ) );
californiaPts.push( new THREE.Vector2 ( 80, 795 ) );
californiaPts.push( new THREE.Vector2 ( 50, 835 ) );
californiaPts.push( new THREE.Vector2 ( 64, 870 ) );
californiaPts.push( new THREE.Vector2 ( 60, 945 ) );
californiaPts.push( new THREE.Vector2 ( 300, 945 ) );
californiaPts.push( new THREE.Vector2 ( 300, 743 ) );
californiaPts.push( new THREE.Vector2 ( 600, 473 ) );
californiaPts.push( new THREE.Vector2 ( 626, 425 ) );
californiaPts.push( new THREE.Vector2 ( 600, 370 ) );
californiaPts.push( new THREE.Vector2 ( 610, 320 ) );
var californiaShape = new THREE.Shape( californiaPts );
var california3d = new THREE.ExtrudeGeometry( californiaShape, { amount: 20 } );
// Triangle
var triangleShape = new THREE.Shape();
triangleShape.moveTo(80, 20);
triangleShape.lineTo(40, 80);
triangleShape.lineTo(120, 80);
triangleShape.lineTo(80,20); // close path
var triangle3d = triangleShape.extrude(extrudeSettings);
triangleShape.moveTo( 80, 20 );
triangleShape.lineTo( 40, 80 );
triangleShape.lineTo( 120, 80 );
triangleShape.lineTo( 80, 20 ); // close path
var triangle3d = triangleShape.extrude( extrudeSettings );
// Heart
var x = 0, y = 0;
var heartShape = new THREE.Shape(); // From http://blog.burlock.org/html5/130-paths
heartShape.moveTo(x + 25, y + 25);
heartShape.bezierCurveTo(x + 25, y + 25, x + 20, y, x, y);
heartShape.bezierCurveTo(x - 30, y, x - 30, y + 35,x - 30,y + 35);
heartShape.bezierCurveTo(x - 30, y + 55, x - 10, y + 77, x + 25, y + 95);
heartShape.bezierCurveTo(x + 60, y + 77, x + 80, y + 55, x + 80, y + 35);
heartShape.bezierCurveTo(x + 80, y + 35, x + 80, y, x + 50, y);
heartShape.bezierCurveTo(x + 35, y, x + 25, y + 25, x + 25, y + 25);
var heart3d = heartShape.extrude(extrudeSettings);
//heartShape.debug(document.getElementById("debug"));
heartShape.moveTo( x + 25, y + 25 );
heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35,x - 30,y + 35 );
heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );
var heart3d = heartShape.extrude( extrudeSettings );
//heartShape.debug( document.getElementById("debug") );
// Square
var sqLength = 80;
var squareShape = new THREE.Shape();
squareShape.moveTo(0,0);
squareShape.lineTo(0, sqLength);
squareShape.lineTo(sqLength, sqLength);
squareShape.lineTo(sqLength, 0);
squareShape.lineTo(0, 0);
var square3d = squareShape.extrude(extrudeSettings);
squareShape.moveTo( 0,0 );
squareShape.lineTo( 0, sqLength );
squareShape.lineTo( sqLength, sqLength );
squareShape.lineTo( sqLength, 0 );
squareShape.lineTo( 0, 0 );
var square3d = squareShape.extrude( extrudeSettings );
// Rectangle
var rectLength = 120, rectWidth = 40;
var rectShape = new THREE.Shape();
rectShape.moveTo(0,0);
rectShape.lineTo(0, rectWidth);
rectShape.lineTo(rectLength, rectWidth);
rectShape.lineTo(rectLength, 0);
rectShape.lineTo(0, 0);
var rect3d = rectShape.extrude(extrudeSettings);
rectShape.moveTo( 0,0 );
rectShape.lineTo( 0, rectWidth );
rectShape.lineTo( rectLength, rectWidth );
rectShape.lineTo( rectLength, 0 );
rectShape.lineTo( 0, 0 );
var rect3d = rectShape.extrude( extrudeSettings );
// Rounded rectangle
var roundedRectShape = new THREE.Shape();
roundedRect(roundedRectShape, 0, 0, 50,50, 20);
var roundedRect3d = roundedRectShape.extrude(extrudeSettings);
function roundedRect(ctx,x,y,width,height,radius){
ctx.moveTo(x,y+radius);
ctx.lineTo(x,y+height-radius);
ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
ctx.lineTo(x+width-radius,y+height);
ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
ctx.lineTo(x+width,y+radius);
ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
ctx.lineTo(x+radius,y);
ctx.quadraticCurveTo(x,y,x,y+radius);
roundedRect( roundedRectShape, 0, 0, 50, 50, 20 );
var roundedRect3d = roundedRectShape.extrude( extrudeSettings );
function roundedRect( ctx, x, y, width, height, radius ){
ctx.moveTo( x, y + radius );
ctx.lineTo( x, y + height - radius );
ctx.quadraticCurveTo( x, y + height, x + radius, y + height );
ctx.lineTo( x + width - radius, y + height) ;
ctx.quadraticCurveTo( x + width, y + height, x + width, y + height - radius );
ctx.lineTo( x + width, y + radius );
ctx.quadraticCurveTo( x + width, y, x + width - radius, y );
ctx.lineTo( x + radius, y );
ctx.quadraticCurveTo( x, y, x, y + radius );
}
var circleRadius = 20;
// Circle
var circleRadius = 40;
var circleShape = new THREE.Shape();
circleShape.moveTo(0,circleRadius);
circleShape.quadraticCurveTo(circleRadius, circleRadius,circleRadius,0);
circleShape.quadraticCurveTo(circleRadius, -circleRadius,0,-circleRadius);
circleShape.quadraticCurveTo(-circleRadius, -circleRadius,-circleRadius,0);
circleShape.quadraticCurveTo(-circleRadius, circleRadius,0,circleRadius);
var circle3d = circleShape.extrude(extrudeSettings);
circleShape.moveTo( 0, circleRadius );
circleShape.quadraticCurveTo( circleRadius, circleRadius, circleRadius, 0 );
circleShape.quadraticCurveTo( circleRadius, -circleRadius, 0, -circleRadius );
circleShape.quadraticCurveTo( -circleRadius, -circleRadius, -circleRadius, 0 );
circleShape.quadraticCurveTo( -circleRadius, circleRadius, 0, circleRadius );
var circle3d = circleShape.extrude( extrudeSettings );
// Fish
x = y = 0;
var fishShape = new THREE.Shape();
fishShape.moveTo(x,y);
fishShape.quadraticCurveTo(x + 50, y - 80, x + 90, y - 10);
fishShape.quadraticCurveTo(x + 100, y - 10, x + 115, y - 40);
fishShape.quadraticCurveTo(x + 115, y, x + 115, y + 40);
fishShape.quadraticCurveTo(x + 100, y + 10, x + 90, y + 10);
fishShape.quadraticCurveTo(x + 50, y + 80, x, y);
var fish3d = fishShape.extrude(extrudeSettings);
// TOFIX: swap order of points around.
var textMaterial = new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe:false } );
text = new THREE.Mesh( square3d, textMaterial );
text.doubleSided = false;
text.position.y = 100;
// text.position.y = 100;
text.position.z = 200;
text.rotation.x = 0;
text.rotation.y = Math.PI*2;
text.overdraw = true;
scene.addObject( text );
var triangleMesh = new THREE.Mesh( triangle3d, textMaterial );
triangleMesh.position.x = 180;
triangleMesh.position.y = 50;
scene.addObject( triangleMesh );
// Plane
plane = new THREE.Mesh( new THREE.PlaneGeometry( 800, 800 ), new THREE.MeshBasicMaterial( { color: 0xe0e0e0, wireframe:true }) );
plane.rotation.x = - 90 * ( Math.PI / 180 );
plane.position.x = 0;
plane.overdraw = true;
//scene.addObject( plane );
var fishShape = new THREE.Shape();
fishShape.moveTo( x, y );
fishShape.quadraticCurveTo( x + 50, y + 80, x + 90, y + 10 );
fishShape.quadraticCurveTo( x + 100, y + 10, x + 115, y + 40 );
fishShape.quadraticCurveTo( x + 100, y, x + 115, y - 40 );
fishShape.quadraticCurveTo( x + 100, y + 10, x + 90, y - 10 );
fishShape.quadraticCurveTo( x + 50, y - 80, x, y );
var fish3d = fishShape.extrude( extrudeSettings );
addGeometry( california3d, 0xffaa00, -300, -100, 0, 0, 0, 0, 0.25 );
addGeometry( triangle3d, 0xffee00, -180, 0, 0, 0, 0, 0, 1 );
addGeometry( roundedRect3d, 0x005500, -150, 150, 0, 0, 0, 0, 1 );
addGeometry( square3d, 0x0055ff, 150, 100, 0, 0, 0, 0, 1 );
addGeometry( heart3d, 0xff1100, 0, 100, 0, 3.14, 0, 0, 1 );
addGeometry( circle3d, 0x00ff11, 150, 0, 0, 0, 0, 0, 1 );
addGeometry( fish3d, 0x222222, -50, 200, 0, 0, 0, 0, 1 );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
......@@ -307,7 +314,7 @@
function render() {
plane.rotation.z = text.rotation.y += ( targetRotation - text.rotation.y ) * 0.05;
parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
......
......@@ -3,405 +3,319 @@
* Creates free form path.
**/
THREE.Path = function (points) {
this.path = [];
if (points) {
this.fromPoints(points);
THREE.Path = function ( points ) {
this.actions = [];
if ( points ) {
this.fromPoints( points );
}
};
var ACTIONS = {
THREE.PathActions = {
MOVE_TO: 'moveTo',
LINE_TO: 'lineTo',
QUADRATIC_CURVE_TO: 'quadraticCurveTo', //BEZIER quadratic CURVE
BEZIER_CURVE_TO: 'bezierCurveTo', //BEZIER cubic CURVE
CSPLINE_TO: 'cSplineTo' // TODO cardinal splines
QUADRATIC_CURVE_TO: 'quadraticCurveTo', // BEZIER quadratic CURVE
BEZIER_CURVE_TO: 'bezierCurveTo', // BEZIER cubic CURVE
CSPLINE_TO: 'cSplineTo' // TODO cardinal splines
};
/* create path using straight lines to connect all points */
THREE.Path.prototype.fromPoints = function(vectors) {
/* Create path using straight lines to connect all points */
THREE.Path.prototype.fromPoints = function( vectors ) {
var v = 0, vlen = vectors.length;
this.moveTo(vectors[0].x, vectors[0].y);
for (v=1; v<vlen ;v++) {
this.lineTo(vectors[v].x, vectors[v].y);
this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
for ( v = 1; v < vlen; v++ ) {
this.lineTo( vectors[ v ].x, vectors[ v ].y );
};
};
THREE.Path.prototype.moveTo = function(x,y) {
var args = Array.prototype.slice.call(arguments);
this.path.push({action:ACTIONS.MOVE_TO, args:args});
THREE.Path.prototype.moveTo = function( x, y ) {
var args = Array.prototype.slice.call( arguments );
this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
};
THREE.Path.prototype.lineTo = function(x,y) {
var args = Array.prototype.slice.call(arguments);
this.path.push({action:ACTIONS.LINE_TO, args:args});
THREE.Path.prototype.lineTo = function( x, y ) {
var args = Array.prototype.slice.call( arguments );
this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
};
THREE.Path.prototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
var args = Array.prototype.slice.call(arguments);
this.path.push({action:ACTIONS.QUADRATIC_CURVE_TO, args:args});
THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
var args = Array.prototype.slice.call( arguments );
this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args });
};
THREE.Path.prototype.bezierCurveTo = function(aCP1x, aCP1y,
aCP2x, aCP2y,
aX, aY) {
var args = Array.prototype.slice.call(arguments);
this.path.push({action:ACTIONS.BEZIER_CURVE_TO, args:args});
THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
aCP2x, aCP2y,
aX, aY) {
var args = Array.prototype.slice.call( arguments );
this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
};
/* Return an array of vectors based on contour of the path */
THREE.Path.prototype.getPoints = function(divisions) {
THREE.Path.prototype.getPoints = function( divisions ) {
divisions = divisions || 12;
var pts = [];
var x,o, args;
for (x in this.path) {
o = this.path[x];
args = o.args;
switch( action = o.action ) {
var points = [];
var i, il, item, action, args;
var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
laste, j,
t, tx, ty;
for ( i = 0, il = this.actions.length; i < il; i++ ) {
item = this.actions[ i ];
action = item.action;
args = item.args;
switch( action ) {
case THREE.PathActions.MOVE_TO:
//points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
case ACTIONS.MOVE_TO:
//pts.push( new THREE.Vector2( args[0], args[1] ) );
break;
case ACTIONS.LINE_TO:
pts.push( new THREE.Vector2( args[0], args[1] ) );
case THREE.PathActions.LINE_TO:
points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
break;
case ACTIONS.QUADRATIC_CURVE_TO:
var cpx, cpy, cpx1, cpy1, cpx0, cpy0;
cpx = args[2];
cpy = args[3];
cpx1 = args[0];
cpy1 = args[1];
var laste, cpx0, cpy0;
if (pts.length > 0 ) {
laste = pts[ pts.length - 1 ];
cpx0 = laste.x;
cpy0 = laste.y;
} else {
laste = this.path[x-1].args;
cpx0 = laste[laste.length-2];
cpy0 = laste[laste.length-1];
}
for ( i2 = 1; i2 <= divisions; i2++ ) {
// TODO use LOD for divions
var t = i2 / divisions;
var tx = THREE.FontUtils.b2( t, cpx0, cpx1, cpx );
var ty = THREE.FontUtils.b2( t, cpy0, cpy1, cpy );
pts.push( new THREE.Vector2( tx, ty ) );
}
case THREE.PathActions.QUADRATIC_CURVE_TO:
cpx = args[ 2 ];
cpy = args[ 3 ];
cpx1 = args[ 0 ];
cpy1 = args[ 1 ];
if ( points.length > 0 ) {
laste = points[ points.length - 1 ];
break;
case ACTIONS.BEZIER_CURVE_TO:
cpx = args[4];
cpy = args[5];
cpx1 = args[0];
cpy1 = args[1];
cpx2 = args[2];
cpy2 = args[3];
var laste, cpx0, cpy0;
if (pts.length > 0 ) {
laste = pts[ pts.length - 1 ];
cpx0 = laste.x;
cpy0 = laste.y;
} else {
laste = this.path[x-1].args;
cpx0 = laste[laste.length-2];
cpy0 = laste[laste.length-1];
}
for ( i2 = 1; i2 <= divisions; i2++ ) {
var t = i2 / divisions;
var tx = THREE.FontUtils.b3( t, cpx0, cpx1, cpx2, cpx );
var ty = THREE.FontUtils.b3( t, cpy0, cpy1, cpy2, cpy );
pts.push( new THREE.Vector2( tx, ty ) );
laste = this.actions[ i - 1 ].args;
cpx0 = laste[ laste.length - 2 ];
cpy0 = laste[ laste.length - 1 ];
}
for ( j = 1; j <= divisions; j ++ ) {
// TODO use LOD for divisions
t = j / divisions;
tx = THREE.FontUtils.b2( t, cpx0, cpx1, cpx );
ty = THREE.FontUtils.b2( t, cpy0, cpy1, cpy );
points.push( new THREE.Vector2( tx, ty ) );
}
break;
}
}
return pts;
};
case THREE.PathActions.BEZIER_CURVE_TO:
cpx = args[ 4 ];
cpy = args[ 5 ];
THREE.Path.prototype.getMinAndMax = function() {
var pts = this.getPoints();
var maxX = maxY = Number.NEGATIVE_INFINITY;
var minX = minY = Number.POSITIVE_INFINITY;
var p, pt;
for (p in pts) {
pt = pts[p];
if (pt.x > maxX) maxX = pt.x;
if (pt.y > maxY) maxY = pt.y;
if (pt.x < minX) minX = pt.x;
if (pt.y < maxY) minY = pt.y;
}
// TODO find mid-pt?
return {
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY
};
};
cpx1 = args[ 0 ];
cpy1 = args[ 1 ];
/* Draws this path onto a 2d canvas easily */
THREE.Path.prototype.debug = function(canvas) {
// JUST A STUB
if (!canvas) {
canvas = document.createElement("canvas");
canvas.setAttribute('width', 200);
canvas.setAttribute('height', 200);
document.body.appendChild(canvas);
}
var ctx = canvas.getContext("2d");
ctx.fillStyle = "white";
ctx.fillRect(0,0,200,200);
cpx2 = args[ 2 ];
cpy2 = args[ 3 ];
ctx.strokeStyle = "black";
ctx.beginPath();
var i,o, a;
// Debug Path
for (i in this.path) {
o = this.path[i];
a = o.args;
// Short hand for now
ctx[o.action].apply(ctx, a);
/*
switch (o.action) {
case ACTIONS.MOVE_TO:
ctx[o.action](a[0],a[1]);
break;
case ACTIONS.LINE_TO:
ctx[o.action](a[0],a[1]);
break;
case ACTIONS.QUADRATIC_CURVE_TO:
ctx[o.action](a[0],a[1],a[2],a[3]);
break;
case ACTIONS.CUBIC_CURVE_TO:
ctx[o.action](a[0],a[1],a[2],a[3], a[4], a[5]);
break;
}*/
}
ctx.stroke();
ctx.closePath();
// DebugPoints
ctx.strokeStyle = "red";
var pts = this.getPoints();
for (var p in pts) {
ctx.beginPath();
ctx.arc(pts[p].x,pts[p].y, 1.5,0, Math.PI*2, false);
ctx.stroke();
ctx.closePath();
}
};
if ( points.length > 0 ) {
// STEP 1 Create a path.
// STEP 2 Turn path into shape.
// STEP 3 Extrude Geometry takes in Shape/Shapes
// STEP 3a - Extract points from each shape, turn to Vertics
// STEP 3b - Triangulate Each Shape
laste = points[ points.length - 1 ];
/* Defines a 2d shape plane using paths */
cpx0 = laste.x;
cpy0 = laste.y;
THREE.Shape = function ( ) {
} else {
THREE.Path.apply( this, arguments);
this.holes = [];
laste = this.actions[ i - 1 ].args;
};
cpx0 = laste[ laste.length - 2 ];
cpy0 = laste[ laste.length - 1 ];
THREE.Shape.prototype = new THREE.Path();
}
THREE.Shape.prototype.constructor = THREE.Path;
/* Returns vertices of triangulated faces | get faces */
THREE.Shape.prototype.triangulate = function() {
return THREE.FontUtils.Triangulate( this.getPoints(), true );
};
for ( j = 1; j <= divisions; j ++ ) {
/* Convienence Method to return ExtrudeGeometry */
THREE.Shape.prototype.extrude = function(options) {
var extruded = new THREE.ExtrudeGeometry(this, options);
return extruded;
};
t = j / divisions;
THREE.ExtrudeGeometry = function(shape, options) {
var amount;
if (!options.amount) {
amount = 100;
} else {
amount = options.amount;
}
THREE.Geometry.call( this );
vertices = shape.getPoints();
faces = shape.triangulate();
contour = vertices;
bezelEnabled = false;
tx = THREE.FontUtils.b3( t, cpx0, cpx1, cpx2, cpx );
ty = THREE.FontUtils.b3( t, cpy0, cpy1, cpy2, cpy );
var scope = this;
points.push( new THREE.Vector2( tx, ty ) );
var i,
vert, vlen = vertices.length,
face, flen = faces.length;
}
// Back facing vertices
for ( i = 0; i < vlen; i++ ) {
break;
vert = vertices[ i ];
v( vert.x, vert.y, 0 );
}
}
// Front facing vertices
return points;
for ( i = 0; i < vlen; i++ ) {
};
vert = vertices[ i ];
v( vert.x, vert.y, amount );
}
THREE.Path.prototype.getMinAndMax = function() {
if ( bezelEnabled ) {
var points = this.getPoints();
for ( i = 0; i < blen; i++ ) {
var maxX, maxY;
var minX, minY;
bezelPt = bezelPoints[ i ];
v( bezelPt.x, bezelPt.y, bezelThickness );
maxX = maxY = Number.NEGATIVE_INFINITY;
minX = minY = Number.POSITIVE_INFINITY;
}
var p, i, il;
for ( i = 0; i < blen; i++ ) {
for ( i = 0, il = points.length; i < il; i ++ ) {
bezelPt = bezelPoints[ i ];
v( bezelPt.x, bezelPt.y, amount - bezelThickness );
p = points[ i ];
}
if ( p.x > maxX ) maxX = p.x;
else if ( p.x < minX ) minX = p.x;
if ( p.y > maxY ) maxY = p.y;
else if ( p.y < maxY ) minY = p.y;
}
// Bottom faces
// TODO find mid-pt?
for ( i = 0; i < flen; i++ ) {
return {
face = faces[ i ];
f3( face[ 2 ], face[ 1 ], face[ 0 ] );
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY
}
};
// Top faces
};
for ( i = 0; i < flen; i++ ) {
/* Draws this path onto a 2d canvas easily */
face = faces[ i ];
f3( face[ 0 ] + vlen, face[ 1 ] + vlen, face[ 2 ] + vlen );
THREE.Path.prototype.debug = function( canvas ) {
}
// JUST A STUB
if ( !canvas ) {
var lastV;
var j, k, l, m;
canvas = document.createElement( "canvas" );
canvas.setAttribute( 'width', 200 );
canvas.setAttribute( 'height', 200 );
// Faces Sides
document.body.appendChild( canvas );
}
contour.push(contour[0]); // in order not to check for boundary indics every time.
i = contour.length;
var ctx = canvas.getContext( "2d" );
ctx.fillStyle = "white";
ctx.fillRect( 0, 0, 200, 200 );
while ( --i > 0 ) {
ctx.strokeStyle = "black";
ctx.beginPath();
lastV = contour[ i ];
var i, il, item, action, args;
for ( j = 0; j < vlen; j++ ) {
// Debug Path
if ( vertices[ j ].equals( contour[ i ] ) ) break;
for ( i = 0, il = this.actions.length; i < il; i ++ ) {
}
for ( k = 0; k < vlen; k++ ) {
item = this.actions[ i ];
if ( vertices[ k ].equals( contour[ i - 1 ] ) ) break;
args = item.args;
action = item.action;
}
// Short hand for now
// Create faces for the z-sides of the text
ctx[ action ].apply( ctx, args );
f4( j, k, k + vlen, j + vlen );
/*
switch ( action ) {
}
case THREE.PathActions.MOVE_TO:
ctx[ action ]( args[ 0 ], args[ 1 ] );
break;
// UVs to be added
case THREE.PathActions.LINE_TO:
this.computeCentroids();
this.computeFaceNormals();
//this.computeVertexNormals();
ctx[ action ]( args[ 0 ], args[ 1 ] );
break;
function v( x, y, z ) {
case THREE.PathActions.QUADRATIC_CURVE_TO:
scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
ctx[ action ]( args[ 0 ], args[ 1 ], args[ 2 ], args[ 3 ] );
break;
}
case THREE.PathActions.CUBIC_CURVE_TO:
function f3( a, b, c ) {
ctx[ action ]( args[ 0 ], args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ] );
break;
scope.faces.push( new THREE.Face3( a, b, c) );
}
*/
}
function f4( a, b, c, d ) {
ctx.stroke();
ctx.closePath();
// DebugPoints
scope.faces.push( new THREE.Face4( a, b, c, d) );
ctx.strokeStyle = "red";
}
var p, points = this.getPoints();
for ( i = 0, il = points.length; i < il; i ++ ) {
};
p = points[ i ];
ctx.beginPath();
ctx.arc( p.x, p.y, 1.5, 0, Math.PI * 2, false );
ctx.stroke();
ctx.closePath();
}
THREE.ExtrudeGeometry.prototype = new THREE.Geometry();
THREE.ExtrudeGeometry.prototype.constructor = THREE.ExtrudeGeometry;
};
......@@ -19,22 +19,22 @@
* bezelThickness: <float>, // how deep into text bezel goes
* bezelSize: <float>, // how far from text outline is bezel
* }
*
* It uses techniques used in
*
*
* It uses techniques used in:
*
* typeface.js and canvastext
* For converting fonts and rendering with javascript
* For converting fonts and rendering with javascript
* http://typeface.neocracy.org
*
*
* Triangulation ported from AS3
* Simple Polygon Triangulation
* http://actionsnippet.com/?p=1462
*
* A Method to triangulate shapes with holes
* A Method to triangulate shapes with holes
* http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
*
*/
THREE.TextGeometry = function ( text, parameters ) {
THREE.Geometry.call( this );
......@@ -87,8 +87,8 @@ THREE.TextGeometry.prototype.set = function ( text, parameters ) {
scope.vertices = [];
scope.faces = [];
var i,
vert, vlen = vertices.length,
var i,
vert, vlen = vertices.length,
face, flen = faces.length,
bezelPt, blen = bezelPoints.length;
......@@ -104,7 +104,7 @@ THREE.TextGeometry.prototype.set = function ( text, parameters ) {
// Front facing vertices
for ( i = 0; i < vlen; i++ ) {
vert = vertices[ i ];
v( vert.x, vert.y, height );
......@@ -247,13 +247,13 @@ THREE.TextGeometry.prototype.set = function ( text, parameters ) {
function f3( a, b, c ) {
scope.faces.push( new THREE.Face3( a, b, c) );
scope.faces.push( new THREE.Face3( a, b, c ) );
}
function f4( a, b, c, d ) {
scope.faces.push( new THREE.Face4( a, b, c, d) );
scope.faces.push( new THREE.Face4( a, b, c, d ) );
}
......@@ -285,7 +285,7 @@ THREE.FontUtils = {
var ThreeFont = this;
ThreeFont.faces[ family ] = ThreeFont.faces[ family ] || {};
ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
......@@ -358,7 +358,7 @@ THREE.FontUtils = {
firstPt = all[ firstIndex ];
endPt = all.slice( firstIndex + 1 ).indexOf( firstPt ) + firstIndex;
if ( endPt <= firstIndex ) break;
if ( endPt <= firstIndex ) break;
var contours = singleCharPoints.slice( firstIndex, endPt + 1 );
......@@ -472,7 +472,7 @@ THREE.FontUtils = {
prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
nextShapeVert = ( shapeIndex + 1 ) < shape.length ? shapeIndex + 1 : 0;
prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
nextHoleVert = ( holeIndex + 1 ) < hole.length ? holeIndex + 1 : 0 ;
var areaapts = [];
......@@ -495,7 +495,7 @@ THREE.FontUtils = {
var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
shapeIndex += shapeOffset;
holeIndex += holeOffset;
if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
shapeIndex %= shape.length;
......@@ -505,7 +505,7 @@ THREE.FontUtils = {
prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
nextShapeVert = ( shapeIndex + 1 ) < shape.length ? shapeIndex + 1 : 0;
prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
nextHoleVert = ( holeIndex + 1 ) < hole.length ? holeIndex + 1 : 0 ;
......@@ -538,7 +538,7 @@ THREE.FontUtils = {
prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
nextShapeVert = ( shapeIndex + 1 ) < shape.length ? shapeIndex + 1 : 0;
prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
nextHoleVert = ( holeIndex + 1 ) < hole.length ? holeIndex + 1 : 0 ;
}
......@@ -563,7 +563,7 @@ THREE.FontUtils = {
shapeGroup.shape = shape;
}
var triangulatedPoints = [];
var triangulatedFaces = [];
var lastTriangles = 0;
......@@ -593,7 +593,7 @@ THREE.FontUtils = {
lastTriangles += shape.length;
}
// Now we push the "cut" vertices back to the triangulated indices.
......@@ -660,10 +660,10 @@ THREE.FontUtils = {
var i, p,
face = this.getFace(),
scale = this.size / face.resolution,
offset = 0,
chars = String( text ).split( '' ),
offset = 0,
chars = String( text ).split( '' ),
length = chars.length;
var fontPaths = [];
for ( i = 0; i < length; i++ ) {
......@@ -676,7 +676,7 @@ THREE.FontUtils = {
}
// get the width
// get the width
var width = offset / 2;
......@@ -853,7 +853,7 @@ THREE.FontUtils = {
var pts = [];
var path = new THREE.Path();
var i, i2,
outline, action, length,
......@@ -861,21 +861,21 @@ THREE.FontUtils = {
x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
laste,
glyph = face.glyphs[ c ] || face.glyphs[ ctxt.options.fallbackCharacter ];
if ( !glyph ) return;
if ( glyph.o ) {
outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
length = outline.length;
scaleX = scale;
scaleY = scale;
for ( i = 0; i < length; ) {
action = outline[ i++ ];
switch( action ) {
case 'm':
......@@ -885,7 +885,7 @@ THREE.FontUtils = {
x = outline[ i++ ] * scaleX + offset;
y = outline[ i++ ] * scaleY;
pts.push( new THREE.Vector2( x, y ) );
path.moveTo(x,y);
break;
......@@ -898,25 +898,25 @@ THREE.FontUtils = {
pts.push( new THREE.Vector2( x, y ) );
path.lineTo(x,y);
break;
case 'q':
// QuadraticCurveTo
cpx = outline[ i++ ] * scaleX + offset;
cpy = outline[ i++ ] * scaleY;
cpx1 = outline[ i++ ] * scaleX + offset;
cpy1 = outline[ i++ ] * scaleY;
path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
laste = pts[ pts.length - 1 ];
if ( laste ) {
cpx0 = laste.x;
cpy0 = laste.y;
for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2++ ) {
var t = i2 / divisions;
......@@ -926,30 +926,30 @@ THREE.FontUtils = {
}
}
}
break;
case 'b':
// Cubic Bezier Curve
cpx = outline[ i++ ] * scaleX + offset;
cpy = outline[ i++ ] * scaleY;
cpx1 = outline[ i++ ] * scaleX + offset;
cpy1 = outline[ i++ ] * -scaleY;
cpx2 = outline[ i++ ] * scaleX + offset;
cpy2 = outline[ i++ ] * -scaleY;
path.quadraticCurveTo(cpx, cpy, cpx1, cpy1, cpx2, cpy2);
path.quadraticCurveTo( cpx, cpy, cpx1, cpy1, cpx2, cpy2 );
laste = pts[ pts.length - 1 ];
if ( laste ) {
cpx0 = laste.x;
cpy0 = laste.y;
for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2++ ) {
var t = i2 / divisions;
......@@ -967,7 +967,7 @@ THREE.FontUtils = {
}
}
path.debug(document.getElementById("boo"));
console.log(path);
......@@ -979,17 +979,17 @@ THREE.FontUtils = {
/**
* This code is a quick port of code written in C++ which was submitted to
* flipcode.com by John W. Ratcliff // July 22, 2000
* This code is a quick port of code written in C++ which was submitted to
* flipcode.com by John W. Ratcliff // July 22, 2000
* See original code and more information here:
* http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
*
*
* ported to actionscript by Zevan Rosser
* www.actionsnippet.com
*
*
* ported to javascript by Joshua Koo
* http://www.lab4games.net/zz85/blog
*
*
*/
......@@ -997,7 +997,7 @@ THREE.FontUtils = {
var EPSILON = 0.0000000001;
// takes in an contour array and returns
// takes in an contour array and returns
var process = function( contour, indices ) {
......@@ -1006,7 +1006,7 @@ THREE.FontUtils = {
if ( n < 3 ) return null;
var result = [],
verts = [],
verts = [],
vertIndices = [];
/* we want a counter-clockwise polygon in verts */
......@@ -1048,19 +1048,19 @@ THREE.FontUtils = {
}
/* three consecutive vertices in current polygon, <u,v,w> */
u = v; if ( nv <= u ) u = 0; /* previous */
v = u + 1; if ( nv <= v ) v = 0; /* new v */
w = v + 1; if ( nv <= w ) w = 0; /* next */
if ( snip( contour, u, v, w, nv, verts ) ) {
var a, b, c, s, t;
/* true names of the vertices */
a = verts[ u ];
b = verts[ v ];
a = verts[ u ];
b = verts[ v ];
c = verts[ w ];
/* output Triangle */
......@@ -1070,17 +1070,17 @@ THREE.FontUtils = {
result.push( contour[ c ] );
vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
/* remove v from the remaining polygon */
for( s = v, t = v + 1; t < nv; s++, t++ ) {
verts[ s ] = verts[ t ];
verts[ s ] = verts[ t ];
}
nv--;
/* reset error detection counter */
count = 2 * nv;
......@@ -1088,19 +1088,19 @@ THREE.FontUtils = {
}
}
if ( indices ) return vertIndices;
return result;
};
// calculate area of the contour polygon
var area = function ( contour ) {
var n = contour.length;
var a = 0.0;
for( var p = n - 1, q = 0; q < n; p = q++ ) {
a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
......@@ -1110,7 +1110,7 @@ THREE.FontUtils = {
return a * 0.5;
};
// see if p is inside triangle abc
var insideTriangle = function( ax, ay,
......@@ -1122,23 +1122,23 @@ THREE.FontUtils = {
var cX, cY, apx, apy;
var bpx, bpy, cpx, cpy;
var cCROSSap, bCROSScp, aCROSSbp;
aX = cx - bx; aY = cy - by;
bX = ax - cx; bY = ay - cy;
cX = bx - ax; cY = by - ay;
apx= px -ax; apy= py - ay;
bpx= px - bx; bpy= py - by;
cpx= px - cx; cpy= py - cy;
aCROSSbp = aX*bpy - aY*bpx;
cCROSSap = cX*apy - cY*apx;
bCROSScp = bX*cpy - bY*cpx;
return ( (aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0) );
};
var snip = function ( contour, u, v, w, n, verts ) {
var p;
......@@ -1153,13 +1153,13 @@ THREE.FontUtils = {
cx = contour[ verts[ w ] ].x;
cy = contour[ verts[ w ] ].y;
if ( EPSILON > (((bx-ax)*(cy-ay)) - ((by-ay)*(cx-ax))) ) return false;
for ( p = 0; p < n; p++ ) {
if( (p == u) || (p == v) || (p == w) ) continue;
px = contour[ verts[ p ] ].x
py = contour[ verts[ p ] ].y
......@@ -1170,11 +1170,11 @@ THREE.FontUtils = {
return true;
};
namespace.Triangulate = process;
namespace.Triangulate.area = area;
return namespace;
})(THREE.FontUtils);
......
......@@ -93,8 +93,11 @@ EXTRAS_FILES = [
'extras/cameras/RollCamera.js',
'extras/cameras/TrackballCamera.js',
'extras/cameras/QuakeCamera.js',
'extras/geometries/Path.js',
'extras/geometries/Shape.js',
'extras/geometries/CubeGeometry.js',
'extras/geometries/CylinderGeometry.js',
'extras/geometries/ExtrudeGeometry.js',
'extras/geometries/IcosahedronGeometry.js',
'extras/geometries/LatheGeometry.js',
'extras/geometries/PlaneGeometry.js',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册