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 * monotonizer.c++ 37f220fa62Smrg * 38f220fa62Smrg */ 39f220fa62Smrg 40f220fa62Smrg#include "glimports.h" 41f220fa62Smrg#include "mystdio.h" 42f220fa62Smrg#include "myassert.h" 43f220fa62Smrg#include "arc.h" 44f220fa62Smrg#include "arctess.h" 45f220fa62Smrg#include "bezierarc.h" 46f220fa62Smrg#include "bin.h" 47f220fa62Smrg#include "mapdesc.h" 48f220fa62Smrg#include "nurbsconsts.h" 49f220fa62Smrg#include "subdivider.h" 50f220fa62Smrg 51f220fa62Smrg/*----------------------------------------------------------------------------- 52f220fa62Smrg * Subdivider::decompose - break all curves into monotone arcs 53f220fa62Smrg *----------------------------------------------------------------------------- 54f220fa62Smrg */ 55f220fa62Smrgint 56f220fa62SmrgSubdivider::decompose( Bin& bin, REAL geo_stepsize ) 57f220fa62Smrg{ 58f220fa62Smrg Arc_ptr jarc; 59f220fa62Smrg for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 60f220fa62Smrg if( ! jarc->isTessellated() ) { 61f220fa62Smrg /* points have not been transformed, therefore they may be either 62f220fa62Smrg homogeneous or inhomogeneous */ 63f220fa62Smrg tessellate( jarc, geo_stepsize ); 64f220fa62Smrg if( jarc->isDisconnected() || jarc->next->isDisconnected() ) 65f220fa62Smrg return 1; 66f220fa62Smrg } 67f220fa62Smrg } 68f220fa62Smrg 69f220fa62Smrg for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 70f220fa62Smrg monotonize( jarc, bin ); 71f220fa62Smrg } 72f220fa62Smrg 73f220fa62Smrg#ifndef NDEBUG 74f220fa62Smrg for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) { 75f220fa62Smrg assert( isMonotone( jarc ) != 0 ); 76f220fa62Smrg } 77f220fa62Smrg#endif 78f220fa62Smrg 79f220fa62Smrg return 0; 80f220fa62Smrg} 81f220fa62Smrg 82f220fa62Smrgvoid 83f220fa62SmrgSubdivider::tessellate( Arc_ptr jarc, REAL geo_stepsize ) 84f220fa62Smrg{ 85f220fa62Smrg BezierArc *b = jarc->bezierArc; 86f220fa62Smrg Mapdesc *mapdesc = b->mapdesc; 87f220fa62Smrg 88f220fa62Smrg if( mapdesc->isRational() ) { 89f220fa62Smrg REAL max = mapdesc->calcVelocityRational( b->cpts, b->stride, b->order ); 90f220fa62Smrg REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0; 91f220fa62Smrg if( jarc->bezierArc->order != 2 ) 92f220fa62Smrg arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 1 ); 93f220fa62Smrg else { 94f220fa62Smrg arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 1 ); 95f220fa62Smrg } 96f220fa62Smrg } else { 97f220fa62Smrg REAL max = mapdesc->calcVelocityNonrational( b->cpts, b->stride, b->order ); 98f220fa62Smrg REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0; 99f220fa62Smrg if( jarc->bezierArc->order != 2 ) 100f220fa62Smrg arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 0 ); 101f220fa62Smrg else { 102f220fa62Smrg arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 0 ); 103f220fa62Smrg } 104f220fa62Smrg } 105f220fa62Smrg} 106f220fa62Smrg 107f220fa62Smrg/*------------------------------------------------------------------------- 108f220fa62Smrg * Subdivider::monotonize - break up a jordan arc into s,t-monotone 109f220fa62Smrg * components. This code will remove degenerate segments, including 110f220fa62Smrg * arcs of only a single point. 111f220fa62Smrg *------------------------------------------------------------------------- 112f220fa62Smrg */ 113f220fa62Smrgvoid 114f220fa62SmrgSubdivider::monotonize( Arc_ptr jarc, Bin& bin ) 115f220fa62Smrg{ 116f220fa62Smrg TrimVertex *firstvert = jarc->pwlArc->pts; 117f220fa62Smrg TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1); 118f220fa62Smrg long uid = jarc->nuid; 119f220fa62Smrg arc_side side = jarc->getside(); 120f220fa62Smrg dir sdir = none; 121f220fa62Smrg dir tdir = none; 122f220fa62Smrg int degenerate = 1; 123f220fa62Smrg 124f220fa62Smrg int nudegenerate; 125f220fa62Smrg int change; 126f220fa62Smrg 127f220fa62Smrg TrimVertex *vert; 128f220fa62Smrg for( vert = firstvert; vert != lastvert; vert++ ) { 129f220fa62Smrg 130f220fa62Smrg nudegenerate = 1; 131f220fa62Smrg change = 0; 132f220fa62Smrg 133f220fa62Smrg /* check change relative to s axis, clear degenerate bit if needed */ 134f220fa62Smrg REAL sdiff = vert[1].param[0] - vert[0].param[0]; 135f220fa62Smrg if( sdiff == 0 ) { 136f220fa62Smrg if( sdir != same ) { 137f220fa62Smrg sdir = same; 138f220fa62Smrg change = 1; 139f220fa62Smrg } 140f220fa62Smrg } else if( sdiff < 0.0 ) { 141f220fa62Smrg if( sdir != down ) { 142f220fa62Smrg sdir = down; 143f220fa62Smrg change = 1; 144f220fa62Smrg } 145f220fa62Smrg nudegenerate = 0; 146f220fa62Smrg } else { 147f220fa62Smrg if( sdir != up ) { 148f220fa62Smrg sdir = up; 149f220fa62Smrg change = 1; 150f220fa62Smrg } 151f220fa62Smrg nudegenerate = 0; 152f220fa62Smrg } 153f220fa62Smrg 154f220fa62Smrg /* check change relative to t axis, clear degenerate bit if needed */ 155f220fa62Smrg REAL tdiff = vert[1].param[1] - vert[0].param[1]; 156f220fa62Smrg if( tdiff == 0 ) { 157f220fa62Smrg if( tdir != same ) { 158f220fa62Smrg tdir = same; 159f220fa62Smrg change = 1; 160f220fa62Smrg } 161f220fa62Smrg } else if( tdiff < 0.0 ) { 162f220fa62Smrg if( tdir != down ) { 163f220fa62Smrg tdir = down; 164f220fa62Smrg change = 1; 165f220fa62Smrg } 166f220fa62Smrg nudegenerate = 0; 167f220fa62Smrg } else { 168f220fa62Smrg if( tdir != up ) { 169f220fa62Smrg tdir = up; 170f220fa62Smrg change = 1; 171f220fa62Smrg } 172f220fa62Smrg nudegenerate = 0; 173f220fa62Smrg } 174f220fa62Smrg 175f220fa62Smrg if( change ) { 176f220fa62Smrg if( ! degenerate ) { 177f220fa62Smrg /* make last segment into separate pwl curve */ 178f220fa62Smrg jarc->pwlArc->npts = vert - firstvert + 1; 179f220fa62Smrg jarc = (new(arcpool) Arc( side, uid ))->append( jarc ); 180f220fa62Smrg jarc->pwlArc = new(pwlarcpool) PwlArc(); 181f220fa62Smrg bin.addarc( jarc ); 182f220fa62Smrg } 183f220fa62Smrg firstvert = jarc->pwlArc->pts = vert; 184f220fa62Smrg degenerate = nudegenerate; 185f220fa62Smrg } 186f220fa62Smrg } 187f220fa62Smrg jarc->pwlArc->npts = vert - firstvert + 1; 188f220fa62Smrg 189f220fa62Smrg if( degenerate ) { 190f220fa62Smrg /* remove jarc from circularly linked list */ 191f220fa62Smrg jarc->prev->next = jarc->next; 192f220fa62Smrg jarc->next->prev = jarc->prev; 193f220fa62Smrg 194f220fa62Smrg assert( jarc->prev->check( ) != 0 ); 195f220fa62Smrg assert( jarc->next->check( ) != 0 ); 196f220fa62Smrg 197f220fa62Smrg /* remove jarc from bin */ 198f220fa62Smrg bin.remove_this_arc( jarc ); 199f220fa62Smrg 200f220fa62Smrg jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0; 201f220fa62Smrg jarc->deleteMe( arcpool ); 202f220fa62Smrg } 203f220fa62Smrg} 204f220fa62Smrg 205f220fa62Smrg/*------------------------------------------------------------------------- 206f220fa62Smrg * Subdivider::isMonotone - return true if arc is monotone AND non-degenerate 207f220fa62Smrg *------------------------------------------------------------------------- 208f220fa62Smrg */ 209f220fa62Smrgint 210f220fa62SmrgSubdivider::isMonotone( Arc_ptr jarc ) 211f220fa62Smrg{ 212f220fa62Smrg TrimVertex *firstvert = jarc->pwlArc->pts; 213f220fa62Smrg TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1); 214f220fa62Smrg 215f220fa62Smrg if( firstvert == lastvert ) return 1; 216f220fa62Smrg 217f220fa62Smrg TrimVertex *vert = firstvert; 218f220fa62Smrg enum dir sdir; 219f220fa62Smrg enum dir tdir; 220f220fa62Smrg 221f220fa62Smrg REAL diff = vert[1].param[0] - vert[0].param[0]; 222f220fa62Smrg if( diff == 0.0 ) 223f220fa62Smrg sdir = same; 224f220fa62Smrg else if( diff < 0.0 ) 225f220fa62Smrg sdir = down; 226f220fa62Smrg else 227f220fa62Smrg sdir = up; 228f220fa62Smrg 229f220fa62Smrg diff = vert[1].param[1] - vert[0].param[1]; 230f220fa62Smrg if( diff == 0.0 ) 231f220fa62Smrg tdir = same; 232f220fa62Smrg else if( diff < 0.0 ) 233f220fa62Smrg tdir = down; 234f220fa62Smrg else 235f220fa62Smrg tdir = up; 236f220fa62Smrg 237f220fa62Smrg if( (sdir == same) && (tdir == same) ) return 0; 238f220fa62Smrg 239f220fa62Smrg for( ++vert ; vert != lastvert; vert++ ) { 240f220fa62Smrg diff = vert[1].param[0] - vert[0].param[0]; 241f220fa62Smrg if( diff == 0.0 ) { 242f220fa62Smrg if( sdir != same ) return 0; 243f220fa62Smrg } else if( diff < 0.0 ) { 244f220fa62Smrg if( sdir != down ) return 0; 245f220fa62Smrg } else { 246f220fa62Smrg if( sdir != up ) return 0; 247f220fa62Smrg } 248f220fa62Smrg 249f220fa62Smrg diff = vert[1].param[1] - vert[0].param[1]; 250f220fa62Smrg if( diff == 0.0 ) { 251f220fa62Smrg if( tdir != same ) return 0; 252f220fa62Smrg } else if( diff < 0.0 ) { 253f220fa62Smrg if( tdir != down ) return 0; 254f220fa62Smrg } else { 255f220fa62Smrg if( tdir != up ) return 0; 256f220fa62Smrg } 257f220fa62Smrg } 258f220fa62Smrg return 1; 259f220fa62Smrg} 260f220fa62Smrg 261