如果我有一个简单的二维矩阵,其x轴上的标准化值在0到1之间,y轴上的标准化值也在0到1之间,并且在该矩阵中有3个点,例如P1(x=0.2,y=0.9),P2(x=0.5,y=0.1)和P3(x=0.9,y=0.4)。
那么如何简单地通过这些点计算曲线,即得到一个函数,可以为任何x给出y值呢?
我知道可能会有无数种曲线通过这3个点。但是,你知道我的意思:我希望得到一条平滑的曲线,适用于音频样本插值,适用于计算音量渐变曲线,适用于计算游戏中怪物行走路径。
现在我已经在网上寻找了3天,我不敢相信没有可用的解决方案来完成这个任务。所有涉及Catmull-rom样条、贝塞尔曲线和所有理论性内容的文本都至少有一个点使得对我来说不适用。例如,Catmull-Rom样条需要控制点之间具有固定的距离(我将使用此代码并将第4个点-y设置为第3个点y):
但我没有看到x1到x4对y的计算有任何影响,所以我认为x1到x4必须具有相同的距离?
...
或者贝塞尔代码不会通过这些点计算曲线。这些点(至少第二个点)似乎只对直线产生了影响。
那么如何简单地通过这些点计算曲线,即得到一个函数,可以为任何x给出y值呢?
我知道可能会有无数种曲线通过这3个点。但是,你知道我的意思:我希望得到一条平滑的曲线,适用于音频样本插值,适用于计算音量渐变曲线,适用于计算游戏中怪物行走路径。
现在我已经在网上寻找了3天,我不敢相信没有可用的解决方案来完成这个任务。所有涉及Catmull-rom样条、贝塞尔曲线和所有理论性内容的文本都至少有一个点使得对我来说不适用。例如,Catmull-Rom样条需要控制点之间具有固定的距离(我将使用此代码并将第4个点-y设置为第3个点y):
void CatmullRomSpline(float *x,float *y,float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,float u)
{
//x,y are calculated for x1,y1,x2,y2,x3,y3 and x4,y4 if u is the normalized distance (0-1) in relation to the distance between x2 and x3 for my whiched point
float u3,u2,f1,f2,f3,f4;
u3=u*u*u;
u2=u*u;
f1=-0.5f * u3 + u2 -0.5f *u;
f2= 1.5f * u3 -2.5f * u2+1.0f;
f3=-1.5f * u3 +2.0f * u2+0.5f*u;
f4=0.5f*u3-0.5f*u2;
*x=x1*f1+x2*f2+x3*f3+x4*f4;
*y=y1*f1+y2*f2+y3*f3+y4*f4;
}
但我没有看到x1到x4对y的计算有任何影响,所以我认为x1到x4必须具有相同的距离?
...
或者贝塞尔代码不会通过这些点计算曲线。这些点(至少第二个点)似乎只对直线产生了影响。
typedef struct Point2D
{
double x;
double y;
} Point2D;
class bezier
{
std::vector<Point2D> points;
bezier();
void PushPoint2D( Point2D point );
Point2D GetPoint( double time );
~bezier();
};
void bezier::PushPoint2D(Point2D point)
{
points.push_back(point);
}
Point2D bezier::GetPoint( double x )
{
int i;
Point2D p;
p.x=0;
p.y=0;
if( points.size() == 1 ) return points[0];
if( points.size() == 0 ) return p;
bezier b;
for (i=0;i<(int)points.size()-1;i++)
{
p.x = ( points[i+1].x - points[i].x ) * x + points[i].x;
p.y = ( points[i+1].y - points[i].y ) * x + points[i].y;
if (points.size()<=2) return p;
b.PushPoint2D(p);
}
return b.GetPoint(x);
}
double GetLogicalYAtX(double x)
{
bezier bz;
Point2D p;
p.x=0.2;
p.y=0.9;
bz.PushPoint2D(p);
p.x=0.5;
p.y=0.1;
bz.PushPoint2D(p);
p.x=0.9;
p.y=0.4;
bz.PushPoint2D(p);
p=bz.GetPoint(x);
return p.y;
}
虽然这比什么都没有要好,但是它有两个缺点:1.非常慢(递归);2.正如我所说的那样,它并不能真正计算出通过第二个点的直线。
是否有数学方面的人能够帮助我呢?