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 Implement the majority of the RenderMan API functions.
23
\author Paul C. Gregory (pgregory@aqsis.com)
32
#include "imagebuffer.h"
43
#include "texturemap.h"
44
#include "objectinstance.h"
45
#include "trimcurve.h"
50
#include "librib2ri.h"
51
#include "converter.h"
54
#include "libribtypes.h"
55
#include "parserstate.h"
56
#include "procedural.h"
60
#include "subdivision2.h"
62
#ifndef AQSIS_SYSTEM_WIN32
64
#endif /* AQSIS_SYSTEM_WIN32 */
73
#include "ri_validate.inl"
75
using namespace Aqsis;
77
static RtBoolean ProcessPrimitiveVariables( CqSurface* pSurface, PARAMETERLIST );
78
static void ProcessCompression( TqInt *compress, TqInt *quality, TqInt count, RtToken *tokens, RtPointer *values );
79
RtVoid CreateGPrim( const boost::shared_ptr<CqBasicSurface>& pSurface );
80
void SetShaderArgument( IqShader* pShader, const char* name, TqPchar val );
81
TqBool ValidateState(...);
84
//---------------------------------------------------------------------
85
// This file contains the interface functions which are published as the
86
// Renderman Interface SPECification (C) 1988 Pixar.
89
//---------------------------------------------------------------------
90
// Interface parameter token strings.
93
RtToken RI_FRAMEBUFFER = "framebuffer";
94
RtToken RI_FILE = "file";
95
RtToken RI_RGB = "rgb";
96
RtToken RI_RGBA = "rgba";
97
RtToken RI_RGBZ = "rgbz";
98
RtToken RI_RGBAZ = "rgbaz";
101
RtToken RI_AZ = "az";
102
RtToken RI_MERGE = "merge";
103
RtToken RI_ORIGIN = "origin";
104
RtToken RI_PERSPECTIVE = "perspective";
105
RtToken RI_ORTHOGRAPHIC = "orthographic";
106
RtToken RI_HIDDEN = "hidden";
107
RtToken RI_PAINT = "paint";
108
RtToken RI_CONSTANT = "constant";
109
RtToken RI_SMOOTH = "smooth";
110
RtToken RI_FLATNESS = "flatness";
111
RtToken RI_FOV = "fov";
113
RtToken RI_AMBIENTLIGHT = "ambientlight";
114
RtToken RI_POINTLIGHT = "pointlight";
115
RtToken RI_DISTANTLIGHT = "distantlight";
116
RtToken RI_SPOTLIGHT = "spotlight";
117
RtToken RI_INTENSITY = "intensity";
118
RtToken RI_LIGHTCOLOR = "lightcolor";
119
RtToken RI_FROM = "from";
120
RtToken RI_TO = "to";
121
RtToken RI_CONEANGLE = "coneangle";
122
RtToken RI_CONEDELTAANGLE = "conedeltaangle";
123
RtToken RI_BEAMDISTRIBUTION = "beamdistribution";
124
RtToken RI_MATTE = "matte";
125
RtToken RI_METAL = "metal";
126
RtToken RI_PLASTIC = "plastic";
127
RtToken RI_SHIINYMETAL = "shinymetal";
128
RtToken RI_PAINTEDPLASTIC = "paintedplastic";
129
RtToken RI_KA = "ka";
130
RtToken RI_KD = "kd";
131
RtToken RI_KS = "ks";
132
RtToken RI_ROUGHNESS = "roughness";
133
RtToken RI_SPECULARCOLOR = "specularcolor";
134
RtToken RI_DEPTHCUE = "depthcue";
135
RtToken RI_FOG = "fog";
136
RtToken RI_BUMPY = "bumpy";
137
RtToken RI_MINDISTANCE = "mindistance";
138
RtToken RI_MAXDISTANCE = "maxdistance";
139
RtToken RI_BACKGROUND = "background";
140
RtToken RI_DISTANCE = "distance";
142
RtToken RI_RASTER = "raster";
143
RtToken RI_SCREEN = "screen";
144
RtToken RI_CAMERA = "camera";
145
RtToken RI_WORLD = "world";
146
RtToken RI_OBJECT = "object";
147
RtToken RI_INSIDE = "inside";
148
RtToken RI_OUTSIDE = "outside";
149
RtToken RI_LH = "lh";
150
RtToken RI_RH = "rh";
152
RtToken RI_PZ = "Pz";
153
RtToken RI_PW = "Pw";
155
RtToken RI_NP = "Np";
156
RtToken RI_CS = "Cs";
157
RtToken RI_OS = "Os";
160
RtToken RI_ST = "st";
161
RtToken RI_BILINEAR = "bilinear";
162
RtToken RI_BICUBIC = "bicubic";
163
RtToken RI_CUBIC = "cubic";
164
RtToken RI_LINEAR = "linear";
165
RtToken RI_PRIMITIVE = "primitive";
166
RtToken RI_INTERSECTION = "intersection";
167
RtToken RI_UNION = "union";
168
RtToken RI_DIFFERENCE = "difference";
169
RtToken RI_WRAP = "wrap";
170
RtToken RI_NOWRAP = "nowrap";
171
RtToken RI_PERIODIC = "periodic";
172
RtToken RI_NONPERIODIC = "nonperiodic";
173
RtToken RI_CLAMP = "clamp";
174
RtToken RI_BLACK = "black";
175
RtToken RI_IGNORE = "ignore";
176
RtToken RI_PRINT = "print";
177
RtToken RI_ABORT = "abort";
178
RtToken RI_HANDLER = "handler";
179
RtToken RI_IDENTIFIER = "identifier";
180
RtToken RI_NAME = "name";
181
RtToken RI_CURRENT = "current";
182
RtToken RI_SHADER = "shader";
183
RtToken RI_EYE = "eye";
184
RtToken RI_NDC = "ndc";
185
RtToken RI_AMPLITUDE = "amplitude";
186
RtToken RI_COMMENT = "comment";
187
RtToken RI_CONSTANTWIDTH = "constantwidth";
188
RtToken RI_KR = "kr";
189
RtToken RI_SHINYMETAL = "shinymetal";
190
RtToken RI_STRUCTURE = "structure";
191
RtToken RI_TEXTURENAME = "texturename";
192
RtToken RI_VERBATIM = "verbatim";
193
RtToken RI_WIDTH = "width";
195
RtBasis RiBezierBasis = {{ -1.0f, 3.0f, -3.0f, 1.0f},
196
{ 3.0f, -6.0f, 3.0f, 0.0f},
197
{ -3.0f, 3.0f, 0.0f, 0.0f},
198
{ 1.0f, 0.0f, 0.0f, 0.0f}};
199
RtBasis RiBSplineBasis = {{ -1.0f/6.0f, 0.5f, -0.5f, 1.0f/6.0f},
200
{ 0.5f, -1.0f, 0.5f, 0.0f},
201
{ -0.5f, 0.0f, 0.5f, 0.0f},
202
{ 1.0f/6.0f, 2.0f/3.0f, 1.0f/6.0f, 0.0f}};
203
RtBasis RiCatmullRomBasis={{ -0.5f, 1.5f, -1.5f, 0.5f},
204
{ 1.0f, -2.5f, 2.0f, -0.5f},
205
{ -0.5f, 0.0f, 0.5f, 0.0f},
206
{ 0.0f, 1.0f, 0.0f, 0.0f}};
207
RtBasis RiHermiteBasis = {{ 2.0f, 1.0f, -2.0f, 1.0f},
208
{ -3.0f, -2.0f, 3.0f, -1.0f},
209
{ 0.0f, 1.0f, 0.0f, 0.0f},
210
{ 1.0f, 0.0f, 0.0f, 0.0f}};
211
RtBasis RiPowerBasis = {{ 1.0f, 0.0f, 0.0f, 0.0f},
212
{ 0.0f, 1.0f, 0.0f, 0.0f},
213
{ 0.0f, 0.0f, 1.0f, 0.0f},
214
{ 0.0f, 0.0f, 0.0f, 1.0f}};
228
static TqUlong RIH_S = CqParameter::hash( RI_S );
229
static TqUlong RIH_T = CqParameter::hash( RI_T );
230
static TqUlong RIH_ST = CqParameter::hash( RI_ST );
231
static TqUlong RIH_CS = CqParameter::hash( RI_CS );
232
static TqUlong RIH_OS = CqParameter::hash( RI_OS );
233
static TqUlong RIH_P = CqParameter::hash( RI_P );
234
static TqUlong RIH_PZ = CqParameter::hash( RI_PZ );
235
static TqUlong RIH_PW = CqParameter::hash( RI_PW );
236
static TqUlong RIH_N = CqParameter::hash( RI_N );
237
static TqUlong RIH_NP = CqParameter::hash( RI_NP );
238
static TqUlong RIH_DEPTHFILTER = CqParameter::hash( "depthfilter" );
239
static TqUlong RIH_JITTER = CqParameter::hash( "jitter" );
241
RtInt RiLastError = 0;
243
//----------------------------------------------------------------------
245
// Helper function to build a GPrim from any boost::shared_ptr<> type..
248
RtVoid CreateGPrim( const boost::shared_ptr<T>& pSurface )
250
CreateGPrim( boost::static_pointer_cast<CqBasicSurface,T>( pSurface ) );
253
//----------------------------------------------------------------------
254
// BuildParameterList
255
// Helper function to build a parameter list to pass on to the V style functions.
256
// returns a parameter count.
258
RtInt BuildParameterList( va_list pArgs, std::vector<RtToken>& aTokens, std::vector<RtPointer>& aValues )
261
RtToken pToken = va_arg( pArgs, RtToken );
265
while ( pToken != 0 && pToken != RI_NULL ) // While not RI_NULL
267
aTokens.push_back( pToken );
268
pValue = va_arg( pArgs, RtPointer );
269
aValues.push_back( pValue );
270
pToken = va_arg( pArgs, RtToken );
277
//----------------------------------------------------------------------
278
// CqRangeCheckCallback implentation
279
// Use this with CheckMinMax
281
class CqLogRangeCheckCallback : public CqRangeCheckCallback
284
CqLogRangeCheckCallback()
287
void set( const char* name )
292
virtual void operator()( int res )
296
case CqRangeCheckCallback::UPPER_BOUND_HIT:
298
std::cerr << error << "Invalid Value for " << m_name << ". Value exceeded upper limit" << std::endl;
301
case CqRangeCheckCallback::LOWER_BOUND_HIT:
303
std::cerr << error << "Invalid Value for " << m_name << ". Value exceeded lower limit" << std::endl;
317
//----------------------------------------------------------------------
319
// Check that the currect graphics state is one of those specified.
321
TqBool ValidateState(int count, ... )
324
va_start( pArgs, count );
326
int currentState = Outside;
327
if( QGetRenderContext() != NULL && QGetRenderContext()->pconCurrent() )
328
currentState = QGetRenderContext()->pconCurrent()->Type();
331
for(i=0; i<count; i++)
333
int state = va_arg( pArgs, int );
334
if( currentState == state )
341
//----------------------------------------------------------------------
343
// Get a string representing the current state.
345
const char* GetStateAsString()
347
int currentState = Outside;
348
if( QGetRenderContext()->pconCurrent() )
349
currentState = QGetRenderContext()->pconCurrent()->Type();
350
switch( currentState )
392
//----------------------------------------------------------------------
394
// Declare a new variable to be recognised by the system.
396
RtToken RiDeclare( RtString name, RtString declaration )
402
CqString strName( name ), strDecl( declaration );
403
QGetRenderContext() ->AddParameterDecl( strName.c_str(), strDecl.c_str() );
407
//----------------------------------------------------------------------
409
// Begin a Renderman render phase.
411
extern "C" char *StandardParameters[][2];
412
RtVoid RiBegin( RtToken name )
416
// Create a new renderer
417
QSetRenderContext( new CqRenderer );
419
QGetRenderContext() ->Initialise();
420
QGetRenderContext() ->BeginMainModeBlock();
421
QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix() );
422
QGetRenderContext() ->SetCameraTransform( QGetRenderContext() ->ptransCurrent() );
423
// Clear the lightsources stack.
424
CqLightsource* pL = Lightsource_stack.pFirst();
427
// Unlink from the stack, and release the stacks reference to the light.
430
pL = Lightsource_stack.pFirst();
433
// Clear any options.
434
QGetRenderContext() ->optCurrent().ClearOptions();
436
// Include the standard options (how can we opt out of this).
438
while( StandardParameters[param][0] != NULL )
441
StandardParameters[param][0],
442
StandardParameters[param][1]
447
// Setup default paths
448
const char* popt[ 1 ];
450
strSetting = Aqsis::CqFile::GetSystemSetting( "shaders" );
451
popt[ 0 ] = strSetting.c_str();
452
RiOption( "searchpath", "shader", &popt, RI_NULL );
453
strSetting = Aqsis::CqFile::GetSystemSetting( "archives" );
454
popt[ 0 ] = strSetting.c_str();
455
RiOption( "searchpath", "archive", &popt, RI_NULL );
456
strSetting = Aqsis::CqFile::GetSystemSetting( "textures" );
457
popt[ 0 ] = strSetting.c_str();
458
RiOption( "searchpath", "texture", &popt, RI_NULL );
459
strSetting = Aqsis::CqFile::GetSystemSetting( "displays" );
460
popt[ 0 ] = strSetting.c_str();
461
RiOption( "searchpath", "display", &popt, RI_NULL );
462
strSetting = Aqsis::CqFile::GetSystemSetting( "dsolibs" );
463
popt[ 0 ] = strSetting.c_str();
464
RiOption( "searchpath", "dsolibs", &popt, RI_NULL );
465
strSetting = Aqsis::CqFile::GetSystemSetting( "procedurals" );
466
popt[ 0 ] = strSetting.c_str();
467
RiOption( "searchpath", "procedural", &popt, RI_NULL );
469
// Setup a default Display
470
RiDisplay( "ri.pic", "file", "rgba", NULL );
472
// Setup a default surface shader
473
CqShaderVM * pShader = new CqShaderVM();
474
pShader->SetstrName( "_def_" );
475
pShader->DefaultSurface();
476
pShader->matCurrent() = QGetRenderContext() ->matCurrent(QGetRenderContext()->Time());
477
pShader->PrepareDefArgs();
478
QGetRenderContext() ->RegisterShader( "_def_", Type_Surface, pShader );
479
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pShader, QGetRenderContext() ->Time() );
481
// Setup the initial transformation.
482
// QGetRenderContext()->ptransWriteCurrent() ->SetHandedness( TqFalse );
483
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
488
//----------------------------------------------------------------------
490
// End the rendermam render stage.
496
QGetRenderContext() ->EndMainModeBlock();
498
// Flush the image cache.
499
CqTextureMap::FlushCache();
501
// Clear the lightsources stack.
502
CqLightsource* pL = Lightsource_stack.pFirst();
505
// Unlink from the stack, and release the stacks reference to the light.
508
pL = Lightsource_stack.pFirst();
511
// Delete the renderer
512
delete( QGetRenderContext() );
513
QSetRenderContext( 0 );
519
//----------------------------------------------------------------------
521
// Begin an individual frame, options are saved at this point.
523
RtVoid RiFrameBegin( RtInt number )
527
Validate_RiFrameBegin
529
// Initialise the statistics variables. If the RIB doesn't contain
530
// a Frame-block the initialisation was previously done in CqStats::Initilise()
531
// which has to be called before a rendering session.
532
QGetRenderContext() ->Stats().InitialiseFrame();
533
// Start the timer. Note: The corresponding call of StopFrameTimer() is
534
// done in WorldEnd (!) not FrameEnd since it can happen that there is
535
// not FrameEnd (and usually there's not much between WorldEnd and FrameEnd).
536
QGetRenderContext() ->Stats().StartFrameTimer();
538
QGetRenderContext() ->BeginFrameModeBlock();
539
QGetRenderContext() ->SetCurrentFrame( number );
540
CqCSGTreeNode::SetRequired( TqFalse );
545
//----------------------------------------------------------------------
547
// End the rendering of an individual frame, options are restored.
555
QGetRenderContext() ->EndFrameModeBlock();
556
QGetRenderContext() ->ClearDisplayRequests();
561
//----------------------------------------------------------------------
563
// Start the information for the world, options are now frozen. The world-to-camera
564
// transformation is set to the current transformation, and current is set to identity.
566
RtVoid RiWorldBegin()
570
Validate_RiWorldBegin
572
// Call any specified pre world function.
573
if ( QGetRenderContext()->pPreWorldFunction() != NULL )
574
( *QGetRenderContext()->pPreWorldFunction() ) ();
576
// Start the frame timer (just in case there was no FrameBegin block. If there
577
// was, nothing happens)
578
QGetRenderContext() ->Stats().StartFrameTimer();
579
QGetRenderContext() ->Stats().MakeParse().Start();
581
// Now that the options have all been set, setup any undefined camera parameters.
582
if ( !QGetRenderContext() ->optCurrent().FrameAspectRatioCalled() )
584
// Derive the FAR from the resolution and pixel aspect ratio.
585
RtFloat PAR = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "PixelAspectRatio" ) [ 0 ];
586
RtFloat resH = QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "Resolution" ) [ 0 ];
587
RtFloat resV = QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "Resolution" ) [ 1 ];
588
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = ( resH * PAR ) / resV ;
591
if ( !QGetRenderContext() ->optCurrent().ScreenWindowCalled() )
593
RtFloat fFAR = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "FrameAspectRatio" ) [ 0 ];
597
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = -fFAR ;
598
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = + fFAR ;
599
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = + 1 ;
600
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = -1 ;
604
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = -1 ;
605
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = + 1 ;
606
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = + 1.0 / fFAR ;
607
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = -1.0 / fFAR ;
611
QGetRenderContext() ->BeginWorldModeBlock();
612
// Set the world to camera transformation matrix to the current matrix.
613
QGetRenderContext() ->SetCameraTransform( QGetRenderContext() ->ptransCurrent() );
614
// and then reset the current matrix to identity, ready for object transformations.
615
if(QGetRenderContext() ->ptransWriteCurrent() ->cTimes() > 1)
618
CqMatrix matOpenShutterInverse = QGetRenderContext() ->ptransCurrent() ->matObjectToWorld( QGetRenderContext() ->ptransCurrent() ->Time( 0 ) );
619
matOpenShutterInverse = matOpenShutterInverse.Inverse();
620
QGetRenderContext() ->ptransWriteCurrent() ->SetCurrentTransform( QGetRenderContext() ->ptransCurrent() ->Time( 0 ), CqMatrix() );
621
for ( i = 1; i < QGetRenderContext() ->ptransWriteCurrent() ->cTimes(); ++i )
622
QGetRenderContext() ->ptransWriteCurrent() ->SetCurrentTransform( QGetRenderContext() ->ptransCurrent() ->Time( i ), matOpenShutterInverse * QGetRenderContext() ->ptransCurrent() ->matObjectToWorld( QGetRenderContext() ->ptransCurrent() ->Time( i ) ) );
625
QGetRenderContext() ->ptransWriteCurrent() ->SetCurrentTransform( QGetRenderContext() ->Time(), CqMatrix() );
626
// Clear the camera transform to a single state, all camera motion is now transferred to the objects.
627
QGetRenderContext()->GetCameraTransform()->ResetTransform( QGetRenderContext()->GetCameraTransform()->matObjectToWorld( QGetRenderContext()->GetCameraTransform()->Time(0) ),
628
QGetRenderContext()->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) );
630
QGetRenderContext() ->optCurrent().InitialiseCamera();
631
QGetRenderContext() ->pImage() ->SetImage();
637
//----------------------------------------------------------------------
639
// End the specifying of world data, options are released.
648
TqBool fFailed = TqFalse;
649
// Call any specified pre render function.
650
if ( QGetRenderContext()->pPreRenderFunction() != NULL )
651
( *QGetRenderContext()->pPreRenderFunction() ) ();
653
// Stop the parsing counter
654
QGetRenderContext() ->Stats().MakeParse().Stop();
657
const TqInt* poptVerbose = QGetRenderContext() ->optCurrent().GetIntegerOption( "statistics", "renderinfo" );
660
QGetRenderContext() -> Stats().PrintInfo();
663
const TqInt* poptGridSize = QGetRenderContext() ->optCurrent().GetIntegerOption( "limits", "gridsize" );
664
if( NULL != poptGridSize )
665
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "SqrtGridSize" )[0] = sqrt( static_cast<float>(poptGridSize[0]) );
667
// Finalise the raytracer database now that all primitives are in.
668
if(QGetRenderContext()->pRaytracer())
669
QGetRenderContext()->pRaytracer()->Finalise();
674
QGetRenderContext() ->RenderWorld();
676
catch ( CqString strError )
678
std::cout << strError.c_str() << std::endl;
682
// Delete the world context
683
QGetRenderContext() ->EndWorldModeBlock();
685
// Stop the frame timer
686
QGetRenderContext() ->Stats().StopFrameTimer();
690
// Get the verbosity level from the options...
692
const TqInt* poptEndofframe = QGetRenderContext() ->optCurrent().GetIntegerOption( "statistics", "endofframe" );
693
if ( poptEndofframe != 0 )
694
verbosity = poptEndofframe[ 0 ];
696
// ...and print the statistics.
697
QGetRenderContext() ->Stats().PrintStats( verbosity );
703
//----------------------------------------------------------------------
705
// Specify the setup of the final image.
707
RtVoid RiFormat( RtInt xresolution, RtInt yresolution, RtFloat pixelaspectratio )
713
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Resolution" ) [ 0 ] = xresolution ;
714
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Resolution" ) [ 1 ] = yresolution ;
715
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "PixelAspectRatio" ) [ 0 ] = ( pixelaspectratio < 0.0 ) ? 1.0 : pixelaspectratio ;
717
// Inform the system that RiFormat has been called, as this takes priority.
718
QGetRenderContext() ->optCurrent().CallFormat();
724
//----------------------------------------------------------------------
725
// RiFrameAspectRatio
726
// Set the aspect ratio of the frame irrespective of the display setup.
728
RtVoid RiFrameAspectRatio( RtFloat frameratio )
730
Cache_RiFrameAspectRatio
732
Validate_RiFrameAspectRatio
734
CqLogRangeCheckCallback rc;
738
rc.set( "frameratio");
739
if( !CheckMinMax( frameratio, 0.0f, RI_INFINITY, &rc ) )
746
std::cerr << error << "RiFrameAspectRatio: Invalid RiFrameAspectRatio, aborting" << std::endl;
747
throw( "INVALID_VALUE" );
751
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = frameratio ;
753
// Inform the system that RiFrameAspectRatio has been called, as this takes priority.
754
QGetRenderContext() ->optCurrent().CallFrameAspectRatio();
760
//----------------------------------------------------------------------
762
// Set the resolution of the screen window in the image plane specified in the screen
763
// coordinate system.
765
RtVoid RiScreenWindow( RtFloat left, RtFloat right, RtFloat bottom, RtFloat top )
769
Validate_RiScreenWindow
771
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = left ;
772
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = right ;
773
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = top ;
774
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = bottom ;
776
// Inform the system that RiScreenWindow has been called, as this takes priority.
777
QGetRenderContext() ->optCurrent().CallScreenWindow();
783
//----------------------------------------------------------------------
785
// Set the position and size of the crop window specified in fractions of the raster
788
RtVoid RiCropWindow( RtFloat left, RtFloat right, RtFloat top, RtFloat bottom )
792
Validate_RiCropWindow
794
CqLogRangeCheckCallback rc;
799
if( !CheckMinMax( left, 0.0f, 1.0f, &rc ) )
805
if( !CheckMinMax( right, 0.0f, 1.0f, &rc ) )
811
if( !CheckMinMax( top, 0.0f, 1.0f, &rc ) )
817
if( !CheckMinMax( bottom, 0.0f, 1.0f, &rc ) )
824
std::cerr << error << "Invalid RiCropWindow, aborting" << std::endl;
825
throw( "INVALID_VALUE" );
829
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 0 ] = left ;
830
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 1 ] = right ;
831
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 2 ] = top ;
832
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 3 ] = bottom ;
838
//----------------------------------------------------------------------
840
// Set the camera projection to be used.
842
RtVoid RiProjection( RtToken name, ... )
845
va_start( pArgs, name );
847
std::vector<RtToken> aTokens;
848
std::vector<RtPointer> aValues;
849
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
851
RiProjectionV( name, count, &aTokens[0], &aValues[0] );
855
//----------------------------------------------------------------------
857
// List mode version of above.
859
RtVoid RiProjectionV( RtToken name, PARAMETERLIST )
863
Validate_RiProjection
865
if ( strcmp( name, RI_PERSPECTIVE ) == 0 )
866
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Projection" ) [ 0 ] = ProjectionPerspective ;
867
else if ( strcmp( name, RI_ORTHOGRAPHIC ) == 0 )
868
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Projection" ) [ 0 ] = ProjectionOrthographic ;
869
else if( name != RI_NULL )
871
std::cerr << error << "RiProjection: Invalid projection: \"" << name << "\"" << std::endl;
876
for ( i = 0; i < count; ++i )
878
RtToken token = tokens[ i ];
879
RtPointer value = values[ i ];
881
if ( strcmp( token, RI_FOV ) == 0 )
882
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FOV" ) [ 0 ] = *( reinterpret_cast<RtFloat*>( value ) ) ;
884
// TODO: need to get the current transformation so that it can be added to the screen transformation.
885
QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix() );
891
//----------------------------------------------------------------------
893
// Set the near and far clipping planes specified as distances from the camera.
895
RtVoid RiClipping( RtFloat cnear, RtFloat cfar )
901
CqLogRangeCheckCallback rc;
906
if( !CheckMinMax( cnear, RI_EPSILON, cfar, &rc ) )
912
if( !CheckMinMax( cfar, cnear, RI_INFINITY, &rc ) )
919
std::cerr << error << "RiClipping: Invalid RiClipping, clipping planes set to RI_EPSILON, RI_INFINITY" << std::endl;
924
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Clipping" ) [ 0 ] = cnear ;
925
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Clipping" ) [ 1 ] = cfar ;
931
//----------------------------------------------------------------------
933
// Specify the parameters which affect focal blur of the camera.
935
RtVoid RiDepthOfField( RtFloat fstop, RtFloat focallength, RtFloat focaldistance )
939
Validate_RiDepthOfField
941
CqLogRangeCheckCallback rc;
946
if( !CheckMinMax( fstop, 0.0f, RI_INFINITY, &rc ) )
951
rc.set( "focallength" );
952
if( !CheckMinMax( focallength, 0.0f, RI_INFINITY, &rc ) )
957
rc.set( "focaldistance" );
958
if( !CheckMinMax( focaldistance, 0.0f, RI_INFINITY, &rc ) )
965
std::cerr << warning << "RiDepthOfField: Invalid DepthOfField, DepthOfField ignored" << std::endl;
969
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "DepthOfField" ) [ 0 ] = fstop ;
970
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "DepthOfField" ) [ 1 ] = focallength ;
971
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "DepthOfField" ) [ 2 ] = focaldistance ;
973
QGetRenderContext() ->SetDepthOfFieldData( fstop, focallength, focaldistance );
977
//----------------------------------------------------------------------
979
// Set the times at which the shutter opens and closes, used for motion blur.
981
RtVoid RiShutter( RtFloat opentime, RtFloat closetime )
987
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Shutter" ) [ 0 ] = opentime;
988
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Shutter" ) [ 1 ] = closetime;
994
//----------------------------------------------------------------------
996
// Set the upper bound on the variance from the true pixel color by the pixel filter
999
RtVoid RiPixelVariance( RtFloat variance )
1001
Cache_RiPixelVariance
1003
Validate_RiPixelVariance
1005
CqLogRangeCheckCallback rc;
1009
rc.set( "variance" );
1010
if( !CheckMinMax( variance, 0.0f, RI_INFINITY, &rc ) )
1017
std::cerr << warning << "RiPixelVariance: Invalid PixelVariance, PixelVariance set to 0" << std::endl;
1021
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "PixelVariance" ) [ 0 ] = variance ;
1027
//----------------------------------------------------------------------
1029
// Set the number of samples per pixel for the hidden surface function.
1031
RtVoid RiPixelSamples( RtFloat xsamples, RtFloat ysamples )
1033
Cache_RiPixelSamples
1035
Validate_RiPixelSamples
1037
CqLogRangeCheckCallback rc;
1041
rc.set( "xsamples" );
1042
if( !CheckMinMax( xsamples, 1.0f, RI_INFINITY, &rc ) )
1047
rc.set( "ysamples" );
1048
if( !CheckMinMax( ysamples, 1.0f, RI_INFINITY, &rc ) )
1055
std::cerr << warning << "RiPixelSamples: Invalid PixelSamples, PixelSamples set to 1, 1" << std::endl;
1060
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "PixelSamples" ) [ 0 ] = static_cast<TqInt>( xsamples ) ;
1061
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "PixelSamples" ) [ 1 ] = static_cast<TqInt>( ysamples ) ;
1067
//----------------------------------------------------------------------
1069
// Set the function used to generate a final pixel value from supersampled values.
1071
RtVoid RiPixelFilter( RtFilterFunc function, RtFloat xwidth, RtFloat ywidth )
1075
Validate_RiPixelFilter
1077
QGetRenderContext() ->optCurrent().SetfuncFilter( function );
1078
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FilterWidth" ) [ 0 ] = xwidth ;
1079
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FilterWidth" ) [ 1 ] = ywidth ;
1085
//----------------------------------------------------------------------
1087
// Set the values of the exposure color modification function.
1089
RtVoid RiExposure( RtFloat gain, RtFloat gamma )
1095
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Exposure" ) [ 0 ] = gain ;
1096
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Exposure" ) [ 1 ] = gamma ;
1102
//----------------------------------------------------------------------
1104
// Specify a prepocessing imager shader.
1106
RtVoid RiImager( RtToken name, ... )
1109
va_start( pArgs, name );
1111
std::vector<RtToken> aTokens;
1112
std::vector<RtPointer> aValues;
1113
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
1115
RiImagerV( name, count, &aTokens[0], &aValues[0] );
1119
//----------------------------------------------------------------------
1121
// List based version of above.
1123
RtVoid RiImagerV( RtToken name, PARAMETERLIST )
1131
if ( strlen( name ) )
1133
QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "Imager" ) [ 0 ] = name ;
1134
QGetRenderContext() ->optCurrent().LoadImager( name );
1135
for ( i = 0; i < count; ++i )
1137
RtToken token = tokens[ i ];
1138
RtPointer value = values[ i ];
1140
QGetRenderContext() ->optCurrent().SetValueImager(
1141
token, static_cast<TqPchar>( value ) );
1148
//----------------------------------------------------------------------
1150
// Specify the color quantization parameters.
1152
RtVoid RiQuantize( RtToken type, RtInt one, RtInt min, RtInt max, RtFloat ditheramplitude )
1158
if ( strcmp( type, "rgba" ) == 0 )
1160
TqFloat* pColorQuantize = QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "Quantize", "Color" );
1161
pColorQuantize [ 0 ] = static_cast<TqFloat>( one );
1162
pColorQuantize [ 1 ] = static_cast<TqFloat>( min );
1163
pColorQuantize [ 2 ] = static_cast<TqFloat>( max );
1164
pColorQuantize [ 3 ] = static_cast<TqFloat>( ditheramplitude );
1166
else if ( strcmp( type, "z" ) == 0 )
1168
TqFloat* pDepthQuantize = QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "Quantize", "Depth" );
1169
pDepthQuantize [ 0 ] = static_cast<TqFloat>( one );
1170
pDepthQuantize [ 1 ] = static_cast<TqFloat>( min );
1171
pDepthQuantize [ 2 ] = static_cast<TqFloat>( max );
1172
pDepthQuantize [ 3 ] = static_cast<TqFloat>( ditheramplitude );
1176
CqNamedParameterList* pOption = QGetRenderContext() ->optCurrent().pOptionWrite( "Quantize" ).get();
1179
CqParameterTypedUniformArray<TqFloat,type_float,TqFloat>* pQuant = new CqParameterTypedUniformArray<TqFloat,type_float,TqFloat>(type,4); \
1180
pQuant->pValue()[0] = static_cast<TqFloat>( one );
1181
pQuant->pValue()[1] = static_cast<TqFloat>( min );
1182
pQuant->pValue()[2] = static_cast<TqFloat>( max );
1183
pQuant->pValue()[3] = static_cast<TqFloat>( ditheramplitude );
1184
pOption->AddParameter( pQuant );
1192
//----------------------------------------------------------------------
1194
// Set the final output name and type.
1196
RtVoid RiDisplay( RtToken name, RtToken type, RtToken mode, ... )
1199
va_start( pArgs, mode );
1201
std::vector<RtToken> aTokens;
1202
std::vector<RtPointer> aValues;
1203
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
1205
RiDisplayV( name, type, mode, count, &aTokens[0], &aValues[0] );
1209
//----------------------------------------------------------------------
1211
// List based version of above.
1213
RtVoid RiDisplayV( RtToken name, RtToken type, RtToken mode, PARAMETERLIST )
1219
CqString strName( name );
1220
CqString strType( type );
1222
QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "DisplayName" ) [ 0 ] = strName.c_str() ;
1223
QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "DisplayType" ) [ 0 ] = strType.c_str() ;
1225
// Append the display mode to the current setting.
1228
TqInt dataOffset = 0;
1230
if ( strncmp( mode, RI_RGB, strlen(RI_RGB) ) == 0 )
1234
index += strlen( RI_RGB );
1236
if ( strncmp( &mode[index], RI_A, strlen( RI_A ) ) == 0 )
1240
index += strlen( RI_A );
1242
if ( strncmp( &mode[index], RI_Z, strlen( RI_Z ) ) == 0 )
1246
index += strlen( RI_Z );
1249
// If none of the standard "rgbaz" strings match, then it is an alternative 'arbitrary output variable'
1252
dataOffset = QGetRenderContext()->RegisterOutputData( mode );
1253
dataSize = QGetRenderContext()->OutputDataSamples( mode );
1256
// Gather the additional arguments into a map to pass through to the manager.
1257
std::map<std::string, void*> mapOfArguments;
1259
for( i = 0; i < count; ++i )
1260
mapOfArguments[ tokens[ i ] ] = values[ i ];
1262
// Check if the request is to add a display driver.
1263
if ( strName[ 0 ] == '+' )
1265
TqInt iMode = QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "DisplayMode" ) [ 0 ] | eValue;
1266
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = iMode;
1267
strName = strName.substr( 1 );
1271
QGetRenderContext() ->ClearDisplayRequests();
1272
QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = eValue ;
1274
// Add a display driver to the list of requested drivers.
1275
QGetRenderContext() ->AddDisplayRequest( strName.c_str(), strType.c_str(), mode, eValue, dataOffset, dataSize, mapOfArguments );
1281
//----------------------------------------------------------------------
1283
// Gaussian filter used as a possible value passed to RiPixelFilter.
1285
RtFloat RiGaussianFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1288
* d = distance from origin
1289
* w = filterwidth ([COOK84a] article used 1.5)
1290
* For here use sqrt( (xwidth/2)*(xwidth/2) + (ywidth/2)*(ywidth/2) ).
1293
* w = sqrt( (xwidth*xwidth)/2 + (ywidth*ywidth)/2 )
1294
* w = sqrt( (xwidth*xwidth + ywidth*ywidth)/2 )
1295
* w*w = (xwidth*xwidth + ywidth*ywidth)/2
1297
* if (d < filterwidth) then 0
1298
* else exp(-d*d) - exp(-w*w)
1301
//RtFloat d,d2,w,w2;
1303
///* d = sqrt(x*x+y*y), d*d = (x*x+y*y) */
1307
//w2 = 0.5*(xwidth*xwidth + ywidth*ywidth);
1313
// return(exp(-d2) - exp(-w2));
1315
// The above version falls faster than the one used by the 3.2 spec
1316
// PRMan and RenderDotC. Since all three match exactly, might as
1317
// well change to the code below:
1321
return exp( -2.0 * ( x * x + y * y ) );
1325
//----------------------------------------------------------------------
1327
// Box filter used as a possible value passed to RiPixelFIlter.
1329
RtFloat RiBoxFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1331
/* [UPST89] -- (RC p. 178) says that x and y will be in the
1332
* following intervals:
1333
* -xwidth/2 <= x <= xwidth/2
1334
* -ywidth/2 <= y <= ywidth/2
1335
* These constraints on x and y really simplifies the
1336
* the following code to just return (1.0).
1339
return MIN( ( fabs( x ) <= xwidth / 2.0 ? 1.0 : 0.0 ),
1340
( fabs( y ) <= ywidth / 2.0 ? 1.0 : 0.0 ) );
1344
//----------------------------------------------------------------------
1346
// Triangle filter used as a possible value passed to RiPixelFilter
1348
RtFloat RiTriangleFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1350
RtFloat hxw = xwidth / 2.0;
1351
RtFloat hyw = ywidth / 2.0;
1352
RtFloat absx = fabs( x );
1353
RtFloat absy = fabs( y );
1355
/* This function can be simplified as well by not worrying about
1356
* returning zero if the sample is beyond the filter window.
1358
return MIN( ( absx <= hxw ? ( hxw - absx ) / hxw : 0.0 ),
1359
( absy <= hyw ? ( hyw - absy ) / hyw : 0.0 ) );
1363
//----------------------------------------------------------------------
1364
// RiCatmullRomFilter
1365
// Catmull Rom filter used as a possible value passed to RiPixelFilter.
1367
RtFloat RiCatmullRomFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1370
* From page 223 of [MITC88]
1373
* f(d) = 1/6*( (12-9*B-9*C)*abs(d*d*d)
1374
* + (-18 + 12*B + 6*C)*d*d + (6-2*B) )
1376
* if 1 <= abs(d) < 2
1377
* f(d) = 1/6*( (-B-6*C)*abs(d*d*d)
1378
* + (6*B + 30*C)*d*d
1379
* + (-12*B - 48*C)*d
1384
* -------------------------------------------------------------
1385
* When B = 0.0 and C = 0.5 the filter is a Catmull-Rom cubic spline.
1388
* f(d) = 1/6*[ (12-3)*abs(d*d*d) + (-18 + 3)*d*d + (6) ]
1390
* if 1 <= abs(d) < 2
1391
* f(d) = 1/6*[ (-3)*abs(d*d*d) + (15)*d*d + (-24)*d + (12) ]
1394
* -------------------------------------------------------------
1398
* f(d) = (3/2)*abs(d*d*d) - (5/2)*d*d + 1
1401
* f(d) = (-0.5)*abs(d*d*d) + (5/2)*d*d - 4*abs(d) + 2
1408
d2 = x * x + y * y; /* d*d */
1409
d = sqrt( d2 ); /* distance from origin */
1412
return ( 1.5 * d * d2 - 2.5 * d2 + 1.0 );
1414
return ( -d * d2 * 0.5 + 2.5 * d2 - 4.0 * d + 2.0 );
1420
//----------------------------------------------------------------------
1422
// Sinc filter used as a possible value passed to RiPixelFilter.
1424
RtFloat RiSincFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1428
//d = sqrt(x*x+y*y);
1431
// return(sin(RI_PI*d)/(RI_PI*d));
1435
// The above is an un-windowed sinc, below is a windowed sinc
1436
// function similar in shape to what PRMan 3.9 uses.
1439
/* Modified version of the RI Spec 3.2 sinc filter to be
1440
* windowed with a positive lobe of a cosine which is half
1441
* of a cosine period.
1444
/* Uses a -PI to PI cosine window. */
1448
x = cos( 0.5 * x / xwidth ) * sin( x ) / x;
1457
y = cos( 0.5 * y / ywidth ) * sin( y ) / y;
1464
/* This is a square separable filter and is the 2D Fourier
1465
* transform of a rectangular box outlining a lowpass bandwidth
1466
* filter in the frequency domain.
1472
//----------------------------------------------------------------------
1473
// RiDiskFilter -- this is in Pixar's ri.h
1474
// Cylindrical filter used as a possible value passed to RiPixelFilter
1476
RtFloat RiDiskFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1485
d = ( xx ) / ( xwidth * xwidth ) + ( yy ) / ( ywidth * ywidth );
1497
//----------------------------------------------------------------------
1498
// RiBesselFilter -- this is in Pixar's ri.h
1499
// Besselj0 filter used as a possible value passed to RiPixelFilter
1501
RtFloat RiBesselFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
1504
double d, w, xx, yy;
1512
w = ( xx ) / ( xwidth * xwidth ) + ( yy ) / ( ywidth * ywidth );
1515
d = sqrt( xx + yy );
1518
/* Half cosine window. */
1519
w = cos( 0.5 * RI_PI * sqrt( w ) );
1520
return w * 2*j1( RI_PI * d ) / d;
1534
//----------------------------------------------------------------------
1536
// Specify a hidden surface calculation mode.
1538
RtVoid RiHider( RtToken name, ... )
1541
va_start( pArgs, name );
1543
std::vector<RtToken> aTokens;
1544
std::vector<RtPointer> aValues;
1545
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
1547
RiHiderV( name, count, &aTokens[0], &aValues[0] );
1551
//----------------------------------------------------------------------
1553
// List based version of above.
1555
RtVoid RiHiderV( RtToken name, PARAMETERLIST )
1561
if ( !strcmp( name, "hidden" ) || !strcmp( name, "painter" ) )
1563
QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "Hider" ) [ 0 ] = name ;
1568
for ( i = 0; i < count; ++i )
1570
SqParameterDeclaration Decl;
1573
Decl = QGetRenderContext()->FindParameterDecl( tokens[ i ] );
1575
catch( XqException e )
1577
std::cerr << error << e.strReason().c_str() << std::endl;
1580
TqUlong hash = CqParameter::hash(Decl.m_strName.c_str());
1581
if ( hash == RIH_DEPTHFILTER )
1582
RiOption( "Hider", "depthfilter", ( RtToken ) values[ i ], NULL );
1583
else if ( hash == RIH_JITTER )
1584
RiOption( "Hider", "jitter", ( RtFloat* ) values[ i ], NULL );
1591
//----------------------------------------------------------------------
1593
// Specify the depth and conversion arrays for color manipulation.
1595
RtVoid RiColorSamples( RtInt N, RtFloat *nRGB, RtFloat *RGBn )
1597
Cache_RiColorSamples
1599
Validate_RiColorSamples
1601
std::cerr << warning << "RiColorSamples not supported" << std::endl;
1606
//----------------------------------------------------------------------
1608
// Set the scale used for all subsequent level of detail calculations.
1610
RtVoid RiRelativeDetail( RtFloat relativedetail )
1612
Cache_RiRelativeDetail
1614
Validate_RiRelativeDetail
1616
if ( relativedetail < 0.0f )
1618
std::cerr << error << "RiRelativeDetail < 0.0" << std::endl;
1622
QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "RelativeDetail" ) [ 0 ] = relativedetail;
1628
//----------------------------------------------------------------------
1630
// Specify system specific option.
1632
RtVoid RiOption( RtToken name, ... )
1635
va_start( pArgs, name );
1637
std::vector<RtToken> aTokens;
1638
std::vector<RtPointer> aValues;
1639
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
1641
RiOptionV( name, count, &aTokens[0], &aValues[0] );
1645
//----------------------------------------------------------------------
1647
// List based version of above.
1649
RtVoid RiOptionV( RtToken name, PARAMETERLIST )
1655
// Find the parameter on the current options.
1656
CqNamedParameterList * pOpt = QGetRenderContext() ->optCurrent().pOptionWrite( name ).get();
1659
for ( i = 0; i < count; ++i )
1661
RtToken token = tokens[ i ];
1662
RtPointer value = values[ i ];
1664
// Search for the parameter in the declarations.
1665
// Note Options can only be uniform.
1666
SqParameterDeclaration Decl;
1669
Decl = QGetRenderContext()->FindParameterDecl( token );
1671
catch( XqException e )
1673
std::cerr << error << e.strReason().c_str() << std::endl;
1676
TqInt Type = Decl.m_Type;
1677
TqInt Class = Decl.m_Class;
1678
TqBool bArray = Decl.m_Count > 1;
1679
CqParameter* pParam = pOpt->pParameter( Decl.m_strName.c_str() );
1682
if ( Decl.m_strName != "" && ( Decl.m_Class ) == class_uniform )
1684
pParam = Decl.m_pCreate( Decl.m_strName.c_str(), Decl.m_Count );
1685
pOpt->AddParameter( pParam );
1689
if ( Decl.m_strName == "" )
1690
std::cerr << warning << "Unrecognised declaration : " << token << std::endl;
1692
std::cerr << warning << "Options can only be uniform [" << token << "]" << std::endl;
1698
Type = pParam->Type();
1699
Class = pParam->Class();
1700
bArray = pParam->Count() > 0;
1707
RtFloat * pf = reinterpret_cast<RtFloat*>( value );
1711
for ( j = 0; j < pParam->Count(); ++j )
1712
static_cast<CqParameterTypedUniformArray<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ j ] = pf[ j ];
1715
static_cast<CqParameterTypedUniform<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pf[ 0 ];
1721
RtInt* pi = reinterpret_cast<RtInt*>( value );
1725
for ( j = 0; j < pParam->Count(); ++j )
1726
static_cast<CqParameterTypedUniformArray<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ j ] = pi[ j ];
1729
static_cast<CqParameterTypedUniform<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pi[ 0 ];
1735
char** ps = reinterpret_cast<char**>( value );
1739
for ( j = 0; j < pParam->Count(); ++j )
1742
if ( strcmp( name, "searchpath" ) == 0 )
1744
// Get the old value for use in escape replacement
1745
CqString str_old = static_cast<CqParameterTypedUniform<CqString, type_string, CqString>*>( pParam ) ->pValue() [ 0 ];
1746
// Build the string, checking for & character and replace with old string.
1747
unsigned int strt = 0;
1748
unsigned int len = 0;
1751
if ( ( len = strcspn( &ps[ j ][ strt ], "&" ) ) < strlen( &ps[ j ][ strt ] ) )
1753
str += CqString( ps[ j ] ).substr( strt, len );
1759
str += CqString( ps[ j ] ).substr( strt );
1765
str = CqString( ps[ j ] );
1767
static_cast<CqParameterTypedUniformArray<CqString, type_string, CqString>*>( pParam ) ->pValue() [ j ] = str;
1773
if ( strcmp( name, "searchpath" ) == 0 )
1775
// Get the old value for use in escape replacement
1776
CqString str_old = static_cast<CqParameterTypedUniform<CqString, type_string, CqString>*>( pParam ) ->pValue() [ 0 ];
1777
// Build the string, checking for & character and replace with old string.
1778
unsigned int strt = 0;
1779
unsigned int len = 0;
1782
if ( ( len = strcspn( &ps[ 0 ][ strt ], "&" ) ) < strlen( &ps[ 0 ][ strt ] ) )
1784
str += CqString( ps[ 0 ] ).substr( strt, len );
1790
str += CqString( ps[ 0 ] ).substr( strt );
1796
str = CqString( ps[ 0 ] );
1798
static_cast<CqParameterTyped<CqString, CqString>*>( pParam ) ->pValue() [ 0 ] = str;
1802
// TODO: Rest of parameter types.
1809
//----------------------------------------------------------------------
1811
// Begin a ne attribute definition, pushes the current attributes.
1813
RtVoid RiAttributeBegin()
1815
Cache_RiAttributeBegin
1817
Validate_RiAttributeBegin
1819
QGetRenderContext() ->BeginAttributeModeBlock();
1825
//----------------------------------------------------------------------
1827
// End the current attribute defintion, pops the previous attributes.
1829
RtVoid RiAttributeEnd()
1831
Cache_RiAttributeEnd
1833
Validate_RiAttributeEnd
1835
QGetRenderContext() ->EndAttributeModeBlock();
1841
//----------------------------------------------------------------------
1843
// Set the current color for use by the geometric primitives.
1845
RtVoid RiColor( RtColor Cq )
1851
QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Color" ) [ 0 ] = CqColor( Cq );
1852
QGetRenderContext() ->AdvanceTime();
1857
//----------------------------------------------------------------------
1859
// Set the current opacity, for use by the geometric primitives.
1861
RtVoid RiOpacity( RtColor Os )
1867
QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Opacity" ) [ 0 ] = CqColor( Os );
1868
QGetRenderContext() ->AdvanceTime();
1873
//----------------------------------------------------------------------
1874
// RiTextureCoordinates
1875
// Set the current texture coordinates used by the parametric geometric primitives.
1877
RtVoid RiTextureCoordinates( RtFloat s1, RtFloat t1,
1878
RtFloat s2, RtFloat t2,
1879
RtFloat s3, RtFloat t3,
1880
RtFloat s4, RtFloat t4 )
1882
Cache_RiTextureCoordinates
1884
Validate_RiTextureCoordinates
1886
TqFloat * pTC = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "TextureCoordinates" );
1888
assert( NULL != pTC );
1898
QGetRenderContext() ->AdvanceTime();
1904
//----------------------------------------------------------------------
1906
// Create a new light source at the current transformation.
1908
RtLightHandle RiLightSource( RtToken name, ... )
1911
va_start( pArgs, name );
1913
std::vector<RtToken> aTokens;
1914
std::vector<RtPointer> aValues;
1915
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
1917
return ( RiLightSourceV( name, count, &aTokens[0], &aValues[0] ) );
1921
//----------------------------------------------------------------------
1923
// List based version of above.
1925
RtLightHandle RiLightSourceV( RtToken name, PARAMETERLIST )
1929
Validate_RiLightSource
1931
// Find the lightsource shader.
1932
IqShader * pShader = static_cast<CqShader*>( QGetRenderContext() ->CreateShader( name, Type_Lightsource ) );
1934
// TODO: Report error.
1935
if ( pShader == 0 ) return ( 0 );
1937
pShader->matCurrent() = QGetRenderContext() ->ptransCurrent()->matObjectToWorld(QGetRenderContext()->Time());
1938
CqLightsource* pNew = new CqLightsource( pShader, RI_TRUE );
1940
// Execute the intiialisation code here, as we now have our shader context complete.
1941
pShader->PrepareDefArgs();
1946
for ( i = 0; i < count; ++i )
1948
RtToken token = tokens[ i ];
1949
RtPointer value = values[ i ];
1951
SetShaderArgument( pShader, token, static_cast<TqPchar>( value ) );
1953
QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( pNew );
1955
// Add it as a Context light as well in case we are in a context that manages it's own lights.
1956
QGetRenderContext() ->pconCurrent() ->AddContextLightSource( pNew );
1957
return ( reinterpret_cast<RtLightHandle>( pNew ) );
1963
//----------------------------------------------------------------------
1964
// RiAreaLightSource
1965
// Create a new area light source at the current transformation, all
1966
// geometric primitives until the next RiAttributeEnd, become part of this
1967
// area light source.
1969
RtLightHandle RiAreaLightSource( RtToken name, ... )
1972
va_start( pArgs, name );
1974
std::vector<RtToken> aTokens;
1975
std::vector<RtPointer> aValues;
1976
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
1978
return ( RiAreaLightSourceV( name, count, &aTokens[0], &aValues[0] ) );
1982
//----------------------------------------------------------------------
1983
// RiAreaLightSourceV
1984
// List based version of above.
1986
RtLightHandle RiAreaLightSourceV( RtToken name, PARAMETERLIST )
1988
Cache_RiAreaLightSource
1990
Validate_RiAreaLightSource
1992
std::cerr << warning << "RiAreaLightSource not supported, will produce a point light" << std::endl;
1994
return ( RiLightSourceV( name, count, tokens, values ) );
1998
//----------------------------------------------------------------------
2000
// Set the current status of the specified light source.
2002
RtVoid RiIlluminate( RtLightHandle light, RtBoolean onoff )
2006
Validate_RiIlluminate
2008
// Check if we are turning the light on or off.
2009
if ( light == NULL ) return ;
2011
QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( reinterpret_cast<CqLightsource*>( light ) );
2013
QGetRenderContext() ->pattrWriteCurrent() ->RemoveLightsource( reinterpret_cast<CqLightsource*>( light ) );
2018
//----------------------------------------------------------------------
2020
// Set the current surface shader, used by geometric primitives.
2022
RtVoid RiSurface( RtToken name, ... )
2025
va_start( pArgs, name );
2027
std::vector<RtToken> aTokens;
2028
std::vector<RtPointer> aValues;
2029
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
2031
RiSurfaceV( name, count, &aTokens[0], &aValues[0] );
2035
//----------------------------------------------------------------------
2037
// List based version of above.
2039
RtVoid RiSurfaceV( RtToken name, PARAMETERLIST )
2046
IqShader * pshadSurface = QGetRenderContext() ->CreateShader( name, Type_Surface );
2048
if ( pshadSurface != 0 )
2050
TqFloat time = QGetRenderContext()->Time();
2051
pshadSurface->matCurrent() = QGetRenderContext() ->matCurrent(time);
2052
// Execute the intiialisation code here, as we now have our shader context complete.
2053
pshadSurface->PrepareDefArgs();
2055
for ( i = 0; i < count; ++i )
2057
RtToken token = tokens[ i ];
2058
RtPointer value = values[ i ];
2060
SetShaderArgument( pshadSurface, token, static_cast<TqPchar>( value ) );
2062
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pshadSurface, QGetRenderContext() ->Time() );
2064
QGetRenderContext() ->AdvanceTime();
2069
//----------------------------------------------------------------------
2071
// Set the current atrmospheric shader.
2073
RtVoid RiAtmosphere( RtToken name, ... )
2076
va_start( pArgs, name );
2078
std::vector<RtToken> aTokens;
2079
std::vector<RtPointer> aValues;
2080
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
2082
RiAtmosphereV( name, count, &aTokens[0], &aValues[0] );
2086
//----------------------------------------------------------------------
2088
// List based version of above.
2090
RtVoid RiAtmosphereV( RtToken name, PARAMETERLIST )
2094
Validate_RiAtmosphere
2097
IqShader * pshadAtmosphere = QGetRenderContext() ->CreateShader( name, Type_Volume );
2099
if ( pshadAtmosphere != 0 )
2101
pshadAtmosphere->matCurrent() = QGetRenderContext() ->matCurrent(QGetRenderContext()->Time());
2102
// Execute the intiialisation code here, as we now have our shader context complete.
2103
pshadAtmosphere->PrepareDefArgs();
2105
for ( i = 0; i < count; ++i )
2107
RtToken token = tokens[ i ];
2108
RtPointer value = values[ i ];
2110
SetShaderArgument( pshadAtmosphere, token, static_cast<TqPchar>( value ) );
2114
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadAtmosphere( pshadAtmosphere, QGetRenderContext() ->Time() );
2115
QGetRenderContext() ->AdvanceTime();
2120
//----------------------------------------------------------------------
2122
// Set the current interior volumetric shader.
2124
RtVoid RiInterior( RtToken name, ... )
2126
std::cerr << warning << "RiInterior not supported" << std::endl;
2131
//----------------------------------------------------------------------
2133
// List based version of above.
2135
RtVoid RiInteriorV( RtToken name, PARAMETERLIST )
2141
std::cerr << warning << "RiInterior not supported" << std::endl;
2146
//----------------------------------------------------------------------
2148
// Set the current exterior volumetric shader.
2150
RtVoid RiExterior( RtToken name, ... )
2152
std::cerr << warning << "RiExterior not supported" << std::endl;
2157
//----------------------------------------------------------------------
2159
// List based version of above.
2161
RtVoid RiExteriorV( RtToken name, PARAMETERLIST )
2167
std::cerr << warning << "ExInterior not supported" << std::endl;
2172
//----------------------------------------------------------------------
2174
// Specify the size of the shading area in pixels.
2176
RtVoid RiShadingRate( RtFloat size )
2180
Validate_RiShadingRate
2182
CqLogRangeCheckCallback rc;
2187
if( !CheckMinMax( size, 0.0f, RI_INFINITY, &rc ) )
2194
std::cerr << warning << "Invalid ShadingRate, ShadingRate set to 1" << std::endl;
2198
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRate" ) [ 0 ] = size;
2199
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRateSqrt" ) [ 0 ] = sqrt( size );
2200
QGetRenderContext() ->AdvanceTime();
2206
//----------------------------------------------------------------------
2207
// RiShadingInterpolation
2208
// Specify the method of shading interpolation.
2210
RtVoid RiShadingInterpolation( RtToken type )
2212
Cache_RiShadingInterpolation
2214
Validate_RiShadingInterpolation
2216
if ( strcmp( type, RI_CONSTANT ) == 0 )
2217
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingConstant;
2219
if ( strcmp( type, RI_SMOOTH ) == 0 )
2220
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingSmooth;
2222
std::cerr << error << "RiShadingInterpolation unrecognised value \"" << type << "\"" << std::endl;
2224
QGetRenderContext() ->AdvanceTime();
2229
//----------------------------------------------------------------------
2231
// Set the matte state of subsequent geometric primitives.
2233
RtVoid RiMatte( RtBoolean onoff )
2239
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Matte" ) [ 0 ] = onoff != 0;
2240
QGetRenderContext() ->AdvanceTime();
2245
//----------------------------------------------------------------------
2247
// Set the bounding cube of the current primitives.
2249
RtVoid RiBound( RtBound bound )
2255
// TODO: Need to add a "Bound" attribute here, and fill it in.
2256
QGetRenderContext() ->AdvanceTime();
2262
//----------------------------------------------------------------------
2264
// Set the current bounding cube for use by level of detail calculation.
2266
RtVoid RiDetail( RtBound bound )
2272
CqBound Bound( bound );
2274
Bound.Transform( QGetRenderContext() ->matSpaceToSpace( "object", "raster", CqMatrix(), QGetRenderContext() ->matCurrent( QGetRenderContext() ->Time() ), QGetRenderContext()->Time() ) );
2276
TqFloat ruler = fabs( MAX( Bound.vecMax().x() - Bound.vecMin().x(), Bound.vecMax().y() - Bound.vecMin().y() ) );
2278
ruler *= QGetRenderContext() ->optCurrent().GetFloatOption( "System", "RelativeDetail" ) [ 0 ];
2280
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailRulerSize" ) [ 0 ] = ruler;
2281
QGetRenderContext() ->AdvanceTime();
2286
//----------------------------------------------------------------------
2288
// Set the visible range of any subsequent geometric primitives.
2290
RtVoid RiDetailRange( RtFloat offlow, RtFloat onlow, RtFloat onhigh, RtFloat offhigh )
2294
Validate_RiDetailRange
2296
if ( offlow > onlow || onhigh > offhigh )
2298
std::cerr << error << "RiDetailRange invalid range" << std::endl;
2302
TqFloat ruler = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailRulerSize" ) [ 0 ];
2304
TqFloat minImportance;
2305
if ( onlow == offlow )
2307
minImportance = ruler < onlow ? 1.0f : 0.0f;
2311
minImportance = CLAMP( ( onlow - ruler ) / ( onlow - offlow ), 0, 1 );
2314
TqFloat maxImportance;
2315
if ( onhigh == offhigh )
2317
maxImportance = ruler < onhigh ? 1.0f : 0.0f;
2321
maxImportance = CLAMP( ( offhigh - ruler ) / ( offhigh - onhigh ), 0, 1 );
2324
if ( minImportance >= maxImportance )
2326
// Geometry is culled. Use the special value -1 to represent this.
2327
minImportance = maxImportance = -1.0f;
2330
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailBounds" ) [ 0 ] = minImportance;
2331
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailBounds" ) [ 1 ] = maxImportance;
2332
QGetRenderContext() ->AdvanceTime();
2337
//----------------------------------------------------------------------
2338
// RiGeometricApproximation
2339
// Specify any parameters used by approximation functions during rendering.
2341
RtVoid RiGeometricApproximation( RtToken type, RtFloat value )
2343
Cache_RiGeometricApproximation
2345
Validate_RiGeometricApproximation
2347
std::cerr << warning << "RiGeometricApproximation not supported" << std::endl;
2352
//----------------------------------------------------------------------
2354
// Set the handedness of any subsequent geometric primitives.
2356
RtVoid RiOrientation( RtToken orientation )
2360
Validate_RiOrientation
2362
if ( orientation != 0 )
2364
if ( strstr( orientation, RI_RH ) != 0 )
2365
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = ( QGetRenderContext() ->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) ) ? 0 : 1;
2366
if ( strstr( orientation, RI_LH ) != 0 )
2367
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = ( QGetRenderContext() ->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) ) ? 1 : 0;
2368
if ( strstr( orientation, RI_INSIDE ) != 0 )
2369
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
2370
if ( strstr( orientation, RI_OUTSIDE ) != 0 )
2371
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
2373
QGetRenderContext() ->AdvanceTime();
2378
//----------------------------------------------------------------------
2379
// RiReverseOrientation
2380
// Reverse the handedness of any subsequent geometric primitives.
2382
RtVoid RiReverseOrientation()
2384
Cache_RiReverseOrientation
2386
Validate_RiReverseOrientation
2388
QGetRenderContext() ->pattrWriteCurrent() ->FlipeOrientation( QGetRenderContext() ->Time() );
2389
QGetRenderContext() ->AdvanceTime();
2394
//----------------------------------------------------------------------
2396
// Set the number of visibles sides for any subsequent geometric primitives.
2398
RtVoid RiSides( RtInt nsides )
2404
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Sides" ) [ 0 ] = nsides;
2405
QGetRenderContext() ->AdvanceTime();
2411
//----------------------------------------------------------------------
2413
// Set the current transformation to the identity matrix.
2421
QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix() );
2423
QGetRenderContext() ->AdvanceTime();
2428
//----------------------------------------------------------------------
2429
// Set the current transformation to the specified matrix.
2431
RtVoid RiTransform( RtMatrix transform )
2435
Validate_RiTransform
2437
CqMatrix matTrans( transform );
2438
// if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2439
// QGetRenderContext() ->ptransWriteCurrent() ->FlipHandedness( QGetRenderContext() ->Time() );
2441
QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix( transform ) );
2442
QGetRenderContext() ->AdvanceTime();
2448
//----------------------------------------------------------------------
2449
// RiConcatTransform
2450
// Concatenate the specified matrix into the current transformation matrix.
2452
RtVoid RiConcatTransform( RtMatrix transform )
2454
Cache_RiConcatTransform
2456
Validate_RiConcatTransform
2458
// Check if this transformation results in a change in orientation.
2459
CqMatrix matTrans( transform );
2460
// if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2461
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2463
QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), CqMatrix( transform ) );
2464
QGetRenderContext() ->AdvanceTime();
2469
//----------------------------------------------------------------------
2471
// Concatenate a perspective transformation into the current transformation.
2473
RtVoid RiPerspective( RtFloat fov )
2477
Validate_RiPerspective
2481
std::cerr << error << "RiPerspective invalid FOV" << std::endl;
2485
fov = tan( RAD( fov / 2 ) );
2487
// This matches PRMan 3.9 in testing, but not BMRT 2.6's rgl and rendrib.
2488
CqMatrix matP( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, fov, fov, 0, 0, -fov, 0 );
2490
// Check if this transformation results in a change in orientation.
2491
// if ( matP.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2492
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2494
QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matP );
2495
QGetRenderContext() ->AdvanceTime();
2501
//----------------------------------------------------------------------
2503
// Concatenate a translation into the current transformation.
2505
RtVoid RiTranslate( RtFloat dx, RtFloat dy, RtFloat dz )
2509
Validate_RiTranslate
2511
CqMatrix matTrans( CqVector3D( dx, dy, dz ) );
2512
// Check if this transformation results in a change in orientation.
2513
// if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2514
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2516
QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matTrans );
2517
QGetRenderContext() ->AdvanceTime();
2523
//----------------------------------------------------------------------
2525
// Concatenate a rotation into the current transformation.
2527
RtVoid RiRotate( RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz )
2533
CqMatrix matRot( RAD( angle ), CqVector4D( dx, dy, dz ) );
2534
// Check if this transformation results in a change in orientation.
2535
// if ( matRot.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2536
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2538
QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matRot );
2539
QGetRenderContext() ->AdvanceTime();
2544
//----------------------------------------------------------------------
2546
// Concatenate a scale into the current transformation.
2548
RtVoid RiScale( RtFloat sx, RtFloat sy, RtFloat sz )
2554
CqMatrix matScale( sx, sy, sz );
2555
// Check if this transformation results in a change in orientation.
2556
// if ( matScale.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2557
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2559
QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matScale );
2560
QGetRenderContext() ->AdvanceTime();
2565
//----------------------------------------------------------------------
2567
// Concatenate a skew into the current transformation.
2569
RtVoid RiSkew( RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1,
2570
RtFloat dx2, RtFloat dy2, RtFloat dz2 )
2576
CqMatrix matSkew( RAD( angle ), dx1, dy1, dz1, dx2, dy2, dz2 );
2578
// This transformation can not change orientation.
2580
QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matSkew );
2581
QGetRenderContext() ->AdvanceTime();
2586
//----------------------------------------------------------------------
2588
// Specify a deformation shader to be included into the current transformation.
2590
RtVoid RiDeformation( RtToken name, ... )
2592
std::cerr << warning << "RiDeformation not supported" << std::endl;
2597
//----------------------------------------------------------------------
2599
// List based version of above.
2601
RtVoid RiDeformationV( RtToken name, PARAMETERLIST )
2605
Validate_RiDeformation
2607
std::cerr << warning << "RiDeformation not supported" << std::endl;
2612
//----------------------------------------------------------------------
2614
// Specify the current displacement shade used by geometric primitives.
2616
RtVoid RiDisplacement( RtToken name, ... )
2619
va_start( pArgs, name );
2621
std::vector<RtToken> aTokens;
2622
std::vector<RtPointer> aValues;
2623
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
2625
RiDisplacementV( name, count, &aTokens[0], &aValues[0] );
2629
//----------------------------------------------------------------------
2631
// List based version of above.
2633
RtVoid RiDisplacementV( RtToken name, PARAMETERLIST )
2635
Cache_RiDisplacement
2637
Validate_RiDisplacement
2640
IqShader * pshadDisplacement = QGetRenderContext() ->CreateShader( name, Type_Displacement );
2642
if ( pshadDisplacement != 0 )
2644
pshadDisplacement->matCurrent() = QGetRenderContext() ->matCurrent(QGetRenderContext()->Time());
2645
// Execute the intiialisation code here, as we now have our shader context complete.
2646
pshadDisplacement->PrepareDefArgs();
2648
for ( i = 0; i < count; ++i )
2650
RtToken token = tokens[ i ];
2651
RtPointer value = values[ i ];
2653
SetShaderArgument( pshadDisplacement, token, static_cast<TqPchar>( value ) );
2657
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadDisplacement( pshadDisplacement, QGetRenderContext() ->Time() );
2658
QGetRenderContext() ->AdvanceTime();
2663
//----------------------------------------------------------------------
2664
// RiCoordinateSystem
2665
// Save the current coordinate system as the specified name.
2667
RtVoid RiCoordinateSystem( RtToken space )
2669
Cache_RiCoordinateSystem
2671
Validate_RiCoordinateSystem
2673
// Insert the named coordinate system into the list help on the renderer.
2674
QGetRenderContext() ->SetCoordSystem( space, QGetRenderContext() ->matCurrent( QGetRenderContext() ->Time() ) );
2675
QGetRenderContext() ->AdvanceTime();
2681
//----------------------------------------------------------------------
2682
// ---Additional to spec. v3.1---
2683
// RiCoordSysTransform
2684
// Replace the current transform with the named space.
2686
RtVoid RiCoordSysTransform( RtToken space )
2688
Cache_RiCoordSysTransform
2690
Validate_RiCoordSysTransform
2692
// Insert the named coordinate system into the list help on the renderer.
2693
QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), QGetRenderContext() ->matSpaceToSpace( space, "world", CqMatrix(), CqMatrix(), QGetRenderContext()->Time() ) );
2694
QGetRenderContext() ->AdvanceTime();
2700
//----------------------------------------------------------------------
2701
// RiTransformPoints
2702
// Transform a list of points from one coordinate system to another.
2704
RtPoint* RiTransformPoints( RtToken fromspace, RtToken tospace, RtInt npoints, RtPoint points[] )
2706
Cache_RiTransformPoints
2708
Validate_RiTransformPoints
2710
std::cerr << warning << "RiTransformPoints not supported" << std::endl;
2715
//----------------------------------------------------------------------
2717
// Push the current transformation state.
2719
RtVoid RiTransformBegin()
2721
Cache_RiTransformBegin
2723
Validate_RiTransformBegin
2725
QGetRenderContext() ->BeginTransformModeBlock();
2731
//----------------------------------------------------------------------
2733
// Pop the previous transformation state.
2735
RtVoid RiTransformEnd()
2737
Cache_RiTransformEnd
2739
Validate_RiTransformEnd
2741
QGetRenderContext() ->EndTransformModeBlock();
2747
//----------------------------------------------------------------------
2749
// Set a system specific attribute.
2751
RtVoid RiAttribute( RtToken name, ... )
2754
va_start( pArgs, name );
2756
std::vector<RtToken> aTokens;
2757
std::vector<RtPointer> aValues;
2758
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
2760
RiAttributeV( name, count, &aTokens[0], &aValues[0] );
2764
//----------------------------------------------------------------------
2766
// List based version of above.
2768
RtVoid RiAttributeV( RtToken name, PARAMETERLIST )
2772
Validate_RiAttribute
2774
// Find the parameter on the current options.
2775
CqNamedParameterList * pAttr = QGetRenderContext() ->pattrWriteCurrent() ->pAttributeWrite( name ).get();
2778
for ( i = 0; i < count; ++i )
2780
RtToken token = tokens[ i ];
2781
RtPointer value = values[ i ];
2786
CqParameter* pParam = pAttr->pParameter( token );
2789
// Search for the parameter in the declarations.
2790
// Note attributes can only be uniform.
2791
SqParameterDeclaration Decl;
2794
Decl = QGetRenderContext()->FindParameterDecl( token );
2796
catch( XqException e )
2798
std::cerr << error << e.strReason().c_str() << std::endl;
2801
if ( Decl.m_strName != "" && Decl.m_Class == class_uniform )
2803
pParam = Decl.m_pCreate( Decl.m_strName.c_str(), Decl.m_Count );
2805
Class = Decl.m_Class;
2806
bArray = Decl.m_Count > 0;
2807
pAttr->AddParameter( pParam );
2811
if ( Decl.m_strName == "" )
2812
std::cerr << warning << "Unrecognised declaration \"" << token << "\"" << std::endl;
2814
std::cerr << warning << "Attributes can only be uniform" << std::endl;
2820
Type = pParam->Type();
2821
Class = pParam->Class();
2822
bArray = pParam->Count() > 0;
2829
RtFloat * pf = reinterpret_cast<RtFloat*>( value );
2833
for ( j = 0; j < pParam->Count(); ++j )
2834
static_cast<CqParameterTypedUniformArray<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ j ] = pf[ j ];
2837
static_cast<CqParameterTypedUniform<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pf[ 0 ];
2843
RtInt* pi = reinterpret_cast<RtInt*>( value );
2847
for ( j = 0; j < pParam->Count(); ++j )
2848
static_cast<CqParameterTypedUniformArray<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ j ] = pi[ j ];
2851
static_cast<CqParameterTypedUniform<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pi[ 0 ];
2857
char** ps = reinterpret_cast<char**>( value );
2861
for ( j = 0; j < pParam->Count(); ++j )
2863
CqString str( ps[ j ] );
2864
static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ j ] = str;
2869
CqString str( ps[ 0 ] );
2870
static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ 0 ] = str;
2873
// TODO: Rest of parameter types.
2880
//----------------------------------------------------------------------
2882
// Specify a coplanar, convex polygon.
2884
RtVoid RiPolygon( RtInt nvertices, ... )
2887
va_start( pArgs, nvertices );
2889
std::vector<RtToken> aTokens;
2890
std::vector<RtPointer> aValues;
2891
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
2893
RiPolygonV( nvertices, count, &aTokens[0], &aValues[0] );
2897
//----------------------------------------------------------------------
2899
// List based version of above.
2901
RtVoid RiPolygonV( RtInt nvertices, PARAMETERLIST )
2907
// Create a new polygon surface primitive.
2908
boost::shared_ptr<CqSurfacePolygon> pSurface( new CqSurfacePolygon( nvertices ) );
2910
// Process any specified primitive variables.
2911
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
2913
if ( !pSurface->CheckDegenerate() )
2915
TqFloat time = QGetRenderContext()->Time();
2916
// Transform the points into camera space for processing,
2917
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
2918
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
2919
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
2920
CreateGPrim( pSurface );
2924
std::cerr << error << "Found degenerate polygon" << std::endl;
2932
//----------------------------------------------------------------------
2934
// Specify a nonconvex coplanar polygon.
2936
RtVoid RiGeneralPolygon( RtInt nloops, RtInt nverts[], ... )
2939
va_start( pArgs, nverts );
2941
std::vector<RtToken> aTokens;
2942
std::vector<RtPointer> aValues;
2943
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
2945
RiGeneralPolygonV( nloops, nverts, count, &aTokens[0], &aValues[0] );
2949
//----------------------------------------------------------------------
2950
// RiGeneralPolygonV
2951
// List based version of above.
2953
RtVoid RiGeneralPolygonV( RtInt nloops, RtInt nverts[], PARAMETERLIST )
2955
Cache_RiGeneralPolygon
2957
Validate_RiGeneralPolygon
2961
// Calcualte how many points there are.
2963
for ( iloop = 0; iloop < nloops; ++iloop )
2965
cVerts += nverts[ iloop ];
2966
// Check for degenerate loops.
2967
if( nverts[ iloop ] < 3 )
2969
CqString objname( "unnamed" );
2970
const CqString* pattrName = QGetRenderContext()->pattrCurrent()->GetStringAttribute( "identifier", "name" );
2971
if ( pattrName != 0 ) objname = pattrName[ 0 ];
2972
std::cerr << warning << "Degenerate loop in GeneralPolygon object \"" << objname.c_str() << "\"" << std::endl;
2976
// Create a storage class for all the points.
2977
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, 1, cVerts ) );
2978
// Process any specified primitive variables
2979
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
2981
pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
2983
// Work out which plane to project to.
2987
CqVector3D vecTemp = pPointsClass->P()->pValue( 0 )[0];
2988
MinX = MaxX = vecTemp.x();
2989
MinY = MaxY = vecTemp.y();
2990
MinZ = MaxZ = vecTemp.z();
2992
// We need to take into account Orientation here.
2993
TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
2996
for ( iVert = 1; iVert < pPointsClass->P() ->Size(); ++iVert )
2998
vecTemp = pPointsClass->P()->pValue( iVert )[0];
2999
MinX = ( MinX < vecTemp.x() ) ? MinX : vecTemp.x();
3000
MinY = ( MinY < vecTemp.y() ) ? MinY : vecTemp.y();
3001
MinZ = ( MinZ < vecTemp.z() ) ? MinZ : vecTemp.z();
3002
MaxX = ( MaxX > vecTemp.x() ) ? MaxX : vecTemp.x();
3003
MaxY = ( MaxY > vecTemp.y() ) ? MaxY : vecTemp.y();
3004
MaxZ = ( MaxZ > vecTemp.z() ) ? MaxZ : vecTemp.z();
3006
TqFloat DiffX = MaxX - MinX;
3007
TqFloat DiffY = MaxY - MinY;
3008
TqFloat DiffZ = MaxZ - MinZ;
3011
if ( DiffX < DiffY && DiffX < DiffZ )
3012
Axis = CqPolygonGeneral2D::Axis_YZ;
3013
else if ( DiffY < DiffX && DiffY < DiffZ )
3014
Axis = CqPolygonGeneral2D::Axis_XZ;
3016
Axis = CqPolygonGeneral2D::Axis_XY;
3018
// Create a general 2D polygon using the points in each loop.
3019
CqPolygonGeneral2D poly;
3021
for ( iloop = 0; iloop < nloops; ++iloop )
3023
CqPolygonGeneral2D polya;
3024
polya.SetAxis( Axis );
3025
polya.SetpVertices( pPointsClass );
3027
for ( ivert = 0; ivert < nverts[ iloop ]; ++ivert )
3029
assert( ipoint < pPointsClass->P() ->Size() );
3030
polya.aiVertices().push_back( ipoint++ );
3034
/// \note: We need to check here if the orientation of the projected poly matches the
3035
/// expected one, of not, we must swap the direction so that the triangulation routines can
3036
/// correctly determine the inside/outside nature of points. However, if doing so breaks the
3037
/// orientation as expected by the rest of the renderer, we need to flip the orientation
3038
/// attribute as well so that normals are correctly calculated.
3041
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3043
QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
3044
polya.SwapDirection();
3049
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3051
QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
3052
polya.SwapDirection();
3061
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3062
polya.SwapDirection();
3066
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3067
polya.SwapDirection();
3069
poly.Combine( polya );
3072
// Now triangulate the general polygon
3074
std::vector<TqInt> aiTriangles;
3075
poly.CalcOrientation();
3076
poly.Triangulate( aiTriangles );
3078
TqUint ctris = aiTriangles.size() / 3;
3079
// Build an array of point counts (always 3 each).
3080
std::vector<RtInt> _nverts;
3081
_nverts.resize( ctris, 3 );
3083
RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
3088
RtVoid RiBlobby( RtInt nleaf, RtInt ncodes, RtInt codes[], RtInt nfloats, RtFloat floats[],
3089
RtInt nstrings, RtString strings[], ... )
3093
va_start( pArgs, strings );
3095
std::vector<RtToken> aTokens;
3096
std::vector<RtPointer> aValues;
3097
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3099
RiBlobbyV( nleaf, ncodes, codes, nfloats, floats, nstrings, strings, count, &aTokens[0], &aValues[0] );
3104
//----------------------------------------------------------------------
3105
/** List based version of above.
3109
RtVoid RiBlobbyV( RtInt nleaf, RtInt ncode, RtInt code[], RtInt nflt, RtFloat flt[],
3110
RtInt nstr, RtString str[], PARAMETERLIST )
3116
std::cerr << warning << "RiBlobby not supported" << std::endl;
3122
//----------------------------------------------------------------------
3123
/** Specify a small Points primitives
3127
RtVoid RiPoints( RtInt nvertices, ... )
3130
va_start( pArgs, nvertices );
3132
std::vector<RtToken> aTokens;
3133
std::vector<RtPointer> aValues;
3134
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3136
RiPointsV( nvertices, count, &aTokens[0], &aValues[0] );
3141
//----------------------------------------------------------------------
3142
/** List based version of above.
3146
RtVoid RiPointsV( RtInt npoints, PARAMETERLIST )
3152
// Create a storage class for all the points.
3153
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( npoints, 1, npoints ) );
3155
// Create a new points storage class
3156
boost::shared_ptr<CqPoints> pSurface;
3158
// read in the parameter list
3159
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3161
// Transform the points into camera space for processing,
3162
// This needs to be done before initialising the KDTree as the tree must be formulated in 'current' (camera) space.
3163
pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
3164
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
3165
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ) );
3167
pSurface = boost::shared_ptr<CqPoints>( new CqPoints( npoints, pPointsClass ) );
3168
// Initialise the KDTree for the points to contain all.
3169
pSurface->InitialiseKDTree();
3170
pSurface->InitialiseMaxWidth();
3172
if ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "LevelOfDetailBounds" ) [ 1 ] < 0.0f )
3174
// Cull this geometry for LOD reasons
3178
/// \note: Have to duplicate the work of CreateGPrim here as we need a special type of CqDeformingSurface.
3179
/// Not happy about this, need to look at it.
3180
// If in a motion block, confirm that the current deformation surface can accept the passed one as a keyframe.
3181
if( QGetRenderContext() ->pconCurrent() ->fMotionBlock() )
3183
CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
3185
boost::shared_ptr<CqDeformingSurface> pMS = pMMB->GetDeformingSurface();
3186
// If this is the first frame, then generate the appropriate CqDeformingSurface and fill in the first frame.
3187
// Then cache the pointer on the motion block.
3190
boost::shared_ptr<CqDeformingPointsSurface> pNewMS( new CqDeformingPointsSurface( pSurface ) );
3191
pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
3193
pMMB->SetDeformingSurface( pNewMS );
3197
pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
3199
QGetRenderContext() ->AdvanceTime();
3203
QGetRenderContext() ->pImage() ->PostSurface( pSurface );
3204
STATS_INC( GPR_created );
3211
//----------------------------------------------------------------------
3212
/** Specify a small line primitives
3214
*\param type could be "linear" "bicubic"
3215
*\param ncurves : number of vertices
3216
*\param nvertices: vertices index
3217
*\param wrap could be "periodic" "nonperiodic"
3221
RtVoid RiCurves( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, ... )
3224
va_start( pArgs, wrap );
3226
std::vector<RtToken> aTokens;
3227
std::vector<RtPointer> aValues;
3228
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3230
RiCurvesV( type, ncurves, nvertices, wrap, count, &aTokens[0], &aValues[0] );
3235
//----------------------------------------------------------------------
3236
/** List based version of above.
3240
RtVoid RiCurvesV( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, PARAMETERLIST )
3246
// find out whether the curve is periodic or non-periodic
3247
TqBool periodic = TqFalse;
3248
if ( strcmp( wrap, RI_PERIODIC ) == 0 )
3252
else if ( strcmp( wrap, RI_NONPERIODIC ) == 0 )
3258
// the wrap mode was neither "periodic" nor "nonperiodic"
3259
std::cerr << error << "RiCurves invalid wrap mode \"" << wrap << "\"" << std::endl;
3262
// handle creation of linear and cubic curve groups separately
3263
if ( strcmp( type, RI_CUBIC ) == 0 )
3265
// create a new group of cubic curves
3266
boost::shared_ptr<CqCubicCurvesGroup> pSurface( new CqCubicCurvesGroup( ncurves, nvertices, periodic ) );
3267
// read in the parameter list
3268
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3270
// set the default primitive variables
3271
pSurface->SetDefaultPrimitiveVariables();
3273
TqFloat time = QGetRenderContext()->Time();
3274
// Transform the points into camera space for processing,
3275
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3276
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3277
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3279
std::vector<boost::shared_ptr<CqBasicSurface> > aSplits;
3280
pSurface->Split( aSplits );
3281
std::vector<boost::shared_ptr<CqBasicSurface> >::iterator iSS;
3282
for ( iSS = aSplits.begin(); iSS != aSplits.end(); ++iSS )
3284
CreateGPrim( *iSS );
3288
else if ( strcmp( type, RI_LINEAR ) == 0 )
3290
// create a new group of linear curves
3291
boost::shared_ptr<CqLinearCurvesGroup> pSurface( new CqLinearCurvesGroup( ncurves, nvertices, periodic ) );
3293
// read in the parameter list
3294
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3296
// set the default primitive variables
3297
pSurface->SetDefaultPrimitiveVariables();
3298
TqFloat time = QGetRenderContext()->Time();
3299
// Transform the points into camera space for processing,
3300
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3301
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3302
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3303
CreateGPrim( pSurface );
3308
// the type of curve was neither "linear" nor "cubic"
3309
std::cerr << error << "RiCurves invalid type \"" << type << "\"" << std::endl;
3314
//----------------------------------------------------------------------
3316
// Specify a list of convex coplanar polygons and their shared vertices.
3318
RtVoid RiPointsPolygons( RtInt npolys, RtInt nverts[], RtInt verts[], ... )
3321
va_start( pArgs, verts );
3323
std::vector<RtToken> aTokens;
3324
std::vector<RtPointer> aValues;
3325
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3327
RiPointsPolygonsV( npolys, nverts, verts, count, &aTokens[0], &aValues[0] );
3331
//----------------------------------------------------------------------
3332
// RiPointsPolygonsV
3333
// List based version of above.
3337
RtVoid RiPointsPolygonsV( RtInt npolys, RtInt nverts[], RtInt verts[], PARAMETERLIST )
3339
Cache_RiPointsPolygons
3341
Validate_RiPointsPolygons
3343
// Calculate how many vertices there are.
3345
RtInt* pVerts = verts;
3347
RtInt sumnVerts = 0;
3348
for ( poly = 0; poly < npolys; ++poly )
3351
sumnVerts += nverts[ poly ];
3352
for ( v = 0; v < nverts[ poly ]; ++v )
3354
cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
3359
// Create a storage class for all the points.
3360
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, npolys, sumnVerts ) );
3361
// Process any specified primitive variables
3362
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3364
boost::shared_ptr<CqSurfacePointsPolygons> pPsPs( new CqSurfacePointsPolygons(pPointsClass, npolys, nverts, verts ) );
3365
TqFloat time = QGetRenderContext()->Time();
3366
// Transform the points into camera space for processing,
3367
pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(time), time ),
3368
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(time), time ),
3369
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(time), time ) );
3377
//----------------------------------------------------------------------
3378
// RiPointsGeneralPolygons
3379
// Specify a list of coplanar, non-convex polygons and their shared vertices.
3381
RtVoid RiPointsGeneralPolygons( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], ... )
3384
va_start( pArgs, verts );
3386
std::vector<RtToken> aTokens;
3387
std::vector<RtPointer> aValues;
3388
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3390
RiPointsGeneralPolygonsV( npolys, nloops, nverts, verts, count, &aTokens[0], &aValues[0] );
3396
//----------------------------------------------------------------------
3397
// RiPointsGeneralPolygonsV
3398
// List based version of above.
3400
RtVoid RiPointsGeneralPolygonsV( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], PARAMETERLIST )
3402
Cache_RiPointsGeneralPolygons
3404
Validate_RiPointsGeneralPolygons
3411
TqInt initial_index;
3412
TqInt sumnVerts = 0;
3414
// Calculate how many points overall.
3415
RtInt* pVerts = verts;
3416
for ( ipoly = 0; ipoly < npolys; ++ipoly )
3418
for ( iloop = 0; iloop < nloops[ ipoly ]; ++iloop, ++igloop )
3421
sumnVerts += nverts[ igloop ];
3422
// Check for degenerate loops.
3423
if( nverts[ igloop ] < 3 )
3425
CqString objname( "unnamed" );
3426
const CqString* pattrName = QGetRenderContext()->pattrCurrent()->GetStringAttribute( "identifier", "name" );
3427
if ( pattrName != 0 ) objname = pattrName[ 0 ];
3428
std::cerr << warning << "Degenerate loop in PointsGeneralPolygons object \"" << objname.c_str() << "\"" << std::endl;
3430
for ( v = 0; v < nverts[ igloop ]; ++v )
3432
cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
3438
// We need to take into account Orientation here.
3439
TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
3441
// Create a storage class for all the points.
3442
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, npolys, sumnVerts ) );
3443
// Process any specified primitive variables
3444
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3446
pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
3448
// Reset loop counter.
3451
std::vector<TqInt> aiTriangles;
3452
std::vector<TqInt> aFVList;
3453
std::vector<TqInt> aUVList;
3455
for ( ipoly = 0; ipoly < npolys; ++ipoly )
3457
initial_index = igvert;
3458
// Create a general 2D polygon using the points in each loop.
3459
CqPolygonGeneral2D poly;
3461
TqUint imaxindex, iminindex;
3464
for ( iloop = 0; iloop < nloops[ ipoly ]; ++iloop, ++igloop )
3466
iminindex = MIN( iminindex, verts[ igvert ] );
3467
imaxindex = MAX( imaxindex, verts[ igvert ] );
3471
CqVector3D vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
3472
MinX = MaxX = vecTemp.x();
3473
MinY = MaxY = vecTemp.y();
3474
MinZ = MaxZ = vecTemp.z();
3476
CqPolygonGeneral2D polya;
3477
polya.SetpVertices( pPointsClass );
3479
for ( ivert = 0; ivert < nverts[ igloop ]; ++ivert, ++igvert )
3481
ipoint = verts[ igvert ];
3482
assert( ipoint < pPointsClass->P() ->Size() );
3483
polya.aiVertices().push_back( ipoint );
3485
vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
3486
MinX = ( MinX < vecTemp.x() ) ? MinX : vecTemp.x();
3487
MinY = ( MinY < vecTemp.y() ) ? MinY : vecTemp.y();
3488
MinZ = ( MinZ < vecTemp.z() ) ? MinZ : vecTemp.z();
3489
MaxX = ( MaxX > vecTemp.x() ) ? MaxX : vecTemp.x();
3490
MaxY = ( MaxY > vecTemp.y() ) ? MaxY : vecTemp.y();
3491
MaxZ = ( MaxZ > vecTemp.z() ) ? MaxZ : vecTemp.z();
3494
// Work out which plane to project to.
3495
TqFloat DiffX = MaxX - MinX;
3496
TqFloat DiffY = MaxY - MinY;
3497
TqFloat DiffZ = MaxZ - MinZ;
3500
if ( DiffX < DiffY && DiffX < DiffZ )
3501
Axis = CqPolygonGeneral2D::Axis_YZ;
3502
else if ( DiffY < DiffX && DiffY < DiffZ )
3503
Axis = CqPolygonGeneral2D::Axis_XZ;
3505
Axis = CqPolygonGeneral2D::Axis_XY;
3506
polya.SetAxis( Axis );
3510
/// \note: We need to check here if the orientation of the projected poly matches the
3511
/// expected one, of not, we must swap the direction so that the triangulation routines can
3512
/// correctly determine the inside/outside nature of points. However, if doing so breaks the
3513
/// orientation as expected by the rest of the renderer, we need to flip the orientation
3514
/// attribute as well so that normals are correctly calculated.
3517
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3518
polya.SwapDirection();
3522
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3523
polya.SwapDirection();
3531
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3532
polya.SwapDirection();
3536
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3537
polya.SwapDirection();
3539
poly.Combine( polya );
3542
// Now triangulate the general polygon
3544
poly.CalcOrientation();
3545
TqInt iStartTri = aiTriangles.size();
3546
poly.Triangulate( aiTriangles );
3547
TqInt iEndTri = aiTriangles.size();
3548
// Store the facevarying information
3549
/// \note This code relies on the fact that vertex indices cannot be duplicated
3550
/// within the loops of a single poly. Make sure this is a reasonable assumption.
3551
for( TqInt ifv = iStartTri; ifv < iEndTri; ++ifv )
3553
TqInt ivaryingindex = aiTriangles[ ifv ];
3554
TqBool found = TqFalse;
3555
for( TqInt iv = initial_index; iv != igvert; ++iv )
3557
if( verts[ iv ] == ivaryingindex )
3559
aFVList.push_back( iv );
3566
// Store the count of triangles generated for this general poly, so that we
3567
// can duplicate up the uniform values as appropriate.
3568
/// \note This code relies on the fact that vertex indices cannot be duplicated
3569
/// within the loops of a single poly. Make sure this is a reasonable assumption.
3570
aUVList.push_back( ( iEndTri - iStartTri ) / 3 );
3573
// Build an array of point counts (always 3 each).
3574
ctris = aiTriangles.size() / 3;
3575
std::vector<RtInt> _nverts;
3576
_nverts.resize( ctris, 3 );
3578
// Rebuild any facevarying or uniform variables.
3580
TqInt fvcount = ctris * 3;
3581
assert( aFVList.size() == fvcount );
3582
std::vector<void*> aNewParams;
3583
for( iUserParam = 0; iUserParam < count; ++iUserParam )
3585
SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( tokens[ iUserParam ] );
3587
switch( Decl.m_Type )
3590
elem_size = sizeof(RtFloat);
3595
elem_size = sizeof(RtPoint);
3598
elem_size = sizeof(RtColor);
3601
elem_size = sizeof(RtMatrix);
3604
if( Decl.m_Class == class_facevarying )
3606
char* pNew = static_cast<char*>( malloc( elem_size * fvcount ) );
3607
aNewParams.push_back( pNew );
3609
for( iElem = 0; iElem < fvcount; ++iElem )
3611
const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] ) + ( aFVList[ iElem ] * elem_size );
3612
memcpy( pNew, pval, elem_size );
3615
values[ iUserParam ] = aNewParams.back();
3617
else if( Decl.m_Class == class_uniform )
3619
// Allocate enough for 1 value per triangle, then duplicate values from the original list
3621
char* pNew = static_cast<char*>( malloc( elem_size * ctris ) );
3622
aNewParams.push_back( pNew );
3624
const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] );
3625
for( iElem = 0; iElem < npolys; ++iElem )
3627
TqInt dup_count = aUVList[ iElem ];
3629
for(dup=0; dup < dup_count; dup++)
3631
memcpy( pNew, pval, elem_size );
3636
values[ iUserParam ] = aNewParams.back();
3640
RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
3642
std::vector<void*>::iterator iNewParam;
3643
for( iNewParam = aNewParams.begin(); iNewParam != aNewParams.end(); ++iNewParam )
3651
//----------------------------------------------------------------------
3653
// Specify the patch basis matrices for the u and v directions, and the knot skip values.
3655
RtVoid RiBasis( RtBasis ubasis, RtInt ustep, RtBasis vbasis, RtInt vstep )
3664
// A good parser will use the Ri*Basis pointers so a quick comparison
3666
//if ( ubasis not same as before )
3668
// // Save off the newly given basis.
3670
// // Calculate the (inverse Bezier Basis) * (given basis), but do
3671
// // a quick check for RiPowerBasis since that is an identity
3672
// // matrix requiring no math.
3673
// if ( ubasis!=RiPowerBasis )
3680
// Do the above again for vbasis.
3681
// Save off (InvBezier * VBasis) and (Transpose(InvBezier*UBasis)).
3685
for ( i = 0; i < 4; ++i )
3688
for ( j = 0; j < 4; ++j )
3690
u.SetElement( i, j, ubasis[ i ][ j ] );
3691
v.SetElement( i, j, vbasis[ i ][ j ] );
3694
u.SetfIdentity( TqFalse );
3695
v.SetfIdentity( TqFalse );
3697
QGetRenderContext() ->pattrWriteCurrent() ->GetMatrixAttributeWrite( "System", "Basis" ) [ 0 ] = u;
3698
QGetRenderContext() ->pattrWriteCurrent() ->GetMatrixAttributeWrite( "System", "Basis" ) [ 1 ] = v;
3699
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "BasisStep" ) [ 0 ] = ustep;
3700
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "BasisStep" ) [ 1 ] = vstep;
3701
QGetRenderContext() ->AdvanceTime();
3706
//----------------------------------------------------------------------
3708
// Specify a new patch primitive.
3710
RtVoid RiPatch( RtToken type, ... )
3713
va_start( pArgs, type );
3715
std::vector<RtToken> aTokens;
3716
std::vector<RtPointer> aValues;
3717
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3719
RiPatchV( type, count, &aTokens[0], &aValues[0] );
3723
//----------------------------------------------------------------------
3725
// List based version of above.
3727
RtVoid RiPatchV( RtToken type, PARAMETERLIST )
3733
if ( strcmp( type, RI_BICUBIC ) == 0 )
3735
// Create a surface patch
3736
boost::shared_ptr<CqSurfacePatchBicubic> pSurface( new CqSurfacePatchBicubic() );
3737
// Fill in primitive variables specified.
3738
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3740
// Fill in default values for all primitive variables not explicitly specified.
3741
pSurface->SetDefaultPrimitiveVariables();
3742
CqMatrix matuBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 0 ];
3743
CqMatrix matvBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 1 ];
3744
pSurface->ConvertToBezierBasis( matuBasis, matvBasis );
3746
TqFloat time = QGetRenderContext()->Time();
3747
// Transform the points into camera space for processing,
3748
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3749
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3750
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3752
CreateGPrim( pSurface );
3755
else if ( strcmp( type, RI_BILINEAR ) == 0 )
3757
// Create a surface patch
3758
boost::shared_ptr<CqSurfacePatchBilinear> pSurface( new CqSurfacePatchBilinear() );
3759
// Fill in primitive variables specified.
3760
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3762
// Fill in default values for all primitive variables not explicitly specified.
3763
pSurface->SetDefaultPrimitiveVariables();
3764
TqFloat time = QGetRenderContext()->Time();
3765
// Transform the points into camera space for processing,
3766
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3767
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3768
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3769
CreateGPrim( pSurface );
3774
std::cerr << error << "RiPatch invalid patch type \"" << type << "\"" << std::endl;
3781
//----------------------------------------------------------------------
3783
// Specify a quadrilaterla mesh of patches.
3785
RtVoid RiPatchMesh( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, ... )
3788
va_start( pArgs, vwrap );
3790
std::vector<RtToken> aTokens;
3791
std::vector<RtPointer> aValues;
3792
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3794
RiPatchMeshV( type, nu, uwrap, nv, vwrap, count, &aTokens[0], &aValues[0] );
3798
//----------------------------------------------------------------------
3800
// List based version of above.
3803
RtVoid RiPatchMeshV( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, PARAMETERLIST )
3807
Validate_RiPatchMesh
3809
if( strcmp( uwrap, RI_PERIODIC ) && strcmp( uwrap, RI_NONPERIODIC ) )
3810
std::cerr << error << "RiPatchMesh invalid u-wrap type: \"" << uwrap << "\"" << std::endl;
3812
if( strcmp( vwrap, RI_PERIODIC ) && strcmp( vwrap, RI_NONPERIODIC ) )
3813
std::cerr << error << "RiPatchMesh invalid v-wrap type: \"" << vwrap << "\"" << std::endl;
3815
if ( strcmp( type, RI_BICUBIC ) == 0 )
3817
// Create a surface patch
3818
TqBool uPeriodic = ( strcmp( uwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
3819
TqBool vPeriodic = ( strcmp( vwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
3821
boost::shared_ptr<CqSurfacePatchMeshBicubic> pSurface( new CqSurfacePatchMeshBicubic( nu, nv, uPeriodic, vPeriodic ) );
3822
// Fill in primitive variables specified.
3823
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3825
// Fill in default values for all primitive variables not explicitly specified.
3826
pSurface->SetDefaultPrimitiveVariables();
3827
std::vector<boost::shared_ptr<CqBasicSurface> > aSplits;
3828
pSurface->Split( aSplits );
3829
std::vector<boost::shared_ptr<CqBasicSurface> >::iterator iSS;
3830
for ( iSS = aSplits.begin(); iSS != aSplits.end(); ++iSS )
3832
CqMatrix matuBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 0 ];
3833
CqMatrix matvBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 1 ];
3834
static_cast<CqSurfacePatchBicubic*>( iSS->get() ) ->ConvertToBezierBasis( matuBasis, matvBasis );
3835
TqFloat time = QGetRenderContext()->Time();
3836
// Transform the points into camera space for processing,
3837
(*iSS)->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3838
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3839
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3840
CreateGPrim( *iSS );
3844
else if ( strcmp( type, RI_BILINEAR ) == 0 )
3846
// Create a surface patch
3847
TqBool uPeriodic = ( strcmp( uwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
3848
TqBool vPeriodic = ( strcmp( vwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
3850
boost::shared_ptr<CqSurfacePatchMeshBilinear> pSurface( new CqSurfacePatchMeshBilinear( nu, nv, uPeriodic, vPeriodic ) );
3851
// Fill in primitive variables specified.
3852
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3854
// Fill in default values for all primitive variables not explicitly specified.
3855
pSurface->SetDefaultPrimitiveVariables();
3856
TqFloat time = QGetRenderContext()->Time();
3857
// Transform the points into camera space for processing,
3858
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3859
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3860
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3861
CreateGPrim( pSurface );
3866
std::cerr << error << "RiPatchMesh invalid type \"" << type << "\"" << std::endl;
3873
//----------------------------------------------------------------------
3875
// Specify a new non uniform patch.
3877
RtVoid RiNuPatch( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
3878
RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, ... )
3881
va_start( pArgs, vmax );
3883
std::vector<RtToken> aTokens;
3884
std::vector<RtPointer> aValues;
3885
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
3887
RiNuPatchV( nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, count, &aTokens[0], &aValues[0] );
3891
//----------------------------------------------------------------------
3893
// List based version of above.
3895
RtVoid RiNuPatchV( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
3896
RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, PARAMETERLIST )
3902
// Create a NURBS patch
3903
boost::shared_ptr<CqSurfaceNURBS> pSurface( new CqSurfaceNURBS() );
3904
pSurface->SetfPatchMesh();
3905
pSurface->Init( uorder, vorder, nu, nv );
3907
pSurface->Setumin( umin );
3908
pSurface->Setumax( umax );
3909
pSurface->Setvmin( vmin );
3910
pSurface->Setvmax( vmax );
3912
// Copy the knot vectors.
3914
for ( i = 0; i < nu + uorder; ++i ) pSurface->auKnots() [ i ] = uknot[ i ];
3915
for ( i = 0; i < nv + vorder; ++i ) pSurface->avKnots() [ i ] = vknot[ i ];
3917
// Process any specified parameters
3918
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3920
// Set up the default primitive variables.
3921
pSurface->SetDefaultPrimitiveVariables();
3922
// Clamp the surface to ensure non-periodic.
3924
TqFloat time = QGetRenderContext()->Time();
3925
// Transform the points into camera space for processing,
3926
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3927
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
3928
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
3929
CreateGPrim( pSurface );
3935
//----------------------------------------------------------------------
3937
// Specify curves which are used to trim NURBS surfaces.
3939
RtVoid RiTrimCurve( RtInt nloops, RtInt ncurves[], RtInt order[], RtFloat knot[], RtFloat min[], RtFloat max[], RtInt n[], RtFloat u[], RtFloat v[], RtFloat w[] )
3943
Validate_RiTrimCurve
3945
// Clear the current loop array.
3946
QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().Clear();
3948
// Build an array of curves per specified loop.
3955
for ( iloop = 0; iloop < nloops; ++iloop )
3959
for ( icurve = 0; icurve < ncurves[ iloop ]; ++icurve )
3961
// Create a NURBS patch
3963
TqInt o = order[ iorder++ ];
3964
TqInt cverts = n[ in++ ];
3965
Curve.Init( o, cverts );
3967
// Copy the knot vectors.
3969
for ( i = 0; i < o + cverts; ++i ) Curve.aKnots() [ i ] = knot[ iknot++ ];
3971
// Copy the vertices from the u,v,w arrays.
3972
CqVector3D vec( 0, 0, 1 );
3973
for ( i = 0; i < cverts; ++i )
3975
vec.x( u[ ivert ] );
3976
vec.y( v[ ivert ] );
3977
vec.z( w[ ivert++ ] );
3978
Curve.CP( i ) = vec;
3980
Loop.aCurves().push_back( Curve );
3982
QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().aLoops().push_back( Loop );
3989
//----------------------------------------------------------------------
3991
// Specify a sphere primitive.
3993
RtVoid RiSphere( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
3996
va_start( pArgs, thetamax );
3998
std::vector<RtToken> aTokens;
3999
std::vector<RtPointer> aValues;
4000
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4002
RiSphereV( radius, zmin, zmax, thetamax, count, &aTokens[0], &aValues[0] );
4006
//----------------------------------------------------------------------
4008
// List based version of above.
4010
RtVoid RiSphereV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4016
CqLogRangeCheckCallback rc;
4018
rc.set( "sphere zmin" );
4019
CheckMinMax( zmin, -radius, radius, &rc );
4020
rc.set( "sphere zmax" );
4021
CheckMinMax( zmax, -radius, radius, &rc );
4024
boost::shared_ptr<CqSphere> pSurface( new CqSphere( radius, zmin, zmax, 0, thetamax ) );
4025
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4026
pSurface->SetDefaultPrimitiveVariables();
4028
TqFloat time = QGetRenderContext()->Time();
4029
// Transform the points into camera space for processing,
4030
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4031
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4032
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4033
CreateGPrim( pSurface );
4039
//----------------------------------------------------------------------
4041
// Specify a cone primitive.
4043
RtVoid RiCone( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
4046
va_start( pArgs, thetamax );
4048
std::vector<RtToken> aTokens;
4049
std::vector<RtPointer> aValues;
4050
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4052
RiConeV( height, radius, thetamax, count, &aTokens[0], &aValues[0] );
4056
//----------------------------------------------------------------------
4058
// List based version of above.
4060
RtVoid RiConeV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
4066
/// \note This should be an exception and get caught further up.
4071
boost::shared_ptr<CqCone> pSurface( new CqCone( height, radius, 0, thetamax, 0, 1.0f ) );
4072
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4073
pSurface->SetDefaultPrimitiveVariables();
4075
TqFloat time = QGetRenderContext()->Time();
4076
// Transform the points into camera space for processing,
4077
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4078
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4079
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4080
CreateGPrim( pSurface );
4086
//----------------------------------------------------------------------
4088
// Specify a culinder primitive.
4090
RtVoid RiCylinder( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4093
va_start( pArgs, thetamax );
4095
std::vector<RtToken> aTokens;
4096
std::vector<RtPointer> aValues;
4097
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4099
RiCylinderV( radius, zmin, zmax, thetamax, count, &aTokens[0], &aValues[0] );
4103
//----------------------------------------------------------------------
4105
// List based version of above.
4107
RtVoid RiCylinderV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4113
// Create a cylinder
4114
boost::shared_ptr<CqCylinder> pSurface( new CqCylinder( radius, zmin, zmax, 0, thetamax ) );
4115
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4116
pSurface->SetDefaultPrimitiveVariables();
4118
TqFloat time = QGetRenderContext()->Time();
4119
// Transform the points into camera space for processing,
4120
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4121
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4122
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4123
CreateGPrim( pSurface );
4129
//----------------------------------------------------------------------
4131
// Specify a hyperboloid primitive.
4133
RtVoid RiHyperboloid( RtPoint point1, RtPoint point2, RtFloat thetamax, ... )
4136
va_start( pArgs, thetamax );
4138
std::vector<RtToken> aTokens;
4139
std::vector<RtPointer> aValues;
4140
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4142
RiHyperboloidV( point1, point2, thetamax, count, &aTokens[0], &aValues[0] );
4146
//----------------------------------------------------------------------
4148
// List based version of above.
4150
RtVoid RiHyperboloidV( RtPoint point1, RtPoint point2, RtFloat thetamax, PARAMETERLIST )
4154
Validate_RiHyperboloid
4156
// Create a hyperboloid
4157
CqVector3D v0( point1[ 0 ], point1[ 1 ], point1[ 2 ] );
4158
CqVector3D v1( point2[ 0 ], point2[ 1 ], point2[ 2 ] );
4159
boost::shared_ptr<CqHyperboloid> pSurface( new CqHyperboloid( v0, v1, 0, thetamax ) );
4160
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4161
pSurface->SetDefaultPrimitiveVariables();
4163
TqFloat time = QGetRenderContext()->Time();
4164
// Transform the points into camera space for processing,
4165
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4166
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4167
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4168
CreateGPrim( pSurface );
4174
//----------------------------------------------------------------------
4176
// Specify a paraboloid primitive.
4178
RtVoid RiParaboloid( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4181
va_start( pArgs, thetamax );
4183
std::vector<RtToken> aTokens;
4184
std::vector<RtPointer> aValues;
4185
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4187
RiParaboloidV( rmax, zmin, zmax, thetamax, count, &aTokens[0], &aValues[0] );
4191
//----------------------------------------------------------------------
4193
// List based version of above.
4195
RtVoid RiParaboloidV( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4199
Validate_RiParaboloid
4201
// Create a paraboloid
4202
boost::shared_ptr<CqParaboloid> pSurface( new CqParaboloid( rmax, zmin, zmax, 0, thetamax ) );
4203
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4204
pSurface->SetDefaultPrimitiveVariables();
4206
TqFloat time = QGetRenderContext()->Time();
4207
// Transform the points into camera space for processing,
4208
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4209
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4210
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4211
CreateGPrim( pSurface );
4217
//----------------------------------------------------------------------
4219
// Specify a disk primitive.
4221
RtVoid RiDisk( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
4224
va_start( pArgs, thetamax );
4226
std::vector<RtToken> aTokens;
4227
std::vector<RtPointer> aValues;
4228
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4230
RiDiskV( height, radius, thetamax, count, &aTokens[0], &aValues[0] );
4234
//----------------------------------------------------------------------
4236
// List based version of above.
4238
RtVoid RiDiskV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
4245
boost::shared_ptr<CqDisk> pSurface( new CqDisk( height, 0, radius, 0, thetamax ) );
4246
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4247
pSurface->SetDefaultPrimitiveVariables();
4249
TqFloat time = QGetRenderContext()->Time();
4250
// Transform the points into camera space for processing,
4251
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4252
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4253
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4255
CreateGPrim( pSurface );
4261
//----------------------------------------------------------------------
4264
RtVoid RiTorus( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, ... )
4267
va_start( pArgs, thetamax );
4269
std::vector<RtToken> aTokens;
4270
std::vector<RtPointer> aValues;
4271
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4273
RiTorusV( majorrad, minorrad, phimin, phimax, thetamax, count, &aTokens[0], &aValues[0] );
4277
//----------------------------------------------------------------------
4279
// Specify a torus primitive.
4281
RtVoid RiTorusV( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, PARAMETERLIST )
4288
boost::shared_ptr<CqTorus> pSurface( new CqTorus( majorrad, minorrad, phimin, phimax, 0, thetamax ) );
4289
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4290
pSurface->SetDefaultPrimitiveVariables();
4292
TqFloat time = QGetRenderContext()->Time();
4293
// Transform the points into camera space for processing,
4294
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4295
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4296
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4298
CreateGPrim( pSurface );
4304
//----------------------------------------------------------------------
4306
// Implement the procedural type primitive.
4308
RtVoid RiProcedural( RtPointer data, RtBound bound, RtProcSubdivFunc refineproc, RtProcFreeFunc freeproc )
4312
Validate_RiProcedural
4316
//printf("bound(%f %f %f %f %f %f)\n", bound[0], bound[1], bound[2], bound[3], bound[4], bound[5]);
4318
// I suspect that in order to handle the RtFreeProc correctly that we need to reference count
4319
// the instances of CqProcedural so that FreeProc gets called on the final Release();
4321
boost::shared_ptr<CqProcedural> pProc( new CqProcedural(data, B, refineproc, freeproc ) );
4322
TqFloat time = QGetRenderContext()->Time();
4323
pProc->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pProc->pTransform() ->matObjectToWorld(time), time ),
4324
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pProc->pTransform() ->matObjectToWorld(time), time ),
4325
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pProc->pTransform() ->matObjectToWorld(time), time ) );
4326
CreateGPrim( pProc );
4333
//----------------------------------------------------------------------
4335
// Specify a special primitive.
4337
RtVoid RiGeometry( RtToken type, ... )
4340
va_start( pArgs, type );
4342
std::vector<RtToken> aTokens;
4343
std::vector<RtPointer> aValues;
4344
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4346
RiGeometryV( type, count, &aTokens[0], &aValues[0] );
4350
//----------------------------------------------------------------------
4352
// List based version of above.
4354
RtVoid RiGeometryV( RtToken type, PARAMETERLIST )
4360
if ( strcmp( type, "teapot" ) == 0 )
4363
// Create a standard teapot
4364
boost::shared_ptr<CqTeapot> pSurface( new CqTeapot( true ) ); // add a bottom if true/false otherwise
4366
pSurface->SetSurfaceParameters( *pSurface );
4367
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4368
pSurface->SetDefaultPrimitiveVariables();
4370
// I don't use the original teapot primitives as defined by T. Burge
4371
// but an array of Patch Bicubic (stolen from example from Pixar) and
4372
// those (6 meshes) are registered as standards GPrims right here.
4373
// Basically I kept the bound, transform and split, dice and diceable methods
4374
// in teapot.cpp but I suspect they are never called since the work of
4375
// dicing will rely on the registered Gprimitives (see below in the for loop).
4376
// I suspect the 6/7 meshes are equivalent in size/definition as the T. Burge
4377
// definition. The 7th is the bottom part of the teapot (see teapot.cpp).
4379
for ( int i = 0; i < pSurface->cNbrPatchMeshBicubic; ++i )
4381
boost::shared_ptr<CqSurface> pMesh = pSurface->pPatchMeshBicubic[ i ];
4383
TqFloat time = QGetRenderContext()->Time();
4384
// Transform the points into camera space for processing,
4385
pMesh->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4386
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4387
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4389
CreateGPrim( boost::static_pointer_cast<CqBasicSurface>( pMesh ) );
4392
else if ( strcmp( type, "sphere" ) == 0 )
4395
boost::shared_ptr<CqSphere> pSurface( new CqSphere( 1, -1, 1, 0, 360.0 ) );
4396
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4397
pSurface->SetDefaultPrimitiveVariables();
4399
TqFloat time = QGetRenderContext()->Time();
4400
// Transform the points into camera space for processing,
4401
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4402
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
4403
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
4405
CreateGPrim( pSurface );
4409
std::cerr << warning << "RiGeometry unrecognised type \"" << type << "\"" << std::endl;
4415
//----------------------------------------------------------------------
4417
// Begin the definition of a CSG object.
4419
RtVoid RiSolidBegin( RtToken type )
4423
Validate_RiSolidBegin
4425
CqString strType( type );
4426
QGetRenderContext() ->BeginSolidModeBlock( strType );
4432
//----------------------------------------------------------------------
4434
// End the definition of a CSG object.
4442
QGetRenderContext() ->EndSolidModeBlock();
4448
//----------------------------------------------------------------------
4450
// Begin the definition of a stored object for use by RiObjectInstance.
4452
RtObjectHandle RiObjectBegin()
4456
Validate_RiObjectBegin
4458
QGetRenderContext() ->BeginObjectModeBlock();
4459
RtObjectHandle ObjectHandle = static_cast<RtObjectHandle>(QGetRenderContext() ->OpenNewObjectInstance());
4461
return ( ObjectHandle );
4465
//----------------------------------------------------------------------
4467
// End the defintion of a stored object for use by RiObjectInstance.
4469
RtVoid RiObjectEnd()
4471
Validate_RiObjectEnd
4473
QGetRenderContext() ->EndObjectModeBlock();
4474
QGetRenderContext() ->CloseObjectInstance();
4482
//----------------------------------------------------------------------
4484
// Instantiate a copt of a pre-stored geometric object.
4486
RtVoid RiObjectInstance( RtObjectHandle handle )
4488
Cache_RiObjectInstance
4490
Validate_RiObjectInstance
4492
QGetRenderContext() ->InstantiateObject( reinterpret_cast<CqObjectInstance*>( handle ) );
4497
//----------------------------------------------------------------------
4499
// Begin the definition of the motion of an object for use by motion blur.
4501
RtVoid RiMotionBegin( RtInt N, ... )
4504
va_start( pArgs, N );
4506
RtFloat* times = new RtFloat[ N ];
4508
for ( i = 0; i < N; ++i )
4509
times[ i ] = va_arg( pArgs, double );
4511
RiMotionBeginV( N, times );
4518
//----------------------------------------------------------------------
4520
// List based version of above.
4522
RtVoid RiMotionBeginV( RtInt N, RtFloat times[] )
4524
Cache_RiMotionBeginV
4526
Validate_RiMotionBeginV
4528
QGetRenderContext() ->BeginMotionModeBlock( N, times );
4534
//----------------------------------------------------------------------
4536
// End the definition of the motion of an object.
4538
RtVoid RiMotionEnd()
4542
Validate_RiMotionEnd
4544
QGetRenderContext() ->EndMotionModeBlock();
4550
//----------------------------------------------------------------------
4552
// Convert a picture to a texture.
4554
RtVoid RiMakeTexture ( RtString pic, RtString tex, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
4557
va_start( pArgs, twidth );
4559
std::vector<RtToken> aTokens;
4560
std::vector<RtPointer> aValues;
4561
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4563
RiMakeTextureV( pic, tex, swrap, twrap, filterfunc, swidth, twidth, count, &aTokens[0], &aValues[0] );
4568
//----------------------------------------------------------------------
4570
// List based version of above.
4572
RtVoid RiMakeTextureV( RtString imagefile, RtString texturefile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
4576
Validate_RiMakeTexture
4579
assert( imagefile != 0 && texturefile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
4581
QGetRenderContext() ->Stats().MakeTextureTimer().Start();
4582
// Get the wrap modes first.
4583
enum EqWrapMode smode = WrapMode_Black;
4584
if ( strcmp( swrap, RI_PERIODIC ) == 0 )
4585
smode = WrapMode_Periodic;
4586
else if ( strcmp( swrap, RI_CLAMP ) == 0 )
4587
smode = WrapMode_Clamp;
4588
else if ( strcmp( swrap, RI_BLACK ) == 0 )
4589
smode = WrapMode_Black;
4591
enum EqWrapMode tmode = WrapMode_Black;
4592
if ( strcmp( twrap, RI_PERIODIC ) == 0 )
4593
tmode = WrapMode_Periodic;
4594
else if ( strcmp( twrap, RI_CLAMP ) == 0 )
4595
tmode = WrapMode_Clamp;
4596
else if ( strcmp( twrap, RI_BLACK ) == 0 )
4597
tmode = WrapMode_Black;
4600
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
4601
if ( filterfunc == RiGaussianFilter )
4602
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "gaussian", swidth, twidth );
4603
if ( filterfunc == RiBoxFilter )
4604
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
4605
if ( filterfunc == RiTriangleFilter )
4606
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "triangle", swidth, twidth );
4607
if ( filterfunc == RiCatmullRomFilter )
4608
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "catmull-rom", swidth, twidth );
4609
if ( filterfunc == RiSincFilter )
4610
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "sinc", swidth, twidth );
4611
if ( filterfunc == RiDiskFilter )
4612
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "disk", swidth, twidth );
4613
if ( filterfunc == RiBesselFilter )
4614
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "bessel", swidth, twidth );
4617
// Now load the original image.
4618
CqTextureMap Source( imagefile );
4621
ProcessCompression( &comp, &qual, count, tokens, values );
4622
Source.SetCompression( comp );
4623
Source.SetQuality( qual );
4625
if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
4627
// Hopefully CqTextureMap will take care of closing the tiff file after
4628
// it has SAT mapped it so we can overwrite if needs be.
4629
// Create a new image.
4630
Source.Interpreted( modes );
4631
Source.CreateMIPMAP();
4632
TIFF* ptex = TIFFOpen( texturefile, "w" );
4634
TIFFCreateDirectory( ptex );
4635
TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
4636
TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, MIPMAP_HEADER );
4637
TIFFSetField( ptex, TIFFTAG_PIXAR_WRAPMODES, modes );
4638
TIFFSetField( ptex, TIFFTAG_SAMPLESPERPIXEL, Source.SamplesPerPixel() );
4639
TIFFSetField( ptex, TIFFTAG_BITSPERSAMPLE, 8 );
4640
TIFFSetField( ptex, TIFFTAG_COMPRESSION, Source.Compression() ); /* COMPRESSION_DEFLATE */
4641
int log2 = MIN( Source.XRes(), Source.YRes() );
4642
log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
4645
for ( int i = 0; i < log2; ++i )
4647
// Write the floating point image to the directory.
4648
CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
4649
if ( !pBuffer ) break;
4650
Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
4656
QGetRenderContext() ->Stats().MakeTextureTimer().Stop();
4660
//----------------------------------------------------------------------
4662
// Convert a picture to a bump map.
4664
RtVoid RiMakeBump( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
4666
std::cerr << warning << "RiMakeBump not supported" << std::endl;
4671
//----------------------------------------------------------------------
4673
// List based version of above.
4675
RtVoid RiMakeBumpV( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
4681
std::cerr << warning << "RiMakeBump not supported" << std::endl;
4686
//----------------------------------------------------------------------
4687
// RiMakeLatLongEnvironment
4688
// Convert a picture to an environment map.
4690
RtVoid RiMakeLatLongEnvironment( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
4693
va_start( pArgs, twidth );
4695
std::vector<RtToken> aTokens;
4696
std::vector<RtPointer> aValues;
4697
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4699
RiMakeLatLongEnvironmentV( imagefile, reflfile, filterfunc, swidth, twidth, count, &aTokens[0], &aValues[0] );
4704
//----------------------------------------------------------------------
4705
// RiMakeLatLongEnvironmentV
4706
// List based version of above.
4708
RtVoid RiMakeLatLongEnvironmentV( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
4710
Cache_RiMakeLatLongEnvironment
4712
Validate_RiMakeLatLongEnvironment
4715
char *swrap = "periodic";
4716
char *twrap = "clamp";
4718
assert( imagefile != 0 && reflfile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
4720
QGetRenderContext() ->Stats().MakeEnvTimer().Start();
4722
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
4723
if ( filterfunc == RiGaussianFilter )
4724
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "gaussian", swidth, twidth );
4725
if ( filterfunc == RiBoxFilter )
4726
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
4727
if ( filterfunc == RiTriangleFilter )
4728
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "triangle", swidth, twidth );
4729
if ( filterfunc == RiCatmullRomFilter )
4730
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "catmull-rom", swidth, twidth );
4731
if ( filterfunc == RiSincFilter )
4732
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "sinc", swidth, twidth );
4733
if ( filterfunc == RiDiskFilter )
4734
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "disk", swidth, twidth );
4735
if ( filterfunc == RiBesselFilter )
4736
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "bessel", swidth, twidth );
4739
// Now load the original image.
4740
CqTextureMap Source( imagefile );
4743
ProcessCompression( &comp, &qual, count, tokens, values );
4744
Source.SetCompression( comp );
4745
Source.SetQuality( qual );
4747
if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
4749
// Hopefully CqTextureMap will take care of closing the tiff file after
4750
// it has SAT mapped it so we can overwrite if needs be.
4751
// Create a new image.
4752
Source.Interpreted( modes );
4753
Source.CreateMIPMAP();
4754
TIFF* ptex = TIFFOpen( reflfile, "w" );
4756
TIFFCreateDirectory( ptex );
4757
TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
4758
TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, LATLONG_HEADER );
4759
TIFFSetField( ptex, TIFFTAG_PIXAR_WRAPMODES, modes );
4760
TIFFSetField( ptex, TIFFTAG_SAMPLESPERPIXEL, Source.SamplesPerPixel() );
4761
TIFFSetField( ptex, TIFFTAG_BITSPERSAMPLE, 8 );
4762
TIFFSetField( ptex, TIFFTAG_COMPRESSION, Source.Compression() ); /* COMPRESSION_DEFLATE */
4763
int log2 = MIN( Source.XRes(), Source.YRes() );
4764
log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
4767
for ( int i = 0; i < log2; ++i )
4769
// Write the floating point image to the directory.
4770
CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
4771
if ( !pBuffer ) break;
4772
Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
4778
QGetRenderContext() ->Stats().MakeEnvTimer().Stop();
4783
//----------------------------------------------------------------------
4784
// RiMakeCubeFaceEnvironment
4785
// Convert a picture to a cubical environment map.
4787
RtVoid RiMakeCubeFaceEnvironment( RtString px, RtString nx, RtString py, RtString ny, RtString pz, RtString nz, RtString reflfile, RtFloat fov, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
4790
va_start( pArgs, twidth );
4792
std::vector<RtToken> aTokens;
4793
std::vector<RtPointer> aValues;
4794
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4796
RiMakeCubeFaceEnvironmentV( px, nx, py, ny, pz, nz, reflfile, fov, filterfunc, swidth, twidth, count, &aTokens[0], &aValues[0] );
4800
//----------------------------------------------------------------------
4801
// RiMakeCubeFaceEnvironment
4802
// List based version of above.
4804
RtVoid RiMakeCubeFaceEnvironmentV( RtString px, RtString nx, RtString py, RtString ny, RtString pz, RtString nz, RtString reflfile, RtFloat fov, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
4806
Cache_RiMakeCubeFaceEnvironment
4808
Validate_RiMakeCubeFaceEnvironment
4810
QGetRenderContext() ->Stats().MakeEnvTimer().Start();
4811
assert( px != 0 && nx != 0 && py != 0 && ny != 0 && pz != 0 && nz != 0 &&
4812
reflfile != 0 && filterfunc != 0 );
4814
// Now load the original image.
4815
CqTextureMap tpx( px );
4816
CqTextureMap tnx( nx );
4817
CqTextureMap tpy( py );
4818
CqTextureMap tny( ny );
4819
CqTextureMap tpz( pz );
4820
CqTextureMap tnz( nz );
4829
if ( tpx.Format() != TexFormat_MIPMAP ) tpx.CreateMIPMAP();
4830
if ( tnx.Format() != TexFormat_MIPMAP ) tnx.CreateMIPMAP();
4831
if ( tpy.Format() != TexFormat_MIPMAP ) tpy.CreateMIPMAP();
4832
if ( tny.Format() != TexFormat_MIPMAP ) tny.CreateMIPMAP();
4833
if ( tpz.Format() != TexFormat_MIPMAP ) tpz.CreateMIPMAP();
4834
if ( tnz.Format() != TexFormat_MIPMAP ) tnz.CreateMIPMAP();
4835
if ( tpx.IsValid() && tnx.IsValid() && tpy.IsValid() && tny.IsValid() && tpz.IsValid() && tnz.IsValid() )
4837
// Check all the same size;
4838
bool fValid = false;
4839
if ( tpx.XRes() == tnx.XRes() && tpx.XRes() == tpy.XRes() && tpx.XRes() == tny.XRes() && tpx.XRes() == tpz.XRes() && tpx.XRes() == tnz.XRes() &&
4840
tpx.XRes() == tnx.XRes() && tpx.XRes() == tpy.XRes() && tpx.XRes() == tny.XRes() && tpx.XRes() == tpz.XRes() && tpx.XRes() == tnz.XRes() )
4845
std::cerr << error << "RiMakeCubeFaceEnvironment all images must be the same size" << std::endl;
4849
// Now copy the images to the big map.
4850
CqTextureMap* Images[ 6 ] =
4860
// Create a new image.
4861
TIFF* ptex = TIFFOpen( reflfile, "w" );
4864
TqInt xRes = tpx.XRes();
4865
TqInt yRes = tpx.YRes();
4867
TqInt numsamples = tpx.SamplesPerPixel();
4868
// Number of mip map levels.
4869
int log2 = MIN( xRes, yRes );
4870
log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
4872
for ( ii = 0; ii < log2; ++ii )
4874
CqTextureMapBuffer* pLevelBuffer = tpx.CreateBuffer( 0, 0, xRes * 3, yRes * 2, numsamples );
4876
for ( view = 0; view < 6; ++view )
4878
// Get the buffer for the approriate cube side at this level.
4879
CqTextureMapBuffer* pBuffer = Images[ view ] ->GetBuffer( 0, 0, ii );
4880
// Work out where in the combined image it goes.
4881
TqInt xoff = view % 3;
4883
TqInt yoff = view / 3;
4885
TqInt line, col, sample;
4886
for ( line = 0; line < yRes; ++line )
4888
for ( col = 0; col < xRes; ++col )
4890
for ( sample = 0; sample < numsamples; ++sample )
4891
pLevelBuffer->SetValue( col + xoff, line + yoff, sample, pBuffer->GetValue( col, line, sample ) );
4896
TIFFCreateDirectory( ptex );
4897
TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
4898
TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, CUBEENVMAP_HEADER );
4899
tpx.WriteTileImage( ptex, pLevelBuffer, 64, 64, tpx.Compression(), tpx.Quality() );
4905
QGetRenderContext() ->Stats().MakeEnvTimer().Stop();
4910
//----------------------------------------------------------------------
4912
// Convert a depth map file to a shadow map.
4914
RtVoid RiMakeShadow( RtString picfile, RtString shadowfile, ... )
4917
va_start( pArgs, shadowfile );
4919
std::vector<RtToken> aTokens;
4920
std::vector<RtPointer> aValues;
4921
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4923
RiMakeShadowV( picfile, shadowfile, count, &aTokens[0], &aValues[0] );
4927
//----------------------------------------------------------------------
4929
// List based version of above.
4931
RtVoid RiMakeShadowV( RtString picfile, RtString shadowfile, PARAMETERLIST )
4935
Validate_RiMakeShadow
4937
QGetRenderContext() ->Stats().MakeShadowTimer().Start();
4938
CqShadowMap ZFile( picfile );
4942
ProcessCompression( &comp, &qual, count, tokens, values );
4943
ZFile.SetCompression( comp );
4944
ZFile.SetQuality( qual );
4946
ZFile.SaveShadowMap( shadowfile );
4947
QGetRenderContext() ->Stats().MakeShadowTimer().Stop();
4952
//----------------------------------------------------------------------
4954
// Convert a series of depth maps to an occlusion map.
4956
RtVoid RiMakeOcclusion( RtInt npics, RtString picfiles[], RtString shadowfile, ... )
4959
va_start( pArgs, shadowfile );
4961
std::vector<RtToken> aTokens;
4962
std::vector<RtPointer> aValues;
4963
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
4965
RiMakeOcclusionV( npics, picfiles, shadowfile, count, &aTokens[0], &aValues[0] );
4969
//----------------------------------------------------------------------
4971
// List based version of above.
4973
RtVoid RiMakeOcclusionV( RtInt npics, RtString picfiles[], RtString shadowfile, RtInt count, RtToken tokens[], RtPointer values[] )
4975
Cache_RiMakeOcclusion
4977
Validate_RiMakeOcclusion
4979
QGetRenderContext() ->Stats().MakeShadowTimer().Start();
4982
for( index = 0; index < npics; ++index )
4984
CqShadowMap ZFile( picfiles[index] );
4988
ProcessCompression( &comp, &qual, count, tokens, values );
4989
ZFile.SetCompression( comp );
4990
ZFile.SetQuality( qual );
4992
ZFile.SaveShadowMap( shadowfile, TqTrue );
4994
QGetRenderContext() ->Stats().MakeShadowTimer().Stop();
4999
//----------------------------------------------------------------------
5001
// Set the function used to report errors.
5003
RtVoid RiErrorHandler( RtErrorFunc handler )
5005
Cache_RiErrorHandler
5007
Validate_RiErrorHandler
5009
QGetRenderContext()->SetpErrorHandler( handler );
5014
//----------------------------------------------------------------------
5016
// Function used by RiErrorHandler to continue after errors.
5018
RtVoid RiErrorIgnore( RtInt code, RtInt severity, RtString message )
5024
//----------------------------------------------------------------------
5026
// Function used by RiErrorHandler to print an error message to stdout and continue.
5028
RtVoid RiErrorPrint( RtInt code, RtInt severity, RtString message )
5031
std::cerr << error << "RiError: " << code << " : " << severity << " : " << message << std::endl;
5036
//----------------------------------------------------------------------
5038
// Function used by RiErrorHandler to print and error and stop.
5040
RtVoid RiErrorAbort( RtInt code, RtInt severity, RtString message )
5046
//----------------------------------------------------------------------
5047
// RiSubdivisionMesh
5048
// Specify a subdivision surface hull with tagging.
5050
RtVoid RiSubdivisionMesh( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], ... )
5053
va_start( pArgs, floatargs );
5055
std::vector<RtToken> aTokens;
5056
std::vector<RtPointer> aValues;
5057
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
5059
RiSubdivisionMeshV( scheme, nfaces, nvertices, vertices, ntags, tags, nargs, intargs, floatargs, count, &aTokens[0], &aValues[0] );
5062
//----------------------------------------------------------------------
5063
// RiSubdivisionMeshV
5064
// List based version of above.
5066
RtVoid RiSubdivisionMeshV( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], PARAMETERLIST )
5068
Cache_RiSubdivisionMesh
5070
Validate_RiSubdivisionMesh
5072
// Calculate how many vertices there are.
5074
RtInt* pVerts = vertices;
5076
RtInt sumnVerts = 0;
5077
for ( face = 0; face < nfaces; ++face )
5080
sumnVerts += nvertices[ face ];
5081
for ( v = 0; v < nvertices[ face ]; ++v )
5083
cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
5088
// Create a storage class for all the points.
5089
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, nfaces, sumnVerts ) );
5091
std::vector<boost::shared_ptr<CqPolygonPoints> > apPoints;
5092
// Process any specified primitive variables
5093
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
5095
// Create experimental version
5096
if ( strcmp( scheme, "catmull-clark" ) == 0 )
5098
// Transform the points into camera space for processing,
5099
pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
5100
QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
5101
QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ) );
5103
boost::shared_ptr<CqSubdivision2> pSubd2( new CqSubdivision2( pPointsClass ) );
5104
pSubd2->Prepare( cVerts );
5107
for ( face = 0; face < nfaces; ++face )
5109
pSubd2->AddFacet( nvertices[ face ], &vertices[ iP ], iP );
5110
iP += nvertices[ face ];
5112
if ( pSubd2->Finalise() )
5115
TqInt argcIndex = 0;
5116
TqInt floatargIndex = 0;
5117
TqInt intargIndex = 0;
5118
for ( TqInt i = 0; i < ntags; ++i )
5120
if ( strcmp( tags[ i ], "interpolateboundary" ) == 0 )
5121
pSubd2->SetInterpolateBoundary( TqTrue );
5122
else if ( strcmp( tags [ i ], "crease" ) == 0 )
5124
TqFloat creaseSharpness = floatargs[ floatargIndex ];
5125
// convert pixars 0->infinity crease values to our 0->1
5126
if( creaseSharpness > 5.0f )
5127
creaseSharpness = 5.0f;
5128
creaseSharpness /= 5.0f;
5129
// bend the curve so values behave more like pixars algorithm
5130
creaseSharpness = pow(creaseSharpness, 0.2f);
5132
while ( iEdge < nargs[ argcIndex ] - 1 )
5134
if ( intargs[ iEdge + intargIndex ] < pSubd2->cVertices() &&
5135
intargs[ iEdge + intargIndex + 1 ] < pSubd2->cVertices() )
5137
// Store the crease sharpness.
5138
CqLath* pEdge = pSubd2->pVertex( intargs[ iEdge + intargIndex ] );
5139
std::vector<CqLath*> aQve;
5141
std::vector<CqLath*>::iterator iOpp;
5142
for( iOpp = aQve.begin(); iOpp != aQve.end(); ++iOpp )
5144
if( ( NULL != (*iOpp)->ec() ) && (*iOpp)->ec()->VertexIndex() == intargs[ iEdge + intargIndex + 1 ] )
5146
pSubd2->AddSharpEdge( (*iOpp), creaseSharpness );
5147
pSubd2->AddSharpEdge( (*iOpp)->ec(), creaseSharpness );
5155
else if ( strcmp( tags [ i ], "corner" ) == 0 )
5158
while ( iVertex < nargs[ argcIndex ] )
5160
if ( intargs[ iVertex + intargIndex ] < pSubd2->cVertices() )
5162
// Store the corner sharpness.
5163
CqLath* pVertex = pSubd2->pVertex( intargs[ iVertex + intargIndex ] );
5164
pSubd2->AddSharpCorner( pVertex, RI_INFINITY );
5169
else if ( strcmp( tags [ i ], "hole" ) == 0 )
5172
while ( iFace < nargs[ argcIndex ] )
5174
pSubd2->SetHoleFace( intargs[ iFace + intargIndex ] );
5179
intargIndex += nargs[ argcIndex++ ];
5180
floatargIndex += nargs[ argcIndex++ ];
5183
boost::shared_ptr<CqSurfaceSubdivisionMesh> pMesh( new CqSurfaceSubdivisionMesh(pSubd2, nfaces ) );
5188
std::cerr << error << "RiSubdivisionMesh contains non-manifold data" << std::endl;
5193
std::cerr << error << "RiSubdivisionMesh invalid scheme \"" << scheme << "\"" << std::endl;
5201
RtVoid RiReadArchive( RtToken name, RtArchiveCallback callback, ... )
5204
va_start( pArgs, callback );
5206
std::vector<RtToken> aTokens;
5207
std::vector<RtPointer> aValues;
5208
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
5210
RiReadArchiveV( name, callback, count, &aTokens[0], &aValues[0] );
5214
RtVoid RiReadArchiveV( RtToken name, RtArchiveCallback callback, PARAMETERLIST )
5218
Validate_RiReadArchive
5220
CqRiFile fileArchive( name, "archive" );
5221
const TqInt* poptVerbose = QGetRenderContext() ->optCurrent().GetIntegerOption( "statistics", "verbose" );
5223
if ( fileArchive.IsValid() )
5225
CqString strRealName( fileArchive.strRealName() );
5226
fileArchive.Close();
5228
if ( ( file = fopen( strRealName.c_str(), "rb" ) ) != NULL )
5232
std::cerr << info << "RiReadArchive: Reading archive \"" << strRealName.c_str() << "\"" << std::endl;
5234
CqRIBParserState currstate = librib::GetParserState();
5235
if (currstate.m_pParseCallbackInterface == NULL) currstate.m_pParseCallbackInterface = new librib2ri::Engine;
5236
librib::Parse( file, name, *(currstate.m_pParseCallbackInterface), *(currstate.m_pParseErrorStream), callback );
5237
librib::SetParserState( currstate );
5244
RtVoid RiArchiveRecord( RtToken type, char *, ... )
5246
Validate_RiArchiveRecord
5249
RtContextHandle RiGetContext( void )
5251
Validate_RiGetContext
5256
RtVoid RiContext( RtContextHandle )
5261
RtVoid RiClippingPlane( RtFloat, RtFloat, RtFloat, RtFloat, RtFloat, RtFloat )
5263
Validate_RiClippingPlane
5267
//---------------------------------------------------------------------
5268
//---------------------------------------------------------------------
5271
//----------------------------------------------------------------------
5272
// ProcessPrimitiveVariables
5273
// Process and fill in any primitive variables.
5274
// return : RI_TRUE if position specified, RI_FALSE otherwise.
5276
static RtBoolean ProcessPrimitiveVariables( CqSurface * pSurface, PARAMETERLIST )
5278
std::vector<TqInt> aUserParams;
5280
// Read recognised parameter values.
5281
RtInt fP = RIL_NONE;
5283
RtFloat* pPoints = 0;
5286
for ( i = 0; i < count; ++i )
5288
RtToken token = tokens[ i ];
5289
RtPointer value = values[ i ];
5290
TqUlong hash = CqParameter::hash(token);
5292
SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( token );
5294
if ( (hash == RIH_P) && (Decl.m_Class == class_vertex ))
5297
pPoints = ( RtFloat* ) value;
5299
else if ( (hash == RIH_PZ) && (Decl.m_Class == class_vertex ) )
5302
pPoints = ( RtFloat* ) value;
5304
else if ( (hash == RIH_PW) && (Decl.m_Class == class_vertex ) )
5307
pPoints = ( RtFloat* ) value;
5311
aUserParams.push_back( i );
5315
// Fill in the position variable according to type.
5316
if ( fP != RIL_NONE )
5318
pSurface->AddPrimitiveVariable( new CqParameterTypedVertex<CqVector4D, type_hpoint, CqVector3D>( "P", 1 ) );
5319
pSurface->P() ->SetSize( pSurface->cVertex() );
5324
for ( i = 0; i < pSurface->cVertex(); ++i )
5325
pSurface->P()->pValue( i )[0] = CqVector3D( pPoints[ ( i * 3 ) ], pPoints[ ( i * 3 ) + 1 ], pPoints[ ( i * 3 ) + 2 ] );
5329
for ( i = 0; i < pSurface->cVertex(); ++i )
5331
CqVector3D vecP = pSurface->SurfaceParametersAtVertex( i );
5332
vecP.z( pPoints[ i ] );
5333
pSurface->P()->pValue( i )[0] = vecP;
5338
for ( i = 0; i < pSurface->cVertex(); ++i )
5339
pSurface->P()->pValue( i )[0] = CqVector4D( pPoints[ ( i * 4 ) ], pPoints[ ( i * 4 ) + 1 ], pPoints[ ( i * 4 ) + 2 ], pPoints[ ( i * 4 ) + 3 ] );
5344
// Now process any user defined paramter variables.
5345
if ( aUserParams.size() > 0 )
5347
std::vector<TqInt>::iterator iUserParam;
5348
for ( iUserParam = aUserParams.begin(); iUserParam != aUserParams.end(); ++iUserParam )
5350
SqParameterDeclaration Decl;
5353
Decl = QGetRenderContext()->FindParameterDecl( tokens[ *iUserParam ] );
5355
catch( XqException e )
5357
std::cerr << error << e.strReason().c_str() << std::endl;
5361
CqParameter* pNewParam = ( *Decl.m_pCreate ) ( Decl.m_strName.c_str(), Decl.m_Count );
5362
// Now go across all values and fill in the parameter variable.
5364
switch ( Decl.m_Class )
5367
cValues = pSurface->cUniform();
5371
cValues = pSurface->cVarying();
5375
cValues = pSurface->cVertex();
5378
case class_facevarying:
5379
cValues = pSurface->cFaceVarying();
5382
pNewParam->SetSize( cValues );
5385
switch ( Decl.m_Type )
5389
CqParameterTyped<TqFloat, TqFloat>* pFloatParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pNewParam );
5390
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5391
TqInt iArrayIndex, iValIndex;
5393
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5394
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5395
pFloatParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
5401
CqParameterTyped<TqInt, TqFloat>* pIntParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pNewParam );
5402
TqInt* pValue = reinterpret_cast<TqInt*>( values[ *iUserParam ] );
5403
TqInt iArrayIndex, iValIndex;
5405
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5406
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5407
pIntParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
5415
CqParameterTyped<CqVector3D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pNewParam );
5416
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5417
TqInt iArrayIndex, iValIndex;
5419
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5420
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5421
pVectorParam->pValue( iValIndex ) [ iArrayIndex ] = CqVector3D( pValue[ ( i * 3 ) ], pValue[ ( i * 3 ) + 1 ], pValue[ ( i * 3 ) + 2 ] );
5427
CqParameterTyped<CqString, CqString>* pStringParam = static_cast<CqParameterTyped<CqString, CqString>*>( pNewParam );
5428
char** pValue = reinterpret_cast<char**>( values[ *iUserParam ] );
5429
TqInt iArrayIndex, iValIndex;
5431
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5432
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5433
pStringParam->pValue( iValIndex ) [ iArrayIndex ] = CqString( pValue[ i ] );
5439
CqParameterTyped<CqColor, CqColor>* pColorParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pNewParam );
5440
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5441
TqInt iArrayIndex, iValIndex;
5443
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5444
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5445
pColorParam->pValue( iValIndex ) [ iArrayIndex ] = CqColor( pValue[ ( i * 3 ) ], pValue[ ( i * 3 ) + 1 ], pValue[ ( i * 3 ) + 2 ] );
5451
CqParameterTyped<CqVector4D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pNewParam );
5452
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5453
TqInt iArrayIndex, iValIndex;
5455
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5456
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5457
pVectorParam->pValue( iValIndex ) [ iArrayIndex ] = CqVector4D( pValue[ ( i * 4 ) ], pValue[ ( i * 4 ) + 1 ], pValue[ ( i * 4 ) + 2 ], pValue[ ( i * 4 ) + 3 ] );
5463
CqParameterTyped<CqMatrix, CqMatrix>* pMatrixParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pNewParam );
5464
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5465
TqInt iArrayIndex, iValIndex;
5467
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5468
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
5469
pMatrixParam->pValue( iValIndex ) [ iArrayIndex ] = CqMatrix( pValue[ ( i * 16 ) ], pValue[ ( i * 16 ) + 1 ], pValue[ ( i * 16 ) + 2 ], pValue[ ( i * 16 ) + 3 ],
5470
pValue[ ( i * 16 ) + 4 ], pValue[ ( i * 16 ) + 5 ], pValue[ ( i * 16 ) + 6 ], pValue[ ( i * 16 ) + 7 ],
5471
pValue[ ( i * 16 ) + 8 ], pValue[ ( i * 16 ) + 9 ], pValue[ ( i * 16 ) + 10 ], pValue[ ( i * 16 ) + 11 ],
5472
pValue[ ( i * 16 ) + 12 ], pValue[ ( i * 16 ) + 13 ], pValue[ ( i * 16 ) + 14 ], pValue[ ( i * 16 ) + 15 ]
5479
// left blank to avoid compiler warnings about unhandled types
5483
pSurface->AddPrimitiveVariable( pNewParam );
5484
CqParameter* pP = pSurface->P();
5488
return ( pSurface->P() != NULL );
5492
//----------------------------------------------------------------------
5494
// Create and register a GPrim according to the current attributes/transform
5496
RtVoid CreateGPrim( const boost::shared_ptr<CqBasicSurface>& pSurface )
5499
if ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "LevelOfDetailBounds" ) [ 1 ] < 0.0f )
5501
// Cull this geometry for LOD reasons.
5505
// If in a motion block, confirm that the current deformation surface can accept the passed one as a keyframe.
5506
if( QGetRenderContext() ->pconCurrent() ->fMotionBlock() )
5508
pSurface->PrepareTrimCurve();
5510
CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
5512
CqDeformingSurface* pMS = pMMB->GetDeformingSurface().get();
5513
// If this is the first frame, then generate the appropriate CqDeformingSurface and fill in the first frame.
5514
// Then cache the pointer on the motion block.
5517
boost::shared_ptr<CqDeformingSurface> pNewMS( new CqDeformingSurface( pSurface ) );
5518
pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
5519
pMMB->SetDeformingSurface( pNewMS );
5523
pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
5525
QGetRenderContext() ->AdvanceTime();
5529
pSurface->PrepareTrimCurve();
5530
QGetRenderContext() ->pImage() ->PostSurface( pSurface );
5531
STATS_INC( GPR_created );
5533
// Add to the raytracer database also
5534
if(QGetRenderContext()->pRaytracer())
5535
QGetRenderContext()->pRaytracer()->AddPrimitive(pSurface);
5542
//----------------------------------------------------------------------
5543
/** Get the basis matrix given a standard basis name.
5544
* \param b Storage for basis matrix.
5545
* \param strName Name of basis.
5546
* \return Boolean indicating the basis is valid.
5549
RtBoolean BasisFromName( RtBasis * b, const char * strName )
5551
RtBasis * pVals = 0;
5552
if ( !strcmp( strName, "bezier" ) )
5553
pVals = &RiBezierBasis;
5554
else if ( !strcmp( strName, "bspline" ) )
5555
pVals = &RiBSplineBasis;
5556
else if ( !strcmp( strName, "catmull-rom" ) )
5557
pVals = &RiCatmullRomBasis;
5558
else if ( !strcmp( strName, "hermite" ) )
5559
pVals = &RiHermiteBasis;
5560
else if ( !strcmp( strName, "power" ) )
5561
pVals = &RiPowerBasis;
5566
for ( i = 0; i < 4; ++i )
5567
for ( j = 0; j < 4; ++j )
5568
( *b ) [ i ][ j ] = ( *pVals ) [ i ][ j ];
5575
//----------------------------------------------------------------------
5576
/** Set the function used to report progress.
5577
* \param handler Pointer to the new function to use.
5580
RtVoid RiProgressHandler( RtProgressFunc handler )
5582
QGetRenderContext()->SetpProgressHandler( handler );
5587
//----------------------------------------------------------------------
5588
/** Set the function called just prior to rendering, after the world is complete.
5589
\param function Pointer to the new function to use.
5590
\return Pointer to the old function.
5593
RtFunc RiPreRenderFunction( RtFunc function )
5595
RtFunc pOldPreRenderFunction = QGetRenderContext()->pPreRenderFunction();
5596
QGetRenderContext()->SetpPreRenderFunction( function );
5597
return ( pOldPreRenderFunction );
5600
//----------------------------------------------------------------------
5601
/** Set the function called just prior to world definition.
5602
\param function Pointer to the new function to use.
5603
\return Pointer to the old function.
5606
RtFunc RiPreWorldFunction( RtFunc function )
5608
RtFunc pOldPreWorldFunction = QGetRenderContext()->pPreWorldFunction();
5609
QGetRenderContext()->SetpPreWorldFunction( function );
5610
return ( pOldPreWorldFunction );
5614
void SetShaderArgument( IqShader * pShader, const char * name, TqPchar val )
5616
// Find the relevant variable.
5617
SqParameterDeclaration Decl;
5620
Decl = QGetRenderContext() ->FindParameterDecl( name );
5622
catch( XqException e )
5624
std::cerr << error << e.strReason().c_str() << std::endl;
5628
pShader->SetArgument( Decl.m_strName, Decl.m_Type, Decl.m_strSpace, val );
5632
//----------------------------------------------------------------------
5633
/** Analyze the parameter list and figure what kind of compression is required for texturemapping output files.
5635
\param compression compression Pointer to an integer to containing the TIFF compression
5636
\param quality it is the quality of jpeg's compression
5637
\param count list counter
5638
\param tokens list of tokens
5639
\param values list of values
5644
static void ProcessCompression( TqInt * compression, TqInt * quality, TqInt count, RtToken * tokens, RtPointer * values )
5646
*compression = COMPRESSION_NONE;
5649
for ( int i = 0; i < count; ++i )
5651
RtToken token = tokens[ i ];
5652
RtString *value = ( RtString * ) values[ i ];
5654
if ( strstr( token, "compression" ) != 0 )
5657
if ( strstr( *value, "none" ) != 0 )
5658
* compression = COMPRESSION_NONE;
5660
else if ( strstr( *value, "lzw" ) != 0 )
5661
* compression = COMPRESSION_LZW;
5663
else if ( strstr( *value, "deflate" ) != 0 )
5664
* compression = COMPRESSION_DEFLATE;
5666
else if ( strstr( *value, "jpeg" ) != 0 )
5667
* compression = COMPRESSION_JPEG;
5669
else if ( strstr( *value, "packbits" ) != 0 )
5670
* compression = COMPRESSION_PACKBITS;
5674
else if ( strstr( token, "quality" ) != 0 )
5677
*quality = ( int ) * ( float * ) value;
5678
if ( *quality < 0 ) * quality = 0;
5679
if ( *quality > 100 ) * quality = 100;