#include #include #include #include #include #define MAXPTS 55 #define EPS 0.000001 #define WIREFRAME 1 #define SOLID 2 #define PTMOVEMUL 5 int mousex, mousey; int sirka=800, vyska=600; int M=0,N=0; double V[MAXPTS][MAXPTS][3]; int sel_pt_i=0,sel_pt_j=0,color=0,mode=0; int is_ctrl,is_alt,is_shift; double ZOOM=2.0,XOFFSET=-1.0,YOFFSET=0.0,ROTATEX=15.0,ROTATEY=0.0; GLuint wlist,slist; double STEP=0.05; double Comb[100][100]; int SHOW_PTS=1; void PreCompute(void){ int i,j; for (i=0;i<100;i++) for (j=0;j<=i;j++) if ((!j)||(j==i)) Comb[i][j]=1; else Comb[i][j]=Comb[i-1][j-1]+Comb[i-1][j]; } void PisBitmapovyText(int x, int y, char *string, void *font) { int len, i; glRasterPos2f(x, y); len = (int) strlen(string); for (i = 0; i < len; i++) glutBitmapCharacter(font, string[i]); } void PisVektorovyText(GLfloat x, GLfloat y, char *format,...) { va_list args; char buffer[200], *p; va_start(args, format); vsprintf(buffer, format, args); va_end(args); glPushMatrix(); glLoadIdentity(); glTranslatef(-1.0,0.0,-6.0f); // move into the screen 6.0 glRotatef(15,1.0,0.0,0.0); glRotatef(0,0.0,1.0,0.0); glScalef(2,2,-2); glTranslatef(x, y, 0); glScalef(0.0005,0.0005,0.0005); for (p = buffer; *p; p++) glutStrokeCharacter(GLUT_STROKE_ROMAN, *p); glPopMatrix(); } void SetVertexColor(double u, double v) { if (u+v<=1.0) glColor3d(1.0,u+v,0.0); else glColor3d(2.0-u-v,1.0,0.0); } double H(int i, double t){ switch (i){ case 0: return 2*t*t*t-3*t*t+1; break; case 1: return t*t*t-2*t*t+t; break; case 2: return t*t*t-t*t; break; case 3: return -2*t*t*t+3*t*t; break; } return 0; } void BezierPoint(int x0, int y0, int dx, int dy, int n, double t, double *x, double *y, double *z){ int i,xx,yy; double pom; *x=*y=*z=0.0; for (i=0;i<=n;i++) { xx=x0+i*dx; yy=y0+i*dy; pom=Comb[n][i]*pow(t,i)*pow(1-t,n-i); *x+=V[xx][yy][0]*pom; *y+=V[xx][yy][1]*pom; *z+=V[xx][yy][2]*pom; } } void Xu0(double u, double *x, double *y, double *z){ BezierPoint(0,0,1,0,N,u,x,y,z); } void Xu1(double u, double *x, double *y, double *z){ BezierPoint(0,M,1,0,N,u,x,y,z); } void X0v(double v, double *x, double *y, double *z){ BezierPoint(0,0,0,1,M,v,x,y,z); } void X1v(double v, double *x, double *y, double *z){ BezierPoint(N,0,0,1,M,v,x,y,z); } void Xu0v(double v, double *x, double *y, double *z){ double xx,yy,zz,hh; *x=*y=*z=0.0; xx=(V[1][0][0]-V[0][0][0])*(N+1); yy=(V[1][0][1]-V[0][0][1])*(N+1); zz=(V[1][0][2]-V[0][0][2])*(N+1); hh=H(0,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; xx=(V[1][M][0]-V[0][M][0])*(N+1); yy=(V[1][M][1]-V[0][M][1])*(N+1); zz=(V[1][M][2]-V[0][M][2])*(N+1); hh=H(3,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; } void Xu1v(double v, double *x, double *y, double *z){ double xx,yy,zz,hh; *x=*y=*z=0.0; xx=(V[N][0][0]-V[N-1][0][0])*(N+1); yy=(V[N][0][1]-V[N-1][0][1])*(N+1); zz=(V[N][0][2]-V[N-1][0][2])*(N+1); hh=H(0,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; xx=(V[N][M][0]-V[N-1][M][0])*(N+1); yy=(V[N][M][1]-V[N-1][M][1])*(N+1); zz=(V[N][M][2]-V[N-1][M][2])*(N+1); hh=H(3,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; } void Xvu0(double u, double *x, double *y, double *z){ double xx,yy,zz,hh; *x=*y=*z=0.0; xx=(V[0][1][0]-V[0][0][0])*(M+1); yy=(V[0][1][1]-V[0][0][1])*(M+1); zz=(V[0][1][2]-V[0][0][2])*(M+1); hh=H(0,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; xx=(V[N][1][0]-V[N][0][0])*(M+1); yy=(V[N][1][1]-V[N][0][1])*(M+1); zz=(V[N][1][2]-V[N][0][2])*(M+1); hh=H(3,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; } void Xvu1(double u, double *x, double *y, double *z){ double xx,yy,zz,hh; *x=*y=*z=0.0; xx=(V[0][M][0]-V[0][M-1][0])*(M+1); yy=(V[0][M][1]-V[0][M-1][1])*(M+1); zz=(V[0][M][2]-V[0][M-1][2])*(M+1); hh=H(0,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; xx=(V[N][M][0]-V[N][M-1][0])*(M+1); yy=(V[N][M][1]-V[N][M-1][1])*(M+1); zz=(V[N][M][2]-V[N][M-1][2])*(M+1); hh=H(3,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; } void Hc(double u, double v, double *x, double *y, double *z){ double xx,yy,zz,hh; *x=*y=*z=0.0; X0v(v,&xx,&yy,&zz); hh=H(0,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; Xu0v(v,&xx,&yy,&zz); hh=H(1,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; Xu1v(v,&xx,&yy,&zz); hh=H(2,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; X1v(v,&xx,&yy,&zz); hh=H(3,u); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; } void Hd(double u, double v, double *x, double *y, double *z){ double xx,yy,zz,hh; *x=*y=*z=0.0; Xu0(u,&xx,&yy,&zz); hh=H(0,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; Xvu0(u,&xx,&yy,&zz); hh=H(1,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; Xvu1(u,&xx,&yy,&zz); hh=H(2,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; Xu1(u,&xx,&yy,&zz); hh=H(3,v); *x+=hh*xx; *y+=hh*yy; *z+=hh*zz; } void Hcd(double u, double v, double *x, double *y, double *z){ double XX[4][4][3],H1[4],H2[4],temp[4][3]; int i,j,k; for (k=0;k<3;k++) XX[0][0][k]=V[0][0][k]; for (k=0;k<3;k++) XX[0][1][k]=(V[0][1][k]-V[0][0][k])*(M+1); for (k=0;k<3;k++) XX[0][2][k]=(V[0][M][k]-V[0][M-1][k])*(M+1); for (k=0;k<3;k++) XX[0][3][k]=V[0][M][k]; for (k=0;k<3;k++) XX[1][0][k]=(V[1][0][k]-V[0][0][k])*(N+1); for (k=0;k<3;k++) XX[1][1][k]=0.0; for (k=0;k<3;k++) XX[1][2][k]=0.0; for (k=0;k<3;k++) XX[1][3][k]=(V[1][M][k]-V[0][M][k])*(N+1); for (k=0;k<3;k++) XX[2][0][k]=(V[N][0][k]-V[N-1][0][k])*(N+1); for (k=0;k<3;k++) XX[2][1][k]=0.0; for (k=0;k<3;k++) XX[2][2][k]=0.0; for (k=0;k<3;k++) XX[2][3][k]=(V[N][M][k]-V[N-1][M][k])*(N+1); for (k=0;k<3;k++) XX[3][0][k]=V[N][0][k]; for (k=0;k<3;k++) XX[3][1][k]=(V[N][1][k]-V[N][0][k])*(M+1); for (k=0;k<3;k++) XX[3][2][k]=(V[N][M][k]-V[N][M-1][k])*(M+1); for (k=0;k<3;k++) XX[3][3][k]=V[N][M][k]; for (k=0;k<4;k++) H1[k]=H(k,u); for (k=0;k<4;k++) H2[k]=H(k,v); for (i=0;i<4;i++) for (k=0;k<3;k++) { temp[i][k]=0.0; for (j=0;j<4;j++) temp[i][k]+=H1[j]*XX[j][i][k]; } *x=*y=*z=0.0; for (i=0;i<4;i++) *x+=temp[i][0]*H2[i]; for (i=0;i<4;i++) *y+=temp[i][1]*H2[i]; for (i=0;i<4;i++) *z+=temp[i][2]*H2[i]; } void BOD(double u, double v, double *x, double *y, double *z){ double xx,yy,zz; *x=*y=*z=0.0; Hc(u,v,&xx,&yy,&zz); *x+=xx; *y+=yy; *z+=zz; Hd(u,v,&xx,&yy,&zz); *x+=xx; *y+=yy; *z+=zz; Hcd(u,v,&xx,&yy,&zz); *x-=xx; *y-=yy; *z-=zz; } void GenerateWireframe(void){ double MSTEP,NSTEP,u,v,x,y,z; glNewList(wlist,GL_COMPILE); MSTEP=1.0/M; NSTEP=1.0/N; glLineWidth(4.0); glColor3d(0.0,0.0,1.0); for (u=0.0;u<=1.0+EPS;u+=1) { glBegin(GL_LINE_STRIP); for (v=0.0;v<=1.0+EPS;v+=STEP) { BOD(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } for (v=0.0;v<=1.0+EPS;v+=1) { glBegin(GL_LINE_STRIP); for (u=0.0;u<=1.0+EPS;u+=STEP) { BOD(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } glLineWidth(2.0); glColor3d(0.0,0.0,1.0); for (u=NSTEP;u<=1.0+EPS-NSTEP;u+=NSTEP) { glBegin(GL_LINE_STRIP); for (v=0.0;v<=1.0+EPS;v+=STEP) { BOD(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } for (v=MSTEP;v<=1.0+EPS-MSTEP;v+=MSTEP) { glBegin(GL_LINE_STRIP); for (u=0.0;u<=1.0+EPS;u+=STEP) { BOD(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } glEndList(); } void GenerateSolid(void){ double u,v,x,y,z; glNewList(slist,GL_COMPILE); glBegin(GL_QUADS); for (u=0;u<1.0-STEP+EPS;u+=STEP) for (v=0;v<1.0-STEP+EPS;v+=STEP) { SetVertexColor(u,v); BOD(u,v,&x,&y,&z); glVertex3d(x,y,z); SetVertexColor(u+STEP,v); BOD(u+STEP,v,&x,&y,&z); glVertex3d(x,y,z); SetVertexColor(u+STEP,v+STEP); BOD(u+STEP,v+STEP,&x,&y,&z); glVertex3d(x,y,z); SetVertexColor(u,v+STEP); BOD(u,v+STEP,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); glEndList(); } void display(void) { int i,j; // char pom[100]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); glTranslatef(XOFFSET,YOFFSET,-6.0f); // move into the screen 6.0 glRotatef(ROTATEX,1.0,0.0,0.0); glRotatef(ROTATEY,0.0,1.0,0.0); glScalef(ZOOM,ZOOM,-ZOOM); glColor3d(1.0,1.0,1.0); glLineWidth(2.0); PisVektorovyText(-0.9,1.0,"N=%d M=%d step=%.2f",N,M,STEP); if (SHOW_PTS) { glColor3d(0.5,0.5,0.5); glLineWidth(1.0); for (i=0;i<=N;i+=N) { glBegin(GL_LINE_STRIP); for (j=0;j<=M;j++) glVertex3dv(V[i][j]); glEnd(); } for (j=0;j<=M;j+=M) { glBegin(GL_LINE_STRIP); for (i=0;i<=N;i++) glVertex3dv(V[i][j]); glEnd(); } } if (mode==WIREFRAME) glCallList(wlist); if (mode==SOLID) glCallList(slist); if (SHOW_PTS) { glColor3d(0.5,0.5,0.5); glPointSize(5.0); glBegin(GL_POINTS); for (i=0;i<=N;i++) for (j=0;j<=M;j++) if (!(i*j*(N-i)*(M-j))) glVertex3dv(V[i][j]); glEnd(); glColor3d(0.0,1.0,0.0); glPointSize(7.0); glBegin(GL_POINTS); glVertex3dv(V[sel_pt_i][sel_pt_j]); glEnd(); } glutSwapBuffers(); } void reshape(int w, int h) { sirka=w; vyska=h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)sirka/(GLfloat)vyska,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); } void GenerujDisplayList(void){ switch (mode) { case 1: GenerateWireframe(); break; case 2: GenerateSolid(); break; } } void keypressed(unsigned char key, int x, int y) { is_ctrl=glutGetModifiers(); is_alt=is_ctrl&GLUT_ACTIVE_ALT; is_shift=is_ctrl&GLUT_ACTIVE_SHIFT; is_ctrl=is_ctrl&GLUT_ACTIVE_CTRL; switch (key) { case 27: exit(0); break; case 'm': if (M-2) { M--; sel_pt_i=sel_pt_j=0; } GenerujDisplayList(); break; case 'M': if (!M-MAXPTS+5) M++; GenerujDisplayList(); break; case 'n': if (N-2) { N--; sel_pt_i=sel_pt_j=0; } GenerujDisplayList(); break; case 'N': if (!N-MAXPTS+5) N++; GenerujDisplayList(); break; case '+': ZOOM+=STEP; break; case '-': ZOOM-=STEP; break; case 'S': STEP+=0.01; GenerujDisplayList(); break; case 's': if (STEP>0.01) STEP-=0.01; GenerujDisplayList(); break; case 'p': SHOW_PTS^=1; break; } glutPostRedisplay(); } void keypressed_special(int key, int x, int y) { is_ctrl=glutGetModifiers(); is_alt=is_ctrl&GLUT_ACTIVE_ALT; is_shift=is_ctrl&GLUT_ACTIVE_SHIFT; is_ctrl=is_ctrl&GLUT_ACTIVE_CTRL; if (is_alt) { switch (key) { case GLUT_KEY_UP: ROTATEX-=2; break; case GLUT_KEY_DOWN: ROTATEX+=2; break; case GLUT_KEY_LEFT: ROTATEY-=2; break; case GLUT_KEY_RIGHT: ROTATEY+=2; break; } } if (is_ctrl) { switch (key) { case GLUT_KEY_UP: YOFFSET-=STEP; break; case GLUT_KEY_DOWN: YOFFSET+=STEP; break; case GLUT_KEY_LEFT: XOFFSET+=STEP; break; case GLUT_KEY_RIGHT: XOFFSET-=STEP; break; } } if (is_shift) { switch (key) { case GLUT_KEY_PAGE_UP: V[sel_pt_i][sel_pt_j][1]+=0.025; break; case GLUT_KEY_PAGE_DOWN: V[sel_pt_i][sel_pt_j][1]-=0.025; break; case GLUT_KEY_UP: V[sel_pt_i][sel_pt_j][2]+=0.025; break; case GLUT_KEY_DOWN: V[sel_pt_i][sel_pt_j][2]-=0.025; break; case GLUT_KEY_LEFT: V[sel_pt_i][sel_pt_j][0]-=0.025; break; case GLUT_KEY_RIGHT: V[sel_pt_i][sel_pt_j][0]+=0.025; break; } GenerujDisplayList(); } if ((!is_alt)&&(!is_ctrl)&&(!is_shift)) { switch (key) { case GLUT_KEY_UP: if (sel_pt_j0) sel_pt_j--; break; case GLUT_KEY_LEFT: if (sel_pt_i>0) sel_pt_i--; break; case GLUT_KEY_RIGHT: if (sel_pt_i