gallium/draw: initial code to properly support llvm in the draw module
[mesa.git] / src / glu / mesa / nurbssrf.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 <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include "gluP.h"
36 #include "nurbs.h"
37 #endif
38
39
40 static int
41 get_surface_dim(GLenum type)
42 {
43 switch (type) {
44 case GL_MAP2_VERTEX_3:
45 return 3;
46 case GL_MAP2_VERTEX_4:
47 return 4;
48 case GL_MAP2_INDEX:
49 return 1;
50 case GL_MAP2_COLOR_4:
51 return 4;
52 case GL_MAP2_NORMAL:
53 return 3;
54 case GL_MAP2_TEXTURE_COORD_1:
55 return 1;
56 case GL_MAP2_TEXTURE_COORD_2:
57 return 2;
58 case GL_MAP2_TEXTURE_COORD_3:
59 return 3;
60 case GL_MAP2_TEXTURE_COORD_4:
61 return 4;
62 default:
63 abort(); /* TODO: is this OK? */
64 }
65 return 0; /*never get here */
66 }
67
68 static GLenum
69 test_nurbs_surface(GLUnurbsObj * nobj, surface_attribs * attrib)
70 {
71 GLenum err;
72 GLint tmp_int;
73
74 if (attrib->sorder < 0 || attrib->torder < 0) {
75 call_user_error(nobj, GLU_INVALID_VALUE);
76 return GLU_ERROR;
77 }
78 glGetIntegerv(GL_MAX_EVAL_ORDER, &tmp_int);
79 if (attrib->sorder > tmp_int || attrib->sorder < 2) {
80 call_user_error(nobj, GLU_NURBS_ERROR1);
81 return GLU_ERROR;
82 }
83 if (attrib->torder > tmp_int || attrib->torder < 2) {
84 call_user_error(nobj, GLU_NURBS_ERROR1);
85 return GLU_ERROR;
86 }
87 if (attrib->sknot_count < attrib->sorder + 2) {
88 call_user_error(nobj, GLU_NURBS_ERROR2);
89 return GLU_ERROR;
90 }
91 if (attrib->tknot_count < attrib->torder + 2) {
92 call_user_error(nobj, GLU_NURBS_ERROR2);
93 return GLU_ERROR;
94 }
95 if (attrib->s_stride < 0 || attrib->t_stride < 0) {
96 call_user_error(nobj, GLU_NURBS_ERROR34);
97 return GLU_ERROR;
98 }
99 if (attrib->sknot == NULL || attrib->tknot == NULL
100 || attrib->ctrlarray == NULL) {
101 call_user_error(nobj, GLU_NURBS_ERROR36);
102 return GLU_ERROR;
103 }
104 if ((err = test_knot(attrib->tknot_count, attrib->tknot, attrib->torder))
105 != GLU_NO_ERROR) {
106 call_user_error(nobj, err);
107 return GLU_ERROR;
108 }
109 if ((err = test_knot(attrib->sknot_count, attrib->sknot, attrib->sorder))
110 != GLU_NO_ERROR) {
111 call_user_error(nobj, err);
112 return GLU_ERROR;
113 }
114 return GLU_NO_ERROR;
115 }
116
117 static GLenum
118 test_nurbs_surfaces(GLUnurbsObj * nobj)
119 {
120 /* test the geometric data */
121 if (test_nurbs_surface(nobj, &(nobj->surface.geom)) != GLU_NO_ERROR)
122 return GLU_ERROR;
123 /* now test the attributive data */
124 /* color */
125 if (nobj->surface.color.type != GLU_INVALID_ENUM)
126 if (test_nurbs_surface(nobj, &(nobj->surface.color)) != GLU_NO_ERROR)
127 return GLU_ERROR;
128 /* normal */
129 if (nobj->surface.normal.type != GLU_INVALID_ENUM)
130 if (test_nurbs_surface(nobj, &(nobj->surface.normal)) != GLU_NO_ERROR)
131 return GLU_ERROR;
132 /* texture */
133 if (nobj->surface.texture.type != GLU_INVALID_ENUM)
134 if (test_nurbs_surface(nobj, &(nobj->surface.texture)) != GLU_NO_ERROR)
135 return GLU_ERROR;
136 return GLU_NO_ERROR;
137 }
138
139 static GLenum
140 convert_surf(knot_str_type * s_knot, knot_str_type * t_knot,
141 surface_attribs * attrib, GLfloat ** new_ctrl,
142 GLint * s_n_ctrl, GLint * t_n_ctrl)
143 {
144 GLfloat **tmp_ctrl;
145 GLfloat *ctrl_offset;
146 GLint tmp_n_control;
147 GLint i, j, t_cnt, s_cnt;
148 GLint tmp_stride;
149 GLint dim;
150 GLenum err;
151
152 /* valid range is empty? */
153 if ((s_knot->unified_knot != NULL && s_knot->unified_nknots == 0) ||
154 (t_knot->unified_knot != NULL && t_knot->unified_nknots == 0)) {
155 if (s_knot->unified_knot) {
156 free(s_knot->unified_knot);
157 s_knot->unified_knot = NULL;
158 }
159 if (t_knot->unified_knot) {
160 free(t_knot->unified_knot);
161 t_knot->unified_knot = NULL;
162 }
163 *s_n_ctrl = 0;
164 *t_n_ctrl = 0;
165 return GLU_NO_ERROR;
166 }
167 t_cnt = attrib->tknot_count - attrib->torder;
168 s_cnt = attrib->sknot_count - attrib->sorder;
169 if ((tmp_ctrl = (GLfloat **) malloc(sizeof(GLfloat *) * t_cnt)) == NULL)
170 return GLU_OUT_OF_MEMORY;
171 if ((err = explode_knot(s_knot)) != GLU_NO_ERROR) {
172 free(tmp_ctrl);
173 if (s_knot->unified_knot) {
174 free(s_knot->unified_knot);
175 s_knot->unified_knot = NULL;
176 }
177 return err;
178 }
179 if (s_knot->unified_knot) {
180 free(s_knot->unified_knot);
181 s_knot->unified_knot = NULL;
182 }
183 if ((err = calc_alphas(s_knot)) != GLU_NO_ERROR) {
184 free(tmp_ctrl);
185 free(s_knot->new_knot);
186 return err;
187 }
188 free(s_knot->new_knot);
189 ctrl_offset = attrib->ctrlarray;
190 dim = attrib->dim;
191 for (i = 0; i < t_cnt; i++) {
192 if ((err = calc_new_ctrl_pts(ctrl_offset, attrib->s_stride, s_knot,
193 dim, &(tmp_ctrl[i]),
194 &tmp_n_control)) != GLU_NO_ERROR) {
195 for (--i; i <= 0; i--)
196 free(tmp_ctrl[i]);
197 free(tmp_ctrl);
198 free(s_knot->alpha);
199 return err;
200 }
201 ctrl_offset += attrib->t_stride;
202 }
203 free(s_knot->alpha);
204 tmp_stride = dim * tmp_n_control;
205 if ((*new_ctrl = (GLfloat *) malloc(sizeof(GLfloat) * tmp_stride * t_cnt))
206 == NULL) {
207 for (i = 0; i < t_cnt; i++)
208 free(tmp_ctrl[i]);
209 free(tmp_ctrl);
210 return GLU_OUT_OF_MEMORY;
211 }
212 for (i = 0; i < tmp_n_control; i++)
213 for (j = 0; j < t_cnt; j++)
214 MEMCPY(*new_ctrl + j * dim + i * dim * t_cnt, tmp_ctrl[j] + dim * i,
215 sizeof(GLfloat) * dim);
216 for (i = 0; i < t_cnt; i++)
217 free(tmp_ctrl[i]);
218 free(tmp_ctrl);
219 *s_n_ctrl = tmp_n_control;
220
221 if ((tmp_ctrl = (GLfloat **) malloc(sizeof(GLfloat *) * (*s_n_ctrl))) ==
222 NULL) {
223 return GLU_OUT_OF_MEMORY;
224 }
225 if ((err = explode_knot(t_knot)) != GLU_NO_ERROR) {
226 free(tmp_ctrl);
227 if (t_knot->unified_knot) {
228 free(t_knot->unified_knot);
229 t_knot->unified_knot = NULL;
230 }
231 return err;
232 }
233 if (t_knot->unified_knot) {
234 free(t_knot->unified_knot);
235 t_knot->unified_knot = NULL;
236 }
237 if ((err = calc_alphas(t_knot)) != GLU_NO_ERROR) {
238 free(tmp_ctrl);
239 free(t_knot->new_knot);
240 return err;
241 }
242 free(t_knot->new_knot);
243 ctrl_offset = *new_ctrl;
244 for (i = 0; i < (*s_n_ctrl); i++) {
245 if ((err = calc_new_ctrl_pts(ctrl_offset, dim, t_knot,
246 dim, &(tmp_ctrl[i]),
247 &tmp_n_control)) != GLU_NO_ERROR) {
248 for (--i; i <= 0; i--)
249 free(tmp_ctrl[i]);
250 free(tmp_ctrl);
251 free(t_knot->alpha);
252 return err;
253 }
254 ctrl_offset += dim * t_cnt;
255 }
256 free(t_knot->alpha);
257 free(*new_ctrl);
258 tmp_stride = dim * tmp_n_control;
259 if (
260 (*new_ctrl =
261 (GLfloat *) malloc(sizeof(GLfloat) * tmp_stride * (*s_n_ctrl))) ==
262 NULL) {
263 for (i = 0; i < (*s_n_ctrl); i++)
264 free(tmp_ctrl[i]);
265 free(tmp_ctrl);
266 return GLU_OUT_OF_MEMORY;
267 }
268 for (i = 0; i < (*s_n_ctrl); i++) {
269 MEMCPY(*new_ctrl + i * tmp_stride, tmp_ctrl[i],
270 sizeof(GLfloat) * tmp_stride);
271 free(tmp_ctrl[i]);
272 }
273 free(tmp_ctrl);
274 *t_n_ctrl = tmp_n_control;
275 return GLU_NO_ERROR;
276 }
277
278 /* prepare the knot information structures */
279 static GLenum
280 fill_knot_structures(GLUnurbsObj * nobj,
281 knot_str_type * geom_s_knot, knot_str_type * geom_t_knot,
282 knot_str_type * color_s_knot,
283 knot_str_type * color_t_knot,
284 knot_str_type * normal_s_knot,
285 knot_str_type * normal_t_knot,
286 knot_str_type * texture_s_knot,
287 knot_str_type * texture_t_knot)
288 {
289 GLint order;
290 GLfloat *knot;
291 GLint nknots;
292 GLint t_min, t_max;
293
294 geom_s_knot->unified_knot = NULL;
295 knot = geom_s_knot->knot = nobj->surface.geom.sknot;
296 nknots = geom_s_knot->nknots = nobj->surface.geom.sknot_count;
297 order = geom_s_knot->order = nobj->surface.geom.sorder;
298 geom_s_knot->delta_nknots = 0;
299 t_min = geom_s_knot->t_min = order - 1;
300 t_max = geom_s_knot->t_max = nknots - order;
301 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
302 call_user_error(nobj, GLU_NURBS_ERROR3);
303 return GLU_ERROR;
304 }
305 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
306 /* knot open at beggining */
307 geom_s_knot->open_at_begin = GL_TRUE;
308 }
309 else
310 geom_s_knot->open_at_begin = GL_FALSE;
311 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
312 /* knot open at end */
313 geom_s_knot->open_at_end = GL_TRUE;
314 }
315 else
316 geom_s_knot->open_at_end = GL_FALSE;
317 geom_t_knot->unified_knot = NULL;
318 knot = geom_t_knot->knot = nobj->surface.geom.tknot;
319 nknots = geom_t_knot->nknots = nobj->surface.geom.tknot_count;
320 order = geom_t_knot->order = nobj->surface.geom.torder;
321 geom_t_knot->delta_nknots = 0;
322 t_min = geom_t_knot->t_min = order - 1;
323 t_max = geom_t_knot->t_max = nknots - order;
324 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
325 call_user_error(nobj, GLU_NURBS_ERROR3);
326 return GLU_ERROR;
327 }
328 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
329 /* knot open at beggining */
330 geom_t_knot->open_at_begin = GL_TRUE;
331 }
332 else
333 geom_t_knot->open_at_begin = GL_FALSE;
334 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
335 /* knot open at end */
336 geom_t_knot->open_at_end = GL_TRUE;
337 }
338 else
339 geom_t_knot->open_at_end = GL_FALSE;
340
341 if (nobj->surface.color.type != GLU_INVALID_ENUM) {
342 color_s_knot->unified_knot = (GLfloat *) 1;
343 knot = color_s_knot->knot = nobj->surface.color.sknot;
344 nknots = color_s_knot->nknots = nobj->surface.color.sknot_count;
345 order = color_s_knot->order = nobj->surface.color.sorder;
346 color_s_knot->delta_nknots = 0;
347 t_min = color_s_knot->t_min = order - 1;
348 t_max = color_s_knot->t_max = nknots - order;
349 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
350 call_user_error(nobj, GLU_NURBS_ERROR3);
351 return GLU_ERROR;
352 }
353 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
354 /* knot open at beggining */
355 color_s_knot->open_at_begin = GL_TRUE;
356 }
357 else
358 color_s_knot->open_at_begin = GL_FALSE;
359 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
360 /* knot open at end */
361 color_s_knot->open_at_end = GL_TRUE;
362 }
363 else
364 color_s_knot->open_at_end = GL_FALSE;
365 color_t_knot->unified_knot = (GLfloat *) 1;
366 knot = color_t_knot->knot = nobj->surface.color.tknot;
367 nknots = color_t_knot->nknots = nobj->surface.color.tknot_count;
368 order = color_t_knot->order = nobj->surface.color.torder;
369 color_t_knot->delta_nknots = 0;
370 t_min = color_t_knot->t_min = order - 1;
371 t_max = color_t_knot->t_max = nknots - order;
372 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
373 call_user_error(nobj, GLU_NURBS_ERROR3);
374 return GLU_ERROR;
375 }
376 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
377 /* knot open at beggining */
378 color_t_knot->open_at_begin = GL_TRUE;
379 }
380 else
381 color_t_knot->open_at_begin = GL_FALSE;
382 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
383 /* knot open at end */
384 color_t_knot->open_at_end = GL_TRUE;
385 }
386 else
387 color_t_knot->open_at_end = GL_FALSE;
388 }
389 else {
390 color_s_knot->unified_knot = NULL;
391 color_t_knot->unified_knot = NULL;
392 }
393
394 if (nobj->surface.normal.type != GLU_INVALID_ENUM) {
395 normal_s_knot->unified_knot = (GLfloat *) 1;
396 knot = normal_s_knot->knot = nobj->surface.normal.sknot;
397 nknots = normal_s_knot->nknots = nobj->surface.normal.sknot_count;
398 order = normal_s_knot->order = nobj->surface.normal.sorder;
399 normal_s_knot->delta_nknots = 0;
400 t_min = normal_s_knot->t_min = order - 1;
401 t_max = normal_s_knot->t_max = nknots - order;
402 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
403 call_user_error(nobj, GLU_NURBS_ERROR3);
404 return GLU_ERROR;
405 }
406 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
407 /* knot open at beggining */
408 normal_s_knot->open_at_begin = GL_TRUE;
409 }
410 else
411 normal_s_knot->open_at_begin = GL_FALSE;
412 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
413 /* knot open at end */
414 normal_s_knot->open_at_end = GL_TRUE;
415 }
416 else
417 normal_s_knot->open_at_end = GL_FALSE;
418 normal_t_knot->unified_knot = (GLfloat *) 1;
419 knot = normal_t_knot->knot = nobj->surface.normal.tknot;
420 nknots = normal_t_knot->nknots = nobj->surface.normal.tknot_count;
421 order = normal_t_knot->order = nobj->surface.normal.torder;
422 normal_t_knot->delta_nknots = 0;
423 t_min = normal_t_knot->t_min = order - 1;
424 t_max = normal_t_knot->t_max = nknots - order;
425 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
426 call_user_error(nobj, GLU_NURBS_ERROR3);
427 return GLU_ERROR;
428 }
429 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
430 /* knot open at beggining */
431 normal_t_knot->open_at_begin = GL_TRUE;
432 }
433 else
434 normal_t_knot->open_at_begin = GL_FALSE;
435 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
436 /* knot open at end */
437 normal_t_knot->open_at_end = GL_TRUE;
438 }
439 else
440 normal_t_knot->open_at_end = GL_FALSE;
441 }
442 else {
443 normal_s_knot->unified_knot = NULL;
444 normal_t_knot->unified_knot = NULL;
445 }
446
447 if (nobj->surface.texture.type != GLU_INVALID_ENUM) {
448 texture_s_knot->unified_knot = (GLfloat *) 1;
449 knot = texture_s_knot->knot = nobj->surface.texture.sknot;
450 nknots = texture_s_knot->nknots = nobj->surface.texture.sknot_count;
451 order = texture_s_knot->order = nobj->surface.texture.sorder;
452 texture_s_knot->delta_nknots = 0;
453 t_min = texture_s_knot->t_min = order - 1;
454 t_max = texture_s_knot->t_max = nknots - order;
455 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
456 call_user_error(nobj, GLU_NURBS_ERROR3);
457 return GLU_ERROR;
458 }
459 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
460 /* knot open at beggining */
461 texture_s_knot->open_at_begin = GL_TRUE;
462 }
463 else
464 texture_s_knot->open_at_begin = GL_FALSE;
465 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
466 /* knot open at end */
467 texture_s_knot->open_at_end = GL_TRUE;
468 }
469 else
470 texture_s_knot->open_at_end = GL_FALSE;
471 texture_t_knot->unified_knot = (GLfloat *) 1;
472 knot = texture_t_knot->knot = nobj->surface.texture.tknot;
473 nknots = texture_t_knot->nknots = nobj->surface.texture.tknot_count;
474 order = texture_t_knot->order = nobj->surface.texture.torder;
475 texture_t_knot->delta_nknots = 0;
476 t_min = texture_t_knot->t_min = order - 1;
477 t_max = texture_t_knot->t_max = nknots - order;
478 if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
479 call_user_error(nobj, GLU_NURBS_ERROR3);
480 return GLU_ERROR;
481 }
482 if (fabs(knot[0] - knot[t_min]) < EPSILON) {
483 /* knot open at beggining */
484 texture_t_knot->open_at_begin = GL_TRUE;
485 }
486 else
487 texture_t_knot->open_at_begin = GL_FALSE;
488 if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
489 /* knot open at end */
490 texture_t_knot->open_at_end = GL_TRUE;
491 }
492 else
493 texture_t_knot->open_at_end = GL_FALSE;
494 }
495 else {
496 texture_s_knot->unified_knot = NULL;
497 texture_t_knot->unified_knot = NULL;
498 }
499 return GLU_NO_ERROR;
500 }
501
502
503 static void
504 free_new_ctrl(new_ctrl_type * p)
505 {
506 if (p->geom_ctrl)
507 free(p->geom_ctrl);
508 if (p->geom_offsets)
509 free(p->geom_offsets);
510 if (p->color_ctrl) {
511 free(p->color_ctrl);
512 if (p->color_offsets)
513 free(p->color_offsets);
514 }
515 if (p->normal_ctrl) {
516 free(p->normal_ctrl);
517 if (p->normal_offsets)
518 free(p->normal_offsets);
519 }
520 if (p->texture_ctrl) {
521 free(p->texture_ctrl);
522 if (p->texture_offsets)
523 free(p->texture_offsets);
524 }
525 }
526
527 /* convert surfaces - geometry and possible attribute ones into equivalent */
528 /* sequence of adjacent Bezier patches */
529 static GLenum
530 convert_surfs(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl)
531 {
532 knot_str_type geom_s_knot, color_s_knot, normal_s_knot, texture_s_knot;
533 knot_str_type geom_t_knot, color_t_knot, normal_t_knot, texture_t_knot;
534 GLenum err;
535
536 if ((err = fill_knot_structures(nobj, &geom_s_knot, &geom_t_knot,
537 &color_s_knot, &color_t_knot,
538 &normal_s_knot, &normal_t_knot,
539 &texture_s_knot,
540 &texture_t_knot)) != GLU_NO_ERROR) {
541 return err;
542 }
543 /* unify knots - all knots should have the same working range */
544 if ((err = select_knot_working_range(nobj, &geom_s_knot, &color_s_knot,
545 &normal_s_knot,
546 &texture_s_knot)) != GLU_NO_ERROR) {
547 call_user_error(nobj, err);
548 return err;
549 }
550 if ((err = select_knot_working_range(nobj, &geom_t_knot, &color_t_knot,
551 &normal_t_knot,
552 &texture_t_knot)) != GLU_NO_ERROR) {
553 free_unified_knots(&geom_s_knot, &color_s_knot, &normal_s_knot,
554 &texture_s_knot);
555 call_user_error(nobj, err);
556 return err;
557 }
558
559 /* convert the geometry surface */
560 nobj->surface.geom.dim = get_surface_dim(nobj->surface.geom.type);
561 if ((err = convert_surf(&geom_s_knot, &geom_t_knot, &(nobj->surface.geom),
562 &(new_ctrl->geom_ctrl), &(new_ctrl->geom_s_pt_cnt),
563 &(new_ctrl->geom_t_pt_cnt))) != GLU_NO_ERROR) {
564 free_unified_knots(&geom_s_knot, &color_s_knot, &normal_s_knot,
565 &texture_s_knot);
566 free_unified_knots(&geom_t_knot, &color_t_knot, &normal_t_knot,
567 &texture_t_knot);
568 call_user_error(nobj, err);
569 return err;
570 }
571 /* if additional attributive surfaces are given convert them as well */
572 if (color_s_knot.unified_knot) {
573 nobj->surface.color.dim = get_surface_dim(nobj->surface.color.type);
574 if (
575 (err =
576 convert_surf(&color_s_knot, &color_t_knot, &(nobj->surface.color),
577 &(new_ctrl->color_ctrl), &(new_ctrl->color_s_pt_cnt),
578 &(new_ctrl->color_t_pt_cnt))) != GLU_NO_ERROR) {
579 free_unified_knots(&color_s_knot, &color_s_knot, &normal_s_knot,
580 &texture_s_knot);
581 free_unified_knots(&color_t_knot, &color_t_knot, &normal_t_knot,
582 &texture_t_knot);
583 free_new_ctrl(new_ctrl);
584 call_user_error(nobj, err);
585 return err;
586 }
587 }
588 if (normal_s_knot.unified_knot) {
589 nobj->surface.normal.dim = get_surface_dim(nobj->surface.normal.type);
590 if ((err = convert_surf(&normal_s_knot, &normal_t_knot,
591 &(nobj->surface.normal),
592 &(new_ctrl->normal_ctrl),
593 &(new_ctrl->normal_s_pt_cnt),
594 &(new_ctrl->normal_t_pt_cnt))) !=
595 GLU_NO_ERROR) {
596 free_unified_knots(&normal_s_knot, &normal_s_knot, &normal_s_knot,
597 &texture_s_knot);
598 free_unified_knots(&normal_t_knot, &normal_t_knot, &normal_t_knot,
599 &texture_t_knot);
600 free_new_ctrl(new_ctrl);
601 call_user_error(nobj, err);
602 return err;
603 }
604 }
605 if (texture_s_knot.unified_knot) {
606 nobj->surface.texture.dim = get_surface_dim(nobj->surface.texture.type);
607 if ((err = convert_surf(&texture_s_knot, &texture_t_knot,
608 &(nobj->surface.texture),
609 &(new_ctrl->texture_ctrl),
610 &(new_ctrl->texture_s_pt_cnt),
611 &(new_ctrl->texture_t_pt_cnt))) !=
612 GLU_NO_ERROR) {
613 free_unified_knots(&texture_s_knot, &texture_s_knot, &texture_s_knot,
614 &texture_s_knot);
615 free_unified_knots(&texture_t_knot, &texture_t_knot, &texture_t_knot,
616 &texture_t_knot);
617 free_new_ctrl(new_ctrl);
618 call_user_error(nobj, err);
619 return err;
620 }
621 }
622 return GLU_NO_ERROR;
623 }
624
625 /* tesselate the "boundary" Bezier edge strips */
626 static void
627 tesselate_strip_t_line(GLint top_start, GLint top_end, GLint top_z,
628 GLint bottom_start, GLint bottom_end, GLint bottom_z,
629 GLint bottom_domain)
630 {
631 GLint top_cnt, bottom_cnt, tri_cnt, k;
632 GLint direction;
633
634 top_cnt = top_end - top_start;
635 direction = (top_cnt >= 0 ? 1 : -1);
636 bottom_cnt = bottom_end - bottom_start;
637 glBegin(GL_LINES);
638 while (top_cnt) {
639 if (bottom_cnt)
640 tri_cnt = top_cnt / bottom_cnt;
641 else
642 tri_cnt = abs(top_cnt);
643 for (k = 0; k <= tri_cnt; k++, top_start += direction) {
644 glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
645 (GLfloat) bottom_start / bottom_domain);
646 glEvalPoint2(top_z, top_start);
647 }
648 if (bottom_cnt) {
649 glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
650 (GLfloat) bottom_start / bottom_domain);
651 bottom_start += direction;
652 top_start -= direction;
653 glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
654 (GLfloat) bottom_start / bottom_domain);
655 glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
656 (GLfloat) bottom_start / bottom_domain);
657 glEvalPoint2(top_z, top_start);
658 }
659 top_cnt -= direction * tri_cnt;
660 bottom_cnt -= direction;
661 }
662 glEnd();
663 }
664
665
666 static void
667 tesselate_strip_t_fill(GLint top_start, GLint top_end, GLint top_z,
668 GLint bottom_start, GLint bottom_end, GLint bottom_z,
669 GLint bottom_domain)
670 {
671 GLint top_cnt, bottom_cnt, tri_cnt, k;
672 GLint direction;
673
674 top_cnt = top_end - top_start;
675 direction = (top_cnt >= 0 ? 1 : -1);
676 bottom_cnt = bottom_end - bottom_start;
677 while (top_cnt) {
678 if (bottom_cnt)
679 tri_cnt = top_cnt / bottom_cnt;
680 else
681 tri_cnt = abs(top_cnt);
682 glBegin(GL_TRIANGLE_FAN);
683 glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
684 (GLfloat) bottom_start / bottom_domain);
685 for (k = 0; k <= tri_cnt; k++, top_start += direction)
686 glEvalPoint2(top_z, top_start);
687 if (bottom_cnt) {
688 bottom_start += direction;
689 top_start -= direction;
690 glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
691 (GLfloat) bottom_start / bottom_domain);
692 }
693 glEnd();
694 top_cnt -= direction * tri_cnt;
695 bottom_cnt -= direction;
696 }
697 }
698
699
700 static void
701 tesselate_strip_t(GLenum display_mode, GLint top_start, GLint top_end,
702 GLint top_z, GLint bottom_start, GLint bottom_end,
703 GLint bottom_z, GLint bottom_domain)
704 {
705 if (display_mode == GL_FILL)
706 tesselate_strip_t_fill(top_start, top_end, top_z, bottom_start,
707 bottom_end, bottom_z, bottom_domain);
708 else
709 tesselate_strip_t_line(top_start, top_end, top_z, bottom_start,
710 bottom_end, bottom_z, bottom_domain);
711 }
712
713
714 static void
715 tesselate_strip_s_fill(GLint top_start, GLint top_end, GLint top_z,
716 GLint bottom_start, GLint bottom_end, GLint bottom_z,
717 GLfloat bottom_domain)
718 {
719 GLint top_cnt, bottom_cnt, tri_cnt, k;
720 GLint direction;
721
722 top_cnt = top_end - top_start;
723 direction = (top_cnt >= 0 ? 1 : -1);
724 bottom_cnt = bottom_end - bottom_start;
725 while (top_cnt) {
726 if (bottom_cnt)
727 tri_cnt = top_cnt / bottom_cnt;
728 else
729 tri_cnt = abs(top_cnt);
730 glBegin(GL_TRIANGLE_FAN);
731 glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
732 (GLfloat) bottom_z / bottom_domain);
733 for (k = 0; k <= tri_cnt; k++, top_start += direction)
734 glEvalPoint2(top_start, top_z);
735 if (bottom_cnt) {
736 bottom_start += direction;
737 top_start -= direction;
738 glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
739 (GLfloat) bottom_z / bottom_domain);
740 }
741 glEnd();
742 top_cnt -= direction * tri_cnt;
743 bottom_cnt -= direction;
744 }
745 }
746
747
748 static void
749 tesselate_strip_s_line(GLint top_start, GLint top_end, GLint top_z,
750 GLint bottom_start, GLint bottom_end, GLint bottom_z,
751 GLfloat bottom_domain)
752 {
753 GLint top_cnt, bottom_cnt, tri_cnt, k;
754 GLint direction;
755
756 top_cnt = top_end - top_start;
757 direction = (top_cnt >= 0 ? 1 : -1);
758 bottom_cnt = bottom_end - bottom_start;
759 glBegin(GL_LINES);
760 while (top_cnt) {
761 if (bottom_cnt)
762 tri_cnt = top_cnt / bottom_cnt;
763 else
764 tri_cnt = abs(top_cnt);
765 for (k = 0; k <= tri_cnt; k++, top_start += direction) {
766 glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
767 (GLfloat) bottom_z / bottom_domain);
768 glEvalPoint2(top_start, top_z);
769 }
770 if (bottom_cnt) {
771 glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
772 (GLfloat) bottom_z / bottom_domain);
773 bottom_start += direction;
774 top_start -= direction;
775 glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
776 (GLfloat) bottom_z / bottom_domain);
777 glEvalPoint2(top_start, top_z);
778 glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
779 (GLfloat) bottom_z / bottom_domain);
780 }
781 top_cnt -= direction * tri_cnt;
782 bottom_cnt -= direction;
783 }
784 glEnd();
785 }
786
787
788 static void
789 tesselate_strip_s(GLenum display_mode, GLint top_start, GLint top_end,
790 GLint top_z, GLint bottom_start, GLint bottom_end,
791 GLint bottom_z, GLfloat bottom_domain)
792 {
793 if (display_mode == GL_FILL)
794 tesselate_strip_s_fill(top_start, top_end, top_z, bottom_start,
795 bottom_end, bottom_z, bottom_domain);
796 else
797 tesselate_strip_s_line(top_start, top_end, top_z, bottom_start,
798 bottom_end, bottom_z, bottom_domain);
799 }
800
801 static void
802 tesselate_bottom_left_corner(GLenum display_mode, GLfloat s_1, GLfloat t_1)
803 {
804 if (display_mode == GL_FILL) {
805 glBegin(GL_TRIANGLE_FAN);
806 glEvalPoint2(1, 1);
807 glEvalCoord2f(s_1, 0.0);
808 glEvalCoord2f(0.0, 0.0);
809 glEvalCoord2f(0.0, t_1);
810 }
811 else {
812 glBegin(GL_LINES);
813 glEvalCoord2f(0.0, 0.0);
814 glEvalCoord2f(0.0, t_1);
815 glEvalCoord2f(0.0, 0.0);
816 glEvalPoint2(1, 1);
817 glEvalCoord2f(0.0, 0.0);
818 glEvalCoord2f(s_1, 0.0);
819 }
820 glEnd();
821 }
822
823 static void
824 tesselate_bottom_right_corner(GLenum display_mode, GLint v_top,
825 GLint v_bottom, GLfloat s_1, GLfloat t_1)
826 {
827 if (display_mode == GL_FILL) {
828 glBegin(GL_TRIANGLE_FAN);
829 glEvalPoint2(1, v_top);
830 glEvalCoord2f(0.0, v_bottom * t_1);
831 glEvalCoord2f(0.0, (v_bottom + 1) * t_1);
832 glEvalCoord2f(s_1, (v_bottom + 1) * t_1);
833 }
834 else {
835 glBegin(GL_LINES);
836 glEvalCoord2f(0.0, (v_bottom + 1) * t_1);
837 glEvalPoint2(1, v_top);
838 glEvalCoord2f(0.0, (v_bottom + 1) * t_1);
839 glEvalCoord2f(0.0, v_bottom * t_1);
840 glEvalCoord2f(0.0, (v_bottom + 1) * t_1);
841 glEvalCoord2f(s_1, (v_bottom + 1) * t_1);
842 }
843 glEnd();
844 }
845
846 static void
847 tesselate_top_left_corner(GLenum display_mode, GLint u_right, GLint u_left,
848 GLfloat s_1, GLfloat t_1)
849 {
850 if (display_mode == GL_FILL) {
851 glBegin(GL_TRIANGLE_FAN);
852 glEvalPoint2(u_right, 1);
853 glEvalCoord2f((u_left + 1) * s_1, t_1);
854 glEvalCoord2f((u_left + 1) * s_1, 0.0);
855 glEvalCoord2f(u_left * s_1, 0.0);
856 }
857 else {
858 glBegin(GL_LINES);
859 glEvalCoord2f((u_left + 1) * s_1, 0.0);
860 glEvalPoint2(u_right, 1);
861 glEvalCoord2f((u_left + 1) * s_1, 0.0);
862 glEvalCoord2f(u_left * s_1, 0.0);
863 glEvalCoord2f((u_left + 1) * s_1, 0.0);
864 glEvalCoord2f((u_left + 1) * s_1, t_1);
865 }
866 glEnd();
867 }
868
869 static void
870 tesselate_top_right_corner(GLenum display_mode, GLint u_left, GLint v_bottom,
871 GLint u_right, GLint v_top, GLfloat s_1,
872 GLfloat t_1)
873 {
874 if (display_mode == GL_FILL) {
875 glBegin(GL_TRIANGLE_FAN);
876 glEvalPoint2(u_left, v_bottom);
877 glEvalCoord2f((u_right - 1) * s_1, v_top * t_1);
878 glEvalCoord2f(u_right * s_1, v_top * t_1);
879 glEvalCoord2f(u_right * s_1, (v_top - 1) * t_1);
880 }
881 else {
882 glBegin(GL_LINES);
883 glEvalCoord2f(u_right * s_1, v_top * t_1);
884 glEvalPoint2(u_left, v_bottom);
885 glEvalCoord2f(u_right * s_1, v_top * t_1);
886 glEvalCoord2f(u_right * s_1, (v_top - 1) * t_1);
887 glEvalCoord2f(u_right * s_1, v_top * t_1);
888 glEvalCoord2f((u_right - 1) * s_1, v_top * t_1);
889 }
890 glEnd();
891 }
892
893 /* do mesh mapping of Bezier */
894 static void
895 nurbs_map_bezier(GLenum display_mode, GLint * sfactors, GLint * tfactors,
896 GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t)
897 {
898 GLint top, bottom, right, left;
899
900
901 if (s == 0) {
902 top = *(tfactors + t * 3);
903 bottom = *(tfactors + t * 3 + 1);
904 }
905 else if (s == s_bezier_cnt - 1) {
906 top = *(tfactors + t * 3 + 2);
907 bottom = *(tfactors + t * 3);
908 }
909 else {
910 top = bottom = *(tfactors + t * 3);
911 }
912 if (t == 0) {
913 left = *(sfactors + s * 3 + 1);
914 right = *(sfactors + s * 3);
915 }
916 else if (t == t_bezier_cnt - 1) {
917 left = *(sfactors + s * 3);
918 right = *(sfactors + s * 3 + 2);
919 }
920 else {
921 left = right = *(sfactors + s * 3);
922 }
923
924 if (top > bottom) {
925 if (left < right) {
926 glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
927 glEvalMesh2(display_mode, 1, right, 1, top);
928 tesselate_strip_s(display_mode, 1, right, 1, 1, left, 0,
929 (GLfloat) left);
930 tesselate_bottom_left_corner(display_mode, (GLfloat) (1.0 / left),
931 (GLfloat) (1.0 / bottom));
932 /* tesselate_strip_t(display_mode,1,top,1,1,bottom,0,(GLfloat)bottom);*/
933 tesselate_strip_t(display_mode, top, 1, 1, bottom, 1, 0,
934 (GLfloat) bottom);
935 }
936 else if (left == right) {
937 glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
938 glEvalMesh2(display_mode, 1, right, 0, top);
939 /* tesselate_strip_t(display_mode,0,top,1,0,bottom,0,(GLfloat)bottom);*/
940 tesselate_strip_t(display_mode, top, 0, 1, bottom, 0, 0,
941 (GLfloat) bottom);
942 }
943 else {
944 glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0);
945 glEvalMesh2(display_mode, 1, left, 0, top - 1);
946 /* tesselate_strip_t(display_mode,0,top-1,1,0,bottom-1,0,
947 (GLfloat)bottom);*/
948 tesselate_strip_t(display_mode, top - 1, 0, 1, bottom - 1, 0, 0,
949 (GLfloat) bottom);
950 tesselate_bottom_right_corner(display_mode, top - 1, bottom - 1,
951 (GLfloat) (1.0 / right),
952 (GLfloat) (1.0 / bottom));
953 /* tesselate_strip_s(display_mode,1,left,top-1,1,right,right,
954 (GLfloat)right);*/
955 tesselate_strip_s(display_mode, left, 1, top - 1, right, 1, right,
956 (GLfloat) right);
957 }
958 }
959 else if (top == bottom) {
960 if (left < right) {
961 glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
962 glEvalMesh2(display_mode, 0, right, 1, top);
963 tesselate_strip_s(display_mode, 0, right, 1, 0, left, 0,
964 (GLfloat) left);
965 }
966 else if (left == right) {
967 glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
968 glEvalMesh2(display_mode, 0, right, 0, top);
969 }
970 else {
971 glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0);
972 glEvalMesh2(display_mode, 0, left, 0, top - 1);
973 /* tesselate_strip_s(display_mode,0,left,top-1,0,right,right,
974 (GLfloat)right);*/
975 tesselate_strip_s(display_mode, left, 0, top - 1, right, 0, right,
976 (GLfloat) right);
977 }
978 }
979 else {
980 if (left < right) {
981 glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0);
982 glEvalMesh2(display_mode, 0, right - 1, 1, bottom);
983 tesselate_strip_s(display_mode, 0, right - 1, 1, 0, left - 1, 0,
984 (GLfloat) left);
985 tesselate_top_left_corner(display_mode, right - 1, left - 1,
986 (GLfloat) (1.0 / left),
987 (GLfloat) (1.0 / top));
988 tesselate_strip_t(display_mode, 1, bottom, right - 1, 1, top, top,
989 (GLfloat) top);
990 }
991 else if (left == right) {
992 glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0);
993 glEvalMesh2(display_mode, 0, right - 1, 0, bottom);
994 tesselate_strip_t(display_mode, 0, bottom, right - 1, 0, top, top,
995 (GLfloat) top);
996 }
997 else {
998 glMapGrid2f(left, 0.0, 1.0, bottom, 0.0, 1.0);
999 glEvalMesh2(display_mode, 0, left - 1, 0, bottom - 1);
1000 tesselate_strip_t(display_mode, 0, bottom - 1, left - 1, 0, top - 1,
1001 top, (GLfloat) top);
1002 tesselate_top_right_corner(display_mode, left - 1, bottom - 1, right,
1003 top, (GLfloat) (1.0 / right),
1004 (GLfloat) (1.0 / top));
1005 /* tesselate_strip_s(display_mode,0,left-1,bottom-1,0,right-1,right,
1006 (GLfloat)right);*/
1007 tesselate_strip_s(display_mode, left - 1, 0, bottom - 1, right - 1,
1008 0, right, (GLfloat) right);
1009 }
1010 }
1011 }
1012
1013 /* draw NURBS surface in OUTLINE POLYGON mode */
1014 static void
1015 draw_polygon_mode(GLenum display_mode, GLUnurbsObj * nobj,
1016 new_ctrl_type * new_ctrl, GLint * sfactors,
1017 GLint * tfactors)
1018 {
1019 GLsizei offset;
1020 GLint t_bezier_cnt, s_bezier_cnt;
1021 GLboolean do_color, do_normal, do_texture;
1022 GLint i, j;
1023
1024 t_bezier_cnt = new_ctrl->t_bezier_cnt;
1025 s_bezier_cnt = new_ctrl->s_bezier_cnt;
1026 glEnable(nobj->surface.geom.type);
1027 if (new_ctrl->color_ctrl) {
1028 glEnable(nobj->surface.color.type);
1029 do_color = GL_TRUE;
1030 }
1031 else
1032 do_color = GL_FALSE;
1033 if (new_ctrl->normal_ctrl) {
1034 glEnable(nobj->surface.normal.type);
1035 do_normal = GL_TRUE;
1036 }
1037 else
1038 do_normal = GL_FALSE;
1039 if (new_ctrl->texture_ctrl) {
1040 glEnable(nobj->surface.texture.type);
1041 do_texture = GL_TRUE;
1042 }
1043 else
1044 do_texture = GL_FALSE;
1045 for (j = 0; j < s_bezier_cnt; j++) {
1046 for (i = 0; i < t_bezier_cnt; i++) {
1047 offset = j * t_bezier_cnt + i;
1048 if (fine_culling_test_3D(nobj, *(new_ctrl->geom_offsets + offset),
1049 nobj->surface.geom.sorder,
1050 nobj->surface.geom.torder,
1051 new_ctrl->geom_s_stride,
1052 new_ctrl->geom_t_stride,
1053 nobj->surface.geom.dim)) continue;
1054 glMap2f(nobj->surface.geom.type, 0.0, 1.0, new_ctrl->geom_s_stride,
1055 nobj->surface.geom.sorder, 0.0, 1.0, new_ctrl->geom_t_stride,
1056 nobj->surface.geom.torder,
1057 *(new_ctrl->geom_offsets + offset));
1058 if (do_color) {
1059 glMap2f(nobj->surface.color.type, 0.0, 1.0,
1060 new_ctrl->color_s_stride, nobj->surface.color.sorder,
1061 0.0, 1.0, new_ctrl->color_t_stride,
1062 nobj->surface.color.torder,
1063 *(new_ctrl->color_offsets + offset));
1064 }
1065 if (do_normal) {
1066 glMap2f(nobj->surface.normal.type, 0.0, 1.0,
1067 new_ctrl->normal_s_stride, nobj->surface.normal.sorder,
1068 0.0, 1.0, new_ctrl->normal_t_stride,
1069 nobj->surface.normal.torder,
1070 *(new_ctrl->normal_offsets + offset));
1071 }
1072 if (do_texture) {
1073 glMap2f(nobj->surface.texture.type, 0.0, 1.0,
1074 new_ctrl->texture_s_stride, nobj->surface.texture.sorder,
1075 0.0, 1.0, new_ctrl->texture_t_stride,
1076 nobj->surface.texture.torder,
1077 *(new_ctrl->texture_offsets + offset));
1078 }
1079 /* glMapGrid2f(sfactors[j*3+0],0.0,1.0,tfactors[i*3+0],0.0,1.0);
1080 glEvalMesh2(display_mode,0,sfactors[j*3+0],0,tfactors[i*3+0]);*/
1081 nurbs_map_bezier(display_mode, sfactors, tfactors, s_bezier_cnt,
1082 t_bezier_cnt, j, i);
1083 }
1084 }
1085 }
1086
1087
1088
1089 /* draw NURBS surface in OUTLINE POLYGON mode */
1090 #if 0
1091 static void
1092 draw_patch_mode(GLenum display_mode, GLUnurbsObj * nobj,
1093 new_ctrl_type * new_ctrl, GLint * sfactors, GLint * tfactors)
1094 {
1095 GLsizei offset;
1096 GLint t_bezier_cnt, s_bezier_cnt;
1097 GLboolean do_color, do_normal, do_texture;
1098 GLint i, j;
1099
1100 t_bezier_cnt = new_ctrl->t_bezier_cnt;
1101 s_bezier_cnt = new_ctrl->s_bezier_cnt;
1102 glEnable(nobj->surface.geom.type);
1103 if (new_ctrl->color_ctrl) {
1104 glEnable(nobj->surface.color.type);
1105 do_color = GL_TRUE;
1106 }
1107 else
1108 do_color = GL_FALSE;
1109 if (new_ctrl->normal_ctrl) {
1110 glEnable(nobj->surface.normal.type);
1111 do_normal = GL_TRUE;
1112 }
1113 else
1114 do_normal = GL_FALSE;
1115 if (new_ctrl->texture_ctrl) {
1116 glEnable(nobj->surface.texture.type);
1117 do_texture = GL_TRUE;
1118 }
1119 else
1120 do_texture = GL_FALSE;
1121 for (j = 0; j < s_bezier_cnt; j++) {
1122 for (i = 0; i < t_bezier_cnt; i++) {
1123 offset = j * t_bezier_cnt + i;
1124 if (fine_culling_test_3D(nobj, *(new_ctrl->geom_offsets + offset),
1125 nobj->surface.geom.sorder,
1126 nobj->surface.geom.torder,
1127 new_ctrl->geom_s_stride,
1128 new_ctrl->geom_t_stride,
1129 nobj->surface.geom.dim)) continue;
1130 glMap2f(nobj->surface.geom.type, 0.0, 1.0, new_ctrl->geom_s_stride,
1131 nobj->surface.geom.sorder, 0.0, 1.0, new_ctrl->geom_t_stride,
1132 nobj->surface.geom.torder,
1133 *(new_ctrl->geom_offsets + offset));
1134 if (do_color) {
1135 glMap2f(nobj->surface.color.type, 0.0, 1.0,
1136 new_ctrl->color_s_stride, nobj->surface.color.sorder,
1137 0.0, 1.0, new_ctrl->color_t_stride,
1138 nobj->surface.color.torder,
1139 *(new_ctrl->color_offsets + offset));
1140 }
1141 if (do_normal) {
1142 glMap2f(nobj->surface.normal.type, 0.0, 1.0,
1143 new_ctrl->normal_s_stride, nobj->surface.normal.sorder,
1144 0.0, 1.0, new_ctrl->normal_t_stride,
1145 nobj->surface.normal.torder,
1146 *(new_ctrl->normal_offsets + offset));
1147 }
1148 if (do_texture) {
1149 glMap2f(nobj->surface.texture.type, 0.0, 1.0,
1150 new_ctrl->texture_s_stride, nobj->surface.texture.sorder,
1151 0.0, 1.0, new_ctrl->texture_t_stride,
1152 nobj->surface.texture.torder,
1153 *(new_ctrl->texture_offsets + offset));
1154 }
1155 nurbs_map_bezier(display_mode, sfactors, tfactors, s_bezier_cnt,
1156 t_bezier_cnt, i, j);
1157 /* glMapGrid2f(sfactors[j],0.0,1.0,tfactors[i],0.0,1.0);
1158 glEvalMesh2(display_mode,0,sfactors[j],0,tfactors[i]);*/
1159 }
1160 }
1161 }
1162 #endif
1163
1164
1165
1166 static void
1167 init_new_ctrl(new_ctrl_type * p)
1168 {
1169 p->geom_ctrl = p->color_ctrl = p->normal_ctrl = p->texture_ctrl = NULL;
1170 p->geom_offsets = p->color_offsets = p->normal_offsets =
1171 p->texture_offsets = NULL;
1172 p->s_bezier_cnt = p->t_bezier_cnt = 0;
1173 }
1174
1175
1176 static GLenum
1177 augment_new_ctrl(GLUnurbsObj * nobj, new_ctrl_type * p)
1178 {
1179 GLsizei offset_size;
1180 GLint i, j;
1181
1182 p->s_bezier_cnt = (p->geom_s_pt_cnt) / (nobj->surface.geom.sorder);
1183 p->t_bezier_cnt = (p->geom_t_pt_cnt) / (nobj->surface.geom.torder);
1184 offset_size = (p->s_bezier_cnt) * (p->t_bezier_cnt);
1185 p->geom_t_stride = nobj->surface.geom.dim;
1186 p->geom_s_stride = (p->geom_t_pt_cnt) * (nobj->surface.geom.dim);
1187 p->color_t_stride = nobj->surface.color.dim;
1188 p->color_s_stride = (p->color_t_pt_cnt) * (nobj->surface.color.dim);
1189 p->normal_t_stride = nobj->surface.normal.dim;
1190 p->normal_s_stride = (p->normal_t_pt_cnt) * (nobj->surface.normal.dim);
1191 p->texture_t_stride = nobj->surface.texture.dim;
1192 p->texture_s_stride = (p->texture_t_pt_cnt) * (nobj->surface.texture.dim);
1193 if (
1194 (p->geom_offsets =
1195 (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1196 call_user_error(nobj, GLU_OUT_OF_MEMORY);
1197 return GLU_ERROR;
1198 }
1199 if (p->color_ctrl)
1200 if (
1201 (p->color_offsets =
1202 (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1203 free_new_ctrl(p);
1204 call_user_error(nobj, GLU_OUT_OF_MEMORY);
1205 return GLU_ERROR;
1206 }
1207 if (p->normal_ctrl)
1208 if (
1209 (p->normal_offsets =
1210 (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1211 free_new_ctrl(p);
1212 call_user_error(nobj, GLU_OUT_OF_MEMORY);
1213 return GLU_ERROR;
1214 }
1215 if (p->texture_ctrl)
1216 if (
1217 (p->texture_offsets =
1218 (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1219 free_new_ctrl(p);
1220 call_user_error(nobj, GLU_OUT_OF_MEMORY);
1221 return GLU_ERROR;
1222 }
1223 for (i = 0; i < p->s_bezier_cnt; i++)
1224 for (j = 0; j < p->t_bezier_cnt; j++)
1225 *(p->geom_offsets + i * (p->t_bezier_cnt) + j) =
1226 p->geom_ctrl + i * (nobj->surface.geom.sorder) *
1227 (nobj->surface.geom.dim) * (p->geom_t_pt_cnt) +
1228 j * (nobj->surface.geom.dim) * (nobj->surface.geom.torder);
1229 if (p->color_ctrl)
1230 for (i = 0; i < p->s_bezier_cnt; i++)
1231 for (j = 0; j < p->t_bezier_cnt; j++)
1232 *(p->color_offsets + i * (p->t_bezier_cnt) + j) =
1233 p->color_ctrl + i * (nobj->surface.color.sorder) *
1234 (nobj->surface.color.dim) * (p->color_t_pt_cnt) +
1235 j * (nobj->surface.color.dim) * (nobj->surface.color.torder);
1236 if (p->normal_ctrl)
1237 for (i = 0; i < p->s_bezier_cnt; i++)
1238 for (j = 0; j < p->t_bezier_cnt; j++)
1239 *(p->normal_offsets + i * (p->t_bezier_cnt) + j) =
1240 p->normal_ctrl + i * (nobj->surface.normal.sorder) *
1241 (nobj->surface.normal.dim) * (p->normal_t_pt_cnt) +
1242 j * (nobj->surface.normal.dim) * (nobj->surface.normal.torder);
1243 if (p->texture_ctrl)
1244 for (i = 0; i < p->s_bezier_cnt; i++)
1245 for (j = 0; j < p->t_bezier_cnt; j++)
1246 *(p->texture_offsets + i * (p->t_bezier_cnt) + j) =
1247 p->texture_ctrl + i * (nobj->surface.texture.sorder) *
1248 (nobj->surface.texture.dim) * (p->texture_t_pt_cnt) +
1249 j * (nobj->surface.texture.dim) *
1250 (nobj->surface.texture.torder);
1251 return GLU_NO_ERROR;
1252 }
1253
1254 /* main NURBS surface procedure */
1255 void
1256 do_nurbs_surface(GLUnurbsObj * nobj)
1257 {
1258 GLint *sfactors, *tfactors;
1259 new_ctrl_type new_ctrl;
1260
1261 /* test user supplied data */
1262 if (test_nurbs_surfaces(nobj) != GLU_NO_ERROR)
1263 return;
1264
1265 init_new_ctrl(&new_ctrl);
1266
1267 if (convert_surfs(nobj, &new_ctrl) != GLU_NO_ERROR)
1268 return;
1269 if (augment_new_ctrl(nobj, &new_ctrl) != GLU_NO_ERROR)
1270 return;
1271 switch (nobj->sampling_method) {
1272 case GLU_PATH_LENGTH:
1273 if (glu_do_sampling_3D(nobj, &new_ctrl, &sfactors, &tfactors) !=
1274 GLU_NO_ERROR) {
1275 free_new_ctrl(&new_ctrl);
1276 return;
1277 }
1278 break;
1279 case GLU_DOMAIN_DISTANCE:
1280 if (glu_do_sampling_uv(nobj, &new_ctrl, &sfactors, &tfactors) !=
1281 GLU_NO_ERROR) {
1282 free_new_ctrl(&new_ctrl);
1283 return;
1284 }
1285 break;
1286 case GLU_PARAMETRIC_ERROR:
1287 if (glu_do_sampling_param_3D(nobj, &new_ctrl, &sfactors, &tfactors) !=
1288 GLU_NO_ERROR) {
1289 free_new_ctrl(&new_ctrl);
1290 return;
1291 }
1292 break;
1293 default:
1294 abort();
1295 }
1296 glFrontFace(GL_CW);
1297 switch (nobj->display_mode) {
1298 case GLU_FILL:
1299 /* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
1300 draw_polygon_mode(GL_FILL, nobj, &new_ctrl, sfactors, tfactors);
1301 break;
1302 case GLU_OUTLINE_POLYGON:
1303 /* TODO - missing trimming handeling */
1304 /* just for now - no OUTLINE_PATCH mode
1305 draw_patch_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors);
1306 break; */
1307 case GLU_OUTLINE_PATCH:
1308 /* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
1309 draw_polygon_mode(GL_LINE, nobj, &new_ctrl, sfactors, tfactors);
1310 break;
1311 default:
1312 abort(); /* TODO: is this OK? */
1313 }
1314 free(sfactors);
1315 free(tfactors);
1316 free_new_ctrl(&new_ctrl);
1317 }