~ubuntu-branches/ubuntu/quantal/aqsis/quantal

« back to all changes in this revision

Viewing changes to renderer/render/ri.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fabrice Coutadeur
  • Date: 2009-08-06 04:53:26 UTC
  • mfrom: (1.2.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090806045326-z6xeaaao62idxcc6
Tags: 1.6.0-0ubuntu1
* New upstream release
* debian/control:
  - changed name of lib package to libaqsis1 instead of aqsis-libsc2a
  - changed name of dev package to libaqsis-dev instead of aqsis-libs-dev
  - Added aqsis-data package
  - Revised summary text according to that specified by the RISpec (Pixar)
* Moved examples installation from aqsis.install to aqsis-data.install
* debian/rules: 
  - added content to binary-indep target
* debian/rules: added explicit name of mime file to force dh_installmime
  to generate postinst and prerm scripts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Aqsis
2
 
// Copyright 1997 - 2001, Paul C. Gregory
3
 
//
4
 
// Contact: pgregory@aqsis.org
5
 
//
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.
10
 
//
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.
15
 
//
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
19
 
 
20
 
 
21
 
/** \file
22
 
                \brief Implement the majority of the RenderMan API functions.
23
 
                \author Paul C. Gregory (pgregory@aqsis.org)
24
 
                \todo: <b>Code Review</b>
25
 
*/
26
 
 
27
 
#include        "MultiTimer.h"
28
 
 
29
 
#include        "aqsis.h"
30
 
 
31
 
#include        <stdarg.h>
32
 
#include        <math.h>
33
 
#include        <list>
34
 
 
35
 
#include        "imagebuffer.h"
36
 
#include        "lights.h"
37
 
#include        "renderer.h"
38
 
#include        "patch.h"
39
 
#include        "polygon.h"
40
 
#include        "nurbs.h"
41
 
#include        "symbols.h"
42
 
#include        "bilinear.h"
43
 
#include        "quadrics.h"
44
 
#include        "teapot.h"
45
 
#include        "bunny.h"
46
 
#include        "shaders.h"
47
 
#include        "texturemap.h"
48
 
#include        "objectinstance.h"
49
 
#include        "trimcurve.h"
50
 
#include        "genpoly.h"
51
 
#include        "points.h"
52
 
#include        "curves.h"
53
 
#include        "rifile.h"
54
 
#include        "librib2ri.h"
55
 
#include        "converter.h"
56
 
#include        "shadervm.h"
57
 
#include        "librib.h"
58
 
#include        "libribtypes.h"
59
 
#include        "parserstate.h"
60
 
#include        "procedural.h"
61
 
#include        "logging.h"
62
 
#include        "logging_streambufs.h"
63
 
 
64
 
#include        "ri_cache.h"
65
 
 
66
 
#include        "subdivision2.h"
67
 
#include        "condition.h"
68
 
 
69
 
#include        "blobby.h"
70
 
 
71
 
#ifndef    AQSIS_SYSTEM_WIN32
72
 
#include        "unistd.h"
73
 
#else
74
 
#include        "io.h"
75
 
#endif /* AQSIS_SYSTEM_WIN32 */
76
 
 
77
 
// These are needed to allow calculation of the default paths
78
 
#ifdef AQSIS_SYSTEM_WIN32
79
 
  #include <windows.h>
80
 
  #ifdef _DEBUG
81
 
    #include <crtdbg.h>
82
 
extern "C" __declspec(dllimport) void report_refcounts();
83
 
#endif // _DEBUG
84
 
#endif // !AQSIS_SYSTEM_WIN32
85
 
 
86
 
#if defined(AQSIS_SYSTEM_MACOSX)
87
 
#include "Carbon/Carbon.h"
88
 
#endif
89
 
 
90
 
 
91
 
#include        "ri.h"
92
 
 
93
 
#include        "sstring.h"
94
 
 
95
 
//#include      "share.h"
96
 
#include        "validate.h"
97
 
 
98
 
#include        "ri_validate.inl"
99
 
 
100
 
using namespace Aqsis;
101
 
 
102
 
#include        "ri_debug.h"
103
 
 
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(...);
109
 
 
110
 
TqBool   IfOk = TqTrue;
111
 
 
112
 
#define VALIDATE_CONDITIONAL \
113
 
        {\
114
 
        if (!IfOk) \
115
 
                return;\
116
 
        }
117
 
 
118
 
#define VALIDATE_CONDITIONAL0 \
119
 
        {\
120
 
        if (!IfOk) \
121
 
                return 0;\
122
 
        }
123
 
 
124
 
#define EXTRACT_PARAMETERS(_start) \
125
 
        va_list pArgs; \
126
 
        va_start( pArgs, _start ); \
127
 
\
128
 
        std::vector<RtToken> aTokens; \
129
 
        std::vector<RtPointer> aValues; \
130
 
        RtInt count = BuildParameterList( pArgs, aTokens, aValues ); 
131
 
 
132
 
#define PASS_PARAMETERS \
133
 
        count, aTokens.size()>0?&aTokens[0]:0, aValues.size()>0?&aValues[0]:0
134
 
 
135
 
//---------------------------------------------------------------------
136
 
// This file contains the interface functions which are published as the
137
 
//      Renderman Interface SPECification (C) 1988 Pixar.
138
 
//
139
 
 
140
 
CqRandom worldrand;
141
 
 
142
 
//---------------------------------------------------------------------
143
 
// Interface parameter token strings.
144
 
 
145
 
 
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";
152
 
RtToken RI_A    = "a";
153
 
RtToken RI_Z    = "z";
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";
165
 
 
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";
193
 
 
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";
203
 
RtToken RI_P    = "P";
204
 
RtToken RI_PZ   = "Pz";
205
 
RtToken RI_PW   = "Pw";
206
 
RtToken RI_N    = "N";
207
 
RtToken RI_NP   = "Np";
208
 
RtToken RI_CS   = "Cs";
209
 
RtToken RI_OS   = "Os";
210
 
RtToken RI_S    = "s";
211
 
RtToken RI_T    = "t";
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";
246
 
 
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}};
267
 
 
268
 
enum RIL_POINTS
269
 
{
270
 
    RIL_NONE = -1,
271
 
    RIL_P,
272
 
    RIL_Pz,
273
 
    RIL_Pw,
274
 
    RIL_N,
275
 
    RIL_Np,
276
 
    RIL_s,
277
 
    RIL_t = RIL_s,
278
 
    RIL_st,
279
 
};
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" );
296
 
 
297
 
RtInt   RiLastError = 0;
298
 
 
299
 
//----------------------------------------------------------------------
300
 
// CreateGPrim
301
 
// Helper function to build a GPrim from any boost::shared_ptr<> type..
302
 
template<class T>
303
 
inline
304
 
RtVoid  CreateGPrim( const boost::shared_ptr<T>& pSurface )
305
 
{
306
 
        CreateGPrim( boost::static_pointer_cast<CqSurface,T>( pSurface ) );
307
 
}
308
 
 
309
 
//----------------------------------------------------------------------
310
 
// BuildParameterList
311
 
// Helper function to build a parameter list to pass on to the V style functions.
312
 
// returns a parameter count.
313
 
 
314
 
RtInt BuildParameterList( va_list pArgs, std::vector<RtToken>& aTokens, std::vector<RtPointer>& aValues )
315
 
{
316
 
        RtInt count = 0;
317
 
        RtToken pToken = va_arg( pArgs, RtToken );
318
 
        RtPointer pValue;
319
 
        aTokens.clear();
320
 
        aValues.clear();
321
 
        while ( pToken != 0 && pToken != RI_NULL )              // While not RI_NULL
322
 
        {
323
 
                aTokens.push_back( pToken );
324
 
                pValue = va_arg( pArgs, RtPointer );
325
 
                aValues.push_back( pValue );
326
 
                pToken = va_arg( pArgs, RtToken );
327
 
                count++;
328
 
        }
329
 
        return ( count );
330
 
}
331
 
 
332
 
 
333
 
//----------------------------------------------------------------------
334
 
//      CqRangeCheckCallback implentation
335
 
//      Use this with CheckMinMax
336
 
//
337
 
class   CqLogRangeCheckCallback : public CqRangeCheckCallback
338
 
{
339
 
        public:
340
 
                CqLogRangeCheckCallback()
341
 
                { }
342
 
 
343
 
                virtual ~CqLogRangeCheckCallback()
344
 
                {
345
 
                }
346
 
 
347
 
                void set
348
 
                        ( const char* name )
349
 
                {
350
 
                        m_name = name;
351
 
                }
352
 
 
353
 
                virtual void operator()( int res )
354
 
                {
355
 
                        switch( res )
356
 
                        {
357
 
                                        case CqRangeCheckCallback::UPPER_BOUND_HIT:
358
 
                                        {
359
 
                                                Aqsis::log() << error << "Invalid Value for " << m_name << ". Value exceeded upper limit" << std::endl;
360
 
                                        }
361
 
 
362
 
                                        case CqRangeCheckCallback::LOWER_BOUND_HIT:
363
 
                                        {
364
 
                                                Aqsis::log() << error << "Invalid Value for " << m_name << ". Value exceeded lower limit" << std::endl;
365
 
                                        }
366
 
 
367
 
                                        default:
368
 
                                        ;
369
 
                        }
370
 
                }
371
 
 
372
 
 
373
 
        private:
374
 
                const char*     m_name;
375
 
};
376
 
 
377
 
 
378
 
//----------------------------------------------------------------------
379
 
// ValidateState
380
 
// Check that the currect graphics state is one of those specified.
381
 
//
382
 
TqBool  ValidateState(int count, ... )
383
 
{
384
 
        va_list pArgs;
385
 
        va_start( pArgs, count );
386
 
 
387
 
        int currentState = Outside;
388
 
        if(  QGetRenderContext() != NULL && QGetRenderContext()->pconCurrent() )
389
 
                currentState = QGetRenderContext()->pconCurrent()->Type();
390
 
 
391
 
        int i;
392
 
        for(i=0; i<count; i++)
393
 
        {
394
 
                int state = va_arg( pArgs, int );
395
 
                if( currentState == state )
396
 
                        return(TqTrue);
397
 
        }
398
 
        return(TqFalse);
399
 
}
400
 
 
401
 
 
402
 
//----------------------------------------------------------------------
403
 
// GetStateAsString
404
 
// Get a string representing the current state.
405
 
//
406
 
const char*     GetStateAsString()
407
 
{
408
 
        int currentState = Outside;
409
 
        if( QGetRenderContext()->pconCurrent() )
410
 
                currentState = QGetRenderContext()->pconCurrent()->Type();
411
 
        switch( currentState )
412
 
        {
413
 
                        case Outside:
414
 
                        return("Outside");
415
 
                        break;
416
 
 
417
 
                        case BeginEnd:
418
 
                        return("BeginEnd");
419
 
                        break;
420
 
 
421
 
                        case Frame:
422
 
                        return("Frame");
423
 
                        break;
424
 
 
425
 
                        case World:
426
 
                        return("World");
427
 
                        break;
428
 
 
429
 
                        case Attribute:
430
 
                        return("Attribute");
431
 
                        break;
432
 
 
433
 
                        case Transform:
434
 
                        return("Transform");
435
 
                        break;
436
 
 
437
 
                        case Solid:
438
 
                        return("Solid");
439
 
                        break;
440
 
 
441
 
                        case Object:
442
 
                        return("Object");
443
 
                        break;
444
 
 
445
 
                        case Motion:
446
 
                        return("Motion");
447
 
                        break;
448
 
        }
449
 
        return("");
450
 
}
451
 
 
452
 
 
453
 
//----------------------------------------------------------------------
454
 
// RiDeclare
455
 
// Declare a new variable to be recognised by the system.
456
 
//
457
 
RtToken RiDeclare( RtString name, RtString declaration )
458
 
{
459
 
        VALIDATE_CONDITIONAL0
460
 
 
461
 
        CACHE_RIDECLARE
462
 
 
463
 
        VALIDATE_RIDECLARE
464
 
 
465
 
        DEBUG_RIDECLARE
466
 
 
467
 
        CqString strName( name ), strDecl( declaration );
468
 
        QGetRenderContext() ->AddParameterDecl( strName.c_str(), strDecl.c_str() );
469
 
        return ( 0 );
470
 
}
471
 
 
472
 
 
473
 
//----------------------------------------------------------------------
474
 
// SetDefaultRiOptions
475
 
// Set some Default Options.
476
 
//
477
 
void SetDefaultRiOptions( void )
478
 
{
479
 
        std::string systemRCPath;
480
 
        std::string homeRCPath;
481
 
        std::string currentRCPath;
482
 
        std::string rootPath;
483
 
        std::string separator;
484
 
 
485
 
#ifdef AQSIS_SYSTEM_WIN32
486
 
 
487
 
        char acPath[256];
488
 
        char root[256];
489
 
        if( GetModuleFileName( NULL, acPath, 256 ) != 0)
490
 
        {
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);
495
 
        }
496
 
        rootPath = root;
497
 
        separator = "\\";
498
 
#elif AQSIS_SYSTEM_MACOSX
499
 
 
500
 
        CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
501
 
        CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle);
502
 
        const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
503
 
        rootPath = pathPtr;
504
 
        separator = "/";
505
 
#else
506
 
        // Minty: Need to work out the executable path here.
507
 
        rootPath = DEFAULT_RC_PATH;
508
 
        separator = "/";
509
 
#endif
510
 
 
511
 
        systemRCPath = rootPath;
512
 
        systemRCPath.append( separator );
513
 
        systemRCPath.append( "aqsisrc" );
514
 
 
515
 
        // Read in the system configuration file if found.
516
 
        FILE* rcfile = fopen( systemRCPath.c_str(), "rb" );
517
 
        if (rcfile != NULL )
518
 
        {
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 );
525
 
                fclose(rcfile);
526
 
        }
527
 
        else
528
 
        {
529
 
                Aqsis::log() << error << "Could not open system config (" << systemRCPath.c_str() << ")" << std::endl;
530
 
        }
531
 
 
532
 
        /* ...then read the .aqsisrc files in $HOME... */
533
 
        if(getenv("HOME"))
534
 
        {
535
 
                homeRCPath = getenv("HOME");
536
 
                if (homeRCPath[ homeRCPath.length() ] != separator[0])
537
 
                {
538
 
                        homeRCPath.append(separator);
539
 
                };
540
 
                homeRCPath.append(".aqsisrc");
541
 
                rcfile = fopen( homeRCPath.c_str(), "rb" );
542
 
                if (rcfile != NULL )
543
 
                {
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 );
550
 
                        fclose(rcfile);
551
 
                }
552
 
                else
553
 
                {
554
 
                        Aqsis::log() << info << "Could not open user config (" << homeRCPath.c_str() << ")" << std::endl;
555
 
                }
556
 
        }
557
 
        else
558
 
        {
559
 
                Aqsis::log() << info << "Environment variable HOME not set (skipping user config)." << std::endl;
560
 
        }
561
 
 
562
 
        /* ...and the current directory... */
563
 
        currentRCPath = ".aqsisrc";
564
 
        rcfile = fopen( currentRCPath.c_str(), "rb" );
565
 
        if (rcfile != NULL )
566
 
        {
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 );
573
 
                fclose(rcfile);
574
 
        }
575
 
        else
576
 
        {
577
 
                Aqsis::log() << info << "Could not open project config (" << currentRCPath.c_str() << ")" << std::endl;
578
 
        }
579
 
 
580
 
        const char* popt[ 1 ];
581
 
        if(getenv("AQSIS_SHADER_PATH"))
582
 
        {
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 );
586
 
        }
587
 
        else
588
 
        {
589
 
                Aqsis::log() << info << "AQSIS_SHADER_PATH not set" << std::endl;
590
 
        }
591
 
 
592
 
        if(getenv("AQSIS_ARCHIVE_PATH"))
593
 
        {
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 );
597
 
        }
598
 
        else
599
 
        {
600
 
                Aqsis::log() << info << "AQSIS_ARCHIVE_PATH not set" << std::endl;
601
 
        }
602
 
 
603
 
        if(getenv("AQSIS_TEXTURE_PATH"))
604
 
        {
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 );
608
 
        }
609
 
        else
610
 
        {
611
 
                Aqsis::log() << info << "AQSIS_TEXTURE_PATH not set" << std::endl;
612
 
        }
613
 
 
614
 
        if(getenv("AQSIS_DISPLAY_PATH"))
615
 
        {
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 );
619
 
        }
620
 
        else
621
 
        {
622
 
                Aqsis::log() << info << "AQSIS_DISPLAY_PATH not set" << std::endl;
623
 
        }
624
 
 
625
 
        if(getenv("AQSIS_PROCEDURAL_PATH"))
626
 
        {
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 );
630
 
        }
631
 
        else
632
 
        {
633
 
                Aqsis::log() << info << "AQSIS_PROCEDURAL_PATH not set" << std::endl;
634
 
        }
635
 
 
636
 
        if(getenv("AQSIS_PLUGIN_PATH"))
637
 
        {
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 );
641
 
        }
642
 
        else
643
 
        {
644
 
                Aqsis::log() << info << "AQSIS_PLUGIN_PATH not set" << std::endl;
645
 
        }
646
 
 
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 );
650
 
}
651
 
 
652
 
//----------------------------------------------------------------------
653
 
// RiBegin
654
 
// Begin a Renderman render phase.
655
 
//
656
 
extern "C" char *StandardParameters[][2];
657
 
RtVoid  RiBegin( RtToken name )
658
 
{
659
 
        VALIDATE_RIBEGIN
660
 
 
661
 
        DEBUG_RIBEGIN
662
 
 
663
 
        // Create a new renderer
664
 
        QSetRenderContext( new CqRenderer );
665
 
 
666
 
        QGetRenderContext() ->Initialise();
667
 
        QGetRenderContext() ->BeginMainModeBlock();
668
 
        QGetRenderContext() ->ptransSetTime( CqMatrix() );
669
 
        QGetRenderContext() ->SetCameraTransform( QGetRenderContext() ->ptransCurrent() );
670
 
        // Clear the lightsources stack.
671
 
        Lightsource_stack.clear();
672
 
 
673
 
        // Include the standard options (how can we opt out of this).
674
 
        int param = 0;
675
 
        while( StandardParameters[param][0] != NULL )
676
 
        {
677
 
                RiDeclare(
678
 
                    StandardParameters[param][0],
679
 
                    StandardParameters[param][1]
680
 
                );
681
 
                param++;
682
 
        };
683
 
 
684
 
        SetDefaultRiOptions();
685
 
 
686
 
        // Setup a default surface shader
687
 
        boost::shared_ptr<IqShader> pDefaultSurfaceShader =
688
 
            QGetRenderContext()->getDefaultSurfaceShader();
689
 
        QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pDefaultSurfaceShader, QGetRenderContext() ->Time() );
690
 
 
691
 
        // Setup the initial transformation.
692
 
        //      QGetRenderContext()->ptransWriteCurrent() ->SetHandedness( TqFalse );
693
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
694
 
 
695
 
        return ;
696
 
}
697
 
 
698
 
//----------------------------------------------------------------------
699
 
// RiEnd
700
 
// End the rendermam render stage.
701
 
//
702
 
RtVoid  RiEnd()
703
 
{
704
 
        VALIDATE_RIEND
705
 
 
706
 
        DEBUG_RIEND
707
 
 
708
 
        QGetRenderContext() ->EndMainModeBlock();
709
 
 
710
 
        // Flush the image cache.
711
 
        CqTextureMap::FlushCache();
712
 
 
713
 
        // Clear the lightsources stack.
714
 
        Lightsource_stack.clear();
715
 
 
716
 
        // Delete the renderer
717
 
        delete( QGetRenderContext() );
718
 
        QSetRenderContext( 0 );
719
 
 
720
 
        return ;
721
 
}
722
 
 
723
 
 
724
 
//----------------------------------------------------------------------
725
 
// RiFrameBegin
726
 
// Begin an individual frame, options are saved at this point.
727
 
//
728
 
RtVoid  RiFrameBegin( RtInt number )
729
 
{
730
 
        VALIDATE_CONDITIONAL
731
 
 
732
 
        CACHE_RIFRAMEBEGIN
733
 
 
734
 
        VALIDATE_RIFRAMEBEGIN
735
 
 
736
 
        DEBUG_RIFRAMEBEGIN
737
 
 
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();
746
 
        TIMER_START("Frame")
747
 
 
748
 
        QGetRenderContext() ->BeginFrameModeBlock();
749
 
        QGetRenderContext() ->SetCurrentFrame( number );
750
 
        CqCSGTreeNode::SetRequired( TqFalse );
751
 
 
752
 
        QGetRenderContext() ->Stats().InitialiseFrame();
753
 
 
754
 
        QGetRenderContext()->clippingVolume().clear();
755
 
 
756
 
 
757
 
        worldrand.Reseed('a'+'q'+'s'+'i'+'s');
758
 
 
759
 
        return ;
760
 
}
761
 
 
762
 
 
763
 
//----------------------------------------------------------------------
764
 
// RiFrameEnd
765
 
// End the rendering of an individual frame, options are restored.
766
 
//
767
 
RtVoid  RiFrameEnd()
768
 
{
769
 
        VALIDATE_CONDITIONAL
770
 
 
771
 
        CACHE_RIFRAMEEND
772
 
 
773
 
        VALIDATE_RIFRAMEEND
774
 
 
775
 
        DEBUG_RIFRAMEEND
776
 
 
777
 
        QGetRenderContext() ->EndFrameModeBlock();
778
 
        QGetRenderContext() ->ClearDisplayRequests();
779
 
 
780
 
        return ;
781
 
}
782
 
 
783
 
//----------------------------------------------------------------------
784
 
// RiWorldBegin
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.
787
 
//
788
 
RtVoid  RiWorldBegin()
789
 
{
790
 
        VALIDATE_CONDITIONAL
791
 
 
792
 
        CACHE_RIWORLDBEGIN
793
 
 
794
 
        VALIDATE_RIWORLDBEGIN
795
 
 
796
 
        DEBUG_RIWORLDBEGIN
797
 
 
798
 
        // Call any specified pre world function.
799
 
        if ( QGetRenderContext()->pPreWorldFunction() != NULL )
800
 
                ( *QGetRenderContext()->pPreWorldFunction() ) ();
801
 
 
802
 
        // Start the frame timer (just in case there was no FrameBegin block. If there
803
 
        // was, nothing happens)
804
 
        //QGetRenderContext() ->Stats().StartFrameTimer();
805
 
        TIMER_START("Frame")
806
 
        TIMER_START("Parse")
807
 
 
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 )
814
 
        {
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 ;
820
 
        }
821
 
 
822
 
        if ( ( cameraOpts & CameraScreenWindowSet) == 0 )
823
 
        {
824
 
                RtFloat fFAR = QGetRenderContext() ->poptCurrent()->GetFloatOption( "System", "FrameAspectRatio" ) [ 0 ];
825
 
 
826
 
                if ( fFAR >= 1.0 )
827
 
                {
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 ;
832
 
                }
833
 
                else
834
 
                {
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 ;
839
 
                }
840
 
        }
841
 
 
842
 
        // Set the world to camera transformation matrix to the current matrix.
843
 
 
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() );
849
 
 
850
 
        // Store the initial object transformation
851
 
        CqTransformPtr newTrans( new CqTransform() );
852
 
        QGetRenderContext()->SetDefObjTransform( newTrans );
853
 
 
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 ];
856
 
        if( iMode & ModeZ )
857
 
        {
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;
863
 
        }
864
 
 
865
 
 
866
 
 
867
 
        QGetRenderContext()->SetWorldBegin();
868
 
        
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();
876
 
 
877
 
        worldrand.Reseed('a'+'q'+'s'+'i'+'s');
878
 
 
879
 
        return ;
880
 
}
881
 
 
882
 
 
883
 
//----------------------------------------------------------------------
884
 
// RiWorldEnd
885
 
// End the specifying of world data, options are released.
886
 
//
887
 
 
888
 
RtVoid  RiWorldEnd()
889
 
{
890
 
        VALIDATE_CONDITIONAL
891
 
 
892
 
        CACHE_RIWORLDEND
893
 
 
894
 
        VALIDATE_RIWORLDEND
895
 
 
896
 
        DEBUG_RIWORLDEND
897
 
 
898
 
        QGetRenderContext()->RenderAutoShadows();
899
 
 
900
 
        TqBool fFailed = TqFalse;
901
 
        // Call any specified pre render function.
902
 
        if ( QGetRenderContext()->pPreRenderFunction() != NULL )
903
 
                ( *QGetRenderContext()->pPreRenderFunction() ) ();
904
 
 
905
 
        // Stop the parsing counter
906
 
        TIMER_STOP("Parse")
907
 
 
908
 
 
909
 
        QGetRenderContext() -> Stats().PrintInfo();
910
 
 
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]) );
914
 
 
915
 
        // Finalise the raytracer database now that all primitives are in.
916
 
        if(QGetRenderContext()->pRaytracer())
917
 
                QGetRenderContext()->pRaytracer()->Finalise();
918
 
 
919
 
        // Render the world
920
 
        try
921
 
        {
922
 
                QGetRenderContext() ->RenderWorld();
923
 
        }
924
 
        catch ( CqString strError )
925
 
        {
926
 
                Aqsis::log() << error << strError.c_str() << std::endl;
927
 
                fFailed = TqTrue;
928
 
        }
929
 
 
930
 
        // Delete the world context
931
 
        QGetRenderContext() ->EndWorldModeBlock();
932
 
 
933
 
        // Stop the frame timer
934
 
        //QGetRenderContext() ->Stats().StopFrameTimer();
935
 
        TIMER_STOP("Frame")
936
 
 
937
 
        if ( !fFailed )
938
 
        {
939
 
                // Get the verbosity level from the options...
940
 
                TqInt verbosity = 0;
941
 
                const TqInt* poptEndofframe = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "statistics", "endofframe" );
942
 
                if ( poptEndofframe != 0 )
943
 
                        verbosity = poptEndofframe[ 0 ];
944
 
 
945
 
                // ...and print the statistics.
946
 
                QGetRenderContext() ->Stats().PrintStats( verbosity );
947
 
        }
948
 
 
949
 
        QGetRenderContext()->SetWorldBegin(TqFalse);
950
 
 
951
 
        return ;
952
 
}
953
 
 
954
 
 
955
 
//----------------------------------------------------------------------
956
 
// RiFormat
957
 
// Specify the setup of the final image.
958
 
//
959
 
RtVoid  RiFormat( RtInt xresolution, RtInt yresolution, RtFloat pixelaspectratio )
960
 
{
961
 
        VALIDATE_CONDITIONAL
962
 
 
963
 
        CACHE_RIFORMAT
964
 
 
965
 
        VALIDATE_RIFORMAT
966
 
 
967
 
        DEBUG_RIFORMAT
968
 
 
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 ;
972
 
 
973
 
        return ;
974
 
}
975
 
 
976
 
 
977
 
//----------------------------------------------------------------------
978
 
// RiFrameAspectRatio
979
 
// Set the aspect ratio of the frame irrespective of the display setup.
980
 
//
981
 
RtVoid  RiFrameAspectRatio( RtFloat frameratio )
982
 
{
983
 
        VALIDATE_CONDITIONAL
984
 
 
985
 
        CACHE_RIFRAMEASPECTRATIO
986
 
 
987
 
        VALIDATE_RIFRAMEASPECTRATIO
988
 
 
989
 
        DEBUG_RIFRAMEASPECTRATIO
990
 
 
991
 
        CqLogRangeCheckCallback rc;
992
 
 
993
 
        bool valid = true;
994
 
 
995
 
        rc.set( "frameratio");
996
 
        if( !CheckMinMax( frameratio, 0.0f, RI_INFINITY, &rc ) )
997
 
        {
998
 
                valid = false;
999
 
        }
1000
 
 
1001
 
        if( !valid )
1002
 
        {
1003
 
                Aqsis::log() << error << "RiFrameAspectRatio: Invalid RiFrameAspectRatio, aborting" << std::endl;
1004
 
                return;
1005
 
        }
1006
 
 
1007
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = frameratio ;
1008
 
 
1009
 
        // Inform the system that RiFrameAspectRatio has been called, as this takes priority.
1010
 
        QGetRenderContext()->poptWriteCurrent()->GetIntegerOptionWrite("System", "CameraFlags")[0] |= CameraFARSet;
1011
 
 
1012
 
        return ;
1013
 
}
1014
 
 
1015
 
 
1016
 
//----------------------------------------------------------------------
1017
 
// RiScreenWindow
1018
 
// Set the resolution of the screen window in the image plane specified in the screen
1019
 
// coordinate system.
1020
 
//
1021
 
RtVoid  RiScreenWindow( RtFloat left, RtFloat right, RtFloat bottom, RtFloat top )
1022
 
{
1023
 
        VALIDATE_CONDITIONAL
1024
 
 
1025
 
        CACHE_RISCREENWINDOW
1026
 
 
1027
 
        VALIDATE_RISCREENWINDOW
1028
 
 
1029
 
        DEBUG_RISCREENWINDOW
1030
 
 
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 ;
1035
 
 
1036
 
        // Inform the system that RiScreenWindow has been called, as this takes priority.
1037
 
        QGetRenderContext()->poptWriteCurrent()->GetIntegerOptionWrite("System", "CameraFlags")[0] |= CameraScreenWindowSet;
1038
 
 
1039
 
        return ;
1040
 
}
1041
 
 
1042
 
 
1043
 
//----------------------------------------------------------------------
1044
 
// RiCropWindow
1045
 
// Set the position and size of the crop window specified in fractions of the raster
1046
 
// window.
1047
 
//
1048
 
RtVoid  RiCropWindow( RtFloat left, RtFloat right, RtFloat top, RtFloat bottom )
1049
 
{
1050
 
        VALIDATE_CONDITIONAL
1051
 
 
1052
 
        CACHE_RICROPWINDOW
1053
 
 
1054
 
        VALIDATE_RICROPWINDOW
1055
 
 
1056
 
        DEBUG_RICROPWINDOW
1057
 
 
1058
 
        CqLogRangeCheckCallback rc;
1059
 
 
1060
 
        bool valid = true;
1061
 
 
1062
 
        rc.set( "left");
1063
 
        if( !CheckMinMax( left, 0.0f, 1.0f, &rc ) )
1064
 
        {
1065
 
                valid = false;
1066
 
        }
1067
 
 
1068
 
        rc.set( "right" );
1069
 
        if( !CheckMinMax( right, 0.0f, 1.0f, &rc ) )
1070
 
        {
1071
 
                valid = false;
1072
 
        }
1073
 
 
1074
 
        rc.set( "top" );
1075
 
        if( !CheckMinMax( top, 0.0f, 1.0f, &rc ) )
1076
 
        {
1077
 
                valid = false;
1078
 
        }
1079
 
 
1080
 
        rc.set( "bottom" );
1081
 
        if( !CheckMinMax( bottom, 0.0f, 1.0f, &rc ) )
1082
 
        {
1083
 
                valid = false;
1084
 
        }
1085
 
 
1086
 
        if (bottom == top)
1087
 
        {
1088
 
                valid = false;
1089
 
        }
1090
 
 
1091
 
        if (left == right)
1092
 
        {
1093
 
                valid = false;
1094
 
        }
1095
 
 
1096
 
        if( !valid )
1097
 
        {
1098
 
                Aqsis::log() << error << "Invalid RiCropWindow, ignoring" << std::endl;
1099
 
                return;
1100
 
        }
1101
 
 
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 ;
1106
 
 
1107
 
        return ;
1108
 
}
1109
 
 
1110
 
 
1111
 
//----------------------------------------------------------------------
1112
 
// RiProjection
1113
 
// Set the camera projection to be used.
1114
 
//
1115
 
RtVoid  RiProjection( RtToken name, ... )
1116
 
{
1117
 
        EXTRACT_PARAMETERS( name )
1118
 
 
1119
 
        RiProjectionV( name, PASS_PARAMETERS );
1120
 
}
1121
 
 
1122
 
 
1123
 
//----------------------------------------------------------------------
1124
 
// RiProjectionV
1125
 
// List mode version of above.
1126
 
//
1127
 
RtVoid  RiProjectionV( RtToken name, PARAMETERLIST )
1128
 
{
1129
 
        VALIDATE_CONDITIONAL
1130
 
 
1131
 
        CACHE_RIPROJECTION
1132
 
 
1133
 
        VALIDATE_RIPROJECTION
1134
 
 
1135
 
        DEBUG_RIPROJECTION
1136
 
 
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 )
1142
 
        {
1143
 
                Aqsis::log() << error << "RiProjection: Invalid projection: \"" << name << "\"" << std::endl;
1144
 
                return ;
1145
 
        }
1146
 
 
1147
 
        RtInt i;
1148
 
        for ( i = 0; i < count; ++i )
1149
 
        {
1150
 
                RtToken token = tokens[ i ];
1151
 
                RtPointer       value = values[ i ];
1152
 
 
1153
 
                if ( strcmp( token, RI_FOV ) == 0 )
1154
 
                        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FOV" ) [ 0 ] = *( reinterpret_cast<RtFloat*>( value ) ) ;
1155
 
        }
1156
 
        // TODO: need to get the current transformation so that it can be added to the screen transformation.
1157
 
        QGetRenderContext() ->ptransSetTime( CqMatrix() );
1158
 
 
1159
 
        return ;
1160
 
}
1161
 
 
1162
 
 
1163
 
//----------------------------------------------------------------------
1164
 
// RiClipping
1165
 
// Set the near and far clipping planes specified as distances from the camera.
1166
 
//
1167
 
RtVoid  RiClipping( RtFloat cnear, RtFloat cfar )
1168
 
{
1169
 
        VALIDATE_CONDITIONAL
1170
 
 
1171
 
        CACHE_RICLIPPING
1172
 
 
1173
 
        VALIDATE_RICLIPPING
1174
 
 
1175
 
        DEBUG_RICLIPPING
1176
 
 
1177
 
        CqLogRangeCheckCallback rc;
1178
 
 
1179
 
        bool valid = true;
1180
 
 
1181
 
        rc.set( "near");
1182
 
        if( !CheckMinMax( cnear, RI_EPSILON, cfar, &rc ) )
1183
 
        {
1184
 
                valid = false;
1185
 
        }
1186
 
 
1187
 
        rc.set( "far" );
1188
 
        if( !CheckMinMax( cfar, cnear, RI_INFINITY, &rc ) )
1189
 
        {
1190
 
                valid = false;
1191
 
        }
1192
 
 
1193
 
        if( !valid )
1194
 
        {
1195
 
                Aqsis::log() << error << "RiClipping: Invalid RiClipping, clipping planes set to RI_EPSILON, RI_INFINITY" << std::endl;
1196
 
                cnear   = RI_EPSILON;
1197
 
                cfar    = RI_INFINITY;
1198
 
        }
1199
 
 
1200
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Clipping" ) [ 0 ] = cnear ;
1201
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Clipping" ) [ 1 ] = cfar ;
1202
 
 
1203
 
        return ;
1204
 
}
1205
 
 
1206
 
 
1207
 
//----------------------------------------------------------------------
1208
 
// RiDepthOfField
1209
 
// Specify the parameters which affect focal blur of the camera.
1210
 
//
1211
 
RtVoid  RiDepthOfField( RtFloat fstop, RtFloat focallength, RtFloat focaldistance )
1212
 
{
1213
 
        VALIDATE_CONDITIONAL
1214
 
 
1215
 
        CACHE_RIDEPTHOFFIELD
1216
 
 
1217
 
        VALIDATE_RIDEPTHOFFIELD
1218
 
 
1219
 
        DEBUG_RIDEPTHOFFIELD
1220
 
 
1221
 
        CqLogRangeCheckCallback rc;
1222
 
 
1223
 
        bool valid = true;
1224
 
 
1225
 
        rc.set( "fstop" );
1226
 
        if( !CheckMinMax( fstop, 0.0f, RI_INFINITY, &rc ) )
1227
 
        {
1228
 
                valid = false;
1229
 
        }
1230
 
 
1231
 
        rc.set( "focallength" );
1232
 
        if( !CheckMinMax( focallength, 0.0f, RI_INFINITY, &rc ) )
1233
 
        {
1234
 
                valid = false;
1235
 
        }
1236
 
 
1237
 
        rc.set( "focaldistance" );
1238
 
        if( !CheckMinMax( focaldistance, 0.0f, RI_INFINITY, &rc ) )
1239
 
        {
1240
 
                valid = false;
1241
 
        }
1242
 
 
1243
 
        if( !valid )
1244
 
        {
1245
 
                Aqsis::log() << warning << "RiDepthOfField: Invalid DepthOfField, DepthOfField ignored" << std::endl;
1246
 
                return;
1247
 
        }
1248
 
 
1249
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "DepthOfField" ) [ 0 ] = fstop ;
1250
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "DepthOfField" ) [ 1 ] = focallength ;
1251
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "DepthOfField" ) [ 2 ] = focaldistance ;
1252
 
 
1253
 
        QGetRenderContext() ->SetDepthOfFieldData( fstop, focallength, focaldistance );
1254
 
}
1255
 
 
1256
 
 
1257
 
//----------------------------------------------------------------------
1258
 
// RiShutter
1259
 
//      Set the times at which the shutter opens and closes, used for motion blur.
1260
 
//
1261
 
RtVoid  RiShutter( RtFloat opentime, RtFloat closetime )
1262
 
{
1263
 
        VALIDATE_CONDITIONAL
1264
 
 
1265
 
        CACHE_RISHUTTER
1266
 
 
1267
 
        VALIDATE_RISHUTTER
1268
 
 
1269
 
        DEBUG_RISHUTTER
1270
 
 
1271
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Shutter" ) [ 0 ] = opentime;
1272
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Shutter" ) [ 1 ] = closetime;
1273
 
 
1274
 
        return ;
1275
 
}
1276
 
 
1277
 
 
1278
 
//----------------------------------------------------------------------
1279
 
// RiPixelVariance
1280
 
// Set the upper bound on the variance from the true pixel color by the pixel filter
1281
 
// function.
1282
 
//
1283
 
RtVoid  RiPixelVariance( RtFloat variance )
1284
 
{
1285
 
        VALIDATE_CONDITIONAL
1286
 
 
1287
 
        CACHE_RIPIXELVARIANCE
1288
 
 
1289
 
        VALIDATE_RIPIXELVARIANCE
1290
 
 
1291
 
        DEBUG_RIPIXELVARIANCE
1292
 
 
1293
 
        CqLogRangeCheckCallback rc;
1294
 
 
1295
 
        bool valid = true;
1296
 
 
1297
 
        rc.set( "variance" );
1298
 
        if( !CheckMinMax( variance, 0.0f, RI_INFINITY, &rc ) )
1299
 
        {
1300
 
                valid = false;
1301
 
        }
1302
 
 
1303
 
        if( !valid )
1304
 
        {
1305
 
                Aqsis::log() << warning << "RiPixelVariance: Invalid PixelVariance, PixelVariance set to 0" << std::endl;
1306
 
                variance = 0;
1307
 
        }
1308
 
 
1309
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "PixelVariance" ) [ 0 ] = variance ;
1310
 
 
1311
 
        return ;
1312
 
}
1313
 
 
1314
 
 
1315
 
//----------------------------------------------------------------------
1316
 
// RiPixelSamples
1317
 
// Set the number of samples per pixel for the hidden surface function.
1318
 
//
1319
 
RtVoid  RiPixelSamples( RtFloat xsamples, RtFloat ysamples )
1320
 
{
1321
 
        VALIDATE_CONDITIONAL
1322
 
 
1323
 
        CACHE_RIPIXELSAMPLES
1324
 
 
1325
 
        VALIDATE_RIPIXELSAMPLES
1326
 
 
1327
 
        DEBUG_RIPIXELSAMPLES
1328
 
 
1329
 
        CqLogRangeCheckCallback rc;
1330
 
 
1331
 
        bool valid = true;
1332
 
 
1333
 
        rc.set( "xsamples" );
1334
 
        if( !CheckMinMax( xsamples, 1.0f, RI_INFINITY, &rc ) )
1335
 
        {
1336
 
                valid = false;
1337
 
        }
1338
 
 
1339
 
        rc.set( "ysamples" );
1340
 
        if( !CheckMinMax( ysamples, 1.0f, RI_INFINITY, &rc ) )
1341
 
        {
1342
 
                valid = false;
1343
 
        }
1344
 
 
1345
 
        if( !valid )
1346
 
        {
1347
 
                Aqsis::log() << warning << "RiPixelSamples: Invalid PixelSamples, PixelSamples set to 1, 1" << std::endl;
1348
 
                xsamples = 1;
1349
 
                ysamples = 1;
1350
 
        }
1351
 
 
1352
 
        QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "PixelSamples" ) [ 0 ] = static_cast<TqInt>( xsamples ) ;
1353
 
        QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "PixelSamples" ) [ 1 ] = static_cast<TqInt>( ysamples ) ;
1354
 
 
1355
 
        return ;
1356
 
}
1357
 
 
1358
 
 
1359
 
//----------------------------------------------------------------------
1360
 
// RiPixelFilter
1361
 
// Set the function used to generate a final pixel value from supersampled values.
1362
 
//
1363
 
RtVoid  RiPixelFilter( RtFilterFunc function, RtFloat xwidth, RtFloat ywidth )
1364
 
{
1365
 
        VALIDATE_CONDITIONAL
1366
 
 
1367
 
        CACHE_RIPIXELFILTER
1368
 
 
1369
 
        VALIDATE_RIPIXELFILTER
1370
 
 
1371
 
        DEBUG_RIPIXELFILTER
1372
 
 
1373
 
        QGetRenderContext() ->poptWriteCurrent()->SetfuncFilter( function );
1374
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FilterWidth" ) [ 0 ] = xwidth ;
1375
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "FilterWidth" ) [ 1 ] = ywidth ;
1376
 
 
1377
 
        return ;
1378
 
}
1379
 
 
1380
 
 
1381
 
//----------------------------------------------------------------------
1382
 
// RiExposure
1383
 
//      Set the values of the exposure color modification function.
1384
 
//
1385
 
RtVoid  RiExposure( RtFloat gain, RtFloat gamma )
1386
 
{
1387
 
        VALIDATE_CONDITIONAL
1388
 
 
1389
 
        CACHE_RIEXPOSURE
1390
 
 
1391
 
        VALIDATE_RIEXPOSURE
1392
 
 
1393
 
        DEBUG_RIEXPOSURE
1394
 
 
1395
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Exposure" ) [ 0 ] = gain ;
1396
 
        QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "Exposure" ) [ 1 ] = gamma ;
1397
 
 
1398
 
        return ;
1399
 
}
1400
 
 
1401
 
 
1402
 
//----------------------------------------------------------------------
1403
 
// RiImager
1404
 
// Specify a prepocessing imager shader.
1405
 
//
1406
 
RtVoid  RiImager( RtToken name, ... )
1407
 
{
1408
 
        EXTRACT_PARAMETERS( name )
1409
 
 
1410
 
        RiImagerV( name, PASS_PARAMETERS );
1411
 
}
1412
 
 
1413
 
 
1414
 
//----------------------------------------------------------------------
1415
 
// RiImagerV
1416
 
// List based version of above.
1417
 
//
1418
 
RtVoid  RiImagerV( RtToken name, PARAMETERLIST )
1419
 
{
1420
 
        VALIDATE_CONDITIONAL
1421
 
 
1422
 
        CACHE_RIIMAGER
1423
 
 
1424
 
        VALIDATE_RIIMAGER
1425
 
 
1426
 
        DEBUG_RIIMAGER
1427
 
 
1428
 
        // Find the shader.
1429
 
        boost::shared_ptr<IqShader> pshadImager = QGetRenderContext()->CreateShader( name, Type_Imager );
1430
 
 
1431
 
        if ( pshadImager )
1432
 
        {
1433
 
                QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "Imager" ) [ 0 ] = name ;
1434
 
                QGetRenderContext()->poptWriteCurrent()->SetpshadImager( pshadImager );
1435
 
                RtInt i;
1436
 
                for ( i = 0; i < count; ++i )
1437
 
                {
1438
 
                        RtToken token = tokens[ i ];
1439
 
                        RtPointer       value = values[ i ];
1440
 
 
1441
 
                        SetShaderArgument( pshadImager, token, static_cast<TqPchar>( value ) );
1442
 
                }
1443
 
        }
1444
 
        return ;
1445
 
}
1446
 
 
1447
 
 
1448
 
//----------------------------------------------------------------------
1449
 
// RiQuantize
1450
 
// Specify the color quantization parameters.
1451
 
//
1452
 
RtVoid  RiQuantize( RtToken type, RtInt one, RtInt min, RtInt max, RtFloat ditheramplitude )
1453
 
{
1454
 
        VALIDATE_CONDITIONAL
1455
 
 
1456
 
        CACHE_RIQUANTIZE
1457
 
 
1458
 
        VALIDATE_RIQUANTIZE
1459
 
 
1460
 
        DEBUG_RIQUANTIZE
1461
 
 
1462
 
        if ( strcmp( type, "rgba" ) == 0 )
1463
 
        {
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 );
1469
 
        }
1470
 
        else if ( strcmp( type, "z" ) == 0 )
1471
 
        {
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 );
1477
 
        }
1478
 
        else
1479
 
        {
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 );
1485
 
        }
1486
 
 
1487
 
        return ;
1488
 
}
1489
 
 
1490
 
 
1491
 
//----------------------------------------------------------------------
1492
 
// RiDisplay
1493
 
// Set the final output name and type.
1494
 
//
1495
 
RtVoid  RiDisplay( RtToken name, RtToken type, RtToken mode, ... )
1496
 
{
1497
 
        EXTRACT_PARAMETERS( mode )
1498
 
 
1499
 
        RiDisplayV( name, type, mode, PASS_PARAMETERS );
1500
 
}
1501
 
 
1502
 
 
1503
 
//----------------------------------------------------------------------
1504
 
// RiDisplayV
1505
 
// List based version of above.
1506
 
//
1507
 
RtVoid  RiDisplayV( RtToken name, RtToken type, RtToken mode, PARAMETERLIST )
1508
 
{
1509
 
        VALIDATE_CONDITIONAL
1510
 
 
1511
 
        CACHE_RIDISPLAY
1512
 
 
1513
 
        VALIDATE_RIDISPLAY
1514
 
 
1515
 
        DEBUG_RIDISPLAY
1516
 
 
1517
 
        CqString strName( name );
1518
 
        CqString strType( type );
1519
 
 
1520
 
        QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "DisplayName" ) [ 0 ] = strName.c_str() ;
1521
 
        QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "DisplayType" ) [ 0 ] = strType.c_str() ;
1522
 
 
1523
 
        // Append the display mode to the current setting.
1524
 
        TqInt eValue = 0;
1525
 
        TqInt index = 0;
1526
 
        TqInt dataOffset = 0;
1527
 
        TqInt dataSize = 0;
1528
 
        if ( strncmp( mode, RI_RGB, strlen(RI_RGB) ) == 0 )
1529
 
        {
1530
 
                eValue |= ModeRGB;
1531
 
                dataSize += 3;
1532
 
                index += strlen( RI_RGB );
1533
 
        }
1534
 
        if ( strncmp( &mode[index], RI_A, strlen( RI_A ) ) == 0 )
1535
 
        {
1536
 
                eValue |= ModeA;
1537
 
                dataSize += 1;
1538
 
                index += strlen( RI_A );
1539
 
        }
1540
 
        if ( strncmp( &mode[index], RI_Z, strlen( RI_Z ) ) == 0 )
1541
 
        {
1542
 
                eValue |= ModeZ;
1543
 
                dataSize += 1;
1544
 
                index += strlen( RI_Z );
1545
 
        }
1546
 
 
1547
 
        // Special case test.
1548
 
        if(strncmp(&mode[index], "depth", strlen("depth") ) == 0 )
1549
 
        {
1550
 
                dataSize = 1;
1551
 
                dataOffset = 6;
1552
 
        }
1553
 
 
1554
 
        // If none of the standard "rgbaz" strings match, then it is an alternative 'arbitrary output variable'
1555
 
        else if( eValue == 0 )
1556
 
        {
1557
 
                dataOffset = QGetRenderContext()->RegisterOutputData( mode );
1558
 
                dataSize = QGetRenderContext()->OutputDataSamples( mode );
1559
 
        }
1560
 
 
1561
 
        // Check if the display request is valid.
1562
 
        if(dataOffset >= 0 && dataSize >0)
1563
 
        {
1564
 
                // Gather the additional arguments into a map to pass through to the manager.
1565
 
                std::map<std::string, void*> mapOfArguments;
1566
 
                TqInt i;
1567
 
                for( i = 0; i < count; ++i )
1568
 
                        mapOfArguments[ tokens[ i ] ] = values[ i ];
1569
 
 
1570
 
                // Check if the request is to add a display driver.
1571
 
                if ( strName[ 0 ] == '+' )
1572
 
                {
1573
 
                        TqInt iMode = QGetRenderContext() ->poptCurrent()->GetIntegerOption( "System", "DisplayMode" ) [ 0 ] | eValue;
1574
 
                        QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = iMode;
1575
 
                        strName = strName.substr( 1 );
1576
 
                }
1577
 
                else
1578
 
                {
1579
 
                        QGetRenderContext() ->ClearDisplayRequests();
1580
 
                        QGetRenderContext() ->poptWriteCurrent()->GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = eValue ;
1581
 
                }
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 );
1584
 
        }
1585
 
        return ;
1586
 
}
1587
 
 
1588
 
//----------------------------------------------------------------------
1589
 
// RiHider
1590
 
// Specify a hidden surface calculation mode.
1591
 
//
1592
 
RtVoid  RiHider( RtToken name, ... )
1593
 
{
1594
 
        EXTRACT_PARAMETERS( name )
1595
 
 
1596
 
        RiHiderV( name, PASS_PARAMETERS );
1597
 
 
1598
 
}
1599
 
 
1600
 
//----------------------------------------------------------------------
1601
 
// RiHiderV
1602
 
// List based version of above.
1603
 
//
1604
 
RtVoid  RiHiderV( RtToken name, PARAMETERLIST )
1605
 
{
1606
 
        VALIDATE_CONDITIONAL
1607
 
 
1608
 
        CACHE_RIHIDER
1609
 
 
1610
 
        VALIDATE_RIHIDER
1611
 
 
1612
 
        DEBUG_RIHIDER
1613
 
 
1614
 
        if ( !strcmp( name, "hidden" ) || !strcmp( name, "painter" ) )
1615
 
        {
1616
 
                QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "Hider" ) [ 0 ] = name ;
1617
 
        }
1618
 
 
1619
 
        // Check options.
1620
 
        TqInt i;
1621
 
        for ( i = 0; i < count; ++i )
1622
 
        {
1623
 
                SqParameterDeclaration Decl;
1624
 
                try
1625
 
                {
1626
 
                        Decl = QGetRenderContext()->FindParameterDecl( tokens[ i ] );
1627
 
                }
1628
 
                catch( XqException e )
1629
 
                {
1630
 
                        Aqsis::log() << error << e.strReason().c_str() << std::endl;
1631
 
                        continue;
1632
 
                }
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 );
1638
 
        }
1639
 
 
1640
 
        return ;
1641
 
}
1642
 
 
1643
 
 
1644
 
//----------------------------------------------------------------------
1645
 
// RiColorSamples
1646
 
// Specify the depth and conversion arrays for color manipulation.
1647
 
//
1648
 
RtVoid  RiColorSamples( RtInt N, RtFloat *nRGB, RtFloat *RGBn )
1649
 
{
1650
 
        VALIDATE_CONDITIONAL
1651
 
 
1652
 
        CACHE_RICOLORSAMPLES
1653
 
 
1654
 
        VALIDATE_RICOLORSAMPLES
1655
 
 
1656
 
        DEBUG_RICOLORSAMPLES
1657
 
 
1658
 
        Aqsis::log() << warning << "RiColorSamples not supported" << std::endl;
1659
 
        return ;
1660
 
}
1661
 
 
1662
 
 
1663
 
//----------------------------------------------------------------------
1664
 
// RiRelativeDetail
1665
 
// Set the scale used for all subsequent level of detail calculations.
1666
 
//
1667
 
RtVoid  RiRelativeDetail( RtFloat relativedetail )
1668
 
{
1669
 
        VALIDATE_CONDITIONAL
1670
 
 
1671
 
        CACHE_RIRELATIVEDETAIL
1672
 
 
1673
 
        VALIDATE_RIRELATIVEDETAIL
1674
 
 
1675
 
        DEBUG_RIRELATIVEDETAIL
1676
 
 
1677
 
        if ( relativedetail < 0.0f )
1678
 
        {
1679
 
                Aqsis::log() << error << "RiRelativeDetail < 0.0" << std::endl;
1680
 
        }
1681
 
        else
1682
 
        {
1683
 
                QGetRenderContext() ->poptWriteCurrent()->GetFloatOptionWrite( "System", "RelativeDetail" ) [ 0 ] = relativedetail;
1684
 
        }
1685
 
        return ;
1686
 
}
1687
 
 
1688
 
 
1689
 
//----------------------------------------------------------------------
1690
 
// RiOption
1691
 
// Specify system specific option.
1692
 
//
1693
 
RtVoid  RiOption( RtToken name, ... )
1694
 
{
1695
 
        EXTRACT_PARAMETERS( name )
1696
 
 
1697
 
        RiOptionV( name, PASS_PARAMETERS );
1698
 
}
1699
 
 
1700
 
 
1701
 
//----------------------------------------------------------------------
1702
 
// RiOptionV
1703
 
// List based version of above.
1704
 
//
1705
 
RtVoid  RiOptionV( RtToken name, PARAMETERLIST )
1706
 
{
1707
 
        VALIDATE_CONDITIONAL
1708
 
 
1709
 
        CACHE_RIOPTION
1710
 
 
1711
 
        VALIDATE_RIOPTION
1712
 
 
1713
 
        DEBUG_RIOPTION
1714
 
 
1715
 
        RtInt i;
1716
 
        for ( i = 0; i < count; ++i )
1717
 
        {
1718
 
                RtToken token = tokens[ i ];
1719
 
                RtPointer       value = values[ i ];
1720
 
 
1721
 
                // Search for the parameter in the declarations.
1722
 
                // Note Options can only be uniform.
1723
 
                SqParameterDeclaration Decl;
1724
 
                try
1725
 
                {
1726
 
                        Decl = QGetRenderContext()->FindParameterDecl( token );
1727
 
                }
1728
 
                catch( XqException e )
1729
 
                {
1730
 
                        Aqsis::log() << error << e.strReason().c_str() << std::endl;
1731
 
                        continue;
1732
 
                }
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 )
1738
 
                {
1739
 
                        if ( Decl.m_strName == "" )
1740
 
                                Aqsis::log() << warning << "Unrecognised declaration : " << token << std::endl;
1741
 
                        else
1742
 
                                Aqsis::log() << warning << "Options can only be uniform [" << token << "]" << std::endl;
1743
 
                        return ;
1744
 
                }
1745
 
 
1746
 
                switch ( Type )
1747
 
                {
1748
 
                        case type_float:
1749
 
                        {
1750
 
                                RtFloat* pf = reinterpret_cast<RtFloat*>( value );
1751
 
                                TqFloat* pOpt = QGetRenderContext()->poptWriteCurrent()->GetFloatOptionWrite(name, undecoratedName.c_str(), Count);
1752
 
                                RtInt j;
1753
 
                                for ( j = 0; j < Count; ++j )
1754
 
                                        pOpt[ j ] = pf[ j ];
1755
 
                        }
1756
 
                        break;
1757
 
 
1758
 
                        case type_integer:
1759
 
                        {
1760
 
                                RtInt* pi = reinterpret_cast<RtInt*>( value );
1761
 
                                TqInt* pOpt = QGetRenderContext()->poptWriteCurrent()->GetIntegerOptionWrite(name, undecoratedName.c_str(), Count);
1762
 
                                RtInt j;
1763
 
                                for ( j = 0; j < Count; ++j )
1764
 
                                        pOpt[ j ] = pi[ j ];
1765
 
                        }
1766
 
                        break;
1767
 
 
1768
 
                        case type_string:
1769
 
                        {
1770
 
                                char** ps = reinterpret_cast<char**>( value );
1771
 
                                CqString* pOpt = QGetRenderContext()->poptWriteCurrent()->GetStringOptionWrite(name, undecoratedName.c_str(), Count);
1772
 
                                RtInt j;
1773
 
                                for ( j = 0; j < Count; ++j )
1774
 
                                {
1775
 
                                        CqString str( "" );
1776
 
                                        if ( strcmp( name, "searchpath" ) == 0 )
1777
 
                                        {
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;
1784
 
                                                while ( 1 )
1785
 
                                                {
1786
 
                                                        if ( ( len = strcspn( &ps[ j ][ strt ], "&" ) ) < strlen( &ps[ j ][ strt ] ) )
1787
 
                                                        {
1788
 
                                                                str += CqString( ps[ j ] ).substr( strt, len );
1789
 
                                                                str += str_old;
1790
 
                                                                strt += len + 1;
1791
 
                                                        }
1792
 
                                                        else
1793
 
                                                        {
1794
 
                                                                str += CqString( ps[ j ] ).substr( strt );
1795
 
                                                                break;
1796
 
                                                        }
1797
 
                                                }
1798
 
                                        }
1799
 
                                        else
1800
 
                                                str = CqString( ps[ j ] );
1801
 
 
1802
 
                                        pOpt[ j ] = str;
1803
 
                                }
1804
 
                        }
1805
 
                        break;
1806
 
 
1807
 
                        case type_color:
1808
 
                        {
1809
 
                                RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1810
 
                                CqColor* pOpt = QGetRenderContext()->poptWriteCurrent()->GetColorOptionWrite(name, undecoratedName.c_str(), Count);
1811
 
                                RtInt j;
1812
 
                                for ( j = 0; j < Count; ++j )
1813
 
                                        pOpt[ j ] = CqColor(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1814
 
                        }
1815
 
                        break;
1816
 
 
1817
 
                        case type_point:
1818
 
                        {
1819
 
                                RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1820
 
                                CqVector3D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetPointOptionWrite(name, undecoratedName.c_str(), Count);
1821
 
                                RtInt j;
1822
 
                                for ( j = 0; j < Count; ++j )
1823
 
                                        pOpt[ j ] = CqVector3D(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1824
 
                        }
1825
 
                        break;
1826
 
 
1827
 
                        case type_normal:
1828
 
                        {
1829
 
                                RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1830
 
                                CqVector3D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetPointOptionWrite(name, undecoratedName.c_str(), Count);
1831
 
                                RtInt j;
1832
 
                                for ( j = 0; j < Count; ++j )
1833
 
                                        pOpt[ j ] = CqVector3D(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1834
 
                        }
1835
 
                        break;
1836
 
 
1837
 
                        case type_vector:
1838
 
                        {
1839
 
                                RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1840
 
                                CqVector3D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetPointOptionWrite(name, undecoratedName.c_str(), Count);
1841
 
                                RtInt j;
1842
 
                                for ( j = 0; j < Count; ++j )
1843
 
                                        pOpt[ j ] = CqVector3D(pc[ (j*3) ], pc[ (j*3)+1 ], pc[ (j*3)+2 ]);
1844
 
                        }
1845
 
                        break;
1846
 
 
1847
 
                        case type_hpoint:
1848
 
                        {
1849
 
/*                              RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1850
 
                                CqVector4D* pOpt = QGetRenderContext()->poptWriteCurrent()->GetHPointOptionWrite(name, undecoratedName.c_str(), Count);
1851
 
                                RtInt j;
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]); */
1854
 
                        }
1855
 
                        break;
1856
 
 
1857
 
                        case type_matrix:
1858
 
                        {
1859
 
/*                              RtFloat* pc = reinterpret_cast<RtFloat*>( value );
1860
 
                                CqMatrix* pOpt = QGetRenderContext()->poptWriteCurrent()->GetMatrixOptionWrite(name, undecoratedName.c_str(), Count);
1861
 
                                RtInt j;
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 ]); */
1867
 
                        }
1868
 
                        break;
1869
 
                }
1870
 
        }
1871
 
        return ;
1872
 
}
1873
 
 
1874
 
 
1875
 
//----------------------------------------------------------------------
1876
 
// RiAttributeBegin
1877
 
// Begin a ne attribute definition, pushes the current attributes.
1878
 
//
1879
 
RtVoid  RiAttributeBegin()
1880
 
{
1881
 
        VALIDATE_CONDITIONAL
1882
 
 
1883
 
        CACHE_RIATTRIBUTEBEGIN
1884
 
 
1885
 
        VALIDATE_RIATTRIBUTEBEGIN
1886
 
 
1887
 
        DEBUG_RIATTRIBUTEBEGIN
1888
 
 
1889
 
        QGetRenderContext() ->BeginAttributeModeBlock();
1890
 
 
1891
 
        return ;
1892
 
}
1893
 
 
1894
 
 
1895
 
//----------------------------------------------------------------------
1896
 
// RiAttributeEnd
1897
 
// End the current attribute defintion, pops the previous attributes.
1898
 
//
1899
 
RtVoid  RiAttributeEnd()
1900
 
{
1901
 
        VALIDATE_CONDITIONAL
1902
 
 
1903
 
        CACHE_RIATTRIBUTEEND
1904
 
 
1905
 
        VALIDATE_RIATTRIBUTEEND
1906
 
 
1907
 
        DEBUG_RIATTRIBUTEEND
1908
 
 
1909
 
        QGetRenderContext() ->EndAttributeModeBlock();
1910
 
 
1911
 
        return ;
1912
 
}
1913
 
 
1914
 
 
1915
 
//----------------------------------------------------------------------
1916
 
// RiColor
1917
 
//      Set the current color for use by the geometric primitives.
1918
 
//
1919
 
RtVoid  RiColor( RtColor Cq )
1920
 
{
1921
 
        VALIDATE_CONDITIONAL
1922
 
 
1923
 
        CACHE_RICOLOR
1924
 
 
1925
 
        VALIDATE_RICOLOR
1926
 
 
1927
 
        DEBUG_RICOLOR
1928
 
 
1929
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Color" ) [ 0 ] = CqColor( Cq );
1930
 
        QGetRenderContext() ->AdvanceTime();
1931
 
        return ;
1932
 
}
1933
 
 
1934
 
 
1935
 
//----------------------------------------------------------------------
1936
 
// RiOpacity
1937
 
// Set the current opacity, for use by the geometric primitives.
1938
 
//
1939
 
RtVoid  RiOpacity( RtColor Os )
1940
 
{
1941
 
        VALIDATE_CONDITIONAL
1942
 
 
1943
 
        CACHE_RIOPACITY
1944
 
 
1945
 
        VALIDATE_RIOPACITY
1946
 
 
1947
 
        DEBUG_RIOPACITY
1948
 
 
1949
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Opacity" ) [ 0 ] = CqColor( Os );
1950
 
        QGetRenderContext() ->AdvanceTime();
1951
 
        return ;
1952
 
}
1953
 
 
1954
 
 
1955
 
//----------------------------------------------------------------------
1956
 
// RiTextureCoordinates
1957
 
// Set the current texture coordinates used by the parametric geometric primitives.
1958
 
//
1959
 
RtVoid  RiTextureCoordinates( RtFloat s1, RtFloat t1,
1960
 
                             RtFloat s2, RtFloat t2,
1961
 
                             RtFloat s3, RtFloat t3,
1962
 
                             RtFloat s4, RtFloat t4 )
1963
 
{
1964
 
        VALIDATE_CONDITIONAL
1965
 
 
1966
 
        CACHE_RITEXTURECOORDINATES
1967
 
 
1968
 
        VALIDATE_RITEXTURECOORDINATES
1969
 
 
1970
 
        DEBUG_RITEXTURECOORDINATES
1971
 
 
1972
 
        TqFloat * pTC = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "TextureCoordinates" );
1973
 
 
1974
 
        assert( NULL != pTC );
1975
 
 
1976
 
        pTC[ 0 ] = s1;
1977
 
        pTC[ 1 ] = t1;
1978
 
        pTC[ 2 ] = s2;
1979
 
        pTC[ 3 ] = t2;
1980
 
        pTC[ 4 ] = s3;
1981
 
        pTC[ 5 ] = t3;
1982
 
        pTC[ 6 ] = s4;
1983
 
        pTC[ 7 ] = t4;
1984
 
        QGetRenderContext() ->AdvanceTime();
1985
 
 
1986
 
        return ;
1987
 
}
1988
 
 
1989
 
 
1990
 
//----------------------------------------------------------------------
1991
 
// RiLightSource
1992
 
// Create a new light source at the current transformation.
1993
 
//
1994
 
RtLightHandle   RiLightSource( RtToken name, ... )
1995
 
{
1996
 
        EXTRACT_PARAMETERS( name )
1997
 
 
1998
 
        return ( RiLightSourceV( name, PASS_PARAMETERS ) );
1999
 
}
2000
 
 
2001
 
 
2002
 
//----------------------------------------------------------------------
2003
 
// RiLightSourceV
2004
 
// List based version of above.
2005
 
//
2006
 
RtLightHandle   RiLightSourceV( RtToken name, PARAMETERLIST )
2007
 
{
2008
 
        VALIDATE_CONDITIONAL0
2009
 
 
2010
 
        CACHE_RILIGHTSOURCE
2011
 
 
2012
 
        VALIDATE_RILIGHTSOURCE
2013
 
 
2014
 
        DEBUG_RILIGHTSOURCE
2015
 
 
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 );
2019
 
 
2020
 
        if ( !pShader )
2021
 
        {
2022
 
                Aqsis::log() << error << "Couldn't create light source shader \"" << name << "\"\n";
2023
 
                return 0;
2024
 
        }
2025
 
 
2026
 
        pShader->SetTransform( QGetRenderContext() ->ptransCurrent() );
2027
 
        CqLightsourcePtr pNew( new CqLightsource( pShader, RI_TRUE ) );
2028
 
        Lightsource_stack.push_back(pNew);
2029
 
 
2030
 
        // Execute the intiialisation code here, as we now have our shader context complete.
2031
 
        pShader->PrepareDefArgs();
2032
 
 
2033
 
        if ( pNew )
2034
 
        {
2035
 
                RtInt i;
2036
 
                for ( i = 0; i < count; ++i )
2037
 
                {
2038
 
                        RtToken token = tokens[ i ];
2039
 
                        RtPointer       value = values[ i ];
2040
 
 
2041
 
                        SetShaderArgument( pShader, token, static_cast<TqPchar>( value ) );
2042
 
                }
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();
2048
 
 
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() ) );
2052
 
        }
2053
 
        return ( 0 );
2054
 
}
2055
 
 
2056
 
 
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.
2062
 
//
2063
 
RtLightHandle   RiAreaLightSource( RtToken name, ... )
2064
 
{
2065
 
 
2066
 
        EXTRACT_PARAMETERS( name )
2067
 
 
2068
 
        return ( RiAreaLightSourceV( name, PASS_PARAMETERS ) );
2069
 
}
2070
 
 
2071
 
 
2072
 
//----------------------------------------------------------------------
2073
 
// RiAreaLightSourceV
2074
 
// List based version of above.
2075
 
//
2076
 
RtLightHandle   RiAreaLightSourceV( RtToken name, PARAMETERLIST )
2077
 
{
2078
 
        VALIDATE_CONDITIONAL0
2079
 
 
2080
 
        CACHE_RIAREALIGHTSOURCE
2081
 
 
2082
 
        VALIDATE_RIAREALIGHTSOURCE
2083
 
 
2084
 
        DEBUG_RIAREALIGHTSOURCE
2085
 
 
2086
 
        Aqsis::log() << warning << "RiAreaLightSource not supported, will produce a point light" << std::endl;
2087
 
 
2088
 
        return ( RiLightSourceV( name, count, tokens, values ) );
2089
 
}
2090
 
 
2091
 
 
2092
 
//----------------------------------------------------------------------
2093
 
// RiIlluminate
2094
 
// Set the current status of the specified light source.
2095
 
//
2096
 
RtVoid  RiIlluminate( RtLightHandle light, RtBoolean onoff )
2097
 
{
2098
 
        VALIDATE_CONDITIONAL
2099
 
 
2100
 
        CACHE_RIILLUMINATE
2101
 
 
2102
 
        VALIDATE_RIILLUMINATE
2103
 
 
2104
 
        DEBUG_RIILLUMINATE
2105
 
 
2106
 
        CqLightsourcePtr pL( reinterpret_cast<CqLightsource*>( light )->shared_from_this() );
2107
 
 
2108
 
        // Check if we are turning the light on or off.
2109
 
        if ( light == NULL ) return ;
2110
 
        if ( onoff )
2111
 
                QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( pL );
2112
 
        else
2113
 
                QGetRenderContext() ->pattrWriteCurrent() ->RemoveLightsource( pL );
2114
 
        return ;
2115
 
}
2116
 
 
2117
 
 
2118
 
//----------------------------------------------------------------------
2119
 
// RiSurface
2120
 
// Set the current surface shader, used by geometric primitives.
2121
 
//
2122
 
RtVoid  RiSurface( RtToken name, ... )
2123
 
{
2124
 
        EXTRACT_PARAMETERS( name )
2125
 
 
2126
 
        RiSurfaceV( name, PASS_PARAMETERS );
2127
 
}
2128
 
 
2129
 
 
2130
 
//----------------------------------------------------------------------
2131
 
// RiSurfaceV
2132
 
// List based version of above.
2133
 
//
2134
 
RtVoid  RiSurfaceV( RtToken name, PARAMETERLIST )
2135
 
{
2136
 
 
2137
 
        VALIDATE_CONDITIONAL
2138
 
 
2139
 
        CACHE_RISURFACE
2140
 
 
2141
 
        VALIDATE_RISURFACE
2142
 
 
2143
 
        DEBUG_RISURFACE
2144
 
 
2145
 
        // Find the shader.
2146
 
        //IqShader * pshadSurface = QGetRenderContext() ->CreateShader( name, Type_Surface );
2147
 
        boost::shared_ptr<IqShader> pshadSurface = QGetRenderContext()->CreateShader( name, Type_Surface );
2148
 
 
2149
 
        if ( pshadSurface )
2150
 
        {
2151
 
                pshadSurface->SetTransform( QGetRenderContext() ->ptransCurrent() );
2152
 
                // Execute the intiialisation code here, as we now have our shader context complete.
2153
 
                pshadSurface->PrepareDefArgs();
2154
 
                RtInt i;
2155
 
                for ( i = 0; i < count; ++i )
2156
 
                {
2157
 
                        RtToken token = tokens[ i ];
2158
 
                        RtPointer       value = values[ i ];
2159
 
 
2160
 
                        SetShaderArgument( pshadSurface, token, static_cast<TqPchar>( value ) );
2161
 
                }
2162
 
                QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pshadSurface, QGetRenderContext() ->Time() );
2163
 
        }
2164
 
        QGetRenderContext() ->AdvanceTime();
2165
 
        return ;
2166
 
}
2167
 
 
2168
 
 
2169
 
//----------------------------------------------------------------------
2170
 
// RiAtmosphere
2171
 
// Set the current atrmospheric shader.
2172
 
//
2173
 
RtVoid  RiAtmosphere( RtToken name, ... )
2174
 
{
2175
 
        EXTRACT_PARAMETERS( name )
2176
 
 
2177
 
        RiAtmosphereV( name, PASS_PARAMETERS );
2178
 
}
2179
 
 
2180
 
 
2181
 
//----------------------------------------------------------------------
2182
 
// RiAtmosphereV
2183
 
// List based version of above.
2184
 
//
2185
 
RtVoid  RiAtmosphereV( RtToken name, PARAMETERLIST )
2186
 
{
2187
 
        VALIDATE_CONDITIONAL
2188
 
 
2189
 
        CACHE_RIATMOSPHERE
2190
 
 
2191
 
        VALIDATE_RIATMOSPHERE
2192
 
 
2193
 
        DEBUG_RIATMOSPHERE
2194
 
 
2195
 
        // Find the shader.
2196
 
        boost::shared_ptr<IqShader> pshadAtmosphere = QGetRenderContext()->CreateShader( name, Type_Volume );
2197
 
 
2198
 
        if ( pshadAtmosphere )
2199
 
        {
2200
 
                pshadAtmosphere->SetTransform( QGetRenderContext() ->ptransCurrent() );
2201
 
                // Execute the intiialisation code here, as we now have our shader context complete.
2202
 
                pshadAtmosphere->PrepareDefArgs();
2203
 
                RtInt i;
2204
 
                for ( i = 0; i < count; ++i )
2205
 
                {
2206
 
                        RtToken token = tokens[ i ];
2207
 
                        RtPointer       value = values[ i ];
2208
 
 
2209
 
                        SetShaderArgument( pshadAtmosphere, token, static_cast<TqPchar>( value ) );
2210
 
                }
2211
 
        }
2212
 
 
2213
 
        QGetRenderContext() ->pattrWriteCurrent() ->SetpshadAtmosphere( pshadAtmosphere, QGetRenderContext() ->Time() );
2214
 
        QGetRenderContext() ->AdvanceTime();
2215
 
        return ;
2216
 
}
2217
 
 
2218
 
 
2219
 
//----------------------------------------------------------------------
2220
 
// RiInterior
2221
 
// Set the current interior volumetric shader.
2222
 
//
2223
 
RtVoid  RiInterior( RtToken name, ... )
2224
 
{
2225
 
        Aqsis::log() << warning << "RiInterior not supported" << std::endl;
2226
 
        return ;
2227
 
}
2228
 
 
2229
 
 
2230
 
//----------------------------------------------------------------------
2231
 
// RiInteriorV
2232
 
// List based version of above.
2233
 
//
2234
 
RtVoid  RiInteriorV( RtToken name, PARAMETERLIST )
2235
 
{
2236
 
        VALIDATE_CONDITIONAL
2237
 
 
2238
 
        CACHE_RIINTERIOR
2239
 
 
2240
 
        VALIDATE_RIINTERIOR
2241
 
 
2242
 
        DEBUG_RIINTERIOR
2243
 
 
2244
 
        Aqsis::log() << warning << "RiInterior not supported" << std::endl;
2245
 
        return ;
2246
 
}
2247
 
 
2248
 
 
2249
 
//----------------------------------------------------------------------
2250
 
// RiExterior
2251
 
// Set the current exterior volumetric shader.
2252
 
//
2253
 
RtVoid  RiExterior( RtToken name, ... )
2254
 
{
2255
 
        Aqsis::log() << warning << "RiExterior not supported" << std::endl;
2256
 
        return ;
2257
 
}
2258
 
 
2259
 
 
2260
 
//----------------------------------------------------------------------
2261
 
// RiExteriorV
2262
 
// List based version of above.
2263
 
//
2264
 
RtVoid  RiExteriorV( RtToken name, PARAMETERLIST )
2265
 
{
2266
 
        VALIDATE_CONDITIONAL
2267
 
 
2268
 
        CACHE_RIEXTERIOR
2269
 
 
2270
 
        VALIDATE_RIEXTERIOR
2271
 
 
2272
 
        DEBUG_RIEXTERIOR
2273
 
 
2274
 
        Aqsis::log() << warning << "ExInterior not supported" << std::endl;
2275
 
        return ;
2276
 
}
2277
 
 
2278
 
 
2279
 
//----------------------------------------------------------------------
2280
 
// RiShadingRate
2281
 
// Specify the size of the shading area in pixels.
2282
 
//
2283
 
RtVoid  RiShadingRate( RtFloat size )
2284
 
{
2285
 
        VALIDATE_CONDITIONAL
2286
 
 
2287
 
        CACHE_RISHADINGRATE
2288
 
 
2289
 
        VALIDATE_RISHADINGRATE
2290
 
 
2291
 
        DEBUG_RISHADINGRATE
2292
 
 
2293
 
        CqLogRangeCheckCallback rc;
2294
 
 
2295
 
        bool valid = true;
2296
 
 
2297
 
        rc.set( "size" );
2298
 
        if( !CheckMinMax( size, 0.0f, RI_INFINITY, &rc ) )
2299
 
        {
2300
 
                valid = false;
2301
 
        }
2302
 
 
2303
 
        if( !valid )
2304
 
        {
2305
 
                Aqsis::log() << warning << "Invalid ShadingRate, ShadingRate set to 1" << std::endl;
2306
 
                size = 1;
2307
 
        }
2308
 
 
2309
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRate" ) [ 0 ] = size;
2310
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRateSqrt" ) [ 0 ] = sqrt( size );
2311
 
        QGetRenderContext() ->AdvanceTime();
2312
 
 
2313
 
        return ;
2314
 
}
2315
 
 
2316
 
 
2317
 
//----------------------------------------------------------------------
2318
 
// RiShadingInterpolation
2319
 
// Specify the method of shading interpolation.
2320
 
//
2321
 
RtVoid  RiShadingInterpolation( RtToken type )
2322
 
{
2323
 
        VALIDATE_CONDITIONAL
2324
 
 
2325
 
        CACHE_RISHADINGINTERPOLATION
2326
 
 
2327
 
        VALIDATE_RISHADINGINTERPOLATION
2328
 
 
2329
 
        DEBUG_RISHADINGINTERPOLATION
2330
 
 
2331
 
        if ( strcmp( type, RI_CONSTANT ) == 0 )
2332
 
                QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingConstant;
2333
 
        else
2334
 
                if ( strcmp( type, RI_SMOOTH ) == 0 )
2335
 
                        QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingSmooth;
2336
 
                else
2337
 
                        Aqsis::log() << error << "RiShadingInterpolation unrecognised value \"" << type << "\"" << std::endl;
2338
 
 
2339
 
        QGetRenderContext() ->AdvanceTime();
2340
 
        return ;
2341
 
}
2342
 
 
2343
 
 
2344
 
//----------------------------------------------------------------------
2345
 
// RiMatte
2346
 
// Set the matte state of subsequent geometric primitives.
2347
 
//
2348
 
RtVoid  RiMatte( RtBoolean onoff )
2349
 
{
2350
 
        VALIDATE_CONDITIONAL
2351
 
 
2352
 
        CACHE_RIMATTE
2353
 
 
2354
 
        VALIDATE_RIMATTE
2355
 
 
2356
 
        DEBUG_RIMATTE
2357
 
 
2358
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Matte" ) [ 0 ] = onoff != 0;
2359
 
        QGetRenderContext() ->AdvanceTime();
2360
 
        return ;
2361
 
}
2362
 
 
2363
 
 
2364
 
//----------------------------------------------------------------------
2365
 
// RiBound
2366
 
// Set the bounding cube of the current primitives.
2367
 
//
2368
 
RtVoid  RiBound( RtBound bound )
2369
 
{
2370
 
        VALIDATE_CONDITIONAL
2371
 
 
2372
 
        CACHE_RIBOUND
2373
 
 
2374
 
        VALIDATE_RIBOUND
2375
 
 
2376
 
        DEBUG_RIBOUND
2377
 
 
2378
 
        // TODO: Need to add a "Bound" attribute here, and fill it in.
2379
 
        QGetRenderContext() ->AdvanceTime();
2380
 
 
2381
 
        return ;
2382
 
}
2383
 
 
2384
 
 
2385
 
//----------------------------------------------------------------------
2386
 
// RiDetail
2387
 
// Set the current bounding cube for use by level of detail calculation.
2388
 
//
2389
 
RtVoid  RiDetail( RtBound bound )
2390
 
{
2391
 
        VALIDATE_CONDITIONAL
2392
 
 
2393
 
        CACHE_RIDETAIL
2394
 
 
2395
 
        VALIDATE_RIDETAIL
2396
 
 
2397
 
        DEBUG_RIDETAIL
2398
 
 
2399
 
        CqBound Bound( bound );
2400
 
 
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];
2408
 
 
2409
 
        return ;
2410
 
}
2411
 
 
2412
 
 
2413
 
//----------------------------------------------------------------------
2414
 
// RiDetailRange
2415
 
// Set the visible range of any subsequent geometric primitives.
2416
 
//
2417
 
RtVoid  RiDetailRange( RtFloat offlow, RtFloat onlow, RtFloat onhigh, RtFloat offhigh )
2418
 
{
2419
 
        VALIDATE_CONDITIONAL
2420
 
 
2421
 
        CACHE_RIDETAILRANGE
2422
 
 
2423
 
        VALIDATE_RIDETAILRANGE
2424
 
 
2425
 
        DEBUG_RIDETAILRANGE
2426
 
 
2427
 
        if ( offlow > onlow || onhigh > offhigh )
2428
 
        {
2429
 
                Aqsis::log() << error << "RiDetailRange invalid range" << std::endl;
2430
 
                return ;
2431
 
        }
2432
 
 
2433
 
        TqFloat* rangeAttr = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LODRanges" );
2434
 
        rangeAttr[0] = offlow;
2435
 
        rangeAttr[1] = onlow;
2436
 
        rangeAttr[2] = onhigh;
2437
 
        rangeAttr[3] = offhigh;
2438
 
        return ;
2439
 
}
2440
 
 
2441
 
 
2442
 
//----------------------------------------------------------------------
2443
 
// RiGeometricApproximation
2444
 
// Specify any parameters used by approximation functions during rendering.
2445
 
//
2446
 
RtVoid  RiGeometricApproximation( RtToken type, RtFloat value )
2447
 
{
2448
 
        VALIDATE_CONDITIONAL
2449
 
 
2450
 
        CACHE_RIGEOMETRICAPPROXIMATION
2451
 
 
2452
 
        VALIDATE_RIGEOMETRICAPPROXIMATION
2453
 
 
2454
 
        DEBUG_RIGEOMETRICAPPROXIMATION
2455
 
 
2456
 
        Aqsis::log() << warning << "RiGeometricApproximation not supported" << std::endl;
2457
 
        return ;
2458
 
}
2459
 
 
2460
 
 
2461
 
//----------------------------------------------------------------------
2462
 
// RiOrientation
2463
 
// Set the handedness of any subsequent geometric primitives.
2464
 
//
2465
 
RtVoid  RiOrientation( RtToken orientation )
2466
 
{
2467
 
        VALIDATE_CONDITIONAL
2468
 
 
2469
 
        CACHE_RIORIENTATION
2470
 
 
2471
 
        VALIDATE_RIORIENTATION
2472
 
 
2473
 
        DEBUG_RIORIENTATION
2474
 
 
2475
 
        if ( orientation != 0 )
2476
 
        {
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;
2485
 
        }
2486
 
        QGetRenderContext() ->AdvanceTime();
2487
 
        return ;
2488
 
}
2489
 
 
2490
 
 
2491
 
//----------------------------------------------------------------------
2492
 
// RiReverseOrientation
2493
 
// Reverse the handedness of any subsequent geometric primitives.
2494
 
//
2495
 
RtVoid  RiReverseOrientation()
2496
 
{
2497
 
        VALIDATE_CONDITIONAL
2498
 
 
2499
 
        CACHE_RIREVERSEORIENTATION
2500
 
 
2501
 
        VALIDATE_RIREVERSEORIENTATION
2502
 
 
2503
 
        DEBUG_RIREVERSEORIENTATION
2504
 
 
2505
 
        QGetRenderContext() ->pattrWriteCurrent() ->FlipeOrientation( QGetRenderContext() ->Time() );
2506
 
        QGetRenderContext() ->AdvanceTime();
2507
 
        return ;
2508
 
}
2509
 
 
2510
 
 
2511
 
//----------------------------------------------------------------------
2512
 
// RiSides
2513
 
// Set the number of visibles sides for any subsequent geometric primitives.
2514
 
//
2515
 
RtVoid  RiSides( RtInt nsides )
2516
 
{
2517
 
        VALIDATE_CONDITIONAL
2518
 
 
2519
 
        CACHE_RISIDES
2520
 
 
2521
 
        VALIDATE_RISIDES
2522
 
 
2523
 
        DEBUG_RISIDES
2524
 
 
2525
 
        QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Sides" ) [ 0 ] = nsides;
2526
 
        QGetRenderContext() ->AdvanceTime();
2527
 
 
2528
 
        return ;
2529
 
}
2530
 
 
2531
 
 
2532
 
//----------------------------------------------------------------------
2533
 
// RiIdentity
2534
 
// Set the current transformation to the identity matrix.
2535
 
//
2536
 
RtVoid  RiIdentity()
2537
 
{
2538
 
        VALIDATE_CONDITIONAL
2539
 
 
2540
 
        CACHE_RIIDENTITY
2541
 
 
2542
 
        VALIDATE_RIIDENTITY
2543
 
 
2544
 
        DEBUG_RIIDENTITY
2545
 
 
2546
 
        QGetRenderContext() ->ptransSetTime( CqMatrix() );
2547
 
        QGetRenderContext() ->AdvanceTime();
2548
 
        return ;
2549
 
}
2550
 
 
2551
 
 
2552
 
//----------------------------------------------------------------------
2553
 
// Set the current transformation to the specified matrix.
2554
 
//
2555
 
RtVoid  RiTransform( RtMatrix transform )
2556
 
{
2557
 
        VALIDATE_CONDITIONAL
2558
 
 
2559
 
        CACHE_RITRANSFORM
2560
 
 
2561
 
        VALIDATE_RITRANSFORM
2562
 
 
2563
 
        DEBUG_RITRANSFORM
2564
 
 
2565
 
        CqMatrix matTrans( transform );
2566
 
        //    if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
2567
 
        //        QGetRenderContext() ->ptransWriteCurrent() ->FlipHandedness( QGetRenderContext() ->Time() );
2568
 
 
2569
 
        if( QGetRenderContext()->IsWorldBegin() )
2570
 
        {
2571
 
                CqTransformPtr newTrans( new CqTransform( QGetRenderContext()->GetDefObjTransform() ) );
2572
 
                QGetRenderContext() ->pconCurrent()->ptransSetCurrent( newTrans );
2573
 
                QGetRenderContext() ->ptransConcatCurrentTime( CqMatrix( transform ) );
2574
 
        }
2575
 
        else
2576
 
                QGetRenderContext() ->ptransSetCurrentTime( CqMatrix( transform ) );
2577
 
        QGetRenderContext() ->AdvanceTime();
2578
 
 
2579
 
        return ;
2580
 
}
2581
 
 
2582
 
 
2583
 
//----------------------------------------------------------------------
2584
 
// RiConcatTransform
2585
 
// Concatenate the specified matrix into the current transformation matrix.
2586
 
//
2587
 
RtVoid  RiConcatTransform( RtMatrix transform )
2588
 
{
2589
 
        VALIDATE_CONDITIONAL
2590
 
 
2591
 
        CACHE_RICONCATTRANSFORM
2592
 
 
2593
 
        VALIDATE_RICONCATTRANSFORM
2594
 
 
2595
 
        DEBUG_RICONCATTRANSFORM
2596
 
 
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() );
2601
 
 
2602
 
        QGetRenderContext() ->ptransConcatCurrentTime( CqMatrix( transform ) );
2603
 
        QGetRenderContext() ->AdvanceTime();
2604
 
        return ;
2605
 
}
2606
 
 
2607
 
 
2608
 
//----------------------------------------------------------------------
2609
 
// RiPerspective
2610
 
// Concatenate a perspective transformation into the current transformation.
2611
 
//
2612
 
RtVoid  RiPerspective( RtFloat fov )
2613
 
{
2614
 
        VALIDATE_CONDITIONAL
2615
 
 
2616
 
        CACHE_RIPERSPECTIVE
2617
 
 
2618
 
        VALIDATE_RIPERSPECTIVE
2619
 
 
2620
 
        DEBUG_RIPERSPECTIVE
2621
 
 
2622
 
        if ( fov <= 0 )
2623
 
        {
2624
 
                Aqsis::log() << error << "RiPerspective invalid FOV" << std::endl;
2625
 
                return ;
2626
 
        }
2627
 
 
2628
 
        fov = tan( RAD( fov / 2 ) );
2629
 
 
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 );
2632
 
 
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() );
2636
 
 
2637
 
        QGetRenderContext() ->ptransConcatCurrentTime( matP );
2638
 
        QGetRenderContext() ->AdvanceTime();
2639
 
 
2640
 
        return ;
2641
 
}
2642
 
 
2643
 
 
2644
 
//----------------------------------------------------------------------
2645
 
// RiTranslate
2646
 
// Concatenate a translation into the current transformation.
2647
 
//
2648
 
RtVoid  RiTranslate( RtFloat dx, RtFloat dy, RtFloat dz )
2649
 
{
2650
 
        VALIDATE_CONDITIONAL
2651
 
 
2652
 
        CACHE_RITRANSLATE
2653
 
 
2654
 
        VALIDATE_RITRANSLATE
2655
 
 
2656
 
        DEBUG_RITRANSLATE
2657
 
 
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() );
2662
 
 
2663
 
        QGetRenderContext() ->ptransConcatCurrentTime( matTrans );
2664
 
        QGetRenderContext() ->AdvanceTime();
2665
 
 
2666
 
        return ;
2667
 
}
2668
 
 
2669
 
 
2670
 
//----------------------------------------------------------------------
2671
 
// RiRotate
2672
 
// Concatenate a rotation into the current transformation.
2673
 
//
2674
 
RtVoid  RiRotate( RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz )
2675
 
{
2676
 
        VALIDATE_CONDITIONAL
2677
 
 
2678
 
        CACHE_RIROTATE
2679
 
 
2680
 
        VALIDATE_RIROTATE
2681
 
 
2682
 
        DEBUG_RIROTATE
2683
 
 
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() );
2688
 
 
2689
 
        QGetRenderContext() ->ptransConcatCurrentTime( matRot );
2690
 
        QGetRenderContext() ->AdvanceTime();
2691
 
        return ;
2692
 
}
2693
 
 
2694
 
 
2695
 
//----------------------------------------------------------------------
2696
 
// RiScale
2697
 
// Concatenate a scale into the current transformation.
2698
 
//
2699
 
RtVoid  RiScale( RtFloat sx, RtFloat sy, RtFloat sz )
2700
 
{
2701
 
        VALIDATE_CONDITIONAL
2702
 
 
2703
 
        CACHE_RISCALE
2704
 
 
2705
 
        VALIDATE_RISCALE
2706
 
 
2707
 
        DEBUG_RISCALE
2708
 
 
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() );
2713
 
 
2714
 
        QGetRenderContext() ->ptransConcatCurrentTime( matScale );
2715
 
        QGetRenderContext() ->AdvanceTime();
2716
 
        return ;
2717
 
}
2718
 
 
2719
 
 
2720
 
//----------------------------------------------------------------------
2721
 
// RiSkew
2722
 
// Concatenate a skew into the current transformation.
2723
 
//
2724
 
RtVoid  RiSkew( RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1,
2725
 
               RtFloat dx2, RtFloat dy2, RtFloat dz2 )
2726
 
{
2727
 
        VALIDATE_CONDITIONAL
2728
 
 
2729
 
        CACHE_RISKEW
2730
 
 
2731
 
        VALIDATE_RISKEW
2732
 
 
2733
 
        DEBUG_RISKEW
2734
 
 
2735
 
        CqMatrix        matSkew( RAD( angle ), dx1, dy1, dz1, dx2, dy2, dz2 );
2736
 
 
2737
 
        // This transformation can not change orientation.
2738
 
 
2739
 
        QGetRenderContext() ->ptransConcatCurrentTime( matSkew );
2740
 
        QGetRenderContext() ->AdvanceTime();
2741
 
        return ;
2742
 
}
2743
 
 
2744
 
 
2745
 
//----------------------------------------------------------------------
2746
 
// RiDeformation
2747
 
// Specify a deformation shader to be included into the current transformation.
2748
 
//
2749
 
RtVoid  RiDeformation( RtToken name, ... )
2750
 
{
2751
 
        Aqsis::log() << warning << "RiDeformation not supported" << std::endl;
2752
 
        return ;
2753
 
}
2754
 
 
2755
 
 
2756
 
//----------------------------------------------------------------------
2757
 
// RiDeformationV
2758
 
// List based version of above.
2759
 
//
2760
 
RtVoid  RiDeformationV( RtToken name, PARAMETERLIST )
2761
 
{
2762
 
        VALIDATE_CONDITIONAL
2763
 
 
2764
 
        CACHE_RIDEFORMATION
2765
 
 
2766
 
        VALIDATE_RIDEFORMATION
2767
 
 
2768
 
        DEBUG_RIDEFORMATION
2769
 
 
2770
 
        Aqsis::log() << warning << "RiDeformation not supported" << std::endl;
2771
 
        return ;
2772
 
}
2773
 
 
2774
 
 
2775
 
//----------------------------------------------------------------------
2776
 
// RiDisplacement
2777
 
// Specify the current displacement shade used by geometric primitives.
2778
 
//
2779
 
RtVoid  RiDisplacement( RtToken name, ... )
2780
 
{
2781
 
        EXTRACT_PARAMETERS( name )
2782
 
 
2783
 
        RiDisplacementV( name, PASS_PARAMETERS );
2784
 
}
2785
 
 
2786
 
 
2787
 
//----------------------------------------------------------------------
2788
 
// RiDisplacementV
2789
 
// List based version of above.
2790
 
//
2791
 
RtVoid  RiDisplacementV( RtToken name, PARAMETERLIST )
2792
 
{
2793
 
        VALIDATE_CONDITIONAL
2794
 
 
2795
 
        CACHE_RIDISPLACEMENT
2796
 
 
2797
 
        VALIDATE_RIDISPLACEMENT
2798
 
 
2799
 
        DEBUG_RIDISPLACEMENT
2800
 
 
2801
 
        // Find the shader.
2802
 
        boost::shared_ptr<IqShader> pshadDisplacement = QGetRenderContext() ->CreateShader( name, Type_Displacement );
2803
 
 
2804
 
        if ( pshadDisplacement )
2805
 
        {
2806
 
                pshadDisplacement->SetTransform( QGetRenderContext() ->ptransCurrent() );
2807
 
                // Execute the intiialisation code here, as we now have our shader context complete.
2808
 
                pshadDisplacement->PrepareDefArgs();
2809
 
                RtInt i;
2810
 
                for ( i = 0; i < count; ++i )
2811
 
                {
2812
 
                        RtToken token = tokens[ i ];
2813
 
                        RtPointer       value = values[ i ];
2814
 
 
2815
 
                        SetShaderArgument( pshadDisplacement, token, static_cast<TqPchar>( value ) );
2816
 
                }
2817
 
        }
2818
 
 
2819
 
        QGetRenderContext() ->pattrWriteCurrent() ->SetpshadDisplacement( pshadDisplacement, QGetRenderContext() ->Time() );
2820
 
        QGetRenderContext() ->AdvanceTime();
2821
 
        return ;
2822
 
}
2823
 
 
2824
 
 
2825
 
//----------------------------------------------------------------------
2826
 
// RiCoordinateSystem
2827
 
// Save the current coordinate system as the specified name.
2828
 
//
2829
 
RtVoid  RiCoordinateSystem( RtToken space )
2830
 
{
2831
 
        VALIDATE_CONDITIONAL
2832
 
 
2833
 
        CACHE_RICOORDINATESYSTEM
2834
 
 
2835
 
        VALIDATE_RICOORDINATESYSTEM
2836
 
 
2837
 
        DEBUG_RICOORDINATESYSTEM
2838
 
 
2839
 
        // Insert the named coordinate system into the list help on the renderer.
2840
 
        QGetRenderContext() ->SetCoordSystem( space, QGetRenderContext() ->matCurrent( QGetRenderContext() ->Time() ) );
2841
 
        QGetRenderContext() ->AdvanceTime();
2842
 
 
2843
 
        return ;
2844
 
}
2845
 
 
2846
 
 
2847
 
//----------------------------------------------------------------------
2848
 
// ---Additional to spec. v3.1---
2849
 
// RiCoordSysTransform
2850
 
// Replace the current transform with the named space.
2851
 
 
2852
 
RtVoid  RiCoordSysTransform( RtToken space )
2853
 
{
2854
 
        VALIDATE_CONDITIONAL
2855
 
 
2856
 
        CACHE_RICOORDSYSTRANSFORM
2857
 
 
2858
 
        VALIDATE_RICOORDSYSTRANSFORM
2859
 
 
2860
 
        DEBUG_RICOORDSYSTRANSFORM
2861
 
 
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();
2865
 
 
2866
 
        return ;
2867
 
}
2868
 
 
2869
 
 
2870
 
//----------------------------------------------------------------------
2871
 
// RiTransformPoints
2872
 
// Transform a list of points from one coordinate system to another.
2873
 
//
2874
 
RtPoint*        RiTransformPoints( RtToken fromspace, RtToken tospace, RtInt npoints, RtPoint points[] )
2875
 
{
2876
 
        CACHE_RITRANSFORMPOINTS
2877
 
 
2878
 
        VALIDATE_RITRANSFORMPOINTS
2879
 
 
2880
 
        DEBUG_RITRANSFORMPOINTS
2881
 
 
2882
 
        if (!IfOk)
2883
 
                return points;
2884
 
 
2885
 
        CqMatrix matCToW = QGetRenderContext() ->matSpaceToSpace( fromspace,
2886
 
                           tospace, NULL, NULL, QGetRenderContextI()->Time() );
2887
 
 
2888
 
        if (matCToW.fIdentity() != TqTrue)
2889
 
        {
2890
 
                for(TqInt i =0; i< npoints; i++)
2891
 
                {
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();
2897
 
                }
2898
 
        }
2899
 
 
2900
 
        return ( points );
2901
 
}
2902
 
 
2903
 
 
2904
 
//----------------------------------------------------------------------
2905
 
// RiTransformBegin
2906
 
// Push the current transformation state.
2907
 
//
2908
 
RtVoid  RiTransformBegin()
2909
 
{
2910
 
        VALIDATE_CONDITIONAL
2911
 
 
2912
 
        CACHE_RITRANSFORMBEGIN
2913
 
 
2914
 
        VALIDATE_RITRANSFORMBEGIN
2915
 
 
2916
 
        DEBUG_RITRANSFORMBEGIN
2917
 
 
2918
 
        QGetRenderContext() ->BeginTransformModeBlock();
2919
 
 
2920
 
        return ;
2921
 
}
2922
 
 
2923
 
 
2924
 
//----------------------------------------------------------------------
2925
 
// RiTransformEnd
2926
 
// Pop the previous transformation state.
2927
 
//
2928
 
RtVoid  RiTransformEnd()
2929
 
{
2930
 
        VALIDATE_CONDITIONAL
2931
 
 
2932
 
        CACHE_RITRANSFORMEND
2933
 
 
2934
 
        VALIDATE_RITRANSFORMEND
2935
 
 
2936
 
        DEBUG_RITRANSFORMEND
2937
 
 
2938
 
        QGetRenderContext() ->EndTransformModeBlock();
2939
 
 
2940
 
        return ;
2941
 
}
2942
 
 
2943
 
 
2944
 
//----------------------------------------------------------------------
2945
 
// RiAttribute
2946
 
// Set a system specific attribute.
2947
 
//
2948
 
RtVoid  RiAttribute( RtToken name, ... )
2949
 
{
2950
 
        EXTRACT_PARAMETERS( name )
2951
 
 
2952
 
        TqUlong hash = CqString::hash(name);
2953
 
 
2954
 
        if (hash == RIH_RENDER)
2955
 
                return;
2956
 
        if (hash == RIH_INDIRECT)
2957
 
                return;
2958
 
        if (hash == RIH_LIGHT)
2959
 
                return;
2960
 
        if (hash == RIH_VISIBILITY)
2961
 
                return;
2962
 
 
2963
 
        RiAttributeV( name, PASS_PARAMETERS );
2964
 
}
2965
 
 
2966
 
 
2967
 
//----------------------------------------------------------------------
2968
 
// RiAttributeV
2969
 
// List based version of above.
2970
 
//
2971
 
RtVoid  RiAttributeV( RtToken name, PARAMETERLIST )
2972
 
{
2973
 
        VALIDATE_CONDITIONAL
2974
 
 
2975
 
        CACHE_RIATTRIBUTE
2976
 
 
2977
 
        VALIDATE_RIATTRIBUTE
2978
 
 
2979
 
        DEBUG_RIATTRIBUTE
2980
 
 
2981
 
        TqUlong hash = CqString::hash(name);
2982
 
 
2983
 
        if (hash == RIH_RENDER)
2984
 
                return;
2985
 
        if (hash == RIH_INDIRECT)
2986
 
                return;
2987
 
        if (hash == RIH_LIGHT)
2988
 
                return;
2989
 
        if (hash == RIH_VISIBILITY)
2990
 
                return;
2991
 
 
2992
 
        // Find the parameter on the current options.
2993
 
        CqNamedParameterList * pAttr = QGetRenderContext() ->pattrWriteCurrent() ->pAttributeWrite( name ).get();
2994
 
 
2995
 
        RtInt i;
2996
 
        for ( i = 0; i < count; ++i )
2997
 
        {
2998
 
                RtToken token = tokens[ i ];
2999
 
                RtPointer       value = values[ i ];
3000
 
 
3001
 
                TqInt Type = 0;
3002
 
                TqInt Class = 0;
3003
 
                TqBool bArray = false;
3004
 
                CqParameter* pParam = pAttr->pParameter( token );
3005
 
                if ( pParam == 0 )
3006
 
                {
3007
 
                        // Search for the parameter in the declarations.
3008
 
                        // Note attributes can only be uniform.
3009
 
                        SqParameterDeclaration Decl;
3010
 
                        try
3011
 
                        {
3012
 
                                Decl = QGetRenderContext()->FindParameterDecl( token );
3013
 
                        }
3014
 
                        catch( XqException e )
3015
 
                        {
3016
 
                                Aqsis::log() << error << e.strReason().c_str() << std::endl;
3017
 
                                continue;
3018
 
                        }
3019
 
                        if ( Decl.m_strName != "" && Decl.m_Class == class_uniform )
3020
 
                        {
3021
 
                                pParam = Decl.m_pCreate( Decl.m_strName.c_str(), Decl.m_Count );
3022
 
                                Type = Decl.m_Type;
3023
 
                                Class = Decl.m_Class;
3024
 
                                bArray = Decl.m_Count > 0;
3025
 
                                pAttr->AddParameter( pParam );
3026
 
                        }
3027
 
                        else
3028
 
                        {
3029
 
                                if ( Decl.m_strName == "" )
3030
 
                                        Aqsis::log() << warning << "Unrecognised declaration \"" << token << "\"" << std::endl;
3031
 
                                else
3032
 
                                        Aqsis::log() << warning << "Attributes can only be uniform" << std::endl;
3033
 
                                return ;
3034
 
                        }
3035
 
                }
3036
 
                else
3037
 
                {
3038
 
                        Type = pParam->Type();
3039
 
                        Class = pParam->Class();
3040
 
                        bArray = pParam->Count() > 0;
3041
 
                }
3042
 
 
3043
 
                switch ( Type )
3044
 
                {
3045
 
                                case type_float:
3046
 
                                {
3047
 
                                        RtFloat * pf = reinterpret_cast<RtFloat*>( value );
3048
 
                                        if ( bArray )
3049
 
                                        {
3050
 
                                                RtInt j;
3051
 
                                                for ( j = 0; j < pParam->Count(); ++j )
3052
 
                                                        static_cast<CqParameterTypedUniformArray<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ j ] = pf[ j ];
3053
 
                                        }
3054
 
                                        else
3055
 
                                                static_cast<CqParameterTypedUniform<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pf[ 0 ];
3056
 
                                }
3057
 
                                break;
3058
 
 
3059
 
                                case type_integer:
3060
 
                                {
3061
 
                                        RtInt* pi = reinterpret_cast<RtInt*>( value );
3062
 
                                        if ( bArray )
3063
 
                                        {
3064
 
                                                RtInt j;
3065
 
                                                for ( j = 0; j < pParam->Count(); ++j )
3066
 
                                                        static_cast<CqParameterTypedUniformArray<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ j ] = pi[ j ];
3067
 
                                        }
3068
 
                                        else
3069
 
                                                static_cast<CqParameterTypedUniform<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pi[ 0 ];
3070
 
                                }
3071
 
                                break;
3072
 
 
3073
 
                                case type_string:
3074
 
                                {
3075
 
                                        char** ps = reinterpret_cast<char**>( value );
3076
 
                                        if ( bArray )
3077
 
                                        {
3078
 
                                                RtInt j;
3079
 
                                                for ( j = 0; j < pParam->Count(); ++j )
3080
 
                                                {
3081
 
                                                        CqString str( ps[ j ] );
3082
 
                                                        static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ j ] = str;
3083
 
                                                }
3084
 
                                        }
3085
 
                                        else
3086
 
                                        {
3087
 
                                                CqString str( ps[ 0 ] );
3088
 
                                                static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ 0 ] = str;
3089
 
                                        }
3090
 
#ifdef REQUIRED
3091
 
                                        if( (strcmp(name, "identifier")==0) && (strcmp(token, "name")==0))
3092
 
                                                Aqsis::log() << info << "Identifier: " << ps[ 0 ] << std::endl;
3093
 
#endif
3094
 
 
3095
 
                                }
3096
 
                                // TODO: Rest of parameter types.
3097
 
                }
3098
 
        }
3099
 
        return ;
3100
 
}
3101
 
 
3102
 
 
3103
 
//----------------------------------------------------------------------
3104
 
// RiPolygon
3105
 
// Specify a coplanar, convex polygon.
3106
 
//
3107
 
RtVoid  RiPolygon( RtInt nvertices, ... )
3108
 
{
3109
 
        EXTRACT_PARAMETERS( nvertices )
3110
 
 
3111
 
        RiPolygonV( nvertices, PASS_PARAMETERS );
3112
 
}
3113
 
 
3114
 
 
3115
 
//----------------------------------------------------------------------
3116
 
// RiPolygonV
3117
 
// List based version of above.
3118
 
//
3119
 
RtVoid  RiPolygonV( RtInt nvertices, PARAMETERLIST )
3120
 
{
3121
 
        VALIDATE_CONDITIONAL
3122
 
 
3123
 
        CACHE_RIPOLYGON
3124
 
 
3125
 
        VALIDATE_RIPOLYGON
3126
 
 
3127
 
        DEBUG_RIPOLYGON
3128
 
 
3129
 
        // Create a new polygon surface primitive.
3130
 
        boost::shared_ptr<CqSurfacePolygon> pSurface( new CqSurfacePolygon( nvertices ) );
3131
 
 
3132
 
        // Process any specified primitive variables.
3133
 
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3134
 
        {
3135
 
                if ( !pSurface->CheckDegenerate() )
3136
 
                {
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 );
3143
 
                }
3144
 
                else
3145
 
                {
3146
 
                        Aqsis::log() << error << "Found degenerate polygon" << std::endl;
3147
 
                }
3148
 
        }
3149
 
 
3150
 
        return ;
3151
 
}
3152
 
 
3153
 
 
3154
 
//----------------------------------------------------------------------
3155
 
// RiGeneralPolygon
3156
 
// Specify a nonconvex coplanar polygon.
3157
 
//
3158
 
RtVoid  RiGeneralPolygon( RtInt nloops, RtInt nverts[], ... )
3159
 
{
3160
 
        EXTRACT_PARAMETERS( nverts )
3161
 
 
3162
 
        RiGeneralPolygonV( nloops, nverts, PASS_PARAMETERS );
3163
 
}
3164
 
 
3165
 
 
3166
 
//----------------------------------------------------------------------
3167
 
// RiGeneralPolygonV
3168
 
// List based version of above.
3169
 
//
3170
 
RtVoid  RiGeneralPolygonV( RtInt nloops, RtInt nverts[], PARAMETERLIST )
3171
 
{
3172
 
        VALIDATE_CONDITIONAL
3173
 
 
3174
 
        CACHE_RIGENERALPOLYGON
3175
 
 
3176
 
        VALIDATE_RIGENERALPOLYGON
3177
 
 
3178
 
        DEBUG_RIGENERALPOLYGON
3179
 
 
3180
 
        TqInt iloop;
3181
 
 
3182
 
        // Calcualte how many points there are.
3183
 
        TqInt cVerts = 0;
3184
 
        for ( iloop = 0; iloop < nloops; ++iloop )
3185
 
        {
3186
 
                cVerts += nverts[ iloop ];
3187
 
                // Check for degenerate loops.
3188
 
                if( nverts[ iloop ] < 3 )
3189
 
                {
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;
3195
 
                }
3196
 
        }
3197
 
 
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 ) )
3202
 
        {
3203
 
                pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
3204
 
 
3205
 
                // Work out which plane to project to.
3206
 
                TqFloat MinX, MaxX;
3207
 
                TqFloat MinY, MaxY;
3208
 
                TqFloat MinZ, MaxZ;
3209
 
                CqVector3D      vecTemp = pPointsClass->P()->pValue( 0 )[0];
3210
 
                MinX = MaxX = vecTemp.x();
3211
 
                MinY = MaxY = vecTemp.y();
3212
 
                MinZ = MaxZ = vecTemp.z();
3213
 
 
3214
 
                // We need to take into account Orientation here.
3215
 
                TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
3216
 
 
3217
 
                TqUint iVert;
3218
 
                for ( iVert = 1; iVert < pPointsClass->P() ->Size(); ++iVert )
3219
 
                {
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();
3227
 
                }
3228
 
                TqFloat DiffX = MaxX - MinX;
3229
 
                TqFloat DiffY = MaxY - MinY;
3230
 
                TqFloat DiffZ = MaxZ - MinZ;
3231
 
 
3232
 
                TqInt Axis;
3233
 
                if ( DiffX < DiffY && DiffX < DiffZ )
3234
 
                        Axis = CqPolygonGeneral2D::Axis_YZ;
3235
 
                else if ( DiffY < DiffX && DiffY < DiffZ )
3236
 
                        Axis = CqPolygonGeneral2D::Axis_XZ;
3237
 
                else
3238
 
                        Axis = CqPolygonGeneral2D::Axis_XY;
3239
 
 
3240
 
                // Create a general 2D polygon using the points in each loop.
3241
 
                CqPolygonGeneral2D poly;
3242
 
                TqUint ipoint = 0;
3243
 
                for ( iloop = 0; iloop < nloops; ++iloop )
3244
 
                {
3245
 
                        CqPolygonGeneral2D polya;
3246
 
                        polya.SetAxis( Axis );
3247
 
                        polya.SetpVertices( pPointsClass );
3248
 
                        TqInt ivert;
3249
 
                        for ( ivert = 0; ivert < nverts[ iloop ]; ++ivert )
3250
 
                        {
3251
 
                                assert( ipoint < pPointsClass->P() ->Size() );
3252
 
                                polya.aiVertices().push_back( ipoint++ );
3253
 
                        }
3254
 
                        if ( iloop == 0 )
3255
 
                        {
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.
3261
 
                                if( O )
3262
 
                                {
3263
 
                                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3264
 
                                        {
3265
 
                                                QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
3266
 
                                                polya.SwapDirection();
3267
 
                                        }
3268
 
                                }
3269
 
                                else
3270
 
                                {
3271
 
                                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3272
 
                                        {
3273
 
                                                QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
3274
 
                                                polya.SwapDirection();
3275
 
                                        }
3276
 
                                }
3277
 
                                poly = polya;
3278
 
                        }
3279
 
                        else
3280
 
                        {
3281
 
                                if( O )
3282
 
                                {
3283
 
                                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3284
 
                                                polya.SwapDirection();
3285
 
                                }
3286
 
                                else
3287
 
                                {
3288
 
                                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3289
 
                                                polya.SwapDirection();
3290
 
                                }
3291
 
                                poly.Combine( polya );
3292
 
                        }
3293
 
                }
3294
 
                // Now triangulate the general polygon
3295
 
 
3296
 
                std::vector<TqInt>      aiTriangles;
3297
 
                poly.CalcOrientation();
3298
 
                poly.Triangulate( aiTriangles );
3299
 
 
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 );
3304
 
 
3305
 
                RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
3306
 
        }
3307
 
        return ;
3308
 
}
3309
 
 
3310
 
RtVoid RiBlobby( RtInt nleaf, RtInt ncodes, RtInt codes[], RtInt nfloats, RtFloat floats[],
3311
 
                 RtInt nstrings, RtString strings[], ... )
3312
 
{
3313
 
 
3314
 
        EXTRACT_PARAMETERS( strings )
3315
 
 
3316
 
        RiBlobbyV( nleaf, ncodes, codes, nfloats, floats, nstrings, strings, PASS_PARAMETERS );
3317
 
 
3318
 
        return ;
3319
 
}
3320
 
 
3321
 
//----------------------------------------------------------------------
3322
 
/** List based version of above.
3323
 
 *
3324
 
 *\return       nothing
3325
 
 **/
3326
 
RtVoid RiBlobbyV( RtInt nleaf, RtInt ncode, RtInt code[], RtInt nflt, RtFloat flt[],
3327
 
                  RtInt nstr, RtString str[], PARAMETERLIST )
3328
 
{
3329
 
        VALIDATE_CONDITIONAL
3330
 
 
3331
 
        CACHE_RIBLOBBY
3332
 
 
3333
 
        VALIDATE_RIBLOBBY
3334
 
 
3335
 
        TqInt i;
3336
 
 
3337
 
        // Initialize the blobby structure
3338
 
        CqBlobby blobby(nleaf, ncode, code, nflt, flt, nstr, str);
3339
 
 
3340
 
        // Get back the bounding box in world coordinates
3341
 
        CqBound Bound(blobby.Bound());
3342
 
 
3343
 
        // Transform the bounding box into camera coordinates
3344
 
        Bound.Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", NULL, QGetRenderContext() ->ptransCurrent().get(), QGetRenderContext()->Time() ));
3345
 
 
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
3350
 
                return;
3351
 
 
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());
3355
 
 
3356
 
        // Transform the bounding box into raster coordinates
3357
 
        Bound.Transform( QGetRenderContext() ->matSpaceToSpace( "camera", "raster", NULL, QGetRenderContext() ->ptransCurrent().get(), QGetRenderContext()->Time() ));
3358
 
 
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() );
3362
 
 
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;
3367
 
 
3368
 
 
3369
 
        // Polygonize this blobby
3370
 
        TqInt npoints;
3371
 
        TqInt npolygons;
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);
3376
 
 
3377
 
        Aqsis::log() << info << "Polygonized : " << npoints << " points, " << npolygons << " triangles." << std::endl;
3378
 
 
3379
 
        TqFloat* colors = new TqFloat[3 * npoints];
3380
 
 
3381
 
        std::vector<TqFloat> splits;
3382
 
        splits.resize(nleaf);
3383
 
 
3384
 
        /* Parameters: RtInt count, RtToken tokens[], RtPointer values[] */
3385
 
        TqBool Cs = TqFalse;
3386
 
        for (TqInt c = 0; c < count; c++)
3387
 
        {
3388
 
                if (strstr(tokens[c], RI_CS))
3389
 
                {
3390
 
 
3391
 
                        CqVector3D cg;
3392
 
 
3393
 
                        for( int i = 0; i < npoints; i++ )
3394
 
                        {
3395
 
                                TqFloat sum;
3396
 
                                TqFloat ocolors[3] = {0.0f,0.0f,0.0f};
3397
 
 
3398
 
                                TqInt m = i * 3;
3399
 
                                cg[0] = points[m];
3400
 
                                cg[1] = points[m + 1];
3401
 
                                cg[2] = points[m + 2];
3402
 
 
3403
 
                                sum = blobby.implicit_value(cg, nleaf, splits);
3404
 
 
3405
 
                                if (sum != 0.0)
3406
 
                                {
3407
 
                                        colors[m] = colors[m+1] = colors[m+2] = 0.0f;
3408
 
                                        for (TqInt j=0; j < nleaf; j++)
3409
 
                                        {
3410
 
                                                TqInt l = j * 3;
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];
3414
 
                                        }
3415
 
                                        colors[m]/=sum;
3416
 
                                        colors[m+1]/=sum;
3417
 
                                        colors[m+2]/=sum;
3418
 
                                        ocolors[0] = colors[m];
3419
 
                                        ocolors[1] = colors[m+1];
3420
 
                                        ocolors[2] = colors[m+2];
3421
 
                                }
3422
 
                                else
3423
 
                                {
3424
 
                                        colors[m] = ocolors[0];
3425
 
                                        colors[m+1] = ocolors[1];
3426
 
                                        colors[m+2] = ocolors[2];
3427
 
                                }
3428
 
 
3429
 
                        }
3430
 
                        Cs = TqTrue;
3431
 
                        break;
3432
 
                }
3433
 
        }
3434
 
 
3435
 
        pieces = MIN(8, pieces);
3436
 
        TqInt m;
3437
 
 
3438
 
        if (Cs)
3439
 
        {
3440
 
                for (i=0; i < pieces-1; i ++)
3441
 
                {
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;
3446
 
                }
3447
 
 
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;
3453
 
        }
3454
 
        else
3455
 
        {
3456
 
                for (i=0; i < pieces-1; i ++)
3457
 
                {
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;
3462
 
                }
3463
 
 
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;
3469
 
        }
3470
 
 
3471
 
        Aqsis::log() << info << "Created RiPointsPolygons for Blobby" << std::endl;
3472
 
 
3473
 
        delete nvertices;
3474
 
        delete vertices;
3475
 
        delete points;
3476
 
        delete colors;
3477
 
 
3478
 
        return ;
3479
 
}
3480
 
 
3481
 
//----------------------------------------------------------------------
3482
 
/** Specify a small Points primitives
3483
 
 *
3484
 
 *\return       nothing
3485
 
 **/
3486
 
RtVoid  RiPoints( RtInt nvertices, ... )
3487
 
{
3488
 
        EXTRACT_PARAMETERS( nvertices )
3489
 
 
3490
 
        RiPointsV( nvertices, PASS_PARAMETERS );
3491
 
 
3492
 
        return ;
3493
 
}
3494
 
 
3495
 
//----------------------------------------------------------------------
3496
 
/** List based version of above.
3497
 
 *
3498
 
 *\return       nothing
3499
 
 **/
3500
 
RtVoid  RiPointsV( RtInt npoints, PARAMETERLIST )
3501
 
{
3502
 
        VALIDATE_CONDITIONAL
3503
 
 
3504
 
        CACHE_RIPOINTS
3505
 
 
3506
 
        VALIDATE_RIPOINTS
3507
 
 
3508
 
        DEBUG_RIPOINTS
3509
 
 
3510
 
        // Create a storage class for all the points.
3511
 
        boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( npoints, 1, npoints ) );
3512
 
 
3513
 
        // Create a new points storage class
3514
 
        boost::shared_ptr<CqPoints> pSurface;
3515
 
 
3516
 
        // read in the parameter list
3517
 
        if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
3518
 
        {
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) ) );
3524
 
 
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();
3529
 
 
3530
 
                if ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "LODBound" ) [ 1 ] < 0.0f )
3531
 
                {
3532
 
                        // Cull this geometry for LOD reasons
3533
 
                        return ;
3534
 
                }
3535
 
 
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() )
3540
 
                {
3541
 
                        CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
3542
 
 
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.
3546
 
                        if( !pMS )
3547
 
                        {
3548
 
                                boost::shared_ptr<CqDeformingPointsSurface> pNewMS( new CqDeformingPointsSurface( pSurface ) );
3549
 
                                pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
3550
 
 
3551
 
                                pMMB->SetDeformingSurface( pNewMS );
3552
 
                        }
3553
 
                        else
3554
 
                        {
3555
 
                                pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
3556
 
                        }
3557
 
                        QGetRenderContext() ->AdvanceTime();
3558
 
                }
3559
 
                else
3560
 
                {
3561
 
                        QGetRenderContext()->StorePrimitive( pSurface );
3562
 
                        STATS_INC( GPR_created );
3563
 
                }
3564
 
        }
3565
 
 
3566
 
        return ;
3567
 
}
3568
 
 
3569
 
//----------------------------------------------------------------------
3570
 
/** Specify a small line primitives
3571
 
 *
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"
3576
 
 *\return       nothing
3577
 
 **/
3578
 
 
3579
 
RtVoid RiCurves( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, ... )
3580
 
{
3581
 
        EXTRACT_PARAMETERS( wrap )
3582
 
 
3583
 
        RiCurvesV( type, ncurves, nvertices, wrap, PASS_PARAMETERS );
3584
 
 
3585
 
        return ;
3586
 
}
3587
 
 
3588
 
//----------------------------------------------------------------------
3589
 
/** List based version of above.
3590
 
 *
3591
 
 *\return       nothing
3592
 
 **/
3593
 
RtVoid RiCurvesV( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, PARAMETERLIST )
3594
 
{
3595
 
        VALIDATE_CONDITIONAL
3596
 
 
3597
 
        CACHE_RICURVES
3598
 
 
3599
 
        VALIDATE_RICURVES
3600
 
 
3601
 
        DEBUG_RICURVES
3602
 
 
3603
 
        // find out whether the curve is periodic or non-periodic
3604
 
        TqBool periodic = TqFalse;
3605
 
        if ( strcmp( wrap, RI_PERIODIC ) == 0 )
3606
 
        {
3607
 
                periodic = TqTrue;
3608
 
        }
3609
 
        else if ( strcmp( wrap, RI_NONPERIODIC ) == 0 )
3610
 
        {
3611
 
                periodic = TqFalse;
3612
 
        }
3613
 
        else
3614
 
        {
3615
 
                // the wrap mode was neither "periodic" nor "nonperiodic"
3616
 
                Aqsis::log() << error << "RiCurves invalid wrap mode \"" << wrap << "\"" << std::endl;
3617
 
        }
3618
 
 
3619
 
        // handle creation of linear and cubic curve groups separately
3620
 
        if ( strcmp( type, RI_CUBIC ) == 0 )
3621
 
        {
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 ) )
3626
 
                {
3627
 
                        // set the default primitive variables
3628
 
                        pSurface->SetDefaultPrimitiveVariables();
3629
 
 
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 ) );
3635
 
 
3636
 
                        CreateGPrim( pSurface );
3637
 
                }
3638
 
        }
3639
 
        else if ( strcmp( type, RI_LINEAR ) == 0 )
3640
 
        {
3641
 
                // create a new group of linear curves
3642
 
                boost::shared_ptr<CqLinearCurvesGroup> pSurface( new CqLinearCurvesGroup( ncurves, nvertices, periodic ) );
3643
 
 
3644
 
                // read in the parameter list
3645
 
                if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
3646
 
                {
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 );
3655
 
                }
3656
 
        }
3657
 
        else
3658
 
        {
3659
 
                // the type of curve was neither "linear" nor "cubic"
3660
 
                Aqsis::log() << error << "RiCurves invalid type \"" << type << "\"" << std::endl;
3661
 
        }
3662
 
}
3663
 
 
3664
 
 
3665
 
//----------------------------------------------------------------------
3666
 
// RiPointsPolygons
3667
 
// Specify a list of convex coplanar polygons and their shared vertices.
3668
 
//
3669
 
RtVoid  RiPointsPolygons( RtInt npolys, RtInt nverts[], RtInt verts[], ... )
3670
 
{
3671
 
        EXTRACT_PARAMETERS( verts )
3672
 
 
3673
 
        RiPointsPolygonsV( npolys, nverts, verts, PASS_PARAMETERS );
3674
 
}
3675
 
 
3676
 
 
3677
 
//----------------------------------------------------------------------
3678
 
// RiPointsPolygonsV
3679
 
// List based version of above.
3680
 
//
3681
 
 
3682
 
 
3683
 
RtVoid  RiPointsPolygonsV( RtInt npolys, RtInt nverts[], RtInt verts[], PARAMETERLIST )
3684
 
{
3685
 
        VALIDATE_CONDITIONAL
3686
 
 
3687
 
        CACHE_RIPOINTSPOLYGONS
3688
 
 
3689
 
        VALIDATE_RIPOINTSPOLYGONS
3690
 
 
3691
 
        DEBUG_RIPOINTSPOLYGONS
3692
 
 
3693
 
        // Calculate how many vertices there are.
3694
 
        RtInt cVerts = 0;
3695
 
        RtInt* pVerts = verts;
3696
 
        RtInt poly;
3697
 
        RtInt sumnVerts = 0;
3698
 
        for ( poly = 0; poly < npolys; ++poly )
3699
 
        {
3700
 
                RtInt v;
3701
 
                sumnVerts += nverts[ poly ];
3702
 
                for ( v = 0; v < nverts[ poly ]; ++v )
3703
 
                {
3704
 
                        cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
3705
 
                        pVerts++;
3706
 
                }
3707
 
        }
3708
 
 
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 ) )
3713
 
        {
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 ) );
3720
 
                CreateGPrim(pPsPs);
3721
 
        }
3722
 
 
3723
 
        return ;
3724
 
}
3725
 
 
3726
 
 
3727
 
//----------------------------------------------------------------------
3728
 
// RiPointsGeneralPolygons
3729
 
// Specify a list of coplanar, non-convex polygons and their shared vertices.
3730
 
//
3731
 
RtVoid  RiPointsGeneralPolygons( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], ... )
3732
 
{
3733
 
        EXTRACT_PARAMETERS( verts )
3734
 
 
3735
 
        RiPointsGeneralPolygonsV( npolys, nloops, nverts, verts, PASS_PARAMETERS );
3736
 
 
3737
 
        return ;
3738
 
}
3739
 
 
3740
 
 
3741
 
//----------------------------------------------------------------------
3742
 
// RiPointsGeneralPolygonsV
3743
 
// List based version of above.
3744
 
//
3745
 
RtVoid  RiPointsGeneralPolygonsV( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], PARAMETERLIST )
3746
 
{
3747
 
        VALIDATE_CONDITIONAL
3748
 
 
3749
 
        CACHE_RIPOINTSGENERALPOLYGONS
3750
 
 
3751
 
        VALIDATE_RIPOINTSGENERALPOLYGONS
3752
 
 
3753
 
        DEBUG_RIPOINTSGENERALPOLYGONS
3754
 
 
3755
 
        TqUint ipoly;
3756
 
        TqUint iloop;
3757
 
        TqUint igloop = 0;
3758
 
        TqInt cVerts = 0;
3759
 
        TqUint igvert = 0;
3760
 
        TqInt initial_index;
3761
 
        TqInt sumnVerts = 0;
3762
 
 
3763
 
        // Calculate how many points overall.
3764
 
        RtInt* pVerts = verts;
3765
 
        for ( ipoly = 0; ipoly < (TqUint) npolys; ++ipoly )
3766
 
        {
3767
 
                for ( iloop = 0; iloop < (TqUint) nloops[ ipoly ]; ++iloop, ++igloop )
3768
 
                {
3769
 
                        TqInt v;
3770
 
                        sumnVerts += nverts[ igloop ];
3771
 
                        // Check for degenerate loops.
3772
 
                        if( nverts[ igloop ] < 3 )
3773
 
                        {
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;
3779
 
                        }
3780
 
                        for ( v = 0; v < nverts[ igloop ]; ++v )
3781
 
                        {
3782
 
                                cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
3783
 
                                pVerts++;
3784
 
                        }
3785
 
                }
3786
 
        }
3787
 
 
3788
 
        // We need to take into account Orientation here.
3789
 
        TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
3790
 
 
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 ) )
3795
 
        {
3796
 
                pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
3797
 
 
3798
 
                // Reset loop counter.
3799
 
                igloop = 0;
3800
 
                TqUint ctris = 0;
3801
 
                std::vector<TqInt>      aiTriangles;
3802
 
                std::vector<TqInt> aFVList;
3803
 
                std::vector<TqInt> aUVList;
3804
 
 
3805
 
                for ( ipoly = 0; ipoly < (TqUint) npolys; ++ipoly )
3806
 
                {
3807
 
                        initial_index = igvert;
3808
 
                        // Create a general 2D polygon using the points in each loop.
3809
 
                        CqPolygonGeneral2D poly;
3810
 
                        TqUint ipoint = 0;
3811
 
                        TqUint imaxindex, iminindex;
3812
 
                        imaxindex = cVerts;
3813
 
                        iminindex = 0;
3814
 
                        for ( iloop = 0; iloop < (TqUint) nloops[ ipoly ]; ++iloop, ++igloop )
3815
 
                        {
3816
 
                                iminindex = MIN( iminindex, (TqUint) verts[ igvert ] );
3817
 
                                imaxindex = MAX( imaxindex, (TqUint) verts[ igvert ] );
3818
 
                                TqFloat MinX, MaxX;
3819
 
                                TqFloat MinY, MaxY;
3820
 
                                TqFloat MinZ, MaxZ;
3821
 
                                CqVector3D      vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
3822
 
                                MinX = MaxX = vecTemp.x();
3823
 
                                MinY = MaxY = vecTemp.y();
3824
 
                                MinZ = MaxZ = vecTemp.z();
3825
 
 
3826
 
                                CqPolygonGeneral2D polya;
3827
 
                                polya.SetpVertices( pPointsClass );
3828
 
                                TqInt ivert;
3829
 
                                for ( ivert = 0; ivert < nverts[ igloop ]; ++ivert, ++igvert )
3830
 
                                {
3831
 
                                        ipoint = verts[ igvert ];
3832
 
                                        assert( ipoint < pPointsClass->P() ->Size() );
3833
 
                                        polya.aiVertices().push_back( ipoint );
3834
 
 
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();
3842
 
                                }
3843
 
 
3844
 
                                // Work out which plane to project to.
3845
 
                                TqFloat DiffX = MaxX - MinX;
3846
 
                                TqFloat DiffY = MaxY - MinY;
3847
 
                                TqFloat DiffZ = MaxZ - MinZ;
3848
 
 
3849
 
                                TqInt Axis;
3850
 
                                if ( DiffX < DiffY && DiffX < DiffZ )
3851
 
                                        Axis = CqPolygonGeneral2D::Axis_YZ;
3852
 
                                else if ( DiffY < DiffX && DiffY < DiffZ )
3853
 
                                        Axis = CqPolygonGeneral2D::Axis_XZ;
3854
 
                                else
3855
 
                                        Axis = CqPolygonGeneral2D::Axis_XY;
3856
 
                                polya.SetAxis( Axis );
3857
 
 
3858
 
                                if ( iloop == 0 )
3859
 
                                {
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.
3865
 
                                        if( !O )
3866
 
                                        {
3867
 
                                                if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3868
 
                                                        polya.SwapDirection();
3869
 
                                        }
3870
 
                                        else
3871
 
                                        {
3872
 
                                                if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3873
 
                                                        polya.SwapDirection();
3874
 
                                        }
3875
 
                                        poly = polya;
3876
 
                                }
3877
 
                                else
3878
 
                                {
3879
 
                                        if( !O )
3880
 
                                        {
3881
 
                                                if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
3882
 
                                                        polya.SwapDirection();
3883
 
                                        }
3884
 
                                        else
3885
 
                                        {
3886
 
                                                if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
3887
 
                                                        polya.SwapDirection();
3888
 
                                        }
3889
 
                                        poly.Combine( polya );
3890
 
                                }
3891
 
                        }
3892
 
                        // Now triangulate the general polygon
3893
 
 
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 )
3902
 
                        {
3903
 
                                TqInt ivaryingindex = aiTriangles[ ifv ];
3904
 
                                TqBool found = TqFalse;
3905
 
                                for( TqUint iv = initial_index; iv != igvert; ++iv )
3906
 
                                {
3907
 
                                        if( verts[ iv ] == ivaryingindex )
3908
 
                                        {
3909
 
                                                aFVList.push_back( iv );
3910
 
                                                found = TqTrue;
3911
 
                                        }
3912
 
                                }
3913
 
                                assert( found );
3914
 
                        }
3915
 
 
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 );
3921
 
                }
3922
 
 
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 );
3927
 
 
3928
 
                // Rebuild any facevarying or uniform variables.
3929
 
                TqInt iUserParam;
3930
 
                TqInt fvcount = ctris * 3;
3931
 
                assert( aFVList.size() == fvcount );
3932
 
                std::vector<void*> aNewParams;
3933
 
                for( iUserParam = 0; iUserParam < count; ++iUserParam )
3934
 
                {
3935
 
                        SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( tokens[ iUserParam ] );
3936
 
                        TqInt elem_size = 0;
3937
 
                        switch( Decl.m_Type )
3938
 
                        {
3939
 
                                case type_float:
3940
 
                                        elem_size = sizeof(RtFloat);
3941
 
                                        break;
3942
 
                                case type_integer:
3943
 
                                        elem_size = sizeof(RtInt);
3944
 
                                        break;
3945
 
                                case type_vector:
3946
 
                                case type_point:
3947
 
                                case type_normal:
3948
 
                                        elem_size = sizeof(RtPoint);
3949
 
                                        break;
3950
 
                                case type_color:
3951
 
                                        elem_size = sizeof(RtColor);
3952
 
                                        break;
3953
 
                                case type_matrix:
3954
 
                                        elem_size = sizeof(RtMatrix);
3955
 
                                        break;
3956
 
                                default:
3957
 
                                        break;
3958
 
                        }
3959
 
                        // Take into account array primitive variables.
3960
 
                        elem_size *= Decl.m_Count;
3961
 
 
3962
 
                        if( Decl.m_Class == class_facevarying || Decl.m_Class == class_facevertex )
3963
 
                        {
3964
 
                                char* pNew = static_cast<char*>( malloc( elem_size * fvcount) );
3965
 
                                aNewParams.push_back( pNew );
3966
 
                                TqInt iElem;
3967
 
                                for( iElem = 0; iElem < fvcount; ++iElem )
3968
 
                                {
3969
 
                                        const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] ) + ( aFVList[ iElem ] * elem_size );
3970
 
                                        memcpy( pNew, pval, ( elem_size ));
3971
 
                                        pNew += elem_size;
3972
 
                                }
3973
 
                                values[ iUserParam ] = aNewParams.back();
3974
 
                        }
3975
 
                        else if( Decl.m_Class == class_uniform )
3976
 
                        {
3977
 
                                // Allocate enough for 1 value per triangle, then duplicate values from the original list
3978
 
                                // accordingly.
3979
 
                                char* pNew = static_cast<char*>( malloc( elem_size * ctris ) );
3980
 
                                aNewParams.push_back( pNew );
3981
 
                                TqInt iElem;
3982
 
                                const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] );
3983
 
                                for( iElem = 0; iElem < npolys; ++iElem )
3984
 
                                {
3985
 
                                        TqInt dup_count = aUVList[ iElem ];
3986
 
                                        TqInt dup;
3987
 
                                        for(dup=0; dup < dup_count; dup++)
3988
 
                                        {
3989
 
                                                memcpy( pNew, pval, ( elem_size ));
3990
 
                                                pNew += elem_size;
3991
 
                                        }
3992
 
                                        pval += elem_size;
3993
 
                                }
3994
 
                                values[ iUserParam ] = aNewParams.back();
3995
 
                        }
3996
 
                }
3997
 
 
3998
 
                RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
3999
 
 
4000
 
                std::vector<void*>::iterator iNewParam;
4001
 
                for( iNewParam = aNewParams.begin(); iNewParam != aNewParams.end(); ++iNewParam )
4002
 
                        free( *iNewParam );
4003
 
        }
4004
 
 
4005
 
        return ;
4006
 
}
4007
 
 
4008
 
 
4009
 
//----------------------------------------------------------------------
4010
 
// RiBasis
4011
 
// Specify the patch basis matrices for the u and v directions, and the knot skip values.
4012
 
//
4013
 
RtVoid  RiBasis( RtBasis ubasis, RtInt ustep, RtBasis vbasis, RtInt vstep )
4014
 
{
4015
 
        VALIDATE_CONDITIONAL
4016
 
 
4017
 
        CACHE_RIBASIS
4018
 
 
4019
 
        VALIDATE_RIBASIS
4020
 
 
4021
 
        DEBUG_RIBASIS
4022
 
 
4023
 
        CqMatrix u;
4024
 
        CqMatrix v;
4025
 
 
4026
 
        // A good parser will use the Ri*Basis pointers so a quick comparison
4027
 
        //   can be done.
4028
 
        //if ( ubasis not same as before )
4029
 
        //{
4030
 
        //      // Save off the newly given basis.
4031
 
        //
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 )
4036
 
        //      {
4037
 
        //      }
4038
 
        //      else
4039
 
        //      {
4040
 
        //      }
4041
 
        //
4042
 
        // Do the above again for vbasis.
4043
 
        // Save off (InvBezier * VBasis) and (Transpose(InvBezier*UBasis)).
4044
 
        //}
4045
 
 
4046
 
        RtInt i;
4047
 
        for ( i = 0; i < 4; ++i )
4048
 
        {
4049
 
                RtInt j;
4050
 
                for ( j = 0; j < 4; ++j )
4051
 
                {
4052
 
                        u.SetElement( i, j, ubasis[ i ][ j ] );
4053
 
                        v.SetElement( i, j, vbasis[ i ][ j ] );
4054
 
                }
4055
 
        }
4056
 
        u.SetfIdentity( TqFalse );
4057
 
        v.SetfIdentity( TqFalse );
4058
 
 
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();
4064
 
        return ;
4065
 
}
4066
 
 
4067
 
 
4068
 
//----------------------------------------------------------------------
4069
 
// RiPatch
4070
 
// Specify a new patch primitive.
4071
 
//
4072
 
RtVoid  RiPatch( RtToken type, ... )
4073
 
{
4074
 
        EXTRACT_PARAMETERS( type )
4075
 
 
4076
 
        RiPatchV( type, PASS_PARAMETERS );
4077
 
}
4078
 
 
4079
 
 
4080
 
//----------------------------------------------------------------------
4081
 
// RiPatchV
4082
 
// List based version of above.
4083
 
//
4084
 
RtVoid  RiPatchV( RtToken type, PARAMETERLIST )
4085
 
{
4086
 
        VALIDATE_CONDITIONAL
4087
 
 
4088
 
        CACHE_RIPATCH
4089
 
 
4090
 
        VALIDATE_RIPATCH
4091
 
 
4092
 
        DEBUG_RIPATCH
4093
 
 
4094
 
        if ( strcmp( type, RI_BICUBIC ) == 0 )
4095
 
        {
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 ) )
4100
 
                {
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 );
4106
 
 
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 ) );
4112
 
 
4113
 
                        CreateGPrim( pSurface );
4114
 
                }
4115
 
        }
4116
 
        else if ( strcmp( type, RI_BILINEAR ) == 0 )
4117
 
        {
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 ) )
4122
 
                {
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 );
4131
 
                }
4132
 
        }
4133
 
        else
4134
 
        {
4135
 
                Aqsis::log() << error << "RiPatch invalid patch type \"" << type << "\"" << std::endl;
4136
 
        }
4137
 
 
4138
 
        return ;
4139
 
}
4140
 
 
4141
 
 
4142
 
//----------------------------------------------------------------------
4143
 
// RiPatchMesh
4144
 
// Specify a quadrilaterla mesh of patches.
4145
 
//
4146
 
RtVoid  RiPatchMesh( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, ... )
4147
 
{
4148
 
        EXTRACT_PARAMETERS( vwrap )
4149
 
 
4150
 
        RiPatchMeshV( type, nu, uwrap, nv, vwrap, PASS_PARAMETERS );
4151
 
}
4152
 
 
4153
 
 
4154
 
//----------------------------------------------------------------------
4155
 
// RiPatchMeshV
4156
 
// List based version of above.
4157
 
//
4158
 
 
4159
 
RtVoid  RiPatchMeshV( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, PARAMETERLIST )
4160
 
{
4161
 
        VALIDATE_CONDITIONAL
4162
 
 
4163
 
        CACHE_RIPATCHMESH
4164
 
 
4165
 
        VALIDATE_RIPATCHMESH
4166
 
 
4167
 
        DEBUG_RIPATCHMESH
4168
 
 
4169
 
        if( strcmp( uwrap, RI_PERIODIC ) && strcmp( uwrap, RI_NONPERIODIC ) )
4170
 
                Aqsis::log() << error << "RiPatchMesh invalid u-wrap type: \"" << uwrap << "\"" << std::endl;
4171
 
 
4172
 
        if( strcmp( vwrap, RI_PERIODIC ) && strcmp( vwrap, RI_NONPERIODIC ) )
4173
 
                Aqsis::log() << error << "RiPatchMesh invalid v-wrap type: \"" << vwrap << "\"" << std::endl;
4174
 
 
4175
 
        if ( strcmp( type, RI_BICUBIC ) == 0 )
4176
 
        {
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;
4180
 
 
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 ) )
4184
 
                {
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 )
4191
 
                        {
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 );
4202
 
                        }
4203
 
                }
4204
 
        }
4205
 
        else if ( strcmp( type, RI_BILINEAR ) == 0 )
4206
 
        {
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;
4210
 
 
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 ) )
4214
 
                {
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 );
4223
 
                }
4224
 
        }
4225
 
        else
4226
 
        {
4227
 
                Aqsis::log() << error << "RiPatchMesh invalid type \"" << type << "\"" << std::endl;
4228
 
        }
4229
 
 
4230
 
        return ;
4231
 
}
4232
 
 
4233
 
 
4234
 
//----------------------------------------------------------------------
4235
 
// RiNuPatch
4236
 
// Specify a new non uniform patch.
4237
 
//
4238
 
RtVoid  RiNuPatch( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
4239
 
                  RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, ... )
4240
 
{
4241
 
        EXTRACT_PARAMETERS( vmax )
4242
 
 
4243
 
        RiNuPatchV( nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, PASS_PARAMETERS );
4244
 
}
4245
 
 
4246
 
 
4247
 
//----------------------------------------------------------------------
4248
 
// RiNuPatchV
4249
 
// List based version of above.
4250
 
//
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 )
4253
 
{
4254
 
        VALIDATE_CONDITIONAL
4255
 
 
4256
 
        CACHE_RINUPATCH
4257
 
 
4258
 
        VALIDATE_RINUPATCH
4259
 
 
4260
 
        DEBUG_RINUPATCH
4261
 
 
4262
 
        // Create a NURBS patch
4263
 
        boost::shared_ptr<CqSurfaceNURBS> pSurface( new CqSurfaceNURBS() );
4264
 
        pSurface->SetfPatchMesh();
4265
 
        pSurface->Init( uorder, vorder, nu, nv );
4266
 
 
4267
 
        pSurface->Setumin( umin );
4268
 
        pSurface->Setumax( umax );
4269
 
        pSurface->Setvmin( vmin );
4270
 
        pSurface->Setvmax( vmax );
4271
 
 
4272
 
        // Copy the knot vectors.
4273
 
        RtInt i;
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 ];
4278
 
 
4279
 
        // Process any specified parameters
4280
 
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
4281
 
        {
4282
 
                // Set up the default primitive variables.
4283
 
                pSurface->SetDefaultPrimitiveVariables();
4284
 
                // Clamp the surface to ensure non-periodic.
4285
 
                pSurface->Clamp();
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 );
4292
 
        }
4293
 
 
4294
 
        return ;
4295
 
}
4296
 
 
4297
 
//----------------------------------------------------------------------
4298
 
// RiTrimCurve
4299
 
// Specify curves which are used to trim NURBS surfaces.
4300
 
//
4301
 
RtVoid  RiTrimCurve( RtInt nloops, RtInt ncurves[], RtInt order[], RtFloat knot[], RtFloat min[], RtFloat max[], RtInt n[], RtFloat u[], RtFloat v[], RtFloat w[] )
4302
 
{
4303
 
        VALIDATE_CONDITIONAL
4304
 
 
4305
 
        CACHE_RITRIMCURVE
4306
 
 
4307
 
        VALIDATE_RITRIMCURVE
4308
 
 
4309
 
        DEBUG_RITRIMCURVE
4310
 
 
4311
 
        // Clear the current loop array.
4312
 
        QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().Clear();
4313
 
 
4314
 
        // Build an array of curves per specified loop.
4315
 
        TqInt in = 0;
4316
 
        TqInt iorder = 0;
4317
 
        TqInt iknot = 0;
4318
 
        TqInt ivert = 0;
4319
 
        TqInt iloop;
4320
 
 
4321
 
        for ( iloop = 0; iloop < nloops; ++iloop )
4322
 
        {
4323
 
                CqTrimLoop Loop;
4324
 
                TqInt icurve;
4325
 
                for ( icurve = 0; icurve < ncurves[ iloop ]; ++icurve )
4326
 
                {
4327
 
                        // Create a NURBS patch
4328
 
                        CqTrimCurve Curve;
4329
 
                        TqInt o = order[ iorder++ ];
4330
 
                        TqInt cverts = n[ in++ ];
4331
 
                        Curve.Init( o, cverts );
4332
 
 
4333
 
                        // Copy the knot vectors.
4334
 
                        RtInt i;
4335
 
                        for ( i = 0; i < o + cverts; ++i )
4336
 
                                Curve.aKnots() [ i ] = knot[ iknot++ ];
4337
 
 
4338
 
                        // Copy the vertices from the u,v,w arrays.
4339
 
                        CqVector3D vec( 0, 0, 1 );
4340
 
                        for ( i = 0; i < cverts; ++i )
4341
 
                        {
4342
 
                                vec.x( u[ ivert ] );
4343
 
                                vec.y( v[ ivert ] );
4344
 
                                vec.z( w[ ivert++ ] );
4345
 
                                Curve.CP( i ) = vec;
4346
 
                        }
4347
 
                        Loop.aCurves().push_back( Curve );
4348
 
                }
4349
 
                QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().aLoops().push_back( Loop );
4350
 
        }
4351
 
        return ;
4352
 
}
4353
 
 
4354
 
 
4355
 
 
4356
 
//----------------------------------------------------------------------
4357
 
// RiSphere
4358
 
// Specify a sphere primitive.
4359
 
//
4360
 
RtVoid  RiSphere( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4361
 
{
4362
 
        EXTRACT_PARAMETERS( thetamax )
4363
 
 
4364
 
        RiSphereV( radius, zmin, zmax, thetamax, PASS_PARAMETERS );
4365
 
}
4366
 
 
4367
 
 
4368
 
//----------------------------------------------------------------------
4369
 
// RiSphereV
4370
 
// List based version of above.
4371
 
//
4372
 
RtVoid  RiSphereV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4373
 
{
4374
 
        VALIDATE_CONDITIONAL
4375
 
 
4376
 
        CACHE_RISPHERE
4377
 
 
4378
 
        VALIDATE_RISPHERE
4379
 
 
4380
 
        DEBUG_RISPHERE
4381
 
 
4382
 
        CqLogRangeCheckCallback rc;
4383
 
 
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 );
4388
 
 
4389
 
        // Create a sphere
4390
 
        boost::shared_ptr<CqSphere> pSurface( new CqSphere( radius, zmin, zmax, 0, thetamax ) );
4391
 
        ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4392
 
        pSurface->SetDefaultPrimitiveVariables();
4393
 
 
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 );
4400
 
 
4401
 
        return ;
4402
 
}
4403
 
 
4404
 
 
4405
 
//----------------------------------------------------------------------
4406
 
// RiCone
4407
 
// Specify a cone primitive.
4408
 
//
4409
 
RtVoid  RiCone( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
4410
 
{
4411
 
        EXTRACT_PARAMETERS( thetamax )
4412
 
 
4413
 
        RiConeV( height, radius, thetamax, PASS_PARAMETERS );
4414
 
}
4415
 
 
4416
 
 
4417
 
//----------------------------------------------------------------------
4418
 
// RiConeV
4419
 
// List based version of above.
4420
 
//
4421
 
RtVoid  RiConeV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
4422
 
{
4423
 
        VALIDATE_CONDITIONAL
4424
 
 
4425
 
        CACHE_RICONE
4426
 
 
4427
 
        VALIDATE_RICONE
4428
 
 
4429
 
        DEBUG_RICONE
4430
 
 
4431
 
        /// \note This should be an exception and get caught further up.
4432
 
        if( thetamax == 0 )
4433
 
                return;
4434
 
 
4435
 
        // Create a cone
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();
4439
 
 
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 );
4446
 
 
4447
 
        return ;
4448
 
}
4449
 
 
4450
 
 
4451
 
//----------------------------------------------------------------------
4452
 
// RiCylinder
4453
 
// Specify a culinder primitive.
4454
 
//
4455
 
RtVoid  RiCylinder( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4456
 
{
4457
 
        EXTRACT_PARAMETERS( thetamax )
4458
 
 
4459
 
        RiCylinderV( radius, zmin, zmax, thetamax, PASS_PARAMETERS );
4460
 
}
4461
 
 
4462
 
 
4463
 
//----------------------------------------------------------------------
4464
 
// RiCylinderV
4465
 
// List based version of above.
4466
 
//
4467
 
RtVoid  RiCylinderV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4468
 
{
4469
 
        VALIDATE_CONDITIONAL
4470
 
 
4471
 
        CACHE_RICYLINDER
4472
 
 
4473
 
        VALIDATE_RICYLINDER
4474
 
 
4475
 
        DEBUG_RICYLINDER
4476
 
 
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();
4481
 
 
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 );
4488
 
 
4489
 
        return ;
4490
 
}
4491
 
 
4492
 
 
4493
 
//----------------------------------------------------------------------
4494
 
// RiHyperboloid
4495
 
// Specify a hyperboloid primitive.
4496
 
//
4497
 
RtVoid  RiHyperboloid( RtPoint point1, RtPoint point2, RtFloat thetamax, ... )
4498
 
{
4499
 
        EXTRACT_PARAMETERS( thetamax )
4500
 
 
4501
 
        RiHyperboloidV( point1, point2, thetamax, PASS_PARAMETERS );
4502
 
}
4503
 
 
4504
 
 
4505
 
//----------------------------------------------------------------------
4506
 
// RiHyperboloidV
4507
 
// List based version of above.
4508
 
//
4509
 
RtVoid  RiHyperboloidV( RtPoint point1, RtPoint point2, RtFloat thetamax, PARAMETERLIST )
4510
 
{
4511
 
        VALIDATE_CONDITIONAL
4512
 
 
4513
 
        CACHE_RIHYPERBOLOID
4514
 
 
4515
 
        VALIDATE_RIHYPERBOLOID
4516
 
 
4517
 
        DEBUG_RIHYPERBOLOID
4518
 
 
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();
4525
 
 
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 );
4532
 
 
4533
 
        return ;
4534
 
}
4535
 
 
4536
 
 
4537
 
//----------------------------------------------------------------------
4538
 
// RiParaboloid
4539
 
// Specify a paraboloid primitive.
4540
 
//
4541
 
RtVoid  RiParaboloid( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
4542
 
{
4543
 
        EXTRACT_PARAMETERS( thetamax )
4544
 
 
4545
 
        RiParaboloidV( rmax, zmin, zmax, thetamax, PASS_PARAMETERS );
4546
 
}
4547
 
 
4548
 
 
4549
 
//----------------------------------------------------------------------
4550
 
// RiParaboloidV
4551
 
// List based version of above.
4552
 
//
4553
 
RtVoid  RiParaboloidV( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
4554
 
{
4555
 
        VALIDATE_CONDITIONAL
4556
 
 
4557
 
        CACHE_RIPARABOLOID
4558
 
 
4559
 
        VALIDATE_RIPARABOLOID
4560
 
 
4561
 
        DEBUG_RIPARABOLOID
4562
 
 
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();
4567
 
 
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 );
4574
 
 
4575
 
        return ;
4576
 
}
4577
 
 
4578
 
 
4579
 
//----------------------------------------------------------------------
4580
 
// RiDisk
4581
 
// Specify a disk primitive.
4582
 
//
4583
 
RtVoid  RiDisk( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
4584
 
{
4585
 
        EXTRACT_PARAMETERS( thetamax )
4586
 
 
4587
 
        RiDiskV( height, radius, thetamax, PASS_PARAMETERS );
4588
 
}
4589
 
 
4590
 
 
4591
 
//----------------------------------------------------------------------
4592
 
// RiDiskV
4593
 
// List based version of above.
4594
 
//
4595
 
RtVoid  RiDiskV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
4596
 
{
4597
 
        VALIDATE_CONDITIONAL
4598
 
 
4599
 
        CACHE_RIDISK
4600
 
 
4601
 
        VALIDATE_RIDISK
4602
 
 
4603
 
        DEBUG_RIDISK
4604
 
 
4605
 
        // Create a disk
4606
 
        boost::shared_ptr<CqDisk> pSurface( new CqDisk( height, 0, radius, 0, thetamax ) );
4607
 
        ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4608
 
        pSurface->SetDefaultPrimitiveVariables();
4609
 
 
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 ) );
4615
 
 
4616
 
        CreateGPrim( pSurface );
4617
 
 
4618
 
        return ;
4619
 
}
4620
 
 
4621
 
 
4622
 
//----------------------------------------------------------------------
4623
 
//
4624
 
//
4625
 
RtVoid  RiTorus( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, ... )
4626
 
{
4627
 
        EXTRACT_PARAMETERS( thetamax )
4628
 
 
4629
 
        RiTorusV( majorrad, minorrad, phimin, phimax, thetamax, PASS_PARAMETERS );
4630
 
}
4631
 
 
4632
 
 
4633
 
//----------------------------------------------------------------------
4634
 
// RiTorus
4635
 
// Specify a torus primitive.
4636
 
//
4637
 
RtVoid  RiTorusV( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, PARAMETERLIST )
4638
 
{
4639
 
        VALIDATE_CONDITIONAL
4640
 
 
4641
 
        CACHE_RITORUS
4642
 
 
4643
 
        VALIDATE_RITORUS
4644
 
 
4645
 
        DEBUG_RITORUS
4646
 
 
4647
 
        // Create a torus
4648
 
        boost::shared_ptr<CqTorus> pSurface( new CqTorus( majorrad, minorrad, phimin, phimax, 0, thetamax ) );
4649
 
        ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4650
 
        pSurface->SetDefaultPrimitiveVariables();
4651
 
 
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 ) );
4657
 
 
4658
 
        CreateGPrim( pSurface );
4659
 
 
4660
 
        return ;
4661
 
}
4662
 
 
4663
 
 
4664
 
//----------------------------------------------------------------------
4665
 
// RiProcedural
4666
 
// Implement the procedural type primitive.
4667
 
//
4668
 
RtVoid  RiProcedural( RtPointer data, RtBound bound, RtProcSubdivFunc refineproc, RtProcFreeFunc freeproc )
4669
 
{
4670
 
        VALIDATE_CONDITIONAL
4671
 
 
4672
 
        CACHE_RIPROCEDURAL
4673
 
 
4674
 
        VALIDATE_RIPROCEDURAL
4675
 
 
4676
 
        DEBUG_RIPROCEDURAL
4677
 
 
4678
 
        CqBound B(bound);
4679
 
 
4680
 
        //printf("bound(%f %f %f %f %f %f)\n", bound[0], bound[1], bound[2], bound[3], bound[4], bound[5]);
4681
 
 
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();
4684
 
 
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 );
4691
 
 
4692
 
        return ;
4693
 
}
4694
 
 
4695
 
 
4696
 
 
4697
 
//----------------------------------------------------------------------
4698
 
// RiGeometry
4699
 
// Specify a special primitive.
4700
 
//
4701
 
RtVoid  RiGeometry( RtToken type, ... )
4702
 
{
4703
 
        EXTRACT_PARAMETERS( type )
4704
 
 
4705
 
        RiGeometryV( type, PASS_PARAMETERS );
4706
 
}
4707
 
 
4708
 
 
4709
 
//----------------------------------------------------------------------
4710
 
// RiGeometryV
4711
 
// List based version of above.
4712
 
//
4713
 
RtVoid  RiGeometryV( RtToken type, PARAMETERLIST )
4714
 
{
4715
 
        VALIDATE_CONDITIONAL
4716
 
 
4717
 
        CACHE_RIGEOMETRY
4718
 
 
4719
 
        VALIDATE_RIGEOMETRY
4720
 
 
4721
 
        DEBUG_RIGEOMETRY
4722
 
 
4723
 
        if ( strcmp( type, "teapot" ) == 0 )
4724
 
        {
4725
 
 
4726
 
                // Create a standard teapot
4727
 
                boost::shared_ptr<CqTeapot> pSurface( new CqTeapot( true ) ); // add a bottom if true/false otherwise
4728
 
 
4729
 
                pSurface->SetSurfaceParameters( *pSurface );
4730
 
                ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4731
 
                pSurface->SetDefaultPrimitiveVariables();
4732
 
 
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).
4741
 
 
4742
 
                for ( int i = 0; i < pSurface->cNbrPatchMeshBicubic; ++i )
4743
 
                {
4744
 
                        boost::shared_ptr<CqSurface> pMesh = pSurface->pPatchMeshBicubic[ i ];
4745
 
 
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 ) );
4751
 
 
4752
 
                        CreateGPrim( boost::static_pointer_cast<CqSurface>( pMesh ) );
4753
 
                }
4754
 
        }
4755
 
        else if ( strcmp( type, "sphere" ) == 0 )
4756
 
        {
4757
 
                // Create a sphere
4758
 
                boost::shared_ptr<CqSphere> pSurface( new CqSphere( 1, -1, 1, 0, 360.0 ) );
4759
 
                ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
4760
 
                pSurface->SetDefaultPrimitiveVariables();
4761
 
 
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 ) );
4767
 
 
4768
 
                CreateGPrim( pSurface );
4769
 
        } else if ( strcmp( type, "bunny" ) == 0 )
4770
 
        {
4771
 
        CqBunny bunny;
4772
 
 
4773
 
        std::vector<RtToken> aTokens;
4774
 
        std::vector<RtPointer> aValues;
4775
 
        std::vector<RtToken> aTags;
4776
 
        aTokens.clear();
4777
 
        aValues.clear();
4778
 
        aTags.clear();
4779
 
 
4780
 
 
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");
4789
 
 
4790
 
        static TqInt params[] = { 0, 0 };
4791
 
 
4792
 
        TqInt count = 3;
4793
 
        // Rotate and scale to match the teapot geometry
4794
 
        RiAttributeBegin();
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],
4799
 
                            bunny.NFaces(),
4800
 
                            bunny.Faces(),
4801
 
                            bunny.Indexes(),
4802
 
                            1,
4803
 
                            &aTags[1],
4804
 
                            params,
4805
 
                            0,
4806
 
                            0,
4807
 
                            PASS_PARAMETERS );
4808
 
        RiAttributeEnd();
4809
 
 
4810
 
        } else
4811
 
        {
4812
 
                Aqsis::log() << warning << "RiGeometry unrecognised type \"" << type << "\"" << std::endl;
4813
 
        }
4814
 
 
4815
 
        return ;
4816
 
}
4817
 
 
4818
 
//----------------------------------------------------------------------
4819
 
// RiSolidBegin
4820
 
// Begin the definition of a CSG object.
4821
 
//
4822
 
RtVoid  RiSolidBegin( RtToken type )
4823
 
{
4824
 
        VALIDATE_CONDITIONAL
4825
 
 
4826
 
        CACHE_RISOLIDBEGIN
4827
 
 
4828
 
        VALIDATE_RISOLIDBEGIN
4829
 
 
4830
 
        DEBUG_RISOLIDBEGIN
4831
 
 
4832
 
        CqString strType( type );
4833
 
        QGetRenderContext() ->BeginSolidModeBlock( strType );
4834
 
 
4835
 
        return ;
4836
 
}
4837
 
 
4838
 
 
4839
 
//----------------------------------------------------------------------
4840
 
// RiSolidEnd
4841
 
// End the definition of a CSG object.
4842
 
//
4843
 
RtVoid  RiSolidEnd()
4844
 
{
4845
 
        VALIDATE_CONDITIONAL
4846
 
 
4847
 
        CACHE_RISOLIDEND
4848
 
 
4849
 
        VALIDATE_RISOLIDEND
4850
 
 
4851
 
        DEBUG_RISOLIDEND
4852
 
 
4853
 
        QGetRenderContext() ->EndSolidModeBlock();
4854
 
 
4855
 
        return ;
4856
 
}
4857
 
 
4858
 
 
4859
 
//----------------------------------------------------------------------
4860
 
// RiObjectBegin
4861
 
// Begin the definition of a stored object for use by RiObjectInstance.
4862
 
//
4863
 
RtObjectHandle  RiObjectBegin()
4864
 
{
4865
 
        VALIDATE_CONDITIONAL0
4866
 
 
4867
 
        CACHE_RIOBJECTBEGIN
4868
 
 
4869
 
        VALIDATE_RIOBJECTBEGIN
4870
 
 
4871
 
        DEBUG_RIOBJECTBEGIN
4872
 
 
4873
 
        QGetRenderContext() ->BeginObjectModeBlock();
4874
 
        RtObjectHandle ObjectHandle = static_cast<RtObjectHandle>(QGetRenderContext() ->OpenNewObjectInstance());
4875
 
 
4876
 
        return ( ObjectHandle );
4877
 
}
4878
 
 
4879
 
 
4880
 
//----------------------------------------------------------------------
4881
 
// RiObjectEnd
4882
 
// End the defintion of a stored object for use by RiObjectInstance.
4883
 
//
4884
 
RtVoid  RiObjectEnd()
4885
 
{
4886
 
        VALIDATE_CONDITIONAL
4887
 
 
4888
 
        VALIDATE_RIOBJECTEND
4889
 
 
4890
 
        DEBUG_RIOBJECTEND
4891
 
 
4892
 
        QGetRenderContext() ->EndObjectModeBlock();
4893
 
        QGetRenderContext() ->CloseObjectInstance();
4894
 
 
4895
 
        CACHE_RIOBJECTEND
4896
 
 
4897
 
        return ;
4898
 
}
4899
 
 
4900
 
 
4901
 
//----------------------------------------------------------------------
4902
 
// RiObjectInstance
4903
 
// Instantiate a copt of a pre-stored geometric object.
4904
 
//
4905
 
RtVoid  RiObjectInstance( RtObjectHandle handle )
4906
 
{
4907
 
        VALIDATE_CONDITIONAL
4908
 
 
4909
 
        CACHE_RIOBJECTINSTANCE
4910
 
 
4911
 
        VALIDATE_RIOBJECTINSTANCE
4912
 
 
4913
 
        DEBUG_RIOBJECTINSTANCE
4914
 
 
4915
 
        QGetRenderContext() ->InstantiateObject( reinterpret_cast<CqObjectInstance*>( handle ) );
4916
 
        return ;
4917
 
}
4918
 
 
4919
 
 
4920
 
//----------------------------------------------------------------------
4921
 
// RiMotionBegin
4922
 
// Begin the definition of the motion of an object for use by motion blur.
4923
 
//
4924
 
RtVoid  RiMotionBegin( RtInt N, ... )
4925
 
{
4926
 
        va_list pArgs;
4927
 
        va_start( pArgs, N );
4928
 
 
4929
 
        RtFloat* times = new RtFloat[ N ];
4930
 
        RtInt i;
4931
 
        for ( i = 0; i < N; ++i )
4932
 
                times[ i ] = va_arg( pArgs, double );
4933
 
 
4934
 
        RiMotionBeginV( N, times );
4935
 
 
4936
 
        delete[] ( times );
4937
 
        return ;
4938
 
}
4939
 
 
4940
 
 
4941
 
//----------------------------------------------------------------------
4942
 
// RiBeginMotionV
4943
 
// List based version of above.
4944
 
//
4945
 
RtVoid  RiMotionBeginV( RtInt N, RtFloat times[] )
4946
 
{
4947
 
        VALIDATE_CONDITIONAL
4948
 
 
4949
 
        CACHE_RIMOTIONBEGINV
4950
 
 
4951
 
        VALIDATE_RIMOTIONBEGINV
4952
 
 
4953
 
        DEBUG_RIMOTIONBEGINV
4954
 
 
4955
 
        QGetRenderContext() ->BeginMotionModeBlock( N, times );
4956
 
 
4957
 
        return ;
4958
 
}
4959
 
 
4960
 
 
4961
 
//----------------------------------------------------------------------
4962
 
// RiMotionEnd
4963
 
// End the definition of the motion of an object.
4964
 
//
4965
 
RtVoid  RiMotionEnd()
4966
 
{
4967
 
        VALIDATE_CONDITIONAL
4968
 
 
4969
 
        CACHE_RIMOTIONEND
4970
 
 
4971
 
        VALIDATE_RIMOTIONEND
4972
 
 
4973
 
        DEBUG_RIMOTIONEND
4974
 
 
4975
 
        QGetRenderContext() ->EndMotionModeBlock();
4976
 
 
4977
 
        return ;
4978
 
}
4979
 
 
4980
 
 
4981
 
//----------------------------------------------------------------------
4982
 
// RiMakeTexture
4983
 
// Convert a picture to a texture.
4984
 
//
4985
 
RtVoid RiMakeTexture ( RtString pic, RtString tex, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
4986
 
{
4987
 
        EXTRACT_PARAMETERS( twidth )
4988
 
 
4989
 
        RiMakeTextureV( pic, tex, swrap, twrap, filterfunc, swidth, twidth, PASS_PARAMETERS );
4990
 
 
4991
 
}
4992
 
 
4993
 
 
4994
 
//----------------------------------------------------------------------
4995
 
// RiMakeTextureV
4996
 
// List based version of above.
4997
 
//
4998
 
RtVoid  RiMakeTextureV( RtString imagefile, RtString texturefile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
4999
 
{
5000
 
        VALIDATE_CONDITIONAL
5001
 
 
5002
 
        CACHE_RIMAKETEXTURE
5003
 
 
5004
 
        VALIDATE_RIMAKETEXTURE
5005
 
 
5006
 
        DEBUG_RIMAKETEXTURE
5007
 
 
5008
 
        char modes[ 1024 ];
5009
 
        assert( imagefile != 0 && texturefile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
5010
 
 
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;
5020
 
 
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;
5028
 
 
5029
 
 
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 );
5047
 
 
5048
 
 
5049
 
        // Now load the original image.
5050
 
        CqTextureMap Source( imagefile );
5051
 
        Source.Open();
5052
 
        TqInt comp, qual;
5053
 
        ProcessCompression( &comp, &qual, count, tokens, values );
5054
 
        Source.SetCompression( comp );
5055
 
        Source.SetQuality( qual );
5056
 
 
5057
 
        if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
5058
 
        {
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" );
5065
 
 
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 ) );
5073
 
 
5074
 
 
5075
 
                for ( int i = 0; i < log2; ++i )
5076
 
                {
5077
 
                        // Write the floating point image to the directory.
5078
 
                        CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
5079
 
                        if ( !pBuffer )
5080
 
                                break;
5081
 
                        Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
5082
 
                }
5083
 
                TIFFClose( ptex );
5084
 
        }
5085
 
 
5086
 
        Source.Close();
5087
 
}
5088
 
 
5089
 
 
5090
 
//----------------------------------------------------------------------
5091
 
// RiMakeBump
5092
 
// Convert a picture to a bump map.
5093
 
//
5094
 
RtVoid  RiMakeBump( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
5095
 
{
5096
 
        Aqsis::log() << warning << "RiMakeBump not supported" << std::endl;
5097
 
        return ;
5098
 
}
5099
 
 
5100
 
 
5101
 
//----------------------------------------------------------------------
5102
 
// RiMakeBumpV
5103
 
// List based version of above.
5104
 
//
5105
 
RtVoid  RiMakeBumpV( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
5106
 
{
5107
 
        VALIDATE_CONDITIONAL
5108
 
 
5109
 
        CACHE_RIMAKEBUMP
5110
 
 
5111
 
        VALIDATE_RIMAKEBUMP
5112
 
 
5113
 
        DEBUG_RIMAKEBUMP
5114
 
 
5115
 
        Aqsis::log() << warning << "RiMakeBump not supported" << std::endl;
5116
 
        return ;
5117
 
}
5118
 
 
5119
 
 
5120
 
//----------------------------------------------------------------------
5121
 
// RiMakeLatLongEnvironment
5122
 
// Convert a picture to an environment map.
5123
 
//
5124
 
RtVoid  RiMakeLatLongEnvironment( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
5125
 
{
5126
 
        EXTRACT_PARAMETERS( twidth )
5127
 
 
5128
 
        RiMakeLatLongEnvironmentV( imagefile, reflfile, filterfunc, swidth, twidth, PASS_PARAMETERS );
5129
 
        return ;
5130
 
}
5131
 
 
5132
 
 
5133
 
//----------------------------------------------------------------------
5134
 
// RiMakeLatLongEnvironmentV
5135
 
// List based version of above.
5136
 
//
5137
 
RtVoid  RiMakeLatLongEnvironmentV( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
5138
 
{
5139
 
        VALIDATE_CONDITIONAL
5140
 
 
5141
 
        CACHE_RIMAKELATLONGENVIRONMENT
5142
 
 
5143
 
        VALIDATE_RIMAKELATLONGENVIRONMENT
5144
 
 
5145
 
        DEBUG_RIMAKELATLONGENVIRONMENT
5146
 
 
5147
 
        char modes[ 1024 ];
5148
 
        char *swrap = "periodic";
5149
 
        char *twrap = "clamp";
5150
 
 
5151
 
        assert( imagefile != 0 && reflfile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
5152
 
 
5153
 
        TIME_SCOPE("Environment Mapping")
5154
 
 
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 );
5172
 
 
5173
 
 
5174
 
        // Now load the original image.
5175
 
        CqTextureMap Source( imagefile );
5176
 
        Source.Open();
5177
 
        TqInt comp, qual;
5178
 
        ProcessCompression( &comp, &qual, count, tokens, values );
5179
 
        Source.SetCompression( comp );
5180
 
        Source.SetQuality( qual );
5181
 
 
5182
 
        if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
5183
 
        {
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" );
5190
 
 
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 ) );
5200
 
 
5201
 
 
5202
 
                for ( int i = 0; i < log2; ++i )
5203
 
                {
5204
 
                        // Write the floating point image to the directory.
5205
 
                        CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
5206
 
                        if ( !pBuffer )
5207
 
                                break;
5208
 
                        Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
5209
 
                }
5210
 
                TIFFClose( ptex );
5211
 
        }
5212
 
 
5213
 
        Source.Close();
5214
 
        return ;
5215
 
}
5216
 
 
5217
 
 
5218
 
//----------------------------------------------------------------------
5219
 
// RiMakeCubeFaceEnvironment
5220
 
// Convert a picture to a cubical environment map.
5221
 
//
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, ... )
5223
 
{
5224
 
        EXTRACT_PARAMETERS( twidth )
5225
 
 
5226
 
        RiMakeCubeFaceEnvironmentV( px, nx, py, ny, pz, nz, reflfile, fov, filterfunc, swidth, twidth, PASS_PARAMETERS );
5227
 
}
5228
 
 
5229
 
 
5230
 
//----------------------------------------------------------------------
5231
 
// RiMakeCubeFaceEnvironment
5232
 
// List based version of above.
5233
 
//
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 )
5235
 
{
5236
 
        VALIDATE_CONDITIONAL
5237
 
 
5238
 
        CACHE_RIMAKECUBEFACEENVIRONMENT
5239
 
 
5240
 
        VALIDATE_RIMAKECUBEFACEENVIRONMENT
5241
 
 
5242
 
        DEBUG_RIMAKECUBEFACEENVIRONMENT
5243
 
 
5244
 
        TIME_SCOPE("Environment Mapping")
5245
 
        assert( px != 0 && nx != 0 && py != 0 && ny != 0 && pz != 0 && nz != 0 &&
5246
 
                reflfile != 0 && filterfunc != 0 );
5247
 
 
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 );
5255
 
 
5256
 
        tpx.Open();
5257
 
        tnx.Open();
5258
 
        tpy.Open();
5259
 
        tny.Open();
5260
 
        tpz.Open();
5261
 
        tnz.Open();
5262
 
 
5263
 
        if ( tpx.Format() != TexFormat_MIPMAP )
5264
 
                tpx.CreateMIPMAP();
5265
 
        if ( tnx.Format() != TexFormat_MIPMAP )
5266
 
                tnx.CreateMIPMAP();
5267
 
        if ( tpy.Format() != TexFormat_MIPMAP )
5268
 
                tpy.CreateMIPMAP();
5269
 
        if ( tny.Format() != TexFormat_MIPMAP )
5270
 
                tny.CreateMIPMAP();
5271
 
        if ( tpz.Format() != TexFormat_MIPMAP )
5272
 
                tpz.CreateMIPMAP();
5273
 
        if ( tnz.Format() != TexFormat_MIPMAP )
5274
 
                tnz.CreateMIPMAP();
5275
 
        if ( tpx.IsValid() && tnx.IsValid() && tpy.IsValid() && tny.IsValid() && tpz.IsValid() && tnz.IsValid() )
5276
 
        {
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() )
5281
 
                        fValid = true;
5282
 
 
5283
 
                if ( !fValid )
5284
 
                {
5285
 
                        Aqsis::log() << error << "RiMakeCubeFaceEnvironment all images must be the same size" << std::endl;
5286
 
                        return ;
5287
 
                }
5288
 
 
5289
 
                // Now copy the images to the big map.
5290
 
                CqTextureMap* Images[ 6 ] =
5291
 
                    {
5292
 
                        &tpx,
5293
 
                        &tpy,
5294
 
                        &tpz,
5295
 
                        &tnx,
5296
 
                        &tny,
5297
 
                        &tnz
5298
 
                    };
5299
 
 
5300
 
                // Create a new image.
5301
 
                TIFF* ptex = TIFFOpen( reflfile, "w" );
5302
 
 
5303
 
                RtInt ii;
5304
 
                TqInt xRes = tpx.XRes();
5305
 
                TqInt yRes = tpx.YRes();
5306
 
 
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 ) );
5311
 
 
5312
 
                for ( ii = 0; ii < log2; ++ii )
5313
 
                {
5314
 
                        CqTextureMapBuffer* pLevelBuffer = tpx.CreateBuffer( 0, 0, xRes * 3, yRes * 2, numsamples );
5315
 
                        TqInt view;
5316
 
                        for ( view = 0; view < 6; ++view )
5317
 
                        {
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;
5322
 
                                xoff *= xRes;
5323
 
                                TqInt yoff = view / 3;
5324
 
                                yoff *= yRes;
5325
 
                                TqInt line, col, sample;
5326
 
                                for ( line = 0; line < yRes; ++line )
5327
 
                                {
5328
 
                                        for ( col = 0; col < xRes; ++col )
5329
 
                                        {
5330
 
                                                for ( sample = 0; sample < numsamples; ++sample )
5331
 
                                                        pLevelBuffer->SetValue( col + xoff, line + yoff, sample, pBuffer->GetValue( col, line, sample ) );
5332
 
                                        }
5333
 
                                }
5334
 
                        }
5335
 
 
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() );
5341
 
                        xRes /= 2;
5342
 
                        yRes /= 2;
5343
 
                }
5344
 
                TIFFClose( ptex );
5345
 
        }
5346
 
        return ;
5347
 
}
5348
 
 
5349
 
 
5350
 
//----------------------------------------------------------------------
5351
 
// RiMakeShadow
5352
 
// Convert a depth map file to a shadow map.
5353
 
//
5354
 
RtVoid  RiMakeShadow( RtString picfile, RtString shadowfile, ... )
5355
 
{
5356
 
        EXTRACT_PARAMETERS( shadowfile )
5357
 
 
5358
 
        RiMakeShadowV( picfile, shadowfile, PASS_PARAMETERS );
5359
 
}
5360
 
 
5361
 
 
5362
 
//----------------------------------------------------------------------
5363
 
// RiMakeShadowV
5364
 
// List based version of above.
5365
 
//
5366
 
RtVoid  RiMakeShadowV( RtString picfile, RtString shadowfile, PARAMETERLIST )
5367
 
{
5368
 
        VALIDATE_CONDITIONAL
5369
 
 
5370
 
        CACHE_RIMAKESHADOW
5371
 
 
5372
 
        VALIDATE_RIMAKESHADOW
5373
 
 
5374
 
        DEBUG_RIMAKESHADOW
5375
 
 
5376
 
        TIME_SCOPE("Shadow Mapping")
5377
 
        CqShadowMap ZFile( picfile );
5378
 
        ZFile.LoadZFile();
5379
 
 
5380
 
        TqInt comp, qual;
5381
 
        ProcessCompression( &comp, &qual, count, tokens, values );
5382
 
        ZFile.SetCompression( comp );
5383
 
        ZFile.SetQuality( qual );
5384
 
 
5385
 
        ZFile.SaveShadowMap( shadowfile );
5386
 
        return ;
5387
 
}
5388
 
 
5389
 
 
5390
 
//----------------------------------------------------------------------
5391
 
// RiMakeOcclusion
5392
 
// Convert a series of depth maps to an occlusion map.
5393
 
//
5394
 
RtVoid  RiMakeOcclusion( RtInt npics, RtString picfiles[], RtString shadowfile, ... )
5395
 
{
5396
 
        EXTRACT_PARAMETERS( shadowfile )
5397
 
 
5398
 
        RiMakeOcclusionV( npics, picfiles, shadowfile, PASS_PARAMETERS );
5399
 
}
5400
 
 
5401
 
 
5402
 
//----------------------------------------------------------------------
5403
 
// RiMakeOcclusionV
5404
 
// List based version of above.
5405
 
//
5406
 
RtVoid  RiMakeOcclusionV( RtInt npics, RtString picfiles[], RtString shadowfile, RtInt count, RtToken tokens[], RtPointer values[] )
5407
 
{
5408
 
        VALIDATE_CONDITIONAL
5409
 
 
5410
 
        CACHE_RIMAKEOCCLUSION
5411
 
 
5412
 
        VALIDATE_RIMAKEOCCLUSION
5413
 
 
5414
 
        DEBUG_RIMAKEOCCLUSION
5415
 
 
5416
 
        TIME_SCOPE("Shadow Mapping")
5417
 
 
5418
 
        RtInt index;
5419
 
        unlink(shadowfile);
5420
 
        for( index = 0; index < npics; ++index )
5421
 
        {
5422
 
                CqShadowMap ZFile( picfiles[index] );
5423
 
                ZFile.LoadZFile();
5424
 
 
5425
 
                TqInt comp, qual;
5426
 
                ProcessCompression( &comp, &qual, count, tokens, values );
5427
 
                ZFile.SetCompression( comp );
5428
 
                ZFile.SetQuality( qual );
5429
 
 
5430
 
                ZFile.SaveShadowMap( shadowfile, TqTrue );
5431
 
        }
5432
 
        return ;
5433
 
}
5434
 
 
5435
 
//----------------------------------------------------------------------
5436
 
/** Conditional handlers for 3.4 new RI Tokens
5437
 
 * It calls TestCondition(); expect to modify the global variable IfOk.
5438
 
 *      \param  condition
5439
 
 */
5440
 
RtVoid  RiIfBegin( RtString condition )
5441
 
{
5442
 
        IfOk = TestCondition(condition, "RiIfBegin");
5443
 
}
5444
 
 
5445
 
RtVoid  RiElseIf( RtString condition )
5446
 
{
5447
 
        IfOk = TestCondition(condition, "RiElseIf");
5448
 
}
5449
 
 
5450
 
RtVoid  RiElse( )
5451
 
{
5452
 
        IfOk = !IfOk;
5453
 
}
5454
 
 
5455
 
RtVoid  RiIfEnd( )
5456
 
{
5457
 
        IfOk = TqTrue;
5458
 
}
5459
 
 
5460
 
//----------------------------------------------------------------------
5461
 
// RiErrorHandler
5462
 
// Set the function used to report errors.
5463
 
//
5464
 
RtVoid  RiErrorHandler( RtErrorFunc handler )
5465
 
{
5466
 
        VALIDATE_CONDITIONAL
5467
 
 
5468
 
        CACHE_RIERRORHANDLER
5469
 
 
5470
 
        VALIDATE_RIERRORHANDLER
5471
 
 
5472
 
        DEBUG_RIERRORHANDLER
5473
 
 
5474
 
        QGetRenderContext()->SetpErrorHandler( handler );
5475
 
        return ;
5476
 
}
5477
 
 
5478
 
 
5479
 
//----------------------------------------------------------------------
5480
 
// RiErrorIgnore
5481
 
// Function used by RiErrorHandler to continue after errors.
5482
 
//
5483
 
RtVoid  RiErrorIgnore( RtInt code, RtInt severity, RtString message )
5484
 
{
5485
 
        return ;
5486
 
}
5487
 
 
5488
 
 
5489
 
//----------------------------------------------------------------------
5490
 
// RiErrorPrint
5491
 
// Function used by RiErrorHandler to print an error message to stdout and continue.
5492
 
//
5493
 
RtVoid  RiErrorPrint( RtInt code, RtInt severity, RtString message )
5494
 
{
5495
 
        // Don't use this!
5496
 
        Aqsis::log() << error << "RiError: " << code << " : " << severity << " : " << message << std::endl;
5497
 
        return ;
5498
 
}
5499
 
 
5500
 
 
5501
 
//----------------------------------------------------------------------
5502
 
// RiErrorAbort
5503
 
// Function used by RiErrorHandler to print and error and stop.
5504
 
//
5505
 
RtVoid  RiErrorAbort( RtInt code, RtInt severity, RtString message )
5506
 
{
5507
 
        return ;
5508
 
}
5509
 
 
5510
 
 
5511
 
//----------------------------------------------------------------------
5512
 
// RiSubdivisionMesh
5513
 
// Specify a subdivision surface hull with tagging.
5514
 
//
5515
 
RtVoid  RiSubdivisionMesh( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], ... )
5516
 
{
5517
 
        EXTRACT_PARAMETERS( floatargs )
5518
 
 
5519
 
        RiSubdivisionMeshV( scheme, nfaces, nvertices, vertices, ntags, tags, nargs, intargs, floatargs, PASS_PARAMETERS );
5520
 
}
5521
 
 
5522
 
//----------------------------------------------------------------------
5523
 
// RiSubdivisionMeshV
5524
 
// List based version of above.
5525
 
//
5526
 
RtVoid  RiSubdivisionMeshV( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], PARAMETERLIST )
5527
 
{
5528
 
        VALIDATE_CONDITIONAL
5529
 
 
5530
 
        CACHE_RISUBDIVISIONMESH
5531
 
 
5532
 
        VALIDATE_RISUBDIVISIONMESH
5533
 
 
5534
 
        DEBUG_RISUBDIVISIONMESH
5535
 
 
5536
 
        // Calculate how many vertices there are.
5537
 
        RtInt cVerts = 0;
5538
 
        RtInt* pVerts = vertices;
5539
 
        RtInt face;
5540
 
        RtInt sumnVerts = 0;
5541
 
        for ( face = 0; face < nfaces; ++face )
5542
 
        {
5543
 
                RtInt v;
5544
 
                sumnVerts += nvertices[ face ];
5545
 
                for ( v = 0; v < nvertices[ face ]; ++v )
5546
 
                {
5547
 
                        cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
5548
 
                        pVerts++;
5549
 
                }
5550
 
        }
5551
 
 
5552
 
        // Create a storage class for all the points.
5553
 
        boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, nfaces, sumnVerts ) );
5554
 
 
5555
 
        std::vector<boost::shared_ptr<CqPolygonPoints> >        apPoints;
5556
 
        // Process any specified primitive variables
5557
 
        if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
5558
 
        {
5559
 
                // Create experimental version
5560
 
                if ( strcmp( scheme, "catmull-clark" ) == 0 )
5561
 
                {
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 ) );
5567
 
 
5568
 
                        boost::shared_ptr<CqSubdivision2> pSubd2( new CqSubdivision2( pPointsClass ) );
5569
 
                        pSubd2->Prepare( cVerts );
5570
 
 
5571
 
                        boost::shared_ptr<CqSurfaceSubdivisionMesh> pMesh( new CqSurfaceSubdivisionMesh(pSubd2, nfaces ) );
5572
 
 
5573
 
                        RtInt   iP = 0;
5574
 
                        for ( face = 0; face < nfaces; ++face )
5575
 
                        {
5576
 
                                pSubd2->AddFacet( nvertices[ face ], &vertices[ iP ], iP );
5577
 
                                iP += nvertices[ face ];
5578
 
                        }
5579
 
                        if ( pSubd2->Finalise() )
5580
 
                        {
5581
 
                                // Process tags.
5582
 
                                TqInt argcIndex = 0;
5583
 
                                TqInt floatargIndex = 0;
5584
 
                                TqInt intargIndex = 0;
5585
 
                                for ( TqInt i = 0; i < ntags; ++i )
5586
 
                                {
5587
 
                                        if ( strcmp( tags[ i ], "interpolateboundary" ) == 0 )
5588
 
                                                pSubd2->SetInterpolateBoundary( TqTrue );
5589
 
                                        else if ( strcmp( tags [ i ], "crease" ) == 0 )
5590
 
                                        {
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);
5598
 
                                                TqInt iEdge = 0;
5599
 
                                                while ( iEdge < nargs[ argcIndex ] - 1 )
5600
 
                                                {
5601
 
                                                        if ( intargs[ iEdge + intargIndex ] < pSubd2->cVertices() &&
5602
 
                                                                intargs[ iEdge + intargIndex + 1 ] < pSubd2->cVertices() )
5603
 
                                                        {
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;
5609
 
                                                                pEdge->Qve( aQve );
5610
 
                                                                std::vector<CqLath*>::iterator iOpp;
5611
 
                                                                for( iOpp = aQve.begin(); iOpp != aQve.end(); ++iOpp )
5612
 
                                                                {
5613
 
                                                                        if( ( NULL != (*iOpp)->ec() ) && (*iOpp)->ec()->VertexIndex() == intargs[ iEdge + intargIndex + 1 ] )
5614
 
                                                                        {
5615
 
                                                                                pSubd2->AddSharpEdge( (*iOpp), creaseSharpness );
5616
 
                                                                                pSubd2->AddSharpEdge( (*iOpp)->ec(), creaseSharpness );
5617
 
                                                                                break;
5618
 
                                                                        }
5619
 
                                                                }
5620
 
                                                        }
5621
 
                                                        iEdge++;
5622
 
                                                }
5623
 
                                        }
5624
 
                                        else if ( strcmp( tags [ i ], "corner" ) == 0 )
5625
 
                                        {
5626
 
                                                TqInt iVertex = 0;
5627
 
                                                while ( iVertex < nargs[ argcIndex ] )
5628
 
                                                {
5629
 
                                                        if ( intargs[ iVertex + intargIndex ] < pSubd2->cVertices() )
5630
 
                                                        {
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 );
5636
 
                                                        }
5637
 
                                                        iVertex++;
5638
 
                                                }
5639
 
                                        }
5640
 
                                        else if ( strcmp( tags [ i ], "hole" ) == 0 )
5641
 
                                        {
5642
 
                                                TqInt iFace = 0;
5643
 
                                                while ( iFace < nargs[ argcIndex ] )
5644
 
                                                {
5645
 
                                                        pSubd2->SetHoleFace( intargs[ iFace + intargIndex ] );
5646
 
                                                        iFace++;
5647
 
                                                }
5648
 
                                        }
5649
 
 
5650
 
                                        intargIndex += nargs[ argcIndex++ ];
5651
 
                                        floatargIndex += nargs[ argcIndex++ ];
5652
 
                                }
5653
 
 
5654
 
                                CreateGPrim(pMesh);
5655
 
                        }
5656
 
                        else
5657
 
                        {
5658
 
                                Aqsis::log() << error << "RiSubdivisionMesh contains non-manifold data" << std::endl;
5659
 
                        }
5660
 
                }
5661
 
                else
5662
 
                {
5663
 
                        Aqsis::log() << error << "RiSubdivisionMesh invalid scheme \"" << scheme << "\"" << std::endl;
5664
 
                }
5665
 
        }
5666
 
 
5667
 
        return ;
5668
 
}
5669
 
 
5670
 
 
5671
 
RtVoid RiReadArchive( RtToken name, RtArchiveCallback callback, ... )
5672
 
{
5673
 
        EXTRACT_PARAMETERS( callback )
5674
 
 
5675
 
        RiReadArchiveV( name, callback, PASS_PARAMETERS );
5676
 
}
5677
 
 
5678
 
 
5679
 
RtVoid  RiReadArchiveV( RtToken name, RtArchiveCallback callback, PARAMETERLIST )
5680
 
{
5681
 
        VALIDATE_CONDITIONAL
5682
 
 
5683
 
        CACHE_RIREADARCHIVE
5684
 
 
5685
 
        VALIDATE_RIREADARCHIVE
5686
 
 
5687
 
        DEBUG_RIREADARCHIVE
5688
 
 
5689
 
        CqRiFile        fileArchive( name, "archive" );
5690
 
 
5691
 
        if ( fileArchive.IsValid() )
5692
 
        {
5693
 
                CqString strRealName( fileArchive.strRealName() );
5694
 
                fileArchive.Close();
5695
 
                FILE *file;
5696
 
                if ( ( file = fopen( strRealName.c_str(), "rb" ) ) != NULL )
5697
 
                {
5698
 
#ifdef REQUIRED
5699
 
                        Aqsis::log() << info << "RiReadArchive: Reading archive \"" << strRealName.c_str() << "\"" << std::endl;
5700
 
#endif
5701
 
 
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 );
5707
 
                        fclose(file);
5708
 
                }
5709
 
        }
5710
 
}
5711
 
 
5712
 
 
5713
 
RtVoid  RiArchiveRecord( RtToken type, char * format, ... )
5714
 
{
5715
 
        VALIDATE_RIARCHIVERECORD
5716
 
 
5717
 
        DEBUG_RIARCHIVERECORD
5718
 
}
5719
 
 
5720
 
RtContextHandle RiGetContext( void )
5721
 
{
5722
 
        VALIDATE_RIGETCONTEXT
5723
 
 
5724
 
        DEBUG_RIGETCONTEXT
5725
 
 
5726
 
        return( NULL );
5727
 
}
5728
 
 
5729
 
RtVoid  RiContext( RtContextHandle handle )
5730
 
{
5731
 
        VALIDATE_RICONTEXT
5732
 
 
5733
 
        DEBUG_RICONTEXT
5734
 
}
5735
 
 
5736
 
RtVoid  RiClippingPlane( RtFloat x, RtFloat y, RtFloat z, RtFloat nx, RtFloat ny, RtFloat nz )
5737
 
{
5738
 
        VALIDATE_RICLIPPINGPLANE
5739
 
 
5740
 
        DEBUG_RICLIPPINGPLANE
5741
 
}
5742
 
 
5743
 
 
5744
 
RtVoid RiShaderLayer( RtToken type, RtToken name, RtToken layername, ... )
5745
 
{
5746
 
        EXTRACT_PARAMETERS( layername )
5747
 
 
5748
 
        RiShaderLayerV( type, name, layername, PASS_PARAMETERS );
5749
 
}
5750
 
 
5751
 
RtVoid RiShaderLayerV( RtToken type, RtToken name, RtToken layername, RtInt count, RtToken tokens[], RtPointer values[] )
5752
 
{
5753
 
        VALIDATE_CONDITIONAL
5754
 
 
5755
 
        CACHE_RISHADERLAYER
5756
 
 
5757
 
        VALIDATE_RISHADERLAYER
5758
 
 
5759
 
        DEBUG_RISHADERLAYER
5760
 
 
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.
5763
 
 
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)
5769
 
        {
5770
 
                newlayer = QGetRenderContext()->CreateShader( name, Type_Surface );
5771
 
                layeredshader = QGetRenderContext()->pattrCurrent()->pshadSurface(QGetRenderContext()->Time());
5772
 
 
5773
 
                if( !layeredshader || !layeredshader->IsLayered() )
5774
 
                {
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() );
5779
 
                }
5780
 
        }
5781
 
        else if(stringtype.compare("displacement")==0)
5782
 
        {
5783
 
                newlayer = QGetRenderContext()->CreateShader( name, Type_Displacement );
5784
 
                layeredshader = QGetRenderContext()->pattrCurrent()->pshadDisplacement(QGetRenderContext()->Time());
5785
 
 
5786
 
                if( !layeredshader || !layeredshader->IsLayered() )
5787
 
                {
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() );
5792
 
                }
5793
 
        }
5794
 
        else if(stringtype.compare("imager")==0)
5795
 
        {
5796
 
                QGetRenderContext() ->poptWriteCurrent()->GetStringOptionWrite( "System", "Imager" ) [ 0 ] = name ;
5797
 
                newlayer = QGetRenderContext()->CreateShader( name, Type_Imager );
5798
 
                layeredshader = QGetRenderContext()->poptCurrent()->pshadImager();
5799
 
 
5800
 
                if( !layeredshader || !layeredshader->IsLayered() )
5801
 
                {
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 );
5806
 
                }
5807
 
        }
5808
 
        else
5809
 
                Aqsis::log() << error << "Layered shaders not supported for type \"" << type << "\"" << std::endl;
5810
 
 
5811
 
        if ( newlayer && layeredshader )
5812
 
        {
5813
 
                newlayer->SetTransform( QGetRenderContext() ->ptransCurrent() );
5814
 
 
5815
 
                // Just add this layer in
5816
 
                layeredshader->AddLayer(layername, newlayer);
5817
 
 
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;
5821
 
 
5822
 
                // Execute the intiialisation code here, as we now have our shader context complete.
5823
 
                newlayer->PrepareDefArgs();
5824
 
                RtInt i;
5825
 
                for ( i = 0; i < count; ++i )
5826
 
                {
5827
 
                        RtToken token = tokens[ i ];
5828
 
                        RtPointer       value = values[ i ];
5829
 
 
5830
 
                        SetShaderArgument( newlayer, token, static_cast<TqPchar>( value ) );
5831
 
                }
5832
 
        }
5833
 
}
5834
 
 
5835
 
RtVoid RiConnectShaderLayers( RtToken type, RtToken layer1, RtToken variable1, RtToken layer2, RtToken variable2 )
5836
 
{
5837
 
        VALIDATE_CONDITIONAL
5838
 
 
5839
 
        CACHE_RICONNECTSHADERLAYERS
5840
 
 
5841
 
        VALIDATE_RICONNECTSHADERLAYERS
5842
 
 
5843
 
        DEBUG_RICONNECTSHADERLAYERS
5844
 
 
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();
5855
 
        else
5856
 
                Aqsis::log() << error << "Layered shaders not supported for type \"" << type << "\"" << std::endl;
5857
 
        if( pcurr && pcurr->IsLayered() )
5858
 
        {
5859
 
                // Just add this layer in
5860
 
                pcurr->AddConnection(layer1, variable1, layer2, variable2);
5861
 
        }
5862
 
}
5863
 
 
5864
 
 
5865
 
//---------------------------------------------------------------------
5866
 
//---------------------------------------------------------------------
5867
 
// Helper functions
5868
 
 
5869
 
//----------------------------------------------------------------------
5870
 
// ProcessPrimitiveVariables
5871
 
// Process and fill in any primitive variables.
5872
 
// return       :       RI_TRUE if position specified, RI_FALSE otherwise.
5873
 
 
5874
 
static RtBoolean ProcessPrimitiveVariables( CqSurface * pSurface, PARAMETERLIST )
5875
 
{
5876
 
        std::vector<TqInt>      aUserParams;
5877
 
 
5878
 
        // Read recognised parameter values.
5879
 
        RtInt   fP = RIL_NONE;
5880
 
 
5881
 
        RtFloat*        pPoints = 0;
5882
 
 
5883
 
        RtInt i;
5884
 
        for ( i = 0; i < count; ++i )
5885
 
        {
5886
 
                RtToken token = tokens[ i ];
5887
 
                RtPointer       value = values[ i ];
5888
 
 
5889
 
                SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( token );
5890
 
                TqUlong hash = CqString::hash(Decl.m_strName.c_str());
5891
 
 
5892
 
                if ( (hash == RIH_P) && (Decl.m_Class == class_vertex ))
5893
 
                {
5894
 
                        fP = RIL_P;
5895
 
                        pPoints = ( RtFloat* ) value;
5896
 
                }
5897
 
                else if ( (hash == RIH_PZ) && (Decl.m_Class == class_vertex ) )
5898
 
                {
5899
 
                        fP = RIL_Pz;
5900
 
                        pPoints = ( RtFloat* ) value;
5901
 
                }
5902
 
                else if ( (hash == RIH_PW) && (Decl.m_Class == class_vertex ) )
5903
 
                {
5904
 
                        fP = RIL_Pw;
5905
 
                        pPoints = ( RtFloat* ) value;
5906
 
                }
5907
 
                else
5908
 
                {
5909
 
                        aUserParams.push_back( i );
5910
 
                }
5911
 
        }
5912
 
 
5913
 
        // Fill in the position variable according to type.
5914
 
        if ( fP != RIL_NONE )
5915
 
        {
5916
 
                pSurface->AddPrimitiveVariable( new CqParameterTypedVertex<CqVector4D, type_hpoint, CqVector3D>( "P", 1 ) );
5917
 
                pSurface->P() ->SetSize( pSurface->cVertex() );
5918
 
                TqUint i;
5919
 
                switch ( fP )
5920
 
                {
5921
 
                                case RIL_P:
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 ] );
5924
 
                                break;
5925
 
 
5926
 
                                case RIL_Pz:
5927
 
                                for ( i = 0; i < pSurface->cVertex(); ++i )
5928
 
                                {
5929
 
                                        CqVector3D vecP = pSurface->SurfaceParametersAtVertex( i );
5930
 
                                        vecP.z( pPoints[ i ] );
5931
 
                                        pSurface->P()->pValue( i )[0] = vecP;
5932
 
                                }
5933
 
                                break;
5934
 
 
5935
 
                                case RIL_Pw:
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 ] );
5938
 
                                break;
5939
 
                }
5940
 
        }
5941
 
 
5942
 
        // Now process any user defined paramter variables.
5943
 
        if ( aUserParams.size() > 0 )
5944
 
        {
5945
 
                std::vector<TqInt>::iterator iUserParam;
5946
 
                for ( iUserParam = aUserParams.begin(); iUserParam != aUserParams.end(); ++iUserParam )
5947
 
                {
5948
 
                        SqParameterDeclaration Decl;
5949
 
                        try
5950
 
                        {
5951
 
                                Decl = QGetRenderContext()->FindParameterDecl( tokens[ *iUserParam ] );
5952
 
                        }
5953
 
                        catch( XqException e )
5954
 
                        {
5955
 
                                Aqsis::log() << error << e.strReason().c_str() << std::endl;
5956
 
                                continue;
5957
 
                        }
5958
 
 
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.
5961
 
                        TqInt cValues = 1;
5962
 
                        switch ( Decl.m_Class )
5963
 
                        {
5964
 
                                case class_uniform:
5965
 
                                        cValues = pSurface->cUniform();
5966
 
                                        break;
5967
 
 
5968
 
                                case class_varying:
5969
 
                                        cValues = pSurface->cVarying();
5970
 
                                        break;
5971
 
 
5972
 
                                case class_vertex:
5973
 
                                        cValues = pSurface->cVertex();
5974
 
                                        break;
5975
 
 
5976
 
                                case class_facevarying:
5977
 
                                        cValues = pSurface->cFaceVarying();
5978
 
                                        break;
5979
 
 
5980
 
                                case class_facevertex:
5981
 
                                        cValues = pSurface->cFaceVertex();
5982
 
                                        break;
5983
 
 
5984
 
                                default:
5985
 
                                        break;
5986
 
                        }
5987
 
                        pNewParam->SetSize( cValues );
5988
 
 
5989
 
                        TqInt i;
5990
 
                        switch ( Decl.m_Type )
5991
 
                        {
5992
 
                                        case type_float:
5993
 
                                        {
5994
 
                                                CqParameterTyped<TqFloat, TqFloat>* pFloatParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pNewParam );
5995
 
                                                TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
5996
 
                                                TqInt iArrayIndex, iValIndex;
5997
 
                                                i = 0;
5998
 
                                                for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
5999
 
                                                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6000
 
                                                                pFloatParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
6001
 
                                        }
6002
 
                                        break;
6003
 
 
6004
 
                                        case type_integer:
6005
 
                                        {
6006
 
                                                CqParameterTyped<TqInt, TqFloat>* pIntParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pNewParam );
6007
 
                                                TqInt* pValue = reinterpret_cast<TqInt*>( values[ *iUserParam ] );
6008
 
                                                TqInt iArrayIndex, iValIndex;
6009
 
                                                i = 0;
6010
 
                                                for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
6011
 
                                                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
6012
 
                                                                pIntParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
6013
 
                                        }
6014
 
                                        break;
6015
 
 
6016
 
                                        case type_point:
6017
 
                                        case type_normal:
6018
 
                                        case type_vector:
6019
 
                                        {
6020
 
                                                CqParameterTyped<CqVector3D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pNewParam );
6021
 
                                                TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6022
 
                                                TqInt iArrayIndex, iValIndex;
6023
 
                                                i = 0;
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 ] );
6027
 
                                        }
6028
 
                                        break;
6029
 
 
6030
 
                                        case type_string:
6031
 
                                        {
6032
 
                                                CqParameterTyped<CqString, CqString>* pStringParam = static_cast<CqParameterTyped<CqString, CqString>*>( pNewParam );
6033
 
                                                char** pValue = reinterpret_cast<char**>( values[ *iUserParam ] );
6034
 
                                                TqInt iArrayIndex, iValIndex;
6035
 
                                                i = 0;
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 ] );
6039
 
                                        }
6040
 
                                        break;
6041
 
 
6042
 
                                        case type_color:
6043
 
                                        {
6044
 
                                                CqParameterTyped<CqColor, CqColor>* pColorParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pNewParam );
6045
 
                                                TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6046
 
                                                TqInt iArrayIndex, iValIndex;
6047
 
                                                i = 0;
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 ] );
6051
 
                                        }
6052
 
                                        break;
6053
 
 
6054
 
                                        case type_hpoint:
6055
 
                                        {
6056
 
                                                CqParameterTyped<CqVector4D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pNewParam );
6057
 
                                                TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6058
 
                                                TqInt iArrayIndex, iValIndex;
6059
 
                                                i = 0;
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 ] );
6063
 
                                        }
6064
 
                                        break;
6065
 
 
6066
 
                                        case type_matrix:
6067
 
                                        {
6068
 
                                                CqParameterTyped<CqMatrix, CqMatrix>* pMatrixParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pNewParam );
6069
 
                                                TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
6070
 
                                                TqInt iArrayIndex, iValIndex;
6071
 
                                                i = 0;
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 ]
6078
 
                                                                                                                            );
6079
 
                                        }
6080
 
                                        break;
6081
 
 
6082
 
                                        default:
6083
 
                                        {
6084
 
                                                // left blank to avoid compiler warnings about unhandled types
6085
 
                                                break;
6086
 
                                        }
6087
 
                        }
6088
 
                        pSurface->AddPrimitiveVariable( pNewParam );
6089
 
                }
6090
 
        }
6091
 
 
6092
 
        return ( pSurface->P() != NULL );
6093
 
}
6094
 
 
6095
 
 
6096
 
//----------------------------------------------------------------------
6097
 
// CreateGPrin
6098
 
// Create and register a GPrim according to the current attributes/transform
6099
 
//
6100
 
RtVoid  CreateGPrim( const boost::shared_ptr<CqSurface>& pSurface )
6101
 
{
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() )
6104
 
        {
6105
 
                CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
6106
 
 
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.
6110
 
                if( pMS == NULL )
6111
 
                {
6112
 
                        boost::shared_ptr<CqDeformingSurface> pNewMS( new CqDeformingSurface( pSurface ) );
6113
 
                        pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
6114
 
                        pMMB->SetDeformingSurface( pNewMS );
6115
 
                }
6116
 
                else
6117
 
                {
6118
 
                        pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
6119
 
                }
6120
 
                QGetRenderContext() ->AdvanceTime();
6121
 
        }
6122
 
        else
6123
 
        {
6124
 
                QGetRenderContext()->StorePrimitive( pSurface );
6125
 
                STATS_INC( GPR_created );
6126
 
 
6127
 
                // Add to the raytracer database also
6128
 
                if(QGetRenderContext()->pRaytracer())
6129
 
                        QGetRenderContext()->pRaytracer()->AddPrimitive(pSurface);
6130
 
        }
6131
 
 
6132
 
        return ;
6133
 
}
6134
 
 
6135
 
 
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.
6141
 
 */
6142
 
 
6143
 
RtBoolean       BasisFromName( RtBasis * b, const char * strName )
6144
 
{
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;
6156
 
 
6157
 
        if ( pVals )
6158
 
        {
6159
 
                TqInt i, j;
6160
 
                for ( i = 0; i < 4; ++i )
6161
 
                        for ( j = 0; j < 4; ++j )
6162
 
                                ( *b ) [ i ][ j ] = ( *pVals ) [ i ][ j ];
6163
 
                return ( TqTrue );
6164
 
        }
6165
 
        return ( TqFalse );
6166
 
}
6167
 
 
6168
 
 
6169
 
//----------------------------------------------------------------------
6170
 
/** Set the function used to report progress.
6171
 
 *      \param  handler Pointer to the new function to use.
6172
 
 */
6173
 
 
6174
 
RtVoid  RiProgressHandler( RtProgressFunc handler )
6175
 
{
6176
 
        QGetRenderContext()->SetpProgressHandler( handler );
6177
 
        return ;
6178
 
}
6179
 
 
6180
 
 
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.
6185
 
 */
6186
 
 
6187
 
RtFunc  RiPreRenderFunction( RtFunc function )
6188
 
{
6189
 
        RtFunc pOldPreRenderFunction = QGetRenderContext()->pPreRenderFunction();
6190
 
        QGetRenderContext()->SetpPreRenderFunction( function );
6191
 
        return ( pOldPreRenderFunction );
6192
 
}
6193
 
 
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.
6198
 
 */
6199
 
 
6200
 
RtFunc  RiPreWorldFunction( RtFunc function )
6201
 
{
6202
 
        RtFunc pOldPreWorldFunction = QGetRenderContext()->pPreWorldFunction();
6203
 
        QGetRenderContext()->SetpPreWorldFunction( function );
6204
 
        return ( pOldPreWorldFunction );
6205
 
}
6206
 
 
6207
 
 
6208
 
void SetShaderArgument( const boost::shared_ptr<IqShader>& pShader, const char * name, TqPchar val )
6209
 
{
6210
 
        // Find the relevant variable.
6211
 
        SqParameterDeclaration Decl;
6212
 
        try
6213
 
        {
6214
 
                Decl = QGetRenderContext() ->FindParameterDecl( name );
6215
 
        }
6216
 
        catch( XqException e )
6217
 
        {
6218
 
                Aqsis::log() << error << e.strReason().c_str() << std::endl;
6219
 
                return;
6220
 
        }
6221
 
 
6222
 
        pShader->SetArgument( Decl.m_strName, Decl.m_Type, Decl.m_strSpace, val );
6223
 
}
6224
 
 
6225
 
 
6226
 
//----------------------------------------------------------------------
6227
 
/** Analyze the parameter list and figure what kind of compression is required for texturemapping output files.
6228
 
 
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
6234
 
 
6235
 
        \return nothing
6236
 
 */
6237
 
 
6238
 
static void ProcessCompression( TqInt * compression, TqInt * quality, TqInt count, RtToken * tokens, RtPointer * values )
6239
 
{
6240
 
        *compression = COMPRESSION_NONE;
6241
 
        *quality = 70;
6242
 
 
6243
 
        for ( int i = 0; i < count; ++i )
6244
 
        {
6245
 
                RtToken token = tokens[ i ];
6246
 
                RtString *value = ( RtString * ) values[ i ];
6247
 
 
6248
 
                if ( strstr( token, "compression" ) != 0 )
6249
 
                {
6250
 
 
6251
 
                        if ( strstr( *value, "none" ) != 0 )
6252
 
                                * compression = COMPRESSION_NONE;
6253
 
 
6254
 
                        else if ( strstr( *value, "lzw" ) != 0 )
6255
 
                                * compression = COMPRESSION_LZW;
6256
 
 
6257
 
                        else if ( strstr( *value, "deflate" ) != 0 )
6258
 
                                * compression = COMPRESSION_DEFLATE;
6259
 
 
6260
 
                        else if ( strstr( *value, "jpeg" ) != 0 )
6261
 
                                * compression = COMPRESSION_JPEG;
6262
 
 
6263
 
                        else if ( strstr( *value, "packbits" ) != 0 )
6264
 
                                * compression = COMPRESSION_PACKBITS;
6265
 
 
6266
 
 
6267
 
                }
6268
 
                else if ( strstr( token, "quality" ) != 0 )
6269
 
                {
6270
 
 
6271
 
                        *quality = ( int ) * ( float * ) value;
6272
 
                        if ( *quality < 0 )
6273
 
                                * quality = 0;
6274
 
                        if ( *quality > 100 )
6275
 
                                * quality = 100;
6276
 
                }
6277
 
        }
6278
 
}