📄 patch.cc
字号:
/*
** License Applicability. Except to the extent portions of this file are
** made subject to an alternative license as permitted in the SGI Free
** Software License B, Version 1.1 (the "License"), the contents of this
** file are subject only to the provisions of the License. You may not use
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
**
** http://oss.sgi.com/projects/FreeB
**
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
**
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
**
** Additional Notice Provisions: The application programming interfaces
** established by SGI in conjunction with the Original Code are The
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
** Window System(R) (Version 1.3), released October 19, 1998. This software
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
** published by SGI, but has not been independently verified as being
** compliant with the OpenGL(R) version 1.2.1 Specification.
*/
/*
* patch.c++
*
* $Date: 2006-03-11 18:07:02 -0600 (Sat, 11 Mar 2006) $ $Revision: 1.1 $
* $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/internals/patch.cc,v 1.1 2004/02/02 16:39:12 navaraf Exp $
*/
#include <stdio.h>
#include "glimports.h"
#include "mystdio.h"
#include "myassert.h"
#include "mymath.h"
#include "mystring.h"
#include "patch.h"
#include "mapdesc.h"
#include "quilt.h"
#include "nurbsconsts.h"
#include "simplemath.h" //for glu_abs function in ::singleStep();
/*--------------------------------------------------------------------------
* Patch - copy patch from quilt and transform control points
*--------------------------------------------------------------------------
*/
Patch::Patch( Quilt_ptr geo, REAL *pta, REAL *ptb, Patch *n )
{
/* pspec[i].range is uninit here */
mapdesc = geo->mapdesc;
cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT;
notInBbox = mapdesc->isBboxSubdividing() ? 1 : 0;
needsSampling = mapdesc->isRangeSampling() ? 1 : 0;
pspec[0].order = geo->qspec[0].order;
pspec[1].order = geo->qspec[1].order;
pspec[0].stride = pspec[1].order * MAXCOORDS;
pspec[1].stride = MAXCOORDS;
/* transform control points to sampling and culling spaces */
REAL *ps = geo->cpts;
geo->select( pta, ptb );
ps += geo->qspec[0].offset;
ps += geo->qspec[1].offset;
ps += geo->qspec[0].index * geo->qspec[0].order * geo->qspec[0].stride;
ps += geo->qspec[1].index * geo->qspec[1].order * geo->qspec[1].stride;
if( needsSampling ) {
mapdesc->xformSampling( ps, geo->qspec[0].order, geo->qspec[0].stride,
geo->qspec[1].order, geo->qspec[1].stride,
spts, pspec[0].stride, pspec[1].stride );
}
if( cullval == CULL_ACCEPT ) {
mapdesc->xformCulling( ps, geo->qspec[0].order, geo->qspec[0].stride,
geo->qspec[1].order, geo->qspec[1].stride,
cpts, pspec[0].stride, pspec[1].stride );
}
if( notInBbox ) {
mapdesc->xformBounding( ps, geo->qspec[0].order, geo->qspec[0].stride,
geo->qspec[1].order, geo->qspec[1].stride,
bpts, pspec[0].stride, pspec[1].stride );
}
/* set scale range */
pspec[0].range[0] = geo->qspec[0].breakpoints[geo->qspec[0].index];
pspec[0].range[1] = geo->qspec[0].breakpoints[geo->qspec[0].index+1];
pspec[0].range[2] = pspec[0].range[1] - pspec[0].range[0];
pspec[1].range[0] = geo->qspec[1].breakpoints[geo->qspec[1].index];
pspec[1].range[1] = geo->qspec[1].breakpoints[geo->qspec[1].index+1];
pspec[1].range[2] = pspec[1].range[1] - pspec[1].range[0];
// may need to subdivide to match range of sub-patch
if( pspec[0].range[0] != pta[0] ) {
assert( pspec[0].range[0] < pta[0] );
Patch lower( *this, 0, pta[0], 0 );
*this = lower;
}
if( pspec[0].range[1] != ptb[0] ) {
assert( pspec[0].range[1] > ptb[0] );
Patch upper( *this, 0, ptb[0], 0 );
}
if( pspec[1].range[0] != pta[1] ) {
assert( pspec[1].range[0] < pta[1] );
Patch lower( *this, 1, pta[1], 0 );
*this = lower;
}
if( pspec[1].range[1] != ptb[1] ) {
assert( pspec[1].range[1] > ptb[1] );
Patch upper( *this, 1, ptb[1], 0 );
}
checkBboxConstraint();
next = n;
}
/*--------------------------------------------------------------------------
* Patch - subdivide a patch along an isoparametric line
*--------------------------------------------------------------------------
*/
Patch::Patch( Patch& upper, int param, REAL value, Patch *n )
{
Patch& lower = *this;
lower.cullval = upper.cullval;
lower.mapdesc = upper.mapdesc;
lower.notInBbox = upper.notInBbox;
lower.needsSampling = upper.needsSampling;
lower.pspec[0].order = upper.pspec[0].order;
lower.pspec[1].order = upper.pspec[1].order;
lower.pspec[0].stride = upper.pspec[0].stride;
lower.pspec[1].stride = upper.pspec[1].stride;
lower.next = n;
/* reset scale range */
switch( param ) {
case 0: {
REAL d = (value-upper.pspec[0].range[0]) / upper.pspec[0].range[2];
if( needsSampling )
mapdesc->subdivide( upper.spts, lower.spts, d, pspec[1].order,
pspec[1].stride, pspec[0].order, pspec[0].stride );
if( cullval == CULL_ACCEPT )
mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[1].order,
pspec[1].stride, pspec[0].order, pspec[0].stride );
if( notInBbox )
mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[1].order,
pspec[1].stride, pspec[0].order, pspec[0].stride );
lower.pspec[0].range[0] = upper.pspec[0].range[0];
lower.pspec[0].range[1] = value;
lower.pspec[0].range[2] = value - upper.pspec[0].range[0];
upper.pspec[0].range[0] = value;
upper.pspec[0].range[2] = upper.pspec[0].range[1] - value;
lower.pspec[1].range[0] = upper.pspec[1].range[0];
lower.pspec[1].range[1] = upper.pspec[1].range[1];
lower.pspec[1].range[2] = upper.pspec[1].range[2];
break;
}
case 1: {
REAL d = (value-upper.pspec[1].range[0]) / upper.pspec[1].range[2];
if( needsSampling )
mapdesc->subdivide( upper.spts, lower.spts, d, pspec[0].order,
pspec[0].stride, pspec[1].order, pspec[1].stride );
if( cullval == CULL_ACCEPT )
mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[0].order,
pspec[0].stride, pspec[1].order, pspec[1].stride );
if( notInBbox )
mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[0].order,
pspec[0].stride, pspec[1].order, pspec[1].stride );
lower.pspec[0].range[0] = upper.pspec[0].range[0];
lower.pspec[0].range[1] = upper.pspec[0].range[1];
lower.pspec[0].range[2] = upper.pspec[0].range[2];
lower.pspec[1].range[0] = upper.pspec[1].range[0];
lower.pspec[1].range[1] = value;
lower.pspec[1].range[2] = value - upper.pspec[1].range[0];
upper.pspec[1].range[0] = value;
upper.pspec[1].range[2] = upper.pspec[1].range[1] - value;
break;
}
}
// inherit bounding box
if( mapdesc->isBboxSubdividing() && ! notInBbox )
memcpy( lower.bb, upper.bb, sizeof( bb ) );
lower.checkBboxConstraint();
upper.checkBboxConstraint();
}
/*--------------------------------------------------------------------------
* clamp - clamp the sampling rate to a given maximum
*--------------------------------------------------------------------------
*/
void
Patch::clamp( void )
{
if( mapdesc->clampfactor != N_NOCLAMPING ) {
pspec[0].clamp( mapdesc->clampfactor );
pspec[1].clamp( mapdesc->clampfactor );
}
}
void
Patchspec::clamp( REAL clampfactor )
{
if( sidestep[0] < minstepsize )
sidestep[0] = clampfactor * minstepsize;
if( sidestep[1] < minstepsize )
sidestep[1] = clampfactor * minstepsize;
if( stepsize < minstepsize )
stepsize = clampfactor * minstepsize;
}
void
Patch::checkBboxConstraint( void )
{
if( notInBbox &&
mapdesc->bboxTooBig( bpts, pspec[0].stride, pspec[1].stride,
pspec[0].order, pspec[1].order, bb ) != 1 ) {
notInBbox = 0;
}
}
void
Patch::bbox( void )
{
if( mapdesc->isBboxSubdividing() )
mapdesc->surfbbox( bb );
}
/*--------------------------------------------------------------------------
* getstepsize - compute the sampling density across the patch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -