home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src-glu / nurbssrf.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  38KB  |  1,384 lines

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