3
* Mesa 3-D graphics library
5
* Copyright (C) 1995-2000 Brian Paul
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.
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.
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.
24
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
25
* See README2 for more info.
41
get_surface_dim(GLenum type)
44
case GL_MAP2_VERTEX_3:
46
case GL_MAP2_VERTEX_4:
54
case GL_MAP2_TEXTURE_COORD_1:
56
case GL_MAP2_TEXTURE_COORD_2:
58
case GL_MAP2_TEXTURE_COORD_3:
60
case GL_MAP2_TEXTURE_COORD_4:
63
abort(); /* TODO: is this OK? */
65
return 0; /*never get here */
69
test_nurbs_surface(GLUnurbsObj * nobj, surface_attribs * attrib)
74
if (attrib->sorder < 0 || attrib->torder < 0) {
75
call_user_error(nobj, GLU_INVALID_VALUE);
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);
83
if (attrib->torder > tmp_int || attrib->torder < 2) {
84
call_user_error(nobj, GLU_NURBS_ERROR1);
87
if (attrib->sknot_count < attrib->sorder + 2) {
88
call_user_error(nobj, GLU_NURBS_ERROR2);
91
if (attrib->tknot_count < attrib->torder + 2) {
92
call_user_error(nobj, GLU_NURBS_ERROR2);
95
if (attrib->s_stride < 0 || attrib->t_stride < 0) {
96
call_user_error(nobj, GLU_NURBS_ERROR34);
99
if (attrib->sknot == NULL || attrib->tknot == NULL
100
|| attrib->ctrlarray == NULL) {
101
call_user_error(nobj, GLU_NURBS_ERROR36);
104
if ((err = test_knot(attrib->tknot_count, attrib->tknot, attrib->torder))
106
call_user_error(nobj, err);
109
if ((err = test_knot(attrib->sknot_count, attrib->sknot, attrib->sorder))
111
call_user_error(nobj, err);
118
test_nurbs_surfaces(GLUnurbsObj * nobj)
120
/* test the geometric data */
121
if (test_nurbs_surface(nobj, &(nobj->surface.geom)) != GLU_NO_ERROR)
123
/* now test the attributive data */
125
if (nobj->surface.color.type != GLU_INVALID_ENUM)
126
if (test_nurbs_surface(nobj, &(nobj->surface.color)) != GLU_NO_ERROR)
129
if (nobj->surface.normal.type != GLU_INVALID_ENUM)
130
if (test_nurbs_surface(nobj, &(nobj->surface.normal)) != GLU_NO_ERROR)
133
if (nobj->surface.texture.type != GLU_INVALID_ENUM)
134
if (test_nurbs_surface(nobj, &(nobj->surface.texture)) != GLU_NO_ERROR)
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)
145
GLfloat *ctrl_offset;
147
GLint i, j, t_cnt, s_cnt;
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;
159
if (t_knot->unified_knot) {
160
free(t_knot->unified_knot);
161
t_knot->unified_knot = NULL;
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) {
173
if (s_knot->unified_knot) {
174
free(s_knot->unified_knot);
175
s_knot->unified_knot = NULL;
179
if (s_knot->unified_knot) {
180
free(s_knot->unified_knot);
181
s_knot->unified_knot = NULL;
183
if ((err = calc_alphas(s_knot)) != GLU_NO_ERROR) {
185
free(s_knot->new_knot);
188
free(s_knot->new_knot);
189
ctrl_offset = attrib->ctrlarray;
191
for (i = 0; i < t_cnt; i++) {
192
if ((err = calc_new_ctrl_pts(ctrl_offset, attrib->s_stride, s_knot,
194
&tmp_n_control)) != GLU_NO_ERROR) {
195
for (--i; i <= 0; i--)
201
ctrl_offset += attrib->t_stride;
204
tmp_stride = dim * tmp_n_control;
205
if ((*new_ctrl = (GLfloat *) malloc(sizeof(GLfloat) * tmp_stride * t_cnt))
207
for (i = 0; i < t_cnt; i++)
210
return GLU_OUT_OF_MEMORY;
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++)
219
*s_n_ctrl = tmp_n_control;
221
if ((tmp_ctrl = (GLfloat **) malloc(sizeof(GLfloat *) * (*s_n_ctrl))) ==
223
return GLU_OUT_OF_MEMORY;
225
if ((err = explode_knot(t_knot)) != GLU_NO_ERROR) {
227
if (t_knot->unified_knot) {
228
free(t_knot->unified_knot);
229
t_knot->unified_knot = NULL;
233
if (t_knot->unified_knot) {
234
free(t_knot->unified_knot);
235
t_knot->unified_knot = NULL;
237
if ((err = calc_alphas(t_knot)) != GLU_NO_ERROR) {
239
free(t_knot->new_knot);
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,
247
&tmp_n_control)) != GLU_NO_ERROR) {
248
for (--i; i <= 0; i--)
254
ctrl_offset += dim * t_cnt;
258
tmp_stride = dim * tmp_n_control;
261
(GLfloat *) malloc(sizeof(GLfloat) * tmp_stride * (*s_n_ctrl))) ==
263
for (i = 0; i < (*s_n_ctrl); i++)
266
return GLU_OUT_OF_MEMORY;
268
for (i = 0; i < (*s_n_ctrl); i++) {
269
MEMCPY(*new_ctrl + i * tmp_stride, tmp_ctrl[i],
270
sizeof(GLfloat) * tmp_stride);
274
*t_n_ctrl = tmp_n_control;
278
/* prepare the knot information structures */
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)
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);
305
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
306
/* knot open at beggining */
307
geom_s_knot->open_at_begin = GL_TRUE;
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;
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);
328
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
329
/* knot open at beggining */
330
geom_t_knot->open_at_begin = GL_TRUE;
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;
339
geom_t_knot->open_at_end = GL_FALSE;
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);
353
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
354
/* knot open at beggining */
355
color_s_knot->open_at_begin = GL_TRUE;
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;
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);
376
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
377
/* knot open at beggining */
378
color_t_knot->open_at_begin = GL_TRUE;
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;
387
color_t_knot->open_at_end = GL_FALSE;
390
color_s_knot->unified_knot = NULL;
391
color_t_knot->unified_knot = NULL;
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);
406
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
407
/* knot open at beggining */
408
normal_s_knot->open_at_begin = GL_TRUE;
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;
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);
429
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
430
/* knot open at beggining */
431
normal_t_knot->open_at_begin = GL_TRUE;
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;
440
normal_t_knot->open_at_end = GL_FALSE;
443
normal_s_knot->unified_knot = NULL;
444
normal_t_knot->unified_knot = NULL;
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);
459
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
460
/* knot open at beggining */
461
texture_s_knot->open_at_begin = GL_TRUE;
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;
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);
482
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
483
/* knot open at beggining */
484
texture_t_knot->open_at_begin = GL_TRUE;
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;
493
texture_t_knot->open_at_end = GL_FALSE;
496
texture_s_knot->unified_knot = NULL;
497
texture_t_knot->unified_knot = NULL;
504
free_new_ctrl(new_ctrl_type * p)
509
free(p->geom_offsets);
512
if (p->color_offsets)
513
free(p->color_offsets);
515
if (p->normal_ctrl) {
516
free(p->normal_ctrl);
517
if (p->normal_offsets)
518
free(p->normal_offsets);
520
if (p->texture_ctrl) {
521
free(p->texture_ctrl);
522
if (p->texture_offsets)
523
free(p->texture_offsets);
527
/* convert surfaces - geometry and possible attribute ones into equivalent */
528
/* sequence of adjacent Bezier patches */
530
convert_surfs(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl)
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;
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,
540
&texture_t_knot)) != GLU_NO_ERROR) {
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,
546
&texture_s_knot)) != GLU_NO_ERROR) {
547
call_user_error(nobj, err);
550
if ((err = select_knot_working_range(nobj, &geom_t_knot, &color_t_knot,
552
&texture_t_knot)) != GLU_NO_ERROR) {
553
free_unified_knots(&geom_s_knot, &color_s_knot, &normal_s_knot,
555
call_user_error(nobj, err);
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,
566
free_unified_knots(&geom_t_knot, &color_t_knot, &normal_t_knot,
568
call_user_error(nobj, err);
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);
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,
581
free_unified_knots(&color_t_knot, &color_t_knot, &normal_t_knot,
583
free_new_ctrl(new_ctrl);
584
call_user_error(nobj, err);
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))) !=
596
free_unified_knots(&normal_s_knot, &normal_s_knot, &normal_s_knot,
598
free_unified_knots(&normal_t_knot, &normal_t_knot, &normal_t_knot,
600
free_new_ctrl(new_ctrl);
601
call_user_error(nobj, err);
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))) !=
613
free_unified_knots(&texture_s_knot, &texture_s_knot, &texture_s_knot,
615
free_unified_knots(&texture_t_knot, &texture_t_knot, &texture_t_knot,
617
free_new_ctrl(new_ctrl);
618
call_user_error(nobj, err);
625
/* tesselate the "boundary" Bezier edge strips */
627
tesselate_strip_t_line(GLint top_start, GLint top_end, GLint top_z,
628
GLint bottom_start, GLint bottom_end, GLint bottom_z,
631
GLint top_cnt, bottom_cnt, tri_cnt, k;
634
top_cnt = top_end - top_start;
635
direction = (top_cnt >= 0 ? 1 : -1);
636
bottom_cnt = bottom_end - bottom_start;
640
tri_cnt = top_cnt / bottom_cnt;
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);
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);
659
top_cnt -= direction * tri_cnt;
660
bottom_cnt -= direction;
667
tesselate_strip_t_fill(GLint top_start, GLint top_end, GLint top_z,
668
GLint bottom_start, GLint bottom_end, GLint bottom_z,
671
GLint top_cnt, bottom_cnt, tri_cnt, k;
674
top_cnt = top_end - top_start;
675
direction = (top_cnt >= 0 ? 1 : -1);
676
bottom_cnt = bottom_end - bottom_start;
679
tri_cnt = top_cnt / bottom_cnt;
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);
688
bottom_start += direction;
689
top_start -= direction;
690
glEvalCoord2f((GLfloat) bottom_z / bottom_domain,
691
(GLfloat) bottom_start / bottom_domain);
694
top_cnt -= direction * tri_cnt;
695
bottom_cnt -= direction;
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)
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);
709
tesselate_strip_t_line(top_start, top_end, top_z, bottom_start,
710
bottom_end, bottom_z, bottom_domain);
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)
719
GLint top_cnt, bottom_cnt, tri_cnt, k;
722
top_cnt = top_end - top_start;
723
direction = (top_cnt >= 0 ? 1 : -1);
724
bottom_cnt = bottom_end - bottom_start;
727
tri_cnt = top_cnt / bottom_cnt;
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);
736
bottom_start += direction;
737
top_start -= direction;
738
glEvalCoord2f((GLfloat) bottom_start / bottom_domain,
739
(GLfloat) bottom_z / bottom_domain);
742
top_cnt -= direction * tri_cnt;
743
bottom_cnt -= direction;
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)
753
GLint top_cnt, bottom_cnt, tri_cnt, k;
756
top_cnt = top_end - top_start;
757
direction = (top_cnt >= 0 ? 1 : -1);
758
bottom_cnt = bottom_end - bottom_start;
762
tri_cnt = top_cnt / bottom_cnt;
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);
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);
781
top_cnt -= direction * tri_cnt;
782
bottom_cnt -= direction;
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)
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);
797
tesselate_strip_s_line(top_start, top_end, top_z, bottom_start,
798
bottom_end, bottom_z, bottom_domain);
802
tesselate_bottom_left_corner(GLenum display_mode, GLfloat s_1, GLfloat t_1)
804
if (display_mode == GL_FILL) {
805
glBegin(GL_TRIANGLE_FAN);
807
glEvalCoord2f(s_1, 0.0);
808
glEvalCoord2f(0.0, 0.0);
809
glEvalCoord2f(0.0, t_1);
813
glEvalCoord2f(0.0, 0.0);
814
glEvalCoord2f(0.0, t_1);
815
glEvalCoord2f(0.0, 0.0);
817
glEvalCoord2f(0.0, 0.0);
818
glEvalCoord2f(s_1, 0.0);
824
tesselate_bottom_right_corner(GLenum display_mode, GLint v_top,
825
GLint v_bottom, GLfloat s_1, GLfloat t_1)
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);
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);
847
tesselate_top_left_corner(GLenum display_mode, GLint u_right, GLint u_left,
848
GLfloat s_1, GLfloat t_1)
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);
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);
870
tesselate_top_right_corner(GLenum display_mode, GLint u_left, GLint v_bottom,
871
GLint u_right, GLint v_top, GLfloat s_1,
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);
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);
893
/* do mesh mapping of Bezier */
895
nurbs_map_bezier(GLenum display_mode, GLint * sfactors, GLint * tfactors,
896
GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t)
898
GLint top, bottom, right, left;
902
top = *(tfactors + t * 3);
903
bottom = *(tfactors + t * 3 + 1);
905
else if (s == s_bezier_cnt - 1) {
906
top = *(tfactors + t * 3 + 2);
907
bottom = *(tfactors + t * 3);
910
top = bottom = *(tfactors + t * 3);
913
left = *(sfactors + s * 3 + 1);
914
right = *(sfactors + s * 3);
916
else if (t == t_bezier_cnt - 1) {
917
left = *(sfactors + s * 3);
918
right = *(sfactors + s * 3 + 2);
921
left = right = *(sfactors + s * 3);
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,
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,
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,
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,
948
tesselate_strip_t(display_mode, top - 1, 0, 1, bottom - 1, 0, 0,
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,
955
tesselate_strip_s(display_mode, left, 1, top - 1, right, 1, right,
959
else if (top == bottom) {
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,
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);
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,
975
tesselate_strip_s(display_mode, left, 0, top - 1, right, 0, 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,
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,
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,
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,
1007
tesselate_strip_s(display_mode, left - 1, 0, bottom - 1, right - 1,
1008
0, right, (GLfloat) right);
1013
/* draw NURBS surface in OUTLINE POLYGON mode */
1015
draw_polygon_mode(GLenum display_mode, GLUnurbsObj * nobj,
1016
new_ctrl_type * new_ctrl, GLint * sfactors,
1020
GLint t_bezier_cnt, s_bezier_cnt;
1021
GLboolean do_color, do_normal, do_texture;
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);
1032
do_color = GL_FALSE;
1033
if (new_ctrl->normal_ctrl) {
1034
glEnable(nobj->surface.normal.type);
1035
do_normal = GL_TRUE;
1038
do_normal = GL_FALSE;
1039
if (new_ctrl->texture_ctrl) {
1040
glEnable(nobj->surface.texture.type);
1041
do_texture = GL_TRUE;
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));
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));
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));
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));
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);
1089
/* draw NURBS surface in OUTLINE POLYGON mode */
1092
draw_patch_mode(GLenum display_mode, GLUnurbsObj * nobj,
1093
new_ctrl_type * new_ctrl, GLint * sfactors, GLint * tfactors)
1096
GLint t_bezier_cnt, s_bezier_cnt;
1097
GLboolean do_color, do_normal, do_texture;
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);
1108
do_color = GL_FALSE;
1109
if (new_ctrl->normal_ctrl) {
1110
glEnable(nobj->surface.normal.type);
1111
do_normal = GL_TRUE;
1114
do_normal = GL_FALSE;
1115
if (new_ctrl->texture_ctrl) {
1116
glEnable(nobj->surface.texture.type);
1117
do_texture = GL_TRUE;
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));
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));
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));
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));
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]);*/
1167
init_new_ctrl(new_ctrl_type * p)
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;
1177
augment_new_ctrl(GLUnurbsObj * nobj, new_ctrl_type * p)
1179
GLsizei offset_size;
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);
1195
(GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1196
call_user_error(nobj, GLU_OUT_OF_MEMORY);
1202
(GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1204
call_user_error(nobj, GLU_OUT_OF_MEMORY);
1209
(p->normal_offsets =
1210
(GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1212
call_user_error(nobj, GLU_OUT_OF_MEMORY);
1215
if (p->texture_ctrl)
1217
(p->texture_offsets =
1218
(GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) {
1220
call_user_error(nobj, GLU_OUT_OF_MEMORY);
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);
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);
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;
1254
/* main NURBS surface procedure */
1256
do_nurbs_surface(GLUnurbsObj * nobj)
1258
GLint *sfactors, *tfactors;
1259
new_ctrl_type new_ctrl;
1261
/* test user supplied data */
1262
if (test_nurbs_surfaces(nobj) != GLU_NO_ERROR)
1265
init_new_ctrl(&new_ctrl);
1267
if (convert_surfs(nobj, &new_ctrl) != GLU_NO_ERROR)
1269
if (augment_new_ctrl(nobj, &new_ctrl) != GLU_NO_ERROR)
1271
switch (nobj->sampling_method) {
1272
case GLU_PATH_LENGTH:
1273
if (glu_do_sampling_3D(nobj, &new_ctrl, &sfactors, &tfactors) !=
1275
free_new_ctrl(&new_ctrl);
1279
case GLU_DOMAIN_DISTANCE:
1280
if (glu_do_sampling_uv(nobj, &new_ctrl, &sfactors, &tfactors) !=
1282
free_new_ctrl(&new_ctrl);
1286
case GLU_PARAMETRIC_ERROR:
1287
if (glu_do_sampling_param_3D(nobj, &new_ctrl, &sfactors, &tfactors) !=
1289
free_new_ctrl(&new_ctrl);
1297
switch (nobj->display_mode) {
1299
/* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
1300
draw_polygon_mode(GL_FILL, nobj, &new_ctrl, sfactors, tfactors);
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);
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);
1312
abort(); /* TODO: is this OK? */
1316
free_new_ctrl(&new_ctrl);