|
|
因为单位不许我用pascal写链接库,只好c++了。我的目的是不让别人乱改算法思想,而c++我毕竟谈不上精通,请大家来帮帮忙哈。
vc++中创建一个控制台应用即可编译通过,bezier curves的算法核心
#include "stdafx.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
//
using namespace std;
struct TFlyMovementVector
{
float x,y,z;
};
#define TInputVector TFlyMovementVector
#define TArrayInputVector TInputVector *
struct TArrayInputVectorData
{
TArrayInputVector Input;
int InputLen;
};
//
#define TOutputVector TFlyMovementVector
#define TArrayOutputVector TOutputVector *
struct TArrayOutputVectorData
{
TArrayOutputVector Output;
int OutputLen;
};
float Factorial(int n)
{
float r=1;
for(int i=2;i<=n;i++) r=r*i;
return r;
}
#define power powf
float BernsteinBasis(int n,int i,float t)
{
float ti,tni;
if((t==0)&&(i==0)) ti=1; else ti=power((float)t,(float)i);
if((n==i)&&(t==1)) tni=1; else tni=power((float)(1-t),(float)(n-i));
return ((Factorial(n)/(Factorial(i)*Factorial(n-i)))*ti*tni);
}
TOutputVector BezierCurvePoint(float t, TArrayInputVectorData _id)
{
TOutputVector r={0,0,0};
float b;
for(int i=0;i<=(_id.InputLen-1);i++)
{
b=BernsteinBasis(_id.InputLen-1,i,t);
r.x=r.x+(_id.Input.x*b);
r.y=r.y+(_id.Input.y*b);
r.z=r.z+(_id.Input.z*b);
}
return r;
}
TArrayOutputVectorData GenerateBezierCurve(int Steps, TArrayInputVectorData _id)
{
TArrayOutputVectorData _od={new TOutputVector[Steps],Steps};
for (int i=0;i<=Steps-1;i++) _od.Output=BezierCurvePoint(i/(float)(Steps-1), _id);
return _od;
}
float sqr(float v)
{
return power(v,2);
}
float VectorDistance(TOutputVector v1, TOutputVector v2)
{
return sqrt(sqr(v2.x-v1.x)+sqr(v2.y-v1.y)+sqr(v2.z-v1.z));
}
TOutputVector VectorLerp(TOutputVector v1, TOutputVector v2, float t)
{
TOutputVector _R={v1.x+(v2.x-v1.x)*t, _R.y=v1.y+(v2.y-v1.y)*t, _R.z=v1.x+(v2.z-v1.z)*t};
return _R;
}
TOutputVector CalcTrackFromTime(float speed, double NewTime, TArrayOutputVectorData _od)
{
TOutputVector v={0,0,0};
float NewDistance=NewTime*speed;
float CurDistance=0;
float nDistance=0;
//
if(_od.OutputLen>0)
{
v=_od.Output[0];
for(int i=1;i<=_od.OutputLen-1;i++)
{
nDistance=VectorDistance(v, _od.Output);
if (CurDistance+nDistance>=NewDistance)
return VectorLerp(v, _od.Output, (CurDistance+nDistance-NewDistance)/nDistance);
CurDistance+=nDistance;
v=_od.Output;
}
}
return v;
}
//test it.
int _tmain(int argc, _TCHAR* argv[])
{
TArrayInputVectorData _id={new TInputVector[4], 4};
_id.Input[0].x=(float)1.55;
_id.Input[0].y=(float)3.14;
_id.Input[0].z=(float)-18.01;
_id.Input[1].x=(float)10.55;
_id.Input[1].y=(float)33.1;
_id.Input[1].z=(float)8.07;
_id.Input[2].x=(float)-80.5;
_id.Input[2].y=(float)-13.1;
_id.Input[2].z=(float)1.07;
//
cout<<"bezier curves test"<<endl;
TArrayOutputVectorData _od=GenerateBezierCurve(10, _id);
TOutputVector v={0,0,0};
for (int i=0;i<=_od.OutputLen-1;i++)
{
v=_od.Output;
cout<<"X:"<<v.x<<" Y:"<<v.y<<" Z:"<<v.z<<endl;
}
//
cout<<"fly track movement test"<<endl;
v=CalcTrackFromTime(5.0, 2, _od);
cout<<"X:"<<v.x<<" Y:"<<v.y<<" Z:"<<v.z<<endl;
return 0;
}
|
|