bezcam.h

来自「Ion Team Lord Of The Rings Demo 模拟指环王的3」· C头文件 代码 · 共 348 行

H
348
字号
// 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 + =
减小字号Ctrl + -
显示快捷键?