2
// Copyright 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.org
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.org)
24
\todo: <b>Code Review</b>
27
#include "MultiTimer.h"
35
#include "imagebuffer.h"
47
#include "texturemap.h"
48
#include "objectinstance.h"
49
#include "trimcurve.h"
54
#include "librib2ri.h"
55
#include "converter.h"
58
#include "libribtypes.h"
59
#include "parserstate.h"
60
#include "procedural.h"
62
#include "logging_streambufs.h"
66
#include "subdivision2.h"
67
#include "condition.h"
71
#ifndef AQSIS_SYSTEM_WIN32
75
#endif /* AQSIS_SYSTEM_WIN32 */
77
// These are needed to allow calculation of the default paths
78
#ifdef AQSIS_SYSTEM_WIN32
82
extern "C" __declspec(dllimport) void report_refcounts();
84
#endif // !AQSIS_SYSTEM_WIN32
86
#if defined(AQSIS_SYSTEM_MACOSX)
87
#include "Carbon/Carbon.h"
98
#include "ri_validate.inl"
100
using namespace Aqsis;
102
#include "ri_debug.h"
104
static RtBoolean ProcessPrimitiveVariables( CqSurface* pSurface, PARAMETERLIST );
105
static void ProcessCompression( TqInt *compress, TqInt *quality, TqInt count, RtToken *tokens, RtPointer *values );
106
RtVoid CreateGPrim( const boost::shared_ptr<CqSurface>& pSurface );
107
void SetShaderArgument( const boost::shared_ptr<IqShader>& pShader, const char* name, TqPchar val );
108
TqBool ValidateState(...);
110
TqBool IfOk = TqTrue;
112
#define VALIDATE_CONDITIONAL \
118
#define VALIDATE_CONDITIONAL0 \
124
#define EXTRACT_PARAMETERS(_start) \
126
va_start( pArgs, _start ); \
128
std::vector<RtToken> aTokens; \
129
std::vector<RtPointer> aValues; \
130
RtInt count = BuildParameterList( pArgs, aTokens, aValues );
132
#define PASS_PARAMETERS \
133
count, aTokens.size()>0?&aTokens[0]:0, aValues.size()>0?&aValues[0]:0
135
//---------------------------------------------------------------------
136
// This file contains the interface functions which are published as the
137
// Renderman Interface SPECification (C) 1988 Pixar.
142
//---------------------------------------------------------------------
143
// Interface parameter token strings.
146
RtToken RI_FRAMEBUFFER = "framebuffer";
147
RtToken RI_FILE = "file";
148
RtToken RI_RGB = "rgb";
149
RtToken RI_RGBA = "rgba";
150
RtToken RI_RGBZ = "rgbz";
151
RtToken RI_RGBAZ = "rgbaz";
154
RtToken RI_AZ = "az";
155
RtToken RI_MERGE = "merge";
156
RtToken RI_ORIGIN = "origin";
157
RtToken RI_PERSPECTIVE = "perspective";
158
RtToken RI_ORTHOGRAPHIC = "orthographic";
159
RtToken RI_HIDDEN = "hidden";
160
RtToken RI_PAINT = "paint";
161
RtToken RI_CONSTANT = "constant";
162
RtToken RI_SMOOTH = "smooth";
163
RtToken RI_FLATNESS = "flatness";
164
RtToken RI_FOV = "fov";
166
RtToken RI_AMBIENTLIGHT = "ambientlight";
167
RtToken RI_POINTLIGHT = "pointlight";
168
RtToken RI_DISTANTLIGHT = "distantlight";
169
RtToken RI_SPOTLIGHT = "spotlight";
170
RtToken RI_INTENSITY = "intensity";
171
RtToken RI_LIGHTCOLOR = "lightcolor";
172
RtToken RI_FROM = "from";
173
RtToken RI_TO = "to";
174
RtToken RI_CONEANGLE = "coneangle";
175
RtToken RI_CONEDELTAANGLE = "conedeltaangle";
176
RtToken RI_BEAMDISTRIBUTION = "beamdistribution";
177
RtToken RI_MATTE = "matte";
178
RtToken RI_METAL = "metal";
179
RtToken RI_PLASTIC = "plastic";
180
RtToken RI_PAINTEDPLASTIC = "paintedplastic";
181
RtToken RI_KA = "ka";
182
RtToken RI_KD = "kd";
183
RtToken RI_KS = "ks";
184
RtToken RI_ROUGHNESS = "roughness";
185
RtToken RI_SPECULARCOLOR = "specularcolor";
186
RtToken RI_DEPTHCUE = "depthcue";
187
RtToken RI_FOG = "fog";
188
RtToken RI_BUMPY = "bumpy";
189
RtToken RI_MINDISTANCE = "mindistance";
190
RtToken RI_MAXDISTANCE = "maxdistance";
191
RtToken RI_BACKGROUND = "background";
192
RtToken RI_DISTANCE = "distance";
194
RtToken RI_RASTER = "raster";
195
RtToken RI_SCREEN = "screen";
196
RtToken RI_CAMERA = "camera";
197
RtToken RI_WORLD = "world";
198
RtToken RI_OBJECT = "object";
199
RtToken RI_INSIDE = "inside";
200
RtToken RI_OUTSIDE = "outside";
201
RtToken RI_LH = "lh";
202
RtToken RI_RH = "rh";
204
RtToken RI_PZ = "Pz";
205
RtToken RI_PW = "Pw";
207
RtToken RI_NP = "Np";
208
RtToken RI_CS = "Cs";
209
RtToken RI_OS = "Os";
212
RtToken RI_ST = "st";
213
RtToken RI_BILINEAR = "bilinear";
214
RtToken RI_BICUBIC = "bicubic";
215
RtToken RI_CUBIC = "cubic";
216
RtToken RI_LINEAR = "linear";
217
RtToken RI_PRIMITIVE = "primitive";
218
RtToken RI_INTERSECTION = "intersection";
219
RtToken RI_UNION = "union";
220
RtToken RI_DIFFERENCE = "difference";
221
RtToken RI_WRAP = "wrap";
222
RtToken RI_NOWRAP = "nowrap";
223
RtToken RI_PERIODIC = "periodic";
224
RtToken RI_NONPERIODIC = "nonperiodic";
225
RtToken RI_CLAMP = "clamp";
226
RtToken RI_BLACK = "black";
227
RtToken RI_IGNORE = "ignore";
228
RtToken RI_PRINT = "print";
229
RtToken RI_ABORT = "abort";
230
RtToken RI_HANDLER = "handler";
231
RtToken RI_IDENTIFIER = "identifier";
232
RtToken RI_NAME = "name";
233
RtToken RI_CURRENT = "current";
234
RtToken RI_SHADER = "shader";
235
RtToken RI_EYE = "eye";
236
RtToken RI_NDC = "ndc";
237
RtToken RI_AMPLITUDE = "amplitude";
238
RtToken RI_COMMENT = "comment";
239
RtToken RI_CONSTANTWIDTH = "constantwidth";
240
RtToken RI_KR = "kr";
241
RtToken RI_SHINYMETAL = "shinymetal";
242
RtToken RI_STRUCTURE = "structure";
243
RtToken RI_TEXTURENAME = "texturename";
244
RtToken RI_VERBATIM = "verbatim";
245
RtToken RI_WIDTH = "width";
247
RtBasis RiBezierBasis = {{ -1.0f, 3.0f, -3.0f, 1.0f},
248
{ 3.0f, -6.0f, 3.0f, 0.0f},
249
{ -3.0f, 3.0f, 0.0f, 0.0f},
250
{ 1.0f, 0.0f, 0.0f, 0.0f}};
251
RtBasis RiBSplineBasis = {{ -1.0f/6.0f, 0.5f, -0.5f, 1.0f/6.0f},
252
{ 0.5f, -1.0f, 0.5f, 0.0f},
253
{ -0.5f, 0.0f, 0.5f, 0.0f},
254
{ 1.0f/6.0f, 2.0f/3.0f, 1.0f/6.0f, 0.0f}};
255
RtBasis RiCatmullRomBasis={{ -0.5f, 1.5f, -1.5f, 0.5f},
256
{ 1.0f, -2.5f, 2.0f, -0.5f},
257
{ -0.5f, 0.0f, 0.5f, 0.0f},
258
{ 0.0f, 1.0f, 0.0f, 0.0f}};
259
RtBasis RiHermiteBasis = {{ 2.0f, 1.0f, -2.0f, 1.0f},
260
{ -3.0f, -2.0f, 3.0f, -1.0f},
261
{ 0.0f, 1.0f, 0.0f, 0.0f},
262
{ 1.0f, 0.0f, 0.0f, 0.0f}};
263
RtBasis RiPowerBasis = {{ 1.0f, 0.0f, 0.0f, 0.0f},
264
{ 0.0f, 1.0f, 0.0f, 0.0f},
265
{ 0.0f, 0.0f, 1.0f, 0.0f},
266
{ 0.0f, 0.0f, 0.0f, 1.0f}};
280
static TqUlong RIH_S = CqString::hash( RI_S );
281
static TqUlong RIH_T = CqString::hash( RI_T );
282
static TqUlong RIH_ST = CqString::hash( RI_ST );
283
static TqUlong RIH_CS = CqString::hash( RI_CS );
284
static TqUlong RIH_OS = CqString::hash( RI_OS );
285
static TqUlong RIH_P = CqString::hash( RI_P );
286
static TqUlong RIH_PZ = CqString::hash( RI_PZ );
287
static TqUlong RIH_PW = CqString::hash( RI_PW );
288
static TqUlong RIH_N = CqString::hash( RI_N );
289
static TqUlong RIH_NP = CqString::hash( RI_NP );
290
static TqUlong RIH_DEPTHFILTER = CqString::hash( "depthfilter" );
291
static TqUlong RIH_JITTER = CqString::hash( "jitter" );
292
static TqUlong RIH_RENDER = CqString::hash( "render" );
293
static TqUlong RIH_INDIRECT = CqString::hash( "indirect" );
294
static TqUlong RIH_LIGHT = CqString::hash( "light" );
295
static TqUlong RIH_VISIBILITY = CqString::hash( "visibility" );
297
RtInt RiLastError = 0;
299
//----------------------------------------------------------------------
301
// Helper function to build a GPrim from any boost::shared_ptr<> type..
304
RtVoid CreateGPrim( const boost::shared_ptr<T>& pSurface )
306
CreateGPrim( boost::static_pointer_cast<CqSurface,T>( pSurface ) );
309
//----------------------------------------------------------------------
310
// BuildParameterList
311
// Helper function to build a parameter list to pass on to the V style functions.
312
// returns a parameter count.
314
RtInt BuildParameterList( va_list pArgs, std::vector<RtToken>& aTokens, std::vector<RtPointer>& aValues )
317
RtToken pToken = va_arg( pArgs, RtToken );
321
while ( pToken != 0 && pToken != RI_NULL ) // While not RI_NULL
323
aTokens.push_back( pToken );
324
pValue = va_arg( pArgs, RtPointer );
325
aValues.push_back( pValue );
326
pToken = va_arg( pArgs, RtToken );
333
//----------------------------------------------------------------------
334
// CqRangeCheckCallback implentation
335
// Use this with CheckMinMax
337
class CqLogRangeCheckCallback : public CqRangeCheckCallback
340
CqLogRangeCheckCallback()
343
virtual ~CqLogRangeCheckCallback()
353
virtual void operator()( int res )
357
case CqRangeCheckCallback::UPPER_BOUND_HIT:
359
Aqsis::log() << error << "Invalid Value for " << m_name << ". Value exceeded upper limit" << std::endl;
362
case CqRangeCheckCallback::LOWER_BOUND_HIT:
364
Aqsis::log() << error << "Invalid Value for " << m_name << ". Value exceeded lower limit" << std::endl;
378
//----------------------------------------------------------------------
380
// Check that the currect graphics state is one of those specified.
382
TqBool ValidateState(int count, ... )
385
va_start( pArgs, count );
387
int currentState = Outside;
388
if( QGetRenderContext() != NULL && QGetRenderContext()->pconCurrent() )
389
currentState = QGetRenderContext()->pconCurrent()->Type();
392
for(i=0; i<count; i++)
394
int state = va_arg( pArgs, int );
395
if( currentState == state )
402
//----------------------------------------------------------------------
404
// Get a string representing the current state.
406
const char* GetStateAsString()
408
int currentState = Outside;
409
if( QGetRenderContext()->pconCurrent() )
410
currentState = QGetRenderContext()->pconCurrent()->Type();
411
switch( currentState )
453
//----------------------------------------------------------------------
455
// Declare a new variable to be recognised by the system.
457
RtToken RiDeclare( RtString name, RtString declaration )
459
VALIDATE_CONDITIONAL0
467
CqString strName( name ), strDecl( declaration );
468
QGetRenderContext() ->AddParameterDecl( strName.c_str(), strDecl.c_str() );
473
//----------------------------------------------------------------------
474
// SetDefaultRiOptions
475
// Set some Default Options.
477
void SetDefaultRiOptions( void )
479
std::string systemRCPath;
480
std::string homeRCPath;
481
std::string currentRCPath;
482
std::string rootPath;
483
std::string separator;
485
#ifdef AQSIS_SYSTEM_WIN32
489
if( GetModuleFileName( NULL, acPath, 256 ) != 0)
491
// guaranteed file name of at least one character after path
492
*( strrchr( acPath, '\\' ) ) = '\0';
493
std::string stracPath(acPath);
494
_fullpath(root,&stracPath[0],256);
498
#elif AQSIS_SYSTEM_MACOSX
500
CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
501
CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle);
502
const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
506
// Minty: Need to work out the executable path here.
507
rootPath = DEFAULT_RC_PATH;
511
systemRCPath = rootPath;
512
systemRCPath.append( separator );
513
systemRCPath.append( "aqsisrc" );
515
// Read in the system configuration file if found.
516
FILE* rcfile = fopen( systemRCPath.c_str(), "rb" );
519
Aqsis::log() << info << "Reading system config \"" << systemRCPath.c_str() << "\"" << std::endl;
520
CqRIBParserState currstate = librib::GetParserState();
521
if (currstate.m_pParseCallbackInterface == NULL)
522
currstate.m_pParseCallbackInterface = new librib2ri::Engine;
523
librib::Parse( rcfile, "System Config", *(currstate.m_pParseCallbackInterface), *(currstate.m_pParseErrorStream), NULL );
524
librib::SetParserState( currstate );
529
Aqsis::log() << error << "Could not open system config (" << systemRCPath.c_str() << ")" << std::endl;
532
/* ...then read the .aqsisrc files in $HOME... */
535
homeRCPath = getenv("HOME");
536
if (homeRCPath[ homeRCPath.length() ] != separator[0])
538
homeRCPath.append(separator);
540
homeRCPath.append(".aqsisrc");
541
rcfile = fopen( homeRCPath.c_str(), "rb" );
544
Aqsis::log() << info << "Reading user config \"" << homeRCPath.c_str() << "\"" << std::endl;
545
CqRIBParserState currstate = librib::GetParserState();
546
if (currstate.m_pParseCallbackInterface == NULL)
547
currstate.m_pParseCallbackInterface = new librib2ri::Engine;
548
librib::Parse( rcfile, "Home Config", *(currstate.m_pParseCallbackInterface), *(currstate.m_pParseErrorStream), NULL );
549
librib::SetParserState( currstate );
554
Aqsis::log() << info << "Could not open user config (" << homeRCPath.c_str() << ")" << std::endl;
559
Aqsis::log() << info << "Environment variable HOME not set (skipping user config)." << std::endl;
562
/* ...and the current directory... */
563
currentRCPath = ".aqsisrc";
564
rcfile = fopen( currentRCPath.c_str(), "rb" );
567
Aqsis::log() << info << "Reading project config \"" << currentRCPath.c_str() << "\"" << std::endl;
568
CqRIBParserState currstate = librib::GetParserState();
569
if (currstate.m_pParseCallbackInterface == NULL)
570
currstate.m_pParseCallbackInterface = new librib2ri::Engine;
571
librib::Parse( rcfile, "Current Config", *(currstate.m_pParseCallbackInterface), *(currstate.m_pParseErrorStream), NULL );
572
librib::SetParserState( currstate );
577
Aqsis::log() << info << "Could not open project config (" << currentRCPath.c_str() << ")" << std::endl;
580
const char* popt[ 1 ];
581
if(getenv("AQSIS_SHADER_PATH"))
583
popt[0] = getenv("AQSIS_SHADER_PATH");
584
Aqsis::log() << info << "Applying AQSIS_SHADER_PATH (" << popt[0] << ")" << std::endl;
585
RiOption( "searchpath", "shader", &popt, RI_NULL );
589
Aqsis::log() << info << "AQSIS_SHADER_PATH not set" << std::endl;
592
if(getenv("AQSIS_ARCHIVE_PATH"))
594
popt[0] = getenv("AQSIS_ARCHIVE_PATH");
595
Aqsis::log() << info << "Applying AQSIS_ARCHIVE_PATH (" << popt[0] << ")" << std::endl;
596
RiOption( "searchpath", "archive", &popt, RI_NULL );
600
Aqsis::log() << info << "AQSIS_ARCHIVE_PATH not set" << std::endl;
603
if(getenv("AQSIS_TEXTURE_PATH"))
605
popt[0] = getenv("AQSIS_TEXTURE_PATH");
606
Aqsis::log() << info << "Applying AQSIS_TEXTURE_PATH (" << popt[0] << ")" << std::endl;
607
RiOption( "searchpath", "texture", &popt, RI_NULL );
611
Aqsis::log() << info << "AQSIS_TEXTURE_PATH not set" << std::endl;
614
if(getenv("AQSIS_DISPLAY_PATH"))
616
popt[0] = getenv("AQSIS_DISPLAY_PATH");
617
Aqsis::log() << info << "Applying AQSIS_DISPLAY_PATH (" << popt[0] << ")" << std::endl;
618
RiOption( "searchpath", "display", &popt, RI_NULL );
622
Aqsis::log() << info << "AQSIS_DISPLAY_PATH not set" << std::endl;
625
if(getenv("AQSIS_PROCEDURAL_PATH"))
627
popt[0] = getenv("AQSIS_PROCEDURAL_PATH");
628
Aqsis::log() << info << "Applying AQSIS_PROCEDURAL_PATH (" << popt[0] << ")" << std::endl;
629
RiOption( "searchpath", "procedural", &popt, RI_NULL );
633
Aqsis::log() << info << "AQSIS_PROCEDURAL_PATH not set" << std::endl;
636
if(getenv("AQSIS_PLUGIN_PATH"))
638
popt[0] = getenv("AQSIS_PLUGIN_PATH");
639
Aqsis::log() << info << "Applying AQSIS_PLUGIN_PATH (" << popt[0] << ")" << std::endl;
640
RiOption( "searchpath", "plugin", &popt, RI_NULL );
644
Aqsis::log() << info << "AQSIS_PLUGIN_PATH not set" << std::endl;
647
// Setup a default Display
648
Aqsis::log() << info << "Setting up default display: Display \"ri.pic\" \"file\" \"rgba\"" << std::endl;
649
RiDisplay( "ri.pic", "file", "rgba", NULL );
652
//----------------------------------------------------------------------
654
// Begin a Renderman render phase.
656
extern "C" char *StandardParameters[][2];
657
RtVoid RiBegin( RtToken name )
663
// Create a new renderer
664
QSetRenderContext( new CqRenderer );
666
QGetRenderContext() ->Initialise();
667
QGetRenderContext() ->BeginMainModeBlock();
668
QGetRenderContext() ->ptransSetTime( CqMatrix() );
669
QGetRenderContext() ->SetCameraTransform( QGetRenderContext() ->ptransCurrent() );
670
// Clear the lightsources stack.
671
Lightsource_stack.clear();
673
// Include the standard options (how can we opt out of this).
675
while( StandardParameters[param][0] != NULL )
678
StandardParameters[param][0],
679
StandardParameters[param][1]
684
SetDefaultRiOptions();
686
// Setup a default surface shader
687
boost::shared_ptr<IqShader> pDefaultSurfaceShader =
688
QGetRenderContext()->getDefaultSurfaceShader();
689
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pDefaultSurfaceShader, QGetRenderContext() ->Time() );
691
// Setup the initial transformation.
692
// QGetRenderContext()->ptransWriteCurrent() ->SetHandedness( TqFalse );
693
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
698
//----------------------------------------------------------------------
700
// End the rendermam render stage.
708
QGetRenderContext() ->EndMainModeBlock();
710
// Flush the image cache.
711
CqTextureMap::FlushCache();
713
// Clear the lightsources stack.
714
Lightsource_stack.clear();
716
// Delete the renderer
717
delete( QGetRenderContext() );
718
QSetRenderContext( 0 );
724
//----------------------------------------------------------------------
726
// Begin an individual frame, options are saved at this point.
728
RtVoid RiFrameBegin( RtInt number )
734
VALIDATE_RIFRAMEBEGIN
738
// Initialise the statistics variables. If the RIB doesn't contain
739
// a Frame-block the initialisation was previously done in CqStats::Initilise()
740
// which has to be called before a rendering session.
741
QGetRenderContext() ->Stats().InitialiseFrame();
742
// Start the timer. Note: The corresponding call of StopFrameTimer() is
743
// done in WorldEnd (!) not FrameEnd since it can happen that there is
744
// not FrameEnd (and usually there's not much between WorldEnd and FrameEnd).
745
//QGetRenderContext() ->Stats().StartFrameTimer();
748
QGetRenderContext() ->BeginFrameModeBlock();
749
QGetRenderContext() ->SetCurrentFrame( number );
750
CqCSGTreeNode::SetRequired( TqFalse );
752
QGetRenderContext() ->Stats().InitialiseFrame();
754
QGetRenderContext()->clippingVolume().clear();
757
worldrand.Reseed('a'+'q'+'s'+'i'+'s');
763
//----------------------------------------------------------------------
765
// End the rendering of an individual frame, options are restored.
777
QGetRenderContext() ->EndFrameModeBlock();
778
QGetRenderContext() ->ClearDisplayRequests();
783
//----------------------------------------------------------------------
785
// Start the information for the world, options are now frozen. The world-to-camera
786
// transformation is set to the current transformation, and current is set to identity.
788
RtVoid RiWorldBegin()
794
VALIDATE_RIWORLDBEGIN
798
// Call any specified pre world function.
799
if ( QGetRenderContext()->pPreWorldFunction() != NULL )
800
( *QGetRenderContext()->pPreWorldFunction() ) ();
802
// Start the frame timer (just in case there was no FrameBegin block. If there
803
// was, nothing happens)
804
//QGetRenderContext() ->Stats().StartFrameTimer();
808
// Now that the options have all been set, setup any undefined camera parameters.
809
const TqInt* pCameraOpts = QGetRenderContext()->poptCurrent()->GetIntegerOption("System", "CameraFlags");
810
TqInt cameraOpts = 0;
811
if(pCameraOpts != NULL)
812
cameraOpts = pCameraOpts[0];
813
if ( (cameraOpts & CameraFARSet) == 0 )
815
// Derive the FAR from the resolution and pixel aspect ratio.
816
RtFloat PAR = QGetRenderContext() ->poptCurrent()->GetFloatOption( "System", "PixelAspectRatio" ) [ 0 ];
817
RtFloat resH = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "System", "Resolution" ) [ 0 ];
818
RtFloat resV = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "System", "Resolution" ) [ 1 ];
819
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = ( resH * PAR ) / resV ;
822
if ( ( cameraOpts & CameraScreenWindowSet) == 0 )
824
RtFloat fFAR = QGetRenderContext() ->poptCurrent()->GetFloatOption( "System", "FrameAspectRatio" ) [ 0 ];
828
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = -fFAR ;
829
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = + fFAR ;
830
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = + 1 ;
831
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = -1 ;
835
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = -1 ;
836
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = + 1 ;
837
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = + 1.0 / fFAR ;
838
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = -1.0 / fFAR ;
842
// Set the world to camera transformation matrix to the current matrix.
844
CqTransformPtr current( QGetRenderContext() ->ptransCurrent() );
845
QGetRenderContext() ->SetCameraTransform( current );
846
QGetRenderContext() ->BeginWorldModeBlock();
847
// Reset the current transformation to identity, this now represents the object-->world transform.
848
QGetRenderContext() ->ptransSetTime( CqMatrix() );
850
// Store the initial object transformation
851
CqTransformPtr newTrans( new CqTransform() );
852
QGetRenderContext()->SetDefObjTransform( newTrans );
854
// If rendering a depth buffer, check that the filter is "box" 1x1, warn if not.
855
TqInt iMode = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "System", "DisplayMode" ) [ 0 ];
858
RtFilterFunc filter = QGetRenderContext() ->poptCurrent()->funcFilter();
859
TqFloat xwidth = QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FilterWidth" ) [ 0 ];
860
TqFloat ywidth = QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FilterWidth" ) [ 1 ];
861
if( filter != RiBoxFilter || xwidth != 1 || ywidth != 1)
862
Aqsis::log() << warning << "When rendering a Z buffer the filter mode should be \"box\" with a width of 1x1" << std::endl;
867
QGetRenderContext()->SetWorldBegin();
869
// Ensure that the camera and projection matrices are initialised.
870
// This is also done in CqRenderer::RenderWorld, but needs to be
871
// done here also in case we're not running in 'multipass' mode, in
872
// which case the primitives all 'fast track' into the pipeline and
873
// therefore rely on information setup here.
874
QGetRenderContext()->poptWriteCurrent()->InitialiseCamera();
875
QGetRenderContext()->pImage()->SetImage();
877
worldrand.Reseed('a'+'q'+'s'+'i'+'s');
883
//----------------------------------------------------------------------
885
// End the specifying of world data, options are released.
898
QGetRenderContext()->RenderAutoShadows();
900
TqBool fFailed = TqFalse;
901
// Call any specified pre render function.
902
if ( QGetRenderContext()->pPreRenderFunction() != NULL )
903
( *QGetRenderContext()->pPreRenderFunction() ) ();
905
// Stop the parsing counter
909
QGetRenderContext() -> Stats().PrintInfo();
911
const TqInt* poptGridSize = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "limits", "gridsize" );
912
if( NULL != poptGridSize )
913
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "SqrtGridSize" )[0] = sqrt( static_cast<float>(poptGridSize[0]) );
915
// Finalise the raytracer database now that all primitives are in.
916
if(QGetRenderContext()->pRaytracer())
917
QGetRenderContext()->pRaytracer()->Finalise();
922
QGetRenderContext() ->RenderWorld();
924
catch ( CqString strError )
926
Aqsis::log() << error << strError.c_str() << std::endl;
930
// Delete the world context
931
QGetRenderContext() ->EndWorldModeBlock();
933
// Stop the frame timer
934
//QGetRenderContext() ->Stats().StopFrameTimer();
939
// Get the verbosity level from the options...
941
const TqInt* poptEndofframe = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "statistics", "endofframe" );
942
if ( poptEndofframe != 0 )
943
verbosity = poptEndofframe[ 0 ];
945
// ...and print the statistics.
946
QGetRenderContext() ->Stats().PrintStats( verbosity );
949
QGetRenderContext()->SetWorldBegin(TqFalse);
955
//----------------------------------------------------------------------
957
// Specify the setup of the final image.
959
RtVoid RiFormat( RtInt xresolution, RtInt yresolution, RtFloat pixelaspectratio )
969
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "Resolution" ) [ 0 ] = xresolution ;
970
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "Resolution" ) [ 1 ] = yresolution ;
971
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "PixelAspectRatio" ) [ 0 ] = ( pixelaspectratio < 0.0 ) ? 1.0 : pixelaspectratio ;
977
//----------------------------------------------------------------------
978
// RiFrameAspectRatio
979
// Set the aspect ratio of the frame irrespective of the display setup.
981
RtVoid RiFrameAspectRatio( RtFloat frameratio )
985
CACHE_RIFRAMEASPECTRATIO
987
VALIDATE_RIFRAMEASPECTRATIO
989
DEBUG_RIFRAMEASPECTRATIO
991
CqLogRangeCheckCallback rc;
995
rc.set( "frameratio");
996
if( !CheckMinMax( frameratio, 0.0f, RI_INFINITY, &rc ) )
1003
Aqsis::log() << error << "RiFrameAspectRatio: Invalid RiFrameAspectRatio, aborting" << std::endl;
1007
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = frameratio ;
1009
// Inform the system that RiFrameAspectRatio has been called, as this takes priority.
1010
QGetRenderContext()->poptWriteCurrent()->GetIntegerOptionWrite("System", "CameraFlags")[0] |= CameraFARSet;
1016
//----------------------------------------------------------------------
1018
// Set the resolution of the screen window in the image plane specified in the screen
1019
// coordinate system.
1021
RtVoid RiScreenWindow( RtFloat left, RtFloat right, RtFloat bottom, RtFloat top )
1023
VALIDATE_CONDITIONAL
1025
CACHE_RISCREENWINDOW
1027
VALIDATE_RISCREENWINDOW
1029
DEBUG_RISCREENWINDOW
1031
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = left ;
1032
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = right ;
1033
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = top ;
1034
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = bottom ;
1036
// Inform the system that RiScreenWindow has been called, as this takes priority.
1037
QGetRenderContext()->poptWriteCurrent()->GetIntegerOptionWrite("System", "CameraFlags")[0] |= CameraScreenWindowSet;
1043
//----------------------------------------------------------------------
1045
// Set the position and size of the crop window specified in fractions of the raster
1048
RtVoid RiCropWindow( RtFloat left, RtFloat right, RtFloat top, RtFloat bottom )
1050
VALIDATE_CONDITIONAL
1054
VALIDATE_RICROPWINDOW
1058
CqLogRangeCheckCallback rc;
1063
if( !CheckMinMax( left, 0.0f, 1.0f, &rc ) )
1069
if( !CheckMinMax( right, 0.0f, 1.0f, &rc ) )
1075
if( !CheckMinMax( top, 0.0f, 1.0f, &rc ) )
1081
if( !CheckMinMax( bottom, 0.0f, 1.0f, &rc ) )
1098
Aqsis::log() << error << "Invalid RiCropWindow, ignoring" << std::endl;
1102
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "CropWindow" ) [ 0 ] = left ;
1103
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "CropWindow" ) [ 1 ] = right ;
1104
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "CropWindow" ) [ 2 ] = top ;
1105
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "CropWindow" ) [ 3 ] = bottom ;
1111
//----------------------------------------------------------------------
1113
// Set the camera projection to be used.
1115
RtVoid RiProjection( RtToken name, ... )
1117
EXTRACT_PARAMETERS( name )
1119
RiProjectionV( name, PASS_PARAMETERS );
1123
//----------------------------------------------------------------------
1125
// List mode version of above.
1127
RtVoid RiProjectionV( RtToken name, PARAMETERLIST )
1129
VALIDATE_CONDITIONAL
1133
VALIDATE_RIPROJECTION
1137
if ( strcmp( name, RI_PERSPECTIVE ) == 0 )
1138
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "Projection" ) [ 0 ] = ProjectionPerspective ;
1139
else if ( strcmp( name, RI_ORTHOGRAPHIC ) == 0 )
1140
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "Projection" ) [ 0 ] = ProjectionOrthographic ;
1141
else if( name != RI_NULL )
1143
Aqsis::log() << error << "RiProjection: Invalid projection: \"" << name << "\"" << std::endl;
1148
for ( i = 0; i < count; ++i )
1150
RtToken token = tokens[ i ];
1151
RtPointer value = values[ i ];
1153
if ( strcmp( token, RI_FOV ) == 0 )
1154
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FOV" ) [ 0 ] = *( reinterpret_cast<RtFloat*>( value ) ) ;
1156
// TODO: need to get the current transformation so that it can be added to the screen transformation.
1157
QGetRenderContext() ->ptransSetTime( CqMatrix() );
1163
//----------------------------------------------------------------------
1165
// Set the near and far clipping planes specified as distances from the camera.
1167
RtVoid RiClipping( RtFloat cnear, RtFloat cfar )
1169
VALIDATE_CONDITIONAL
1177
CqLogRangeCheckCallback rc;
1182
if( !CheckMinMax( cnear, RI_EPSILON, cfar, &rc ) )
1188
if( !CheckMinMax( cfar, cnear, RI_INFINITY, &rc ) )
1195
Aqsis::log() << error << "RiClipping: Invalid RiClipping, clipping planes set to RI_EPSILON, RI_INFINITY" << std::endl;
1200
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Clipping" ) [ 0 ] = cnear ;
1201
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Clipping" ) [ 1 ] = cfar ;
1207
//----------------------------------------------------------------------
1209
// Specify the parameters which affect focal blur of the camera.
1211
RtVoid RiDepthOfField( RtFloat fstop, RtFloat focallength, RtFloat focaldistance )
1213
VALIDATE_CONDITIONAL
1215
CACHE_RIDEPTHOFFIELD
1217
VALIDATE_RIDEPTHOFFIELD
1219
DEBUG_RIDEPTHOFFIELD
1221
CqLogRangeCheckCallback rc;
1226
if( !CheckMinMax( fstop, 0.0f, RI_INFINITY, &rc ) )
1231
rc.set( "focallength" );
1232
if( !CheckMinMax( focallength, 0.0f, RI_INFINITY, &rc ) )
1237
rc.set( "focaldistance" );
1238
if( !CheckMinMax( focaldistance, 0.0f, RI_INFINITY, &rc ) )
1245
Aqsis::log() << warning << "RiDepthOfField: Invalid DepthOfField, DepthOfField ignored" << std::endl;
1249
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "DepthOfField" ) [ 0 ] = fstop ;
1250
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "DepthOfField" ) [ 1 ] = focallength ;
1251
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "DepthOfField" ) [ 2 ] = focaldistance ;
1253
QGetRenderContext() ->SetDepthOfFieldData( fstop, focallength, focaldistance );
1257
//----------------------------------------------------------------------
1259
// Set the times at which the shutter opens and closes, used for motion blur.
1261
RtVoid RiShutter( RtFloat opentime, RtFloat closetime )
1263
VALIDATE_CONDITIONAL
1271
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Shutter" ) [ 0 ] = opentime;
1272
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Shutter" ) [ 1 ] = closetime;
1278
//----------------------------------------------------------------------
1280
// Set the upper bound on the variance from the true pixel color by the pixel filter
1283
RtVoid RiPixelVariance( RtFloat variance )
1285
VALIDATE_CONDITIONAL
1287
CACHE_RIPIXELVARIANCE
1289
VALIDATE_RIPIXELVARIANCE
1291
DEBUG_RIPIXELVARIANCE
1293
CqLogRangeCheckCallback rc;
1297
rc.set( "variance" );
1298
if( !CheckMinMax( variance, 0.0f, RI_INFINITY, &rc ) )
1305
Aqsis::log() << warning << "RiPixelVariance: Invalid PixelVariance, PixelVariance set to 0" << std::endl;
1309
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "PixelVariance" ) [ 0 ] = variance ;
1315
//----------------------------------------------------------------------
1317
// Set the number of samples per pixel for the hidden surface function.
1319
RtVoid RiPixelSamples( RtFloat xsamples, RtFloat ysamples )
1321
VALIDATE_CONDITIONAL
1323
CACHE_RIPIXELSAMPLES
1325
VALIDATE_RIPIXELSAMPLES
1327
DEBUG_RIPIXELSAMPLES
1329
CqLogRangeCheckCallback rc;
1333
rc.set( "xsamples" );
1334
if( !CheckMinMax( xsamples, 1.0f, RI_INFINITY, &rc ) )
1339
rc.set( "ysamples" );
1340
if( !CheckMinMax( ysamples, 1.0f, RI_INFINITY, &rc ) )
1347
Aqsis::log() << warning << "RiPixelSamples: Invalid PixelSamples, PixelSamples set to 1, 1" << std::endl;
1352
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "PixelSamples" ) [ 0 ] = static_cast<TqInt>( xsamples ) ;
1353
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "PixelSamples" ) [ 1 ] = static_cast<TqInt>( ysamples ) ;
1359
//----------------------------------------------------------------------
1361
// Set the function used to generate a final pixel value from supersampled values.
1363
RtVoid RiPixelFilter( RtFilterFunc function, RtFloat xwidth, RtFloat ywidth )
1365
VALIDATE_CONDITIONAL
1369
VALIDATE_RIPIXELFILTER
1373
QGetRenderContext() ->poptWriteCurrent()->SetfuncFilter( function );
1374
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FilterWidth" ) [ 0 ] = xwidth ;
1375
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FilterWidth" ) [ 1 ] = ywidth ;
1381
//----------------------------------------------------------------------
1383
// Set the values of the exposure color modification function.
1385
RtVoid RiExposure( RtFloat gain, RtFloat gamma )
1387
VALIDATE_CONDITIONAL
1395
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Exposure" ) [ 0 ] = gain ;
1396
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Exposure" ) [ 1 ] = gamma ;
1402
//----------------------------------------------------------------------
1404
// Specify a prepocessing imager shader.
1406
RtVoid RiImager( RtToken name, ... )
1408
EXTRACT_PARAMETERS( name )
1410
RiImagerV( name, PASS_PARAMETERS );
1414
//----------------------------------------------------------------------
1416
// List based version of above.
1418
RtVoid RiImagerV( RtToken name, PARAMETERLIST )
1420
VALIDATE_CONDITIONAL
1429
boost::shared_ptr<IqShader> pshadImager = QGetRenderContext()->CreateShader( name, Type_Imager );
1433
QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "Imager" ) [ 0 ] = name ;
1434
QGetRenderContext()->poptWriteCurrent()->SetpshadImager( pshadImager );
1436
for ( i = 0; i < count; ++i )
1438
RtToken token = tokens[ i ];
1439
RtPointer value = values[ i ];
1441
SetShaderArgument( pshadImager, token, static_cast<TqPchar>( value ) );
1448
//----------------------------------------------------------------------
1450
// Specify the color quantization parameters.
1452
RtVoid RiQuantize( RtToken type, RtInt one, RtInt min, RtInt max, RtFloat ditheramplitude )
1454
VALIDATE_CONDITIONAL
1462
if ( strcmp( type, "rgba" ) == 0 )
1464
TqFloat* pColorQuantize = QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "Quantize", "Color" );
1465
pColorQuantize [ 0 ] = static_cast<TqFloat>( one );
1466
pColorQuantize [ 1 ] = static_cast<TqFloat>( min );
1467
pColorQuantize [ 2 ] = static_cast<TqFloat>( max );
1468
pColorQuantize [ 3 ] = static_cast<TqFloat>( ditheramplitude );
1470
else if ( strcmp( type, "z" ) == 0 )
1472
TqFloat* pDepthQuantize = QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "Quantize", "Depth" );
1473
pDepthQuantize [ 0 ] = static_cast<TqFloat>( one );
1474
pDepthQuantize [ 1 ] = static_cast<TqFloat>( min );
1475
pDepthQuantize [ 2 ] = static_cast<TqFloat>( max );
1476
pDepthQuantize [ 3 ] = static_cast<TqFloat>( ditheramplitude );
1480
TqFloat* quantOpt = QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite("Quantize", type, 4);
1481
quantOpt[0] = static_cast<TqFloat>( one );
1482
quantOpt[1] = static_cast<TqFloat>( min );
1483
quantOpt[2] = static_cast<TqFloat>( max );
1484
quantOpt[3] = static_cast<TqFloat>( ditheramplitude );
1491
//----------------------------------------------------------------------
1493
// Set the final output name and type.
1495
RtVoid RiDisplay( RtToken name, RtToken type, RtToken mode, ... )
1497
EXTRACT_PARAMETERS( mode )
1499
RiDisplayV( name, type, mode, PASS_PARAMETERS );
1503
//----------------------------------------------------------------------
1505
// List based version of above.
1507
RtVoid RiDisplayV( RtToken name, RtToken type, RtToken mode, PARAMETERLIST )
1509
VALIDATE_CONDITIONAL
1517
CqString strName( name );
1518
CqString strType( type );
1520
QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "DisplayName" ) [ 0 ] = strName.c_str() ;
1521
QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "DisplayType" ) [ 0 ] = strType.c_str() ;
1523
// Append the display mode to the current setting.
1526
TqInt dataOffset = 0;
1528
if ( strncmp( mode, RI_RGB, strlen(RI_RGB) ) == 0 )
1532
index += strlen( RI_RGB );
1534
if ( strncmp( &mode[index], RI_A, strlen( RI_A ) ) == 0 )
1538
index += strlen( RI_A );
1540
if ( strncmp( &mode[index], RI_Z, strlen( RI_Z ) ) == 0 )
1544
index += strlen( RI_Z );
1547
// Special case test.
1548
if(strncmp(&mode[index], "depth", strlen("depth") ) == 0 )
1554
// If none of the standard "rgbaz" strings match, then it is an alternative 'arbitrary output variable'
1555
else if( eValue == 0 )
1557
dataOffset = QGetRenderContext()->RegisterOutputData( mode );
1558
dataSize = QGetRenderContext()->OutputDataSamples( mode );
1561
// Check if the display request is valid.
1562
if(dataOffset >= 0 && dataSize >0)
1564
// Gather the additional arguments into a map to pass through to the manager.
1565
std::map<std::string, void*> mapOfArguments;
1567
for( i = 0; i < count; ++i )
1568
mapOfArguments[ tokens[ i ] ] = values[ i ];
1570
// Check if the request is to add a display driver.
1571
if ( strName[ 0 ] == '+' )
1573
TqInt iMode = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "System", "DisplayMode" ) [ 0 ] | eValue;
1574
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = iMode;
1575
strName = strName.substr( 1 );
1579
QGetRenderContext() ->ClearDisplayRequests();
1580
QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = eValue ;
1582
// Add a display driver to the list of requested drivers.
1583
QGetRenderContext() ->AddDisplayRequest( strName.c_str(), strType.c_str(), mode, eValue, dataOffset, dataSize, mapOfArguments );
1588
//----------------------------------------------------------------------
1590
// Specify a hidden surface calculation mode.
1592
RtVoid RiHider( RtToken name, ... )
1594
EXTRACT_PARAMETERS( name )
1596
RiHiderV( name, PASS_PARAMETERS );
1600
//----------------------------------------------------------------------
1602
// List based version of above.
1604
RtVoid RiHiderV( RtToken name, PARAMETERLIST )
1606
VALIDATE_CONDITIONAL
1614
if ( !strcmp( name, "hidden" ) || !strcmp( name, "painter" ) )
1616
QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "Hider" ) [ 0 ] = name ;
1621
for ( i = 0; i < count; ++i )
1623
SqParameterDeclaration Decl;
1626
Decl = QGetRenderContext()->FindParameterDecl( tokens[ i ] );
1628
catch( XqException e )
1630
Aqsis::log() << error << e.strReason().c_str() << std::endl;
1633
TqUlong hash = CqString::hash(Decl.m_strName.c_str());
1634
if ( hash == RIH_DEPTHFILTER )
1635
RiOption( "Hider", "depthfilter", ( RtToken ) values[ i ], NULL );
1636
else if ( hash == RIH_JITTER )
1637
RiOption( "Hider", "jitter", ( RtFloat* ) values[ i ], NULL );
1644
//----------------------------------------------------------------------
1646
// Specify the depth and conversion arrays for color manipulation.
1648
RtVoid RiColorSamples( RtInt N, RtFloat *nRGB, RtFloat *RGBn )
1650
VALIDATE_CONDITIONAL
1652
CACHE_RICOLORSAMPLES
1654
VALIDATE_RICOLORSAMPLES
1656
DEBUG_RICOLORSAMPLES
1658
Aqsis::log() << warning << "RiColorSamples not supported" << std::endl;
1663
//----------------------------------------------------------------------
1665
// Set the scale used for all subsequent level of detail calculations.
1667
RtVoid RiRelativeDetail( RtFloat relativedetail )
1669
VALIDATE_CONDITIONAL
1671
CACHE_RIRELATIVEDETAIL
1673
VALIDATE_RIRELATIVEDETAIL
1675
DEBUG_RIRELATIVEDETAIL
1677
if ( relativedetail < 0.0f )
1679
Aqsis::log() << error << "RiRelativeDetail < 0.0" << std::endl;
1683
QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "RelativeDetail" ) [ 0 ] = relativedetail;
1689
//----------------------------------------------------------------------
1691
// Specify system specific option.
1693
RtVoid RiOption( RtToken name, ... )
1695
EXTRACT_PARAMETERS( name )
1697
RiOptionV( name, PASS_PARAMETERS );
1701
//----------------------------------------------------------------------
1703
// List based version of above.
1705
RtVoid RiOptionV( RtToken name, PARAMETERLIST )
1707
VALIDATE_CONDITIONAL
1716
for ( i = 0; i < count; ++i )
1718
RtToken token = tokens[ i ];
1719
RtPointer value = values[ i ];
1721
// Search for the parameter in the declarations.
1722
// Note Options can only be uniform.
1723
SqParameterDeclaration Decl;
1726
Decl = QGetRenderContext()->FindParameterDecl( token );
1728
catch( XqException e )
1730
Aqsis::log() << error << e.strReason().c_str() << std::endl;
1733
TqInt Type = Decl.m_Type;
1734
TqInt Class = Decl.m_Class;
1735
TqInt Count = Decl.m_Count;
1736
CqString undecoratedName = Decl.m_strName;
1737
if ( Decl.m_strName == "" || Class != class_uniform )
1739
if ( Decl.m_strName == "" )
1740
Aqsis::log() << warning << "Unrecognised declaration : " << token << std::endl;
1742
Aqsis::log() << warning << "Options can only be uniform [" << token << "]" << std::endl;
1750
RtFloat* pf = reinterpret_cast<RtFloat*>( value );
1751
TqFloat* pOpt = QGetRenderContext()->poptWriteCurrent()->GetFloatOptionWrite(name, undecoratedName.c_str(), Count);
1753
for ( j = 0; j < Count; ++j )
1754
pOpt[ j ] = pf[ j ];
1760
RtInt* pi = reinterpret_cast<RtInt*>( value );
1761
TqInt* pOpt = QGetRenderContext()->poptWriteCurrent()->GetIntegerOptionWrite(name, undecoratedName.c_str(), Count);
1763
for ( j = 0; j < Count; ++j )
1764
pOpt[ j ] = pi[ j ];
1770
char** ps = reinterpret_cast<char**>( value );
1771
CqString* pOpt = QGetRenderContext()->poptWriteCurrent()->GetStringOptionWrite(name, undecoratedName.c_str(), Count);
1773
for ( j = 0; j < Count; ++j )
1776
if ( strcmp( name, "searchpath" ) == 0 )
1778
// Get the old value for use in escape replacement
1779
CqString str_old = pOpt[ 0 ];
1780
Aqsis::log() << debug << "Old searchpath = " << str_old.c_str() << std::endl;
1781
// Build the string, checking for & character and replace with old string.
1782
unsigned int strt = 0;
1783
unsigned int len = 0;
1786
if ( ( len = strcspn( &ps[ j ][ strt ], "&" ) ) < strlen( &ps[ j ][ strt ] ) )
1788
str += CqString( ps[ j ] ).substr( strt, len );
1794
str += CqString( ps[ j ] ).substr( strt );
1800
str = CqString( ps[ j ] );
1809
RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1810
CqColor* pOpt = QGetRenderContext()->poptWriteCurrent()->GetColorOptionWrite(name, undecoratedName.c_str(), Count);
1812
for ( j = 0; j < Count; ++j )
1813
pOpt[ j ] = CqColor(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1819
RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1820
CqVector3D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetPointOptionWrite(name, undecoratedName.c_str(), Count);
1822
for ( j = 0; j < Count; ++j )
1823
pOpt[ j ] = CqVector3D(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1829
RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1830
CqVector3D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetPointOptionWrite(name, undecoratedName.c_str(), Count);
1832
for ( j = 0; j < Count; ++j )
1833
pOpt[ j ] = CqVector3D(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1839
RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1840
CqVector3D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetPointOptionWrite(name, undecoratedName.c_str(), Count);
1842
for ( j = 0; j < Count; ++j )
1843
pOpt[ j ] = CqVector3D(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1849
/* RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1850
CqVector4D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetHPointOptionWrite(name, undecoratedName.c_str(), Count);
1852
for ( j = 0; j < Count; ++j )
1853
pOpt[ j ] = CqVector4D(pc[ (j*4) ], pc[ (j*4)+1 ], pc[ (j*4)+2 ], pc[ (j*4)+3]); */
1859
/* RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1860
CqMatrix* pOpt = QGetRenderContext()->poptWriteCurrent()->GetMatrixOptionWrite(name, undecoratedName.c_str(), Count);
1862
for ( j = 0; j < Count; ++j )
1863
pOpt[ j ] = CqMatrix(pm[ j ], pm[ j+1 ], pm[ j+2 ], pm[ j+3 ],
1864
pm[ j+4 ], pm[ j+5 ], pm[ j+6 ], pm[ j+7 ],
1865
pm[ j+8 ], pm[ j+9 ], pm[ j+10 ], pm[ j+11 ],
1866
pm[ j+12 ], pm[ j+13 ], pm[ j+14 ], pm[ j+15 ]); */
1875
//----------------------------------------------------------------------
1877
// Begin a ne attribute definition, pushes the current attributes.
1879
RtVoid RiAttributeBegin()
1881
VALIDATE_CONDITIONAL
1883
CACHE_RIATTRIBUTEBEGIN
1885
VALIDATE_RIATTRIBUTEBEGIN
1887
DEBUG_RIATTRIBUTEBEGIN
1889
QGetRenderContext() ->BeginAttributeModeBlock();
1895
//----------------------------------------------------------------------
1897
// End the current attribute defintion, pops the previous attributes.
1899
RtVoid RiAttributeEnd()
1901
VALIDATE_CONDITIONAL
1903
CACHE_RIATTRIBUTEEND
1905
VALIDATE_RIATTRIBUTEEND
1907
DEBUG_RIATTRIBUTEEND
1909
QGetRenderContext() ->EndAttributeModeBlock();
1915
//----------------------------------------------------------------------
1917
// Set the current color for use by the geometric primitives.
1919
RtVoid RiColor( RtColor Cq )
1921
VALIDATE_CONDITIONAL
1929
QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Color" ) [ 0 ] = CqColor( Cq );
1930
QGetRenderContext() ->AdvanceTime();
1935
//----------------------------------------------------------------------
1937
// Set the current opacity, for use by the geometric primitives.
1939
RtVoid RiOpacity( RtColor Os )
1941
VALIDATE_CONDITIONAL
1949
QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Opacity" ) [ 0 ] = CqColor( Os );
1950
QGetRenderContext() ->AdvanceTime();
1955
//----------------------------------------------------------------------
1956
// RiTextureCoordinates
1957
// Set the current texture coordinates used by the parametric geometric primitives.
1959
RtVoid RiTextureCoordinates( RtFloat s1, RtFloat t1,
1960
RtFloat s2, RtFloat t2,
1961
RtFloat s3, RtFloat t3,
1962
RtFloat s4, RtFloat t4 )
1964
VALIDATE_CONDITIONAL
1966
CACHE_RITEXTURECOORDINATES
1968
VALIDATE_RITEXTURECOORDINATES
1970
DEBUG_RITEXTURECOORDINATES
1972
TqFloat * pTC = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "TextureCoordinates" );
1974
assert( NULL != pTC );
1984
QGetRenderContext() ->AdvanceTime();
1990
//----------------------------------------------------------------------
1992
// Create a new light source at the current transformation.
1994
RtLightHandle RiLightSource( RtToken name, ... )
1996
EXTRACT_PARAMETERS( name )
1998
return ( RiLightSourceV( name, PASS_PARAMETERS ) );
2002
//----------------------------------------------------------------------
2004
// List based version of above.
2006
RtLightHandle RiLightSourceV( RtToken name, PARAMETERLIST )
2008
VALIDATE_CONDITIONAL0
2012
VALIDATE_RILIGHTSOURCE
2016
// Find the lightsource shader.
2017
//IqShader * pShader = static_cast<CqShader*>( QGetRenderContext() ->CreateShader( name, Type_Lightsource ) );
2018
boost::shared_ptr<IqShader> pShader = QGetRenderContext()->CreateShader( name, Type_Lightsource );
2022
Aqsis::log() << error << "Couldn't create light source shader \"" << name << "\"\n";
2026
pShader->SetTransform( QGetRenderContext() ->ptransCurrent() );
2027
CqLightsourcePtr pNew( new CqLightsource( pShader, RI_TRUE ) );
2028
Lightsource_stack.push_back(pNew);
2030
// Execute the intiialisation code here, as we now have our shader context complete.
2031
pShader->PrepareDefArgs();
2036
for ( i = 0; i < count; ++i )
2038
RtToken token = tokens[ i ];
2039
RtPointer value = values[ i ];
2041
SetShaderArgument( pShader, token, static_cast<TqPchar>( value ) );
2043
QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( pNew );
2044
// If this light is being defined outside the WorldBegin, then we can
2045
// go ahead and initialise the parameters, as they are invariant under changes to the camera space.
2046
if(!QGetRenderContext()->IsWorldBegin())
2047
pShader->InitialiseParameters();
2049
// Add it as a Context light as well in case we are in a context that manages it's own lights.
2050
QGetRenderContext() ->pconCurrent() ->AddContextLightSource( pNew );
2051
return ( reinterpret_cast<RtLightHandle>( pNew.get() ) );
2057
//----------------------------------------------------------------------
2058
// RiAreaLightSource
2059
// Create a new area light source at the current transformation, all
2060
// geometric primitives until the next RiAttributeEnd, become part of this
2061
// area light source.
2063
RtLightHandle RiAreaLightSource( RtToken name, ... )
2066
EXTRACT_PARAMETERS( name )
2068
return ( RiAreaLightSourceV( name, PASS_PARAMETERS ) );
2072
//----------------------------------------------------------------------
2073
// RiAreaLightSourceV
2074
// List based version of above.
2076
RtLightHandle RiAreaLightSourceV( RtToken name, PARAMETERLIST )
2078
VALIDATE_CONDITIONAL0
2080
CACHE_RIAREALIGHTSOURCE
2082
VALIDATE_RIAREALIGHTSOURCE
2084
DEBUG_RIAREALIGHTSOURCE
2086
Aqsis::log() << warning << "RiAreaLightSource not supported, will produce a point light" << std::endl;
2088
return ( RiLightSourceV( name, count, tokens, values ) );
2092
//----------------------------------------------------------------------
2094
// Set the current status of the specified light source.
2096
RtVoid RiIlluminate( RtLightHandle light, RtBoolean onoff )
2098
VALIDATE_CONDITIONAL
2102
VALIDATE_RIILLUMINATE
2106
CqLightsourcePtr pL( reinterpret_cast<CqLightsource*>( light )->shared_from_this() );
2108
// Check if we are turning the light on or off.
2109
if ( light == NULL ) return ;
2111
QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( pL );
2113
QGetRenderContext() ->pattrWriteCurrent() ->RemoveLightsource( pL );
2118
//----------------------------------------------------------------------
2120
// Set the current surface shader, used by geometric primitives.
2122
RtVoid RiSurface( RtToken name, ... )
2124
EXTRACT_PARAMETERS( name )
2126
RiSurfaceV( name, PASS_PARAMETERS );
2130
//----------------------------------------------------------------------
2132
// List based version of above.
2134
RtVoid RiSurfaceV( RtToken name, PARAMETERLIST )
2137
VALIDATE_CONDITIONAL
2146
//IqShader * pshadSurface = QGetRenderContext() ->CreateShader( name, Type_Surface );
2147
boost::shared_ptr<IqShader> pshadSurface = QGetRenderContext()->CreateShader( name, Type_Surface );
2151
pshadSurface->SetTransform( QGetRenderContext() ->ptransCurrent() );
2152
// Execute the intiialisation code here, as we now have our shader context complete.
2153
pshadSurface->PrepareDefArgs();
2155
for ( i = 0; i < count; ++i )
2157
RtToken token = tokens[ i ];
2158
RtPointer value = values[ i ];
2160
SetShaderArgument( pshadSurface, token, static_cast<TqPchar>( value ) );
2162
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pshadSurface, QGetRenderContext() ->Time() );
2164
QGetRenderContext() ->AdvanceTime();
2169
//----------------------------------------------------------------------
2171
// Set the current atrmospheric shader.
2173
RtVoid RiAtmosphere( RtToken name, ... )
2175
EXTRACT_PARAMETERS( name )
2177
RiAtmosphereV( name, PASS_PARAMETERS );
2181
//----------------------------------------------------------------------
2183
// List based version of above.
2185
RtVoid RiAtmosphereV( RtToken name, PARAMETERLIST )
2187
VALIDATE_CONDITIONAL
2191
VALIDATE_RIATMOSPHERE
2196
boost::shared_ptr<IqShader> pshadAtmosphere = QGetRenderContext()->CreateShader( name, Type_Volume );
2198
if ( pshadAtmosphere )
2200
pshadAtmosphere->SetTransform( QGetRenderContext() ->ptransCurrent() );
2201
// Execute the intiialisation code here, as we now have our shader context complete.
2202
pshadAtmosphere->PrepareDefArgs();
2204
for ( i = 0; i < count; ++i )
2206
RtToken token = tokens[ i ];
2207
RtPointer value = values[ i ];
2209
SetShaderArgument( pshadAtmosphere, token, static_cast<TqPchar>( value ) );
2213
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadAtmosphere( pshadAtmosphere, QGetRenderContext() ->Time() );
2214
QGetRenderContext() ->AdvanceTime();
2219
//----------------------------------------------------------------------
2221
// Set the current interior volumetric shader.
2223
RtVoid RiInterior( RtToken name, ... )
2225
Aqsis::log() << warning << "RiInterior not supported" << std::endl;
2230
//----------------------------------------------------------------------
2232
// List based version of above.
2234
RtVoid RiInteriorV( RtToken name, PARAMETERLIST )
2236
VALIDATE_CONDITIONAL
2244
Aqsis::log() << warning << "RiInterior not supported" << std::endl;
2249
//----------------------------------------------------------------------
2251
// Set the current exterior volumetric shader.
2253
RtVoid RiExterior( RtToken name, ... )
2255
Aqsis::log() << warning << "RiExterior not supported" << std::endl;
2260
//----------------------------------------------------------------------
2262
// List based version of above.
2264
RtVoid RiExteriorV( RtToken name, PARAMETERLIST )
2266
VALIDATE_CONDITIONAL
2274
Aqsis::log() << warning << "ExInterior not supported" << std::endl;
2279
//----------------------------------------------------------------------
2281
// Specify the size of the shading area in pixels.
2283
RtVoid RiShadingRate( RtFloat size )
2285
VALIDATE_CONDITIONAL
2289
VALIDATE_RISHADINGRATE
2293
CqLogRangeCheckCallback rc;
2298
if( !CheckMinMax( size, 0.0f, RI_INFINITY, &rc ) )
2305
Aqsis::log() << warning << "Invalid ShadingRate, ShadingRate set to 1" << std::endl;
2309
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRate" ) [ 0 ] = size;
2310
QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRateSqrt" ) [ 0 ] = sqrt( size );
2311
QGetRenderContext() ->AdvanceTime();
2317
//----------------------------------------------------------------------
2318
// RiShadingInterpolation
2319
// Specify the method of shading interpolation.
2321
RtVoid RiShadingInterpolation( RtToken type )
2323
VALIDATE_CONDITIONAL
2325
CACHE_RISHADINGINTERPOLATION
2327
VALIDATE_RISHADINGINTERPOLATION
2329
DEBUG_RISHADINGINTERPOLATION
2331
if ( strcmp( type, RI_CONSTANT ) == 0 )
2332
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingConstant;
2334
if ( strcmp( type, RI_SMOOTH ) == 0 )
2335
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingSmooth;
2337
Aqsis::log() << error << "RiShadingInterpolation unrecognised value \"" << type << "\"" << std::endl;
2339
QGetRenderContext() ->AdvanceTime();
2344
//----------------------------------------------------------------------
2346
// Set the matte state of subsequent geometric primitives.
2348
RtVoid RiMatte( RtBoolean onoff )
2350
VALIDATE_CONDITIONAL
2358
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Matte" ) [ 0 ] = onoff != 0;
2359
QGetRenderContext() ->AdvanceTime();
2364
//----------------------------------------------------------------------
2366
// Set the bounding cube of the current primitives.
2368
RtVoid RiBound( RtBound bound )
2370
VALIDATE_CONDITIONAL
2378
// TODO: Need to add a "Bound" attribute here, and fill it in.
2379
QGetRenderContext() ->AdvanceTime();
2385
//----------------------------------------------------------------------
2387
// Set the current bounding cube for use by level of detail calculation.
2389
RtVoid RiDetail( RtBound bound )
2391
VALIDATE_CONDITIONAL
2399
CqBound Bound( bound );
2401
TqFloat* boundAttr = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LODBound" );
2402
boundAttr[0] = bound[0];
2403
boundAttr[1] = bound[1];
2404
boundAttr[2] = bound[2];
2405
boundAttr[3] = bound[3];
2406
boundAttr[4] = bound[4];
2407
boundAttr[5] = bound[5];
2413
//----------------------------------------------------------------------
2415
// Set the visible range of any subsequent geometric primitives.
2417
RtVoid RiDetailRange( RtFloat offlow, RtFloat onlow, RtFloat onhigh, RtFloat offhigh )
2419
VALIDATE_CONDITIONAL
2423
VALIDATE_RIDETAILRANGE
2427
if ( offlow > onlow || onhigh > offhigh )
2429
Aqsis::log() << error << "RiDetailRange invalid range" << std::endl;
2433
TqFloat* rangeAttr = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LODRanges" );
2434
rangeAttr[0] = offlow;
2435
rangeAttr[1] = onlow;
2436
rangeAttr[2] = onhigh;
2437
rangeAttr[3] = offhigh;
2442
//----------------------------------------------------------------------
2443
// RiGeometricApproximation
2444
// Specify any parameters used by approximation functions during rendering.
2446
RtVoid RiGeometricApproximation( RtToken type, RtFloat value )
2448
VALIDATE_CONDITIONAL
2450
CACHE_RIGEOMETRICAPPROXIMATION
2452
VALIDATE_RIGEOMETRICAPPROXIMATION
2454
DEBUG_RIGEOMETRICAPPROXIMATION
2456
Aqsis::log() << warning << "RiGeometricApproximation not supported" << std::endl;
2461
//----------------------------------------------------------------------
2463
// Set the handedness of any subsequent geometric primitives.
2465
RtVoid RiOrientation( RtToken orientation )
2467
VALIDATE_CONDITIONAL
2471
VALIDATE_RIORIENTATION
2475
if ( orientation != 0 )
2477
if ( strstr( orientation, RI_RH ) != 0 )
2478
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = ( QGetRenderContext() ->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) ) ? 0 : 1;
2479
if ( strstr( orientation, RI_LH ) != 0 )
2480
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = ( QGetRenderContext() ->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) ) ? 1 : 0;
2481
if ( strstr( orientation, RI_INSIDE ) != 0 )
2482
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
2483
if ( strstr( orientation, RI_OUTSIDE ) != 0 )
2484
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
2486
QGetRenderContext() ->AdvanceTime();
2491
//----------------------------------------------------------------------
2492
// RiReverseOrientation
2493
// Reverse the handedness of any subsequent geometric primitives.
2495
RtVoid RiReverseOrientation()
2497
VALIDATE_CONDITIONAL
2499
CACHE_RIREVERSEORIENTATION
2501
VALIDATE_RIREVERSEORIENTATION
2503
DEBUG_RIREVERSEORIENTATION
2505
QGetRenderContext() ->pattrWriteCurrent() ->FlipeOrientation( QGetRenderContext() ->Time() );
2506
QGetRenderContext() ->AdvanceTime();
2511
//----------------------------------------------------------------------
2513
// Set the number of visibles sides for any subsequent geometric primitives.
2515
RtVoid RiSides( RtInt nsides )
2517
VALIDATE_CONDITIONAL
2525
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Sides" ) [ 0 ] = nsides;
2526
QGetRenderContext() ->AdvanceTime();
2532
//----------------------------------------------------------------------
2534
// Set the current transformation to the identity matrix.
2538
VALIDATE_CONDITIONAL
2546
QGetRenderContext() ->ptransSetTime( CqMatrix() );
2547
QGetRenderContext() ->AdvanceTime();
2552
//----------------------------------------------------------------------
2553
// Set the current transformation to the specified matrix.
2555
RtVoid RiTransform( RtMatrix transform )
2557
VALIDATE_CONDITIONAL
2561
VALIDATE_RITRANSFORM
2565
CqMatrix matTrans( transform );
2566
// if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2567
// QGetRenderContext() ->ptransWriteCurrent() ->FlipHandedness( QGetRenderContext() ->Time() );
2569
if( QGetRenderContext()->IsWorldBegin() )
2571
CqTransformPtr newTrans( new CqTransform( QGetRenderContext()->GetDefObjTransform() ) );
2572
QGetRenderContext() ->pconCurrent()->ptransSetCurrent( newTrans );
2573
QGetRenderContext() ->ptransConcatCurrentTime( CqMatrix( transform ) );
2576
QGetRenderContext() ->ptransSetCurrentTime( CqMatrix( transform ) );
2577
QGetRenderContext() ->AdvanceTime();
2583
//----------------------------------------------------------------------
2584
// RiConcatTransform
2585
// Concatenate the specified matrix into the current transformation matrix.
2587
RtVoid RiConcatTransform( RtMatrix transform )
2589
VALIDATE_CONDITIONAL
2591
CACHE_RICONCATTRANSFORM
2593
VALIDATE_RICONCATTRANSFORM
2595
DEBUG_RICONCATTRANSFORM
2597
// Check if this transformation results in a change in orientation.
2598
CqMatrix matTrans( transform );
2599
// if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2600
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2602
QGetRenderContext() ->ptransConcatCurrentTime( CqMatrix( transform ) );
2603
QGetRenderContext() ->AdvanceTime();
2608
//----------------------------------------------------------------------
2610
// Concatenate a perspective transformation into the current transformation.
2612
RtVoid RiPerspective( RtFloat fov )
2614
VALIDATE_CONDITIONAL
2618
VALIDATE_RIPERSPECTIVE
2624
Aqsis::log() << error << "RiPerspective invalid FOV" << std::endl;
2628
fov = tan( RAD( fov / 2 ) );
2630
// This matches PRMan 3.9 in testing, but not BMRT 2.6's rgl and rendrib.
2631
CqMatrix matP( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, fov, fov, 0, 0, -fov, 0 );
2633
// Check if this transformation results in a change in orientation.
2634
// if ( matP.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2635
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2637
QGetRenderContext() ->ptransConcatCurrentTime( matP );
2638
QGetRenderContext() ->AdvanceTime();
2644
//----------------------------------------------------------------------
2646
// Concatenate a translation into the current transformation.
2648
RtVoid RiTranslate( RtFloat dx, RtFloat dy, RtFloat dz )
2650
VALIDATE_CONDITIONAL
2654
VALIDATE_RITRANSLATE
2658
CqMatrix matTrans( CqVector3D( dx, dy, dz ) );
2659
// Check if this transformation results in a change in orientation.
2660
// if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2661
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2663
QGetRenderContext() ->ptransConcatCurrentTime( matTrans );
2664
QGetRenderContext() ->AdvanceTime();
2670
//----------------------------------------------------------------------
2672
// Concatenate a rotation into the current transformation.
2674
RtVoid RiRotate( RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz )
2676
VALIDATE_CONDITIONAL
2684
CqMatrix matRot( RAD( angle ), CqVector4D( dx, dy, dz ) );
2685
// Check if this transformation results in a change in orientation.
2686
// if ( matRot.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2687
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2689
QGetRenderContext() ->ptransConcatCurrentTime( matRot );
2690
QGetRenderContext() ->AdvanceTime();
2695
//----------------------------------------------------------------------
2697
// Concatenate a scale into the current transformation.
2699
RtVoid RiScale( RtFloat sx, RtFloat sy, RtFloat sz )
2701
VALIDATE_CONDITIONAL
2709
CqMatrix matScale( sx, sy, sz );
2710
// Check if this transformation results in a change in orientation.
2711
// if ( matScale.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2712
// QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
2714
QGetRenderContext() ->ptransConcatCurrentTime( matScale );
2715
QGetRenderContext() ->AdvanceTime();
2720
//----------------------------------------------------------------------
2722
// Concatenate a skew into the current transformation.
2724
RtVoid RiSkew( RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1,
2725
RtFloat dx2, RtFloat dy2, RtFloat dz2 )
2727
VALIDATE_CONDITIONAL
2735
CqMatrix matSkew( RAD( angle ), dx1, dy1, dz1, dx2, dy2, dz2 );
2737
// This transformation can not change orientation.
2739
QGetRenderContext() ->ptransConcatCurrentTime( matSkew );
2740
QGetRenderContext() ->AdvanceTime();
2745
//----------------------------------------------------------------------
2747
// Specify a deformation shader to be included into the current transformation.
2749
RtVoid RiDeformation( RtToken name, ... )
2751
Aqsis::log() << warning << "RiDeformation not supported" << std::endl;
2756
//----------------------------------------------------------------------
2758
// List based version of above.
2760
RtVoid RiDeformationV( RtToken name, PARAMETERLIST )
2762
VALIDATE_CONDITIONAL
2766
VALIDATE_RIDEFORMATION
2770
Aqsis::log() << warning << "RiDeformation not supported" << std::endl;
2775
//----------------------------------------------------------------------
2777
// Specify the current displacement shade used by geometric primitives.
2779
RtVoid RiDisplacement( RtToken name, ... )
2781
EXTRACT_PARAMETERS( name )
2783
RiDisplacementV( name, PASS_PARAMETERS );
2787
//----------------------------------------------------------------------
2789
// List based version of above.
2791
RtVoid RiDisplacementV( RtToken name, PARAMETERLIST )
2793
VALIDATE_CONDITIONAL
2795
CACHE_RIDISPLACEMENT
2797
VALIDATE_RIDISPLACEMENT
2799
DEBUG_RIDISPLACEMENT
2802
boost::shared_ptr<IqShader> pshadDisplacement = QGetRenderContext() ->CreateShader( name, Type_Displacement );
2804
if ( pshadDisplacement )
2806
pshadDisplacement->SetTransform( QGetRenderContext() ->ptransCurrent() );
2807
// Execute the intiialisation code here, as we now have our shader context complete.
2808
pshadDisplacement->PrepareDefArgs();
2810
for ( i = 0; i < count; ++i )
2812
RtToken token = tokens[ i ];
2813
RtPointer value = values[ i ];
2815
SetShaderArgument( pshadDisplacement, token, static_cast<TqPchar>( value ) );
2819
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadDisplacement( pshadDisplacement, QGetRenderContext() ->Time() );
2820
QGetRenderContext() ->AdvanceTime();
2825
//----------------------------------------------------------------------
2826
// RiCoordinateSystem
2827
// Save the current coordinate system as the specified name.
2829
RtVoid RiCoordinateSystem( RtToken space )
2831
VALIDATE_CONDITIONAL
2833
CACHE_RICOORDINATESYSTEM
2835
VALIDATE_RICOORDINATESYSTEM
2837
DEBUG_RICOORDINATESYSTEM
2839
// Insert the named coordinate system into the list help on the renderer.
2840
QGetRenderContext() ->SetCoordSystem( space, QGetRenderContext() ->matCurrent( QGetRenderContext() ->Time() ) );
2841
QGetRenderContext() ->AdvanceTime();
2847
//----------------------------------------------------------------------
2848
// ---Additional to spec. v3.1---
2849
// RiCoordSysTransform
2850
// Replace the current transform with the named space.
2852
RtVoid RiCoordSysTransform( RtToken space )
2854
VALIDATE_CONDITIONAL
2856
CACHE_RICOORDSYSTRANSFORM
2858
VALIDATE_RICOORDSYSTRANSFORM
2860
DEBUG_RICOORDSYSTRANSFORM
2862
// Insert the named coordinate system into the list help on the renderer.
2863
QGetRenderContext() ->ptransSetTime( QGetRenderContext() ->matSpaceToSpace( space, "world", NULL, NULL, QGetRenderContext()->Time() ) );
2864
QGetRenderContext() ->AdvanceTime();
2870
//----------------------------------------------------------------------
2871
// RiTransformPoints
2872
// Transform a list of points from one coordinate system to another.
2874
RtPoint* RiTransformPoints( RtToken fromspace, RtToken tospace, RtInt npoints, RtPoint points[] )
2876
CACHE_RITRANSFORMPOINTS
2878
VALIDATE_RITRANSFORMPOINTS
2880
DEBUG_RITRANSFORMPOINTS
2885
CqMatrix matCToW = QGetRenderContext() ->matSpaceToSpace( fromspace,
2886
tospace, NULL, NULL, QGetRenderContextI()->Time() );
2888
if (matCToW.fIdentity() != TqTrue)
2890
for(TqInt i =0; i< npoints; i++)
2892
CqVector3D tmp = points[i];
2893
tmp = tmp * matCToW;
2894
points[i][0] = tmp.x();
2895
points[i][1] = tmp.y();
2896
points[i][2] = tmp.z();
2904
//----------------------------------------------------------------------
2906
// Push the current transformation state.
2908
RtVoid RiTransformBegin()
2910
VALIDATE_CONDITIONAL
2912
CACHE_RITRANSFORMBEGIN
2914
VALIDATE_RITRANSFORMBEGIN
2916
DEBUG_RITRANSFORMBEGIN
2918
QGetRenderContext() ->BeginTransformModeBlock();
2924
//----------------------------------------------------------------------
2926
// Pop the previous transformation state.
2928
RtVoid RiTransformEnd()
2930
VALIDATE_CONDITIONAL
2932
CACHE_RITRANSFORMEND
2934
VALIDATE_RITRANSFORMEND
2936
DEBUG_RITRANSFORMEND
2938
QGetRenderContext() ->EndTransformModeBlock();
2944
//----------------------------------------------------------------------
2946
// Set a system specific attribute.
2948
RtVoid RiAttribute( RtToken name, ... )
2950
EXTRACT_PARAMETERS( name )
2952
TqUlong hash = CqString::hash(name);
2954
if (hash == RIH_RENDER)
2956
if (hash == RIH_INDIRECT)
2958
if (hash == RIH_LIGHT)
2960
if (hash == RIH_VISIBILITY)
2963
RiAttributeV( name, PASS_PARAMETERS );
2967
//----------------------------------------------------------------------
2969
// List based version of above.
2971
RtVoid RiAttributeV( RtToken name, PARAMETERLIST )
2973
VALIDATE_CONDITIONAL
2977
VALIDATE_RIATTRIBUTE
2981
TqUlong hash = CqString::hash(name);
2983
if (hash == RIH_RENDER)
2985
if (hash == RIH_INDIRECT)
2987
if (hash == RIH_LIGHT)
2989
if (hash == RIH_VISIBILITY)
2992
// Find the parameter on the current options.
2993
CqNamedParameterList * pAttr = QGetRenderContext() ->pattrWriteCurrent() ->pAttributeWrite( name ).get();
2996
for ( i = 0; i < count; ++i )
2998
RtToken token = tokens[ i ];
2999
RtPointer value = values[ i ];
3003
TqBool bArray = false;
3004
CqParameter* pParam = pAttr->pParameter( token );
3007
// Search for the parameter in the declarations.
3008
// Note attributes can only be uniform.
3009
SqParameterDeclaration Decl;
3012
Decl = QGetRenderContext()->FindParameterDecl( token );
3014
catch( XqException e )
3016
Aqsis::log() << error << e.strReason().c_str() << std::endl;
3019
if ( Decl.m_strName != "" && Decl.m_Class == class_uniform )
3021
pParam = Decl.m_pCreate( Decl.m_strName.c_str(), Decl.m_Count );
3023
Class = Decl.m_Class;
3024
bArray = Decl.m_Count > 0;
3025
pAttr->AddParameter( pParam );
3029
if ( Decl.m_strName == "" )
3030
Aqsis::log() << warning << "Unrecognised declaration \"" << token << "\"" << std::endl;
3032
Aqsis::log() << warning << "Attributes can only be uniform" << std::endl;
3038
Type = pParam->Type();
3039
Class = pParam->Class();
3040
bArray = pParam->Count() > 0;
3047
RtFloat * pf = reinterpret_cast<RtFloat*>( value );
3051
for ( j = 0; j < pParam->Count(); ++j )
3052
static_cast<CqParameterTypedUniformArray<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ j ] = pf[ j ];
3055
static_cast<CqParameterTypedUniform<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pf[ 0 ];
3061
RtInt* pi = reinterpret_cast<RtInt*>( value );
3065
for ( j = 0; j < pParam->Count(); ++j )
3066
static_cast<CqParameterTypedUniformArray<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ j ] = pi[ j ];
3069
static_cast<CqParameterTypedUniform<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pi[ 0 ];
3075
char** ps = reinterpret_cast<char**>( value );
3079
for ( j = 0; j < pParam->Count(); ++j )
3081
CqString str( ps[ j ] );
3082
static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ j ] = str;
3087
CqString str( ps[ 0 ] );
3088
static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ 0 ] = str;
3091
if( (strcmp(name, "identifier")==0) && (strcmp(token, "name")==0))
3092
Aqsis::log() << info << "Identifier: " << ps[ 0 ] << std::endl;
3096
// TODO: Rest of parameter types.
3103
//----------------------------------------------------------------------
3105
// Specify a coplanar, convex polygon.
3107
RtVoid RiPolygon( RtInt nvertices, ... )
3109
EXTRACT_PARAMETERS( nvertices )
3111
RiPolygonV( nvertices, PASS_PARAMETERS );
3115
//----------------------------------------------------------------------
3117
// List based version of above.
3119
RtVoid RiPolygonV( RtInt nvertices, PARAMETERLIST )
3121
VALIDATE_CONDITIONAL
3129
// Create a new polygon surface primitive.
3130
boost::shared_ptr<CqSurfacePolygon> pSurface( new CqSurfacePolygon( nvertices ) );
3132
// Process any specified primitive variables.
3133
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3135
if ( !pSurface->CheckDegenerate() )
3137
TqFloat time = QGetRenderContext()->Time();
3138
// Transform the points into camera space for processing,
3139
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
3140
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
3141
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
3142
CreateGPrim( pSurface );
3146
Aqsis::log() << error << "Found degenerate polygon" << std::endl;
3154
//----------------------------------------------------------------------
3156
// Specify a nonconvex coplanar polygon.
3158
RtVoid RiGeneralPolygon( RtInt nloops, RtInt nverts[], ... )
3160
EXTRACT_PARAMETERS( nverts )
3162
RiGeneralPolygonV( nloops, nverts, PASS_PARAMETERS );
3166
//----------------------------------------------------------------------
3167
// RiGeneralPolygonV
3168
// List based version of above.
3170
RtVoid RiGeneralPolygonV( RtInt nloops, RtInt nverts[], PARAMETERLIST )
3172
VALIDATE_CONDITIONAL
3174
CACHE_RIGENERALPOLYGON
3176
VALIDATE_RIGENERALPOLYGON
3178
DEBUG_RIGENERALPOLYGON
3182
// Calcualte how many points there are.
3184
for ( iloop = 0; iloop < nloops; ++iloop )
3186
cVerts += nverts[ iloop ];
3187
// Check for degenerate loops.
3188
if( nverts[ iloop ] < 3 )
3190
CqString objname( "unnamed" );
3191
const CqString* pattrName = QGetRenderContext()->pattrCurrent()->GetStringAttribute( "identifier", "name" );
3192
if ( pattrName != 0 )
3193
objname = pattrName[ 0 ];
3194
Aqsis::log() << warning << "Degenerate loop in GeneralPolygon object \"" << objname.c_str() << "\"" << std::endl;
3198
// Create a storage class for all the points.
3199
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, 1, cVerts ) );
3200
// Process any specified primitive variables
3201
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3203
pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
3205
// Work out which plane to project to.
3209
CqVector3D vecTemp = pPointsClass->P()->pValue( 0 )[0];
3210
MinX = MaxX = vecTemp.x();
3211
MinY = MaxY = vecTemp.y();
3212
MinZ = MaxZ = vecTemp.z();
3214
// We need to take into account Orientation here.
3215
TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
3218
for ( iVert = 1; iVert < pPointsClass->P() ->Size(); ++iVert )
3220
vecTemp = pPointsClass->P()->pValue( iVert )[0];
3221
MinX = ( MinX < vecTemp.x() ) ? MinX : vecTemp.x();
3222
MinY = ( MinY < vecTemp.y() ) ? MinY : vecTemp.y();
3223
MinZ = ( MinZ < vecTemp.z() ) ? MinZ : vecTemp.z();
3224
MaxX = ( MaxX > vecTemp.x() ) ? MaxX : vecTemp.x();
3225
MaxY = ( MaxY > vecTemp.y() ) ? MaxY : vecTemp.y();
3226
MaxZ = ( MaxZ > vecTemp.z() ) ? MaxZ : vecTemp.z();
3228
TqFloat DiffX = MaxX - MinX;
3229
TqFloat DiffY = MaxY - MinY;
3230
TqFloat DiffZ = MaxZ - MinZ;
3233
if ( DiffX < DiffY && DiffX < DiffZ )
3234
Axis = CqPolygonGeneral2D::Axis_YZ;
3235
else if ( DiffY < DiffX && DiffY < DiffZ )
3236
Axis = CqPolygonGeneral2D::Axis_XZ;
3238
Axis = CqPolygonGeneral2D::Axis_XY;
3240
// Create a general 2D polygon using the points in each loop.
3241
CqPolygonGeneral2D poly;
3243
for ( iloop = 0; iloop < nloops; ++iloop )
3245
CqPolygonGeneral2D polya;
3246
polya.SetAxis( Axis );
3247
polya.SetpVertices( pPointsClass );
3249
for ( ivert = 0; ivert < nverts[ iloop ]; ++ivert )
3251
assert( ipoint < pPointsClass->P() ->Size() );
3252
polya.aiVertices().push_back( ipoint++ );
3256
/// \note: We need to check here if the orientation of the projected poly matches the
3257
/// expected one, of not, we must swap the direction so that the triangulation routines can
3258
/// correctly determine the inside/outside nature of points. However, if doing so breaks the
3259
/// orientation as expected by the rest of the renderer, we need to flip the orientation
3260
/// attribute as well so that normals are correctly calculated.
3263
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3265
QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
3266
polya.SwapDirection();
3271
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3273
QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
3274
polya.SwapDirection();
3283
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3284
polya.SwapDirection();
3288
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3289
polya.SwapDirection();
3291
poly.Combine( polya );
3294
// Now triangulate the general polygon
3296
std::vector<TqInt> aiTriangles;
3297
poly.CalcOrientation();
3298
poly.Triangulate( aiTriangles );
3300
TqUint ctris = aiTriangles.size() / 3;
3301
// Build an array of point counts (always 3 each).
3302
std::vector<RtInt> _nverts;
3303
_nverts.resize( ctris, 3 );
3305
RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
3310
RtVoid RiBlobby( RtInt nleaf, RtInt ncodes, RtInt codes[], RtInt nfloats, RtFloat floats[],
3311
RtInt nstrings, RtString strings[], ... )
3314
EXTRACT_PARAMETERS( strings )
3316
RiBlobbyV( nleaf, ncodes, codes, nfloats, floats, nstrings, strings, PASS_PARAMETERS );
3321
//----------------------------------------------------------------------
3322
/** List based version of above.
3326
RtVoid RiBlobbyV( RtInt nleaf, RtInt ncode, RtInt code[], RtInt nflt, RtFloat flt[],
3327
RtInt nstr, RtString str[], PARAMETERLIST )
3329
VALIDATE_CONDITIONAL
3337
// Initialize the blobby structure
3338
CqBlobby blobby(nleaf, ncode, code, nflt, flt, nstr, str);
3340
// Get back the bounding box in world coordinates
3341
CqBound Bound(blobby.Bound());
3343
// Transform the bounding box into camera coordinates
3344
Bound.Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", NULL, QGetRenderContext() ->ptransCurrent().get(), QGetRenderContext()->Time() ));
3346
// The bounding-box stops at camera's plane
3347
TqFloat camera_z = QGetRenderContext() ->poptCurrent() ->GetFloatOption( "System", "Clipping" ) [ 0 ];
3348
if(Bound.vecMax().z() < camera_z)
3349
// Blobby's behind the camera
3352
if(Bound.vecMin().z() < camera_z)
3353
// Cut the bounding-box with camera's plane
3354
Bound = CqBound(CqVector3D(Bound.vecMin().x(), Bound.vecMin().y(), camera_z), Bound.vecMax());
3356
// Transform the bounding box into raster coordinates
3357
Bound.Transform( QGetRenderContext() ->matSpaceToSpace( "camera", "raster", NULL, QGetRenderContext() ->ptransCurrent().get(), QGetRenderContext()->Time() ));
3359
// Get bounding-box size in pixels
3360
TqInt pixels_w = static_cast<TqInt> ( Bound.vecCross().x() );
3361
TqInt pixels_h = static_cast<TqInt> ( Bound.vecCross().y() );
3363
// Adjust to shading rate
3364
TqInt shading_rate = MAX(1, static_cast<TqInt> ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "ShadingRate" ) [ 0 ]));
3365
pixels_w /= shading_rate;
3366
pixels_h /= shading_rate;
3369
// Polygonize this blobby
3372
TqInt* nvertices = 0;
3373
TqInt* vertices = 0;
3374
TqFloat* points = 0;
3375
TqInt pieces = blobby.polygonize(pixels_w, pixels_h, npoints, npolygons, nvertices, vertices, points);
3377
Aqsis::log() << info << "Polygonized : " << npoints << " points, " << npolygons << " triangles." << std::endl;
3379
TqFloat* colors = new TqFloat[3 * npoints];
3381
std::vector<TqFloat> splits;
3382
splits.resize(nleaf);
3384
/* Parameters: RtInt count, RtToken tokens[], RtPointer values[] */
3385
TqBool Cs = TqFalse;
3386
for (TqInt c = 0; c < count; c++)
3388
if (strstr(tokens[c], RI_CS))
3393
for( int i = 0; i < npoints; i++ )
3396
TqFloat ocolors[3] = {0.0f,0.0f,0.0f};
3400
cg[1] = points[m + 1];
3401
cg[2] = points[m + 2];
3403
sum = blobby.implicit_value(cg, nleaf, splits);
3407
colors[m] = colors[m+1] = colors[m+2] = 0.0f;
3408
for (TqInt j=0; j < nleaf; j++)
3411
colors[m] += splits[j] * ((TqFloat *) *values)[l];
3412
colors[m+1] += splits[j] * ((TqFloat *) *values)[l+1];
3413
colors[m+2] += splits[j] * ((TqFloat *) *values)[l+2];
3418
ocolors[0] = colors[m];
3419
ocolors[1] = colors[m+1];
3420
ocolors[2] = colors[m+2];
3424
colors[m] = ocolors[0];
3425
colors[m+1] = ocolors[1];
3426
colors[m+2] = ocolors[2];
3435
pieces = MIN(8, pieces);
3440
for (i=0; i < pieces-1; i ++)
3442
Aqsis::log() << info << "Creating RiPointsPolygons for piece " << i << "[" << pieces-1 << "]" << std::endl;
3443
m = (i * npolygons)/pieces;
3444
RiPointsPolygons(npolygons/pieces, nvertices, &vertices[3 * m], RI_P, points, RI_CS, colors, RI_NULL);
3445
Aqsis::log() << info << "Done creating RiPointsPolygons for piece " << i << std::endl;
3448
Aqsis::log() << info << "Creating RiPointsPolygons for piece " << (pieces-1) << "[" << pieces-1 << "]" << std::endl;
3449
m = ((pieces-1) * npolygons) / pieces;
3450
TqInt nmax = npolygons - m;
3451
RiPointsPolygons(nmax, nvertices, &vertices[3 * m], RI_P, points, RI_CS, colors, RI_NULL);
3452
Aqsis::log() << info << "Done creating RiPointsPolygons for piece " << (pieces-1) << std::endl;
3456
for (i=0; i < pieces-1; i ++)
3458
Aqsis::log() << info << "Creating RiPointsPolygons for piece " << i << "[" << pieces-1 << "]" << std::endl;
3459
m = (i * npolygons)/pieces;
3460
RiPointsPolygons(npolygons/pieces, nvertices, &vertices[3 * m], RI_P, points, RI_NULL);
3461
Aqsis::log() << info << "Done creating RiPointsPolygons for piece " << i << std::endl;
3464
Aqsis::log() << info << "Creating RiPointsPolygons for piece " << (pieces-1) << "[" << pieces-1 << "]" << std::endl;
3465
m = ((pieces-1) * npolygons) / pieces;
3466
TqInt nmax = npolygons - m;
3467
RiPointsPolygons(nmax, nvertices, &vertices[3 * m], RI_P, points, RI_NULL);
3468
Aqsis::log() << info << "Done creating RiPointsPolygons for piece " << (pieces-1) << std::endl;
3471
Aqsis::log() << info << "Created RiPointsPolygons for Blobby" << std::endl;
3481
//----------------------------------------------------------------------
3482
/** Specify a small Points primitives
3486
RtVoid RiPoints( RtInt nvertices, ... )
3488
EXTRACT_PARAMETERS( nvertices )
3490
RiPointsV( nvertices, PASS_PARAMETERS );
3495
//----------------------------------------------------------------------
3496
/** List based version of above.
3500
RtVoid RiPointsV( RtInt npoints, PARAMETERLIST )
3502
VALIDATE_CONDITIONAL
3510
// Create a storage class for all the points.
3511
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( npoints, 1, npoints ) );
3513
// Create a new points storage class
3514
boost::shared_ptr<CqPoints> pSurface;
3516
// read in the parameter list
3517
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3519
// Transform the points into camera space for processing,
3520
// This needs to be done before initialising the KDTree as the tree must be formulated in 'current' (camera) space.
3521
pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), pPointsClass->pTransform() ->Time(0) ),
3522
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), pPointsClass->pTransform() ->Time(0) ),
3523
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), pPointsClass->pTransform() ->Time(0) ) );
3525
pSurface = boost::shared_ptr<CqPoints>( new CqPoints( npoints, pPointsClass ) );
3526
// Initialise the KDTree for the points to contain all.
3527
pSurface->InitialiseKDTree();
3528
pSurface->InitialiseMaxWidth();
3530
if ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "LODBound" ) [ 1 ] < 0.0f )
3532
// Cull this geometry for LOD reasons
3536
/// \note: Have to duplicate the work of CreateGPrim here as we need a special type of CqDeformingSurface.
3537
/// Not happy about this, need to look at it.
3538
// If in a motion block, confirm that the current deformation surface can accept the passed one as a keyframe.
3539
if( QGetRenderContext() ->pconCurrent() ->fMotionBlock() )
3541
CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
3543
boost::shared_ptr<CqDeformingSurface> pMS = pMMB->GetDeformingSurface();
3544
// If this is the first frame, then generate the appropriate CqDeformingSurface and fill in the first frame.
3545
// Then cache the pointer on the motion block.
3548
boost::shared_ptr<CqDeformingPointsSurface> pNewMS( new CqDeformingPointsSurface( pSurface ) );
3549
pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
3551
pMMB->SetDeformingSurface( pNewMS );
3555
pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
3557
QGetRenderContext() ->AdvanceTime();
3561
QGetRenderContext()->StorePrimitive( pSurface );
3562
STATS_INC( GPR_created );
3569
//----------------------------------------------------------------------
3570
/** Specify a small line primitives
3572
*\param type could be "linear" "bicubic"
3573
*\param ncurves : number of vertices
3574
*\param nvertices: vertices index
3575
*\param wrap could be "periodic" "nonperiodic"
3579
RtVoid RiCurves( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, ... )
3581
EXTRACT_PARAMETERS( wrap )
3583
RiCurvesV( type, ncurves, nvertices, wrap, PASS_PARAMETERS );
3588
//----------------------------------------------------------------------
3589
/** List based version of above.
3593
RtVoid RiCurvesV( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, PARAMETERLIST )
3595
VALIDATE_CONDITIONAL
3603
// find out whether the curve is periodic or non-periodic
3604
TqBool periodic = TqFalse;
3605
if ( strcmp( wrap, RI_PERIODIC ) == 0 )
3609
else if ( strcmp( wrap, RI_NONPERIODIC ) == 0 )
3615
// the wrap mode was neither "periodic" nor "nonperiodic"
3616
Aqsis::log() << error << "RiCurves invalid wrap mode \"" << wrap << "\"" << std::endl;
3619
// handle creation of linear and cubic curve groups separately
3620
if ( strcmp( type, RI_CUBIC ) == 0 )
3622
// create a new group of cubic curves
3623
boost::shared_ptr<CqCubicCurvesGroup> pSurface( new CqCubicCurvesGroup( ncurves, nvertices, periodic ) );
3624
// read in the parameter list
3625
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3627
// set the default primitive variables
3628
pSurface->SetDefaultPrimitiveVariables();
3630
TqFloat time = QGetRenderContext()->Time();
3631
// Transform the points into camera space for processing,
3632
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
3633
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
3634
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
3636
CreateGPrim( pSurface );
3639
else if ( strcmp( type, RI_LINEAR ) == 0 )
3641
// create a new group of linear curves
3642
boost::shared_ptr<CqLinearCurvesGroup> pSurface( new CqLinearCurvesGroup( ncurves, nvertices, periodic ) );
3644
// read in the parameter list
3645
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3647
// set the default primitive variables
3648
pSurface->SetDefaultPrimitiveVariables();
3649
TqFloat time = QGetRenderContext()->Time();
3650
// Transform the points into camera space for processing,
3651
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
3652
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
3653
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
3654
CreateGPrim( pSurface );
3659
// the type of curve was neither "linear" nor "cubic"
3660
Aqsis::log() << error << "RiCurves invalid type \"" << type << "\"" << std::endl;
3665
//----------------------------------------------------------------------
3667
// Specify a list of convex coplanar polygons and their shared vertices.
3669
RtVoid RiPointsPolygons( RtInt npolys, RtInt nverts[], RtInt verts[], ... )
3671
EXTRACT_PARAMETERS( verts )
3673
RiPointsPolygonsV( npolys, nverts, verts, PASS_PARAMETERS );
3677
//----------------------------------------------------------------------
3678
// RiPointsPolygonsV
3679
// List based version of above.
3683
RtVoid RiPointsPolygonsV( RtInt npolys, RtInt nverts[], RtInt verts[], PARAMETERLIST )
3685
VALIDATE_CONDITIONAL
3687
CACHE_RIPOINTSPOLYGONS
3689
VALIDATE_RIPOINTSPOLYGONS
3691
DEBUG_RIPOINTSPOLYGONS
3693
// Calculate how many vertices there are.
3695
RtInt* pVerts = verts;
3697
RtInt sumnVerts = 0;
3698
for ( poly = 0; poly < npolys; ++poly )
3701
sumnVerts += nverts[ poly ];
3702
for ( v = 0; v < nverts[ poly ]; ++v )
3704
cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
3709
// Create a storage class for all the points.
3710
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, npolys, sumnVerts ) );
3711
// Process any specified primitive variables
3712
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3714
boost::shared_ptr<CqSurfacePointsPolygons> pPsPs( new CqSurfacePointsPolygons(pPointsClass, npolys, nverts, verts ) );
3715
TqFloat time = QGetRenderContext()->Time();
3716
// Transform the points into camera space for processing,
3717
pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), time ),
3718
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), time ),
3719
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), time ) );
3727
//----------------------------------------------------------------------
3728
// RiPointsGeneralPolygons
3729
// Specify a list of coplanar, non-convex polygons and their shared vertices.
3731
RtVoid RiPointsGeneralPolygons( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], ... )
3733
EXTRACT_PARAMETERS( verts )
3735
RiPointsGeneralPolygonsV( npolys, nloops, nverts, verts, PASS_PARAMETERS );
3741
//----------------------------------------------------------------------
3742
// RiPointsGeneralPolygonsV
3743
// List based version of above.
3745
RtVoid RiPointsGeneralPolygonsV( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], PARAMETERLIST )
3747
VALIDATE_CONDITIONAL
3749
CACHE_RIPOINTSGENERALPOLYGONS
3751
VALIDATE_RIPOINTSGENERALPOLYGONS
3753
DEBUG_RIPOINTSGENERALPOLYGONS
3760
TqInt initial_index;
3761
TqInt sumnVerts = 0;
3763
// Calculate how many points overall.
3764
RtInt* pVerts = verts;
3765
for ( ipoly = 0; ipoly < (TqUint) npolys; ++ipoly )
3767
for ( iloop = 0; iloop < (TqUint) nloops[ ipoly ]; ++iloop, ++igloop )
3770
sumnVerts += nverts[ igloop ];
3771
// Check for degenerate loops.
3772
if( nverts[ igloop ] < 3 )
3774
CqString objname( "unnamed" );
3775
const CqString* pattrName = QGetRenderContext()->pattrCurrent()->GetStringAttribute( "identifier", "name" );
3776
if ( pattrName != 0 )
3777
objname = pattrName[ 0 ];
3778
Aqsis::log() << warning << "Degenerate loop in PointsGeneralPolygons object \"" << objname.c_str() << "\"" << std::endl;
3780
for ( v = 0; v < nverts[ igloop ]; ++v )
3782
cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
3788
// We need to take into account Orientation here.
3789
TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
3791
// Create a storage class for all the points.
3792
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, npolys, sumnVerts ) );
3793
// Process any specified primitive variables
3794
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3796
pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
3798
// Reset loop counter.
3801
std::vector<TqInt> aiTriangles;
3802
std::vector<TqInt> aFVList;
3803
std::vector<TqInt> aUVList;
3805
for ( ipoly = 0; ipoly < (TqUint) npolys; ++ipoly )
3807
initial_index = igvert;
3808
// Create a general 2D polygon using the points in each loop.
3809
CqPolygonGeneral2D poly;
3811
TqUint imaxindex, iminindex;
3814
for ( iloop = 0; iloop < (TqUint) nloops[ ipoly ]; ++iloop, ++igloop )
3816
iminindex = MIN( iminindex, (TqUint) verts[ igvert ] );
3817
imaxindex = MAX( imaxindex, (TqUint) verts[ igvert ] );
3821
CqVector3D vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
3822
MinX = MaxX = vecTemp.x();
3823
MinY = MaxY = vecTemp.y();
3824
MinZ = MaxZ = vecTemp.z();
3826
CqPolygonGeneral2D polya;
3827
polya.SetpVertices( pPointsClass );
3829
for ( ivert = 0; ivert < nverts[ igloop ]; ++ivert, ++igvert )
3831
ipoint = verts[ igvert ];
3832
assert( ipoint < pPointsClass->P() ->Size() );
3833
polya.aiVertices().push_back( ipoint );
3835
vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
3836
MinX = ( MinX < vecTemp.x() ) ? MinX : vecTemp.x();
3837
MinY = ( MinY < vecTemp.y() ) ? MinY : vecTemp.y();
3838
MinZ = ( MinZ < vecTemp.z() ) ? MinZ : vecTemp.z();
3839
MaxX = ( MaxX > vecTemp.x() ) ? MaxX : vecTemp.x();
3840
MaxY = ( MaxY > vecTemp.y() ) ? MaxY : vecTemp.y();
3841
MaxZ = ( MaxZ > vecTemp.z() ) ? MaxZ : vecTemp.z();
3844
// Work out which plane to project to.
3845
TqFloat DiffX = MaxX - MinX;
3846
TqFloat DiffY = MaxY - MinY;
3847
TqFloat DiffZ = MaxZ - MinZ;
3850
if ( DiffX < DiffY && DiffX < DiffZ )
3851
Axis = CqPolygonGeneral2D::Axis_YZ;
3852
else if ( DiffY < DiffX && DiffY < DiffZ )
3853
Axis = CqPolygonGeneral2D::Axis_XZ;
3855
Axis = CqPolygonGeneral2D::Axis_XY;
3856
polya.SetAxis( Axis );
3860
/// \note: We need to check here if the orientation of the projected poly matches the
3861
/// expected one, of not, we must swap the direction so that the triangulation routines can
3862
/// correctly determine the inside/outside nature of points. However, if doing so breaks the
3863
/// orientation as expected by the rest of the renderer, we need to flip the orientation
3864
/// attribute as well so that normals are correctly calculated.
3867
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3868
polya.SwapDirection();
3872
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3873
polya.SwapDirection();
3881
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3882
polya.SwapDirection();
3886
if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3887
polya.SwapDirection();
3889
poly.Combine( polya );
3892
// Now triangulate the general polygon
3894
poly.CalcOrientation();
3895
TqUint iStartTri = aiTriangles.size();
3896
poly.Triangulate( aiTriangles );
3897
TqUint iEndTri = aiTriangles.size();
3898
// Store the facevarying information
3899
/// \note This code relies on the fact that vertex indices cannot be duplicated
3900
/// within the loops of a single poly. Make sure this is a reasonable assumption.
3901
for( TqUint ifv = iStartTri; ifv < iEndTri; ++ifv )
3903
TqInt ivaryingindex = aiTriangles[ ifv ];
3904
TqBool found = TqFalse;
3905
for( TqUint iv = initial_index; iv != igvert; ++iv )
3907
if( verts[ iv ] == ivaryingindex )
3909
aFVList.push_back( iv );
3916
// Store the count of triangles generated for this general poly, so that we
3917
// can duplicate up the uniform values as appropriate.
3918
/// \note This code relies on the fact that vertex indices cannot be duplicated
3919
/// within the loops of a single poly. Make sure this is a reasonable assumption.
3920
aUVList.push_back( ( iEndTri - iStartTri ) / 3 );
3923
// Build an array of point counts (always 3 each).
3924
ctris = aiTriangles.size() / 3;
3925
std::vector<RtInt> _nverts;
3926
_nverts.resize( ctris, 3 );
3928
// Rebuild any facevarying or uniform variables.
3930
TqInt fvcount = ctris * 3;
3931
assert( aFVList.size() == fvcount );
3932
std::vector<void*> aNewParams;
3933
for( iUserParam = 0; iUserParam < count; ++iUserParam )
3935
SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( tokens[ iUserParam ] );
3936
TqInt elem_size = 0;
3937
switch( Decl.m_Type )
3940
elem_size = sizeof(RtFloat);
3943
elem_size = sizeof(RtInt);
3948
elem_size = sizeof(RtPoint);
3951
elem_size = sizeof(RtColor);
3954
elem_size = sizeof(RtMatrix);
3959
// Take into account array primitive variables.
3960
elem_size *= Decl.m_Count;
3962
if( Decl.m_Class == class_facevarying || Decl.m_Class == class_facevertex )
3964
char* pNew = static_cast<char*>( malloc( elem_size * fvcount) );
3965
aNewParams.push_back( pNew );
3967
for( iElem = 0; iElem < fvcount; ++iElem )
3969
const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] ) + ( aFVList[ iElem ] * elem_size );
3970
memcpy( pNew, pval, ( elem_size ));
3973
values[ iUserParam ] = aNewParams.back();
3975
else if( Decl.m_Class == class_uniform )
3977
// Allocate enough for 1 value per triangle, then duplicate values from the original list
3979
char* pNew = static_cast<char*>( malloc( elem_size * ctris ) );
3980
aNewParams.push_back( pNew );
3982
const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] );
3983
for( iElem = 0; iElem < npolys; ++iElem )
3985
TqInt dup_count = aUVList[ iElem ];
3987
for(dup=0; dup < dup_count; dup++)
3989
memcpy( pNew, pval, ( elem_size ));
3994
values[ iUserParam ] = aNewParams.back();
3998
RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
4000
std::vector<void*>::iterator iNewParam;
4001
for( iNewParam = aNewParams.begin(); iNewParam != aNewParams.end(); ++iNewParam )
4009
//----------------------------------------------------------------------
4011
// Specify the patch basis matrices for the u and v directions, and the knot skip values.
4013
RtVoid RiBasis( RtBasis ubasis, RtInt ustep, RtBasis vbasis, RtInt vstep )
4015
VALIDATE_CONDITIONAL
4026
// A good parser will use the Ri*Basis pointers so a quick comparison
4028
//if ( ubasis not same as before )
4030
// // Save off the newly given basis.
4032
// // Calculate the (inverse Bezier Basis) * (given basis), but do
4033
// // a quick check for RiPowerBasis since that is an identity
4034
// // matrix requiring no math.
4035
// if ( ubasis!=RiPowerBasis )
4042
// Do the above again for vbasis.
4043
// Save off (InvBezier * VBasis) and (Transpose(InvBezier*UBasis)).
4047
for ( i = 0; i < 4; ++i )
4050
for ( j = 0; j < 4; ++j )
4052
u.SetElement( i, j, ubasis[ i ][ j ] );
4053
v.SetElement( i, j, vbasis[ i ][ j ] );
4056
u.SetfIdentity( TqFalse );
4057
v.SetfIdentity( TqFalse );
4059
QGetRenderContext() ->pattrWriteCurrent() ->GetMatrixAttributeWrite( "System", "Basis" ) [ 0 ] = u;
4060
QGetRenderContext() ->pattrWriteCurrent() ->GetMatrixAttributeWrite( "System", "Basis" ) [ 1 ] = v;
4061
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "BasisStep" ) [ 0 ] = ustep;
4062
QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "BasisStep" ) [ 1 ] = vstep;
4063
QGetRenderContext() ->AdvanceTime();
4068
//----------------------------------------------------------------------
4070
// Specify a new patch primitive.
4072
RtVoid RiPatch( RtToken type, ... )
4074
EXTRACT_PARAMETERS( type )
4076
RiPatchV( type, PASS_PARAMETERS );
4080
//----------------------------------------------------------------------
4082
// List based version of above.
4084
RtVoid RiPatchV( RtToken type, PARAMETERLIST )
4086
VALIDATE_CONDITIONAL
4094
if ( strcmp( type, RI_BICUBIC ) == 0 )
4096
// Create a surface patch
4097
boost::shared_ptr<CqSurfacePatchBicubic> pSurface( new CqSurfacePatchBicubic() );
4098
// Fill in primitive variables specified.
4099
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
4101
// Fill in default values for all primitive variables not explicitly specified.
4102
pSurface->SetDefaultPrimitiveVariables();
4103
CqMatrix matuBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 0 ];
4104
CqMatrix matvBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 1 ];
4105
pSurface->ConvertToBezierBasis( matuBasis, matvBasis );
4107
TqFloat time = QGetRenderContext()->Time();
4108
// Transform the points into camera space for processing,
4109
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4110
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4111
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4113
CreateGPrim( pSurface );
4116
else if ( strcmp( type, RI_BILINEAR ) == 0 )
4118
// Create a surface patch
4119
boost::shared_ptr<CqSurfacePatchBilinear> pSurface( new CqSurfacePatchBilinear() );
4120
// Fill in primitive variables specified.
4121
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
4123
// Fill in default values for all primitive variables not explicitly specified.
4124
pSurface->SetDefaultPrimitiveVariables();
4125
TqFloat time = QGetRenderContext()->Time();
4126
// Transform the points into camera space for processing,
4127
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4128
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4129
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4130
CreateGPrim( pSurface );
4135
Aqsis::log() << error << "RiPatch invalid patch type \"" << type << "\"" << std::endl;
4142
//----------------------------------------------------------------------
4144
// Specify a quadrilaterla mesh of patches.
4146
RtVoid RiPatchMesh( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, ... )
4148
EXTRACT_PARAMETERS( vwrap )
4150
RiPatchMeshV( type, nu, uwrap, nv, vwrap, PASS_PARAMETERS );
4154
//----------------------------------------------------------------------
4156
// List based version of above.
4159
RtVoid RiPatchMeshV( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, PARAMETERLIST )
4161
VALIDATE_CONDITIONAL
4165
VALIDATE_RIPATCHMESH
4169
if( strcmp( uwrap, RI_PERIODIC ) && strcmp( uwrap, RI_NONPERIODIC ) )
4170
Aqsis::log() << error << "RiPatchMesh invalid u-wrap type: \"" << uwrap << "\"" << std::endl;
4172
if( strcmp( vwrap, RI_PERIODIC ) && strcmp( vwrap, RI_NONPERIODIC ) )
4173
Aqsis::log() << error << "RiPatchMesh invalid v-wrap type: \"" << vwrap << "\"" << std::endl;
4175
if ( strcmp( type, RI_BICUBIC ) == 0 )
4177
// Create a surface patch
4178
TqBool uPeriodic = ( strcmp( uwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
4179
TqBool vPeriodic = ( strcmp( vwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
4181
boost::shared_ptr<CqSurfacePatchMeshBicubic> pSurface( new CqSurfacePatchMeshBicubic( nu, nv, uPeriodic, vPeriodic ) );
4182
// Fill in primitive variables specified.
4183
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
4185
// Fill in default values for all primitive variables not explicitly specified.
4186
pSurface->SetDefaultPrimitiveVariables();
4187
std::vector<boost::shared_ptr<CqSurface> > aSplits;
4188
pSurface->Split( aSplits );
4189
std::vector<boost::shared_ptr<CqSurface> >::iterator iSS;
4190
for ( iSS = aSplits.begin(); iSS != aSplits.end(); ++iSS )
4192
CqMatrix matuBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 0 ];
4193
CqMatrix matvBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 1 ];
4194
static_cast<CqSurfacePatchBicubic*>( iSS->get
4195
() ) ->ConvertToBezierBasis( matuBasis, matvBasis );
4196
TqFloat time = QGetRenderContext()->Time();
4197
// Transform the points into camera space for processing,
4198
(*iSS)->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4199
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4200
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4201
CreateGPrim( *iSS );
4205
else if ( strcmp( type, RI_BILINEAR ) == 0 )
4207
// Create a surface patch
4208
TqBool uPeriodic = ( strcmp( uwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
4209
TqBool vPeriodic = ( strcmp( vwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
4211
boost::shared_ptr<CqSurfacePatchMeshBilinear> pSurface( new CqSurfacePatchMeshBilinear( nu, nv, uPeriodic, vPeriodic ) );
4212
// Fill in primitive variables specified.
4213
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
4215
// Fill in default values for all primitive variables not explicitly specified.
4216
pSurface->SetDefaultPrimitiveVariables();
4217
TqFloat time = QGetRenderContext()->Time();
4218
// Transform the points into camera space for processing,
4219
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4220
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4221
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4222
CreateGPrim( pSurface );
4227
Aqsis::log() << error << "RiPatchMesh invalid type \"" << type << "\"" << std::endl;
4234
//----------------------------------------------------------------------
4236
// Specify a new non uniform patch.
4238
RtVoid RiNuPatch( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
4239
RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, ... )
4241
EXTRACT_PARAMETERS( vmax )
4243
RiNuPatchV( nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, PASS_PARAMETERS );
4247
//----------------------------------------------------------------------
4249
// List based version of above.
4251
RtVoid RiNuPatchV( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
4252
RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, PARAMETERLIST )
4254
VALIDATE_CONDITIONAL
4262
// Create a NURBS patch
4263
boost::shared_ptr<CqSurfaceNURBS> pSurface( new CqSurfaceNURBS() );
4264
pSurface->SetfPatchMesh();
4265
pSurface->Init( uorder, vorder, nu, nv );
4267
pSurface->Setumin( umin );
4268
pSurface->Setumax( umax );
4269
pSurface->Setvmin( vmin );
4270
pSurface->Setvmax( vmax );
4272
// Copy the knot vectors.
4274
for ( i = 0; i < nu + uorder; ++i )
4275
pSurface->auKnots() [ i ] = uknot[ i ];
4276
for ( i = 0; i < nv + vorder; ++i )
4277
pSurface->avKnots() [ i ] = vknot[ i ];
4279
// Process any specified parameters
4280
if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
4282
// Set up the default primitive variables.
4283
pSurface->SetDefaultPrimitiveVariables();
4284
// Clamp the surface to ensure non-periodic.
4286
TqFloat time = QGetRenderContext()->Time();
4287
// Transform the points into camera space for processing,
4288
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4289
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4290
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4291
CreateGPrim( pSurface );
4297
//----------------------------------------------------------------------
4299
// Specify curves which are used to trim NURBS surfaces.
4301
RtVoid RiTrimCurve( RtInt nloops, RtInt ncurves[], RtInt order[], RtFloat knot[], RtFloat min[], RtFloat max[], RtInt n[], RtFloat u[], RtFloat v[], RtFloat w[] )
4303
VALIDATE_CONDITIONAL
4307
VALIDATE_RITRIMCURVE
4311
// Clear the current loop array.
4312
QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().Clear();
4314
// Build an array of curves per specified loop.
4321
for ( iloop = 0; iloop < nloops; ++iloop )
4325
for ( icurve = 0; icurve < ncurves[ iloop ]; ++icurve )
4327
// Create a NURBS patch
4329
TqInt o = order[ iorder++ ];
4330
TqInt cverts = n[ in++ ];
4331
Curve.Init( o, cverts );
4333
// Copy the knot vectors.
4335
for ( i = 0; i < o + cverts; ++i )
4336
Curve.aKnots() [ i ] = knot[ iknot++ ];
4338
// Copy the vertices from the u,v,w arrays.
4339
CqVector3D vec( 0, 0, 1 );
4340
for ( i = 0; i < cverts; ++i )
4342
vec.x( u[ ivert ] );
4343
vec.y( v[ ivert ] );
4344
vec.z( w[ ivert++ ] );
4345
Curve.CP( i ) = vec;
4347
Loop.aCurves().push_back( Curve );
4349
QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().aLoops().push_back( Loop );
4356
//----------------------------------------------------------------------
4358
// Specify a sphere primitive.
4360
RtVoid RiSphere( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4362
EXTRACT_PARAMETERS( thetamax )
4364
RiSphereV( radius, zmin, zmax, thetamax, PASS_PARAMETERS );
4368
//----------------------------------------------------------------------
4370
// List based version of above.
4372
RtVoid RiSphereV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4374
VALIDATE_CONDITIONAL
4382
CqLogRangeCheckCallback rc;
4384
rc.set( "sphere zmin" );
4385
CheckMinMax( zmin, MIN(-radius, radius), MAX(-radius,radius), &rc );
4386
rc.set( "sphere zmax" );
4387
CheckMinMax( zmax, MIN(-radius, radius), MAX(-radius,radius), &rc );
4390
boost::shared_ptr<CqSphere> pSurface( new CqSphere( radius, zmin, zmax, 0, thetamax ) );
4391
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4392
pSurface->SetDefaultPrimitiveVariables();
4394
TqFloat time = QGetRenderContext()->Time();
4395
// Transform the points into camera space for processing,
4396
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4397
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4398
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4399
CreateGPrim( pSurface );
4405
//----------------------------------------------------------------------
4407
// Specify a cone primitive.
4409
RtVoid RiCone( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
4411
EXTRACT_PARAMETERS( thetamax )
4413
RiConeV( height, radius, thetamax, PASS_PARAMETERS );
4417
//----------------------------------------------------------------------
4419
// List based version of above.
4421
RtVoid RiConeV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
4423
VALIDATE_CONDITIONAL
4431
/// \note This should be an exception and get caught further up.
4436
boost::shared_ptr<CqCone> pSurface( new CqCone( height, radius, 0, thetamax, 0, 1.0f ) );
4437
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4438
pSurface->SetDefaultPrimitiveVariables();
4440
TqFloat time = QGetRenderContext()->Time();
4441
// Transform the points into camera space for processing,
4442
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4443
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4444
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4445
CreateGPrim( pSurface );
4451
//----------------------------------------------------------------------
4453
// Specify a culinder primitive.
4455
RtVoid RiCylinder( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4457
EXTRACT_PARAMETERS( thetamax )
4459
RiCylinderV( radius, zmin, zmax, thetamax, PASS_PARAMETERS );
4463
//----------------------------------------------------------------------
4465
// List based version of above.
4467
RtVoid RiCylinderV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4469
VALIDATE_CONDITIONAL
4477
// Create a cylinder
4478
boost::shared_ptr<CqCylinder> pSurface( new CqCylinder( radius, zmin, zmax, 0, thetamax ) );
4479
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4480
pSurface->SetDefaultPrimitiveVariables();
4482
TqFloat time = QGetRenderContext()->Time();
4483
// Transform the points into camera space for processing,
4484
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4485
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4486
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4487
CreateGPrim( pSurface );
4493
//----------------------------------------------------------------------
4495
// Specify a hyperboloid primitive.
4497
RtVoid RiHyperboloid( RtPoint point1, RtPoint point2, RtFloat thetamax, ... )
4499
EXTRACT_PARAMETERS( thetamax )
4501
RiHyperboloidV( point1, point2, thetamax, PASS_PARAMETERS );
4505
//----------------------------------------------------------------------
4507
// List based version of above.
4509
RtVoid RiHyperboloidV( RtPoint point1, RtPoint point2, RtFloat thetamax, PARAMETERLIST )
4511
VALIDATE_CONDITIONAL
4515
VALIDATE_RIHYPERBOLOID
4519
// Create a hyperboloid
4520
CqVector3D v0( point1[ 0 ], point1[ 1 ], point1[ 2 ] );
4521
CqVector3D v1( point2[ 0 ], point2[ 1 ], point2[ 2 ] );
4522
boost::shared_ptr<CqHyperboloid> pSurface( new CqHyperboloid( v0, v1, 0, thetamax ) );
4523
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4524
pSurface->SetDefaultPrimitiveVariables();
4526
TqFloat time = QGetRenderContext()->Time();
4527
// Transform the points into camera space for processing,
4528
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4529
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4530
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4531
CreateGPrim( pSurface );
4537
//----------------------------------------------------------------------
4539
// Specify a paraboloid primitive.
4541
RtVoid RiParaboloid( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4543
EXTRACT_PARAMETERS( thetamax )
4545
RiParaboloidV( rmax, zmin, zmax, thetamax, PASS_PARAMETERS );
4549
//----------------------------------------------------------------------
4551
// List based version of above.
4553
RtVoid RiParaboloidV( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4555
VALIDATE_CONDITIONAL
4559
VALIDATE_RIPARABOLOID
4563
// Create a paraboloid
4564
boost::shared_ptr<CqParaboloid> pSurface( new CqParaboloid( rmax, zmin, zmax, 0, thetamax ) );
4565
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4566
pSurface->SetDefaultPrimitiveVariables();
4568
TqFloat time = QGetRenderContext()->Time();
4569
// Transform the points into camera space for processing,
4570
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4571
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4572
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4573
CreateGPrim( pSurface );
4579
//----------------------------------------------------------------------
4581
// Specify a disk primitive.
4583
RtVoid RiDisk( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
4585
EXTRACT_PARAMETERS( thetamax )
4587
RiDiskV( height, radius, thetamax, PASS_PARAMETERS );
4591
//----------------------------------------------------------------------
4593
// List based version of above.
4595
RtVoid RiDiskV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
4597
VALIDATE_CONDITIONAL
4606
boost::shared_ptr<CqDisk> pSurface( new CqDisk( height, 0, radius, 0, thetamax ) );
4607
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4608
pSurface->SetDefaultPrimitiveVariables();
4610
TqFloat time = QGetRenderContext()->Time();
4611
// Transform the points into camera space for processing,
4612
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4613
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4614
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4616
CreateGPrim( pSurface );
4622
//----------------------------------------------------------------------
4625
RtVoid RiTorus( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, ... )
4627
EXTRACT_PARAMETERS( thetamax )
4629
RiTorusV( majorrad, minorrad, phimin, phimax, thetamax, PASS_PARAMETERS );
4633
//----------------------------------------------------------------------
4635
// Specify a torus primitive.
4637
RtVoid RiTorusV( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, PARAMETERLIST )
4639
VALIDATE_CONDITIONAL
4648
boost::shared_ptr<CqTorus> pSurface( new CqTorus( majorrad, minorrad, phimin, phimax, 0, thetamax ) );
4649
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4650
pSurface->SetDefaultPrimitiveVariables();
4652
TqFloat time = QGetRenderContext()->Time();
4653
// Transform the points into camera space for processing,
4654
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4655
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4656
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4658
CreateGPrim( pSurface );
4664
//----------------------------------------------------------------------
4666
// Implement the procedural type primitive.
4668
RtVoid RiProcedural( RtPointer data, RtBound bound, RtProcSubdivFunc refineproc, RtProcFreeFunc freeproc )
4670
VALIDATE_CONDITIONAL
4674
VALIDATE_RIPROCEDURAL
4680
//printf("bound(%f %f %f %f %f %f)\n", bound[0], bound[1], bound[2], bound[3], bound[4], bound[5]);
4682
// I suspect that in order to handle the RtFreeProc correctly that we need to reference count
4683
// the instances of CqProcedural so that FreeProc gets called on the final Release();
4685
boost::shared_ptr<CqProcedural> pProc( new CqProcedural(data, B, refineproc, freeproc ) );
4686
TqFloat time = QGetRenderContext()->Time();
4687
pProc->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pProc->pTransform().get(), time ),
4688
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pProc->pTransform().get(), time ),
4689
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pProc->pTransform().get(), time ) );
4690
CreateGPrim( pProc );
4697
//----------------------------------------------------------------------
4699
// Specify a special primitive.
4701
RtVoid RiGeometry( RtToken type, ... )
4703
EXTRACT_PARAMETERS( type )
4705
RiGeometryV( type, PASS_PARAMETERS );
4709
//----------------------------------------------------------------------
4711
// List based version of above.
4713
RtVoid RiGeometryV( RtToken type, PARAMETERLIST )
4715
VALIDATE_CONDITIONAL
4723
if ( strcmp( type, "teapot" ) == 0 )
4726
// Create a standard teapot
4727
boost::shared_ptr<CqTeapot> pSurface( new CqTeapot( true ) ); // add a bottom if true/false otherwise
4729
pSurface->SetSurfaceParameters( *pSurface );
4730
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4731
pSurface->SetDefaultPrimitiveVariables();
4733
// I don't use the original teapot primitives as defined by T. Burge
4734
// but an array of Patch Bicubic (stolen from example from Pixar) and
4735
// those (6 meshes) are registered as standards GPrims right here.
4736
// Basically I kept the bound, transform and split, dice and diceable methods
4737
// in teapot.cpp but I suspect they are never called since the work of
4738
// dicing will rely on the registered Gprimitives (see below in the for loop).
4739
// I suspect the 6/7 meshes are equivalent in size/definition as the T. Burge
4740
// definition. The 7th is the bottom part of the teapot (see teapot.cpp).
4742
for ( int i = 0; i < pSurface->cNbrPatchMeshBicubic; ++i )
4744
boost::shared_ptr<CqSurface> pMesh = pSurface->pPatchMeshBicubic[ i ];
4746
TqFloat time = QGetRenderContext()->Time();
4747
// Transform the points into camera space for processing,
4748
pMesh->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4749
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4750
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4752
CreateGPrim( boost::static_pointer_cast<CqSurface>( pMesh ) );
4755
else if ( strcmp( type, "sphere" ) == 0 )
4758
boost::shared_ptr<CqSphere> pSurface( new CqSphere( 1, -1, 1, 0, 360.0 ) );
4759
ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4760
pSurface->SetDefaultPrimitiveVariables();
4762
TqFloat time = QGetRenderContext()->Time();
4763
// Transform the points into camera space for processing,
4764
pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4765
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ),
4766
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pSurface->pTransform().get(), time ) );
4768
CreateGPrim( pSurface );
4769
} else if ( strcmp( type, "bunny" ) == 0 )
4773
std::vector<RtToken> aTokens;
4774
std::vector<RtPointer> aValues;
4775
std::vector<RtToken> aTags;
4781
aTokens.push_back(RI_P);
4782
aTokens.push_back(RI_S);
4783
aTokens.push_back(RI_T);
4784
aValues.push_back(bunny.Points());
4785
aValues.push_back(bunny.S());
4786
aValues.push_back(bunny.T());
4787
aTags.push_back("catmull-clark");
4788
aTags.push_back("interpolateboundary");
4790
static TqInt params[] = { 0, 0 };
4793
// Rotate and scale to match the teapot geometry
4795
RiTranslate(0.0, 0.0, 2.5);
4796
RiRotate(90.0, 1.0, 0.0, 0.0);
4797
RiScale(1.0/30.0, 1.0/30.0, 1.0/30.0);
4798
RiSubdivisionMeshV( aTags[0],
4812
Aqsis::log() << warning << "RiGeometry unrecognised type \"" << type << "\"" << std::endl;
4818
//----------------------------------------------------------------------
4820
// Begin the definition of a CSG object.
4822
RtVoid RiSolidBegin( RtToken type )
4824
VALIDATE_CONDITIONAL
4828
VALIDATE_RISOLIDBEGIN
4832
CqString strType( type );
4833
QGetRenderContext() ->BeginSolidModeBlock( strType );
4839
//----------------------------------------------------------------------
4841
// End the definition of a CSG object.
4845
VALIDATE_CONDITIONAL
4853
QGetRenderContext() ->EndSolidModeBlock();
4859
//----------------------------------------------------------------------
4861
// Begin the definition of a stored object for use by RiObjectInstance.
4863
RtObjectHandle RiObjectBegin()
4865
VALIDATE_CONDITIONAL0
4869
VALIDATE_RIOBJECTBEGIN
4873
QGetRenderContext() ->BeginObjectModeBlock();
4874
RtObjectHandle ObjectHandle = static_cast<RtObjectHandle>(QGetRenderContext() ->OpenNewObjectInstance());
4876
return ( ObjectHandle );
4880
//----------------------------------------------------------------------
4882
// End the defintion of a stored object for use by RiObjectInstance.
4884
RtVoid RiObjectEnd()
4886
VALIDATE_CONDITIONAL
4888
VALIDATE_RIOBJECTEND
4892
QGetRenderContext() ->EndObjectModeBlock();
4893
QGetRenderContext() ->CloseObjectInstance();
4901
//----------------------------------------------------------------------
4903
// Instantiate a copt of a pre-stored geometric object.
4905
RtVoid RiObjectInstance( RtObjectHandle handle )
4907
VALIDATE_CONDITIONAL
4909
CACHE_RIOBJECTINSTANCE
4911
VALIDATE_RIOBJECTINSTANCE
4913
DEBUG_RIOBJECTINSTANCE
4915
QGetRenderContext() ->InstantiateObject( reinterpret_cast<CqObjectInstance*>( handle ) );
4920
//----------------------------------------------------------------------
4922
// Begin the definition of the motion of an object for use by motion blur.
4924
RtVoid RiMotionBegin( RtInt N, ... )
4927
va_start( pArgs, N );
4929
RtFloat* times = new RtFloat[ N ];
4931
for ( i = 0; i < N; ++i )
4932
times[ i ] = va_arg( pArgs, double );
4934
RiMotionBeginV( N, times );
4941
//----------------------------------------------------------------------
4943
// List based version of above.
4945
RtVoid RiMotionBeginV( RtInt N, RtFloat times[] )
4947
VALIDATE_CONDITIONAL
4949
CACHE_RIMOTIONBEGINV
4951
VALIDATE_RIMOTIONBEGINV
4953
DEBUG_RIMOTIONBEGINV
4955
QGetRenderContext() ->BeginMotionModeBlock( N, times );
4961
//----------------------------------------------------------------------
4963
// End the definition of the motion of an object.
4965
RtVoid RiMotionEnd()
4967
VALIDATE_CONDITIONAL
4971
VALIDATE_RIMOTIONEND
4975
QGetRenderContext() ->EndMotionModeBlock();
4981
//----------------------------------------------------------------------
4983
// Convert a picture to a texture.
4985
RtVoid RiMakeTexture ( RtString pic, RtString tex, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
4987
EXTRACT_PARAMETERS( twidth )
4989
RiMakeTextureV( pic, tex, swrap, twrap, filterfunc, swidth, twidth, PASS_PARAMETERS );
4994
//----------------------------------------------------------------------
4996
// List based version of above.
4998
RtVoid RiMakeTextureV( RtString imagefile, RtString texturefile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
5000
VALIDATE_CONDITIONAL
5004
VALIDATE_RIMAKETEXTURE
5009
assert( imagefile != 0 && texturefile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
5011
TIME_SCOPE("Texture")
5012
// Get the wrap modes first.
5013
enum EqWrapMode smode = WrapMode_Black;
5014
if ( strcmp( swrap, RI_PERIODIC ) == 0 )
5015
smode = WrapMode_Periodic;
5016
else if ( strcmp( swrap, RI_CLAMP ) == 0 )
5017
smode = WrapMode_Clamp;
5018
else if ( strcmp( swrap, RI_BLACK ) == 0 )
5019
smode = WrapMode_Black;
5021
enum EqWrapMode tmode = WrapMode_Black;
5022
if ( strcmp( twrap, RI_PERIODIC ) == 0 )
5023
tmode = WrapMode_Periodic;
5024
else if ( strcmp( twrap, RI_CLAMP ) == 0 )
5025
tmode = WrapMode_Clamp;
5026
else if ( strcmp( twrap, RI_BLACK ) == 0 )
5027
tmode = WrapMode_Black;
5030
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
5031
if ( filterfunc == RiGaussianFilter )
5032
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "gaussian", swidth, twidth );
5033
if ( filterfunc == RiMitchellFilter )
5034
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "mitchell", swidth, twidth );
5035
if ( filterfunc == RiBoxFilter )
5036
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
5037
if ( filterfunc == RiTriangleFilter )
5038
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "triangle", swidth, twidth );
5039
if ( filterfunc == RiCatmullRomFilter )
5040
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "catmull-rom", swidth, twidth );
5041
if ( filterfunc == RiSincFilter )
5042
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "sinc", swidth, twidth );
5043
if ( filterfunc == RiDiskFilter )
5044
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "disk", swidth, twidth );
5045
if ( filterfunc == RiBesselFilter )
5046
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "bessel", swidth, twidth );
5049
// Now load the original image.
5050
CqTextureMap Source( imagefile );
5053
ProcessCompression( &comp, &qual, count, tokens, values );
5054
Source.SetCompression( comp );
5055
Source.SetQuality( qual );
5057
if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
5059
// Hopefully CqTextureMap will take care of closing the tiff file after
5060
// it has SAT mapped it so we can overwrite if needs be.
5061
// Create a new image.
5062
Source.Interpreted( modes );
5063
Source.CreateMIPMAP();
5064
TIFF* ptex = TIFFOpen( texturefile, "w" );
5066
TIFFCreateDirectory( ptex );
5067
TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
5068
TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, MIPMAP_HEADER );
5069
TIFFSetField( ptex, TIFFTAG_PIXAR_WRAPMODES, modes );
5070
TIFFSetField( ptex, TIFFTAG_COMPRESSION, Source.Compression() ); /* COMPRESSION_DEFLATE */
5071
int log2 = MIN( Source.XRes(), Source.YRes() );
5072
log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
5075
for ( int i = 0; i < log2; ++i )
5077
// Write the floating point image to the directory.
5078
CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
5081
Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
5090
//----------------------------------------------------------------------
5092
// Convert a picture to a bump map.
5094
RtVoid RiMakeBump( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
5096
Aqsis::log() << warning << "RiMakeBump not supported" << std::endl;
5101
//----------------------------------------------------------------------
5103
// List based version of above.
5105
RtVoid RiMakeBumpV( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
5107
VALIDATE_CONDITIONAL
5115
Aqsis::log() << warning << "RiMakeBump not supported" << std::endl;
5120
//----------------------------------------------------------------------
5121
// RiMakeLatLongEnvironment
5122
// Convert a picture to an environment map.
5124
RtVoid RiMakeLatLongEnvironment( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
5126
EXTRACT_PARAMETERS( twidth )
5128
RiMakeLatLongEnvironmentV( imagefile, reflfile, filterfunc, swidth, twidth, PASS_PARAMETERS );
5133
//----------------------------------------------------------------------
5134
// RiMakeLatLongEnvironmentV
5135
// List based version of above.
5137
RtVoid RiMakeLatLongEnvironmentV( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
5139
VALIDATE_CONDITIONAL
5141
CACHE_RIMAKELATLONGENVIRONMENT
5143
VALIDATE_RIMAKELATLONGENVIRONMENT
5145
DEBUG_RIMAKELATLONGENVIRONMENT
5148
char *swrap = "periodic";
5149
char *twrap = "clamp";
5151
assert( imagefile != 0 && reflfile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
5153
TIME_SCOPE("Environment Mapping")
5155
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
5156
if ( filterfunc == RiGaussianFilter )
5157
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "gaussian", swidth, twidth );
5158
if ( filterfunc == RiMitchellFilter )
5159
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "mitchell", swidth, twidth );
5160
if ( filterfunc == RiBoxFilter )
5161
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
5162
if ( filterfunc == RiTriangleFilter )
5163
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "triangle", swidth, twidth );
5164
if ( filterfunc == RiCatmullRomFilter )
5165
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "catmull-rom", swidth, twidth );
5166
if ( filterfunc == RiSincFilter )
5167
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "sinc", swidth, twidth );
5168
if ( filterfunc == RiDiskFilter )
5169
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "disk", swidth, twidth );
5170
if ( filterfunc == RiBesselFilter )
5171
sprintf( modes, "%s %s %s %f %f", swrap, twrap, "bessel", swidth, twidth );
5174
// Now load the original image.
5175
CqTextureMap Source( imagefile );
5178
ProcessCompression( &comp, &qual, count, tokens, values );
5179
Source.SetCompression( comp );
5180
Source.SetQuality( qual );
5182
if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
5184
// Hopefully CqTextureMap will take care of closing the tiff file after
5185
// it has SAT mapped it so we can overwrite if needs be.
5186
// Create a new image.
5187
Source.Interpreted( modes );
5188
Source.CreateMIPMAP();
5189
TIFF* ptex = TIFFOpen( reflfile, "w" );
5191
TIFFCreateDirectory( ptex );
5192
TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
5193
TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, LATLONG_HEADER );
5194
TIFFSetField( ptex, TIFFTAG_PIXAR_WRAPMODES, modes );
5195
TIFFSetField( ptex, TIFFTAG_SAMPLESPERPIXEL, Source.SamplesPerPixel() );
5196
TIFFSetField( ptex, TIFFTAG_BITSPERSAMPLE, 8 );
5197
TIFFSetField( ptex, TIFFTAG_COMPRESSION, Source.Compression() ); /* COMPRESSION_DEFLATE */
5198
int log2 = MIN( Source.XRes(), Source.YRes() );
5199
log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
5202
for ( int i = 0; i < log2; ++i )
5204
// Write the floating point image to the directory.
5205
CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
5208
Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
5218
//----------------------------------------------------------------------
5219
// RiMakeCubeFaceEnvironment
5220
// Convert a picture to a cubical environment map.
5222
RtVoid RiMakeCubeFaceEnvironment( RtString px, RtString nx, RtString py, RtString ny, RtString pz, RtString nz, RtString reflfile, RtFloat fov, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
5224
EXTRACT_PARAMETERS( twidth )
5226
RiMakeCubeFaceEnvironmentV( px, nx, py, ny, pz, nz, reflfile, fov, filterfunc, swidth, twidth, PASS_PARAMETERS );
5230
//----------------------------------------------------------------------
5231
// RiMakeCubeFaceEnvironment
5232
// List based version of above.
5234
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 )
5236
VALIDATE_CONDITIONAL
5238
CACHE_RIMAKECUBEFACEENVIRONMENT
5240
VALIDATE_RIMAKECUBEFACEENVIRONMENT
5242
DEBUG_RIMAKECUBEFACEENVIRONMENT
5244
TIME_SCOPE("Environment Mapping")
5245
assert( px != 0 && nx != 0 && py != 0 && ny != 0 && pz != 0 && nz != 0 &&
5246
reflfile != 0 && filterfunc != 0 );
5248
// Now load the original image.
5249
CqTextureMap tpx( px );
5250
CqTextureMap tnx( nx );
5251
CqTextureMap tpy( py );
5252
CqTextureMap tny( ny );
5253
CqTextureMap tpz( pz );
5254
CqTextureMap tnz( nz );
5263
if ( tpx.Format() != TexFormat_MIPMAP )
5265
if ( tnx.Format() != TexFormat_MIPMAP )
5267
if ( tpy.Format() != TexFormat_MIPMAP )
5269
if ( tny.Format() != TexFormat_MIPMAP )
5271
if ( tpz.Format() != TexFormat_MIPMAP )
5273
if ( tnz.Format() != TexFormat_MIPMAP )
5275
if ( tpx.IsValid() && tnx.IsValid() && tpy.IsValid() && tny.IsValid() && tpz.IsValid() && tnz.IsValid() )
5277
// Check all the same size;
5278
bool fValid = false;
5279
if ( tpx.XRes() == tnx.XRes() && tpx.XRes() == tpy.XRes() && tpx.XRes() == tny.XRes() && tpx.XRes() == tpz.XRes() && tpx.XRes() == tnz.XRes() &&
5280
tpx.XRes() == tnx.XRes() && tpx.XRes() == tpy.XRes() && tpx.XRes() == tny.XRes() && tpx.XRes() == tpz.XRes() && tpx.XRes() == tnz.XRes() )
5285
Aqsis::log() << error << "RiMakeCubeFaceEnvironment all images must be the same size" << std::endl;
5289
// Now copy the images to the big map.
5290
CqTextureMap* Images[ 6 ] =
5300
// Create a new image.
5301
TIFF* ptex = TIFFOpen( reflfile, "w" );
5304
TqInt xRes = tpx.XRes();
5305
TqInt yRes = tpx.YRes();
5307
TqInt numsamples = tpx.SamplesPerPixel();
5308
// Number of mip map levels.
5309
int log2 = MIN( xRes, yRes );
5310
log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
5312
for ( ii = 0; ii < log2; ++ii )
5314
CqTextureMapBuffer* pLevelBuffer = tpx.CreateBuffer( 0, 0, xRes * 3, yRes * 2, numsamples );
5316
for ( view = 0; view < 6; ++view )
5318
// Get the buffer for the approriate cube side at this level.
5319
CqTextureMapBuffer* pBuffer = Images[ view ] ->GetBuffer( 0, 0, ii );
5320
// Work out where in the combined image it goes.
5321
TqInt xoff = view % 3;
5323
TqInt yoff = view / 3;
5325
TqInt line, col, sample;
5326
for ( line = 0; line < yRes; ++line )
5328
for ( col = 0; col < xRes; ++col )
5330
for ( sample = 0; sample < numsamples; ++sample )
5331
pLevelBuffer->SetValue( col + xoff, line + yoff, sample, pBuffer->GetValue( col, line, sample ) );
5336
TIFFCreateDirectory( ptex );
5337
TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
5338
TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, CUBEENVMAP_HEADER );
5339
TIFFSetField( ptex, TIFFTAG_PIXAR_FOVCOT, 1.0/tan(RAD(fov)/2.0) );
5340
tpx.WriteTileImage( ptex, pLevelBuffer, 64, 64, tpx.Compression(), tpx.Quality() );
5350
//----------------------------------------------------------------------
5352
// Convert a depth map file to a shadow map.
5354
RtVoid RiMakeShadow( RtString picfile, RtString shadowfile, ... )
5356
EXTRACT_PARAMETERS( shadowfile )
5358
RiMakeShadowV( picfile, shadowfile, PASS_PARAMETERS );
5362
//----------------------------------------------------------------------
5364
// List based version of above.
5366
RtVoid RiMakeShadowV( RtString picfile, RtString shadowfile, PARAMETERLIST )
5368
VALIDATE_CONDITIONAL
5372
VALIDATE_RIMAKESHADOW
5376
TIME_SCOPE("Shadow Mapping")
5377
CqShadowMap ZFile( picfile );
5381
ProcessCompression( &comp, &qual, count, tokens, values );
5382
ZFile.SetCompression( comp );
5383
ZFile.SetQuality( qual );
5385
ZFile.SaveShadowMap( shadowfile );
5390
//----------------------------------------------------------------------
5392
// Convert a series of depth maps to an occlusion map.
5394
RtVoid RiMakeOcclusion( RtInt npics, RtString picfiles[], RtString shadowfile, ... )
5396
EXTRACT_PARAMETERS( shadowfile )
5398
RiMakeOcclusionV( npics, picfiles, shadowfile, PASS_PARAMETERS );
5402
//----------------------------------------------------------------------
5404
// List based version of above.
5406
RtVoid RiMakeOcclusionV( RtInt npics, RtString picfiles[], RtString shadowfile, RtInt count, RtToken tokens[], RtPointer values[] )
5408
VALIDATE_CONDITIONAL
5410
CACHE_RIMAKEOCCLUSION
5412
VALIDATE_RIMAKEOCCLUSION
5414
DEBUG_RIMAKEOCCLUSION
5416
TIME_SCOPE("Shadow Mapping")
5420
for( index = 0; index < npics; ++index )
5422
CqShadowMap ZFile( picfiles[index] );
5426
ProcessCompression( &comp, &qual, count, tokens, values );
5427
ZFile.SetCompression( comp );
5428
ZFile.SetQuality( qual );
5430
ZFile.SaveShadowMap( shadowfile, TqTrue );
5435
//----------------------------------------------------------------------
5436
/** Conditional handlers for 3.4 new RI Tokens
5437
* It calls TestCondition(); expect to modify the global variable IfOk.
5440
RtVoid RiIfBegin( RtString condition )
5442
IfOk = TestCondition(condition, "RiIfBegin");
5445
RtVoid RiElseIf( RtString condition )
5447
IfOk = TestCondition(condition, "RiElseIf");
5460
//----------------------------------------------------------------------
5462
// Set the function used to report errors.
5464
RtVoid RiErrorHandler( RtErrorFunc handler )
5466
VALIDATE_CONDITIONAL
5468
CACHE_RIERRORHANDLER
5470
VALIDATE_RIERRORHANDLER
5472
DEBUG_RIERRORHANDLER
5474
QGetRenderContext()->SetpErrorHandler( handler );
5479
//----------------------------------------------------------------------
5481
// Function used by RiErrorHandler to continue after errors.
5483
RtVoid RiErrorIgnore( RtInt code, RtInt severity, RtString message )
5489
//----------------------------------------------------------------------
5491
// Function used by RiErrorHandler to print an error message to stdout and continue.
5493
RtVoid RiErrorPrint( RtInt code, RtInt severity, RtString message )
5496
Aqsis::log() << error << "RiError: " << code << " : " << severity << " : " << message << std::endl;
5501
//----------------------------------------------------------------------
5503
// Function used by RiErrorHandler to print and error and stop.
5505
RtVoid RiErrorAbort( RtInt code, RtInt severity, RtString message )
5511
//----------------------------------------------------------------------
5512
// RiSubdivisionMesh
5513
// Specify a subdivision surface hull with tagging.
5515
RtVoid RiSubdivisionMesh( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], ... )
5517
EXTRACT_PARAMETERS( floatargs )
5519
RiSubdivisionMeshV( scheme, nfaces, nvertices, vertices, ntags, tags, nargs, intargs, floatargs, PASS_PARAMETERS );
5522
//----------------------------------------------------------------------
5523
// RiSubdivisionMeshV
5524
// List based version of above.
5526
RtVoid RiSubdivisionMeshV( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], PARAMETERLIST )
5528
VALIDATE_CONDITIONAL
5530
CACHE_RISUBDIVISIONMESH
5532
VALIDATE_RISUBDIVISIONMESH
5534
DEBUG_RISUBDIVISIONMESH
5536
// Calculate how many vertices there are.
5538
RtInt* pVerts = vertices;
5540
RtInt sumnVerts = 0;
5541
for ( face = 0; face < nfaces; ++face )
5544
sumnVerts += nvertices[ face ];
5545
for ( v = 0; v < nvertices[ face ]; ++v )
5547
cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
5552
// Create a storage class for all the points.
5553
boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, nfaces, sumnVerts ) );
5555
std::vector<boost::shared_ptr<CqPolygonPoints> > apPoints;
5556
// Process any specified primitive variables
5557
if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
5559
// Create experimental version
5560
if ( strcmp( scheme, "catmull-clark" ) == 0 )
5562
// Transform the points into camera space for processing,
5563
TqFloat time = QGetRenderContext()->Time();
5564
pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), time ),
5565
QGetRenderContext() ->matNSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), time ),
5566
QGetRenderContext() ->matVSpaceToSpace( "object", "world", NULL, pPointsClass->pTransform().get(), time ) );
5568
boost::shared_ptr<CqSubdivision2> pSubd2( new CqSubdivision2( pPointsClass ) );
5569
pSubd2->Prepare( cVerts );
5571
boost::shared_ptr<CqSurfaceSubdivisionMesh> pMesh( new CqSurfaceSubdivisionMesh(pSubd2, nfaces ) );
5574
for ( face = 0; face < nfaces; ++face )
5576
pSubd2->AddFacet( nvertices[ face ], &vertices[ iP ], iP );
5577
iP += nvertices[ face ];
5579
if ( pSubd2->Finalise() )
5582
TqInt argcIndex = 0;
5583
TqInt floatargIndex = 0;
5584
TqInt intargIndex = 0;
5585
for ( TqInt i = 0; i < ntags; ++i )
5587
if ( strcmp( tags[ i ], "interpolateboundary" ) == 0 )
5588
pSubd2->SetInterpolateBoundary( TqTrue );
5589
else if ( strcmp( tags [ i ], "crease" ) == 0 )
5591
TqFloat creaseSharpness = floatargs[ floatargIndex ];
5592
// convert pixars 0->infinity crease values to our 0->1
5593
if( creaseSharpness > 5.0f )
5594
creaseSharpness = 5.0f;
5595
creaseSharpness /= 5.0f;
5596
// bend the curve so values behave more like pixars algorithm
5597
creaseSharpness = pow(creaseSharpness, 0.2f);
5599
while ( iEdge < nargs[ argcIndex ] - 1 )
5601
if ( intargs[ iEdge + intargIndex ] < pSubd2->cVertices() &&
5602
intargs[ iEdge + intargIndex + 1 ] < pSubd2->cVertices() )
5604
// Store the sharp edge information in the top level mesh.
5605
pMesh->AddSharpEdge(intargs[ iEdge + intargIndex ], intargs[ iEdge + intargIndex + 1 ], creaseSharpness);
5606
// Store the crease sharpness.
5607
CqLath* pEdge = pSubd2->pVertex( intargs[ iEdge + intargIndex ] );
5608
std::vector<CqLath*> aQve;
5610
std::vector<CqLath*>::iterator iOpp;
5611
for( iOpp = aQve.begin(); iOpp != aQve.end(); ++iOpp )
5613
if( ( NULL != (*iOpp)->ec() ) && (*iOpp)->ec()->VertexIndex() == intargs[ iEdge + intargIndex + 1 ] )
5615
pSubd2->AddSharpEdge( (*iOpp), creaseSharpness );
5616
pSubd2->AddSharpEdge( (*iOpp)->ec(), creaseSharpness );
5624
else if ( strcmp( tags [ i ], "corner" ) == 0 )
5627
while ( iVertex < nargs[ argcIndex ] )
5629
if ( intargs[ iVertex + intargIndex ] < pSubd2->cVertices() )
5631
// Store the sharp edge information in the top level mesh.
5632
pMesh->AddSharpCorner(intargs[ iVertex + intargIndex ], RI_INFINITY);
5633
// Store the corner sharpness.
5634
CqLath* pVertex = pSubd2->pVertex( intargs[ iVertex + intargIndex ] );
5635
pSubd2->AddSharpCorner( pVertex, RI_INFINITY );
5640
else if ( strcmp( tags [ i ], "hole" ) == 0 )
5643
while ( iFace < nargs[ argcIndex ] )
5645
pSubd2->SetHoleFace( intargs[ iFace + intargIndex ] );
5650
intargIndex += nargs[ argcIndex++ ];
5651
floatargIndex += nargs[ argcIndex++ ];
5658
Aqsis::log() << error << "RiSubdivisionMesh contains non-manifold data" << std::endl;
5663
Aqsis::log() << error << "RiSubdivisionMesh invalid scheme \"" << scheme << "\"" << std::endl;
5671
RtVoid RiReadArchive( RtToken name, RtArchiveCallback callback, ... )
5673
EXTRACT_PARAMETERS( callback )
5675
RiReadArchiveV( name, callback, PASS_PARAMETERS );
5679
RtVoid RiReadArchiveV( RtToken name, RtArchiveCallback callback, PARAMETERLIST )
5681
VALIDATE_CONDITIONAL
5685
VALIDATE_RIREADARCHIVE
5689
CqRiFile fileArchive( name, "archive" );
5691
if ( fileArchive.IsValid() )
5693
CqString strRealName( fileArchive.strRealName() );
5694
fileArchive.Close();
5696
if ( ( file = fopen( strRealName.c_str(), "rb" ) ) != NULL )
5699
Aqsis::log() << info << "RiReadArchive: Reading archive \"" << strRealName.c_str() << "\"" << std::endl;
5702
CqRIBParserState currstate = librib::GetParserState();
5703
if (currstate.m_pParseCallbackInterface == NULL)
5704
currstate.m_pParseCallbackInterface = new librib2ri::Engine;
5705
librib::Parse( file, name, *(currstate.m_pParseCallbackInterface), *(currstate.m_pParseErrorStream), callback );
5706
librib::SetParserState( currstate );
5713
RtVoid RiArchiveRecord( RtToken type, char * format, ... )
5715
VALIDATE_RIARCHIVERECORD
5717
DEBUG_RIARCHIVERECORD
5720
RtContextHandle RiGetContext( void )
5722
VALIDATE_RIGETCONTEXT
5729
RtVoid RiContext( RtContextHandle handle )
5736
RtVoid RiClippingPlane( RtFloat x, RtFloat y, RtFloat z, RtFloat nx, RtFloat ny, RtFloat nz )
5738
VALIDATE_RICLIPPINGPLANE
5740
DEBUG_RICLIPPINGPLANE
5744
RtVoid RiShaderLayer( RtToken type, RtToken name, RtToken layername, ... )
5746
EXTRACT_PARAMETERS( layername )
5748
RiShaderLayerV( type, name, layername, PASS_PARAMETERS );
5751
RtVoid RiShaderLayerV( RtToken type, RtToken name, RtToken layername, RtInt count, RtToken tokens[], RtPointer values[] )
5753
VALIDATE_CONDITIONAL
5757
VALIDATE_RISHADERLAYER
5761
// If the current shader for the specified type is already a layer container, add this layer to it, if not,
5762
// create one and add this layer as the first.
5764
boost::shared_ptr<IqShader> newlayer;
5765
boost::shared_ptr<IqShader> layeredshader;
5766
CqString stringtype(type);
5767
stringtype = stringtype.ToLower();
5768
if(stringtype.compare("surface")==0)
5770
newlayer = QGetRenderContext()->CreateShader( name, Type_Surface );
5771
layeredshader = QGetRenderContext()->pattrCurrent()->pshadSurface(QGetRenderContext()->Time());
5773
if( !layeredshader || !layeredshader->IsLayered() )
5775
// Create a new layered shader and add this shader to it.
5776
layeredshader = boost::shared_ptr<IqShader>(new CqLayeredShader);
5777
layeredshader->SetTransform( QGetRenderContext() ->ptransCurrent() );
5778
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( layeredshader, QGetRenderContext() ->Time() );
5781
else if(stringtype.compare("displacement")==0)
5783
newlayer = QGetRenderContext()->CreateShader( name, Type_Displacement );
5784
layeredshader = QGetRenderContext()->pattrCurrent()->pshadDisplacement(QGetRenderContext()->Time());
5786
if( !layeredshader || !layeredshader->IsLayered() )
5788
// Create a new layered shader and add this shader to it.
5789
layeredshader = boost::shared_ptr<IqShader>(new CqLayeredShader);
5790
layeredshader->SetTransform( QGetRenderContext() ->ptransCurrent() );
5791
QGetRenderContext() ->pattrWriteCurrent() ->SetpshadDisplacement( layeredshader, QGetRenderContext() ->Time() );
5794
else if(stringtype.compare("imager")==0)
5796
QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "Imager" ) [ 0 ] = name ;
5797
newlayer = QGetRenderContext()->CreateShader( name, Type_Imager );
5798
layeredshader = QGetRenderContext()->poptCurrent()->pshadImager();
5800
if( !layeredshader || !layeredshader->IsLayered() )
5802
// Create a new layered shader and add this shader to it.
5803
layeredshader = boost::shared_ptr<IqShader>(new CqLayeredShader);
5804
layeredshader->SetTransform( QGetRenderContext() ->ptransCurrent() );
5805
QGetRenderContext() ->poptWriteCurrent()->SetpshadImager( layeredshader );
5809
Aqsis::log() << error << "Layered shaders not supported for type \"" << type << "\"" << std::endl;
5811
if ( newlayer && layeredshader )
5813
newlayer->SetTransform( QGetRenderContext() ->ptransCurrent() );
5815
// Just add this layer in
5816
layeredshader->AddLayer(layername, newlayer);
5818
// Just check that the transformation hasn't changed between layers, as this is not handled.
5819
if(newlayer->matCurrent() != layeredshader->matCurrent())
5820
Aqsis::log() << error << "The shader space has changed between layers, this is not supported" << std::endl;
5822
// Execute the intiialisation code here, as we now have our shader context complete.
5823
newlayer->PrepareDefArgs();
5825
for ( i = 0; i < count; ++i )
5827
RtToken token = tokens[ i ];
5828
RtPointer value = values[ i ];
5830
SetShaderArgument( newlayer, token, static_cast<TqPchar>( value ) );
5835
RtVoid RiConnectShaderLayers( RtToken type, RtToken layer1, RtToken variable1, RtToken layer2, RtToken variable2 )
5837
VALIDATE_CONDITIONAL
5839
CACHE_RICONNECTSHADERLAYERS
5841
VALIDATE_RICONNECTSHADERLAYERS
5843
DEBUG_RICONNECTSHADERLAYERS
5845
// If the current shader for the specified type is a layer container, add this connection to it
5846
CqString stringtype(type);
5847
stringtype = stringtype.ToLower();
5848
boost::shared_ptr<IqShader> pcurr;
5849
if(stringtype.compare("surface")==0)
5850
pcurr = QGetRenderContext()->pattrWriteCurrent()->pshadSurface(QGetRenderContext()->Time());
5851
else if(stringtype.compare("displacement")==0)
5852
pcurr = QGetRenderContext()->pattrWriteCurrent()->pshadDisplacement(QGetRenderContext()->Time());
5853
else if(stringtype.compare("imager")==0)
5854
pcurr = QGetRenderContext()->poptCurrent()->pshadImager();
5856
Aqsis::log() << error << "Layered shaders not supported for type \"" << type << "\"" << std::endl;
5857
if( pcurr && pcurr->IsLayered() )
5859
// Just add this layer in
5860
pcurr->AddConnection(layer1, variable1, layer2, variable2);
5865
//---------------------------------------------------------------------
5866
//---------------------------------------------------------------------
5869
//----------------------------------------------------------------------
5870
// ProcessPrimitiveVariables
5871
// Process and fill in any primitive variables.
5872
// return : RI_TRUE if position specified, RI_FALSE otherwise.
5874
static RtBoolean ProcessPrimitiveVariables( CqSurface * pSurface, PARAMETERLIST )
5876
std::vector<TqInt> aUserParams;
5878
// Read recognised parameter values.
5879
RtInt fP = RIL_NONE;
5881
RtFloat* pPoints = 0;
5884
for ( i = 0; i < count; ++i )
5886
RtToken token = tokens[ i ];
5887
RtPointer value = values[ i ];
5889
SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( token );
5890
TqUlong hash = CqString::hash(Decl.m_strName.c_str());
5892
if ( (hash == RIH_P) && (Decl.m_Class == class_vertex ))
5895
pPoints = ( RtFloat* ) value;
5897
else if ( (hash == RIH_PZ) && (Decl.m_Class == class_vertex ) )
5900
pPoints = ( RtFloat* ) value;
5902
else if ( (hash == RIH_PW) && (Decl.m_Class == class_vertex ) )
5905
pPoints = ( RtFloat* ) value;
5909
aUserParams.push_back( i );
5913
// Fill in the position variable according to type.
5914
if ( fP != RIL_NONE )
5916
pSurface->AddPrimitiveVariable( new CqParameterTypedVertex<CqVector4D, type_hpoint, CqVector3D>( "P", 1 ) );
5917
pSurface->P() ->SetSize( pSurface->cVertex() );
5922
for ( i = 0; i < pSurface->cVertex(); ++i )
5923
pSurface->P()->pValue( i )[0] = CqVector3D( pPoints[ ( i * 3 ) ], pPoints[ ( i * 3 ) + 1 ], pPoints[ ( i * 3 ) + 2 ] );
5927
for ( i = 0; i < pSurface->cVertex(); ++i )
5929
CqVector3D vecP = pSurface->SurfaceParametersAtVertex( i );
5930
vecP.z( pPoints[ i ] );
5931
pSurface->P()->pValue( i )[0] = vecP;
5936
for ( i = 0; i < pSurface->cVertex(); ++i )
5937
pSurface->P()->pValue( i )[0] = CqVector4D( pPoints[ ( i * 4 ) ], pPoints[ ( i * 4 ) + 1 ], pPoints[ ( i * 4 ) + 2 ], pPoints[ ( i * 4 ) + 3 ] );
5942
// Now process any user defined paramter variables.
5943
if ( aUserParams.size() > 0 )
5945
std::vector<TqInt>::iterator iUserParam;
5946
for ( iUserParam = aUserParams.begin(); iUserParam != aUserParams.end(); ++iUserParam )
5948
SqParameterDeclaration Decl;
5951
Decl = QGetRenderContext()->FindParameterDecl( tokens[ *iUserParam ] );
5953
catch( XqException e )
5955
Aqsis::log() << error << e.strReason().c_str() << std::endl;
5959
CqParameter* pNewParam = ( *Decl.m_pCreate ) ( Decl.m_strName.c_str(), Decl.m_Count );
5960
// Now go across all values and fill in the parameter variable.
5962
switch ( Decl.m_Class )
5965
cValues = pSurface->cUniform();
5969
cValues = pSurface->cVarying();
5973
cValues = pSurface->cVertex();
5976
case class_facevarying:
5977
cValues = pSurface->cFaceVarying();
5980
case class_facevertex:
5981
cValues = pSurface->cFaceVertex();
5987
pNewParam->SetSize( cValues );
5990
switch ( Decl.m_Type )
5994
CqParameterTyped<TqFloat, TqFloat>* pFloatParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pNewParam );
5995
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5996
TqInt iArrayIndex, iValIndex;
5998
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5999
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6000
pFloatParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
6006
CqParameterTyped<TqInt, TqFloat>* pIntParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pNewParam );
6007
TqInt* pValue = reinterpret_cast<TqInt*>( values[ *iUserParam ] );
6008
TqInt iArrayIndex, iValIndex;
6010
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6011
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6012
pIntParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
6020
CqParameterTyped<CqVector3D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pNewParam );
6021
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6022
TqInt iArrayIndex, iValIndex;
6024
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6025
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6026
pVectorParam->pValue( iValIndex ) [ iArrayIndex ] = CqVector3D( pValue[ ( i * 3 ) ], pValue[ ( i * 3 ) + 1 ], pValue[ ( i * 3 ) + 2 ] );
6032
CqParameterTyped<CqString, CqString>* pStringParam = static_cast<CqParameterTyped<CqString, CqString>*>( pNewParam );
6033
char** pValue = reinterpret_cast<char**>( values[ *iUserParam ] );
6034
TqInt iArrayIndex, iValIndex;
6036
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6037
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6038
pStringParam->pValue( iValIndex ) [ iArrayIndex ] = CqString( pValue[ i ] );
6044
CqParameterTyped<CqColor, CqColor>* pColorParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pNewParam );
6045
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6046
TqInt iArrayIndex, iValIndex;
6048
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6049
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6050
pColorParam->pValue( iValIndex ) [ iArrayIndex ] = CqColor( pValue[ ( i * 3 ) ], pValue[ ( i * 3 ) + 1 ], pValue[ ( i * 3 ) + 2 ] );
6056
CqParameterTyped<CqVector4D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pNewParam );
6057
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6058
TqInt iArrayIndex, iValIndex;
6060
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6061
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6062
pVectorParam->pValue( iValIndex ) [ iArrayIndex ] = CqVector4D( pValue[ ( i * 4 ) ], pValue[ ( i * 4 ) + 1 ], pValue[ ( i * 4 ) + 2 ], pValue[ ( i * 4 ) + 3 ] );
6068
CqParameterTyped<CqMatrix, CqMatrix>* pMatrixParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pNewParam );
6069
TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6070
TqInt iArrayIndex, iValIndex;
6072
for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6073
for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6074
pMatrixParam->pValue( iValIndex ) [ iArrayIndex ] = CqMatrix( pValue[ ( i * 16 ) ], pValue[ ( i * 16 ) + 1 ], pValue[ ( i * 16 ) + 2 ], pValue[ ( i * 16 ) + 3 ],
6075
pValue[ ( i * 16 ) + 4 ], pValue[ ( i * 16 ) + 5 ], pValue[ ( i * 16 ) + 6 ], pValue[ ( i * 16 ) + 7 ],
6076
pValue[ ( i * 16 ) + 8 ], pValue[ ( i * 16 ) + 9 ], pValue[ ( i * 16 ) + 10 ], pValue[ ( i * 16 ) + 11 ],
6077
pValue[ ( i * 16 ) + 12 ], pValue[ ( i * 16 ) + 13 ], pValue[ ( i * 16 ) + 14 ], pValue[ ( i * 16 ) + 15 ]
6084
// left blank to avoid compiler warnings about unhandled types
6088
pSurface->AddPrimitiveVariable( pNewParam );
6092
return ( pSurface->P() != NULL );
6096
//----------------------------------------------------------------------
6098
// Create and register a GPrim according to the current attributes/transform
6100
RtVoid CreateGPrim( const boost::shared_ptr<CqSurface>& pSurface )
6102
// If in a motion block, confirm that the current deformation surface can accept the passed one as a keyframe.
6103
if( QGetRenderContext() ->pconCurrent() ->fMotionBlock() )
6105
CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
6107
CqDeformingSurface* pMS = pMMB->GetDeformingSurface().get();
6108
// If this is the first frame, then generate the appropriate CqDeformingSurface and fill in the first frame.
6109
// Then cache the pointer on the motion block.
6112
boost::shared_ptr<CqDeformingSurface> pNewMS( new CqDeformingSurface( pSurface ) );
6113
pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
6114
pMMB->SetDeformingSurface( pNewMS );
6118
pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
6120
QGetRenderContext() ->AdvanceTime();
6124
QGetRenderContext()->StorePrimitive( pSurface );
6125
STATS_INC( GPR_created );
6127
// Add to the raytracer database also
6128
if(QGetRenderContext()->pRaytracer())
6129
QGetRenderContext()->pRaytracer()->AddPrimitive(pSurface);
6136
//----------------------------------------------------------------------
6137
/** Get the basis matrix given a standard basis name.
6138
* \param b Storage for basis matrix.
6139
* \param strName Name of basis.
6140
* \return Boolean indicating the basis is valid.
6143
RtBoolean BasisFromName( RtBasis * b, const char * strName )
6145
RtBasis * pVals = 0;
6146
if ( !strcmp( strName, "bezier" ) )
6147
pVals = &RiBezierBasis;
6148
else if ( !strcmp( strName, "bspline" ) )
6149
pVals = &RiBSplineBasis;
6150
else if ( !strcmp( strName, "catmull-rom" ) )
6151
pVals = &RiCatmullRomBasis;
6152
else if ( !strcmp( strName, "hermite" ) )
6153
pVals = &RiHermiteBasis;
6154
else if ( !strcmp( strName, "power" ) )
6155
pVals = &RiPowerBasis;
6160
for ( i = 0; i < 4; ++i )
6161
for ( j = 0; j < 4; ++j )
6162
( *b ) [ i ][ j ] = ( *pVals ) [ i ][ j ];
6169
//----------------------------------------------------------------------
6170
/** Set the function used to report progress.
6171
* \param handler Pointer to the new function to use.
6174
RtVoid RiProgressHandler( RtProgressFunc handler )
6176
QGetRenderContext()->SetpProgressHandler( handler );
6181
//----------------------------------------------------------------------
6182
/** Set the function called just prior to rendering, after the world is complete.
6183
\param function Pointer to the new function to use.
6184
\return Pointer to the old function.
6187
RtFunc RiPreRenderFunction( RtFunc function )
6189
RtFunc pOldPreRenderFunction = QGetRenderContext()->pPreRenderFunction();
6190
QGetRenderContext()->SetpPreRenderFunction( function );
6191
return ( pOldPreRenderFunction );
6194
//----------------------------------------------------------------------
6195
/** Set the function called just prior to world definition.
6196
\param function Pointer to the new function to use.
6197
\return Pointer to the old function.
6200
RtFunc RiPreWorldFunction( RtFunc function )
6202
RtFunc pOldPreWorldFunction = QGetRenderContext()->pPreWorldFunction();
6203
QGetRenderContext()->SetpPreWorldFunction( function );
6204
return ( pOldPreWorldFunction );
6208
void SetShaderArgument( const boost::shared_ptr<IqShader>& pShader, const char * name, TqPchar val )
6210
// Find the relevant variable.
6211
SqParameterDeclaration Decl;
6214
Decl = QGetRenderContext() ->FindParameterDecl( name );
6216
catch( XqException e )
6218
Aqsis::log() << error << e.strReason().c_str() << std::endl;
6222
pShader->SetArgument( Decl.m_strName, Decl.m_Type, Decl.m_strSpace, val );
6226
//----------------------------------------------------------------------
6227
/** Analyze the parameter list and figure what kind of compression is required for texturemapping output files.
6229
\param compression compression Pointer to an integer to containing the TIFF compression
6230
\param quality it is the quality of jpeg's compression
6231
\param count list counter
6232
\param tokens list of tokens
6233
\param values list of values
6238
static void ProcessCompression( TqInt * compression, TqInt * quality, TqInt count, RtToken * tokens, RtPointer * values )
6240
*compression = COMPRESSION_NONE;
6243
for ( int i = 0; i < count; ++i )
6245
RtToken token = tokens[ i ];
6246
RtString *value = ( RtString * ) values[ i ];
6248
if ( strstr( token, "compression" ) != 0 )
6251
if ( strstr( *value, "none" ) != 0 )
6252
* compression = COMPRESSION_NONE;
6254
else if ( strstr( *value, "lzw" ) != 0 )
6255
* compression = COMPRESSION_LZW;
6257
else if ( strstr( *value, "deflate" ) != 0 )
6258
* compression = COMPRESSION_DEFLATE;
6260
else if ( strstr( *value, "jpeg" ) != 0 )
6261
* compression = COMPRESSION_JPEG;
6263
else if ( strstr( *value, "packbits" ) != 0 )
6264
* compression = COMPRESSION_PACKBITS;
6268
else if ( strstr( token, "quality" ) != 0 )
6271
*quality = ( int ) * ( float * ) value;
6274
if ( *quality > 100 )