1f220fa62Smrg/*
2f220fa62Smrg** License Applicability. Except to the extent portions of this file are
3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free
4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this
5f220fa62Smrg** file are subject only to the provisions of the License. You may not use
6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy
7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9f220fa62Smrg**
10f220fa62Smrg** http://oss.sgi.com/projects/FreeB
11f220fa62Smrg**
12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an
13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17f220fa62Smrg**
18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation,
19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21f220fa62Smrg** Copyright in any portions created by third parties is as indicated
22f220fa62Smrg** elsewhere herein. All Rights Reserved.
23f220fa62Smrg**
24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces
25f220fa62Smrg** established by SGI in conjunction with the Original Code are The
26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software
30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31f220fa62Smrg** published by SGI, but has not been independently verified as being
32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification.
33f220fa62Smrg*/
34f220fa62Smrg
35f220fa62Smrg/*
36f220fa62Smrg * mapdesc.c++
37f220fa62Smrg *
38f220fa62Smrg */
39f220fa62Smrg
40f220fa62Smrg#include <stdio.h>
41f220fa62Smrg#include "glimports.h"
42f220fa62Smrg#include "mystdio.h"
43f220fa62Smrg#include "myassert.h"
44f220fa62Smrg#include "mystring.h"
45f220fa62Smrg#include "mymath.h"
46f220fa62Smrg#include "backend.h"
47f220fa62Smrg#include "nurbsconsts.h"
48f220fa62Smrg#include "mapdesc.h"
49f220fa62Smrg
50f220fa62SmrgMapdesc::Mapdesc( long _type, int _israt, int _ncoords, Backend& b )
51f220fa62Smrg    : backend( b )
52f220fa62Smrg{
53f220fa62Smrg    type 		= _type;
54f220fa62Smrg    isrational 		= _israt;
55f220fa62Smrg    ncoords 		= _ncoords;
56f220fa62Smrg    hcoords		= _ncoords + (_israt ? 0 : 1 );
57f220fa62Smrg    inhcoords		= _ncoords - (_israt ? 1 : 0 );
58f220fa62Smrg    mask 		= ((1<<(inhcoords*2))-1);
59f220fa62Smrg    next		= 0;
60f220fa62Smrg
61f220fa62Smrg    assert( hcoords <= MAXCOORDS );
62f220fa62Smrg    assert( inhcoords >= 1 );
63f220fa62Smrg
64f220fa62Smrg    pixel_tolerance 	= 1.0;
65f220fa62Smrg    error_tolerance	= 1.0;
66f220fa62Smrg    bbox_subdividing	= N_NOBBOXSUBDIVISION;
67f220fa62Smrg    culling_method 	= N_NOCULLING;
68f220fa62Smrg    sampling_method 	= N_NOSAMPLING;
69f220fa62Smrg    clampfactor 	= N_NOCLAMPING;
70f220fa62Smrg    minsavings 		= N_NOSAVINGSSUBDIVISION;
71f220fa62Smrg    s_steps  		= 0.0;
72f220fa62Smrg    t_steps 		= 0.0;
73f220fa62Smrg    maxrate 		= ( s_steps < 0.0 ) ? 0.0 : s_steps;
74f220fa62Smrg    maxsrate 		= ( s_steps < 0.0 ) ? 0.0 : s_steps;
75f220fa62Smrg    maxtrate 		= ( t_steps < 0.0 ) ? 0.0 : t_steps;
76f220fa62Smrg    identify( bmat );
77f220fa62Smrg    identify( cmat );
78f220fa62Smrg    identify( smat );
79f220fa62Smrg    for( int i = 0; i != inhcoords; i++ )
80f220fa62Smrg	bboxsize[i] = 1.0;
81f220fa62Smrg}
82f220fa62Smrg
83f220fa62Smrgvoid
84f220fa62SmrgMapdesc::setBboxsize( INREAL *mat )
85f220fa62Smrg{
86f220fa62Smrg    for( int i = 0; i != inhcoords; i++ )
87f220fa62Smrg	bboxsize[i] = (REAL) mat[i];
88f220fa62Smrg}
89f220fa62Smrg
90f220fa62Smrgvoid
91f220fa62SmrgMapdesc::identify( REAL dest[MAXCOORDS][MAXCOORDS] )
92f220fa62Smrg{
93f220fa62Smrg    memset( dest, 0, sizeof( REAL ) * MAXCOORDS * MAXCOORDS );
94f220fa62Smrg    for( int i=0; i != hcoords; i++ )
95f220fa62Smrg	dest[i][i] = 1.0;
96f220fa62Smrg}
97f220fa62Smrg
98f220fa62Smrgvoid
99f220fa62SmrgMapdesc::surfbbox( REAL bb[2][MAXCOORDS] )
100f220fa62Smrg{
101f220fa62Smrg    backend.surfbbox( type, bb[0], bb[1] );
102f220fa62Smrg}
103f220fa62Smrg
104f220fa62Smrgvoid
105f220fa62SmrgMapdesc::copy( REAL dest[MAXCOORDS][MAXCOORDS], long n, INREAL *src,
106f220fa62Smrg	long rstride, long cstride )
107f220fa62Smrg{
108f220fa62Smrg    assert( n >= 0 );
109f220fa62Smrg    for( int i=0; i != n; i++ )
110f220fa62Smrg        for( int j=0; j != n; j++ )
111f220fa62Smrg	    dest[i][j] = src[i*rstride + j*cstride];
112f220fa62Smrg}
113f220fa62Smrg
114f220fa62Smrg/*--------------------------------------------------------------------------
115f220fa62Smrg * copyPt - copy a homogeneous point
116f220fa62Smrg *--------------------------------------------------------------------------
117f220fa62Smrg */
118f220fa62Smrgvoid
119f220fa62SmrgMapdesc::copyPt( REAL *d, REAL *s )
120f220fa62Smrg{
121f220fa62Smrg    assert( hcoords > 0 );
122f220fa62Smrg    switch( hcoords  ) {
123f220fa62Smrg	case 4:
124f220fa62Smrg	    d[3] = s[3];
125f220fa62Smrg	    d[2] = s[2];
126f220fa62Smrg	    d[1] = s[1];
127f220fa62Smrg	    d[0] = s[0];
128f220fa62Smrg	    break;
129f220fa62Smrg	case 3:
130f220fa62Smrg	    d[2] = s[2];
131f220fa62Smrg	    d[1] = s[1];
132f220fa62Smrg	    d[0] = s[0];
133f220fa62Smrg	    break;
134f220fa62Smrg	case 2:
135f220fa62Smrg	    d[1] = s[1];
136f220fa62Smrg	    d[0] = s[0];
137f220fa62Smrg	    break;
138f220fa62Smrg	case 1:
139f220fa62Smrg	    d[0] = s[0];
140f220fa62Smrg	    break;
141f220fa62Smrg	case 5:
142f220fa62Smrg	    d[4] = s[4];
143f220fa62Smrg	    d[3] = s[3];
144f220fa62Smrg	    d[2] = s[2];
145f220fa62Smrg	    d[1] = s[1];
146f220fa62Smrg	    d[0] = s[0];
147f220fa62Smrg	    break;
148f220fa62Smrg	default:
149f220fa62Smrg	    memcpy( d, s, hcoords * sizeof( REAL ) );
150f220fa62Smrg	    break;
151f220fa62Smrg    }
152f220fa62Smrg}
153f220fa62Smrg
154f220fa62Smrg/*--------------------------------------------------------------------------
155f220fa62Smrg * sumPt - compute affine combination of two homogeneous points
156f220fa62Smrg *--------------------------------------------------------------------------
157f220fa62Smrg */
158f220fa62Smrgvoid
159e7980a23SmrgMapdesc::sumPt( REAL *dst, REAL *src1, REAL *src2, REAL alpha, REAL beta )
160f220fa62Smrg{
161f220fa62Smrg    assert( hcoords > 0 );
162f220fa62Smrg    switch( hcoords  ) {
163f220fa62Smrg	case 4:
164f220fa62Smrg	    dst[3] = src1[3] * alpha + src2[3] * beta;
165f220fa62Smrg	    dst[2] = src1[2] * alpha + src2[2] * beta;
166f220fa62Smrg	    dst[1] = src1[1] * alpha + src2[1] * beta;
167f220fa62Smrg	    dst[0] = src1[0] * alpha + src2[0] * beta;
168f220fa62Smrg	    break;
169f220fa62Smrg	case 3:
170f220fa62Smrg	    dst[2] = src1[2] * alpha + src2[2] * beta;
171f220fa62Smrg	    dst[1] = src1[1] * alpha + src2[1] * beta;
172f220fa62Smrg	    dst[0] = src1[0] * alpha + src2[0] * beta;
173f220fa62Smrg	    break;
174f220fa62Smrg	case 2:
175f220fa62Smrg	    dst[1] = src1[1] * alpha + src2[1] * beta;
176f220fa62Smrg	    dst[0] = src1[0] * alpha + src2[0] * beta;
177f220fa62Smrg	    break;
178f220fa62Smrg	case 1:
179f220fa62Smrg	    dst[0] = src1[0] * alpha + src2[0] * beta;
180f220fa62Smrg	    break;
181f220fa62Smrg	case 5:
182f220fa62Smrg	    dst[4] = src1[4] * alpha + src2[4] * beta;
183f220fa62Smrg	    dst[3] = src1[3] * alpha + src2[3] * beta;
184f220fa62Smrg	    dst[2] = src1[2] * alpha + src2[2] * beta;
185f220fa62Smrg	    dst[1] = src1[1] * alpha + src2[1] * beta;
186f220fa62Smrg	    dst[0] = src1[0] * alpha + src2[0] * beta;
187f220fa62Smrg	    break;
188f220fa62Smrg	default: {
189f220fa62Smrg		for( int i = 0; i != hcoords; i++ )
190f220fa62Smrg		    dst[i] = src1[i] * alpha + src2[i] * beta;
191f220fa62Smrg            }
192f220fa62Smrg	    break;
193f220fa62Smrg    }
194f220fa62Smrg}
195f220fa62Smrg
196f220fa62Smrg/*--------------------------------------------------------------------------
197f220fa62Smrg * clipbits - compute bit-vector indicating point/window position
198f220fa62Smrg *		       of a (transformed) homogeneous point
199f220fa62Smrg *--------------------------------------------------------------------------
200f220fa62Smrg */
201f220fa62Smrgunsigned int
202f220fa62SmrgMapdesc::clipbits( REAL *p )
203f220fa62Smrg{
204f220fa62Smrg    assert( inhcoords >= 0 );
205f220fa62Smrg    assert( inhcoords <= 3 );
206f220fa62Smrg
207e7980a23Smrg    int nc = inhcoords;
208e7980a23Smrg    REAL pw = p[nc];
209e7980a23Smrg    REAL nw = -pw;
210e7980a23Smrg    unsigned int bits = 0;
211f220fa62Smrg
212f220fa62Smrg    if( pw == 0.0 ) return mask;
213f220fa62Smrg
214f220fa62Smrg    if( pw > 0.0 ) {
215f220fa62Smrg	switch( nc ) {
216f220fa62Smrg	case 3:
217f220fa62Smrg	    if( p[2] <= pw ) bits |= (1<<5);
218f220fa62Smrg	    if( p[2] >= nw ) bits |= (1<<4);
219f220fa62Smrg	    if( p[1] <= pw ) bits |= (1<<3);
220f220fa62Smrg	    if( p[1] >= nw ) bits |= (1<<2);
221f220fa62Smrg	    if( p[0] <= pw ) bits |= (1<<1);
222f220fa62Smrg	    if( p[0] >= nw ) bits |= (1<<0);
223f220fa62Smrg            return bits;
224f220fa62Smrg	case 2:
225f220fa62Smrg	    if( p[1] <= pw ) bits |= (1<<3);
226f220fa62Smrg	    if( p[1] >= nw ) bits |= (1<<2);
227f220fa62Smrg	    if( p[0] <= pw ) bits |= (1<<1);
228f220fa62Smrg	    if( p[0] >= nw ) bits |= (1<<0);
229f220fa62Smrg            return bits;
230f220fa62Smrg	case 1:
231f220fa62Smrg	    if( p[0] <= pw ) bits |= (1<<1);
232f220fa62Smrg	    if( p[0] >= nw ) bits |= (1<<0);
233f220fa62Smrg            return bits;
234f220fa62Smrg	default: {
235f220fa62Smrg		int bit = 1;
236f220fa62Smrg		for( int i=0; i<nc; i++ ) {
237f220fa62Smrg		    if( p[i] >= nw ) bits |= bit;
238f220fa62Smrg		    bit <<= 1;
239f220fa62Smrg		    if( p[i] <= pw ) bits |= bit;
240f220fa62Smrg		    bit <<= 1;
241f220fa62Smrg		}
242f220fa62Smrg		abort();
243f220fa62Smrg		break;
244f220fa62Smrg	    }
245f220fa62Smrg	}
246f220fa62Smrg    } else {
247f220fa62Smrg	switch( nc ) {
248f220fa62Smrg	case 3:
249f220fa62Smrg	    if( p[2] <= nw ) bits |= (1<<5);
250f220fa62Smrg	    if( p[2] >= pw ) bits |= (1<<4);
251f220fa62Smrg	    if( p[1] <= nw ) bits |= (1<<3);
252f220fa62Smrg	    if( p[1] >= pw ) bits |= (1<<2);
253f220fa62Smrg	    if( p[0] <= nw ) bits |= (1<<1);
254f220fa62Smrg	    if( p[0] >= pw ) bits |= (1<<0);
255f220fa62Smrg            return bits;
256f220fa62Smrg	case 2:
257f220fa62Smrg	    if( p[1] <= nw ) bits |= (1<<3);
258f220fa62Smrg	    if( p[1] >= pw ) bits |= (1<<2);
259f220fa62Smrg	    if( p[0] <= nw ) bits |= (1<<1);
260f220fa62Smrg	    if( p[0] >= pw ) bits |= (1<<0);
261f220fa62Smrg            return bits;
262f220fa62Smrg	case 1:
263f220fa62Smrg	    if( p[0] <= nw ) bits |= (1<<1);
264f220fa62Smrg	    if( p[0] >= pw ) bits |= (1<<0);
265f220fa62Smrg            return bits;
266f220fa62Smrg	default: {
267f220fa62Smrg		int bit = 1;
268f220fa62Smrg		for( int i=0; i<nc; i++ ) {
269f220fa62Smrg		    if( p[i] >= pw ) bits |= bit;
270f220fa62Smrg		    bit <<= 1;
271f220fa62Smrg		    if( p[i] <= nw ) bits |= bit;
272f220fa62Smrg		    bit <<= 1;
273f220fa62Smrg		}
274f220fa62Smrg		abort();
275f220fa62Smrg		break;
276f220fa62Smrg	    }
277f220fa62Smrg	}
278f220fa62Smrg    }
279f220fa62Smrg    return bits;
280f220fa62Smrg}
281f220fa62Smrg
282f220fa62Smrg/*--------------------------------------------------------------------------
283f220fa62Smrg * xformRational - transform a homogeneous point
284f220fa62Smrg *--------------------------------------------------------------------------
285f220fa62Smrg */
286f220fa62Smrgvoid
287f220fa62SmrgMapdesc::xformRational( Maxmatrix mat, REAL *d, REAL *s )
288f220fa62Smrg{
289f220fa62Smrg    assert( hcoords >= 0 );
290f220fa62Smrg
291f220fa62Smrg    if( hcoords == 3 ) {
292f220fa62Smrg	REAL x = s[0];
293f220fa62Smrg	REAL y = s[1];
294f220fa62Smrg	REAL z = s[2];
295f220fa62Smrg	d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0];
296f220fa62Smrg	d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1];
297f220fa62Smrg	d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2];
298f220fa62Smrg    } else if( hcoords == 4 ) {
299f220fa62Smrg	REAL x = s[0];
300f220fa62Smrg	REAL y = s[1];
301f220fa62Smrg	REAL z = s[2];
302f220fa62Smrg	REAL w = s[3];
303f220fa62Smrg	d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+w*mat[3][0];
304f220fa62Smrg	d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+w*mat[3][1];
305f220fa62Smrg	d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+w*mat[3][2];
306f220fa62Smrg	d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+w*mat[3][3];
307f220fa62Smrg    } else {
308f220fa62Smrg	for( int i=0; i != hcoords; i++ ) {
309f220fa62Smrg	    d[i] = 0;
310f220fa62Smrg	    for( int j = 0; j != hcoords; j++ )
311f220fa62Smrg		d[i] += s[j] * mat[j][i];
312f220fa62Smrg	}
313f220fa62Smrg    }
314f220fa62Smrg}
315f220fa62Smrg
316f220fa62Smrg/*--------------------------------------------------------------------------
317f220fa62Smrg * xformNonrational - transform a inhomogeneous point to a homogeneous point
318f220fa62Smrg *--------------------------------------------------------------------------
319f220fa62Smrg */
320f220fa62Smrgvoid
321f220fa62SmrgMapdesc::xformNonrational( Maxmatrix mat, REAL *d, REAL *s )
322f220fa62Smrg{
323f220fa62Smrg    if( inhcoords == 2 ) {
324f220fa62Smrg	REAL x = s[0];
325f220fa62Smrg	REAL y = s[1];
326f220fa62Smrg	d[0] = x*mat[0][0]+y*mat[1][0]+mat[2][0];
327f220fa62Smrg	d[1] = x*mat[0][1]+y*mat[1][1]+mat[2][1];
328f220fa62Smrg	d[2] = x*mat[0][2]+y*mat[1][2]+mat[2][2];
329f220fa62Smrg    } else if( inhcoords == 3 ) {
330f220fa62Smrg	REAL x = s[0];
331f220fa62Smrg	REAL y = s[1];
332f220fa62Smrg	REAL z = s[2];
333f220fa62Smrg	d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+mat[3][0];
334f220fa62Smrg	d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+mat[3][1];
335f220fa62Smrg	d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+mat[3][2];
336f220fa62Smrg	d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+mat[3][3];
337f220fa62Smrg    } else {
338f220fa62Smrg        assert( inhcoords >= 0 );
339f220fa62Smrg	for( int i=0; i != hcoords; i++ ) {
340f220fa62Smrg	    d[i] = mat[inhcoords][i];
341f220fa62Smrg	    for( int j = 0; j < inhcoords; j++ )
342f220fa62Smrg		d[i] += s[j] * mat[j][i];
343f220fa62Smrg	}
344f220fa62Smrg    }
345f220fa62Smrg}
346f220fa62Smrg
347f220fa62Smrg/*--------------------------------------------------------------------------
348f220fa62Smrg * xformAndCullCheck - transform a set of points that may be EITHER
349f220fa62Smrg *	homogeneous or inhomogeneous depending on the map description and
350f220fa62Smrg *	check if they are either completely inside, completely outside,
351f220fa62Smrg *	or intersecting the viewing frustrum.
352f220fa62Smrg *--------------------------------------------------------------------------
353f220fa62Smrg */
354f220fa62Smrgint
355f220fa62SmrgMapdesc::xformAndCullCheck(
356f220fa62Smrg    REAL *pts, int uorder, int ustride, int vorder, int vstride )
357f220fa62Smrg{
358f220fa62Smrg    assert( uorder > 0 );
359f220fa62Smrg    assert( vorder > 0 );
360f220fa62Smrg
361f220fa62Smrg    unsigned int inbits = mask;
362f220fa62Smrg    unsigned int outbits = 0;
363f220fa62Smrg
364f220fa62Smrg    REAL *p = pts;
365f220fa62Smrg    for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
366f220fa62Smrg        REAL *q = p;
367f220fa62Smrg        for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
368f220fa62Smrg    	    REAL cpts[MAXCOORDS];
369f220fa62Smrg	    xformCulling( cpts, q );
370f220fa62Smrg	    unsigned int bits = clipbits( cpts );
371f220fa62Smrg	    outbits |= bits;
372f220fa62Smrg	    inbits &= bits;
373f220fa62Smrg	    if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
374f220fa62Smrg	}
375f220fa62Smrg    }
376f220fa62Smrg
377f220fa62Smrg    if( outbits != (unsigned int)mask ) {
378f220fa62Smrg	return CULL_TRIVIAL_REJECT;
379f220fa62Smrg    } else if( inbits == (unsigned int)mask ) {
380f220fa62Smrg	return CULL_TRIVIAL_ACCEPT;
381f220fa62Smrg    } else {
382f220fa62Smrg	return CULL_ACCEPT;
383f220fa62Smrg    }
384f220fa62Smrg}
385f220fa62Smrg
386f220fa62Smrg/*--------------------------------------------------------------------------
387f220fa62Smrg * cullCheck - check if a set of homogeneous transformed points are
388f220fa62Smrg *	either completely inside, completely outside,
389f220fa62Smrg *	or intersecting the viewing frustrum.
390f220fa62Smrg *--------------------------------------------------------------------------
391f220fa62Smrg */
392f220fa62Smrgint
393f220fa62SmrgMapdesc::cullCheck( REAL *pts, int uorder, int ustride, int vorder, int vstride )
394f220fa62Smrg{
395f220fa62Smrg    unsigned int inbits = mask;
396f220fa62Smrg    unsigned int outbits  = 0;
397f220fa62Smrg
398f220fa62Smrg    REAL *p = pts;
399f220fa62Smrg    for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
400f220fa62Smrg        REAL *q = p;
401f220fa62Smrg        for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
402f220fa62Smrg	    unsigned int bits = clipbits( q );
403f220fa62Smrg	    outbits |= bits;
404f220fa62Smrg	    inbits &= bits;
405f220fa62Smrg	    if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
406f220fa62Smrg	}
407f220fa62Smrg    }
408f220fa62Smrg
409f220fa62Smrg    if( outbits != (unsigned int)mask ) {
410f220fa62Smrg	return CULL_TRIVIAL_REJECT;
411f220fa62Smrg    } else if( inbits == (unsigned int)mask ) {
412f220fa62Smrg	return CULL_TRIVIAL_ACCEPT;
413f220fa62Smrg    } else {
414f220fa62Smrg	return CULL_ACCEPT;
415f220fa62Smrg    }
416f220fa62Smrg}
417f220fa62Smrg
418f220fa62Smrg/*--------------------------------------------------------------------------
419f220fa62Smrg * cullCheck - check if a set of homogeneous transformed points are
420f220fa62Smrg *	either completely inside, completely outside,
421f220fa62Smrg *	or intersecting the viewing frustrum.
422f220fa62Smrg *--------------------------------------------------------------------------
423f220fa62Smrg */
424f220fa62Smrgint
425f220fa62SmrgMapdesc::cullCheck( REAL *pts, int order, int stride )
426f220fa62Smrg{
427f220fa62Smrg    unsigned int inbits = mask;
428f220fa62Smrg    unsigned int outbits  = 0;
429f220fa62Smrg
430f220fa62Smrg    REAL *p = pts;
431f220fa62Smrg    for( REAL *pend = p + order * stride; p != pend; p += stride ) {
432f220fa62Smrg	unsigned int bits = clipbits( p );
433f220fa62Smrg	outbits |= bits;
434f220fa62Smrg	inbits &= bits;
435f220fa62Smrg	if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
436f220fa62Smrg    }
437f220fa62Smrg
438f220fa62Smrg    if( outbits != (unsigned int)mask ) {
439f220fa62Smrg	return CULL_TRIVIAL_REJECT;
440f220fa62Smrg    } else if( inbits == (unsigned int)mask ) {
441f220fa62Smrg	return CULL_TRIVIAL_ACCEPT;
442f220fa62Smrg    } else {
443f220fa62Smrg	return CULL_ACCEPT;
444f220fa62Smrg    }
445f220fa62Smrg}
446f220fa62Smrg
447f220fa62Smrg/*--------------------------------------------------------------------------
448f220fa62Smrg * xformSampling - transform a set of points that may be EITHER
449f220fa62Smrg *	homogeneous or inhomogeneous depending on the map description
450f220fa62Smrg *	into sampling space
451f220fa62Smrg *--------------------------------------------------------------------------
452f220fa62Smrg */
453f220fa62Smrgvoid
454f220fa62SmrgMapdesc::xformSampling( REAL *pts, int order, int stride, REAL *sp, int outstride )
455f220fa62Smrg{
456f220fa62Smrg    xformMat( smat, pts, order, stride, sp, outstride );
457f220fa62Smrg}
458f220fa62Smrg
459f220fa62Smrgvoid
460f220fa62SmrgMapdesc::xformBounding( REAL *pts, int order, int stride, REAL *sp, int outstride )
461f220fa62Smrg{
462f220fa62Smrg    xformMat( bmat, pts, order, stride, sp, outstride );
463f220fa62Smrg}
464f220fa62Smrg
465f220fa62Smrg/*--------------------------------------------------------------------------
466f220fa62Smrg * xformCulling - transform a set of points that may be EITHER
467f220fa62Smrg *	homogeneous or inhomogeneous depending on the map description
468f220fa62Smrg *	into culling space
469f220fa62Smrg *--------------------------------------------------------------------------
470f220fa62Smrg */
471f220fa62Smrgvoid
472f220fa62SmrgMapdesc::xformCulling( REAL *pts, int order, int stride, REAL *cp, int outstride )
473f220fa62Smrg{
474f220fa62Smrg    xformMat( cmat, pts, order, stride, cp, outstride );
475f220fa62Smrg}
476f220fa62Smrg
477f220fa62Smrg/*--------------------------------------------------------------------------
478f220fa62Smrg * xformCulling - transform a set of points that may be EITHER
479f220fa62Smrg *	homogeneous or inhomogeneous depending on the map description
480f220fa62Smrg *	into culling space
481f220fa62Smrg *--------------------------------------------------------------------------
482f220fa62Smrg */
483f220fa62Smrgvoid
484f220fa62SmrgMapdesc::xformCulling( REAL *pts,
485f220fa62Smrg    int uorder, int ustride,
486f220fa62Smrg    int vorder, int vstride,
487f220fa62Smrg    REAL *cp, int outustride, int outvstride )
488f220fa62Smrg{
489f220fa62Smrg    xformMat( cmat, pts, uorder, ustride, vorder, vstride, cp, outustride, outvstride );
490f220fa62Smrg}
491f220fa62Smrg
492f220fa62Smrg/*--------------------------------------------------------------------------
493f220fa62Smrg * xformSampling - transform a set of points that may be EITHER
494f220fa62Smrg *	homogeneous or inhomogeneous depending on the map description
495f220fa62Smrg *	into sampling space
496f220fa62Smrg *--------------------------------------------------------------------------
497f220fa62Smrg */
498f220fa62Smrgvoid
499f220fa62SmrgMapdesc::xformSampling( REAL *pts,
500f220fa62Smrg    int uorder, int ustride,
501f220fa62Smrg    int vorder, int vstride,
502f220fa62Smrg    REAL *sp, int outustride, int outvstride )
503f220fa62Smrg{
504f220fa62Smrg    xformMat( smat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
505f220fa62Smrg}
506f220fa62Smrg
507f220fa62Smrgvoid
508f220fa62SmrgMapdesc::xformBounding( REAL *pts,
509f220fa62Smrg    int uorder, int ustride,
510f220fa62Smrg    int vorder, int vstride,
511f220fa62Smrg    REAL *sp, int outustride, int outvstride )
512f220fa62Smrg{
513f220fa62Smrg    xformMat( bmat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
514f220fa62Smrg}
515f220fa62Smrg
516f220fa62Smrgvoid
517f220fa62SmrgMapdesc::xformMat(
518f220fa62Smrg    Maxmatrix	mat,
519f220fa62Smrg    REAL *	pts,
520f220fa62Smrg    int 	order,
521f220fa62Smrg    int 	stride,
522f220fa62Smrg    REAL *	cp,
523f220fa62Smrg    int 	outstride )
524f220fa62Smrg{
525f220fa62Smrg    if( isrational ) {
526f220fa62Smrg	REAL *pend = pts + order * stride;
527f220fa62Smrg	for( REAL *p = pts ; p != pend; p += stride ) {
528f220fa62Smrg	    xformRational( mat, cp, p );
529f220fa62Smrg	    cp += outstride;
530f220fa62Smrg	}
531f220fa62Smrg    } else {
532f220fa62Smrg	REAL *pend = pts + order * stride;
533f220fa62Smrg	for( REAL *p = pts ; p != pend; p += stride ) {
534f220fa62Smrg	    xformNonrational( mat, cp, p );
535f220fa62Smrg	    cp += outstride;
536f220fa62Smrg	}
537f220fa62Smrg    }
538f220fa62Smrg}
539f220fa62Smrg
540f220fa62Smrgvoid
541f220fa62SmrgMapdesc::xformMat( Maxmatrix mat, REAL *pts,
542f220fa62Smrg    int uorder, int ustride,
543f220fa62Smrg    int vorder, int vstride,
544f220fa62Smrg    REAL *cp, int outustride, int outvstride )
545f220fa62Smrg{
546f220fa62Smrg    if( isrational ) {
547f220fa62Smrg	REAL *pend = pts + uorder * ustride;
548f220fa62Smrg	for( REAL *p = pts ; p != pend; p += ustride ) {
549f220fa62Smrg	    REAL *cpts2 = cp;
550f220fa62Smrg	    REAL *qend = p + vorder * vstride;
551f220fa62Smrg	    for( REAL *q = p; q != qend; q += vstride ) {
552f220fa62Smrg		xformRational( mat, cpts2, q );
553f220fa62Smrg		cpts2 += outvstride;
554f220fa62Smrg	    }
555f220fa62Smrg	    cp += outustride;
556f220fa62Smrg	}
557f220fa62Smrg    } else {
558f220fa62Smrg	REAL *pend = pts + uorder * ustride;
559f220fa62Smrg	for( REAL *p = pts ; p != pend; p += ustride ) {
560f220fa62Smrg	    REAL *cpts2 = cp;
561f220fa62Smrg	    REAL *qend = p + vorder * vstride;
562f220fa62Smrg	    for( REAL *q = p; q != qend; q += vstride ) {
563f220fa62Smrg		xformNonrational( mat, cpts2, q );
564f220fa62Smrg		cpts2 += outvstride;
565f220fa62Smrg	    }
566f220fa62Smrg	    cp += outustride;
567f220fa62Smrg	}
568f220fa62Smrg    }
569f220fa62Smrg}
570f220fa62Smrg
571f220fa62Smrg/*--------------------------------------------------------------------------
572f220fa62Smrg * subdivide - subdivide a curve along an isoparametric line
573f220fa62Smrg *--------------------------------------------------------------------------
574f220fa62Smrg */
575f220fa62Smrg
576f220fa62Smrgvoid
577f220fa62SmrgMapdesc::subdivide( REAL *src, REAL *dst, REAL v, int stride, int order )
578f220fa62Smrg{
579f220fa62Smrg    REAL mv = 1.0 - v;
580f220fa62Smrg
581f220fa62Smrg    for( REAL *send=src+stride*order; src!=send; send-=stride, dst+=stride ) {
582f220fa62Smrg	copyPt( dst, src );
583f220fa62Smrg	REAL *qpnt = src + stride;
584f220fa62Smrg	for( REAL *qp=src; qpnt!=send; qp=qpnt, qpnt+=stride )
585f220fa62Smrg	    sumPt( qp, qp, qpnt, mv, v );
586f220fa62Smrg    }
587f220fa62Smrg}
588f220fa62Smrg
589f220fa62Smrg/*--------------------------------------------------------------------------
590f220fa62Smrg * subdivide - subdivide a patch along an isoparametric line
591f220fa62Smrg *--------------------------------------------------------------------------
592f220fa62Smrg */
593f220fa62Smrg
594f220fa62Smrgvoid
595f220fa62SmrgMapdesc::subdivide( REAL *src, REAL *dst, REAL v,
596f220fa62Smrg    int so, int ss, int to, int ts  )
597f220fa62Smrg{
598f220fa62Smrg    REAL mv = 1.0 - v;
599f220fa62Smrg
600f220fa62Smrg    for( REAL *slast = src+ss*so; src != slast; src += ss, dst += ss ) {
601f220fa62Smrg	REAL *sp = src;
602f220fa62Smrg	REAL *dp = dst;
603f220fa62Smrg        for( REAL *send = src+ts*to; sp != send; send -= ts, dp += ts ) {
604f220fa62Smrg	    copyPt( dp, sp );
605f220fa62Smrg	    REAL *qp = sp;
606f220fa62Smrg	    for( REAL *qpnt = sp+ts; qpnt != send; qp = qpnt, qpnt += ts )
607f220fa62Smrg	        sumPt( qp, qp, qpnt, mv, v );
608f220fa62Smrg	}
609f220fa62Smrg    }
610f220fa62Smrg}
611f220fa62Smrg
612f220fa62Smrg
613f220fa62Smrg#define sign(x)	((x > 0) ? 1 : ((x < 0.0) ? -1 : 0))
614f220fa62Smrg
615f220fa62Smrg/*--------------------------------------------------------------------------
616f220fa62Smrg * project - project a set of homogeneous coordinates into inhomogeneous ones
617f220fa62Smrg *--------------------------------------------------------------------------
618f220fa62Smrg */
619f220fa62Smrgint
620f220fa62SmrgMapdesc::project( REAL *src, int rstride, int cstride,
621f220fa62Smrg	          REAL *dest, int trstride, int tcstride,
622f220fa62Smrg		  int nrows, int ncols )
623f220fa62Smrg{
624f220fa62Smrg    int s = sign( src[inhcoords] );
625f220fa62Smrg    REAL *rlast = src + nrows * rstride;
626f220fa62Smrg    REAL *trptr = dest;
627f220fa62Smrg    for( REAL *rptr=src; rptr != rlast; rptr+=rstride, trptr+=trstride ) {
628f220fa62Smrg	REAL *clast = rptr + ncols * cstride;
629f220fa62Smrg	REAL *tcptr = trptr;
630f220fa62Smrg	for( REAL *cptr = rptr; cptr != clast; cptr+=cstride, tcptr+=tcstride ) {
631f220fa62Smrg	    REAL *coordlast = cptr + inhcoords;
632f220fa62Smrg	    if( sign( *coordlast ) != s ) return 0;
633f220fa62Smrg	    REAL *tcoord = tcptr;
634f220fa62Smrg	    for( REAL *coord = cptr; coord != coordlast; coord++, tcoord++ ) {
635f220fa62Smrg		*tcoord = *coord / *coordlast;
636f220fa62Smrg	    }
637f220fa62Smrg	}
638f220fa62Smrg    }
639f220fa62Smrg    return 1;
640f220fa62Smrg}
641f220fa62Smrg
642f220fa62Smrg/*--------------------------------------------------------------------------
643f220fa62Smrg * project - project a set of homogeneous coordinates into inhomogeneous ones
644f220fa62Smrg *--------------------------------------------------------------------------
645f220fa62Smrg */
646f220fa62Smrgint
647f220fa62SmrgMapdesc::project( REAL *src, int stride, REAL *dest, int tstride, int ncols )
648f220fa62Smrg{
649f220fa62Smrg    int s = sign( src[inhcoords] );
650f220fa62Smrg
651f220fa62Smrg    REAL *clast = src + ncols * stride;
652f220fa62Smrg    for( REAL *cptr = src, *tcptr = dest; cptr != clast; cptr+=stride, tcptr+=tstride ) {
653f220fa62Smrg	REAL *coordlast = cptr + inhcoords;
654f220fa62Smrg	if( sign( *coordlast ) != s ) return 0;
655f220fa62Smrg	for( REAL *coord = cptr, *tcoord = tcptr; coord != coordlast; coord++, tcoord++ )
656f220fa62Smrg	    *tcoord = *coord / *coordlast;
657f220fa62Smrg    }
658f220fa62Smrg
659f220fa62Smrg    return 1;
660f220fa62Smrg}
661f220fa62Smrg
662f220fa62Smrgint
663f220fa62SmrgMapdesc::bboxTooBig(
664f220fa62Smrg    REAL *p,
665f220fa62Smrg    int	 rstride,
666f220fa62Smrg    int	 cstride,
667f220fa62Smrg    int	 nrows,
668f220fa62Smrg    int	 ncols,
669f220fa62Smrg    REAL bb[2][MAXCOORDS] )
670f220fa62Smrg{
671f220fa62Smrg    REAL bbpts[MAXORDER][MAXORDER][MAXCOORDS];
672f220fa62Smrg    const int trstride = sizeof(bbpts[0]) / sizeof(REAL);
673f220fa62Smrg    const int tcstride = sizeof(bbpts[0][0]) / sizeof(REAL);
674f220fa62Smrg
675f220fa62Smrg    // points have been transformed, therefore they are homogeneous
676f220fa62Smrg    // project points
677f220fa62Smrg    int val = project( p, rstride, cstride,
678f220fa62Smrg	     &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
679f220fa62Smrg    if( val == 0 ) return -1;
680f220fa62Smrg
681f220fa62Smrg    // compute bounding box
682f220fa62Smrg    bbox( bb, &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
683f220fa62Smrg
684f220fa62Smrg    // find out if bounding box can't fit in unit cube
685f220fa62Smrg    if( bbox_subdividing == N_BBOXROUND ) {
686f220fa62Smrg	for( int k=0; k != inhcoords; k++ )
687f220fa62Smrg	    if( ceilf(bb[1][k]) - floorf(bb[0][k]) > bboxsize[k] ) return 1;
688f220fa62Smrg    } else {
689f220fa62Smrg	for( int k=0; k != inhcoords; k++ )
690f220fa62Smrg	    if( bb[1][k] - bb[0][k] > bboxsize[k] ) return 1;
691f220fa62Smrg    }
692f220fa62Smrg    return 0;
693f220fa62Smrg}
694f220fa62Smrg
695f220fa62Smrgvoid
696f220fa62SmrgMapdesc::bbox(
697f220fa62Smrg    REAL bb[2][MAXCOORDS],
698f220fa62Smrg    REAL *p,
699f220fa62Smrg    int	 rstride,
700f220fa62Smrg    int	 cstride,
701f220fa62Smrg    int	 nrows,
702f220fa62Smrg    int	 ncols )
703f220fa62Smrg{
704f220fa62Smrg    int k;
705f220fa62Smrg    for( k=0; k != inhcoords; k++ )
706f220fa62Smrg	 bb[0][k] = bb[1][k] = p[k];
707f220fa62Smrg
708f220fa62Smrg    for( int i=0; i != nrows; i++ )
709f220fa62Smrg	for( int j=0; j != ncols; j++ )
710f220fa62Smrg	    for( k=0; k != inhcoords; k++ ) {
711f220fa62Smrg		REAL x = p[i*rstride + j*cstride + k];
712f220fa62Smrg		if(  x < bb[0][k] ) bb[0][k] = x;
713f220fa62Smrg		else if( x > bb[1][k] ) bb[1][k] = x;
714f220fa62Smrg	    }
715f220fa62Smrg}
716f220fa62Smrg
717f220fa62Smrg/*--------------------------------------------------------------------------
718f220fa62Smrg * calcVelocityRational - calculate upper bound on first partial derivative
719f220fa62Smrg *	of a homogeneous set of points and bounds on each row of points.
720f220fa62Smrg *--------------------------------------------------------------------------
721f220fa62Smrg */
722f220fa62SmrgREAL
723f220fa62SmrgMapdesc::calcVelocityRational( REAL *p, int stride, int ncols )
724f220fa62Smrg{
725f220fa62Smrg    REAL tmp[MAXORDER][MAXCOORDS];
726f220fa62Smrg
727f220fa62Smrg    assert( ncols <= MAXORDER );
728f220fa62Smrg
729f220fa62Smrg    const int tstride = sizeof(tmp[0]) / sizeof(REAL);
730f220fa62Smrg
731f220fa62Smrg    if( project( p, stride, &tmp[0][0], tstride, ncols ) ) {
732f220fa62Smrg	return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
733f220fa62Smrg    } else { /* XXX */
734f220fa62Smrg	return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
735f220fa62Smrg    }
736f220fa62Smrg}
737f220fa62Smrg
738f220fa62Smrg/*--------------------------------------------------------------------------
739f220fa62Smrg * calcVelocityNonrational - calculate upper bound on  first partial
740f220fa62Smrg *	derivative of a inhomogeneous set of points.
741f220fa62Smrg *--------------------------------------------------------------------------
742f220fa62Smrg */
743f220fa62SmrgREAL
744f220fa62SmrgMapdesc::calcVelocityNonrational( REAL *pts, int stride, int ncols )
745f220fa62Smrg{
746f220fa62Smrg    return calcPartialVelocity( pts, stride, ncols, 1, 1.0 );
747f220fa62Smrg}
748f220fa62Smrg
749f220fa62Smrgint
750f220fa62SmrgMapdesc::isProperty( long property )
751f220fa62Smrg{
752f220fa62Smrg    switch ( property ) {
753f220fa62Smrg	case N_PIXEL_TOLERANCE:
754f220fa62Smrg	case N_ERROR_TOLERANCE:
755f220fa62Smrg	case N_CULLING:
756f220fa62Smrg	case N_BBOX_SUBDIVIDING:
757f220fa62Smrg	case N_S_STEPS:
758f220fa62Smrg	case N_T_STEPS:
759f220fa62Smrg        case N_SAMPLINGMETHOD:
760f220fa62Smrg        case N_CLAMPFACTOR:
761f220fa62Smrg        case N_MINSAVINGS:
762f220fa62Smrg	    return 1;
763f220fa62Smrg	default:
764f220fa62Smrg	    return 0;
765f220fa62Smrg    }
766f220fa62Smrg}
767f220fa62Smrg
768f220fa62SmrgREAL
769f220fa62SmrgMapdesc::getProperty( long property )
770f220fa62Smrg{
771f220fa62Smrg    switch ( property ) {
772f220fa62Smrg	case N_PIXEL_TOLERANCE:
773f220fa62Smrg	    return pixel_tolerance;
774f220fa62Smrg	case N_ERROR_TOLERANCE:
775f220fa62Smrg	    return error_tolerance;
776f220fa62Smrg	case N_CULLING:
777f220fa62Smrg	    return culling_method;
778f220fa62Smrg	case N_BBOX_SUBDIVIDING:
779f220fa62Smrg	    return bbox_subdividing;
780f220fa62Smrg	case N_S_STEPS:
781f220fa62Smrg	    return s_steps;
782f220fa62Smrg	case N_T_STEPS:
783f220fa62Smrg	    return t_steps;
784f220fa62Smrg        case N_SAMPLINGMETHOD:
785f220fa62Smrg	    return sampling_method;
786f220fa62Smrg        case N_CLAMPFACTOR:
787f220fa62Smrg	    return clampfactor;
788f220fa62Smrg        case N_MINSAVINGS:
789f220fa62Smrg	    return minsavings;
790f220fa62Smrg	default:
791f220fa62Smrg	    abort();
792f220fa62Smrg	    return -1; //not necessary, needed to shut up compiler
793f220fa62Smrg    }
794f220fa62Smrg}
795f220fa62Smrg
796f220fa62Smrgvoid
797f220fa62SmrgMapdesc::setProperty( long property, REAL value )
798f220fa62Smrg{
799f220fa62Smrg
800f220fa62Smrg    switch ( property ) {
801f220fa62Smrg	case N_PIXEL_TOLERANCE:
802f220fa62Smrg	    pixel_tolerance = value;
803f220fa62Smrg	    break;
804f220fa62Smrg	case N_ERROR_TOLERANCE:
805f220fa62Smrg	    error_tolerance = value;
806f220fa62Smrg	    break;
807f220fa62Smrg	case N_CULLING:
808f220fa62Smrg	    culling_method = value;
809f220fa62Smrg	    break;
810f220fa62Smrg	case N_BBOX_SUBDIVIDING:
811f220fa62Smrg	    if( value <= 0.0 ) value = N_NOBBOXSUBDIVISION;
812f220fa62Smrg	    bbox_subdividing = value;
813f220fa62Smrg	    break;
814f220fa62Smrg	case N_S_STEPS:
815f220fa62Smrg	    if( value < 0.0 ) value = 0.0;
816f220fa62Smrg	    s_steps = value;
817f220fa62Smrg	    maxrate = ( value < 0.0 ) ? 0.0 : value;
818f220fa62Smrg	    maxsrate = ( value < 0.0 ) ? 0.0 : value;
819f220fa62Smrg	    break;
820f220fa62Smrg	case N_T_STEPS:
821f220fa62Smrg	    if( value < 0.0 ) value = 0.0;
822f220fa62Smrg	    t_steps = value;
823f220fa62Smrg	    maxtrate = ( value < 0.0 ) ? 0.0 : value;
824f220fa62Smrg	    break;
825f220fa62Smrg	case N_SAMPLINGMETHOD:
826f220fa62Smrg	    sampling_method = value;
827f220fa62Smrg	    break;
828f220fa62Smrg	case N_CLAMPFACTOR:
829f220fa62Smrg	    if( value <= 0.0 ) value = N_NOCLAMPING;
830f220fa62Smrg	    clampfactor = value;
831f220fa62Smrg	    break;
832f220fa62Smrg	case N_MINSAVINGS:
833f220fa62Smrg	    if( value <= 0.0 ) value = N_NOSAVINGSSUBDIVISION;
834f220fa62Smrg	    minsavings = value;
835f220fa62Smrg	    break;
836f220fa62Smrg	default:
837f220fa62Smrg	    abort();
838f220fa62Smrg	    break;
839f220fa62Smrg    }
840f220fa62Smrg}
841f220fa62Smrg
842