2
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.com
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
\brief Implements the base GPrim handling classes.
23
\author Paul C. Gregory (pgregory@aqsis.com)
28
#include "micropolygon.h"
31
#include "imagebuffer.h"
33
START_NAMESPACE( Aqsis )
35
TqFloat CqBasicSurface::m_fGridSize = sqrt(256.0);
37
//---------------------------------------------------------------------
38
/** Default constructor
41
CqBasicSurface::CqBasicSurface() : m_fDiceable( TqTrue ), m_fDiscard( TqFalse ), m_EyeSplitCount( 0 ),
42
m_pAttributes( 0 ), m_pTransform( 0 ), m_SplitDir( SplitDir_U )
44
// Set a refernce with the current attributes.
45
m_pAttributes = const_cast<CqAttributes*>( QGetRenderContext() ->pattrCurrent() );
46
ADDREF( m_pAttributes );
48
m_pTransform = const_cast<CqTransform*>( QGetRenderContext() ->ptransCurrent() );
49
ADDREF( m_pTransform );
51
m_CachedBound = TqFalse;
53
// If the current context is a solid node, and is a 'primitive', attatch this surface to the node.
54
if ( QGetRenderContext() ->pconCurrent() ->isSolid() )
56
CqModeBlock * pSolid = QGetRenderContext() ->pconCurrent().get();
57
if ( pSolid->pCSGNode() ->NodeType() == CqCSGTreeNode::CSGNodeType_Primitive )
59
m_pCSGNode = pSolid->pCSGNode();
63
CqString objname( "unnamed" );
64
const CqString* pattrName = m_pAttributes->GetStringAttribute( "identifier", "name" );
65
if ( pattrName != 0 ) objname = pattrName[ 0 ];
66
std::cerr << warning << "Primitive \"" << objname.c_str() << "\" defined when not in 'Primitive' solid block" << std::endl;
70
STATS_INC( GPR_allocated );
71
STATS_INC( GPR_current );
72
TqInt cGprim = STATS_GETI( GPR_current );
73
TqInt cPeak = STATS_GETI( GPR_peak );
74
STATS_SETI( GPR_peak, cGprim > cPeak ? cGprim : cPeak );
78
//---------------------------------------------------------------------
82
CqBasicSurface::CqBasicSurface( const CqBasicSurface& From ) : m_fDiceable( TqTrue ), m_SplitDir( SplitDir_U )
86
// Set a reference with the donors attributes.
87
m_pAttributes = From.m_pAttributes;
88
ADDREF( m_pAttributes );
90
m_pTransform = From.m_pTransform;
91
ADDREF( m_pTransform );
93
m_CachedBound = From.m_CachedBound;
94
m_Bound = From.m_Bound;
96
STATS_INC( GPR_allocated );
97
STATS_INC( GPR_current );
98
TqInt cGprim = STATS_GETI( GPR_current );
99
TqInt cPeak = STATS_GETI( GPR_peak );
100
STATS_SETI( GPR_peak, cGprim > cPeak ? cGprim : cPeak );
104
//---------------------------------------------------------------------
105
/** Assignement operator
108
CqBasicSurface& CqBasicSurface::operator=( const CqBasicSurface& From )
110
m_fDiceable = From.m_fDiceable;
111
m_EyeSplitCount = From.m_EyeSplitCount;
112
m_fDiscard = From.m_fDiscard;
114
SetSurfaceParameters( From );
120
//---------------------------------------------------------------------
121
/** Copy the local surface parameters from the donor surface.
124
void CqBasicSurface::SetSurfaceParameters( const CqBasicSurface& From )
126
// If we already have attributes, unreference them now as we don't need them anymore.
127
if ( m_pAttributes ) RELEASEREF( m_pAttributes );
128
if ( m_pTransform ) RELEASEREF( m_pTransform );
130
// Now store and reference our new attributes.
131
m_pAttributes = From.m_pAttributes;
132
ADDREF( m_pAttributes );
134
m_pTransform = From.m_pTransform;
135
ADDREF( m_pTransform );
137
m_pCSGNode = From.m_pCSGNode;
141
//---------------------------------------------------------------------
142
/** Return the name of this primitive surface if specified as a "identifier" "name" attribute,
143
* otherwise return "not named"
146
CqString CqBasicSurface::strName() const
148
const CqString * pattrLightName = pAttributes() ->GetStringAttribute( "identifier", "name" );
149
CqString strName( "not named" );
150
if ( pattrLightName != 0 ) strName = pattrLightName[ 0 ];
156
//---------------------------------------------------------------------
157
/** Work out which standard shader variables this surface requires by looking at the shaders.
160
TqInt CqBasicSurface::Uses() const
162
TqInt Uses = gDefUses | QGetRenderContext()->pDDmanager()->Uses();
163
IqShader* pshadSurface = pAttributes() ->pshadSurface(QGetRenderContextI()->Time());
164
IqShader* pshadDisplacement = pAttributes() ->pshadDisplacement(QGetRenderContextI()->Time());
165
IqShader* pshadAtmosphere = pAttributes() ->pshadAtmosphere(QGetRenderContextI()->Time());
167
if ( NULL == pshadSurface && NULL == pshadDisplacement && NULL == pshadAtmosphere )
170
if ( pshadSurface ) Uses |= pshadSurface->Uses();
171
if ( pshadDisplacement ) Uses |= pshadDisplacement->Uses();
172
if ( pshadAtmosphere ) Uses |= pshadAtmosphere->Uses();
174
// Just a quick check, if it uses dPdu/dPdv must also use du/dv
175
if ( USES( Uses, EnvVars_dPdu ) ) Uses |= ( 1 << EnvVars_du );
176
if ( USES( Uses, EnvVars_dPdv ) ) Uses |= ( 1 << EnvVars_dv );
177
// Just a quick check, if it uses du/dv must also use u/v
178
if ( USES( Uses, EnvVars_du ) ) Uses |= ( 1 << EnvVars_u );
179
if ( USES( Uses, EnvVars_dv ) ) Uses |= ( 1 << EnvVars_v );
185
//---------------------------------------------------------------------
186
/** Adjust the bound of the quadric taking into account transformation motion blur.
189
CqBound CqBasicSurface::AdjustBoundForTransformationMotion( const CqBound& B ) const
193
if( pTransform()->cTimes() > 1 )
195
CqMatrix matCameraToObject0 = QGetRenderContext() ->matSpaceToSpace( "camera", "object", CqMatrix(), pTransform()->matObjectToWorld( pTransform()->Time( 0 ) ), pTransform()->Time( 0 ) );
197
B0.Transform( matCameraToObject0 );
200
for( i = 1; i < pTransform()->cTimes(); i++ )
203
CqMatrix matObjectToCameraT = QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pTransform()->matObjectToWorld( pTransform()->Time( i ) ), pTransform()->Time( i ) );
204
Btx.Transform( matObjectToCameraT );
205
Bm.Encapsulate( Btx );
213
//---------------------------------------------------------------------
214
/** Default constructor
217
CqSurface::CqSurface() : CqBasicSurface()
219
// Nullify the standard primitive variables index table.
221
for ( i = 0; i < EnvVars_Last; i++ )
222
m_aiStdPrimitiveVars[ i ] = -1;
225
//---------------------------------------------------------------------
229
CqSurface::CqSurface( const CqSurface& From )
235
//---------------------------------------------------------------------
236
/** Assignement operator
239
CqSurface& CqSurface::operator=( const CqSurface& From )
241
CqBasicSurface::operator=( From );
242
// Nullify the standard primitive variables index table.
244
for ( i = 0; i < EnvVars_Last; i++ )
245
m_aiStdPrimitiveVars[ i ] = -1;
249
//---------------------------------------------------------------------
250
/** Copy all the primitive variables from the donor to this.
253
void CqSurface::ClonePrimitiveVariables( const CqSurface& From )
255
// Clone any primitive variables.
256
m_aUserParams.clear();
257
std::vector<CqParameter*>::const_iterator iUP;
258
std::vector<CqParameter*>::const_iterator end = From.m_aUserParams.end() ;
259
for ( iUP = From.m_aUserParams.begin(); iUP != end; iUP++ )
260
AddPrimitiveVariable( ( *iUP ) ->Clone() );
262
// Copy the standard primitive variables index table.
264
for ( i = 0; i < EnvVars_Last; i++ )
265
m_aiStdPrimitiveVars[ i ] = From.m_aiStdPrimitiveVars[ i ];
268
//---------------------------------------------------------------------
269
/** Set the default values (where available) from the attribute state for all standard
270
* primitive variables.
273
void CqSurface::SetDefaultPrimitiveVariables( TqBool bUseDef_st )
275
TqInt bUses = Uses();
277
// Set default values for all of our parameters
279
// s and t default to four values, if the particular surface type requires different it is up
280
// to the surface to override or change this after the fact.
281
if ( USES( bUses, EnvVars_s ) && bUseDef_st && !bHasVar(EnvVars_s) )
283
AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "s" ) );
286
for ( i = 0; i < 4; i++ )
287
s() ->pValue() [ i ] = m_pAttributes->GetFloatAttribute( "System", "TextureCoordinates" ) [ i * 2 ];
290
if ( USES( bUses, EnvVars_t ) && bUseDef_st && !bHasVar(EnvVars_t))
292
AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "t" ) );
295
for ( i = 0; i < 4; i++ )
296
t() ->pValue() [ i ] = m_pAttributes->GetFloatAttribute( "System", "TextureCoordinates" ) [ ( i * 2 ) + 1 ];
299
if ( USES( bUses, EnvVars_u ) )
301
AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "u" ) );
303
u() ->pValue() [ 0 ] = u() ->pValue() [ 2 ] = 0.0;
304
u() ->pValue() [ 1 ] = u() ->pValue() [ 3 ] = 1.0;
307
if ( USES( bUses, EnvVars_v ) )
309
AddPrimitiveVariable( new CqParameterTypedVarying<TqFloat, type_float, TqFloat>( "v" ) );
311
v() ->pValue() [ 0 ] = v() ->pValue() [ 1 ] = 0.0;
312
v() ->pValue() [ 2 ] = v() ->pValue() [ 3 ] = 1.0;
317
void CqSurface::NaturalSubdivide( CqParameter* pParam, CqParameter* pParam1, CqParameter* pParam2, TqBool u )
319
switch ( pParam->Type() )
323
CqParameterTyped<TqFloat, TqFloat>* pTParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam );
324
CqParameterTyped<TqFloat, TqFloat>* pTResult1 = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam1 );
325
CqParameterTyped<TqFloat, TqFloat>* pTResult2 = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParam2 );
326
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
332
CqParameterTyped<TqInt, TqFloat>* pTParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam );
333
CqParameterTyped<TqInt, TqFloat>* pTResult1 = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam1 );
334
CqParameterTyped<TqInt, TqFloat>* pTResult2 = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParam2 );
335
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
343
CqParameterTyped<CqVector3D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam );
344
CqParameterTyped<CqVector3D, CqVector3D>* pTResult1 = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam1 );
345
CqParameterTyped<CqVector3D, CqVector3D>* pTResult2 = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParam2 );
346
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
352
CqParameterTyped<CqVector4D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam );
353
CqParameterTyped<CqVector4D, CqVector3D>* pTResult1 = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam1 );
354
CqParameterTyped<CqVector4D, CqVector3D>* pTResult2 = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParam2 );
355
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
362
CqParameterTyped<CqColor, CqColor>* pTParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam );
363
CqParameterTyped<CqColor, CqColor>* pTResult1 = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam1 );
364
CqParameterTyped<CqColor, CqColor>* pTResult2 = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParam2 );
365
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
371
CqParameterTyped<CqString, CqString>* pTParam = static_cast<CqParameterTyped<CqString, CqString>*>( pParam );
372
CqParameterTyped<CqString, CqString>* pTResult1 = static_cast<CqParameterTyped<CqString, CqString>*>( pParam1 );
373
CqParameterTyped<CqString, CqString>* pTResult2 = static_cast<CqParameterTyped<CqString, CqString>*>( pParam2 );
374
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
380
CqParameterTyped<CqMatrix, CqMatrix>* pTParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam );
381
CqParameterTyped<CqMatrix, CqMatrix>* pTResult1 = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam1 );
382
CqParameterTyped<CqMatrix, CqMatrix>* pTResult2 = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParam2 );
383
TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
389
// blank to avoid compiler warnings about unhandled cases
396
void CqSurface::NaturalDice( CqParameter* pParameter, TqInt uDiceSize, TqInt vDiceSize, IqShaderData* pData )
398
switch ( pParameter->Type() )
402
CqParameterTyped<TqFloat, TqFloat>* pTParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pParameter );
403
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
409
CqParameterTyped<TqInt, TqFloat>* pTParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pParameter );
410
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
418
CqParameterTyped<CqVector3D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pParameter );
419
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
425
CqParameterTyped<CqVector4D, CqVector3D>* pTParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pParameter );
426
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
432
CqParameterTyped<CqColor, CqColor>* pTParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pParameter );
433
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
439
CqParameterTyped<CqString, CqString>* pTParam = static_cast<CqParameterTyped<CqString, CqString>*>( pParameter );
440
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
446
CqParameterTyped<CqMatrix, CqMatrix>* pTParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pParameter );
447
TypedNaturalDice( uDiceSize, vDiceSize, pTParam, pData );
453
// left blank to avoid compiler warnings about unhandled types
461
//---------------------------------------------------------------------
462
/** Dice the patch into a mesh of micropolygons.
465
CqMicroPolyGridBase* CqSurface::Dice()
467
PreDice( m_uDiceSize, m_vDiceSize );
469
// Create a new CqMicorPolyGrid for this patch
470
CqMicroPolyGrid* pGrid = new CqMicroPolyGrid( m_uDiceSize, m_vDiceSize, shared_from_this() );
472
TqInt lUses = Uses();
474
// Allow the surface to fill in as much as possible on the grid in one go for speed.
475
TqInt lDone = DiceAll( pGrid );
477
// Dice the primitive variables.
479
// Special cases for s and t if "st" exists, it should override s and t.
481
if( ( pParam = FindUserParam("st") ) != NULL )
483
if ( !isDONE( lDone, EnvVars_s ) && USES( lUses, EnvVars_s ) && ( NULL != pGrid->pVar(EnvVars_s) ) )
484
pParam ->DiceOne( m_uDiceSize, m_vDiceSize, pGrid->pVar(EnvVars_s), this, 0 );
485
if ( !isDONE( lDone, EnvVars_t ) && USES( lUses, EnvVars_t ) && ( NULL != pGrid->pVar(EnvVars_t) ) )
486
pParam ->DiceOne( m_uDiceSize, m_vDiceSize, pGrid->pVar(EnvVars_t), this, 1 );
487
DONE( lDone, EnvVars_s);
488
DONE( lDone, EnvVars_t);
491
// Loop over all the variables checking if they have been specified in the scene, and
492
// if they are needed by the shaders, and id the grid can accept them.
493
// If all the tests pass, dice them into the grid based on their type.
495
for( varID = EnvVars_Cs; varID != EnvVars_Last; varID++ )
497
if ( !isDONE( lDone, varID ) && USES( lUses, varID ) && ( NULL != pGrid->pVar(varID) ) )
499
// Check if Cs has been specified by the user.
500
if ( bHasVar(varID) )
502
if( pVar(varID)->Class() == class_vertex || pVar(varID)->Class() == class_facevarying )
503
// "vertex" and "facevarying" need to be dealt with by the surface as they are diced using the
504
// natural subdivision algorithms for that particular surface.
505
NaturalDice( pVar(varID), m_uDiceSize, m_vDiceSize, pGrid->pVar(varID) );
507
// "varying" are just bilinearly interpolated, so can be handled by the primitive variable.
508
pVar(varID) ->Dice( m_uDiceSize, m_vDiceSize, pGrid->pVar(varID), this );
510
// Mark this as done, so that the special case default handlers later don't need to worry about it.
516
// Special case handlers for primitive variables that have defaults.
517
if ( !isDONE( lDone, EnvVars_Cs ) && USES( lUses, EnvVars_Cs ) && ( NULL != pGrid->pVar(EnvVars_Cs) ) )
519
if ( NULL != pAttributes() ->GetColorAttribute( "System", "Color" ) )
520
pGrid->pVar(EnvVars_Cs) ->SetColor( pAttributes() ->GetColorAttribute( "System", "Color" ) [ 0 ] );
522
pGrid->pVar(EnvVars_Cs) ->SetColor( CqColor( 1, 1, 1 ) );
525
if ( !isDONE( lDone, EnvVars_Os ) && USES( lUses, EnvVars_Os ) && ( NULL != pGrid->pVar(EnvVars_Os) ) )
527
if ( NULL != pAttributes() ->GetColorAttribute( "System", "Opacity" ) )
528
pGrid->pVar(EnvVars_Os) ->SetColor( pAttributes() ->GetColorAttribute( "System", "Opacity" ) [ 0 ] );
530
pGrid->pVar(EnvVars_Os) ->SetColor( CqColor( 1, 1, 1 ) );
533
// If the shaders need N and they have been explicitly specified, then bilinearly interpolate them.
534
if ( isDONE( lDone, EnvVars_N ) )
535
pGrid->SetbShadingNormals( TqTrue );
537
if ( !isDONE( lDone, EnvVars_Ng ) && CanGenerateNormals() && USES( lUses, EnvVars_Ng ) )
539
GenerateGeometricNormals( m_uDiceSize, m_vDiceSize, pGrid->pVar(EnvVars_Ng) );
540
pGrid->SetbGeometricNormals( TqTrue );
543
// Now we need to dice the user specified parameters as appropriate.
544
std::vector<CqParameter*>::iterator iUP;
545
std::vector<CqParameter*>::iterator end = m_aUserParams.end();
546
for ( iUP = m_aUserParams.begin(); iUP != end ; iUP++ )
549
if ( NULL != (pShader=pGrid->pAttributes() ->pshadSurface(QGetRenderContext()->Time())) )
550
pShader->SetArgument( ( *iUP ), this );
552
if ( NULL != (pShader=pGrid->pAttributes() ->pshadDisplacement(QGetRenderContext()->Time())) )
553
pShader->SetArgument( ( *iUP ), this );
555
if ( NULL != (pShader=pGrid->pAttributes() ->pshadAtmosphere(QGetRenderContext()->Time())) )
556
pShader->SetArgument( ( *iUP ), this );
565
TqInt CqSurface::Split( std::vector<boost::shared_ptr<CqBasicSurface> >& aSplits )
567
TqInt cSplits = PreSubdivide( aSplits, m_SplitDir == SplitDir_U );
569
assert( aSplits.size() == 2 );
571
aSplits[ 0 ] ->SetSurfaceParameters( *this );
572
aSplits[ 0 ] ->SetSplitDir( ( SplitDir() == SplitDir_U ) ? SplitDir_V : SplitDir_U );
573
aSplits[ 0 ] ->SetEyeSplitCount( EyeSplitCount() );
574
aSplits[ 0 ] ->m_fDiceable = TqTrue;
575
//ADDREF( aSplits[ 0 ] );
577
aSplits[ 1 ] ->SetSurfaceParameters( *this );
578
aSplits[ 1 ] ->SetSplitDir( ( SplitDir() == SplitDir_U ) ? SplitDir_V : SplitDir_U );
579
aSplits[ 1 ] ->SetEyeSplitCount( EyeSplitCount() );
580
aSplits[ 1 ] ->m_fDiceable = TqTrue;
581
//ADDREF( aSplits[ 1 ] );
583
// Iterate through any use parameters subdividing and storing the second value in the target surface.
584
std::vector<CqParameter*>::iterator iUP;
585
std::vector<CqParameter*>::iterator end = m_aUserParams.end();
586
TqBool direction = SplitDir() == SplitDir_U;
588
for ( iUP = m_aUserParams.begin(); iUP != end; iUP++ )
590
CqParameter* pNewA = ( *iUP ) ->Clone();
591
CqParameter* pNewB = ( *iUP ) ->Clone();
592
( *iUP ) ->Subdivide( pNewA, pNewB, direction , this );
593
static_cast<CqSurface*>( aSplits[ 0 ].get() ) ->AddPrimitiveVariable( pNewA );
594
static_cast<CqSurface*>( aSplits[ 1 ].get() ) ->AddPrimitiveVariable( pNewB );
599
std::vector<boost::shared_ptr<CqBasicSurface> > aSplits0;
600
std::vector<boost::shared_ptr<CqBasicSurface> > aSplits1;
602
cSplits = aSplits[ 0 ] ->Split( aSplits0 );
603
cSplits += aSplits[ 1 ] ->Split( aSplits1 );
606
aSplits.swap( aSplits0 );
607
aSplits.insert( aSplits.end(), aSplits1.begin(), aSplits1.end() );
610
PostSubdivide( aSplits );
612
return ( aSplits.size() );
616
//---------------------------------------------------------------------
617
/** uSubdivide any user defined parameter variables.
620
void CqSurface::uSubdivideUserParameters( CqSurface* pA, CqSurface* pB )
622
// Iterate through any use parameters subdividing and storing the second value in the target surface.
623
std::vector<CqParameter*>::iterator iUP;
624
std::vector<CqParameter*>::iterator end = m_aUserParams.end();
625
for ( iUP = m_aUserParams.begin(); iUP != end; iUP++ )
627
CqParameter* pNewA = ( *iUP ) ->Clone();
628
CqParameter* pNewB = ( *iUP ) ->Clone();
629
( *iUP ) ->Subdivide( pNewA, pNewB, TqTrue, this );
630
pA->AddPrimitiveVariable( pNewA );
631
pB->AddPrimitiveVariable( pNewB );
636
//---------------------------------------------------------------------
637
/** vSubdivide any user defined parameter variables.
640
void CqSurface::vSubdivideUserParameters( CqSurface* pA, CqSurface* pB )
642
// Iterate through any use parameters subdividing and storing the second value in the target surface.
643
std::vector<CqParameter*>::iterator iUP;
644
std::vector<CqParameter*>::iterator end = m_aUserParams.end();
645
for ( iUP = m_aUserParams.begin(); iUP != end; iUP++ )
647
CqParameter* pNewA = ( *iUP ) ->Clone();
648
CqParameter* pNewB = ( *iUP ) ->Clone();
649
( *iUP ) ->Subdivide( pNewA, pNewB, TqFalse, this );
650
pA->AddPrimitiveVariable( pNewA );
651
pB->AddPrimitiveVariable( pNewB );
656
//---------------------------------------------------------------------
657
/** Transform the surface by the specified matrix.
660
void CqSurface::Transform( const CqMatrix& matTx, const CqMatrix& matITTx, const CqMatrix& matRTx, TqInt iTime )
662
// Tansform the control hull by the specified matrix.
663
std::vector<CqParameter*>::iterator iUP;
664
std::vector<CqParameter*>::iterator end = m_aUserParams.end();
665
for ( iUP = m_aUserParams.begin(); iUP != end; iUP++ )
669
if ( ( *iUP ) ->Type() == type_point )
671
CqParameterTyped<CqVector3D, CqVector3D>* pTPV = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
672
TqInt size = ( *iUP ) ->Size();
673
for ( i = 0; i < size; i++ )
674
pTPV->pValue() [ i ] = matTx * pTPV->pValue() [ i ];
676
else if ( ( *iUP ) ->Type() == type_normal )
678
CqParameterTyped<CqVector3D, CqVector3D>* pTPV = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
679
TqInt size = ( *iUP ) ->Size();
680
for ( i = 0; i < size; i++ )
681
pTPV->pValue() [ i ] = matITTx * pTPV->pValue() [ i ];
683
if ( ( *iUP ) ->Type() == type_vector )
685
CqParameterTyped<CqVector3D, CqVector3D>* pTPV = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( ( *iUP ) );
686
TqInt size = ( *iUP ) ->Size();
687
for ( i = 0; i < size; i++ )
688
pTPV->pValue() [ i ] = matRTx * pTPV->pValue() [ i ];
690
if ( ( *iUP ) ->Type() == type_hpoint )
692
CqParameterTyped<CqVector4D, CqVector3D>* pTPV = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( ( *iUP ) );
693
TqInt size = ( *iUP ) ->Size();
694
for ( i = 0; i < size; i++ )
695
pTPV->pValue() [ i ] = matTx * pTPV->pValue() [ i ];
702
/** Find out if a named user parameter exists on this surface.
704
CqParameter* CqSurface::FindUserParam( const char* name ) const
706
CqString strName( name );
707
std::vector<CqParameter*>::const_iterator iUP;
708
std::vector<CqParameter*>::const_iterator end = m_aUserParams.end();
709
for ( iUP = m_aUserParams.begin(); iUP != end ; iUP++ )
711
if( ( *iUP )->strName() == strName )
718
//---------------------------------------------------------------------
720
END_NAMESPACE( Aqsis )