#include #include #include #include #include #define MAXPTS 20 #define EPS 0.000001 #define WIREFRAME 1 #define SOLID_ANALYTIC 2 #define SOLID_CASTELJAU 3 int mousex, mousey; int sirka=800, vyska=600; int N=0; double V[MAXPTS][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,STEP=0.05; GLuint wlist,slist1,slist2; int SHOW_PTS=1; double Fact[55]; 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); // glRotatef(10,1.0,0.0,0.0); glRotatef(0,0.0,1.0,0.0); glScalef(2,2,-2); glTranslatef(x, y, 0); glScalef(0.0007,0.0007,0.0007); for (p = buffer; *p; p++) glutStrokeCharacter(GLUT_STROKE_ROMAN, *p); glPopMatrix(); } void SetVertexColor(double u, double v) { glColor3d(u,v,1.0-u-v); } void ComputeVertex(double u, double v, double *x, double *y, double *z) { int i,j,k; double w,pom; w=1.0-u-v; *x=*y=*z=0.0; for (i=0;i<=N;i++) for (j=0;j<=N-i;j++) { k=N-i-j; pom=Fact[N]*pow(u,i)*pow(v,j)*pow(w,k)/(Fact[i]*Fact[j]*Fact[k]); *x+=V[i][j][k][0]*pom; *y+=V[i][j][k][1]*pom; *z+=V[i][j][k][2]*pom; } } void GenerateBezierWireframe(void){ double u,v,w,x,y,z,WSTEP; WSTEP=0.5/N; glNewList(wlist,GL_COMPILE); glColor3d(0.0,0.0,0.7); glLineWidth(3); for (u=0.0;u<1.0+EPS;u+=WSTEP) { glBegin(GL_LINE_STRIP); for (v=0.0;v<1.0+EPS-u;v+=STEP) { ComputeVertex(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } for (v=0.0;v<1.0+EPS;v+=WSTEP) { glBegin(GL_LINE_STRIP); for (u=0.0;u<1.0+EPS-v;u+=STEP) { ComputeVertex(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } for (w=0.0;w<1.0+EPS;w+=WSTEP) { glBegin(GL_LINE_STRIP); for (u=0.0;u<1.0+EPS-w;u+=STEP) { v=1.0-u-w; ComputeVertex(u,v,&x,&y,&z); glVertex3d(x,y,z); } glEnd(); } glLineWidth(1); glEndList(); } void GenerateBezierSolidAnalytic(void){ double u,v,w,x,y,z; glNewList(slist1,GL_COMPILE); glBegin(GL_TRIANGLES); for (u=0.0;u<1.0+EPS;u+=STEP) for (v=0.0;v<1.0+EPS-u;v+=STEP) { w=1.0-u-v; if (w>=STEP-EPS) { ComputeVertex(u,v,&x,&y,&z); SetVertexColor(u,v); glVertex3d(x,y,z); ComputeVertex(u,v+STEP,&x,&y,&z); SetVertexColor(u,v+STEP); glVertex3d(x,y,z); ComputeVertex(u+STEP,v,&x,&y,&z); SetVertexColor(u+STEP,v); glVertex3d(x,y,z); if (u+v+2*STEP<1.0+EPS) { ComputeVertex(u,v+STEP,&x,&y,&z); SetVertexColor(u,v+STEP); glVertex3d(x,y,z); ComputeVertex(u+STEP,v+STEP,&x,&y,&z); SetVertexColor(u+STEP,v+STEP); glVertex3d(x,y,z); ComputeVertex(u+STEP,v,&x,&y,&z); SetVertexColor(u+STEP,v); glVertex3d(x,y,z); } }} glEnd(); glEndList(); } void ComputeCasteljauVertex(int r, int i0, int i1, int i2, double u, double v, double *x, double *y, double *z) { double xx,yy,zz,w; if (!r) { *x=V[i0][i1][i2][0]; *y=V[i0][i1][i2][1]; *z=V[i0][i1][i2][2]; return; } *x=*y=*z=0.0; w=1.0-u-v; ComputeCasteljauVertex(r-1,i0+1,i1,i2,u,v,&xx,&yy,&zz); *x+=u*xx; *y+=u*yy; *z+=u*zz; ComputeCasteljauVertex(r-1,i0,i1+1,i2,u,v,&xx,&yy,&zz); *x+=v*xx; *y+=v*yy; *z+=v*zz; ComputeCasteljauVertex(r-1,i0,i1,i2+1,u,v,&xx,&yy,&zz); *x+=w*xx; *y+=w*yy; *z+=w*zz; } void GenerateBezierSolidCasteljau(void){ double u,v,w,x,y,z; glNewList(slist2,GL_COMPILE); glBegin(GL_TRIANGLES); // glBegin(GL_QUADS); for (u=0.0;u<1.0-EPS;u+=STEP) for (v=0.0;v<1.0-EPS-u;v+=STEP) { w=1.0-u-v; if (w>=-EPS) { ComputeCasteljauVertex(N,0,0,0,u,v,&x,&y,&z); SetVertexColor(v,1-u-v); glVertex3d(x,y,z); ComputeCasteljauVertex(N,0,0,0,u,v+STEP,&x,&y,&z); SetVertexColor(v+STEP,1-u-v-STEP); glVertex3d(x,y,z); ComputeCasteljauVertex(N,0,0,0,u+STEP,v,&x,&y,&z); SetVertexColor(v,1-u-v-STEP); glVertex3d(x,y,z); if (u+v+2*STEP<1.0+EPS) { ComputeCasteljauVertex(N,0,0,0,u,v+STEP,&x,&y,&z); SetVertexColor(v+STEP,1-u-v-STEP); glVertex3d(x,y,z); ComputeCasteljauVertex(N,0,0,0,u+STEP,v+STEP,&x,&y,&z); SetVertexColor(v+STEP,1-u-v-2*STEP); glVertex3d(x,y,z); ComputeCasteljauVertex(N,0,0,0,u+STEP,v,&x,&y,&z); SetVertexColor(v,1-u-v-STEP); glVertex3d(x,y,z); } }} glEnd(); glEndList(); } void display(void) { int i,j,k; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode(GL_MODELVIEW); 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 point=[%d,%d,%d] step=%.2f mode=%d",N,sel_pt_i,sel_pt_j,N-sel_pt_i-sel_pt_j,STEP,mode); if (SHOW_PTS) { glColor3d(0.5,0.5,0.5); glLineWidth(1.0); for (i=0;i<=N;i++) { glBegin(GL_LINE_STRIP); for (j=0;j<=N-i;j++) { k=N-i-j; glVertex3dv(V[i][j][k]); } glEnd(); } for (j=0;j<=N;j++) { glBegin(GL_LINE_STRIP); for (i=0;i<=N-j;i++) { k=N-i-j; glVertex3dv(V[i][j][k]); } glEnd(); } for (k=0;k<=N;k++) { glBegin(GL_LINE_STRIP); for (i=0;i<=N-k;i++) { j=N-i-k; glVertex3dv(V[i][j][k]); } glEnd(); } } if (mode==1) glCallList(wlist); if (mode==2) glCallList(slist1); if (mode==3) glCallList(slist2); 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<=N-i;j++) { k=N-i-j; glVertex3dv(V[i][j][k]); } glEnd(); glColor3d(0.0,1.0,0.0); glPointSize(7.0); glBegin(GL_POINTS); glVertex3dv(V[sel_pt_i][sel_pt_j][N-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 keypressed(unsigned char key, int x, int y) { int i,j,k; 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 'n': if (N-2) { N--; for (i=0;i<=N;i++) for (j=0;j<=N-i;j++){ k=N-i-j; V[i][j][k][0]=i/5.0; V[i][j][k][2]=j/5.0; V[i][j][k][1]=0.0; } sel_pt_i=sel_pt_j=0; } if (mode==WIREFRAME) GenerateBezierWireframe(); if (mode==SOLID_ANALYTIC) GenerateBezierSolidAnalytic(); if (mode==SOLID_CASTELJAU) GenerateBezierSolidCasteljau(); break; case 'N': if (!N-MAXPTS+5) { N++; for (i=0;i<=N;i++) for (j=0;j<=N-i;j++){ k=N-i-j; V[i][j][k][0]=i/5.0; V[i][j][k][2]=j/5.0; V[i][j][k][1]=0.0; } sel_pt_i=sel_pt_j=0; } if (mode==WIREFRAME) GenerateBezierWireframe(); if (mode==SOLID_ANALYTIC) GenerateBezierSolidAnalytic(); if (mode==SOLID_CASTELJAU) GenerateBezierSolidCasteljau(); break; case '+': ZOOM+=STEP; break; case '-': ZOOM-=STEP; break; case 'S': STEP+=0.01; if (mode==WIREFRAME) GenerateBezierWireframe(); if (mode==SOLID_ANALYTIC) GenerateBezierSolidAnalytic(); if (mode==SOLID_CASTELJAU) GenerateBezierSolidCasteljau(); break; case 's': if (STEP>0.01) STEP-=0.01; if (mode==WIREFRAME) GenerateBezierWireframe(); if (mode==SOLID_ANALYTIC) GenerateBezierSolidAnalytic(); if (mode==SOLID_CASTELJAU) GenerateBezierSolidCasteljau(); 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][N-sel_pt_i-sel_pt_j][1]+=0.025; break; case GLUT_KEY_PAGE_DOWN: V[sel_pt_i][sel_pt_j][N-sel_pt_i-sel_pt_j][1]-=0.025; break; case GLUT_KEY_UP: V[sel_pt_i][sel_pt_j][N-sel_pt_i-sel_pt_j][2]+=0.025; break; case GLUT_KEY_DOWN: V[sel_pt_i][sel_pt_j][N-sel_pt_i-sel_pt_j][2]-=0.025; break; case GLUT_KEY_LEFT: V[sel_pt_i][sel_pt_j][N-sel_pt_i-sel_pt_j][0]-=0.025; break; case GLUT_KEY_RIGHT: V[sel_pt_i][sel_pt_j][N-sel_pt_i-sel_pt_j][0]+=0.025; break; } if (mode==WIREFRAME) GenerateBezierWireframe(); if (mode==SOLID_ANALYTIC) GenerateBezierSolidAnalytic(); if (mode==SOLID_CASTELJAU) GenerateBezierSolidCasteljau(); } if ((!is_alt)&&(!is_ctrl)&&(!is_shift)) { switch (key) { case GLUT_KEY_UP: if (sel_pt_i+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+sel_pt_j