3
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory
5
// Contact: pgregory@aqsis.com
7
// This library is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU 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.
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
// General Public License for more details.
17
// You should have received a copy of the GNU General Public
18
// License along with this library; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
\brief Implements the classes and support structures for handling RenderMan patch primitives.
24
\author Paul C. Gregory (pgregory@aqsis.com)
30
#include "imagebuffer.h"
31
#include "micropolygon.h"
36
START_NAMESPACE( Aqsis )
38
#pragma warning(push, 3)
40
//---------------------------------------------------------------------
41
/** Constructor both u and vbasis matrices default to bezier.
44
CqSurfacePatchBicubic::CqSurfacePatchBicubic() : CqSurface()
46
STATS_INC( GPR_patch );
50
//---------------------------------------------------------------------
54
CqSurfacePatchBicubic::CqSurfacePatchBicubic( const CqSurfacePatchBicubic& From ) :
59
STATS_INC( GPR_patch );
63
//---------------------------------------------------------------------
67
CqSurfacePatchBicubic::~CqSurfacePatchBicubic()
71
//---------------------------------------------------------------------
72
/** Assignment operator.
75
CqSurfacePatchBicubic& CqSurfacePatchBicubic::operator=( const CqSurfacePatchBicubic& From )
77
// Perform per surface copy function
78
CqSurface::operator=( From );
81
// for(i=0; i<16; i++)
82
// P()[i]=From.P()[i];
89
void CqSurfacePatchBicubic::NaturalSubdivide( CqParameter* pParam, CqParameter* pParam1, CqParameter* pParam2, TqBool u )
91
switch ( pParam->Type() )
95
CqParameterTyped<TqFloat, TqFloat>* pTParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam );
96
CqParameterTyped<TqFloat, TqFloat>* pTResult1 = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam1 );
97
CqParameterTyped<TqFloat, TqFloat>* pTResult2 = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam2 );
98
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
104
CqParameterTyped<TqInt, TqFloat>* pTParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam );
105
CqParameterTyped<TqInt, TqFloat>* pTResult1 = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam1 );
106
CqParameterTyped<TqInt, TqFloat>* pTResult2 = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam2 );
107
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
115
CqParameterTyped<CqVector3D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam );
116
CqParameterTyped<CqVector3D, CqVector3D>* pTResult1 = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam1 );
117
CqParameterTyped<CqVector3D, CqVector3D>* pTResult2 = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam2 );
118
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
124
CqParameterTyped<CqVector4D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam );
125
CqParameterTyped<CqVector4D, CqVector3D>* pTResult1 = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam1 );
126
CqParameterTyped<CqVector4D, CqVector3D>* pTResult2 = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam2 );
127
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
134
CqParameterTyped<CqColor, CqColor>* pTParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam );
135
CqParameterTyped<CqColor, CqColor>* pTResult1 = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam1 );
136
CqParameterTyped<CqColor, CqColor>* pTResult2 = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam2 );
137
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
143
CqParameterTyped<CqString, CqString>* pTParam = static_cast<CqParameterTyped<CqString, CqString>*>( pParam );
144
CqParameterTyped<CqString, CqString>* pTResult1 = static_cast<CqParameterTyped<CqString, CqString>*>( pParam1 );
145
CqParameterTyped<CqString, CqString>* pTResult2 = static_cast<CqParameterTyped<CqString, CqString>*>( pParam2 );
146
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
152
// CqParameterTyped<CqMatrix, CqMatrix>* pTParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam );
153
// CqParameterTyped<CqMatrix, CqMatrix>* pTResult1 = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam1 );
154
// CqParameterTyped<CqMatrix, CqMatrix>* pTResult2 = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam2 );
155
// TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
161
// left blank to avoid compiler warnings about unhandled types
168
//---------------------------------------------------------------------
169
/** Get the boundary extents in camera space of the surface patch
172
CqBound CqSurfacePatchBicubic::Bound() const
174
// Get the boundary in camera space.
175
CqVector3D vecA( FLT_MAX, FLT_MAX, FLT_MAX );
176
CqVector3D vecB( -FLT_MAX, -FLT_MAX, -FLT_MAX );
178
for ( i = 0; i < 16; i++ )
180
CqVector3D vecV = P()->pValue( i )[0];
181
if ( vecV.x() < vecA.x() ) vecA.x( vecV.x() );
182
if ( vecV.y() < vecA.y() ) vecA.y( vecV.y() );
183
if ( vecV.x() > vecB.x() ) vecB.x( vecV.x() );
184
if ( vecV.y() > vecB.y() ) vecB.y( vecV.y() );
185
if ( vecV.z() < vecA.z() ) vecA.z( vecV.z() );
186
if ( vecV.z() > vecB.z() ) vecB.z( vecV.z() );
191
return ( AdjustBoundForTransformationMotion( B ) );
195
//---------------------------------------------------------------------
196
/** Dice the patch into a mesh of micropolygons.
200
void CqSurfacePatchBicubic::NaturalDice( CqParameter* pParameter, TqInt uDiceSize, TqInt vDiceSize, IqShaderData* pData )
202
switch ( pParameter->Type() )
206
CqParameterTyped<TqFloat, TqFloat>* pTParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParameter );
207
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
213
CqParameterTyped<TqInt, TqFloat>* pTParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParameter );
214
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
222
CqParameterTyped<CqVector3D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParameter );
223
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
229
CqParameterTyped<CqVector4D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParameter );
230
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
236
CqParameterTyped<CqColor, CqColor>* pTParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParameter );
237
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
243
CqParameterTyped<CqString, CqString>* pTParam = static_cast<CqParameterTyped<CqString, CqString>*>( pParameter );
244
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
250
CqParameterTyped<CqMatrix, CqMatrix>* pTParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParameter );
251
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
257
// left blank to avoid compiler warnings about unhandled types
263
//---------------------------------------------------------------------
264
/** Split the patch into smaller patches.
267
TqInt CqSurfacePatchBicubic::PreSubdivide( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits, TqBool u )
269
// Create two new surface of the appropriate type
270
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBicubic ) );
271
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBicubic ) );
276
//---------------------------------------------------------------------
277
/** Determine whether or not the patch is diceable
280
TqBool CqSurfacePatchBicubic::Diceable()
282
assert( NULL != P() );
283
// If the cull check showed that the primitive cannot be diced due to crossing the e and hither planes,
284
// then we can return immediately.
288
// Otherwise we should continue to try to find the most advantageous split direction, OR the dice size.
289
const CqMatrix & matCtoR = QGetRenderContext() ->matSpaceToSpace( "camera", "raster", CqMatrix(), CqMatrix(), QGetRenderContext()->Time() );
291
// Convert the control hull to raster space.
292
CqVector2D avecHull[ 16 ];
295
TqFloat ShadingRate = pAttributes() ->GetFloatAttribute( "System", "ShadingRate" ) [ 0 ];
297
for ( i = 0; i < 16; i++ )
298
avecHull[ i ] = matCtoR * P()->pValue( i )[0];
300
// First check flatness, a curve which is too far off flat will
301
// produce unreliable results when the length is approximated below.
302
m_SplitDir = SplitDir_U;
304
for ( u = 0; u < 16; u += 4 )
306
// Find an initial line
308
CqVector2D vec0 = avecHull[ u ];
311
while ( i-- > 0 && Len < FLT_EPSILON )
313
vecL = avecHull[ u + i ] - vec0;
314
Len = vecL.Magnitude();
316
vecL /= Len; // Normalise
321
// Get the distance to the line for each point
322
CqVector3D vec = avecHull[ u + i ] - vec0;
325
if ( vec.Magnitude() > 1 ) return ( TqFalse );
328
m_SplitDir = SplitDir_V;
330
for ( v = 0; v < 4; v++ )
332
// Find an initial line
334
CqVector2D vec0 = avecHull[ v ];
337
while ( i-- > 0 && Len < FLT_EPSILON )
339
vecL = avecHull[ v + ( i * 4 ) ] - vec0;
340
Len = vecL.Magnitude();
342
vecL /= Len; // Normalise
347
// Get the distance to the line for each point
348
CqVector3D vec = avecHull[ v + ( i * 4 ) ] - vec0;
351
if ( vec.Magnitude() > 1 ) return ( TqFalse );
359
for ( u = 0; u < 16; u += 4 )
361
CqVector2D Vec1 = avecHull[ u + 1 ] - avecHull[ u ];
362
CqVector2D Vec2 = avecHull[ u + 2 ] - avecHull[ u + 1 ];
363
CqVector2D Vec3 = avecHull[ u + 3 ] - avecHull[ u + 2 ];
364
if ( Vec1.Magnitude2() > uLen ) uLen = Vec1.Magnitude2();
365
if ( Vec2.Magnitude2() > uLen ) uLen = Vec2.Magnitude2();
366
if ( Vec3.Magnitude2() > uLen ) uLen = Vec3.Magnitude2();
368
for ( v = 0; v < 4; v++ )
370
CqVector2D Vec1 = avecHull[ v + 4 ] - avecHull[ v ];
371
CqVector2D Vec2 = avecHull[ v + 8 ] - avecHull[ v + 4 ];
372
CqVector2D Vec3 = avecHull[ v + 12 ] - avecHull[ v + 8 ];
373
if ( Vec1.Magnitude2() > vLen ) vLen = Vec1.Magnitude2();
374
if ( Vec2.Magnitude2() > vLen ) vLen = Vec2.Magnitude2();
375
if ( Vec3.Magnitude2() > vLen ) vLen = Vec3.Magnitude2();
378
uLen = sqrt( uLen / ShadingRate);
379
vLen = sqrt( vLen / ShadingRate);
381
m_SplitDir = ( uLen > vLen ) ? SplitDir_U : SplitDir_V;
382
// TODO: Should ensure powers of half to prevent cracking.
385
m_uDiceSize = static_cast<TqInt>( MAX( ROUND( uLen ), 1 ) );
386
m_vDiceSize = static_cast<TqInt>( MAX( ROUND( vLen ), 1 ) );
388
// Ensure power of 2 to avoid cracking
389
const TqInt *binary = pAttributes() ->GetIntegerAttribute( "dice", "binary" );
390
if ( binary && *binary)
392
m_uDiceSize = CEIL_POW2( m_uDiceSize );
393
m_vDiceSize = CEIL_POW2( m_vDiceSize );
396
if ( uLen < FLT_EPSILON || vLen < FLT_EPSILON )
403
const TqFloat* poptGridSize = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "SqrtGridSize" );
404
if( NULL != poptGridSize )
405
gs = poptGridSize[0];
407
if( m_uDiceSize * m_vDiceSize > gs * gs )
414
//---------------------------------------------------------------------
415
/** Convert from the current basis into Bezier for processing.
418
void CqSurfacePatchBicubic::ConvertToBezierBasis( CqMatrix& matuBasis, CqMatrix& matvBasis )
420
static CqMatrix matMim1;
423
if ( matMim1.fIdentity() )
425
for ( i = 0; i < 4; i++ )
426
for ( j = 0; j < 4; j++ )
427
matMim1[ i ][ j ] = RiBezierBasis[ i ][ j ];
428
matMim1.SetfIdentity( TqFalse );
429
matMim1 = matMim1.Inverse();
432
CqMatrix matuMj = matuBasis;
433
CqMatrix matvMj = matvBasis;
435
CqMatrix matuConv = matuMj * matMim1;
436
CqMatrix matvConv = matvMj * matMim1;
438
std::vector<CqParameter*>::iterator iUP;
439
std::vector<CqParameter*>::iterator end = aUserParams().end();
440
for ( iUP = aUserParams().begin(); iUP != end; iUP++ )
442
if ( ( *iUP ) ->Class() == class_vertex )
444
TqInt ptype = (*iUP)->Type();
448
case type_vector: ///! \todo Not sure if this is correct, do vectors and normals need to be treated differently?
449
case type_normal: ///! \todo Not sure if this is correct, do vectors and normals need to be treated differently?
451
// Get the parameter pointer as the correct type.
452
CqParameterTyped<CqVector3D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
454
// Store the data into a matrix for conversion.
455
CqMatrix matCPx, matCPy, matCPz, matCPh;
456
for ( i = 0; i < 4; i++ )
458
for ( j = 0; j < 4; j++ )
460
matCPx[ i ][ j ] = pParam->pValue( i*4 + j )[0][0];
461
matCPy[ i ][ j ] = pParam->pValue( i*4 + j )[0][1];
462
matCPz[ i ][ j ] = pParam->pValue( i*4 + j )[0][2];
463
matCPh[ i ][ j ] = 1.0f;
466
matCPx.SetfIdentity( TqFalse ); matCPy.SetfIdentity( TqFalse );
467
matCPz.SetfIdentity( TqFalse ); matCPh.SetfIdentity( TqFalse );
469
matCPx = matuConv.Transpose() * matCPx * matvConv;
470
matCPy = matuConv.Transpose() * matCPy * matvConv;
471
matCPz = matuConv.Transpose() * matCPz * matvConv;
472
matCPh = matuConv.Transpose() * matCPh * matvConv;
474
for ( i = 0; i < 4; i++ )
476
for ( j = 0; j < 4; j++ )
478
pParam->pValue( i*4 + j )[0][0] = matCPx[ i ][ j ];
479
pParam->pValue( i*4 + j )[0][1] = matCPy[ i ][ j ];
480
pParam->pValue( i*4 + j )[0][2] = matCPz[ i ][ j ];
488
// Get the parameter pointer as the correct type.
489
CqParameterTyped<CqVector4D, CqVector3D>* pParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( ( *iUP ) );
491
// Store the data into a matrix for conversion.
492
CqMatrix matCPx, matCPy, matCPz, matCPh;
493
for ( i = 0; i < 4; i++ )
495
for ( j = 0; j < 4; j++ )
497
matCPx[ i ][ j ] = pParam->pValue( i*4 + j )[0][0];
498
matCPy[ i ][ j ] = pParam->pValue( i*4 + j )[0][1];
499
matCPz[ i ][ j ] = pParam->pValue( i*4 + j )[0][2];
500
matCPh[ i ][ j ] = pParam->pValue( i*4 + j )[0][3];
503
matCPx.SetfIdentity( TqFalse ); matCPy.SetfIdentity( TqFalse );
504
matCPz.SetfIdentity( TqFalse ); matCPh.SetfIdentity( TqFalse );
506
matCPx = matuConv.Transpose() * matCPx * matvConv;
507
matCPy = matuConv.Transpose() * matCPy * matvConv;
508
matCPz = matuConv.Transpose() * matCPz * matvConv;
509
matCPh = matuConv.Transpose() * matCPh * matvConv;
511
for ( i = 0; i < 4; i++ )
513
for ( j = 0; j < 4; j++ )
515
pParam->pValue( i*4 + j )[0][0] = matCPx[ i ][ j ];
516
pParam->pValue( i*4 + j )[0][1] = matCPy[ i ][ j ];
517
pParam->pValue( i*4 + j )[0][2] = matCPz[ i ][ j ];
518
pParam->pValue( i*4 + j )[0][3] = matCPh[ i ][ j ];
526
// Get the parameter pointer as the correct type.
527
CqParameterTyped<CqColor, CqColor>* pParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( ( *iUP ) );
529
// Store the data into a matrix for conversion.
530
CqMatrix matRed, matGreen, matBlue;
531
for ( i = 0; i < 4; i++ )
533
for ( j = 0; j < 4; j++ )
535
matRed[ i ][ j ] = pParam->pValue( i*4 + j )[0][0];
536
matGreen[ i ][ j ] = pParam->pValue( i*4 + j )[0][1];
537
matBlue[ i ][ j ] = pParam->pValue( i*4 + j )[0][2];
540
matRed.SetfIdentity( TqFalse );
541
matGreen.SetfIdentity( TqFalse );
542
matBlue.SetfIdentity( TqFalse );
544
matRed = matuConv.Transpose() * matRed * matvConv;
545
matGreen = matuConv.Transpose() * matGreen * matvConv;
546
matBlue = matuConv.Transpose() * matBlue * matvConv;
548
for ( i = 0; i < 4; i++ )
550
for ( j = 0; j < 4; j++ )
552
pParam->pValue( i*4 + j )[0][0] = matRed[ i ][ j ];
553
pParam->pValue( i*4 + j )[0][1] = matGreen[ i ][ j ];
554
pParam->pValue( i*4 + j )[0][2] = matBlue[ i ][ j ];
562
// Get the parameter pointer as the correct type.
563
CqParameterTyped<TqFloat, TqFloat>* pParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( ( *iUP ) );
565
// Store the data into a matrix for conversion.
567
for ( i = 0; i < 4; i++ )
569
for ( j = 0; j < 4; j++ )
570
matCPx[ i ][ j ] = pParam->pValue( i*4 + j )[0];
572
matCPx.SetfIdentity( TqFalse );
573
matCPx = matuConv.Transpose() * matCPx * matvConv;
575
for ( i = 0; i < 4; i++ )
577
for ( j = 0; j < 4; j++ )
578
pParam->pValue( i*4 + j )[0] = matCPx[ i ][ j ];
583
/// \todo Need to work out how to convert Matrix types to Bezier as well at some point.
588
/* for ( i = 0; i < 4; i++ )
590
for ( j = 0; j < 4; j++ )
592
CP( i, j ).x( matCPx[ i ][ j ] );
593
CP( i, j ).y( matCPy[ i ][ j ] );
594
CP( i, j ).z( matCPz[ i ][ j ] );
595
CP( i, j ).h( matCPh[ i ][ j ] );
601
//---------------------------------------------------------------------
605
CqSurfacePatchBilinear::CqSurfacePatchBilinear() : CqSurface(), m_fHasPhantomFourthVertex( TqFalse ), m_iInternalu( -1 ), m_iInternalv( -1 )
609
//---------------------------------------------------------------------
610
/** Copy constructor.
613
CqSurfacePatchBilinear::CqSurfacePatchBilinear( const CqSurfacePatchBilinear& From ) :
620
//---------------------------------------------------------------------
624
CqSurfacePatchBilinear::~CqSurfacePatchBilinear()
628
//---------------------------------------------------------------------
629
/** Assignment operator.
632
CqSurfacePatchBilinear& CqSurfacePatchBilinear::operator=( const CqSurfacePatchBilinear& From )
634
CqSurface::operator=( From );
636
m_fHasPhantomFourthVertex = From.m_fHasPhantomFourthVertex;
637
m_iInternalu = From.m_iInternalu;
638
m_iInternalv = From.m_iInternalv;
644
//---------------------------------------------------------------------
645
/** Return the boundary extents in camera space of the surface patch
648
CqBound CqSurfacePatchBilinear::Bound() const
650
assert( NULL != P() );
652
// Get the boundary in camera space.
653
CqVector3D vecA( FLT_MAX, FLT_MAX, FLT_MAX );
654
CqVector3D vecB( -FLT_MAX, -FLT_MAX, -FLT_MAX );
656
for ( i = 0; i < ( m_fHasPhantomFourthVertex ? 3 : 4 ); i++ )
658
CqVector3D vecV = P()->pValue( i )[0];
659
if ( vecV.x() < vecA.x() ) vecA.x( vecV.x() );
660
if ( vecV.y() < vecA.y() ) vecA.y( vecV.y() );
661
if ( vecV.x() > vecB.x() ) vecB.x( vecV.x() );
662
if ( vecV.y() > vecB.y() ) vecB.y( vecV.y() );
663
if ( vecV.z() < vecA.z() ) vecA.z( vecV.z() );
664
if ( vecV.z() > vecB.z() ) vecB.z( vecV.z() );
669
return ( AdjustBoundForTransformationMotion( B ) );
674
//---------------------------------------------------------------------
675
/** Split the patch into smaller patches.
678
TqInt CqSurfacePatchBilinear::PreSubdivide( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits, TqBool u )
680
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBilinear ) );
681
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBilinear ) );
687
//---------------------------------------------------------------------
688
/** Determine whether or not the patch is diceable
691
TqBool CqSurfacePatchBilinear::Diceable()
693
assert( NULL != P() );
695
// If the cull check showed that the primitive cannot be diced due to crossing the e and hither planes,
696
// then we can return immediately.
700
// Otherwise we should continue to try to find the most advantageous split direction, OR the dice size.
701
const CqMatrix & matCtoR = QGetRenderContext() ->matSpaceToSpace( "camera", "raster", CqMatrix(), CqMatrix(), QGetRenderContext()->Time() );
703
// Convert the control hull to raster space.
704
CqVector2D avecHull[ 4 ];
707
TqFloat ShadingRate = pAttributes() ->GetFloatAttribute( "System", "ShadingRate" ) [ 0 ];
709
for ( i = 0; i < 4; i++ )
710
avecHull[ i ] = matCtoR * P()->pValue( i )[0];
715
CqVector2D Vec1 = avecHull[ 1 ] - avecHull[ 0 ];
716
CqVector2D Vec2 = avecHull[ 3 ] - avecHull[ 2 ];
717
uLen = ( Vec1.Magnitude2() > Vec2.Magnitude2() ) ? Vec1.Magnitude2() : Vec2.Magnitude2();
719
Vec1 = avecHull[ 2 ] - avecHull[ 0 ];
720
Vec2 = avecHull[ 3 ] - avecHull[ 1 ];
721
vLen = ( Vec1.Magnitude2() > Vec2.Magnitude2() ) ? Vec1.Magnitude2() : Vec2.Magnitude2();
723
uLen = sqrt( uLen / ShadingRate);
724
vLen = sqrt( vLen / ShadingRate);
726
m_SplitDir = ( uLen > vLen ) ? SplitDir_U : SplitDir_V;
728
// TODO: Should ensure powers of half to prevent cracking.
729
uLen = MAX( ROUND( uLen ), 1 );
730
vLen = MAX( ROUND( vLen ), 1 );
732
m_uDiceSize = static_cast<TqInt>( uLen );
733
m_vDiceSize = static_cast<TqInt>( vLen );
735
// Ensure power of 2 to avoid cracking
736
const TqInt *binary = pAttributes() ->GetIntegerAttribute( "dice", "binary" );
737
if ( binary && *binary)
739
m_uDiceSize = CEIL_POW2( m_uDiceSize );
740
m_vDiceSize = CEIL_POW2( m_vDiceSize );
743
if ( uLen < FLT_EPSILON || vLen < FLT_EPSILON )
750
const TqFloat* poptGridSize = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "SqrtGridSize" );
751
if( NULL != poptGridSize )
752
gs = poptGridSize[0];
755
if( m_uDiceSize > gs2 || m_vDiceSize > gs2 || (m_uDiceSize * m_vDiceSize) > gs2 )
763
TqInt CqSurfacePatchBilinear::Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits )
765
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBilinear ) );
766
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBilinear ) );
768
if ( m_fHasPhantomFourthVertex )
770
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBilinear ) );
771
aSplits.push_back( boost::shared_ptr<CqBasicSurface>( new CqSurfacePatchBilinear ) );
773
TqBool direction = SplitDir() == SplitDir_U;
774
TqBool opposite = !direction;
776
for ( i = 0; i < ( m_fHasPhantomFourthVertex ? 4 : 2 ); i++ )
778
aSplits[ i ] ->SetSurfaceParameters( *this );
779
aSplits[ i ] ->SetSplitDir( direction ? SplitDir_V : SplitDir_U );
780
aSplits[ i ] ->SetEyeSplitCount( EyeSplitCount() );
781
aSplits[ i ] ->m_fDiceable = TqTrue;
784
// Iterate through any use parameters subdividing and storing the second value in the target surface.
785
std::vector<CqParameter*>::iterator iUP;
786
std::vector<CqParameter*>::iterator end = m_aUserParams.end();
788
for ( iUP = m_aUserParams.begin(); iUP != end; iUP++ )
790
CqParameter* pNewA = ( *iUP ) ->Clone();
791
CqParameter* pNewB = ( *iUP ) ->Clone();
792
( *iUP ) ->Subdivide( pNewA, pNewB, direction, this );
794
if ( m_fHasPhantomFourthVertex )
796
CqParameter * pNewC = pNewA ->Clone();
797
CqParameter* pNewD = pNewA ->Clone();
798
CqParameter* pNewE = pNewB ->Clone();
799
CqParameter* pNewF = pNewB ->Clone();
800
pNewA ->Subdivide( pNewC, pNewD, opposite, this );
801
pNewB ->Subdivide( pNewE, pNewF, opposite, this );
803
static_cast<CqSurface*>( aSplits[ 0 ].get() ) ->AddPrimitiveVariable( pNewC );
804
static_cast<CqSurface*>( aSplits[ 1 ].get() ) ->AddPrimitiveVariable( pNewD );
805
static_cast<CqSurface*>( aSplits[ 2 ].get() ) ->AddPrimitiveVariable( pNewE );
806
static_cast<CqSurface*>( aSplits[ 3 ].get() ) ->AddPrimitiveVariable( pNewF );
813
static_cast<CqSurface*>( aSplits[ 0 ].get() ) ->AddPrimitiveVariable( pNewA );
814
static_cast<CqSurface*>( aSplits[ 1 ].get() ) ->AddPrimitiveVariable( pNewB );
818
if ( m_fHasPhantomFourthVertex )
822
static_cast<CqSurfacePatchBilinear*>( aSplits[ 0 ].get() ) ->m_fHasPhantomFourthVertex = TqFalse;
823
static_cast<CqSurfacePatchBilinear*>( aSplits[ 1 ].get() ) ->m_fHasPhantomFourthVertex = TqTrue;
824
static_cast<CqSurfacePatchBilinear*>( aSplits[ 2 ].get() ) ->m_fHasPhantomFourthVertex = TqTrue;
830
static_cast<CqSurfacePatchBilinear*>( aSplits[ 0 ].get() ) ->m_fHasPhantomFourthVertex = TqFalse;
831
static_cast<CqSurfacePatchBilinear*>( aSplits[ 1 ].get() ) ->m_fHasPhantomFourthVertex = TqFalse;
838
//---------------------------------------------------------------------
839
/** Copy constructor.
842
CqSurfacePatchMeshBicubic::CqSurfacePatchMeshBicubic( const CqSurfacePatchMeshBicubic& From ) :
849
//---------------------------------------------------------------------
853
CqSurfacePatchMeshBicubic::~CqSurfacePatchMeshBicubic()
857
//---------------------------------------------------------------------
858
/** Assignment operator.
861
CqSurfacePatchMeshBicubic& CqSurfacePatchMeshBicubic::operator=( const CqSurfacePatchMeshBicubic& From )
863
// Perform per surface copy function
864
CqSurface::operator=( From );
866
m_uPatches = From.m_uPatches;
867
m_vPatches = From.m_vPatches;
870
m_uPeriodic = From.m_uPeriodic;
871
m_vPeriodic = From.m_vPeriodic;
877
//---------------------------------------------------------------------
878
/** Get the boundary extents in camera space of the surface patch mesh
881
CqBound CqSurfacePatchMeshBicubic::Bound() const
883
assert( NULL != P() );
885
// Get the boundary in camera space.
886
CqVector3D vecA( FLT_MAX, FLT_MAX, FLT_MAX );
887
CqVector3D vecB( -FLT_MAX, -FLT_MAX, -FLT_MAX );
889
for ( i = 0; i < P() ->Size(); i++ )
891
CqVector3D vecV = P()->pValue( i )[0];
892
if ( vecV.x() < vecA.x() ) vecA.x( vecV.x() );
893
if ( vecV.y() < vecA.y() ) vecA.y( vecV.y() );
894
if ( vecV.x() > vecB.x() ) vecB.x( vecV.x() );
895
if ( vecV.y() > vecB.y() ) vecB.y( vecV.y() );
896
if ( vecV.z() < vecA.z() ) vecA.z( vecV.z() );
897
if ( vecV.z() > vecB.z() ) vecB.z( vecV.z() );
902
return ( AdjustBoundForTransformationMotion( B ) );
906
//---------------------------------------------------------------------
907
/** Split the patch mesh into individual patches and post them.
910
#define PatchCoord(v,u) ((((v)%m_nv)*m_nu)+((u)%m_nu))
911
#define PatchCorner(v,u) ((((v)%nvaryingv)*nvaryingu)+((u)%nvaryingu));
913
TqInt CqSurfacePatchMeshBicubic::Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits )
919
TqInt uStep = pAttributes() ->GetIntegerAttribute( "System", "BasisStep" ) [ 0 ];
920
TqInt vStep = pAttributes() ->GetIntegerAttribute( "System", "BasisStep" ) [ 1 ];
922
TqInt nvaryingu = ( m_uPeriodic ) ? m_uPatches : m_uPatches + 1;
923
TqInt nvaryingv = ( m_vPeriodic ) ? m_vPatches : m_vPatches + 1;
925
TqInt MyUses = Uses();
927
const TqFloat* pTC = pAttributes() ->GetFloatAttribute( "System", "TextureCoordinates" );
928
CqVector2D st1( pTC[ 0 ], pTC[ 1 ] );
929
CqVector2D st2( pTC[ 2 ], pTC[ 3 ] );
930
CqVector2D st3( pTC[ 4 ], pTC[ 5 ] );
931
CqVector2D st4( pTC[ 6 ], pTC[ 7 ] );
933
// Fill in the variables.
935
for ( i = 0; i < m_vPatches; i++ )
937
// vRow is the coordinate row of the mesh.
938
RtInt vRow = i * vStep;
939
TqFloat v0 = ( 1.0f / m_vPatches ) * i;
940
TqFloat v1 = ( 1.0f / m_vPatches ) * ( i + 1 );
942
for ( j = 0; j < m_uPatches; j++ )
944
// uCol is the coordinate column of the mesh.
945
RtInt uCol = j * uStep;
946
boost::shared_ptr<CqSurfacePatchBicubic> pSurface( new CqSurfacePatchBicubic() );
947
pSurface->SetSurfaceParameters( *this );
951
TqInt iTa = PatchCorner( i, j );
952
TqInt iTb = PatchCorner( i, j + 1 );
953
TqInt iTc = PatchCorner( i + 1, j );
954
TqInt iTd = PatchCorner( i + 1, j + 1 );
956
TqFloat u0 = ( 1.0f / m_uPatches ) * j;
957
TqFloat u1 = ( 1.0f / m_uPatches ) * ( j + 1 );
959
std::vector<CqParameter*>::iterator iUP;
960
std::vector<CqParameter*>::iterator end = aUserParams().end();
961
for ( iUP = aUserParams().begin(); iUP != end; iUP++ )
963
if ( ( *iUP ) ->Class() == class_varying )
965
// Copy any 'varying' class primitive variables.
966
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
967
pNewUP->SetSize( pSurface->cVarying() );
969
pNewUP->SetValue( ( *iUP ), 0, iTa );
970
pNewUP->SetValue( ( *iUP ), 1, iTb );
971
pNewUP->SetValue( ( *iUP ), 2, iTc );
972
pNewUP->SetValue( ( *iUP ), 3, iTd );
973
pSurface->AddPrimitiveVariable( pNewUP );
975
else if ( ( *iUP ) ->Class() == class_vertex )
977
// Copy any 'vertex' class primitive variables.
978
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
980
pNewUP->SetSize( pSurface->cVertex() );
982
for ( v = 0; v < 4; v++ )
984
iP = PatchCoord( vRow + v, uCol );
985
pNewUP->SetValue( ( *iUP ), ( v * 4 ), iP );
986
iP = PatchCoord( vRow + v, uCol + 1 );
987
pNewUP->SetValue( ( *iUP ), ( v * 4 ) + 1, iP );
988
iP = PatchCoord( vRow + v, uCol + 2 );
989
pNewUP->SetValue( ( *iUP ), ( v * 4 ) + 2, iP );
990
iP = PatchCoord( vRow + v, uCol + 3 );
991
pNewUP->SetValue( ( *iUP ), ( v * 4 ) + 3, iP );
993
pSurface->AddPrimitiveVariable( pNewUP );
995
else if ( ( *iUP ) ->Class() == class_uniform )
997
// Copy any 'uniform' class primitive variables.
998
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
999
pNewUP->SetSize( pSurface->cUniform() );
1000
pNewUP->SetValue( ( *iUP ), 0, j );
1001
pSurface->AddPrimitiveVariable( pNewUP );
1003
else if ( ( *iUP ) ->Class() == class_constant )
1005
// Copy any 'constant' class primitive variables.
1006
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1007
pNewUP->SetSize( 1 );
1008
pNewUP->SetValue( ( *iUP ), 0, 0 );
1009
pSurface->AddPrimitiveVariable( pNewUP );
1013
// If the shaders need u/v or s/t and they are not specified, then we need to put them in as defaults.
1014
if ( USES( MyUses, EnvVars_u ) && !bHasVar(EnvVars_u) )
1016
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "u" ) );
1017
pSurface->u() ->SetSize( 4 );
1018
pSurface->u() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u0, v0 );
1019
pSurface->u() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u1, v0 );
1020
pSurface->u() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u0, v1 );
1021
pSurface->u() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u1, v1 );
1024
if ( USES( MyUses, EnvVars_v ) && !bHasVar(EnvVars_v) )
1026
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "v" ) );
1027
pSurface->v() ->SetSize( 4 );
1028
pSurface->v() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u0, v0 );
1029
pSurface->v() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u1, v0 );
1030
pSurface->v() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u0, v1 );
1031
pSurface->v() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u1, v1 );
1034
if ( USES( MyUses, EnvVars_s ) && !bHasVar(EnvVars_s) )
1036
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "s" ) );
1037
pSurface->s() ->SetSize( 4 );
1038
pSurface->s() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u0, v0 );
1039
pSurface->s() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u1, v0 );
1040
pSurface->s() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u0, v1 );
1041
pSurface->s() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u1, v1 );
1044
if ( USES( MyUses, EnvVars_t ) && !bHasVar(EnvVars_t) )
1046
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "t" ) );
1047
pSurface->t() ->SetSize( 4 );
1048
pSurface->t() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u0, v0 );
1049
pSurface->t() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u1, v0 );
1050
pSurface->t() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u0, v1 );
1051
pSurface->t() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u1, v1 );
1054
aSplits.push_back( pSurface );
1062
//---------------------------------------------------------------------
1063
/** Copy constructor.
1066
CqSurfacePatchMeshBilinear::CqSurfacePatchMeshBilinear( const CqSurfacePatchMeshBilinear& From ) :
1073
//---------------------------------------------------------------------
1077
CqSurfacePatchMeshBilinear::~CqSurfacePatchMeshBilinear()
1081
//---------------------------------------------------------------------
1082
/** Assignment operator.
1085
CqSurfacePatchMeshBilinear& CqSurfacePatchMeshBilinear::operator=( const CqSurfacePatchMeshBilinear& From )
1087
// Perform per surface copy function
1088
CqSurface::operator=( From );
1090
m_uPatches = From.m_uPatches;
1091
m_vPatches = From.m_vPatches;
1094
m_uPeriodic = From.m_uPeriodic;
1095
m_vPeriodic = From.m_vPeriodic;
1101
//---------------------------------------------------------------------
1102
/** Get the boundary extents in camera space of the surface patch mesh
1105
CqBound CqSurfacePatchMeshBilinear::Bound() const
1107
assert( NULL != P() );
1109
// Get the boundary in camera space.
1110
CqVector3D vecA( FLT_MAX, FLT_MAX, FLT_MAX );
1111
CqVector3D vecB( -FLT_MAX, -FLT_MAX, -FLT_MAX );
1113
for ( i = 0; i < P() ->Size(); i++ )
1115
CqVector3D vecV = P()->pValue( i )[0];
1116
if ( vecV.x() < vecA.x() ) vecA.x( vecV.x() );
1117
if ( vecV.y() < vecA.y() ) vecA.y( vecV.y() );
1118
if ( vecV.x() > vecB.x() ) vecB.x( vecV.x() );
1119
if ( vecV.y() > vecB.y() ) vecB.y( vecV.y() );
1120
if ( vecV.z() < vecA.z() ) vecA.z( vecV.z() );
1121
if ( vecV.z() > vecB.z() ) vecB.z( vecV.z() );
1126
return ( AdjustBoundForTransformationMotion( B ) );
1130
//---------------------------------------------------------------------
1131
/** Split the patch mesh into individual patches and post them.
1134
#define PatchCoord(v,u) ((((v)%m_nv)*m_nu)+((u)%m_nu))
1135
#define PatchCorner(v,u) ((((v)%nvaryingv)*nvaryingu)+((u)%nvaryingu));
1137
TqInt CqSurfacePatchMeshBilinear::Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits )
1141
// Create a surface patch
1143
TqInt MyUses = Uses();
1145
const TqFloat* pTC = pAttributes() ->GetFloatAttribute( "System", "TextureCoordinates" );
1146
CqVector2D st1( pTC[ 0 ], pTC[ 1 ] );
1147
CqVector2D st2( pTC[ 2 ], pTC[ 3 ] );
1148
CqVector2D st3( pTC[ 4 ], pTC[ 5 ] );
1149
CqVector2D st4( pTC[ 6 ], pTC[ 7 ] );
1152
for ( i = 0; i < m_vPatches; i++ )
1154
TqFloat v0 = ( 1.0f / m_vPatches ) * i;
1155
TqFloat v1 = ( 1.0f / m_vPatches ) * ( i + 1 );
1157
for ( j = 0; j < m_uPatches; j++ )
1159
boost::shared_ptr<CqSurfacePatchBilinear> pSurface( new CqSurfacePatchBilinear );
1160
pSurface->SetSurfaceParameters( *this );
1162
RtInt iTa = PatchCoord( i, j );
1163
RtInt iTb = PatchCoord( i, j + 1 );
1164
RtInt iTc = PatchCoord( i + 1, j );
1165
RtInt iTd = PatchCoord( i + 1, j + 1 );
1167
TqFloat u0 = ( 1.0f / m_uPatches ) * j;
1168
TqFloat u1 = ( 1.0f / m_uPatches ) * ( j + 1 );
1170
// Copy any primitive variables.
1171
std::vector<CqParameter*>::iterator iUP;
1172
std::vector<CqParameter*>::iterator end = aUserParams().end();
1173
for ( iUP = aUserParams().begin(); iUP != end; iUP++ )
1175
if ( ( *iUP ) ->Class() == class_varying )
1177
// Copy any 'varying' class primitive variables.
1178
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1179
pNewUP->SetSize( pSurface->cVarying() );
1181
pNewUP->SetValue( ( *iUP ), 0, iTa );
1182
pNewUP->SetValue( ( *iUP ), 1, iTb );
1183
pNewUP->SetValue( ( *iUP ), 2, iTc );
1184
pNewUP->SetValue( ( *iUP ), 3, iTd );
1186
pSurface->AddPrimitiveVariable( pNewUP );
1188
else if ( ( *iUP ) ->Class() == class_vertex )
1190
// Copy any 'vertex' class primitive variables.
1191
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1192
pNewUP->SetSize( pSurface->cVertex() );
1194
iP = PatchCoord( i, j );
1195
pNewUP->SetValue( ( *iUP ), 0, iP );
1196
iP = PatchCoord( i, j + 1 );
1197
pNewUP->SetValue( ( *iUP ), 1, iP );
1198
iP = PatchCoord( i + 1, j );
1199
pNewUP->SetValue( ( *iUP ), 2, iP );
1200
iP = PatchCoord( i + 1, j + 1 );
1201
pNewUP->SetValue( ( *iUP ), 3, iP );
1203
pSurface->AddPrimitiveVariable( pNewUP );
1205
else if ( ( *iUP ) ->Class() == class_uniform )
1207
// Copy any 'uniform' class primitive variables.
1208
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1209
pNewUP->SetSize( pSurface->cUniform() );
1210
pNewUP->SetValue( ( *iUP ), 0, j );
1211
pSurface->AddPrimitiveVariable( pNewUP );
1213
else if ( ( *iUP ) ->Class() == class_constant )
1215
// Copy any 'constant' class primitive variables.
1216
CqParameter * pNewUP = ( *iUP ) ->CloneType( ( *iUP ) ->strName().c_str(), ( *iUP ) ->Count() );
1217
pNewUP->SetSize( 1 );
1219
pNewUP->SetValue( ( *iUP ), 0, 0 );
1220
pSurface->AddPrimitiveVariable( pNewUP );
1224
// If the shaders need u/v or s/t and they are not specified, then we need to put them in as defaults.
1225
if ( USES( MyUses, EnvVars_u ) && !bHasVar(EnvVars_u) )
1227
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "u" ) );
1228
pSurface->u() ->SetSize( 4 );
1229
pSurface->u() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u0, v0 );
1230
pSurface->u() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u1, v0 );
1231
pSurface->u() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u0, v1 );
1232
pSurface->u() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( 0.0f, 1.0f, 0.0f, 1.0f, u1, v1 );
1235
if ( USES( MyUses, EnvVars_v ) && !bHasVar(EnvVars_v) )
1237
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "v" ) );
1238
pSurface->v() ->SetSize( 4 );
1239
pSurface->v() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u0, v0 );
1240
pSurface->v() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u1, v0 );
1241
pSurface->v() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u0, v1 );
1242
pSurface->v() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( 0.0f, 0.0f, 1.0f, 1.0f, u1, v1 );
1245
if ( USES( MyUses, EnvVars_s ) && !bHasVar(EnvVars_s) )
1247
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "s" ) );
1248
pSurface->s() ->SetSize( 4 );
1249
pSurface->s() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u0, v0 );
1250
pSurface->s() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u1, v0 );
1251
pSurface->s() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u0, v1 );
1252
pSurface->s() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( st1.x(), st2.x(), st3.x(), st4.x(), u1, v1 );
1255
if ( USES( MyUses, EnvVars_t ) && !bHasVar(EnvVars_t) )
1257
pSurface->AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "t" ) );
1258
pSurface->t() ->SetSize( 4 );
1259
pSurface->t() ->pValue( 0 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u0, v0 );
1260
pSurface->t() ->pValue( 1 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u1, v0 );
1261
pSurface->t() ->pValue( 2 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u0, v1 );
1262
pSurface->t() ->pValue( 3 ) [ 0 ] = BilinearEvaluate( st1.y(), st2.y(), st3.y(), st4.y(), u1, v1 );
1265
aSplits.push_back( pSurface );
1273
#pragma warning(pop)
1275
END_NAMESPACE( Aqsis )