~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to render/ri.cpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

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.com
 
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.com)
 
24
*/
 
25
 
 
26
#include        "aqsis.h"
 
27
 
 
28
#include        <stdarg.h>
 
29
#include        <math.h>
 
30
#include        <list>
 
31
 
 
32
#include        "imagebuffer.h"
 
33
#include        "lights.h"
 
34
#include        "renderer.h"
 
35
#include        "patch.h"
 
36
#include        "polygon.h"
 
37
#include        "nurbs.h"
 
38
#include        "symbols.h"
 
39
#include        "bilinear.h"
 
40
#include        "quadrics.h"
 
41
#include        "teapot.h"
 
42
#include        "shaders.h"
 
43
#include        "texturemap.h"
 
44
#include        "objectinstance.h"
 
45
#include        "trimcurve.h"
 
46
#include        "genpoly.h"
 
47
#include        "points.h"
 
48
#include        "curves.h"
 
49
#include        "rifile.h"
 
50
#include        "librib2ri.h"
 
51
#include        "converter.h"
 
52
#include        "shadervm.h"
 
53
#include        "librib.h"
 
54
#include        "libribtypes.h"
 
55
#include        "parserstate.h"
 
56
#include        "procedural.h"
 
57
 
 
58
#include        "ri_cache.h"
 
59
 
 
60
#include        "subdivision2.h"
 
61
 
 
62
#ifndef    AQSIS_SYSTEM_WIN32
 
63
#include        "unistd.h"
 
64
#endif /* AQSIS_SYSTEM_WIN32 */
 
65
 
 
66
#include        "ri.h"
 
67
 
 
68
#include        "sstring.h"
 
69
 
 
70
//#include      "share.h"
 
71
#include        "validate.h"
 
72
 
 
73
#include        "ri_validate.inl"
 
74
 
 
75
using namespace Aqsis;
 
76
 
 
77
static RtBoolean ProcessPrimitiveVariables( CqSurface* pSurface, PARAMETERLIST );
 
78
static void ProcessCompression( TqInt *compress, TqInt *quality, TqInt count, RtToken *tokens, RtPointer *values );
 
79
RtVoid  CreateGPrim( const boost::shared_ptr<CqBasicSurface>& pSurface );
 
80
void SetShaderArgument( IqShader* pShader, const char* name, TqPchar val );
 
81
TqBool  ValidateState(...);
 
82
 
 
83
 
 
84
//---------------------------------------------------------------------
 
85
// This file contains the interface functions which are published as the
 
86
//      Renderman Interface SPECification (C) 1988 Pixar.
 
87
//
 
88
 
 
89
//---------------------------------------------------------------------
 
90
// Interface parameter token strings.
 
91
 
 
92
 
 
93
RtToken RI_FRAMEBUFFER  = "framebuffer";
 
94
RtToken RI_FILE = "file";
 
95
RtToken RI_RGB  = "rgb";
 
96
RtToken RI_RGBA = "rgba";
 
97
RtToken RI_RGBZ = "rgbz";
 
98
RtToken RI_RGBAZ        = "rgbaz";
 
99
RtToken RI_A    = "a";
 
100
RtToken RI_Z    = "z";
 
101
RtToken RI_AZ   = "az";
 
102
RtToken RI_MERGE        = "merge";
 
103
RtToken RI_ORIGIN       = "origin";
 
104
RtToken RI_PERSPECTIVE  = "perspective";
 
105
RtToken RI_ORTHOGRAPHIC = "orthographic";
 
106
RtToken RI_HIDDEN       = "hidden";
 
107
RtToken RI_PAINT        = "paint";
 
108
RtToken RI_CONSTANT     = "constant";
 
109
RtToken RI_SMOOTH       = "smooth";
 
110
RtToken RI_FLATNESS     = "flatness";
 
111
RtToken RI_FOV  = "fov";
 
112
 
 
113
RtToken RI_AMBIENTLIGHT = "ambientlight";
 
114
RtToken RI_POINTLIGHT   = "pointlight";
 
115
RtToken RI_DISTANTLIGHT = "distantlight";
 
116
RtToken RI_SPOTLIGHT    = "spotlight";
 
117
RtToken RI_INTENSITY    = "intensity";
 
118
RtToken RI_LIGHTCOLOR   = "lightcolor";
 
119
RtToken RI_FROM = "from";
 
120
RtToken RI_TO   = "to";
 
121
RtToken RI_CONEANGLE    = "coneangle";
 
122
RtToken RI_CONEDELTAANGLE       = "conedeltaangle";
 
123
RtToken RI_BEAMDISTRIBUTION     = "beamdistribution";
 
124
RtToken RI_MATTE        = "matte";
 
125
RtToken RI_METAL        = "metal";
 
126
RtToken RI_PLASTIC      = "plastic";
 
127
RtToken RI_SHIINYMETAL  = "shinymetal";
 
128
RtToken RI_PAINTEDPLASTIC       = "paintedplastic";
 
129
RtToken RI_KA   = "ka";
 
130
RtToken RI_KD   = "kd";
 
131
RtToken RI_KS   = "ks";
 
132
RtToken RI_ROUGHNESS    = "roughness";
 
133
RtToken RI_SPECULARCOLOR        = "specularcolor";
 
134
RtToken RI_DEPTHCUE     = "depthcue";
 
135
RtToken RI_FOG  = "fog";
 
136
RtToken RI_BUMPY        = "bumpy";
 
137
RtToken RI_MINDISTANCE  = "mindistance";
 
138
RtToken RI_MAXDISTANCE  = "maxdistance";
 
139
RtToken RI_BACKGROUND   = "background";
 
140
RtToken RI_DISTANCE     = "distance";
 
141
 
 
142
RtToken RI_RASTER       = "raster";
 
143
RtToken RI_SCREEN       = "screen";
 
144
RtToken RI_CAMERA       = "camera";
 
145
RtToken RI_WORLD        = "world";
 
146
RtToken RI_OBJECT       = "object";
 
147
RtToken RI_INSIDE       = "inside";
 
148
RtToken RI_OUTSIDE      = "outside";
 
149
RtToken RI_LH   = "lh";
 
150
RtToken RI_RH   = "rh";
 
151
RtToken RI_P    = "P";
 
152
RtToken RI_PZ   = "Pz";
 
153
RtToken RI_PW   = "Pw";
 
154
RtToken RI_N    = "N";
 
155
RtToken RI_NP   = "Np";
 
156
RtToken RI_CS   = "Cs";
 
157
RtToken RI_OS   = "Os";
 
158
RtToken RI_S    = "s";
 
159
RtToken RI_T    = "t";
 
160
RtToken RI_ST   = "st";
 
161
RtToken RI_BILINEAR     = "bilinear";
 
162
RtToken RI_BICUBIC      = "bicubic";
 
163
RtToken RI_CUBIC        = "cubic";
 
164
RtToken RI_LINEAR       = "linear";
 
165
RtToken RI_PRIMITIVE    = "primitive";
 
166
RtToken RI_INTERSECTION = "intersection";
 
167
RtToken RI_UNION        = "union";
 
168
RtToken RI_DIFFERENCE   = "difference";
 
169
RtToken RI_WRAP = "wrap";
 
170
RtToken RI_NOWRAP       = "nowrap";
 
171
RtToken RI_PERIODIC     = "periodic";
 
172
RtToken RI_NONPERIODIC  = "nonperiodic";
 
173
RtToken RI_CLAMP        = "clamp";
 
174
RtToken RI_BLACK        = "black";
 
175
RtToken RI_IGNORE       = "ignore";
 
176
RtToken RI_PRINT        = "print";
 
177
RtToken RI_ABORT        = "abort";
 
178
RtToken RI_HANDLER      = "handler";
 
179
RtToken RI_IDENTIFIER   = "identifier";
 
180
RtToken RI_NAME = "name";
 
181
RtToken RI_CURRENT      = "current";
 
182
RtToken RI_SHADER       = "shader";
 
183
RtToken RI_EYE  = "eye";
 
184
RtToken RI_NDC  = "ndc";
 
185
RtToken RI_AMPLITUDE    =       "amplitude";
 
186
RtToken RI_COMMENT      =       "comment";
 
187
RtToken RI_CONSTANTWIDTH        =       "constantwidth";
 
188
RtToken RI_KR   =       "kr";
 
189
RtToken RI_SHINYMETAL   =       "shinymetal";
 
190
RtToken RI_STRUCTURE    =       "structure";
 
191
RtToken RI_TEXTURENAME  =       "texturename";
 
192
RtToken RI_VERBATIM     =       "verbatim";
 
193
RtToken RI_WIDTH        =       "width";
 
194
 
 
195
RtBasis RiBezierBasis   = {{ -1.0f,       3.0f,      -3.0f,       1.0f},
 
196
                         {  3.0f,      -6.0f,       3.0f,       0.0f},
 
197
                         { -3.0f,       3.0f,       0.0f,       0.0f},
 
198
                         {  1.0f,       0.0f,       0.0f,       0.0f}};
 
199
RtBasis RiBSplineBasis  = {{ -1.0f/6.0f,  0.5f,      -0.5f,       1.0f/6.0f},
 
200
                          {  0.5f,      -1.0f,       0.5f,       0.0f},
 
201
                          { -0.5f,       0.0f,        0.5f,       0.0f},
 
202
                          {  1.0f/6.0f,  2.0f/3.0f,  1.0f/6.0f,  0.0f}};
 
203
RtBasis RiCatmullRomBasis={{ -0.5f,       1.5f,      -1.5f,       0.5f},
 
204
                           {  1.0f,      -2.5f,       2.0f,      -0.5f},
 
205
                           { -0.5f,       0.0f,       0.5f,       0.0f},
 
206
                           {  0.0f,       1.0f,       0.0f,       0.0f}};
 
207
RtBasis RiHermiteBasis  = {{  2.0f,       1.0f,      -2.0f,       1.0f},
 
208
                          { -3.0f,      -2.0f,       3.0f,      -1.0f},
 
209
                          {  0.0f,       1.0f,       0.0f,       0.0f},
 
210
                          {  1.0f,       0.0f,       0.0f,       0.0f}};
 
211
RtBasis RiPowerBasis    = {{  1.0f,       0.0f,       0.0f,       0.0f},
 
212
                        {  0.0f,       1.0f,       0.0f,       0.0f},
 
213
                        {  0.0f,       0.0f,       1.0f,       0.0f},
 
214
                        {  0.0f,       0.0f,       0.0f,       1.0f}};
 
215
 
 
216
enum RIL_POINTS
 
217
{
 
218
    RIL_NONE = -1,
 
219
    RIL_P,
 
220
    RIL_Pz,
 
221
    RIL_Pw,
 
222
    RIL_N,
 
223
    RIL_Np,
 
224
    RIL_s,
 
225
    RIL_t = RIL_s,
 
226
    RIL_st,
 
227
};
 
228
static TqUlong RIH_S = CqParameter::hash( RI_S );
 
229
static TqUlong RIH_T = CqParameter::hash( RI_T );
 
230
static TqUlong RIH_ST = CqParameter::hash( RI_ST );
 
231
static TqUlong RIH_CS = CqParameter::hash( RI_CS );
 
232
static TqUlong RIH_OS = CqParameter::hash( RI_OS );
 
233
static TqUlong RIH_P = CqParameter::hash( RI_P );
 
234
static TqUlong RIH_PZ = CqParameter::hash( RI_PZ );
 
235
static TqUlong RIH_PW = CqParameter::hash( RI_PW );
 
236
static TqUlong RIH_N = CqParameter::hash( RI_N );
 
237
static TqUlong RIH_NP = CqParameter::hash( RI_NP );
 
238
static TqUlong RIH_DEPTHFILTER = CqParameter::hash( "depthfilter" );
 
239
static TqUlong RIH_JITTER = CqParameter::hash( "jitter" );
 
240
 
 
241
RtInt   RiLastError = 0;
 
242
 
 
243
//----------------------------------------------------------------------
 
244
// CreateGPrim
 
245
// Helper function to build a GPrim from any boost::shared_ptr<> type..
 
246
template<class T>
 
247
inline
 
248
RtVoid  CreateGPrim( const boost::shared_ptr<T>& pSurface )
 
249
{
 
250
    CreateGPrim( boost::static_pointer_cast<CqBasicSurface,T>( pSurface ) );
 
251
}
 
252
 
 
253
//----------------------------------------------------------------------
 
254
// BuildParameterList
 
255
// Helper function to build a parameter list to pass on to the V style functions.
 
256
// returns a parameter count.
 
257
 
 
258
RtInt BuildParameterList( va_list pArgs, std::vector<RtToken>& aTokens, std::vector<RtPointer>& aValues )
 
259
{
 
260
    RtInt count = 0;
 
261
    RtToken pToken = va_arg( pArgs, RtToken );
 
262
    RtPointer pValue;
 
263
    aTokens.clear();
 
264
    aValues.clear();
 
265
    while ( pToken != 0 && pToken != RI_NULL )                  // While not RI_NULL
 
266
    {
 
267
        aTokens.push_back( pToken );
 
268
        pValue = va_arg( pArgs, RtPointer );
 
269
        aValues.push_back( pValue );
 
270
        pToken = va_arg( pArgs, RtToken );
 
271
        count++;
 
272
    }
 
273
    return ( count );
 
274
}
 
275
 
 
276
 
 
277
//----------------------------------------------------------------------
 
278
//      CqRangeCheckCallback implentation
 
279
//      Use this with CheckMinMax
 
280
//
 
281
class   CqLogRangeCheckCallback : public CqRangeCheckCallback
 
282
{
 
283
public:
 
284
    CqLogRangeCheckCallback()
 
285
    { }
 
286
 
 
287
    void set( const char* name )
 
288
    {
 
289
        m_name = name;
 
290
    }
 
291
 
 
292
    virtual void operator()( int res )
 
293
    {
 
294
        switch( res )
 
295
        {
 
296
        case CqRangeCheckCallback::UPPER_BOUND_HIT:
 
297
            {
 
298
                std::cerr << error << "Invalid Value for " << m_name << ". Value exceeded upper limit" << std::endl;
 
299
            }
 
300
 
 
301
        case CqRangeCheckCallback::LOWER_BOUND_HIT:
 
302
            {
 
303
                std::cerr << error << "Invalid Value for " << m_name << ". Value exceeded lower limit" << std::endl;
 
304
            }
 
305
 
 
306
        default:
 
307
            ;
 
308
        }
 
309
    }
 
310
 
 
311
 
 
312
private:
 
313
    const char* m_name;
 
314
};
 
315
 
 
316
 
 
317
//----------------------------------------------------------------------
 
318
// ValidateState
 
319
// Check that the currect graphics state is one of those specified.
 
320
//
 
321
TqBool  ValidateState(int count, ... )
 
322
{
 
323
    va_list     pArgs;
 
324
    va_start( pArgs, count );
 
325
 
 
326
        int currentState = Outside;
 
327
        if(  QGetRenderContext() != NULL && QGetRenderContext()->pconCurrent() )
 
328
                currentState = QGetRenderContext()->pconCurrent()->Type();
 
329
 
 
330
        int i;
 
331
        for(i=0; i<count; i++)
 
332
        {
 
333
                int state = va_arg( pArgs, int );
 
334
                if( currentState == state )
 
335
                        return(TqTrue);
 
336
        }
 
337
        return(TqFalse);
 
338
}
 
339
 
 
340
 
 
341
//----------------------------------------------------------------------
 
342
// GetStateAsString
 
343
// Get a string representing the current state.
 
344
//
 
345
const char*     GetStateAsString()
 
346
{
 
347
        int currentState = Outside;
 
348
        if( QGetRenderContext()->pconCurrent() )
 
349
                currentState = QGetRenderContext()->pconCurrent()->Type();
 
350
        switch( currentState )
 
351
        {
 
352
                case Outside:
 
353
                        return("Outside");
 
354
                        break;
 
355
 
 
356
                case BeginEnd:
 
357
                        return("BeginEnd");
 
358
                        break;
 
359
 
 
360
                case Frame:
 
361
                        return("Frame");
 
362
                        break;
 
363
 
 
364
                case World:
 
365
                        return("World");
 
366
                        break;
 
367
 
 
368
                case Attribute:
 
369
                        return("Attribute");
 
370
                        break;
 
371
 
 
372
                case Transform:
 
373
                        return("Transform");
 
374
                        break;
 
375
 
 
376
                case Solid:
 
377
                        return("Solid");
 
378
                        break;
 
379
 
 
380
                case Object:
 
381
                        return("Object");
 
382
                        break;
 
383
 
 
384
                case Motion:
 
385
                        return("Motion");
 
386
                        break;
 
387
        }
 
388
        return("");
 
389
}
 
390
 
 
391
 
 
392
//----------------------------------------------------------------------
 
393
// RiDeclare
 
394
// Declare a new variable to be recognised by the system.
 
395
//
 
396
RtToken RiDeclare( RtString name, RtString declaration )
 
397
{
 
398
        Cache_RiDeclare
 
399
 
 
400
        Validate_RiDeclare
 
401
 
 
402
    CqString strName( name ), strDecl( declaration );
 
403
    QGetRenderContext() ->AddParameterDecl( strName.c_str(), strDecl.c_str() );
 
404
    return ( 0 );
 
405
}
 
406
 
 
407
//----------------------------------------------------------------------
 
408
// RiBegin
 
409
// Begin a Renderman render phase.
 
410
//
 
411
extern "C" char *StandardParameters[][2];
 
412
RtVoid  RiBegin( RtToken name )
 
413
{
 
414
        Validate_RiBegin
 
415
 
 
416
    // Create a new renderer
 
417
    QSetRenderContext( new CqRenderer );
 
418
 
 
419
    QGetRenderContext() ->Initialise();
 
420
    QGetRenderContext() ->BeginMainModeBlock();
 
421
    QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix() );
 
422
    QGetRenderContext() ->SetCameraTransform( QGetRenderContext() ->ptransCurrent() );
 
423
    // Clear the lightsources stack.
 
424
    CqLightsource* pL = Lightsource_stack.pFirst();
 
425
    while ( pL )
 
426
    {
 
427
        // Unlink from the stack, and release the stacks reference to the light.
 
428
        pL->UnLink();
 
429
        RELEASEREF( pL );
 
430
        pL = Lightsource_stack.pFirst();
 
431
    }
 
432
 
 
433
    // Clear any options.
 
434
    QGetRenderContext() ->optCurrent().ClearOptions();
 
435
 
 
436
    // Include the standard options (how can we opt out of this).
 
437
    int param = 0;
 
438
    while( StandardParameters[param][0] != NULL )
 
439
    {
 
440
        RiDeclare(
 
441
            StandardParameters[param][0],
 
442
            StandardParameters[param][1]
 
443
        );
 
444
        param++;
 
445
    };
 
446
 
 
447
    // Setup default paths
 
448
    const char* popt[ 1 ];
 
449
    CqString strSetting;
 
450
    strSetting = Aqsis::CqFile::GetSystemSetting( "shaders" );
 
451
    popt[ 0 ] = strSetting.c_str();
 
452
    RiOption( "searchpath", "shader", &popt, RI_NULL );
 
453
    strSetting = Aqsis::CqFile::GetSystemSetting( "archives" );
 
454
    popt[ 0 ] = strSetting.c_str();
 
455
    RiOption( "searchpath", "archive", &popt, RI_NULL );
 
456
    strSetting = Aqsis::CqFile::GetSystemSetting( "textures" );
 
457
    popt[ 0 ] = strSetting.c_str();
 
458
    RiOption( "searchpath", "texture", &popt, RI_NULL );
 
459
    strSetting = Aqsis::CqFile::GetSystemSetting( "displays" );
 
460
    popt[ 0 ] = strSetting.c_str();
 
461
    RiOption( "searchpath", "display", &popt, RI_NULL );
 
462
    strSetting = Aqsis::CqFile::GetSystemSetting( "dsolibs" );
 
463
    popt[ 0 ] = strSetting.c_str();
 
464
    RiOption( "searchpath", "dsolibs", &popt, RI_NULL );
 
465
    strSetting = Aqsis::CqFile::GetSystemSetting( "procedurals" );
 
466
    popt[ 0 ] = strSetting.c_str();
 
467
    RiOption( "searchpath", "procedural", &popt, RI_NULL );
 
468
 
 
469
    // Setup a default Display
 
470
    RiDisplay( "ri.pic", "file", "rgba", NULL );
 
471
 
 
472
    // Setup a default surface shader
 
473
    CqShaderVM * pShader = new CqShaderVM();
 
474
    pShader->SetstrName( "_def_" );
 
475
    pShader->DefaultSurface();
 
476
    pShader->matCurrent() = QGetRenderContext() ->matCurrent(QGetRenderContext()->Time());
 
477
    pShader->PrepareDefArgs();
 
478
    QGetRenderContext() ->RegisterShader( "_def_", Type_Surface, pShader );
 
479
    QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pShader, QGetRenderContext() ->Time() );
 
480
 
 
481
        // Setup the initial transformation.
 
482
//      QGetRenderContext()->ptransWriteCurrent() ->SetHandedness( TqFalse );
 
483
        QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
 
484
 
 
485
    return ;
 
486
}
 
487
 
 
488
//----------------------------------------------------------------------
 
489
// RiEnd
 
490
// End the rendermam render stage.
 
491
//
 
492
RtVoid  RiEnd()
 
493
{
 
494
        Validate_RiEnd
 
495
 
 
496
    QGetRenderContext() ->EndMainModeBlock();
 
497
 
 
498
    // Flush the image cache.
 
499
    CqTextureMap::FlushCache();
 
500
 
 
501
    // Clear the lightsources stack.
 
502
    CqLightsource* pL = Lightsource_stack.pFirst();
 
503
    while ( pL )
 
504
    {
 
505
        // Unlink from the stack, and release the stacks reference to the light.
 
506
        pL->UnLink();
 
507
        RELEASEREF( pL );
 
508
        pL = Lightsource_stack.pFirst();
 
509
    }
 
510
 
 
511
    // Delete the renderer
 
512
    delete( QGetRenderContext() );
 
513
    QSetRenderContext( 0 );
 
514
 
 
515
    return ;
 
516
}
 
517
 
 
518
 
 
519
//----------------------------------------------------------------------
 
520
// RiFrameBegin
 
521
// Begin an individual frame, options are saved at this point.
 
522
//
 
523
RtVoid  RiFrameBegin( RtInt number )
 
524
{
 
525
        Cache_RiFrameBegin
 
526
 
 
527
        Validate_RiFrameBegin
 
528
 
 
529
    // Initialise the statistics variables. If the RIB doesn't contain
 
530
    // a Frame-block the initialisation was previously done in CqStats::Initilise()
 
531
    // which has to be called before a rendering session.
 
532
    QGetRenderContext() ->Stats().InitialiseFrame();
 
533
    // Start the timer. Note: The corresponding call of StopFrameTimer() is
 
534
    // done in WorldEnd (!) not FrameEnd since it can happen that there is
 
535
    // not FrameEnd (and usually there's not much between WorldEnd and FrameEnd).
 
536
    QGetRenderContext() ->Stats().StartFrameTimer();
 
537
 
 
538
    QGetRenderContext() ->BeginFrameModeBlock();
 
539
    QGetRenderContext() ->SetCurrentFrame( number );
 
540
    CqCSGTreeNode::SetRequired( TqFalse );
 
541
    return ;
 
542
}
 
543
 
 
544
 
 
545
//----------------------------------------------------------------------
 
546
// RiFrameEnd
 
547
// End the rendering of an individual frame, options are restored.
 
548
//
 
549
RtVoid  RiFrameEnd()
 
550
{
 
551
        Cache_RiFrameEnd
 
552
 
 
553
        Validate_RiFrameEnd
 
554
 
 
555
    QGetRenderContext() ->EndFrameModeBlock();
 
556
    QGetRenderContext() ->ClearDisplayRequests();
 
557
 
 
558
    return ;
 
559
}
 
560
 
 
561
//----------------------------------------------------------------------
 
562
// RiWorldBegin
 
563
// Start the information for the world, options are now frozen.  The world-to-camera
 
564
// transformation is set to the current transformation, and current is set to identity.
 
565
//
 
566
RtVoid  RiWorldBegin()
 
567
{
 
568
        Cache_RiWorldBegin
 
569
 
 
570
        Validate_RiWorldBegin
 
571
 
 
572
    // Call any specified pre world function.
 
573
    if ( QGetRenderContext()->pPreWorldFunction() != NULL )
 
574
        ( *QGetRenderContext()->pPreWorldFunction() ) ();
 
575
 
 
576
    // Start the frame timer (just in case there was no FrameBegin block. If there
 
577
    // was, nothing happens)
 
578
    QGetRenderContext() ->Stats().StartFrameTimer();
 
579
    QGetRenderContext() ->Stats().MakeParse().Start();
 
580
 
 
581
    // Now that the options have all been set, setup any undefined camera parameters.
 
582
    if ( !QGetRenderContext() ->optCurrent().FrameAspectRatioCalled() )
 
583
    {
 
584
        // Derive the FAR from the resolution and pixel aspect ratio.
 
585
        RtFloat PAR = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "PixelAspectRatio" ) [ 0 ];
 
586
        RtFloat resH = QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "Resolution" ) [ 0 ];
 
587
        RtFloat resV = QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "Resolution" ) [ 1 ];
 
588
        QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = ( resH * PAR ) / resV ;
 
589
    }
 
590
 
 
591
    if ( !QGetRenderContext() ->optCurrent().ScreenWindowCalled() )
 
592
    {
 
593
        RtFloat fFAR = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "FrameAspectRatio" ) [ 0 ];
 
594
 
 
595
        if ( fFAR >= 1.0 )
 
596
        {
 
597
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = -fFAR ;
 
598
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = + fFAR ;
 
599
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = + 1 ;
 
600
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = -1 ;
 
601
        }
 
602
        else
 
603
        {
 
604
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = -1 ;
 
605
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = + 1 ;
 
606
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = + 1.0 / fFAR ;
 
607
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = -1.0 / fFAR ;
 
608
        }
 
609
    }
 
610
 
 
611
    QGetRenderContext() ->BeginWorldModeBlock();
 
612
    // Set the world to camera transformation matrix to the current matrix.
 
613
    QGetRenderContext() ->SetCameraTransform( QGetRenderContext() ->ptransCurrent() );
 
614
    // and then reset the current matrix to identity, ready for object transformations.
 
615
    if(QGetRenderContext() ->ptransWriteCurrent() ->cTimes() > 1)
 
616
        {
 
617
                TqInt i;
 
618
                CqMatrix matOpenShutterInverse = QGetRenderContext() ->ptransCurrent() ->matObjectToWorld( QGetRenderContext() ->ptransCurrent() ->Time( 0 ) );
 
619
                matOpenShutterInverse = matOpenShutterInverse.Inverse();
 
620
                QGetRenderContext() ->ptransWriteCurrent() ->SetCurrentTransform( QGetRenderContext() ->ptransCurrent() ->Time( 0 ), CqMatrix() );
 
621
                for ( i = 1; i < QGetRenderContext() ->ptransWriteCurrent() ->cTimes(); ++i )
 
622
                        QGetRenderContext() ->ptransWriteCurrent() ->SetCurrentTransform( QGetRenderContext() ->ptransCurrent() ->Time( i ), matOpenShutterInverse * QGetRenderContext() ->ptransCurrent() ->matObjectToWorld( QGetRenderContext() ->ptransCurrent() ->Time( i ) ) );
 
623
        }
 
624
        else
 
625
                QGetRenderContext() ->ptransWriteCurrent() ->SetCurrentTransform( QGetRenderContext() ->Time(), CqMatrix() );
 
626
        // Clear the camera transform to a single state, all camera motion is now transferred to the objects.
 
627
        QGetRenderContext()->GetCameraTransform()->ResetTransform( QGetRenderContext()->GetCameraTransform()->matObjectToWorld( QGetRenderContext()->GetCameraTransform()->Time(0) ), 
 
628
                                                                                                                           QGetRenderContext()->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) );
 
629
 
 
630
    QGetRenderContext() ->optCurrent().InitialiseCamera();
 
631
    QGetRenderContext() ->pImage() ->SetImage();
 
632
 
 
633
    return ;
 
634
}
 
635
 
 
636
 
 
637
//----------------------------------------------------------------------
 
638
// RiWorldEnd
 
639
// End the specifying of world data, options are released.
 
640
//
 
641
 
 
642
RtVoid  RiWorldEnd()
 
643
{
 
644
        Cache_RiWorldEnd
 
645
 
 
646
        Validate_RiWorldEnd
 
647
 
 
648
    TqBool fFailed = TqFalse;
 
649
    // Call any specified pre render function.
 
650
    if ( QGetRenderContext()->pPreRenderFunction() != NULL )
 
651
        ( *QGetRenderContext()->pPreRenderFunction() ) ();
 
652
 
 
653
    // Stop the parsing counter
 
654
    QGetRenderContext() ->Stats().MakeParse().Stop();
 
655
 
 
656
 
 
657
    const TqInt* poptVerbose = QGetRenderContext() ->optCurrent().GetIntegerOption( "statistics", "renderinfo" );
 
658
    if ( poptVerbose )
 
659
    {
 
660
        QGetRenderContext() -> Stats().PrintInfo();
 
661
    }
 
662
 
 
663
    const TqInt* poptGridSize = QGetRenderContext() ->optCurrent().GetIntegerOption( "limits", "gridsize" );
 
664
    if( NULL != poptGridSize )
 
665
        QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "SqrtGridSize" )[0] = sqrt( static_cast<float>(poptGridSize[0]) );
 
666
 
 
667
        // Finalise the raytracer database now that all primitives are in.
 
668
        if(QGetRenderContext()->pRaytracer())
 
669
                QGetRenderContext()->pRaytracer()->Finalise();
 
670
 
 
671
    // Render the world
 
672
    try
 
673
    {
 
674
        QGetRenderContext() ->RenderWorld();
 
675
    }
 
676
    catch ( CqString strError )
 
677
    {
 
678
        std::cout << strError.c_str() << std::endl;
 
679
        fFailed = TqTrue;
 
680
    }
 
681
 
 
682
    // Delete the world context
 
683
    QGetRenderContext() ->EndWorldModeBlock();
 
684
 
 
685
    // Stop the frame timer
 
686
    QGetRenderContext() ->Stats().StopFrameTimer();
 
687
 
 
688
    if ( !fFailed )
 
689
    {
 
690
        // Get the verbosity level from the options...
 
691
        TqInt verbosity = 0;
 
692
        const TqInt* poptEndofframe = QGetRenderContext() ->optCurrent().GetIntegerOption( "statistics", "endofframe" );
 
693
        if ( poptEndofframe != 0 )
 
694
            verbosity = poptEndofframe[ 0 ];
 
695
 
 
696
        // ...and print the statistics.
 
697
        QGetRenderContext() ->Stats().PrintStats( verbosity );
 
698
    }
 
699
    return ;
 
700
}
 
701
 
 
702
 
 
703
//----------------------------------------------------------------------
 
704
// RiFormat
 
705
// Specify the setup of the final image.
 
706
//
 
707
RtVoid  RiFormat( RtInt xresolution, RtInt yresolution, RtFloat pixelaspectratio )
 
708
{
 
709
        Cache_RiFormat
 
710
 
 
711
        Validate_RiFormat
 
712
 
 
713
    QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Resolution" ) [ 0 ] = xresolution ;
 
714
    QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Resolution" ) [ 1 ] = yresolution ;
 
715
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "PixelAspectRatio" ) [ 0 ] = ( pixelaspectratio < 0.0 ) ? 1.0 : pixelaspectratio ;
 
716
 
 
717
    // Inform the system that RiFormat has been called, as this takes priority.
 
718
    QGetRenderContext() ->optCurrent().CallFormat();
 
719
 
 
720
    return ;
 
721
}
 
722
 
 
723
 
 
724
//----------------------------------------------------------------------
 
725
// RiFrameAspectRatio
 
726
// Set the aspect ratio of the frame irrespective of the display setup.
 
727
//
 
728
RtVoid  RiFrameAspectRatio( RtFloat frameratio )
 
729
{
 
730
        Cache_RiFrameAspectRatio
 
731
 
 
732
        Validate_RiFrameAspectRatio
 
733
 
 
734
    CqLogRangeCheckCallback rc;
 
735
 
 
736
    bool valid = true;
 
737
 
 
738
    rc.set( "frameratio");
 
739
    if( !CheckMinMax( frameratio, 0.0f, RI_INFINITY, &rc ) )
 
740
    {
 
741
        valid = false;
 
742
    }
 
743
 
 
744
    if( !valid )
 
745
    {
 
746
        std::cerr << error << "RiFrameAspectRatio: Invalid RiFrameAspectRatio, aborting" << std::endl;
 
747
        throw( "INVALID_VALUE" );
 
748
        return;
 
749
    }
 
750
 
 
751
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FrameAspectRatio" ) [ 0 ] = frameratio ;
 
752
 
 
753
    // Inform the system that RiFrameAspectRatio has been called, as this takes priority.
 
754
    QGetRenderContext() ->optCurrent().CallFrameAspectRatio();
 
755
 
 
756
    return ;
 
757
}
 
758
 
 
759
 
 
760
//----------------------------------------------------------------------
 
761
// RiScreenWindow
 
762
// Set the resolution of the screen window in the image plane specified in the screen
 
763
// coordinate system.
 
764
//
 
765
RtVoid  RiScreenWindow( RtFloat left, RtFloat right, RtFloat bottom, RtFloat top )
 
766
{
 
767
        Cache_RiScreenWindow
 
768
 
 
769
        Validate_RiScreenWindow
 
770
 
 
771
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 0 ] = left ;
 
772
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 1 ] = right ;
 
773
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 2 ] = top ;
 
774
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "ScreenWindow" ) [ 3 ] = bottom ;
 
775
 
 
776
    // Inform the system that RiScreenWindow has been called, as this takes priority.
 
777
    QGetRenderContext() ->optCurrent().CallScreenWindow();
 
778
 
 
779
    return ;
 
780
}
 
781
 
 
782
 
 
783
//----------------------------------------------------------------------
 
784
// RiCropWindow
 
785
// Set the position and size of the crop window specified in fractions of the raster
 
786
// window.
 
787
//
 
788
RtVoid  RiCropWindow( RtFloat left, RtFloat right, RtFloat top, RtFloat bottom )
 
789
{
 
790
        Cache_RiCropWindow
 
791
 
 
792
        Validate_RiCropWindow
 
793
 
 
794
    CqLogRangeCheckCallback rc;
 
795
 
 
796
    bool valid = true;
 
797
 
 
798
    rc.set( "left");
 
799
    if( !CheckMinMax( left, 0.0f, 1.0f, &rc ) )
 
800
    {
 
801
        valid = false;
 
802
    }
 
803
 
 
804
    rc.set( "right" );
 
805
    if( !CheckMinMax( right, 0.0f, 1.0f, &rc ) )
 
806
    {
 
807
        valid = false;
 
808
    }
 
809
 
 
810
    rc.set( "top" );
 
811
    if( !CheckMinMax( top, 0.0f, 1.0f, &rc ) )
 
812
    {
 
813
        valid = false;
 
814
    }
 
815
 
 
816
    rc.set( "bottom" );
 
817
    if( !CheckMinMax( bottom, 0.0f, 1.0f, &rc ) )
 
818
    {
 
819
        valid = false;
 
820
    }
 
821
 
 
822
    if( !valid )
 
823
    {
 
824
        std::cerr << error << "Invalid RiCropWindow, aborting" << std::endl;
 
825
        throw( "INVALID_VALUE" );
 
826
        return;
 
827
    }
 
828
 
 
829
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 0 ] = left ;
 
830
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 1 ] = right ;
 
831
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 2 ] = top ;
 
832
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "CropWindow" ) [ 3 ] = bottom ;
 
833
 
 
834
    return ;
 
835
}
 
836
 
 
837
 
 
838
//----------------------------------------------------------------------
 
839
// RiProjection
 
840
// Set the camera projection to be used.
 
841
//
 
842
RtVoid  RiProjection( RtToken name, ... )
 
843
{
 
844
    va_list     pArgs;
 
845
    va_start( pArgs, name );
 
846
 
 
847
    std::vector<RtToken> aTokens;
 
848
    std::vector<RtPointer> aValues;
 
849
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
850
 
 
851
    RiProjectionV( name, count, &aTokens[0], &aValues[0] );
 
852
}
 
853
 
 
854
 
 
855
//----------------------------------------------------------------------
 
856
// RiProjectionV
 
857
// List mode version of above.
 
858
//
 
859
RtVoid  RiProjectionV( RtToken name, PARAMETERLIST )
 
860
{
 
861
        Cache_RiProjection
 
862
 
 
863
        Validate_RiProjection
 
864
 
 
865
    if ( strcmp( name, RI_PERSPECTIVE ) == 0 )
 
866
        QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Projection" ) [ 0 ] = ProjectionPerspective ;
 
867
    else if     ( strcmp( name, RI_ORTHOGRAPHIC ) == 0 )
 
868
        QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "Projection" ) [ 0 ] = ProjectionOrthographic ;
 
869
    else if( name != RI_NULL )
 
870
    {
 
871
        std::cerr << error << "RiProjection: Invalid projection: \"" << name << "\"" << std::endl;
 
872
        return ;
 
873
    }
 
874
 
 
875
    RtInt i;
 
876
    for ( i = 0; i < count; ++i )
 
877
    {
 
878
        RtToken token = tokens[ i ];
 
879
        RtPointer       value = values[ i ];
 
880
 
 
881
        if ( strcmp( token, RI_FOV ) == 0 )
 
882
            QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FOV" ) [ 0 ] = *( reinterpret_cast<RtFloat*>( value ) ) ;
 
883
    }
 
884
    // TODO: need to get the current transformation so that it can be added to the screen transformation.
 
885
    QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix() );
 
886
 
 
887
    return ;
 
888
}
 
889
 
 
890
 
 
891
//----------------------------------------------------------------------
 
892
// RiClipping
 
893
// Set the near and far clipping planes specified as distances from the camera.
 
894
//
 
895
RtVoid  RiClipping( RtFloat cnear, RtFloat cfar )
 
896
{
 
897
        Cache_RiClipping
 
898
 
 
899
        Validate_RiClipping
 
900
 
 
901
    CqLogRangeCheckCallback rc;
 
902
 
 
903
    bool valid = true;
 
904
 
 
905
    rc.set( "near");
 
906
    if( !CheckMinMax( cnear, RI_EPSILON, cfar, &rc ) )
 
907
    {
 
908
        valid = false;
 
909
    }
 
910
 
 
911
    rc.set( "far" );
 
912
    if( !CheckMinMax( cfar, cnear, RI_INFINITY, &rc ) )
 
913
    {
 
914
        valid = false;
 
915
    }
 
916
 
 
917
    if( !valid )
 
918
    {
 
919
        std::cerr << error << "RiClipping: Invalid RiClipping, clipping planes set to RI_EPSILON, RI_INFINITY" << std::endl;
 
920
        cnear   = RI_EPSILON;
 
921
        cfar    = RI_INFINITY;
 
922
    }
 
923
 
 
924
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Clipping" ) [ 0 ] = cnear ;
 
925
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Clipping" ) [ 1 ] = cfar ;
 
926
 
 
927
    return ;
 
928
}
 
929
 
 
930
 
 
931
//----------------------------------------------------------------------
 
932
// RiDepthOfField
 
933
// Specify the parameters which affect focal blur of the camera.
 
934
//
 
935
RtVoid  RiDepthOfField( RtFloat fstop, RtFloat focallength, RtFloat focaldistance )
 
936
{
 
937
        Cache_RiDepthOfField
 
938
 
 
939
        Validate_RiDepthOfField
 
940
 
 
941
    CqLogRangeCheckCallback rc;
 
942
 
 
943
    bool valid = true;
 
944
 
 
945
    rc.set( "fstop" );
 
946
    if( !CheckMinMax( fstop, 0.0f, RI_INFINITY, &rc ) )
 
947
    {
 
948
        valid = false;
 
949
    }
 
950
 
 
951
    rc.set( "focallength" );
 
952
    if( !CheckMinMax( focallength, 0.0f, RI_INFINITY, &rc ) )
 
953
    {
 
954
        valid = false;
 
955
    }
 
956
 
 
957
    rc.set( "focaldistance" );
 
958
    if( !CheckMinMax( focaldistance, 0.0f, RI_INFINITY, &rc ) )
 
959
    {
 
960
        valid = false;
 
961
    }
 
962
 
 
963
    if( !valid )
 
964
    {
 
965
        std::cerr << warning << "RiDepthOfField: Invalid DepthOfField, DepthOfField ignored" << std::endl;
 
966
        return;
 
967
    }
 
968
 
 
969
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "DepthOfField" ) [ 0 ] = fstop ;
 
970
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "DepthOfField" ) [ 1 ] = focallength ;
 
971
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "DepthOfField" ) [ 2 ] = focaldistance ;
 
972
 
 
973
    QGetRenderContext() ->SetDepthOfFieldData( fstop, focallength, focaldistance );
 
974
}
 
975
 
 
976
 
 
977
//----------------------------------------------------------------------
 
978
// RiShutter
 
979
//      Set the times at which the shutter opens and closes, used for motion blur.
 
980
//
 
981
RtVoid  RiShutter( RtFloat opentime, RtFloat closetime )
 
982
{
 
983
        Cache_RiShutter
 
984
 
 
985
        Validate_RiShutter
 
986
 
 
987
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Shutter" ) [ 0 ] = opentime;
 
988
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Shutter" ) [ 1 ] = closetime;
 
989
 
 
990
    return ;
 
991
}
 
992
 
 
993
 
 
994
//----------------------------------------------------------------------
 
995
// RiPixelVariance
 
996
// Set the upper bound on the variance from the true pixel color by the pixel filter
 
997
// function.
 
998
//
 
999
RtVoid  RiPixelVariance( RtFloat variance )
 
1000
{
 
1001
        Cache_RiPixelVariance
 
1002
 
 
1003
        Validate_RiPixelVariance
 
1004
 
 
1005
    CqLogRangeCheckCallback rc;
 
1006
 
 
1007
    bool valid = true;
 
1008
 
 
1009
    rc.set( "variance" );
 
1010
    if( !CheckMinMax( variance, 0.0f, RI_INFINITY, &rc ) )
 
1011
    {
 
1012
        valid = false;
 
1013
    }
 
1014
 
 
1015
    if( !valid )
 
1016
    {
 
1017
        std::cerr << warning << "RiPixelVariance: Invalid PixelVariance, PixelVariance set to 0" << std::endl;
 
1018
        variance = 0;
 
1019
    }
 
1020
 
 
1021
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "PixelVariance" ) [ 0 ] = variance ;
 
1022
 
 
1023
    return ;
 
1024
}
 
1025
 
 
1026
 
 
1027
//----------------------------------------------------------------------
 
1028
// RiPixelSamples
 
1029
// Set the number of samples per pixel for the hidden surface function.
 
1030
//
 
1031
RtVoid  RiPixelSamples( RtFloat xsamples, RtFloat ysamples )
 
1032
{
 
1033
        Cache_RiPixelSamples
 
1034
 
 
1035
        Validate_RiPixelSamples
 
1036
 
 
1037
    CqLogRangeCheckCallback rc;
 
1038
 
 
1039
    bool valid = true;
 
1040
 
 
1041
    rc.set( "xsamples" );
 
1042
    if( !CheckMinMax( xsamples, 1.0f, RI_INFINITY, &rc ) )
 
1043
    {
 
1044
        valid = false;
 
1045
    }
 
1046
 
 
1047
    rc.set( "ysamples" );
 
1048
    if( !CheckMinMax( ysamples, 1.0f, RI_INFINITY, &rc ) )
 
1049
    {
 
1050
        valid = false;
 
1051
    }
 
1052
 
 
1053
    if( !valid )
 
1054
    {
 
1055
        std::cerr << warning << "RiPixelSamples: Invalid PixelSamples, PixelSamples set to 1, 1" << std::endl;
 
1056
        xsamples = 1;
 
1057
        ysamples = 1;
 
1058
    }
 
1059
 
 
1060
    QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "PixelSamples" ) [ 0 ] = static_cast<TqInt>( xsamples ) ;
 
1061
    QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "PixelSamples" ) [ 1 ] = static_cast<TqInt>( ysamples ) ;
 
1062
 
 
1063
    return ;
 
1064
}
 
1065
 
 
1066
 
 
1067
//----------------------------------------------------------------------
 
1068
// RiPixelFilter
 
1069
// Set the function used to generate a final pixel value from supersampled values.
 
1070
//
 
1071
RtVoid  RiPixelFilter( RtFilterFunc function, RtFloat xwidth, RtFloat ywidth )
 
1072
{
 
1073
        Cache_RiPixelFilter
 
1074
 
 
1075
        Validate_RiPixelFilter
 
1076
 
 
1077
    QGetRenderContext() ->optCurrent().SetfuncFilter( function );
 
1078
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FilterWidth" ) [ 0 ] = xwidth ;
 
1079
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "FilterWidth" ) [ 1 ] = ywidth ;
 
1080
 
 
1081
    return ;
 
1082
}
 
1083
 
 
1084
 
 
1085
//----------------------------------------------------------------------
 
1086
// RiExposure
 
1087
//      Set the values of the exposure color modification function.
 
1088
//
 
1089
RtVoid  RiExposure( RtFloat gain, RtFloat gamma )
 
1090
{
 
1091
        Cache_RiExposure
 
1092
 
 
1093
        Validate_RiExposure
 
1094
 
 
1095
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Exposure" ) [ 0 ] = gain ;
 
1096
    QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Exposure" ) [ 1 ] = gamma ;
 
1097
 
 
1098
    return ;
 
1099
}
 
1100
 
 
1101
 
 
1102
//----------------------------------------------------------------------
 
1103
// RiImager
 
1104
// Specify a prepocessing imager shader.
 
1105
//
 
1106
RtVoid  RiImager( RtToken name, ... )
 
1107
{
 
1108
    va_list     pArgs;
 
1109
    va_start( pArgs, name );
 
1110
 
 
1111
    std::vector<RtToken> aTokens;
 
1112
    std::vector<RtPointer> aValues;
 
1113
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
1114
 
 
1115
    RiImagerV( name, count, &aTokens[0], &aValues[0] );
 
1116
}
 
1117
 
 
1118
 
 
1119
//----------------------------------------------------------------------
 
1120
// RiImagerV
 
1121
// List based version of above.
 
1122
//
 
1123
RtVoid  RiImagerV( RtToken name, PARAMETERLIST )
 
1124
{
 
1125
        Cache_RiImager
 
1126
 
 
1127
        Validate_RiImager
 
1128
 
 
1129
    RtInt i;
 
1130
 
 
1131
    if ( strlen( name ) )
 
1132
    {
 
1133
        QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "Imager" ) [ 0 ] = name ;
 
1134
        QGetRenderContext() ->optCurrent().LoadImager( name );
 
1135
        for ( i = 0; i < count; ++i )
 
1136
        {
 
1137
            RtToken     token = tokens[ i ];
 
1138
            RtPointer   value = values[ i ];
 
1139
 
 
1140
            QGetRenderContext() ->optCurrent().SetValueImager(
 
1141
                token, static_cast<TqPchar>( value ) );
 
1142
        }
 
1143
    }
 
1144
    return ;
 
1145
}
 
1146
 
 
1147
 
 
1148
//----------------------------------------------------------------------
 
1149
// RiQuantize
 
1150
// Specify the color quantization parameters.
 
1151
//
 
1152
RtVoid  RiQuantize( RtToken type, RtInt one, RtInt min, RtInt max, RtFloat ditheramplitude )
 
1153
{
 
1154
        Cache_RiQuantize
 
1155
 
 
1156
        Validate_RiQuantize
 
1157
 
 
1158
    if ( strcmp( type, "rgba" ) == 0 )
 
1159
    {
 
1160
        TqFloat* pColorQuantize = QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "Quantize", "Color" );
 
1161
        pColorQuantize [ 0 ] = static_cast<TqFloat>( one );
 
1162
        pColorQuantize [ 1 ] = static_cast<TqFloat>( min );
 
1163
        pColorQuantize [ 2 ] = static_cast<TqFloat>( max );
 
1164
        pColorQuantize [ 3 ] = static_cast<TqFloat>( ditheramplitude );
 
1165
    }
 
1166
    else if ( strcmp( type, "z" ) == 0 )
 
1167
    {
 
1168
        TqFloat* pDepthQuantize = QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "Quantize", "Depth" );
 
1169
        pDepthQuantize [ 0 ] = static_cast<TqFloat>( one );
 
1170
        pDepthQuantize [ 1 ] = static_cast<TqFloat>( min );
 
1171
        pDepthQuantize [ 2 ] = static_cast<TqFloat>( max );
 
1172
        pDepthQuantize [ 3 ] = static_cast<TqFloat>( ditheramplitude );
 
1173
    }
 
1174
    else
 
1175
    {
 
1176
        CqNamedParameterList* pOption = QGetRenderContext() ->optCurrent().pOptionWrite( "Quantize" ).get();
 
1177
        if( pOption )
 
1178
        {
 
1179
            CqParameterTypedUniformArray<TqFloat,type_float,TqFloat>* pQuant = new CqParameterTypedUniformArray<TqFloat,type_float,TqFloat>(type,4); \
 
1180
            pQuant->pValue()[0] = static_cast<TqFloat>( one );
 
1181
            pQuant->pValue()[1] = static_cast<TqFloat>( min );
 
1182
            pQuant->pValue()[2] = static_cast<TqFloat>( max );
 
1183
            pQuant->pValue()[3] = static_cast<TqFloat>( ditheramplitude );
 
1184
            pOption->AddParameter( pQuant );
 
1185
        }
 
1186
    }
 
1187
 
 
1188
    return ;
 
1189
}
 
1190
 
 
1191
 
 
1192
//----------------------------------------------------------------------
 
1193
// RiDisplay
 
1194
// Set the final output name and type.
 
1195
//
 
1196
RtVoid  RiDisplay( RtToken name, RtToken type, RtToken mode, ... )
 
1197
{
 
1198
    va_list     pArgs;
 
1199
    va_start( pArgs, mode );
 
1200
 
 
1201
    std::vector<RtToken> aTokens;
 
1202
    std::vector<RtPointer> aValues;
 
1203
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
1204
 
 
1205
    RiDisplayV( name, type, mode, count, &aTokens[0], &aValues[0] );
 
1206
}
 
1207
 
 
1208
 
 
1209
//----------------------------------------------------------------------
 
1210
// RiDisplayV
 
1211
// List based version of above.
 
1212
//
 
1213
RtVoid  RiDisplayV( RtToken name, RtToken type, RtToken mode, PARAMETERLIST )
 
1214
{
 
1215
        Cache_RiDisplay
 
1216
 
 
1217
        Validate_RiDisplay
 
1218
 
 
1219
    CqString strName( name );
 
1220
    CqString strType( type );
 
1221
 
 
1222
    QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "DisplayName" ) [ 0 ] = strName.c_str() ;
 
1223
    QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "DisplayType" ) [ 0 ] = strType.c_str() ;
 
1224
 
 
1225
    // Append the display mode to the current setting.
 
1226
    TqInt eValue = 0;
 
1227
    TqInt index = 0;
 
1228
    TqInt dataOffset = 0;
 
1229
    TqInt dataSize = 0;
 
1230
    if ( strncmp( mode, RI_RGB, strlen(RI_RGB) ) == 0 )
 
1231
    {
 
1232
        eValue |= ModeRGB;
 
1233
        dataSize += 3;
 
1234
        index += strlen( RI_RGB );
 
1235
    }
 
1236
    if ( strncmp( &mode[index], RI_A, strlen( RI_A ) ) == 0 )
 
1237
    {
 
1238
        eValue |= ModeA;
 
1239
        dataSize += 1;
 
1240
        index += strlen( RI_A );
 
1241
    }
 
1242
    if ( strncmp( &mode[index], RI_Z, strlen( RI_Z ) ) == 0 )
 
1243
    {
 
1244
        eValue |= ModeZ;
 
1245
        dataSize += 1;
 
1246
        index += strlen( RI_Z );
 
1247
    }
 
1248
 
 
1249
    // If none of the standard "rgbaz" strings match, then it is an alternative 'arbitrary output variable'
 
1250
    if( eValue == 0 )
 
1251
    {
 
1252
        dataOffset = QGetRenderContext()->RegisterOutputData( mode );
 
1253
        dataSize = QGetRenderContext()->OutputDataSamples( mode );
 
1254
    }
 
1255
 
 
1256
    // Gather the additional arguments into a map to pass through to the manager.
 
1257
    std::map<std::string, void*> mapOfArguments;
 
1258
    TqInt i;
 
1259
    for( i = 0; i < count; ++i )
 
1260
        mapOfArguments[ tokens[ i ] ] = values[ i ];
 
1261
 
 
1262
    // Check if the request is to add a display driver.
 
1263
    if ( strName[ 0 ] == '+' )
 
1264
    {
 
1265
        TqInt iMode = QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "DisplayMode" ) [ 0 ] | eValue;
 
1266
        QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = iMode;
 
1267
        strName = strName.substr( 1 );
 
1268
    }
 
1269
    else
 
1270
    {
 
1271
        QGetRenderContext() ->ClearDisplayRequests();
 
1272
        QGetRenderContext() ->optCurrent().GetIntegerOptionWrite( "System", "DisplayMode" ) [ 0 ] = eValue ;
 
1273
    }
 
1274
    // Add a display driver to the list of requested drivers.
 
1275
    QGetRenderContext() ->AddDisplayRequest( strName.c_str(), strType.c_str(), mode, eValue, dataOffset, dataSize, mapOfArguments );
 
1276
 
 
1277
    return ;
 
1278
}
 
1279
 
 
1280
 
 
1281
//----------------------------------------------------------------------
 
1282
// RiGaussianFilter
 
1283
// Gaussian filter used as a possible value passed to RiPixelFilter.
 
1284
//
 
1285
RtFloat RiGaussianFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1286
{
 
1287
    /*
 
1288
     *  d = distance from origin
 
1289
     *  w = filterwidth ([COOK84a] article used 1.5)
 
1290
     *      For here use sqrt( (xwidth/2)*(xwidth/2) + (ywidth/2)*(ywidth/2) ).
 
1291
     *      Simplifying:
 
1292
     *
 
1293
     *          w = sqrt( (xwidth*xwidth)/2 + (ywidth*ywidth)/2 )
 
1294
     *          w = sqrt( (xwidth*xwidth + ywidth*ywidth)/2 )
 
1295
     *        w*w = (xwidth*xwidth + ywidth*ywidth)/2
 
1296
     *
 
1297
     *  if (d < filterwidth) then 0
 
1298
     *  else  exp(-d*d) - exp(-w*w)
 
1299
     *
 
1300
     */ 
 
1301
    //RtFloat d,d2,w,w2;
 
1302
    //
 
1303
    ///* d = sqrt(x*x+y*y), d*d = (x*x+y*y)  */
 
1304
    //d2 = (x*x+y*y);
 
1305
    //d = sqrt(d2);
 
1306
    //
 
1307
    //w2 = 0.5*(xwidth*xwidth + ywidth*ywidth);
 
1308
    //w = sqrt(w2);
 
1309
    //
 
1310
    //if(d>w)
 
1311
    //  return(0.0);
 
1312
    //else
 
1313
    //  return(exp(-d2) - exp(-w2));
 
1314
 
 
1315
    // The above version falls faster than the one used by the 3.2 spec
 
1316
    //   PRMan and RenderDotC.  Since all three match exactly, might as
 
1317
    //   well change to the code below:
 
1318
    x *= 2.0 / xwidth;
 
1319
    y *= 2.0 / ywidth;
 
1320
 
 
1321
    return exp( -2.0 * ( x * x + y * y ) );
 
1322
}
 
1323
 
 
1324
 
 
1325
//----------------------------------------------------------------------
 
1326
// RiBoxFilter
 
1327
// Box filter used as a possible value passed to RiPixelFIlter.
 
1328
//
 
1329
RtFloat RiBoxFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1330
{
 
1331
    /* [UPST89] -- (RC p. 178) says that x and y will be in the
 
1332
     *    following intervals:
 
1333
     *           -xwidth/2 <= x <= xwidth/2
 
1334
     *           -ywidth/2 <= y <= ywidth/2
 
1335
     *    These constraints on x and y really simplifies the
 
1336
     *       the following code to just return (1.0).  
 
1337
     *
 
1338
     */ 
 
1339
    return MIN( ( fabs( x ) <= xwidth / 2.0 ? 1.0 : 0.0 ),
 
1340
                ( fabs( y ) <= ywidth / 2.0 ? 1.0 : 0.0 ) );
 
1341
}
 
1342
 
 
1343
 
 
1344
//----------------------------------------------------------------------
 
1345
// RiTriangleFilter
 
1346
// Triangle filter used as a possible value passed to RiPixelFilter
 
1347
//
 
1348
RtFloat RiTriangleFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1349
{
 
1350
    RtFloat     hxw = xwidth / 2.0;
 
1351
    RtFloat     hyw = ywidth / 2.0;
 
1352
    RtFloat     absx = fabs( x );
 
1353
    RtFloat     absy = fabs( y );
 
1354
 
 
1355
    /* This function can be simplified as well by not worrying about
 
1356
     *    returning zero if the sample is beyond the filter window.
 
1357
     */ 
 
1358
    return MIN( ( absx <= hxw ? ( hxw - absx ) / hxw : 0.0 ),
 
1359
                ( absy <= hyw ? ( hyw - absy ) / hyw : 0.0 ) );
 
1360
}
 
1361
 
 
1362
 
 
1363
//----------------------------------------------------------------------
 
1364
// RiCatmullRomFilter
 
1365
// Catmull Rom filter used as a possible value passed to RiPixelFilter.
 
1366
//
 
1367
RtFloat RiCatmullRomFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1368
{
 
1369
    /*
 
1370
     * From page 223 of [MITC88] 
 
1371
     *
 
1372
     * if abs(d) < 1
 
1373
     *    f(d) = 1/6*(  (12-9*B-9*C)*abs(d*d*d)
 
1374
     *                + (-18 + 12*B + 6*C)*d*d + (6-2*B) )
 
1375
     *
 
1376
     * if 1 <= abs(d) < 2
 
1377
     *    f(d) = 1/6*(  (-B-6*C)*abs(d*d*d)
 
1378
     *                + (6*B + 30*C)*d*d
 
1379
     *                + (-12*B - 48*C)*d
 
1380
     *                + (8*B + 24*C) )
 
1381
     *
 
1382
     * otherwise  f(d)=0
 
1383
     *
 
1384
     * -------------------------------------------------------------
 
1385
     *  When B = 0.0 and C = 0.5 the filter is a Catmull-Rom cubic spline.
 
1386
     *
 
1387
     * if abs(d) < 1
 
1388
     *    f(d) = 1/6*[  (12-3)*abs(d*d*d) + (-18 + 3)*d*d + (6) ]
 
1389
     *
 
1390
     * if 1 <= abs(d) < 2
 
1391
     *    f(d) = 1/6*[  (-3)*abs(d*d*d) + (15)*d*d + (-24)*d + (12) ]
 
1392
     *
 
1393
     * otherwise  f(d)=0
 
1394
     * -------------------------------------------------------------
 
1395
     * Simplifying:
 
1396
     *
 
1397
     * if abs(d) < 1
 
1398
     *    f(d) = (3/2)*abs(d*d*d) - (5/2)*d*d + 1
 
1399
     *
 
1400
     * if 1 <= abs(d) <2
 
1401
     *    f(d) = (-0.5)*abs(d*d*d) + (5/2)*d*d - 4*abs(d) + 2
 
1402
     *
 
1403
     * otherwise  f(d)=0
 
1404
     *
 
1405
     */
 
1406
    RtFloat d, d2;
 
1407
 
 
1408
    d2 = x * x + y * y; /* d*d */
 
1409
    d = sqrt( d2 ); /* distance from origin */
 
1410
 
 
1411
    if ( d < 1 )
 
1412
        return ( 1.5 * d * d2 - 2.5 * d2 + 1.0 );
 
1413
    else if ( d < 2 )
 
1414
        return ( -d * d2 * 0.5 + 2.5 * d2 - 4.0 * d + 2.0 );
 
1415
    else
 
1416
        return 0.0;
 
1417
}
 
1418
 
 
1419
 
 
1420
//----------------------------------------------------------------------
 
1421
// RiSincFilter
 
1422
// Sinc filter used as a possible value passed to RiPixelFilter.
 
1423
//
 
1424
RtFloat RiSincFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1425
{
 
1426
    //RtFloat d;
 
1427
    //
 
1428
    //d = sqrt(x*x+y*y);
 
1429
    //
 
1430
    //if(d!=0)
 
1431
    //  return(sin(RI_PI*d)/(RI_PI*d));
 
1432
    //else
 
1433
    //  return(1.0);
 
1434
 
 
1435
    // The above is an un-windowed sinc, below is a windowed sinc
 
1436
    //   function similar in shape to what PRMan 3.9 uses.
 
1437
    // tburge 5-28-01
 
1438
 
 
1439
    /* Modified version of the RI Spec 3.2 sinc filter to be
 
1440
     *   windowed with a positive lobe of a cosine which is half
 
1441
     *   of a cosine period.  
 
1442
     */
 
1443
 
 
1444
    /* Uses a -PI to PI cosine window. */
 
1445
    if ( x != 0.0 )
 
1446
    {
 
1447
        x *= RI_PI;
 
1448
        x = cos( 0.5 * x / xwidth ) * sin( x ) / x;
 
1449
    }
 
1450
    else
 
1451
    {
 
1452
        x = 1.0;
 
1453
    }
 
1454
    if ( y != 0.0 )
 
1455
    {
 
1456
        y *= RI_PI;
 
1457
        y = cos( 0.5 * y / ywidth ) * sin( y ) / y;
 
1458
    }
 
1459
    else
 
1460
    {
 
1461
        y = 1.0;
 
1462
    }
 
1463
 
 
1464
    /* This is a square separable filter and is the 2D Fourier
 
1465
     * transform of a rectangular box outlining a lowpass bandwidth
 
1466
    * filter in the frequency domain.
 
1467
    */ 
 
1468
    return x*y;
 
1469
}
 
1470
 
 
1471
 
 
1472
//----------------------------------------------------------------------
 
1473
// RiDiskFilter -- this is in Pixar's ri.h
 
1474
// Cylindrical filter used as a possible value passed to RiPixelFilter
 
1475
//
 
1476
RtFloat RiDiskFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1477
{
 
1478
    double d, xx, yy;
 
1479
 
 
1480
    xx = x * x;
 
1481
    yy = y * y;
 
1482
    xwidth *= 0.5;
 
1483
    ywidth *= 0.5;
 
1484
 
 
1485
    d = ( xx ) / ( xwidth * xwidth ) + ( yy ) / ( ywidth * ywidth );
 
1486
    if ( d < 1.0 )
 
1487
    {
 
1488
        return 1.0;
 
1489
    }
 
1490
    else
 
1491
    {
 
1492
        return 0.0;
 
1493
    }
 
1494
}
 
1495
 
 
1496
 
 
1497
//----------------------------------------------------------------------
 
1498
// RiBesselFilter -- this is in Pixar's ri.h
 
1499
// Besselj0 filter used as a possible value passed to RiPixelFilter
 
1500
//
 
1501
RtFloat RiBesselFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
 
1502
{
 
1503
 
 
1504
    double d, w, xx, yy;
 
1505
 
 
1506
    xx = x * x;
 
1507
    yy = y * y;
 
1508
 
 
1509
    xwidth *= 0.5;
 
1510
    ywidth *= 0.5;
 
1511
 
 
1512
    w = ( xx ) / ( xwidth * xwidth ) + ( yy ) / ( ywidth * ywidth );
 
1513
    if ( w < 1.0 )
 
1514
    {
 
1515
        d = sqrt( xx + yy );
 
1516
        if ( d != 0.0 )
 
1517
        {
 
1518
            /* Half cosine window. */
 
1519
            w = cos( 0.5 * RI_PI * sqrt( w ) );
 
1520
            return w * 2*j1( RI_PI * d ) / d;
 
1521
        }
 
1522
        else
 
1523
        {
 
1524
            return RI_PI;
 
1525
        }
 
1526
    }
 
1527
    else
 
1528
    {
 
1529
        return 0.0;
 
1530
    }
 
1531
}
 
1532
 
 
1533
 
 
1534
//----------------------------------------------------------------------
 
1535
// RiHider
 
1536
// Specify a hidden surface calculation mode.
 
1537
//
 
1538
RtVoid  RiHider( RtToken name, ... )
 
1539
{
 
1540
    va_list     pArgs;
 
1541
    va_start( pArgs, name );
 
1542
 
 
1543
    std::vector<RtToken> aTokens;
 
1544
    std::vector<RtPointer> aValues;
 
1545
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
1546
 
 
1547
    RiHiderV( name, count, &aTokens[0], &aValues[0] );
 
1548
 
 
1549
}
 
1550
 
 
1551
//----------------------------------------------------------------------
 
1552
// RiHiderV
 
1553
// List based version of above.
 
1554
//
 
1555
RtVoid  RiHiderV( RtToken name, PARAMETERLIST )
 
1556
{
 
1557
        Cache_RiHider
 
1558
 
 
1559
        Validate_RiHider
 
1560
 
 
1561
    if ( !strcmp( name, "hidden" ) || !strcmp( name, "painter" ) )
 
1562
    {
 
1563
        QGetRenderContext() ->optCurrent().GetStringOptionWrite( "System", "Hider" ) [ 0 ] = name ;
 
1564
    }
 
1565
 
 
1566
    // Check options.
 
1567
    TqInt i;
 
1568
    for ( i = 0; i < count; ++i )
 
1569
    {
 
1570
        SqParameterDeclaration Decl;
 
1571
        try
 
1572
        {
 
1573
            Decl = QGetRenderContext()->FindParameterDecl( tokens[ i ] );
 
1574
        }
 
1575
        catch( XqException e )
 
1576
        {
 
1577
            std::cerr << error << e.strReason().c_str() << std::endl;
 
1578
            continue;
 
1579
        }
 
1580
                TqUlong hash = CqParameter::hash(Decl.m_strName.c_str());
 
1581
                if ( hash == RIH_DEPTHFILTER )
 
1582
            RiOption( "Hider", "depthfilter", ( RtToken ) values[ i ], NULL );
 
1583
                else if ( hash == RIH_JITTER )
 
1584
            RiOption( "Hider", "jitter", ( RtFloat* ) values[ i ], NULL );
 
1585
    }
 
1586
 
 
1587
    return ;
 
1588
}
 
1589
 
 
1590
 
 
1591
//----------------------------------------------------------------------
 
1592
// RiColorSamples
 
1593
// Specify the depth and conversion arrays for color manipulation.
 
1594
//
 
1595
RtVoid  RiColorSamples( RtInt N, RtFloat *nRGB, RtFloat *RGBn )
 
1596
{
 
1597
        Cache_RiColorSamples
 
1598
 
 
1599
        Validate_RiColorSamples
 
1600
 
 
1601
    std::cerr << warning << "RiColorSamples not supported" << std::endl;
 
1602
    return ;
 
1603
}
 
1604
 
 
1605
 
 
1606
//----------------------------------------------------------------------
 
1607
// RiRelativeDetail
 
1608
// Set the scale used for all subsequent level of detail calculations.
 
1609
//
 
1610
RtVoid  RiRelativeDetail( RtFloat relativedetail )
 
1611
{
 
1612
        Cache_RiRelativeDetail
 
1613
 
 
1614
        Validate_RiRelativeDetail
 
1615
 
 
1616
    if ( relativedetail < 0.0f )
 
1617
    {
 
1618
        std::cerr << error << "RiRelativeDetail < 0.0" << std::endl;
 
1619
    }
 
1620
    else
 
1621
    {
 
1622
        QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "RelativeDetail" ) [ 0 ] = relativedetail;
 
1623
    }
 
1624
    return ;
 
1625
}
 
1626
 
 
1627
 
 
1628
//----------------------------------------------------------------------
 
1629
// RiOption
 
1630
// Specify system specific option.
 
1631
//
 
1632
RtVoid  RiOption( RtToken name, ... )
 
1633
{
 
1634
    va_list     pArgs;
 
1635
    va_start( pArgs, name );
 
1636
 
 
1637
    std::vector<RtToken> aTokens;
 
1638
    std::vector<RtPointer> aValues;
 
1639
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
1640
 
 
1641
    RiOptionV( name, count, &aTokens[0], &aValues[0] );
 
1642
}
 
1643
 
 
1644
 
 
1645
//----------------------------------------------------------------------
 
1646
// RiOptionV
 
1647
// List based version of above.
 
1648
//
 
1649
RtVoid  RiOptionV( RtToken name, PARAMETERLIST )
 
1650
{
 
1651
        Cache_RiOption
 
1652
 
 
1653
        Validate_RiOption
 
1654
 
 
1655
    // Find the parameter on the current options.
 
1656
    CqNamedParameterList * pOpt = QGetRenderContext() ->optCurrent().pOptionWrite( name ).get();
 
1657
 
 
1658
    RtInt i;
 
1659
    for ( i = 0; i < count; ++i )
 
1660
    {
 
1661
        RtToken token = tokens[ i ];
 
1662
        RtPointer       value = values[ i ];
 
1663
 
 
1664
        // Search for the parameter in the declarations.
 
1665
        // Note Options can only be uniform.
 
1666
        SqParameterDeclaration Decl;
 
1667
        try
 
1668
        {
 
1669
            Decl = QGetRenderContext()->FindParameterDecl( token );
 
1670
        }
 
1671
        catch( XqException e )
 
1672
        {
 
1673
            std::cerr << error << e.strReason().c_str() << std::endl;
 
1674
            continue;
 
1675
        }
 
1676
        TqInt Type = Decl.m_Type;
 
1677
        TqInt Class = Decl.m_Class;
 
1678
        TqBool bArray = Decl.m_Count > 1;
 
1679
        CqParameter* pParam = pOpt->pParameter( Decl.m_strName.c_str() );
 
1680
        if ( pParam == 0 )
 
1681
        {
 
1682
            if ( Decl.m_strName != "" && ( Decl.m_Class ) == class_uniform )
 
1683
            {
 
1684
                pParam = Decl.m_pCreate( Decl.m_strName.c_str(), Decl.m_Count );
 
1685
                pOpt->AddParameter( pParam );
 
1686
            }
 
1687
            else
 
1688
            {
 
1689
                if ( Decl.m_strName == "" )
 
1690
                    std::cerr << warning << "Unrecognised declaration : " << token << std::endl;
 
1691
                else
 
1692
                    std::cerr << warning << "Options can only be uniform [" << token << "]" << std::endl;
 
1693
                return ;
 
1694
            }
 
1695
        }
 
1696
        else
 
1697
        {
 
1698
            Type = pParam->Type();
 
1699
            Class = pParam->Class();
 
1700
            bArray = pParam->Count() > 0;
 
1701
        }
 
1702
 
 
1703
        switch ( Type )
 
1704
        {
 
1705
        case type_float:
 
1706
            {
 
1707
                RtFloat * pf = reinterpret_cast<RtFloat*>( value );
 
1708
                if ( bArray )
 
1709
                {
 
1710
                    RtInt j;
 
1711
                    for ( j = 0; j < pParam->Count(); ++j )
 
1712
                        static_cast<CqParameterTypedUniformArray<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ j ] = pf[ j ];
 
1713
                }
 
1714
                else
 
1715
                    static_cast<CqParameterTypedUniform<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pf[ 0 ];
 
1716
            }
 
1717
            break;
 
1718
 
 
1719
        case type_integer:
 
1720
            {
 
1721
                RtInt* pi = reinterpret_cast<RtInt*>( value );
 
1722
                if ( bArray )
 
1723
                {
 
1724
                    RtInt j;
 
1725
                    for ( j = 0; j < pParam->Count(); ++j )
 
1726
                        static_cast<CqParameterTypedUniformArray<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ j ] = pi[ j ];
 
1727
                }
 
1728
                else
 
1729
                    static_cast<CqParameterTypedUniform<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pi[ 0 ];
 
1730
            }
 
1731
            break;
 
1732
 
 
1733
        case type_string:
 
1734
            {
 
1735
                char** ps = reinterpret_cast<char**>( value );
 
1736
                if ( bArray )
 
1737
                {
 
1738
                    RtInt j;
 
1739
                    for ( j = 0; j < pParam->Count(); ++j )
 
1740
                    {
 
1741
                        CqString str( "" );
 
1742
                        if ( strcmp( name, "searchpath" ) == 0 )
 
1743
                        {
 
1744
                            // Get the old value for use in escape replacement
 
1745
                            CqString str_old = static_cast<CqParameterTypedUniform<CqString, type_string, CqString>*>( pParam ) ->pValue() [ 0 ];
 
1746
                            // Build the string, checking for & character and replace with old string.
 
1747
                            unsigned int strt = 0;
 
1748
                            unsigned int len = 0;
 
1749
                            while ( 1 )
 
1750
                            {
 
1751
                                if ( ( len = strcspn( &ps[ j ][ strt ], "&" ) ) < strlen( &ps[ j ][ strt ] ) )
 
1752
                                {
 
1753
                                    str += CqString( ps[ j ] ).substr( strt, len );
 
1754
                                    str += str_old;
 
1755
                                    strt += len + 1;
 
1756
                                }
 
1757
                                else
 
1758
                                {
 
1759
                                    str += CqString( ps[ j ] ).substr( strt );
 
1760
                                    break;
 
1761
                                }
 
1762
                            }
 
1763
                        }
 
1764
                        else
 
1765
                            str = CqString( ps[ j ] );
 
1766
 
 
1767
                        static_cast<CqParameterTypedUniformArray<CqString, type_string, CqString>*>( pParam ) ->pValue() [ j ] = str;
 
1768
                    }
 
1769
                }
 
1770
                else
 
1771
                {
 
1772
                    CqString str( "" );
 
1773
                    if ( strcmp( name, "searchpath" ) == 0 )
 
1774
                    {
 
1775
                        // Get the old value for use in escape replacement
 
1776
                        CqString str_old = static_cast<CqParameterTypedUniform<CqString, type_string, CqString>*>( pParam ) ->pValue() [ 0 ];
 
1777
                        // Build the string, checking for & character and replace with old string.
 
1778
                        unsigned int strt = 0;
 
1779
                        unsigned int len = 0;
 
1780
                        while ( 1 )
 
1781
                        {
 
1782
                            if ( ( len = strcspn( &ps[ 0 ][ strt ], "&" ) ) < strlen( &ps[ 0 ][ strt ] ) )
 
1783
                            {
 
1784
                                str += CqString( ps[ 0 ] ).substr( strt, len );
 
1785
                                str += str_old;
 
1786
                                strt += len + 1;
 
1787
                            }
 
1788
                            else
 
1789
                            {
 
1790
                                str += CqString( ps[ 0 ] ).substr( strt );
 
1791
                                break;
 
1792
                            }
 
1793
                        }
 
1794
                    }
 
1795
                    else
 
1796
                        str = CqString( ps[ 0 ] );
 
1797
 
 
1798
                    static_cast<CqParameterTyped<CqString, CqString>*>( pParam ) ->pValue() [ 0 ] = str;
 
1799
                }
 
1800
            }
 
1801
            break;
 
1802
            // TODO: Rest of parameter types.
 
1803
        }
 
1804
    }
 
1805
    return ;
 
1806
}
 
1807
 
 
1808
 
 
1809
//----------------------------------------------------------------------
 
1810
// RiAttributeBegin
 
1811
// Begin a ne attribute definition, pushes the current attributes.
 
1812
//
 
1813
RtVoid  RiAttributeBegin()
 
1814
{
 
1815
        Cache_RiAttributeBegin
 
1816
 
 
1817
        Validate_RiAttributeBegin
 
1818
 
 
1819
    QGetRenderContext() ->BeginAttributeModeBlock();
 
1820
 
 
1821
    return ;
 
1822
}
 
1823
 
 
1824
 
 
1825
//----------------------------------------------------------------------
 
1826
// RiAttributeEnd
 
1827
// End the current attribute defintion, pops the previous attributes.
 
1828
//
 
1829
RtVoid  RiAttributeEnd()
 
1830
{
 
1831
        Cache_RiAttributeEnd
 
1832
 
 
1833
        Validate_RiAttributeEnd
 
1834
 
 
1835
    QGetRenderContext() ->EndAttributeModeBlock();
 
1836
 
 
1837
    return ;
 
1838
}
 
1839
 
 
1840
 
 
1841
//----------------------------------------------------------------------
 
1842
// RiColor
 
1843
//      Set the current color for use by the geometric primitives.
 
1844
//
 
1845
RtVoid  RiColor( RtColor Cq )
 
1846
{
 
1847
        Cache_RiColor
 
1848
 
 
1849
        Validate_RiColor
 
1850
 
 
1851
    QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Color" ) [ 0 ] = CqColor( Cq );
 
1852
    QGetRenderContext() ->AdvanceTime();
 
1853
    return ;
 
1854
}
 
1855
 
 
1856
 
 
1857
//----------------------------------------------------------------------
 
1858
// RiOpacity
 
1859
// Set the current opacity, for use by the geometric primitives.
 
1860
//
 
1861
RtVoid  RiOpacity( RtColor Os )
 
1862
{
 
1863
        Cache_RiOpacity
 
1864
 
 
1865
        Validate_RiOpacity
 
1866
 
 
1867
    QGetRenderContext() ->pattrWriteCurrent() ->GetColorAttributeWrite( "System", "Opacity" ) [ 0 ] = CqColor( Os );
 
1868
    QGetRenderContext() ->AdvanceTime();
 
1869
    return ;
 
1870
}
 
1871
 
 
1872
 
 
1873
//----------------------------------------------------------------------
 
1874
// RiTextureCoordinates
 
1875
// Set the current texture coordinates used by the parametric geometric primitives.
 
1876
//
 
1877
RtVoid  RiTextureCoordinates( RtFloat s1, RtFloat t1,
 
1878
                             RtFloat s2, RtFloat t2,
 
1879
                             RtFloat s3, RtFloat t3,
 
1880
                             RtFloat s4, RtFloat t4 )
 
1881
{
 
1882
        Cache_RiTextureCoordinates
 
1883
 
 
1884
        Validate_RiTextureCoordinates
 
1885
 
 
1886
    TqFloat * pTC = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "TextureCoordinates" );
 
1887
 
 
1888
    assert( NULL != pTC );
 
1889
 
 
1890
    pTC[ 0 ] = s1;
 
1891
    pTC[ 1 ] = t1;
 
1892
    pTC[ 2 ] = s2;
 
1893
    pTC[ 3 ] = t2;
 
1894
    pTC[ 4 ] = s3;
 
1895
    pTC[ 5 ] = t3;
 
1896
    pTC[ 6 ] = s4;
 
1897
    pTC[ 7 ] = t4;
 
1898
    QGetRenderContext() ->AdvanceTime();
 
1899
 
 
1900
    return ;
 
1901
}
 
1902
 
 
1903
 
 
1904
//----------------------------------------------------------------------
 
1905
// RiLightSource
 
1906
// Create a new light source at the current transformation.
 
1907
//
 
1908
RtLightHandle   RiLightSource( RtToken name, ... )
 
1909
{
 
1910
    va_list     pArgs;
 
1911
    va_start( pArgs, name );
 
1912
 
 
1913
    std::vector<RtToken> aTokens;
 
1914
    std::vector<RtPointer> aValues;
 
1915
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
1916
 
 
1917
    return ( RiLightSourceV( name, count, &aTokens[0], &aValues[0] ) );
 
1918
}
 
1919
 
 
1920
 
 
1921
//----------------------------------------------------------------------
 
1922
// RiLightSourceV
 
1923
// List based version of above.
 
1924
//
 
1925
RtLightHandle   RiLightSourceV( RtToken name, PARAMETERLIST )
 
1926
{
 
1927
        Cache_RiLightSource
 
1928
 
 
1929
        Validate_RiLightSource
 
1930
 
 
1931
    // Find the lightsource shader.
 
1932
    IqShader * pShader = static_cast<CqShader*>( QGetRenderContext() ->CreateShader( name, Type_Lightsource ) );
 
1933
 
 
1934
    // TODO: Report error.
 
1935
    if ( pShader == 0 ) return ( 0 );
 
1936
 
 
1937
    pShader->matCurrent() = QGetRenderContext() ->ptransCurrent()->matObjectToWorld(QGetRenderContext()->Time());
 
1938
    CqLightsource* pNew = new CqLightsource( pShader, RI_TRUE );
 
1939
 
 
1940
    // Execute the intiialisation code here, as we now have our shader context complete.
 
1941
    pShader->PrepareDefArgs();
 
1942
 
 
1943
    if ( pNew != 0 )
 
1944
    {
 
1945
        RtInt i;
 
1946
        for ( i = 0; i < count; ++i )
 
1947
        {
 
1948
            RtToken     token = tokens[ i ];
 
1949
            RtPointer   value = values[ i ];
 
1950
 
 
1951
            SetShaderArgument( pShader, token, static_cast<TqPchar>( value ) );
 
1952
        }
 
1953
        QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( pNew );
 
1954
 
 
1955
        // Add it as a Context light as well in case we are in a context that manages it's own lights.
 
1956
        QGetRenderContext() ->pconCurrent() ->AddContextLightSource( pNew );
 
1957
        return ( reinterpret_cast<RtLightHandle>( pNew ) );
 
1958
    }
 
1959
    return ( 0 );
 
1960
}
 
1961
 
 
1962
 
 
1963
//----------------------------------------------------------------------
 
1964
// RiAreaLightSource
 
1965
// Create a new area light source at the current transformation, all
 
1966
// geometric primitives until the next RiAttributeEnd, become part of this
 
1967
// area light source.
 
1968
//
 
1969
RtLightHandle   RiAreaLightSource( RtToken name, ... )
 
1970
{
 
1971
    va_list     pArgs;
 
1972
    va_start( pArgs, name );
 
1973
 
 
1974
    std::vector<RtToken> aTokens;
 
1975
    std::vector<RtPointer> aValues;
 
1976
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
1977
 
 
1978
    return ( RiAreaLightSourceV( name, count, &aTokens[0], &aValues[0] ) );
 
1979
}
 
1980
 
 
1981
 
 
1982
//----------------------------------------------------------------------
 
1983
// RiAreaLightSourceV
 
1984
// List based version of above.
 
1985
//
 
1986
RtLightHandle   RiAreaLightSourceV( RtToken name, PARAMETERLIST )
 
1987
{
 
1988
        Cache_RiAreaLightSource
 
1989
 
 
1990
        Validate_RiAreaLightSource
 
1991
 
 
1992
    std::cerr << warning << "RiAreaLightSource not supported, will produce a point light" << std::endl;
 
1993
 
 
1994
    return ( RiLightSourceV( name, count, tokens, values ) );
 
1995
}
 
1996
 
 
1997
 
 
1998
//----------------------------------------------------------------------
 
1999
// RiIlluminate
 
2000
// Set the current status of the specified light source.
 
2001
//
 
2002
RtVoid  RiIlluminate( RtLightHandle light, RtBoolean onoff )
 
2003
{
 
2004
        Cache_RiIlluminate
 
2005
 
 
2006
        Validate_RiIlluminate
 
2007
 
 
2008
    // Check if we are turning the light on or off.
 
2009
    if ( light == NULL ) return ;
 
2010
    if ( onoff )
 
2011
        QGetRenderContext() ->pattrWriteCurrent() ->AddLightsource( reinterpret_cast<CqLightsource*>( light ) );
 
2012
    else
 
2013
        QGetRenderContext() ->pattrWriteCurrent() ->RemoveLightsource( reinterpret_cast<CqLightsource*>( light ) );
 
2014
    return ;
 
2015
}
 
2016
 
 
2017
 
 
2018
//----------------------------------------------------------------------
 
2019
// RiSurface
 
2020
// Set the current surface shader, used by geometric primitives.
 
2021
//
 
2022
RtVoid  RiSurface( RtToken name, ... )
 
2023
{
 
2024
    va_list     pArgs;
 
2025
    va_start( pArgs, name );
 
2026
 
 
2027
    std::vector<RtToken> aTokens;
 
2028
    std::vector<RtPointer> aValues;
 
2029
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
2030
 
 
2031
    RiSurfaceV( name, count, &aTokens[0], &aValues[0] );
 
2032
}
 
2033
 
 
2034
 
 
2035
//----------------------------------------------------------------------
 
2036
// RiSurfaceV
 
2037
// List based version of above.
 
2038
//
 
2039
RtVoid  RiSurfaceV( RtToken name, PARAMETERLIST )
 
2040
{
 
2041
        Cache_RiSurface
 
2042
 
 
2043
        Validate_RiSurface
 
2044
 
 
2045
    // Find the shader.
 
2046
    IqShader * pshadSurface = QGetRenderContext() ->CreateShader( name, Type_Surface );
 
2047
 
 
2048
    if ( pshadSurface != 0 )
 
2049
    {
 
2050
        TqFloat time = QGetRenderContext()->Time();
 
2051
                pshadSurface->matCurrent() = QGetRenderContext() ->matCurrent(time);
 
2052
        // Execute the intiialisation code here, as we now have our shader context complete.
 
2053
        pshadSurface->PrepareDefArgs();
 
2054
        RtInt i;
 
2055
        for ( i = 0; i < count; ++i )
 
2056
        {
 
2057
            RtToken     token = tokens[ i ];
 
2058
            RtPointer   value = values[ i ];
 
2059
 
 
2060
            SetShaderArgument( pshadSurface, token, static_cast<TqPchar>( value ) );
 
2061
        }
 
2062
        QGetRenderContext() ->pattrWriteCurrent() ->SetpshadSurface( pshadSurface, QGetRenderContext() ->Time() );
 
2063
    }
 
2064
    QGetRenderContext() ->AdvanceTime();
 
2065
    return ;
 
2066
}
 
2067
 
 
2068
 
 
2069
//----------------------------------------------------------------------
 
2070
// RiAtmosphere
 
2071
// Set the current atrmospheric shader.
 
2072
//
 
2073
RtVoid  RiAtmosphere( RtToken name, ... )
 
2074
{
 
2075
    va_list     pArgs;
 
2076
    va_start( pArgs, name );
 
2077
 
 
2078
    std::vector<RtToken> aTokens;
 
2079
    std::vector<RtPointer> aValues;
 
2080
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
2081
 
 
2082
    RiAtmosphereV( name, count, &aTokens[0], &aValues[0] );
 
2083
}
 
2084
 
 
2085
 
 
2086
//----------------------------------------------------------------------
 
2087
// RiAtmosphereV
 
2088
// List based version of above.
 
2089
//
 
2090
RtVoid  RiAtmosphereV( RtToken name, PARAMETERLIST )
 
2091
{
 
2092
        Cache_RiAtmosphere
 
2093
 
 
2094
        Validate_RiAtmosphere
 
2095
 
 
2096
    // Find the shader.
 
2097
    IqShader * pshadAtmosphere = QGetRenderContext() ->CreateShader( name, Type_Volume );
 
2098
 
 
2099
    if ( pshadAtmosphere != 0 )
 
2100
    {
 
2101
        pshadAtmosphere->matCurrent() = QGetRenderContext() ->matCurrent(QGetRenderContext()->Time());
 
2102
        // Execute the intiialisation code here, as we now have our shader context complete.
 
2103
        pshadAtmosphere->PrepareDefArgs();
 
2104
        RtInt i;
 
2105
        for ( i = 0; i < count; ++i )
 
2106
        {
 
2107
            RtToken     token = tokens[ i ];
 
2108
            RtPointer   value = values[ i ];
 
2109
 
 
2110
            SetShaderArgument( pshadAtmosphere, token, static_cast<TqPchar>( value ) );
 
2111
        }
 
2112
    }
 
2113
 
 
2114
    QGetRenderContext() ->pattrWriteCurrent() ->SetpshadAtmosphere( pshadAtmosphere, QGetRenderContext() ->Time() );
 
2115
    QGetRenderContext() ->AdvanceTime();
 
2116
    return ;
 
2117
}
 
2118
 
 
2119
 
 
2120
//----------------------------------------------------------------------
 
2121
// RiInterior
 
2122
// Set the current interior volumetric shader.
 
2123
//
 
2124
RtVoid  RiInterior( RtToken name, ... )
 
2125
{
 
2126
    std::cerr << warning << "RiInterior not supported" << std::endl;
 
2127
    return ;
 
2128
}
 
2129
 
 
2130
 
 
2131
//----------------------------------------------------------------------
 
2132
// RiInteriorV
 
2133
// List based version of above.
 
2134
//
 
2135
RtVoid  RiInteriorV( RtToken name, PARAMETERLIST )
 
2136
{
 
2137
        Cache_RiInterior
 
2138
 
 
2139
        Validate_RiInterior
 
2140
 
 
2141
    std::cerr << warning << "RiInterior not supported" << std::endl;
 
2142
    return ;
 
2143
}
 
2144
 
 
2145
 
 
2146
//----------------------------------------------------------------------
 
2147
// RiExterior
 
2148
// Set the current exterior volumetric shader.
 
2149
//
 
2150
RtVoid  RiExterior( RtToken name, ... )
 
2151
{
 
2152
    std::cerr << warning << "RiExterior not supported" << std::endl;
 
2153
    return ;
 
2154
}
 
2155
 
 
2156
 
 
2157
//----------------------------------------------------------------------
 
2158
// RiExteriorV
 
2159
// List based version of above.
 
2160
//
 
2161
RtVoid  RiExteriorV( RtToken name, PARAMETERLIST )
 
2162
{
 
2163
        Cache_RiExterior
 
2164
 
 
2165
        Validate_RiExterior
 
2166
 
 
2167
    std::cerr << warning << "ExInterior not supported" << std::endl;
 
2168
    return ;
 
2169
}
 
2170
 
 
2171
 
 
2172
//----------------------------------------------------------------------
 
2173
// RiShadingRate
 
2174
// Specify the size of the shading area in pixels.
 
2175
//
 
2176
RtVoid  RiShadingRate( RtFloat size )
 
2177
{
 
2178
        Cache_RiShadingRate
 
2179
 
 
2180
        Validate_RiShadingRate
 
2181
 
 
2182
    CqLogRangeCheckCallback rc;
 
2183
 
 
2184
    bool valid = true;
 
2185
 
 
2186
    rc.set( "size" );
 
2187
    if( !CheckMinMax( size, 0.0f, RI_INFINITY, &rc ) )
 
2188
    {
 
2189
        valid = false;
 
2190
    }
 
2191
 
 
2192
    if( !valid )
 
2193
    {
 
2194
        std::cerr << warning << "Invalid ShadingRate, ShadingRate set to 1" << std::endl;
 
2195
        size = 1;
 
2196
    }
 
2197
 
 
2198
    QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRate" ) [ 0 ] = size;
 
2199
    QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "ShadingRateSqrt" ) [ 0 ] = sqrt( size );
 
2200
    QGetRenderContext() ->AdvanceTime();
 
2201
 
 
2202
    return ;
 
2203
}
 
2204
 
 
2205
 
 
2206
//----------------------------------------------------------------------
 
2207
// RiShadingInterpolation
 
2208
// Specify the method of shading interpolation.
 
2209
//
 
2210
RtVoid  RiShadingInterpolation( RtToken type )
 
2211
{
 
2212
        Cache_RiShadingInterpolation
 
2213
 
 
2214
        Validate_RiShadingInterpolation
 
2215
 
 
2216
    if ( strcmp( type, RI_CONSTANT ) == 0 )
 
2217
        QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingConstant;
 
2218
    else
 
2219
        if ( strcmp( type, RI_SMOOTH ) == 0 )
 
2220
            QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "ShadingInterpolation" ) [ 0 ] = ShadingSmooth;
 
2221
        else
 
2222
            std::cerr << error << "RiShadingInterpolation unrecognised value \"" << type << "\"" << std::endl;
 
2223
 
 
2224
    QGetRenderContext() ->AdvanceTime();
 
2225
    return ;
 
2226
}
 
2227
 
 
2228
 
 
2229
//----------------------------------------------------------------------
 
2230
// RiMatte
 
2231
// Set the matte state of subsequent geometric primitives.
 
2232
//
 
2233
RtVoid  RiMatte( RtBoolean onoff )
 
2234
{
 
2235
        Cache_RiMatte
 
2236
 
 
2237
        Validate_RiMatte
 
2238
 
 
2239
    QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Matte" ) [ 0 ] = onoff != 0;
 
2240
    QGetRenderContext() ->AdvanceTime();
 
2241
    return ;
 
2242
}
 
2243
 
 
2244
 
 
2245
//----------------------------------------------------------------------
 
2246
// RiBound
 
2247
// Set the bounding cube of the current primitives.
 
2248
//
 
2249
RtVoid  RiBound( RtBound bound )
 
2250
{
 
2251
        Cache_RiBound
 
2252
 
 
2253
        Validate_RiBound
 
2254
 
 
2255
    // TODO: Need to add a "Bound" attribute here, and fill it in.
 
2256
    QGetRenderContext() ->AdvanceTime();
 
2257
 
 
2258
    return ;
 
2259
}
 
2260
 
 
2261
 
 
2262
//----------------------------------------------------------------------
 
2263
// RiDetail
 
2264
// Set the current bounding cube for use by level of detail calculation.
 
2265
//
 
2266
RtVoid  RiDetail( RtBound bound )
 
2267
{
 
2268
        Cache_RiDetail
 
2269
 
 
2270
        Validate_RiDetail
 
2271
 
 
2272
    CqBound Bound( bound );
 
2273
 
 
2274
    Bound.Transform( QGetRenderContext() ->matSpaceToSpace( "object", "raster", CqMatrix(), QGetRenderContext() ->matCurrent( QGetRenderContext() ->Time() ), QGetRenderContext()->Time() ) );
 
2275
 
 
2276
    TqFloat ruler = fabs( MAX( Bound.vecMax().x() - Bound.vecMin().x(), Bound.vecMax().y() - Bound.vecMin().y() ) );
 
2277
 
 
2278
    ruler *= QGetRenderContext() ->optCurrent().GetFloatOption( "System", "RelativeDetail" ) [ 0 ];
 
2279
 
 
2280
    QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailRulerSize" ) [ 0 ] = ruler;
 
2281
    QGetRenderContext() ->AdvanceTime();
 
2282
    return ;
 
2283
}
 
2284
 
 
2285
 
 
2286
//----------------------------------------------------------------------
 
2287
// RiDetailRange
 
2288
// Set the visible range of any subsequent geometric primitives.
 
2289
//
 
2290
RtVoid  RiDetailRange( RtFloat offlow, RtFloat onlow, RtFloat onhigh, RtFloat offhigh )
 
2291
{
 
2292
        Cache_RiDetailRange
 
2293
 
 
2294
        Validate_RiDetailRange
 
2295
 
 
2296
    if ( offlow > onlow || onhigh > offhigh )
 
2297
    {
 
2298
        std::cerr << error << "RiDetailRange invalid range" << std::endl;
 
2299
        return ;
 
2300
    }
 
2301
 
 
2302
    TqFloat ruler = QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailRulerSize" ) [ 0 ];
 
2303
 
 
2304
    TqFloat minImportance;
 
2305
    if ( onlow == offlow )
 
2306
    {
 
2307
        minImportance = ruler < onlow ? 1.0f : 0.0f;
 
2308
    }
 
2309
    else
 
2310
    {
 
2311
        minImportance = CLAMP( ( onlow - ruler ) / ( onlow - offlow ), 0, 1 );
 
2312
    }
 
2313
 
 
2314
    TqFloat maxImportance;
 
2315
    if ( onhigh == offhigh )
 
2316
    {
 
2317
        maxImportance = ruler < onhigh ? 1.0f : 0.0f;
 
2318
    }
 
2319
    else
 
2320
    {
 
2321
        maxImportance = CLAMP( ( offhigh - ruler ) / ( offhigh - onhigh ), 0, 1 );
 
2322
    }
 
2323
 
 
2324
    if ( minImportance >= maxImportance )
 
2325
    {
 
2326
        // Geometry is culled.  Use the special value -1 to represent this.
 
2327
        minImportance = maxImportance = -1.0f;
 
2328
    }
 
2329
 
 
2330
    QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailBounds" ) [ 0 ] = minImportance;
 
2331
    QGetRenderContext() ->pattrWriteCurrent() ->GetFloatAttributeWrite( "System", "LevelOfDetailBounds" ) [ 1 ] = maxImportance;
 
2332
    QGetRenderContext() ->AdvanceTime();
 
2333
    return ;
 
2334
}
 
2335
 
 
2336
 
 
2337
//----------------------------------------------------------------------
 
2338
// RiGeometricApproximation
 
2339
// Specify any parameters used by approximation functions during rendering.
 
2340
//
 
2341
RtVoid  RiGeometricApproximation( RtToken type, RtFloat value )
 
2342
{
 
2343
        Cache_RiGeometricApproximation
 
2344
 
 
2345
        Validate_RiGeometricApproximation
 
2346
 
 
2347
    std::cerr << warning << "RiGeometricApproximation not supported" << std::endl;
 
2348
    return ;
 
2349
}
 
2350
 
 
2351
 
 
2352
//----------------------------------------------------------------------
 
2353
// RiOrientation
 
2354
// Set the handedness of any subsequent geometric primitives.
 
2355
//
 
2356
RtVoid  RiOrientation( RtToken orientation )
 
2357
{
 
2358
        Cache_RiOrientation
 
2359
 
 
2360
        Validate_RiOrientation
 
2361
 
 
2362
    if ( orientation != 0 )
 
2363
    {
 
2364
        if ( strstr( orientation, RI_RH ) != 0 )
 
2365
            QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = ( QGetRenderContext() ->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) ) ? 0 : 1;
 
2366
        if ( strstr( orientation, RI_LH ) != 0 )
 
2367
            QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = ( QGetRenderContext() ->ptransCurrent()->GetHandedness(QGetRenderContext()->Time()) ) ? 1 : 0;
 
2368
        if ( strstr( orientation, RI_INSIDE ) != 0 )
 
2369
            QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
 
2370
        if ( strstr( orientation, RI_OUTSIDE ) != 0 )
 
2371
            QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
 
2372
    }
 
2373
    QGetRenderContext() ->AdvanceTime();
 
2374
    return ;
 
2375
}
 
2376
 
 
2377
 
 
2378
//----------------------------------------------------------------------
 
2379
// RiReverseOrientation
 
2380
// Reverse the handedness of any subsequent geometric primitives.
 
2381
//
 
2382
RtVoid  RiReverseOrientation()
 
2383
{
 
2384
        Cache_RiReverseOrientation
 
2385
 
 
2386
        Validate_RiReverseOrientation
 
2387
 
 
2388
    QGetRenderContext() ->pattrWriteCurrent() ->FlipeOrientation( QGetRenderContext() ->Time() );
 
2389
    QGetRenderContext() ->AdvanceTime();
 
2390
    return ;
 
2391
}
 
2392
 
 
2393
 
 
2394
//----------------------------------------------------------------------
 
2395
// RiSides
 
2396
// Set the number of visibles sides for any subsequent geometric primitives.
 
2397
//
 
2398
RtVoid  RiSides( RtInt nsides )
 
2399
{
 
2400
        Cache_RiSides
 
2401
 
 
2402
        Validate_RiSides
 
2403
 
 
2404
    QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "Sides" ) [ 0 ] = nsides;
 
2405
    QGetRenderContext() ->AdvanceTime();
 
2406
 
 
2407
    return ;
 
2408
}
 
2409
 
 
2410
 
 
2411
//----------------------------------------------------------------------
 
2412
// RiIdentity
 
2413
// Set the current transformation to the identity matrix.
 
2414
//
 
2415
RtVoid  RiIdentity()
 
2416
{
 
2417
        Cache_RiIdentity
 
2418
 
 
2419
        Validate_RiIdentity
 
2420
 
 
2421
    QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix() );
 
2422
 
 
2423
    QGetRenderContext() ->AdvanceTime();
 
2424
    return ;
 
2425
}
 
2426
 
 
2427
 
 
2428
//----------------------------------------------------------------------
 
2429
// Set the current transformation to the specified matrix.
 
2430
//
 
2431
RtVoid  RiTransform( RtMatrix transform )
 
2432
{
 
2433
        Cache_RiTransform
 
2434
 
 
2435
        Validate_RiTransform
 
2436
 
 
2437
    CqMatrix matTrans( transform );
 
2438
//    if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
 
2439
//        QGetRenderContext() ->ptransWriteCurrent() ->FlipHandedness( QGetRenderContext() ->Time() );
 
2440
 
 
2441
    QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), CqMatrix( transform ) );
 
2442
    QGetRenderContext() ->AdvanceTime();
 
2443
 
 
2444
    return ;
 
2445
}
 
2446
 
 
2447
 
 
2448
//----------------------------------------------------------------------
 
2449
// RiConcatTransform
 
2450
// Concatenate the specified matrix into the current transformation matrix.
 
2451
//
 
2452
RtVoid  RiConcatTransform( RtMatrix transform )
 
2453
{
 
2454
        Cache_RiConcatTransform
 
2455
 
 
2456
        Validate_RiConcatTransform
 
2457
 
 
2458
    // Check if this transformation results in a change in orientation.
 
2459
    CqMatrix matTrans( transform );
 
2460
//    if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
 
2461
//        QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
 
2462
 
 
2463
    QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), CqMatrix( transform ) );
 
2464
    QGetRenderContext() ->AdvanceTime();
 
2465
    return ;
 
2466
}
 
2467
 
 
2468
 
 
2469
//----------------------------------------------------------------------
 
2470
// RiPerspective
 
2471
// Concatenate a perspective transformation into the current transformation.
 
2472
//
 
2473
RtVoid  RiPerspective( RtFloat fov )
 
2474
{
 
2475
        Cache_RiPerspective
 
2476
 
 
2477
        Validate_RiPerspective
 
2478
 
 
2479
    if ( fov <= 0 )
 
2480
    {
 
2481
        std::cerr << error << "RiPerspective invalid FOV" << std::endl;
 
2482
        return ;
 
2483
    }
 
2484
 
 
2485
    fov = tan( RAD( fov / 2 ) );
 
2486
 
 
2487
    // This matches PRMan 3.9 in testing, but not BMRT 2.6's rgl and rendrib.
 
2488
    CqMatrix    matP( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, fov, fov, 0, 0, -fov, 0 );
 
2489
 
 
2490
    // Check if this transformation results in a change in orientation.
 
2491
//    if ( matP.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
 
2492
//        QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
 
2493
 
 
2494
    QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matP );
 
2495
    QGetRenderContext() ->AdvanceTime();
 
2496
 
 
2497
    return ;
 
2498
}
 
2499
 
 
2500
 
 
2501
//----------------------------------------------------------------------
 
2502
// RiTranslate
 
2503
// Concatenate a translation into the current transformation.
 
2504
//
 
2505
RtVoid  RiTranslate( RtFloat dx, RtFloat dy, RtFloat dz )
 
2506
{
 
2507
        Cache_RiTranslate
 
2508
 
 
2509
        Validate_RiTranslate
 
2510
 
 
2511
    CqMatrix    matTrans( CqVector3D( dx, dy, dz ) );
 
2512
    // Check if this transformation results in a change in orientation.
 
2513
//    if ( matTrans.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
 
2514
//        QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
 
2515
 
 
2516
    QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matTrans );
 
2517
    QGetRenderContext() ->AdvanceTime();
 
2518
 
 
2519
    return ;
 
2520
}
 
2521
 
 
2522
 
 
2523
//----------------------------------------------------------------------
 
2524
// RiRotate
 
2525
// Concatenate a rotation into the current transformation.
 
2526
//
 
2527
RtVoid  RiRotate( RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz )
 
2528
{
 
2529
        Cache_RiRotate
 
2530
 
 
2531
        Validate_RiRotate
 
2532
 
 
2533
    CqMatrix    matRot( RAD( angle ), CqVector4D( dx, dy, dz ) );
 
2534
    // Check if this transformation results in a change in orientation.
 
2535
//    if ( matRot.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
 
2536
//        QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
 
2537
 
 
2538
    QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matRot );
 
2539
    QGetRenderContext() ->AdvanceTime();
 
2540
    return ;
 
2541
}
 
2542
 
 
2543
 
 
2544
//----------------------------------------------------------------------
 
2545
// RiScale
 
2546
// Concatenate a scale into the current transformation.
 
2547
//
 
2548
RtVoid  RiScale( RtFloat sx, RtFloat sy, RtFloat sz )
 
2549
{
 
2550
        Cache_RiScale
 
2551
 
 
2552
        Validate_RiScale
 
2553
 
 
2554
    CqMatrix    matScale( sx, sy, sz );
 
2555
    // Check if this transformation results in a change in orientation.
 
2556
//    if ( matScale.Determinant() < 0 && ( QGetRenderContext()->pconCurrent()->Type() != Motion || QGetRenderContext()->pconCurrent()->TimeIndex() == 0 ) )
 
2557
//        QGetRenderContext() ->pattrWriteCurrent() ->FlipeCoordsysOrientation( QGetRenderContext() ->Time() );
 
2558
 
 
2559
    QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matScale );
 
2560
    QGetRenderContext() ->AdvanceTime();
 
2561
    return ;
 
2562
}
 
2563
 
 
2564
 
 
2565
//----------------------------------------------------------------------
 
2566
// RiSkew
 
2567
// Concatenate a skew into the current transformation.
 
2568
//
 
2569
RtVoid  RiSkew( RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1,
 
2570
               RtFloat dx2, RtFloat dy2, RtFloat dz2 )
 
2571
{
 
2572
        Cache_RiSkew
 
2573
 
 
2574
        Validate_RiSkew
 
2575
 
 
2576
    CqMatrix    matSkew( RAD( angle ), dx1, dy1, dz1, dx2, dy2, dz2 );
 
2577
 
 
2578
    // This transformation can not change orientation.
 
2579
 
 
2580
    QGetRenderContext() ->ptransWriteCurrent() ->ConcatCurrentTransform( QGetRenderContext() ->Time(), matSkew );
 
2581
    QGetRenderContext() ->AdvanceTime();
 
2582
    return ;
 
2583
}
 
2584
 
 
2585
 
 
2586
//----------------------------------------------------------------------
 
2587
// RiDeformation
 
2588
// Specify a deformation shader to be included into the current transformation.
 
2589
//
 
2590
RtVoid  RiDeformation( RtToken name, ... )
 
2591
{
 
2592
    std::cerr << warning << "RiDeformation not supported" << std::endl;
 
2593
    return ;
 
2594
}
 
2595
 
 
2596
 
 
2597
//----------------------------------------------------------------------
 
2598
// RiDeformationV
 
2599
// List based version of above.
 
2600
//
 
2601
RtVoid  RiDeformationV( RtToken name, PARAMETERLIST )
 
2602
{
 
2603
        Cache_RiDeformation
 
2604
 
 
2605
        Validate_RiDeformation
 
2606
 
 
2607
    std::cerr << warning << "RiDeformation not supported" << std::endl;
 
2608
    return ;
 
2609
}
 
2610
 
 
2611
 
 
2612
//----------------------------------------------------------------------
 
2613
// RiDisplacement
 
2614
// Specify the current displacement shade used by geometric primitives.
 
2615
//
 
2616
RtVoid  RiDisplacement( RtToken name, ... )
 
2617
{
 
2618
    va_list     pArgs;
 
2619
    va_start( pArgs, name );
 
2620
 
 
2621
    std::vector<RtToken> aTokens;
 
2622
    std::vector<RtPointer> aValues;
 
2623
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
2624
 
 
2625
    RiDisplacementV( name, count, &aTokens[0], &aValues[0] );
 
2626
}
 
2627
 
 
2628
 
 
2629
//----------------------------------------------------------------------
 
2630
// RiDisplacementV
 
2631
// List based version of above.
 
2632
//
 
2633
RtVoid  RiDisplacementV( RtToken name, PARAMETERLIST )
 
2634
{
 
2635
        Cache_RiDisplacement
 
2636
 
 
2637
        Validate_RiDisplacement
 
2638
 
 
2639
    // Find the shader.
 
2640
    IqShader * pshadDisplacement = QGetRenderContext() ->CreateShader( name, Type_Displacement );
 
2641
 
 
2642
    if ( pshadDisplacement != 0 )
 
2643
    {
 
2644
        pshadDisplacement->matCurrent() = QGetRenderContext() ->matCurrent(QGetRenderContext()->Time());
 
2645
        // Execute the intiialisation code here, as we now have our shader context complete.
 
2646
        pshadDisplacement->PrepareDefArgs();
 
2647
        RtInt i;
 
2648
        for ( i = 0; i < count; ++i )
 
2649
        {
 
2650
            RtToken     token = tokens[ i ];
 
2651
            RtPointer   value = values[ i ];
 
2652
 
 
2653
            SetShaderArgument( pshadDisplacement, token, static_cast<TqPchar>( value ) );
 
2654
        }
 
2655
    }
 
2656
 
 
2657
    QGetRenderContext() ->pattrWriteCurrent() ->SetpshadDisplacement( pshadDisplacement, QGetRenderContext() ->Time() );
 
2658
    QGetRenderContext() ->AdvanceTime();
 
2659
    return ;
 
2660
}
 
2661
 
 
2662
 
 
2663
//----------------------------------------------------------------------
 
2664
// RiCoordinateSystem
 
2665
// Save the current coordinate system as the specified name.
 
2666
//
 
2667
RtVoid  RiCoordinateSystem( RtToken space )
 
2668
{
 
2669
        Cache_RiCoordinateSystem
 
2670
 
 
2671
        Validate_RiCoordinateSystem
 
2672
 
 
2673
    // Insert the named coordinate system into the list help on the renderer.
 
2674
    QGetRenderContext() ->SetCoordSystem( space, QGetRenderContext() ->matCurrent( QGetRenderContext() ->Time() ) );
 
2675
    QGetRenderContext() ->AdvanceTime();
 
2676
 
 
2677
    return ;
 
2678
}
 
2679
 
 
2680
 
 
2681
//----------------------------------------------------------------------
 
2682
// ---Additional to spec. v3.1---
 
2683
// RiCoordSysTransform
 
2684
// Replace the current transform with the named space.
 
2685
 
 
2686
RtVoid  RiCoordSysTransform( RtToken space )
 
2687
{
 
2688
        Cache_RiCoordSysTransform
 
2689
 
 
2690
        Validate_RiCoordSysTransform
 
2691
 
 
2692
    // Insert the named coordinate system into the list help on the renderer.
 
2693
    QGetRenderContext() ->ptransWriteCurrent() ->SetTransform( QGetRenderContext() ->Time(), QGetRenderContext() ->matSpaceToSpace( space, "world", CqMatrix(), CqMatrix(), QGetRenderContext()->Time() ) );
 
2694
    QGetRenderContext() ->AdvanceTime();
 
2695
 
 
2696
    return ;
 
2697
}
 
2698
 
 
2699
 
 
2700
//----------------------------------------------------------------------
 
2701
// RiTransformPoints
 
2702
// Transform a list of points from one coordinate system to another.
 
2703
//
 
2704
RtPoint*        RiTransformPoints( RtToken fromspace, RtToken tospace, RtInt npoints, RtPoint points[] )
 
2705
{
 
2706
        Cache_RiTransformPoints
 
2707
 
 
2708
        Validate_RiTransformPoints
 
2709
 
 
2710
    std::cerr << warning << "RiTransformPoints not supported" << std::endl;
 
2711
    return ( 0 );
 
2712
}
 
2713
 
 
2714
 
 
2715
//----------------------------------------------------------------------
 
2716
// RiTransformBegin
 
2717
// Push the current transformation state.
 
2718
//
 
2719
RtVoid  RiTransformBegin()
 
2720
{
 
2721
        Cache_RiTransformBegin
 
2722
 
 
2723
        Validate_RiTransformBegin
 
2724
 
 
2725
    QGetRenderContext() ->BeginTransformModeBlock();
 
2726
 
 
2727
    return ;
 
2728
}
 
2729
 
 
2730
 
 
2731
//----------------------------------------------------------------------
 
2732
// RiTransformEnd
 
2733
// Pop the previous transformation state.
 
2734
//
 
2735
RtVoid  RiTransformEnd()
 
2736
{
 
2737
        Cache_RiTransformEnd
 
2738
 
 
2739
        Validate_RiTransformEnd
 
2740
 
 
2741
    QGetRenderContext() ->EndTransformModeBlock();
 
2742
 
 
2743
    return ;
 
2744
}
 
2745
 
 
2746
 
 
2747
//----------------------------------------------------------------------
 
2748
// RiAttribute
 
2749
// Set a system specific attribute.
 
2750
//
 
2751
RtVoid  RiAttribute( RtToken name, ... )
 
2752
{
 
2753
    va_list     pArgs;
 
2754
    va_start( pArgs, name );
 
2755
 
 
2756
    std::vector<RtToken> aTokens;
 
2757
    std::vector<RtPointer> aValues;
 
2758
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
2759
 
 
2760
    RiAttributeV( name, count, &aTokens[0], &aValues[0] );
 
2761
}
 
2762
 
 
2763
 
 
2764
//----------------------------------------------------------------------
 
2765
// RiAttributeV
 
2766
// List based version of above.
 
2767
//
 
2768
RtVoid  RiAttributeV( RtToken name, PARAMETERLIST )
 
2769
{
 
2770
        Cache_RiAttribute
 
2771
 
 
2772
        Validate_RiAttribute
 
2773
 
 
2774
    // Find the parameter on the current options.
 
2775
    CqNamedParameterList * pAttr = QGetRenderContext() ->pattrWriteCurrent() ->pAttributeWrite( name ).get();
 
2776
 
 
2777
    RtInt i;
 
2778
    for ( i = 0; i < count; ++i )
 
2779
    {
 
2780
        RtToken token = tokens[ i ];
 
2781
        RtPointer       value = values[ i ];
 
2782
 
 
2783
        TqInt Type;
 
2784
        TqInt Class;
 
2785
        TqBool bArray;
 
2786
        CqParameter* pParam = pAttr->pParameter( token );
 
2787
        if ( pParam == 0 )
 
2788
        {
 
2789
            // Search for the parameter in the declarations.
 
2790
            // Note attributes can only be uniform.
 
2791
            SqParameterDeclaration Decl;
 
2792
            try
 
2793
            {
 
2794
                Decl = QGetRenderContext()->FindParameterDecl( token );
 
2795
            }
 
2796
            catch( XqException e )
 
2797
            {
 
2798
                std::cerr << error << e.strReason().c_str() << std::endl;
 
2799
                continue;
 
2800
            }
 
2801
            if ( Decl.m_strName != "" && Decl.m_Class == class_uniform )
 
2802
            {
 
2803
                pParam = Decl.m_pCreate( Decl.m_strName.c_str(), Decl.m_Count );
 
2804
                Type = Decl.m_Type;
 
2805
                Class = Decl.m_Class;
 
2806
                bArray = Decl.m_Count > 0;
 
2807
                pAttr->AddParameter( pParam );
 
2808
            }
 
2809
            else
 
2810
            {
 
2811
                if ( Decl.m_strName == "" )
 
2812
                    std::cerr << warning << "Unrecognised declaration \"" << token << "\"" << std::endl;
 
2813
                else
 
2814
                    std::cerr << warning << "Attributes can only be uniform" << std::endl;
 
2815
                return ;
 
2816
            }
 
2817
        }
 
2818
        else
 
2819
        {
 
2820
            Type = pParam->Type();
 
2821
            Class = pParam->Class();
 
2822
            bArray = pParam->Count() > 0;
 
2823
        }
 
2824
 
 
2825
        switch ( Type )
 
2826
        {
 
2827
        case type_float:
 
2828
            {
 
2829
                RtFloat * pf = reinterpret_cast<RtFloat*>( value );
 
2830
                if ( bArray )
 
2831
                {
 
2832
                    RtInt j;
 
2833
                    for ( j = 0; j < pParam->Count(); ++j )
 
2834
                        static_cast<CqParameterTypedUniformArray<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ j ] = pf[ j ];
 
2835
                }
 
2836
                else
 
2837
                    static_cast<CqParameterTypedUniform<RtFloat, type_float, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pf[ 0 ];
 
2838
            }
 
2839
            break;
 
2840
 
 
2841
        case type_integer:
 
2842
            {
 
2843
                RtInt* pi = reinterpret_cast<RtInt*>( value );
 
2844
                if ( bArray )
 
2845
                {
 
2846
                    RtInt j;
 
2847
                    for ( j = 0; j < pParam->Count(); ++j )
 
2848
                        static_cast<CqParameterTypedUniformArray<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ j ] = pi[ j ];
 
2849
                }
 
2850
                else
 
2851
                    static_cast<CqParameterTypedUniform<RtInt, type_integer, RtFloat>*>( pParam ) ->pValue() [ 0 ] = pi[ 0 ];
 
2852
            }
 
2853
            break;
 
2854
 
 
2855
        case type_string:
 
2856
            {
 
2857
                char** ps = reinterpret_cast<char**>( value );
 
2858
                if ( bArray )
 
2859
                {
 
2860
                    RtInt j;
 
2861
                    for ( j = 0; j < pParam->Count(); ++j )
 
2862
                    {
 
2863
                        CqString str( ps[ j ] );
 
2864
                        static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ j ] = str;
 
2865
                    }
 
2866
                }
 
2867
                else
 
2868
                {
 
2869
                    CqString str( ps[ 0 ] );
 
2870
                    static_cast<CqParameterTypedUniform<CqString, type_string, RtFloat>*>( pParam ) ->pValue() [ 0 ] = str;
 
2871
                }
 
2872
            }
 
2873
            // TODO: Rest of parameter types.
 
2874
        }
 
2875
    }
 
2876
    return ;
 
2877
}
 
2878
 
 
2879
 
 
2880
//----------------------------------------------------------------------
 
2881
// RiPolygon
 
2882
// Specify a coplanar, convex polygon.
 
2883
//
 
2884
RtVoid  RiPolygon( RtInt nvertices, ... )
 
2885
{
 
2886
    va_list     pArgs;
 
2887
    va_start( pArgs, nvertices );
 
2888
 
 
2889
    std::vector<RtToken> aTokens;
 
2890
    std::vector<RtPointer> aValues;
 
2891
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
2892
 
 
2893
    RiPolygonV( nvertices, count, &aTokens[0], &aValues[0] );
 
2894
}
 
2895
 
 
2896
 
 
2897
//----------------------------------------------------------------------
 
2898
// RiPolygonV
 
2899
// List based version of above.
 
2900
//
 
2901
RtVoid  RiPolygonV( RtInt nvertices, PARAMETERLIST )
 
2902
{
 
2903
        Cache_RiPolygon
 
2904
 
 
2905
        Validate_RiPolygon
 
2906
 
 
2907
    // Create a new polygon surface primitive.
 
2908
    boost::shared_ptr<CqSurfacePolygon> pSurface( new CqSurfacePolygon( nvertices ) );
 
2909
 
 
2910
        // Process any specified primitive variables.
 
2911
    if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
2912
    {
 
2913
        if ( !pSurface->CheckDegenerate() )
 
2914
        {
 
2915
            TqFloat time = QGetRenderContext()->Time();
 
2916
            // Transform the points into camera space for processing,
 
2917
            pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
2918
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
2919
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
2920
            CreateGPrim( pSurface );
 
2921
        }
 
2922
        else
 
2923
        {
 
2924
            std::cerr << error << "Found degenerate polygon" << std::endl;
 
2925
        }
 
2926
    }
 
2927
 
 
2928
    return ;
 
2929
}
 
2930
 
 
2931
 
 
2932
//----------------------------------------------------------------------
 
2933
// RiGeneralPolygon
 
2934
// Specify a nonconvex coplanar polygon.
 
2935
//
 
2936
RtVoid  RiGeneralPolygon( RtInt nloops, RtInt nverts[], ... )
 
2937
{
 
2938
    va_list     pArgs;
 
2939
    va_start( pArgs, nverts );
 
2940
 
 
2941
    std::vector<RtToken> aTokens;
 
2942
    std::vector<RtPointer> aValues;
 
2943
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
2944
 
 
2945
    RiGeneralPolygonV( nloops, nverts, count, &aTokens[0], &aValues[0] );
 
2946
}
 
2947
 
 
2948
 
 
2949
//----------------------------------------------------------------------
 
2950
// RiGeneralPolygonV
 
2951
// List based version of above.
 
2952
//
 
2953
RtVoid  RiGeneralPolygonV( RtInt nloops, RtInt nverts[], PARAMETERLIST )
 
2954
{
 
2955
        Cache_RiGeneralPolygon
 
2956
 
 
2957
        Validate_RiGeneralPolygon
 
2958
 
 
2959
    TqInt iloop;
 
2960
 
 
2961
    // Calcualte how many points there are.
 
2962
    TqInt cVerts = 0;
 
2963
    for ( iloop = 0; iloop < nloops; ++iloop )
 
2964
        {
 
2965
        cVerts += nverts[ iloop ];
 
2966
                // Check for degenerate loops.
 
2967
                if( nverts[ iloop ] < 3 )
 
2968
                {
 
2969
            CqString objname( "unnamed" );
 
2970
            const CqString* pattrName = QGetRenderContext()->pattrCurrent()->GetStringAttribute( "identifier", "name" );
 
2971
            if ( pattrName != 0 ) objname = pattrName[ 0 ];
 
2972
            std::cerr << warning << "Degenerate loop in GeneralPolygon object \"" << objname.c_str() << "\"" << std::endl;
 
2973
                }
 
2974
        }
 
2975
 
 
2976
    // Create a storage class for all the points.
 
2977
    boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, 1, cVerts ) );
 
2978
    // Process any specified primitive variables
 
2979
    if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
 
2980
    {
 
2981
        pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
 
2982
 
 
2983
        // Work out which plane to project to.
 
2984
        TqFloat MinX, MaxX;
 
2985
        TqFloat MinY, MaxY;
 
2986
        TqFloat MinZ, MaxZ;
 
2987
        CqVector3D      vecTemp = pPointsClass->P()->pValue( 0 )[0];
 
2988
        MinX = MaxX = vecTemp.x();
 
2989
        MinY = MaxY = vecTemp.y();
 
2990
        MinZ = MaxZ = vecTemp.z();
 
2991
 
 
2992
        // We need to take into account Orientation here.
 
2993
        TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
 
2994
 
 
2995
        TqUint iVert;
 
2996
        for ( iVert = 1; iVert < pPointsClass->P() ->Size(); ++iVert )
 
2997
        {
 
2998
            vecTemp = pPointsClass->P()->pValue( iVert )[0];
 
2999
            MinX = ( MinX < vecTemp.x() ) ? MinX : vecTemp.x();
 
3000
            MinY = ( MinY < vecTemp.y() ) ? MinY : vecTemp.y();
 
3001
            MinZ = ( MinZ < vecTemp.z() ) ? MinZ : vecTemp.z();
 
3002
            MaxX = ( MaxX > vecTemp.x() ) ? MaxX : vecTemp.x();
 
3003
            MaxY = ( MaxY > vecTemp.y() ) ? MaxY : vecTemp.y();
 
3004
            MaxZ = ( MaxZ > vecTemp.z() ) ? MaxZ : vecTemp.z();
 
3005
        }
 
3006
        TqFloat DiffX = MaxX - MinX;
 
3007
        TqFloat DiffY = MaxY - MinY;
 
3008
        TqFloat DiffZ = MaxZ - MinZ;
 
3009
 
 
3010
        TqInt Axis;
 
3011
        if ( DiffX < DiffY && DiffX < DiffZ )
 
3012
            Axis = CqPolygonGeneral2D::Axis_YZ;
 
3013
        else if ( DiffY < DiffX && DiffY < DiffZ )
 
3014
            Axis = CqPolygonGeneral2D::Axis_XZ;
 
3015
        else
 
3016
            Axis = CqPolygonGeneral2D::Axis_XY;
 
3017
 
 
3018
        // Create a general 2D polygon using the points in each loop.
 
3019
        CqPolygonGeneral2D poly;
 
3020
        TqUint ipoint = 0;
 
3021
        for ( iloop = 0; iloop < nloops; ++iloop )
 
3022
        {
 
3023
            CqPolygonGeneral2D polya;
 
3024
            polya.SetAxis( Axis );
 
3025
            polya.SetpVertices( pPointsClass );
 
3026
            TqInt ivert;
 
3027
            for ( ivert = 0; ivert < nverts[ iloop ]; ++ivert )
 
3028
            {
 
3029
                assert( ipoint < pPointsClass->P() ->Size() );
 
3030
                polya.aiVertices().push_back( ipoint++ );
 
3031
            }
 
3032
            if ( iloop == 0 )
 
3033
            {
 
3034
                                /// \note: We need to check here if the orientation of the projected poly matches the
 
3035
                                /// expected one, of not, we must swap the direction so that the triangulation routines can
 
3036
                                /// correctly determine the inside/outside nature of points. However, if doing so breaks the
 
3037
                                /// orientation as expected by the rest of the renderer, we need to flip the orientation
 
3038
                                /// attribute as well so that normals are correctly calculated.
 
3039
                if( O )
 
3040
                {
 
3041
                    if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
 
3042
                                        {
 
3043
                                        QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 0;
 
3044
                        polya.SwapDirection();
 
3045
                                        }
 
3046
                }
 
3047
                else
 
3048
                {
 
3049
                    if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
 
3050
                                        {
 
3051
                                        QGetRenderContext() ->pattrWriteCurrent()->GetIntegerAttributeWrite( "System", "Orientation" ) [ 0 ] = 1;
 
3052
                        polya.SwapDirection();
 
3053
                                        }
 
3054
                }
 
3055
                poly = polya;
 
3056
            }
 
3057
            else
 
3058
            {
 
3059
                if( O )
 
3060
                {
 
3061
                    if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
 
3062
                        polya.SwapDirection();
 
3063
                }
 
3064
                else
 
3065
                {
 
3066
                    if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
 
3067
                        polya.SwapDirection();
 
3068
                }
 
3069
                poly.Combine( polya );
 
3070
            }
 
3071
        }
 
3072
        // Now triangulate the general polygon
 
3073
 
 
3074
        std::vector<TqInt>      aiTriangles;
 
3075
        poly.CalcOrientation();
 
3076
        poly.Triangulate( aiTriangles );
 
3077
 
 
3078
        TqUint ctris = aiTriangles.size() / 3;
 
3079
        // Build an array of point counts (always 3 each).
 
3080
        std::vector<RtInt> _nverts;
 
3081
        _nverts.resize( ctris, 3 );
 
3082
 
 
3083
        RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
 
3084
    }
 
3085
    return ;
 
3086
}
 
3087
 
 
3088
RtVoid RiBlobby( RtInt nleaf, RtInt ncodes, RtInt codes[], RtInt nfloats, RtFloat floats[],
 
3089
                 RtInt nstrings, RtString strings[], ... )
 
3090
{
 
3091
 
 
3092
    va_list     pArgs;
 
3093
    va_start( pArgs, strings );
 
3094
 
 
3095
    std::vector<RtToken> aTokens;
 
3096
    std::vector<RtPointer> aValues;
 
3097
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3098
 
 
3099
    RiBlobbyV( nleaf, ncodes, codes, nfloats, floats, nstrings, strings, count, &aTokens[0], &aValues[0] );
 
3100
 
 
3101
    return ;
 
3102
}
 
3103
 
 
3104
//----------------------------------------------------------------------
 
3105
/** List based version of above.
 
3106
 *  
 
3107
 *\return       nothing
 
3108
 **/
 
3109
RtVoid RiBlobbyV( RtInt nleaf, RtInt ncode, RtInt code[], RtInt nflt, RtFloat flt[],
 
3110
                  RtInt nstr, RtString str[], PARAMETERLIST )
 
3111
{
 
3112
        Cache_RiBlobby
 
3113
 
 
3114
        Validate_RiBlobby
 
3115
 
 
3116
    std::cerr << warning << "RiBlobby not supported" << std::endl;
 
3117
 
 
3118
    return ;
 
3119
}
 
3120
 
 
3121
 
 
3122
//----------------------------------------------------------------------
 
3123
/** Specify a small Points primitives
 
3124
 *  
 
3125
 *\return       nothing
 
3126
 **/
 
3127
RtVoid  RiPoints( RtInt nvertices, ... )
 
3128
{
 
3129
    va_list     pArgs;
 
3130
    va_start( pArgs, nvertices );
 
3131
 
 
3132
    std::vector<RtToken> aTokens;
 
3133
    std::vector<RtPointer> aValues;
 
3134
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3135
 
 
3136
    RiPointsV( nvertices, count, &aTokens[0], &aValues[0] );
 
3137
 
 
3138
    return ;
 
3139
}
 
3140
 
 
3141
//----------------------------------------------------------------------
 
3142
/** List based version of above.
 
3143
 *  
 
3144
 *\return       nothing
 
3145
 **/
 
3146
RtVoid  RiPointsV( RtInt npoints, PARAMETERLIST )
 
3147
{
 
3148
        Cache_RiPoints
 
3149
 
 
3150
        Validate_RiPoints
 
3151
 
 
3152
    // Create a storage class for all the points.
 
3153
    boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( npoints, 1, npoints ) );
 
3154
 
 
3155
    // Create a new points storage class
 
3156
    boost::shared_ptr<CqPoints> pSurface;
 
3157
 
 
3158
    // read in the parameter list
 
3159
    if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
 
3160
    {
 
3161
        // Transform the points into camera space for processing,
 
3162
        // This needs to be done before initialising the KDTree as the tree must be formulated in 'current' (camera) space.
 
3163
        pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
 
3164
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
 
3165
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ) );
 
3166
 
 
3167
        pSurface = boost::shared_ptr<CqPoints>( new CqPoints( npoints, pPointsClass ) );
 
3168
        // Initialise the KDTree for the points to contain all.
 
3169
        pSurface->InitialiseKDTree();
 
3170
        pSurface->InitialiseMaxWidth();
 
3171
 
 
3172
        if ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "LevelOfDetailBounds" ) [ 1 ] < 0.0f )
 
3173
        {
 
3174
            // Cull this geometry for LOD reasons
 
3175
            return ;
 
3176
        }
 
3177
 
 
3178
        /// \note:      Have to duplicate the work of CreateGPrim here as we need a special type of CqDeformingSurface.
 
3179
        ///                     Not happy about this, need to look at it.
 
3180
        // If in a motion block, confirm that the current deformation surface can accept the passed one as a keyframe.
 
3181
        if( QGetRenderContext() ->pconCurrent() ->fMotionBlock() )
 
3182
        {
 
3183
            CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
 
3184
 
 
3185
            boost::shared_ptr<CqDeformingSurface> pMS = pMMB->GetDeformingSurface();
 
3186
            // If this is the first frame, then generate the appropriate CqDeformingSurface and fill in the first frame.
 
3187
            // Then cache the pointer on the motion block.
 
3188
            if( !pMS )
 
3189
            {
 
3190
                boost::shared_ptr<CqDeformingPointsSurface> pNewMS( new CqDeformingPointsSurface( pSurface ) );
 
3191
                pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
 
3192
 
 
3193
                pMMB->SetDeformingSurface( pNewMS );
 
3194
            }
 
3195
            else
 
3196
            {
 
3197
                pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
 
3198
            }
 
3199
            QGetRenderContext() ->AdvanceTime();
 
3200
        }
 
3201
        else
 
3202
        {
 
3203
            QGetRenderContext() ->pImage() ->PostSurface( pSurface );
 
3204
            STATS_INC( GPR_created );
 
3205
        }
 
3206
    }
 
3207
 
 
3208
    return ;
 
3209
}
 
3210
 
 
3211
//----------------------------------------------------------------------
 
3212
/** Specify a small line primitives
 
3213
 *  
 
3214
 *\param        type could be "linear" "bicubic"
 
3215
 *\param        ncurves : number of vertices
 
3216
 *\param        nvertices: vertices index
 
3217
 *\param        wrap could be "periodic" "nonperiodic"
 
3218
 *\return       nothing
 
3219
 **/
 
3220
 
 
3221
RtVoid RiCurves( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, ... )
 
3222
{
 
3223
    va_list     pArgs;
 
3224
    va_start( pArgs, wrap );
 
3225
 
 
3226
    std::vector<RtToken> aTokens;
 
3227
    std::vector<RtPointer> aValues;
 
3228
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3229
 
 
3230
    RiCurvesV( type, ncurves, nvertices, wrap, count, &aTokens[0], &aValues[0] );
 
3231
 
 
3232
    return ;
 
3233
}
 
3234
 
 
3235
//----------------------------------------------------------------------
 
3236
/** List based version of above.
 
3237
 *  
 
3238
 *\return       nothing
 
3239
 **/
 
3240
RtVoid RiCurvesV( RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap, PARAMETERLIST )
 
3241
{
 
3242
        Cache_RiCurves
 
3243
 
 
3244
        Validate_RiCurves
 
3245
 
 
3246
    // find out whether the curve is periodic or non-periodic
 
3247
    TqBool periodic = TqFalse;
 
3248
    if ( strcmp( wrap, RI_PERIODIC ) == 0 )
 
3249
    {
 
3250
        periodic = TqTrue;
 
3251
    }
 
3252
    else if ( strcmp( wrap, RI_NONPERIODIC ) == 0 )
 
3253
    {
 
3254
        periodic = TqFalse;
 
3255
    }
 
3256
    else
 
3257
    {
 
3258
        // the wrap mode was neither "periodic" nor "nonperiodic"
 
3259
        std::cerr << error << "RiCurves invalid wrap mode \"" << wrap << "\"" << std::endl;
 
3260
    }
 
3261
 
 
3262
    // handle creation of linear and cubic curve groups separately
 
3263
    if ( strcmp( type, RI_CUBIC ) == 0 )
 
3264
    {
 
3265
        // create a new group of cubic curves
 
3266
        boost::shared_ptr<CqCubicCurvesGroup> pSurface( new CqCubicCurvesGroup( ncurves, nvertices, periodic ) );
 
3267
        // read in the parameter list
 
3268
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3269
        {
 
3270
            // set the default primitive variables
 
3271
            pSurface->SetDefaultPrimitiveVariables();
 
3272
                        
 
3273
                        TqFloat time = QGetRenderContext()->Time();
 
3274
            // Transform the points into camera space for processing,
 
3275
            pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3276
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3277
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3278
                        
 
3279
            std::vector<boost::shared_ptr<CqBasicSurface> > aSplits;
 
3280
            pSurface->Split( aSplits );
 
3281
            std::vector<boost::shared_ptr<CqBasicSurface> >::iterator iSS;
 
3282
            for ( iSS = aSplits.begin(); iSS != aSplits.end(); ++iSS )
 
3283
            {
 
3284
                CreateGPrim( *iSS );
 
3285
            }
 
3286
        }
 
3287
    }
 
3288
    else if ( strcmp( type, RI_LINEAR ) == 0 )
 
3289
    {
 
3290
        // create a new group of linear curves
 
3291
        boost::shared_ptr<CqLinearCurvesGroup> pSurface( new CqLinearCurvesGroup( ncurves, nvertices, periodic ) );
 
3292
 
 
3293
        // read in the parameter list
 
3294
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3295
        {
 
3296
            // set the default primitive variables
 
3297
            pSurface->SetDefaultPrimitiveVariables();
 
3298
            TqFloat time = QGetRenderContext()->Time();
 
3299
            // Transform the points into camera space for processing,
 
3300
            pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3301
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3302
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3303
            CreateGPrim( pSurface );
 
3304
        }
 
3305
    }
 
3306
    else
 
3307
    {
 
3308
        // the type of curve was neither "linear" nor "cubic"
 
3309
        std::cerr << error << "RiCurves invalid type \"" << type << "\"" << std::endl;
 
3310
    }
 
3311
}
 
3312
 
 
3313
 
 
3314
//----------------------------------------------------------------------
 
3315
// RiPointsPolygons
 
3316
// Specify a list of convex coplanar polygons and their shared vertices.
 
3317
//
 
3318
RtVoid  RiPointsPolygons( RtInt npolys, RtInt nverts[], RtInt verts[], ... )
 
3319
{
 
3320
    va_list     pArgs;
 
3321
    va_start( pArgs, verts );
 
3322
 
 
3323
    std::vector<RtToken> aTokens;
 
3324
    std::vector<RtPointer> aValues;
 
3325
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3326
 
 
3327
    RiPointsPolygonsV( npolys, nverts, verts, count, &aTokens[0], &aValues[0] );
 
3328
}
 
3329
 
 
3330
 
 
3331
//----------------------------------------------------------------------
 
3332
// RiPointsPolygonsV
 
3333
// List based version of above.
 
3334
//
 
3335
 
 
3336
 
 
3337
RtVoid  RiPointsPolygonsV( RtInt npolys, RtInt nverts[], RtInt verts[], PARAMETERLIST )
 
3338
{
 
3339
        Cache_RiPointsPolygons
 
3340
 
 
3341
        Validate_RiPointsPolygons
 
3342
 
 
3343
    // Calculate how many vertices there are.
 
3344
    RtInt cVerts = 0;
 
3345
    RtInt* pVerts = verts;
 
3346
    RtInt poly;
 
3347
    RtInt sumnVerts = 0;
 
3348
    for ( poly = 0; poly < npolys; ++poly )
 
3349
    {
 
3350
        RtInt v;
 
3351
        sumnVerts += nverts[ poly ];
 
3352
        for ( v = 0; v < nverts[ poly ]; ++v )
 
3353
        {
 
3354
            cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
 
3355
            pVerts++;
 
3356
        }
 
3357
    }
 
3358
 
 
3359
    // Create a storage class for all the points.
 
3360
    boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, npolys, sumnVerts ) );
 
3361
    // Process any specified primitive variables
 
3362
    if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
 
3363
    {
 
3364
        boost::shared_ptr<CqSurfacePointsPolygons> pPsPs( new CqSurfacePointsPolygons(pPointsClass, npolys, nverts, verts ) );
 
3365
        TqFloat time = QGetRenderContext()->Time();
 
3366
       // Transform the points into camera space for processing,
 
3367
        pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(time), time ),
 
3368
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(time), time ),
 
3369
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(time), time ) );
 
3370
        CreateGPrim(pPsPs);
 
3371
    }
 
3372
 
 
3373
    return ;
 
3374
}
 
3375
 
 
3376
 
 
3377
//----------------------------------------------------------------------
 
3378
// RiPointsGeneralPolygons
 
3379
// Specify a list of coplanar, non-convex polygons and their shared vertices.
 
3380
//
 
3381
RtVoid  RiPointsGeneralPolygons( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], ... )
 
3382
{
 
3383
    va_list     pArgs;
 
3384
    va_start( pArgs, verts );
 
3385
 
 
3386
    std::vector<RtToken> aTokens;
 
3387
    std::vector<RtPointer> aValues;
 
3388
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3389
 
 
3390
    RiPointsGeneralPolygonsV( npolys, nloops, nverts, verts, count, &aTokens[0], &aValues[0] );
 
3391
 
 
3392
    return ;
 
3393
}
 
3394
 
 
3395
 
 
3396
//----------------------------------------------------------------------
 
3397
// RiPointsGeneralPolygonsV
 
3398
// List based version of above.
 
3399
//
 
3400
RtVoid  RiPointsGeneralPolygonsV( RtInt npolys, RtInt nloops[], RtInt nverts[], RtInt verts[], PARAMETERLIST )
 
3401
{
 
3402
        Cache_RiPointsGeneralPolygons
 
3403
 
 
3404
        Validate_RiPointsGeneralPolygons
 
3405
 
 
3406
    TqInt ipoly;
 
3407
    TqInt iloop;
 
3408
    TqInt igloop = 0;
 
3409
    TqInt cVerts = 0;
 
3410
    TqInt igvert = 0;
 
3411
    TqInt initial_index;
 
3412
    TqInt sumnVerts = 0;
 
3413
 
 
3414
    // Calculate how many points overall.
 
3415
    RtInt* pVerts = verts;
 
3416
    for ( ipoly = 0; ipoly < npolys; ++ipoly )
 
3417
    {
 
3418
        for ( iloop = 0; iloop < nloops[ ipoly ]; ++iloop, ++igloop )
 
3419
        {
 
3420
            TqInt v;
 
3421
            sumnVerts += nverts[ igloop ];
 
3422
                        // Check for degenerate loops.
 
3423
                        if( nverts[ igloop ] < 3 )
 
3424
                        {
 
3425
                CqString objname( "unnamed" );
 
3426
                const CqString* pattrName = QGetRenderContext()->pattrCurrent()->GetStringAttribute( "identifier", "name" );
 
3427
                if ( pattrName != 0 ) objname = pattrName[ 0 ];
 
3428
                std::cerr << warning << "Degenerate loop in PointsGeneralPolygons object \"" << objname.c_str() << "\"" << std::endl;
 
3429
                        }
 
3430
            for ( v = 0; v < nverts[ igloop ]; ++v )
 
3431
            {
 
3432
                cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
 
3433
                pVerts++;
 
3434
            }
 
3435
        }
 
3436
    }
 
3437
 
 
3438
    // We need to take into account Orientation here.
 
3439
    TqBool O = QGetRenderContext()->pattrCurrent() ->GetIntegerAttribute( "System", "Orientation" ) [ 0 ] != 0;
 
3440
 
 
3441
    // Create a storage class for all the points.
 
3442
    boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, npolys, sumnVerts ) );
 
3443
    // Process any specified primitive variables
 
3444
    if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
 
3445
    {
 
3446
        pPointsClass->SetDefaultPrimitiveVariables( RI_FALSE );
 
3447
 
 
3448
        // Reset loop counter.
 
3449
        igloop = 0;
 
3450
        TqUint ctris = 0;
 
3451
        std::vector<TqInt>      aiTriangles;
 
3452
        std::vector<TqInt> aFVList;
 
3453
        std::vector<TqInt> aUVList;
 
3454
 
 
3455
        for ( ipoly = 0; ipoly < npolys; ++ipoly )
 
3456
        {
 
3457
            initial_index = igvert;
 
3458
            // Create a general 2D polygon using the points in each loop.
 
3459
            CqPolygonGeneral2D poly;
 
3460
            TqUint ipoint = 0;
 
3461
            TqUint imaxindex, iminindex;
 
3462
            imaxindex = cVerts;
 
3463
            iminindex = 0;
 
3464
            for ( iloop = 0; iloop < nloops[ ipoly ]; ++iloop, ++igloop )
 
3465
            {
 
3466
                iminindex = MIN( iminindex, verts[ igvert ] );
 
3467
                imaxindex = MAX( imaxindex, verts[ igvert ] );
 
3468
                TqFloat MinX, MaxX;
 
3469
                TqFloat MinY, MaxY;
 
3470
                TqFloat MinZ, MaxZ;
 
3471
                CqVector3D      vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
 
3472
                MinX = MaxX = vecTemp.x();
 
3473
                MinY = MaxY = vecTemp.y();
 
3474
                MinZ = MaxZ = vecTemp.z();
 
3475
 
 
3476
                CqPolygonGeneral2D polya;
 
3477
                polya.SetpVertices( pPointsClass );
 
3478
                TqInt ivert;
 
3479
                for ( ivert = 0; ivert < nverts[ igloop ]; ++ivert, ++igvert )
 
3480
                {
 
3481
                    ipoint = verts[ igvert ];
 
3482
                    assert( ipoint < pPointsClass->P() ->Size() );
 
3483
                    polya.aiVertices().push_back( ipoint );
 
3484
 
 
3485
                    vecTemp = pPointsClass->P()->pValue( verts[ igvert ] )[0];
 
3486
                    MinX = ( MinX < vecTemp.x() ) ? MinX : vecTemp.x();
 
3487
                    MinY = ( MinY < vecTemp.y() ) ? MinY : vecTemp.y();
 
3488
                    MinZ = ( MinZ < vecTemp.z() ) ? MinZ : vecTemp.z();
 
3489
                    MaxX = ( MaxX > vecTemp.x() ) ? MaxX : vecTemp.x();
 
3490
                    MaxY = ( MaxY > vecTemp.y() ) ? MaxY : vecTemp.y();
 
3491
                    MaxZ = ( MaxZ > vecTemp.z() ) ? MaxZ : vecTemp.z();
 
3492
                }
 
3493
 
 
3494
                // Work out which plane to project to.
 
3495
                TqFloat DiffX = MaxX - MinX;
 
3496
                TqFloat DiffY = MaxY - MinY;
 
3497
                TqFloat DiffZ = MaxZ - MinZ;
 
3498
 
 
3499
                TqInt Axis;
 
3500
                if ( DiffX < DiffY && DiffX < DiffZ )
 
3501
                    Axis = CqPolygonGeneral2D::Axis_YZ;
 
3502
                else if ( DiffY < DiffX && DiffY < DiffZ )
 
3503
                    Axis = CqPolygonGeneral2D::Axis_XZ;
 
3504
                else
 
3505
                    Axis = CqPolygonGeneral2D::Axis_XY;
 
3506
                polya.SetAxis( Axis );
 
3507
 
 
3508
                if ( iloop == 0 )
 
3509
                {
 
3510
                                        /// \note: We need to check here if the orientation of the projected poly matches the
 
3511
                                        /// expected one, of not, we must swap the direction so that the triangulation routines can
 
3512
                                        /// correctly determine the inside/outside nature of points. However, if doing so breaks the
 
3513
                                        /// orientation as expected by the rest of the renderer, we need to flip the orientation
 
3514
                                        /// attribute as well so that normals are correctly calculated.
 
3515
                    if( !O )
 
3516
                    {
 
3517
                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
 
3518
                            polya.SwapDirection();
 
3519
                    }
 
3520
                    else
 
3521
                    {
 
3522
                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
 
3523
                            polya.SwapDirection();
 
3524
                    }
 
3525
                    poly = polya;
 
3526
                }
 
3527
                else
 
3528
                {
 
3529
                    if( !O )
 
3530
                    {
 
3531
                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_AntiClockwise )
 
3532
                            polya.SwapDirection();
 
3533
                    }
 
3534
                    else
 
3535
                    {
 
3536
                        if ( polya.CalcOrientation() != CqPolygonGeneral2D::Orientation_Clockwise )
 
3537
                            polya.SwapDirection();
 
3538
                    }
 
3539
                    poly.Combine( polya );
 
3540
                }
 
3541
            }
 
3542
            // Now triangulate the general polygon
 
3543
 
 
3544
            poly.CalcOrientation();
 
3545
            TqInt iStartTri = aiTriangles.size();
 
3546
            poly.Triangulate( aiTriangles );
 
3547
            TqInt iEndTri = aiTriangles.size();
 
3548
            // Store the facevarying information
 
3549
            /// \note This code relies on the fact that vertex indices cannot be duplicated
 
3550
            /// within the loops of a single poly. Make sure this is a reasonable assumption.
 
3551
            for( TqInt ifv = iStartTri; ifv < iEndTri; ++ifv )
 
3552
            {
 
3553
                TqInt ivaryingindex = aiTriangles[ ifv ];
 
3554
                TqBool found = TqFalse;
 
3555
                for( TqInt iv = initial_index; iv != igvert; ++iv )
 
3556
                {
 
3557
                    if( verts[ iv ] == ivaryingindex )
 
3558
                    {
 
3559
                        aFVList.push_back( iv );
 
3560
                        found = TqTrue;
 
3561
                    }
 
3562
                }
 
3563
                assert( found );
 
3564
            }
 
3565
 
 
3566
            // Store the count of triangles generated for this general poly, so that we
 
3567
                        // can duplicate up the uniform values as appropriate.
 
3568
            /// \note This code relies on the fact that vertex indices cannot be duplicated
 
3569
            /// within the loops of a single poly. Make sure this is a reasonable assumption.
 
3570
                        aUVList.push_back( ( iEndTri - iStartTri ) / 3 );
 
3571
        }
 
3572
 
 
3573
        // Build an array of point counts (always 3 each).
 
3574
        ctris = aiTriangles.size() / 3;
 
3575
        std::vector<RtInt> _nverts;
 
3576
        _nverts.resize( ctris, 3 );
 
3577
 
 
3578
        // Rebuild any facevarying or uniform variables.
 
3579
        TqInt iUserParam;
 
3580
        TqInt fvcount = ctris * 3;
 
3581
        assert( aFVList.size() == fvcount );
 
3582
        std::vector<void*> aNewParams;
 
3583
        for( iUserParam = 0; iUserParam < count; ++iUserParam )
 
3584
        {
 
3585
            SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( tokens[ iUserParam ] );
 
3586
            TqInt elem_size;
 
3587
            switch( Decl.m_Type )
 
3588
            {
 
3589
            case type_float:
 
3590
                elem_size = sizeof(RtFloat);
 
3591
                break;
 
3592
            case type_vector:
 
3593
            case type_point:
 
3594
            case type_normal:
 
3595
                elem_size = sizeof(RtPoint);
 
3596
                break;
 
3597
            case type_color:
 
3598
                elem_size = sizeof(RtColor);
 
3599
                break;
 
3600
            case type_matrix:
 
3601
                elem_size = sizeof(RtMatrix);
 
3602
                break;
 
3603
            }
 
3604
            if( Decl.m_Class == class_facevarying )
 
3605
            {
 
3606
                char* pNew = static_cast<char*>( malloc( elem_size * fvcount ) );
 
3607
                aNewParams.push_back( pNew );
 
3608
                TqInt iElem;
 
3609
                for( iElem = 0; iElem < fvcount; ++iElem )
 
3610
                {
 
3611
                    const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] ) + ( aFVList[ iElem ] * elem_size );
 
3612
                    memcpy( pNew, pval, elem_size );
 
3613
                    pNew += elem_size;
 
3614
                }
 
3615
                values[ iUserParam ] = aNewParams.back();
 
3616
            }
 
3617
            else if( Decl.m_Class == class_uniform )
 
3618
            {
 
3619
                                // Allocate enough for 1 value per triangle, then duplicate values from the original list
 
3620
                                // accordingly.
 
3621
                char* pNew = static_cast<char*>( malloc( elem_size * ctris ) );
 
3622
                aNewParams.push_back( pNew );
 
3623
                TqInt iElem;
 
3624
                                const unsigned char* pval = static_cast<const unsigned char*>( values[ iUserParam ] );
 
3625
                for( iElem = 0; iElem < npolys; ++iElem )
 
3626
                {
 
3627
                    TqInt dup_count = aUVList[ iElem ]; 
 
3628
                                        TqInt dup;
 
3629
                                        for(dup=0; dup < dup_count; dup++)
 
3630
                                        {
 
3631
                                                memcpy( pNew, pval, elem_size );
 
3632
                            pNew += elem_size;
 
3633
                                        }
 
3634
                                        pval += elem_size;
 
3635
                }
 
3636
                values[ iUserParam ] = aNewParams.back();
 
3637
            }
 
3638
        }
 
3639
 
 
3640
        RiPointsPolygonsV( ctris, &_nverts[ 0 ], &aiTriangles[ 0 ], count, tokens, values );
 
3641
 
 
3642
        std::vector<void*>::iterator iNewParam;
 
3643
        for( iNewParam = aNewParams.begin(); iNewParam != aNewParams.end(); ++iNewParam )
 
3644
            free( *iNewParam );
 
3645
    }
 
3646
 
 
3647
    return ;
 
3648
}
 
3649
 
 
3650
 
 
3651
//----------------------------------------------------------------------
 
3652
// RiBasis
 
3653
// Specify the patch basis matrices for the u and v directions, and the knot skip values.
 
3654
//
 
3655
RtVoid  RiBasis( RtBasis ubasis, RtInt ustep, RtBasis vbasis, RtInt vstep )
 
3656
{
 
3657
        Cache_RiBasis
 
3658
 
 
3659
        Validate_RiBasis
 
3660
 
 
3661
    CqMatrix u;
 
3662
    CqMatrix v;
 
3663
 
 
3664
    // A good parser will use the Ri*Basis pointers so a quick comparison
 
3665
    //   can be done.
 
3666
    //if ( ubasis not same as before )
 
3667
    //{
 
3668
    //  // Save off the newly given basis.
 
3669
    //
 
3670
    //  // Calculate the (inverse Bezier Basis) * (given basis), but do
 
3671
    //  //   a quick check for RiPowerBasis since that is an identity
 
3672
    //  //   matrix requiring no math.
 
3673
    //  if ( ubasis!=RiPowerBasis )
 
3674
    //  {
 
3675
    //  }
 
3676
    //  else
 
3677
    //  {
 
3678
    //  }
 
3679
    //
 
3680
    // Do the above again for vbasis.
 
3681
    // Save off (InvBezier * VBasis) and (Transpose(InvBezier*UBasis)).
 
3682
    //}
 
3683
 
 
3684
    RtInt i;
 
3685
    for ( i = 0; i < 4; ++i )
 
3686
    {
 
3687
        RtInt j;
 
3688
        for ( j = 0; j < 4; ++j )
 
3689
        {
 
3690
            u.SetElement( i, j, ubasis[ i ][ j ] );
 
3691
            v.SetElement( i, j, vbasis[ i ][ j ] );
 
3692
        }
 
3693
    }
 
3694
    u.SetfIdentity( TqFalse );
 
3695
    v.SetfIdentity( TqFalse );
 
3696
 
 
3697
    QGetRenderContext() ->pattrWriteCurrent() ->GetMatrixAttributeWrite( "System", "Basis" ) [ 0 ] = u;
 
3698
    QGetRenderContext() ->pattrWriteCurrent() ->GetMatrixAttributeWrite( "System", "Basis" ) [ 1 ] = v;
 
3699
    QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "BasisStep" ) [ 0 ] = ustep;
 
3700
    QGetRenderContext() ->pattrWriteCurrent() ->GetIntegerAttributeWrite( "System", "BasisStep" ) [ 1 ] = vstep;
 
3701
    QGetRenderContext() ->AdvanceTime();
 
3702
    return ;
 
3703
}
 
3704
 
 
3705
 
 
3706
//----------------------------------------------------------------------
 
3707
// RiPatch
 
3708
// Specify a new patch primitive.
 
3709
//
 
3710
RtVoid  RiPatch( RtToken type, ... )
 
3711
{
 
3712
    va_list     pArgs;
 
3713
    va_start( pArgs, type );
 
3714
 
 
3715
    std::vector<RtToken> aTokens;
 
3716
    std::vector<RtPointer> aValues;
 
3717
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3718
 
 
3719
    RiPatchV( type, count, &aTokens[0], &aValues[0] );
 
3720
}
 
3721
 
 
3722
 
 
3723
//----------------------------------------------------------------------
 
3724
// RiPatchV
 
3725
// List based version of above.
 
3726
//
 
3727
RtVoid  RiPatchV( RtToken type, PARAMETERLIST )
 
3728
{
 
3729
        Cache_RiPatch
 
3730
 
 
3731
        Validate_RiPatch
 
3732
 
 
3733
    if ( strcmp( type, RI_BICUBIC ) == 0 )
 
3734
    {
 
3735
        // Create a surface patch
 
3736
        boost::shared_ptr<CqSurfacePatchBicubic> pSurface( new CqSurfacePatchBicubic() );
 
3737
        // Fill in primitive variables specified.
 
3738
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3739
        {
 
3740
            // Fill in default values for all primitive variables not explicitly specified.
 
3741
            pSurface->SetDefaultPrimitiveVariables();
 
3742
            CqMatrix matuBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 0 ];
 
3743
            CqMatrix matvBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 1 ];
 
3744
            pSurface->ConvertToBezierBasis( matuBasis, matvBasis );
 
3745
 
 
3746
            TqFloat time = QGetRenderContext()->Time();
 
3747
            // Transform the points into camera space for processing,
 
3748
            pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3749
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3750
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3751
 
 
3752
            CreateGPrim( pSurface );
 
3753
        }
 
3754
    }
 
3755
    else if ( strcmp( type, RI_BILINEAR ) == 0 )
 
3756
    {
 
3757
        // Create a surface patch
 
3758
        boost::shared_ptr<CqSurfacePatchBilinear> pSurface( new CqSurfacePatchBilinear() );
 
3759
        // Fill in primitive variables specified.
 
3760
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3761
        {
 
3762
            // Fill in default values for all primitive variables not explicitly specified.
 
3763
            pSurface->SetDefaultPrimitiveVariables();
 
3764
            TqFloat time = QGetRenderContext()->Time();
 
3765
            // Transform the points into camera space for processing,
 
3766
            pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3767
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3768
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3769
            CreateGPrim( pSurface );
 
3770
        }
 
3771
    }
 
3772
    else
 
3773
    {
 
3774
        std::cerr << error << "RiPatch invalid patch type \"" << type << "\"" << std::endl;
 
3775
    }
 
3776
 
 
3777
    return ;
 
3778
}
 
3779
 
 
3780
 
 
3781
//----------------------------------------------------------------------
 
3782
// RiPatchMesh
 
3783
// Specify a quadrilaterla mesh of patches.
 
3784
//
 
3785
RtVoid  RiPatchMesh( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, ... )
 
3786
{
 
3787
    va_list     pArgs;
 
3788
    va_start( pArgs, vwrap );
 
3789
 
 
3790
    std::vector<RtToken> aTokens;
 
3791
    std::vector<RtPointer> aValues;
 
3792
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3793
 
 
3794
    RiPatchMeshV( type, nu, uwrap, nv, vwrap, count, &aTokens[0], &aValues[0] );
 
3795
}
 
3796
 
 
3797
 
 
3798
//----------------------------------------------------------------------
 
3799
// RiPatchMeshV
 
3800
// List based version of above.
 
3801
//
 
3802
 
 
3803
RtVoid  RiPatchMeshV( RtToken type, RtInt nu, RtToken uwrap, RtInt nv, RtToken vwrap, PARAMETERLIST )
 
3804
{
 
3805
        Cache_RiPatchMesh
 
3806
 
 
3807
        Validate_RiPatchMesh
 
3808
 
 
3809
    if( strcmp( uwrap, RI_PERIODIC ) && strcmp( uwrap, RI_NONPERIODIC ) )
 
3810
        std::cerr << error << "RiPatchMesh invalid u-wrap type: \"" << uwrap << "\"" << std::endl;
 
3811
 
 
3812
    if( strcmp( vwrap, RI_PERIODIC ) && strcmp( vwrap, RI_NONPERIODIC ) )
 
3813
        std::cerr << error << "RiPatchMesh invalid v-wrap type: \"" << vwrap << "\"" << std::endl;
 
3814
 
 
3815
    if ( strcmp( type, RI_BICUBIC ) == 0 )
 
3816
    {
 
3817
        // Create a surface patch
 
3818
        TqBool  uPeriodic = ( strcmp( uwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
 
3819
        TqBool  vPeriodic = ( strcmp( vwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
 
3820
 
 
3821
        boost::shared_ptr<CqSurfacePatchMeshBicubic> pSurface( new CqSurfacePatchMeshBicubic( nu, nv, uPeriodic, vPeriodic ) );
 
3822
        // Fill in primitive variables specified.
 
3823
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3824
        {
 
3825
            // Fill in default values for all primitive variables not explicitly specified.
 
3826
            pSurface->SetDefaultPrimitiveVariables();
 
3827
            std::vector<boost::shared_ptr<CqBasicSurface> > aSplits;
 
3828
            pSurface->Split( aSplits );
 
3829
            std::vector<boost::shared_ptr<CqBasicSurface> >::iterator iSS;
 
3830
            for ( iSS = aSplits.begin(); iSS != aSplits.end(); ++iSS )
 
3831
            {
 
3832
                CqMatrix matuBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 0 ];
 
3833
                CqMatrix matvBasis = pSurface->pAttributes() ->GetMatrixAttribute( "System", "Basis" ) [ 1 ];
 
3834
                static_cast<CqSurfacePatchBicubic*>( iSS->get() ) ->ConvertToBezierBasis( matuBasis, matvBasis );
 
3835
                TqFloat time = QGetRenderContext()->Time();
 
3836
                // Transform the points into camera space for processing,
 
3837
                (*iSS)->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3838
                                   QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3839
                                   QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3840
                CreateGPrim( *iSS );
 
3841
            }
 
3842
        }
 
3843
    }
 
3844
    else if ( strcmp( type, RI_BILINEAR ) == 0 )
 
3845
    {
 
3846
        // Create a surface patch
 
3847
        TqBool  uPeriodic = ( strcmp( uwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
 
3848
        TqBool  vPeriodic = ( strcmp( vwrap, RI_PERIODIC ) == 0 ) ? TqTrue : TqFalse;
 
3849
 
 
3850
        boost::shared_ptr<CqSurfacePatchMeshBilinear> pSurface( new CqSurfacePatchMeshBilinear( nu, nv, uPeriodic, vPeriodic ) );
 
3851
        // Fill in primitive variables specified.
 
3852
        if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3853
        {
 
3854
            // Fill in default values for all primitive variables not explicitly specified.
 
3855
            pSurface->SetDefaultPrimitiveVariables();
 
3856
            TqFloat time = QGetRenderContext()->Time();
 
3857
            // Transform the points into camera space for processing,
 
3858
            pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3859
                                 QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3860
                                 QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3861
            CreateGPrim( pSurface );
 
3862
        }
 
3863
    }
 
3864
    else
 
3865
    {
 
3866
        std::cerr << error << "RiPatchMesh invalid type \"" << type << "\"" << std::endl;
 
3867
    }
 
3868
 
 
3869
    return ;
 
3870
}
 
3871
 
 
3872
 
 
3873
//----------------------------------------------------------------------
 
3874
// RiNuPatch
 
3875
// Specify a new non uniform patch.
 
3876
//
 
3877
RtVoid  RiNuPatch( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
 
3878
                  RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, ... )
 
3879
{
 
3880
    va_list     pArgs;
 
3881
    va_start( pArgs, vmax );
 
3882
 
 
3883
    std::vector<RtToken> aTokens;
 
3884
    std::vector<RtPointer> aValues;
 
3885
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
3886
 
 
3887
    RiNuPatchV( nu, uorder, uknot, umin, umax, nv, vorder, vknot, vmin, vmax, count, &aTokens[0], &aValues[0] );
 
3888
}
 
3889
 
 
3890
 
 
3891
//----------------------------------------------------------------------
 
3892
// RiNuPatchV
 
3893
// List based version of above.
 
3894
//
 
3895
RtVoid  RiNuPatchV( RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin, RtFloat umax,
 
3896
                   RtInt nv, RtInt vorder, RtFloat vknot[], RtFloat vmin, RtFloat vmax, PARAMETERLIST )
 
3897
{
 
3898
        Cache_RiNuPatch
 
3899
 
 
3900
        Validate_RiNuPatch
 
3901
 
 
3902
    // Create a NURBS patch
 
3903
    boost::shared_ptr<CqSurfaceNURBS> pSurface( new CqSurfaceNURBS() );
 
3904
    pSurface->SetfPatchMesh();
 
3905
    pSurface->Init( uorder, vorder, nu, nv );
 
3906
 
 
3907
    pSurface->Setumin( umin );
 
3908
    pSurface->Setumax( umax );
 
3909
    pSurface->Setvmin( vmin );
 
3910
    pSurface->Setvmax( vmax );
 
3911
 
 
3912
    // Copy the knot vectors.
 
3913
    RtInt i;
 
3914
    for ( i = 0; i < nu + uorder; ++i ) pSurface->auKnots() [ i ] = uknot[ i ];
 
3915
    for ( i = 0; i < nv + vorder; ++i ) pSurface->avKnots() [ i ] = vknot[ i ];
 
3916
 
 
3917
    // Process any specified parameters
 
3918
    if ( ProcessPrimitiveVariables( pSurface.get(), count, tokens, values ) )
 
3919
    {
 
3920
        // Set up the default primitive variables.
 
3921
        pSurface->SetDefaultPrimitiveVariables();
 
3922
        // Clamp the surface to ensure non-periodic.
 
3923
        pSurface->Clamp();
 
3924
        TqFloat time = QGetRenderContext()->Time();
 
3925
        // Transform the points into camera space for processing,
 
3926
        pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3927
                             QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
3928
                             QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
3929
        CreateGPrim( pSurface );
 
3930
    }
 
3931
 
 
3932
    return ;
 
3933
}
 
3934
 
 
3935
//----------------------------------------------------------------------
 
3936
// RiTrimCurve
 
3937
// Specify curves which are used to trim NURBS surfaces.
 
3938
//
 
3939
RtVoid  RiTrimCurve( RtInt nloops, RtInt ncurves[], RtInt order[], RtFloat knot[], RtFloat min[], RtFloat max[], RtInt n[], RtFloat u[], RtFloat v[], RtFloat w[] )
 
3940
{
 
3941
        Cache_RiTrimCurve
 
3942
 
 
3943
        Validate_RiTrimCurve
 
3944
 
 
3945
    // Clear the current loop array.
 
3946
    QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().Clear();
 
3947
 
 
3948
    // Build an array of curves per specified loop.
 
3949
    TqInt in = 0;
 
3950
    TqInt iorder = 0;
 
3951
    TqInt iknot = 0;
 
3952
    TqInt ivert = 0;
 
3953
    TqInt iloop;
 
3954
 
 
3955
    for ( iloop = 0; iloop < nloops; ++iloop )
 
3956
    {
 
3957
        CqTrimLoop Loop;
 
3958
        TqInt icurve;
 
3959
        for ( icurve = 0; icurve < ncurves[ iloop ]; ++icurve )
 
3960
        {
 
3961
            // Create a NURBS patch
 
3962
            CqTrimCurve Curve;
 
3963
            TqInt o = order[ iorder++ ];
 
3964
            TqInt cverts = n[ in++ ];
 
3965
            Curve.Init( o, cverts );
 
3966
 
 
3967
            // Copy the knot vectors.
 
3968
            RtInt i;
 
3969
            for ( i = 0; i < o + cverts; ++i ) Curve.aKnots() [ i ] = knot[ iknot++ ];
 
3970
 
 
3971
            // Copy the vertices from the u,v,w arrays.
 
3972
            CqVector3D vec( 0, 0, 1 );
 
3973
            for ( i = 0; i < cverts; ++i )
 
3974
            {
 
3975
                vec.x( u[ ivert ] );
 
3976
                vec.y( v[ ivert ] );
 
3977
                vec.z( w[ ivert++ ] );
 
3978
                Curve.CP( i ) = vec;
 
3979
            }
 
3980
            Loop.aCurves().push_back( Curve );
 
3981
        }
 
3982
        QGetRenderContext() ->pattrWriteCurrent() ->TrimLoops().aLoops().push_back( Loop );
 
3983
    }
 
3984
    return ;
 
3985
}
 
3986
 
 
3987
 
 
3988
 
 
3989
//----------------------------------------------------------------------
 
3990
// RiSphere
 
3991
// Specify a sphere primitive.
 
3992
//
 
3993
RtVoid  RiSphere( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
 
3994
{
 
3995
    va_list     pArgs;
 
3996
    va_start( pArgs, thetamax );
 
3997
 
 
3998
    std::vector<RtToken> aTokens;
 
3999
    std::vector<RtPointer> aValues;
 
4000
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4001
 
 
4002
    RiSphereV( radius, zmin, zmax, thetamax, count, &aTokens[0], &aValues[0] );
 
4003
}
 
4004
 
 
4005
 
 
4006
//----------------------------------------------------------------------
 
4007
// RiSphereV
 
4008
// List based version of above.
 
4009
//
 
4010
RtVoid  RiSphereV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
 
4011
{
 
4012
        Cache_RiSphere
 
4013
 
 
4014
        Validate_RiSphere
 
4015
 
 
4016
    CqLogRangeCheckCallback rc;
 
4017
 
 
4018
    rc.set( "sphere zmin" );
 
4019
    CheckMinMax( zmin, -radius, radius, &rc );
 
4020
    rc.set( "sphere zmax" );
 
4021
    CheckMinMax( zmax, -radius, radius, &rc );
 
4022
 
 
4023
    // Create a sphere
 
4024
    boost::shared_ptr<CqSphere> pSurface( new CqSphere( radius, zmin, zmax, 0, thetamax ) );
 
4025
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4026
    pSurface->SetDefaultPrimitiveVariables();
 
4027
 
 
4028
    TqFloat time = QGetRenderContext()->Time();
 
4029
    // Transform the points into camera space for processing,
 
4030
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4031
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4032
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4033
    CreateGPrim( pSurface );
 
4034
 
 
4035
    return ;
 
4036
}
 
4037
 
 
4038
 
 
4039
//----------------------------------------------------------------------
 
4040
// RiCone
 
4041
// Specify a cone primitive.
 
4042
//
 
4043
RtVoid  RiCone( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
 
4044
{
 
4045
    va_list     pArgs;
 
4046
    va_start( pArgs, thetamax );
 
4047
 
 
4048
    std::vector<RtToken> aTokens;
 
4049
    std::vector<RtPointer> aValues;
 
4050
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4051
 
 
4052
    RiConeV( height, radius, thetamax, count, &aTokens[0], &aValues[0] );
 
4053
}
 
4054
 
 
4055
 
 
4056
//----------------------------------------------------------------------
 
4057
// RiConeV
 
4058
// List based version of above.
 
4059
//
 
4060
RtVoid  RiConeV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
 
4061
{
 
4062
        Cache_RiCone
 
4063
 
 
4064
        Validate_RiCone
 
4065
 
 
4066
    /// \note This should be an exception and get caught further up.
 
4067
    if( thetamax == 0 )
 
4068
        return;
 
4069
 
 
4070
    // Create a cone
 
4071
    boost::shared_ptr<CqCone> pSurface( new CqCone( height, radius, 0, thetamax, 0, 1.0f ) );
 
4072
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4073
    pSurface->SetDefaultPrimitiveVariables();
 
4074
 
 
4075
    TqFloat time = QGetRenderContext()->Time();
 
4076
    // Transform the points into camera space for processing,
 
4077
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4078
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4079
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4080
    CreateGPrim( pSurface );
 
4081
 
 
4082
    return ;
 
4083
}
 
4084
 
 
4085
 
 
4086
//----------------------------------------------------------------------
 
4087
// RiCylinder
 
4088
// Specify a culinder primitive.
 
4089
//
 
4090
RtVoid  RiCylinder( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
 
4091
{
 
4092
    va_list     pArgs;
 
4093
    va_start( pArgs, thetamax );
 
4094
 
 
4095
    std::vector<RtToken> aTokens;
 
4096
    std::vector<RtPointer> aValues;
 
4097
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4098
 
 
4099
    RiCylinderV( radius, zmin, zmax, thetamax, count, &aTokens[0], &aValues[0] );
 
4100
}
 
4101
 
 
4102
 
 
4103
//----------------------------------------------------------------------
 
4104
// RiCylinderV
 
4105
// List based version of above.
 
4106
//
 
4107
RtVoid  RiCylinderV( RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
 
4108
{
 
4109
        Cache_RiCylinder
 
4110
 
 
4111
        Validate_RiCylinder
 
4112
 
 
4113
    // Create a cylinder
 
4114
    boost::shared_ptr<CqCylinder> pSurface( new CqCylinder( radius, zmin, zmax, 0, thetamax ) );
 
4115
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4116
    pSurface->SetDefaultPrimitiveVariables();
 
4117
 
 
4118
    TqFloat time = QGetRenderContext()->Time();
 
4119
    // Transform the points into camera space for processing,
 
4120
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4121
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4122
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4123
    CreateGPrim( pSurface );
 
4124
 
 
4125
    return ;
 
4126
}
 
4127
 
 
4128
 
 
4129
//----------------------------------------------------------------------
 
4130
// RiHyperboloid
 
4131
// Specify a hyperboloid primitive.
 
4132
//
 
4133
RtVoid  RiHyperboloid( RtPoint point1, RtPoint point2, RtFloat thetamax, ... )
 
4134
{
 
4135
    va_list     pArgs;
 
4136
    va_start( pArgs, thetamax );
 
4137
 
 
4138
    std::vector<RtToken> aTokens;
 
4139
    std::vector<RtPointer> aValues;
 
4140
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4141
 
 
4142
    RiHyperboloidV( point1, point2, thetamax, count, &aTokens[0], &aValues[0] );
 
4143
}
 
4144
 
 
4145
 
 
4146
//----------------------------------------------------------------------
 
4147
// RiHyperboloidV
 
4148
// List based version of above.
 
4149
//
 
4150
RtVoid  RiHyperboloidV( RtPoint point1, RtPoint point2, RtFloat thetamax, PARAMETERLIST )
 
4151
{
 
4152
        Cache_RiHyperboloid
 
4153
 
 
4154
        Validate_RiHyperboloid
 
4155
 
 
4156
    // Create a hyperboloid
 
4157
    CqVector3D v0( point1[ 0 ], point1[ 1 ], point1[ 2 ] );
 
4158
    CqVector3D v1( point2[ 0 ], point2[ 1 ], point2[ 2 ] );
 
4159
    boost::shared_ptr<CqHyperboloid> pSurface( new CqHyperboloid( v0, v1, 0, thetamax ) );
 
4160
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4161
    pSurface->SetDefaultPrimitiveVariables();
 
4162
 
 
4163
    TqFloat time = QGetRenderContext()->Time();
 
4164
    // Transform the points into camera space for processing,
 
4165
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4166
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4167
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4168
    CreateGPrim( pSurface );
 
4169
 
 
4170
    return ;
 
4171
}
 
4172
 
 
4173
 
 
4174
//----------------------------------------------------------------------
 
4175
// RiParaboloid
 
4176
// Specify a paraboloid primitive.
 
4177
//
 
4178
RtVoid  RiParaboloid( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, ... )
 
4179
{
 
4180
    va_list     pArgs;
 
4181
    va_start( pArgs, thetamax );
 
4182
 
 
4183
    std::vector<RtToken> aTokens;
 
4184
    std::vector<RtPointer> aValues;
 
4185
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4186
 
 
4187
    RiParaboloidV( rmax, zmin, zmax, thetamax, count, &aTokens[0], &aValues[0] );
 
4188
}
 
4189
 
 
4190
 
 
4191
//----------------------------------------------------------------------
 
4192
// RiParaboloidV
 
4193
// List based version of above.
 
4194
//
 
4195
RtVoid  RiParaboloidV( RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat thetamax, PARAMETERLIST )
 
4196
{
 
4197
        Cache_RiParaboloid
 
4198
 
 
4199
        Validate_RiParaboloid
 
4200
                
 
4201
    // Create a paraboloid
 
4202
    boost::shared_ptr<CqParaboloid> pSurface( new CqParaboloid( rmax, zmin, zmax, 0, thetamax ) );
 
4203
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4204
    pSurface->SetDefaultPrimitiveVariables();
 
4205
 
 
4206
    TqFloat time = QGetRenderContext()->Time();
 
4207
    // Transform the points into camera space for processing,
 
4208
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4209
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4210
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4211
    CreateGPrim( pSurface );
 
4212
 
 
4213
    return ;
 
4214
}
 
4215
 
 
4216
 
 
4217
//----------------------------------------------------------------------
 
4218
// RiDisk
 
4219
// Specify a disk primitive.
 
4220
//
 
4221
RtVoid  RiDisk( RtFloat height, RtFloat radius, RtFloat thetamax, ... )
 
4222
{
 
4223
    va_list     pArgs;
 
4224
    va_start( pArgs, thetamax );
 
4225
 
 
4226
    std::vector<RtToken> aTokens;
 
4227
    std::vector<RtPointer> aValues;
 
4228
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4229
 
 
4230
    RiDiskV( height, radius, thetamax, count, &aTokens[0], &aValues[0] );
 
4231
}
 
4232
 
 
4233
 
 
4234
//----------------------------------------------------------------------
 
4235
// RiDiskV
 
4236
// List based version of above.
 
4237
//
 
4238
RtVoid  RiDiskV( RtFloat height, RtFloat radius, RtFloat thetamax, PARAMETERLIST )
 
4239
{
 
4240
        Cache_RiDisk
 
4241
 
 
4242
        Validate_RiDisk
 
4243
 
 
4244
    // Create a disk
 
4245
    boost::shared_ptr<CqDisk> pSurface( new CqDisk( height, 0, radius, 0, thetamax ) );
 
4246
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4247
    pSurface->SetDefaultPrimitiveVariables();
 
4248
 
 
4249
    TqFloat time = QGetRenderContext()->Time();
 
4250
    // Transform the points into camera space for processing,
 
4251
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4252
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4253
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4254
 
 
4255
    CreateGPrim( pSurface );
 
4256
 
 
4257
    return ;
 
4258
}
 
4259
 
 
4260
 
 
4261
//----------------------------------------------------------------------
 
4262
//
 
4263
//
 
4264
RtVoid  RiTorus( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, ... )
 
4265
{
 
4266
    va_list     pArgs;
 
4267
    va_start( pArgs, thetamax );
 
4268
 
 
4269
    std::vector<RtToken> aTokens;
 
4270
    std::vector<RtPointer> aValues;
 
4271
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4272
 
 
4273
    RiTorusV( majorrad, minorrad, phimin, phimax, thetamax, count, &aTokens[0], &aValues[0] );
 
4274
}
 
4275
 
 
4276
 
 
4277
//----------------------------------------------------------------------
 
4278
// RiTorus
 
4279
// Specify a torus primitive.
 
4280
//
 
4281
RtVoid  RiTorusV( RtFloat majorrad, RtFloat minorrad, RtFloat phimin, RtFloat phimax, RtFloat thetamax, PARAMETERLIST )
 
4282
{
 
4283
        Cache_RiTorus
 
4284
 
 
4285
        Validate_RiTorus
 
4286
 
 
4287
    // Create a torus
 
4288
    boost::shared_ptr<CqTorus> pSurface( new CqTorus( majorrad, minorrad, phimin, phimax, 0, thetamax ) );
 
4289
    ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4290
    pSurface->SetDefaultPrimitiveVariables();
 
4291
 
 
4292
    TqFloat time = QGetRenderContext()->Time();
 
4293
    // Transform the points into camera space for processing,
 
4294
    pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4295
                         QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4296
                         QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4297
 
 
4298
    CreateGPrim( pSurface );
 
4299
 
 
4300
    return ;
 
4301
}
 
4302
 
 
4303
 
 
4304
//----------------------------------------------------------------------
 
4305
// RiProcedural
 
4306
// Implement the procedural type primitive.
 
4307
//
 
4308
RtVoid  RiProcedural( RtPointer data, RtBound bound, RtProcSubdivFunc refineproc, RtProcFreeFunc freeproc )
 
4309
{
 
4310
        Cache_RiProcedural
 
4311
 
 
4312
        Validate_RiProcedural
 
4313
 
 
4314
    CqBound B(bound);
 
4315
 
 
4316
    //printf("bound(%f %f %f %f %f %f)\n", bound[0], bound[1], bound[2], bound[3], bound[4], bound[5]);
 
4317
 
 
4318
    // I suspect that in order to handle the RtFreeProc correctly that we need to reference count
 
4319
    // the instances of CqProcedural so that FreeProc gets called on the final Release();
 
4320
 
 
4321
    boost::shared_ptr<CqProcedural> pProc( new CqProcedural(data, B, refineproc, freeproc ) );
 
4322
        TqFloat time = QGetRenderContext()->Time();
 
4323
    pProc->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pProc->pTransform() ->matObjectToWorld(time), time ),
 
4324
                      QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pProc->pTransform() ->matObjectToWorld(time), time ),
 
4325
                      QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pProc->pTransform() ->matObjectToWorld(time), time ) );
 
4326
    CreateGPrim( pProc );
 
4327
 
 
4328
    return ;
 
4329
}
 
4330
 
 
4331
 
 
4332
 
 
4333
//----------------------------------------------------------------------
 
4334
// RiGeometry
 
4335
// Specify a special primitive.
 
4336
//
 
4337
RtVoid  RiGeometry( RtToken type, ... )
 
4338
{
 
4339
    va_list     pArgs;
 
4340
    va_start( pArgs, type );
 
4341
 
 
4342
    std::vector<RtToken> aTokens;
 
4343
    std::vector<RtPointer> aValues;
 
4344
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4345
 
 
4346
    RiGeometryV( type, count, &aTokens[0], &aValues[0] );
 
4347
}
 
4348
 
 
4349
 
 
4350
//----------------------------------------------------------------------
 
4351
// RiGeometryV
 
4352
// List based version of above.
 
4353
//
 
4354
RtVoid  RiGeometryV( RtToken type, PARAMETERLIST )
 
4355
{
 
4356
        Cache_RiGeometry
 
4357
 
 
4358
        Validate_RiGeometry
 
4359
 
 
4360
    if ( strcmp( type, "teapot" ) == 0 )
 
4361
    {
 
4362
 
 
4363
        // Create a standard teapot
 
4364
        boost::shared_ptr<CqTeapot> pSurface( new CqTeapot( true ) ); // add a bottom if true/false otherwise
 
4365
 
 
4366
        pSurface->SetSurfaceParameters( *pSurface );
 
4367
        ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4368
        pSurface->SetDefaultPrimitiveVariables();
 
4369
 
 
4370
        // I don't use the original teapot primitives as defined by T. Burge
 
4371
        // but an array of Patch Bicubic (stolen from example from Pixar) and
 
4372
        // those (6 meshes) are registered as standards GPrims right here.
 
4373
        // Basically I kept the bound, transform and split, dice and diceable methods
 
4374
        // in teapot.cpp but I suspect they are never called since the work of
 
4375
        // dicing will rely on the registered Gprimitives (see below in the for loop).
 
4376
        // I suspect the 6/7 meshes are equivalent in size/definition as the T. Burge
 
4377
        // definition. The 7th is the bottom part of the teapot (see teapot.cpp).
 
4378
 
 
4379
        for ( int i = 0; i < pSurface->cNbrPatchMeshBicubic; ++i )
 
4380
        {
 
4381
            boost::shared_ptr<CqSurface> pMesh = pSurface->pPatchMeshBicubic[ i ];
 
4382
 
 
4383
            TqFloat time = QGetRenderContext()->Time();
 
4384
            // Transform the points into camera space for processing,
 
4385
            pMesh->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4386
                              QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4387
                              QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4388
 
 
4389
            CreateGPrim( boost::static_pointer_cast<CqBasicSurface>( pMesh ) );
 
4390
        }
 
4391
    }
 
4392
    else if ( strcmp( type, "sphere" ) == 0 )
 
4393
    {
 
4394
        // Create a sphere
 
4395
        boost::shared_ptr<CqSphere> pSurface( new CqSphere( 1, -1, 1, 0, 360.0 ) );
 
4396
        ProcessPrimitiveVariables( pSurface.get(), count, tokens, values );
 
4397
        pSurface->SetDefaultPrimitiveVariables();
 
4398
 
 
4399
        TqFloat time = QGetRenderContext()->Time();
 
4400
        // Transform the points into camera space for processing,
 
4401
        pSurface->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4402
                             QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ),
 
4403
                             QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pSurface->pTransform() ->matObjectToWorld(time), time ) );
 
4404
 
 
4405
        CreateGPrim( pSurface );
 
4406
    }
 
4407
    else
 
4408
    {
 
4409
        std::cerr << warning << "RiGeometry unrecognised type \"" << type << "\"" << std::endl;
 
4410
    }
 
4411
 
 
4412
    return ;
 
4413
}
 
4414
 
 
4415
//----------------------------------------------------------------------
 
4416
// RiSolidBegin
 
4417
// Begin the definition of a CSG object.
 
4418
//
 
4419
RtVoid  RiSolidBegin( RtToken type )
 
4420
{
 
4421
        Cache_RiSolidBegin
 
4422
 
 
4423
        Validate_RiSolidBegin
 
4424
 
 
4425
    CqString strType( type );
 
4426
    QGetRenderContext() ->BeginSolidModeBlock( strType );
 
4427
 
 
4428
    return ;
 
4429
}
 
4430
 
 
4431
 
 
4432
//----------------------------------------------------------------------
 
4433
// RiSolidEnd
 
4434
// End the definition of a CSG object.
 
4435
//
 
4436
RtVoid  RiSolidEnd()
 
4437
{       
 
4438
        Cache_RiSolidEnd
 
4439
 
 
4440
        Validate_RiSolidEnd
 
4441
 
 
4442
    QGetRenderContext() ->EndSolidModeBlock();
 
4443
 
 
4444
    return ;
 
4445
}
 
4446
 
 
4447
 
 
4448
//----------------------------------------------------------------------
 
4449
// RiObjectBegin
 
4450
// Begin the definition of a stored object for use by RiObjectInstance.
 
4451
//
 
4452
RtObjectHandle  RiObjectBegin()
 
4453
{
 
4454
        Cache_RiObjectBegin
 
4455
 
 
4456
        Validate_RiObjectBegin
 
4457
 
 
4458
    QGetRenderContext() ->BeginObjectModeBlock();
 
4459
        RtObjectHandle ObjectHandle = static_cast<RtObjectHandle>(QGetRenderContext() ->OpenNewObjectInstance());
 
4460
 
 
4461
    return ( ObjectHandle );
 
4462
}
 
4463
 
 
4464
 
 
4465
//----------------------------------------------------------------------
 
4466
// RiObjectEnd
 
4467
// End the defintion of a stored object for use by RiObjectInstance.
 
4468
//
 
4469
RtVoid  RiObjectEnd()
 
4470
{
 
4471
        Validate_RiObjectEnd
 
4472
 
 
4473
    QGetRenderContext() ->EndObjectModeBlock();
 
4474
        QGetRenderContext() ->CloseObjectInstance();
 
4475
 
 
4476
        Cache_RiObjectEnd
 
4477
 
 
4478
    return ;
 
4479
}
 
4480
 
 
4481
 
 
4482
//----------------------------------------------------------------------
 
4483
// RiObjectInstance
 
4484
// Instantiate a copt of a pre-stored geometric object.
 
4485
//
 
4486
RtVoid  RiObjectInstance( RtObjectHandle handle )
 
4487
{
 
4488
        Cache_RiObjectInstance
 
4489
 
 
4490
        Validate_RiObjectInstance
 
4491
 
 
4492
        QGetRenderContext() ->InstantiateObject( reinterpret_cast<CqObjectInstance*>( handle ) );
 
4493
    return ;
 
4494
}
 
4495
 
 
4496
 
 
4497
//----------------------------------------------------------------------
 
4498
// RiMotionBegin
 
4499
// Begin the definition of the motion of an object for use by motion blur.
 
4500
//
 
4501
RtVoid  RiMotionBegin( RtInt N, ... )
 
4502
{
 
4503
    va_list     pArgs;
 
4504
    va_start( pArgs, N );
 
4505
 
 
4506
    RtFloat* times = new RtFloat[ N ];
 
4507
    RtInt i;
 
4508
    for ( i = 0; i < N; ++i )
 
4509
        times[ i ] = va_arg( pArgs, double );
 
4510
 
 
4511
    RiMotionBeginV( N, times );
 
4512
 
 
4513
    delete[] ( times );
 
4514
    return ;
 
4515
}
 
4516
 
 
4517
 
 
4518
//----------------------------------------------------------------------
 
4519
// RiBeginMotionV
 
4520
// List based version of above.
 
4521
//
 
4522
RtVoid  RiMotionBeginV( RtInt N, RtFloat times[] )
 
4523
{
 
4524
        Cache_RiMotionBeginV
 
4525
 
 
4526
        Validate_RiMotionBeginV
 
4527
 
 
4528
    QGetRenderContext() ->BeginMotionModeBlock( N, times );
 
4529
 
 
4530
    return ;
 
4531
}
 
4532
 
 
4533
 
 
4534
//----------------------------------------------------------------------
 
4535
// RiMotionEnd
 
4536
// End the definition of the motion of an object.
 
4537
//
 
4538
RtVoid  RiMotionEnd()
 
4539
{
 
4540
        Cache_RiMotionEnd
 
4541
 
 
4542
        Validate_RiMotionEnd
 
4543
 
 
4544
    QGetRenderContext() ->EndMotionModeBlock();
 
4545
 
 
4546
    return ;
 
4547
}
 
4548
 
 
4549
 
 
4550
//----------------------------------------------------------------------
 
4551
// RiMakeTexture
 
4552
// Convert a picture to a texture.
 
4553
//
 
4554
RtVoid RiMakeTexture ( RtString pic, RtString tex, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
 
4555
{
 
4556
    va_list     pArgs;
 
4557
    va_start( pArgs, twidth );
 
4558
 
 
4559
    std::vector<RtToken> aTokens;
 
4560
    std::vector<RtPointer> aValues;
 
4561
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4562
 
 
4563
    RiMakeTextureV( pic, tex, swrap, twrap, filterfunc, swidth, twidth, count, &aTokens[0], &aValues[0] );
 
4564
 
 
4565
}
 
4566
 
 
4567
 
 
4568
//----------------------------------------------------------------------
 
4569
// RiMakeTextureV
 
4570
// List based version of above.
 
4571
//
 
4572
RtVoid  RiMakeTextureV( RtString imagefile, RtString texturefile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
 
4573
{
 
4574
        Cache_RiMakeTexture
 
4575
 
 
4576
        Validate_RiMakeTexture
 
4577
 
 
4578
    char modes[ 1024 ];
 
4579
    assert( imagefile != 0 && texturefile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
 
4580
 
 
4581
    QGetRenderContext() ->Stats().MakeTextureTimer().Start();
 
4582
    // Get the wrap modes first.
 
4583
    enum EqWrapMode smode = WrapMode_Black;
 
4584
    if ( strcmp( swrap, RI_PERIODIC ) == 0 )
 
4585
        smode = WrapMode_Periodic;
 
4586
    else if ( strcmp( swrap, RI_CLAMP ) == 0 )
 
4587
        smode = WrapMode_Clamp;
 
4588
    else if ( strcmp( swrap, RI_BLACK ) == 0 )
 
4589
        smode = WrapMode_Black;
 
4590
 
 
4591
    enum EqWrapMode tmode = WrapMode_Black;
 
4592
    if ( strcmp( twrap, RI_PERIODIC ) == 0 )
 
4593
        tmode = WrapMode_Periodic;
 
4594
    else if ( strcmp( twrap, RI_CLAMP ) == 0 )
 
4595
        tmode = WrapMode_Clamp;
 
4596
    else if ( strcmp( twrap, RI_BLACK ) == 0 )
 
4597
        tmode = WrapMode_Black;
 
4598
 
 
4599
 
 
4600
    sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
 
4601
    if ( filterfunc == RiGaussianFilter )
 
4602
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "gaussian", swidth, twidth );
 
4603
    if ( filterfunc == RiBoxFilter )
 
4604
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
 
4605
    if ( filterfunc == RiTriangleFilter )
 
4606
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "triangle", swidth, twidth );
 
4607
    if ( filterfunc == RiCatmullRomFilter )
 
4608
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "catmull-rom", swidth, twidth );
 
4609
    if ( filterfunc == RiSincFilter )
 
4610
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "sinc", swidth, twidth );
 
4611
    if ( filterfunc == RiDiskFilter )
 
4612
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "disk", swidth, twidth );
 
4613
    if ( filterfunc == RiBesselFilter )
 
4614
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "bessel", swidth, twidth );
 
4615
 
 
4616
 
 
4617
    // Now load the original image.
 
4618
    CqTextureMap Source( imagefile );
 
4619
    Source.Open();
 
4620
    TqInt comp, qual;
 
4621
    ProcessCompression( &comp, &qual, count, tokens, values );
 
4622
    Source.SetCompression( comp );
 
4623
    Source.SetQuality( qual );
 
4624
 
 
4625
    if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
 
4626
    {
 
4627
        // Hopefully CqTextureMap will take care of closing the tiff file after
 
4628
        // it has SAT mapped it so we can overwrite if needs be.
 
4629
        // Create a new image.
 
4630
        Source.Interpreted( modes );
 
4631
        Source.CreateMIPMAP();
 
4632
        TIFF* ptex = TIFFOpen( texturefile, "w" );
 
4633
 
 
4634
        TIFFCreateDirectory( ptex );
 
4635
        TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
 
4636
        TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, MIPMAP_HEADER );
 
4637
        TIFFSetField( ptex, TIFFTAG_PIXAR_WRAPMODES, modes );
 
4638
        TIFFSetField( ptex, TIFFTAG_SAMPLESPERPIXEL, Source.SamplesPerPixel() );
 
4639
        TIFFSetField( ptex, TIFFTAG_BITSPERSAMPLE, 8 );
 
4640
        TIFFSetField( ptex, TIFFTAG_COMPRESSION, Source.Compression() ); /* COMPRESSION_DEFLATE */
 
4641
        int log2 = MIN( Source.XRes(), Source.YRes() );
 
4642
        log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
 
4643
 
 
4644
 
 
4645
        for ( int i = 0; i < log2; ++i )
 
4646
        {
 
4647
            // Write the floating point image to the directory.
 
4648
            CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
 
4649
            if ( !pBuffer ) break;
 
4650
            Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
 
4651
        }
 
4652
        TIFFClose( ptex );
 
4653
    }
 
4654
 
 
4655
    Source.Close();
 
4656
    QGetRenderContext() ->Stats().MakeTextureTimer().Stop();
 
4657
}
 
4658
 
 
4659
 
 
4660
//----------------------------------------------------------------------
 
4661
// RiMakeBump
 
4662
// Convert a picture to a bump map.
 
4663
//
 
4664
RtVoid  RiMakeBump( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
 
4665
{
 
4666
    std::cerr << warning << "RiMakeBump not supported" << std::endl;
 
4667
    return ;
 
4668
}
 
4669
 
 
4670
 
 
4671
//----------------------------------------------------------------------
 
4672
// RiMakeBumpV
 
4673
// List based version of above.
 
4674
//
 
4675
RtVoid  RiMakeBumpV( RtString imagefile, RtString bumpfile, RtToken swrap, RtToken twrap, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
 
4676
{
 
4677
        Cache_RiMakeBump
 
4678
 
 
4679
        Validate_RiMakeBump
 
4680
 
 
4681
    std::cerr << warning << "RiMakeBump not supported" << std::endl;
 
4682
    return ;
 
4683
}
 
4684
 
 
4685
 
 
4686
//----------------------------------------------------------------------
 
4687
// RiMakeLatLongEnvironment
 
4688
// Convert a picture to an environment map.
 
4689
//
 
4690
RtVoid  RiMakeLatLongEnvironment( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
 
4691
{
 
4692
    va_list     pArgs;
 
4693
    va_start( pArgs, twidth );
 
4694
 
 
4695
    std::vector<RtToken> aTokens;
 
4696
    std::vector<RtPointer> aValues;
 
4697
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4698
 
 
4699
    RiMakeLatLongEnvironmentV( imagefile, reflfile, filterfunc, swidth, twidth, count, &aTokens[0], &aValues[0] );
 
4700
    return ;
 
4701
}
 
4702
 
 
4703
 
 
4704
//----------------------------------------------------------------------
 
4705
// RiMakeLatLongEnvironmentV
 
4706
// List based version of above.
 
4707
//
 
4708
RtVoid  RiMakeLatLongEnvironmentV( RtString imagefile, RtString reflfile, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
 
4709
{
 
4710
        Cache_RiMakeLatLongEnvironment
 
4711
 
 
4712
        Validate_RiMakeLatLongEnvironment
 
4713
 
 
4714
    char modes[ 1024 ];
 
4715
    char *swrap = "periodic";
 
4716
    char *twrap = "clamp";
 
4717
 
 
4718
    assert( imagefile != 0 && reflfile != 0 && swrap != 0 && twrap != 0 && filterfunc != 0 );
 
4719
 
 
4720
    QGetRenderContext() ->Stats().MakeEnvTimer().Start();
 
4721
 
 
4722
    sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
 
4723
    if ( filterfunc == RiGaussianFilter )
 
4724
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "gaussian", swidth, twidth );
 
4725
    if ( filterfunc == RiBoxFilter )
 
4726
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "box", swidth, twidth );
 
4727
    if ( filterfunc == RiTriangleFilter )
 
4728
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "triangle", swidth, twidth );
 
4729
    if ( filterfunc == RiCatmullRomFilter )
 
4730
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "catmull-rom", swidth, twidth );
 
4731
    if ( filterfunc == RiSincFilter )
 
4732
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "sinc", swidth, twidth );
 
4733
    if ( filterfunc == RiDiskFilter )
 
4734
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "disk", swidth, twidth );
 
4735
    if ( filterfunc == RiBesselFilter )
 
4736
        sprintf( modes, "%s %s %s %f %f", swrap, twrap, "bessel", swidth, twidth );
 
4737
 
 
4738
 
 
4739
    // Now load the original image.
 
4740
    CqTextureMap Source( imagefile );
 
4741
    Source.Open();
 
4742
    TqInt comp, qual;
 
4743
    ProcessCompression( &comp, &qual, count, tokens, values );
 
4744
    Source.SetCompression( comp );
 
4745
    Source.SetQuality( qual );
 
4746
 
 
4747
    if ( Source.IsValid() && Source.Format() == TexFormat_Plain )
 
4748
    {
 
4749
        // Hopefully CqTextureMap will take care of closing the tiff file after
 
4750
        // it has SAT mapped it so we can overwrite if needs be.
 
4751
        // Create a new image.
 
4752
        Source.Interpreted( modes );
 
4753
        Source.CreateMIPMAP();
 
4754
        TIFF* ptex = TIFFOpen( reflfile, "w" );
 
4755
 
 
4756
        TIFFCreateDirectory( ptex );
 
4757
        TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
 
4758
        TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, LATLONG_HEADER );
 
4759
        TIFFSetField( ptex, TIFFTAG_PIXAR_WRAPMODES, modes );
 
4760
        TIFFSetField( ptex, TIFFTAG_SAMPLESPERPIXEL, Source.SamplesPerPixel() );
 
4761
        TIFFSetField( ptex, TIFFTAG_BITSPERSAMPLE, 8 );
 
4762
        TIFFSetField( ptex, TIFFTAG_COMPRESSION, Source.Compression() ); /* COMPRESSION_DEFLATE */
 
4763
        int log2 = MIN( Source.XRes(), Source.YRes() );
 
4764
        log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
 
4765
 
 
4766
 
 
4767
        for ( int i = 0; i < log2; ++i )
 
4768
        {
 
4769
            // Write the floating point image to the directory.
 
4770
            CqTextureMapBuffer* pBuffer = Source.GetBuffer( 0, 0, i );
 
4771
            if ( !pBuffer ) break;
 
4772
            Source.WriteTileImage( ptex, pBuffer, 64, 64, Source.Compression(), Source.Quality() );
 
4773
        }
 
4774
        TIFFClose( ptex );
 
4775
    }
 
4776
 
 
4777
    Source.Close();
 
4778
    QGetRenderContext() ->Stats().MakeEnvTimer().Stop();
 
4779
    return ;
 
4780
}
 
4781
 
 
4782
 
 
4783
//----------------------------------------------------------------------
 
4784
// RiMakeCubeFaceEnvironment
 
4785
// Convert a picture to a cubical environment map.
 
4786
//
 
4787
RtVoid  RiMakeCubeFaceEnvironment( RtString px, RtString nx, RtString py, RtString ny, RtString pz, RtString nz, RtString reflfile, RtFloat fov, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ... )
 
4788
{
 
4789
    va_list     pArgs;
 
4790
    va_start( pArgs, twidth );
 
4791
 
 
4792
    std::vector<RtToken> aTokens;
 
4793
    std::vector<RtPointer> aValues;
 
4794
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4795
 
 
4796
    RiMakeCubeFaceEnvironmentV( px, nx, py, ny, pz, nz, reflfile, fov, filterfunc, swidth, twidth, count, &aTokens[0], &aValues[0] );
 
4797
}
 
4798
 
 
4799
 
 
4800
//----------------------------------------------------------------------
 
4801
// RiMakeCubeFaceEnvironment
 
4802
// List based version of above.
 
4803
//
 
4804
RtVoid  RiMakeCubeFaceEnvironmentV( RtString px, RtString nx, RtString py, RtString ny, RtString pz, RtString nz, RtString reflfile, RtFloat fov, RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, PARAMETERLIST )
 
4805
{
 
4806
        Cache_RiMakeCubeFaceEnvironment
 
4807
 
 
4808
        Validate_RiMakeCubeFaceEnvironment
 
4809
 
 
4810
    QGetRenderContext() ->Stats().MakeEnvTimer().Start();
 
4811
    assert( px != 0 && nx != 0 && py != 0 && ny != 0 && pz != 0 && nz != 0 &&
 
4812
            reflfile != 0 && filterfunc != 0 );
 
4813
 
 
4814
    // Now load the original image.
 
4815
    CqTextureMap tpx( px );
 
4816
    CqTextureMap tnx( nx );
 
4817
    CqTextureMap tpy( py );
 
4818
    CqTextureMap tny( ny );
 
4819
    CqTextureMap tpz( pz );
 
4820
    CqTextureMap tnz( nz );
 
4821
 
 
4822
    tpx.Open();
 
4823
    tnx.Open();
 
4824
    tpy.Open();
 
4825
    tny.Open();
 
4826
    tpz.Open();
 
4827
    tnz.Open();
 
4828
 
 
4829
    if ( tpx.Format() != TexFormat_MIPMAP ) tpx.CreateMIPMAP();
 
4830
    if ( tnx.Format() != TexFormat_MIPMAP ) tnx.CreateMIPMAP();
 
4831
    if ( tpy.Format() != TexFormat_MIPMAP ) tpy.CreateMIPMAP();
 
4832
    if ( tny.Format() != TexFormat_MIPMAP ) tny.CreateMIPMAP();
 
4833
    if ( tpz.Format() != TexFormat_MIPMAP ) tpz.CreateMIPMAP();
 
4834
    if ( tnz.Format() != TexFormat_MIPMAP ) tnz.CreateMIPMAP();
 
4835
    if ( tpx.IsValid() && tnx.IsValid() && tpy.IsValid() && tny.IsValid() && tpz.IsValid() && tnz.IsValid() )
 
4836
    {
 
4837
        // Check all the same size;
 
4838
        bool fValid = false;
 
4839
        if ( tpx.XRes() == tnx.XRes() && tpx.XRes() == tpy.XRes() && tpx.XRes() == tny.XRes() && tpx.XRes() == tpz.XRes() && tpx.XRes() == tnz.XRes() &&
 
4840
                tpx.XRes() == tnx.XRes() && tpx.XRes() == tpy.XRes() && tpx.XRes() == tny.XRes() && tpx.XRes() == tpz.XRes() && tpx.XRes() == tnz.XRes() )
 
4841
            fValid = true;
 
4842
 
 
4843
        if ( !fValid )
 
4844
        {
 
4845
            std::cerr << error << "RiMakeCubeFaceEnvironment all images must be the same size" << std::endl;
 
4846
            return ;
 
4847
        }
 
4848
 
 
4849
        // Now copy the images to the big map.
 
4850
        CqTextureMap* Images[ 6 ] =
 
4851
            {
 
4852
                &tpz,
 
4853
                &tpx,
 
4854
                &tpy,
 
4855
                &tnx,
 
4856
                &tny,
 
4857
                &tnz
 
4858
            };
 
4859
 
 
4860
        // Create a new image.
 
4861
        TIFF* ptex = TIFFOpen( reflfile, "w" );
 
4862
 
 
4863
        RtInt ii;
 
4864
        TqInt xRes = tpx.XRes();
 
4865
        TqInt yRes = tpx.YRes();
 
4866
 
 
4867
        TqInt numsamples = tpx.SamplesPerPixel();
 
4868
        // Number of mip map levels.
 
4869
        int log2 = MIN( xRes, yRes );
 
4870
        log2 = ( int ) ( log( static_cast<float>(log2) ) / log( 2.0 ) );
 
4871
 
 
4872
        for ( ii = 0; ii < log2; ++ii )
 
4873
        {
 
4874
            CqTextureMapBuffer* pLevelBuffer = tpx.CreateBuffer( 0, 0, xRes * 3, yRes * 2, numsamples );
 
4875
            TqInt view;
 
4876
            for ( view = 0; view < 6; ++view )
 
4877
            {
 
4878
                // Get the buffer for the approriate cube side at this level.
 
4879
                CqTextureMapBuffer* pBuffer = Images[ view ] ->GetBuffer( 0, 0, ii );
 
4880
                // Work out where in the combined image it goes.
 
4881
                TqInt xoff = view % 3;
 
4882
                xoff *= xRes;
 
4883
                TqInt yoff = view / 3;
 
4884
                yoff *= yRes;
 
4885
                TqInt line, col, sample;
 
4886
                for ( line = 0; line < yRes; ++line )
 
4887
                {
 
4888
                    for ( col = 0; col < xRes; ++col )
 
4889
                    {
 
4890
                        for ( sample = 0; sample < numsamples; ++sample )
 
4891
                            pLevelBuffer->SetValue( col + xoff, line + yoff, sample, pBuffer->GetValue( col, line, sample ) );
 
4892
                    }
 
4893
                }
 
4894
            }
 
4895
 
 
4896
            TIFFCreateDirectory( ptex );
 
4897
            TIFFSetField( ptex, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
 
4898
            TIFFSetField( ptex, TIFFTAG_PIXAR_TEXTUREFORMAT, CUBEENVMAP_HEADER );
 
4899
            tpx.WriteTileImage( ptex, pLevelBuffer, 64, 64, tpx.Compression(), tpx.Quality() );
 
4900
            xRes /= 2;
 
4901
            yRes /= 2;
 
4902
        }
 
4903
        TIFFClose( ptex );
 
4904
    }
 
4905
    QGetRenderContext() ->Stats().MakeEnvTimer().Stop();
 
4906
    return ;
 
4907
}
 
4908
 
 
4909
 
 
4910
//----------------------------------------------------------------------
 
4911
// RiMakeShadow
 
4912
// Convert a depth map file to a shadow map.
 
4913
//
 
4914
RtVoid  RiMakeShadow( RtString picfile, RtString shadowfile, ... )
 
4915
{
 
4916
    va_list     pArgs;
 
4917
    va_start( pArgs, shadowfile );
 
4918
 
 
4919
    std::vector<RtToken> aTokens;
 
4920
    std::vector<RtPointer> aValues;
 
4921
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4922
 
 
4923
    RiMakeShadowV( picfile, shadowfile, count, &aTokens[0], &aValues[0] );
 
4924
}
 
4925
 
 
4926
 
 
4927
//----------------------------------------------------------------------
 
4928
// RiMakeShadowV
 
4929
// List based version of above.
 
4930
//
 
4931
RtVoid  RiMakeShadowV( RtString picfile, RtString shadowfile, PARAMETERLIST )
 
4932
{
 
4933
        Cache_RiMakeShadow
 
4934
 
 
4935
        Validate_RiMakeShadow
 
4936
 
 
4937
    QGetRenderContext() ->Stats().MakeShadowTimer().Start();
 
4938
    CqShadowMap ZFile( picfile );
 
4939
    ZFile.LoadZFile();
 
4940
 
 
4941
    TqInt comp, qual;
 
4942
    ProcessCompression( &comp, &qual, count, tokens, values );
 
4943
    ZFile.SetCompression( comp );
 
4944
    ZFile.SetQuality( qual );
 
4945
 
 
4946
    ZFile.SaveShadowMap( shadowfile );
 
4947
    QGetRenderContext() ->Stats().MakeShadowTimer().Stop();
 
4948
    return ;
 
4949
}
 
4950
 
 
4951
 
 
4952
//----------------------------------------------------------------------
 
4953
// RiMakeOcclusion
 
4954
// Convert a series of depth maps to an occlusion map.
 
4955
//
 
4956
RtVoid  RiMakeOcclusion( RtInt npics, RtString picfiles[], RtString shadowfile, ... )
 
4957
{
 
4958
    va_list     pArgs;
 
4959
    va_start( pArgs, shadowfile );
 
4960
 
 
4961
    std::vector<RtToken> aTokens;
 
4962
    std::vector<RtPointer> aValues;
 
4963
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
4964
 
 
4965
    RiMakeOcclusionV( npics, picfiles, shadowfile, count, &aTokens[0], &aValues[0] );
 
4966
}
 
4967
 
 
4968
 
 
4969
//----------------------------------------------------------------------
 
4970
// RiMakeOcclusionV
 
4971
// List based version of above.
 
4972
//
 
4973
RtVoid  RiMakeOcclusionV( RtInt npics, RtString picfiles[], RtString shadowfile, RtInt count, RtToken tokens[], RtPointer values[] )
 
4974
{
 
4975
        Cache_RiMakeOcclusion
 
4976
 
 
4977
        Validate_RiMakeOcclusion
 
4978
 
 
4979
    QGetRenderContext() ->Stats().MakeShadowTimer().Start();
 
4980
 
 
4981
    RtInt index;
 
4982
    for( index = 0; index < npics; ++index )
 
4983
    {
 
4984
        CqShadowMap ZFile( picfiles[index] );
 
4985
        ZFile.LoadZFile();
 
4986
 
 
4987
        TqInt comp, qual;
 
4988
        ProcessCompression( &comp, &qual, count, tokens, values );
 
4989
        ZFile.SetCompression( comp );
 
4990
        ZFile.SetQuality( qual );
 
4991
 
 
4992
        ZFile.SaveShadowMap( shadowfile, TqTrue );
 
4993
    }
 
4994
    QGetRenderContext() ->Stats().MakeShadowTimer().Stop();
 
4995
    return ;
 
4996
}
 
4997
 
 
4998
 
 
4999
//----------------------------------------------------------------------
 
5000
// RiErrorHandler
 
5001
// Set the function used to report errors.
 
5002
//
 
5003
RtVoid  RiErrorHandler( RtErrorFunc handler )
 
5004
{
 
5005
        Cache_RiErrorHandler
 
5006
 
 
5007
        Validate_RiErrorHandler
 
5008
 
 
5009
    QGetRenderContext()->SetpErrorHandler( handler );
 
5010
    return ;
 
5011
}
 
5012
 
 
5013
 
 
5014
//----------------------------------------------------------------------
 
5015
// RiErrorIgnore
 
5016
// Function used by RiErrorHandler to continue after errors.
 
5017
//
 
5018
RtVoid  RiErrorIgnore( RtInt code, RtInt severity, RtString message )
 
5019
{
 
5020
    return ;
 
5021
}
 
5022
 
 
5023
 
 
5024
//----------------------------------------------------------------------
 
5025
// RiErrorPrint
 
5026
// Function used by RiErrorHandler to print an error message to stdout and continue.
 
5027
//
 
5028
RtVoid  RiErrorPrint( RtInt code, RtInt severity, RtString message )
 
5029
{
 
5030
    // Don't use this!
 
5031
    std::cerr << error << "RiError: " << code << " : " << severity << " : " << message << std::endl;
 
5032
    return ;
 
5033
}
 
5034
 
 
5035
 
 
5036
//----------------------------------------------------------------------
 
5037
// RiErrorAbort
 
5038
// Function used by RiErrorHandler to print and error and stop.
 
5039
//
 
5040
RtVoid  RiErrorAbort( RtInt code, RtInt severity, RtString message )
 
5041
{
 
5042
    return ;
 
5043
}
 
5044
 
 
5045
 
 
5046
//----------------------------------------------------------------------
 
5047
// RiSubdivisionMesh
 
5048
// Specify a subdivision surface hull with tagging.
 
5049
//
 
5050
RtVoid  RiSubdivisionMesh( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], ... )
 
5051
{
 
5052
    va_list     pArgs;
 
5053
    va_start( pArgs, floatargs );
 
5054
 
 
5055
    std::vector<RtToken> aTokens;
 
5056
    std::vector<RtPointer> aValues;
 
5057
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
5058
 
 
5059
    RiSubdivisionMeshV( scheme, nfaces, nvertices, vertices, ntags, tags, nargs, intargs, floatargs, count, &aTokens[0], &aValues[0] );
 
5060
}
 
5061
 
 
5062
//----------------------------------------------------------------------
 
5063
// RiSubdivisionMeshV
 
5064
// List based version of above.
 
5065
//
 
5066
RtVoid  RiSubdivisionMeshV( RtToken scheme, RtInt nfaces, RtInt nvertices[], RtInt vertices[], RtInt ntags, RtToken tags[], RtInt nargs[], RtInt intargs[], RtFloat floatargs[], PARAMETERLIST )
 
5067
{
 
5068
        Cache_RiSubdivisionMesh
 
5069
 
 
5070
        Validate_RiSubdivisionMesh
 
5071
 
 
5072
    // Calculate how many vertices there are.
 
5073
    RtInt cVerts = 0;
 
5074
    RtInt* pVerts = vertices;
 
5075
    RtInt face;
 
5076
    RtInt sumnVerts = 0;
 
5077
    for ( face = 0; face < nfaces; ++face )
 
5078
    {
 
5079
        RtInt v;
 
5080
        sumnVerts += nvertices[ face ];
 
5081
        for ( v = 0; v < nvertices[ face ]; ++v )
 
5082
        {
 
5083
            cVerts = MAX( ( ( *pVerts ) + 1 ), cVerts );
 
5084
            pVerts++;
 
5085
        }
 
5086
    }
 
5087
 
 
5088
    // Create a storage class for all the points.
 
5089
    boost::shared_ptr<CqPolygonPoints> pPointsClass( new CqPolygonPoints( cVerts, nfaces, sumnVerts ) );
 
5090
 
 
5091
    std::vector<boost::shared_ptr<CqPolygonPoints> >    apPoints;
 
5092
    // Process any specified primitive variables
 
5093
    if ( ProcessPrimitiveVariables( pPointsClass.get(), count, tokens, values ) )
 
5094
    {
 
5095
        // Create experimental version
 
5096
        if ( strcmp( scheme, "catmull-clark" ) == 0 )
 
5097
        {
 
5098
            // Transform the points into camera space for processing,
 
5099
            pPointsClass->Transform( QGetRenderContext() ->matSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
 
5100
                                     QGetRenderContext() ->matNSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ),
 
5101
                                     QGetRenderContext() ->matVSpaceToSpace( "object", "camera", CqMatrix(), pPointsClass->pTransform() ->matObjectToWorld(pPointsClass->pTransform() ->Time(0)), pPointsClass->pTransform() ->Time(0) ) );
 
5102
 
 
5103
            boost::shared_ptr<CqSubdivision2> pSubd2( new CqSubdivision2( pPointsClass ) );
 
5104
            pSubd2->Prepare( cVerts );
 
5105
 
 
5106
            RtInt       iP = 0;
 
5107
            for ( face = 0; face < nfaces; ++face )
 
5108
            {
 
5109
                pSubd2->AddFacet( nvertices[ face ], &vertices[ iP ], iP );
 
5110
                iP += nvertices[ face ];
 
5111
            }
 
5112
            if ( pSubd2->Finalise() )
 
5113
            {
 
5114
                // Process tags.
 
5115
                TqInt argcIndex = 0;
 
5116
                TqInt floatargIndex = 0;
 
5117
                TqInt intargIndex = 0;
 
5118
                for ( TqInt i = 0; i < ntags; ++i )
 
5119
                {
 
5120
                    if ( strcmp( tags[ i ], "interpolateboundary" ) == 0 )
 
5121
                        pSubd2->SetInterpolateBoundary( TqTrue );
 
5122
                    else if ( strcmp( tags [ i ], "crease" ) == 0 )
 
5123
                    {
 
5124
                        TqFloat creaseSharpness = floatargs[ floatargIndex ];
 
5125
                        // convert pixars 0->infinity crease values to our 0->1
 
5126
                        if( creaseSharpness > 5.0f )
 
5127
                            creaseSharpness = 5.0f;
 
5128
                        creaseSharpness /= 5.0f;
 
5129
                        // bend the curve so values behave more like pixars algorithm
 
5130
                        creaseSharpness = pow(creaseSharpness, 0.2f);
 
5131
                        TqInt iEdge = 0;
 
5132
                        while ( iEdge < nargs[ argcIndex ] - 1 )
 
5133
                        {
 
5134
                            if ( intargs[ iEdge + intargIndex ] < pSubd2->cVertices() &&
 
5135
                                    intargs[ iEdge + intargIndex + 1 ] < pSubd2->cVertices() )
 
5136
                            {
 
5137
                                // Store the crease sharpness.
 
5138
                                CqLath* pEdge = pSubd2->pVertex( intargs[ iEdge + intargIndex ] );
 
5139
                                std::vector<CqLath*> aQve;
 
5140
                                pEdge->Qve( aQve );
 
5141
                                std::vector<CqLath*>::iterator iOpp;
 
5142
                                for( iOpp = aQve.begin(); iOpp != aQve.end(); ++iOpp )
 
5143
                                {
 
5144
                                    if( ( NULL != (*iOpp)->ec() ) && (*iOpp)->ec()->VertexIndex() == intargs[ iEdge + intargIndex + 1 ] )
 
5145
                                    {
 
5146
                                        pSubd2->AddSharpEdge( (*iOpp), creaseSharpness );
 
5147
                                        pSubd2->AddSharpEdge( (*iOpp)->ec(), creaseSharpness );
 
5148
                                        break;
 
5149
                                    }
 
5150
                                }
 
5151
                            }
 
5152
                            iEdge++;
 
5153
                        }
 
5154
                    }
 
5155
                    else if ( strcmp( tags [ i ], "corner" ) == 0 )
 
5156
                    {
 
5157
                        TqInt iVertex = 0;
 
5158
                        while ( iVertex < nargs[ argcIndex ] )
 
5159
                        {
 
5160
                            if ( intargs[ iVertex + intargIndex ] < pSubd2->cVertices() )
 
5161
                            {
 
5162
                                // Store the corner sharpness.
 
5163
                                CqLath* pVertex = pSubd2->pVertex( intargs[ iVertex + intargIndex ] );
 
5164
                                pSubd2->AddSharpCorner( pVertex, RI_INFINITY );
 
5165
                            }
 
5166
                            iVertex++;
 
5167
                        }
 
5168
                    }
 
5169
                    else if ( strcmp( tags [ i ], "hole" ) == 0 )
 
5170
                    {
 
5171
                        TqInt iFace = 0;
 
5172
                        while ( iFace < nargs[ argcIndex ] )
 
5173
                        {
 
5174
                            pSubd2->SetHoleFace( intargs[ iFace + intargIndex ] );
 
5175
                            iFace++;
 
5176
                        }
 
5177
                    }
 
5178
 
 
5179
                    intargIndex += nargs[ argcIndex++ ];
 
5180
                    floatargIndex += nargs[ argcIndex++ ];
 
5181
                }
 
5182
 
 
5183
                boost::shared_ptr<CqSurfaceSubdivisionMesh> pMesh( new CqSurfaceSubdivisionMesh(pSubd2, nfaces ) );
 
5184
                CreateGPrim(pMesh);
 
5185
            }
 
5186
            else
 
5187
            {
 
5188
                std::cerr << error << "RiSubdivisionMesh contains non-manifold data" << std::endl;
 
5189
            }
 
5190
        }
 
5191
        else
 
5192
        {
 
5193
            std::cerr << error << "RiSubdivisionMesh invalid scheme \"" << scheme << "\"" << std::endl;
 
5194
        }
 
5195
    }
 
5196
 
 
5197
    return ;
 
5198
}
 
5199
 
 
5200
 
 
5201
RtVoid RiReadArchive( RtToken name, RtArchiveCallback callback, ... )
 
5202
{
 
5203
    va_list     pArgs;
 
5204
    va_start( pArgs, callback );
 
5205
 
 
5206
    std::vector<RtToken> aTokens;
 
5207
    std::vector<RtPointer> aValues;
 
5208
    RtInt count = BuildParameterList( pArgs, aTokens, aValues );
 
5209
 
 
5210
    RiReadArchiveV( name, callback, count, &aTokens[0], &aValues[0] );
 
5211
}
 
5212
 
 
5213
 
 
5214
RtVoid  RiReadArchiveV( RtToken name, RtArchiveCallback callback, PARAMETERLIST )
 
5215
{
 
5216
        Cache_RiReadArchive
 
5217
 
 
5218
        Validate_RiReadArchive
 
5219
 
 
5220
    CqRiFile    fileArchive( name, "archive" );
 
5221
    const TqInt* poptVerbose = QGetRenderContext() ->optCurrent().GetIntegerOption( "statistics", "verbose" );
 
5222
 
 
5223
    if ( fileArchive.IsValid() )
 
5224
    {
 
5225
        CqString strRealName( fileArchive.strRealName() );
 
5226
        fileArchive.Close();
 
5227
        FILE *file;
 
5228
        if ( ( file = fopen( strRealName.c_str(), "rb" ) ) != NULL )
 
5229
        {
 
5230
            if ( poptVerbose )
 
5231
            {
 
5232
                std::cerr << info << "RiReadArchive: Reading archive \"" << strRealName.c_str() << "\"" << std::endl;
 
5233
            }
 
5234
            CqRIBParserState currstate = librib::GetParserState();
 
5235
            if (currstate.m_pParseCallbackInterface == NULL) currstate.m_pParseCallbackInterface = new librib2ri::Engine;
 
5236
            librib::Parse( file, name, *(currstate.m_pParseCallbackInterface), *(currstate.m_pParseErrorStream), callback );
 
5237
            librib::SetParserState( currstate );
 
5238
            fclose(file);
 
5239
        }
 
5240
    }
 
5241
}
 
5242
 
 
5243
 
 
5244
RtVoid  RiArchiveRecord( RtToken type, char *, ... )
 
5245
{
 
5246
        Validate_RiArchiveRecord
 
5247
}
 
5248
 
 
5249
RtContextHandle RiGetContext( void )
 
5250
{
 
5251
        Validate_RiGetContext
 
5252
 
 
5253
    return( NULL );
 
5254
}
 
5255
 
 
5256
RtVoid  RiContext( RtContextHandle )
 
5257
{
 
5258
        Validate_RiContext
 
5259
}
 
5260
 
 
5261
RtVoid  RiClippingPlane( RtFloat, RtFloat, RtFloat, RtFloat, RtFloat, RtFloat )
 
5262
{
 
5263
        Validate_RiClippingPlane
 
5264
}
 
5265
 
 
5266
 
 
5267
//---------------------------------------------------------------------
 
5268
//---------------------------------------------------------------------
 
5269
// Helper functions
 
5270
 
 
5271
//----------------------------------------------------------------------
 
5272
// ProcessPrimitiveVariables
 
5273
// Process and fill in any primitive variables.
 
5274
// return       :       RI_TRUE if position specified, RI_FALSE otherwise.
 
5275
 
 
5276
static RtBoolean ProcessPrimitiveVariables( CqSurface * pSurface, PARAMETERLIST )
 
5277
{
 
5278
    std::vector<TqInt>  aUserParams;
 
5279
 
 
5280
    // Read recognised parameter values.
 
5281
    RtInt       fP = RIL_NONE;
 
5282
 
 
5283
    RtFloat*    pPoints = 0;
 
5284
 
 
5285
    RtInt i;
 
5286
    for ( i = 0; i < count; ++i )
 
5287
    {
 
5288
        RtToken token = tokens[ i ];
 
5289
        RtPointer       value = values[ i ];
 
5290
                TqUlong hash = CqParameter::hash(token);
 
5291
 
 
5292
        SqParameterDeclaration Decl = QGetRenderContext()->FindParameterDecl( token );
 
5293
 
 
5294
                if ( (hash == RIH_P) && (Decl.m_Class == class_vertex ))
 
5295
        {
 
5296
            fP = RIL_P;
 
5297
            pPoints = ( RtFloat* ) value;
 
5298
        }
 
5299
                else if ( (hash == RIH_PZ) && (Decl.m_Class == class_vertex ) )
 
5300
        {
 
5301
            fP = RIL_Pz;
 
5302
            pPoints = ( RtFloat* ) value;
 
5303
        }
 
5304
                else if ( (hash == RIH_PW) && (Decl.m_Class == class_vertex ) )
 
5305
        {
 
5306
            fP = RIL_Pw;
 
5307
            pPoints = ( RtFloat* ) value;
 
5308
        }
 
5309
        else
 
5310
        {
 
5311
            aUserParams.push_back( i );
 
5312
        }
 
5313
    }
 
5314
 
 
5315
    // Fill in the position variable according to type.
 
5316
    if ( fP != RIL_NONE )
 
5317
    {
 
5318
        pSurface->AddPrimitiveVariable( new CqParameterTypedVertex<CqVector4D, type_hpoint, CqVector3D>( "P", 1 ) );
 
5319
        pSurface->P() ->SetSize( pSurface->cVertex() );
 
5320
        TqInt i;
 
5321
        switch ( fP )
 
5322
        {
 
5323
        case RIL_P:
 
5324
            for ( i = 0; i < pSurface->cVertex(); ++i )
 
5325
                pSurface->P()->pValue( i )[0] = CqVector3D( pPoints[ ( i * 3 ) ], pPoints[ ( i * 3 ) + 1 ], pPoints[ ( i * 3 ) + 2 ] );
 
5326
            break;
 
5327
 
 
5328
        case RIL_Pz:
 
5329
            for ( i = 0; i < pSurface->cVertex(); ++i )
 
5330
            {
 
5331
                CqVector3D vecP = pSurface->SurfaceParametersAtVertex( i );
 
5332
                vecP.z( pPoints[ i ] );
 
5333
                pSurface->P()->pValue( i )[0] = vecP;
 
5334
            }
 
5335
            break;
 
5336
 
 
5337
        case RIL_Pw:
 
5338
            for ( i = 0; i < pSurface->cVertex(); ++i )
 
5339
                pSurface->P()->pValue( i )[0] = CqVector4D( pPoints[ ( i * 4 ) ], pPoints[ ( i * 4 ) + 1 ], pPoints[ ( i * 4 ) + 2 ], pPoints[ ( i * 4 ) + 3 ] );
 
5340
            break;
 
5341
        }
 
5342
    }
 
5343
 
 
5344
    // Now process any user defined paramter variables.
 
5345
    if ( aUserParams.size() > 0 )
 
5346
    {
 
5347
        std::vector<TqInt>::iterator iUserParam;
 
5348
        for ( iUserParam = aUserParams.begin(); iUserParam != aUserParams.end(); ++iUserParam )
 
5349
        {
 
5350
            SqParameterDeclaration Decl;
 
5351
            try
 
5352
            {
 
5353
                Decl = QGetRenderContext()->FindParameterDecl( tokens[ *iUserParam ] );
 
5354
            }
 
5355
            catch( XqException e )
 
5356
            {
 
5357
                std::cerr << error << e.strReason().c_str() << std::endl;
 
5358
                continue;
 
5359
            }
 
5360
 
 
5361
            CqParameter* pNewParam = ( *Decl.m_pCreate ) ( Decl.m_strName.c_str(), Decl.m_Count );
 
5362
            // Now go across all values and fill in the parameter variable.
 
5363
            TqInt cValues = 1;
 
5364
            switch ( Decl.m_Class )
 
5365
            {
 
5366
            case class_uniform:
 
5367
                cValues = pSurface->cUniform();
 
5368
                break;
 
5369
 
 
5370
            case class_varying:
 
5371
                cValues = pSurface->cVarying();
 
5372
                break;
 
5373
 
 
5374
            case class_vertex:
 
5375
                cValues = pSurface->cVertex();
 
5376
                break;
 
5377
 
 
5378
            case class_facevarying:
 
5379
                cValues = pSurface->cFaceVarying();
 
5380
                break;
 
5381
            }
 
5382
            pNewParam->SetSize( cValues );
 
5383
 
 
5384
            TqInt i;
 
5385
            switch ( Decl.m_Type )
 
5386
            {
 
5387
            case type_float:
 
5388
                {
 
5389
                    CqParameterTyped<TqFloat, TqFloat>* pFloatParam = static_cast<CqParameterTyped<TqFloat, TqFloat>*>( pNewParam );
 
5390
                    TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
 
5391
                    TqInt iArrayIndex, iValIndex;
 
5392
                    i = 0;
 
5393
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5394
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5395
                            pFloatParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
 
5396
                }
 
5397
                break;
 
5398
 
 
5399
            case type_integer:
 
5400
                {
 
5401
                    CqParameterTyped<TqInt, TqFloat>* pIntParam = static_cast<CqParameterTyped<TqInt, TqFloat>*>( pNewParam );
 
5402
                    TqInt* pValue = reinterpret_cast<TqInt*>( values[ *iUserParam ] );
 
5403
                    TqInt iArrayIndex, iValIndex;
 
5404
                    i = 0;
 
5405
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5406
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5407
                            pIntParam->pValue( iValIndex ) [ iArrayIndex ] = pValue[ i ];
 
5408
                }
 
5409
                break;
 
5410
 
 
5411
            case type_point:
 
5412
            case type_normal:
 
5413
            case type_vector:
 
5414
                {
 
5415
                    CqParameterTyped<CqVector3D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector3D, CqVector3D>*>( pNewParam );
 
5416
                    TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
 
5417
                    TqInt iArrayIndex, iValIndex;
 
5418
                    i = 0;
 
5419
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5420
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5421
                            pVectorParam->pValue( iValIndex ) [ iArrayIndex ] = CqVector3D( pValue[ ( i * 3 ) ], pValue[ ( i * 3 ) + 1 ], pValue[ ( i * 3 ) + 2 ] );
 
5422
                }
 
5423
                break;
 
5424
 
 
5425
            case type_string:
 
5426
                {
 
5427
                    CqParameterTyped<CqString, CqString>* pStringParam = static_cast<CqParameterTyped<CqString, CqString>*>( pNewParam );
 
5428
                    char** pValue = reinterpret_cast<char**>( values[ *iUserParam ] );
 
5429
                    TqInt iArrayIndex, iValIndex;
 
5430
                    i = 0;
 
5431
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5432
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5433
                            pStringParam->pValue( iValIndex ) [ iArrayIndex ] = CqString( pValue[ i ] );
 
5434
                }
 
5435
                break;
 
5436
 
 
5437
            case type_color:
 
5438
                {
 
5439
                    CqParameterTyped<CqColor, CqColor>* pColorParam = static_cast<CqParameterTyped<CqColor, CqColor>*>( pNewParam );
 
5440
                    TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
 
5441
                    TqInt iArrayIndex, iValIndex;
 
5442
                    i = 0;
 
5443
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5444
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5445
                            pColorParam->pValue( iValIndex ) [ iArrayIndex ] = CqColor( pValue[ ( i * 3 ) ], pValue[ ( i * 3 ) + 1 ], pValue[ ( i * 3 ) + 2 ] );
 
5446
                }
 
5447
                break;
 
5448
 
 
5449
            case type_hpoint:
 
5450
                {
 
5451
                    CqParameterTyped<CqVector4D, CqVector3D>* pVectorParam = static_cast<CqParameterTyped<CqVector4D, CqVector3D>*>( pNewParam );
 
5452
                    TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
 
5453
                    TqInt iArrayIndex, iValIndex;
 
5454
                    i = 0;
 
5455
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5456
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5457
                            pVectorParam->pValue( iValIndex ) [ iArrayIndex ] = CqVector4D( pValue[ ( i * 4 ) ], pValue[ ( i * 4 ) + 1 ], pValue[ ( i * 4 ) + 2 ], pValue[ ( i * 4 ) + 3 ] );
 
5458
                }
 
5459
                break;
 
5460
 
 
5461
            case type_matrix:
 
5462
                {
 
5463
                    CqParameterTyped<CqMatrix, CqMatrix>* pMatrixParam = static_cast<CqParameterTyped<CqMatrix, CqMatrix>*>( pNewParam );
 
5464
                    TqFloat* pValue = reinterpret_cast<TqFloat*>( values[ *iUserParam ] );
 
5465
                    TqInt iArrayIndex, iValIndex;
 
5466
                    i = 0;
 
5467
                    for ( iValIndex = 0; iValIndex < cValues; ++iValIndex )
 
5468
                        for ( iArrayIndex = 0; iArrayIndex < Decl.m_Count; ++iArrayIndex, ++i )
 
5469
                            pMatrixParam->pValue( iValIndex ) [ iArrayIndex ] = CqMatrix( pValue[ ( i * 16 ) ], pValue[ ( i * 16 ) + 1 ], pValue[ ( i * 16 ) + 2 ], pValue[ ( i * 16 ) + 3 ],
 
5470
                                    pValue[ ( i * 16 ) + 4 ], pValue[ ( i * 16 ) + 5 ], pValue[ ( i * 16 ) + 6 ], pValue[ ( i * 16 ) + 7 ],
 
5471
                                    pValue[ ( i * 16 ) + 8 ], pValue[ ( i * 16 ) + 9 ], pValue[ ( i * 16 ) + 10 ], pValue[ ( i * 16 ) + 11 ],
 
5472
                                    pValue[ ( i * 16 ) + 12 ], pValue[ ( i * 16 ) + 13 ], pValue[ ( i * 16 ) + 14 ], pValue[ ( i * 16 ) + 15 ]
 
5473
                                                                                        );
 
5474
                }
 
5475
                break;
 
5476
 
 
5477
            default:
 
5478
                {
 
5479
                    // left blank to avoid compiler warnings about unhandled types
 
5480
                    break;
 
5481
                }
 
5482
            }
 
5483
            pSurface->AddPrimitiveVariable( pNewParam );
 
5484
            CqParameter* pP = pSurface->P();
 
5485
        }
 
5486
    }
 
5487
 
 
5488
    return ( pSurface->P() != NULL );
 
5489
}
 
5490
 
 
5491
 
 
5492
//----------------------------------------------------------------------
 
5493
// CreateGPrin
 
5494
// Create and register a GPrim according to the current attributes/transform
 
5495
//
 
5496
RtVoid  CreateGPrim( const boost::shared_ptr<CqBasicSurface>& pSurface )
 
5497
{
 
5498
 
 
5499
    if ( QGetRenderContext() ->pattrCurrent() ->GetFloatAttribute( "System", "LevelOfDetailBounds" ) [ 1 ] < 0.0f )
 
5500
    {
 
5501
        // Cull this geometry for LOD reasons.
 
5502
        return ;
 
5503
    }
 
5504
 
 
5505
    // If in a motion block, confirm that the current deformation surface can accept the passed one as a keyframe.
 
5506
    if( QGetRenderContext() ->pconCurrent() ->fMotionBlock() )
 
5507
    {
 
5508
        pSurface->PrepareTrimCurve();
 
5509
 
 
5510
        CqMotionModeBlock* pMMB = static_cast<CqMotionModeBlock*>(QGetRenderContext() ->pconCurrent().get());
 
5511
 
 
5512
        CqDeformingSurface* pMS = pMMB->GetDeformingSurface().get();
 
5513
        // If this is the first frame, then generate the appropriate CqDeformingSurface and fill in the first frame.
 
5514
        // Then cache the pointer on the motion block.
 
5515
        if( pMS == NULL )
 
5516
        {
 
5517
            boost::shared_ptr<CqDeformingSurface> pNewMS( new CqDeformingSurface( pSurface ) );
 
5518
            pNewMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
 
5519
            pMMB->SetDeformingSurface( pNewMS );
 
5520
        }
 
5521
        else
 
5522
        {
 
5523
            pMS->AddTimeSlot( QGetRenderContext()->Time(), pSurface );
 
5524
        }
 
5525
        QGetRenderContext() ->AdvanceTime();
 
5526
    }
 
5527
    else
 
5528
    {
 
5529
        pSurface->PrepareTrimCurve();
 
5530
        QGetRenderContext() ->pImage() ->PostSurface( pSurface );
 
5531
        STATS_INC( GPR_created );
 
5532
 
 
5533
        // Add to the raytracer database also
 
5534
        if(QGetRenderContext()->pRaytracer())
 
5535
            QGetRenderContext()->pRaytracer()->AddPrimitive(pSurface);
 
5536
    }
 
5537
 
 
5538
    return ;
 
5539
}
 
5540
 
 
5541
 
 
5542
//----------------------------------------------------------------------
 
5543
/** Get the basis matrix given a standard basis name.
 
5544
 * \param b Storage for basis matrix.
 
5545
 * \param strName Name of basis.
 
5546
 * \return Boolean indicating the basis is valid.
 
5547
 */
 
5548
 
 
5549
RtBoolean       BasisFromName( RtBasis * b, const char * strName )
 
5550
{
 
5551
    RtBasis * pVals = 0;
 
5552
    if ( !strcmp( strName, "bezier" ) )
 
5553
        pVals = &RiBezierBasis;
 
5554
    else if ( !strcmp( strName, "bspline" ) )
 
5555
        pVals = &RiBSplineBasis;
 
5556
    else if ( !strcmp( strName, "catmull-rom" ) )
 
5557
        pVals = &RiCatmullRomBasis;
 
5558
    else if ( !strcmp( strName, "hermite" ) )
 
5559
        pVals = &RiHermiteBasis;
 
5560
    else if ( !strcmp( strName, "power" ) )
 
5561
        pVals = &RiPowerBasis;
 
5562
 
 
5563
    if ( pVals )
 
5564
    {
 
5565
        TqInt i, j;
 
5566
        for ( i = 0; i < 4; ++i )
 
5567
            for ( j = 0; j < 4; ++j )
 
5568
                ( *b ) [ i ][ j ] = ( *pVals ) [ i ][ j ];
 
5569
        return ( TqTrue );
 
5570
    }
 
5571
    return ( TqFalse );
 
5572
}
 
5573
 
 
5574
 
 
5575
//----------------------------------------------------------------------
 
5576
/** Set the function used to report progress.
 
5577
 *      \param  handler Pointer to the new function to use.
 
5578
 */
 
5579
 
 
5580
RtVoid  RiProgressHandler( RtProgressFunc handler )
 
5581
{
 
5582
    QGetRenderContext()->SetpProgressHandler( handler );
 
5583
    return ;
 
5584
}
 
5585
 
 
5586
 
 
5587
//----------------------------------------------------------------------
 
5588
/** Set the function called just prior to rendering, after the world is complete.
 
5589
        \param  function        Pointer to the new function to use.
 
5590
        \return Pointer to the old function.
 
5591
 */
 
5592
 
 
5593
RtFunc  RiPreRenderFunction( RtFunc function )
 
5594
{
 
5595
    RtFunc pOldPreRenderFunction = QGetRenderContext()->pPreRenderFunction();
 
5596
    QGetRenderContext()->SetpPreRenderFunction( function );
 
5597
    return ( pOldPreRenderFunction );
 
5598
}
 
5599
 
 
5600
//----------------------------------------------------------------------
 
5601
/** Set the function called just prior to world definition.
 
5602
        \param  function        Pointer to the new function to use.
 
5603
        \return Pointer to the old function.
 
5604
 */
 
5605
 
 
5606
RtFunc  RiPreWorldFunction( RtFunc function )
 
5607
{
 
5608
    RtFunc pOldPreWorldFunction = QGetRenderContext()->pPreWorldFunction();
 
5609
    QGetRenderContext()->SetpPreWorldFunction( function );
 
5610
    return ( pOldPreWorldFunction );
 
5611
}
 
5612
 
 
5613
 
 
5614
void SetShaderArgument( IqShader * pShader, const char * name, TqPchar val )
 
5615
{
 
5616
    // Find the relevant variable.
 
5617
    SqParameterDeclaration Decl;
 
5618
    try
 
5619
    {
 
5620
        Decl = QGetRenderContext() ->FindParameterDecl( name );
 
5621
    }
 
5622
    catch( XqException e )
 
5623
    {
 
5624
        std::cerr << error << e.strReason().c_str() << std::endl;
 
5625
        return;
 
5626
    }
 
5627
 
 
5628
    pShader->SetArgument( Decl.m_strName, Decl.m_Type, Decl.m_strSpace, val );
 
5629
}
 
5630
 
 
5631
 
 
5632
//----------------------------------------------------------------------
 
5633
/** Analyze the parameter list and figure what kind of compression is required for texturemapping output files.
 
5634
 
 
5635
        \param  compression     compression     Pointer to an integer to containing the TIFF compression
 
5636
        \param  quality it is the quality of jpeg's compression
 
5637
        \param  count list counter
 
5638
        \param  tokens list of tokens
 
5639
        \param  values list of values
 
5640
 
 
5641
        \return nothing
 
5642
 */
 
5643
 
 
5644
static void ProcessCompression( TqInt * compression, TqInt * quality, TqInt count, RtToken * tokens, RtPointer * values )
 
5645
{
 
5646
    *compression = COMPRESSION_NONE;
 
5647
    *quality = 70;
 
5648
 
 
5649
    for ( int i = 0; i < count; ++i )
 
5650
    {
 
5651
        RtToken token = tokens[ i ];
 
5652
        RtString *value = ( RtString * ) values[ i ];
 
5653
 
 
5654
        if ( strstr( token, "compression" ) != 0 )
 
5655
        {
 
5656
 
 
5657
            if ( strstr( *value, "none" ) != 0 )
 
5658
                * compression = COMPRESSION_NONE;
 
5659
 
 
5660
            else if ( strstr( *value, "lzw" ) != 0 )
 
5661
                * compression = COMPRESSION_LZW;
 
5662
 
 
5663
            else if ( strstr( *value, "deflate" ) != 0 )
 
5664
                * compression = COMPRESSION_DEFLATE;
 
5665
 
 
5666
            else if ( strstr( *value, "jpeg" ) != 0 )
 
5667
                * compression = COMPRESSION_JPEG;
 
5668
 
 
5669
            else if ( strstr( *value, "packbits" ) != 0 )
 
5670
                * compression = COMPRESSION_PACKBITS;
 
5671
 
 
5672
 
 
5673
        }
 
5674
        else if ( strstr( token, "quality" ) != 0 )
 
5675
        {
 
5676
 
 
5677
            *quality = ( int ) * ( float * ) value;
 
5678
            if ( *quality < 0 ) * quality = 0;
 
5679
            if ( *quality > 100 ) * quality = 100;
 
5680
        }
 
5681
    }
 
5682
}