void display(void) { GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}; GLfloat edgePt[5][2] = /* counter clockwise */ {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}}; GLfloat curvePt[4][2] = /* clockwise */ {{0.25, 0.5}, {0.25, 0.75}, {0.75, 0.75}, {0.75, 0.5}}; GLfloat curveKnots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}; GLfloat pwlPt[4][2] = /* clockwise */ {{0.75, 0.5}, {0.5, 0.25}, {0.25, 0.5}}; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(330.0, 1.,0.,0.); glScalef (0.5, 0.5, 0.5); gluBeginSurface(theNurb); gluNurbsSurface(theNurb, 8, knots, 8, knots, 4 * 3, 3, &ctlpoints[0][0][0], 4, 4, GL_MAP2_VERTEX_3); gluBeginTrim (theNurb); gluPwlCurve (theNurb, 5, &edgePt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (theNurb); gluBeginTrim (theNurb); gluNurbsCurve (theNurb, 8, curveKnots, 2, &curvePt[0][0], 4, GLU_MAP1_TRIM_2); gluPwlCurve (theNurb, 3, &pwlPt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (theNurb); gluEndSurface(theNurb); glPopMatrix(); glFlush(); }
void display(void) { GLfloat knots1[12] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 , 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; GLfloat knots2[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}; int i, j; GLfloat edgePt[5][2] = {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}}; GLfloat pwlPt[42][2]; for(unsigned int k = 0; k < 42; ++k) { pwlPt[k][0] = 0.5 + 0.3 * cos(2.0*PI*k/41.0); pwlPt[k][1] = 0.5 + 0.3 * sin(-2.0*PI*k/41.0); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(330.0, 1.,0.,0.); glScalef (0.3, 0.3, 0.3); gluBeginSurface(theNurb); gluNurbsSurface(theNurb, 12, knots1, 8, knots2, 4 * 3, 3, &ctlpoints[0][0][0], 6, 4, GL_MAP2_VERTEX_3); // trim gluBeginTrim (theNurb); gluPwlCurve(theNurb, 5, &edgePt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (theNurb); gluBeginTrim (theNurb); gluPwlCurve (theNurb, 42, &pwlPt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (theNurb); gluEndSurface(theNurb); if (showPoints) { glPointSize(5.0); glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 0.0); glBegin(GL_POINTS); for (i = 0; i < 8; i++) { for (j = 0; j < 4; j++) { glVertex3f(ctlpoints[i][j][0], ctlpoints[i][j][1], ctlpoints[i][j][2]); } } glEnd(); glEnable(GL_LIGHTING); } glPopMatrix(); glFlush(); }
// Called to draw scene void RenderScene(void) { // Draw in Blue glColor3ub(0,0,220); // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the modelview matrix stack glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Rotate the mesh around to make it easier to see glRotatef(330.0f, 1.0f,0.0f,0.0f); // Render the NURB // Begin the NURB definition gluBeginSurface(pNurb); // Evaluate the surface gluNurbsSurface(pNurb, // pointer to NURBS renderer 8, Knots, // No. of knots and knot array u direction 8, Knots, // No. of knots and knot array v direction 4 * 3, // Distance between control points in u dir. 3, // Distance between control points in v dir. &ctrlPoints[0][0][0], // Control points 4, 4, // u and v order of surface GL_MAP2_VERTEX_3); // Type of surface // Outer area, include entire curve gluBeginTrim (pNurb); gluPwlCurve (pNurb, 5, &outsidePts[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (pNurb); // Inner triangluar area gluBeginTrim (pNurb); gluPwlCurve (pNurb, 4, &insidePts[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (pNurb); // Done with surface gluEndSurface(pNurb); // Restore the modelview matrix glPopMatrix(); // Dispalay the image glutSwapBuffers(); }
void Sample_12_8::draw() { int i, j; GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}; GLfloat edgePt[5][2] = /* counter clockwise */ {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}}; GLfloat curvePt[4][2] = /* clockwise */ {{0.25, 0.5}, {0.25, 0.75}, {0.75, 0.75}, {0.75, 0.5}}; GLfloat curveKnots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0}; GLfloat pwlPt[4][2] = /* clockwise */ {{0.75, 0.5}, {0.5, 0.25}, {0.25, 0.5}}; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(330.0, 1.,0.,0.); glScalef (0.5, 0.5, 0.5); gluBeginSurface(m_theNurb); gluNurbsSurface(m_theNurb, 8, knots, 8, knots, 4 * 3, 3, &m_ctlpoints[0][0][0], 4, 4, GL_MAP2_VERTEX_3); gluBeginTrim (m_theNurb); gluPwlCurve (m_theNurb, 5, &edgePt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (m_theNurb); gluBeginTrim (m_theNurb); gluNurbsCurve (m_theNurb, 8, curveKnots, 2, &curvePt[0][0], 4, GLU_MAP1_TRIM_2); gluPwlCurve (m_theNurb, 3, &pwlPt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim (m_theNurb); gluEndSurface(m_theNurb); if (m_showPoints) { glPointSize(5.0); glDisable(GL_LIGHTING); glColor3f(1.0, 1.0, 0.0); glBegin(GL_POINTS); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { glVertex3f(m_ctlpoints[i][j][0], m_ctlpoints[i][j][1], m_ctlpoints[i][j][2]); } } glEnd(); glEnable(GL_LIGHTING); } glPopMatrix(); }
void RenderScene(void) { glColor3ub(0,0,220); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glRotatef(330.0f, 1.0f, 0.0f, 0.0f); //修剪框是一个闭合的环 //外修剪框 GLfloat outSidePts[5][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}}; //内修剪框 GLfloat inSidePts[4][2] = {{0.25f, 0.25f}, { 0.5f, 0.5f}, {0.75f, 0.25f},{0.25f, 0.25f} }; gluBeginSurface(pNurb); //定义NURBS表面 gluNurbsSurface(pNurb, 8, Knots, //u定义域内的结点个数,以及结点序列 8, Knots,//v定义域内的结点个数,以及结点序列 4 * 3, //u方向上的控制点间隔 3, //v方向上的控制点间隔 &ctrlPoints[0][0][0], //控制点数组 4, 4, //u v的次数 GL_MAP2_VERTEX_3);//产生的类型 //开始修剪 gluBeginTrim(pNurb); gluPwlCurve(pNurb, 5, //修剪点的个数 &outSidePts[0][0], //修剪点数组 2, //点之间的间隔 GLU_MAP1_TRIM_2);//修剪的类型 gluEndTrim(pNurb); gluBeginTrim(pNurb); gluPwlCurve(pNurb, 4, &inSidePts[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim(pNurb); gluEndSurface(pNurb); DrawPoints(); glPopMatrix(); glutSwapBuffers(); }
/* nurb:BeginTrim() -> nurb */ static int luaglu_begin_trim(lua_State *L) { LuaGLUnurb *lnurb=luaglu_checknurb(L,1); gluBeginTrim(lnurb->nurb); lua_pushvalue(L,1); return 1; }
void render_scene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Render trimmed surface */ gluBeginSurface(nurb); gluNurbsSurface(nurb, 8, knots, 8, knots, 4*3, 3, &ctlpoints[0][0][0], 4, 4, GLU_MAP2_VERTEX_3); gluBeginTrim(nurb); gluPwlCurve(nurb, 5, &edgePt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim(nurb); gluBeginTrim(nurb); gluNurbsCurve(nurb, 8, curveKnots, 2, &curvePt[0][0], 4, GLU_MAP1_TRIM_2); gluPwlCurve (nurb, 3, &pwlPt[0][0], 2, GLU_MAP1_TRIM_2); gluEndTrim(nurb); gluEndSurface(nurb); /* Flush all drawings */ glFlush(); }
/* Execute a bgn/endtrim pair for the given trim curve structure. */ void dotrim(TrimCurve *trim_curve) { int i; gluBeginTrim(nurbsflag); for (i=0; i<trim_curve->pieces; i++) { if (trim_curve->trim[i].type == PWL) { gluPwlCurve(nurbsflag, trim_curve->trim[i].points, &trim_curve->trim[i].point[0][0], 2, GLU_MAP1_TRIM_2); } else { gluNurbsCurve(nurbsflag, ELEMENTS(trimknots),trimknots, 2,&trim_curve->trim[i].point[0][0], trim_curve->trim[i].points, GLU_MAP1_TRIM_2); } } gluEndTrim(nurbsflag); }
static int tolua_glu_gluBeginTrim00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"GLUnurbsObj",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { GLUnurbsObj* nobj = ((GLUnurbsObj*) tolua_tousertype(tolua_S,1,0)); { gluBeginTrim(nobj); } } return 0; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'gluBeginTrim'.",&tolua_err); return 0; #endif }
void ON_GL( const ON_BrepFace& face, GLUnurbsObj* nobj // created with gluNewNurbsRenderer ) ) { bool bSkipTrims = false; const ON_Mesh* mesh; mesh = face.Mesh(ON::render_mesh); if ( mesh ) { // use saved render mesh ON_GL(*mesh); } else { // use (slow and buggy) glu trimmed NURBS rendering double knot_scale[2][2] = {{0.0,1.0},{0.0,1.0}}; const ON_Brep* brep = face.Brep(); if ( !brep ) return; // untrimmed surface { ON_NurbsSurface tmp_nurbssrf; const ON_Surface* srf = brep->m_S[face.m_si]; const ON_NurbsSurface* nurbs_srf = ON_NurbsSurface::Cast(srf); if ( !nurbs_srf ) { // attempt to get NURBS form of this surface if ( srf->GetNurbForm( tmp_nurbssrf ) ) nurbs_srf = &tmp_nurbssrf; } if ( !nurbs_srf ) return; gluBeginSurface( nobj ); ON_GL( *nurbs_srf, nobj, (nurbs_srf->IsRational()) ? GL_MAP2_VERTEX_4 : GL_MAP2_VERTEX_3, true, knot_scale[0], knot_scale[1] ); } if ( bSkipTrims || brep->FaceIsSurface( face.m_face_index ) ) { gluEndSurface( nobj ); return; // face is trivially trimmed } int fli, li, lti, ti; // any knot scaling applied to the surface must also be applied to // the parameter space trimming geometry double xform[4][4] = {{knot_scale[0][1], 0.0, 0.0, -knot_scale[0][0]*knot_scale[0][1] }, {0.0, knot_scale[1][1], 0.0, -knot_scale[1][0]*knot_scale[1][1] }, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}; // Add face's 2d trimming loop(s) const int face_loop_count = face.m_li.Count(); for ( fli = 0; fli < face_loop_count; fli++ ) { gluBeginTrim( nobj ); li = face.m_li[fli]; const ON_BrepLoop& loop = brep->m_L[li]; const int loop_trim_count = loop.m_ti.Count(); for ( lti = 0; lti < loop_trim_count; lti++ ) { ti = loop.m_ti[lti]; const ON_BrepTrim& trim = brep->m_T[ti]; ON_GL( trim, nobj, GLU_MAP1_TRIM_2, xform ); } gluEndTrim( nobj ); } gluEndSurface( nobj ); } }
void SoNurbsSurface::GLRender(SoGLRenderAction *action) // //////////////////////////////////////////////////////////////////////// { // First see if the object is visible and should be rendered now if (! shouldGLRender(action)) return; const SoCoordinateElement *ce = SoCoordinateElement::getInstance(action->getState()); GLfloat *sKnots, *tKnots, *dstCoords; GLenum type; float *fKnots; int32_t nCoords, uOffset, vOffset; int32_t nsKnots, ntKnots, nsCoords, ntCoords; int32_t nDstCoords; int32_t sOffset, tOffset; int i, j; // Check for 0 control points nCoords = ce->getNum(); if (nCoords == 0) return; // Make sure the first current material is sent to GL SoMaterialBundle mb(action); mb.sendFirst(); // // Find the number of steps required for object space tessellation and // the pixel tolerance used for screen space tessellation. // float val = SoComplexityElement::get(action->getState()); if (val < 0.0) val = 0.0; if (val > 1.0) val = 1.0; int steps; if (val < 0.10) steps = 2; else if (val < 0.25) steps = 3; else if (val < 0.40) steps = 4; else if (val < 0.55) steps = 5; else steps = (int)(powf(val, 3.32)*28) + 2; float pixTolerance = 104.0*val*val - 252.0*val + 150; // // If the surface is being cached, or if the tessellation is in object // space, use the software NURBS library. Create a software NURBS // rendering class and use it to make nurbs rendering calls. Since // the software NURBS library generates triangles, texture mapping // will happen automatically without having to render a separate // texture surface. // if (SoComplexityTypeElement::get(action->getState()) == SoComplexityTypeElement::OBJECT_SPACE) { _SoNurbsGLRender *GLRender = new _SoNurbsGLRender(); // // Set the sampling to be constant across the surface with the // tessellation to be 'steps' across the S and T parameters // GLRender->setnurbsproperty( N_T2D, N_SAMPLINGMETHOD, N_FIXEDRATE ); GLRender->setnurbsproperty( N_V3D, N_SAMPLINGMETHOD, N_FIXEDRATE ); GLRender->setnurbsproperty( N_V3DR, N_SAMPLINGMETHOD, N_FIXEDRATE ); GLRender->setnurbsproperty( N_T2D, N_S_STEPS, steps); GLRender->setnurbsproperty( N_T2D, N_T_STEPS, steps); GLRender->setnurbsproperty( N_V3D, N_S_STEPS, steps); GLRender->setnurbsproperty( N_V3D, N_T_STEPS, steps); GLRender->setnurbsproperty( N_V3DR, N_S_STEPS, steps); GLRender->setnurbsproperty( N_V3DR, N_T_STEPS, steps); // Determine whether a texture coordinate surface must be generated SbBool doTextures = SoGLTextureEnabledElement::get(action->getState()); // Draw the surface drawNURBS (GLRender, action->getState(), doTextures); delete GLRender; return; } if (SoDrawStyleElement::get(action->getState()) == SoDrawStyleElement::POINTS) { // // Render the control points of the surface. Rendering the points // of the surface would be very slow, as the Software NURBS library // would have to be used, and because of the view dependent // tessellation, points would not necessarily remain visible. // glBegin(GL_POINTS); if (ce->is3D()) { for (i=0; i<nCoords; i++) { const SbVec3f & coords3 = ce->get3((int)i); glVertex3f ((GLfloat)(coords3[0]), (GLfloat)(coords3[1]), (GLfloat)(coords3[2])); } } else { for (i=0; i<nCoords; i++) { const SbVec4f & coords4 = ce->get4((int)i); glVertex4f ((GLfloat)(coords4[0]), (GLfloat)(coords4[1]), (GLfloat)(coords4[2]), (GLfloat)(coords4[3])); } } glEnd(); return; } // // Render the NURBS surface using the GLU. // GLUnurbsObj *nurbsObj = gluNewNurbsRenderer(); switch (SoDrawStyleElement::get(action->getState())) { case SoDrawStyleElement::FILLED: gluNurbsProperty (nurbsObj, (GLenum)GLU_DISPLAY_MODE, GLU_FILL); break; case SoDrawStyleElement::LINES: gluNurbsProperty (nurbsObj, (GLenum)GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON); break; } gluNurbsProperty (nurbsObj, (GLenum)GLU_SAMPLING_TOLERANCE, (GLfloat)pixTolerance); // // Collect the control points and knot vectors into an array suitable // for sending to the GL. The control points and knot vectors must be // converted to double precision so that they can be passed to the // GL NURBS routines. // GLfloat *dCoords, *duKnots, *dvKnots; if (ce->is3D()) { dCoords = (GLfloat *)new GLfloat[3*nCoords]; for (i=0; i<nCoords; i++) { const SbVec3f &c3 = ce->get3((int)i); dCoords[3*i] = (GLfloat)c3[0]; dCoords[3*i+1] = (GLfloat)c3[1]; dCoords[3*i+2] = (GLfloat)c3[2]; } uOffset = 3; type = GL_MAP2_VERTEX_3; } else { dCoords = (GLfloat *)new GLfloat[4*nCoords]; for (i=0; i<nCoords; i++) { const SbVec4f &c4 = ce->get4((int)i); dCoords[4*i] = (GLfloat)c4[0]; dCoords[4*i+1] = (GLfloat)c4[1]; dCoords[4*i+2] = (GLfloat)c4[2]; dCoords[4*i+3] = (GLfloat)c4[3]; } uOffset = 4; type = GL_MAP2_VERTEX_4; } vOffset = uOffset * numUControlPoints.getValue(); fKnots = (float *)uKnotVector.getValues(0); duKnots = (GLfloat *)new GLfloat[uKnotVector.getNum()]; for (i=0; i<uKnotVector.getNum(); i++) duKnots[i] = (GLfloat)fKnots[i]; fKnots = (GLfloat *)vKnotVector.getValues(0); dvKnots = (GLfloat *)new GLfloat[vKnotVector.getNum()]; for (i=0; i<vKnotVector.getNum(); i++) dvKnots[i] = (GLfloat)fKnots[i]; // Texture mapping. If doTextures == TRUE // we are drawing textures. If the textureCoordinateBinding is // DEFAULT, we have to build a default NURBS surface for the texture // coordinates, otherwise we use the texture coordinates in the texture // element. // If there is a software texture function defined, then we have to // create a texture nurb surface with the same number of points and // knots as the original surface, and call the texture coordinate function // at each vertex. SbBool doTextures = SoGLTextureEnabledElement::get(action->getState()); if(doTextures) { switch (SoTextureCoordinateElement::getType(action->getState())) { // software texture functions case SoTextureCoordinateElement::FUNCTION: { // generate S and T coords from U and V coords SbVec3f coord; SbVec2f stCoord; int offset; SoTextureCoordinateBundle tb(action, TRUE); nsCoords = numUControlPoints.getValue(); ntCoords = numVControlPoints.getValue(); sKnots = duKnots; tKnots = dvKnots; nsKnots = uKnotVector.getNum(); ntKnots = vKnotVector.getNum(); nDstCoords = nsCoords * ntCoords; dstCoords = (GLfloat *)new GLfloat[nDstCoords * 2]; for(int v = 0; v < ntCoords; v++) { for(int u = 0; u < nsCoords; u++) { if (ce->is3D()) { offset = 3 * (v * (int)nsCoords + u); coord[0] = dCoords[offset + 0]; coord[1] = dCoords[offset + 1]; coord[2] = dCoords[offset + 2]; } else { offset = 4 * (v * (int)nsCoords + u); coord[0] = dCoords[offset + 0] / dCoords[offset + 3]; coord[1] = dCoords[offset + 1] / dCoords[offset + 3]; coord[2] = dCoords[offset + 2] / dCoords[offset + 3]; } const SbVec4f &tc = tb.get(coord, SbVec3f(0.0, 1.0, 0.0)); dstCoords[(v * (int)nsCoords + u) * 2 + 0] = tc[0]; dstCoords[(v * (int)nsCoords + u) * 2 + 1] = tc[1]; } } break; } // texture coordinates defined from texture node case SoTextureCoordinateElement::EXPLICIT: // get texture coordinates from texture node const SoTextureCoordinateElement *te = SoTextureCoordinateElement::getInstance(action->getState()); int32_t nstCoords = te->getNum(); if (nstCoords < 1) { // Default texture coordinates are computed by defining // a bezier surface that is defined in the same valid // parameter space as the geometric surface. The valid // parameter space is defined based on the order and knot // vector. The coordinates go from 0 to one and the knot // vectors span the valid range of the geometric surface. // The knot vectors default to 0 and 1 in the event of bogus // input data. int uOrder, vOrder; GLfloat sKnotVal1, sKnotVal2, tKnotVal1, tKnotVal2; uOrder = uKnotVector.getNum() - numUControlPoints.getValue(); vOrder = vKnotVector.getNum() - numVControlPoints.getValue(); if ((uOrder > 0) && (uOrder < uKnotVector.getNum())) sKnotVal1 = duKnots[uOrder-1]; else sKnotVal1 = 0; if ((uOrder > 0) && (uOrder < uKnotVector.getNum())) sKnotVal2 = duKnots[uKnotVector.getNum()-uOrder]; else sKnotVal2 = 1; if ((vOrder > 0) && (vOrder < vKnotVector.getNum())) tKnotVal1 = dvKnots[vOrder-1]; else tKnotVal1 = 0; if ((vOrder > 0) && (vOrder < vKnotVector.getNum())) tKnotVal2 = dvKnots[vKnotVector.getNum()-vOrder]; else tKnotVal2 = 1; // do a linear 2x2 array nsKnots = 4; ntKnots = 4; sKnots = (GLfloat *)new GLfloat[4]; tKnots = (GLfloat *)new GLfloat[4]; sKnots[0] = sKnots[1] = sKnotVal1; tKnots[0] = tKnots[1] = tKnotVal1; sKnots[2] = sKnots[3] = sKnotVal2; tKnots[2] = tKnots[3] = tKnotVal2; // allocate a 2 x 2 array of GLfloat[2]'s nsCoords = 2; ntCoords = 2; nDstCoords = nsCoords * ntCoords * 2; dstCoords = (GLfloat *)new GLfloat[nDstCoords]; for(i = 0; i < 2; i++) { for(j = 0; j < 2; j++) { dstCoords[(i * 2 + j) * 2 + 0] = j; dstCoords[(i * 2 + j) * 2 + 1] = i; } } } else { // get knot vectors from this node nsKnots = sKnotVector.getNum(); fKnots = (float *)sKnotVector.getValues(0); sKnots = (GLfloat *)new GLfloat[nsKnots]; for (i=0; i < nsKnots; i++) sKnots[i] = (GLfloat)fKnots[i]; ntKnots = tKnotVector.getNum(); fKnots = (float *)tKnotVector.getValues(0); tKnots = (GLfloat *)new GLfloat[ntKnots]; for (i=0; i < ntKnots; i++) tKnots[i] = (GLfloat)fKnots[i]; nsCoords = numSControlPoints.getValue(); ntCoords = numTControlPoints.getValue(); nDstCoords = 2 * nstCoords; dstCoords = (GLfloat *)new GLfloat[nDstCoords]; for(i = 0; i < nstCoords; i++) { const SbVec2f &tc2 = te->get2(i); dstCoords[2*i] = (GLfloat)tc2[0]; dstCoords[2*i+1] = (GLfloat)tc2[1]; } } break; } sOffset = 2; tOffset = sOffset * nsCoords; } // // Draw the NURBS surface. Begin the surface. Then load the texture // map as a nurbs surface. Then, draw the geometric surface followed // by all of its trim curves. Then, end the surface. // glEnable(GL_AUTO_NORMAL); // Get one camera based element so that this node will be registered // with the cache. If the camera changes, this element will cause // the cache to be blown for this node and the nurbs surface will be // regenerated. SbMatrix vMat = SoViewingMatrixElement::get (action->getState()); SbMatrix mMat = SoModelMatrixElement::get (action->getState()); // Begin the surface. gluBeginSurface(nurbsObj); // Draw the texture surface if(doTextures) { // send down nurbs surface, then free memory gluNurbsSurface(nurbsObj, (GLint)nsKnots, sKnots, (GLint)ntKnots, tKnots, (GLint)sOffset, (GLint)tOffset, dstCoords, (GLint)(nsKnots - nsCoords), (GLint)(ntKnots - ntCoords), GL_MAP2_TEXTURE_COORD_2); // delete knots if not sharing them with the surface description // (in the case of software texture coordinates only) if(sKnots != duKnots) { delete [] sKnots; delete [] tKnots; } delete [] dstCoords; } gluNurbsSurface (nurbsObj, (GLint)(uKnotVector.getNum()), duKnots, (GLint)(vKnotVector.getNum()), dvKnots, (GLint)uOffset, (GLint)vOffset, dCoords, (GLint)(uKnotVector.getNum() - numUControlPoints.getValue()), (GLint)(vKnotVector.getNum() - numVControlPoints.getValue()), type); // // Get all of the trim curves and use them to trim the surface. // SoProfile *profile; const SoNodeList &trimNodes = SoProfileElement::get(action->getState()); SbBool haveTrim = FALSE; float *trimCoords, *trimKnots; int32_t numTrimCoords, numKnots, offset; int numTrims = trimNodes.getLength(); int floatsPerVec; // // For each trim curve, check its linkage to find out if it should be // continued on to the previous trim curve or if it should begin a // new trim curve. Then, send the trim to the NURBS library. // for (i=0; i<numTrims; i++) { GLfloat *dTrimCoords; GLfloat *dtmp; float *ftmp; // Get the trim curve. profile = (SoProfile *)trimNodes[(int) i]; profile->getTrimCurve (action->getState(), numTrimCoords, trimCoords, floatsPerVec, numKnots, trimKnots); // Check for degenerate trim curves if (numTrimCoords == 0) continue; // Check the linkage. if ((profile->linkage.getValue() == SoProfileElement::START_FIRST) || (profile->linkage.getValue() == SoProfileElement::START_NEW)) { if (haveTrim) gluEndTrim(nurbsObj); gluBeginTrim(nurbsObj); haveTrim = TRUE; } // Set the data type of the control points to non-rational or rational if (floatsPerVec == 2) type = (GLenum)GLU_MAP1_TRIM_2; else type = (GLenum)GLU_MAP1_TRIM_3; offset = floatsPerVec; dTrimCoords = new GLfloat[numTrimCoords*floatsPerVec]; dtmp = dTrimCoords; ftmp = trimCoords; for (j=0; j<floatsPerVec*numTrimCoords; j++) *dtmp++ = (GLfloat)(*ftmp++); if (numKnots == 0) { // Send down a Piecewise Linear Trim Curve gluPwlCurve (nurbsObj, (GLint)numTrimCoords, dTrimCoords, (GLint)offset, type); } else { // Send down a NURBS Trim Curve GLfloat *dTrimKnots = new GLfloat[numKnots]; dtmp = dTrimKnots; ftmp = trimKnots; for (j=0; j<numKnots; j++) *dtmp++ = (GLfloat)(*ftmp++); gluNurbsCurve (nurbsObj, (GLint)numKnots, dTrimKnots, (GLint)offset, dTrimCoords, (GLint)(numKnots - numTrimCoords), type); delete[] dTrimKnots; delete[] trimKnots; } delete[] dTrimCoords; delete[] trimCoords; } if (haveTrim) gluEndTrim(nurbsObj); gluEndSurface(nurbsObj); gluDeleteNurbsRenderer(nurbsObj); glDisable(GL_AUTO_NORMAL); delete[] dvKnots; delete[] duKnots; delete[] dCoords; }