1 /* $Id: nurbscrv.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-1997 Brian Paul
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.
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.
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.
25 * $Log: nurbscrv.c,v $
26 * Revision 1.1 1999/08/19 00:55:42 jtg
29 * Revision 1.6 1997/07/24 01:28:44 brianp
30 * changed precompiled header symbol from PCH to PC_HEADER
32 * Revision 1.5 1997/05/28 02:29:38 brianp
33 * added support for precompiled headers (PCH), inserted APIENTRY keyword
35 * Revision 1.4 1997/05/27 03:21:22 brianp
38 * Revision 1.3 1997/05/27 03:00:16 brianp
39 * incorporated Bogdan's new NURBS code
41 * Revision 1.2 1996/09/27 23:12:22 brianp
42 * added return 0 to get_surface_dim() to silence warning
44 * Revision 1.1 1996/09/27 01:19:39 brianp
51 * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
52 * See README2 for more info.
67 get_curve_dim(GLenum type
)
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? */
82 return 0; /*never get here*/
86 test_nurbs_curve(GLUnurbsObj
*nobj
, curve_attribs
*attribs
)
91 if(attribs
->order
< 0)
93 call_user_error(nobj
,GLU_INVALID_VALUE
);
96 glGetIntegerv(GL_MAX_EVAL_ORDER
,&tmp_int
);
97 if(attribs
->order
> tmp_int
|| attribs
->order
< 2)
99 call_user_error(nobj
,GLU_NURBS_ERROR1
);
102 if(attribs
->knot_count
< attribs
->order
+2)
104 call_user_error(nobj
,GLU_NURBS_ERROR2
);
107 if(attribs
->stride
< 0)
109 call_user_error(nobj
,GLU_NURBS_ERROR34
);
112 if(attribs
->knot
==NULL
|| attribs
->ctrlarray
==NULL
)
114 call_user_error(nobj
,GLU_NURBS_ERROR36
);
117 if((err
=test_knot(attribs
->knot_count
,attribs
->knot
,attribs
->order
))
120 call_user_error(nobj
,err
);
127 test_nurbs_curves(GLUnurbsObj
*nobj
)
129 /* test the geometric data */
130 if(test_nurbs_curve(nobj
,&(nobj
->curve
.geom
))!=GLU_NO_ERROR
)
132 /* now test the attributive data */
134 if(nobj
->curve
.color
.type
!=GLU_INVALID_ENUM
)
135 if(test_nurbs_curve(nobj
,&(nobj
->curve
.color
))!=GLU_NO_ERROR
)
138 if(nobj
->curve
.normal
.type
!=GLU_INVALID_ENUM
)
139 if(test_nurbs_curve(nobj
,&(nobj
->curve
.normal
))!=GLU_NO_ERROR
)
142 if(nobj
->curve
.texture
.type
!=GLU_INVALID_ENUM
)
143 if(test_nurbs_curve(nobj
,&(nobj
->curve
.texture
))!=GLU_NO_ERROR
)
148 /* prepare the knot information structures */
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
)
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
)
168 call_user_error(nobj
,GLU_NURBS_ERROR3
);
171 if(fabs(knot
[0]-knot
[t_min
])<EPSILON
)
173 /* knot open at beggining */
174 geom_knot
->open_at_begin
=GL_TRUE
;
177 geom_knot
->open_at_begin
=GL_FALSE
;
178 if(fabs(knot
[t_max
]-knot
[nknots
-1])<EPSILON
)
180 /* knot open at end */
181 geom_knot
->open_at_end
=GL_TRUE
;
184 geom_knot
->open_at_end
=GL_FALSE
;
185 if(nobj
->curve
.color
.type
!=GLU_INVALID_ENUM
)
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
)
196 call_user_error(nobj
,GLU_NURBS_ERROR3
);
199 if(fabs(knot
[0]-knot
[t_min
])<EPSILON
)
201 /* knot open at beggining */
202 color_knot
->open_at_begin
=GL_TRUE
;
205 color_knot
->open_at_begin
=GL_FALSE
;
206 if(fabs(knot
[t_max
]-knot
[nknots
-1])<EPSILON
)
208 /* knot open at end */
209 color_knot
->open_at_end
=GL_TRUE
;
212 color_knot
->open_at_end
=GL_FALSE
;
215 color_knot
->unified_knot
=NULL
;
216 if(nobj
->curve
.normal
.type
!=GLU_INVALID_ENUM
)
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
)
227 call_user_error(nobj
,GLU_NURBS_ERROR3
);
230 if(fabs(knot
[0]-knot
[t_min
])<EPSILON
)
232 /* knot open at beggining */
233 normal_knot
->open_at_begin
=GL_TRUE
;
236 normal_knot
->open_at_begin
=GL_FALSE
;
237 if(fabs(knot
[t_max
]-knot
[nknots
-1])<EPSILON
)
239 /* knot open at end */
240 normal_knot
->open_at_end
=GL_TRUE
;
243 normal_knot
->open_at_end
=GL_FALSE
;
246 normal_knot
->unified_knot
=NULL
;
247 if(nobj
->curve
.texture
.type
!=GLU_INVALID_ENUM
)
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
)
258 call_user_error(nobj
,GLU_NURBS_ERROR3
);
261 if(fabs(knot
[0]-knot
[t_min
])<EPSILON
)
263 /* knot open at beggining */
264 texture_knot
->open_at_begin
=GL_TRUE
;
267 texture_knot
->open_at_begin
=GL_FALSE
;
268 if(fabs(knot
[t_max
]-knot
[nknots
-1])<EPSILON
)
270 /* knot open at end */
271 texture_knot
->open_at_end
=GL_TRUE
;
274 texture_knot
->open_at_end
=GL_FALSE
;
277 texture_knot
->unified_knot
=NULL
;
281 /* covert the NURBS curve into a series of adjacent Bezier curves */
283 convert_curve(knot_str_type
*the_knot
, curve_attribs
*attrib
,
284 GLfloat
**new_ctrl
,GLint
*ncontrol
)
288 if((err
=explode_knot(the_knot
))!=GLU_NO_ERROR
)
290 if(the_knot
->unified_knot
)
292 free(the_knot
->unified_knot
);
293 the_knot
->unified_knot
=NULL
;
297 if(the_knot
->unified_knot
)
299 free(the_knot
->unified_knot
);
300 the_knot
->unified_knot
=NULL
;
302 if((err
=calc_alphas(the_knot
))!=GLU_NO_ERROR
)
304 free(the_knot
->new_knot
);
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
))
312 free(the_knot
->alpha
);
315 free(the_knot
->alpha
);
319 /* covert curves - geometry and possible attribute ones into equivalent */
320 /* sequence of adjacent Bezier curves */
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
)
326 knot_str_type geom_knot
,color_knot
,normal_knot
,texture_knot
;
330 *new_color_ctrl
=*new_normal_ctrl
=*new_texture_ctrl
=NULL
;
332 if(fill_knot_structures(nobj
,&geom_knot
,&color_knot
,&normal_knot
,
333 &texture_knot
)!=GLU_NO_ERROR
)
336 /* unify knots - all knots should have the same number of working */
338 if((err
=select_knot_working_range(nobj
,&geom_knot
,&color_knot
,&normal_knot
,
339 &texture_knot
))!=GLU_NO_ERROR
)
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
)
348 free_unified_knots(&geom_knot
,&color_knot
,&normal_knot
,&texture_knot
);
349 call_user_error(nobj
,err
);
352 /* if additional attributive curves are given convert them as well */
353 if(color_knot
.unified_knot
)
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
)
359 free_unified_knots(&geom_knot
,&color_knot
,&normal_knot
,&texture_knot
);
360 free(*new_geom_ctrl
);
361 call_user_error(nobj
,err
);
365 if(normal_knot
.unified_knot
)
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
)
371 free_unified_knots(&geom_knot
,&color_knot
,&normal_knot
,&texture_knot
);
372 free(*new_geom_ctrl
);
374 free(*new_color_ctrl
);
375 call_user_error(nobj
,err
);
379 if(texture_knot
.unified_knot
)
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
)
385 free_unified_knots(&geom_knot
,&color_knot
,&normal_knot
,&texture_knot
);
386 free(*new_geom_ctrl
);
388 free(*new_color_ctrl
);
390 free(*new_normal_ctrl
);
391 call_user_error(nobj
,err
);
398 /* main NURBS curve procedure */
399 void do_nurbs_curve( GLUnurbsObj
*nobj
)
401 GLint geom_order
,color_order
=0,normal_order
=0,texture_order
=0;
404 GLfloat
*new_geom_ctrl
,*new_color_ctrl
,*new_normal_ctrl
,*new_texture_ctrl
;
405 GLfloat
*geom_ctrl
,*color_ctrl
,*normal_ctrl
,*texture_ctrl
;
408 GLint geom_dim
,color_dim
=0,normal_dim
=0,texture_dim
=0;
410 /* test the user supplied data */
411 if(test_nurbs_curves(nobj
)!=GLU_NO_ERROR
)
414 if(convert_curves(nobj
,&new_geom_ctrl
,&n_ctrl
,&new_color_ctrl
,
415 &new_normal_ctrl
,&new_texture_ctrl
)!=GLU_NO_ERROR
)
418 geom_order
=nobj
->curve
.geom
.order
;
419 geom_type
=nobj
->curve
.geom
.type
;
420 geom_dim
=nobj
->curve
.geom
.dim
;
422 if(glu_do_sampling_crv(nobj
,new_geom_ctrl
,n_ctrl
,geom_order
,geom_dim
,
428 free(new_color_ctrl
);
430 free(new_normal_ctrl
);
432 free(new_texture_ctrl
);
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
;
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
;
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
;
457 for(i
=0 , j
=0, geom_ctrl
=new_geom_ctrl
;
459 i
+=geom_order
, j
++ , geom_ctrl
+=geom_order
*geom_dim
)
461 if(fine_culling_test_2D(nobj
,geom_ctrl
,geom_order
,geom_dim
,geom_dim
))
463 color_ctrl
+=color_order
*color_dim
;
464 normal_ctrl
+=normal_order
*normal_dim
;
465 texture_ctrl
+=texture_order
*texture_dim
;
468 glMap1f(geom_type
, 0.0, 1.0, geom_dim
, geom_order
, geom_ctrl
);
471 glMap1f(nobj
->curve
.color
.type
, 0.0, 1.0, color_dim
,
472 color_order
,color_ctrl
);
473 color_ctrl
+=color_order
*color_dim
;
477 glMap1f(nobj
->curve
.normal
.type
, 0.0, 1.0, normal_dim
,
478 normal_order
,normal_ctrl
);
479 normal_ctrl
+=normal_order
*normal_dim
;
483 glMap1f(nobj
->curve
.texture
.type
, 0.0, 1.0, texture_dim
,
484 texture_order
,texture_ctrl
);
485 texture_ctrl
+=texture_order
*texture_dim
;
487 glMapGrid1f(factors
[j
],0.0,1.0);
488 glEvalMesh1(GL_LINE
,0,factors
[j
]);
493 free(new_color_ctrl
);
495 free(new_normal_ctrl
);
497 free(new_texture_ctrl
);