Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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