//////////////////////////////////////////////////////// // // GEM - Graphics Environment for Multimedia // // zmoelnig@iem.kug.ac.at // // Curve3D : create a besier surface // made by Cyrille Henry // // Copyright (c) 1997-1998 Mark Danks. // Copyright (c) Günther Geiger. // Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM // For information on usage and redistribution, and for a DISCLAIMER OF ALL // WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. // ///////////////////////////////////////////////////////// #include "curve3d.h" #include "Base/GemState.h" #include "Base/Matrix.h" #include "Base/GemFuncUtil.h" #include CPPEXTERN_NEW_WITH_TWO_ARGS(curve3d, t_floatarg, A_DEFFLOAT, t_floatarg, A_DEFFLOAT) ///////////////////////////////////////////////////////// // // curve3d // ///////////////////////////////////////////////////////// // Constructor // ///////////////////////////////////////////////////////// curve3d :: curve3d(t_floatarg sizeX,t_floatarg sizeY ) : GemShape(1), nb_pts_control_X(2), nb_pts_control_Y(2), nb_pts_affich_X (30), nb_pts_affich_Y (30), m_drawType(1), m_posXYZ(NULL) { int i, j, a; nb_pts_control_X = MAX(2, (int)sizeX); nb_pts_control_Y = MAX(2, (int)sizeY); m_posXYZ = new t_float3[nb_pts_control_X*nb_pts_control_Y]; if(!m_posXYZ){ nb_pts_control_X=0; nb_pts_control_Y=0; } for (i=0; i < nb_pts_control_X; i++) for (j=0; j < nb_pts_control_Y; j++) { a= i + j * nb_pts_control_X; m_posXYZ[a].x= (float)i/nb_pts_control_X; m_posXYZ[a].y= (float)j/nb_pts_control_Y; m_posXYZ[a].z= 0.0; } } ////////////////////////////////////////////////////////// // Destructor // ///////////////////////////////////////////////////////// curve3d :: ~curve3d() { if(m_posXYZ)delete[]m_posXYZ; } ////////////////////////////////////////////////////////// // setMess // ///////////////////////////////////////////////////////// void curve3d :: setMess(int X, int Y, float posX, float posY, float posZ){ if ((X>=0)&(X=0)&(Ys_name, "line")) m_drawType = 0; else if (!strcmp(type->s_name, "fill")) m_drawType = 1; else if (!strcmp(type->s_name, "point")) m_drawType = 2; else if (!strcmp(type->s_name, "line1")) m_drawType = 3; else if (!strcmp(type->s_name, "line2")) m_drawType = 4; else if (!strcmp(type->s_name, "line3")) m_drawType = 5; else if (!strcmp(type->s_name, "line4")) m_drawType = 6; else if (!strcmp(type->s_name, "control_fill")) m_drawType = 7; else if (!strcmp(type->s_name, "control_point")) m_drawType = 8; else if (!strcmp(type->s_name, "control_line")) m_drawType = 9; else if (!strcmp(type->s_name, "control_line1")) m_drawType = 10; else if (!strcmp(type->s_name, "control_line2")) m_drawType = 11; else if (!strcmp(type->s_name, "default")) m_drawType = 1; else { error ("unknown draw style"); return; } setModified(); } ////////////////////////////////////////////////////////// // renderShape // ///////////////////////////////////////////////////////// void curve3d :: renderShape(GemState *state){ if(m_drawType==GL_DEFAULT_GEM)m_drawType=1; float norm[3]; int n, m; glNormal3f(0.0f, 0.0f, 1.0f); glLineWidth(m_linewidth); glMap2f(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, (GLint)nb_pts_control_X, 0,1,(GLint)(3*nb_pts_control_X),(GLint)nb_pts_control_Y, &(m_posXYZ[0].x)); glEnable(GL_MAP2_VERTEX_3); GLfloat xsize = 1.0f; GLfloat ysize = 1.0f; GLfloat ysize0= 0.0f; if (state->texture && state->numTexCoords>=3) { xsize = state->texCoords[1].s; ysize0 = state->texCoords[2].t; ysize = state->texCoords[1].t; } GLfloat ysizediff = ysize0 - ysize; switch (m_drawType){ //line case 0: { if (state->texture) { for (n = 0; n < nb_pts_affich_X+1; n++) { glBegin(GL_LINE_STRIP); for (m = 0; m < nb_pts_affich_Y+1; m++){ glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } for(m = 0; m < nb_pts_affich_Y+1; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_affich_X+1; n++){ glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } else { for(n = 0; n < nb_pts_affich_X+1; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_affich_Y+1; m++){ glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } for(m = 0; m < nb_pts_affich_Y+1; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_affich_X+1; n++){ glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } } break; // fill case 1: { if (state->texture) for(n = 0; n < nb_pts_affich_X; n++) { glBegin(GL_TRIANGLE_STRIP); for(m = 0; m < nb_pts_affich_Y+1; m++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); glTexCoord2f(xsize*(GLfloat)(n+1)/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)(n+1)/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } else for(n = 0; n < nb_pts_affich_X; n++) { glBegin(GL_TRIANGLE_STRIP); for(m = 0; m < nb_pts_affich_Y+1; m++) { glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)(n+1)/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } break; case 2: //point { glBegin(GL_POINTS); if (state->texture) for(n = 0; n < nb_pts_affich_X+1; n++) { for(m = 0; m < nb_pts_affich_Y+1; m++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } } else for(n = 0; n < nb_pts_affich_X+1; n++) { for(m = 0; m < nb_pts_affich_Y+1; m++) glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } break; case 3: // line1 { if (state->texture) for(n = 0; n < nb_pts_affich_X; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_affich_Y; m++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } else for(n = 0; n < nb_pts_affich_X; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_affich_Y; m++) { glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } break; case 4: //line2 { if (state->texture) for(m = 0; m < nb_pts_affich_Y+1; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_affich_X+1; n++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X,ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } else for(m = 0; m < nb_pts_affich_Y+1; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_affich_X+1; n++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } break; case 5: //line3 { if (state->texture) for(n = 0; n < nb_pts_affich_X; n++) { glBegin(GL_LINES); for(m = 0; m < nb_pts_affich_Y; m++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } else for(n = 0; n < nb_pts_affich_X; n++) { glBegin(GL_LINES); for(m = 0; m < nb_pts_affich_Y; m++) { glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } break; case 6: //line4 { if (state->texture) for(m = 0; m < nb_pts_affich_Y; m++) { glBegin(GL_LINES); for(n = 0; n < nb_pts_affich_X; n++) { glTexCoord2f(xsize*(GLfloat)n/(float)nb_pts_affich_X, ysize+ysizediff*(GLfloat)m/(float)nb_pts_affich_Y); glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } else for(m = 0; m < nb_pts_affich_Y; m++) { glBegin(GL_LINES); for(n = 0; n < nb_pts_affich_X; n++) { glEvalCoord2f((GLfloat)n/(float)nb_pts_affich_X, (GLfloat)m/(float)nb_pts_affich_Y); } glEnd(); } } break; case 7: // control_fill { if (state->texture) for(n = 0; n < nb_pts_control_X-1; n++) for(m = 0; m < nb_pts_control_Y-1; m++) { Matrix::generateNormal((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X], (GLfloat*)&m_posXYZ[n+m*nb_pts_control_X+1], (GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X], norm); glNormal3fv(norm); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glTexCoord2f(xsize*(GLfloat)(n+1)/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X+1]); glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)(m+1)/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X]); glEnd(); Matrix::generateNormal((GLfloat*)&m_posXYZ[n+1+(m+1)*nb_pts_control_X], (GLfloat*)&m_posXYZ[n+1+m*nb_pts_control_X], (GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X], norm); glNormal3fv(norm); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(xsize*(GLfloat)(n+1)/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)(m+1)/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+1+(m+1)*nb_pts_control_X]); glTexCoord2f(xsize*(GLfloat)(n+1)/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+1+m*nb_pts_control_X]); glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)(m+1)/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X]); glEnd(); } else for(n = 0; n < nb_pts_control_X-1; n++) for(m = 0; m < nb_pts_control_Y-1; m++) { Matrix::generateNormal((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X], (GLfloat*)&m_posXYZ[n+m*nb_pts_control_X+1], (GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X], norm); glNormal3fv(norm); glBegin(GL_TRIANGLE_STRIP); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X+1]); glVertex3fv((GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X]); glEnd(); Matrix::generateNormal((GLfloat*)&m_posXYZ[n+1+(m+1)*nb_pts_control_X], (GLfloat*)&m_posXYZ[n+(1+m)*nb_pts_control_X], (GLfloat*)&m_posXYZ[n+1+m*nb_pts_control_X], norm); glNormal3fv(norm); glBegin(GL_TRIANGLE_STRIP); glVertex3fv((GLfloat*)&m_posXYZ[n+1+(m+1)*nb_pts_control_X]); glVertex3fv((GLfloat*)&m_posXYZ[n+(m+1)*nb_pts_control_X]); glVertex3fv((GLfloat*)&m_posXYZ[n+1+m*nb_pts_control_X]); glEnd(); } } break; case 8: // point de control de la structure (control_point) { if (state->texture) for(n = 0; n < nb_pts_control_X; n++) for(m = 0; m < nb_pts_control_Y; m++) { glBegin(GL_POINTS); glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glEnd(); } else for(n = 0; n < nb_pts_control_X; n++) for(m = 0; m < nb_pts_control_Y; m++) { glBegin(GL_POINTS); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glEnd(); } } break; case 9: //control_line { if (state->texture){ for(n = 0; n < nb_pts_control_X; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_control_Y; m++){ glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); } glEnd(); } for(m = 0; m < nb_pts_control_Y; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_control_X; n++){ glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); } glEnd(); } } else { for(n = 0; n < nb_pts_control_X; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_control_Y; m++) glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glEnd(); } for(m = 0; m < nb_pts_control_Y; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_control_X; n++) glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glEnd(); } } } break; case 11: //control_line2 { if (state->texture) for(m = 0; m < nb_pts_control_Y; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_control_X; n++) { glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); } glEnd(); } else for(m = 0; m < nb_pts_control_Y; m++) { glBegin(GL_LINE_STRIP); for(n = 0; n < nb_pts_control_X; n++) glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glEnd(); } } break; case 10: //control_line1 { if (state->texture) for(n = 0; n < nb_pts_control_X; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_control_Y; m++) { glTexCoord2f(xsize*(GLfloat)n/(nb_pts_control_X-1), ysize+ysizediff*(GLfloat)m/(nb_pts_control_Y-1)); glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); } glEnd(); } else for(n = 0; n < nb_pts_control_X; n++) { glBegin(GL_LINE_STRIP); for(m = 0; m < nb_pts_control_Y; m++) glVertex3fv((GLfloat*)&m_posXYZ[n+m*nb_pts_control_X]); glEnd(); } } return; } } ////////////////////////////////////////////////////////// // static member function // ///////////////////////////////////////////////////////// void curve3d :: obj_setupCallback(t_class *classPtr){ class_addmethod(classPtr, reinterpret_cast(&curve3d::resolutionMessCallback), gensym("res"), A_FLOAT, A_FLOAT, A_NULL); class_addmethod(classPtr, reinterpret_cast(&curve3d::gridMessCallback), gensym("grid"), A_FLOAT, A_FLOAT, A_NULL); class_addmethod(classPtr, reinterpret_cast(&curve3d::setMessCallback), gensym("set"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); } void curve3d :: resolutionMessCallback(void *data, t_floatarg resX, t_floatarg resY) { GetMyClass(data)->resolutionMess((int)resX, (int)resY); } void curve3d :: gridMessCallback(void *data, t_floatarg gridX, t_floatarg gridY) { GetMyClass(data)->gridMess((int)gridX, (int)gridY); } void curve3d :: setMessCallback(void *data, float X, float Y, float posX, float posY, float posZ) { GetMyClass(data)->setMess((int)X, (int)Y, posX, posY, posZ); }