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

  1. /* nurbscrv.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: nurbscrv.c,v 1.5 1995/11/03 14:14:07 brianp Exp $
  26.  
  27. $Log: nurbscrv.c,v $
  28.  * Revision 1.5  1995/11/03  14:14:07  brianp
  29.  * Bogdan's November 3, 1995 updates
  30.  *
  31.  * Revision 1.4  1995/09/20  18:25:57  brianp
  32.  * removed Bogdan's old email address
  33.  *
  34.  * Revision 1.3  1995/08/04  13:09:59  brianp
  35.  * include gluP.h to define NULL, just in case
  36.  *
  37.  * Revision 1.2  1995/07/28  21:37:04  brianp
  38.  * updates from Bogdan on July 28
  39.  *
  40.  * Revision 1.1  1995/07/28  14:44:43  brianp
  41.  * Initial revision
  42.  *
  43.  */
  44.  
  45.  
  46. /*
  47.  * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
  48.  * See README-nurbs for more info.
  49.  */
  50.  
  51.  
  52. #include "nurbs.h"
  53. #include <stdlib.h>
  54. #include <math.h>
  55.  
  56. static int
  57. get_curve_dim(GLenum type)
  58. {
  59.     switch(type)
  60.     {
  61.         case GL_MAP1_VERTEX_3:            return 3;
  62.         case GL_MAP1_VERTEX_4:            return 4;
  63.         case GL_MAP1_INDEX:                return 1;
  64.         case GL_MAP1_COLOR_4:            return 4;
  65.         case GL_MAP1_NORMAL:            return 3;
  66.         case GL_MAP1_TEXTURE_COORD_1:    return 1;
  67.         case GL_MAP1_TEXTURE_COORD_2:    return 2;
  68.         case GL_MAP1_TEXTURE_COORD_3:    return 3;
  69.         case GL_MAP1_TEXTURE_COORD_4:    return 4;
  70.     }
  71. }
  72.  
  73. static GLenum
  74. test_nurbs_curve(GLUnurbsObj *nobj, curve_attribs *attribs)
  75. {
  76.     GLenum err;
  77.     GLint tmp_int;
  78.  
  79.     if(attribs->order < 0)
  80.     {
  81.         call_user_error(nobj,GLU_INVALID_VALUE);
  82.         return GLU_ERROR;
  83.     }
  84.     glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
  85.     if(attribs->order > tmp_int || attribs->order < 2)
  86.     {
  87.         call_user_error(nobj,GLU_NURBS_ERROR1);
  88.         return GLU_ERROR;
  89.     }
  90.     if(attribs->knot_count < attribs->order +2)
  91.     {
  92.         call_user_error(nobj,GLU_NURBS_ERROR2);
  93.         return GLU_ERROR;
  94.     }
  95.     if(attribs->stride < 0)
  96.     {
  97.         call_user_error(nobj,GLU_NURBS_ERROR34);
  98.         return GLU_ERROR;
  99.     }
  100.     if(attribs->knot==NULL || attribs->ctrlarray==NULL)
  101.     {
  102.         call_user_error(nobj,GLU_NURBS_ERROR36);
  103.         return GLU_ERROR;
  104.     }
  105.     if((err=test_knot(attribs->knot_count,attribs->knot,attribs->order))
  106.         !=GLU_NO_ERROR)
  107.     {
  108.         call_user_error(nobj,err);
  109.         return GLU_ERROR;
  110.     }
  111.     return GLU_NO_ERROR;
  112. }
  113.  
  114. static GLenum
  115. test_nurbs_curves(GLUnurbsObj *nobj)
  116. {
  117.     /* test the geometric data */
  118.     if(test_nurbs_curve(nobj,&(nobj->curve.geom))!=GLU_NO_ERROR)
  119.         return GLU_ERROR;
  120.     /* now test the attributive data */
  121.     /* color */
  122.     if(nobj->curve.color.type!=GLU_INVALID_ENUM)
  123.         if(test_nurbs_curve(nobj,&(nobj->curve.color))!=GLU_NO_ERROR)
  124.             return GLU_ERROR;
  125.     /* normal */
  126.     if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
  127.         if(test_nurbs_curve(nobj,&(nobj->curve.normal))!=GLU_NO_ERROR)
  128.             return GLU_ERROR;
  129.     /* texture */
  130.     if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
  131.         if(test_nurbs_curve(nobj,&(nobj->curve.texture))!=GLU_NO_ERROR)
  132.             return GLU_ERROR;
  133.     return GLU_NO_ERROR;
  134. }
  135.  
  136. /* prepare the knot information structures */
  137. static GLenum
  138. fill_knot_structures(GLUnurbsObj *nobj,knot_str_type *geom_knot,
  139.     knot_str_type *color_knot, knot_str_type *normal_knot,
  140.     knot_str_type *texture_knot)
  141. {
  142.     GLint order;
  143.     GLfloat *knot;
  144.     GLint nknots;
  145.     GLint t_min,t_max;
  146.  
  147.     geom_knot->unified_knot=NULL;
  148.     knot=geom_knot->knot=nobj->curve.geom.knot;
  149.     nknots=geom_knot->nknots=nobj->curve.geom.knot_count;
  150.     order=geom_knot->order=nobj->curve.geom.order;
  151.     geom_knot->delta_nknots=0;
  152.     t_min=geom_knot->t_min=order-1;
  153.     t_max=geom_knot->t_max=nknots-order;
  154.     if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  155.     {
  156.         call_user_error(nobj,GLU_NURBS_ERROR3);
  157.         return GLU_ERROR;
  158.     }
  159.     if(fabs(knot[0]-knot[t_min])<EPSILON)
  160.     {
  161.         /* knot open at beggining */
  162.         geom_knot->open_at_begin=GL_TRUE;
  163.     }
  164.     else
  165.         geom_knot->open_at_begin=GL_FALSE;
  166.     if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  167.     {
  168.         /* knot open at end */
  169.         geom_knot->open_at_end=GL_TRUE;
  170.     }
  171.     else
  172.         geom_knot->open_at_end=GL_FALSE;
  173.     if(nobj->curve.color.type!=GLU_INVALID_ENUM)
  174.     {
  175.         color_knot->unified_knot=(GLfloat *)1;
  176.         knot=color_knot->knot=nobj->curve.color.knot;
  177.         nknots=color_knot->nknots=nobj->curve.color.knot_count;
  178.         order=color_knot->order=nobj->curve.color.order;
  179.         color_knot->delta_nknots=0;
  180.         t_min=color_knot->t_min=order-1;
  181.         t_max=color_knot->t_max=nknots-order;
  182.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  183.         {
  184.             call_user_error(nobj,GLU_NURBS_ERROR3);
  185.             return GLU_ERROR;
  186.         }
  187.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  188.         {
  189.             /* knot open at beggining */
  190.             color_knot->open_at_begin=GL_TRUE;
  191.         }
  192.         else
  193.             color_knot->open_at_begin=GL_FALSE;
  194.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  195.         {
  196.             /* knot open at end */
  197.             color_knot->open_at_end=GL_TRUE;
  198.         }
  199.         else
  200.             color_knot->open_at_end=GL_FALSE;
  201.     }
  202.     else
  203.         color_knot->unified_knot=NULL;
  204.     if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
  205.     {
  206.         normal_knot->unified_knot=(GLfloat *)1;
  207.         knot=normal_knot->knot=nobj->curve.normal.knot;
  208.         nknots=normal_knot->nknots=nobj->curve.normal.knot_count;
  209.         order=normal_knot->order=nobj->curve.normal.order;
  210.         normal_knot->delta_nknots=0;
  211.         t_min=normal_knot->t_min=order-1;
  212.         t_max=normal_knot->t_max=nknots-order;
  213.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  214.         {
  215.             call_user_error(nobj,GLU_NURBS_ERROR3);
  216.             return GLU_ERROR;
  217.         }
  218.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  219.         {
  220.             /* knot open at beggining */
  221.             normal_knot->open_at_begin=GL_TRUE;
  222.         }
  223.         else
  224.             normal_knot->open_at_begin=GL_FALSE;
  225.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  226.         {
  227.             /* knot open at end */
  228.             normal_knot->open_at_end=GL_TRUE;
  229.         }
  230.         else
  231.             normal_knot->open_at_end=GL_FALSE;
  232.     }
  233.     else
  234.         normal_knot->unified_knot=NULL;
  235.     if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
  236.     {
  237.         texture_knot->unified_knot=(GLfloat *)1;
  238.         knot=texture_knot->knot=nobj->curve.texture.knot;
  239.         nknots=texture_knot->nknots=nobj->curve.texture.knot_count;
  240.         order=texture_knot->order=nobj->curve.texture.order;
  241.         texture_knot->delta_nknots=0;
  242.         t_min=texture_knot->t_min=order-1;
  243.         t_max=texture_knot->t_max=nknots-order;
  244.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  245.         {
  246.             call_user_error(nobj,GLU_NURBS_ERROR3);
  247.             return GLU_ERROR;
  248.         }
  249.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  250.         {
  251.             /* knot open at beggining */
  252.             texture_knot->open_at_begin=GL_TRUE;
  253.         }
  254.         else
  255.             texture_knot->open_at_begin=GL_FALSE;
  256.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  257.         {
  258.             /* knot open at end */
  259.             texture_knot->open_at_end=GL_TRUE;
  260.         }
  261.         else
  262.             texture_knot->open_at_end=GL_FALSE;
  263.     }
  264.     else
  265.         texture_knot->unified_knot=NULL;
  266.     return GLU_NO_ERROR;
  267. }
  268.  
  269. /* qsort function */
  270. static int
  271. knot_sort(const void *a, const void *b)
  272. {
  273.     GLfloat x,y;
  274.  
  275.     x=*((GLfloat *)a);
  276.     y=*((GLfloat *)b);
  277.     if(fabs(x-y) < EPSILON)
  278.         return 0;
  279.     if(x > y)
  280.         return 1;
  281.     return -1;
  282. }
  283.  
  284. /* insert into dest knot all values within the valid range from src knot */
  285. /* that do not appear in dest */
  286. /* First we have to transfor all knot values of src in such a way that */
  287. /* the valid knot range boundaries allign with the ones of dest */
  288. static void
  289. collect_unified_knot(knot_str_type *dest, knot_str_type *src,
  290.     GLfloat *mult_factor, GLfloat *add_factor)
  291. {
  292.     GLfloat *src_knot,*dest_knot;
  293.     GLint src_t_min,src_t_max,dest_t_min,dest_t_max;
  294.     GLint src_nknots,dest_nknots;
  295.     GLint i,j,k,new_cnt;
  296.  
  297.     src_knot=src->unified_knot;
  298.     dest_knot=dest->unified_knot;
  299.     src_t_min=src->t_min;
  300.     src_t_max=src->t_max;
  301.     dest_t_min=dest->t_min;
  302.     dest_t_max=dest->t_max;
  303.     src_nknots=src->unified_nknots;
  304.     dest_nknots=dest->unified_nknots;
  305.     /* convert src knot to have the same range values for its valid range */
  306.     *mult_factor=(dest_knot[dest_t_max]-dest_knot[dest_t_min]) /
  307.         (src_knot[src_t_max]-src_knot[src_t_min]);
  308.     for(i=0;i<src_nknots;i++)
  309.         src_knot[i] *= *mult_factor;
  310.     *add_factor=dest_knot[dest_t_min]-src_knot[src_t_min];
  311.     if(fabs(*add_factor)>EPSILON)
  312.         for(i=0;i<src_nknots;i++)
  313.             src_knot[i] += *add_factor;
  314.  
  315.     for(i=src_t_min+1 , j=dest_t_min+1 , k=dest_nknots , new_cnt=dest_nknots;
  316.         i<src_t_max;
  317.         i++)
  318.     {
  319.         if(fabs(dest_knot[j]-src_knot[i]) < EPSILON)
  320.             continue; /* knot from src already appears in dest */
  321.         else
  322.         if(dest_knot[j] > src_knot[i])
  323.         {
  324.             /* knot from src is not in dest - add this knot to dest */
  325.             dest_knot[k++]=src_knot[i];
  326.             ++new_cnt;
  327.             ++(dest->t_max); /* the valid range widens */
  328.             ++(dest->delta_nknots); /* increment the extra knot value counter */
  329.         }
  330.         else
  331.         {
  332.             /* the knot value at dest is smaller than the knot from src */
  333.             /* scan the dest, and stop when we find a greater or equal value */
  334.             /* after positioning, the former code will decide if to insert */
  335.             /* or not the current src knot value */
  336.             while(src_knot[i] > dest_knot[j])
  337.                 j++;
  338.             --i;
  339.         }
  340.     }
  341.     dest->unified_nknots=new_cnt;
  342.     qsort((void *)dest_knot,(size_t)new_cnt,(size_t)sizeof(GLfloat),
  343.         &knot_sort);
  344. }
  345.  
  346. /* similar as above - insert into the dest knot new values from src knot */
  347. /* since the dest knot had its values "scaled" to the same valid range */
  348. /* as the src previously, we have revert this process */
  349. static void
  350. fill_unified_knot(knot_str_type *dest, knot_str_type *src,
  351.     GLfloat mult_factor, GLfloat add_factor)
  352. {
  353.     GLfloat *src_knot,*dest_knot;
  354.     GLint src_t_min,src_t_max,dest_t_min;
  355.     GLint src_nknots,dest_nknots;
  356.     GLint i,j,k,new_cnt;
  357.     GLfloat delta;
  358.  
  359.     src_knot=src->unified_knot;
  360.     dest_knot=dest->unified_knot;
  361.     src_t_min=src->t_min;
  362.     src_t_max=src->t_max;
  363.     dest_t_min=dest->t_min;
  364.     src_nknots=src->unified_nknots;
  365.     dest_nknots=dest->unified_nknots;
  366.     for(i=src_t_min+1 , j=dest_t_min+1 , k=dest_nknots , new_cnt=dest_nknots;
  367.         i<src_t_max;
  368.         i++)
  369.     {
  370.         if(fabs(dest_knot[j]-src_knot[i]) < EPSILON)
  371.             continue;
  372.         else
  373.         if(dest_knot[j] > src_knot[i])
  374.         {
  375.             /* insert */
  376.             dest_knot[k++]=src_knot[i];
  377.             ++new_cnt;
  378.             ++(dest->t_max);
  379.             ++(dest->delta_nknots);
  380.         }
  381.         else
  382.         {
  383.             while(src_knot[i] > dest_knot[j])
  384.                 j++;
  385.             --i;
  386.         }
  387.     }
  388.     dest->unified_nknots=new_cnt;
  389.     qsort((void *)dest_knot,(size_t)new_cnt,(size_t)sizeof(GLfloat),
  390.         &knot_sort);
  391.     /* return back to the original values of knot */
  392.     for(i=0;i<new_cnt;i++)
  393.     {
  394.         dest_knot[i] -= add_factor;
  395.         dest_knot[i] /= mult_factor;
  396.     }
  397. }
  398.  
  399. /* modify all knot valid ranges in such a way that all have the same number */
  400. /* of knots in between, but preserve scaling */
  401. /* do this by knot insertion */
  402. static GLenum
  403. unify_knots(GLUnurbsObj *nobj,knot_str_type *geom_knot,
  404.     knot_str_type *color_knot, knot_str_type *normal_knot,
  405.     knot_str_type *texture_knot)
  406. {
  407.     GLint max_nknots;
  408.     GLfloat color_mult, color_add;
  409.     GLfloat normal_mult, normal_add;
  410.     GLfloat texture_mult, texture_add;
  411.     GLint i;
  412.  
  413.     if(fill_knot_structures(nobj,geom_knot,color_knot,normal_knot,texture_knot)
  414.             !=GLU_NO_ERROR)
  415.         return GLU_ERROR;
  416.     /* find the maximum modified knot length */
  417.     max_nknots=geom_knot->nknots;
  418.     if(color_knot->unified_knot)
  419.         max_nknots+=color_knot->nknots;
  420.     if(normal_knot->unified_knot)
  421.         max_nknots+=normal_knot->nknots;
  422.     if(texture_knot->unified_knot)
  423.         max_nknots+=texture_knot->nknots;
  424.     /* any attirb data ? */
  425.     if(max_nknots!=geom_knot->nknots)
  426.     {
  427.         /* allocate space for the unified knots */
  428.         if((geom_knot->unified_knot=
  429.                 (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  430.         {
  431.             call_user_error(nobj,GLU_OUT_OF_MEMORY);
  432.             return GLU_ERROR;
  433.         }
  434.         /* copy the original knot to the unified one */
  435.         geom_knot->unified_nknots=geom_knot->nknots;
  436.         for(i=0;i<geom_knot->nknots;i++)
  437.             (geom_knot->unified_knot)[i]=(geom_knot->knot)[i];
  438.         if(color_knot->unified_knot)
  439.         {
  440.             if((color_knot->unified_knot=
  441.                     (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  442.             {
  443.                 free(geom_knot->unified_knot);
  444.                 call_user_error(nobj,GLU_OUT_OF_MEMORY);
  445.                 return GLU_ERROR;
  446.             }
  447.             /* copy the original knot to the unified one */
  448.             color_knot->unified_nknots=color_knot->nknots;
  449.             for(i=0;i<color_knot->nknots;i++)
  450.                 (color_knot->unified_knot)[i]=(color_knot->knot)[i];
  451.         }
  452.         if(normal_knot->unified_knot)
  453.         {
  454.             if((normal_knot->unified_knot=
  455.                     (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  456.             {
  457.                 free(geom_knot->unified_knot);
  458.                 free(color_knot->unified_knot);
  459.                 call_user_error(nobj,GLU_OUT_OF_MEMORY);
  460.                 return GLU_ERROR;
  461.             }
  462.             /* copy the original knot to the unified one */
  463.             normal_knot->unified_nknots=normal_knot->nknots;
  464.             for(i=0;i<normal_knot->nknots;i++)
  465.                 (normal_knot->unified_knot)[i]=(normal_knot->knot)[i];
  466.         }
  467.         if(texture_knot->unified_knot)
  468.         {
  469.             if((texture_knot->unified_knot=
  470.                     (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
  471.             {
  472.                 free(geom_knot->unified_knot);
  473.                 free(color_knot->unified_knot);
  474.                 free(normal_knot->unified_knot);
  475.                 call_user_error(nobj,GLU_OUT_OF_MEMORY);
  476.                 return GLU_ERROR;
  477.             }
  478.             /* copy the original knot to the unified one */
  479.             texture_knot->unified_nknots=texture_knot->nknots;
  480.             for(i=0;i<texture_knot->nknots;i++)
  481.                 (texture_knot->unified_knot)[i]=(texture_knot->knot)[i];
  482.         }
  483.         /* fill in the geometry knot with all additional knot values */
  484.         /* appearing in attirbutive knots */
  485.         if(color_knot->unified_knot)
  486.             collect_unified_knot(geom_knot,color_knot,&color_mult,&color_add);
  487.         if(normal_knot->unified_knot)
  488.             collect_unified_knot(geom_knot,normal_knot,&normal_mult,&normal_add);
  489.         if(texture_knot->unified_knot)
  490.             collect_unified_knot(geom_knot,texture_knot,&texture_mult,&texture_add);
  491.         /* since we have now built the "unified" geometry knot */
  492.         /* add same knot values to all attributive knots */
  493.         if(color_knot->unified_knot)
  494.             fill_unified_knot(color_knot,geom_knot,color_mult,color_add);
  495.         if(normal_knot->unified_knot)
  496.             fill_unified_knot(normal_knot,geom_knot,normal_mult,normal_add);
  497.         if(texture_knot->unified_knot)
  498.             fill_unified_knot(texture_knot,geom_knot,texture_mult,texture_add);
  499.     }
  500.     return GLU_NO_ERROR;
  501. }
  502.  
  503. /* covert the NURBS curve into a series of adjacent Bezier curves */
  504. static GLenum
  505. convert_curve(knot_str_type *the_knot, curve_attribs *attrib,
  506.     GLfloat **new_ctrl,GLint *ncontrol)
  507. {
  508.     GLenum err;
  509.  
  510.     if((err=explode_knot(the_knot))!=GLU_NO_ERROR)
  511.     {
  512.         if(the_knot->unified_knot)
  513.         {
  514.             free(the_knot->unified_knot);
  515.             the_knot->unified_knot=NULL;
  516.         }
  517.         return err;
  518.     }
  519.     if(the_knot->unified_knot)
  520.     {
  521.         free(the_knot->unified_knot);
  522.         the_knot->unified_knot=NULL;
  523.     }
  524.     if((err=calc_alphas(the_knot))!=GLU_NO_ERROR)
  525.     {
  526.         free(the_knot->new_knot);
  527.         return err;
  528.     }
  529.     free(the_knot->new_knot);
  530.     if((err=calc_new_ctrl_pts(attrib->ctrlarray,attrib->stride,the_knot,
  531.                             attrib->dim,new_ctrl,ncontrol))
  532.         !=GLU_NO_ERROR)
  533.     {
  534.         free(the_knot->alpha);
  535.         return err;
  536.     }
  537.     free(the_knot->alpha);
  538.     return GLU_NO_ERROR;
  539. }
  540.  
  541. static void
  542. free_unified_knots(knot_str_type *geom_knot, knot_str_type *color_knot,
  543.     knot_str_type *normal_knot, knot_str_type *texture_knot)
  544. {
  545.     if(geom_knot->unified_knot)
  546.         free(geom_knot->unified_knot);
  547.     if(color_knot->unified_knot)
  548.         free(color_knot->unified_knot);
  549.     if(normal_knot->unified_knot)
  550.         free(normal_knot->unified_knot);
  551.     if(texture_knot->unified_knot)
  552.         free(texture_knot->unified_knot);
  553. }
  554.  
  555. /* covert curves - geometry and possible attribute ones into equivalent */
  556. /* sequence of adjacent Bezier curves */
  557. static GLenum
  558. convert_curves(GLUnurbsObj *nobj, GLfloat **new_geom_ctrl,
  559.     GLint *ncontrol, GLfloat **new_color_ctrl, GLfloat **new_normal_ctrl,
  560.     GLfloat **new_texture_ctrl)
  561. {
  562.     knot_str_type    geom_knot,color_knot,normal_knot,texture_knot;
  563.     GLint            junk;
  564.     GLenum            err;
  565.  
  566.     *new_color_ctrl=*new_normal_ctrl=*new_texture_ctrl=NULL;
  567.  
  568.     /* unify knots - all knots should have the same number of working */
  569.     /* ranges */
  570.     if((err=unify_knots(nobj,&geom_knot,&color_knot,&normal_knot,&texture_knot))
  571.             !=GLU_NO_ERROR)
  572.     {
  573.         return err;
  574.     }
  575.     /* convert the geometry curve */
  576.     nobj->curve.geom.dim=get_curve_dim(nobj->curve.geom.type);
  577.     if((err=convert_curve(&geom_knot,&(nobj->curve.geom),new_geom_ctrl,
  578.                         ncontrol))!=GLU_NO_ERROR)
  579.     {
  580.         free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  581.         call_user_error(nobj,err);
  582.         return err;
  583.     }
  584.     /* if additional attributive curves are given convert them as well */
  585.     if(color_knot.unified_knot)
  586.     {
  587.         nobj->curve.color.dim=get_curve_dim(nobj->curve.color.type);
  588.         if((err=convert_curve(&color_knot,&(nobj->curve.color),
  589.             new_color_ctrl,&junk))!=GLU_NO_ERROR)
  590.         {
  591.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  592.             free(*new_geom_ctrl);
  593.             call_user_error(nobj,err);
  594.             return err;
  595.         }
  596.     }
  597.     if(normal_knot.unified_knot)
  598.     {
  599.         nobj->curve.normal.dim=get_curve_dim(nobj->curve.normal.type);
  600.         if((err=convert_curve(&normal_knot,&(nobj->curve.normal),
  601.             new_normal_ctrl,&junk))!=GLU_NO_ERROR)
  602.         {
  603.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  604.             free(*new_geom_ctrl);
  605.             if(*new_color_ctrl)
  606.                 free(*new_color_ctrl);
  607.             call_user_error(nobj,err);
  608.             return err;
  609.         }
  610.     }
  611.     if(texture_knot.unified_knot)
  612.     {
  613.         nobj->curve.texture.dim=get_curve_dim(nobj->curve.texture.type);
  614.         if((err=convert_curve(&texture_knot,&(nobj->curve.texture),
  615.             new_texture_ctrl,&junk))!=GLU_NO_ERROR)
  616.         {
  617.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  618.             free(*new_geom_ctrl);
  619.             if(*new_color_ctrl)
  620.                 free(*new_color_ctrl);
  621.             if(*new_normal_ctrl)
  622.                 free(*new_normal_ctrl);
  623.             call_user_error(nobj,err);
  624.             return err;
  625.         }
  626.     }
  627.     return GLU_NO_ERROR;
  628. }
  629.  
  630. /* main NURBS curve procedure */
  631. void do_nurbs_curve( GLUnurbsObj *nobj)
  632. {
  633.     GLint geom_order,color_order=0,normal_order=0,texture_order=0;
  634.     GLenum geom_type;
  635.     GLint n_ctrl;
  636.     GLfloat *new_geom_ctrl,*new_color_ctrl,*new_normal_ctrl,*new_texture_ctrl;
  637.     GLfloat *geom_ctrl,*color_ctrl,*normal_ctrl,*texture_ctrl;
  638.     GLint *factors;
  639.     GLint i,j;
  640.     GLint geom_dim,color_dim=0,normal_dim=0,texture_dim=0;
  641.  
  642.     /* test the user supplied data */
  643.     if(test_nurbs_curves(nobj)!=GLU_NO_ERROR)
  644.         return;
  645.  
  646.     if(convert_curves(nobj,&new_geom_ctrl,&n_ctrl,&new_color_ctrl,
  647.                     &new_normal_ctrl,&new_texture_ctrl)!=GLU_NO_ERROR)
  648.         return;
  649.  
  650.     geom_order=nobj->curve.geom.order;
  651.     geom_type=nobj->curve.geom.type;
  652.     geom_dim=nobj->curve.geom.dim;
  653.  
  654.     if(glu_do_sampling_2D(nobj,new_geom_ctrl,n_ctrl,geom_order,geom_dim,
  655.                         &factors)
  656.         !=GLU_NO_ERROR)
  657.     {
  658.         free(new_geom_ctrl);
  659.         if(new_color_ctrl)
  660.             free(new_color_ctrl);
  661.         if(new_normal_ctrl)
  662.             free(new_normal_ctrl);
  663.         if(new_texture_ctrl)
  664.             free(new_texture_ctrl);
  665.         return;
  666.     }
  667.     glEnable(geom_type);
  668.     if(new_color_ctrl)
  669.     {
  670.         glEnable(nobj->curve.color.type);
  671.         color_dim=nobj->curve.color.dim;
  672.         color_ctrl=new_color_ctrl;
  673.         color_order=nobj->curve.color.order;
  674.     }
  675.     if(new_normal_ctrl)
  676.     {
  677.         glEnable(nobj->curve.normal.type);
  678.         normal_dim=nobj->curve.normal.dim;
  679.         normal_ctrl=new_normal_ctrl;
  680.         normal_order=nobj->curve.normal.order;
  681.     }
  682.     if(new_texture_ctrl)
  683.     {
  684.         glEnable(nobj->curve.texture.type);
  685.         texture_dim=nobj->curve.texture.dim;
  686.         texture_ctrl=new_texture_ctrl;
  687.         texture_order=nobj->curve.texture.order;
  688.     }
  689.     for(i=0 , j=0, geom_ctrl=new_geom_ctrl;
  690.         i<n_ctrl;
  691.         i+=geom_order , j++ , geom_ctrl+=geom_order*geom_dim)
  692.     {
  693.         if(fine_culling_test_2D(nobj,geom_ctrl,geom_order,geom_dim,geom_dim))
  694.         {
  695.             color_ctrl+=color_order*color_dim;
  696.             normal_ctrl+=normal_order*normal_dim;
  697.             texture_ctrl+=texture_order*texture_dim;
  698.             continue;
  699.         }
  700.         glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
  701.         if(new_color_ctrl)
  702.         {
  703.             glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
  704.                 color_order,color_ctrl);
  705.             color_ctrl+=color_order*color_dim;
  706.         }
  707.         if(new_normal_ctrl)
  708.         {
  709.             glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
  710.                 normal_order,normal_ctrl);
  711.             normal_ctrl+=normal_order*normal_dim;
  712.         }
  713.         if(new_texture_ctrl)
  714.         {
  715.             glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
  716.                 texture_order,texture_ctrl);
  717.             texture_ctrl+=texture_order*texture_dim;
  718.         }
  719.         glMapGrid1f(factors[j],0.0,1.0);
  720.         glEvalMesh1(GL_LINE,0,factors[j]);
  721.     }
  722.     free(new_geom_ctrl);
  723.     free(factors);
  724.     if(new_color_ctrl)
  725.         free(new_color_ctrl);
  726.     if(new_normal_ctrl)
  727.         free(new_normal_ctrl);
  728.     if(new_texture_ctrl)
  729.         free(new_texture_ctrl);
  730. }
  731.  
  732.  
  733.