📄 bezcam.h
字号:
// Curve equations
#define B1(t) t * t * t
#define B2(t) 3 * t * t * (1 - t)
#define B3(t) 3 * t * (1 - t) * (1 - t)
#define B4(t) (1 - t) * (1 - t) * (1 - t)
//how to draw the thing
#define CURVE_MODE GL_LINE_STRIP
#pragma warning(disable:4244)
// A Camera class that follows origin and object points in a smoothed way, using Bezier curves.
class BezCam
{
public:
double dCounter; //used as our counter
double dDetailBias; //how many points should we put on our curve.
float fSmoothFactor; // bigger it is, the smoother the curves get (0.0f - 1.0f, preferably)
Uint16 CurrentOriginPoint, CurrentObjectPoint; // the current points in the vector<>s
float CurrentOriginPointCounter, CurrentObjectPointCounter;//how far are we in between points
Vector3d OriginPoint, ObjectPoint; // the calculated current points
vector<Vector3d> OriginPointList, OriginPointCPs, ObjectPointList, ObjectPointCPs; /* Camera Path is composed of 2
curves: The origin curve, and
the object curve, being the 1st
the group of points where the
origin of the camera passes and
the second group of points where
the camera looks at*/
BezCam (double DetailBias, float SmoothFactor) // constructor ;)
{
dDetailBias=DetailBias;
fSmoothFactor=SmoothFactor;
CurrentObjectPoint = CurrentOriginPoint = 0;
CurrentObjectPointCounter = CurrentOriginPointCounter = 0.0f;
}
// adds a point to the origin path
void AddOriginPoint(Vector3d Point);
// adds a point to the object path
void AddObjectPoint(Vector3d Point);
// Loads paths from a file
void LoadFromFile (string Filename);
//smoothes both paths
void SmoothCurves();
//draws the bezier curves that make up the cammera path
inline void DrawCurves();
//draws both the points in the path, as well as the calculated control points of the curve
inline void DrawPoints();
// restarts animation.
inline void Restart();
// recalculates the current points
inline void LookAtNextPoint(float Milliseconds);
//positions the cammera acoording to the current points
inline void Position();
//positions the cammera acoording to the current points, but so that it's possible to draw a skybox
inline void PositionSkybox();
void ClearCurves();
};
void BezCam::AddOriginPoint(Vector3d Point)
{
OriginPointList.push_back(Point);
}
void BezCam::AddObjectPoint(Vector3d Point)
{
ObjectPointList.push_back(Point);
}
void BezCam::SmoothCurves() // Used the great algorithm @ http://homepages.borland.com/efg2lab/Graphics/Jean-YvesQueinecBezierCurves.htm
{
Vector3d MidlePoint,S1,S2;
Uint16 Size=OriginPointList.size();
if (Size==0)
return;
Size--;
OriginPointCPs.clear();
for (Uint16 i=0;i<Size;i++)
{
MidlePoint=(OriginPointList[i]+OriginPointList[i+1])*0.5; // find the middlepoint between the two
if (i!=0) //if this isn't the first point.
S1 = OriginPointList[i] + ((OriginPointList[i] - OriginPointList[i-1])*fSmoothFactor*0.5f); // dont try to understand it without the drawing :)
else
S1=OriginPointList[i];//if it is, then make a null control point (doesn't affect the curve)
if (i!=Size-1) // if this ain't the point before the last.
S2 = OriginPointList[i+1] + ((OriginPointList[i+1]-OriginPointList[i+2])*fSmoothFactor*0.5f);
else
S2 = OriginPointList[i+1];
S1 = (S1+MidlePoint)*0.5;
S2 = (S2+MidlePoint)*0.5;
OriginPointCPs.push_back(S1);
OriginPointCPs.push_back(S2);
}
Size=ObjectPointList.size();
if (Size==0)
return;
Size--;
ObjectPointCPs.clear();
for (Uint16 i=0;i<Size;i++)
{
MidlePoint=(ObjectPointList[i]+ObjectPointList[i+1])*0.5; // find the middlepoint between the two
if (i!=0) //if this isn't the first point.
S1 = ObjectPointList[i] + ((ObjectPointList[i] - ObjectPointList[i-1])*fSmoothFactor*0.5f); // dont try to understand it without the drawing :)
else
S1=ObjectPointList[i];//if it is, then make a null control point (doesn't affect the curve)
if (i!=Size-1) // if this ain't the point before the last.
S2 = ObjectPointList[i+1] + ((ObjectPointList[i+1]-ObjectPointList[i+2])*fSmoothFactor*0.5f);
else
S2 = ObjectPointList[i+1];
S1 = (S1+MidlePoint)*0.5;
S2 = (S2+MidlePoint)*0.5;
ObjectPointCPs.push_back(S1);
ObjectPointCPs.push_back(S2);
}
}
inline void BezCam::DrawCurves()
{
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
dCounter=0.0;
Vector3d Point;
Uint16 Size=OriginPointList.size();
glColor3f(1.0f,1.0f,1.0f);
for (Uint16 i=0;i<Size;i++)
{
glBegin(CURVE_MODE);
do
{
Point = OriginPointList[i]*B4(dCounter) + OriginPointCPs[(i*2)]*B3(dCounter) \
+ OriginPointCPs[(i*2)+1]*B2(dCounter) + OriginPointList[i+1]*B1(dCounter);
glVertex3fv(Point.Coords);
dCounter += dDetailBias;
}
while( dCounter <= 1);
dCounter=0.0;
glEnd();
}
Size=ObjectPointList.size();
glBegin(CURVE_MODE);
glColor3f(0.7f,0.7f,0.7f);
for (Uint16 i=0;i<Size;i++)
{
do
{
Point = ObjectPointList[i]*B4(dCounter) + ObjectPointCPs[(i*2)]*B3(dCounter) \
+ ObjectPointCPs[(i*2)+1]*B2(dCounter) + ObjectPointList[i+1]*B1(dCounter);
glVertex3fv(Point.Coords);
dCounter += dDetailBias;
}
while( dCounter <= 1);
dCounter=0.0;
}
glEnd();
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
}
inline void BezCam::DrawPoints()
{
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glPointSize(3.0f);
glBegin(GL_POINTS);
for (Uint16 i=0;i<OriginPointList.size();i++)
{
glColor3f(0,0,1.0f);
glVertex3fv(OriginPointList[i].Coords);
glColor3f(1.0f,0,0);
glVertex3fv(OriginPointCPs[(i*2)].Coords);
glVertex3fv(OriginPointCPs[(i*2)+1].Coords);
}
for (Uint16 i=0;i<ObjectPointList.size();i++)
{
glColor3f(0,0,0.5f);
glVertex3fv(ObjectPointList[i].Coords);
glColor3f(0.5f,0,0);
glVertex3fv(ObjectPointCPs[(i*2)].Coords);
glVertex3fv(ObjectPointCPs[(i*2)+1].Coords);
}
glEnd();
glPointSize(1.0f);
glColor3f(1.0f,1.0f,1.0f);
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
}
inline void BezCam::LookAtNextPoint(float Milliseconds)
{
if (CurrentOriginPoint<OriginPointList.size())
{
if (CurrentOriginPointCounter>=1.0f)
{
CurrentOriginPoint+=(int)CurrentOriginPointCounter;;
CurrentOriginPointCounter=dDetailBias*Milliseconds;
while (CurrentOriginPointCounter>1.0f)
CurrentOriginPointCounter-=1.0f;
}
else
{
if (!(CurrentOriginPoint==OriginPointList.size()-1))
CurrentOriginPointCounter+=dDetailBias*Milliseconds;
}
if (CurrentOriginPoint==OriginPointList.size()-1)
OriginPoint = OriginPointList[CurrentOriginPoint];
else
OriginPoint = OriginPointList[CurrentOriginPoint]*B4(CurrentOriginPointCounter) \
+ OriginPointCPs[(CurrentOriginPoint*2)]*B3(CurrentOriginPointCounter) \
+ OriginPointCPs[(CurrentOriginPoint*2)+1]*B2(CurrentOriginPointCounter)
+ OriginPointList[CurrentOriginPoint+1]*B1(CurrentOriginPointCounter);
}
if (CurrentObjectPoint<ObjectPointList.size())
{
if (CurrentObjectPointCounter>=1.0f)
{
CurrentObjectPoint+=(int)CurrentObjectPointCounter;;
CurrentObjectPointCounter=dDetailBias*Milliseconds;
while (CurrentObjectPointCounter>1.0f)
CurrentObjectPointCounter-=1.0f;
}
else
{
if (!(CurrentObjectPoint==ObjectPointList.size()-1))
CurrentObjectPointCounter+=dDetailBias*Milliseconds;
}
if (CurrentObjectPoint==ObjectPointList.size()-1)
ObjectPoint = ObjectPointList[CurrentObjectPoint];
else
ObjectPoint = ObjectPointList[CurrentObjectPoint]*B4(CurrentObjectPointCounter) \
+ ObjectPointCPs[(CurrentObjectPoint*2)]*B3(CurrentObjectPointCounter) \
+ ObjectPointCPs[(CurrentObjectPoint*2)+1]*B2(CurrentObjectPointCounter)
+ ObjectPointList[CurrentObjectPoint+1]*B1(CurrentObjectPointCounter);
}
/*glDisable(GL_TEXTURE_2D);
glBegin(GL_LINES);
glVertex3fv(OriginPoint.Coords);
glVertex3fv(ObjectPoint.Coords);
glEnd();
glEnable(GL_TEXTURE_2D);*/
}
inline void BezCam::Position()
{
gluLookAt(OriginPoint.Coords[0],OriginPoint.Coords[1],OriginPoint.Coords[2],
ObjectPoint.Coords[0],ObjectPoint.Coords[1],ObjectPoint.Coords[2],
0.0f,1.0f,0.0f);
}
inline void BezCam::PositionSkybox()
{
gluLookAt(0,0,0,
ObjectPoint.Coords[0]-OriginPoint.Coords[0],
ObjectPoint.Coords[1]-OriginPoint.Coords[1],
ObjectPoint.Coords[2]-OriginPoint.Coords[2],
0.0f,1.0f,0.0f);
}
void BezCam::Restart()
{
CurrentObjectPoint = CurrentOriginPoint = 0;
CurrentObjectPointCounter = CurrentOriginPointCounter = 0;
}
void BezCam::ClearCurves()
{
OriginPointCPs.clear();
OriginPointList.clear();
ObjectPointCPs.clear();
ObjectPointList.clear();
}
void BezCam::LoadFromFile (string Filename)
{
unsigned int NumberOfFrames;
string File,Number;
int Offset[2]={0,0};
Vector3d t;
FILE *f=fopen(Filename.c_str(),"r");
if (!f)
return;
//fseek(f,0,SEEK_SET);
while (!feof(f))
File+=fgetc(f);
Offset[1]=File.find("\n",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
Offset[0]=Offset[1];
NumberOfFrames=atoi(Number.c_str());
for (unsigned int i=0;i<NumberOfFrames;i++)
{
Offset[0]=File.find("(",Offset[0])+1;
Offset[1]=File.find(",",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
t.Coords[0]=atof(Number.c_str());
Offset[0]=Offset[1]+1;
Offset[1]=File.find(",",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
t.Coords[1]=atof(Number.c_str());
Offset[0]=Offset[1]+1;
Offset[1]=File.find(")",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
t.Coords[2]=atof(Number.c_str());
Offset[0]=Offset[1]+1;
AddOriginPoint(t);
Offset[0]=File.find("(",Offset[0])+1;
Offset[1]=File.find(",",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
t.Coords[0]=atof(Number.c_str());
Offset[0]=Offset[1]+1;
Offset[1]=File.find(",",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
t.Coords[1]=atof(Number.c_str());
Offset[0]=Offset[1]+1;
Offset[1]=File.find(")",Offset[0]);
Number=File.substr(Offset[0],Offset[1]-Offset[0]);
t.Coords[2]=atof(Number.c_str());
Offset[0]=Offset[1]+1;
AddObjectPoint(t);
}
fclose(f);
SmoothCurves();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -