商域无疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商业用途-保持一致”创作公用协议
转载请保留此句:商域无疆 - 本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。
俺也是刚开始学,好多地儿肯定不对还请见谅.
以下代码是THREE.JS 源码文件中Math/Spline.js文件的注释.
/** * Spline from Tween.js, slightly optimized (and trashed) * http://sole.github.com/tween.js/examples/05_spline.html * * @author mrdoob / http://mrdoob.com/ * @author alteredq / http://alteredqualia.com/ */ /* ///Spline对象的构造函数.用来在三维空间内通过参数points(Vector3数组)创建一个样条曲线对象.. /// /// 定义:样条曲线是经过一系列给定点的光滑曲线。最初,样条曲线都是借助于物理样条得到的,放样员把富有弹性的细木条(或有机玻璃条), /// 用压铁固定在曲线应该通过的给定型值点处,样条做自然弯曲所绘制出来的曲线就是样条曲线。样条曲线不仅通过各有序型值点, /// 并且在各型值点处的一阶和二阶导数连续,也即该曲线具有连续的、曲率变化均匀的特点。 /// NOTE:参考百度百科http://baike.baidu.com/view/1896463.htm?fr=aladdin /// NOTE:关于三次样条插值,参考百度百科http://baike.baidu.com/view/2326225.htm?fr=aladdin /// NOTE:关于更多样条曲线插值,参考维基百科http://zh.wikipedia.org/wiki/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A /// NOTE:关于样条曲线,参考维基百科http://zh.wikipedia.org/wiki/%E6%A0%B7%E6%9D%A1%E5%87%BD%E6%95%B0 /// /// /// 用法: var a = new Vector3(0,0,0),b = new Vector3(1,1,1),c = new Vector3(2,2,2); var points = new Array(a,b,c); var spline = new Spline(points); ///创建一个a,b,c三点组成的样条曲线对象. */ ///Spline ///Vector3对象组成的points数组对象 THREE.Spline = function ( points ) { this.points = points; //将参数points设置给当前样条对象的points属性 var c = [], v3 = { x: 0, y: 0, z: 0 }, point, intPoint, weight, w2, w3, pa, pb, pc, pd; /**************************************** ****下面是Spline对象提供的功能函数. ****************************************/ /* ///initFromArray方法通过Vector3对象组成的数组(参数a),重新设置当前样条曲线. */ ///initFromArray ///Vector3对象组成的points数组对象 ///返回新的样条曲线 this.initFromArray = function ( a ) { this.points = []; for ( var i = 0; i < a.length; i ++ ) { //获得数组长度,并将数组中元素赋值给当前样条曲线的points属性. this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] }; } }; /* ///getPoint方法将当前样条曲线作为一个整体,返回位于当前样条曲线k位置上的点坐标. /// NOTE:getPoint()方法中k值取值范围是0.0-1.0. */ ///getPoint ///返回位于当前样条曲线k位置上的点坐标 ///返回新的样条曲线 this.getPoint = function ( k ) { point = ( this.points.length - 1 ) * k; //获得k大概位于当前样条曲线的第几个节点后,得出结果可能是小数(例如样条曲线有9个节点,参数k为0.4,得出结果3.2说明参数k位于当前样条曲线第三个节点到第四个节点长度20%的位置),赋值给point intPoint = Math.floor( point ); //调用Math.floor()方法,获得整数,第三个节点,赋值给intPoint weight = point - intPoint; //或得权值,赋值给weight c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1; //三次样条曲线的起始点c[0] c[ 1 ] = intPoint; //三次样条曲线的控制点c[1] c[ 2 ] = intPoint > this.points.length - 2 ? this.points.length - 1 : intPoint + 1; //三次样条曲线的控制点c[2] c[ 3 ] = intPoint > this.points.length - 3 ? this.points.length - 1 : intPoint + 2; //三次样条曲线的结束点c[3] pa = this.points[ c[ 0 ] ]; pb = this.points[ c[ 1 ] ]; pc = this.points[ c[ 2 ] ]; pd = this.points[ c[ 3 ] ]; w2 = weight * weight; //权值的平方 w3 = weight * w2; //权值的立方 v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 ); //调用interpolate方法是样条插值函数,返回计算位于参数值t的曲线点x坐标 v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 ); //调用interpolate方法是样条插值函数,返回计算位于参数值t的曲线点y坐标 v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 ); //调用interpolate方法是样条插值函数,返回计算位于参数值t的曲线点z坐标 return v3; //返回位于当前样条曲线k位置上的点坐标 }; /* ///getControlPointsArray方法返回当前样条曲线节点坐标构成的数组 */ ///getControlPointsArray ///返回当前样条曲线节点坐标构成的数组 this.getControlPointsArray = function () { var i, p, l = this.points.length, coords = []; for ( i = 0; i < l; i ++ ) { //遍历当前样条曲线points属性 p = this.points[ i ]; coords[ i ] = [ p.x, p.y, p.z ]; //将points属性直接赋值给coords数组 } return coords; //返回当前样条曲线节点坐标构成的数组 }; /* ///getLength方法返回被参数nSubDivisions(将当前样条曲线等分成多少段)等分当前样条曲线的长度数组和总长度组成的对象. */ ///getLength ///分段数 ///返回被参数nSubDivisions(将当前样条曲线等分成多少段)等分当前样条曲线的长度数组和总长度组成的对象 // approximate length by summing linear segments //汇总线性线段获得近似长度 this.getLength = function ( nSubDivisions ) { var i, index, nSamples, position, point = 0, intPoint = 0, oldIntPoint = 0, oldPosition = new THREE.Vector3(), tmpVec = new THREE.Vector3(), chunkLengths = [], totalLength = 0; // first point has 0 length // 第一个起点长度是0 chunkLengths[ 0 ] = 0; if ( ! nSubDivisions ) nSubDivisions = 100; nSamples = this.points.length * nSubDivisions; oldPosition.copy( this.points[ 0 ] ); for ( i = 1; i < nSamples; i ++ ) { index = i / nSamples; position = this.getPoint( index ); //调用getPoint()方法,获得当前段数的位置坐标. tmpVec.copy( position ); totalLength += tmpVec.distanceTo( oldPosition ); //求当前段数长度. oldPosition.copy( position ); point = ( this.points.length - 1 ) * index; intPoint = Math.floor( point ); if ( intPoint != oldIntPoint ) { chunkLengths[ intPoint ] = totalLength; oldIntPoint = intPoint; } } // last point ends with total length //最后一个结束点,返回总长度. chunkLengths[ chunkLengths.length ] = totalLength; return { chunks: chunkLengths, total: totalLength }; }; this.reparametrizeByArcLength = function ( samplingCoef ) { var i, j, index, indexCurrent, indexNext, linearDistance, realDistance, sampling, position, newpoints = [], tmpVec = new THREE.Vector3(), sl = this.getLength(); newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() ); for ( i = 1; i < this.points.length; i ++ ) { //tmpVec.copy( this.points[ i - 1 ] ); //linearDistance = tmpVec.distanceTo( this.points[ i ] ); realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ]; sampling = Math.ceil( samplingCoef * realDistance / sl.total ); indexCurrent = ( i - 1 ) / ( this.points.length - 1 ); indexNext = i / ( this.points.length - 1 ); for ( j = 1; j < sampling - 1; j ++ ) { index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent ); position = this.getPoint( index ); newpoints.push( tmpVec.copy( position ).clone() ); } newpoints.push( tmpVec.copy( this.points[ i ] ).clone() ); } this.points = newpoints; }; // Catmull-Rom /* ///interpolate方法是传说中的样条插值函数,这里是三次样条插值算法,返回计算位于参数值t的曲线点. /// NOTE:关于三次样条插值,参考百度百科http://baike.baidu.com/view/2326225.htm?fr=aladdin /// NOTE:关于更多样条曲线插值,参考维基百科http://zh.wikipedia.org/wiki/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A /// http://zh.wikipedia.org/wiki/%E6%A0%B7%E6%9D%A1%E6%8F%92%E5%80%BC /// NOTE:关于样条曲线,参考维基百科http://zh.wikipedia.org/wiki/%E6%A0%B7%E6%9D%A1%E5%87%BD%E6%95%B0 */ ///interpolate ///样条曲线起始点p0 ///样条曲线控制点p1 ///样条曲线控制点p2 ///样条曲线结束点p3 ///t为参数值,0<=t<=1 ///t2是参数值t的平方 ///t3是参数值t的立方 ///返回计算位于参数值t的曲线点 function interpolate( p0, p1, p2, p3, t, t2, t3 ) { var v0 = ( p2 - p0 ) * 0.5, v1 = ( p3 - p1 ) * 0.5; return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1; //返回计算位于参数值t的曲线点 }; };
商域无疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商业用途-保持一致”创作公用协议
转载请保留此句:商域无疆 - 本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。
以下代码是THREE.JS 源码文件中Math/Spline.js文件的注释.
更多更新在 : https://github.com/omni360/three.js.sourcecode