您的位置:首页 > Web前端 > JavaScript

three.js 源码注释(九十一)extras/core/Curve.js

2015-02-01 20:12 801 查看
商域无疆 (http://blog.csdn.net/omni360/)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:商域无疆 - 本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。

俺也是刚开始学,好多地儿肯定不对还请见谅.

以下代码是THREE.JS 源码文件中extras/core/Curve.js文件的注释.

更多更新在 : https://github.com/omni360/three.js.sourcecode

/**
 * @author zz85 / http://www.lab4games.net/zz85/blog  * Extensible curve object
 *
 * Some common of Curve methods 一些通用的方法.
 * .getPoint(t), getTangent(t)
 * .getPointAt(u), getTagentAt(u)
 * .getPoints(), .getSpacedPoints()
 * .getLength()
 * .updateArcLengths()
 *
 * This following classes subclasses THREE.Curve:
 * 这些是THREE.Curve的一些子类.
 *
 * -- 2d classes --
 * THREE.LineCurve
 * THREE.QuadraticBezierCurve
 * THREE.CubicBezierCurve
 * THREE.SplineCurve
 * THREE.ArcCurve
 * THREE.EllipseCurve
 *
 * -- 3d classes --
 * THREE.LineCurve3
 * THREE.QuadraticBezierCurve3
 * THREE.CubicBezierCurve3
 * THREE.SplineCurve3
 * THREE.ClosedSplineCurve3
 *
 * A series of curves can be represented as a THREE.CurvePath
 * 一个曲线序列可以用THREE.CurvePath
 *
 **/

/**************************************************************
 *	Abstract Curve base class 曲线抽象基类
 **************************************************************/
/*
///Curve对象曲线抽象基类,一个可扩展的曲线对象包含插值方法.
///
///	定义:样条曲线是经过一系列给定点的光滑曲线。最初,样条曲线都是借助于物理样条得到的,放样员把富有弹性的细木条(或有机玻璃条),
///		 用压铁固定在曲线应该通过的给定型值点处,样条做自然弯曲所绘制出来的曲线就是样条曲线。样条曲线不仅通过各有序型值点,
///		 并且在各型值点处的一阶和二阶导数连续,也即该曲线具有连续的、曲率变化均匀的特点。
///	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
*/
///<summary>Curve</summary>
THREE.Curve = function () {

};

/****************************************
****下面是Curve对象提供的功能函数.
****************************************/

/*
///getPoint方法返回在curve对象上t点(取值范围0.0-1.0之间)的矢量.
*/
///<summary>getPoint</summary>
///<param name ="t" type="float">t的取值范围是0.0 - 1.0,将曲线作为一个整体,一个点在这个整体的位置.</param>
///<returns type="null">返回t点的具体坐标.</returns>

// Virtual base class method to overwrite and implement in subclasses
// 虚基类方法,需要在子类中重写具体实现.
//	- t [0 .. 1]
// t的取值范围是0.0 - 1.0,将曲线作为一个整体,一个点在这个整体的位置.
THREE.Curve.prototype.getPoint = function ( t ) {

	console.log( "Warning, getPoint() not implemented!" );
	return null;

};

/*
///getPointAt方法获得一个点u在曲线上的相对位置,用弧长表示.
///定距等分曲线
*/
///<summary>getPointAt</summary>
///<param name ="u" type="float">u表示距离,通过调用getUtoTmapping方法,换算成t.</param>
///<returns type="float">返回点u在曲线上的相对位置,用弧长表示.</returns>

// Get point at relative position in curve according to arc length
//获得一个点u在曲线上的相对位置,用弧长表示.
// - u [0 .. 1]
// u的取值范围是0.0 - 1.0,将曲线作为一个整体,一个点在这个整体的位置.
THREE.Curve.prototype.getPointAt = function ( u ) {

	var t = this.getUtoTmapping( u );	//调用getUtoTmapping,将当前样条曲线作为一个整体,返回点u在曲线上的相对位置或者对应distance对应的位置(0.0-1.0).
	return this.getPoint( t );	//返回点u在曲线上的相对位置,用弧长表示.

};

/*
///getPoints方法根据divisions将曲线等分,获得在曲线对象上等分点的点序列.如果没有设置参数divisions,默认初始化为5等分.返回对应等分线段顶点的坐标数组.
///定量等分曲线
*/
///<summary>getPoints</summary>
///<param name ="divisions" type="int">根据divisions将曲线等分,获得在曲线对象上等分点的点序列.如果没有设置参数divisions,默认初始化为5等分.</param>
///<returns type="Vector3Array">返回对应等分线段顶点的坐标数组.</returns>

// Get sequence of points using getPoint( t )
// 根据divisions将曲线等分,获得在曲线对象上等分点的点序列.如果没有设置参数divisions,默认初始化为5等分.
THREE.Curve.prototype.getPoints = function ( divisions ) {

	if ( ! divisions ) divisions = 5;

	var d, pts = [];

	for ( d = 0; d <= divisions; d ++ ) {	//遍历等分数量

		pts.push( this.getPoint( d / divisions ) );	//调用getPoint方法,返回对应等分线段端点的坐标.

	}

	return pts;		//返回对应等分线段顶点的坐标数组.

};

/*
///getSpacedPoints方法根据divisions将曲线等分,获得在曲线对象上等分点的点序列.如果没有设置参数divisions,默认初始化为5等分.返回对应等分线段端点在曲线上的相对位置数组,用弧长表示.
*/
///<summary>getSpacedPoints</summary>
///<param name ="divisions" type="int">根据divisions将曲线等分,获得在曲线对象上等分点的点序列.如果没有设置参数divisions,默认初始化为5等分.</param>
///<returns type="Vector3Array">返回对应等分线段端点在曲线上的相对位置数组,用弧长表示.</returns>
// Get sequence of points using getPointAt( u )
// 获得一系列顶点的相对位置的数组.调用getPointAt方法.
THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {

	if ( ! divisions ) divisions = 5;

	var d, pts = [];

	for ( d = 0; d <= divisions; d ++ ) {		//遍历等分数量

		pts.push( this.getPointAt( d / divisions ) );	//调用getPointAt方法,返回对应等分线段端点在曲线上的相对位置数组,用弧长表示.

	}

	return pts;		//返回对应等分线段端点在曲线上的相对位置数组,用弧长表示.

};

/*
///getLength将子曲线的长度的和放入缓存数组.返回曲线路经总长度
*/
///<summary>getLength</summary>
///<returns type="float">返回曲线路经总长度.</returns>

// Get total curve arc length
//获得曲线总的弧长

THREE.Curve.prototype.getLength = function () {

	var lengths = this.getLengths();
	return lengths[ lengths.length - 1 ];

};

/*
///getLengths将子曲线的长度的和放入缓存数组.返回长度数组
*/
///<summary>getLengths</summary>
///<returns type="floatArray">返回长度数组.</returns>

// Get list of cumulative segment lengths
// 获得个线段的长度的列表
THREE.Curve.prototype.getLengths = function ( divisions ) {

	if ( ! divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions): 200;

	if ( this.cacheArcLengths
		&& ( this.cacheArcLengths.length == divisions + 1 )
		&& ! this.needsUpdate) {

		//console.log( "cached", this.cacheArcLengths );
		return this.cacheArcLengths;

	}

	this.needsUpdate = false;

	var cache = [];
	var current, last = this.getPoint( 0 );
	var p, sum = 0;

	cache.push( 0 );

	for ( p = 1; p <= divisions; p ++ ) {

		current = this.getPoint ( p / divisions );
		sum += current.distanceTo( last );
		cache.push( sum );
		last = current;

	}

	this.cacheArcLengths = cache;

	return cache; // { sums: cache, sum:sum }; Sum is in the last element.

};

/*
///updateArcLengths调用getLengths方法,更新长度数组.
*/
///<summary>updateArcLengths</summary>
///<returns type="floatArray">返回长度数组.</returns>

THREE.Curve.prototype.updateArcLengths = function() {
	this.needsUpdate = true;
	this.getLengths();
};

/*
///getUtoTmapping方法将当前样条曲线作为一个整体,返回点u在曲线上的相对位置或者对应distance对应的位置(0.0-1.0).
*/
///<summary>getUtoTmapping</summary>
///<param name ="u" type="float">u的取值范围是0.0 - 1.0,将曲线作为一个整体,一个点在这个整体的位置.</param>
///<param name ="distance" type="float">如果设置长度值,则返回对应长度在整条线段的位置</param>
///<returns type="float">点u在曲线上的相对位置或者对应distance对应的位置(0.0-1.0)</returns>

// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance
// 获得在curve对象上u点(取值范围0.0-1.0之间)距离等于distance的点t.
THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {

	var arcLengths = this.getLengths();	//获得这个线段的长度列表

	var i = 0, il = arcLengths.length;

	var targetArcLength; // The targeted u distance value to get 获得目标点u的长度值

	if ( distance ) {	//如果设置了长度

		targetArcLength = distance;		

	} else {

		targetArcLength = u * arcLengths[ il - 1 ];	//获得u点在整条线段(是由多个曲线对象组成的线段)中的位置.

	}

	//var time = Date.now();

	// binary search for the index with largest value smaller than target u distance
	// 遍历线段的索引,u值在曲线线段上的第几段,就是u值所在位置的线段在arcLengths的索引.

	var low = 0, high = il - 1, comparison;

	while ( low <= high ) {

		i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
													// 很少有可能溢出,为了保险,将浮点数转成整数

		comparison = arcLengths[ i ] - targetArcLength;

		if ( comparison < 0 ) {

			low = i + 1;
			continue;

		} else if ( comparison > 0 ) {

			high = i - 1;
			continue;

		} else {

			high = i;
			break;

			// DONE

		}

	}

	i = high;

	//console.log('b' , i, low, high, Date.now()- time);

	if ( arcLengths[ i ] == targetArcLength ) {

		var t = i / ( il - 1 );
		return t;	//返回位置

	}

	// we could get finer grain at lengths, or use simple interpolatation between two points
	// 获得更精确的长度,在两个索引值之间的位置.

	var lengthBefore = arcLengths[ i ];
    var lengthAfter = arcLengths[ i + 1 ];

    var segmentLength = lengthAfter - lengthBefore;

    // determine where we are between the 'before' and 'after' points
    // 确定点在“before”和“after"的确切位置.

    var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;

    // add that fractional amount to t
    // 获得t在整个线段中的位置

    var t = ( i + segmentFraction ) / ( il -1 );

	return t;	//返回位置.

};

/*
///getTangent方法将返回一个点t在曲线上位置向量的法线向量.
*/
///<summary>getTangent</summary>
///<param name ="t" type="float">t的取值范围是0.0 - 1.0,将曲线作为一个整体,一个点在这个整体的位置.</param>
///<returns type="Vector3">返回一个点t在曲线上位置向量的单位向量</returns>

// Returns a unit vector tangent at t
// 返回一个点t在曲线上位置向量的单位向量
// In case any sub curve does not implement its tangent derivation,
// 2 points a small delta apart will be used to find its gradient
// which seems to give a reasonable approximation
THREE.Curve.prototype.getTangent = function( t ) {
	//这里为了给向量设定一个方向.
	var delta = 0.0001;	//设置一个delta值
	var t1 = t - delta;	//t点减delta值,
	var t2 = t + delta;	//t点加delta值.

	// Capping in case of danger

	if ( t1 < 0 ) t1 = 0;
	if ( t2 > 1 ) t2 = 1;

	var pt1 = this.getPoint( t1 );
	var pt2 = this.getPoint( t2 );

	var vec = pt2.clone().sub(pt1);
	return vec.normalize();	//返回一个点t在曲线上位置向量的法线向量.

};

/*
///getTangent方法将返回一个点t在曲线上位置向量的法线向量.
*/
///<summary>getTangentAt</summary>
///<param name ="u" type="float">t的取值范围是0.0 - 1.0,将曲线作为一个整体,一个点在这个整体的位置.</param>
///<returns type="Vector3">返回一个点t在曲线上位置向量的单位向量</returns>
THREE.Curve.prototype.getTangentAt = function ( u ) {

	var t = this.getUtoTmapping( u );	//getUtoTmapping方法将当前样条曲线作为一个整体,返回点u在曲线上的相对位置或者对应distance对应的位置(0.0-1.0).
	return this.getTangent( t );	//getTangent方法将返回一个点t在曲线上位置向量的法线向量

};

/**************************************************************
 *	Utils
 **************************************************************/
// 关于bezier曲线,b样条,nurbs曲线的一些差别.
//§  Bezier曲线中的每个控制点都会影响整个曲线的形状,而B样条中的控制点只会影响整个曲线的一部分,显然B样条提供了更多的灵活性;
//§  Bezier和B样条都是多项式参数曲线,不能表示一些基本的曲线,比如圆,所以引入了NURBS,即非均匀有理B样条来解决这个问题;
// 关于二次样条,3次样条曲线的一些简单的差别,二次样条有3个控制点控制一段曲线,三次样条曲线由4个控制点控制一段曲线.更细分的区别百度吧.
THREE.Curve.Utils = {
	/*
	///tangentQuadraticBezier方法将返回二次Bezier曲线上点t的切线
	*/
	///<summary>tangentQuadraticBezier</summary>
	///<param name ="t" type="Vector3">三维向量</param>
	///<param name ="p0" type="Vector3">三维向量</param>
	///<param name ="p1" type="Vector3">三维向量</param>
	///<param name ="p2" type="Vector3">三维向量</param>
	///<returns type="number">二次Bezier曲线上点t的切线</returns>
	tangentQuadraticBezier: function ( t, p0, p1, p2 ) {

		return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );		//二次Bezier曲线上点t的切线

	},

	// Puay Bing, thanks for helping with this derivative!
	/*
	///tangentCubicBezier方法将返回三次Bezier曲线上点t的切线
	*/
	///<summary>tangentQuadraticBezier</summary>
	///<param name ="t" type="Vector3">三维向量</param>
	///<param name ="p0" type="Vector3">三维向量</param>
	///<param name ="p1" type="Vector3">三维向量</param>
	///<param name ="p2" type="Vector3">三维向量</param>
	///<param name ="p3" type="Vector3">三维向量</param>
	///<returns type="number">三次Bezier曲线上点t的切线</returns>
	tangentCubicBezier: function (t, p0, p1, p2, p3 ) {

		return - 3 * p0 * (1 - t) * (1 - t)  +
			3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
			6 * t *  p2 * (1-t) - 3 * t * t * p2 +
			3 * t * t * p3;		//三次Bezier曲线上点t的切线
	},

	/*
	///tangentSpline方法将返回Spline曲线上点t的切线
	*/
	///<summary>tangentSpline</summary>
	///<param name ="t" type="Vector3">三维向量</param>
	///<param name ="p0" type="Vector3">三维向量</param>
	///<param name ="p1" type="Vector3">三维向量</param>
	///<param name ="p2" type="Vector3">三维向量</param>
	///<param name ="p3" type="Vector3">三维向量</param>
	///<returns type="number">返回Spline曲线上点t的切线</returns>
	tangentSpline: function ( t, p0, p1, p2, p3 ) {

		// To check if my formulas are correct

		var h00 = 6 * t * t - 6 * t; 	// derived from 2t^3 − 3t^2 + 1
		var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
		var h01 = - 6 * t * t + 6 * t; 	// − 2t3 + 3t2
		var h11 = 3 * t * t - 2 * t;	// t3 − t2

		return h00 + h10 + h01 + h11;	//三次Bezier曲线上点t的切线

	},

	// Catmull-Rom

	/*
	///tangentSpline方法将点t在三次Bezier曲线上插值.
	*/
	///<summary>tangentSpline</summary>
	///<param name ="t" type="Vector3">三维向量</param>
	///<param name ="p0" type="Vector3">三维向量</param>
	///<param name ="p1" type="Vector3">三维向量</param>
	///<param name ="p2" type="Vector3">三维向量</param>
	///<param name ="p3" type="Vector3">三维向量</param>
	///<returns type="number">返回点t插值后的三次Bezier曲线</returns>
	interpolate: function( p0, p1, p2, p3, t ) {

		var v0 = ( p2 - p0 ) * 0.5;
		var v1 = ( p3 - p1 ) * 0.5;
		var t2 = t * t;
		var t3 = t * t2;
		return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;	//返回点t插值后的三次Bezier曲线

	}

};

// TODO: Transformation for Curves?
// TODO: 曲线这个东西,我还是接触的非常少的,不过理解的应该差不多.我自己能说服自己.以后希望更多有才的人来补充.

/**************************************************************
 *	3D Curves
 **************************************************************/

// A Factory method for creating new curve subclasses
// 一个构造方法用来创建新曲线子类.

/*
///create方法一个构造方法用来创建新曲线子类
*/
///<summary>create</summary>
///<param name ="constructor" type="Object.prototype">.</param>
///<returns type="Vector3">返回一个点t在曲线上位置向量的单位向量</returns>
THREE.Curve.create = function ( constructor, getPointFunc ) {

	constructor.prototype = Object.create( THREE.Curve.prototype );	//构造新区线类.
	constructor.prototype.getPoint = getPointFunc;	//getPoint方法的具体实现

	return constructor;		//返回构造对象.

};


商域无疆 (http://blog.csdn.net/omni360/)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:商域无疆 - 本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。

以下代码是THREE.JS 源码文件中extras/core/Curve.js文件的注释.

更多更新在 : https://github.com/omni360/three.js.sourcecode
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: