~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/glu/mesa/nurbsutl.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

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