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