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

  1. /* $Id: nurbscrv.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: nurbscrv.c,v $
  26.  * Revision 1.1.1.1  1999/08/19 00:55:42  jtg
  27.  * Imported sources
  28.  *
  29.  * Revision 1.6  1997/07/24 01:28:44  brianp
  30.  * changed precompiled header symbol from PCH to PC_HEADER
  31.  *
  32.  * Revision 1.5  1997/05/28 02:29:38  brianp
  33.  * added support for precompiled headers (PCH), inserted APIENTRY keyword
  34.  *
  35.  * Revision 1.4  1997/05/27 03:21:22  brianp
  36.  * minor clean-up
  37.  *
  38.  * Revision 1.3  1997/05/27 03:00:16  brianp
  39.  * incorporated Bogdan's new NURBS code
  40.  *
  41.  * Revision 1.2  1996/09/27 23:12:22  brianp
  42.  * added return 0 to get_surface_dim() to silence warning
  43.  *
  44.  * Revision 1.1  1996/09/27 01:19:39  brianp
  45.  * Initial revision
  46.  *
  47.  */
  48.  
  49.  
  50. /*
  51.  * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
  52.  * See README2 for more info.
  53.  */
  54.  
  55.  
  56. #ifdef PC_HEADER
  57. #include "all.h"
  58. #else
  59. #include <math.h>
  60. #include <stdlib.h>
  61. #include "gluP.h"
  62. #include "nurbs.h"
  63. #endif
  64.  
  65.  
  66. static int
  67. get_curve_dim(GLenum type)
  68. {
  69.     switch(type)
  70.     {
  71.         case GL_MAP1_VERTEX_3:            return 3;
  72.         case GL_MAP1_VERTEX_4:            return 4;
  73.         case GL_MAP1_INDEX:                return 1;
  74.         case GL_MAP1_COLOR_4:            return 4;
  75.         case GL_MAP1_NORMAL:            return 3;
  76.         case GL_MAP1_TEXTURE_COORD_1:    return 1;
  77.         case GL_MAP1_TEXTURE_COORD_2:    return 2;
  78.         case GL_MAP1_TEXTURE_COORD_3:    return 3;
  79.         case GL_MAP1_TEXTURE_COORD_4:    return 4;
  80.                 default:  abort();  /* TODO: is this OK? */
  81.     }
  82.         return 0; /*never get here*/
  83. }
  84.  
  85. static GLenum
  86. test_nurbs_curve(GLUnurbsObj *nobj, curve_attribs *attribs)
  87. {
  88.     GLenum err;
  89.     GLint tmp_int;
  90.  
  91.     if(attribs->order < 0)
  92.     {
  93.         call_user_error(nobj,GLU_INVALID_VALUE);
  94.         return GLU_ERROR;
  95.     }
  96.     glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
  97.     if(attribs->order > tmp_int || attribs->order < 2)
  98.     {
  99.         call_user_error(nobj,GLU_NURBS_ERROR1);
  100.         return GLU_ERROR;
  101.     }
  102.     if(attribs->knot_count < attribs->order +2)
  103.     {
  104.         call_user_error(nobj,GLU_NURBS_ERROR2);
  105.         return GLU_ERROR;
  106.     }
  107.     if(attribs->stride < 0)
  108.     {
  109.         call_user_error(nobj,GLU_NURBS_ERROR34);
  110.         return GLU_ERROR;
  111.     }
  112.     if(attribs->knot==NULL || attribs->ctrlarray==NULL)
  113.     {
  114.         call_user_error(nobj,GLU_NURBS_ERROR36);
  115.         return GLU_ERROR;
  116.     }
  117.     if((err=test_knot(attribs->knot_count,attribs->knot,attribs->order))
  118.         !=GLU_NO_ERROR)
  119.     {
  120.         call_user_error(nobj,err);
  121.         return GLU_ERROR;
  122.     }
  123.     return GLU_NO_ERROR;
  124. }
  125.  
  126. static GLenum
  127. test_nurbs_curves(GLUnurbsObj *nobj)
  128. {
  129.     /* test the geometric data */
  130.     if(test_nurbs_curve(nobj,&(nobj->curve.geom))!=GLU_NO_ERROR)
  131.         return GLU_ERROR;
  132.     /* now test the attributive data */
  133.     /* color */
  134.     if(nobj->curve.color.type!=GLU_INVALID_ENUM)
  135.         if(test_nurbs_curve(nobj,&(nobj->curve.color))!=GLU_NO_ERROR)
  136.             return GLU_ERROR;
  137.     /* normal */
  138.     if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
  139.         if(test_nurbs_curve(nobj,&(nobj->curve.normal))!=GLU_NO_ERROR)
  140.             return GLU_ERROR;
  141.     /* texture */
  142.     if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
  143.         if(test_nurbs_curve(nobj,&(nobj->curve.texture))!=GLU_NO_ERROR)
  144.             return GLU_ERROR;
  145.     return GLU_NO_ERROR;
  146. }
  147.  
  148. /* prepare the knot information structures */
  149. static GLenum
  150. fill_knot_structures(GLUnurbsObj *nobj,knot_str_type *geom_knot,
  151.     knot_str_type *color_knot, knot_str_type *normal_knot,
  152.     knot_str_type *texture_knot)
  153. {
  154.     GLint order;
  155.     GLfloat *knot;
  156.     GLint nknots;
  157.     GLint t_min,t_max;
  158.  
  159.     geom_knot->unified_knot=NULL;
  160.     knot=geom_knot->knot=nobj->curve.geom.knot;
  161.     nknots=geom_knot->nknots=nobj->curve.geom.knot_count;
  162.     order=geom_knot->order=nobj->curve.geom.order;
  163.     geom_knot->delta_nknots=0;
  164.     t_min=geom_knot->t_min=order-1;
  165.     t_max=geom_knot->t_max=nknots-order;
  166.     if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  167.     {
  168.         call_user_error(nobj,GLU_NURBS_ERROR3);
  169.         return GLU_ERROR;
  170.     }
  171.     if(fabs(knot[0]-knot[t_min])<EPSILON)
  172.     {
  173.         /* knot open at beggining */
  174.         geom_knot->open_at_begin=GL_TRUE;
  175.     }
  176.     else
  177.         geom_knot->open_at_begin=GL_FALSE;
  178.     if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  179.     {
  180.         /* knot open at end */
  181.         geom_knot->open_at_end=GL_TRUE;
  182.     }
  183.     else
  184.         geom_knot->open_at_end=GL_FALSE;
  185.     if(nobj->curve.color.type!=GLU_INVALID_ENUM)
  186.     {
  187.         color_knot->unified_knot=(GLfloat *)1;
  188.         knot=color_knot->knot=nobj->curve.color.knot;
  189.         nknots=color_knot->nknots=nobj->curve.color.knot_count;
  190.         order=color_knot->order=nobj->curve.color.order;
  191.         color_knot->delta_nknots=0;
  192.         t_min=color_knot->t_min=order-1;
  193.         t_max=color_knot->t_max=nknots-order;
  194.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  195.         {
  196.             call_user_error(nobj,GLU_NURBS_ERROR3);
  197.             return GLU_ERROR;
  198.         }
  199.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  200.         {
  201.             /* knot open at beggining */
  202.             color_knot->open_at_begin=GL_TRUE;
  203.         }
  204.         else
  205.             color_knot->open_at_begin=GL_FALSE;
  206.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  207.         {
  208.             /* knot open at end */
  209.             color_knot->open_at_end=GL_TRUE;
  210.         }
  211.         else
  212.             color_knot->open_at_end=GL_FALSE;
  213.     }
  214.     else
  215.         color_knot->unified_knot=NULL;
  216.     if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
  217.     {
  218.         normal_knot->unified_knot=(GLfloat *)1;
  219.         knot=normal_knot->knot=nobj->curve.normal.knot;
  220.         nknots=normal_knot->nknots=nobj->curve.normal.knot_count;
  221.         order=normal_knot->order=nobj->curve.normal.order;
  222.         normal_knot->delta_nknots=0;
  223.         t_min=normal_knot->t_min=order-1;
  224.         t_max=normal_knot->t_max=nknots-order;
  225.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  226.         {
  227.             call_user_error(nobj,GLU_NURBS_ERROR3);
  228.             return GLU_ERROR;
  229.         }
  230.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  231.         {
  232.             /* knot open at beggining */
  233.             normal_knot->open_at_begin=GL_TRUE;
  234.         }
  235.         else
  236.             normal_knot->open_at_begin=GL_FALSE;
  237.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  238.         {
  239.             /* knot open at end */
  240.             normal_knot->open_at_end=GL_TRUE;
  241.         }
  242.         else
  243.             normal_knot->open_at_end=GL_FALSE;
  244.     }
  245.     else
  246.         normal_knot->unified_knot=NULL;
  247.     if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
  248.     {
  249.         texture_knot->unified_knot=(GLfloat *)1;
  250.         knot=texture_knot->knot=nobj->curve.texture.knot;
  251.         nknots=texture_knot->nknots=nobj->curve.texture.knot_count;
  252.         order=texture_knot->order=nobj->curve.texture.order;
  253.         texture_knot->delta_nknots=0;
  254.         t_min=texture_knot->t_min=order-1;
  255.         t_max=texture_knot->t_max=nknots-order;
  256.         if(fabs(knot[t_min]-knot[t_max])<EPSILON)
  257.         {
  258.             call_user_error(nobj,GLU_NURBS_ERROR3);
  259.             return GLU_ERROR;
  260.         }
  261.         if(fabs(knot[0]-knot[t_min])<EPSILON)
  262.         {
  263.             /* knot open at beggining */
  264.             texture_knot->open_at_begin=GL_TRUE;
  265.         }
  266.         else
  267.             texture_knot->open_at_begin=GL_FALSE;
  268.         if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
  269.         {
  270.             /* knot open at end */
  271.             texture_knot->open_at_end=GL_TRUE;
  272.         }
  273.         else
  274.             texture_knot->open_at_end=GL_FALSE;
  275.     }
  276.     else
  277.         texture_knot->unified_knot=NULL;
  278.     return GLU_NO_ERROR;
  279. }
  280.  
  281. /* covert the NURBS curve into a series of adjacent Bezier curves */
  282. static GLenum
  283. convert_curve(knot_str_type *the_knot, curve_attribs *attrib,
  284.     GLfloat **new_ctrl,GLint *ncontrol)
  285. {
  286.     GLenum err;
  287.  
  288.     if((err=explode_knot(the_knot))!=GLU_NO_ERROR)
  289.     {
  290.         if(the_knot->unified_knot)
  291.         {
  292.             free(the_knot->unified_knot);
  293.             the_knot->unified_knot=NULL;
  294.         }
  295.         return err;
  296.     }
  297.     if(the_knot->unified_knot)
  298.     {
  299.         free(the_knot->unified_knot);
  300.         the_knot->unified_knot=NULL;
  301.     }
  302.     if((err=calc_alphas(the_knot))!=GLU_NO_ERROR)
  303.     {
  304.         free(the_knot->new_knot);
  305.         return err;
  306.     }
  307.     free(the_knot->new_knot);
  308.     if((err=calc_new_ctrl_pts(attrib->ctrlarray,attrib->stride,the_knot,
  309.                             attrib->dim,new_ctrl,ncontrol))
  310.         !=GLU_NO_ERROR)
  311.     {
  312.         free(the_knot->alpha);
  313.         return err;
  314.     }
  315.     free(the_knot->alpha);
  316.     return GLU_NO_ERROR;
  317. }
  318.  
  319. /* covert curves - geometry and possible attribute ones into equivalent */
  320. /* sequence of adjacent Bezier curves */
  321. static GLenum
  322. convert_curves(GLUnurbsObj *nobj, GLfloat **new_geom_ctrl,
  323.     GLint *ncontrol, GLfloat **new_color_ctrl, GLfloat **new_normal_ctrl,
  324.     GLfloat **new_texture_ctrl)
  325. {
  326.     knot_str_type    geom_knot,color_knot,normal_knot,texture_knot;
  327.     GLint            junk;
  328.     GLenum            err;
  329.  
  330.     *new_color_ctrl=*new_normal_ctrl=*new_texture_ctrl=NULL;
  331.  
  332.     if(fill_knot_structures(nobj,&geom_knot,&color_knot,&normal_knot,
  333.             &texture_knot)!=GLU_NO_ERROR)
  334.         return GLU_ERROR;
  335.  
  336.     /* unify knots - all knots should have the same number of working */
  337.     /* ranges */
  338.     if((err=select_knot_working_range(nobj,&geom_knot,&color_knot,&normal_knot,
  339.                 &texture_knot))!=GLU_NO_ERROR)
  340.     {
  341.         return err;
  342.     }
  343.     /* convert the geometry curve */
  344.     nobj->curve.geom.dim=get_curve_dim(nobj->curve.geom.type);
  345.     if((err=convert_curve(&geom_knot,&(nobj->curve.geom),new_geom_ctrl,
  346.                         ncontrol))!=GLU_NO_ERROR)
  347.     {
  348.         free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  349.         call_user_error(nobj,err);
  350.         return err;
  351.     }
  352.     /* if additional attributive curves are given convert them as well */
  353.     if(color_knot.unified_knot)
  354.     {
  355.         nobj->curve.color.dim=get_curve_dim(nobj->curve.color.type);
  356.         if((err=convert_curve(&color_knot,&(nobj->curve.color),
  357.             new_color_ctrl,&junk))!=GLU_NO_ERROR)
  358.         {
  359.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  360.             free(*new_geom_ctrl);
  361.             call_user_error(nobj,err);
  362.             return err;
  363.         }
  364.     }
  365.     if(normal_knot.unified_knot)
  366.     {
  367.         nobj->curve.normal.dim=get_curve_dim(nobj->curve.normal.type);
  368.         if((err=convert_curve(&normal_knot,&(nobj->curve.normal),
  369.             new_normal_ctrl,&junk))!=GLU_NO_ERROR)
  370.         {
  371.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  372.             free(*new_geom_ctrl);
  373.             if(*new_color_ctrl)
  374.                 free(*new_color_ctrl);
  375.             call_user_error(nobj,err);
  376.             return err;
  377.         }
  378.     }
  379.     if(texture_knot.unified_knot)
  380.     {
  381.         nobj->curve.texture.dim=get_curve_dim(nobj->curve.texture.type);
  382.         if((err=convert_curve(&texture_knot,&(nobj->curve.texture),
  383.             new_texture_ctrl,&junk))!=GLU_NO_ERROR)
  384.         {
  385.             free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
  386.             free(*new_geom_ctrl);
  387.             if(*new_color_ctrl)
  388.                 free(*new_color_ctrl);
  389.             if(*new_normal_ctrl)
  390.                 free(*new_normal_ctrl);
  391.             call_user_error(nobj,err);
  392.             return err;
  393.         }
  394.     }
  395.     return GLU_NO_ERROR;
  396. }
  397.  
  398. /* main NURBS curve procedure */
  399. void do_nurbs_curve( GLUnurbsObj *nobj)
  400. {
  401.     GLint geom_order,color_order=0,normal_order=0,texture_order=0;
  402.     GLenum geom_type;
  403.     GLint n_ctrl;
  404.     GLfloat *new_geom_ctrl,*new_color_ctrl,*new_normal_ctrl,*new_texture_ctrl;
  405.     GLfloat *geom_ctrl,*color_ctrl,*normal_ctrl,*texture_ctrl;
  406.     GLint *factors;
  407.     GLint i,j;
  408.     GLint geom_dim,color_dim=0,normal_dim=0,texture_dim=0;
  409.  
  410.     /* test the user supplied data */
  411.     if(test_nurbs_curves(nobj)!=GLU_NO_ERROR)
  412.         return;
  413.  
  414.     if(convert_curves(nobj,&new_geom_ctrl,&n_ctrl,&new_color_ctrl,
  415.                     &new_normal_ctrl,&new_texture_ctrl)!=GLU_NO_ERROR)
  416.         return;
  417.  
  418.     geom_order=nobj->curve.geom.order;
  419.     geom_type=nobj->curve.geom.type;
  420.     geom_dim=nobj->curve.geom.dim;
  421.  
  422.     if(glu_do_sampling_crv(nobj,new_geom_ctrl,n_ctrl,geom_order,geom_dim,
  423.                         &factors)
  424.         !=GLU_NO_ERROR)
  425.     {
  426.         free(new_geom_ctrl);
  427.         if(new_color_ctrl)
  428.             free(new_color_ctrl);
  429.         if(new_normal_ctrl)
  430.             free(new_normal_ctrl);
  431.         if(new_texture_ctrl)
  432.             free(new_texture_ctrl);
  433.         return;
  434.     }
  435.     glEnable(geom_type);
  436.     if(new_color_ctrl)
  437.     {
  438.         glEnable(nobj->curve.color.type);
  439.         color_dim=nobj->curve.color.dim;
  440.         color_ctrl=new_color_ctrl;
  441.         color_order=nobj->curve.color.order;
  442.     }
  443.     if(new_normal_ctrl)
  444.     {
  445.         glEnable(nobj->curve.normal.type);
  446.         normal_dim=nobj->curve.normal.dim;
  447.         normal_ctrl=new_normal_ctrl;
  448.         normal_order=nobj->curve.normal.order;
  449.     }
  450.     if(new_texture_ctrl)
  451.     {
  452.         glEnable(nobj->curve.texture.type);
  453.         texture_dim=nobj->curve.texture.dim;
  454.         texture_ctrl=new_texture_ctrl;
  455.         texture_order=nobj->curve.texture.order;
  456.     }
  457.     for(i=0 , j=0, geom_ctrl=new_geom_ctrl;
  458.         i<n_ctrl;
  459.         i+=geom_order , j++ , geom_ctrl+=geom_order*geom_dim)
  460.     {
  461.         if(fine_culling_test_2D(nobj,geom_ctrl,geom_order,geom_dim,geom_dim))
  462.         {
  463.             color_ctrl+=color_order*color_dim;
  464.             normal_ctrl+=normal_order*normal_dim;
  465.             texture_ctrl+=texture_order*texture_dim;
  466.             continue;
  467.         }
  468.         glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
  469.         if(new_color_ctrl)
  470.         {
  471.             glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
  472.                 color_order,color_ctrl);
  473.             color_ctrl+=color_order*color_dim;
  474.         }
  475.         if(new_normal_ctrl)
  476.         {
  477.             glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
  478.                 normal_order,normal_ctrl);
  479.             normal_ctrl+=normal_order*normal_dim;
  480.         }
  481.         if(new_texture_ctrl)
  482.         {
  483.             glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
  484.                 texture_order,texture_ctrl);
  485.             texture_ctrl+=texture_order*texture_dim;
  486.         }
  487.         glMapGrid1f(factors[j],0.0,1.0);
  488.         glEvalMesh1(GL_LINE,0,factors[j]);
  489.     }
  490.     free(new_geom_ctrl);
  491.     free(factors);
  492.     if(new_color_ctrl)
  493.         free(new_color_ctrl);
  494.     if(new_normal_ctrl)
  495.         free(new_normal_ctrl);
  496.     if(new_texture_ctrl)
  497.         free(new_texture_ctrl);
  498. }
  499.  
  500.  
  501.