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

« back to all changes in this revision

Viewing changes to render/bucket.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 (C) 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 Implements the CqBucket class responsible for bookkeeping the primitives and storing the results.
 
23
                \author Paul C. Gregory (pgregory@aqsis.com)
 
24
*/
 
25
 
 
26
#include        "aqsis.h"
 
27
 
 
28
#ifdef WIN32
 
29
#include    <windows.h>
 
30
#endif
 
31
#include        <math.h>
 
32
 
 
33
#include        "surface.h"
 
34
#include        "imagepixel.h"
 
35
#include        "bucket.h"
 
36
 
 
37
#include        "imagers.h"
 
38
 
 
39
 
 
40
 
 
41
 
 
42
 
 
43
START_NAMESPACE( Aqsis )
 
44
 
 
45
 
 
46
//----------------------------------------------------------------------
 
47
/** Static data on CqBucket
 
48
 */
 
49
 
 
50
TqInt   CqBucket::m_XSize;
 
51
TqInt   CqBucket::m_YSize;
 
52
TqInt   CqBucket::m_FilterXWidth;
 
53
TqInt   CqBucket::m_FilterYWidth;
 
54
TqInt   CqBucket::m_XMax;
 
55
TqInt   CqBucket::m_YMax;
 
56
TqInt   CqBucket::m_XOrigin;
 
57
TqInt   CqBucket::m_YOrigin;
 
58
TqInt   CqBucket::m_PixelXSamples;
 
59
TqInt   CqBucket::m_PixelYSamples;
 
60
std::vector<CqImagePixel>       CqBucket::m_aieImage;
 
61
std::vector<std::vector<CqVector2D> >   CqBucket::m_aSamplePositions;
 
62
std::vector<TqFloat> CqBucket::m_aFilterValues;
 
63
std::vector<TqFloat> CqBucket::m_aDatas;
 
64
std::vector<TqFloat> CqBucket::m_aCoverages;
 
65
 
 
66
 
 
67
//----------------------------------------------------------------------
 
68
/** Initialise the static image storage area.
 
69
 *  Clear,Allocate, Init. the m_aieImage samples
 
70
 */
 
71
 
 
72
void CqBucket::InitialiseBucket( TqInt xorigin, TqInt yorigin, TqInt xsize, TqInt ysize, TqInt xfwidth, TqInt yfwidth, TqInt xsamples, TqInt ysamples, TqBool fJitter )
 
73
{
 
74
    m_XOrigin = xorigin;
 
75
    m_YOrigin = yorigin;
 
76
    m_XSize = xsize;
 
77
    m_YSize = ysize;
 
78
    m_FilterXWidth = xfwidth;
 
79
    m_FilterYWidth = yfwidth;
 
80
    m_XMax = static_cast<TqInt>( CEIL( ( xfwidth - 1 ) * 0.5f ) );
 
81
    m_YMax = static_cast<TqInt>( CEIL( ( xfwidth - 1 ) * 0.5f ) );
 
82
    m_PixelXSamples = xsamples;
 
83
    m_PixelYSamples = ysamples;
 
84
 
 
85
    TqInt ywidth1, xwidth1;
 
86
    ywidth1 = m_YSize + m_FilterYWidth;
 
87
    xwidth1 = m_XSize + m_FilterXWidth;
 
88
 
 
89
    // Allocate the image element storage if this is the first bucket
 
90
    if(m_aieImage.empty())
 
91
    {
 
92
        m_aieImage.resize( xwidth1 * ywidth1);
 
93
        m_aSamplePositions.resize( xwidth1 * ywidth1 );
 
94
 
 
95
        // Initialise the samples for this bucket.
 
96
        TqInt which = 0;
 
97
        for ( TqInt i = 0; i < ywidth1; i++ )
 
98
        {
 
99
            for ( TqInt j = 0; j < xwidth1; j++ )
 
100
            {
 
101
                m_aieImage[which].Clear();
 
102
                m_aieImage[which].AllocateSamples( xsamples, ysamples );
 
103
                m_aieImage[which].InitialiseSamples( m_aSamplePositions[which], fJitter );
 
104
 
 
105
                which++;
 
106
            }
 
107
        }
 
108
    }
 
109
 
 
110
    // now shuffle the pixels around and add in the pixel offset to the position.
 
111
    static CqRandom random(  53 );
 
112
    TqInt shuffleX = random.RandomInt( xwidth1 );
 
113
    TqInt shuffleY = random.RandomInt( ywidth1 );
 
114
    TqInt which = 0;
 
115
    TqInt sourceIndex = shuffleY*xwidth1 + shuffleX;
 
116
    TqInt numPixels = xwidth1*ywidth1;
 
117
    for ( TqInt i = 0; i < ywidth1; i++ )
 
118
    {
 
119
        for ( TqInt j = 0; j < xwidth1; j++ )
 
120
        {
 
121
            CqVector2D bPos2( m_XOrigin, m_YOrigin );
 
122
            bPos2 += CqVector2D( ( j - m_FilterXWidth / 2 ), ( i - m_FilterYWidth / 2 ) );
 
123
 
 
124
            m_aieImage[which].Clear();
 
125
            m_aieImage[which].OffsetSamples( bPos2, m_aSamplePositions[sourceIndex] );
 
126
 
 
127
            which++;
 
128
            sourceIndex = (sourceIndex+1) % (numPixels);
 
129
        }
 
130
    }
 
131
}
 
132
 
 
133
 
 
134
//----------------------------------------------------------------------
 
135
/** Initialise the static filter values.
 
136
 */
 
137
 
 
138
void CqBucket::InitialiseFilterValues()
 
139
{
 
140
    if( !m_aFilterValues.empty() )
 
141
        return;
 
142
 
 
143
    // Allocate and fill in the filter values array for each pixel.
 
144
    TqInt numsubpixels = ( m_PixelXSamples * m_PixelYSamples );
 
145
    TqInt numperpixel = numsubpixels * numsubpixels;
 
146
 
 
147
    TqUint numvalues = static_cast<TqUint>( ( ( m_FilterXWidth + 1 ) * ( m_FilterYWidth + 1 ) ) * ( numperpixel ) );
 
148
 
 
149
    m_aFilterValues.resize( numvalues );
 
150
 
 
151
    RtFilterFunc pFilter;
 
152
    pFilter = QGetRenderContext() ->optCurrent().funcFilter();
 
153
 
 
154
    // Sanity check
 
155
    if( NULL == pFilter )
 
156
        pFilter = RiBoxFilter;
 
157
 
 
158
    TqFloat xmax = m_XMax;
 
159
    TqFloat ymax = m_YMax;
 
160
    TqFloat xfwo2 = m_FilterXWidth * 0.5f;
 
161
    TqFloat yfwo2 = m_FilterYWidth * 0.5f;
 
162
    TqFloat xfw = m_FilterXWidth;
 
163
 
 
164
    TqFloat subcellwidth = 1.0f / numsubpixels;
 
165
    TqFloat subcellcentre = subcellwidth * 0.5f;
 
166
 
 
167
    // Go over every pixel touched by the filter
 
168
    TqInt px, py;
 
169
    for ( py = static_cast<TqInt>( -ymax ); py <= static_cast<TqInt>( ymax ); py++ )
 
170
    {
 
171
        for( px = static_cast<TqInt>( -xmax ); px <= static_cast<TqInt>( xmax ); px++ )
 
172
        {
 
173
            // Get the index of the pixel in the array.
 
174
            TqInt index = static_cast<TqInt>( ( ( ( py + ymax ) * xfw ) + ( px + xmax ) ) * numperpixel );
 
175
            TqFloat pfx = px - 0.5f;
 
176
            TqFloat pfy = py - 0.5f;
 
177
            // Go over every subpixel in the pixel.
 
178
            TqInt sx, sy;
 
179
            for ( sy = 0; sy < m_PixelYSamples; sy++ )
 
180
            {
 
181
                for ( sx = 0; sx < m_PixelXSamples; sx++ )
 
182
                {
 
183
                    // Get the index of the subpixel in the array
 
184
                    TqInt sindex = index + ( ( ( sy * m_PixelXSamples ) + sx ) * numsubpixels );
 
185
                    TqFloat sfx = static_cast<TqFloat>( sx ) / m_PixelXSamples;
 
186
                    TqFloat sfy = static_cast<TqFloat>( sy ) / m_PixelYSamples;
 
187
                    // Go over each subcell in the subpixel
 
188
                    TqInt cx, cy;
 
189
                    for ( cy = 0; cy < m_PixelXSamples; cy++ )
 
190
                    {
 
191
                        for ( cx = 0; cx < m_PixelYSamples; cx++ )
 
192
                        {
 
193
                            // Get the index of the subpixel in the array
 
194
                            TqInt cindex = sindex + ( ( cy * m_PixelYSamples ) + cx );
 
195
                            TqFloat fx = ( cx * subcellwidth ) + sfx + pfx + subcellcentre;
 
196
                            TqFloat fy = ( cy * subcellwidth ) + sfy + pfy + subcellcentre;
 
197
                            TqFloat w = 0.0f;
 
198
                            if ( fx >= -xfwo2 && fy >= -yfwo2 && fx <= xfwo2 && fy <= yfwo2 )
 
199
                                w = ( *pFilter ) ( fx, fy, m_FilterXWidth, m_FilterYWidth );
 
200
                            m_aFilterValues[ cindex ] = w;
 
201
                        }
 
202
                    }
 
203
                }
 
204
            }
 
205
        }
 
206
    }
 
207
 
 
208
}
 
209
 
 
210
 
 
211
//----------------------------------------------------------------------
 
212
/** Combine the subsamples into single pixel samples and coverage information.
 
213
 */
 
214
 
 
215
void CqBucket::CombineElements()
 
216
{
 
217
    std::vector<CqImagePixel>::iterator end = m_aieImage.end();
 
218
    for ( std::vector<CqImagePixel>::iterator i = m_aieImage.begin(); i != end ; i++ )
 
219
        i->Combine();
 
220
}
 
221
 
 
222
 
 
223
//----------------------------------------------------------------------
 
224
/** Get the sample color for the specified screen position.
 
225
 * If position is outside bucket, returns black.
 
226
 * \param iXPos Screen position of sample.
 
227
 * \param iYPos Screen position of sample.
 
228
 */
 
229
 
 
230
CqColor CqBucket::Color( TqInt iXPos, TqInt iYPos )
 
231
{
 
232
    CqImagePixel * pie;
 
233
    ImageElement( iXPos, iYPos, pie );
 
234
    if( NULL != pie )
 
235
        return ( pie->Color() );
 
236
    else
 
237
        return ( gColBlack);
 
238
}
 
239
 
 
240
//----------------------------------------------------------------------
 
241
/** Get the sample opacity for the specified screen position.
 
242
 * If position is outside bucket, returns black.
 
243
 * \param iXPos Screen position of sample.
 
244
 * \param iYPos Screen position of sample.
 
245
 */
 
246
 
 
247
CqColor CqBucket::Opacity( TqInt iXPos, TqInt iYPos )
 
248
{
 
249
    CqImagePixel * pie;
 
250
    ImageElement( iXPos, iYPos, pie );
 
251
    if( NULL != pie )
 
252
        return ( pie->Opacity() );
 
253
    else
 
254
        return ( gColBlack);
 
255
}
 
256
 
 
257
 
 
258
//----------------------------------------------------------------------
 
259
/** Get the sample coverage for the specified screen position.
 
260
 * If position is outside bucket, returns 0.
 
261
 * \param iXPos Screen position of sample.
 
262
 * \param iYPos Screen position of sample.
 
263
 */
 
264
 
 
265
TqFloat CqBucket::Coverage( TqInt iXPos, TqInt iYPos )
 
266
{
 
267
    CqImagePixel * pie;
 
268
    ImageElement( iXPos, iYPos, pie );
 
269
    if( NULL != pie )
 
270
        return ( pie->Coverage() );
 
271
    else
 
272
        return ( 0.0f );
 
273
}
 
274
 
 
275
 
 
276
//----------------------------------------------------------------------
 
277
/** Get the sample depth for the specified screen position.
 
278
 * If position is outside bucket, returns FLT_MAX.
 
279
 * \param iXPos Screen position of sample.
 
280
 * \param iYPos Screen position of sample.
 
281
 */
 
282
 
 
283
TqFloat CqBucket::Depth( TqInt iXPos, TqInt iYPos )
 
284
{
 
285
    CqImagePixel * pie;
 
286
    ImageElement( iXPos, iYPos, pie );
 
287
    if( NULL != pie )
 
288
        return ( pie->Depth() );
 
289
    else
 
290
        return ( FLT_MAX );
 
291
}
 
292
 
 
293
 
 
294
//----------------------------------------------------------------------
 
295
/** Get the maximum sample depth for the specified screen position.
 
296
 * If position is outside bucket, returns FLT_MAX.
 
297
 * \param iXPos Screen position of sample.
 
298
 * \param iYPos Screen position of sample.
 
299
 */
 
300
 
 
301
TqFloat CqBucket::MaxDepth( TqInt iXPos, TqInt iYPos )
 
302
{
 
303
    CqImagePixel * pie;
 
304
    ImageElement( iXPos, iYPos, pie );
 
305
    if( NULL != pie )
 
306
        return ( pie->MaxDepth() );
 
307
    else
 
308
        return ( FLT_MAX );
 
309
}
 
310
 
 
311
 
 
312
//----------------------------------------------------------------------
 
313
/** Get a pointer to the samples for a given pixel.
 
314
 * If position is outside bucket, returns NULL.
 
315
 * \param iXPos Screen position of sample.
 
316
 * \param iYPos Screen position of sample.
 
317
 */
 
318
 
 
319
const TqFloat* CqBucket::Data( TqInt iXPos, TqInt iYPos )
 
320
{
 
321
    CqImagePixel * pie;
 
322
    ImageElement( iXPos, iYPos, pie );
 
323
    if( NULL != pie )
 
324
        return ( pie->Data() );
 
325
    else
 
326
        return ( NULL );
 
327
}
 
328
 
 
329
//----------------------------------------------------------------------
 
330
/** Get count of samples.
 
331
 * If position is outside bucket, returns 0.
 
332
 * \param iXPos Screen position of sample.
 
333
 * \param iYPos Screen position of sample.
 
334
 */
 
335
 
 
336
TqInt CqBucket::DataSize( TqInt iXPos, TqInt iYPos )
 
337
{
 
338
    CqImagePixel * pie;
 
339
    ImageElement( iXPos, iYPos, pie );
 
340
    if( NULL != pie )
 
341
        return ( pie->DataSize() );
 
342
    else
 
343
        return ( 0 );
 
344
}
 
345
 
 
346
 
 
347
//----------------------------------------------------------------------
 
348
/** Filter the samples in this bucket according to type and filter widths.
 
349
 */
 
350
 
 
351
void CqBucket::FilterBucket(TqBool empty)
 
352
{
 
353
    CqImagePixel * pie;
 
354
 
 
355
    TqInt datasize = QGetRenderContext()->GetOutputDataTotalSize();
 
356
    m_aDatas.resize( datasize * Width() * Height() );
 
357
    m_aCoverages.resize( Width() * Height() );
 
358
 
 
359
    TqInt xmax = static_cast<TqInt>( CEIL( ( FilterXWidth() - 1 ) * 0.5f ) );
 
360
    TqInt ymax = static_cast<TqInt>( CEIL( ( FilterYWidth() - 1 ) * 0.5f ) );
 
361
    TqFloat xfwo2 = FilterXWidth() * 0.5f;
 
362
    TqFloat yfwo2 = FilterYWidth() * 0.5f;
 
363
    TqInt numsubpixels = ( m_PixelXSamples * m_PixelYSamples );
 
364
 
 
365
    TqInt numperpixel = numsubpixels * numsubpixels;
 
366
    TqInt       xlen = Width() + FilterXWidth();
 
367
 
 
368
    TqInt SampleCount = 0;
 
369
    CqColor imager;
 
370
 
 
371
    TqInt x, y;
 
372
    TqInt i = 0;
 
373
 
 
374
    TqBool fImager = ( QGetRenderContext() ->optCurrent().GetStringOption( "System", "Imager" ) [ 0 ] != "null" );
 
375
 
 
376
    TqInt endy = YOrigin() + Height();
 
377
    TqInt endx = XOrigin() + Width();
 
378
 
 
379
    for ( y = YOrigin(); y < endy ; y++ )
 
380
    {
 
381
        TqFloat ycent = y + 0.5f;
 
382
        for ( x = XOrigin(); x < endx ; x++ )
 
383
        {
 
384
            TqFloat xcent = x + 0.5f;
 
385
            TqFloat gTot = 0.0;
 
386
            SampleCount = 0;
 
387
            std::valarray<TqFloat> samples( 0.0f, datasize);
 
388
 
 
389
            if(!empty)
 
390
            {
 
391
                TqInt fx, fy;
 
392
                // Get the element at the upper left corner of the filter area.
 
393
                ImageElement( x - xmax, y - ymax, pie );
 
394
                for ( fy = -ymax; fy <= ymax; fy++ )
 
395
                {
 
396
                    CqImagePixel* pie2 = pie;
 
397
                    for ( fx = -xmax; fx <= xmax; fx++ )
 
398
                    {
 
399
                        TqInt index = ( ( ( fy + ymax ) * FilterXWidth() ) + ( fx + xmax ) ) * numperpixel;
 
400
                        // Now go over each subsample within the pixel
 
401
                        TqInt sx, sy;
 
402
                        TqInt sampleIndex = 0;
 
403
                        for ( sy = 0; sy < m_PixelYSamples; sy++ )
 
404
                        {
 
405
                            for ( sx = 0; sx < m_PixelXSamples; sx++ )
 
406
                            {
 
407
                                TqInt sindex = index + ( ( ( sy * m_PixelXSamples ) + sx ) * numsubpixels );
 
408
                                const SqSampleData& sampleData = pie2->SampleData( sampleIndex );
 
409
                                CqVector2D vecS = sampleData.m_Position;
 
410
                                vecS -= CqVector2D( xcent, ycent );
 
411
                                if ( vecS.x() >= -xfwo2 && vecS.y() >= -yfwo2 && vecS.x() <= xfwo2 && vecS.y() <= yfwo2 )
 
412
                                {
 
413
                                    TqInt cindex = sindex + sampleData.m_SubCellIndex;
 
414
                                    TqFloat g = m_aFilterValues[ cindex ];
 
415
                                    gTot += g;
 
416
                                    if ( pie2->Values( sx, sy ).size() > 0 )
 
417
                                    {
 
418
                                        SqImageSample* pSample = &pie2->Values( sx, sy ) [ 0 ];
 
419
                                        samples += pSample->m_Data * g;
 
420
                                        SampleCount++;
 
421
                                    }
 
422
                                }
 
423
                                sampleIndex++;
 
424
                            }
 
425
                        }
 
426
                        pie2++;
 
427
                    }
 
428
                    pie += xlen;
 
429
                }
 
430
            }
 
431
 
 
432
 
 
433
            for ( TqInt k = 0; k < datasize; k ++)
 
434
                m_aDatas[ i*datasize + k ] = samples[k] / gTot;
 
435
 
 
436
            // Set depth to infinity if no samples.
 
437
            if ( SampleCount <= 0 )
 
438
                m_aDatas[ i*datasize+6 ] = FLT_MAX;
 
439
 
 
440
            if ( SampleCount >= numsubpixels)
 
441
                m_aCoverages[ i ] = 1.0;
 
442
            else
 
443
                m_aCoverages[ i ] = ( TqFloat ) SampleCount / ( TqFloat ) (numsubpixels );
 
444
 
 
445
            i++;
 
446
        }
 
447
    }
 
448
 
 
449
    i = 0;
 
450
    ImageElement( XOrigin(), YOrigin(), pie );
 
451
    endy = Height();
 
452
    endx = Width();
 
453
 
 
454
    for ( y = 0; y < endy; y++ )
 
455
    {
 
456
        CqImagePixel* pie2 = pie;
 
457
        for ( x = 0; x < endx; x++ )
 
458
        {
 
459
            for (TqInt k=0; k < datasize; k++)
 
460
                pie2->GetPixelSample().m_Data[k] = m_aDatas[ i * datasize + k ];
 
461
            pie2->SetCoverage( m_aCoverages[ i++ ] );
 
462
            pie2++;
 
463
        }
 
464
        pie += xlen;
 
465
    }
 
466
 
 
467
    endy = YOrigin() + Height();
 
468
    endx = XOrigin() + Width();
 
469
 
 
470
    if ( NULL != QGetRenderContext() ->optCurrent().pshadImager() && NULL != QGetRenderContext() ->optCurrent().pshadImager() ->pShader() )
 
471
    {
 
472
        QGetRenderContext() ->Stats().MakeFilterBucket().Stop();
 
473
        // Init & Execute the imager shader
 
474
 
 
475
        QGetRenderContext() ->optCurrent().InitialiseColorImager( this );
 
476
 
 
477
        if ( fImager )
 
478
        {
 
479
            i = 0;
 
480
            ImageElement( XOrigin(), YOrigin(), pie );
 
481
            for ( y = YOrigin(); y < endy ; y++ )
 
482
            {
 
483
                CqImagePixel* pie2 = pie;
 
484
                for ( x = XOrigin(); x < endx ; x++ )
 
485
                {
 
486
                    imager = QGetRenderContext() ->optCurrent().GetColorImager( x , y );
 
487
                    // Normal case will be to poke the alpha from the image shader and
 
488
                    // multiply imager color with it... but after investigation alpha is always
 
489
                    // == 1 after a call to imager shader in 3delight and BMRT.
 
490
                    // Therefore I did not ask for alpha value and set directly the pCols[i]
 
491
                    // with imager value. see imagers.cpp
 
492
                    pie2->SetColor( imager );
 
493
                    imager = QGetRenderContext() ->optCurrent().GetOpacityImager( x , y );
 
494
                    pie2->SetOpacity( imager );
 
495
                    pie2++;
 
496
                    i++;
 
497
                }
 
498
                pie += xlen;
 
499
            }
 
500
        }
 
501
        QGetRenderContext() ->Stats().MakeFilterBucket().Start();
 
502
    }
 
503
}
 
504
 
 
505
 
 
506
//----------------------------------------------------------------------
 
507
/** Expose the samples in this bucket according to specified gain and gamma settings.
 
508
 */
 
509
 
 
510
void CqBucket::ExposeBucket()
 
511
{
 
512
    if ( QGetRenderContext() ->optCurrent().GetFloatOption( "System", "Exposure" ) [ 0 ] == 1.0 &&
 
513
            QGetRenderContext() ->optCurrent().GetFloatOption( "System", "Exposure" ) [ 1 ] == 1.0 )
 
514
        return ;
 
515
    else
 
516
    {
 
517
        CqImagePixel* pie;
 
518
        ImageElement( XOrigin(), YOrigin(), pie );
 
519
        TqInt x, y;
 
520
        TqFloat exposegain = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "Exposure" ) [ 0 ];
 
521
        TqFloat exposegamma = QGetRenderContext() ->optCurrent().GetFloatOption( "System", "Exposure" ) [ 1 ];
 
522
        TqFloat oneovergamma = 1.0f / exposegamma;
 
523
        TqFloat endx, endy;
 
524
        TqInt   nextx;
 
525
        endy = Height();
 
526
        endx = Width();
 
527
        nextx = Width() + FilterXWidth();
 
528
 
 
529
        for ( y = 0; y < endy; y++ )
 
530
        {
 
531
            CqImagePixel* pie2 = pie;
 
532
            for ( x = 0; x < endx; x++ )
 
533
            {
 
534
                // color=(color*gain)^1/gamma
 
535
                if ( exposegain != 1.0 )
 
536
                    pie2->SetColor( pie2->Color() * exposegain );
 
537
 
 
538
                if ( exposegamma != 1.0 )
 
539
                {
 
540
                    CqColor col = pie2->Color();
 
541
                    col.SetfRed ( pow( col.fRed (), oneovergamma ) );
 
542
                    col.SetfGreen( pow( col.fGreen(), oneovergamma ) );
 
543
                    col.SetfBlue ( pow( col.fBlue (), oneovergamma ) );
 
544
                    pie2->SetColor( col );
 
545
                }
 
546
                pie2++;
 
547
            }
 
548
            pie += nextx;
 
549
        }
 
550
    }
 
551
}
 
552
 
 
553
 
 
554
//----------------------------------------------------------------------
 
555
/** Quantize the samples in this bucket according to type.
 
556
 */
 
557
 
 
558
void CqBucket::QuantizeBucket()
 
559
{
 
560
    // Initiliaze the random with a value based on the X,Y coordinate
 
561
    static CqRandom random( 61 );
 
562
    TqFloat endx, endy;
 
563
    TqInt   nextx;
 
564
    endy = Height();
 
565
    endx = Width();
 
566
    nextx = Width() + FilterXWidth();
 
567
 
 
568
 
 
569
    if ( QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "DisplayMode" ) [ 0 ] & ModeRGB )
 
570
    {
 
571
        const TqFloat* pQuant = QGetRenderContext() ->optCurrent().GetFloatOption( "Quantize", "Color" );
 
572
        TqInt one = static_cast<TqInt>( pQuant [ 0 ] );
 
573
        TqInt min = static_cast<TqInt>( pQuant [ 1 ] );
 
574
        TqInt max = static_cast<TqInt>( pQuant [ 2 ] );
 
575
        double ditheramplitude = pQuant [ 3 ];
 
576
 
 
577
        // If settings are 0,0,0,0 then leave as floating point and we will save an FP tiff.
 
578
        if ( one == 0 && min == 0 && max == 0 )
 
579
            return ;
 
580
 
 
581
        CqImagePixel* pie;
 
582
        ImageElement( XOrigin(), YOrigin(), pie );
 
583
        TqInt x, y;
 
584
 
 
585
        for ( y = 0; y < endy; y++ )
 
586
        {
 
587
            CqImagePixel* pie2 = pie;
 
588
            for ( x = 0; x < endx; x++ )
 
589
            {
 
590
                double r, g, b;
 
591
                double _or, _og, _ob;
 
592
                double s = random.RandomFloat();
 
593
                CqColor col = pie2->Color();
 
594
                CqColor opa = pie2->Opacity();
 
595
                if ( modf( one * col.fRed () + ditheramplitude * s, &r ) > 0.5 ) r += 1;
 
596
                if ( modf( one * col.fGreen() + ditheramplitude * s, &g ) > 0.5 ) g += 1;
 
597
                if ( modf( one * col.fBlue () + ditheramplitude * s, &b ) > 0.5 ) b += 1;
 
598
                if ( modf( one * opa.fRed () + ditheramplitude * s, &_or ) > 0.5 ) _or += 1;
 
599
                if ( modf( one * opa.fGreen() + ditheramplitude * s, &_og ) > 0.5 ) _og += 1;
 
600
                if ( modf( one * opa.fBlue () + ditheramplitude * s, &_ob ) > 0.5 ) _ob += 1;
 
601
                r = CLAMP( r, min, max );
 
602
                g = CLAMP( g, min, max );
 
603
                b = CLAMP( b, min, max );
 
604
                _or = CLAMP( _or, min, max );
 
605
                _og = CLAMP( _og, min, max );
 
606
                _ob = CLAMP( _ob, min, max );
 
607
                col.SetfRed ( r );
 
608
                col.SetfGreen( g );
 
609
                col.SetfBlue ( b );
 
610
                opa.SetfRed ( _or );
 
611
                opa.SetfGreen( _og );
 
612
                opa.SetfBlue ( _ob );
 
613
                pie2->SetColor( col );
 
614
                pie2->SetOpacity( opa );
 
615
 
 
616
                pie2++;
 
617
            }
 
618
            pie += nextx;
 
619
        }
 
620
    }
 
621
 
 
622
    if ( QGetRenderContext() ->optCurrent().GetIntegerOption( "System", "DisplayMode" ) [ 0 ] & ModeZ )
 
623
    {
 
624
        const TqFloat* pQuant = QGetRenderContext() ->optCurrent().GetFloatOption( "Quantize", "Depth" );
 
625
        TqInt one = static_cast<TqInt>( pQuant [ 0 ] );
 
626
        TqInt min = static_cast<TqInt>( pQuant [ 1 ] );
 
627
        TqInt max = static_cast<TqInt>( pQuant [ 2 ] );
 
628
        double ditheramplitude = pQuant [ 3 ];
 
629
        if( ditheramplitude == 0.0f && one == 0 && min == 0 && max == 0 )
 
630
            return;
 
631
 
 
632
        CqImagePixel* pie;
 
633
        ImageElement( XOrigin(), YOrigin(), pie );
 
634
        TqInt x, y;
 
635
        for ( y = 0; y < endy; y++ )
 
636
        {
 
637
            CqImagePixel* pie2 = pie;
 
638
            for ( x = 0; x < endx; x++ )
 
639
            {
 
640
                double d;
 
641
                if ( modf( one * pie2->Depth() + ditheramplitude * random.RandomFloat(), &d ) > 0.5 ) d += 1;
 
642
                d = CLAMP( d, min, max );
 
643
                pie2->SetDepth( d );
 
644
                pie2++;
 
645
            }
 
646
            pie += nextx;
 
647
        }
 
648
    }
 
649
 
 
650
    // Now go through the other AOV's and quantize those if necessary.
 
651
    std::map<std::string, CqRenderer::SqOutputDataEntry>& DataMap = QGetRenderContext()->GetMapOfOutputDataEntries();
 
652
    std::map<std::string, CqRenderer::SqOutputDataEntry>::iterator entry;
 
653
    for( entry = DataMap.begin(); entry != DataMap.end(); entry++ )
 
654
    {
 
655
        const TqFloat* pQuant = QGetRenderContext() ->optCurrent().GetFloatOption( "Quantize", entry->first.c_str() );
 
656
        if( NULL != pQuant )
 
657
        {
 
658
            TqInt startindex = entry->second.m_Offset;
 
659
            TqInt endindex = startindex + entry->second.m_NumSamples;
 
660
            TqInt one = static_cast<TqInt>( pQuant [ 0 ] );
 
661
            TqInt min = static_cast<TqInt>( pQuant [ 1 ] );
 
662
            TqInt max = static_cast<TqInt>( pQuant [ 2 ] );
 
663
            double ditheramplitude = pQuant [ 3 ];
 
664
 
 
665
            CqImagePixel* pie;
 
666
            ImageElement( XOrigin(), YOrigin(), pie );
 
667
            TqInt x, y;
 
668
            for ( y = 0; y < endy; y++ )
 
669
            {
 
670
                CqImagePixel* pie2 = pie;
 
671
                for ( x = 0; x < endx; x++ )
 
672
                {
 
673
                    TqInt sampleindex;
 
674
                    for( sampleindex = startindex; sampleindex < endindex; sampleindex++ )
 
675
                    {
 
676
                        double d;
 
677
                        if ( modf( one * pie2->GetPixelSample().m_Data[sampleindex] + ditheramplitude * random.RandomFloat(), &d ) > 0.5 ) d += 1.0f;
 
678
                        d = CLAMP( d, min, max );
 
679
                        pie2->GetPixelSample().m_Data[sampleindex] = d;
 
680
                    }
 
681
                    pie2++;
 
682
                }
 
683
                pie += nextx;
 
684
            }
 
685
        }
 
686
    }
 
687
}
 
688
 
 
689
//----------------------------------------------------------------------
 
690
/** Clear any data on the bucket
 
691
 */
 
692
void CqBucket::ShutdownBucket()
 
693
{
 
694
    m_aieImage.clear();
 
695
    m_aFilterValues.clear();
 
696
        m_aCoverages.clear();
 
697
        m_aDatas.clear();
 
698
        std::vector<std::vector<CqVector2D> >::iterator i;
 
699
        for( i=m_aSamplePositions.begin(); i!=m_aSamplePositions.end(); i++ )
 
700
                (*i).clear();
 
701
        m_aSamplePositions.clear();
 
702
}
 
703
 
 
704
//---------------------------------------------------------------------
 
705
 
 
706
END_NAMESPACE( Aqsis )
 
707