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

« back to all changes in this revision

Viewing changes to src/glu/mesa/nurbscrv.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
 
static int
40
 
get_curve_dim(GLenum type)
41
 
{
42
 
   switch (type) {
43
 
   case GL_MAP1_VERTEX_3:
44
 
      return 3;
45
 
   case GL_MAP1_VERTEX_4:
46
 
      return 4;
47
 
   case GL_MAP1_INDEX:
48
 
      return 1;
49
 
   case GL_MAP1_COLOR_4:
50
 
      return 4;
51
 
   case GL_MAP1_NORMAL:
52
 
      return 3;
53
 
   case GL_MAP1_TEXTURE_COORD_1:
54
 
      return 1;
55
 
   case GL_MAP1_TEXTURE_COORD_2:
56
 
      return 2;
57
 
   case GL_MAP1_TEXTURE_COORD_3:
58
 
      return 3;
59
 
   case GL_MAP1_TEXTURE_COORD_4:
60
 
      return 4;
61
 
   default:
62
 
      abort();                  /* TODO: is this OK? */
63
 
   }
64
 
   return 0;                    /*never get here */
65
 
}
66
 
 
67
 
static GLenum
68
 
test_nurbs_curve(GLUnurbsObj * nobj, curve_attribs * attribs)
69
 
{
70
 
   GLenum err;
71
 
   GLint tmp_int;
72
 
 
73
 
   if (attribs->order < 0) {
74
 
      call_user_error(nobj, GLU_INVALID_VALUE);
75
 
      return GLU_ERROR;
76
 
   }
77
 
   glGetIntegerv(GL_MAX_EVAL_ORDER, &tmp_int);
78
 
   if (attribs->order > tmp_int || attribs->order < 2) {
79
 
      call_user_error(nobj, GLU_NURBS_ERROR1);
80
 
      return GLU_ERROR;
81
 
   }
82
 
   if (attribs->knot_count < attribs->order + 2) {
83
 
      call_user_error(nobj, GLU_NURBS_ERROR2);
84
 
      return GLU_ERROR;
85
 
   }
86
 
   if (attribs->stride < 0) {
87
 
      call_user_error(nobj, GLU_NURBS_ERROR34);
88
 
      return GLU_ERROR;
89
 
   }
90
 
   if (attribs->knot == NULL || attribs->ctrlarray == NULL) {
91
 
      call_user_error(nobj, GLU_NURBS_ERROR36);
92
 
      return GLU_ERROR;
93
 
   }
94
 
   if ((err = test_knot(attribs->knot_count, attribs->knot, attribs->order))
95
 
       != GLU_NO_ERROR) {
96
 
      call_user_error(nobj, err);
97
 
      return GLU_ERROR;
98
 
   }
99
 
   return GLU_NO_ERROR;
100
 
}
101
 
 
102
 
static GLenum
103
 
test_nurbs_curves(GLUnurbsObj * nobj)
104
 
{
105
 
   /* test the geometric data */
106
 
   if (test_nurbs_curve(nobj, &(nobj->curve.geom)) != GLU_NO_ERROR)
107
 
      return GLU_ERROR;
108
 
   /* now test the attributive data */
109
 
   /* color */
110
 
   if (nobj->curve.color.type != GLU_INVALID_ENUM)
111
 
      if (test_nurbs_curve(nobj, &(nobj->curve.color)) != GLU_NO_ERROR)
112
 
         return GLU_ERROR;
113
 
   /* normal */
114
 
   if (nobj->curve.normal.type != GLU_INVALID_ENUM)
115
 
      if (test_nurbs_curve(nobj, &(nobj->curve.normal)) != GLU_NO_ERROR)
116
 
         return GLU_ERROR;
117
 
   /* texture */
118
 
   if (nobj->curve.texture.type != GLU_INVALID_ENUM)
119
 
      if (test_nurbs_curve(nobj, &(nobj->curve.texture)) != GLU_NO_ERROR)
120
 
         return GLU_ERROR;
121
 
   return GLU_NO_ERROR;
122
 
}
123
 
 
124
 
/* prepare the knot information structures */
125
 
static GLenum
126
 
fill_knot_structures(GLUnurbsObj * nobj, knot_str_type * geom_knot,
127
 
                     knot_str_type * color_knot, knot_str_type * normal_knot,
128
 
                     knot_str_type * texture_knot)
129
 
{
130
 
   GLint order;
131
 
   GLfloat *knot;
132
 
   GLint nknots;
133
 
   GLint t_min, t_max;
134
 
 
135
 
   geom_knot->unified_knot = NULL;
136
 
   knot = geom_knot->knot = nobj->curve.geom.knot;
137
 
   nknots = geom_knot->nknots = nobj->curve.geom.knot_count;
138
 
   order = geom_knot->order = nobj->curve.geom.order;
139
 
   geom_knot->delta_nknots = 0;
140
 
   t_min = geom_knot->t_min = order - 1;
141
 
   t_max = geom_knot->t_max = nknots - order;
142
 
   if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
143
 
      call_user_error(nobj, GLU_NURBS_ERROR3);
144
 
      return GLU_ERROR;
145
 
   }
146
 
   if (fabs(knot[0] - knot[t_min]) < EPSILON) {
147
 
      /* knot open at beggining */
148
 
      geom_knot->open_at_begin = GL_TRUE;
149
 
   }
150
 
   else
151
 
      geom_knot->open_at_begin = GL_FALSE;
152
 
   if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
153
 
      /* knot open at end */
154
 
      geom_knot->open_at_end = GL_TRUE;
155
 
   }
156
 
   else
157
 
      geom_knot->open_at_end = GL_FALSE;
158
 
   if (nobj->curve.color.type != GLU_INVALID_ENUM) {
159
 
      color_knot->unified_knot = (GLfloat *) 1;
160
 
      knot = color_knot->knot = nobj->curve.color.knot;
161
 
      nknots = color_knot->nknots = nobj->curve.color.knot_count;
162
 
      order = color_knot->order = nobj->curve.color.order;
163
 
      color_knot->delta_nknots = 0;
164
 
      t_min = color_knot->t_min = order - 1;
165
 
      t_max = color_knot->t_max = nknots - order;
166
 
      if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
167
 
         call_user_error(nobj, GLU_NURBS_ERROR3);
168
 
         return GLU_ERROR;
169
 
      }
170
 
      if (fabs(knot[0] - knot[t_min]) < EPSILON) {
171
 
         /* knot open at beggining */
172
 
         color_knot->open_at_begin = GL_TRUE;
173
 
      }
174
 
      else
175
 
         color_knot->open_at_begin = GL_FALSE;
176
 
      if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
177
 
         /* knot open at end */
178
 
         color_knot->open_at_end = GL_TRUE;
179
 
      }
180
 
      else
181
 
         color_knot->open_at_end = GL_FALSE;
182
 
   }
183
 
   else
184
 
      color_knot->unified_knot = NULL;
185
 
   if (nobj->curve.normal.type != GLU_INVALID_ENUM) {
186
 
      normal_knot->unified_knot = (GLfloat *) 1;
187
 
      knot = normal_knot->knot = nobj->curve.normal.knot;
188
 
      nknots = normal_knot->nknots = nobj->curve.normal.knot_count;
189
 
      order = normal_knot->order = nobj->curve.normal.order;
190
 
      normal_knot->delta_nknots = 0;
191
 
      t_min = normal_knot->t_min = order - 1;
192
 
      t_max = normal_knot->t_max = nknots - order;
193
 
      if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
194
 
         call_user_error(nobj, GLU_NURBS_ERROR3);
195
 
         return GLU_ERROR;
196
 
      }
197
 
      if (fabs(knot[0] - knot[t_min]) < EPSILON) {
198
 
         /* knot open at beggining */
199
 
         normal_knot->open_at_begin = GL_TRUE;
200
 
      }
201
 
      else
202
 
         normal_knot->open_at_begin = GL_FALSE;
203
 
      if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
204
 
         /* knot open at end */
205
 
         normal_knot->open_at_end = GL_TRUE;
206
 
      }
207
 
      else
208
 
         normal_knot->open_at_end = GL_FALSE;
209
 
   }
210
 
   else
211
 
      normal_knot->unified_knot = NULL;
212
 
   if (nobj->curve.texture.type != GLU_INVALID_ENUM) {
213
 
      texture_knot->unified_knot = (GLfloat *) 1;
214
 
      knot = texture_knot->knot = nobj->curve.texture.knot;
215
 
      nknots = texture_knot->nknots = nobj->curve.texture.knot_count;
216
 
      order = texture_knot->order = nobj->curve.texture.order;
217
 
      texture_knot->delta_nknots = 0;
218
 
      t_min = texture_knot->t_min = order - 1;
219
 
      t_max = texture_knot->t_max = nknots - order;
220
 
      if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
221
 
         call_user_error(nobj, GLU_NURBS_ERROR3);
222
 
         return GLU_ERROR;
223
 
      }
224
 
      if (fabs(knot[0] - knot[t_min]) < EPSILON) {
225
 
         /* knot open at beggining */
226
 
         texture_knot->open_at_begin = GL_TRUE;
227
 
      }
228
 
      else
229
 
         texture_knot->open_at_begin = GL_FALSE;
230
 
      if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
231
 
         /* knot open at end */
232
 
         texture_knot->open_at_end = GL_TRUE;
233
 
      }
234
 
      else
235
 
         texture_knot->open_at_end = GL_FALSE;
236
 
   }
237
 
   else
238
 
      texture_knot->unified_knot = NULL;
239
 
   return GLU_NO_ERROR;
240
 
}
241
 
 
242
 
/* covert the NURBS curve into a series of adjacent Bezier curves */
243
 
static GLenum
244
 
convert_curve(knot_str_type * the_knot, curve_attribs * attrib,
245
 
              GLfloat ** new_ctrl, GLint * ncontrol)
246
 
{
247
 
   GLenum err;
248
 
 
249
 
   if ((err = explode_knot(the_knot)) != GLU_NO_ERROR) {
250
 
      if (the_knot->unified_knot) {
251
 
         free(the_knot->unified_knot);
252
 
         the_knot->unified_knot = NULL;
253
 
      }
254
 
      return err;
255
 
   }
256
 
   if (the_knot->unified_knot) {
257
 
      free(the_knot->unified_knot);
258
 
      the_knot->unified_knot = NULL;
259
 
   }
260
 
   if ((err = calc_alphas(the_knot)) != GLU_NO_ERROR) {
261
 
      free(the_knot->new_knot);
262
 
      return err;
263
 
   }
264
 
   free(the_knot->new_knot);
265
 
   if ((err = calc_new_ctrl_pts(attrib->ctrlarray, attrib->stride, the_knot,
266
 
                                attrib->dim, new_ctrl, ncontrol))
267
 
       != GLU_NO_ERROR) {
268
 
      free(the_knot->alpha);
269
 
      return err;
270
 
   }
271
 
   free(the_knot->alpha);
272
 
   return GLU_NO_ERROR;
273
 
}
274
 
 
275
 
/* covert curves - geometry and possible attribute ones into equivalent */
276
 
/* sequence of adjacent Bezier curves */
277
 
static GLenum
278
 
convert_curves(GLUnurbsObj * nobj, GLfloat ** new_geom_ctrl,
279
 
               GLint * ncontrol, GLfloat ** new_color_ctrl,
280
 
               GLfloat ** new_normal_ctrl, GLfloat ** new_texture_ctrl)
281
 
{
282
 
   knot_str_type geom_knot, color_knot, normal_knot, texture_knot;
283
 
   GLint junk;
284
 
   GLenum err;
285
 
 
286
 
   *new_color_ctrl = *new_normal_ctrl = *new_texture_ctrl = NULL;
287
 
 
288
 
   if (fill_knot_structures(nobj, &geom_knot, &color_knot, &normal_knot,
289
 
                            &texture_knot) != GLU_NO_ERROR)
290
 
      return GLU_ERROR;
291
 
 
292
 
   /* unify knots - all knots should have the same number of working */
293
 
   /* ranges */
294
 
   if (
295
 
       (err =
296
 
        select_knot_working_range(nobj, &geom_knot, &color_knot, &normal_knot,
297
 
                                  &texture_knot)) != GLU_NO_ERROR) {
298
 
      return err;
299
 
   }
300
 
   /* convert the geometry curve */
301
 
   nobj->curve.geom.dim = get_curve_dim(nobj->curve.geom.type);
302
 
   if ((err = convert_curve(&geom_knot, &(nobj->curve.geom), new_geom_ctrl,
303
 
                            ncontrol)) != GLU_NO_ERROR) {
304
 
      free_unified_knots(&geom_knot, &color_knot, &normal_knot,
305
 
                         &texture_knot);
306
 
      call_user_error(nobj, err);
307
 
      return err;
308
 
   }
309
 
   /* if additional attributive curves are given convert them as well */
310
 
   if (color_knot.unified_knot) {
311
 
      nobj->curve.color.dim = get_curve_dim(nobj->curve.color.type);
312
 
      if ((err = convert_curve(&color_knot, &(nobj->curve.color),
313
 
                               new_color_ctrl, &junk)) != GLU_NO_ERROR) {
314
 
         free_unified_knots(&geom_knot, &color_knot, &normal_knot,
315
 
                            &texture_knot);
316
 
         free(*new_geom_ctrl);
317
 
         call_user_error(nobj, err);
318
 
         return err;
319
 
      }
320
 
   }
321
 
   if (normal_knot.unified_knot) {
322
 
      nobj->curve.normal.dim = get_curve_dim(nobj->curve.normal.type);
323
 
      if ((err = convert_curve(&normal_knot, &(nobj->curve.normal),
324
 
                               new_normal_ctrl, &junk)) != GLU_NO_ERROR) {
325
 
         free_unified_knots(&geom_knot, &color_knot, &normal_knot,
326
 
                            &texture_knot);
327
 
         free(*new_geom_ctrl);
328
 
         if (*new_color_ctrl)
329
 
            free(*new_color_ctrl);
330
 
         call_user_error(nobj, err);
331
 
         return err;
332
 
      }
333
 
   }
334
 
   if (texture_knot.unified_knot) {
335
 
      nobj->curve.texture.dim = get_curve_dim(nobj->curve.texture.type);
336
 
      if ((err = convert_curve(&texture_knot, &(nobj->curve.texture),
337
 
                               new_texture_ctrl, &junk)) != GLU_NO_ERROR) {
338
 
         free_unified_knots(&geom_knot, &color_knot, &normal_knot,
339
 
                            &texture_knot);
340
 
         free(*new_geom_ctrl);
341
 
         if (*new_color_ctrl)
342
 
            free(*new_color_ctrl);
343
 
         if (*new_normal_ctrl)
344
 
            free(*new_normal_ctrl);
345
 
         call_user_error(nobj, err);
346
 
         return err;
347
 
      }
348
 
   }
349
 
   return GLU_NO_ERROR;
350
 
}
351
 
 
352
 
/* main NURBS curve procedure */
353
 
void
354
 
do_nurbs_curve(GLUnurbsObj * nobj)
355
 
{
356
 
   GLint geom_order, color_order = 0, normal_order = 0, texture_order = 0;
357
 
   GLenum geom_type;
358
 
   GLint n_ctrl;
359
 
   GLfloat *new_geom_ctrl, *new_color_ctrl, *new_normal_ctrl,
360
 
      *new_texture_ctrl;
361
 
   GLfloat *geom_ctrl = 0, *color_ctrl = 0, *normal_ctrl = 0, *texture_ctrl = 0;
362
 
   GLint *factors;
363
 
   GLint i, j;
364
 
   GLint geom_dim, color_dim = 0, normal_dim = 0, texture_dim = 0;
365
 
 
366
 
   /* test the user supplied data */
367
 
   if (test_nurbs_curves(nobj) != GLU_NO_ERROR)
368
 
      return;
369
 
 
370
 
   if (convert_curves(nobj, &new_geom_ctrl, &n_ctrl, &new_color_ctrl,
371
 
                      &new_normal_ctrl, &new_texture_ctrl) != GLU_NO_ERROR)
372
 
      return;
373
 
 
374
 
   geom_order = nobj->curve.geom.order;
375
 
   geom_type = nobj->curve.geom.type;
376
 
   geom_dim = nobj->curve.geom.dim;
377
 
 
378
 
   if (glu_do_sampling_crv(nobj, new_geom_ctrl, n_ctrl, geom_order, geom_dim,
379
 
                           &factors) != GLU_NO_ERROR) {
380
 
      free(new_geom_ctrl);
381
 
      if (new_color_ctrl)
382
 
         free(new_color_ctrl);
383
 
      if (new_normal_ctrl)
384
 
         free(new_normal_ctrl);
385
 
      if (new_texture_ctrl)
386
 
         free(new_texture_ctrl);
387
 
      return;
388
 
   }
389
 
   glEnable(geom_type);
390
 
   if (new_color_ctrl) {
391
 
      glEnable(nobj->curve.color.type);
392
 
      color_dim = nobj->curve.color.dim;
393
 
      color_ctrl = new_color_ctrl;
394
 
      color_order = nobj->curve.color.order;
395
 
   }
396
 
   if (new_normal_ctrl) {
397
 
      glEnable(nobj->curve.normal.type);
398
 
      normal_dim = nobj->curve.normal.dim;
399
 
      normal_ctrl = new_normal_ctrl;
400
 
      normal_order = nobj->curve.normal.order;
401
 
   }
402
 
   if (new_texture_ctrl) {
403
 
      glEnable(nobj->curve.texture.type);
404
 
      texture_dim = nobj->curve.texture.dim;
405
 
      texture_ctrl = new_texture_ctrl;
406
 
      texture_order = nobj->curve.texture.order;
407
 
   }
408
 
   for (i = 0, j = 0, geom_ctrl = new_geom_ctrl;
409
 
        i < n_ctrl; i += geom_order, j++, geom_ctrl += geom_order * geom_dim) {
410
 
      if (fine_culling_test_2D
411
 
          (nobj, geom_ctrl, geom_order, geom_dim, geom_dim)) {
412
 
         color_ctrl += color_order * color_dim;
413
 
         normal_ctrl += normal_order * normal_dim;
414
 
         texture_ctrl += texture_order * texture_dim;
415
 
         continue;
416
 
      }
417
 
      glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
418
 
      if (new_color_ctrl) {
419
 
         glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
420
 
                 color_order, color_ctrl);
421
 
         color_ctrl += color_order * color_dim;
422
 
      }
423
 
      if (new_normal_ctrl) {
424
 
         glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
425
 
                 normal_order, normal_ctrl);
426
 
         normal_ctrl += normal_order * normal_dim;
427
 
      }
428
 
      if (new_texture_ctrl) {
429
 
         glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
430
 
                 texture_order, texture_ctrl);
431
 
         texture_ctrl += texture_order * texture_dim;
432
 
      }
433
 
      glMapGrid1f(factors[j], 0.0, 1.0);
434
 
      glEvalMesh1(GL_LINE, 0, factors[j]);
435
 
   }
436
 
   free(new_geom_ctrl);
437
 
   free(factors);
438
 
   if (new_color_ctrl)
439
 
      free(new_color_ctrl);
440
 
   if (new_normal_ctrl)
441
 
      free(new_normal_ctrl);
442
 
   if (new_texture_ctrl)
443
 
      free(new_texture_ctrl);
444
 
}