• 插值技术之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)为此时曲线的状态。由于是直线,所以这个非常easy理解。



    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>



  • 相关阅读:
    题目分享M
    题目分享L
    题目分享J
    题目分享I
    FarmCraft
    C++语言中一些可能会用到的函数及头文件
    最小生成树(Kruskal & Prim & Boruvka)
    线段树板子(懒惰标记)
    FarmCraft——树形DP+贪心
    tarjan算法板子
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5377362.html
Copyright © 2020-2023  润新知