基於bSpline插值的直紋面和旋轉曲面

此程序主要分爲兩部分,一部分是抽象旋轉曲面和直紋面的類,另一部分是視圖界面的類組織,二者通過在視圖界面定義數據成員建立聯繫。

 

第一部分:

旋轉曲面類:

 

class Revsurf:public bspline,public Mesh                         //旋轉曲面

{

public:

       Revsurf(Point3* pt1,int num,int uu,int vv,int mm);             //構造函數

       ~Revsurf();

public:

       void writeMesh(char *fname);                             //將生成的點、法線、面片寫入文件

       void makefaces();                                       //生成面片及索引

       void makenormals();                                     //生成法線及索引

       int ctlpt_num;                                          //控制點的個數

       int v;                                                  //經度方向

       int u;                                                  //緯度方向

       Point3 *ctlpt;                                           //保存控制點

       void makepoints();                                       //生成點及索引

};

 

Revsurf::Revsurf(Point3 *pt1,int num,int uu,int vv,int mm)                                          //旋轉曲面

:ctlpt(pt1),ctlpt_num(num),u(uu),v(vv),bspline(mm,num)

{

       numVerts=u*v;

       numNorms=u*v;

       numFaces=(u-1)*v;

      

    pt=new Point3[numVerts];

       norm=new Vector3[numNorms];

       face=new Face[numFaces];

}

 

Revsurf::~Revsurf()

{

}

 

/******************************旋轉曲面生成頂點*********************************/

void Revsurf::makepoints()

{

       int i=0,j=0,k=0;

       float t=0,x=0,y=0,z=0;

       Point3 *p;                                        //記錄兩條u線的點

       p=new Point3[u];

 

       //細節處理1e-5

       for(t=knot[0]+1e-5;i<u;t+=knot[ctlpt_num+m-1]/(float)(u-1)-1e-5)                           //採集兩條u線的點

       {

              p[i].set(0,0,0);

              for(k=0;k<ctlpt_num;k++)

              {

                     p[i].x+=ctlpt[k].x*getbsplineValue(k,m,t,knot);

                     p[i].y+=ctlpt[k].y*getbsplineValue(k,m,t,knot);

                     p[i].z+=ctlpt[k].z*getbsplineValue(k,m,t,knot);

              }

              i++;

       }

 

       glBegin(GL_LINE_STRIP);

       for(i=0;i<u;i++)

              glVertex3f(p[i].x,p[i].y,p[i].z);

       glEnd();

 

       for(j=0;j<v;j++)                                           //生成網格點i*v+j                                  

              for(i=0;i<u;i++)

              {

                     x=p[i].x*cos(j/(float)v*2*PI);

                     y=p[i].y;

                     z=p[i].x*sin(j/(float)v*2*PI);

                     pt[j*u+i].set(x,y,z);

                     pt[j*u+i].set(j*u+i);

              }

              delete[] p;

              p=NULL;

}

 

/******************************旋轉曲面生成法線*********************************/

void Revsurf::makenormals()

{

       Vector3 va(0,0,0),vb(0,0,0);

       int i=0,j=0;

 

       for(;j<v-1;j++)                                        

       {

              for(i=0;i<u-1;i++)

              {

                     va.set(pt[j*u+i+1].x-pt[j*u+i].x,pt[j*u+i+1].y-pt[j*u+i].y,pt[j*u+i+1].z-pt[j*u+i].z);

                     vb.set(pt[(j+1)*u+i].x-pt[j*u+i].x,pt[(j+1)*u+i].y-pt[j*u+i].y,pt[(j+1)*u+i].z-pt[j*u+i].z);

 

            va.normalize();

                     vb.normalize();

 

                     norm[j*u+i].set(va.cross(vb));

            norm[j*u+i].set(j*u+i);

              }

 

              va.set(pt[j*u+i].x-pt[j*u+i-1].x,pt[j*u+i].y-pt[j*u+i-1].y,pt[j*u+i].z-pt[j*u+i-1].z);

              vb.set(pt[(j+1)*u+i].x-pt[j*u+i].x,pt[(j+1)*u+i].y-pt[j*u+i].y,pt[(j+1)*u+i].z-pt[j*u+i].z);

 

              va.normalize();

              vb.normalize();

 

              norm[j*u+i].set(va.cross(vb));

              norm[j*u+i].set(j*u+i);

       }

 

       for(i=0;i<u-1;i++)

       {

              va.set(pt[j*u+i+1].x-pt[j*u+i].x,pt[j*u+i+1].y-pt[j*u+i].y,pt[j*u+i+1].z-pt[j*u+i].z);

              vb.set(pt[0*u+i].x-pt[j*u+i].x,pt[0*u+i].y-pt[j*u+i].y,pt[0*u+i].z-pt[j*u+i].z);

             

              va.normalize();

              vb.normalize();

             

              norm[j*u+i].set(va.cross(vb));

              norm[j*u+i].set(j*u+i);

       }

 

       va.set(pt[j*u+i].x-pt[j*u+i-1].x,pt[j*u+i].y-pt[j*u+i-1].y,pt[j*u+i].z-pt[j*u+i-1].z);

       vb.set(pt[0*u+i].x-pt[j*u+i].x,pt[0*u+i].y-pt[j*u+i].y,pt[0*u+i].z-pt[j*u+i].z);

      

       va.normalize();

       vb.normalize();

      

       norm[j*u+i].set(va.cross(vb));

       norm[j*u+i].set(j*u+i);

}

 

/******************************旋轉曲面生成面片*********************************/

void Revsurf::makefaces()

{

       int i=0,j=0;

      

       for(;j<v-1;j++)

       {

              for(i=0;i<u-1;i++)

              {

                     face[j*(u-1)+i].nVerts=4;

                     face[j*(u-1)+i].vert=new VertexID[4];

                    

                     face[j*(u-1)+i].vert[0].normIndex=j*u+i;

                     face[j*(u-1)+i].vert[1].normIndex=j*u+i+1;

            face[j*(u-1)+i].vert[2].normIndex=(j+1)*u+i+1;

                     face[j*(u-1)+i].vert[3].normIndex=(j+1)*u+i;

                    

            face[j*(u-1)+i].vert[0].vertIndex=j*u+i;

                     face[j*(u-1)+i].vert[1].vertIndex=j*u+i+1;

            face[j*(u-1)+i].vert[2].vertIndex=(j+1)*u+i+1;

                     face[j*(u-1)+i].vert[3].vertIndex=(j+1)*u+i;

              }

       }

      

       for(i=0;i<u-1;i++)

       {

              face[j*(u-1)+i].nVerts=4;

              face[j*(u-1)+i].vert=new VertexID[4];

             

              face[j*(u-1)+i].vert[0].normIndex=j*u+i;

              face[j*(u-1)+i].vert[1].normIndex=j*u+i+1;

              face[j*(u-1)+i].vert[2].normIndex=0*u+i+1;

              face[j*(u-1)+i].vert[3].normIndex=0*u+i;

             

              face[j*(u-1)+i].vert[0].vertIndex=j*u+i;

              face[j*(u-1)+i].vert[1].vertIndex=j*u+i+1;

              face[j*(u-1)+i].vert[2].vertIndex=0*u+i+1;

              face[j*(u-1)+i].vert[3].vertIndex=0*u+i;

       }

}

 

void Revsurf::writeMesh(char *fname)

{

       Mesh::writeMesh(face,norm,pt,numFaces,numNorms,numVerts,fname);

}

 

直紋面類:

 

class Rulesurf:public bspline,public Mesh                            //直紋面

{

public:

       Rulesurf(Point3* pt1,Point3* pt2,int num,int uu,int vv,int mm);       //構造函數

       ~Rulesurf();                                                //析構函數

public:

       void writeMesh(char *fname);                                  //將生成點、法線、面片 寫入文件

       void makefaces(void);                                        //生成面片及索引

       void makenormals();                                         //生成法線及索引

       int ctlpt_num;                                              //控制點的個數

    int u;                                                     //u線上的點數

       int v;                                                     //v線上的點數

       Point3 *ctlpt1;                                             //一條u線的控制點

       Point3 *ctlpt2;                                             //另一條u線的控制點

       void makepoints();                                         //生成點及索引

};

 

 

Rulesurf::Rulesurf(Point3* pt1,Point3* pt2,int num,int uu,int vv,int mm)                                          //直紋面

:ctlpt1(pt1),ctlpt2(pt2),ctlpt_num(num),u(uu),v(vv),bspline(mm,num)

{

       numVerts=u*v;

       numNorms=u*v;

       numFaces=(u-1)*(v-1);

 

    pt=new Point3[numVerts];

 

       norm=new Vector3[numNorms];

 

       face=new Face[numFaces];

}

 

Rulesurf::~Rulesurf()

{

}

 

/*************************************直紋面生成點****************************************/

void Rulesurf::makepoints()                      

{

       int i=0,j=0,k=0;

       float t=0,x=0,y=0,z=0;

       Point3 *p0,*p1;                                        //記錄兩條u線的點+knot[ctlpt_num+m-1]/(float)(u-1)

       p0=new Point3[u];

       p1=new Point3[u];

 

       //細節處理1e-5

       for(t=knot[0]+1e-5;i<u;t+=knot[ctlpt_num+m-1]/(float)(u-1)-1e-5)                           //採集兩條u線的點

       {

              p0[i].set(0,0,0);

              p1[i].set(0,0,0);

              for(k=0;k<ctlpt_num;k++)

              {

                     p0[i].x+=ctlpt1[k].x*getbsplineValue(k,m,t,knot);

                     p0[i].y+=ctlpt1[k].y*getbsplineValue(k,m,t,knot);

                     p0[i].z+=ctlpt1[k].z*getbsplineValue(k,m,t,knot);

                     p1[i].x+=ctlpt2[k].x*getbsplineValue(k,m,t,knot);

                     p1[i].y+=ctlpt2[k].y*getbsplineValue(k,m,t,knot);

                     p1[i].z+=ctlpt2[k].z*getbsplineValue(k,m,t,knot);

              }

              i++;

       }

 

       for(i=0;i<u;i++)                                           //生成網格點                                  

              for(j=0;j<v;j++)

              {

                     x=p0[i].x*(1-j/(float)(v-1))+p1[i].x*j/(float)(v-1);

                     y=p0[i].y*(1-j/(float)(v-1))+p1[i].y*j/(float)(v-1);

                     z=p0[i].z*(1-j/(float)(v-1))+p1[i].z*j/(float)(v-1);

                     pt[i*v+j].set(x,y,z);

                     pt[i*v+j].set(i*v+j);

              }

 

              delete[] p0;

              delete[] p1;

              p0=NULL;p1=NULL;

}

 

/*************************************直紋面生成法線****************************************/

void Rulesurf::makenormals()

{

       Vector3 va(0,0,0),vb(0,0,0);

       int i=0,j=0;

 

       for(;i<u-1;i++)                                         //生成法向量 

       {

              for(j=0;j<v-1;j++)

              {

                     va.set(pt[(i+1)*v+j].x-pt[i*v+j].x,pt[(i+1)*v+j].y-pt[i*v+j].y,pt[(i+1)*v+j].z-pt[i*v+j].z);

                     vb.set(pt[i*v+j+1].x-pt[i*v+j].x,pt[i*v+j+1].y-pt[i*v+j].y,pt[i*v+j+1].z-pt[i*v+j].z);

 

            va.normalize();

                     vb.normalize();

 

                     norm[i*v+j].set(va.cross(vb));

            norm[i*v+j].set(i*v+j);

              }

 

              va.set(pt[(i+1)*v+j].x-pt[i*v+j].x,pt[(i+1)*v+j].y-pt[i*v+j].y,pt[(i+1)*v+j].z-pt[i*v+j].z);

              vb.set(pt[i*v+j].x-pt[i*v+j-1].x,pt[i*v+j].y-pt[i*v+j-1].y,pt[i*v+j].z-pt[i*v+j-1].z);

 

              va.normalize();

              vb.normalize();

 

              norm[i*v+j].set(va.cross(vb));

              norm[i*v+j].set(i*v+j);

       }

 

       for(j=0;j<v-1;j++)

       {

              va.set(pt[i*v+j].x-pt[(i-1)*v+j].x,pt[i*v+j].y-pt[(i-1)*v+j].y,pt[i*v+j].z-pt[(i-1)*v+j].z);

              vb.set(pt[i*v+j+1].x-pt[i*v+j].x,pt[i*v+j+1].y-pt[i*v+j].y,pt[i*v+j+1].z-pt[i*v+j].z);

 

              va.normalize();

              vb.normalize();

 

              norm[i*v+j].set(va.cross(vb));

              norm[i*v+j].set(i*v+j);

       }

 

       va.set(pt[i*v+j].x-pt[(i-1)*v+j].x,pt[i*v+j].y-pt[(i-1)*v+j].y,pt[i*v+j].z-pt[(i-1)*v+j].z);

       vb.set(pt[i*v+j].x-pt[i*v+j-1].x,pt[i*v+j].y-pt[i*v+j-1].y,pt[i*v+j].z-pt[i*v+j-1].z);

 

       va.normalize();

       vb.normalize();

 

       norm[i*v+j].set(va.cross(vb));

       norm[i*v+j].set(i*v+j);

}

 

/*************************************直紋面生成面片****************************************/

void Rulesurf::makefaces()

{

       int i=0,j=0;

 

       for(;i<u-1;i++)

       {

              for(j=0;j<v-1;j++)

              {

                     face[i*(v-1)+j].nVerts=4;

                     face[i*(v-1)+j].vert=new VertexID[4];

                    

                     face[i*(v-1)+j].vert[0].normIndex=i*v+j;

                     face[i*(v-1)+j].vert[1].normIndex=i*v+j/*i*v+j+1*/;

            face[i*(v-1)+j].vert[2].normIndex=i*v+j/*(i+1)*v+j+1*/;

                     face[i*(v-1)+j].vert[3].normIndex=i*v+j/*(i+1)*v+j*/;

                    

            face[i*(v-1)+j].vert[0].vertIndex=i*v+j;

                     face[i*(v-1)+j].vert[1].vertIndex=i*v+j+1;

                     face[i*(v-1)+j].vert[2].vertIndex=(i+1)*v+j+1;

                     face[i*(v-1)+j].vert[3].vertIndex=(i+1)*v+j;

              }

       }

}

 

 

void Rulesurf::writeMesh(char *fname)

{

       Mesh::writeMesh(face,norm,pt,numFaces,numNorms,numVerts,fname);

}

 

補充說明:

二者都是從bspline, Mesh類派生的,其中bspline類是爲了生成數據點以b樣條的方式插值,Mesh類主要負責繪製曲面,類代碼如下:

 

bSpline

class bspline

{

public:

       bspline(int mm,int num);                                          //構造函數

       bspline();

       ~bspline();                                                     

public:

       float *knot;                                                    //保存生成節點

       float getbsplineValue(int k, int m, float t, float *knot);                  //計算樣條插值

       void buildKnots(int m, int L, float knot[]);                           //生成標準節點向量

       int m;                                                        //記錄樣條的階數                                               

};

 

bspline::bspline(int mm,int num)

{

       int L=num;

       m=mm;

       knot=new float[L+m];

       ASSERT(knot!=NULL);

 

       buildKnots(m,L,knot);

}

 

bspline::bspline()

{

}

 

bspline::~bspline()

{

       if(knot)                                            //基本數據類型刪除操作delete knotdelete []knot效果一樣

       {

              delete knot;                                   

              knot=NULL;

       }

}

 

float bspline::getbsplineValue(int k, int m, float t, float *knot)

{

       float demo1,demo2,sum=0.0;

       if(m==1)return (t>knot[k] && t<=knot[k+1]);

       demo1=knot[k+m-1]-knot[k];

       sum=(demo1!=0 ? (t-knot[k])*getbsplineValue(k,m-1,t,knot)/demo1 : 0);

       demo2=knot[k+m]-knot[k+1];

       sum+=(demo2!=0 ? (knot[k+m]-t)*getbsplineValue(k+1,m-1,t,knot)/demo2 : 0);

       return sum;

}

 

void bspline::buildKnots(int m, int L, float knot[])

{

       int i;

       if(L<(m-1))return;

       for(i=0; i<=L+m; i++)

       {

              if(i<m)knot[i]=0.0;

              else if(i<L)knot[i]=i-m+1;

              else knot[i]=L-m+1;

       }

}

 

Mesh類:

 

class Mesh

{

public:

       int numVerts, numNorms, numFaces;                          //點數、法線數、面數

       Point3 *pt;                                               // array of points                                 

       Vector3 *norm;                                           // array of normals

       Face *face;                                              // array of faces

public:

       Mesh();                                                 //構造函數

       ~Mesh();

       Mesh(char* fname);

       void virtual writeMesh(Face* face,Vector3* norm,Point3* pt,int numFaces,int numNorms,int numVerts,char* fname);                                        //寫入文件

       float GetAngle(Vector3 v1,Vector3 v2);                      //計算夾角

       void readMesh(char* fname);                              //讀文件

       void writeMesh(char* fname);                             //寫入文件

       void drawMesh();                                       //繪製曲面

       int isEmpty();                                             //判斷是否爲空

       void makeEmpty();                                     //將點數、法線數、面數置爲空

      

       Vector3 newell4(int indx[]);                               //newell4生成法線方式

       char* meshFileName;                                    //待繪製的文件名

}; // end of Mesh class

 

Mesh :: Mesh()

{

       /*

       numVerts = numFaces = numNorms = 0;

       pt = NULL; norm  =  NULL; face = NULL;*/

}

 

Mesh :: ~Mesh()

{ // free up memory used by this mesh.

      

       if(pt)

       {

              delete[] pt; // release whole vertex list

              pt=NULL;

       }

 

       if(norm)

       {

              delete[] norm;

              pt=NULL;

       }

 

       if(face)

       {

              for(int f = 0; f < numFaces; f++)

                     delete[] face[f].vert; // delete the vert[] array of this face

              face=NULL;

       }

}

 

void Mesh :: freeMesh()

{

       if(pt)

       {

              delete[] pt; // release whole vertex list

              pt=NULL;

       }

 

       if(norm)

       {

              delete[] norm;

              pt=NULL;

       }

 

       if(face)

       {

              for(int f = 0; f < numFaces; f++)

                     delete[] face[f].vert; // delete the vert[] array of this face

              face=NULL;

       }

 

}

 

//////////////Mesh////////////////////

int Mesh :: isEmpty()

{

       return (numVerts == 0) || (numFaces == 0) || (numNorms == 0);

}

 

void Mesh :: makeEmpty()

{

       numVerts = numFaces = numNorms = 0;

}

 

Mesh :: Mesh(char* fname){ // read this file to build mesh

       numVerts = numFaces = numNorms = 0;

       pt = NULL; norm  =  NULL; face = NULL;

       //                   lastVertUsed = lastNormUsed = lastFaceUsed = -1;

       readMesh(fname);

}

 

 

Vector3 Mesh :: newell4(int indx[])

{ /* return the normalized normal to face with vertices

  pt[indx[0]],...,pt[indx[3]]. i.e. indx[] contains the four indices

       into the vertex list to be used in the Newell calculation */

                     Vector3 m;

                     for(int i = 0; i < 4 ; i++)

                     {

                            int next = (i== 3) ? 0 : i + 1; // which index is next?

                            int f = indx[i], n = indx[next]; // names for the indices in the pair

                            m.x += (pt[f].y - pt[n].y) * (pt[f].z + pt[n].z);

                            m.y += (pt[f].z - pt[n].z) * (pt[f].x + pt[n].x);

                            m.z += (pt[f].x - pt[n].x) * (pt[f].y + pt[n].y);

                     }

                     m.normalize();

                     return m;

}

 

//<<<<<<<<<<<<<<<<<<<<<<<<<<<< readMesh >>>>>>>>>>>>>>>>>>>>>>>>

void Mesh:: readMesh(char* fname)

{

       fstream inStream;

//     inStream.open(fname.c_str(), ios ::in); //open needs a c-like string

       inStream.open(fname, ios ::in);

       if(inStream.fail() || inStream.eof())

       {

              cout << "can't open file or eof: " << fname << endl;

              makeEmpty();return;

       }

       inStream >> numVerts >> numNorms >> numFaces;

       // make arrays for vertices, normals, and faces

       pt = new Point3[numVerts];        assert(pt != NULL);

       norm = new Vector3[numNorms];     assert(norm != NULL);

       face = new Face[numFaces];        assert(face != NULL);

       for(int i = 0; i < numVerts; i++)    // read in the vertices

              inStream >> pt[i].x >> pt[i].y >> pt[i].z;

       for(int ii = 0; ii < numNorms; ii++)      // read in the normals

              inStream >> norm[ii].x >> norm[ii].y >> norm[ii].z;

       for(int f = 0; f < numFaces; f++)   // read in face data

       {

              inStream >> face[f].nVerts;

              int n = face[f].nVerts;

              face[f].vert = new VertexID[n]; assert(face[f].vert != NULL);

              for(int k = 0; k < n; k++)            // read vertex indices for this face

                     inStream >> face[f].vert[k].vertIndex;

              for(int kk = 0; kk < n; kk++)              // read normal indices for this face

                     inStream >> face[f].vert[kk].normIndex;

       }

       inStream.close();

} // end of readMesh

 

//<<<<<<<<<<<<<<<<<<<<<< drawMesh >>>>>>>>>>>>>>>>>>>>

void Mesh :: drawMesh()

{ // draw each face of this mesh using OpenGL: draw each polygon.

       if(isEmpty()) return; // mesh is empty

       for(int f = 0; f < numFaces; f++)

       {

              int n = face[f].nVerts;

              glBegin(GL_POLYGON);

              //glBegin(GL_POINTS);

              for(int v = 0; v < n; v++)

              {

                     int in = face[f].vert[v].normIndex;

                     assert(in >= 0 && in < numNorms);

                     glNormal3f(norm[in].x, norm[in].y, norm[in].z);

                     int iv = face[f].vert[v].vertIndex; assert(iv >= 0 && iv < numVerts);

                     glColor3f((norm[in].x+1.0)/2.0, (norm[in].y+1.0)/2.0, (norm[in].z+1.0)/2.0 );

                     glVertex3f(pt[iv].x, pt[iv].y, pt[iv].z);

              }

              glEnd();  

       }

       glColor3f(1.0f,1.0f,1.0f);

}    

      

//<<<<<<<<<<<<<<<<<<<<<<<<<<<< write mesh>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

void Mesh:: writeMesh(char * fname)

{ // write this mesh object into a new Chapter 6 format file.

       if(numVerts == 0 || numNorms   == 0 || numFaces == 0) return; //empty

       fstream outStream(fname, ios ::out); // open the output stream

       if(outStream.fail()) {cout << "can't make new file: " << fname << endl;     

       return;}

       outStream << numVerts << " " << numNorms << " " << numFaces << "/n";

       // write the vertex and vertex normal list

       for(int i = 0; i < numVerts; i++)

              outStream << pt[i].x   << " " << pt[i].y   << " " << pt[i].z << "/n";

       for(int ii = 0; ii < numNorms; ii++)

              outStream  << norm[ii].x << " " << norm[ii].y << " " << norm[ii].z << "/n";

       // write the face data

       for(int f = 0; f < numFaces; f++)

       {

              int n = face[f].nVerts;

              outStream << n << "/n";

              for(int v = 0; v < n; v++)// write vertex indices for this face

                     outStream << face[f].vert[v].vertIndex << " ";    outStream << "/n";

              for(int k = 0; k < n; k++)      // write normal indices for this face

                     outStream << face[f].vert[k].normIndex << " "; outStream << "/n";

       }

       outStream.close();

}

 

 

float Mesh::GetAngle(Vector3 v1, Vector3 v2)

{

       float theta=0;

       theta=acos(v1.dot(v2))/PI*180;

       if(theta<180)

              return theta;

       else

              return theta-180;

}

 

void Mesh::writeMesh(Face *face, Vector3 *norm, Point3 *pt, int numFaces, int numNorms, int numVerts, char *fname)

{

       if(numVerts == 0 || numNorms   == 0 || numFaces == 0) return; //empty

       fstream outStream(fname, ios ::out); // open the output stream

       if(outStream.fail()) {cout << "can't make new file: " << fname << endl;     

       return;}

       outStream << numVerts << " " << numNorms << " " << numFaces << "/n";

       // write the vertex and vertex normal list

       for(int i = 0; i < numVerts; i++)

              outStream << pt[i].x   << " " << pt[i].y   << " " << pt[i].z << "/n";

       for(int ii = 0; ii < numNorms; ii++)

              outStream  << norm[ii].x << " " << norm[ii].y << " " << norm[ii].z << "/n";

       // write the face data

       for(int f = 0; f < numFaces; f++)

       {

              int n = face[f].nVerts;

              outStream << n << "/n";

              for(int v = 0; v < n; v++)// write vertex indices for this face

                     outStream << face[f].vert[v].vertIndex << " ";    outStream << "/n";

              for(int k = 0; k < n; k++)      // write normal indices for this face

                     outStream << face[f].vert[k].normIndex << " "; outStream << "/n";

       }

       outStream.close();

}

 

Point3 Vector3 類:

 

class Point3

{

public:

       float x,y,z,nID;

       void set(float dx,float dy,float dz){x=dx;y=dy;z=dz;}

       void set(int n){nID=n;}

       void set(Point3& p){x=p.x;y=p.y;z=p.z;}

       Point3(float xx,float yy,float zz){x=xx;y=yy;z=zz;}

       Point3(){x=y=z=0;}

       void bulid4tuple(float v[])

       { v[0]=x;v[1]=y;v[2]=z;v[3]=1.0f;

       }

};

 

class Vector3

{

public:

       void set(int n){nID=n;};

       float x,y,z,nID;

       void set(float dx,float dy,float dz){x=dx;y=dy;z=dz;}

       void set(Vector3& v){x=v.x;y=v.y;z=v.z;}

       void flip(){x=-x;y=-y;z=-z;}

       void setDiff(Point3& a,Point3& b)

       {

              x=a.x-b.x;y=a.y-b.y;z=a.z-b.z;

       }

       void normalize();

       Vector3(float xx,float yy,float zz){x=xx;y=yy;z=zz;}

       Vector3(Vector3& v){x=v.x;y=v.y;z=v.z;}

       Vector3(){x=y=z=0;}

       Vector3 cross(Vector3 b);

       float dot(Vector3 b);

};

 

Vector3 Vector3 :: cross(Vector3 b) //return this cross b

{

       Vector3 c(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x);

       return c;

}

 

float Vector3 :: dot(Vector3 b) // return this dotted with b

{return x * b.x + y * b.y + z * b.z;}

 

void Vector3 :: normalize()//adjust this vector to unit length

{           

       double sizeSq = x * x + y * y + z * z;

       if(sizeSq < 0.0000001)

       {

              cerr << "/nnormalize() sees vector (0,0,0)!";

              return; // does nothing to zero vectors;

       }

       float scaleFactor = 1.0/(float)sqrt(sizeSq);

       x *= scaleFactor; y *= scaleFactor; z *= scaleFactor;

}

 

 

第二部分:

視圖界面分爲兩個部分,即將視圖切分爲兩個視,左邊是基於CFormView的視,右邊是基於CView

 

 

 

切分的主要代碼如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

       CRect rect;

       GetClientRect(rect);

       m_wndSplitter.CreateStatic(this,1,2);

      

       m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CLeftView),

              CSize(rect.Width()*2/10,rect.Height()),pContext);

       m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CCurvedsurfaceView),

              CSize(rect.Width()*8/10,rect.Height()),pContext);

       return true;

}

 

左邊的視與右邊的視的聯繫:

顯示和重繪按鈕是建立二者聯繫的橋樑

 

顯示按鈕:

void CLeftView::Draw()

{

       UpdateData(true);

       CCurvedsurfaceView *pView=(CCurvedsurfaceView*)((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,1);      //視圖間的通信        pView->SendMessage(WM_MY_MESSAGE,0,0);

       pView->SetFocus();

}

 

重繪按鈕:

void CLeftView::OnInvalidate()

{

       CCurvedsurfaceView *pView=(CCurvedsurfaceView*)((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,1);

       pView->m_bInvalidate=true;

       pView->m_nCount=0;

       pView->m_bRot=false;

       pView->Invalidate(false);

}

 

右邊的視響應情況:

LRESULT CCurvedsurfaceView::OnMyMessage(WPARAM wParam, LPARAM lParam)

{

       CLeftView *pView=(CLeftView *)((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,0);

 

       //加載變量的值

       m_u=pView->m_u;

       m_v=pView->m_v;

       m_nDefault=pView->m_nDefault;

       m_nRulesurf=pView->m_nRulesurf;

       PreDraw();

       return 0;

}

 

void CCurvedsurfaceView::PreDraw()

{

       switch(m_nDefault)

       {

       case 0:

              if(m_nRulesurf==0)

              {

              m_rulesurf=new Rulesurf(m_ctlpt1,m_ctlpt2,m_ctlpt_num,m_u,m_v,3);

              }

              else

              {

                     m_revsurf=new Revsurf(m_ctlpt1,m_ctlpt_num,m_u,m_v,3);

              }

              Invalidate(false);

              break;

       case 1:

              break;

       }

 

       m_bInvalidate=false;

}

 

void CCurvedsurfaceView::DrawScene()

{

       glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

      

    glMatrixMode(GL_PROJECTION);

       glLoadIdentity();

       glOrtho(-2.0,2.0,-2.0,2.0,0,100);

       glMatrixMode(GL_MODELVIEW);

       glLoadIdentity();

       glTranslatef(0,0,-2.0f);

 

       glMatrixMode(GL_MODELVIEW);

       if(m_bRot)

       {

              glRotatef(m_fRot,1,1,0);

       }

 

       int i=0;

 

       if(m_bInvalidate==false)

       {

              switch(m_nDefault)

              {

              case 0:

                     if(m_nRulesurf==0)

                     {

                     m_rulesurf->readMesh("rulesurf.txt");

                     }

                     else

                     {

                            m_revsurf->readMesh("revsurf.txt");

                     }

                     break;

              case 1:

                     if(m_nRulesurf==0)

                     {

                            m_rulesurf->makepoints();

                            m_rulesurf->makenormals();

                            m_rulesurf->makefaces();

                            m_rulesurf->writeMesh("rulesurf1.txt");

                           

                            glPointSize(6.0);

                            glColor3f(0,0,1.0);

                            glBegin(GL_POINTS);

                            for(i=0;i<m_ctlpt_num;i++)

                                   glVertex3f(m_ctlpt1[i].x,m_ctlpt1[i].y,m_ctlpt1[i].z);

                            glEnd();

                            glBegin(GL_POINTS);

                            for(i=0;i<m_ctlpt_num;i++)

                                   glVertex3f(m_ctlpt2[i].x,m_ctlpt2[i].y,m_ctlpt2[i].z);

                            glEnd();

                           

                            glColor3f(1.0f,0,0);

                            glBegin(GL_LINE_STRIP);

                            for(i=0;i<m_ctlpt_num;i++)

                                   glVertex3f(m_ctlpt1[i].x,m_ctlpt1[i].y,m_ctlpt1[i].z);

                            glEnd();

                           

                            glBegin(GL_LINE_STRIP);

                            for(i=0;i<m_ctlpt_num;i++)

                                   glVertex3f(m_ctlpt2[i].x,m_ctlpt2[i].y,m_ctlpt2[i].z);

                            glEnd();

                            m_rulesurf->drawMesh();

                     }

                    

                     else

                     {

                            m_revsurf->makepoints();

                            m_revsurf->makenormals();

                            m_revsurf->makefaces();

                            m_revsurf->writeMesh("revsurf1.txt");

                           

                            glPointSize(6.0);

                            glColor3f(0,0,1.0);

                            glBegin(GL_POINTS);

                            for(i=0;i<m_ctlpt_num;i++)

                                   glVertex3f(m_ctlpt1[i].x,m_ctlpt1[i].y,m_ctlpt1[i].z);

                            glEnd();

                           

                            glColor3f(1.0f,0,0);

                            glBegin(GL_LINE_STRIP);

                            for(i=0;i<m_ctlpt_num;i++)

                                   glVertex3f(m_ctlpt1[i].x,m_ctlpt1[i].y,m_ctlpt1[i].z);

                            glEnd();

                            m_revsurf->drawMesh();

                     }

                     glColor3f(1.0f,1.0f,1.0f);

                     break;

              default:

                     break;

              }

       }

 

鼠標採集點的函數:

void CCurvedsurfaceView::OnLButtonDown(UINT nFlags, CPoint point)

{

       m_nCount++;

       if(m_nDefault==1 && m_nCount<=2*m_ctlpt_num)

       {

              if(m_nCount<=m_ctlpt_num)

              {

                     m_ctlpt1[m_nCount-1].set(point.x/(float)m_rect.Width()*4.0-2.0,-point.y/(float)m_rect.Height()*4.0+2.0,-1);

              }

              else

              {

                     m_ctlpt2[m_nCount-(m_ctlpt_num+1)].set(point.x/(float)m_rect.Width()*4.0-2.0,-point.y/(float)m_rect.Height()*4.0+2.0,0.0);

              }

             

              glMatrixMode(GL_MODELVIEW);

              glLoadIdentity();

              glTranslatef(0,0,-2.0f);

              glPointSize(6.0);

              glBegin(GL_POINTS);

              glVertex3f(point.x/(float)m_rect.Width()*4.0-2.0,-point.y/(float)m_rect.Height()*4.0+2.0,0);

              glEnd();

 

              if(m_nCount==m_ctlpt_num && m_nRulesurf==1)

              {

                     m_revsurf=new Revsurf(m_ctlpt1,m_ctlpt_num,m_u,m_v,3);

                     m_bRot=true;

                     Invalidate(false);

                     return;

              }

             

              if(m_nCount==2*m_ctlpt_num)

              {

                     m_rulesurf=new Rulesurf(m_ctlpt1,m_ctlpt2,m_ctlpt_num,m_u,m_v,3);

                     m_bRot=true;

                     Invalidate(false);

              }

       }

      

       SwapBuffers(::wglGetCurrentDC());

       CView::OnLButtonDown(nFlags, point);

}

 

運行的結果:

旋轉曲面:

直紋面:

 

發佈了31 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章