home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / gfx / x11 / Mesa_Amiwin.lha / Mesa-Amiwin / src-glu / nurbsutl.c < prev    next >
C/C++ Source or Header  |  1995-11-17  |  14KB  |  665 lines

  1. /* nurbsutl.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: nurbsutl.c,v 1.5 1995/11/03 14:15:13 brianp Exp $
  26.  
  27. $Log: nurbsutl.c,v $
  28.  * Revision 1.5  1995/11/03  14:15:13  brianp
  29.  * Bogdan's November 3, 1995 updates
  30.  *
  31.  * Revision 1.4  1995/09/20  18:25:57  brianp
  32.  * removed Bogdan's old email address
  33.  *
  34.  * Revision 1.3  1995/08/04  13:09:59  brianp
  35.  * include gluP.h to define NULL, just in case
  36.  *
  37.  * Revision 1.2  1995/07/28  21:37:30  brianp
  38.  * updates from Bogdan on July 28
  39.  *
  40.  * Revision 1.1  1995/07/28  14:45:10  brianp
  41.  * Initial revision
  42.  *
  43.  */
  44.  
  45.  
  46. /*
  47.  * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
  48.  * See README-nurbs for more info.
  49.  */
  50.  
  51.  
  52. #include <math.h>
  53. #include <stdlib.h>
  54. #include "nurbs.h"
  55.  
  56. GLenum
  57. test_knot(GLint nknots, GLfloat *knot, GLint order)
  58. {
  59.     GLsizei i;
  60.     GLint knot_mult;
  61.     GLfloat tmp_knot;
  62.  
  63.     tmp_knot=knot[0];
  64.     knot_mult=1;
  65.     for(i=1;i<nknots;i++)
  66.     {
  67.         if(knot[i] < tmp_knot)
  68.             return GLU_NURBS_ERROR4;
  69.         if(fabs(tmp_knot-knot[i]) > EPSILON)
  70.         {
  71.             if(knot_mult>order)
  72.                 return GLU_NURBS_ERROR5;
  73.             knot_mult=1;
  74.             tmp_knot=knot[i];
  75.         }
  76.         else
  77.             ++knot_mult;
  78.     }
  79.     return GLU_NO_ERROR;
  80. }
  81.  
  82. GLenum
  83. explode_knot(knot_str_type *the_knot)
  84. {
  85.     GLfloat *knot,*new_knot;
  86.     GLint nknots,n_new_knots=0;
  87.     GLint t_min,t_max;
  88.     GLint ord;
  89.     GLboolean knot_open_at_begin=GL_FALSE,knot_open_at_end=GL_FALSE;
  90.     GLsizei i,j,k;
  91.     GLfloat tmp_float;
  92.  
  93.     if(the_knot->unified_knot)
  94.     {
  95.         knot=the_knot->unified_knot;
  96.         nknots=the_knot->unified_nknots;
  97.     }
  98.     else
  99.     {
  100.         knot=the_knot->knot;
  101.         nknots=the_knot->nknots;
  102.     }
  103.     ord=the_knot->order;
  104.     t_min=the_knot->t_min;
  105.     t_max=the_knot->t_max;
  106.  
  107.     if(the_knot->open_at_begin)
  108.     {
  109.         /* knot open at beggining */
  110.         knot_open_at_begin=GL_TRUE;
  111.         ++t_min;
  112.     }
  113.     if(the_knot->open_at_end)
  114.     {
  115.         /* knot open at end */
  116.         knot_open_at_end=GL_TRUE;
  117.         --t_max;
  118.     }
  119.     for(i=t_min;i<=t_max;)
  120.     {
  121.         tmp_float=knot[i];
  122.         for(j=0;j<ord && (i+j)<=t_max;j++)
  123.             if(fabs(tmp_float-knot[i+j])>EPSILON)
  124.                 break;
  125.         n_new_knots+=ord-j;
  126.         i+=j;
  127.     }
  128.     /* alloc space for new_knot */
  129.     if((new_knot=(GLfloat *)malloc(sizeof(GLfloat)*(nknots+n_new_knots)))==NULL)
  130.     {
  131.         return GLU_OUT_OF_MEMORY;
  132.     }
  133.     /* fill in new knot */
  134.     for(j=0;j<t_min;j++)
  135.         new_knot[j]=knot[j];
  136.     for(i=j;i<=t_max;i++)
  137.     {
  138.         tmp_float=knot[i];
  139.         for(k=0;k<ord;k++)
  140.         {
  141.             new_knot[j++]=knot[i];
  142.             if(tmp_float==knot[i+1])
  143.                 i++;
  144.         }
  145.     }
  146.     for(i=t_max+1;i<(int)nknots;i++)
  147.         new_knot[j++]=knot[i];
  148.     /* fill in the knot structure */
  149.     the_knot->new_knot=new_knot;
  150.     the_knot->delta_nknots+=n_new_knots;
  151.     return GLU_NO_ERROR;
  152. }
  153.  
  154. GLenum
  155. calc_alphas(knot_str_type *the_knot)
  156. {
  157.     GLfloat tmp_float;
  158.     int i,j,k,m,n;
  159.     int order;
  160.     GLfloat *alpha,*alpha_new,*tmp_alpha;
  161.     GLfloat denom;
  162.     GLfloat *knot,*new_knot;
  163.  
  164.  
  165.     knot=the_knot->knot;
  166.     order=the_knot->order;
  167.     new_knot=the_knot->new_knot;
  168.     n=the_knot->nknots-the_knot->order;
  169.     m=n+the_knot->delta_nknots;
  170.     if((alpha=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
  171.     {
  172.         return GLU_OUT_OF_MEMORY;
  173.     }
  174.     if((alpha_new=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
  175.     {
  176.         free(alpha);
  177.         return GLU_OUT_OF_MEMORY;
  178.     }
  179.     for(j=0;j<m;j++)
  180.     {
  181.         for(i=0;i<n;i++)
  182.         {
  183.             if((knot[i] <= new_knot[j]) && (new_knot[j] < knot[i+1]))
  184.                 tmp_float=1.0;
  185.             else
  186.                 tmp_float=0.0;
  187.             alpha[i+j*n]=tmp_float;
  188.         }
  189.     }
  190.     for(k=1;k<order;k++)
  191.     {
  192.         for(j=0;j<m;j++)
  193.             for(i=0;i<n;i++)
  194.             {
  195.                 denom=knot[i+k]-knot[i];
  196.                 if(fabs(denom)<EPSILON)
  197.                     tmp_float=0.0;
  198.                 else
  199.                     tmp_float=(new_knot[j+k]-knot[i])/denom*
  200.                         alpha[i+j*n];
  201.                 denom=knot[i+k+1]-knot[i+1];
  202.                 if(fabs(denom)>EPSILON)
  203.                     tmp_float+=(knot[i+k+1]-new_knot[j+k])/denom*
  204.                         alpha[(i+1)+j*n];
  205.                 alpha_new[i+j*n]=tmp_float;
  206.             }
  207.         tmp_alpha=alpha_new;
  208.         alpha_new=alpha;
  209.         alpha=tmp_alpha;
  210.     }
  211.     the_knot->alpha=alpha;
  212.     free(alpha_new);
  213.     return GLU_NO_ERROR;
  214. }
  215.  
  216. GLenum
  217. calc_new_ctrl_pts(GLfloat *ctrl,GLint stride,knot_str_type *the_knot,
  218.     GLint dim,GLfloat **new_ctrl,GLint *ncontrol)
  219. {
  220.     GLsizei i,j,k,l,m,n;
  221.     GLsizei index1,index2;
  222.     GLfloat *alpha;
  223.     GLfloat *new_knot;
  224.  
  225.     new_knot=the_knot->new_knot;
  226.     n=the_knot->nknots-the_knot->order;
  227.     m=n+the_knot->delta_nknots;
  228.     alpha=the_knot->alpha;
  229.     if(the_knot->open_at_begin==GL_TRUE)
  230.     {
  231.         k=0;
  232.     }
  233.     else
  234.     {
  235.         k=the_knot->order-1;
  236.         m-=k;
  237.     }
  238.     /* is knot open at end? */
  239.     if(the_knot->open_at_end==GL_FALSE)
  240.         m-=the_knot->order-1;
  241.     /* allocate space for new control points */
  242.     if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*dim*m))==NULL)
  243.     {
  244.         return GLU_OUT_OF_MEMORY;
  245.     }
  246.     for(j=0;j<m;j++)
  247.     {
  248.         for(l=0;l<dim;l++)
  249.             (*new_ctrl)[j*dim+l]=0.0;
  250.         for(i=0;i<n;i++)
  251.         {
  252.             index1=i+(j+k)*n;
  253.             index2=i*stride;
  254.             for(l=0;l<dim;l++)
  255.                 (*new_ctrl)[j*dim+l]+=alpha[index1]*ctrl[index2+l];
  256.         }
  257.     }
  258.     *ncontrol=(GLint)m;
  259.     return GLU_NO_ERROR;
  260. }
  261.  
  262. static GLint
  263. calc_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,GLfloat tolerance,
  264.     GLint dim)
  265. {
  266.     GLdouble model[16],proj[16];
  267.     GLint viewport[4];
  268.     GLdouble x,y,z,w,winx1,winy1,winz,winx2,winy2;
  269.     GLint i;
  270.     GLdouble len,dx,dy;
  271.  
  272.     glGetDoublev(GL_MODELVIEW_MATRIX,model);
  273.     glGetDoublev(GL_PROJECTION_MATRIX,proj);
  274.     glGetIntegerv(GL_VIEWPORT,viewport);
  275.     if(dim==3)
  276.     {
  277.         x=(GLdouble)pts[indx];
  278.         y=(GLdouble)pts[indx+1];
  279.         z=(GLdouble)pts[indx+2];
  280.         gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
  281.         len=0.0;
  282.         for(i=1;i<order;i++)
  283.         {
  284.             x=(GLdouble)pts[indx+i*stride];
  285.             y=(GLdouble)pts[indx+i*stride+1];
  286.             z=(GLdouble)pts[indx+i*stride+2];
  287.             if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
  288.             {
  289.                 dx=winx2-winx1;
  290.                 dy=winy2-winy1;
  291.                 len+=sqrt(dx*dx+dy*dy);
  292.             }
  293.             winx1=winx2; winy1=winy2;
  294.         }
  295.     }
  296.     else
  297.     {
  298.         w=(GLdouble)pts[indx+3];
  299.         x=(GLdouble)pts[indx]/w;
  300.         y=(GLdouble)pts[indx+1]/w;
  301.         z=(GLdouble)pts[indx+2]/w;
  302.         gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
  303.         len=0.0;
  304.         for(i=1;i<order;i++)
  305.         {
  306.             w=(GLdouble)pts[indx+i*stride+3];
  307.             x=(GLdouble)pts[indx+i*stride]/w;
  308.             y=(GLdouble)pts[indx+i*stride+1]/w;
  309.             z=(GLdouble)pts[indx+i*stride+2]/w;
  310.             if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
  311.             {
  312.                 dx=winx2-winx1;
  313.                 dy=winy2-winy1;
  314.                 len+=sqrt(dx*dx+dy*dy);
  315.             }
  316.             winx1=winx2; winy1=winy2;
  317.         }
  318.     }
  319.     len /= tolerance;
  320.     return (GLint)len;
  321. }
  322.  
  323. static GLenum
  324. calc_sampling_3D(GLfloat *ctrl, GLint ucnt, GLint vcnt, GLint uorder, GLint vorder,
  325.     GLfloat tolerance, GLint dim, GLint **ufactors, GLint **vfactors)
  326. {
  327.     GLint        ufactor_cnt,vfactor_cnt;
  328.     GLint        tmp_factor,max_factor;
  329.     GLint        offset1,offset2;
  330.     GLint        i,j;
  331.  
  332.     ufactor_cnt=ucnt/uorder;
  333.     vfactor_cnt=vcnt/vorder;
  334.     if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt))==NULL)
  335.     {
  336.         return GLU_OUT_OF_MEMORY;
  337.     }
  338.     if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt))==NULL)
  339.     {
  340.         free(ufactors);
  341.         return GLU_OUT_OF_MEMORY;
  342.     }
  343.     offset1=vorder*dim;
  344.     offset2=vcnt*dim;
  345.     for(j=0;j<vfactor_cnt;j++)
  346.     {
  347.         for(i=0 , max_factor=1;i<ucnt;i++)
  348.         {
  349.             tmp_factor=calc_factor(ctrl,vorder,j*offset1+i*offset2,
  350.                 dim,tolerance,dim);
  351.             if(tmp_factor>max_factor)
  352.                 max_factor=tmp_factor;
  353.         }
  354.         (*vfactors)[j]=max_factor;
  355.     }
  356.     offset1=offset2;
  357.     offset2*=uorder;
  358.     for(j=0;j<ufactor_cnt;j++)
  359.     {
  360.         for(i=0 , max_factor=1;i<vcnt;i++)
  361.         {
  362.             tmp_factor=calc_factor(ctrl,uorder,j*offset2+i*dim,
  363.                 offset1,tolerance,dim);
  364.             if(tmp_factor>max_factor)
  365.                 max_factor=tmp_factor;
  366.         }
  367.         (*ufactors)[j]=max_factor;
  368.     }
  369.     return GL_NO_ERROR;
  370. }
  371.  
  372. static GLenum
  373. calc_sampling_2D(GLfloat *ctrl, GLint cnt, GLint order,
  374.     GLfloat tolerance, GLint dim, GLint **factors)
  375. {
  376.     GLint        factor_cnt;
  377.     GLint        tmp_factor;
  378.     GLint        offset;
  379.     GLint        i;
  380.  
  381.     factor_cnt=cnt/order;
  382.     if((*factors=(GLint *)malloc(sizeof(GLint)*factor_cnt))==NULL)
  383.     {
  384.         return GLU_OUT_OF_MEMORY;
  385.     }
  386.     offset=order*dim;
  387.     for(i=0;i<factor_cnt;i++)
  388.     {
  389.         tmp_factor=calc_factor(ctrl,order,i*offset,dim,tolerance,dim);
  390.         if(tmp_factor == 0)
  391.             (*factors)[i]=1;
  392.         else
  393.             (*factors)[i]=tmp_factor;
  394.     }
  395.     return GL_NO_ERROR;
  396. }
  397.  
  398. static void
  399. set_sampling_and_culling( GLUnurbsObj *nobj )
  400. {
  401.     if(nobj->auto_load_matrix==GL_FALSE)
  402.     {
  403.         GLint i;
  404.         GLfloat m[4];
  405.  
  406.         glPushAttrib(GL_VIEWPORT_BIT | GL_TRANSFORM_BIT);
  407.         for(i=0;i<4;i++)
  408.             m[i]=nobj->sampling_matrices.viewport[i];
  409.         glViewport(m[0],m[1],m[2],m[3]);
  410.         glMatrixMode(GL_PROJECTION);
  411.         glPushMatrix();
  412.         glLoadMatrixf(nobj->sampling_matrices.proj);
  413.         glMatrixMode(GL_MODELVIEW);
  414.         glPushMatrix();
  415.         glLoadMatrixf(nobj->sampling_matrices.model);
  416.     }
  417. }
  418.  
  419. static void
  420. revert_sampling_and_culling( GLUnurbsObj *nobj )
  421. {
  422.     if(nobj->auto_load_matrix==GL_FALSE)
  423.     {
  424.         glMatrixMode(GL_MODELVIEW);
  425.         glPopMatrix();
  426.         glMatrixMode(GL_PROJECTION);
  427.         glPopMatrix();
  428.         glPopAttrib();
  429.     }
  430. }
  431.  
  432. GLenum
  433. glu_do_sampling_3D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint scnt, GLint tcnt,
  434.     GLint **sfactors, GLint **tfactors)
  435. {
  436.     GLint  dim;
  437.     GLenum err;
  438.  
  439.     *sfactors=NULL;
  440.     *tfactors=NULL;
  441.     dim=nobj->surface.geom.dim;
  442.     set_sampling_and_culling(nobj);
  443.     if((err=calc_sampling_3D(ctrl,scnt,tcnt,nobj->surface.geom.sorder,
  444.         nobj->surface.geom.torder,nobj->sampling_tolerance,dim,
  445.         sfactors,tfactors))==GLU_ERROR)
  446.     {
  447.         revert_sampling_and_culling(nobj);
  448.         call_user_error(nobj,err);
  449.         return GLU_ERROR;
  450.     }
  451.     revert_sampling_and_culling(nobj);
  452.     return GLU_NO_ERROR;
  453. }
  454.  
  455. GLenum
  456. glu_do_sampling_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
  457.     GLint dim, GLint **factors)
  458. {
  459.     GLenum err;
  460.  
  461.     *factors=NULL;
  462.     set_sampling_and_culling(nobj);
  463.     if((err=calc_sampling_2D(ctrl,cnt,order,nobj->sampling_tolerance,dim,
  464.         factors))==GLU_ERROR)
  465.     {
  466.         revert_sampling_and_culling(nobj);
  467.         call_user_error(nobj,err);
  468.         return GLU_ERROR;
  469.     }
  470.     revert_sampling_and_culling(nobj);
  471.     return GLU_NO_ERROR;
  472. }
  473.  
  474. /* TODO - i don't like this culling - this one just tests if at least one */
  475. /* ctrl point lies within the viewport . Also the point_in_viewport() */
  476. /* should be included in the fnctions for efficiency reasons */
  477.  
  478. static GLboolean
  479. point_in_viewport(GLfloat *pt, GLint dim)
  480. {
  481.     GLdouble model[16],proj[16];
  482.     GLint viewport[4];
  483.     GLdouble x,y,z,w,winx,winy,winz;
  484.  
  485.     glGetDoublev(GL_MODELVIEW_MATRIX,model);
  486.     glGetDoublev(GL_PROJECTION_MATRIX,proj);
  487.     glGetIntegerv(GL_VIEWPORT,viewport);
  488.     if(dim==3)
  489.     {
  490.         x=(GLdouble)pt[0];
  491.         y=(GLdouble)pt[1];
  492.         z=(GLdouble)pt[2];
  493.         gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
  494.     }
  495.     else
  496.     {
  497.         w=(GLdouble)pt[3];
  498.         x=(GLdouble)pt[0]/w;
  499.         y=(GLdouble)pt[1]/w;
  500.         z=(GLdouble)pt[2]/w;
  501.         gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
  502.     }
  503.     if((GLint)winx >= viewport[0] && (GLint)winx < viewport[2] &&
  504.             (GLint)winy >= viewport[1] && (GLint)winy < viewport[3])
  505.         return GL_TRUE;
  506.     return GL_FALSE;
  507. }
  508.  
  509. GLboolean
  510. fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
  511.     GLint s_stride,GLint t_stride, GLint dim)
  512. {
  513.     GLint     i,j;
  514.  
  515.     if(nobj->culling==GL_FALSE)
  516.         return GL_FALSE;
  517.     set_sampling_and_culling(nobj);
  518.     
  519.     if(dim==3)
  520.     {
  521.         for(i=0;i<s_cnt;i++)
  522.             for(j=0;j<t_cnt;j++)
  523.                 if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
  524.                 {
  525.                     revert_sampling_and_culling(nobj);
  526.                     return GL_FALSE;
  527.                 }
  528.     }
  529.     else
  530.     {
  531.         for(i=0;i<s_cnt;i++)
  532.             for(j=0;j<t_cnt;j++)
  533.                 if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
  534.                 {
  535.                     revert_sampling_and_culling(nobj);
  536.                     return GL_FALSE;
  537.                 }
  538.     }
  539.     revert_sampling_and_culling(nobj);
  540.     return GL_TRUE;
  541. }
  542.  
  543. /*GLboolean
  544. fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
  545.     GLint s_stride,GLint t_stride, GLint dim)
  546. {
  547.     GLint        visible_cnt;
  548.     GLfloat        feedback_buffer[5];
  549.     GLsizei        buffer_size;
  550.     GLint         i,j;
  551.  
  552.     if(nobj->culling==GL_FALSE)
  553.         return GL_FALSE;
  554.     buffer_size=5;
  555.     set_sampling_and_culling(nobj);
  556.     
  557.     glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
  558.     glRenderMode(GL_FEEDBACK);
  559.     if(dim==3)
  560.     {
  561.         for(i=0;i<s_cnt;i++)
  562.         {
  563.             glBegin(GL_LINE_LOOP);
  564.             for(j=0;j<t_cnt;j++)
  565.                 glVertex3fv(pts+i*s_stride+j*t_stride);
  566.             glEnd();
  567.         }
  568.         for(j=0;j<t_cnt;j++)
  569.         {
  570.             glBegin(GL_LINE_LOOP);
  571.             for(i=0;i<s_cnt;i++)
  572.                 glVertex3fv(pts+i*s_stride+j*t_stride);
  573.             glEnd();
  574.         }
  575.     }
  576.     else
  577.     {
  578.         for(i=0;i<s_cnt;i++)
  579.         {
  580.             glBegin(GL_LINE_LOOP);
  581.             for(j=0;j<t_cnt;j++)
  582.                 glVertex4fv(pts+i*s_stride+j*t_stride);
  583.             glEnd();
  584.         }
  585.         for(j=0;j<t_cnt;j++)
  586.         {
  587.             glBegin(GL_LINE_LOOP);
  588.             for(i=0;i<s_cnt;i++)
  589.                 glVertex4fv(pts+i*s_stride+j*t_stride);
  590.             glEnd();
  591.         }
  592.     }
  593.     visible_cnt=glRenderMode(GL_RENDER);
  594.  
  595.     revert_sampling_and_culling(nobj);
  596.     return (GLboolean)(visible_cnt==0);
  597. }*/
  598.  
  599. GLboolean
  600. fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
  601.     GLint stride, GLint dim)
  602. {
  603.     GLint     i;
  604.  
  605.     if(nobj->culling==GL_FALSE)
  606.         return GL_FALSE;
  607.     set_sampling_and_culling(nobj);
  608.     
  609.     if(dim==3)
  610.     {
  611.         for(i=0;i<cnt;i++)
  612.             if(point_in_viewport(pts+i*stride,dim))
  613.             {
  614.                 revert_sampling_and_culling(nobj);
  615.                 return GL_FALSE;
  616.             }
  617.     }
  618.     else
  619.     {
  620.         for(i=0;i<cnt;i++)
  621.             if(point_in_viewport(pts+i*stride,dim))
  622.             {
  623.                 revert_sampling_and_culling(nobj);
  624.                 return GL_FALSE;
  625.             }
  626.     }
  627.     revert_sampling_and_culling(nobj);
  628.     return GL_TRUE;
  629. }
  630.  
  631. /*GLboolean
  632. fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
  633.     GLint stride, GLint dim)
  634. {
  635.     GLint        visible_cnt;
  636.     GLfloat        feedback_buffer[5];
  637.     GLsizei        buffer_size;
  638.     GLint         i;
  639.  
  640.     if(nobj->culling==GL_FALSE)
  641.         return GL_FALSE;
  642.     buffer_size=5;
  643.     set_sampling_and_culling(nobj);
  644.     
  645.     glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
  646.     glRenderMode(GL_FEEDBACK);
  647.     glBegin(GL_LINE_LOOP);
  648.     if(dim==3)
  649.     {
  650.         for(i=0;i<cnt;i++)
  651.             glVertex3fv(pts+i*stride);
  652.     }
  653.     else
  654.     {
  655.         for(i=0;i<cnt;i++)
  656.             glVertex4fv(pts+i*stride);
  657.     }
  658.     glEnd();
  659.     visible_cnt=glRenderMode(GL_RENDER);
  660.  
  661.     revert_sampling_and_culling(nobj);
  662.     return (GLboolean)(visible_cnt==0);
  663. }*/
  664.  
  665.