glu/sgi: Initialize members of class Arc.
[mesa.git] / src / glu / mesa / nurbsutl.c
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 }*/