此程序主要分爲兩部分,一部分是抽象旋轉曲面和直紋面的類,另一部分是視圖界面的類組織,二者通過在視圖界面定義數據成員建立聯繫。
第一部分:
旋轉曲面類:
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 knot與delete []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);
}
運行的結果:
旋轉曲面:
直紋面: