home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src-glu / nurbsutl.c < prev    next >
C/C++ Source or Header  |  1999-08-18  |  35KB  |  1,404 lines

  1. /* $Id: nurbsutl.c,v 1.1.1.1 1999/08/19 00:55:42 jtg Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1997  Brian Paul
  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.  * $Log: nurbsutl.c,v $
  26.  * Revision 1.1.1.1  1999/08/19 00:55:42  jtg
  27.  * Imported sources
  28.  *
  29.  * Revision 1.8  1999/06/08 00:44:51  brianp
  30.  * OpenStep updates (pete@ohm.york.ac.uk)
  31.  *
  32.  * Revision 1.7  1998/07/26 02:07:59  brianp
  33.  * updated for Windows compilation per Ted Jump
  34.  *
  35.  * Revision 1.6  1997/10/29 02:02:20  brianp
  36.  * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
  37.  *
  38.  * Revision 1.5  1997/07/24 01:28:44  brianp
  39.  * changed precompiled header symbol from PCH to PC_HEADER
  40.  *
  41.  * Revision 1.4  1997/05/28 02:29:38  brianp
  42.  * added support for precompiled headers (PCH), inserted APIENTRY keyword
  43.  *
  44.  * Revision 1.3  1997/05/27 03:19:54  brianp
  45.  * minor clean-up
  46.  *
  47.  * Revision 1.2  1997/05/27 03:00:16  brianp
  48.  * incorporated Bogdan's new NURBS code
  49.  *
  50.  * Revision 1.1  1996/09/27 01:19:39  brianp
  51.  * Initial revision
  52.  *
  53.  */
  54.  
  55.  
  56. /*
  57.  * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
  58.  * See README2 for more info.
  59.  */
  60.  
  61.  
  62. #ifdef PC_HEADER
  63. #include "all.h"
  64. #else
  65. #include <math.h>
  66. #include <stdlib.h>
  67. #include "gluP.h"
  68. #include "nurbs.h"
  69. #endif
  70.  
  71.  
  72. GLenum
  73. test_knot(GLint nknots, GLfloat *knot, GLint order)
  74. {
  75.     GLsizei i;
  76.     GLint knot_mult;
  77.     GLfloat tmp_knot;
  78.  
  79.     tmp_knot=knot[0];
  80.     knot_mult=1;
  81.     for(i=1;i<nknots;i++)
  82.     {
  83.         if(knot[i] < tmp_knot)
  84.             return GLU_NURBS_ERROR4;
  85.         if(fabs(tmp_knot-knot[i]) > EPSILON)
  86.         {
  87.             if(knot_mult>order)
  88.                 return GLU_NURBS_ERROR5;
  89.             knot_mult=1;
  90.             tmp_knot=knot[i];
  91.         }
  92.         else
  93.             ++knot_mult;
  94.     }
  95.     return GLU_NO_ERROR;
  96. }
  97.  
  98. static int
  99. /* qsort function */
  100. #if defined(WIN32) && !defined(OPENSTEP)
  101. __cdecl
  102. #endif
  103. knot_sort(const void *a, const void *b)
  104. {
  105.     GLfloat x,y;
  106.  
  107.     x=*((GLfloat *)a);
  108.     y=*((GLfloat *)b);
  109.     if(fabs(x-y) < EPSILON)
  110.         return 0;
  111.     if(x > y)
  112.         return 1;
  113.     return -1;
  114. }
  115.  
  116. /* insert into dest knot all values within the valid range from src knot */
  117. /* that do not appear in dest */
  118. void
  119. collect_unified_knot(knot_str_type *dest, knot_str_type *src,
  120.     GLfloat maximal_min_knot, GLfloat minimal_max_knot)
  121. {
  122.     GLfloat *src_knot,*dest_knot;
  123.     GLint src_t_min,src_t_max,dest_t_min,dest_t_max;
  124.     GLint src_nknots,dest_nknots;
  125.     GLint i,j,k,new_cnt;
  126.     GLboolean    not_found_flag;
  127.  
  128.     src_knot=src->unified_knot;
  129.     dest_knot=dest->unified_knot;
  130.     src_t_min=src->t_min;
  131.     src_t_max=src->t_max;
  132.     dest_t_min=dest->t_min;
  133.     dest_t_max=dest->t_max;
  134.     src_nknots=src->unified_nknots;
  135.     dest_nknots=dest->unified_nknots;
  136.  
  137.     k=new_cnt=dest_nknots;
  138.     for(i=src_t_min;i<=src_t_max;i++)
  139.         if(src_knot[i] - maximal_min_knot > -EPSILON &&
  140.         src_knot[i] - minimal_max_knot < EPSILON)
  141.     {
  142.         not_found_flag=GL_TRUE;
  143.         for(j=dest_t_min;j<=dest_t_max;j++)
  144.             if(fabs(dest_knot[j]-src_knot[i]) < EPSILON)
  145.             {
  146.                 not_found_flag=GL_FALSE;
  147.                 break;
  148.             }
  149.         if(not_found_flag)
  150.         {
  151.             /* knot from src is not in dest - add this knot to dest */
  152.             dest_knot[k++]=src_knot[i];
  153.             ++new_cnt;
  154.             ++(dest->t_max); /* the valid range widens */
  155.             ++(dest->delta_nknots); /* increment the extra knot value counter */
  156.         }
  157.     }
  158.     dest->unified_nknots=new_cnt;
  159.     qsort((void *)dest_knot,(size_t)new_cnt,(size_t)sizeof(GLfloat),
  160.         &knot_sort);
  161. }
  162.  
  163. /* basing on the new common knot range for all attributes set */
  164. /* t_min and t_max values for each knot - they will be used later on */
  165. /* by explode_knot() and calc_new_ctrl_pts */
  166. static void
  167. set_new_t_min_t_max(knot_str_type *geom_knot, knot_str_type *color_knot,
  168.     knot_str_type *normal_knot, knot_str_type *texture_knot,
  169.     GLfloat maximal_min_knot, GLfloat minimal_max_knot)
  170. {
  171.     GLuint    t_min,t_max,cnt;
  172.  
  173.     if(minimal_max_knot-maximal_min_knot < EPSILON)
  174.     {
  175.         /* knot common range empty */
  176.         geom_knot->t_min=geom_knot->t_max=0;
  177.         color_knot->t_min=color_knot->t_max=0;
  178.         normal_knot->t_min=normal_knot->t_max=0;
  179.         texture_knot->t_min=texture_knot->t_max=0;
  180.     }
  181.     else
  182.     {
  183.         if(geom_knot->unified_knot!=NULL)
  184.         {
  185.             cnt=geom_knot->unified_nknots;
  186.             for(t_min=0;t_min<cnt;t_min++)
  187.                 if(fabs((geom_knot->unified_knot)[t_min] - maximal_min_knot) <
  188.                         EPSILON)
  189.                     break;
  190.             for(t_max=cnt-1;t_max;t_max--)
  191.                 if(fabs((geom_knot->unified_knot)[t_max] - minimal_max_knot) < 
  192.                         EPSILON)
  193.                     break;
  194.         }
  195.         else
  196.         if(geom_knot->nknots)
  197.         {
  198.             cnt=geom_knot->nknots;
  199.             for(t_min=0;t_min<cnt;t_min++)
  200.                 if(fabs((geom_knot->knot)[t_min] - maximal_min_knot) < EPSILON)
  201.                     break;
  202.             for(t_max=cnt-1;t_max;t_max--)
  203.                 if(fabs((geom_knot->knot)[t_max] - minimal_max_knot) < EPSILON)
  204.                     break;
  205.         }
  206.         geom_knot->t_min=t_min;
  207.         geom_knot->t_max=t_max;
  208.         if(color_knot->unified_knot!=NULL)
  209.         {
  210.             cnt=color_knot->unified_nknots;
  211.             for(t_min=0;t_min<cnt;t_min++)
  212.                 if(fabs((color_knot->unified_knot)[t_min] - maximal_min_knot) <
  213.                         EPSILON)
  214.                     break;
  215.             for(t_max=cnt-1;t_max;t_max--)
  216.                 if(fabs((color_knot->unified_knot)[t_max] - minimal_max_knot) < 
  217.                         EPSILON)
  218.                     break;
  219.             color_knot->t_min=t_min;
  220.             color_knot->t_max=t_max;
  221.         }
  222.         if(normal_knot->unified_knot!=NULL)
  223.         {
  224.             cnt=normal_knot->unified_nknots;
  225.             for(t_min=0;t_min<cnt;t_min++)
  226.                 if(fabs((normal_knot->unified_knot)[t_min] - maximal_min_knot) <
  227.                         EPSILON)
  228.                     break;
  229.             for(t_max=cnt-1;t_max;t_max--)
  230.                 if(fabs((normal_knot->unified_knot)[t_max] - minimal_max_knot) < 
  231.                         EPSILON)
  232.                     break;
  233.             normal_knot->t_min=t_min;
  234.             normal_knot->t_max=t_max;
  235.         }
  236.         if(texture_knot->unified_knot!=NULL)
  237.         {
  238.             cnt=texture_knot->unified_nknots;
  239.             for(t_min=0;t_min<cnt;t_min++)
  240.                 if(fabs((texture_knot->unified_knot)[t_min] - maximal_min_knot) 
  241.                         < EPSILON)
  242.                     break;
  243.             for(t_max=cnt-1;t_max;t_max--)
  244.                 if(fabs((texture_knot->unified_knot)[t_max] - minimal_max_knot) 
  245.                         < EPSILON)
  246.                     break;
  247.             texture_knot->t_min=t_min;
  248.             texture_knot->t_max=t_max;
  249.         }
  250.     }
  251. }
  252.  
  253. /* modify all knot valid ranges in such a way that all have the same */
  254. /* range, common to all knots */
  255. /* do this by knot insertion */
  256. GLenum
  257. select_knot_working_range(GLUnurbsObj *nobj,knot_str_type *geom_knot,
  258.     knot_str_type *color_knot, knot_str_type *normal_knot,
  259.     knot_str_type *texture_knot)
  260. {
  261.     GLint max_nknots;
  262.     GLfloat maximal_min_knot,minimal_max_knot;
  263.     GLint i;
  264.  
  265.     /* find the maximum modified knot length */
  266.     max_nknots=geom_knot->nknots;
  267.     if(color_knot->unified_knot)
  268.         max_nknots+=color_knot->nknots;
  269.     if(normal_knot->unified_knot)
  270.         max_nknots+=normal_knot->nknots;
  271.     if(texture_knot->unified_knot)
  272.         max_nknots+=texture_knot->nknots;
  273.     maximal_min_knot=(geom_knot->knot)[geom_knot->t_min];
  274.     minimal_max_knot=(geom_knot->knot)[geom_knot->t_max];
  275.     /* any attirb data ? */
  276.     if(max_nknots!=geom_knot->nknots)
  277.     {
  278.         /* allocate space for the unified knots */
  279.         if((geom_knot->unified_knot=
  280.                 (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  281.         {
  282.             call_user_error(nobj,GLU_OUT_OF_MEMORY);
  283.             return GLU_ERROR;
  284.         }
  285.         /* copy the original knot to the unified one */
  286.         geom_knot->unified_nknots=geom_knot->nknots;
  287.         for(i=0;i<geom_knot->nknots;i++)
  288.             (geom_knot->unified_knot)[i]=(geom_knot->knot)[i];
  289.         if(color_knot->unified_knot)
  290.         {
  291.             if((color_knot->knot)[color_knot->t_min] - maximal_min_knot >
  292.                     EPSILON)
  293.                 maximal_min_knot=(color_knot->knot)[color_knot->t_min];
  294.             if(minimal_max_knot - (color_knot->knot)[color_knot->t_max] >
  295.                     EPSILON)
  296.                 minimal_max_knot=(color_knot->knot)[color_knot->t_max];
  297.             if((color_knot->unified_knot=
  298.                     (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  299.             {
  300.                 free(geom_knot->unified_knot);
  301.                 call_user_error(nobj,GLU_OUT_OF_MEMORY);
  302.                 return GLU_ERROR;
  303.             }
  304.             /* copy the original knot to the unified one */
  305.             color_knot->unified_nknots=color_knot->nknots;
  306.             for(i=0;i<color_knot->nknots;i++)
  307.                 (color_knot->unified_knot)[i]=(color_knot->knot)[i];
  308.         }
  309.         if(normal_knot->unified_knot)
  310.         {
  311.             if((normal_knot->knot)[normal_knot->t_min] - maximal_min_knot >
  312.                     EPSILON)
  313.                 maximal_min_knot=(normal_knot->knot)[normal_knot->t_min];
  314.             if(minimal_max_knot - (normal_knot->knot)[normal_knot->t_max] >
  315.                     EPSILON)
  316.                 minimal_max_knot=(normal_knot->knot)[normal_knot->t_max];
  317.             if((normal_knot->unified_knot=
  318.                     (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  319.             {
  320.                 free(geom_knot->unified_knot);
  321.                 free(color_knot->unified_knot);
  322.                 call_user_error(nobj,GLU_OUT_OF_MEMORY);
  323.                 return GLU_ERROR;
  324.             }
  325.             /* copy the original knot to the unified one */
  326.             normal_knot->unified_nknots=normal_knot->nknots;
  327.             for(i=0;i<normal_knot->nknots;i++)
  328.                 (normal_knot->unified_knot)[i]=(normal_knot->knot)[i];
  329.         }
  330.         if(texture_knot->unified_knot)
  331.         {
  332.             if((texture_knot->knot)[texture_knot->t_min] - maximal_min_knot >
  333.                     EPSILON)
  334.                 maximal_min_knot=(texture_knot->knot)[texture_knot->t_min];
  335.             if(minimal_max_knot - (texture_knot->knot)[texture_knot->t_max] >
  336.                     EPSILON)
  337.                 minimal_max_knot=(texture_knot->knot)[texture_knot->t_max];
  338.             if((texture_knot->unified_knot=
  339.                     (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  340.             {
  341.                 free(geom_knot->unified_knot);
  342.                 free(color_knot->unified_knot);
  343.                 free(normal_knot->unified_knot);
  344.                 call_user_error(nobj,GLU_OUT_OF_MEMORY);
  345.                 return GLU_ERROR;
  346.             }
  347.             /* copy the original knot to the unified one */
  348.             texture_knot->unified_nknots=texture_knot->nknots;
  349.             for(i=0;i<texture_knot->nknots;i++)
  350.                 (texture_knot->unified_knot)[i]=(texture_knot->knot)[i];
  351.         }
  352.         /* work on the geometry knot with all additional knot values */
  353.         /* appearing in attirbutive knots */
  354.         if(minimal_max_knot-maximal_min_knot < EPSILON)
  355.         {
  356.             /* empty working range */
  357.             geom_knot->unified_nknots=0;
  358.             color_knot->unified_nknots=0;
  359.             normal_knot->unified_nknots=0;
  360.             texture_knot->unified_nknots=0;
  361.         }
  362.         else
  363.         {
  364.             if(color_knot->unified_knot)
  365.                 collect_unified_knot(geom_knot,color_knot,maximal_min_knot,
  366.                     minimal_max_knot);
  367.             if(normal_knot->unified_knot)
  368.                 collect_unified_knot(geom_knot,normal_knot,maximal_min_knot,
  369.                     minimal_max_knot);
  370.             if(texture_knot->unified_knot)
  371.                 collect_unified_knot(geom_knot,texture_knot,maximal_min_knot,
  372.                     minimal_max_knot);
  373.             /* since we have now built the "unified" geometry knot */
  374.             /* add same knot values to all attributive knots */
  375.             if(color_knot->unified_knot)
  376.                 collect_unified_knot(color_knot,geom_knot,maximal_min_knot,
  377.                     minimal_max_knot);
  378.             if(normal_knot->unified_knot)
  379.                 collect_unified_knot(normal_knot,geom_knot,maximal_min_knot,
  380.                     minimal_max_knot);
  381.             if(texture_knot->unified_knot)
  382.                 collect_unified_knot(texture_knot,geom_knot,maximal_min_knot,
  383.                     minimal_max_knot);
  384.         }
  385.     }
  386.     set_new_t_min_t_max(geom_knot,color_knot,normal_knot,texture_knot,
  387.         maximal_min_knot,minimal_max_knot);
  388.     return GLU_NO_ERROR;
  389. }
  390.  
  391. void
  392. free_unified_knots(knot_str_type *geom_knot, knot_str_type *color_knot,
  393.     knot_str_type *normal_knot, knot_str_type *texture_knot)
  394. {
  395.     if(geom_knot->unified_knot)
  396.         free(geom_knot->unified_knot);
  397.     if(color_knot->unified_knot)
  398.         free(color_knot->unified_knot);
  399.     if(normal_knot->unified_knot)
  400.         free(normal_knot->unified_knot);
  401.     if(texture_knot->unified_knot)
  402.         free(texture_knot->unified_knot);
  403. }
  404.  
  405. GLenum
  406. explode_knot(knot_str_type *the_knot)
  407. {
  408.     GLfloat *knot,*new_knot;
  409.     GLint nknots,n_new_knots=0;
  410.     GLint t_min,t_max;
  411.     GLint ord;
  412.     GLsizei i,j,k;
  413.     GLfloat tmp_float;
  414.  
  415.     if(the_knot->unified_knot)
  416.     {
  417.         knot=the_knot->unified_knot;
  418.         nknots=the_knot->unified_nknots;
  419.     }
  420.     else
  421.     {
  422.         knot=the_knot->knot;
  423.         nknots=the_knot->nknots;
  424.     }
  425.     ord=the_knot->order;
  426.     t_min=the_knot->t_min;
  427.     t_max=the_knot->t_max;
  428.  
  429.     for(i=t_min;i<=t_max;)
  430.     {
  431.         tmp_float=knot[i];
  432.         for(j=0;j<ord && (i+j)<=t_max;j++)
  433.             if(fabs(tmp_float-knot[i+j])>EPSILON)
  434.                 break;
  435.         n_new_knots+=ord-j;
  436.         i+=j;
  437.     }
  438.     /* alloc space for new_knot */
  439.     if((new_knot=(GLfloat *)malloc(sizeof(GLfloat)*(nknots+n_new_knots)))==NULL)
  440.     {
  441.         return GLU_OUT_OF_MEMORY;
  442.     }
  443.     /* fill in new knot */
  444.     for(j=0;j<t_min;j++)
  445.         new_knot[j]=knot[j];
  446.     for(i=j;i<=t_max;i++)
  447.     {
  448.         tmp_float=knot[i];
  449.         for(k=0;k<ord;k++)
  450.         {
  451.             new_knot[j++]=knot[i];
  452.             if(tmp_float==knot[i+1])
  453.                 i++;
  454.         }
  455.     }
  456.     for(i=t_max+1;i<(int)nknots;i++)
  457.         new_knot[j++]=knot[i];
  458.     /* fill in the knot structure */
  459.     the_knot->new_knot=new_knot;
  460.     the_knot->delta_nknots+=n_new_knots;
  461.     the_knot->t_max+=n_new_knots;
  462.     return GLU_NO_ERROR;
  463. }
  464.  
  465. GLenum
  466. calc_alphas(knot_str_type *the_knot)
  467. {
  468.     GLfloat tmp_float;
  469.     int i,j,k,m,n;
  470.     int order;
  471.     GLfloat *alpha,*alpha_new,*tmp_alpha;
  472.     GLfloat denom;
  473.     GLfloat *knot,*new_knot;
  474.  
  475.  
  476.     knot=the_knot->knot;
  477.     order=the_knot->order;
  478.     new_knot=the_knot->new_knot;
  479.     n=the_knot->nknots-the_knot->order;
  480.     m=n+the_knot->delta_nknots;
  481.     if((alpha=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
  482.     {
  483.         return GLU_OUT_OF_MEMORY;
  484.     }
  485.     if((alpha_new=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
  486.     {
  487.         free(alpha);
  488.         return GLU_OUT_OF_MEMORY;
  489.     }
  490.     for(j=0;j<m;j++)
  491.     {
  492.         for(i=0;i<n;i++)
  493.         {
  494.             if((knot[i] <= new_knot[j]) && (new_knot[j] < knot[i+1]))
  495.                 tmp_float=1.0;
  496.             else
  497.                 tmp_float=0.0;
  498.             alpha[i+j*n]=tmp_float;
  499.         }
  500.     }
  501.     for(k=1;k<order;k++)
  502.     {
  503.         for(j=0;j<m;j++)
  504.             for(i=0;i<n;i++)
  505.             {
  506.                 denom=knot[i+k]-knot[i];
  507.                 if(fabs(denom)<EPSILON)
  508.                     tmp_float=0.0;
  509.                 else
  510.                     tmp_float=(new_knot[j+k]-knot[i])/denom*
  511.                         alpha[i+j*n];
  512.                 denom=knot[i+k+1]-knot[i+1];
  513.                 if(fabs(denom)>EPSILON)
  514.                     tmp_float+=(knot[i+k+1]-new_knot[j+k])/denom*
  515.                         alpha[(i+1)+j*n];
  516.                 alpha_new[i+j*n]=tmp_float;
  517.             }
  518.         tmp_alpha=alpha_new;
  519.         alpha_new=alpha;
  520.         alpha=tmp_alpha;
  521.     }
  522.     the_knot->alpha=alpha;
  523.     free(alpha_new);
  524.     return GLU_NO_ERROR;
  525. }
  526.  
  527. GLenum
  528. calc_new_ctrl_pts(GLfloat *ctrl,GLint stride,knot_str_type *the_knot,
  529.     GLint dim,GLfloat **new_ctrl,GLint *ncontrol)
  530. {
  531.     GLsizei i,j,k,l,m,n;
  532.     GLsizei index1,index2;
  533.     GLfloat *alpha;
  534.     GLfloat *new_knot;
  535.  
  536.     new_knot=the_knot->new_knot;
  537.     n=the_knot->nknots-the_knot->order;
  538.     alpha=the_knot->alpha;
  539.  
  540.     m=the_knot->t_max+1-the_knot->t_min-the_knot->order;
  541.     k=the_knot->t_min;
  542.     /* allocate space for new control points */
  543.     if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*dim*m))==NULL)
  544.     {
  545.         return GLU_OUT_OF_MEMORY;
  546.     }
  547.     for(j=0;j<m;j++)
  548.     {
  549.         for(l=0;l<dim;l++)
  550.             (*new_ctrl)[j*dim+l]=0.0;
  551.         for(i=0;i<n;i++)
  552.         {
  553.             index1=i+(j+k)*n;
  554.             index2=i*stride;
  555.             for(l=0;l<dim;l++)
  556.                 (*new_ctrl)[j*dim+l]+=alpha[index1]*ctrl[index2+l];
  557.         }
  558.     }
  559.     *ncontrol=(GLint)m;
  560.     return GLU_NO_ERROR;
  561. }
  562.  
  563. static GLint
  564. calc_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,GLfloat tolerance,
  565.     GLint dim)
  566. {
  567.     GLdouble model[16],proj[16];
  568.     GLint viewport[4];
  569.     GLdouble x,y,z,w,winx1,winy1,winz,winx2,winy2;
  570.     GLint i;
  571.     GLdouble len,dx,dy;
  572.  
  573.     glGetDoublev(GL_MODELVIEW_MATRIX,model);
  574.     glGetDoublev(GL_PROJECTION_MATRIX,proj);
  575.     glGetIntegerv(GL_VIEWPORT,viewport);
  576.     if(dim==4)
  577.     {
  578.         w=(GLdouble)pts[indx+3];
  579.         x=(GLdouble)pts[indx]/w;
  580.         y=(GLdouble)pts[indx+1]/w;
  581.         z=(GLdouble)pts[indx+2]/w;
  582.         gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
  583.         len=0.0;
  584.         for(i=1;i<order;i++)
  585.         {
  586.             w=(GLdouble)pts[indx+i*stride+3];
  587.             x=(GLdouble)pts[indx+i*stride]/w;
  588.             y=(GLdouble)pts[indx+i*stride+1]/w;
  589.             z=(GLdouble)pts[indx+i*stride+2]/w;
  590.             if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
  591.             {
  592.                 dx=winx2-winx1;
  593.                 dy=winy2-winy1;
  594.                 len+=sqrt(dx*dx+dy*dy);
  595.             }
  596.             winx1=winx2; winy1=winy2;
  597.         }
  598.     }
  599.     else
  600.     {
  601.         x=(GLdouble)pts[indx];
  602.         y=(GLdouble)pts[indx+1];
  603.         if(dim==2)
  604.             z=0.0;
  605.         else
  606.             z=(GLdouble)pts[indx+2];
  607.         gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
  608.         len=0.0;
  609.         for(i=1;i<order;i++)
  610.         {
  611.             x=(GLdouble)pts[indx+i*stride];
  612.             y=(GLdouble)pts[indx+i*stride+1];
  613.             if(dim==2)
  614.                 z=0.0;
  615.             else
  616.                 z=(GLdouble)pts[indx+i*stride+2];
  617.             if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
  618.             {
  619.                 dx=winx2-winx1;
  620.                 dy=winy2-winy1;
  621.                 len+=sqrt(dx*dx+dy*dy);
  622.             }
  623.             winx1=winx2; winy1=winy2;
  624.         }
  625.     }
  626.     len /= tolerance;
  627.     return ((GLint)len+1);
  628. }
  629.  
  630. /* we can't use the Mesa evaluators - no way to get the point coords */
  631. /* so we use our own Bezier point calculus routines */
  632. /* because I'm lazy, I reuse the ones from eval.c */
  633.  
  634. static void
  635. bezier_curve(GLfloat *cp, GLfloat *out, GLfloat t,
  636.     GLuint dim, GLuint order, GLint offset)
  637. {
  638.     GLfloat s, powert;
  639.     GLuint i, k, bincoeff;
  640.  
  641.     if(order >= 2)
  642.     { 
  643.         bincoeff = order-1;
  644.         s = 1.0-t;
  645.  
  646.         for(k=0; k<dim; k++)
  647.             out[k] = s*cp[k] + bincoeff*t*cp[offset+k];
  648.  
  649.         for(i=2, cp+=2*offset, powert=t*t; i<order; i++, powert*=t, cp +=offset)
  650.         {
  651.             bincoeff *= order-i;
  652.             bincoeff /= i;
  653.  
  654.             for(k=0; k<dim; k++)
  655.                 out[k] = s*out[k] + bincoeff*powert*cp[k];
  656.         }
  657.     }
  658.     else /* order=1 -> constant curve */
  659.     { 
  660.         for(k=0; k<dim; k++)
  661.             out[k] = cp[k];
  662.     } 
  663. }
  664.  
  665. static GLint
  666. calc_parametric_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,
  667.     GLfloat tolerance,GLint dim)
  668. {
  669.     GLdouble model[16],proj[16];
  670.     GLint viewport[4];
  671.     GLdouble x,y,z,w,x1,y1,z1,x2,y2,z2,x3,y3,z3;
  672.     GLint i;
  673.     GLint P;
  674.     GLfloat bez_pt[4];
  675.     GLdouble len=0.0,tmp,z_med;
  676.  
  677.     P = 2*(order+2);
  678.     glGetDoublev(GL_MODELVIEW_MATRIX,model);
  679.     glGetDoublev(GL_PROJECTION_MATRIX,proj);
  680.     glGetIntegerv(GL_VIEWPORT,viewport);
  681.     z_med = (viewport[2] + viewport[3]) * 0.5;
  682.     switch(dim)
  683.     {
  684.         case 4:
  685.             for(i=1;i<P;i++)
  686.             {
  687.                 bezier_curve(pts+indx, bez_pt, (GLfloat)i/(GLfloat)P, 4,
  688.                     order,stride);
  689.                 w = (GLdouble)bez_pt[3];
  690.                 x = (GLdouble)bez_pt[0] / w;
  691.                 y = (GLdouble)bez_pt[1] / w;
  692.                 z = (GLdouble)bez_pt[2] / w;
  693.                 gluProject(x,y,z,model,proj,viewport,&x3,&y3,&z3);
  694.                 z3 *= z_med;
  695.                 bezier_curve(pts+indx, bez_pt, (GLfloat)(i-1)/(GLfloat)P, 4,
  696.                     order,stride);
  697.                 w = (GLdouble)bez_pt[3];
  698.                 x = (GLdouble)bez_pt[0] / w;
  699.                 y = (GLdouble)bez_pt[1] / w;
  700.                 z = (GLdouble)bez_pt[2] / w;
  701.                 gluProject(x,y,z,model,proj,viewport,&x1,&y1,&z1);
  702.                 z1 *= z_med;
  703.                 bezier_curve(pts+indx, bez_pt, (GLfloat)(i+1)/(GLfloat)P, 4,
  704.                     order,stride);
  705.                 w = (GLdouble)bez_pt[3];
  706.                 x = (GLdouble)bez_pt[0] / w;
  707.                 y = (GLdouble)bez_pt[1] / w;
  708.                 z = (GLdouble)bez_pt[2] / w;
  709.                 gluProject(x,y,z,model,proj,viewport,&x2,&y2,&z2);
  710.                 z2 *= z_med;
  711.                 /* calc distance between point (x3,y3,z3) and line segment */
  712.                 /* <x1,y1,z1><x2,y2,z2> */
  713.                 x = x2-x1;
  714.                 y = y2-y1;
  715.                 z = z2-z1;
  716.                 tmp = sqrt(x*x+y*y+z*z);
  717.                 x /= tmp;
  718.                 y /= tmp;
  719.                 z /= tmp;
  720.                 tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z;
  721.                 x = x1+x*tmp-x3;
  722.                 y = y1+y*tmp-y3;
  723.                 z = z1+z*tmp-z3;
  724.                 tmp = sqrt(x*x+y*y+z*z);
  725.                 if(tmp > len)
  726.                     len = tmp;
  727.             }
  728.             break;
  729.         case 3:
  730.             for(i=1;i<P;i++)
  731.             {
  732.                 bezier_curve(pts+indx, bez_pt, (GLfloat)i/(GLfloat)P, 3,
  733.                     order,stride);
  734.                 x = (GLdouble)bez_pt[0];
  735.                 y = (GLdouble)bez_pt[1];
  736.                 z = (GLdouble)bez_pt[2];
  737.                 gluProject(x,y,z,model,proj,viewport,&x3,&y3,&z3);
  738.                 z3 *= z_med;
  739.                 bezier_curve(pts+indx, bez_pt, (GLfloat)(i-1)/(GLfloat)P, 3,
  740.                     order,stride);
  741.                 x = (GLdouble)bez_pt[0];
  742.                 y = (GLdouble)bez_pt[1];
  743.                 z = (GLdouble)bez_pt[2];
  744.                 gluProject(x,y,z,model,proj,viewport,&x1,&y1,&z1);
  745.                 z1 *= z_med;
  746.                 bezier_curve(pts+indx, bez_pt, (GLfloat)(i+1)/(GLfloat)P, 3,
  747.                     order,stride);
  748.                 x = (GLdouble)bez_pt[0];
  749.                 y = (GLdouble)bez_pt[1];
  750.                 z = (GLdouble)bez_pt[2];
  751.                 gluProject(x,y,z,model,proj,viewport,&x2,&y2,&z2);
  752.                 z2 *= z_med;
  753.                 /* calc distance between point (x3,y3,z3) and line segment */
  754.                 /* <x1,y1,z1><x2,y2,z2> */
  755.                 x = x2-x1;
  756.                 y = y2-y1;
  757.                 z = z2-z1;
  758.                 tmp = sqrt(x*x+y*y+z*z);
  759.                 x /= tmp;
  760.                 y /= tmp;
  761.                 z /= tmp;
  762.                 tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z;
  763.                 x = x1+x*tmp-x3;
  764.                 y = y1+y*tmp-y3;
  765.                 z = z1+z*tmp-z3;
  766.                 tmp = sqrt(x*x+y*y+z*z);
  767.                 if(tmp > len)
  768.                     len = tmp;
  769.             }
  770.             break;
  771.         case 2:
  772.             for(i=1;i<P;i++)
  773.             {
  774.                 bezier_curve(pts+indx, bez_pt, (GLfloat)i/(GLfloat)P, 2,
  775.                     order,stride);
  776.                 x = (GLdouble)bez_pt[0];
  777.                 y = (GLdouble)bez_pt[1];
  778.                 z = 0.0;
  779.                 gluProject(x,y,z,model,proj,viewport,&x3,&y3,&z3);
  780.                 z3 *= z_med;
  781.                 bezier_curve(pts+indx, bez_pt, (GLfloat)(i-1)/(GLfloat)P, 2,
  782.                     order,stride);
  783.                 x = (GLdouble)bez_pt[0];
  784.                 y = (GLdouble)bez_pt[1];
  785.                 z = 0.0;
  786.                 gluProject(x,y,z,model,proj,viewport,&x1,&y1,&z1);
  787.                 z1 *= z_med;
  788.                 bezier_curve(pts+indx, bez_pt, (GLfloat)(i+1)/(GLfloat)P, 2,
  789.                     order,stride);
  790.                 x = (GLdouble)bez_pt[0];
  791.                 y = (GLdouble)bez_pt[1];
  792.                 z = 0.0;
  793.                 gluProject(x,y,z,model,proj,viewport,&x2,&y2,&z2);
  794.                 z2 *= z_med;
  795.                 /* calc distance between point (x3,y3,z3) and line segment */
  796.                 /* <x1,y1,z1><x2,y2,z2> */
  797.                 x = x2-x1;
  798.                 y = y2-y1;
  799.                 z = z2-z1;
  800.                 tmp = sqrt(x*x+y*y+z*z);
  801.                 x /= tmp;
  802.                 y /= tmp;
  803.                 z /= tmp;
  804.                 tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z;
  805.                 x = x1+x*tmp-x3;
  806.                 y = y1+y*tmp-y3;
  807.                 z = z1+z*tmp-z3;
  808.                 tmp = sqrt(x*x+y*y+z*z);
  809.                 if(tmp > len)
  810.                     len = tmp;
  811.             }
  812.             break;
  813.  
  814.     }
  815.     if(len < tolerance)
  816.         return (order);
  817.     else
  818.         return (GLint)(sqrt(len/tolerance)*(order+2)+1);
  819. }
  820.  
  821. static GLenum
  822. calc_sampling_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim,
  823.     GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors)
  824. {
  825.     GLfloat        *ctrl;
  826.     GLint        tmp_factor1,tmp_factor2;
  827.     GLint        ufactor_cnt,vfactor_cnt;
  828.     GLint        offset1,offset2,offset3;
  829.     GLint        i,j;
  830.  
  831.     ufactor_cnt=new_ctrl->s_bezier_cnt;
  832.     vfactor_cnt=new_ctrl->t_bezier_cnt;
  833.     if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3))
  834.             ==NULL)
  835.     {
  836.         return GLU_OUT_OF_MEMORY;
  837.     }
  838.     if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3))
  839.             ==NULL)
  840.     {
  841.         free(*ufactors);
  842.         return GLU_OUT_OF_MEMORY;
  843.     }
  844.     ctrl=new_ctrl->geom_ctrl;
  845.     offset1=new_ctrl->geom_t_stride*vorder;
  846.     offset2=new_ctrl->geom_s_stride*uorder;
  847.     for(j=0;j<vfactor_cnt;j++)
  848.     {
  849.         *(*vfactors+j*3+1)=tmp_factor1=calc_factor(ctrl,vorder,
  850.             j*offset1,dim,tolerance,dim);
  851.         /* loop ufactor_cnt-1 times */
  852.         for(i=1;i<ufactor_cnt;i++)
  853.         {
  854.             tmp_factor2=calc_factor(ctrl,vorder,
  855.                 j*offset1+i*offset2,dim,tolerance,dim);
  856.             if(tmp_factor2>tmp_factor1)
  857.                 tmp_factor1=tmp_factor2;
  858.         }
  859.         /* last time for the opposite edge */
  860.         *(*vfactors+j*3+2)=tmp_factor2=calc_factor(ctrl,vorder,
  861.             j*offset1+i*offset2-new_ctrl->geom_s_stride,
  862.             dim,tolerance,dim);
  863.         if(tmp_factor2>tmp_factor1)
  864.             *(*vfactors+j*3)=tmp_factor2;
  865.         else
  866.             *(*vfactors+j*3)=tmp_factor1;
  867.     }
  868.     offset3=new_ctrl->geom_s_stride;
  869.     offset2=new_ctrl->geom_s_stride*uorder;
  870.     for(j=0;j<ufactor_cnt;j++)
  871.     {
  872.         *(*ufactors+j*3+1)=tmp_factor1=calc_factor(ctrl,uorder,
  873.             j*offset2,offset3,tolerance,dim);
  874.         /* loop vfactor_cnt-1 times */
  875.         for(i=1;i<vfactor_cnt;i++)
  876.         {
  877.             tmp_factor2=calc_factor(ctrl,uorder,
  878.                 j*offset2+i*offset1,offset3,tolerance,dim);
  879.             if(tmp_factor2>tmp_factor1)
  880.                 tmp_factor1=tmp_factor2;
  881.         }
  882.         /* last time for the opposite edge */
  883.         *(*ufactors+j*3+2)=tmp_factor2=calc_factor(ctrl,uorder,
  884.             j*offset2+i*offset1-new_ctrl->geom_t_stride,
  885.             offset3,tolerance,dim);
  886.         if(tmp_factor2>tmp_factor1)
  887.             *(*ufactors+j*3)=tmp_factor2;
  888.         else
  889.             *(*ufactors+j*3)=tmp_factor1;
  890.     }
  891.     return GL_NO_ERROR;
  892. }
  893.  
  894. static GLenum
  895. calc_sampling_param_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim,
  896.     GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors)
  897. {
  898.     GLfloat        *ctrl;
  899.     GLint        tmp_factor1,tmp_factor2;
  900.     GLint        ufactor_cnt,vfactor_cnt;
  901.     GLint        offset1,offset2,offset3;
  902.     GLint        i,j;
  903.  
  904.     ufactor_cnt=new_ctrl->s_bezier_cnt;
  905.     vfactor_cnt=new_ctrl->t_bezier_cnt;
  906.     if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3))
  907.             ==NULL)
  908.     {
  909.         return GLU_OUT_OF_MEMORY;
  910.     }
  911.     if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3))
  912.             ==NULL)
  913.     {
  914.         free(*ufactors);
  915.         return GLU_OUT_OF_MEMORY;
  916.     }
  917.     ctrl=new_ctrl->geom_ctrl;
  918.     offset1=new_ctrl->geom_t_stride*vorder;
  919.     offset2=new_ctrl->geom_s_stride*uorder;
  920.     for(j=0;j<vfactor_cnt;j++)
  921.     {
  922.         *(*vfactors+j*3+1)=tmp_factor1=calc_parametric_factor(ctrl,vorder,
  923.             j*offset1,dim,tolerance,dim);
  924.         /* loop ufactor_cnt-1 times */
  925.         for(i=1;i<ufactor_cnt;i++)
  926.         {
  927.             tmp_factor2=calc_parametric_factor(ctrl,vorder,
  928.                 j*offset1+i*offset2,dim,tolerance,dim);
  929.             if(tmp_factor2>tmp_factor1)
  930.                 tmp_factor1=tmp_factor2;
  931.         }
  932.         /* last time for the opposite edge */
  933.         *(*vfactors+j*3+2)=tmp_factor2=calc_parametric_factor(ctrl,vorder,
  934.             j*offset1+i*offset2-new_ctrl->geom_s_stride,
  935.             dim,tolerance,dim);
  936.         if(tmp_factor2>tmp_factor1)
  937.             *(*vfactors+j*3)=tmp_factor2;
  938.         else
  939.             *(*vfactors+j*3)=tmp_factor1;
  940.     }
  941.     offset3=new_ctrl->geom_s_stride;
  942.     offset2=new_ctrl->geom_s_stride*uorder;
  943.     for(j=0;j<ufactor_cnt;j++)
  944.     {
  945.         *(*ufactors+j*3+1)=tmp_factor1=calc_parametric_factor(ctrl,uorder,
  946.             j*offset2,offset3,tolerance,dim);
  947.         /* loop vfactor_cnt-1 times */
  948.         for(i=1;i<vfactor_cnt;i++)
  949.         {
  950.             tmp_factor2=calc_parametric_factor(ctrl,uorder,
  951.                 j*offset2+i*offset1,offset3,tolerance,dim);
  952.             if(tmp_factor2>tmp_factor1)
  953.                 tmp_factor1=tmp_factor2;
  954.         }
  955.         /* last time for the opposite edge */
  956.         *(*ufactors+j*3+2)=tmp_factor2=calc_parametric_factor(ctrl,uorder,
  957.             j*offset2+i*offset1-new_ctrl->geom_t_stride,
  958.             offset3,tolerance,dim);
  959.         if(tmp_factor2>tmp_factor1)
  960.             *(*ufactors+j*3)=tmp_factor2;
  961.         else
  962.             *(*ufactors+j*3)=tmp_factor1;
  963.     }
  964.     return GL_NO_ERROR;
  965. }
  966.  
  967. static GLenum
  968. calc_sampling_2D(GLfloat *ctrl, GLint cnt, GLint order,
  969.     GLfloat tolerance, GLint dim, GLint **factors)
  970. {
  971.     GLint        factor_cnt;
  972.     GLint        tmp_factor;
  973.     GLint        offset;
  974.     GLint        i;
  975.  
  976.     factor_cnt=cnt/order;
  977.     if((*factors=(GLint *)malloc(sizeof(GLint)*factor_cnt))==NULL)
  978.     {
  979.         return GLU_OUT_OF_MEMORY;
  980.     }
  981.     offset=order*dim;
  982.     for(i=0;i<factor_cnt;i++)
  983.     {
  984.         tmp_factor=calc_factor(ctrl,order,i*offset,dim,tolerance,dim);
  985.         if(tmp_factor == 0)
  986.             (*factors)[i]=1;
  987.         else
  988.             (*factors)[i]=tmp_factor;
  989.     }
  990.     return GL_NO_ERROR;
  991. }
  992.  
  993. static void
  994. set_sampling_and_culling( GLUnurbsObj *nobj )
  995. {
  996.     if(nobj->auto_load_matrix==GL_FALSE)
  997.     {
  998.         GLint i;
  999.         GLfloat m[4];
  1000.  
  1001.         glPushAttrib( (GLbitfield) (GL_VIEWPORT_BIT | GL_TRANSFORM_BIT));
  1002.         for(i=0;i<4;i++)
  1003.             m[i]=nobj->sampling_matrices.viewport[i];
  1004.         glViewport(m[0],m[1],m[2],m[3]);
  1005.         glMatrixMode(GL_PROJECTION);
  1006.         glPushMatrix();
  1007.         glLoadMatrixf(nobj->sampling_matrices.proj);
  1008.         glMatrixMode(GL_MODELVIEW);
  1009.         glPushMatrix();
  1010.         glLoadMatrixf(nobj->sampling_matrices.model);
  1011.     }
  1012. }
  1013.  
  1014. static void
  1015. revert_sampling_and_culling( GLUnurbsObj *nobj )
  1016. {
  1017.     if(nobj->auto_load_matrix==GL_FALSE)
  1018.     {
  1019.         glMatrixMode(GL_MODELVIEW);
  1020.         glPopMatrix();
  1021.         glMatrixMode(GL_PROJECTION);
  1022.         glPopMatrix();
  1023.         glPopAttrib();
  1024.     }
  1025. }
  1026.  
  1027. GLenum
  1028. glu_do_sampling_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
  1029.     GLint **sfactors, GLint **tfactors)
  1030. {
  1031.     GLint    dim;
  1032.     GLenum    err;
  1033.  
  1034.     *sfactors=NULL;
  1035.     *tfactors=NULL;
  1036.     dim=nobj->surface.geom.dim;
  1037.     set_sampling_and_culling(nobj);
  1038.     if((err=calc_sampling_3D(new_ctrl,nobj->sampling_tolerance,dim,
  1039.         nobj->surface.geom.sorder,nobj->surface.geom.torder,
  1040.         sfactors,tfactors))==GLU_ERROR)
  1041.     {
  1042.         revert_sampling_and_culling(nobj);
  1043.         call_user_error(nobj,err);
  1044.         return GLU_ERROR;
  1045.     }
  1046.     revert_sampling_and_culling(nobj);
  1047.     return GLU_NO_ERROR;
  1048. }
  1049.  
  1050. GLenum
  1051. glu_do_sampling_uv( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
  1052.     GLint **sfactors, GLint **tfactors)
  1053. {
  1054.     GLint    s_cnt, t_cnt, i;
  1055.     GLint    u_steps, v_steps;
  1056.  
  1057.     s_cnt = new_ctrl->s_bezier_cnt;
  1058.     t_cnt = new_ctrl->t_bezier_cnt;
  1059.     *sfactors=NULL;
  1060.     *tfactors=NULL;
  1061.     if((*sfactors=(GLint *)malloc(sizeof(GLint)*s_cnt*3))
  1062.             ==NULL)
  1063.     {
  1064.         return GLU_OUT_OF_MEMORY;
  1065.     }
  1066.     if((*tfactors=(GLint *)malloc(sizeof(GLint)*t_cnt*3))
  1067.             ==NULL)
  1068.     {
  1069.         free(*sfactors);
  1070.         return GLU_OUT_OF_MEMORY;
  1071.     }
  1072.     u_steps = nobj->u_step;
  1073.     v_steps = nobj->v_step;
  1074.     for(i=0; i<s_cnt; i++)
  1075.     {
  1076.         *(*sfactors+i*3) = u_steps;
  1077.         *(*sfactors+i*3+1) = u_steps;
  1078.         *(*sfactors+i*3+2) = u_steps;
  1079.     }
  1080.     for(i=0; i<t_cnt; i++)
  1081.     {
  1082.         *(*tfactors+i*3) = v_steps;
  1083.         *(*tfactors+i*3+1) = v_steps;
  1084.         *(*tfactors+i*3+2) = v_steps;
  1085.     }
  1086.     return GLU_NO_ERROR;
  1087. }
  1088.  
  1089. GLenum
  1090. glu_do_sampling_param_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
  1091.     GLint **sfactors, GLint **tfactors)
  1092. {
  1093.     GLint    dim;
  1094.     GLenum    err;
  1095.  
  1096.     *sfactors=NULL;
  1097.     *tfactors=NULL;
  1098.     dim=nobj->surface.geom.dim;
  1099.     set_sampling_and_culling(nobj);
  1100.     if((err=calc_sampling_param_3D(new_ctrl,nobj->parametric_tolerance,dim,
  1101.         nobj->surface.geom.sorder,nobj->surface.geom.torder,
  1102.         sfactors,tfactors))==GLU_ERROR)
  1103.     {
  1104.         revert_sampling_and_culling(nobj);
  1105.         call_user_error(nobj,err);
  1106.         return GLU_ERROR;
  1107.     }
  1108.     revert_sampling_and_culling(nobj);
  1109.     return GLU_NO_ERROR;
  1110. }
  1111.  
  1112. GLenum
  1113. glu_do_sampling_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
  1114.     GLint dim, GLint **factors)
  1115. {
  1116.     GLenum err;
  1117.  
  1118.     set_sampling_and_culling(nobj);
  1119.     err=calc_sampling_2D(ctrl,cnt,order,nobj->sampling_tolerance,dim,
  1120.         factors);
  1121.     revert_sampling_and_culling(nobj);
  1122.     return err;
  1123. }
  1124.  
  1125.  
  1126. GLenum
  1127. glu_do_sampling_u( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
  1128.     GLint dim, GLint **factors)
  1129. {
  1130.     GLint    i;
  1131.     GLint    u_steps;
  1132.  
  1133.     cnt /= order;
  1134.     if((*factors=(GLint *)malloc(sizeof(GLint)*cnt))
  1135.             ==NULL)
  1136.     {
  1137.         return GLU_OUT_OF_MEMORY;
  1138.     }
  1139.     u_steps = nobj->u_step;
  1140.     for(i=0; i<cnt; i++)
  1141.         (*factors)[i] = u_steps;
  1142.     return GLU_NO_ERROR;
  1143. }
  1144.  
  1145. GLenum
  1146. glu_do_sampling_param_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt,
  1147.     GLint order, GLint dim, GLint **factors)
  1148. {
  1149.     GLint    i;
  1150.     GLint    u_steps;
  1151.     GLfloat    tolerance;
  1152.  
  1153.     set_sampling_and_culling(nobj);
  1154.     tolerance = nobj->parametric_tolerance;
  1155.     cnt /= order;
  1156.     if((*factors=(GLint *)malloc(sizeof(GLint)*cnt))
  1157.             ==NULL)
  1158.     {
  1159.         revert_sampling_and_culling(nobj);
  1160.         return GLU_OUT_OF_MEMORY;
  1161.     }
  1162.     u_steps = nobj->u_step;
  1163.     for(i=0; i<cnt; i++)
  1164.     {
  1165.         (*factors)[i] = calc_parametric_factor(ctrl,order,0,
  1166.             dim,tolerance,dim);
  1167.  
  1168.     }
  1169.     revert_sampling_and_culling(nobj);
  1170.     return GLU_NO_ERROR;
  1171. }
  1172.  
  1173. GLenum
  1174. glu_do_sampling_crv( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
  1175.     GLint dim, GLint **factors)
  1176. {
  1177.     GLenum err;
  1178.  
  1179.     *factors=NULL;
  1180.     switch(nobj->sampling_method)
  1181.     {
  1182.         case GLU_PATH_LENGTH:
  1183.             if((err=glu_do_sampling_2D(nobj,ctrl,cnt,order,dim,factors))!=
  1184.                 GLU_NO_ERROR)
  1185.             {
  1186.                 call_user_error(nobj,err);
  1187.                 return GLU_ERROR;
  1188.             }
  1189.             break;
  1190.         case GLU_DOMAIN_DISTANCE:
  1191.             if((err=glu_do_sampling_u(nobj,ctrl,cnt,order,dim,factors))!=
  1192.                 GLU_NO_ERROR)
  1193.             {
  1194.                 call_user_error(nobj,err);
  1195.                 return GLU_ERROR;
  1196.             }
  1197.             break;
  1198.         case GLU_PARAMETRIC_ERROR:
  1199.             if((err=glu_do_sampling_param_2D(nobj,ctrl,cnt,order,dim,factors))!=
  1200.                 GLU_NO_ERROR)
  1201.             {
  1202.                 call_user_error(nobj,err);
  1203.                 return GLU_ERROR;
  1204.             }
  1205.             break;
  1206.         default:
  1207.             abort();
  1208.     }
  1209.  
  1210.     return GLU_NO_ERROR;
  1211. }
  1212.  
  1213. /* TODO - i don't like this culling - this one just tests if at least one */
  1214. /* ctrl point lies within the viewport . Also the point_in_viewport() */
  1215. /* should be included in the fnctions for efficiency reasons */
  1216.  
  1217. static GLboolean
  1218. point_in_viewport(GLfloat *pt, GLint dim)
  1219. {
  1220.     GLdouble model[16],proj[16];
  1221.     GLint viewport[4];
  1222.     GLdouble x,y,z,w,winx,winy,winz;
  1223.  
  1224.     glGetDoublev(GL_MODELVIEW_MATRIX,model);
  1225.     glGetDoublev(GL_PROJECTION_MATRIX,proj);
  1226.     glGetIntegerv(GL_VIEWPORT,viewport);
  1227.     if(dim==3)
  1228.     {
  1229.         x=(GLdouble)pt[0];
  1230.         y=(GLdouble)pt[1];
  1231.         z=(GLdouble)pt[2];
  1232.         gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
  1233.     }
  1234.     else
  1235.     {
  1236.         w=(GLdouble)pt[3];
  1237.         x=(GLdouble)pt[0]/w;
  1238.         y=(GLdouble)pt[1]/w;
  1239.         z=(GLdouble)pt[2]/w;
  1240.         gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
  1241.     }
  1242.     if((GLint)winx >= viewport[0] && (GLint)winx < viewport[2] &&
  1243.             (GLint)winy >= viewport[1] && (GLint)winy < viewport[3])
  1244.         return GL_TRUE;
  1245.     return GL_FALSE;
  1246. }
  1247.  
  1248. GLboolean
  1249. fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
  1250.     GLint s_stride,GLint t_stride, GLint dim)
  1251. {
  1252.     GLint     i,j;
  1253.  
  1254.     if(nobj->culling==GL_FALSE)
  1255.         return GL_FALSE;
  1256.     set_sampling_and_culling(nobj);
  1257.     
  1258.     if(dim==3)
  1259.     {
  1260.         for(i=0;i<s_cnt;i++)
  1261.             for(j=0;j<t_cnt;j++)
  1262.                 if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
  1263.                 {
  1264.                     revert_sampling_and_culling(nobj);
  1265.                     return GL_FALSE;
  1266.                 }
  1267.     }
  1268.     else
  1269.     {
  1270.         for(i=0;i<s_cnt;i++)
  1271.             for(j=0;j<t_cnt;j++)
  1272.                 if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
  1273.                 {
  1274.                     revert_sampling_and_culling(nobj);
  1275.                     return GL_FALSE;
  1276.                 }
  1277.     }
  1278.     revert_sampling_and_culling(nobj);
  1279.     return GL_TRUE;
  1280. }
  1281.  
  1282. /*GLboolean
  1283. fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
  1284.     GLint s_stride,GLint t_stride, GLint dim)
  1285. {
  1286.     GLint        visible_cnt;
  1287.     GLfloat        feedback_buffer[5];
  1288.     GLsizei        buffer_size;
  1289.     GLint         i,j;
  1290.  
  1291.     if(nobj->culling==GL_FALSE)
  1292.         return GL_FALSE;
  1293.     buffer_size=5;
  1294.     set_sampling_and_culling(nobj);
  1295.     
  1296.     glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
  1297.     glRenderMode(GL_FEEDBACK);
  1298.     if(dim==3)
  1299.     {
  1300.         for(i=0;i<s_cnt;i++)
  1301.         {
  1302.             glBegin(GL_LINE_LOOP);
  1303.             for(j=0;j<t_cnt;j++)
  1304.                 glVertex3fv(pts+i*s_stride+j*t_stride);
  1305.             glEnd();
  1306.         }
  1307.         for(j=0;j<t_cnt;j++)
  1308.         {
  1309.             glBegin(GL_LINE_LOOP);
  1310.             for(i=0;i<s_cnt;i++)
  1311.                 glVertex3fv(pts+i*s_stride+j*t_stride);
  1312.             glEnd();
  1313.         }
  1314.     }
  1315.     else
  1316.     {
  1317.         for(i=0;i<s_cnt;i++)
  1318.         {
  1319.             glBegin(GL_LINE_LOOP);
  1320.             for(j=0;j<t_cnt;j++)
  1321.                 glVertex4fv(pts+i*s_stride+j*t_stride);
  1322.             glEnd();
  1323.         }
  1324.         for(j=0;j<t_cnt;j++)
  1325.         {
  1326.             glBegin(GL_LINE_LOOP);
  1327.             for(i=0;i<s_cnt;i++)
  1328.                 glVertex4fv(pts+i*s_stride+j*t_stride);
  1329.             glEnd();
  1330.         }
  1331.     }
  1332.     visible_cnt=glRenderMode(GL_RENDER);
  1333.  
  1334.     revert_sampling_and_culling(nobj);
  1335.     return (GLboolean)(visible_cnt==0);
  1336. }*/
  1337.  
  1338. GLboolean
  1339. fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
  1340.     GLint stride, GLint dim)
  1341. {
  1342.     GLint     i;
  1343.  
  1344.     if(nobj->culling==GL_FALSE)
  1345.         return GL_FALSE;
  1346.     set_sampling_and_culling(nobj);
  1347.     
  1348.     if(dim==3)
  1349.     {
  1350.         for(i=0;i<cnt;i++)
  1351.             if(point_in_viewport(pts+i*stride,dim))
  1352.             {
  1353.                 revert_sampling_and_culling(nobj);
  1354.                 return GL_FALSE;
  1355.             }
  1356.     }
  1357.     else
  1358.     {
  1359.         for(i=0;i<cnt;i++)
  1360.             if(point_in_viewport(pts+i*stride,dim))
  1361.             {
  1362.                 revert_sampling_and_culling(nobj);
  1363.                 return GL_FALSE;
  1364.             }
  1365.     }
  1366.     revert_sampling_and_culling(nobj);
  1367.     return GL_TRUE;
  1368. }
  1369.  
  1370. /*GLboolean
  1371. fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
  1372.     GLint stride, GLint dim)
  1373. {
  1374.     GLint        visible_cnt;
  1375.     GLfloat        feedback_buffer[5];
  1376.     GLsizei        buffer_size;
  1377.     GLint         i;
  1378.  
  1379.     if(nobj->culling==GL_FALSE)
  1380.         return GL_FALSE;
  1381.     buffer_size=5;
  1382.     set_sampling_and_culling(nobj);
  1383.     
  1384.     glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
  1385.     glRenderMode(GL_FEEDBACK);
  1386.     glBegin(GL_LINE_LOOP);
  1387.     if(dim==3)
  1388.     {
  1389.         for(i=0;i<cnt;i++)
  1390.             glVertex3fv(pts+i*stride);
  1391.     }
  1392.     else
  1393.     {
  1394.         for(i=0;i<cnt;i++)
  1395.             glVertex4fv(pts+i*stride);
  1396.     }
  1397.     glEnd();
  1398.     visible_cnt=glRenderMode(GL_RENDER);
  1399.  
  1400.     revert_sampling_and_culling(nobj);
  1401.     return (GLboolean)(visible_cnt==0);
  1402. }*/
  1403.  
  1404.