Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / glu / mesa / nurbs.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 3.3
5 * Copyright (C) 1995-2000 Brian Paul
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23 /*
24 * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
25 * See README2 for more info.
26 */
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
54 gluNewNurbsRenderer(void)
55 {
56 GLUnurbsObj *n;
57 GLfloat tmp_viewport[4];
58 GLint i, j;
59
60 n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj));
61 if (n) {
62 /* init */
63 n->culling = GL_FALSE;
64 n->nurbs_type = GLU_NURBS_NONE;
65 n->error = GLU_NO_ERROR;
66 n->error_callback = NULL;
67 n->auto_load_matrix = GL_TRUE;
68 n->sampling_tolerance = 50.0;
69 n->parametric_tolerance = 0.5;
70 n->u_step = n->v_step = 100;
71 n->sampling_method = GLU_PATH_LENGTH;
72 n->display_mode = GLU_FILL;
73 /* in case the user doesn't supply the sampling matrices */
74 /* set projection and modelview to identity */
75 for (i = 0; i < 4; i++)
76 for (j = 0; j < 4; j++)
77 if (i == j) {
78 n->sampling_matrices.model[i * 4 + j] = 1.0;
79 n->sampling_matrices.proj[i * 4 + j] = 1.0;
80 }
81 else {
82 n->sampling_matrices.model[i * 4 + j] = 0.0;
83 n->sampling_matrices.proj[i * 4 + j] = 0.0;
84 }
85 /* and set the viewport sampling matrix to current ciewport */
86 glGetFloatv(GL_VIEWPORT, tmp_viewport);
87 for (i = 0; i < 4; i++)
88 n->sampling_matrices.viewport[i] = tmp_viewport[i];
89 n->trim = NULL;
90 }
91 return n;
92 }
93
94
95
96 void GLAPIENTRY
97 gluDeleteNurbsRenderer(GLUnurbsObj * nobj)
98 {
99 if (nobj) {
100 free(nobj);
101 }
102 }
103
104
105
106 void GLAPIENTRY
107 gluLoadSamplingMatrices(GLUnurbsObj * nobj,
108 const GLfloat modelMatrix[16],
109 const GLfloat projMatrix[16], const GLint viewport[4])
110 {
111 GLint i;
112
113 for (i = 0; i < 16; i++) {
114 nobj->sampling_matrices.model[i] = modelMatrix[i];
115 nobj->sampling_matrices.proj[i] = projMatrix[i];
116 }
117 for (i = 0; i < 4; i++)
118 nobj->sampling_matrices.viewport[i] = viewport[i];
119 }
120
121
122 void GLAPIENTRY
123 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 call_user_error(nobj, GLU_INVALID_VALUE);
131 return;
132 }
133 nobj->sampling_tolerance = value;
134 break;
135 case GLU_PARAMETRIC_TOLERANCE:
136 if (value <= 0.0) {
137 call_user_error(nobj, GLU_INVALID_VALUE);
138 return;
139 }
140 nobj->parametric_tolerance = value;
141 break;
142 case GLU_U_STEP:
143 if (value <= 0.0) {
144 call_user_error(nobj, GLU_INVALID_VALUE);
145 return;
146 }
147 nobj->u_step = (GLint) value;
148 break;
149 case GLU_V_STEP:
150 if (value <= 0.0) {
151 call_user_error(nobj, GLU_INVALID_VALUE);
152 return;
153 }
154 nobj->v_step = (GLint) value;
155 break;
156 case GLU_SAMPLING_METHOD:
157 val = (GLenum) value;
158 if (val != GLU_PATH_LENGTH && val != GLU_PARAMETRIC_ERROR
159 && val != GLU_DOMAIN_DISTANCE) {
160 call_user_error(nobj, GLU_INVALID_ENUM);
161 return;
162 }
163 nobj->sampling_method = val;
164 break;
165 case GLU_DISPLAY_MODE:
166 val = (GLenum) value;
167 if (val != GLU_FILL && val != GLU_OUTLINE_POLYGON
168 && val != GLU_OUTLINE_PATCH) {
169 call_user_error(nobj, GLU_INVALID_ENUM);
170 return;
171 }
172 if (nobj->nurbs_type == GLU_NURBS_CURVE) {
173 call_user_error(nobj, GLU_NURBS_ERROR26);
174 return;
175 }
176 nobj->display_mode = val;
177 if (val == GLU_OUTLINE_PATCH)
178 fprintf(stderr,
179 "NURBS, for the moment, can display only in POLYGON mode\n");
180 break;
181 case GLU_CULLING:
182 val = (GLenum) value;
183 if (val != GL_TRUE && val != GL_FALSE) {
184 call_user_error(nobj, GLU_INVALID_ENUM);
185 return;
186 }
187 nobj->culling = (GLboolean) value;
188 break;
189 case GLU_AUTO_LOAD_MATRIX:
190 val = (GLenum) value;
191 if (val != GL_TRUE && val != GL_FALSE) {
192 call_user_error(nobj, GLU_INVALID_ENUM);
193 return;
194 }
195 nobj->auto_load_matrix = (GLboolean) value;
196 break;
197 default:
198 call_user_error(nobj, GLU_NURBS_ERROR26);
199 }
200 }
201
202
203 void GLAPIENTRY
204 gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
205 {
206 switch (property) {
207 case GLU_SAMPLING_TOLERANCE:
208 *value = nobj->sampling_tolerance;
209 break;
210 case GLU_DISPLAY_MODE:
211 *value = (GLfloat) (GLint) nobj->display_mode;
212 break;
213 case GLU_CULLING:
214 *value = nobj->culling ? 1.0 : 0.0;
215 break;
216 case GLU_AUTO_LOAD_MATRIX:
217 *value = nobj->auto_load_matrix ? 1.0 : 0.0;
218 break;
219 default:
220 call_user_error(nobj, GLU_INVALID_ENUM);
221 }
222 }
223
224
225
226 void GLAPIENTRY
227 gluBeginCurve(GLUnurbsObj * nobj)
228 {
229 if (nobj->nurbs_type == GLU_NURBS_CURVE) {
230 call_user_error(nobj, GLU_NURBS_ERROR6);
231 return;
232 }
233 nobj->nurbs_type = GLU_NURBS_CURVE;
234 nobj->curve.geom.type = GLU_INVALID_ENUM;
235 nobj->curve.color.type = GLU_INVALID_ENUM;
236 nobj->curve.texture.type = GLU_INVALID_ENUM;
237 nobj->curve.normal.type = GLU_INVALID_ENUM;
238 }
239
240
241 void GLAPIENTRY
242 gluEndCurve(GLUnurbsObj * nobj)
243 {
244 if (nobj->nurbs_type == GLU_NURBS_NONE) {
245 call_user_error(nobj, GLU_NURBS_ERROR7);
246 return;
247 }
248 if (nobj->curve.geom.type == GLU_INVALID_ENUM) {
249 call_user_error(nobj, GLU_NURBS_ERROR8);
250 nobj->nurbs_type = GLU_NURBS_NONE;
251 return;
252 }
253 glPushAttrib((GLbitfield) (GL_EVAL_BIT | GL_ENABLE_BIT));
254 glDisable(GL_MAP1_VERTEX_3);
255 glDisable(GL_MAP1_VERTEX_4);
256 glDisable(GL_MAP1_INDEX);
257 glDisable(GL_MAP1_COLOR_4);
258 glDisable(GL_MAP1_NORMAL);
259 glDisable(GL_MAP1_TEXTURE_COORD_1);
260 glDisable(GL_MAP1_TEXTURE_COORD_2);
261 glDisable(GL_MAP1_TEXTURE_COORD_3);
262 glDisable(GL_MAP1_TEXTURE_COORD_4);
263 glDisable(GL_MAP2_VERTEX_3);
264 glDisable(GL_MAP2_VERTEX_4);
265 glDisable(GL_MAP2_INDEX);
266 glDisable(GL_MAP2_COLOR_4);
267 glDisable(GL_MAP2_NORMAL);
268 glDisable(GL_MAP2_TEXTURE_COORD_1);
269 glDisable(GL_MAP2_TEXTURE_COORD_2);
270 glDisable(GL_MAP2_TEXTURE_COORD_3);
271 glDisable(GL_MAP2_TEXTURE_COORD_4);
272 do_nurbs_curve(nobj);
273 glPopAttrib();
274 nobj->nurbs_type = GLU_NURBS_NONE;
275 }
276
277
278 void GLAPIENTRY
279 gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
280 GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
281 {
282 if (nobj->nurbs_type == GLU_NURBS_TRIM) {
283 #if 0
284 /* TODO: NOT IMPLEMENTED YET */
285 nurbs_trim *ptr1;
286 trim_list *ptr2;
287
288 if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) {
289 call_user_error(nobj, GLU_NURBS_ERROR14);
290 return;
291 }
292 for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next);
293 if (ptr1->trim_loop) {
294 for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next);
295 if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
296 call_user_error(nobj, GLU_OUT_OF_MEMORY);
297 return;
298 }
299 ptr2 = ptr2->next;
300 }
301 else {
302 if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
303 call_user_error(nobj, GLU_OUT_OF_MEMORY);
304 return;
305 }
306 ptr1->trim_loop = ptr2;
307 }
308 ptr2->trim_type = GLU_TRIM_NURBS;
309 ptr2->curve.nurbs_curve.knot_count = nknots;
310 ptr2->curve.nurbs_curve.knot = knot;
311 ptr2->curve.nurbs_curve.stride = stride;
312 ptr2->curve.nurbs_curve.ctrlarray = ctlarray;
313 ptr2->curve.nurbs_curve.order = order;
314 ptr2->curve.nurbs_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
315 ptr2->curve.nurbs_curve.type = type;
316 ptr2->next = NULL;
317 #endif
318 }
319 else {
320 if (type == GLU_MAP1_TRIM_2 || type == GLU_MAP1_TRIM_3) {
321 call_user_error(nobj, GLU_NURBS_ERROR22);
322 return;
323 }
324 if (nobj->nurbs_type != GLU_NURBS_CURVE) {
325 call_user_error(nobj, GLU_NURBS_ERROR10);
326 return;
327 }
328 switch (type) {
329 case GL_MAP1_VERTEX_3:
330 case GL_MAP1_VERTEX_4:
331 if (nobj->curve.geom.type != GLU_INVALID_ENUM) {
332 call_user_error(nobj, GLU_NURBS_ERROR8);
333 return;
334 }
335 nobj->curve.geom.type = type;
336 nobj->curve.geom.knot_count = nknots;
337 nobj->curve.geom.knot = knot;
338 nobj->curve.geom.stride = stride;
339 nobj->curve.geom.ctrlarray = ctlarray;
340 nobj->curve.geom.order = order;
341 break;
342 case GL_MAP1_INDEX:
343 case GL_MAP1_COLOR_4:
344 nobj->curve.color.type = type;
345 nobj->curve.color.knot_count = nknots;
346 nobj->curve.color.knot = knot;
347 nobj->curve.color.stride = stride;
348 nobj->curve.color.ctrlarray = ctlarray;
349 nobj->curve.color.order = order;
350 break;
351 case GL_MAP1_NORMAL:
352 nobj->curve.normal.type = type;
353 nobj->curve.normal.knot_count = nknots;
354 nobj->curve.normal.knot = knot;
355 nobj->curve.normal.stride = stride;
356 nobj->curve.normal.ctrlarray = ctlarray;
357 nobj->curve.normal.order = order;
358 break;
359 case GL_MAP1_TEXTURE_COORD_1:
360 case GL_MAP1_TEXTURE_COORD_2:
361 case GL_MAP1_TEXTURE_COORD_3:
362 case GL_MAP1_TEXTURE_COORD_4:
363 nobj->curve.texture.type = type;
364 nobj->curve.texture.knot_count = nknots;
365 nobj->curve.texture.knot = knot;
366 nobj->curve.texture.stride = stride;
367 nobj->curve.texture.ctrlarray = ctlarray;
368 nobj->curve.texture.order = order;
369 break;
370 default:
371 call_user_error(nobj, GLU_INVALID_ENUM);
372 }
373 }
374 }
375
376
377 void GLAPIENTRY
378 gluBeginSurface(GLUnurbsObj * nobj)
379 {
380 switch (nobj->nurbs_type) {
381 case GLU_NURBS_NONE:
382 nobj->nurbs_type = GLU_NURBS_SURFACE;
383 nobj->surface.geom.type = GLU_INVALID_ENUM;
384 nobj->surface.color.type = GLU_INVALID_ENUM;
385 nobj->surface.texture.type = GLU_INVALID_ENUM;
386 nobj->surface.normal.type = GLU_INVALID_ENUM;
387 break;
388 case GLU_NURBS_TRIM:
389 call_user_error(nobj, GLU_NURBS_ERROR16);
390 break;
391 case GLU_NURBS_SURFACE:
392 case GLU_NURBS_NO_TRIM:
393 case GLU_NURBS_TRIM_DONE:
394 call_user_error(nobj, GLU_NURBS_ERROR27);
395 break;
396 case GLU_NURBS_CURVE:
397 call_user_error(nobj, GLU_NURBS_ERROR6);
398 break;
399 }
400 }
401
402
403 void GLAPIENTRY
404 gluEndSurface(GLUnurbsObj * nobj)
405 {
406 switch (nobj->nurbs_type) {
407 case GLU_NURBS_NONE:
408 call_user_error(nobj, GLU_NURBS_ERROR13);
409 break;
410 case GLU_NURBS_TRIM:
411 call_user_error(nobj, GLU_NURBS_ERROR12);
412 break;
413 case GLU_NURBS_TRIM_DONE:
414 /* if(nobj->trim->trim_loop==NULL)
415 {
416 call_user_error(nobj,GLU_NURBS_ERROR18);
417 return;
418 }*/
419 /* no break - fallthrough */
420 case GLU_NURBS_NO_TRIM:
421 glPushAttrib((GLbitfield)
422 (GL_EVAL_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT));
423 glDisable(GL_MAP2_VERTEX_3);
424 glDisable(GL_MAP2_VERTEX_4);
425 glDisable(GL_MAP2_INDEX);
426 glDisable(GL_MAP2_COLOR_4);
427 glDisable(GL_MAP2_NORMAL);
428 glDisable(GL_MAP2_TEXTURE_COORD_1);
429 glDisable(GL_MAP2_TEXTURE_COORD_2);
430 glDisable(GL_MAP2_TEXTURE_COORD_3);
431 glDisable(GL_MAP2_TEXTURE_COORD_4);
432 /* glDisable(GL_MAP1_VERTEX_3);
433 glDisable(GL_MAP1_VERTEX_4);
434 glDisable(GL_MAP1_INDEX);
435 glDisable(GL_MAP1_COLOR_4);
436 glDisable(GL_MAP1_NORMAL);
437 glDisable(GL_MAP1_TEXTURE_COORD_1);
438 glDisable(GL_MAP1_TEXTURE_COORD_2);
439 glDisable(GL_MAP1_TEXTURE_COORD_3);
440 glDisable(GL_MAP1_TEXTURE_COORD_4);*/
441 do_nurbs_surface(nobj);
442 glPopAttrib();
443 break;
444 default:
445 call_user_error(nobj, GLU_NURBS_ERROR8);
446 }
447 nobj->nurbs_type = GLU_NURBS_NONE;
448 }
449
450
451 void GLAPIENTRY
452 gluNurbsSurface(GLUnurbsObj * nobj,
453 GLint sknot_count, GLfloat * sknot,
454 GLint tknot_count, GLfloat * tknot,
455 GLint s_stride, GLint t_stride,
456 GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type)
457 {
458 if (nobj->nurbs_type == GLU_NURBS_NO_TRIM
459 || nobj->nurbs_type == GLU_NURBS_TRIM
460 || nobj->nurbs_type == GLU_NURBS_TRIM_DONE) {
461 if (type == GL_MAP2_VERTEX_3 || type == GL_MAP2_VERTEX_4) {
462 call_user_error(nobj, GLU_NURBS_ERROR8);
463 return;
464 }
465 }
466 else if (nobj->nurbs_type != GLU_NURBS_SURFACE) {
467 call_user_error(nobj, GLU_NURBS_ERROR11);
468 return;
469 }
470 switch (type) {
471 case GL_MAP2_VERTEX_3:
472 case GL_MAP2_VERTEX_4:
473 nobj->surface.geom.sknot_count = sknot_count;
474 nobj->surface.geom.sknot = sknot;
475 nobj->surface.geom.tknot_count = tknot_count;
476 nobj->surface.geom.tknot = tknot;
477 nobj->surface.geom.s_stride = s_stride;
478 nobj->surface.geom.t_stride = t_stride;
479 nobj->surface.geom.ctrlarray = ctrlarray;
480 nobj->surface.geom.sorder = sorder;
481 nobj->surface.geom.torder = torder;
482 nobj->surface.geom.type = type;
483 nobj->nurbs_type = GLU_NURBS_NO_TRIM;
484 break;
485 case GL_MAP2_INDEX:
486 case GL_MAP2_COLOR_4:
487 nobj->surface.color.sknot_count = sknot_count;
488 nobj->surface.color.sknot = sknot;
489 nobj->surface.color.tknot_count = tknot_count;
490 nobj->surface.color.tknot = tknot;
491 nobj->surface.color.s_stride = s_stride;
492 nobj->surface.color.t_stride = t_stride;
493 nobj->surface.color.ctrlarray = ctrlarray;
494 nobj->surface.color.sorder = sorder;
495 nobj->surface.color.torder = torder;
496 nobj->surface.color.type = type;
497 break;
498 case GL_MAP2_NORMAL:
499 nobj->surface.normal.sknot_count = sknot_count;
500 nobj->surface.normal.sknot = sknot;
501 nobj->surface.normal.tknot_count = tknot_count;
502 nobj->surface.normal.tknot = tknot;
503 nobj->surface.normal.s_stride = s_stride;
504 nobj->surface.normal.t_stride = t_stride;
505 nobj->surface.normal.ctrlarray = ctrlarray;
506 nobj->surface.normal.sorder = sorder;
507 nobj->surface.normal.torder = torder;
508 nobj->surface.normal.type = type;
509 break;
510 case GL_MAP2_TEXTURE_COORD_1:
511 case GL_MAP2_TEXTURE_COORD_2:
512 case GL_MAP2_TEXTURE_COORD_3:
513 case GL_MAP2_TEXTURE_COORD_4:
514 nobj->surface.texture.sknot_count = sknot_count;
515 nobj->surface.texture.sknot = sknot;
516 nobj->surface.texture.tknot_count = tknot_count;
517 nobj->surface.texture.tknot = tknot;
518 nobj->surface.texture.s_stride = s_stride;
519 nobj->surface.texture.t_stride = t_stride;
520 nobj->surface.texture.ctrlarray = ctrlarray;
521 nobj->surface.texture.sorder = sorder;
522 nobj->surface.texture.torder = torder;
523 nobj->surface.texture.type = type;
524 break;
525 default:
526 call_user_error(nobj, GLU_INVALID_ENUM);
527 }
528 }
529
530
531 void GLAPIENTRY
532 gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
533 {
534 nobj->error_callback = (void (GLCALLBACKPCAST) (GLenum)) fn;
535
536 if (which != GLU_ERROR)
537 call_user_error(nobj, GLU_INVALID_ENUM);
538 }
539
540 void GLAPIENTRY
541 gluBeginTrim(GLUnurbsObj * nobj)
542 {
543 #if 0
544 nurbs_trim *ptr;
545 #endif
546
547 if (nobj->nurbs_type != GLU_NURBS_TRIM_DONE)
548 if (nobj->nurbs_type != GLU_NURBS_NO_TRIM) {
549 call_user_error(nobj, GLU_NURBS_ERROR15);
550 return;
551 }
552 nobj->nurbs_type = GLU_NURBS_TRIM;
553 fprintf(stderr, "NURBS - trimming not supported yet\n");
554 #if 0
555 if ((ptr = (nurbs_trim *) malloc(sizeof(nurbs_trim))) == NULL) {
556 call_user_error(nobj, GLU_OUT_OF_MEMORY);
557 return;
558 }
559 if (nobj->trim) {
560 nurbs_trim *tmp_ptr;
561
562 for (tmp_ptr = nobj->trim; tmp_ptr->next; tmp_ptr = tmp_ptr->next);
563 tmp_ptr->next = ptr;
564 }
565 else
566 nobj->trim = ptr;
567 ptr->trim_loop = NULL;
568 ptr->segments = NULL;
569 ptr->next = NULL;
570 #endif
571 }
572
573 void GLAPIENTRY
574 gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
575 GLenum type)
576 {
577 #if 0
578 nurbs_trim *ptr1;
579 trim_list *ptr2;
580 #endif
581 if (nobj->nurbs_type == GLU_NURBS_CURVE) {
582 call_user_error(nobj, GLU_NURBS_ERROR9);
583 return;
584 }
585 if (nobj->nurbs_type == GLU_NURBS_NONE) {
586 call_user_error(nobj, GLU_NURBS_ERROR19);
587 return;
588 }
589 if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) {
590 call_user_error(nobj, GLU_NURBS_ERROR14);
591 return;
592 }
593 #if 0
594 for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next);
595 if (ptr1->trim_loop) {
596 for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next);
597 if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
598 call_user_error(nobj, GLU_OUT_OF_MEMORY);
599 return;
600 }
601 ptr2 = ptr2->next;
602 }
603 else {
604 if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
605 call_user_error(nobj, GLU_OUT_OF_MEMORY);
606 return;
607 }
608 ptr1->trim_loop = ptr2;
609 }
610 ptr2->trim_type = GLU_TRIM_PWL;
611 ptr2->curve.pwl_curve.pt_count = count;
612 ptr2->curve.pwl_curve.ctrlarray = array;
613 ptr2->curve.pwl_curve.stride = stride;
614 ptr2->curve.pwl_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
615 ptr2->curve.pwl_curve.type = type;
616 ptr2->next = NULL;
617 #endif
618 }
619
620 void GLAPIENTRY
621 gluEndTrim(GLUnurbsObj * nobj)
622 {
623 if (nobj->nurbs_type != GLU_NURBS_TRIM) {
624 call_user_error(nobj, GLU_NURBS_ERROR17);
625 return;
626 }
627 nobj->nurbs_type = GLU_NURBS_TRIM_DONE;
628 }