1 /* $Id: nurbs.c,v 1.3 2000/02/10 17:45:52 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-2000 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 * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
26 * See README2 for more info.
40 call_user_error( GLUnurbsObj
*nobj
, GLenum error
)
43 if(nobj
->error_callback
!= NULL
) {
44 (*(nobj
->error_callback
))(error
);
47 printf("NURBS error %d %s\n", error
, (char *) gluErrorString(error
) );
53 GLUnurbsObj
* GLAPIENTRY
gluNewNurbsRenderer( void )
56 GLfloat tmp_viewport
[4];
59 n
= (GLUnurbsObj
*) malloc( sizeof(GLUnurbsObj
) );
63 n
->nurbs_type
=GLU_NURBS_NONE
;
64 n
->error
=GLU_NO_ERROR
;
65 n
->error_callback
=NULL
;
66 n
->auto_load_matrix
=GL_TRUE
;
67 n
->sampling_tolerance
=50.0;
68 n
->parametric_tolerance
=0.5;
69 n
->u_step
= n
->v_step
= 100;
70 n
->sampling_method
= GLU_PATH_LENGTH
;
71 n
->display_mode
=GLU_FILL
;
72 /* in case the user doesn't supply the sampling matrices */
73 /* set projection and modelview to identity */
78 n
->sampling_matrices
.model
[i
*4+j
]=1.0;
79 n
->sampling_matrices
.proj
[i
*4+j
]=1.0;
83 n
->sampling_matrices
.model
[i
*4+j
]=0.0;
84 n
->sampling_matrices
.proj
[i
*4+j
]=0.0;
86 /* and set the viewport sampling matrix to current ciewport */
87 glGetFloatv(GL_VIEWPORT
,tmp_viewport
);
89 n
->sampling_matrices
.viewport
[i
]=tmp_viewport
[i
];
97 void GLAPIENTRY
gluDeleteNurbsRenderer( GLUnurbsObj
*nobj
)
106 void GLAPIENTRY
gluLoadSamplingMatrices( GLUnurbsObj
*nobj
,
107 const GLfloat modelMatrix
[16],
108 const GLfloat projMatrix
[16],
109 const GLint viewport
[4] )
115 nobj
->sampling_matrices
.model
[i
]=modelMatrix
[i
];
116 nobj
->sampling_matrices
.proj
[i
]=projMatrix
[i
];
119 nobj
->sampling_matrices
.viewport
[i
]=viewport
[i
];
123 void GLAPIENTRY
gluNurbsProperty( GLUnurbsObj
*nobj
, GLenum property
, GLfloat value
)
128 case GLU_SAMPLING_TOLERANCE
:
131 call_user_error(nobj
,GLU_INVALID_VALUE
);
134 nobj
->sampling_tolerance
=value
;
136 case GLU_PARAMETRIC_TOLERANCE
:
139 call_user_error(nobj
,GLU_INVALID_VALUE
);
142 nobj
->parametric_tolerance
=value
;
147 call_user_error(nobj
,GLU_INVALID_VALUE
);
150 nobj
->u_step
=(GLint
)value
;
155 call_user_error(nobj
,GLU_INVALID_VALUE
);
158 nobj
->v_step
=(GLint
)value
;
160 case GLU_SAMPLING_METHOD
:
162 if(val
!=GLU_PATH_LENGTH
&& val
!=GLU_PARAMETRIC_ERROR
&& val
!=GLU_DOMAIN_DISTANCE
)
164 call_user_error(nobj
,GLU_INVALID_ENUM
);
167 nobj
->sampling_method
=val
;
169 case GLU_DISPLAY_MODE
:
171 if(val
!=GLU_FILL
&& val
!=GLU_OUTLINE_POLYGON
&& val
!=GLU_OUTLINE_PATCH
)
173 call_user_error(nobj
,GLU_INVALID_ENUM
);
176 if(nobj
->nurbs_type
==GLU_NURBS_CURVE
)
178 call_user_error(nobj
,GLU_NURBS_ERROR26
);
181 nobj
->display_mode
=val
;
182 if(val
==GLU_OUTLINE_PATCH
)
183 fprintf(stderr
,"NURBS, for the moment, can display only in POLYGON mode\n");
187 if(val
!=GL_TRUE
&& val
!=GL_FALSE
)
189 call_user_error(nobj
,GLU_INVALID_ENUM
);
192 nobj
->culling
= (GLboolean
) value
;
194 case GLU_AUTO_LOAD_MATRIX
:
196 if(val
!=GL_TRUE
&& val
!=GL_FALSE
)
198 call_user_error(nobj
,GLU_INVALID_ENUM
);
201 nobj
->auto_load_matrix
= (GLboolean
) value
;
204 call_user_error(nobj
,GLU_NURBS_ERROR26
);
209 void GLAPIENTRY
gluGetNurbsProperty( GLUnurbsObj
*nobj
, GLenum property
, GLfloat
*value
)
212 case GLU_SAMPLING_TOLERANCE
:
213 *value
= nobj
->sampling_tolerance
;
215 case GLU_DISPLAY_MODE
:
216 *value
= (GLfloat
) (GLint
) nobj
->display_mode
;
219 *value
= nobj
->culling
? 1.0 : 0.0;
221 case GLU_AUTO_LOAD_MATRIX
:
222 *value
= nobj
->auto_load_matrix
? 1.0 : 0.0;
225 call_user_error(nobj
,GLU_INVALID_ENUM
);
231 void GLAPIENTRY
gluBeginCurve( GLUnurbsObj
*nobj
)
233 if(nobj
->nurbs_type
==GLU_NURBS_CURVE
)
235 call_user_error(nobj
,GLU_NURBS_ERROR6
);
238 nobj
->nurbs_type
=GLU_NURBS_CURVE
;
239 nobj
->curve
.geom
.type
=GLU_INVALID_ENUM
;
240 nobj
->curve
.color
.type
=GLU_INVALID_ENUM
;
241 nobj
->curve
.texture
.type
=GLU_INVALID_ENUM
;
242 nobj
->curve
.normal
.type
=GLU_INVALID_ENUM
;
246 void GLAPIENTRY
gluEndCurve( GLUnurbsObj
* nobj
)
248 if(nobj
->nurbs_type
==GLU_NURBS_NONE
)
250 call_user_error(nobj
,GLU_NURBS_ERROR7
);
253 if(nobj
->curve
.geom
.type
==GLU_INVALID_ENUM
)
255 call_user_error(nobj
,GLU_NURBS_ERROR8
);
256 nobj
->nurbs_type
=GLU_NURBS_NONE
;
259 glPushAttrib( (GLbitfield
) (GL_EVAL_BIT
| GL_ENABLE_BIT
) );
260 glDisable(GL_MAP1_VERTEX_3
);
261 glDisable(GL_MAP1_VERTEX_4
);
262 glDisable(GL_MAP1_INDEX
);
263 glDisable(GL_MAP1_COLOR_4
);
264 glDisable(GL_MAP1_NORMAL
);
265 glDisable(GL_MAP1_TEXTURE_COORD_1
);
266 glDisable(GL_MAP1_TEXTURE_COORD_2
);
267 glDisable(GL_MAP1_TEXTURE_COORD_3
);
268 glDisable(GL_MAP1_TEXTURE_COORD_4
);
269 glDisable(GL_MAP2_VERTEX_3
);
270 glDisable(GL_MAP2_VERTEX_4
);
271 glDisable(GL_MAP2_INDEX
);
272 glDisable(GL_MAP2_COLOR_4
);
273 glDisable(GL_MAP2_NORMAL
);
274 glDisable(GL_MAP2_TEXTURE_COORD_1
);
275 glDisable(GL_MAP2_TEXTURE_COORD_2
);
276 glDisable(GL_MAP2_TEXTURE_COORD_3
);
277 glDisable(GL_MAP2_TEXTURE_COORD_4
);
278 do_nurbs_curve(nobj
);
280 nobj
->nurbs_type
=GLU_NURBS_NONE
;
284 void GLAPIENTRY
gluNurbsCurve( GLUnurbsObj
*nobj
, GLint nknots
, GLfloat
*knot
,
285 GLint stride
, GLfloat
*ctlarray
, GLint order
, GLenum type
)
287 if(nobj
->nurbs_type
==GLU_NURBS_TRIM
)
290 /* TODO: NOT IMPLEMENTED YET */
294 if(type
!=GLU_MAP1_TRIM_2
&& type
!=GLU_MAP1_TRIM_3
)
296 call_user_error(nobj
,GLU_NURBS_ERROR14
);
299 for(ptr1
=nobj
->trim
;ptr1
->next
;ptr1
=ptr1
->next
);
302 for(ptr2
=ptr1
->trim_loop
;ptr2
->next
;ptr2
=ptr2
->next
);
303 if((ptr2
->next
=(trim_list
*)malloc(sizeof(trim_list
)))==NULL
)
305 call_user_error(nobj
,GLU_OUT_OF_MEMORY
);
312 if((ptr2
=(trim_list
*)malloc(sizeof(trim_list
)))==NULL
)
314 call_user_error(nobj
,GLU_OUT_OF_MEMORY
);
317 ptr1
->trim_loop
=ptr2
;
319 ptr2
->trim_type
=GLU_TRIM_NURBS
;
320 ptr2
->curve
.nurbs_curve
.knot_count
=nknots
;
321 ptr2
->curve
.nurbs_curve
.knot
=knot
;
322 ptr2
->curve
.nurbs_curve
.stride
=stride
;
323 ptr2
->curve
.nurbs_curve
.ctrlarray
=ctlarray
;
324 ptr2
->curve
.nurbs_curve
.order
=order
;
325 ptr2
->curve
.nurbs_curve
.dim
= (type
==GLU_MAP1_TRIM_2
? 2 : 3 );
326 ptr2
->curve
.nurbs_curve
.type
=type
;
332 if(type
==GLU_MAP1_TRIM_2
|| type
==GLU_MAP1_TRIM_3
)
334 call_user_error(nobj
,GLU_NURBS_ERROR22
);
337 if(nobj
->nurbs_type
!=GLU_NURBS_CURVE
)
339 call_user_error(nobj
,GLU_NURBS_ERROR10
);
344 case GL_MAP1_VERTEX_3
:
345 case GL_MAP1_VERTEX_4
:
346 if(nobj
->curve
.geom
.type
!=GLU_INVALID_ENUM
)
348 call_user_error(nobj
,GLU_NURBS_ERROR8
);
351 nobj
->curve
.geom
.type
=type
;
352 nobj
->curve
.geom
.knot_count
=nknots
;
353 nobj
->curve
.geom
.knot
=knot
;
354 nobj
->curve
.geom
.stride
=stride
;
355 nobj
->curve
.geom
.ctrlarray
=ctlarray
;
356 nobj
->curve
.geom
.order
=order
;
359 case GL_MAP1_COLOR_4
:
360 nobj
->curve
.color
.type
=type
;
361 nobj
->curve
.color
.knot_count
=nknots
;
362 nobj
->curve
.color
.knot
=knot
;
363 nobj
->curve
.color
.stride
=stride
;
364 nobj
->curve
.color
.ctrlarray
=ctlarray
;
365 nobj
->curve
.color
.order
=order
;
368 nobj
->curve
.normal
.type
=type
;
369 nobj
->curve
.normal
.knot_count
=nknots
;
370 nobj
->curve
.normal
.knot
=knot
;
371 nobj
->curve
.normal
.stride
=stride
;
372 nobj
->curve
.normal
.ctrlarray
=ctlarray
;
373 nobj
->curve
.normal
.order
=order
;
375 case GL_MAP1_TEXTURE_COORD_1
:
376 case GL_MAP1_TEXTURE_COORD_2
:
377 case GL_MAP1_TEXTURE_COORD_3
:
378 case GL_MAP1_TEXTURE_COORD_4
:
379 nobj
->curve
.texture
.type
=type
;
380 nobj
->curve
.texture
.knot_count
=nknots
;
381 nobj
->curve
.texture
.knot
=knot
;
382 nobj
->curve
.texture
.stride
=stride
;
383 nobj
->curve
.texture
.ctrlarray
=ctlarray
;
384 nobj
->curve
.texture
.order
=order
;
387 call_user_error(nobj
,GLU_INVALID_ENUM
);
393 void GLAPIENTRY
gluBeginSurface( GLUnurbsObj
*nobj
)
395 switch(nobj
->nurbs_type
)
398 nobj
->nurbs_type
=GLU_NURBS_SURFACE
;
399 nobj
->surface
.geom
.type
=GLU_INVALID_ENUM
;
400 nobj
->surface
.color
.type
=GLU_INVALID_ENUM
;
401 nobj
->surface
.texture
.type
=GLU_INVALID_ENUM
;
402 nobj
->surface
.normal
.type
=GLU_INVALID_ENUM
;
405 call_user_error(nobj
,GLU_NURBS_ERROR16
);
407 case GLU_NURBS_SURFACE
:
408 case GLU_NURBS_NO_TRIM
:
409 case GLU_NURBS_TRIM_DONE
:
410 call_user_error(nobj
,GLU_NURBS_ERROR27
);
412 case GLU_NURBS_CURVE
:
413 call_user_error(nobj
,GLU_NURBS_ERROR6
);
419 void GLAPIENTRY
gluEndSurface( GLUnurbsObj
* nobj
)
421 switch(nobj
->nurbs_type
)
424 call_user_error(nobj
,GLU_NURBS_ERROR13
);
427 call_user_error(nobj
,GLU_NURBS_ERROR12
);
429 case GLU_NURBS_TRIM_DONE
:
430 /* if(nobj->trim->trim_loop==NULL)
432 call_user_error(nobj,GLU_NURBS_ERROR18);
435 /* no break - fallthrough */
436 case GLU_NURBS_NO_TRIM
:
437 glPushAttrib( (GLbitfield
)
438 (GL_EVAL_BIT
| GL_ENABLE_BIT
| GL_POLYGON_BIT
) );
439 glDisable(GL_MAP2_VERTEX_3
);
440 glDisable(GL_MAP2_VERTEX_4
);
441 glDisable(GL_MAP2_INDEX
);
442 glDisable(GL_MAP2_COLOR_4
);
443 glDisable(GL_MAP2_NORMAL
);
444 glDisable(GL_MAP2_TEXTURE_COORD_1
);
445 glDisable(GL_MAP2_TEXTURE_COORD_2
);
446 glDisable(GL_MAP2_TEXTURE_COORD_3
);
447 glDisable(GL_MAP2_TEXTURE_COORD_4
);
448 /* glDisable(GL_MAP1_VERTEX_3);
449 glDisable(GL_MAP1_VERTEX_4);
450 glDisable(GL_MAP1_INDEX);
451 glDisable(GL_MAP1_COLOR_4);
452 glDisable(GL_MAP1_NORMAL);
453 glDisable(GL_MAP1_TEXTURE_COORD_1);
454 glDisable(GL_MAP1_TEXTURE_COORD_2);
455 glDisable(GL_MAP1_TEXTURE_COORD_3);
456 glDisable(GL_MAP1_TEXTURE_COORD_4);*/
457 do_nurbs_surface(nobj
);
461 call_user_error(nobj
,GLU_NURBS_ERROR8
);
463 nobj
->nurbs_type
=GLU_NURBS_NONE
;
467 void GLAPIENTRY
gluNurbsSurface( GLUnurbsObj
*nobj
,
468 GLint sknot_count
, GLfloat
*sknot
,
469 GLint tknot_count
, GLfloat
*tknot
,
470 GLint s_stride
, GLint t_stride
,
472 GLint sorder
, GLint torder
,
475 if(nobj
->nurbs_type
==GLU_NURBS_NO_TRIM
|| nobj
->nurbs_type
==GLU_NURBS_TRIM
||
476 nobj
->nurbs_type
==GLU_NURBS_TRIM_DONE
)
478 if(type
==GL_MAP2_VERTEX_3
|| type
==GL_MAP2_VERTEX_4
)
480 call_user_error(nobj
,GLU_NURBS_ERROR8
);
485 if(nobj
->nurbs_type
!=GLU_NURBS_SURFACE
)
487 call_user_error(nobj
,GLU_NURBS_ERROR11
);
492 case GL_MAP2_VERTEX_3
:
493 case GL_MAP2_VERTEX_4
:
494 nobj
->surface
.geom
.sknot_count
=sknot_count
;
495 nobj
->surface
.geom
.sknot
=sknot
;
496 nobj
->surface
.geom
.tknot_count
=tknot_count
;
497 nobj
->surface
.geom
.tknot
=tknot
;
498 nobj
->surface
.geom
.s_stride
=s_stride
;
499 nobj
->surface
.geom
.t_stride
=t_stride
;
500 nobj
->surface
.geom
.ctrlarray
=ctrlarray
;
501 nobj
->surface
.geom
.sorder
=sorder
;
502 nobj
->surface
.geom
.torder
=torder
;
503 nobj
->surface
.geom
.type
=type
;
504 nobj
->nurbs_type
=GLU_NURBS_NO_TRIM
;
507 case GL_MAP2_COLOR_4
:
508 nobj
->surface
.color
.sknot_count
=sknot_count
;
509 nobj
->surface
.color
.sknot
=sknot
;
510 nobj
->surface
.color
.tknot_count
=tknot_count
;
511 nobj
->surface
.color
.tknot
=tknot
;
512 nobj
->surface
.color
.s_stride
=s_stride
;
513 nobj
->surface
.color
.t_stride
=t_stride
;
514 nobj
->surface
.color
.ctrlarray
=ctrlarray
;
515 nobj
->surface
.color
.sorder
=sorder
;
516 nobj
->surface
.color
.torder
=torder
;
517 nobj
->surface
.color
.type
=type
;
520 nobj
->surface
.normal
.sknot_count
=sknot_count
;
521 nobj
->surface
.normal
.sknot
=sknot
;
522 nobj
->surface
.normal
.tknot_count
=tknot_count
;
523 nobj
->surface
.normal
.tknot
=tknot
;
524 nobj
->surface
.normal
.s_stride
=s_stride
;
525 nobj
->surface
.normal
.t_stride
=t_stride
;
526 nobj
->surface
.normal
.ctrlarray
=ctrlarray
;
527 nobj
->surface
.normal
.sorder
=sorder
;
528 nobj
->surface
.normal
.torder
=torder
;
529 nobj
->surface
.normal
.type
=type
;
531 case GL_MAP2_TEXTURE_COORD_1
:
532 case GL_MAP2_TEXTURE_COORD_2
:
533 case GL_MAP2_TEXTURE_COORD_3
:
534 case GL_MAP2_TEXTURE_COORD_4
:
535 nobj
->surface
.texture
.sknot_count
=sknot_count
;
536 nobj
->surface
.texture
.sknot
=sknot
;
537 nobj
->surface
.texture
.tknot_count
=tknot_count
;
538 nobj
->surface
.texture
.tknot
=tknot
;
539 nobj
->surface
.texture
.s_stride
=s_stride
;
540 nobj
->surface
.texture
.t_stride
=t_stride
;
541 nobj
->surface
.texture
.ctrlarray
=ctrlarray
;
542 nobj
->surface
.texture
.sorder
=sorder
;
543 nobj
->surface
.texture
.torder
=torder
;
544 nobj
->surface
.texture
.type
=type
;
547 call_user_error(nobj
,GLU_INVALID_ENUM
);
553 gluNurbsCallback( GLUnurbsObj
*nobj
, GLenum which
, void (GLCALLBACKP fn
)())
555 nobj
->error_callback
= (void(GLCALLBACKPCAST
)(GLenum
))fn
;
558 call_user_error(nobj
,GLU_INVALID_ENUM
);
562 gluBeginTrim( GLUnurbsObj
*nobj
)
568 if(nobj
->nurbs_type
!=GLU_NURBS_TRIM_DONE
)
569 if(nobj
->nurbs_type
!=GLU_NURBS_NO_TRIM
)
571 call_user_error(nobj
,GLU_NURBS_ERROR15
);
574 nobj
->nurbs_type
=GLU_NURBS_TRIM
;
575 fprintf(stderr
,"NURBS - trimming not supported yet\n");
577 if((ptr
=(nurbs_trim
*)malloc(sizeof(nurbs_trim
)))==NULL
)
579 call_user_error(nobj
,GLU_OUT_OF_MEMORY
);
586 for(tmp_ptr
=nobj
->trim
;tmp_ptr
->next
;tmp_ptr
=tmp_ptr
->next
);
598 gluPwlCurve( GLUnurbsObj
*nobj
, GLint count
, GLfloat
*array
, GLint stride
,
605 if(nobj
->nurbs_type
==GLU_NURBS_CURVE
)
607 call_user_error(nobj
,GLU_NURBS_ERROR9
);
610 if(nobj
->nurbs_type
==GLU_NURBS_NONE
)
612 call_user_error(nobj
,GLU_NURBS_ERROR19
);
615 if(type
!=GLU_MAP1_TRIM_2
&& type
!=GLU_MAP1_TRIM_3
)
617 call_user_error(nobj
,GLU_NURBS_ERROR14
);
621 for(ptr1
=nobj
->trim
;ptr1
->next
;ptr1
=ptr1
->next
);
624 for(ptr2
=ptr1
->trim_loop
;ptr2
->next
;ptr2
=ptr2
->next
);
625 if((ptr2
->next
=(trim_list
*)malloc(sizeof(trim_list
)))==NULL
)
627 call_user_error(nobj
,GLU_OUT_OF_MEMORY
);
634 if((ptr2
=(trim_list
*)malloc(sizeof(trim_list
)))==NULL
)
636 call_user_error(nobj
,GLU_OUT_OF_MEMORY
);
639 ptr1
->trim_loop
=ptr2
;
641 ptr2
->trim_type
=GLU_TRIM_PWL
;
642 ptr2
->curve
.pwl_curve
.pt_count
=count
;
643 ptr2
->curve
.pwl_curve
.ctrlarray
=array
;
644 ptr2
->curve
.pwl_curve
.stride
=stride
;
645 ptr2
->curve
.pwl_curve
.dim
= (type
==GLU_MAP1_TRIM_2
? 2 : 3 );
646 ptr2
->curve
.pwl_curve
.type
=type
;
652 gluEndTrim( GLUnurbsObj
*nobj
)
654 if(nobj
->nurbs_type
!=GLU_NURBS_TRIM
)
656 call_user_error(nobj
,GLU_NURBS_ERROR17
);
659 nobj
->nurbs_type
=GLU_NURBS_TRIM_DONE
;