Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: nurbsutl.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 "gluP.h"
36
#include "nurbs.h"
37
#endif
38
 
39
 
40
GLenum test_knot(GLint nknots, GLfloat * knot, GLint order)
41
{
42
   GLsizei i;
43
   GLint knot_mult;
44
   GLfloat tmp_knot;
45
 
46
   tmp_knot = knot[0];
47
   knot_mult = 1;
48
   for (i = 1; i < nknots; i++) {
49
      if (knot[i] < tmp_knot)
50
         return GLU_NURBS_ERROR4;
51
      if (fabs(tmp_knot - knot[i]) > EPSILON) {
52
         if (knot_mult > order)
53
            return GLU_NURBS_ERROR5;
54
         knot_mult = 1;
55
         tmp_knot = knot[i];
56
      }
57
      else
58
         ++knot_mult;
59
   }
60
   return GLU_NO_ERROR;
61
}
62
 
63
static int
64
/* qsort function */
65
#if defined(WIN32) && !defined(OPENSTEP)
66
  __cdecl
67
#endif
68
knot_sort(const void *a, const void *b)
69
{
70
   GLfloat x, y;
71
 
72
   x = *((GLfloat *) a);
73
   y = *((GLfloat *) b);
74
   if (fabs(x - y) < EPSILON)
75
      return 0;
76
   if (x > y)
77
      return 1;
78
   return -1;
79
}
80
 
81
/* insert into dest knot all values within the valid range from src knot */
82
/* that do not appear in dest */
83
void
84
collect_unified_knot(knot_str_type * dest, knot_str_type * src,
85
                     GLfloat maximal_min_knot, GLfloat minimal_max_knot)
86
{
87
   GLfloat *src_knot, *dest_knot;
88
   GLint src_t_min, src_t_max, dest_t_min, dest_t_max;
89
   GLint src_nknots, dest_nknots;
90
   GLint i, j, k, new_cnt;
91
   GLboolean not_found_flag;
92
 
93
   src_knot = src->unified_knot;
94
   dest_knot = dest->unified_knot;
95
   src_t_min = src->t_min;
96
   src_t_max = src->t_max;
97
   dest_t_min = dest->t_min;
98
   dest_t_max = dest->t_max;
99
   src_nknots = src->unified_nknots;
100
   dest_nknots = dest->unified_nknots;
101
 
102
   k = new_cnt = dest_nknots;
103
   for (i = src_t_min; i <= src_t_max; i++)
104
      if (src_knot[i] - maximal_min_knot > -EPSILON &&
105
          src_knot[i] - minimal_max_knot < EPSILON) {
106
         not_found_flag = GL_TRUE;
107
         for (j = dest_t_min; j <= dest_t_max; j++)
108
            if (fabs(dest_knot[j] - src_knot[i]) < EPSILON) {
109
               not_found_flag = GL_FALSE;
110
               break;
111
            }
112
         if (not_found_flag) {
113
            /* knot from src is not in dest - add this knot to dest */
114
            dest_knot[k++] = src_knot[i];
115
            ++new_cnt;
116
            ++(dest->t_max);    /* the valid range widens */
117
            ++(dest->delta_nknots);     /* increment the extra knot value counter */
118
         }
119
      }
120
   dest->unified_nknots = new_cnt;
121
   qsort((void *) dest_knot, (size_t) new_cnt, (size_t) sizeof(GLfloat),
122
         &knot_sort);
123
}
124
 
125
/* basing on the new common knot range for all attributes set */
126
/* t_min and t_max values for each knot - they will be used later on */
127
/* by explode_knot() and calc_new_ctrl_pts */
128
static void
129
set_new_t_min_t_max(knot_str_type * geom_knot, knot_str_type * color_knot,
130
                    knot_str_type * normal_knot, knot_str_type * texture_knot,
131
                    GLfloat maximal_min_knot, GLfloat minimal_max_knot)
132
{
133
   GLuint t_min = 0, t_max = 0, cnt = 0;
134
 
135
   if (minimal_max_knot - maximal_min_knot < EPSILON) {
136
      /* knot common range empty */
137
      geom_knot->t_min = geom_knot->t_max = 0;
138
      color_knot->t_min = color_knot->t_max = 0;
139
      normal_knot->t_min = normal_knot->t_max = 0;
140
      texture_knot->t_min = texture_knot->t_max = 0;
141
   }
142
   else {
143
      if (geom_knot->unified_knot != NULL) {
144
         cnt = geom_knot->unified_nknots;
145
         for (t_min = 0; t_min < cnt; t_min++)
146
            if (fabs((geom_knot->unified_knot)[t_min] - maximal_min_knot) <
147
                EPSILON) break;
148
         for (t_max = cnt - 1; t_max; t_max--)
149
            if (fabs((geom_knot->unified_knot)[t_max] - minimal_max_knot) <
150
                EPSILON) break;
151
      }
152
      else if (geom_knot->nknots) {
153
         cnt = geom_knot->nknots;
154
         for (t_min = 0; t_min < cnt; t_min++)
155
            if (fabs((geom_knot->knot)[t_min] - maximal_min_knot) < EPSILON)
156
               break;
157
         for (t_max = cnt - 1; t_max; t_max--)
158
            if (fabs((geom_knot->knot)[t_max] - minimal_max_knot) < EPSILON)
159
               break;
160
      }
161
      geom_knot->t_min = t_min;
162
      geom_knot->t_max = t_max;
163
      if (color_knot->unified_knot != NULL) {
164
         cnt = color_knot->unified_nknots;
165
         for (t_min = 0; t_min < cnt; t_min++)
166
            if (fabs((color_knot->unified_knot)[t_min] - maximal_min_knot) <
167
                EPSILON) break;
168
         for (t_max = cnt - 1; t_max; t_max--)
169
            if (fabs((color_knot->unified_knot)[t_max] - minimal_max_knot) <
170
                EPSILON) break;
171
         color_knot->t_min = t_min;
172
         color_knot->t_max = t_max;
173
      }
174
      if (normal_knot->unified_knot != NULL) {
175
         cnt = normal_knot->unified_nknots;
176
         for (t_min = 0; t_min < cnt; t_min++)
177
            if (fabs((normal_knot->unified_knot)[t_min] - maximal_min_knot) <
178
                EPSILON) break;
179
         for (t_max = cnt - 1; t_max; t_max--)
180
            if (fabs((normal_knot->unified_knot)[t_max] - minimal_max_knot) <
181
                EPSILON) break;
182
         normal_knot->t_min = t_min;
183
         normal_knot->t_max = t_max;
184
      }
185
      if (texture_knot->unified_knot != NULL) {
186
         cnt = texture_knot->unified_nknots;
187
         for (t_min = 0; t_min < cnt; t_min++)
188
            if (fabs((texture_knot->unified_knot)[t_min] - maximal_min_knot)
189
                < EPSILON)
190
               break;
191
         for (t_max = cnt - 1; t_max; t_max--)
192
            if (fabs((texture_knot->unified_knot)[t_max] - minimal_max_knot)
193
                < EPSILON)
194
               break;
195
         texture_knot->t_min = t_min;
196
         texture_knot->t_max = t_max;
197
      }
198
   }
199
}
200
 
201
/* modify all knot valid ranges in such a way that all have the same */
202
/* range, common to all knots */
203
/* do this by knot insertion */
204
GLenum
205
select_knot_working_range(GLUnurbsObj * nobj, knot_str_type * geom_knot,
206
                          knot_str_type * color_knot,
207
                          knot_str_type * normal_knot,
208
                          knot_str_type * texture_knot)
209
{
210
   GLint max_nknots;
211
   GLfloat maximal_min_knot, minimal_max_knot;
212
   GLint i;
213
 
214
   /* find the maximum modified knot length */
215
   max_nknots = geom_knot->nknots;
216
   if (color_knot->unified_knot)
217
      max_nknots += color_knot->nknots;
218
   if (normal_knot->unified_knot)
219
      max_nknots += normal_knot->nknots;
220
   if (texture_knot->unified_knot)
221
      max_nknots += texture_knot->nknots;
222
   maximal_min_knot = (geom_knot->knot)[geom_knot->t_min];
223
   minimal_max_knot = (geom_knot->knot)[geom_knot->t_max];
224
   /* any attirb data ? */
225
   if (max_nknots != geom_knot->nknots) {
226
      /* allocate space for the unified knots */
227
      if ((geom_knot->unified_knot =
228
           (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) {
229
         call_user_error(nobj, GLU_OUT_OF_MEMORY);
230
         return GLU_ERROR;
231
      }
232
      /* copy the original knot to the unified one */
233
      geom_knot->unified_nknots = geom_knot->nknots;
234
      for (i = 0; i < geom_knot->nknots; i++)
235
         (geom_knot->unified_knot)[i] = (geom_knot->knot)[i];
236
      if (color_knot->unified_knot) {
237
         if ((color_knot->knot)[color_knot->t_min] - maximal_min_knot >
238
             EPSILON)
239
               maximal_min_knot = (color_knot->knot)[color_knot->t_min];
240
         if (minimal_max_knot - (color_knot->knot)[color_knot->t_max] >
241
             EPSILON)
242
               minimal_max_knot = (color_knot->knot)[color_knot->t_max];
243
         if ((color_knot->unified_knot =
244
              (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) {
245
            free(geom_knot->unified_knot);
246
            call_user_error(nobj, GLU_OUT_OF_MEMORY);
247
            return GLU_ERROR;
248
         }
249
         /* copy the original knot to the unified one */
250
         color_knot->unified_nknots = color_knot->nknots;
251
         for (i = 0; i < color_knot->nknots; i++)
252
            (color_knot->unified_knot)[i] = (color_knot->knot)[i];
253
      }
254
      if (normal_knot->unified_knot) {
255
         if ((normal_knot->knot)[normal_knot->t_min] - maximal_min_knot >
256
             EPSILON)
257
               maximal_min_knot = (normal_knot->knot)[normal_knot->t_min];
258
         if (minimal_max_knot - (normal_knot->knot)[normal_knot->t_max] >
259
             EPSILON)
260
               minimal_max_knot = (normal_knot->knot)[normal_knot->t_max];
261
         if ((normal_knot->unified_knot =
262
              (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) {
263
            free(geom_knot->unified_knot);
264
            free(color_knot->unified_knot);
265
            call_user_error(nobj, GLU_OUT_OF_MEMORY);
266
            return GLU_ERROR;
267
         }
268
         /* copy the original knot to the unified one */
269
         normal_knot->unified_nknots = normal_knot->nknots;
270
         for (i = 0; i < normal_knot->nknots; i++)
271
            (normal_knot->unified_knot)[i] = (normal_knot->knot)[i];
272
      }
273
      if (texture_knot->unified_knot) {
274
         if ((texture_knot->knot)[texture_knot->t_min] - maximal_min_knot >
275
             EPSILON)
276
               maximal_min_knot = (texture_knot->knot)[texture_knot->t_min];
277
         if (minimal_max_knot - (texture_knot->knot)[texture_knot->t_max] >
278
             EPSILON)
279
               minimal_max_knot = (texture_knot->knot)[texture_knot->t_max];
280
         if ((texture_knot->unified_knot =
281
              (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) {
282
            free(geom_knot->unified_knot);
283
            free(color_knot->unified_knot);
284
            free(normal_knot->unified_knot);
285
            call_user_error(nobj, GLU_OUT_OF_MEMORY);
286
            return GLU_ERROR;
287
         }
288
         /* copy the original knot to the unified one */
289
         texture_knot->unified_nknots = texture_knot->nknots;
290
         for (i = 0; i < texture_knot->nknots; i++)
291
            (texture_knot->unified_knot)[i] = (texture_knot->knot)[i];
292
      }
293
      /* work on the geometry knot with all additional knot values */
294
      /* appearing in attirbutive knots */
295
      if (minimal_max_knot - maximal_min_knot < EPSILON) {
296
         /* empty working range */
297
         geom_knot->unified_nknots = 0;
298
         color_knot->unified_nknots = 0;
299
         normal_knot->unified_nknots = 0;
300
         texture_knot->unified_nknots = 0;
301
      }
302
      else {
303
         if (color_knot->unified_knot)
304
            collect_unified_knot(geom_knot, color_knot, maximal_min_knot,
305
                                 minimal_max_knot);
306
         if (normal_knot->unified_knot)
307
            collect_unified_knot(geom_knot, normal_knot, maximal_min_knot,
308
                                 minimal_max_knot);
309
         if (texture_knot->unified_knot)
310
            collect_unified_knot(geom_knot, texture_knot, maximal_min_knot,
311
                                 minimal_max_knot);
312
         /* since we have now built the "unified" geometry knot */
313
         /* add same knot values to all attributive knots */
314
         if (color_knot->unified_knot)
315
            collect_unified_knot(color_knot, geom_knot, maximal_min_knot,
316
                                 minimal_max_knot);
317
         if (normal_knot->unified_knot)
318
            collect_unified_knot(normal_knot, geom_knot, maximal_min_knot,
319
                                 minimal_max_knot);
320
         if (texture_knot->unified_knot)
321
            collect_unified_knot(texture_knot, geom_knot, maximal_min_knot,
322
                                 minimal_max_knot);
323
      }
324
   }
325
   set_new_t_min_t_max(geom_knot, color_knot, normal_knot, texture_knot,
326
                       maximal_min_knot, minimal_max_knot);
327
   return GLU_NO_ERROR;
328
}
329
 
330
void
331
free_unified_knots(knot_str_type * geom_knot, knot_str_type * color_knot,
332
                   knot_str_type * normal_knot, knot_str_type * texture_knot)
333
{
334
   if (geom_knot->unified_knot)
335
      free(geom_knot->unified_knot);
336
   if (color_knot->unified_knot)
337
      free(color_knot->unified_knot);
338
   if (normal_knot->unified_knot)
339
      free(normal_knot->unified_knot);
340
   if (texture_knot->unified_knot)
341
      free(texture_knot->unified_knot);
342
}
343
 
344
GLenum explode_knot(knot_str_type * the_knot)
345
{
346
   GLfloat *knot, *new_knot;
347
   GLint nknots, n_new_knots = 0;
348
   GLint t_min, t_max;
349
   GLint ord;
350
   GLsizei i, j, k;
351
   GLfloat tmp_float;
352
 
353
   if (the_knot->unified_knot) {
354
      knot = the_knot->unified_knot;
355
      nknots = the_knot->unified_nknots;
356
   }
357
   else {
358
      knot = the_knot->knot;
359
      nknots = the_knot->nknots;
360
   }
361
   ord = the_knot->order;
362
   t_min = the_knot->t_min;
363
   t_max = the_knot->t_max;
364
 
365
   for (i = t_min; i <= t_max;) {
366
      tmp_float = knot[i];
367
      for (j = 0; j < ord && (i + j) <= t_max; j++)
368
         if (fabs(tmp_float - knot[i + j]) > EPSILON)
369
            break;
370
      n_new_knots += ord - j;
371
      i += j;
372
   }
373
   /* alloc space for new_knot */
374
   if (
375
       (new_knot =
376
        (GLfloat *) malloc(sizeof(GLfloat) * (nknots + n_new_knots + 1))) == NULL) {
377
      return GLU_OUT_OF_MEMORY;
378
   }
379
   /* fill in new knot */
380
   for (j = 0; j < t_min; j++)
381
      new_knot[j] = knot[j];
382
   for (i = j; i <= t_max; i++) {
383
      tmp_float = knot[i];
384
      for (k = 0; k < ord; k++) {
385
         new_knot[j++] = knot[i];
386
         if (tmp_float == knot[i + 1])
387
            i++;
388
      }
389
   }
390
   for (i = t_max + 1; i < (int) nknots; i++)
391
      new_knot[j++] = knot[i];
392
   /* fill in the knot structure */
393
   the_knot->new_knot = new_knot;
394
   the_knot->delta_nknots += n_new_knots;
395
   the_knot->t_max += n_new_knots;
396
   return GLU_NO_ERROR;
397
}
398
 
399
GLenum calc_alphas(knot_str_type * the_knot)
400
{
401
   GLfloat tmp_float;
402
   int i, j, k, m, n;
403
   int order;
404
   GLfloat *alpha, *alpha_new, *tmp_alpha;
405
   GLfloat denom;
406
   GLfloat *knot, *new_knot;
407
 
408
 
409
   knot = the_knot->knot;
410
   order = the_knot->order;
411
   new_knot = the_knot->new_knot;
412
   n = the_knot->nknots - the_knot->order;
413
   m = n + the_knot->delta_nknots;
414
   if ((alpha = (GLfloat *) malloc(sizeof(GLfloat) * n * m)) == NULL) {
415
      return GLU_OUT_OF_MEMORY;
416
   }
417
   if ((alpha_new = (GLfloat *) malloc(sizeof(GLfloat) * n * m)) == NULL) {
418
      free(alpha);
419
      return GLU_OUT_OF_MEMORY;
420
   }
421
   for (j = 0; j < m; j++) {
422
      for (i = 0; i < n; i++) {
423
         if ((knot[i] <= new_knot[j]) && (new_knot[j] < knot[i + 1]))
424
            tmp_float = 1.0;
425
         else
426
            tmp_float = 0.0;
427
         alpha[i + j * n] = tmp_float;
428
      }
429
   }
430
   for (k = 1; k < order; k++) {
431
      for (j = 0; j < m; j++)
432
         for (i = 0; i < n; i++) {
433
            denom = knot[i + k] - knot[i];
434
            if (fabs(denom) < EPSILON)
435
               tmp_float = 0.0;
436
            else
437
               tmp_float = (new_knot[j + k] - knot[i]) / denom *
438
                  alpha[i + j * n];
439
            denom = knot[i + k + 1] - knot[i + 1];
440
            if (fabs(denom) > EPSILON)
441
               tmp_float += (knot[i + k + 1] - new_knot[j + k]) / denom *
442
                  alpha[(i + 1) + j * n];
443
            alpha_new[i + j * n] = tmp_float;
444
         }
445
      tmp_alpha = alpha_new;
446
      alpha_new = alpha;
447
      alpha = tmp_alpha;
448
   }
449
   the_knot->alpha = alpha;
450
   free(alpha_new);
451
   return GLU_NO_ERROR;
452
}
453
 
454
GLenum
455
calc_new_ctrl_pts(GLfloat * ctrl, GLint stride, knot_str_type * the_knot,
456
                  GLint dim, GLfloat ** new_ctrl, GLint * ncontrol)
457
{
458
   GLsizei i, j, k, l, m, n;
459
   GLsizei index1, index2;
460
   GLfloat *alpha;
461
   GLfloat *new_knot;
462
 
463
   new_knot = the_knot->new_knot;
464
   n = the_knot->nknots - the_knot->order;
465
   alpha = the_knot->alpha;
466
 
467
   m = the_knot->t_max + 1 - the_knot->t_min - the_knot->order;
468
   k = the_knot->t_min;
469
   /* allocate space for new control points */
470
   if ((*new_ctrl = (GLfloat *) malloc(sizeof(GLfloat) * dim * m)) == NULL) {
471
      return GLU_OUT_OF_MEMORY;
472
   }
473
   for (j = 0; j < m; j++) {
474
      for (l = 0; l < dim; l++)
475
         (*new_ctrl)[j * dim + l] = 0.0;
476
      for (i = 0; i < n; i++) {
477
         index1 = i + (j + k) * n;
478
         index2 = i * stride;
479
         for (l = 0; l < dim; l++)
480
            (*new_ctrl)[j * dim + l] += alpha[index1] * ctrl[index2 + l];
481
      }
482
   }
483
   *ncontrol = (GLint) m;
484
   return GLU_NO_ERROR;
485
}
486
 
487
static GLint
488
calc_factor(GLfloat * pts, GLint order, GLint indx, GLint stride,
489
            GLfloat tolerance, GLint dim)
490
{
491
   GLdouble model[16], proj[16];
492
   GLint viewport[4];
493
   GLdouble x, y, z, w, winx1, winy1, winz, winx2, winy2;
494
   GLint i;
495
   GLdouble len, dx, dy;
496
 
497
   glGetDoublev(GL_MODELVIEW_MATRIX, model);
498
   glGetDoublev(GL_PROJECTION_MATRIX, proj);
499
   glGetIntegerv(GL_VIEWPORT, viewport);
500
   if (dim == 4) {
501
      w = (GLdouble) pts[indx + 3];
502
      x = (GLdouble) pts[indx] / w;
503
      y = (GLdouble) pts[indx + 1] / w;
504
      z = (GLdouble) pts[indx + 2] / w;
505
      gluProject(x, y, z, model, proj, viewport, &winx1, &winy1, &winz);
506
      len = 0.0;
507
      for (i = 1; i < order; i++) {
508
         w = (GLdouble) pts[indx + i * stride + 3];
509
         x = (GLdouble) pts[indx + i * stride] / w;
510
         y = (GLdouble) pts[indx + i * stride + 1] / w;
511
         z = (GLdouble) pts[indx + i * stride + 2] / w;
512
         if (gluProject
513
             (x, y, z, model, proj, viewport, &winx2, &winy2, &winz)) {
514
            dx = winx2 - winx1;
515
            dy = winy2 - winy1;
516
            len += sqrt(dx * dx + dy * dy);
517
         }
518
         winx1 = winx2;
519
         winy1 = winy2;
520
      }
521
   }
522
   else {
523
      x = (GLdouble) pts[indx];
524
      y = (GLdouble) pts[indx + 1];
525
      if (dim == 2)
526
         z = 0.0;
527
      else
528
         z = (GLdouble) pts[indx + 2];
529
      gluProject(x, y, z, model, proj, viewport, &winx1, &winy1, &winz);
530
      len = 0.0;
531
      for (i = 1; i < order; i++) {
532
         x = (GLdouble) pts[indx + i * stride];
533
         y = (GLdouble) pts[indx + i * stride + 1];
534
         if (dim == 2)
535
            z = 0.0;
536
         else
537
            z = (GLdouble) pts[indx + i * stride + 2];
538
         if (gluProject
539
             (x, y, z, model, proj, viewport, &winx2, &winy2, &winz)) {
540
            dx = winx2 - winx1;
541
            dy = winy2 - winy1;
542
            len += sqrt(dx * dx + dy * dy);
543
         }
544
         winx1 = winx2;
545
         winy1 = winy2;
546
      }
547
   }
548
   len /= tolerance;
549
   return ((GLint) len + 1);
550
}
551
 
552
/* we can't use the Mesa evaluators - no way to get the point coords */
553
/* so we use our own Bezier point calculus routines */
554
/* because I'm lazy, I reuse the ones from eval.c */
555
 
556
static void
557
bezier_curve(GLfloat * cp, GLfloat * out, GLfloat t,
558
             GLuint dim, GLuint order, GLint offset)
559
{
560
   GLfloat s, powert;
561
   GLuint i, k, bincoeff;
562
 
563
   if (order >= 2) {
564
      bincoeff = order - 1;
565
      s = 1.0 - t;
566
 
567
      for (k = 0; k < dim; k++)
568
         out[k] = s * cp[k] + bincoeff * t * cp[offset + k];
569
 
570
      for (i = 2, cp += 2 * offset, powert = t * t; i < order;
571
           i++, powert *= t, cp += offset) {
572
         bincoeff *= order - i;
573
         bincoeff /= i;
574
 
575
         for (k = 0; k < dim; k++)
576
            out[k] = s * out[k] + bincoeff * powert * cp[k];
577
      }
578
   }
579
   else {                       /* order=1 -> constant curve */
580
 
581
      for (k = 0; k < dim; k++)
582
         out[k] = cp[k];
583
   }
584
}
585
 
586
static GLint
587
calc_parametric_factor(GLfloat * pts, GLint order, GLint indx, GLint stride,
588
                       GLfloat tolerance, GLint dim)
589
{
590
   GLdouble model[16], proj[16];
591
   GLint viewport[4];
592
   GLdouble x, y, z, w, x1, y1, z1, x2, y2, z2, x3, y3, z3;
593
   GLint i;
594
   GLint P;
595
   GLfloat bez_pt[4];
596
   GLdouble len = 0.0, tmp, z_med;
597
 
598
   P = 2 * (order + 2);
599
   glGetDoublev(GL_MODELVIEW_MATRIX, model);
600
   glGetDoublev(GL_PROJECTION_MATRIX, proj);
601
   glGetIntegerv(GL_VIEWPORT, viewport);
602
   z_med = (viewport[2] + viewport[3]) * 0.5;
603
   switch (dim) {
604
   case 4:
605
      for (i = 1; i < P; i++) {
606
         bezier_curve(pts + indx, bez_pt, (GLfloat) i / (GLfloat) P, 4,
607
                      order, stride);
608
         w = (GLdouble) bez_pt[3];
609
         x = (GLdouble) bez_pt[0] / w;
610
         y = (GLdouble) bez_pt[1] / w;
611
         z = (GLdouble) bez_pt[2] / w;
612
         gluProject(x, y, z, model, proj, viewport, &x3, &y3, &z3);
613
         z3 *= z_med;
614
         bezier_curve(pts + indx, bez_pt, (GLfloat) (i - 1) / (GLfloat) P, 4,
615
                      order, stride);
616
         w = (GLdouble) bez_pt[3];
617
         x = (GLdouble) bez_pt[0] / w;
618
         y = (GLdouble) bez_pt[1] / w;
619
         z = (GLdouble) bez_pt[2] / w;
620
         gluProject(x, y, z, model, proj, viewport, &x1, &y1, &z1);
621
         z1 *= z_med;
622
         bezier_curve(pts + indx, bez_pt, (GLfloat) (i + 1) / (GLfloat) P, 4,
623
                      order, stride);
624
         w = (GLdouble) bez_pt[3];
625
         x = (GLdouble) bez_pt[0] / w;
626
         y = (GLdouble) bez_pt[1] / w;
627
         z = (GLdouble) bez_pt[2] / w;
628
         gluProject(x, y, z, model, proj, viewport, &x2, &y2, &z2);
629
         z2 *= z_med;
630
         /* calc distance between point (x3,y3,z3) and line segment */
631
         /* <x1,y1,z1><x2,y2,z2> */
632
         x = x2 - x1;
633
         y = y2 - y1;
634
         z = z2 - z1;
635
         tmp = sqrt(x * x + y * y + z * z);
636
         x /= tmp;
637
         y /= tmp;
638
         z /= tmp;
639
         tmp = x3 * x + y3 * y + z3 * z - x1 * x - y1 * y - z1 * z;
640
         x = x1 + x * tmp - x3;
641
         y = y1 + y * tmp - y3;
642
         z = z1 + z * tmp - z3;
643
         tmp = sqrt(x * x + y * y + z * z);
644
         if (tmp > len)
645
            len = tmp;
646
      }
647
      break;
648
   case 3:
649
      for (i = 1; i < P; i++) {
650
         bezier_curve(pts + indx, bez_pt, (GLfloat) i / (GLfloat) P, 3,
651
                      order, stride);
652
         x = (GLdouble) bez_pt[0];
653
         y = (GLdouble) bez_pt[1];
654
         z = (GLdouble) bez_pt[2];
655
         gluProject(x, y, z, model, proj, viewport, &x3, &y3, &z3);
656
         z3 *= z_med;
657
         bezier_curve(pts + indx, bez_pt, (GLfloat) (i - 1) / (GLfloat) P, 3,
658
                      order, stride);
659
         x = (GLdouble) bez_pt[0];
660
         y = (GLdouble) bez_pt[1];
661
         z = (GLdouble) bez_pt[2];
662
         gluProject(x, y, z, model, proj, viewport, &x1, &y1, &z1);
663
         z1 *= z_med;
664
         bezier_curve(pts + indx, bez_pt, (GLfloat) (i + 1) / (GLfloat) P, 3,
665
                      order, stride);
666
         x = (GLdouble) bez_pt[0];
667
         y = (GLdouble) bez_pt[1];
668
         z = (GLdouble) bez_pt[2];
669
         gluProject(x, y, z, model, proj, viewport, &x2, &y2, &z2);
670
         z2 *= z_med;
671
         /* calc distance between point (x3,y3,z3) and line segment */
672
         /* <x1,y1,z1><x2,y2,z2> */
673
         x = x2 - x1;
674
         y = y2 - y1;
675
         z = z2 - z1;
676
         tmp = sqrt(x * x + y * y + z * z);
677
         x /= tmp;
678
         y /= tmp;
679
         z /= tmp;
680
         tmp = x3 * x + y3 * y + z3 * z - x1 * x - y1 * y - z1 * z;
681
         x = x1 + x * tmp - x3;
682
         y = y1 + y * tmp - y3;
683
         z = z1 + z * tmp - z3;
684
         tmp = sqrt(x * x + y * y + z * z);
685
         if (tmp > len)
686
            len = tmp;
687
      }
688
      break;
689
   case 2:
690
      for (i = 1; i < P; i++) {
691
         bezier_curve(pts + indx, bez_pt, (GLfloat) i / (GLfloat) P, 2,
692
                      order, stride);
693
         x = (GLdouble) bez_pt[0];
694
         y = (GLdouble) bez_pt[1];
695
         z = 0.0;
696
         gluProject(x, y, z, model, proj, viewport, &x3, &y3, &z3);
697
         z3 *= z_med;
698
         bezier_curve(pts + indx, bez_pt, (GLfloat) (i - 1) / (GLfloat) P, 2,
699
                      order, stride);
700
         x = (GLdouble) bez_pt[0];
701
         y = (GLdouble) bez_pt[1];
702
         z = 0.0;
703
         gluProject(x, y, z, model, proj, viewport, &x1, &y1, &z1);
704
         z1 *= z_med;
705
         bezier_curve(pts + indx, bez_pt, (GLfloat) (i + 1) / (GLfloat) P, 2,
706
                      order, stride);
707
         x = (GLdouble) bez_pt[0];
708
         y = (GLdouble) bez_pt[1];
709
         z = 0.0;
710
         gluProject(x, y, z, model, proj, viewport, &x2, &y2, &z2);
711
         z2 *= z_med;
712
         /* calc distance between point (x3,y3,z3) and line segment */
713
         /* <x1,y1,z1><x2,y2,z2> */
714
         x = x2 - x1;
715
         y = y2 - y1;
716
         z = z2 - z1;
717
         tmp = sqrt(x * x + y * y + z * z);
718
         x /= tmp;
719
         y /= tmp;
720
         z /= tmp;
721
         tmp = x3 * x + y3 * y + z3 * z - x1 * x - y1 * y - z1 * z;
722
         x = x1 + x * tmp - x3;
723
         y = y1 + y * tmp - y3;
724
         z = z1 + z * tmp - z3;
725
         tmp = sqrt(x * x + y * y + z * z);
726
         if (tmp > len)
727
            len = tmp;
728
      }
729
      break;
730
 
731
   }
732
   if (len < tolerance)
733
      return (order);
734
   else
735
      return (GLint) (sqrt(len / tolerance) * (order + 2) + 1);
736
}
737
 
738
static GLenum
739
calc_sampling_3D(new_ctrl_type * new_ctrl, GLfloat tolerance, GLint dim,
740
                 GLint uorder, GLint vorder, GLint ** ufactors,
741
                 GLint ** vfactors)
742
{
743
   GLfloat *ctrl;
744
   GLint tmp_factor1, tmp_factor2;
745
   GLint ufactor_cnt, vfactor_cnt;
746
   GLint offset1, offset2, offset3;
747
   GLint i, j;
748
 
749
   ufactor_cnt = new_ctrl->s_bezier_cnt;
750
   vfactor_cnt = new_ctrl->t_bezier_cnt;
751
   if ((*ufactors = (GLint *) malloc(sizeof(GLint) * ufactor_cnt * 3))
752
       == NULL) {
753
      return GLU_OUT_OF_MEMORY;
754
   }
755
   if ((*vfactors = (GLint *) malloc(sizeof(GLint) * vfactor_cnt * 3))
756
       == NULL) {
757
      free(*ufactors);
758
      return GLU_OUT_OF_MEMORY;
759
   }
760
   ctrl = new_ctrl->geom_ctrl;
761
   offset1 = new_ctrl->geom_t_stride * vorder;
762
   offset2 = new_ctrl->geom_s_stride * uorder;
763
   for (j = 0; j < vfactor_cnt; j++) {
764
      *(*vfactors + j * 3 + 1) = tmp_factor1 = calc_factor(ctrl, vorder,
765
                                                           j * offset1, dim,
766
                                                           tolerance, dim);
767
      /* loop ufactor_cnt-1 times */
768
      for (i = 1; i < ufactor_cnt; i++) {
769
         tmp_factor2 = calc_factor(ctrl, vorder,
770
                                   j * offset1 + i * offset2, dim, tolerance,
771
                                   dim);
772
         if (tmp_factor2 > tmp_factor1)
773
            tmp_factor1 = tmp_factor2;
774
      }
775
      /* last time for the opposite edge */
776
      *(*vfactors + j * 3 + 2) = tmp_factor2 = calc_factor(ctrl, vorder,
777
                                                           j * offset1 +
778
                                                           i * offset2 -
779
                                                           new_ctrl->
780
                                                           geom_s_stride, dim,
781
                                                           tolerance, dim);
782
      if (tmp_factor2 > tmp_factor1)
783
         *(*vfactors + j * 3) = tmp_factor2;
784
      else
785
         *(*vfactors + j * 3) = tmp_factor1;
786
   }
787
   offset3 = new_ctrl->geom_s_stride;
788
   offset2 = new_ctrl->geom_s_stride * uorder;
789
   for (j = 0; j < ufactor_cnt; j++) {
790
      *(*ufactors + j * 3 + 1) = tmp_factor1 = calc_factor(ctrl, uorder,
791
                                                           j * offset2,
792
                                                           offset3, tolerance,
793
                                                           dim);
794
      /* loop vfactor_cnt-1 times */
795
      for (i = 1; i < vfactor_cnt; i++) {
796
         tmp_factor2 = calc_factor(ctrl, uorder,
797
                                   j * offset2 + i * offset1, offset3,
798
                                   tolerance, dim);
799
         if (tmp_factor2 > tmp_factor1)
800
            tmp_factor1 = tmp_factor2;
801
      }
802
      /* last time for the opposite edge */
803
      *(*ufactors + j * 3 + 2) = tmp_factor2 = calc_factor(ctrl, uorder,
804
                                                           j * offset2 +
805
                                                           i * offset1 -
806
                                                           new_ctrl->
807
                                                           geom_t_stride,
808
                                                           offset3, tolerance,
809
                                                           dim);
810
      if (tmp_factor2 > tmp_factor1)
811
         *(*ufactors + j * 3) = tmp_factor2;
812
      else
813
         *(*ufactors + j * 3) = tmp_factor1;
814
   }
815
   return GL_NO_ERROR;
816
}
817
 
818
static GLenum
819
calc_sampling_param_3D(new_ctrl_type * new_ctrl, GLfloat tolerance, GLint dim,
820
                       GLint uorder, GLint vorder, GLint ** ufactors,
821
                       GLint ** vfactors)
822
{
823
   GLfloat *ctrl;
824
   GLint tmp_factor1, tmp_factor2;
825
   GLint ufactor_cnt, vfactor_cnt;
826
   GLint offset1, offset2, offset3;
827
   GLint i, j;
828
 
829
   ufactor_cnt = new_ctrl->s_bezier_cnt;
830
   vfactor_cnt = new_ctrl->t_bezier_cnt;
831
   if ((*ufactors = (GLint *) malloc(sizeof(GLint) * ufactor_cnt * 3))
832
       == NULL) {
833
      return GLU_OUT_OF_MEMORY;
834
   }
835
   if ((*vfactors = (GLint *) malloc(sizeof(GLint) * vfactor_cnt * 3))
836
       == NULL) {
837
      free(*ufactors);
838
      return GLU_OUT_OF_MEMORY;
839
   }
840
   ctrl = new_ctrl->geom_ctrl;
841
   offset1 = new_ctrl->geom_t_stride * vorder;
842
   offset2 = new_ctrl->geom_s_stride * uorder;
843
   for (j = 0; j < vfactor_cnt; j++) {
844
      *(*vfactors + j * 3 + 1) = tmp_factor1 =
845
         calc_parametric_factor(ctrl, vorder, j * offset1, dim, tolerance,
846
                                dim);
847
      /* loop ufactor_cnt-1 times */
848
      for (i = 1; i < ufactor_cnt; i++) {
849
         tmp_factor2 = calc_parametric_factor(ctrl, vorder,
850
                                              j * offset1 + i * offset2, dim,
851
                                              tolerance, dim);
852
         if (tmp_factor2 > tmp_factor1)
853
            tmp_factor1 = tmp_factor2;
854
      }
855
      /* last time for the opposite edge */
856
      *(*vfactors + j * 3 + 2) = tmp_factor2 =
857
         calc_parametric_factor(ctrl, vorder,
858
                                j * offset1 + i * offset2 -
859
                                new_ctrl->geom_s_stride, dim, tolerance, dim);
860
      if (tmp_factor2 > tmp_factor1)
861
         *(*vfactors + j * 3) = tmp_factor2;
862
      else
863
         *(*vfactors + j * 3) = tmp_factor1;
864
   }
865
   offset3 = new_ctrl->geom_s_stride;
866
   offset2 = new_ctrl->geom_s_stride * uorder;
867
   for (j = 0; j < ufactor_cnt; j++) {
868
      *(*ufactors + j * 3 + 1) = tmp_factor1 =
869
         calc_parametric_factor(ctrl, uorder, j * offset2, offset3, tolerance,
870
                                dim);
871
      /* loop vfactor_cnt-1 times */
872
      for (i = 1; i < vfactor_cnt; i++) {
873
         tmp_factor2 = calc_parametric_factor(ctrl, uorder,
874
                                              j * offset2 + i * offset1,
875
                                              offset3, tolerance, dim);
876
         if (tmp_factor2 > tmp_factor1)
877
            tmp_factor1 = tmp_factor2;
878
      }
879
      /* last time for the opposite edge */
880
      *(*ufactors + j * 3 + 2) = tmp_factor2 =
881
         calc_parametric_factor(ctrl, uorder,
882
                                j * offset2 + i * offset1 -
883
                                new_ctrl->geom_t_stride, offset3, tolerance,
884
                                dim);
885
      if (tmp_factor2 > tmp_factor1)
886
         *(*ufactors + j * 3) = tmp_factor2;
887
      else
888
         *(*ufactors + j * 3) = tmp_factor1;
889
   }
890
   return GL_NO_ERROR;
891
}
892
 
893
static GLenum
894
calc_sampling_2D(GLfloat * ctrl, GLint cnt, GLint order,
895
                 GLfloat tolerance, GLint dim, GLint ** factors)
896
{
897
   GLint factor_cnt;
898
   GLint tmp_factor;
899
   GLint offset;
900
   GLint i;
901
 
902
   factor_cnt = cnt / order;
903
   if ((*factors = (GLint *) malloc(sizeof(GLint) * factor_cnt)) == NULL) {
904
      return GLU_OUT_OF_MEMORY;
905
   }
906
   offset = order * dim;
907
   for (i = 0; i < factor_cnt; i++) {
908
      tmp_factor = calc_factor(ctrl, order, i * offset, dim, tolerance, dim);
909
      if (tmp_factor == 0)
910
         (*factors)[i] = 1;
911
      else
912
         (*factors)[i] = tmp_factor;
913
   }
914
   return GL_NO_ERROR;
915
}
916
 
917
static void
918
set_sampling_and_culling(GLUnurbsObj * nobj)
919
{
920
   if (nobj->auto_load_matrix == GL_FALSE) {
921
      GLint i;
922
      GLfloat m[4];
923
 
924
      glPushAttrib((GLbitfield) (GL_VIEWPORT_BIT | GL_TRANSFORM_BIT));
925
      for (i = 0; i < 4; i++)
926
         m[i] = nobj->sampling_matrices.viewport[i];
927
      glViewport(m[0], m[1], m[2], m[3]);
928
      glMatrixMode(GL_PROJECTION);
929
      glPushMatrix();
930
      glLoadMatrixf(nobj->sampling_matrices.proj);
931
      glMatrixMode(GL_MODELVIEW);
932
      glPushMatrix();
933
      glLoadMatrixf(nobj->sampling_matrices.model);
934
   }
935
}
936
 
937
static void
938
revert_sampling_and_culling(GLUnurbsObj * nobj)
939
{
940
   if (nobj->auto_load_matrix == GL_FALSE) {
941
      glMatrixMode(GL_MODELVIEW);
942
      glPopMatrix();
943
      glMatrixMode(GL_PROJECTION);
944
      glPopMatrix();
945
      glPopAttrib();
946
   }
947
}
948
 
949
GLenum
950
glu_do_sampling_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
951
                   GLint ** sfactors, GLint ** tfactors)
952
{
953
   GLint dim;
954
   GLenum err;
955
 
956
   *sfactors = NULL;
957
   *tfactors = NULL;
958
   dim = nobj->surface.geom.dim;
959
   set_sampling_and_culling(nobj);
960
   if ((err = calc_sampling_3D(new_ctrl, nobj->sampling_tolerance, dim,
961
                               nobj->surface.geom.sorder,
962
                               nobj->surface.geom.torder, sfactors,
963
                               tfactors)) == GLU_ERROR) {
964
      revert_sampling_and_culling(nobj);
965
      call_user_error(nobj, err);
966
      return GLU_ERROR;
967
   }
968
   revert_sampling_and_culling(nobj);
969
   return GLU_NO_ERROR;
970
}
971
 
972
GLenum
973
glu_do_sampling_uv(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
974
                   GLint ** sfactors, GLint ** tfactors)
975
{
976
   GLint s_cnt, t_cnt, i;
977
   GLint u_steps, v_steps;
978
 
979
   s_cnt = new_ctrl->s_bezier_cnt;
980
   t_cnt = new_ctrl->t_bezier_cnt;
981
   *sfactors = NULL;
982
   *tfactors = NULL;
983
   if ((*sfactors = (GLint *) malloc(sizeof(GLint) * s_cnt * 3))
984
       == NULL) {
985
      return GLU_OUT_OF_MEMORY;
986
   }
987
   if ((*tfactors = (GLint *) malloc(sizeof(GLint) * t_cnt * 3))
988
       == NULL) {
989
      free(*sfactors);
990
      return GLU_OUT_OF_MEMORY;
991
   }
992
   u_steps = nobj->u_step;
993
   v_steps = nobj->v_step;
994
   for (i = 0; i < s_cnt; i++) {
995
      *(*sfactors + i * 3) = u_steps;
996
      *(*sfactors + i * 3 + 1) = u_steps;
997
      *(*sfactors + i * 3 + 2) = u_steps;
998
   }
999
   for (i = 0; i < t_cnt; i++) {
1000
      *(*tfactors + i * 3) = v_steps;
1001
      *(*tfactors + i * 3 + 1) = v_steps;
1002
      *(*tfactors + i * 3 + 2) = v_steps;
1003
   }
1004
   return GLU_NO_ERROR;
1005
}
1006
 
1007
 
1008
GLenum
1009
glu_do_sampling_param_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
1010
                         GLint ** sfactors, GLint ** tfactors)
1011
{
1012
   GLint dim;
1013
   GLenum err;
1014
 
1015
   *sfactors = NULL;
1016
   *tfactors = NULL;
1017
   dim = nobj->surface.geom.dim;
1018
   set_sampling_and_culling(nobj);
1019
   if (
1020
       (err =
1021
        calc_sampling_param_3D(new_ctrl, nobj->parametric_tolerance, dim,
1022
                               nobj->surface.geom.sorder,
1023
                               nobj->surface.geom.torder, sfactors,
1024
                               tfactors)) == GLU_ERROR) {
1025
      revert_sampling_and_culling(nobj);
1026
      call_user_error(nobj, err);
1027
      return GLU_ERROR;
1028
   }
1029
   revert_sampling_and_culling(nobj);
1030
   return GLU_NO_ERROR;
1031
}
1032
 
1033
 
1034
static GLenum
1035
glu_do_sampling_2D(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt, GLint order,
1036
                   GLint dim, GLint ** factors)
1037
{
1038
   GLenum err;
1039
 
1040
   set_sampling_and_culling(nobj);
1041
   err = calc_sampling_2D(ctrl, cnt, order, nobj->sampling_tolerance, dim,
1042
                          factors);
1043
   revert_sampling_and_culling(nobj);
1044
   return err;
1045
}
1046
 
1047
 
1048
static GLenum
1049
glu_do_sampling_u(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt, GLint order,
1050
                  GLint dim, GLint ** factors)
1051
{
1052
   GLint i;
1053
   GLint u_steps;
1054
 
1055
   cnt /= order;
1056
   if ((*factors = (GLint *) malloc(sizeof(GLint) * cnt))
1057
       == NULL) {
1058
      return GLU_OUT_OF_MEMORY;
1059
   }
1060
   u_steps = nobj->u_step;
1061
   for (i = 0; i < cnt; i++)
1062
      (*factors)[i] = u_steps;
1063
   return GLU_NO_ERROR;
1064
}
1065
 
1066
 
1067
static GLenum
1068
glu_do_sampling_param_2D(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt,
1069
                         GLint order, GLint dim, GLint ** factors)
1070
{
1071
   GLint i;
1072
   GLint u_steps;
1073
   GLfloat tolerance;
1074
 
1075
   set_sampling_and_culling(nobj);
1076
   tolerance = nobj->parametric_tolerance;
1077
   cnt /= order;
1078
   if ((*factors = (GLint *) malloc(sizeof(GLint) * cnt))
1079
       == NULL) {
1080
      revert_sampling_and_culling(nobj);
1081
      return GLU_OUT_OF_MEMORY;
1082
   }
1083
   u_steps = nobj->u_step;
1084
   for (i = 0; i < cnt; i++) {
1085
      (*factors)[i] = calc_parametric_factor(ctrl, order, 0,
1086
                                             dim, tolerance, dim);
1087
 
1088
   }
1089
   revert_sampling_and_culling(nobj);
1090
   return GLU_NO_ERROR;
1091
}
1092
 
1093
GLenum
1094
glu_do_sampling_crv(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt,
1095
                    GLint order, GLint dim, GLint ** factors)
1096
{
1097
   GLenum err;
1098
 
1099
   *factors = NULL;
1100
   switch (nobj->sampling_method) {
1101
   case GLU_PATH_LENGTH:
1102
      if ((err = glu_do_sampling_2D(nobj, ctrl, cnt, order, dim, factors)) !=
1103
          GLU_NO_ERROR) {
1104
         call_user_error(nobj, err);
1105
         return GLU_ERROR;
1106
      }
1107
      break;
1108
   case GLU_DOMAIN_DISTANCE:
1109
      if ((err = glu_do_sampling_u(nobj, ctrl, cnt, order, dim, factors)) !=
1110
          GLU_NO_ERROR) {
1111
         call_user_error(nobj, err);
1112
         return GLU_ERROR;
1113
      }
1114
      break;
1115
   case GLU_PARAMETRIC_ERROR:
1116
      if (
1117
          (err =
1118
           glu_do_sampling_param_2D(nobj, ctrl, cnt, order, dim,
1119
                                    factors)) != GLU_NO_ERROR) {
1120
         call_user_error(nobj, err);
1121
         return GLU_ERROR;
1122
      }
1123
      break;
1124
   default:
1125
      abort();
1126
   }
1127
 
1128
   return GLU_NO_ERROR;
1129
}
1130
 
1131
/* TODO - i don't like this culling - this one just tests if at least one */
1132
/* ctrl point lies within the viewport . Also the point_in_viewport() */
1133
/* should be included in the fnctions for efficiency reasons */
1134
 
1135
static GLboolean
1136
point_in_viewport(GLfloat * pt, GLint dim)
1137
{
1138
   GLdouble model[16], proj[16];
1139
   GLint viewport[4];
1140
   GLdouble x, y, z, w, winx, winy, winz;
1141
 
1142
   glGetDoublev(GL_MODELVIEW_MATRIX, model);
1143
   glGetDoublev(GL_PROJECTION_MATRIX, proj);
1144
   glGetIntegerv(GL_VIEWPORT, viewport);
1145
   if (dim == 3) {
1146
      x = (GLdouble) pt[0];
1147
      y = (GLdouble) pt[1];
1148
      z = (GLdouble) pt[2];
1149
      gluProject(x, y, z, model, proj, viewport, &winx, &winy, &winz);
1150
   }
1151
   else {
1152
      w = (GLdouble) pt[3];
1153
      x = (GLdouble) pt[0] / w;
1154
      y = (GLdouble) pt[1] / w;
1155
      z = (GLdouble) pt[2] / w;
1156
      gluProject(x, y, z, model, proj, viewport, &winx, &winy, &winz);
1157
   }
1158
   if ((GLint) winx >= viewport[0] && (GLint) winx < viewport[2] &&
1159
       (GLint) winy >= viewport[1] && (GLint) winy < viewport[3])
1160
      return GL_TRUE;
1161
   return GL_FALSE;
1162
}
1163
 
1164
GLboolean
1165
fine_culling_test_3D(GLUnurbsObj * nobj, GLfloat * pts, GLint s_cnt,
1166
                     GLint t_cnt, GLint s_stride, GLint t_stride, GLint dim)
1167
{
1168
   GLint i, j;
1169
 
1170
   if (nobj->culling == GL_FALSE)
1171
      return GL_FALSE;
1172
   set_sampling_and_culling(nobj);
1173
 
1174
   if (dim == 3) {
1175
      for (i = 0; i < s_cnt; i++)
1176
         for (j = 0; j < t_cnt; j++)
1177
            if (point_in_viewport(pts + i * s_stride + j * t_stride, dim)) {
1178
               revert_sampling_and_culling(nobj);
1179
               return GL_FALSE;
1180
            }
1181
   }
1182
   else {
1183
      for (i = 0; i < s_cnt; i++)
1184
         for (j = 0; j < t_cnt; j++)
1185
            if (point_in_viewport(pts + i * s_stride + j * t_stride, dim)) {
1186
               revert_sampling_and_culling(nobj);
1187
               return GL_FALSE;
1188
            }
1189
   }
1190
   revert_sampling_and_culling(nobj);
1191
   return GL_TRUE;
1192
}
1193
 
1194
/*GLboolean
1195
fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
1196
        GLint s_stride,GLint t_stride, GLint dim)
1197
{
1198
        GLint           visible_cnt;
1199
        GLfloat         feedback_buffer[5];
1200
        GLsizei         buffer_size;
1201
        GLint           i,j;
1202
 
1203
        if(nobj->culling==GL_FALSE)
1204
                return GL_FALSE;
1205
        buffer_size=5;
1206
        set_sampling_and_culling(nobj);
1207
 
1208
        glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
1209
        glRenderMode(GL_FEEDBACK);
1210
        if(dim==3)
1211
        {
1212
                for(i=0;i<s_cnt;i++)
1213
                {
1214
                        glBegin(GL_LINE_LOOP);
1215
                        for(j=0;j<t_cnt;j++)
1216
                                glVertex3fv(pts+i*s_stride+j*t_stride);
1217
                        glEnd();
1218
                }
1219
                for(j=0;j<t_cnt;j++)
1220
                {
1221
                        glBegin(GL_LINE_LOOP);
1222
                        for(i=0;i<s_cnt;i++)
1223
                                glVertex3fv(pts+i*s_stride+j*t_stride);
1224
                        glEnd();
1225
                }
1226
        }
1227
        else
1228
        {
1229
                for(i=0;i<s_cnt;i++)
1230
                {
1231
                        glBegin(GL_LINE_LOOP);
1232
                        for(j=0;j<t_cnt;j++)
1233
                                glVertex4fv(pts+i*s_stride+j*t_stride);
1234
                        glEnd();
1235
                }
1236
                for(j=0;j<t_cnt;j++)
1237
                {
1238
                        glBegin(GL_LINE_LOOP);
1239
                        for(i=0;i<s_cnt;i++)
1240
                                glVertex4fv(pts+i*s_stride+j*t_stride);
1241
                        glEnd();
1242
                }
1243
        }
1244
        visible_cnt=glRenderMode(GL_RENDER);
1245
 
1246
        revert_sampling_and_culling(nobj);
1247
        return (GLboolean)(visible_cnt==0);
1248
}*/
1249
 
1250
GLboolean
1251
fine_culling_test_2D(GLUnurbsObj * nobj, GLfloat * pts, GLint cnt,
1252
                     GLint stride, GLint dim)
1253
{
1254
   GLint i;
1255
 
1256
   if (nobj->culling == GL_FALSE)
1257
      return GL_FALSE;
1258
   set_sampling_and_culling(nobj);
1259
 
1260
   if (dim == 3) {
1261
      for (i = 0; i < cnt; i++)
1262
         if (point_in_viewport(pts + i * stride, dim)) {
1263
            revert_sampling_and_culling(nobj);
1264
            return GL_FALSE;
1265
         }
1266
   }
1267
   else {
1268
      for (i = 0; i < cnt; i++)
1269
         if (point_in_viewport(pts + i * stride, dim)) {
1270
            revert_sampling_and_culling(nobj);
1271
            return GL_FALSE;
1272
         }
1273
   }
1274
   revert_sampling_and_culling(nobj);
1275
   return GL_TRUE;
1276
}
1277
 
1278
/*GLboolean
1279
fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
1280
        GLint stride, GLint dim)
1281
{
1282
        GLint           visible_cnt;
1283
        GLfloat         feedback_buffer[5];
1284
        GLsizei         buffer_size;
1285
        GLint           i;
1286
 
1287
        if(nobj->culling==GL_FALSE)
1288
                return GL_FALSE;
1289
        buffer_size=5;
1290
        set_sampling_and_culling(nobj);
1291
 
1292
        glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
1293
        glRenderMode(GL_FEEDBACK);
1294
        glBegin(GL_LINE_LOOP);
1295
        if(dim==3)
1296
        {
1297
                for(i=0;i<cnt;i++)
1298
                        glVertex3fv(pts+i*stride);
1299
        }
1300
        else
1301
        {
1302
                for(i=0;i<cnt;i++)
1303
                        glVertex4fv(pts+i*stride);
1304
        }
1305
        glEnd();
1306
        visible_cnt=glRenderMode(GL_RENDER);
1307
 
1308
        revert_sampling_and_culling(nobj);
1309
        return (GLboolean)(visible_cnt==0);
1310
}*/