⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bezcam.h

📁 Ion Team Lord Of The Rings Demo 模拟指环王的3D游戏 VS.NET编译 里面提供高级渲染算法
💻 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 + -