插值技术之Bezier插值(1) -- Bezier Curve

作者:i_dovelemon

来源:CSDN

日期:2015 / 7 / 11

主题:Interpolate,Bezier Curve

引言

在游戏开发中,诸如动画系统,路径计算等等操作,都会遇到对数值进行插值的问题。从今天开始,将会陆陆续续的向大家介绍什么是插值技术?以及在计算机视频游戏开发中经常使用的插值技术有哪些。

插值技术(Interpolate Technology),是通过数学计算的方式,将两个值之间的部分进行平滑过渡的一种技术方案。这样的技术可以在诸如动画系统等游戏内容中得到使用。就拿动画系统举例,现在的动画系统大都流行一种基于关键帧的动画。美术人员在一些动画制作软件中,如flash,制作好动画的关键帧,然后就将该动画导出成一个文件。这个文件中只保存了每一个动画的关键运动部分。那么,当我们在游戏中使用的时候,就需要通过程序来补充每两个关键帧之间的帧状态数据。这种通过两个首尾值来构建中间部分值的技术就称之为插值技术。本文就会向大家展示其中一种经常使用的插值技术的数学技术。它的实际应用将在后续章节向大家展示。

Bezier Curve

Bezier Curve,即为贝塞尔曲线。它是一些曲线几何的总称。在本文中,将会向大家展示三种Bezier Curve,分别是Linear Bezier Curve, Quadratic Bezier Curve, Cubic Bezier Curv。这三种Bezier Curve都是经常用到的曲线,并且分别是一次曲线,二次曲线和三次曲线。其他更高维度的曲线将不再讲述。关于Bezier Curve的详细讲解,大家可以看下这篇Wiki:Bezier
Curve
.

Linear Bezier Curve

一次Bezier Curve,被称为Linear Bezier Curve,它实际上指的就是一条直线,并没有任何的弯曲度。所以,使用一次Bezier Curve进行插值的技术,又被称为值Linear Interpolating(线性插值)。线性插值技术的应用十分广泛,除了在动画系统中使用到之外,在3D图形的光栅化阶段也用来对顶点数据和纹理数据进行插值计算。下面给出线性插值的公式:

B(t) = p0 + (p1 - p0) * t [0<=t <= 1]            (1)

上面公式中的t,表示了p0和p1之间某个时刻,而B(t)为此时曲线的状态。因为是直线,所以这个很容易理解。

Quadratic Bezier Curve

二次曲线的公式是在一次曲线的基础上推导来的,数学推导部分同样可以到上面的wiki中找到,这里将直接给出公式:

B(t) = (1 - t) ^2 * p0 + 2 * (1 - t) * t * p1 + t^2 * p2      (2)

Cubic Bezier Curve

三次曲线的公式如下所示:

B(t) = (1 - t)^3 * p0 + 3 * (1 - t) ^2 * t * p1 + 3 * (1 - t ) * t^2 * p2 + t^3 * p3      (3)

绘制Bezier Curve

下面的代码演示了如何绘制Linear Bezier,Quadratic Bezier以及Cubic Bezier。代码使用的是javascript来编写:

<span style="font-family:Microsoft YaHei;"><html>
	<script>
		var _2dContext = 0;

		/*Begin Solve Bezier Curve method*/
		function LinearBezierCurve(p0,p1,t)
		{
			return p0 + (p1 - p0) * t;
		}

		function QuadBezierCurve(p0,p1,p2,t)
		{
			var current = 0;
			var InvT = 1 - t;
			var InvT_2 = InvT * InvT;
			var T2 = t * t;
			current = InvT_2 * p0;
			current += 2 * InvT * t * p1;
			current += T2* p2;
			return current;
		}

		function CubicBezierCurve(p0,p1,p2,p3,t)
		{
			var current = 0;
			var InvT = 1 - t;
			var InvT_2 = InvT * InvT;
			var InvT_3 = InvT_2 * InvT;
			var T2 = t * t;
			var T3 = T2 * t;
			current += InvT_3 * p0;
			current += 3 * InvT_2 *t * p1;
			current += 3 * InvT * T2 * p2;
			current += T3 * p3;
			return current;
		}
		/*End Solve Bezier Curve*/

		//Draw a point in the cavans
		function DrawPoint(context,x,y,color)
		{
			context.beginPath();
			context.moveTo(x,y);
			context.lineTo(x + 1,y);
			context.closePath();
			context.strokeStyle = color;
			context.stroke();
		}

		/*Begin Draw Bezier Curve*/
		function DrawLinearBezierCurve(context,p0_x,p0_y,p1_x,p1_y,step,color)
		{
			var t = 0;
			for(;t<=1;t+=step)
			{
				//Calculate the new position
				var current_x = LinearBezierCurve(p0_x,p1_x,t);
				var current_y = LinearBezierCurve(p0_y,p1_y,t);

				//Draw the point
				DrawPoint(context,current_x,current_y,color);
			}
		}

		function DrawQuadBezierCurve(context, p0_x,p0_y,p1_x,p1_y,p2_x,p2_y,step,color)
		{
			var t = 0;
			for(;t<=1;t+=step)
			{
				//Calculate the new position
				var current_x = QuadBezierCurve(p0_x,p1_x,p2_x,t);
				var current_y = QuadBezierCurve(p0_y,p1_y,p2_y,t);

				//Draw the point
				DrawPoint(context,current_x,current_y,color);
			}
		}

		function DrawCubicBezierCurve(context,p0_x,p0_y,p1_x,p1_y,p2_x,p2_y,p3_x,p3_y,step,color)
		{
			var t = 0;
			for(;t<=1;t+=step)
			{
				//Calculate the new position
				var current_x = CubicBezierCurve(p0_x,p1_x,p2_x,p3_x,t);
				var current_y = CubicBezierCurve(p0_y,p1_y,p2_y,p3_y,t);

				//Draw the point
				DrawPoint(context,current_x,current_y,color);
			}
		}
		/*End Draw Bezier Curve*/

		function gameInit()
		{
			//Get the canvas context
			_2dContext = document.getElementById("canvas").getContext("2d");

			//enable game loop
			setInterval(gameLoop,100.0);
		}

		function gameLoop()
		{
			//Clear the canvas
			_2dContext.clearRect(0,0,1024,768);

			//Draw the linear bezier curve
			DrawLinearBezierCurve(_2dContext,100,100,1000,100,0.001,"rgb(255,0,0)");

			//Draw the Quadratic bezier curve
			var qp1_x = Math.random() * 1024;
			var qp1_y = Math.random() * 768;
			DrawQuadBezierCurve(_2dContext,100,400,qp1_x,qp1_y,1000,400,0.001,"rgb(0,255,0)");

			//Draw the Cubic bezier curve
			var cp1_x = Math.random() * 1024;
			var cp1_y = Math.random() * 768;
			var cp2_x = Math.random() * 1024;
			var cp2_y = Math.random() * 768;
			DrawCubicBezierCurve(_2dContext,100,600,cp1_x,cp1_y,cp2_x,cp2_y,1000,600,0.001,"rgb(0,0,255)");
		}
	</script>
	<body>
	<body onLoad="gameInit();">
		<canvas id="canvas" width="1024" height="768">
			您的浏览器不支持Canvas特性!!!请使用Chrome,Firefox!!
		</canvas>
	</body>
</html></span>

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-22 23:04:01

插值技术之Bezier插值(1) -- Bezier Curve的相关文章

bezier插值绕过打结问题

html5 canvas bezierCurveTo涉及4个点:o(开始点),cp1(控制点1),cp2(控制点2),p(结束点)当 o到p的走向(向量op)和cp1到cp2的走向(向量c12)相反时,就会出现打结的情况,我采取降级处理的方法,即发现会打结时,改为使用lineTo: p = parts[i][j]; var o = parts[i][j-1]; //p前面一点 var cp1 = cps[2*(j-1)]; var cp2 = cps[2*j-1]; var op = p.sub

Shading中的插值技术

提要 在Per Vertex shader中处理着色计算的情况计算出的是每个顶点上shading的结果,通常模型都是由三角面来构成,面上的颜色如何处理,就是今天要探讨的.常用的三种方法是Flat Shading, Gouraud Shading, Phong Shading,对于渲染一个小球,结果对比如下,从左到右依次是Flat Shading, Gouraud Shading, Phong Shading. Flat Shading 这个最简单,整个面片的颜色都是一致的,没有平滑,只有很硬的边

插值技术之Catmull-Rom Spline Interpolating(2)

作者:i_dovelemon 来源:CSDN,http://www.dxstudio.com/guide_content.aspx?id=70a2b2cf-193e-4019-859c-28210b1da81f 日期:2015 / 8 / 25 主题:Catmull-Rom Spline Interpolating 引言 在游戏开发中,我们经常会遇到如下的情景:我们已知了一些路径点,我们希望我们的角色能够平滑的沿着这些路径点进行移动,而不是"直直的"从一个点走到另外一个点上去.对于这样

插值技术之Catmull-Rom Spline Interpolating

作者:i_dovelemon 来源:CSDN,http://www.dxstudio.com/guide_content.aspx?id=70a2b2cf-193e-4019-859c-28210b1da81f 日期:2015 / 8 / 25 主题:Catmull-Rom Spline Interpolating 引言 在游戏开发中,我们经常会遇到如下的情景:我们已知了一些路径点,我们希望我们的角色能够平滑的沿着这些路径点进行移动,而不是“直直的”从一个点走到另外一个点上去.对于这样的问题,在

空间插值文献阅读(Geostatistical approaches for incorporating elevation into the spatial interpolation of rainfall)

空间插值技术应用必读论文---P. Goovaerts, Geostatistical approaches for incorporating elevation into the spatial interpolation of rainfall. Journal of Hydrology, 2000, 113-129. 本博文从研究意义.研究区及预处理.所使用的插值方法以及对插值方法的评价这四个角度对该文进行了详细评述,并分析了该文的一些不足. 1内容评述 该文利用三种以高程作为辅助信息的

使用贝塞尔曲线进行插值 一种非常简单的平滑多边形的方法

原文Interpolation with Bezier Curves A very simple method of smoothing polygons Initially, there was a question in comp.graphic.algorithms how to interpolate a polygon with a curve in such a way that the resulting curve would be smooth and hit all its

数据结构之--插值查找

数据结构之--插值查找 定义:插值查找就是把要查找的关键字key与查找表中最大和最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式(key-a[low])/(a[high]-a[low]) 图解: 时间复杂度:只是把折半的算法由mid=(low+high)/2变为了(mid=low+(high-low)*(key-a[low])/(a[high]-a[low])),所以时间复杂度还是为与普通折半查找一样为:O(logn). #include<stdio.h> int Binary_S

OpenGL绘制简单的参数曲线——三阶Bezier曲线(二)

今天我们来介绍三次Bezier曲线,这曲线网上资料非常多,我这里只是简单介绍下原理. 在二维空间中(三维也类似),给定n+1个点P0.P1.... .Pn.参数t的n次的Bezier曲线是: 图1 我们根据上面式子可以推出一阶.二阶.三阶贝塞尔曲线,下面是一阶贝塞尔曲线: 图2 下面是二阶贝塞尔曲线,表示的是从P0P1线段取Q0,P1P2线段取Q1,每一个Q0Q1都是曲线的切向量: 图3 下面是三阶贝塞尔曲线,表示的是从P0P1线段取Q0,P1P2线段取Q1,P2P3线段取Q2,再从Q0Q1取R

Matlab随笔之插值与拟合(上)

1.拉格朗日插值 新建如下函数: function y=lagrange(x0,y0,x) %拉格朗日插值函数 %n 个节点数据以数组 x0, y0 输入(注意 Matlat 的数组下标从1开始), %m 个插值点以数组 x 输入,输出数组 y 为 m 个插值 n=length(x0);m=length(x); for i=1:m z=x(i); s=0.0; for k=1:n p=1.0; for j=1:n if j~=k p=p*(z-x0(j))/(x0(k)-x0(j)); end