| /* $Id: nurbssrf.c,v 1.1.1.1 1999/08/19 00:55:42 jtg Exp $ */ |
| |
| /* |
| * Mesa 3-D graphics library |
| * Version: 2.4 |
| * Copyright (C) 1995-1997 Brian Paul |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the Free |
| * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| |
| /* |
| * $Log: nurbssrf.c,v $ |
| * Revision 1.1.1.1 1999/08/19 00:55:42 jtg |
| * Imported sources |
| * |
| * Revision 1.7 1997/07/24 01:28:44 brianp |
| * changed precompiled header symbol from PCH to PC_HEADER |
| * |
| * Revision 1.6 1997/06/23 00:22:07 brianp |
| * include <string.h> |
| * |
| * Revision 1.5 1997/05/28 02:29:38 brianp |
| * added support for precompiled headers (PCH), inserted APIENTRY keyword |
| * |
| * Revision 1.4 1997/05/27 03:20:35 brianp |
| * minor clean-up |
| * |
| * Revision 1.3 1997/05/27 03:00:16 brianp |
| * incorporated Bogdan's new NURBS code |
| * |
| * Revision 1.2 1996/09/27 23:13:02 brianp |
| * added return 0 to get_surface_dim() to silence warning |
| * |
| * Revision 1.1 1996/09/27 01:19:39 brianp |
| * Initial revision |
| * |
| */ |
| |
| |
| /* |
| * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it) |
| * See README2 for more info. |
| */ |
| |
| |
| #ifdef PC_HEADER |
| #include "all.h" |
| #else |
| #include <math.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include "gluP.h" |
| #include "nurbs.h" |
| #endif |
| |
| |
| static int |
| get_surface_dim(GLenum type) |
| { |
| switch(type) |
| { |
| case GL_MAP2_VERTEX_3: return 3; |
| case GL_MAP2_VERTEX_4: return 4; |
| case GL_MAP2_INDEX: return 1; |
| case GL_MAP2_COLOR_4: return 4; |
| case GL_MAP2_NORMAL: return 3; |
| case GL_MAP2_TEXTURE_COORD_1: return 1; |
| case GL_MAP2_TEXTURE_COORD_2: return 2; |
| case GL_MAP2_TEXTURE_COORD_3: return 3; |
| case GL_MAP2_TEXTURE_COORD_4: return 4; |
| default: abort(); /* TODO: is this OK? */ |
| } |
| return 0; /*never get here*/ |
| } |
| |
| static GLenum |
| test_nurbs_surface(GLUnurbsObj *nobj, surface_attribs *attrib) |
| { |
| GLenum err; |
| GLint tmp_int; |
| |
| if(attrib->sorder < 0 || attrib->torder < 0) |
| { |
| call_user_error(nobj,GLU_INVALID_VALUE); |
| return GLU_ERROR; |
| } |
| glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int); |
| if(attrib->sorder > tmp_int || attrib->sorder < 2) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR1); |
| return GLU_ERROR; |
| } |
| if(attrib->torder > tmp_int || attrib->torder < 2) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR1); |
| return GLU_ERROR; |
| } |
| if(attrib->sknot_count < attrib->sorder +2) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR2); |
| return GLU_ERROR; |
| } |
| if(attrib->tknot_count < attrib->torder +2) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR2); |
| return GLU_ERROR; |
| } |
| if(attrib->s_stride < 0 || attrib->t_stride < 0) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR34); |
| return GLU_ERROR; |
| } |
| if(attrib->sknot==NULL || attrib->tknot==NULL || attrib->ctrlarray==NULL) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR36); |
| return GLU_ERROR; |
| } |
| if((err=test_knot(attrib->tknot_count,attrib->tknot,attrib->torder)) |
| !=GLU_NO_ERROR) |
| { |
| call_user_error(nobj,err); |
| return GLU_ERROR; |
| } |
| if((err=test_knot(attrib->sknot_count,attrib->sknot,attrib->sorder)) |
| !=GLU_NO_ERROR) |
| { |
| call_user_error(nobj,err); |
| return GLU_ERROR; |
| } |
| return GLU_NO_ERROR; |
| } |
| |
| static GLenum |
| test_nurbs_surfaces(GLUnurbsObj *nobj) |
| { |
| /* test the geometric data */ |
| if(test_nurbs_surface(nobj,&(nobj->surface.geom))!=GLU_NO_ERROR) |
| return GLU_ERROR; |
| /* now test the attributive data */ |
| /* color */ |
| if(nobj->surface.color.type!=GLU_INVALID_ENUM) |
| if(test_nurbs_surface(nobj,&(nobj->surface.color))!=GLU_NO_ERROR) |
| return GLU_ERROR; |
| /* normal */ |
| if(nobj->surface.normal.type!=GLU_INVALID_ENUM) |
| if(test_nurbs_surface(nobj,&(nobj->surface.normal))!=GLU_NO_ERROR) |
| return GLU_ERROR; |
| /* texture */ |
| if(nobj->surface.texture.type!=GLU_INVALID_ENUM) |
| if(test_nurbs_surface(nobj,&(nobj->surface.texture))!=GLU_NO_ERROR) |
| return GLU_ERROR; |
| return GLU_NO_ERROR; |
| } |
| |
| static GLenum |
| convert_surf(knot_str_type *s_knot, knot_str_type *t_knot, |
| surface_attribs *attrib, GLfloat **new_ctrl, |
| GLint *s_n_ctrl, GLint *t_n_ctrl) |
| { |
| GLfloat **tmp_ctrl; |
| GLfloat *ctrl_offset; |
| GLint tmp_n_control; |
| GLint i,j,t_cnt,s_cnt; |
| GLint tmp_stride; |
| GLint dim; |
| GLenum err; |
| |
| /* valid range is empty? */ |
| if((s_knot->unified_knot !=NULL && s_knot->unified_nknots==0) || |
| (t_knot->unified_knot !=NULL && t_knot->unified_nknots==0)) |
| { |
| if(s_knot->unified_knot) |
| { |
| free(s_knot->unified_knot); |
| s_knot->unified_knot=NULL; |
| } |
| if(t_knot->unified_knot) |
| { |
| free(t_knot->unified_knot); |
| t_knot->unified_knot=NULL; |
| } |
| *s_n_ctrl=0; |
| *t_n_ctrl=0; |
| return GLU_NO_ERROR; |
| } |
| t_cnt=attrib->tknot_count-attrib->torder; |
| s_cnt=attrib->sknot_count-attrib->sorder; |
| if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*t_cnt))==NULL) |
| return GLU_OUT_OF_MEMORY; |
| if((err=explode_knot(s_knot))!=GLU_NO_ERROR) |
| { |
| free(tmp_ctrl); |
| if(s_knot->unified_knot) |
| { |
| free(s_knot->unified_knot); |
| s_knot->unified_knot=NULL; |
| } |
| return err; |
| } |
| if(s_knot->unified_knot) |
| { |
| free(s_knot->unified_knot); |
| s_knot->unified_knot=NULL; |
| } |
| if((err=calc_alphas(s_knot))!=GLU_NO_ERROR) |
| { |
| free(tmp_ctrl); |
| free(s_knot->new_knot); |
| return err; |
| } |
| free(s_knot->new_knot); |
| ctrl_offset=attrib->ctrlarray; |
| dim=attrib->dim; |
| for(i=0;i<t_cnt;i++) |
| { |
| if((err=calc_new_ctrl_pts(ctrl_offset,attrib->s_stride,s_knot, |
| dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR) |
| { |
| for(--i;i<=0;i--) |
| free(tmp_ctrl[i]); |
| free(tmp_ctrl); |
| free(s_knot->alpha); |
| return err; |
| } |
| ctrl_offset+=attrib->t_stride; |
| } |
| free(s_knot->alpha); |
| tmp_stride=dim*tmp_n_control; |
| if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*t_cnt)) |
| ==NULL) |
| { |
| for(i=0;i<t_cnt;i++) |
| free(tmp_ctrl[i]); |
| free(tmp_ctrl); |
| return GLU_OUT_OF_MEMORY; |
| } |
| for(i=0;i<tmp_n_control;i++) |
| for(j=0;j<t_cnt;j++) |
| MEMCPY(*new_ctrl+j*dim+i*dim*t_cnt,tmp_ctrl[j]+dim*i, |
| sizeof(GLfloat)*dim); |
| for(i=0;i<t_cnt;i++) |
| free(tmp_ctrl[i]); |
| free(tmp_ctrl); |
| *s_n_ctrl=tmp_n_control; |
| |
| if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*(*s_n_ctrl)))==NULL) |
| { |
| return GLU_OUT_OF_MEMORY; |
| } |
| if((err=explode_knot(t_knot))!=GLU_NO_ERROR) |
| { |
| free(tmp_ctrl); |
| if(t_knot->unified_knot) |
| { |
| free(t_knot->unified_knot); |
| t_knot->unified_knot=NULL; |
| } |
| return err; |
| } |
| if(t_knot->unified_knot) |
| { |
| free(t_knot->unified_knot); |
| t_knot->unified_knot=NULL; |
| } |
| if((err=calc_alphas(t_knot))!=GLU_NO_ERROR) |
| { |
| free(tmp_ctrl); |
| free(t_knot->new_knot); |
| return err; |
| } |
| free(t_knot->new_knot); |
| ctrl_offset=*new_ctrl; |
| for(i=0;i<(*s_n_ctrl);i++) |
| { |
| if((err=calc_new_ctrl_pts(ctrl_offset,dim,t_knot, |
| dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR) |
| { |
| for(--i;i<=0;i--) |
| free(tmp_ctrl[i]); |
| free(tmp_ctrl); |
| free(t_knot->alpha); |
| return err; |
| } |
| ctrl_offset+=dim*t_cnt; |
| } |
| free(t_knot->alpha); |
| free(*new_ctrl); |
| tmp_stride=dim*tmp_n_control; |
| if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*(*s_n_ctrl))) |
| ==NULL) |
| { |
| for(i=0;i<(*s_n_ctrl);i++) |
| free(tmp_ctrl[i]); |
| free(tmp_ctrl); |
| return GLU_OUT_OF_MEMORY; |
| } |
| for(i=0;i<(*s_n_ctrl);i++) |
| { |
| MEMCPY(*new_ctrl+i*tmp_stride,tmp_ctrl[i],sizeof(GLfloat)*tmp_stride); |
| free(tmp_ctrl[i]); |
| } |
| free(tmp_ctrl); |
| *t_n_ctrl=tmp_n_control; |
| return GLU_NO_ERROR; |
| } |
| |
| /* prepare the knot information structures */ |
| static GLenum |
| fill_knot_structures(GLUnurbsObj *nobj, |
| knot_str_type *geom_s_knot, knot_str_type *geom_t_knot, |
| knot_str_type *color_s_knot, knot_str_type *color_t_knot, |
| knot_str_type *normal_s_knot, knot_str_type *normal_t_knot, |
| knot_str_type *texture_s_knot, knot_str_type *texture_t_knot) |
| { |
| GLint order; |
| GLfloat *knot; |
| GLint nknots; |
| GLint t_min,t_max; |
| |
| geom_s_knot->unified_knot=NULL; |
| knot=geom_s_knot->knot=nobj->surface.geom.sknot; |
| nknots=geom_s_knot->nknots=nobj->surface.geom.sknot_count; |
| order=geom_s_knot->order=nobj->surface.geom.sorder; |
| geom_s_knot->delta_nknots=0; |
| t_min=geom_s_knot->t_min=order-1; |
| t_max=geom_s_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| geom_s_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| geom_s_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| geom_s_knot->open_at_end=GL_TRUE; |
| } |
| else |
| geom_s_knot->open_at_end=GL_FALSE; |
| geom_t_knot->unified_knot=NULL; |
| knot=geom_t_knot->knot=nobj->surface.geom.tknot; |
| nknots=geom_t_knot->nknots=nobj->surface.geom.tknot_count; |
| order=geom_t_knot->order=nobj->surface.geom.torder; |
| geom_t_knot->delta_nknots=0; |
| t_min=geom_t_knot->t_min=order-1; |
| t_max=geom_t_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| geom_t_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| geom_t_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| geom_t_knot->open_at_end=GL_TRUE; |
| } |
| else |
| geom_t_knot->open_at_end=GL_FALSE; |
| |
| if(nobj->surface.color.type!=GLU_INVALID_ENUM) |
| { |
| color_s_knot->unified_knot=(GLfloat *)1; |
| knot=color_s_knot->knot=nobj->surface.color.sknot; |
| nknots=color_s_knot->nknots=nobj->surface.color.sknot_count; |
| order=color_s_knot->order=nobj->surface.color.sorder; |
| color_s_knot->delta_nknots=0; |
| t_min=color_s_knot->t_min=order-1; |
| t_max=color_s_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| color_s_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| color_s_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| color_s_knot->open_at_end=GL_TRUE; |
| } |
| else |
| color_s_knot->open_at_end=GL_FALSE; |
| color_t_knot->unified_knot=(GLfloat *)1; |
| knot=color_t_knot->knot=nobj->surface.color.tknot; |
| nknots=color_t_knot->nknots=nobj->surface.color.tknot_count; |
| order=color_t_knot->order=nobj->surface.color.torder; |
| color_t_knot->delta_nknots=0; |
| t_min=color_t_knot->t_min=order-1; |
| t_max=color_t_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| color_t_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| color_t_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| color_t_knot->open_at_end=GL_TRUE; |
| } |
| else |
| color_t_knot->open_at_end=GL_FALSE; |
| } |
| else |
| { |
| color_s_knot->unified_knot=NULL; |
| color_t_knot->unified_knot=NULL; |
| } |
| |
| if(nobj->surface.normal.type!=GLU_INVALID_ENUM) |
| { |
| normal_s_knot->unified_knot=(GLfloat *)1; |
| knot=normal_s_knot->knot=nobj->surface.normal.sknot; |
| nknots=normal_s_knot->nknots=nobj->surface.normal.sknot_count; |
| order=normal_s_knot->order=nobj->surface.normal.sorder; |
| normal_s_knot->delta_nknots=0; |
| t_min=normal_s_knot->t_min=order-1; |
| t_max=normal_s_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| normal_s_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| normal_s_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| normal_s_knot->open_at_end=GL_TRUE; |
| } |
| else |
| normal_s_knot->open_at_end=GL_FALSE; |
| normal_t_knot->unified_knot=(GLfloat *)1; |
| knot=normal_t_knot->knot=nobj->surface.normal.tknot; |
| nknots=normal_t_knot->nknots=nobj->surface.normal.tknot_count; |
| order=normal_t_knot->order=nobj->surface.normal.torder; |
| normal_t_knot->delta_nknots=0; |
| t_min=normal_t_knot->t_min=order-1; |
| t_max=normal_t_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| normal_t_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| normal_t_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| normal_t_knot->open_at_end=GL_TRUE; |
| } |
| else |
| normal_t_knot->open_at_end=GL_FALSE; |
| } |
| else |
| { |
| normal_s_knot->unified_knot=NULL; |
| normal_t_knot->unified_knot=NULL; |
| } |
| |
| if(nobj->surface.texture.type!=GLU_INVALID_ENUM) |
| { |
| texture_s_knot->unified_knot=(GLfloat *)1; |
| knot=texture_s_knot->knot=nobj->surface.texture.sknot; |
| nknots=texture_s_knot->nknots=nobj->surface.texture.sknot_count; |
| order=texture_s_knot->order=nobj->surface.texture.sorder; |
| texture_s_knot->delta_nknots=0; |
| t_min=texture_s_knot->t_min=order-1; |
| t_max=texture_s_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| texture_s_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| texture_s_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| texture_s_knot->open_at_end=GL_TRUE; |
| } |
| else |
| texture_s_knot->open_at_end=GL_FALSE; |
| texture_t_knot->unified_knot=(GLfloat *)1; |
| knot=texture_t_knot->knot=nobj->surface.texture.tknot; |
| nknots=texture_t_knot->nknots=nobj->surface.texture.tknot_count; |
| order=texture_t_knot->order=nobj->surface.texture.torder; |
| texture_t_knot->delta_nknots=0; |
| t_min=texture_t_knot->t_min=order-1; |
| t_max=texture_t_knot->t_max=nknots-order; |
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) |
| { |
| call_user_error(nobj,GLU_NURBS_ERROR3); |
| return GLU_ERROR; |
| } |
| if(fabs(knot[0]-knot[t_min])<EPSILON) |
| { |
| /* knot open at beggining */ |
| texture_t_knot->open_at_begin=GL_TRUE; |
| } |
| else |
| texture_t_knot->open_at_begin=GL_FALSE; |
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) |
| { |
| /* knot open at end */ |
| texture_t_knot->open_at_end=GL_TRUE; |
| } |
| else |
| texture_t_knot->open_at_end=GL_FALSE; |
| } |
| else |
| { |
| texture_s_knot->unified_knot=NULL; |
| texture_t_knot->unified_knot=NULL; |
| } |
| return GLU_NO_ERROR; |
| } |
| |
| void |
| free_new_ctrl(new_ctrl_type *p) |
| { |
| if(p->geom_ctrl) |
| free(p->geom_ctrl); |
| if(p->geom_offsets) |
| free(p->geom_offsets); |
| if(p->color_ctrl) |
| { |
| free(p->color_ctrl); |
| if(p->color_offsets) |
| free(p->color_offsets); |
| } |
| if(p->normal_ctrl) |
| { |
| free(p->normal_ctrl); |
| if(p->normal_offsets) |
| free(p->normal_offsets); |
| } |
| if(p->texture_ctrl) |
| { |
| free(p->texture_ctrl); |
| if(p->texture_offsets) |
| free(p->texture_offsets); |
| } |
| } |
| |
| /* convert surfaces - geometry and possible attribute ones into equivalent */ |
| /* sequence of adjacent Bezier patches */ |
| static GLenum |
| convert_surfs(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl) |
| { |
| knot_str_type geom_s_knot,color_s_knot,normal_s_knot,texture_s_knot; |
| knot_str_type geom_t_knot,color_t_knot,normal_t_knot,texture_t_knot; |
| GLenum err; |
| |
| if((err=fill_knot_structures(nobj,&geom_s_knot,&geom_t_knot, |
| &color_s_knot,&color_t_knot,&normal_s_knot,&normal_t_knot, |
| &texture_s_knot,&texture_t_knot)) !=GLU_NO_ERROR) |
| { |
| return err; |
| } |
| /* unify knots - all knots should have the same working range */ |
| if((err=select_knot_working_range(nobj,&geom_s_knot,&color_s_knot, |
| &normal_s_knot,&texture_s_knot)) !=GLU_NO_ERROR) |
| { |
| call_user_error(nobj,err); |
| return err; |
| } |
| if((err=select_knot_working_range(nobj,&geom_t_knot,&color_t_knot, |
| &normal_t_knot,&texture_t_knot)) !=GLU_NO_ERROR) |
| { |
| free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot, |
| &texture_s_knot); |
| call_user_error(nobj,err); |
| return err; |
| } |
| |
| /* convert the geometry surface */ |
| nobj->surface.geom.dim=get_surface_dim(nobj->surface.geom.type); |
| if((err=convert_surf(&geom_s_knot,&geom_t_knot,&(nobj->surface.geom), |
| &(new_ctrl->geom_ctrl),&(new_ctrl->geom_s_pt_cnt), |
| &(new_ctrl->geom_t_pt_cnt)))!=GLU_NO_ERROR) |
| { |
| free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot, |
| &texture_s_knot); |
| free_unified_knots(&geom_t_knot,&color_t_knot,&normal_t_knot, |
| &texture_t_knot); |
| call_user_error(nobj,err); |
| return err; |
| } |
| /* if additional attributive surfaces are given convert them as well */ |
| if(color_s_knot.unified_knot) |
| { |
| nobj->surface.color.dim=get_surface_dim(nobj->surface.color.type); |
| if((err=convert_surf(&color_s_knot,&color_t_knot,&(nobj->surface.color), |
| &(new_ctrl->color_ctrl),&(new_ctrl->color_s_pt_cnt), |
| &(new_ctrl->color_t_pt_cnt)))!=GLU_NO_ERROR) |
| { |
| free_unified_knots(&color_s_knot,&color_s_knot,&normal_s_knot, |
| &texture_s_knot); |
| free_unified_knots(&color_t_knot,&color_t_knot,&normal_t_knot, |
| &texture_t_knot); |
| free_new_ctrl(new_ctrl); |
| call_user_error(nobj,err); |
| return err; |
| } |
| } |
| if(normal_s_knot.unified_knot) |
| { |
| nobj->surface.normal.dim=get_surface_dim(nobj->surface.normal.type); |
| if((err=convert_surf(&normal_s_knot,&normal_t_knot, |
| &(nobj->surface.normal), |
| &(new_ctrl->normal_ctrl),&(new_ctrl->normal_s_pt_cnt), |
| &(new_ctrl->normal_t_pt_cnt)))!=GLU_NO_ERROR) |
| { |
| free_unified_knots(&normal_s_knot,&normal_s_knot,&normal_s_knot, |
| &texture_s_knot); |
| free_unified_knots(&normal_t_knot,&normal_t_knot,&normal_t_knot, |
| &texture_t_knot); |
| free_new_ctrl(new_ctrl); |
| call_user_error(nobj,err); |
| return err; |
| } |
| } |
| if(texture_s_knot.unified_knot) |
| { |
| nobj->surface.texture.dim=get_surface_dim(nobj->surface.texture.type); |
| if((err=convert_surf(&texture_s_knot,&texture_t_knot, |
| &(nobj->surface.texture), |
| &(new_ctrl->texture_ctrl),&(new_ctrl->texture_s_pt_cnt), |
| &(new_ctrl->texture_t_pt_cnt)))!=GLU_NO_ERROR) |
| { |
| free_unified_knots(&texture_s_knot,&texture_s_knot,&texture_s_knot, |
| &texture_s_knot); |
| free_unified_knots(&texture_t_knot,&texture_t_knot,&texture_t_knot, |
| &texture_t_knot); |
| free_new_ctrl(new_ctrl); |
| call_user_error(nobj,err); |
| return err; |
| } |
| } |
| return GLU_NO_ERROR; |
| } |
| |
| /* tesselate the "boundary" Bezier edge strips */ |
| void |
| tesselate_strip_t_line(GLint top_start,GLint top_end,GLint top_z, |
| GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain) |
| { |
| GLint top_cnt,bottom_cnt,tri_cnt,k; |
| GLint direction; |
| |
| top_cnt=top_end-top_start; |
| direction= (top_cnt>=0 ? 1: -1); |
| bottom_cnt=bottom_end-bottom_start; |
| glBegin(GL_LINES); |
| while(top_cnt) |
| { |
| if(bottom_cnt) |
| tri_cnt=top_cnt/bottom_cnt; |
| else |
| tri_cnt=abs(top_cnt); |
| for(k=0;k<=tri_cnt;k++ , top_start+=direction) |
| { |
| glEvalCoord2f((GLfloat)bottom_z/bottom_domain, |
| (GLfloat)bottom_start/bottom_domain); |
| glEvalPoint2(top_z,top_start); |
| } |
| if(bottom_cnt) |
| { |
| glEvalCoord2f((GLfloat)bottom_z/bottom_domain, |
| (GLfloat)bottom_start/bottom_domain); |
| bottom_start+=direction; |
| top_start-=direction; |
| glEvalCoord2f((GLfloat)bottom_z/bottom_domain, |
| (GLfloat)bottom_start/bottom_domain); |
| glEvalCoord2f((GLfloat)bottom_z/bottom_domain, |
| (GLfloat)bottom_start/bottom_domain); |
| glEvalPoint2(top_z,top_start); |
| } |
| top_cnt-=direction*tri_cnt; |
| bottom_cnt-=direction; |
| } |
| glEnd(); |
| } |
| |
| void |
| tesselate_strip_t_fill(GLint top_start,GLint top_end,GLint top_z, |
| GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain) |
| { |
| GLint top_cnt,bottom_cnt,tri_cnt,k; |
| GLint direction; |
| |
| top_cnt=top_end-top_start; |
| direction= (top_cnt>=0 ? 1: -1); |
| bottom_cnt=bottom_end-bottom_start; |
| while(top_cnt) |
| { |
| if(bottom_cnt) |
| tri_cnt=top_cnt/bottom_cnt; |
| else |
| tri_cnt=abs(top_cnt); |
| glBegin(GL_TRIANGLE_FAN); |
| glEvalCoord2f((GLfloat)bottom_z/bottom_domain, |
| (GLfloat)bottom_start/bottom_domain); |
| for(k=0;k<=tri_cnt;k++ , top_start+=direction) |
| glEvalPoint2(top_z,top_start); |
| if(bottom_cnt) |
| { |
| bottom_start+=direction; |
| top_start-=direction; |
| glEvalCoord2f((GLfloat)bottom_z/bottom_domain, |
| (GLfloat)bottom_start/bottom_domain); |
| } |
| glEnd(); |
| top_cnt-=direction*tri_cnt; |
| bottom_cnt-=direction; |
| } |
| } |
| |
| void |
| tesselate_strip_t(GLenum display_mode, GLint top_start, GLint top_end, |
| GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z, |
| GLint bottom_domain) |
| { |
| if(display_mode==GL_FILL) |
| tesselate_strip_t_fill(top_start,top_end,top_z,bottom_start, |
| bottom_end,bottom_z,bottom_domain); |
| else |
| tesselate_strip_t_line(top_start,top_end,top_z,bottom_start, |
| bottom_end,bottom_z,bottom_domain); |
| } |
| |
| |
| void |
| tesselate_strip_s_fill(GLint top_start, GLint top_end, GLint top_z, |
| GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain) |
| { |
| GLint top_cnt,bottom_cnt,tri_cnt,k; |
| GLint direction; |
| |
| top_cnt=top_end-top_start; |
| direction= (top_cnt>=0 ? 1: -1); |
| bottom_cnt=bottom_end-bottom_start; |
| while(top_cnt) |
| { |
| if(bottom_cnt) |
| tri_cnt=top_cnt/bottom_cnt; |
| else |
| tri_cnt=abs(top_cnt); |
| glBegin(GL_TRIANGLE_FAN); |
| glEvalCoord2f((GLfloat)bottom_start/bottom_domain, |
| (GLfloat)bottom_z/bottom_domain); |
| for(k=0;k<=tri_cnt;k++ , top_start+=direction) |
| glEvalPoint2(top_start,top_z); |
| if(bottom_cnt) |
| { |
| bottom_start+=direction; |
| top_start-=direction; |
| glEvalCoord2f((GLfloat)bottom_start/bottom_domain, |
| (GLfloat)bottom_z/bottom_domain); |
| } |
| glEnd(); |
| top_cnt-=direction*tri_cnt; |
| bottom_cnt-=direction; |
| } |
| } |
| |
| void |
| tesselate_strip_s_line(GLint top_start, GLint top_end, GLint top_z, |
| GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain) |
| { |
| GLint top_cnt,bottom_cnt,tri_cnt,k; |
| GLint direction; |
| |
| top_cnt=top_end-top_start; |
| direction= (top_cnt>=0 ? 1: -1); |
| bottom_cnt=bottom_end-bottom_start; |
| glBegin(GL_LINES); |
| while(top_cnt) |
| { |
| if(bottom_cnt) |
| tri_cnt=top_cnt/bottom_cnt; |
| else |
| tri_cnt=abs(top_cnt); |
| for(k=0;k<=tri_cnt;k++ , top_start+=direction) |
| { |
| glEvalCoord2f((GLfloat)bottom_start/bottom_domain, |
| (GLfloat)bottom_z/bottom_domain); |
| glEvalPoint2(top_start,top_z); |
| } |
| if(bottom_cnt) |
| { |
| glEvalCoord2f((GLfloat)bottom_start/bottom_domain, |
| (GLfloat)bottom_z/bottom_domain); |
| bottom_start+=direction; |
| top_start-=direction; |
| glEvalCoord2f((GLfloat)bottom_start/bottom_domain, |
| (GLfloat)bottom_z/bottom_domain); |
| glEvalPoint2(top_start,top_z); |
| glEvalCoord2f((GLfloat)bottom_start/bottom_domain, |
| (GLfloat)bottom_z/bottom_domain); |
| } |
| top_cnt-=direction*tri_cnt; |
| bottom_cnt-=direction; |
| } |
| glEnd(); |
| } |
| |
| void |
| tesselate_strip_s(GLenum display_mode, GLint top_start, GLint top_end, |
| GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z, |
| GLfloat bottom_domain) |
| { |
| if(display_mode==GL_FILL) |
| tesselate_strip_s_fill(top_start,top_end,top_z,bottom_start, |
| bottom_end,bottom_z,bottom_domain); |
| else |
| tesselate_strip_s_line(top_start,top_end,top_z,bottom_start, |
| bottom_end,bottom_z,bottom_domain); |
| } |
| |
| void |
| tesselate_bottom_left_corner(GLenum display_mode, GLfloat s_1, GLfloat t_1) |
| { |
| if(display_mode==GL_FILL) |
| { |
| glBegin(GL_TRIANGLE_FAN); |
| glEvalPoint2(1,1); |
| glEvalCoord2f(s_1,0.0); |
| glEvalCoord2f(0.0,0.0); |
| glEvalCoord2f(0.0,t_1); |
| } |
| else |
| { |
| glBegin(GL_LINES); |
| glEvalCoord2f(0.0,0.0); |
| glEvalCoord2f(0.0,t_1); |
| glEvalCoord2f(0.0,0.0); |
| glEvalPoint2(1,1); |
| glEvalCoord2f(0.0,0.0); |
| glEvalCoord2f(s_1,0.0); |
| } |
| glEnd(); |
| } |
| |
| void |
| tesselate_bottom_right_corner(GLenum display_mode, GLint v_top,GLint v_bottom, |
| GLfloat s_1, GLfloat t_1) |
| { |
| if(display_mode==GL_FILL) |
| { |
| glBegin(GL_TRIANGLE_FAN); |
| glEvalPoint2(1,v_top); |
| glEvalCoord2f(0.0,v_bottom*t_1); |
| glEvalCoord2f(0.0,(v_bottom+1)*t_1); |
| glEvalCoord2f(s_1,(v_bottom+1)*t_1); |
| } |
| else |
| { |
| glBegin(GL_LINES); |
| glEvalCoord2f(0.0,(v_bottom+1)*t_1); |
| glEvalPoint2(1,v_top); |
| glEvalCoord2f(0.0,(v_bottom+1)*t_1); |
| glEvalCoord2f(0.0,v_bottom*t_1); |
| glEvalCoord2f(0.0,(v_bottom+1)*t_1); |
| glEvalCoord2f(s_1,(v_bottom+1)*t_1); |
| } |
| glEnd(); |
| } |
| |
| void |
| tesselate_top_left_corner(GLenum display_mode, GLint u_right, GLint u_left, |
| GLfloat s_1, GLfloat t_1) |
| { |
| if(display_mode==GL_FILL) |
| { |
| glBegin(GL_TRIANGLE_FAN); |
| glEvalPoint2(u_right,1); |
| glEvalCoord2f((u_left+1)*s_1,t_1); |
| glEvalCoord2f((u_left+1)*s_1,0.0); |
| glEvalCoord2f(u_left*s_1,0.0); |
| } |
| else |
| { |
| glBegin(GL_LINES); |
| glEvalCoord2f((u_left+1)*s_1,0.0); |
| glEvalPoint2(u_right,1); |
| glEvalCoord2f((u_left+1)*s_1,0.0); |
| glEvalCoord2f(u_left*s_1,0.0); |
| glEvalCoord2f((u_left+1)*s_1,0.0); |
| glEvalCoord2f((u_left+1)*s_1,t_1); |
| } |
| glEnd(); |
| } |
| |
| void |
| tesselate_top_right_corner(GLenum display_mode, GLint u_left, GLint v_bottom, |
| GLint u_right, GLint v_top, GLfloat s_1, GLfloat t_1) |
| { |
| if(display_mode==GL_FILL) |
| { |
| glBegin(GL_TRIANGLE_FAN); |
| glEvalPoint2(u_left,v_bottom); |
| glEvalCoord2f((u_right-1)*s_1,v_top*t_1); |
| glEvalCoord2f(u_right*s_1,v_top*t_1); |
| glEvalCoord2f(u_right*s_1,(v_top-1)*t_1); |
| } |
| else |
| { |
| glBegin(GL_LINES); |
| glEvalCoord2f(u_right*s_1,v_top*t_1); |
| glEvalPoint2(u_left,v_bottom); |
| glEvalCoord2f(u_right*s_1,v_top*t_1); |
| glEvalCoord2f(u_right*s_1,(v_top-1)*t_1); |
| glEvalCoord2f(u_right*s_1,v_top*t_1); |
| glEvalCoord2f((u_right-1)*s_1,v_top*t_1); |
| } |
| glEnd(); |
| } |
| |
| /* do mesh mapping of Bezier */ |
| static void |
| nurbs_map_bezier(GLenum display_mode,GLint *sfactors,GLint *tfactors, |
| GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t) |
| { |
| GLint top,bottom,right,left; |
| |
| |
| if(s==0) |
| { |
| top=*(tfactors+t*3); |
| bottom=*(tfactors+t*3+1); |
| } |
| else |
| if(s==s_bezier_cnt-1) |
| { |
| top=*(tfactors+t*3+2); |
| bottom=*(tfactors+t*3); |
| } |
| else |
| { |
| top=bottom=*(tfactors+t*3); |
| } |
| if(t==0) |
| { |
| left=*(sfactors+s*3+1); |
| right=*(sfactors+s*3); |
| } |
| else |
| if(t==t_bezier_cnt-1) |
| { |
| left=*(sfactors+s*3); |
| right=*(sfactors+s*3+2); |
| } |
| else |
| { |
| left=right=*(sfactors+s*3); |
| } |
| |
| if(top>bottom) |
| { |
| if(left<right) |
| { |
| glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); |
| glEvalMesh2(display_mode,1,right, 1, top); |
| tesselate_strip_s(display_mode,1,right,1,1,left,0,(GLfloat)left); |
| tesselate_bottom_left_corner(display_mode,(GLfloat)(1.0/left), |
| (GLfloat)(1.0/bottom)); |
| /* tesselate_strip_t(display_mode,1,top,1,1,bottom,0,(GLfloat)bottom);*/ |
| tesselate_strip_t(display_mode,top,1,1,bottom,1,0,(GLfloat)bottom); |
| } |
| else |
| if(left==right) |
| { |
| glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); |
| glEvalMesh2(display_mode,1,right, 0, top); |
| /* tesselate_strip_t(display_mode,0,top,1,0,bottom,0,(GLfloat)bottom);*/ |
| tesselate_strip_t(display_mode,top,0,1,bottom,0,0,(GLfloat)bottom); |
| } |
| else |
| { |
| glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0); |
| glEvalMesh2(display_mode,1,left, 0, top-1); |
| /* tesselate_strip_t(display_mode,0,top-1,1,0,bottom-1,0, |
| (GLfloat)bottom);*/ |
| tesselate_strip_t(display_mode,top-1,0,1,bottom-1,0,0, |
| (GLfloat)bottom); |
| tesselate_bottom_right_corner(display_mode,top-1,bottom-1, |
| (GLfloat)(1.0/right),(GLfloat)(1.0/bottom)); |
| /* tesselate_strip_s(display_mode,1,left,top-1,1,right,right, |
| (GLfloat)right);*/ |
| tesselate_strip_s(display_mode,left,1,top-1,right,1,right, |
| (GLfloat)right); |
| } |
| } |
| else |
| if(top==bottom) |
| { |
| if(left<right) |
| { |
| glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); |
| glEvalMesh2(display_mode,0,right, 1, top); |
| tesselate_strip_s(display_mode,0,right,1,0,left,0,(GLfloat)left); |
| } |
| else |
| if(left==right) |
| { |
| glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); |
| glEvalMesh2(display_mode,0,right, 0, top); |
| } |
| else |
| { |
| glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0); |
| glEvalMesh2(display_mode,0,left, 0, top-1); |
| /* tesselate_strip_s(display_mode,0,left,top-1,0,right,right, |
| (GLfloat)right);*/ |
| tesselate_strip_s(display_mode,left,0,top-1,right,0,right, |
| (GLfloat)right); |
| } |
| } |
| else |
| { |
| if(left<right) |
| { |
| glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0); |
| glEvalMesh2(display_mode,0,right-1, 1, bottom); |
| tesselate_strip_s(display_mode,0,right-1,1,0,left-1,0, |
| (GLfloat)left); |
| tesselate_top_left_corner(display_mode,right-1,left-1, |
| (GLfloat)(1.0/left),(GLfloat)(1.0/top)); |
| tesselate_strip_t(display_mode,1,bottom,right-1,1,top,top, |
| (GLfloat)top); |
| } |
| else |
| if(left==right) |
| { |
| glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0); |
| glEvalMesh2(display_mode,0,right-1, 0, bottom); |
| tesselate_strip_t(display_mode,0,bottom,right-1,0,top,top, |
| (GLfloat)top); |
| } |
| else |
| { |
| glMapGrid2f(left, 0.0, 1.0, bottom, 0.0, 1.0); |
| glEvalMesh2(display_mode,0,left-1, 0, bottom-1); |
| tesselate_strip_t(display_mode,0,bottom-1,left-1,0,top-1,top, |
| (GLfloat)top); |
| tesselate_top_right_corner(display_mode,left-1,bottom-1,right,top, |
| (GLfloat)(1.0/right),(GLfloat)(1.0/top)); |
| /* tesselate_strip_s(display_mode,0,left-1,bottom-1,0,right-1,right, |
| (GLfloat)right);*/ |
| tesselate_strip_s(display_mode,left-1,0,bottom-1,right-1,0,right, |
| (GLfloat)right); |
| } |
| } |
| } |
| |
| /* draw NURBS surface in OUTLINE POLYGON mode */ |
| static void |
| draw_polygon_mode( GLenum display_mode, GLUnurbsObj *nobj, |
| new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors ) |
| { |
| GLsizei offset; |
| GLint t_bezier_cnt,s_bezier_cnt; |
| GLboolean do_color,do_normal,do_texture; |
| GLint i,j; |
| |
| t_bezier_cnt=new_ctrl->t_bezier_cnt; |
| s_bezier_cnt=new_ctrl->s_bezier_cnt; |
| glEnable(nobj->surface.geom.type); |
| if(new_ctrl->color_ctrl) |
| { |
| glEnable(nobj->surface.color.type); |
| do_color=GL_TRUE; |
| } |
| else |
| do_color=GL_FALSE; |
| if(new_ctrl->normal_ctrl) |
| { |
| glEnable(nobj->surface.normal.type); |
| do_normal=GL_TRUE; |
| } |
| else |
| do_normal=GL_FALSE; |
| if(new_ctrl->texture_ctrl) |
| { |
| glEnable(nobj->surface.texture.type); |
| do_texture=GL_TRUE; |
| } |
| else |
| do_texture=GL_FALSE; |
| for(j=0; j<s_bezier_cnt; j++) |
| { |
| for(i=0; i<t_bezier_cnt; i++) |
| { |
| offset=j*t_bezier_cnt + i; |
| if(fine_culling_test_3D(nobj,*(new_ctrl->geom_offsets + offset), |
| nobj->surface.geom.sorder,nobj->surface.geom.torder, |
| new_ctrl->geom_s_stride,new_ctrl->geom_t_stride, |
| nobj->surface.geom.dim)) |
| continue; |
| glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride, |
| nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride, |
| nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset)); |
| if(do_color) |
| { |
| glMap2f(nobj->surface.color.type,0.0,1.0, |
| new_ctrl->color_s_stride,nobj->surface.color.sorder, |
| 0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder, |
| *(new_ctrl->color_offsets + offset)); |
| } |
| if(do_normal) |
| { |
| glMap2f(nobj->surface.normal.type,0.0,1.0, |
| new_ctrl->normal_s_stride,nobj->surface.normal.sorder, |
| 0.0,1.0,new_ctrl->normal_t_stride, |
| nobj->surface.normal.torder, |
| *(new_ctrl->normal_offsets+offset)); |
| } |
| if(do_texture) |
| { |
| glMap2f(nobj->surface.texture.type,0.0,1.0, |
| new_ctrl->texture_s_stride,nobj->surface.texture.sorder, |
| 0.0,1.0,new_ctrl->texture_t_stride, |
| nobj->surface.texture.torder, |
| *(new_ctrl->texture_offsets+offset)); |
| } |
| /* glMapGrid2f(sfactors[j*3+0],0.0,1.0,tfactors[i*3+0],0.0,1.0); |
| glEvalMesh2(display_mode,0,sfactors[j*3+0],0,tfactors[i*3+0]);*/ |
| nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt, |
| t_bezier_cnt,j,i); |
| } |
| } |
| } |
| |
| |
| |
| /* draw NURBS surface in OUTLINE POLYGON mode */ |
| #if 0 |
| static void |
| draw_patch_mode( GLenum display_mode, GLUnurbsObj *nobj, |
| new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors ) |
| { |
| GLsizei offset; |
| GLint t_bezier_cnt,s_bezier_cnt; |
| GLboolean do_color,do_normal,do_texture; |
| GLint i,j; |
| |
| t_bezier_cnt=new_ctrl->t_bezier_cnt; |
| s_bezier_cnt=new_ctrl->s_bezier_cnt; |
| glEnable(nobj->surface.geom.type); |
| if(new_ctrl->color_ctrl) |
| { |
| glEnable(nobj->surface.color.type); |
| do_color=GL_TRUE; |
| } |
| else |
| do_color=GL_FALSE; |
| if(new_ctrl->normal_ctrl) |
| { |
| glEnable(nobj->surface.normal.type); |
| do_normal=GL_TRUE; |
| } |
| else |
| do_normal=GL_FALSE; |
| if(new_ctrl->texture_ctrl) |
| { |
| glEnable(nobj->surface.texture.type); |
| do_texture=GL_TRUE; |
| } |
| else |
| do_texture=GL_FALSE; |
| for(j=0; j<s_bezier_cnt; j++) |
| { |
| for(i=0; i<t_bezier_cnt; i++) |
| { |
| offset=j*t_bezier_cnt + i; |
| if(fine_culling_test_3D(nobj,*(new_ctrl->geom_offsets + offset), |
| nobj->surface.geom.sorder,nobj->surface.geom.torder, |
| new_ctrl->geom_s_stride,new_ctrl->geom_t_stride, |
| nobj->surface.geom.dim)) |
| continue; |
| glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride, |
| nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride, |
| nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset)); |
| if(do_color) |
| { |
| glMap2f(nobj->surface.color.type,0.0,1.0, |
| new_ctrl->color_s_stride,nobj->surface.color.sorder, |
| 0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder, |
| *(new_ctrl->color_offsets + offset)); |
| } |
| if(do_normal) |
| { |
| glMap2f(nobj->surface.normal.type,0.0,1.0, |
| new_ctrl->normal_s_stride,nobj->surface.normal.sorder, |
| 0.0,1.0,new_ctrl->normal_t_stride, |
| nobj->surface.normal.torder, |
| *(new_ctrl->normal_offsets+offset)); |
| } |
| if(do_texture) |
| { |
| glMap2f(nobj->surface.texture.type,0.0,1.0, |
| new_ctrl->texture_s_stride,nobj->surface.texture.sorder, |
| 0.0,1.0,new_ctrl->texture_t_stride, |
| nobj->surface.texture.torder, |
| *(new_ctrl->texture_offsets+offset)); |
| } |
| nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt, |
| t_bezier_cnt,i,j); |
| /* glMapGrid2f(sfactors[j],0.0,1.0,tfactors[i],0.0,1.0); |
| glEvalMesh2(display_mode,0,sfactors[j],0,tfactors[i]);*/ |
| } |
| } |
| } |
| #endif |
| |
| |
| |
| void |
| init_new_ctrl(new_ctrl_type *p) |
| { |
| p->geom_ctrl=p->color_ctrl=p->normal_ctrl=p->texture_ctrl=NULL; |
| p->geom_offsets=p->color_offsets=p->normal_offsets=p->texture_offsets=NULL; |
| p->s_bezier_cnt=p->t_bezier_cnt=0; |
| } |
| |
| GLenum |
| augment_new_ctrl(GLUnurbsObj *nobj, new_ctrl_type *p) |
| { |
| GLsizei offset_size; |
| GLint i,j; |
| |
| p->s_bezier_cnt=(p->geom_s_pt_cnt)/(nobj->surface.geom.sorder); |
| p->t_bezier_cnt=(p->geom_t_pt_cnt)/(nobj->surface.geom.torder); |
| offset_size=(p->s_bezier_cnt)*(p->t_bezier_cnt); |
| p->geom_t_stride=nobj->surface.geom.dim; |
| p->geom_s_stride=(p->geom_t_pt_cnt)*(nobj->surface.geom.dim); |
| p->color_t_stride=nobj->surface.color.dim; |
| p->color_s_stride=(p->color_t_pt_cnt)*(nobj->surface.color.dim); |
| p->normal_t_stride=nobj->surface.normal.dim; |
| p->normal_s_stride=(p->normal_t_pt_cnt)*(nobj->surface.normal.dim); |
| p->texture_t_stride=nobj->surface.texture.dim; |
| p->texture_s_stride=(p->texture_t_pt_cnt)*(nobj->surface.texture.dim); |
| if((p->geom_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) |
| { |
| call_user_error(nobj,GLU_OUT_OF_MEMORY); |
| return GLU_ERROR; |
| } |
| if(p->color_ctrl) |
| if((p->color_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) |
| { |
| free_new_ctrl(p); |
| call_user_error(nobj,GLU_OUT_OF_MEMORY); |
| return GLU_ERROR; |
| } |
| if(p->normal_ctrl) |
| if((p->normal_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) |
| { |
| free_new_ctrl(p); |
| call_user_error(nobj,GLU_OUT_OF_MEMORY); |
| return GLU_ERROR; |
| } |
| if(p->texture_ctrl) |
| if((p->texture_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) |
| { |
| free_new_ctrl(p); |
| call_user_error(nobj,GLU_OUT_OF_MEMORY); |
| return GLU_ERROR; |
| } |
| for(i=0;i<p->s_bezier_cnt;i++) |
| for(j=0;j<p->t_bezier_cnt;j++) |
| *(p->geom_offsets + i*(p->t_bezier_cnt) + j) = |
| p->geom_ctrl + i*(nobj->surface.geom.sorder)* |
| (nobj->surface.geom.dim)*(p->geom_t_pt_cnt) + |
| j*(nobj->surface.geom.dim)*(nobj->surface.geom.torder); |
| if(p->color_ctrl) |
| for(i=0;i<p->s_bezier_cnt;i++) |
| for(j=0;j<p->t_bezier_cnt;j++) |
| *(p->color_offsets + i*(p->t_bezier_cnt) + j) = |
| p->color_ctrl + i*(nobj->surface.color.sorder)* |
| (nobj->surface.color.dim)*(p->color_t_pt_cnt) + |
| j*(nobj->surface.color.dim)*(nobj->surface.color.torder); |
| if(p->normal_ctrl) |
| for(i=0;i<p->s_bezier_cnt;i++) |
| for(j=0;j<p->t_bezier_cnt;j++) |
| *(p->normal_offsets + i*(p->t_bezier_cnt) + j) = |
| p->normal_ctrl + i*(nobj->surface.normal.sorder)* |
| (nobj->surface.normal.dim)*(p->normal_t_pt_cnt) + |
| j*(nobj->surface.normal.dim)*(nobj->surface.normal.torder); |
| if(p->texture_ctrl) |
| for(i=0;i<p->s_bezier_cnt;i++) |
| for(j=0;j<p->t_bezier_cnt;j++) |
| *(p->texture_offsets + i*(p->t_bezier_cnt) + j) = |
| p->texture_ctrl + i*(nobj->surface.texture.sorder)* |
| (nobj->surface.texture.dim)*(p->texture_t_pt_cnt) + |
| j*(nobj->surface.texture.dim)*(nobj->surface.texture.torder); |
| return GLU_NO_ERROR; |
| } |
| |
| /* main NURBS surface procedure */ |
| void |
| do_nurbs_surface( GLUnurbsObj *nobj ) |
| { |
| GLint *sfactors,*tfactors; |
| new_ctrl_type new_ctrl; |
| |
| /* test user supplied data */ |
| if(test_nurbs_surfaces(nobj)!=GLU_NO_ERROR) |
| return; |
| |
| init_new_ctrl(&new_ctrl); |
| |
| if(convert_surfs(nobj,&new_ctrl)!=GLU_NO_ERROR) |
| return; |
| if(augment_new_ctrl(nobj,&new_ctrl)!=GLU_NO_ERROR) |
| return; |
| switch(nobj->sampling_method) |
| { |
| case GLU_PATH_LENGTH: |
| if(glu_do_sampling_3D(nobj,&new_ctrl,&sfactors,&tfactors)!= |
| GLU_NO_ERROR) |
| { |
| free_new_ctrl(&new_ctrl); |
| return; |
| } |
| break; |
| case GLU_DOMAIN_DISTANCE: |
| if(glu_do_sampling_uv(nobj,&new_ctrl,&sfactors,&tfactors)!= |
| GLU_NO_ERROR) |
| { |
| free_new_ctrl(&new_ctrl); |
| return; |
| } |
| break; |
| case GLU_PARAMETRIC_ERROR: |
| if(glu_do_sampling_param_3D(nobj,&new_ctrl,&sfactors,&tfactors)!= |
| GLU_NO_ERROR) |
| { |
| free_new_ctrl(&new_ctrl); |
| return; |
| } |
| break; |
| default: |
| abort(); |
| } |
| glFrontFace(GL_CW); |
| switch(nobj->display_mode) |
| { |
| case GLU_FILL: |
| /* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/ |
| draw_polygon_mode(GL_FILL,nobj,&new_ctrl,sfactors,tfactors); |
| break; |
| case GLU_OUTLINE_POLYGON: |
| /* TODO - missing trimming handeling */ |
| /* just for now - no OUTLINE_PATCH mode |
| draw_patch_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors); |
| break; */ |
| case GLU_OUTLINE_PATCH: |
| /* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/ |
| draw_polygon_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors); |
| break; |
| default: |
| abort(); /* TODO: is this OK? */ |
| } |
| free(sfactors); |
| free(tfactors); |
| free_new_ctrl(&new_ctrl); |
| } |
| |