home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src-glu / nurbsutl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  33.5 KB  |  1,395 lines

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