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

  1. /* $Id: nurbssrf.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: nurbssrf.c,v $
  26.  * Revision 1.1.1.1  1999/08/19 00:55:42  jtg
  27.  * Imported sources
  28.  *
  29.  * Revision 1.7  1997/07/24 01:28:44  brianp
  30.  * changed precompiled header symbol from PCH to PC_HEADER
  31.  *
  32.  * Revision 1.6  1997/06/23 00:22:07  brianp
  33.  * include <string.h>
  34.  *
  35.  * Revision 1.5  1997/05/28 02:29:38  brianp
  36.  * added support for precompiled headers (PCH), inserted APIENTRY keyword
  37.  *
  38.  * Revision 1.4  1997/05/27 03:20:35  brianp
  39.  * minor clean-up
  40.  *
  41.  * Revision 1.3  1997/05/27 03:00:16  brianp
  42.  * incorporated Bogdan's new NURBS code
  43.  *
  44.  * Revision 1.2  1996/09/27 23:13:02  brianp
  45.  * added return 0 to get_surface_dim() to silence warning
  46.  *
  47.  * Revision 1.1  1996/09/27 01:19:39  brianp
  48.  * Initial revision
  49.  *
  50.  */
  51.  
  52.  
  53. /*
  54.  * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
  55.  * See README2 for more info.
  56.  */
  57.  
  58.  
  59. #ifdef PC_HEADER
  60. #include "all.h"
  61. #else
  62. #include <math.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include "gluP.h"
  66. #include "nurbs.h"
  67. #endif
  68.  
  69.  
  70. static int
  71. get_surface_dim(GLenum type)
  72. {
  73.     switch(type)
  74.     {
  75.         case GL_MAP2_VERTEX_3:            return 3;
  76.         case GL_MAP2_VERTEX_4:            return 4;
  77.         case GL_MAP2_INDEX:                return 1;
  78.         case GL_MAP2_COLOR_4:            return 4;
  79.         case GL_MAP2_NORMAL:            return 3;
  80.         case GL_MAP2_TEXTURE_COORD_1:    return 1;
  81.         case GL_MAP2_TEXTURE_COORD_2:    return 2;
  82.         case GL_MAP2_TEXTURE_COORD_3:    return 3;
  83.         case GL_MAP2_TEXTURE_COORD_4:    return 4;
  84.                 default:  abort();  /* TODO: is this OK? */
  85.     }
  86.         return 0; /*never get here*/
  87. }
  88.  
  89. static GLenum
  90. test_nurbs_surface(GLUnurbsObj *nobj, surface_attribs *attrib)
  91. {
  92.     GLenum err;
  93.     GLint tmp_int;
  94.  
  95.     if(attrib->sorder < 0 || attrib->torder < 0)
  96.     {
  97.         call_user_error(nobj,GLU_INVALID_VALUE);
  98.         return GLU_ERROR;
  99.     }
  100.     glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
  101.     if(attrib->sorder > tmp_int || attrib->sorder < 2)
  102.     {
  103.         call_user_error(nobj,GLU_NURBS_ERROR1);
  104.         return GLU_ERROR;
  105.     }
  106.     if(attrib->torder > tmp_int || attrib->torder < 2)
  107.     {
  108.         call_user_error(nobj,GLU_NURBS_ERROR1);
  109.         return GLU_ERROR;
  110.     }
  111.     if(attrib->sknot_count < attrib->sorder +2)
  112.     {
  113.         call_user_error(nobj,GLU_NURBS_ERROR2);
  114.         return GLU_ERROR;
  115.     }
  116.     if(attrib->tknot_count < attrib->torder +2)
  117.     {
  118.         call_user_error(nobj,GLU_NURBS_ERROR2);
  119.         return GLU_ERROR;
  120.     }
  121.     if(attrib->s_stride < 0 || attrib->t_stride < 0)
  122.     {
  123.         call_user_error(nobj,GLU_NURBS_ERROR34);
  124.         return GLU_ERROR;
  125.     }
  126.     if(attrib->sknot==NULL || attrib->tknot==NULL || attrib->ctrlarray==NULL)
  127.     {
  128.         call_user_error(nobj,GLU_NURBS_ERROR36);
  129.         return GLU_ERROR;
  130.     }
  131.     if((err=test_knot(attrib->tknot_count,attrib->tknot,attrib->torder))
  132.         !=GLU_NO_ERROR)
  133.     {
  134.         call_user_error(nobj,err);
  135.         return GLU_ERROR;
  136.     }
  137.     if((err=test_knot(attrib->sknot_count,attrib->sknot,attrib->sorder))
  138.         !=GLU_NO_ERROR)
  139.     {
  140.         call_user_error(nobj,err);
  141.         return GLU_ERROR;
  142.     }
  143.     return GLU_NO_ERROR;
  144. }
  145.  
  146. static GLenum
  147. test_nurbs_surfaces(GLUnurbsObj *nobj)
  148. {
  149.     /* test the geometric data */
  150.     if(test_nurbs_surface(nobj,&(nobj->surface.geom))!=GLU_NO_ERROR)
  151.         return GLU_ERROR;
  152.     /* now test the attributive data */
  153.     /* color */
  154.     if(nobj->surface.color.type!=GLU_INVALID_ENUM)
  155.         if(test_nurbs_surface(nobj,&(nobj->surface.color))!=GLU_NO_ERROR)
  156.             return GLU_ERROR;
  157.     /* normal */
  158.     if(nobj->surface.normal.type!=GLU_INVALID_ENUM)
  159.         if(test_nurbs_surface(nobj,&(nobj->surface.normal))!=GLU_NO_ERROR)
  160.             return GLU_ERROR;
  161.     /* texture */
  162.     if(nobj->surface.texture.type!=GLU_INVALID_ENUM)
  163.         if(test_nurbs_surface(nobj,&(nobj->surface.texture))!=GLU_NO_ERROR)
  164.             return GLU_ERROR;
  165.     return GLU_NO_ERROR;
  166. }
  167.  
  168. static GLenum
  169. convert_surf(knot_str_type *s_knot, knot_str_type *t_knot,
  170.     surface_attribs *attrib, GLfloat **new_ctrl,
  171.     GLint *s_n_ctrl, GLint *t_n_ctrl)
  172. {
  173.     GLfloat **tmp_ctrl;
  174.     GLfloat *ctrl_offset;
  175.     GLint tmp_n_control;
  176.     GLint i,j,t_cnt,s_cnt;
  177.     GLint tmp_stride;
  178.     GLint dim;
  179.     GLenum err;
  180.  
  181.     /* valid range is empty? */
  182.     if((s_knot->unified_knot !=NULL && s_knot->unified_nknots==0) || 
  183.         (t_knot->unified_knot !=NULL && t_knot->unified_nknots==0))
  184.     {
  185.         if(s_knot->unified_knot)
  186.         {
  187.             free(s_knot->unified_knot);
  188.             s_knot->unified_knot=NULL;
  189.         }
  190.         if(t_knot->unified_knot)
  191.         {
  192.             free(t_knot->unified_knot);
  193.             t_knot->unified_knot=NULL;
  194.         }
  195.         *s_n_ctrl=0;
  196.         *t_n_ctrl=0;
  197.         return GLU_NO_ERROR;
  198.     }
  199.     t_cnt=attrib->tknot_count-attrib->torder;
  200.     s_cnt=attrib->sknot_count-attrib->sorder;
  201.     if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*t_cnt))==NULL)
  202.         return GLU_OUT_OF_MEMORY;
  203.     if((err=explode_knot(s_knot))!=GLU_NO_ERROR)
  204.     {
  205.         free(tmp_ctrl);
  206.         if(s_knot->unified_knot)
  207.         {
  208.             free(s_knot->unified_knot);
  209.             s_knot->unified_knot=NULL;
  210.         }
  211.         return err;
  212.     }
  213.     if(s_knot->unified_knot)
  214.     {
  215.         free(s_knot->unified_knot);
  216.         s_knot->unified_knot=NULL;
  217.     }
  218.     if((err=calc_alphas(s_knot))!=GLU_NO_ERROR)
  219.     {
  220.         free(tmp_ctrl);
  221.         free(s_knot->new_knot);
  222.         return err;
  223.     }
  224.     free(s_knot->new_knot);
  225.     ctrl_offset=attrib->ctrlarray;
  226.     dim=attrib->dim;
  227.     for(i=0;i<t_cnt;i++)
  228.     {
  229.         if((err=calc_new_ctrl_pts(ctrl_offset,attrib->s_stride,s_knot,
  230.             dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR)
  231.         {
  232.             for(--i;i<=0;i--)
  233.                 free(tmp_ctrl[i]);
  234.             free(tmp_ctrl);
  235.             free(s_knot->alpha);
  236.             return err;
  237.         }
  238.         ctrl_offset+=attrib->t_stride;
  239.     }
  240.     free(s_knot->alpha);
  241.     tmp_stride=dim*tmp_n_control;
  242.     if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*t_cnt))
  243.         ==NULL)
  244.     {
  245.         for(i=0;i<t_cnt;i++)
  246.             free(tmp_ctrl[i]);
  247.         free(tmp_ctrl);
  248.         return GLU_OUT_OF_MEMORY;
  249.     }
  250.     for(i=0;i<tmp_n_control;i++)
  251.         for(j=0;j<t_cnt;j++)
  252.             MEMCPY(*new_ctrl+j*dim+i*dim*t_cnt,tmp_ctrl[j]+dim*i,
  253.                 sizeof(GLfloat)*dim);
  254.     for(i=0;i<t_cnt;i++)
  255.         free(tmp_ctrl[i]);
  256.     free(tmp_ctrl);
  257.     *s_n_ctrl=tmp_n_control;
  258.     
  259.     if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*(*s_n_ctrl)))==NULL)
  260.     {
  261.         return GLU_OUT_OF_MEMORY;
  262.     }
  263.     if((err=explode_knot(t_knot))!=GLU_NO_ERROR)
  264.     {
  265.         free(tmp_ctrl);
  266.         if(t_knot->unified_knot)
  267.         {
  268.             free(t_knot->unified_knot);
  269.             t_knot->unified_knot=NULL;
  270.         }
  271.         return err;
  272.     }
  273.     if(t_knot->unified_knot)
  274.     {
  275.         free(t_knot->unified_knot);
  276.         t_knot->unified_knot=NULL;
  277.     }
  278.     if((err=calc_alphas(t_knot))!=GLU_NO_ERROR)
  279.     {
  280.         free(tmp_ctrl);
  281.         free(t_knot->new_knot);
  282.         return err;
  283.     }
  284.     free(t_knot->new_knot);
  285.     ctrl_offset=*new_ctrl;
  286.     for(i=0;i<(*s_n_ctrl);i++)
  287.     {
  288.         if((err=calc_new_ctrl_pts(ctrl_offset,dim,t_knot,
  289.             dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR)
  290.         {
  291.             for(--i;i<=0;i--)
  292.                 free(tmp_ctrl[i]);
  293.             free(tmp_ctrl);
  294.             free(t_knot->alpha);
  295.             return err;
  296.         }
  297.         ctrl_offset+=dim*t_cnt;
  298.     }
  299.     free(t_knot->alpha);
  300.     free(*new_ctrl);
  301.     tmp_stride=dim*tmp_n_control;
  302.     if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*(*s_n_ctrl)))
  303.         ==NULL)
  304.     {
  305.         for(i=0;i<(*s_n_ctrl);i++)
  306.             free(tmp_ctrl[i]);
  307.         free(tmp_ctrl);
  308.         return GLU_OUT_OF_MEMORY;
  309.     }
  310.     for(i=0;i<(*s_n_ctrl);i++)
  311.     {
  312.         MEMCPY(*new_ctrl+i*tmp_stride,tmp_ctrl[i],sizeof(GLfloat)*tmp_stride);
  313.         free(tmp_ctrl[i]);
  314.     }
  315.     free(tmp_ctrl);
  316.     *t_n_ctrl=tmp_n_control;
  317.     return GLU_NO_ERROR;
  318. }
  319.  
  320. /* prepare the knot information structures */
  321. static GLenum
  322. fill_knot_structures(GLUnurbsObj *nobj,
  323.     knot_str_type *geom_s_knot, knot_str_type *geom_t_knot,
  324.     knot_str_type *color_s_knot, knot_str_type *color_t_knot,
  325.     knot_str_type *normal_s_knot,  knot_str_type *normal_t_knot,
  326.     knot_str_type *texture_s_knot, knot_str_type *texture_t_knot)
  327. {
  328.     GLint order;
  329.     GLfloat *knot;
  330.     GLint nknots;
  331.     GLint t_min,t_max;
  332.  
  333.     geom_s_knot->unified_knot=NULL;
  334.     knot=geom_s_knot->knot=nobj->surface.geom.sknot;
  335.     nknots=geom_s_knot->nknots=nobj->surface.geom.sknot_count;
  336.     order=geom_s_knot->order=nobj->surface.geom.sorder;
  337.     geom_s_knot->delta_nknots=0;
  338.     t_min=geom_s_knot->t_min=order-1;
  339.     t_max=geom_s_knot->t_max=nknots-order;
  340.     if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  341.     {
  342.         call_user_error(nobj,GLU_NURBS_ERROR3);
  343.         return GLU_ERROR;
  344.     }
  345.     if(fabs(knot[0]-knot[t_min])<EPSILON)
  346.     {
  347.         /* knot open at beggining */
  348.         geom_s_knot->open_at_begin=GL_TRUE;
  349.     }
  350.     else
  351.         geom_s_knot->open_at_begin=GL_FALSE;
  352.     if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  353.     {
  354.         /* knot open at end */
  355.         geom_s_knot->open_at_end=GL_TRUE;
  356.     }
  357.     else
  358.         geom_s_knot->open_at_end=GL_FALSE;
  359.     geom_t_knot->unified_knot=NULL;
  360.     knot=geom_t_knot->knot=nobj->surface.geom.tknot;
  361.     nknots=geom_t_knot->nknots=nobj->surface.geom.tknot_count;
  362.     order=geom_t_knot->order=nobj->surface.geom.torder;
  363.     geom_t_knot->delta_nknots=0;
  364.     t_min=geom_t_knot->t_min=order-1;
  365.     t_max=geom_t_knot->t_max=nknots-order;
  366.     if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  367.     {
  368.         call_user_error(nobj,GLU_NURBS_ERROR3);
  369.         return GLU_ERROR;
  370.     }
  371.     if(fabs(knot[0]-knot[t_min])<EPSILON)
  372.     {
  373.         /* knot open at beggining */
  374.         geom_t_knot->open_at_begin=GL_TRUE;
  375.     }
  376.     else
  377.         geom_t_knot->open_at_begin=GL_FALSE;
  378.     if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  379.     {
  380.         /* knot open at end */
  381.         geom_t_knot->open_at_end=GL_TRUE;
  382.     }
  383.     else
  384.         geom_t_knot->open_at_end=GL_FALSE;
  385.  
  386.     if(nobj->surface.color.type!=GLU_INVALID_ENUM)
  387.     {
  388.         color_s_knot->unified_knot=(GLfloat *)1;
  389.         knot=color_s_knot->knot=nobj->surface.color.sknot;
  390.         nknots=color_s_knot->nknots=nobj->surface.color.sknot_count;
  391.         order=color_s_knot->order=nobj->surface.color.sorder;
  392.         color_s_knot->delta_nknots=0;
  393.         t_min=color_s_knot->t_min=order-1;
  394.         t_max=color_s_knot->t_max=nknots-order;
  395.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  396.         {
  397.             call_user_error(nobj,GLU_NURBS_ERROR3);
  398.             return GLU_ERROR;
  399.         }
  400.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  401.         {
  402.             /* knot open at beggining */
  403.             color_s_knot->open_at_begin=GL_TRUE;
  404.         }
  405.         else
  406.             color_s_knot->open_at_begin=GL_FALSE;
  407.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  408.         {
  409.             /* knot open at end */
  410.             color_s_knot->open_at_end=GL_TRUE;
  411.         }
  412.         else
  413.             color_s_knot->open_at_end=GL_FALSE;
  414.         color_t_knot->unified_knot=(GLfloat *)1;
  415.         knot=color_t_knot->knot=nobj->surface.color.tknot;
  416.         nknots=color_t_knot->nknots=nobj->surface.color.tknot_count;
  417.         order=color_t_knot->order=nobj->surface.color.torder;
  418.         color_t_knot->delta_nknots=0;
  419.         t_min=color_t_knot->t_min=order-1;
  420.         t_max=color_t_knot->t_max=nknots-order;
  421.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  422.         {
  423.             call_user_error(nobj,GLU_NURBS_ERROR3);
  424.             return GLU_ERROR;
  425.         }
  426.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  427.         {
  428.             /* knot open at beggining */
  429.             color_t_knot->open_at_begin=GL_TRUE;
  430.         }
  431.         else
  432.             color_t_knot->open_at_begin=GL_FALSE;
  433.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  434.         {
  435.             /* knot open at end */
  436.             color_t_knot->open_at_end=GL_TRUE;
  437.         }
  438.         else
  439.             color_t_knot->open_at_end=GL_FALSE;
  440.     }
  441.     else
  442.     {
  443.         color_s_knot->unified_knot=NULL;
  444.         color_t_knot->unified_knot=NULL;
  445.     }
  446.  
  447.     if(nobj->surface.normal.type!=GLU_INVALID_ENUM)
  448.     {
  449.         normal_s_knot->unified_knot=(GLfloat *)1;
  450.         knot=normal_s_knot->knot=nobj->surface.normal.sknot;
  451.         nknots=normal_s_knot->nknots=nobj->surface.normal.sknot_count;
  452.         order=normal_s_knot->order=nobj->surface.normal.sorder;
  453.         normal_s_knot->delta_nknots=0;
  454.         t_min=normal_s_knot->t_min=order-1;
  455.         t_max=normal_s_knot->t_max=nknots-order;
  456.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  457.         {
  458.             call_user_error(nobj,GLU_NURBS_ERROR3);
  459.             return GLU_ERROR;
  460.         }
  461.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  462.         {
  463.             /* knot open at beggining */
  464.             normal_s_knot->open_at_begin=GL_TRUE;
  465.         }
  466.         else
  467.             normal_s_knot->open_at_begin=GL_FALSE;
  468.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  469.         {
  470.             /* knot open at end */
  471.             normal_s_knot->open_at_end=GL_TRUE;
  472.         }
  473.         else
  474.             normal_s_knot->open_at_end=GL_FALSE;
  475.         normal_t_knot->unified_knot=(GLfloat *)1;
  476.         knot=normal_t_knot->knot=nobj->surface.normal.tknot;
  477.         nknots=normal_t_knot->nknots=nobj->surface.normal.tknot_count;
  478.         order=normal_t_knot->order=nobj->surface.normal.torder;
  479.         normal_t_knot->delta_nknots=0;
  480.         t_min=normal_t_knot->t_min=order-1;
  481.         t_max=normal_t_knot->t_max=nknots-order;
  482.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  483.         {
  484.             call_user_error(nobj,GLU_NURBS_ERROR3);
  485.             return GLU_ERROR;
  486.         }
  487.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  488.         {
  489.             /* knot open at beggining */
  490.             normal_t_knot->open_at_begin=GL_TRUE;
  491.         }
  492.         else
  493.             normal_t_knot->open_at_begin=GL_FALSE;
  494.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  495.         {
  496.             /* knot open at end */
  497.             normal_t_knot->open_at_end=GL_TRUE;
  498.         }
  499.         else
  500.             normal_t_knot->open_at_end=GL_FALSE;
  501.     }
  502.     else
  503.     {
  504.         normal_s_knot->unified_knot=NULL;
  505.         normal_t_knot->unified_knot=NULL;
  506.     }
  507.  
  508.     if(nobj->surface.texture.type!=GLU_INVALID_ENUM)
  509.     {
  510.         texture_s_knot->unified_knot=(GLfloat *)1;
  511.         knot=texture_s_knot->knot=nobj->surface.texture.sknot;
  512.         nknots=texture_s_knot->nknots=nobj->surface.texture.sknot_count;
  513.         order=texture_s_knot->order=nobj->surface.texture.sorder;
  514.         texture_s_knot->delta_nknots=0;
  515.         t_min=texture_s_knot->t_min=order-1;
  516.         t_max=texture_s_knot->t_max=nknots-order;
  517.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  518.         {
  519.             call_user_error(nobj,GLU_NURBS_ERROR3);
  520.             return GLU_ERROR;
  521.         }
  522.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  523.         {
  524.             /* knot open at beggining */
  525.             texture_s_knot->open_at_begin=GL_TRUE;
  526.         }
  527.         else
  528.             texture_s_knot->open_at_begin=GL_FALSE;
  529.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  530.         {
  531.             /* knot open at end */
  532.             texture_s_knot->open_at_end=GL_TRUE;
  533.         }
  534.         else
  535.             texture_s_knot->open_at_end=GL_FALSE;
  536.         texture_t_knot->unified_knot=(GLfloat *)1;
  537.         knot=texture_t_knot->knot=nobj->surface.texture.tknot;
  538.         nknots=texture_t_knot->nknots=nobj->surface.texture.tknot_count;
  539.         order=texture_t_knot->order=nobj->surface.texture.torder;
  540.         texture_t_knot->delta_nknots=0;
  541.         t_min=texture_t_knot->t_min=order-1;
  542.         t_max=texture_t_knot->t_max=nknots-order;
  543.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  544.         {
  545.             call_user_error(nobj,GLU_NURBS_ERROR3);
  546.             return GLU_ERROR;
  547.         }
  548.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  549.         {
  550.             /* knot open at beggining */
  551.             texture_t_knot->open_at_begin=GL_TRUE;
  552.         }
  553.         else
  554.             texture_t_knot->open_at_begin=GL_FALSE;
  555.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  556.         {
  557.             /* knot open at end */
  558.             texture_t_knot->open_at_end=GL_TRUE;
  559.         }
  560.         else
  561.             texture_t_knot->open_at_end=GL_FALSE;
  562.     }
  563.     else
  564.     {
  565.         texture_s_knot->unified_knot=NULL;
  566.         texture_t_knot->unified_knot=NULL;
  567.     }
  568.     return GLU_NO_ERROR;
  569. }
  570.  
  571. void
  572. free_new_ctrl(new_ctrl_type *p)
  573. {
  574.     if(p->geom_ctrl)
  575.         free(p->geom_ctrl);
  576.     if(p->geom_offsets)
  577.         free(p->geom_offsets);
  578.     if(p->color_ctrl)
  579.     {
  580.         free(p->color_ctrl);
  581.         if(p->color_offsets)
  582.             free(p->color_offsets);
  583.     }
  584.     if(p->normal_ctrl)
  585.     {
  586.         free(p->normal_ctrl);
  587.         if(p->normal_offsets)
  588.             free(p->normal_offsets);
  589.     }
  590.     if(p->texture_ctrl)
  591.     {
  592.         free(p->texture_ctrl);
  593.         if(p->texture_offsets)
  594.             free(p->texture_offsets);
  595.     }
  596. }
  597.  
  598. /* convert surfaces - geometry and possible attribute ones into equivalent */
  599. /* sequence of adjacent Bezier patches */
  600. static GLenum
  601. convert_surfs(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl)
  602. {
  603.     knot_str_type    geom_s_knot,color_s_knot,normal_s_knot,texture_s_knot;
  604.     knot_str_type    geom_t_knot,color_t_knot,normal_t_knot,texture_t_knot;
  605.     GLenum            err;
  606.  
  607.     if((err=fill_knot_structures(nobj,&geom_s_knot,&geom_t_knot,
  608.         &color_s_knot,&color_t_knot,&normal_s_knot,&normal_t_knot,
  609.         &texture_s_knot,&texture_t_knot)) !=GLU_NO_ERROR)
  610.     {
  611.         return err;
  612.     }
  613.     /* unify knots - all knots should have the same working range */
  614.     if((err=select_knot_working_range(nobj,&geom_s_knot,&color_s_knot,
  615.         &normal_s_knot,&texture_s_knot)) !=GLU_NO_ERROR)
  616.     {
  617.         call_user_error(nobj,err);
  618.         return err;
  619.     }
  620.     if((err=select_knot_working_range(nobj,&geom_t_knot,&color_t_knot,
  621.         &normal_t_knot,&texture_t_knot)) !=GLU_NO_ERROR)
  622.     {
  623.         free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot,
  624.             &texture_s_knot);
  625.         call_user_error(nobj,err);
  626.         return err;
  627.     }
  628.  
  629.     /* convert the geometry surface */
  630.     nobj->surface.geom.dim=get_surface_dim(nobj->surface.geom.type);
  631.     if((err=convert_surf(&geom_s_knot,&geom_t_knot,&(nobj->surface.geom),
  632.         &(new_ctrl->geom_ctrl),&(new_ctrl->geom_s_pt_cnt),
  633.         &(new_ctrl->geom_t_pt_cnt)))!=GLU_NO_ERROR)
  634.     {
  635.         free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot,
  636.             &texture_s_knot);
  637.         free_unified_knots(&geom_t_knot,&color_t_knot,&normal_t_knot,
  638.             &texture_t_knot);
  639.         call_user_error(nobj,err);
  640.         return err;
  641.     }
  642.     /* if additional attributive surfaces are given convert them as well */
  643.     if(color_s_knot.unified_knot)
  644.     {
  645.         nobj->surface.color.dim=get_surface_dim(nobj->surface.color.type);
  646.         if((err=convert_surf(&color_s_knot,&color_t_knot,&(nobj->surface.color),
  647.             &(new_ctrl->color_ctrl),&(new_ctrl->color_s_pt_cnt),
  648.             &(new_ctrl->color_t_pt_cnt)))!=GLU_NO_ERROR)
  649.         {
  650.             free_unified_knots(&color_s_knot,&color_s_knot,&normal_s_knot,
  651.                 &texture_s_knot);
  652.             free_unified_knots(&color_t_knot,&color_t_knot,&normal_t_knot,
  653.                 &texture_t_knot);
  654.             free_new_ctrl(new_ctrl);
  655.             call_user_error(nobj,err);
  656.             return err;
  657.         }
  658.     }
  659.     if(normal_s_knot.unified_knot)
  660.     {
  661.         nobj->surface.normal.dim=get_surface_dim(nobj->surface.normal.type);
  662.         if((err=convert_surf(&normal_s_knot,&normal_t_knot,
  663.             &(nobj->surface.normal),
  664.             &(new_ctrl->normal_ctrl),&(new_ctrl->normal_s_pt_cnt),
  665.             &(new_ctrl->normal_t_pt_cnt)))!=GLU_NO_ERROR)
  666.         {
  667.             free_unified_knots(&normal_s_knot,&normal_s_knot,&normal_s_knot,
  668.                 &texture_s_knot);
  669.             free_unified_knots(&normal_t_knot,&normal_t_knot,&normal_t_knot,
  670.                 &texture_t_knot);
  671.             free_new_ctrl(new_ctrl);
  672.             call_user_error(nobj,err);
  673.             return err;
  674.         }
  675.     }
  676.     if(texture_s_knot.unified_knot)
  677.     {
  678.         nobj->surface.texture.dim=get_surface_dim(nobj->surface.texture.type);
  679.         if((err=convert_surf(&texture_s_knot,&texture_t_knot,
  680.             &(nobj->surface.texture),
  681.             &(new_ctrl->texture_ctrl),&(new_ctrl->texture_s_pt_cnt),
  682.             &(new_ctrl->texture_t_pt_cnt)))!=GLU_NO_ERROR)
  683.         {
  684.             free_unified_knots(&texture_s_knot,&texture_s_knot,&texture_s_knot,
  685.                 &texture_s_knot);
  686.             free_unified_knots(&texture_t_knot,&texture_t_knot,&texture_t_knot,
  687.                 &texture_t_knot);
  688.             free_new_ctrl(new_ctrl);
  689.             call_user_error(nobj,err);
  690.             return err;
  691.         }
  692.     }
  693.     return GLU_NO_ERROR;
  694. }
  695.  
  696. /* tesselate the "boundary" Bezier edge strips */
  697. void
  698. tesselate_strip_t_line(GLint top_start,GLint top_end,GLint top_z,
  699.     GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain)
  700. {
  701.     GLint top_cnt,bottom_cnt,tri_cnt,k;
  702.     GLint direction;
  703.  
  704.     top_cnt=top_end-top_start;
  705.     direction= (top_cnt>=0 ? 1: -1);
  706.     bottom_cnt=bottom_end-bottom_start;
  707.     glBegin(GL_LINES);
  708.     while(top_cnt)
  709.     {
  710.         if(bottom_cnt)
  711.             tri_cnt=top_cnt/bottom_cnt;
  712.         else
  713.             tri_cnt=abs(top_cnt);
  714.         for(k=0;k<=tri_cnt;k++ , top_start+=direction)
  715.         {
  716.             glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
  717.                 (GLfloat)bottom_start/bottom_domain);
  718.             glEvalPoint2(top_z,top_start);
  719.         }
  720.         if(bottom_cnt)
  721.         {
  722.             glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
  723.                 (GLfloat)bottom_start/bottom_domain);
  724.             bottom_start+=direction;
  725.             top_start-=direction;
  726.             glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
  727.                 (GLfloat)bottom_start/bottom_domain);
  728.             glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
  729.                 (GLfloat)bottom_start/bottom_domain);
  730.             glEvalPoint2(top_z,top_start);
  731.         }
  732.         top_cnt-=direction*tri_cnt;
  733.         bottom_cnt-=direction;
  734.     }
  735.     glEnd();
  736. }
  737.  
  738. void
  739. tesselate_strip_t_fill(GLint top_start,GLint top_end,GLint top_z,
  740.     GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain)
  741. {
  742.     GLint top_cnt,bottom_cnt,tri_cnt,k;
  743.     GLint direction;
  744.  
  745.     top_cnt=top_end-top_start;
  746.     direction= (top_cnt>=0 ? 1: -1);
  747.     bottom_cnt=bottom_end-bottom_start;
  748.     while(top_cnt)
  749.     {
  750.         if(bottom_cnt)
  751.             tri_cnt=top_cnt/bottom_cnt;
  752.         else
  753.             tri_cnt=abs(top_cnt);
  754.         glBegin(GL_TRIANGLE_FAN);
  755.         glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
  756.             (GLfloat)bottom_start/bottom_domain);
  757.         for(k=0;k<=tri_cnt;k++ , top_start+=direction)
  758.             glEvalPoint2(top_z,top_start);
  759.         if(bottom_cnt)
  760.         {
  761.             bottom_start+=direction;
  762.             top_start-=direction;
  763.             glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
  764.                 (GLfloat)bottom_start/bottom_domain);
  765.         }
  766.         glEnd();
  767.         top_cnt-=direction*tri_cnt;
  768.         bottom_cnt-=direction;
  769.     }
  770. }
  771.  
  772. void
  773. tesselate_strip_t(GLenum display_mode, GLint top_start, GLint top_end, 
  774.     GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z, 
  775.     GLint bottom_domain)
  776. {
  777.     if(display_mode==GL_FILL)
  778.         tesselate_strip_t_fill(top_start,top_end,top_z,bottom_start,
  779.             bottom_end,bottom_z,bottom_domain);
  780.     else
  781.         tesselate_strip_t_line(top_start,top_end,top_z,bottom_start,
  782.             bottom_end,bottom_z,bottom_domain);
  783. }
  784.     
  785.  
  786. void
  787. tesselate_strip_s_fill(GLint top_start, GLint top_end, GLint top_z,
  788.     GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain)
  789. {
  790.     GLint top_cnt,bottom_cnt,tri_cnt,k;
  791.     GLint direction;
  792.  
  793.     top_cnt=top_end-top_start;
  794.     direction= (top_cnt>=0 ? 1: -1);
  795.     bottom_cnt=bottom_end-bottom_start;
  796.     while(top_cnt)
  797.     {
  798.         if(bottom_cnt)
  799.             tri_cnt=top_cnt/bottom_cnt;
  800.         else
  801.             tri_cnt=abs(top_cnt);
  802.         glBegin(GL_TRIANGLE_FAN);
  803.         glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
  804.             (GLfloat)bottom_z/bottom_domain);
  805.         for(k=0;k<=tri_cnt;k++ , top_start+=direction)
  806.             glEvalPoint2(top_start,top_z);
  807.         if(bottom_cnt)
  808.         {
  809.             bottom_start+=direction;
  810.             top_start-=direction;
  811.             glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
  812.                 (GLfloat)bottom_z/bottom_domain);
  813.         }
  814.         glEnd();
  815.         top_cnt-=direction*tri_cnt;
  816.         bottom_cnt-=direction;
  817.     }
  818. }
  819.  
  820. void
  821. tesselate_strip_s_line(GLint top_start, GLint top_end, GLint top_z,
  822.     GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain)
  823. {
  824.     GLint top_cnt,bottom_cnt,tri_cnt,k;
  825.     GLint direction;
  826.  
  827.     top_cnt=top_end-top_start;
  828.     direction= (top_cnt>=0 ? 1: -1);
  829.     bottom_cnt=bottom_end-bottom_start;
  830.     glBegin(GL_LINES);
  831.     while(top_cnt)
  832.     {
  833.         if(bottom_cnt)
  834.             tri_cnt=top_cnt/bottom_cnt;
  835.         else
  836.             tri_cnt=abs(top_cnt);
  837.         for(k=0;k<=tri_cnt;k++ , top_start+=direction)
  838.         {
  839.             glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
  840.                 (GLfloat)bottom_z/bottom_domain);
  841.             glEvalPoint2(top_start,top_z);
  842.         }
  843.         if(bottom_cnt)
  844.         {
  845.             glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
  846.                 (GLfloat)bottom_z/bottom_domain);
  847.             bottom_start+=direction;
  848.             top_start-=direction;
  849.             glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
  850.                 (GLfloat)bottom_z/bottom_domain);
  851.             glEvalPoint2(top_start,top_z);
  852.             glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
  853.                 (GLfloat)bottom_z/bottom_domain);
  854.         }
  855.         top_cnt-=direction*tri_cnt;
  856.         bottom_cnt-=direction;
  857.     }
  858.     glEnd();
  859. }
  860.  
  861. void
  862. tesselate_strip_s(GLenum display_mode, GLint top_start, GLint top_end,
  863.     GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z,
  864.     GLfloat bottom_domain)
  865. {
  866.     if(display_mode==GL_FILL)
  867.         tesselate_strip_s_fill(top_start,top_end,top_z,bottom_start,
  868.             bottom_end,bottom_z,bottom_domain);
  869.     else
  870.         tesselate_strip_s_line(top_start,top_end,top_z,bottom_start,
  871.             bottom_end,bottom_z,bottom_domain);
  872. }
  873.  
  874. void
  875. tesselate_bottom_left_corner(GLenum display_mode, GLfloat s_1, GLfloat t_1)
  876. {
  877.     if(display_mode==GL_FILL)
  878.     {
  879.         glBegin(GL_TRIANGLE_FAN);
  880.         glEvalPoint2(1,1);
  881.         glEvalCoord2f(s_1,0.0);
  882.         glEvalCoord2f(0.0,0.0);
  883.         glEvalCoord2f(0.0,t_1);
  884.     }
  885.     else
  886.     {
  887.         glBegin(GL_LINES);
  888.         glEvalCoord2f(0.0,0.0);
  889.         glEvalCoord2f(0.0,t_1);
  890.         glEvalCoord2f(0.0,0.0);
  891.         glEvalPoint2(1,1);
  892.         glEvalCoord2f(0.0,0.0);
  893.         glEvalCoord2f(s_1,0.0);
  894.     }
  895.     glEnd();
  896. }
  897.  
  898. void
  899. tesselate_bottom_right_corner(GLenum display_mode, GLint v_top,GLint v_bottom,
  900.     GLfloat s_1, GLfloat t_1)
  901. {
  902.     if(display_mode==GL_FILL)
  903.     {
  904.         glBegin(GL_TRIANGLE_FAN);
  905.         glEvalPoint2(1,v_top);
  906.         glEvalCoord2f(0.0,v_bottom*t_1);
  907.         glEvalCoord2f(0.0,(v_bottom+1)*t_1);
  908.         glEvalCoord2f(s_1,(v_bottom+1)*t_1);
  909.     }
  910.     else
  911.     {
  912.         glBegin(GL_LINES);
  913.         glEvalCoord2f(0.0,(v_bottom+1)*t_1);
  914.         glEvalPoint2(1,v_top);
  915.         glEvalCoord2f(0.0,(v_bottom+1)*t_1);
  916.         glEvalCoord2f(0.0,v_bottom*t_1);
  917.         glEvalCoord2f(0.0,(v_bottom+1)*t_1);
  918.         glEvalCoord2f(s_1,(v_bottom+1)*t_1);
  919.     }
  920.     glEnd();
  921. }
  922.  
  923. void
  924. tesselate_top_left_corner(GLenum display_mode, GLint u_right, GLint u_left,
  925.     GLfloat s_1, GLfloat t_1)
  926. {
  927.     if(display_mode==GL_FILL)
  928.     {
  929.         glBegin(GL_TRIANGLE_FAN);
  930.         glEvalPoint2(u_right,1);
  931.         glEvalCoord2f((u_left+1)*s_1,t_1);
  932.         glEvalCoord2f((u_left+1)*s_1,0.0);
  933.         glEvalCoord2f(u_left*s_1,0.0);
  934.     }
  935.     else
  936.     {
  937.         glBegin(GL_LINES);
  938.         glEvalCoord2f((u_left+1)*s_1,0.0);
  939.         glEvalPoint2(u_right,1);
  940.         glEvalCoord2f((u_left+1)*s_1,0.0);
  941.         glEvalCoord2f(u_left*s_1,0.0);
  942.         glEvalCoord2f((u_left+1)*s_1,0.0);
  943.         glEvalCoord2f((u_left+1)*s_1,t_1);
  944.     }
  945.     glEnd();
  946. }
  947.  
  948. void
  949. tesselate_top_right_corner(GLenum display_mode, GLint u_left, GLint v_bottom,
  950.     GLint u_right, GLint v_top, GLfloat s_1, GLfloat t_1)
  951. {
  952.     if(display_mode==GL_FILL)
  953.     {
  954.         glBegin(GL_TRIANGLE_FAN);
  955.         glEvalPoint2(u_left,v_bottom);
  956.         glEvalCoord2f((u_right-1)*s_1,v_top*t_1);
  957.         glEvalCoord2f(u_right*s_1,v_top*t_1);
  958.         glEvalCoord2f(u_right*s_1,(v_top-1)*t_1);
  959.     }
  960.     else
  961.     {
  962.         glBegin(GL_LINES);
  963.         glEvalCoord2f(u_right*s_1,v_top*t_1);
  964.         glEvalPoint2(u_left,v_bottom);
  965.         glEvalCoord2f(u_right*s_1,v_top*t_1);
  966.         glEvalCoord2f(u_right*s_1,(v_top-1)*t_1);
  967.         glEvalCoord2f(u_right*s_1,v_top*t_1);
  968.         glEvalCoord2f((u_right-1)*s_1,v_top*t_1);
  969.     }
  970.     glEnd();
  971. }
  972.  
  973. /* do mesh mapping of Bezier */
  974. static void
  975. nurbs_map_bezier(GLenum display_mode,GLint *sfactors,GLint *tfactors,
  976.     GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t)
  977. {
  978.     GLint        top,bottom,right,left;
  979.  
  980.  
  981.     if(s==0)
  982.     {
  983.         top=*(tfactors+t*3);
  984.         bottom=*(tfactors+t*3+1);
  985.     }
  986.     else
  987.     if(s==s_bezier_cnt-1)
  988.     {
  989.         top=*(tfactors+t*3+2);
  990.         bottom=*(tfactors+t*3);
  991.     }
  992.     else
  993.     {
  994.         top=bottom=*(tfactors+t*3);
  995.     }
  996.     if(t==0)
  997.     {
  998.         left=*(sfactors+s*3+1);
  999.         right=*(sfactors+s*3);
  1000.     }
  1001.     else
  1002.     if(t==t_bezier_cnt-1)
  1003.     {
  1004.         left=*(sfactors+s*3);
  1005.         right=*(sfactors+s*3+2);
  1006.     }
  1007.     else
  1008.     {
  1009.         left=right=*(sfactors+s*3);
  1010.     }
  1011.  
  1012.     if(top>bottom)
  1013.     {
  1014.         if(left<right)
  1015.         {
  1016.             glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
  1017.             glEvalMesh2(display_mode,1,right, 1, top);
  1018.             tesselate_strip_s(display_mode,1,right,1,1,left,0,(GLfloat)left);
  1019.             tesselate_bottom_left_corner(display_mode,(GLfloat)(1.0/left),
  1020.                 (GLfloat)(1.0/bottom));
  1021. /*            tesselate_strip_t(display_mode,1,top,1,1,bottom,0,(GLfloat)bottom);*/
  1022.             tesselate_strip_t(display_mode,top,1,1,bottom,1,0,(GLfloat)bottom);
  1023.         }
  1024.         else
  1025.         if(left==right)
  1026.         {
  1027.             glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
  1028.             glEvalMesh2(display_mode,1,right, 0, top);
  1029. /*            tesselate_strip_t(display_mode,0,top,1,0,bottom,0,(GLfloat)bottom);*/
  1030.             tesselate_strip_t(display_mode,top,0,1,bottom,0,0,(GLfloat)bottom);
  1031.         }
  1032.         else
  1033.         {
  1034.             glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0);
  1035.             glEvalMesh2(display_mode,1,left, 0, top-1);
  1036. /*            tesselate_strip_t(display_mode,0,top-1,1,0,bottom-1,0,
  1037.                 (GLfloat)bottom);*/
  1038.             tesselate_strip_t(display_mode,top-1,0,1,bottom-1,0,0,
  1039.                 (GLfloat)bottom);
  1040.             tesselate_bottom_right_corner(display_mode,top-1,bottom-1,
  1041.                 (GLfloat)(1.0/right),(GLfloat)(1.0/bottom));
  1042. /*            tesselate_strip_s(display_mode,1,left,top-1,1,right,right,
  1043.                 (GLfloat)right);*/
  1044.             tesselate_strip_s(display_mode,left,1,top-1,right,1,right,
  1045.                 (GLfloat)right);
  1046.         }
  1047.     }
  1048.     else
  1049.     if(top==bottom)
  1050.     {
  1051.         if(left<right)
  1052.         {
  1053.             glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
  1054.             glEvalMesh2(display_mode,0,right, 1, top);
  1055.             tesselate_strip_s(display_mode,0,right,1,0,left,0,(GLfloat)left);
  1056.         }
  1057.         else
  1058.         if(left==right)
  1059.         {
  1060.             glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
  1061.             glEvalMesh2(display_mode,0,right, 0, top);
  1062.         }
  1063.         else
  1064.         {
  1065.             glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0);
  1066.             glEvalMesh2(display_mode,0,left, 0, top-1);
  1067. /*            tesselate_strip_s(display_mode,0,left,top-1,0,right,right,
  1068.                 (GLfloat)right);*/
  1069.             tesselate_strip_s(display_mode,left,0,top-1,right,0,right,
  1070.                 (GLfloat)right);
  1071.         }
  1072.     }
  1073.     else
  1074.     {
  1075.         if(left<right)
  1076.         {
  1077.             glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0);
  1078.             glEvalMesh2(display_mode,0,right-1, 1, bottom);
  1079.             tesselate_strip_s(display_mode,0,right-1,1,0,left-1,0,
  1080.                 (GLfloat)left);
  1081.             tesselate_top_left_corner(display_mode,right-1,left-1,
  1082.                 (GLfloat)(1.0/left),(GLfloat)(1.0/top));
  1083.             tesselate_strip_t(display_mode,1,bottom,right-1,1,top,top,
  1084.                 (GLfloat)top);
  1085.         }
  1086.         else
  1087.         if(left==right)
  1088.         {
  1089.             glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0);
  1090.             glEvalMesh2(display_mode,0,right-1, 0, bottom);
  1091.             tesselate_strip_t(display_mode,0,bottom,right-1,0,top,top,
  1092.                 (GLfloat)top);
  1093.         }
  1094.         else
  1095.         {
  1096.             glMapGrid2f(left, 0.0, 1.0, bottom, 0.0, 1.0);
  1097.             glEvalMesh2(display_mode,0,left-1, 0, bottom-1);
  1098.             tesselate_strip_t(display_mode,0,bottom-1,left-1,0,top-1,top,
  1099.                 (GLfloat)top);
  1100.             tesselate_top_right_corner(display_mode,left-1,bottom-1,right,top,
  1101.                 (GLfloat)(1.0/right),(GLfloat)(1.0/top));
  1102. /*            tesselate_strip_s(display_mode,0,left-1,bottom-1,0,right-1,right,
  1103.                 (GLfloat)right);*/
  1104.             tesselate_strip_s(display_mode,left-1,0,bottom-1,right-1,0,right,
  1105.                 (GLfloat)right);
  1106.         }
  1107.     }
  1108. }
  1109.  
  1110. /* draw NURBS surface in OUTLINE POLYGON mode */
  1111. static void
  1112. draw_polygon_mode( GLenum display_mode, GLUnurbsObj *nobj,
  1113.     new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors )
  1114. {
  1115.     GLsizei                offset;
  1116.     GLint                t_bezier_cnt,s_bezier_cnt;
  1117.     GLboolean            do_color,do_normal,do_texture;
  1118.     GLint                i,j;
  1119.  
  1120.     t_bezier_cnt=new_ctrl->t_bezier_cnt;
  1121.     s_bezier_cnt=new_ctrl->s_bezier_cnt;
  1122.     glEnable(nobj->surface.geom.type);
  1123.     if(new_ctrl->color_ctrl)
  1124.     {
  1125.         glEnable(nobj->surface.color.type);
  1126.         do_color=GL_TRUE;
  1127.     }
  1128.     else
  1129.         do_color=GL_FALSE;
  1130.     if(new_ctrl->normal_ctrl)
  1131.     {
  1132.         glEnable(nobj->surface.normal.type);
  1133.         do_normal=GL_TRUE;
  1134.     }
  1135.     else
  1136.         do_normal=GL_FALSE;
  1137.     if(new_ctrl->texture_ctrl)
  1138.     {
  1139.         glEnable(nobj->surface.texture.type);
  1140.         do_texture=GL_TRUE;
  1141.     }
  1142.     else
  1143.         do_texture=GL_FALSE;
  1144.     for(j=0; j<s_bezier_cnt; j++)
  1145.     {
  1146.         for(i=0; i<t_bezier_cnt; i++)
  1147.         {
  1148.             offset=j*t_bezier_cnt + i;
  1149.             if(fine_culling_test_3D(nobj,*(new_ctrl->geom_offsets + offset),
  1150.                     nobj->surface.geom.sorder,nobj->surface.geom.torder,
  1151.                     new_ctrl->geom_s_stride,new_ctrl->geom_t_stride,
  1152.                     nobj->surface.geom.dim))
  1153.                 continue;
  1154.             glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride,
  1155.                 nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride,
  1156.                 nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset));
  1157.             if(do_color)
  1158.             {
  1159.                 glMap2f(nobj->surface.color.type,0.0,1.0,
  1160.                     new_ctrl->color_s_stride,nobj->surface.color.sorder,
  1161.                     0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder,
  1162.                     *(new_ctrl->color_offsets + offset));
  1163.             }
  1164.             if(do_normal)
  1165.             {
  1166.                 glMap2f(nobj->surface.normal.type,0.0,1.0,
  1167.                     new_ctrl->normal_s_stride,nobj->surface.normal.sorder,
  1168.                     0.0,1.0,new_ctrl->normal_t_stride,
  1169.                     nobj->surface.normal.torder,
  1170.                     *(new_ctrl->normal_offsets+offset));
  1171.             }
  1172.             if(do_texture)
  1173.             {
  1174.                 glMap2f(nobj->surface.texture.type,0.0,1.0,
  1175.                     new_ctrl->texture_s_stride,nobj->surface.texture.sorder,
  1176.                     0.0,1.0,new_ctrl->texture_t_stride,
  1177.                     nobj->surface.texture.torder,
  1178.                     *(new_ctrl->texture_offsets+offset));
  1179.             }
  1180. /*            glMapGrid2f(sfactors[j*3+0],0.0,1.0,tfactors[i*3+0],0.0,1.0);
  1181.             glEvalMesh2(display_mode,0,sfactors[j*3+0],0,tfactors[i*3+0]);*/
  1182.             nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt,
  1183.                 t_bezier_cnt,j,i);
  1184.         }
  1185.     }
  1186. }
  1187.  
  1188.  
  1189.  
  1190. /* draw NURBS surface in OUTLINE POLYGON mode */
  1191. #if 0
  1192. static void
  1193. draw_patch_mode( GLenum display_mode, GLUnurbsObj *nobj,
  1194.     new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors )
  1195. {
  1196.     GLsizei                offset;
  1197.     GLint                t_bezier_cnt,s_bezier_cnt;
  1198.     GLboolean            do_color,do_normal,do_texture;
  1199.     GLint                i,j;
  1200.  
  1201.     t_bezier_cnt=new_ctrl->t_bezier_cnt;
  1202.     s_bezier_cnt=new_ctrl->s_bezier_cnt;
  1203.     glEnable(nobj->surface.geom.type);
  1204.     if(new_ctrl->color_ctrl)
  1205.     {
  1206.         glEnable(nobj->surface.color.type);
  1207.         do_color=GL_TRUE;
  1208.     }
  1209.     else
  1210.         do_color=GL_FALSE;
  1211.     if(new_ctrl->normal_ctrl)
  1212.     {
  1213.         glEnable(nobj->surface.normal.type);
  1214.         do_normal=GL_TRUE;
  1215.     }
  1216.     else
  1217.         do_normal=GL_FALSE;
  1218.     if(new_ctrl->texture_ctrl)
  1219.     {
  1220.         glEnable(nobj->surface.texture.type);
  1221.         do_texture=GL_TRUE;
  1222.     }
  1223.     else
  1224.         do_texture=GL_FALSE;
  1225.     for(j=0; j<s_bezier_cnt; j++)
  1226.     {
  1227.         for(i=0; i<t_bezier_cnt; i++)
  1228.         {
  1229.             offset=j*t_bezier_cnt + i;
  1230.             if(fine_culling_test_3D(nobj,*(new_ctrl->geom_offsets + offset),
  1231.                     nobj->surface.geom.sorder,nobj->surface.geom.torder,
  1232.                     new_ctrl->geom_s_stride,new_ctrl->geom_t_stride,
  1233.                     nobj->surface.geom.dim))
  1234.                 continue;
  1235.             glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride,
  1236.                 nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride,
  1237.                 nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset));
  1238.             if(do_color)
  1239.             {
  1240.                 glMap2f(nobj->surface.color.type,0.0,1.0,
  1241.                     new_ctrl->color_s_stride,nobj->surface.color.sorder,
  1242.                     0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder,
  1243.                     *(new_ctrl->color_offsets + offset));
  1244.             }
  1245.             if(do_normal)
  1246.             {
  1247.                 glMap2f(nobj->surface.normal.type,0.0,1.0,
  1248.                     new_ctrl->normal_s_stride,nobj->surface.normal.sorder,
  1249.                     0.0,1.0,new_ctrl->normal_t_stride,
  1250.                     nobj->surface.normal.torder,
  1251.                     *(new_ctrl->normal_offsets+offset));
  1252.             }
  1253.             if(do_texture)
  1254.             {
  1255.                 glMap2f(nobj->surface.texture.type,0.0,1.0,
  1256.                     new_ctrl->texture_s_stride,nobj->surface.texture.sorder,
  1257.                     0.0,1.0,new_ctrl->texture_t_stride,
  1258.                     nobj->surface.texture.torder,
  1259.                     *(new_ctrl->texture_offsets+offset));
  1260.             }
  1261.             nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt,
  1262.                 t_bezier_cnt,i,j);
  1263. /*            glMapGrid2f(sfactors[j],0.0,1.0,tfactors[i],0.0,1.0);
  1264.             glEvalMesh2(display_mode,0,sfactors[j],0,tfactors[i]);*/
  1265.         }
  1266.     }
  1267. }
  1268. #endif
  1269.  
  1270.  
  1271.  
  1272. void
  1273. init_new_ctrl(new_ctrl_type *p)
  1274. {
  1275.     p->geom_ctrl=p->color_ctrl=p->normal_ctrl=p->texture_ctrl=NULL;
  1276.     p->geom_offsets=p->color_offsets=p->normal_offsets=p->texture_offsets=NULL;
  1277.     p->s_bezier_cnt=p->t_bezier_cnt=0;
  1278. }
  1279.  
  1280. GLenum
  1281. augment_new_ctrl(GLUnurbsObj *nobj, new_ctrl_type *p)
  1282. {
  1283.     GLsizei offset_size;
  1284.     GLint    i,j;
  1285.  
  1286.     p->s_bezier_cnt=(p->geom_s_pt_cnt)/(nobj->surface.geom.sorder);
  1287.     p->t_bezier_cnt=(p->geom_t_pt_cnt)/(nobj->surface.geom.torder);
  1288.     offset_size=(p->s_bezier_cnt)*(p->t_bezier_cnt);
  1289.     p->geom_t_stride=nobj->surface.geom.dim;
  1290.     p->geom_s_stride=(p->geom_t_pt_cnt)*(nobj->surface.geom.dim);
  1291.     p->color_t_stride=nobj->surface.color.dim;
  1292.     p->color_s_stride=(p->color_t_pt_cnt)*(nobj->surface.color.dim);
  1293.     p->normal_t_stride=nobj->surface.normal.dim;
  1294.     p->normal_s_stride=(p->normal_t_pt_cnt)*(nobj->surface.normal.dim);
  1295.     p->texture_t_stride=nobj->surface.texture.dim;
  1296.     p->texture_s_stride=(p->texture_t_pt_cnt)*(nobj->surface.texture.dim);
  1297.     if((p->geom_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
  1298.     {
  1299.         call_user_error(nobj,GLU_OUT_OF_MEMORY);
  1300.         return GLU_ERROR;
  1301.     }
  1302.     if(p->color_ctrl)
  1303.         if((p->color_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
  1304.         {
  1305.             free_new_ctrl(p);
  1306.             call_user_error(nobj,GLU_OUT_OF_MEMORY);
  1307.             return GLU_ERROR;
  1308.         }
  1309.     if(p->normal_ctrl)
  1310.         if((p->normal_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
  1311.         {
  1312.             free_new_ctrl(p);
  1313.             call_user_error(nobj,GLU_OUT_OF_MEMORY);
  1314.             return GLU_ERROR;
  1315.         }
  1316.     if(p->texture_ctrl)
  1317.         if((p->texture_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
  1318.         {
  1319.             free_new_ctrl(p);
  1320.             call_user_error(nobj,GLU_OUT_OF_MEMORY);
  1321.             return GLU_ERROR;
  1322.         }
  1323.     for(i=0;i<p->s_bezier_cnt;i++)
  1324.         for(j=0;j<p->t_bezier_cnt;j++)
  1325.             *(p->geom_offsets + i*(p->t_bezier_cnt) + j) =
  1326.                 p->geom_ctrl + i*(nobj->surface.geom.sorder)*
  1327.                 (nobj->surface.geom.dim)*(p->geom_t_pt_cnt) +
  1328.                 j*(nobj->surface.geom.dim)*(nobj->surface.geom.torder);
  1329.     if(p->color_ctrl)
  1330.         for(i=0;i<p->s_bezier_cnt;i++)
  1331.             for(j=0;j<p->t_bezier_cnt;j++)
  1332.                 *(p->color_offsets + i*(p->t_bezier_cnt) + j) =
  1333.                     p->color_ctrl + i*(nobj->surface.color.sorder)*
  1334.                     (nobj->surface.color.dim)*(p->color_t_pt_cnt) +
  1335.                     j*(nobj->surface.color.dim)*(nobj->surface.color.torder);
  1336.     if(p->normal_ctrl)
  1337.         for(i=0;i<p->s_bezier_cnt;i++)
  1338.             for(j=0;j<p->t_bezier_cnt;j++)
  1339.                 *(p->normal_offsets + i*(p->t_bezier_cnt) + j) =
  1340.                     p->normal_ctrl + i*(nobj->surface.normal.sorder)*
  1341.                     (nobj->surface.normal.dim)*(p->normal_t_pt_cnt) +
  1342.                     j*(nobj->surface.normal.dim)*(nobj->surface.normal.torder);
  1343.     if(p->texture_ctrl)
  1344.         for(i=0;i<p->s_bezier_cnt;i++)
  1345.             for(j=0;j<p->t_bezier_cnt;j++)
  1346.                 *(p->texture_offsets + i*(p->t_bezier_cnt) + j) =
  1347.                     p->texture_ctrl + i*(nobj->surface.texture.sorder)*
  1348.                     (nobj->surface.texture.dim)*(p->texture_t_pt_cnt) +
  1349.                     j*(nobj->surface.texture.dim)*(nobj->surface.texture.torder);
  1350.     return GLU_NO_ERROR;
  1351. }
  1352.  
  1353. /* main NURBS surface procedure */
  1354. void
  1355. do_nurbs_surface( GLUnurbsObj *nobj )
  1356. {
  1357.     GLint            *sfactors,*tfactors;
  1358.     new_ctrl_type    new_ctrl;
  1359.  
  1360.     /* test user supplied data */
  1361.     if(test_nurbs_surfaces(nobj)!=GLU_NO_ERROR)
  1362.         return;
  1363.  
  1364.     init_new_ctrl(&new_ctrl);
  1365.  
  1366.     if(convert_surfs(nobj,&new_ctrl)!=GLU_NO_ERROR)
  1367.         return;
  1368.     if(augment_new_ctrl(nobj,&new_ctrl)!=GLU_NO_ERROR)
  1369.         return;
  1370.     switch(nobj->sampling_method)
  1371.     {
  1372.         case GLU_PATH_LENGTH:
  1373.             if(glu_do_sampling_3D(nobj,&new_ctrl,&sfactors,&tfactors)!=
  1374.                 GLU_NO_ERROR)
  1375.             {
  1376.                 free_new_ctrl(&new_ctrl);
  1377.                 return;
  1378.             }
  1379.             break;
  1380.         case GLU_DOMAIN_DISTANCE:
  1381.             if(glu_do_sampling_uv(nobj,&new_ctrl,&sfactors,&tfactors)!=
  1382.                 GLU_NO_ERROR)
  1383.             {
  1384.                 free_new_ctrl(&new_ctrl);
  1385.                 return;
  1386.             }
  1387.             break;
  1388.         case GLU_PARAMETRIC_ERROR:
  1389.             if(glu_do_sampling_param_3D(nobj,&new_ctrl,&sfactors,&tfactors)!=
  1390.                 GLU_NO_ERROR)
  1391.             {
  1392.                 free_new_ctrl(&new_ctrl);
  1393.                 return;
  1394.             }
  1395.             break;
  1396.         default:
  1397.             abort();
  1398.     }
  1399.     glFrontFace(GL_CW);
  1400.     switch(nobj->display_mode)
  1401.     {
  1402.         case GLU_FILL:
  1403. /*            if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
  1404.                 draw_polygon_mode(GL_FILL,nobj,&new_ctrl,sfactors,tfactors);
  1405.             break;
  1406.         case GLU_OUTLINE_POLYGON:
  1407.             /* TODO - missing trimming handeling */
  1408. /* just for now - no OUTLINE_PATCH mode 
  1409.             draw_patch_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors);
  1410.             break; */
  1411.         case GLU_OUTLINE_PATCH:
  1412. /*            if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
  1413.                 draw_polygon_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors);
  1414.             break;
  1415.         default:
  1416.             abort();  /* TODO: is this OK? */
  1417.     }
  1418.     free(sfactors);
  1419.     free(tfactors);
  1420.     free_new_ctrl(&new_ctrl);
  1421. }
  1422.  
  1423.