商域無疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商業用途-保持一緻”創作公用協定
轉載請保留此句:商域無疆 - 本部落格專注于 靈活開發及移動和物聯裝置研究:資料可視化、GOLANG、Html5、WEBGL、THREE.JS,否則,出自本部落格的文章拒絕轉載或再轉載,謝謝合作。
俺也是剛開始學,好多地兒肯定不對還請見諒.
以下代碼是THREE.JS 源碼檔案中extras/TubeGeometry.js檔案的注釋.
更多更新在 : https://github.com/omni360/three.js.sourcecode
/**
* @author zz85 / http://www.lab4games.net/zz85/blog
* @author alteredq / http://alteredqualia.com/
*
* For Text operations in three.js (See TextGeometry)
*
* It uses techniques used in:
*
* typeface.js and canvastext
* For converting fonts and rendering with javascript
* 使用javascript渲染和轉換字型通過typeface.js,通路下面網站.
* http://typeface.neocracy.org
*
* Triangulation ported from AS3
* Simple Polygon Triangulation
* 簡單的多邊形三角化
* http://actionsnippet.com/?p=1462
*
* A Method to triangulate shapes with holes
* 一個将帶有孔洞(镂空,用這個詞肯能更加的專業一些吧.)的圖形三角化
* http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
*/
/****************************typeface_js檔案格式,下面是一個字元"o",有興趣的朋友可以看看形字型的規範.*************************************************
* if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace(
* {"glyphs":
* {"ο":
* {"x_min":30,
* "x_max":741,
* "ha":774,
* "o":"m 395 683 q 645 587 550 683 q 741 337 741 492 q 646 79 741 173 q 385 -15 552 -15 q 127 78 225 -15 q 30 333 30 172 q 129 590 30 498 q 395 683 228 683 m 269 174 q 305 85 275 119 q 386 52 335 52 q 464 85 436 52 q 503 172 491 119 q 510 237 506 194 q 515 336 515 279 q 510 431 515 391 q 503 494 506 472 q 464 581 491 548 q 385 615 436 615 q 291 563 315 615 q 261 459 267 512 q 256 333 256 407 q 269 174 256 248 "
* }
* }
* }
* }
* )
****************************************************************************************************************************************************/
/**************************************************************
* FontUtils Font對象的工具集
**************************************************************/
THREE.FontUtils = {
faces: {}, //組成字型的面.
// Just for now. face[weight][style]
face: 'helvetiker', //字型名稱
weight: 'normal', //字寬,字型筆劃的寬度.
style: 'normal', //字型樣式,粗體,斜體等等
size: 150, //字型尺寸
divisions: 10, //定距等分數量
getFace: function () {
try { //捕獲字型字寬字型樣式等異常
return this.faces[ this.face ][ this.weight ][ this.style ];
} catch (e) {
throw "The font " + this.face + " with " + this.weight + " weight and " + this.style + " style is missing."
};
},
/*
///loadFace方法的具體實作,讀取字型檔案内的字元的比劃圖形路徑資料.
///****************************typeface_js檔案格式,下面是一個字元"o",有興趣的朋友可以看看形字型的規範.*************************************************
/// if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace(
/// {"glyphs":
/// {"ο":
/// {"x_min":30,
/// "x_max":741,
/// "ha":774,
/// "o":"m 395 683 q 645 587 550 683 q 741 337 741 492 q 646 79 741 173 q 385 -15 552 -15 q 127 78 225 -15 q 30 333 30 172 q 129 590 30 498 q 395 683 228 683 m 269 174 q 305 85 275 119 q 386 52 335 52 q 464 85 436 52 q 503 172 491 119 q 510 237 506 194 q 515 336 515 279 q 510 431 515 391 q 503 494 506 472 q 464 581 491 548 q 385 615 436 615 q 291 563 315 615 q 261 459 267 512 q 256 333 256 407 q 269 174 256 248 "
/// }
/// }
/// }
/// }
/// )
///****************************************************************************************************************************************************
*/
///<summary>loadFace</summary>
///<param name ="data" type="Object">字型形資料.</param>
///<returns type="Object3d">傳回Object3D對象</returns>
loadFace: function ( data ) {
var family = data.familyName.toLowerCase(); //字型族名字轉換成小寫
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;
var face = ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
return data; //傳回字型檔案内的字元的比劃圖形路徑資料.
},
/*
///drawText方法的具體實作,從讀取的字型資料中,按照文字内容中的每個字元,獲得字元的比劃路徑
*/
///<summary>loadFace</summary>
///<param name ="text" type="String">文字内容.</param>
///<returns type="Object3d">傳回字元的比劃圖形路徑</returns>
drawText: function ( text ) {
var characterPts = [], allPts = [];
// RenderText
var i, p,
face = this.getFace(), //字型檔案内的字元的比劃圖形路徑資料.
scale = this.size / face.resolution, //字型縮放
offset = 0, //字元間距
chars = String( text ).split( '' ), //分割字元串
length = chars.length;
var fontPaths = []; //字型路徑頂點資料數組.
for ( i = 0; i < length; i ++ ) { //周遊所有的字元
var path = new THREE.Path();
var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset, path ); //調用extractGlyphPoints方法,解析字元路徑.
offset += ret.offset;
fontPaths.push( ret.path );
}
// get the width
var width = offset / 2; //字寬,字型筆劃的寬度
//
// for ( p = 0; p < allPts.length; p++ ) {
//
// allPts[ p ].x -= width;
//
// }
//var extract = this.extractPoints( allPts, characterPts );
//extract.contour = allPts;
//extract.paths = fontPaths;
//extract.offset = width;
return { paths: fontPaths, offset: width }; //傳回特定格式的對象.
},
/*
///extractGlyphPoints方法解析字元路徑.傳回特定格式的字元路徑對象
///****************************typeface_js檔案格式,下面是一個字元"o",有興趣的朋友可以看看形字型的規範.*************************************************
/// if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace(
/// {"glyphs":
/// {"ο":
/// {"x_min":30,
/// "x_max":741,
/// "ha":774,
/// "o":"m 395 683 q 645 587 550 683 q 741 337 741 492 q 646 79 741 173 q 385 -15 552 -15 q 127 78 225 -15 q 30 333 30 172 q 129 590 30 498 q 395 683 228 683 m 269 174 q 305 85 275 119 q 386 52 335 52 q 464 85 436 52 q 503 172 491 119 q 510 237 506 194 q 515 336 515 279 q 510 431 515 391 q 503 494 506 472 q 464 581 491 548 q 385 615 436 615 q 291 563 315 615 q 261 459 267 512 q 256 333 256 407 q 269 174 256 248 "
/// }
/// }
/// }
/// }
/// )
///****************************************************************************************************************************************************
*/
///<summary>extractGlyphPoints</summary>
///<param name ="c" type="Char">字元.</param>
///<param name ="face" type="Object">字型檔案内的字元的比劃圖形路徑資料.</param>
///<param name ="scale" type="float">字型縮放.</param>
///<param name ="offset" type="float">字元間距.</param>
///<param name ="path" type="THREE.Path">文字的圖形路徑.</param>
///<returns type="Object3d">傳回特定格式的字元路徑對象</returns>
extractGlyphPoints: function ( c, face, scale, offset, path ) {
var pts = [];
var i, i2, divisions,
outline, action, length,
scaleX, scaleY,
x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
laste,
glyph = face.glyphs[ c ] || face.glyphs[ '?' ];
if ( ! glyph ) return;
//下邊的代碼,和THREE.Path裡定義的動作定義的一樣.結合字元的資料.這樣筆劃的圖形路徑就畫出來了.
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 ++ ];
//console.log( action );
switch ( action ) {
case 'm':
// Move To
x = outline[ i ++ ] * scaleX + offset;
y = outline[ i ++ ] * scaleY;
path.moveTo( x, y );
break;
case 'l':
// Line To
x = outline[ i ++ ] * scaleX + offset;
y = outline[ i ++ ] * scaleY;
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;
var tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
var ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
}
}
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.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, 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;
var tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
var ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
}
}
break;
}
}
}
return { offset: glyph.ha * scale, path:path }; //傳回特定格式的字元路徑輪廓圖形對象
}
};
/*
///generateShapes方法的根據文字内容(參數text),參數選項(參數parameters),生成文字路徑輪廓圖形數組.
/// NOTE:參數parameters的格式如下,和材質的用法一緻.
/// parameters = {
/// size: <float>, // size of the text 字型的大小
/// height: <float>, // thickness to extrude text 3維字型的拉伸厚度,
/// curveSegments: <int>, // number of points on the curves 拉伸厚度上的細分線段數.
///
/// font: <string>, // font name //字型名稱
/// weight: <string>, // font weight (normal, bold) //字型寬度
/// style: <string>, // font style (normal, italics) //字型樣式
///
/// bevelEnabled: <bool>, // turn on bevel 是否啟用字型倒角
/// bevelThickness: <float>, // how deep into text bevel goes //倒角的厚度
/// bevelSize: <float>, // how far from text outline is bevel //從截面外輪廓倒角的尺寸
/// }
*/
///<summary>generateShapes</summary>
///<param name ="text" type="String">文字内容.</param>
///<param name ="parameters" type="Object">文字内容.</param>
///<returns type="Object3d">傳回文字路徑輪廓圖形數組</returns>
THREE.FontUtils.generateShapes = function ( text, parameters ) {
// Parameters
parameters = parameters || {}; //參數選項.
var size = parameters.size !== undefined ? parameters.size : 100; //字型的大小,如果未定義初始化為100.
var curveSegments = parameters.curveSegments !== undefined ? parameters.curveSegments : 4; //拉伸厚度上的細分線段數,如果未定義初始化為4
var font = parameters.font !== undefined ? parameters.font : 'helvetiker'; //字型名稱,如果未定義初始化為'helvetiker'
var weight = parameters.weight !== undefined ? parameters.weight : 'normal'; //字型寬度,如果未定義初始化為'normal'
var style = parameters.style !== undefined ? parameters.style : 'normal'; //字型樣式,如果未定義初始化為'normal'
THREE.FontUtils.size = size; //指派字型的大小
THREE.FontUtils.divisions = curveSegments; //指派定距等分數量
THREE.FontUtils.face = font; //指派字型名稱
THREE.FontUtils.weight = weight; //指派字型寬度
THREE.FontUtils.style = style; //指派字型樣式
// Get a Font data json object
var data = THREE.FontUtils.drawText( text ); //調用THREE.FontUtils.drawText()方法,傳回字元的比劃圖形路徑
var paths = data.paths;
var shapes = [];
for ( var p = 0, pl = paths.length; p < pl; p ++ ) { //周遊圖形數組
Array.prototype.push.apply( shapes, paths[ p ].toShapes() ); //将圖形複制到shapes數組内.
}
return shapes; //傳回文字路徑輪廓圖形數組
};
/**
* 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
*
*/
( function ( namespace ) {
var EPSILON = 0.0000000001;
// takes in an contour array and returns
//多邊形三角化算法參考:
// http://en.wikipedia.org/wiki/Delaunay_triangulation
/*
///process方法将多邊形三角化.特别詳細的還是找本幾何造型的書,自己看看吧.
*/
///<summary>process</summary>
///<param name ="contour" type="Vector2Array">二維向量數組.</param>
///<param name ="indices" type="Geometry">true 或者 false,一個布爾值,訓示是否需要傳回索引</param>
///<returns type="Number">傳回三角形頂點資料</returns>
var process = function ( contour, indices ) {
var n = contour.length;
if ( n < 3 ) return null;
var result = [],
verts = [],
vertIndices = [];
/* we want a counter-clockwise polygon in verts */
/* 我們想要頂點順序順時針的多邊形*/
var u, v, w;
if ( area( contour ) > 0.0 ) {
for ( v = 0; v < n; v ++ ) verts[ v ] = v;
} else {
for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v;
}
var nv = n;
/* remove nv - 2 vertices, creating 1 triangle every time */
// 删除nv 2個頂點,每次建立一個三角形.
var count = 2 * nv; /* error detection */ //錯誤檢查
for ( v = nv - 1; nv > 2; ) {
/* if we loop, it is probably a non-simple polygon */
// 如果上面條件成立,這個圖形将不是一個簡化多邊形.
if ( ( count -- ) <= 0 ) { //如果數量小于等于0
//** Triangulate: ERROR - probable bad polygon! 錯誤的多邊形對象
//throw ( "Warning, unable to triangulate polygon!" );
//return null;
// Sometimes warning is fine, especially polygons are triangulated in reverse.
console.log( 'Warning, unable to triangulate polygon!' ); //提示使用者不能三角化多邊形
if ( indices ) return vertIndices;
return result;
}
/* three consecutive vertices in current polygon, <u,v,w> */
// 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,b,c
a = verts[ u ];
b = verts[ v ];
c = verts[ w ];
/* output Triangle */
//輸出三角形
result.push( [ contour[ a ],
contour[ b ],
contour[ c ] ] );
vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
//包含系列的三角形頂點數組
/* remove v from the remaining polygon */
//從剩餘的多邊形删除v
for ( s = v, t = v + 1; t < nv; s++, t++ ) {
verts[ s ] = verts[ t ];
}
nv --;
/* reset error detection counter */
//複位錯誤檢測計數器
count = 2 * nv;
}
}
if ( indices ) return vertIndices; //傳回
return result;
};
/*
///area用來計算多邊形輪廓的面積,經常用來判斷頂點的排列順序,是順時針,還是逆時針,結果小于0,為順時針,大于0,為逆時針.
*/
///<summary>area</summary>
///<param name ="contour" type="Vector2Array">多邊形頂點數組</param>
///<returns type="float">傳回多邊形的面積</returns>
// 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;
}
return a * 0.5; //傳回多邊形的面積.
};
var snip = function ( contour, u, v, w, n, verts ) {
var p;
var ax, ay, bx, by;
var cx, cy, px, py;
ax = contour[ verts[ u ] ].x;
ay = contour[ verts[ u ] ].y;
bx = contour[ verts[ v ] ].x;
by = contour[ verts[ v ] ].y;
cx = contour[ verts[ w ] ].x;
cy = contour[ verts[ w ] ].y;
if ( EPSILON > ( ( ( bx - ax ) * ( cy - ay ) ) - ( ( by - ay ) * ( cx - ax ) ) ) ) return false; //如果底邊乘以高
var aX, aY, bX, bY, cX, cY;
var apx, apy, 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;
for ( p = 0; p < n; p ++ ) {
px = contour[ verts[ p ] ].x
py = contour[ verts[ p ] ].y
if ( ( ( px === ax ) && ( py === ay ) ) ||
( ( px === bx ) && ( py === by ) ) ||
( ( px === cx ) && ( py === cy ) ) ) continue;
apx = px - ax; apy = py - ay;
bpx = px - bx; bpy = py - by;
cpx = px - cx; cpy = py - cy;
// see if p is inside triangle abc
aCROSSbp = aX * bpy - aY * bpx;
cCROSSap = cX * apy - cY * apx;
bCROSScp = bX * cpy - bY * cpx;
if ( ( aCROSSbp >= - EPSILON ) && ( bCROSScp >= - EPSILON ) && ( cCROSSap >= - EPSILON ) ) return false;
}
return true;
};
namespace.Triangulate = process;
namespace.Triangulate.area = area;
return namespace;
} )( THREE.FontUtils );
// To use the typeface.js face files, hook up the API
// 使用typeface.js面檔案,挂接API,
self._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };
THREE.typeface_js = self._typeface_js;
商域無疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商業用途-保持一緻”創作公用協定
轉載請保留此句:商域無疆 - 本部落格專注于 靈活開發及移動和物聯裝置研究:資料可視化、GOLANG、Html5、WEBGL、THREE.JS,否則,出自本部落格的文章拒絕轉載或再轉載,謝謝合作。
以下代碼是THREE.JS 源碼檔案中extras/TubeGeometry.js檔案的注釋.
更多更新在 : https://github.com/omni360/three.js.sourcecode