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

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