added GLCALLBACKPCAST for Cygnus (Sven Panne)
[mesa.git] / src / glu / mesa / nurbs.c
1 /* $Id: nurbs.c,v 1.3 2000/02/10 17:45:52 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 * Copyright (C) 1995-2000 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 * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
26 * See README2 for more info.
27 */
28
29 #ifdef PC_HEADER
30 #include "all.h"
31 #else
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include "gluP.h"
35 #include "nurbs.h"
36 #endif
37
38
39 void
40 call_user_error( GLUnurbsObj *nobj, GLenum error )
41 {
42 nobj->error=error;
43 if(nobj->error_callback != NULL) {
44 (*(nobj->error_callback))(error);
45 }
46 else {
47 printf("NURBS error %d %s\n", error, (char *) gluErrorString(error) );
48 }
49 }
50
51
52
53 GLUnurbsObj * GLAPIENTRY gluNewNurbsRenderer( void )
54 {
55 GLUnurbsObj *n;
56 GLfloat tmp_viewport[4];
57 GLint i,j;
58
59 n = (GLUnurbsObj *) malloc( sizeof(GLUnurbsObj) );
60 if (n) {
61 /* init */
62 n->culling=GL_FALSE;
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 */
74 for(i=0;i<4;i++)
75 for(j=0;j<4;j++)
76 if(i==j)
77 {
78 n->sampling_matrices.model[i*4+j]=1.0;
79 n->sampling_matrices.proj[i*4+j]=1.0;
80 }
81 else
82 {
83 n->sampling_matrices.model[i*4+j]=0.0;
84 n->sampling_matrices.proj[i*4+j]=0.0;
85 }
86 /* and set the viewport sampling matrix to current ciewport */
87 glGetFloatv(GL_VIEWPORT,tmp_viewport);
88 for(i=0;i<4;i++)
89 n->sampling_matrices.viewport[i]=tmp_viewport[i];
90 n->trim=NULL;
91 }
92 return n;
93 }
94
95
96
97 void GLAPIENTRY gluDeleteNurbsRenderer( GLUnurbsObj *nobj )
98 {
99 if (nobj) {
100 free( nobj );
101 }
102 }
103
104
105
106 void GLAPIENTRY gluLoadSamplingMatrices( GLUnurbsObj *nobj,
107 const GLfloat modelMatrix[16],
108 const GLfloat projMatrix[16],
109 const GLint viewport[4] )
110 {
111 GLint i;
112
113 for(i=0;i<16;i++)
114 {
115 nobj->sampling_matrices.model[i]=modelMatrix[i];
116 nobj->sampling_matrices.proj[i]=projMatrix[i];
117 }
118 for(i=0;i<4;i++)
119 nobj->sampling_matrices.viewport[i]=viewport[i];
120 }
121
122
123 void GLAPIENTRY gluNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat value )
124 {
125 GLenum val;
126
127 switch (property) {
128 case GLU_SAMPLING_TOLERANCE:
129 if(value <= 0.0)
130 {
131 call_user_error(nobj,GLU_INVALID_VALUE);
132 return;
133 }
134 nobj->sampling_tolerance=value;
135 break;
136 case GLU_PARAMETRIC_TOLERANCE:
137 if(value <= 0.0)
138 {
139 call_user_error(nobj,GLU_INVALID_VALUE);
140 return;
141 }
142 nobj->parametric_tolerance=value;
143 break;
144 case GLU_U_STEP:
145 if(value <= 0.0)
146 {
147 call_user_error(nobj,GLU_INVALID_VALUE);
148 return;
149 }
150 nobj->u_step=(GLint)value;
151 break;
152 case GLU_V_STEP:
153 if(value <= 0.0)
154 {
155 call_user_error(nobj,GLU_INVALID_VALUE);
156 return;
157 }
158 nobj->v_step=(GLint)value;
159 break;
160 case GLU_SAMPLING_METHOD:
161 val = (GLenum)value;
162 if(val!=GLU_PATH_LENGTH && val!=GLU_PARAMETRIC_ERROR && val!=GLU_DOMAIN_DISTANCE)
163 {
164 call_user_error(nobj,GLU_INVALID_ENUM);
165 return;
166 }
167 nobj->sampling_method=val;
168 break;
169 case GLU_DISPLAY_MODE:
170 val=(GLenum)value;
171 if(val!=GLU_FILL && val!=GLU_OUTLINE_POLYGON && val!=GLU_OUTLINE_PATCH)
172 {
173 call_user_error(nobj,GLU_INVALID_ENUM);
174 return;
175 }
176 if(nobj->nurbs_type==GLU_NURBS_CURVE)
177 {
178 call_user_error(nobj,GLU_NURBS_ERROR26);
179 return;
180 }
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");
184 break;
185 case GLU_CULLING:
186 val=(GLenum)value;
187 if(val!=GL_TRUE && val!=GL_FALSE)
188 {
189 call_user_error(nobj,GLU_INVALID_ENUM);
190 return;
191 }
192 nobj->culling = (GLboolean) value;
193 break;
194 case GLU_AUTO_LOAD_MATRIX:
195 val=(GLenum)value;
196 if(val!=GL_TRUE && val!=GL_FALSE)
197 {
198 call_user_error(nobj,GLU_INVALID_ENUM);
199 return;
200 }
201 nobj->auto_load_matrix = (GLboolean) value;
202 break;
203 default:
204 call_user_error(nobj,GLU_NURBS_ERROR26);
205 }
206 }
207
208
209 void GLAPIENTRY gluGetNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat *value )
210 {
211 switch (property) {
212 case GLU_SAMPLING_TOLERANCE:
213 *value = nobj->sampling_tolerance;
214 break;
215 case GLU_DISPLAY_MODE:
216 *value = (GLfloat) (GLint) nobj->display_mode;
217 break;
218 case GLU_CULLING:
219 *value = nobj->culling ? 1.0 : 0.0;
220 break;
221 case GLU_AUTO_LOAD_MATRIX:
222 *value = nobj->auto_load_matrix ? 1.0 : 0.0;
223 break;
224 default:
225 call_user_error(nobj,GLU_INVALID_ENUM);
226 }
227 }
228
229
230
231 void GLAPIENTRY gluBeginCurve( GLUnurbsObj *nobj )
232 {
233 if(nobj->nurbs_type==GLU_NURBS_CURVE)
234 {
235 call_user_error(nobj,GLU_NURBS_ERROR6);
236 return;
237 }
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;
243 }
244
245
246 void GLAPIENTRY gluEndCurve( GLUnurbsObj * nobj )
247 {
248 if(nobj->nurbs_type==GLU_NURBS_NONE)
249 {
250 call_user_error(nobj,GLU_NURBS_ERROR7);
251 return;
252 }
253 if(nobj->curve.geom.type==GLU_INVALID_ENUM)
254 {
255 call_user_error(nobj,GLU_NURBS_ERROR8);
256 nobj->nurbs_type=GLU_NURBS_NONE;
257 return;
258 }
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);
279 glPopAttrib();
280 nobj->nurbs_type=GLU_NURBS_NONE;
281 }
282
283
284 void GLAPIENTRY gluNurbsCurve( GLUnurbsObj *nobj, GLint nknots, GLfloat *knot,
285 GLint stride, GLfloat *ctlarray, GLint order, GLenum type )
286 {
287 if(nobj->nurbs_type==GLU_NURBS_TRIM)
288 {
289 #if 0
290 /* TODO: NOT IMPLEMENTED YET */
291 nurbs_trim *ptr1;
292 trim_list *ptr2;
293
294 if(type!=GLU_MAP1_TRIM_2 && type!=GLU_MAP1_TRIM_3)
295 {
296 call_user_error(nobj,GLU_NURBS_ERROR14);
297 return;
298 }
299 for(ptr1=nobj->trim;ptr1->next;ptr1=ptr1->next);
300 if(ptr1->trim_loop)
301 {
302 for(ptr2=ptr1->trim_loop;ptr2->next;ptr2=ptr2->next);
303 if((ptr2->next=(trim_list *)malloc(sizeof(trim_list)))==NULL)
304 {
305 call_user_error(nobj,GLU_OUT_OF_MEMORY);
306 return;
307 }
308 ptr2=ptr2->next;
309 }
310 else
311 {
312 if((ptr2=(trim_list *)malloc(sizeof(trim_list)))==NULL)
313 {
314 call_user_error(nobj,GLU_OUT_OF_MEMORY);
315 return;
316 }
317 ptr1->trim_loop=ptr2;
318 }
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;
327 ptr2->next=NULL;
328 #endif
329 }
330 else
331 {
332 if(type==GLU_MAP1_TRIM_2 || type==GLU_MAP1_TRIM_3)
333 {
334 call_user_error(nobj,GLU_NURBS_ERROR22);
335 return;
336 }
337 if(nobj->nurbs_type!=GLU_NURBS_CURVE)
338 {
339 call_user_error(nobj,GLU_NURBS_ERROR10);
340 return;
341 }
342 switch(type)
343 {
344 case GL_MAP1_VERTEX_3:
345 case GL_MAP1_VERTEX_4:
346 if(nobj->curve.geom.type!=GLU_INVALID_ENUM)
347 {
348 call_user_error(nobj,GLU_NURBS_ERROR8);
349 return;
350 }
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;
357 break;
358 case GL_MAP1_INDEX:
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;
366 break;
367 case GL_MAP1_NORMAL:
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;
374 break;
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;
385 break;
386 default:
387 call_user_error(nobj,GLU_INVALID_ENUM);
388 }
389 }
390 }
391
392
393 void GLAPIENTRY gluBeginSurface( GLUnurbsObj *nobj )
394 {
395 switch(nobj->nurbs_type)
396 {
397 case GLU_NURBS_NONE:
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;
403 break;
404 case GLU_NURBS_TRIM:
405 call_user_error(nobj,GLU_NURBS_ERROR16);
406 break;
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);
411 break;
412 case GLU_NURBS_CURVE:
413 call_user_error(nobj,GLU_NURBS_ERROR6);
414 break;
415 }
416 }
417
418
419 void GLAPIENTRY gluEndSurface( GLUnurbsObj * nobj )
420 {
421 switch(nobj->nurbs_type)
422 {
423 case GLU_NURBS_NONE:
424 call_user_error(nobj,GLU_NURBS_ERROR13);
425 break;
426 case GLU_NURBS_TRIM:
427 call_user_error(nobj,GLU_NURBS_ERROR12);
428 break;
429 case GLU_NURBS_TRIM_DONE:
430 /* if(nobj->trim->trim_loop==NULL)
431 {
432 call_user_error(nobj,GLU_NURBS_ERROR18);
433 return;
434 }*/
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);
458 glPopAttrib();
459 break;
460 default:
461 call_user_error(nobj,GLU_NURBS_ERROR8);
462 }
463 nobj->nurbs_type=GLU_NURBS_NONE;
464 }
465
466
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,
471 GLfloat *ctrlarray,
472 GLint sorder, GLint torder,
473 GLenum type )
474 {
475 if(nobj->nurbs_type==GLU_NURBS_NO_TRIM || nobj->nurbs_type==GLU_NURBS_TRIM ||
476 nobj->nurbs_type==GLU_NURBS_TRIM_DONE)
477 {
478 if(type==GL_MAP2_VERTEX_3 || type==GL_MAP2_VERTEX_4)
479 {
480 call_user_error(nobj,GLU_NURBS_ERROR8);
481 return;
482 }
483 }
484 else
485 if(nobj->nurbs_type!=GLU_NURBS_SURFACE)
486 {
487 call_user_error(nobj,GLU_NURBS_ERROR11);
488 return;
489 }
490 switch(type)
491 {
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;
505 break;
506 case GL_MAP2_INDEX:
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;
518 break;
519 case GL_MAP2_NORMAL:
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;
530 break;
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;
545 break;
546 default:
547 call_user_error(nobj,GLU_INVALID_ENUM);
548 }
549 }
550
551
552 void GLAPIENTRY
553 gluNurbsCallback( GLUnurbsObj *nobj, GLenum which, void (GLCALLBACKP fn)())
554 {
555 nobj->error_callback = (void(GLCALLBACKPCAST)(GLenum))fn;
556
557 if(which!=GLU_ERROR)
558 call_user_error(nobj,GLU_INVALID_ENUM);
559 }
560
561 void GLAPIENTRY
562 gluBeginTrim( GLUnurbsObj *nobj )
563 {
564 #if 0
565 nurbs_trim *ptr;
566 #endif
567
568 if(nobj->nurbs_type!=GLU_NURBS_TRIM_DONE)
569 if(nobj->nurbs_type!=GLU_NURBS_NO_TRIM)
570 {
571 call_user_error(nobj,GLU_NURBS_ERROR15);
572 return;
573 }
574 nobj->nurbs_type=GLU_NURBS_TRIM;
575 fprintf(stderr,"NURBS - trimming not supported yet\n");
576 #if 0
577 if((ptr=(nurbs_trim *)malloc(sizeof(nurbs_trim)))==NULL)
578 {
579 call_user_error(nobj,GLU_OUT_OF_MEMORY);
580 return;
581 }
582 if(nobj->trim)
583 {
584 nurbs_trim *tmp_ptr;
585
586 for(tmp_ptr=nobj->trim;tmp_ptr->next;tmp_ptr=tmp_ptr->next);
587 tmp_ptr->next=ptr;
588 }
589 else
590 nobj->trim=ptr;
591 ptr->trim_loop=NULL;
592 ptr->segments=NULL;
593 ptr->next=NULL;
594 #endif
595 }
596
597 void GLAPIENTRY
598 gluPwlCurve( GLUnurbsObj *nobj, GLint count, GLfloat *array, GLint stride,
599 GLenum type)
600 {
601 #if 0
602 nurbs_trim *ptr1;
603 trim_list *ptr2;
604 #endif
605 if(nobj->nurbs_type==GLU_NURBS_CURVE)
606 {
607 call_user_error(nobj,GLU_NURBS_ERROR9);
608 return;
609 }
610 if(nobj->nurbs_type==GLU_NURBS_NONE)
611 {
612 call_user_error(nobj,GLU_NURBS_ERROR19);
613 return;
614 }
615 if(type!=GLU_MAP1_TRIM_2 && type!=GLU_MAP1_TRIM_3)
616 {
617 call_user_error(nobj,GLU_NURBS_ERROR14);
618 return;
619 }
620 #if 0
621 for(ptr1=nobj->trim;ptr1->next;ptr1=ptr1->next);
622 if(ptr1->trim_loop)
623 {
624 for(ptr2=ptr1->trim_loop;ptr2->next;ptr2=ptr2->next);
625 if((ptr2->next=(trim_list *)malloc(sizeof(trim_list)))==NULL)
626 {
627 call_user_error(nobj,GLU_OUT_OF_MEMORY);
628 return;
629 }
630 ptr2=ptr2->next;
631 }
632 else
633 {
634 if((ptr2=(trim_list *)malloc(sizeof(trim_list)))==NULL)
635 {
636 call_user_error(nobj,GLU_OUT_OF_MEMORY);
637 return;
638 }
639 ptr1->trim_loop=ptr2;
640 }
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;
647 ptr2->next=NULL;
648 #endif
649 }
650
651 void GLAPIENTRY
652 gluEndTrim( GLUnurbsObj *nobj )
653 {
654 if(nobj->nurbs_type!=GLU_NURBS_TRIM)
655 {
656 call_user_error(nobj,GLU_NURBS_ERROR17);
657 return;
658 }
659 nobj->nurbs_type=GLU_NURBS_TRIM_DONE;
660 }
661