[Aqsis-commits] SF.net SVN: aqsis: [1870] branches/beaker/bucketoverlapcache/renderer/ render
Brought to you by:
ltatkinson,
pgregory
From: <pgr...@us...> - 2008-01-29 22:05:12
|
Revision: 1870 http://aqsis.svn.sourceforge.net/aqsis/?rev=1870&view=rev Author: pgregory Date: 2008-01-29 14:05:15 -0800 (Tue, 29 Jan 2008) Log Message: ----------- * Reincarnate the old scan based MP sampling code. * Excise completely the old occlusion tree code. Seems to work on a simple test case, but not done RTS or speed testing on it yet. Initial impressions are positive (but I've seen that before, so not saying anything just yet). Modified Paths: -------------- branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.cpp branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.h branches/beaker/bucketoverlapcache/renderer/render/imagepixel.cpp branches/beaker/bucketoverlapcache/renderer/render/imagepixel.h branches/beaker/bucketoverlapcache/renderer/render/occlusion.cpp branches/beaker/bucketoverlapcache/renderer/render/occlusion.h branches/beaker/bucketoverlapcache/renderer/render/renderer.cpp Modified: branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.cpp =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.cpp 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.cpp 2008-01-29 22:05:15 UTC (rev 1870) @@ -774,48 +774,75 @@ // this function assumes that either dof or mb or both are being used. void CqImageBuffer::RenderMPG_MBOrDof( CqMicroPolygon* pMPG, - long xmin, long xmax, long ymin, long ymax, - bool IsMoving, bool UsingDof ) + long xmin, long xmax, long ymin, long ymax, + bool IsMoving, bool UsingDof ) { + CqBucket & Bucket = CurrentBucket(); + CqStats& theStats = QGetRenderContext() ->Stats(); + + const TqFloat* LodBounds = m_CurrentGridInfo.m_LodBounds; + bool UsingLevelOfDetail = LodBounds[ 0 ] >= 0.0f; + + TqInt sample_hits = 0; + TqFloat shd_rate = m_CurrentGridInfo.m_ShadingRate; + CqHitTestCache hitTestCache; - pMPG->CacheHitTestValues(&hitTestCache); + bool cachedHitData = false; + bool mustDraw = !m_CurrentGridInfo.m_IsCullable; + + TqInt iXSamples = PixelXSamples(); + TqInt iYSamples = PixelYSamples(); + + TqFloat opentime = m_CurrentGridInfo.m_ShutterOpenTime; TqFloat closetime = m_CurrentGridInfo.m_ShutterCloseTime; - - TqInt bound_maxMB = pMPG->cSubBounds(); - TqInt bound_maxMB_1 = bound_maxMB - 1; - for ( TqInt bound_numMB = 0; bound_numMB < bound_maxMB; bound_numMB++ ) + TqFloat timePerSample; + if(IsMoving) { - TqFloat time0 = m_CurrentGridInfo.m_ShutterOpenTime; - TqFloat time1 = m_CurrentGridInfo.m_ShutterCloseTime; - const CqBound& Bound = pMPG->SubBound( bound_numMB, time0 ); + TqInt numSamples = iXSamples * iYSamples; + timePerSample = (float)numSamples / ( closetime - opentime ); + } + TqInt bound_maxMB = pMPG->cSubBounds(); + TqInt bound_maxMB_1 = bound_maxMB - 1; + TqInt currentIndex = 0; + for ( TqInt bound_numMB = 0; bound_numMB < bound_maxMB; bound_numMB++ ) + { + TqFloat time0; + TqFloat time1; + const CqBound& Bound = pMPG->SubBound( bound_numMB, time0 ); + // get the index of the first and last samples that can fall inside // the time range of this bound + TqInt indexT0; + TqInt indexT1; if(IsMoving) { if ( bound_numMB != bound_maxMB_1 ) pMPG->SubBound( bound_numMB + 1, time1 ); else - time1 = closetime;//QGetRenderContext() ->poptCurrent()->GetFloatOptionWrite( "System", "Shutter" ) [ 1 ]; + time1 = closetime;//QGetRenderContext() ->optCurrent().GetFloatOptionWrite( "System", "Shutter" ) [ 1 ]; + + indexT0 = static_cast<TqInt>(FLOOR((time0 - opentime) * timePerSample)); + indexT1 = static_cast<TqInt>(CEIL((time1 - opentime) * timePerSample)); } - TqFloat maxCocX = 0.0f; - TqFloat maxCocY = 0.0f; + TqFloat maxCocX; + TqFloat maxCocY; - TqFloat bminx = 0.0f; - TqFloat bmaxx = 0.0f; - TqFloat bminy = 0.0f; - TqFloat bmaxy = 0.0f; - TqFloat bminz = 0.0f; - TqFloat bmaxz = 0.0f; + TqFloat bminx; + TqFloat bmaxx; + TqFloat bminy; + TqFloat bmaxy; + TqFloat bminz; + TqFloat bmaxz; // these values are the bound of the mpg not including dof extension. // reduce the mpg bound so it doesn't include the coc. - TqFloat mpgbminx = 0.0f; - TqFloat mpgbmaxx = 0.0f; - TqFloat mpgbminy = 0.0f; - TqFloat mpgbmaxy = 0.0f; - TqInt bound_maxDof = 0; + TqFloat mpgbminx; + TqFloat mpgbmaxx; + TqFloat mpgbminy; + TqFloat mpgbmaxy; + TqInt bound_maxDof; if(UsingDof) { const CqVector2D& minZCoc = QGetRenderContext()->GetCircleOfConfusion( Bound.vecMin().z() ); @@ -864,23 +891,142 @@ // if bounding box is outside our viewing range, then cull it. if ( bmaxx < (float)xmin || bmaxy < (float)ymin || - bminx > (float)xmax || bminy > (float)ymax || - bminz > ClippingFar() || bmaxz < ClippingNear()) + bminx > (float)xmax || bminy > (float)ymax || + bminz > ClippingFar() || bmaxz < ClippingNear()) { continue; } - if(UsingDof) + // Now go across all pixels touched by the micropolygon bound. + // The first pixel position is at (sX, sY), the last one + // at (eX, eY). + TqInt eX = CEIL( bmaxx ); + TqInt eY = CEIL( bmaxy ); + if ( eX > xmax ) eX = xmax; + if ( eY > ymax ) eY = ymax; + + TqInt sX = FLOOR( bminx ); + TqInt sY = FLOOR( bminy ); + if ( sY < ymin ) sY = ymin; + if ( sX < xmin ) sX = xmin; + + CqImagePixel* pie, *pie2; + + TqInt nextx = Bucket.RealWidth(); + Bucket.ImageElement( sX, sY, pie ); + + for( int iY = sY; iY < eY; ++iY) { - CqBound DofBound(bminx, bminy, bminz, bmaxx, bmaxy, bmaxz); - CqOcclusionBox::KDTree()->SampleMPG(pMPG, DofBound, IsMoving, time0, time1, true, bound_numDof, m_CurrentMpgSampleInfo, m_CurrentGridInfo.m_LodBounds[0] >= 0.0f, m_CurrentGridInfo); + pie2 = pie; + pie += nextx; + + for(int iX = sX; iX < eX; ++iX, ++pie2) + { + TqInt index; + if(UsingDof) + { + // when using dof only one sample per pixel can + // possibbly hit (the one corresponding to the + // current bounding box). + index = pie2->GetDofOffsetIndex(bound_numDof); + } + else + { + // when using mb without dof, a range of samples + // may have times within the current mb bounding box. + index = indexT0; + } + // only bother sampling if the mpg is not occluded in this pixel. + //if(mustDraw || bminz <= pie2->SampleData(index).m_occlusionBox->MaxOpaqueZ()) + { + + // loop over potential samples + do + { + const SqSampleData& sampleData = pie2->SampleData( index ); + const CqVector2D& vecP = sampleData.m_Position; + const TqFloat time = sampleData.m_Time; + + index++; + + CqStats::IncI( CqStats::SPL_count ); + + if(IsMoving && (time < time0 || time > time1)) + { + continue; + } + + // check if sample lies inside mpg bounding box. + if ( UsingDof ) + { + CqBound DofBound(bminx, bminy, bminz, bmaxx, bmaxy, bmaxz); + + if(!DofBound.Contains2D( vecP )) + continue; + + // Check to see if the sample is within the sample's level of detail + if ( UsingLevelOfDetail) + { + TqFloat LevelOfDetail = sampleData.m_DetailLevel; + if ( LodBounds[ 0 ] > LevelOfDetail || LevelOfDetail >= LodBounds[ 1 ] ) + { + continue; + } + } + + + CqStats::IncI( CqStats::SPL_bound_hits ); + + // Now check if the subsample hits the micropoly + bool SampleHit; + TqFloat D; + + SampleHit = pMPG->Sample( sampleData, D, time, UsingDof ); + if ( SampleHit ) + { + sample_hits++; + // note index has already been incremented, so we use the previous value. + StoreSample( pMPG, pie2, index-1, D ); + } + } + else + { + if(!Bound.Contains2D( vecP )) + continue; + // Check to see if the sample is within the sample's level of detail + if ( UsingLevelOfDetail) + { + TqFloat LevelOfDetail = sampleData.m_DetailLevel; + if ( LodBounds[ 0 ] > LevelOfDetail || LevelOfDetail >= LodBounds[ 1 ] ) + { + continue; + } + } + + + CqStats::IncI( CqStats::SPL_bound_hits ); + + // Now check if the subsample hits the micropoly + bool SampleHit; + TqFloat D; + + pMPG->CacheHitTestValues(&hitTestCache); + cachedHitData = true; + + SampleHit = pMPG->Sample( sampleData, D, time ); + if ( SampleHit ) + { + sample_hits++; + // note index has already been incremented, so we use the previous value. + StoreSample( pMPG, pie2, index-1, D ); + } + } + } while (!UsingDof && index < indexT1); + } + } } - else - { - CqOcclusionBox::KDTree()->SampleMPG(pMPG, Bound, IsMoving, time0, time1, false, 0, m_CurrentMpgSampleInfo, m_CurrentGridInfo.m_LodBounds[0] >= 0.0f, m_CurrentGridInfo); - } } - } + } } @@ -889,16 +1035,242 @@ // simpler than the general case dealt with above. void CqImageBuffer::RenderMPG_Static( CqMicroPolygon* pMPG, long xmin, long xmax, long ymin, long ymax ) { + CqBucket & Bucket = CurrentBucket(); + CqStats& theStats = QGetRenderContext() ->Stats(); + + const TqFloat* LodBounds = m_CurrentGridInfo.m_LodBounds; + bool UsingLevelOfDetail = LodBounds[ 0 ] >= 0.0f; + + TqInt sample_hits = 0; + TqFloat shd_rate = m_CurrentGridInfo.m_ShadingRate; + CqHitTestCache hitTestCache; - pMPG->CacheHitTestValues(&hitTestCache); + bool cachedHitData = false; - const CqBound& Bound = pMPG->GetTotalBound(); + bool mustDraw = !m_CurrentGridInfo.m_IsCullable; - CqOcclusionBox::KDTree()->SampleMPG(pMPG, Bound, false, 0, 0, false, 0, m_CurrentMpgSampleInfo, m_CurrentGridInfo.m_LodBounds[0] >= 0.0f, m_CurrentGridInfo); + CqBound Bound = pMPG->GetTotalBound(); + + TqFloat bminx = Bound.vecMin().x(); + TqFloat bmaxx = Bound.vecMax().x(); + TqFloat bminy = Bound.vecMin().y(); + TqFloat bmaxy = Bound.vecMax().y(); + TqFloat bminz = Bound.vecMin().z(); + + // Now go across all pixels touched by the micropolygon bound. + // The first pixel position is at (sX, sY), the last one + // at (eX, eY). + TqInt eX = CEIL( bmaxx ); + TqInt eY = CEIL( bmaxy ); + if ( eX > xmax ) eX = xmax; + if ( eY > ymax ) eY = ymax; + + TqInt sX = FLOOR( bminx ); + TqInt sY = FLOOR( bminy ); + if ( sY < ymin ) sY = ymin; + if ( sX < xmin ) sX = xmin; + + CqImagePixel* pie, *pie2; + + TqInt iXSamples = PixelXSamples(); + TqInt iYSamples = PixelYSamples(); + + TqInt im = ( bminx < sX ) ? 0 : FLOOR( ( bminx - sX ) * iXSamples ); + TqInt in = ( bminy < sY ) ? 0 : FLOOR( ( bminy - sY ) * iYSamples ); + TqInt em = ( bmaxx > eX ) ? iXSamples : CEIL( ( bmaxx - ( eX - 1 ) ) * iXSamples ); + TqInt en = ( bmaxy > eY ) ? iYSamples : CEIL( ( bmaxy - ( eY - 1 ) ) * iYSamples ); + + TqInt nextx = Bucket.RealWidth(); + Bucket.ImageElement( sX, sY, pie ); + + for( int iY = sY; iY < eY; ++iY) + { + pie2 = pie; + pie += nextx; + + for(int iX = sX; iX < eX; ++iX, ++pie2) + { + // only bother sampling if the mpg is not occluded in this pixel. + //if(mustDraw || bminz <= pie2->SampleData(index).m_occlusionBox->MaxOpaqueZ()) + { + if(!cachedHitData) + { + pMPG->CacheHitTestValues(&hitTestCache); + cachedHitData = true; + } + + // Now sample the micropolygon at several subsample positions + // within the pixel. The subsample indices range from (start_m, n) + // to (end_m-1, end_n-1). + register int m, n; + n = ( iY == sY ) ? in : 0; + int end_n = ( iY == ( eY - 1 ) ) ? en : iYSamples; + int start_m = ( iX == sX ) ? im : 0; + int end_m = ( iX == ( eX - 1 ) ) ? em : iXSamples; + int index_start = n*iXSamples + start_m; + + for ( ; n < end_n; n++ ) + { + int index = index_start; + for ( m = start_m; m < end_m; m++, index++ ) + { + const SqSampleData& sampleData = pie2->SampleData( index ); + //if(mustDraw || bminz <= pie2->SampleData(index).m_occlusionBox->MaxOpaqueZ()) + { + const CqVector2D& vecP = sampleData.m_Position; + const TqFloat time = 0.0; + + CqStats::IncI( CqStats::SPL_count ); + + if(!Bound.Contains2D( vecP )) + continue; + + // Check to see if the sample is within the sample's level of detail + if ( UsingLevelOfDetail) + { + TqFloat LevelOfDetail = sampleData.m_DetailLevel; + if ( LodBounds[ 0 ] > LevelOfDetail || LevelOfDetail >= LodBounds[ 1 ] ) + { + continue; + } + } + + CqStats::IncI( CqStats::SPL_bound_hits ); + + // Now check if the subsample hits the micropoly + bool SampleHit; + TqFloat D; + + SampleHit = pMPG->Sample( sampleData, D, time ); + + if ( SampleHit ) + { + sample_hits++; + StoreSample( pMPG, pie2, index, D ); + } + } + } + index_start += iXSamples; + } + } + /* // Now compute the % of samples that hit... + TqInt scount = iXSamples * iYSamples; + TqFloat max_hits = scount * shd_rate; + TqInt hit_rate = ( sample_hits / max_hits ) / 0.125; + STATS_INC( MPG_sample_coverage0_125 + CLAMP( hit_rate - 1 , 0, 7 ) ); + */ } + } } +void CqImageBuffer::StoreSample( CqMicroPolygon* pMPG, CqImagePixel* pie2, TqInt index, TqFloat D ) +{ + bool Occludes = m_CurrentMpgSampleInfo.m_Occludes; + bool opaque = m_CurrentMpgSampleInfo.m_IsOpaque; + SqImageSample& currentOpaqueSample = pie2->OpaqueValues(index); + //static SqImageSample localImageVal( QGetRenderContext() ->GetOutputDataTotalSize() ); + SqImageSample localImageVal; + + SqImageSample& ImageVal = opaque ? currentOpaqueSample : localImageVal; + + std::deque<SqImageSample>& aValues = pie2->Values( index ); + std::deque<SqImageSample>::iterator sample = aValues.begin(); + std::deque<SqImageSample>::iterator end = aValues.end(); + + // return if the sample is occluded and can be culled. + if(opaque) + { + if((currentOpaqueSample.m_flags & SqImageSample::Flag_Valid) && + currentOpaqueSample.Data()[Sample_Depth] <= D) + { + return; + } + } + else + { + // Sort the color/opacity into the visible point list + // return if the sample is occluded and can be culled. + while( sample != end ) + { + if((*sample).Data()[Sample_Depth] >= D) + break; + + if(((*sample).m_flags & SqImageSample::Flag_Occludes) && + !(*sample).m_pCSGNode && m_CurrentGridInfo.m_IsCullable) + return; + + ++sample; + } + } + + ImageVal.Data()[Sample_Depth] = D ; + + CqStats::IncI( CqStats::SPL_hits ); + pMPG->MarkHit(); + + TqFloat* val = ImageVal.Data(); + val[ Sample_Red ] = m_CurrentMpgSampleInfo.m_Colour.fRed(); + val[ Sample_Green ] = m_CurrentMpgSampleInfo.m_Colour.fGreen(); + val[ Sample_Blue ] = m_CurrentMpgSampleInfo.m_Colour.fBlue(); + val[ Sample_ORed ] = m_CurrentMpgSampleInfo.m_Opacity.fRed(); + val[ Sample_OGreen ] = m_CurrentMpgSampleInfo.m_Opacity.fGreen(); + val[ Sample_OBlue ] = m_CurrentMpgSampleInfo.m_Opacity.fBlue(); + val[ Sample_Depth ] = D; + + // Now store any other data types that have been registered. + if(m_CurrentGridInfo.m_UsesDataMap) + { + StoreExtraData(pMPG, ImageVal); + } + + if(!opaque) + { + // If depth is exactly the same as previous sample, chances are we've + // hit a MPG grid line. + // \note: Cannot do this if there is CSG involved, as all samples must be taken and kept the same. + if ( sample != end && (*sample).Data()[Sample_Depth] == ImageVal.Data()[Sample_Depth] && !(*sample).m_pCSGNode ) + { + //(*sample).m_Data = ( (*sample).m_Data + val ) * 0.5f; + return; + } + } + + // Update max depth values + //if ( !( DisplayMode() & ModeZ ) && Occludes ) +// if ( opaque ) + // { +// if( D < pie2->SampleData(index).m_occlusionBox->MaxOpaqueZ() ) +// { +// pie2->SampleData(index).m_occlusionBox->SetMaxOpaqueZ(D); +// pie2->SampleData(index).m_occlusionBox->PropagateChanges(); +// CqOcclusionBox::UpdateDepth(pie2->SampleData(index).m_occlusionIndex, D); +// } +// } + + ImageVal.m_pCSGNode = pMPG->pGrid() ->pCSGNode(); + + ImageVal.m_flags = 0; + if ( Occludes ) + { + ImageVal.m_flags |= SqImageSample::Flag_Occludes; + } + if( m_CurrentGridInfo.m_IsMatte ) + { + ImageVal.m_flags |= SqImageSample::Flag_Matte; + } + + if(!opaque) + { + aValues.insert( sample, ImageVal ); + } + else + { + // mark this sample as having been written into. + ImageVal.m_flags |= SqImageSample::Flag_Valid; + } +} + void CqImageBuffer::StoreExtraData( CqMicroPolygon* pMPG, SqImageSample& sample) { std::map<std::string, CqRenderer::SqOutputDataEntry>& DataMap = QGetRenderContext() ->GetMapOfOutputDataEntries(); @@ -1355,7 +1727,6 @@ ImageComplete(); CqBucket::ShutdownBucket(); - CqOcclusionBox::DeleteHierarchy(); // Pass >100 through to progress to allow it to indicate completion. Modified: branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.h =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.h 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/imagebuffer.h 2008-01-29 22:05:15 UTC (rev 1870) @@ -299,6 +299,7 @@ void RenderMicroPoly( CqMicroPolygon* pMPG, long xmin, long xmax, long ymin, long ymax ); void RenderSurfaces( long xmin, long xmax, long ymin, long ymax, bool fImager, enum EqFilterDepth filterdepth, CqColor zThreshold ); void RenderImage(); + void StoreSample( CqMicroPolygon* pMPG, CqImagePixel* pie2, TqInt index, TqFloat D ); void StoreExtraData( CqMicroPolygon* pMPG, SqImageSample& sample); void RenderMPG_MBOrDof( CqMicroPolygon* pMPG, long xmin, long xmax, long ymin, long ymax, bool IsMoving, bool UsingDof ); Modified: branches/beaker/bucketoverlapcache/renderer/render/imagepixel.cpp =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/imagepixel.cpp 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/imagepixel.cpp 2008-01-29 22:05:15 UTC (rev 1870) @@ -557,11 +557,11 @@ } } -//std::deque<SqImageSample>& CqImagePixel::Values( TqInt index ) -//{ -// assert( index < m_XSamples*m_YSamples ); -// return ( CqBucket::SamplePoints()[m_SampleIndices[ index ]].m_Data ); -//} +std::deque<SqImageSample>& CqImagePixel::Values( TqInt index ) +{ + assert( index < m_XSamples*m_YSamples ); + return ( CqBucket::SamplePoints()[m_SampleIndices[ index ]].m_Data ); +} SqImageSample& CqImagePixel::OpaqueValues( TqInt index ) { Modified: branches/beaker/bucketoverlapcache/renderer/render/imagepixel.h =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/imagepixel.h 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/imagepixel.h 2008-01-29 22:05:15 UTC (rev 1870) @@ -345,7 +345,7 @@ * \param n The vertical index of the required sample point. * \return A Reference to a vector of SqImageSample data. */ - //std::list<SqImageSample>& Values( TqInt index ); + std::deque<SqImageSample>& Values( TqInt index ); SqImageSample& OpaqueValues( TqInt index ); Modified: branches/beaker/bucketoverlapcache/renderer/render/occlusion.cpp =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/occlusion.cpp 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/occlusion.cpp 2008-01-29 22:05:15 UTC (rev 1870) @@ -37,280 +37,10 @@ START_NAMESPACE( Aqsis ) -TqInt CqOcclusionTree::m_Tab = 0; - -CqOcclusionTree::CqOcclusionTree(TqInt dimension) - : m_Parent(0), m_Dimension(dimension) -{ - TqChildArray::iterator child = m_Children.begin(); - for(; child != m_Children.end(); ++child) - (*child) = 0; -} - -CqOcclusionTree::~CqOcclusionTree() -{ - TqChildArray::iterator child = m_Children.begin(); - for(; child != m_Children.end(); ++child) - { - if (*child != NULL) - { - delete (*child); - (*child) = NULL; - } - }; -} - -void -CqOcclusionTree::SplitNode(CqOcclusionTreePtr& a, CqOcclusionTreePtr& b) -{ - SortElements(m_Dimension); - - TqInt samplecount = m_SampleIndices.size(); - TqInt median = samplecount / 2; - - // Create the children nodes. - a = CqOcclusionTreePtr(new CqOcclusionTree()); - b = CqOcclusionTreePtr(new CqOcclusionTree()); - - a->m_MinSamplePoint = m_MinSamplePoint; - b->m_MinSamplePoint = m_MinSamplePoint; - a->m_MaxSamplePoint = m_MaxSamplePoint; - b->m_MaxSamplePoint = m_MaxSamplePoint; - TqInt newdim = ( m_Dimension + 1 ) % Dimensions(); - a->m_Dimension = b->m_Dimension = newdim; - - TqFloat dividingplane = CqBucket::ImageElement(m_SampleIndices[median].first).SampleData(m_SampleIndices[median].second).m_Position[m_Dimension]; - - a->m_MaxSamplePoint[m_Dimension] = dividingplane; - b->m_MinSamplePoint[m_Dimension] = dividingplane; - - TqFloat minTime = m_MaxTime, maxTime = m_MinTime; - TqInt minDofIndex = m_MaxDofBoundIndex, maxDofIndex = m_MinDofBoundIndex; - TqFloat minDetailLevel = m_MaxDetailLevel, maxDetailLevel = m_MinDetailLevel; - - TqInt i; - for(i = 0; i<median; ++i) - { - a->m_SampleIndices.push_back(m_SampleIndices[i]); - const SqSampleData& sample = CqBucket::ImageElement(m_SampleIndices[i].first).SampleData(m_SampleIndices[i].second); - minTime = MIN(minTime, sample.m_Time); - maxTime = MAX(maxTime, sample.m_Time); - minDofIndex = MIN(minDofIndex, sample.m_DofOffsetIndex); - maxDofIndex = MAX(maxDofIndex, sample.m_DofOffsetIndex); - minDetailLevel = MIN(minDetailLevel, sample.m_DetailLevel); - maxDetailLevel = MAX(maxDetailLevel, sample.m_DetailLevel); - } - a->m_MinTime = minTime; - a->m_MaxTime = maxTime; - a->m_MinDofBoundIndex = minDofIndex; - a->m_MaxDofBoundIndex = maxDofIndex; - a->m_MinDetailLevel = minDetailLevel; - a->m_MaxDetailLevel = maxDetailLevel; - - minTime = m_MaxTime, maxTime = m_MinTime; - minDofIndex = m_MaxDofBoundIndex, maxDofIndex = m_MinDofBoundIndex; - minDetailLevel = m_MaxDetailLevel, maxDetailLevel = m_MinDetailLevel; - for(; i<samplecount; ++i) - { - b->m_SampleIndices.push_back(m_SampleIndices[i]); - const SqSampleData& sample = CqBucket::ImageElement(m_SampleIndices[i].first).SampleData(m_SampleIndices[i].second); - minTime = MIN(minTime, sample.m_Time); - maxTime = MAX(maxTime, sample.m_Time); - minDofIndex = MIN(minDofIndex, sample.m_DofOffsetIndex); - maxDofIndex = MAX(maxDofIndex, sample.m_DofOffsetIndex); - minDetailLevel = MIN(minDetailLevel, sample.m_DetailLevel); - maxDetailLevel = MAX(maxDetailLevel, sample.m_DetailLevel); - } - b->m_MinTime = minTime; - b->m_MaxTime = maxTime; - b->m_MinDofBoundIndex = minDofIndex; - b->m_MaxDofBoundIndex = maxDofIndex; - b->m_MinDetailLevel = minDetailLevel; - b->m_MaxDetailLevel = maxDetailLevel; -} - -void CqOcclusionTree::ConstructTree() -{ - std::deque<CqOcclusionTreePtr> ChildQueue; - ChildQueue.push_back(this/*shared_from_this()*/); - - TqInt NonLeafCount = NumSamples() >= 1 ? 1 : 0; - TqInt split_counter = 0; - - while (NonLeafCount > 0 && ChildQueue.size() < s_ChildrenPerNode) - { - CqOcclusionTreePtr old = ChildQueue.front(); - ChildQueue.pop_front(); - if (old->NumSamples() > 1) - { - --NonLeafCount; - } - - CqOcclusionTreePtr a; - CqOcclusionTreePtr b; - old->SplitNode(a, b); - split_counter++; - if (a) - { - ChildQueue.push_back(a); - if (a->NumSamples() > 1) - { - ++NonLeafCount; - } - } - if (b) - { - ChildQueue.push_back(b); - if (b->NumSamples() > 1) - { - ++NonLeafCount; - } - }; - - if(split_counter >1 ) - delete old; - } - - TqChildArray::iterator ii; - std::deque<CqOcclusionTreePtr>::const_iterator jj; - for (ii = m_Children.begin(), jj = ChildQueue.begin(); jj != ChildQueue.end(); ++jj) - { - // Check if the child actually has any samples, ignore it if no. - if( (*jj)->NumSamples() > 0) - { - *ii = *jj; - (*ii)->m_Parent = this/*shared_from_this()*/; - if ((*ii)->NumSamples() > 1) - { - (*ii)->ConstructTree(); - } - ++ii; - } - } - - while (ii != m_Children.end()) - { - if (*ii != NULL) - { - delete *ii; - *ii = NULL; - } - ii++; - } -} - - -void CqOcclusionTree::InitialiseBounds() -{ - if (m_SampleIndices.size() < 1) - return; - - const SqSampleData& sample = CqBucket::ImageElement(m_SampleIndices[0].first).SampleData(m_SampleIndices[0].second); - TqFloat minXVal = sample.m_Position.x(); - TqFloat maxXVal = minXVal; - TqFloat minYVal = sample.m_Position.y(); - TqFloat maxYVal = minYVal; - TqFloat minTime = sample.m_Time; - TqFloat maxTime = minTime; - TqInt minDofIndex = sample.m_DofOffsetIndex; - TqInt maxDofIndex = minDofIndex; - TqFloat minDetailLevel = sample.m_DetailLevel; - TqFloat maxDetailLevel = minDetailLevel; - std::vector<std::pair<TqInt, TqInt> >::iterator i; - for(i = m_SampleIndices.begin()+1; i!=m_SampleIndices.end(); ++i) - { - const SqSampleData& sample = CqBucket::ImageElement(i->first).SampleData(i->second); - minXVal = MIN(minXVal, sample.m_Position.x()); - maxXVal = MAX(maxXVal, sample.m_Position.x()); - minYVal = MIN(minYVal, sample.m_Position.y()); - maxYVal = MAX(maxYVal, sample.m_Position.y()); - minTime = MIN(minTime, sample.m_Time); - maxTime = MAX(maxTime, sample.m_Time); - minDofIndex = MIN(minDofIndex, sample.m_DofOffsetIndex); - maxDofIndex = MAX(maxDofIndex, sample.m_DofOffsetIndex); - minDetailLevel = MIN(minDetailLevel, sample.m_DetailLevel); - maxDetailLevel = MAX(maxDetailLevel, sample.m_DetailLevel); - } - m_MinSamplePoint[0] = minXVal; - m_MaxSamplePoint[0] = maxXVal; - m_MinSamplePoint[1] = minYVal; - m_MaxSamplePoint[1] = maxYVal; - m_MinTime = minTime; - m_MaxTime = maxTime; - m_MinDofBoundIndex = minDofIndex; - m_MaxDofBoundIndex = maxDofIndex; - m_MinDetailLevel = minDetailLevel; - m_MaxDetailLevel = maxDetailLevel; -} - - -void CqOcclusionTree::UpdateBounds() -{ - if (m_Children[0]) - { - assert(m_SampleIndices.size() > 1); - - TqChildArray::iterator child = m_Children.begin(); - (*child)->UpdateBounds(); - - m_MinSamplePoint[0] = (*child)->m_MinSamplePoint[0]; - m_MaxSamplePoint[0] = (*child)->m_MaxSamplePoint[0]; - m_MinSamplePoint[1] = (*child)->m_MinSamplePoint[1]; - m_MaxSamplePoint[1] = (*child)->m_MaxSamplePoint[1]; - m_MinTime = (*child)->m_MinTime; - m_MaxTime = (*child)->m_MaxTime; - m_MinDofBoundIndex = (*child)->m_MinDofBoundIndex; - m_MaxDofBoundIndex = (*child)->m_MaxDofBoundIndex; - m_MinDetailLevel = (*child)->m_MinDetailLevel; - m_MaxDetailLevel = (*child)->m_MaxDetailLevel; - - for(++child; child != m_Children.end(); ++child) - { - if (*child) - { - (*child)->UpdateBounds(); - - m_MinSamplePoint[0] = std::min(m_MinSamplePoint[0], (*child)->m_MinSamplePoint[0]); - m_MaxSamplePoint[0] = std::max(m_MaxSamplePoint[0], (*child)->m_MaxSamplePoint[0]); - m_MinSamplePoint[1] = std::min(m_MinSamplePoint[1], (*child)->m_MinSamplePoint[1]); - m_MaxSamplePoint[1] = std::max(m_MaxSamplePoint[1], (*child)->m_MaxSamplePoint[1]); - m_MinTime = std::min(m_MinTime, (*child)->m_MinTime); - m_MaxTime = std::max(m_MaxTime, (*child)->m_MaxTime); - m_MinDofBoundIndex = std::min(m_MinDofBoundIndex, (*child)->m_MinDofBoundIndex); - m_MaxDofBoundIndex = std::max(m_MaxDofBoundIndex, (*child)->m_MaxDofBoundIndex); - m_MinDetailLevel = std::min(m_MinDetailLevel, (*child)->m_MinDetailLevel); - m_MaxDetailLevel = std::max(m_MaxDetailLevel, (*child)->m_MaxDetailLevel); - } - } - } - else - { - assert(m_SampleIndices.size() == 1); - - const SqSampleData& sample = Sample(); - m_MinSamplePoint[0] = m_MaxSamplePoint[0] = sample.m_Position[0]; - m_MinSamplePoint[1] = m_MaxSamplePoint[1] = sample.m_Position[1]; - m_MinTime = m_MaxTime = sample.m_Time; - m_MinDofBoundIndex = m_MaxDofBoundIndex = sample.m_DofOffsetIndex; - m_MinDetailLevel = m_MaxDetailLevel = sample.m_DetailLevel; - } -} - //---------------------------------------------------------------------- // Static Variables CqBucket* CqOcclusionBox::m_Bucket = NULL; - -bool CqOcclusionTree::CqOcclusionTreeComparator::operator()(const std::pair<TqInt, TqInt>& a, const std::pair<TqInt, TqInt>& b) -{ - const SqSampleData& A = CqBucket::ImageElement(a.first).SampleData(a.second); - const SqSampleData& B = CqBucket::ImageElement(b.first).SampleData(b.second); - return( A.m_Position[m_Dim] < B.m_Position[m_Dim] ); -} - - -CqOcclusionTreePtr CqOcclusionBox::m_KDTree; ///< KD Tree representing the samples in the bucket. - std::vector<CqOcclusionBox::SqOcclusionNode> CqOcclusionBox::m_depthTree; TqLong CqOcclusionBox::m_firstTerminalNode; @@ -330,18 +60,6 @@ CqOcclusionBox::~CqOcclusionBox() {} - - -//---------------------------------------------------------------------- -/** Delete the static hierarchy created in CreateHierachy(). static. -*/ -void CqOcclusionBox::DeleteHierarchy() -{ - delete m_KDTree; - m_KDTree = NULL; -} - - //------------------------------------------------------------------------------ /** Return the tree index for leaf node containing the given point. * @@ -411,27 +129,6 @@ assert( bucket ); m_Bucket = bucket; - if(!m_KDTree) - { - m_KDTree = CqOcclusionTreePtr(new CqOcclusionTree()); - // Setup the KDTree of samples - TqInt numpixels = bucket->RealHeight() * bucket->RealWidth(); - TqInt numsamples = bucket->PixelXSamples() * bucket->PixelYSamples(); - for ( TqInt j = 0; j < numpixels; j++ ) - { - // Gather all samples within the pixel - for ( TqInt i = 0; i < numsamples; i++ ) - { - m_KDTree->AddSample(std::pair<TqInt, TqInt>(j,i)); - } - } - // Now split the tree down until each leaf has only one sample. - m_KDTree->InitialiseBounds(); - m_KDTree->ConstructTree(); - } - - m_KDTree->UpdateBounds(); - // Now setup the new array based tree. // First work out how deep the tree needs to be. TqLong numLeafNodes = (bucket->RealHeight() * bucket->RealWidth()) * (bucket->PixelXSamples() * bucket->PixelYSamples()); @@ -532,188 +229,6 @@ } -void StoreExtraData( CqMicroPolygon* pMPG, SqImageSample& sample) -{ - std::map<std::string, CqRenderer::SqOutputDataEntry>& DataMap = QGetRenderContext() ->GetMapOfOutputDataEntries(); - std::map<std::string, CqRenderer::SqOutputDataEntry>::iterator entry; - for ( entry = DataMap.begin(); entry != DataMap.end(); ++entry ) - { - IqShaderData* pData; - if ( ( pData = pMPG->pGrid() ->FindStandardVar( entry->first.c_str() ) ) != NULL ) - { - switch ( pData->Type() ) - { - case type_float: - case type_integer: - { - TqFloat f; - pData->GetFloat( f, pMPG->GetIndex() ); - sample.Data()[ entry->second.m_Offset ] = f; - break; - } - case type_point: - case type_normal: - case type_vector: - case type_hpoint: - { - CqVector3D v; - pData->GetPoint( v, pMPG->GetIndex() ); - sample.Data()[ entry->second.m_Offset ] = v.x(); - sample.Data()[ entry->second.m_Offset + 1 ] = v.y(); - sample.Data()[ entry->second.m_Offset + 2 ] = v.z(); - break; - } - case type_color: - { - CqColor c; - pData->GetColor( c, pMPG->GetIndex() ); - sample.Data()[ entry->second.m_Offset ] = c.fRed(); - sample.Data()[ entry->second.m_Offset + 1 ] = c.fGreen(); - sample.Data()[ entry->second.m_Offset + 2 ] = c.fBlue(); - break; - } - case type_matrix: - { - CqMatrix m; - pData->GetMatrix( m, pMPG->GetIndex() ); - TqFloat* pElements = m.pElements(); - sample.Data()[ entry->second.m_Offset ] = pElements[ 0 ]; - sample.Data()[ entry->second.m_Offset + 1 ] = pElements[ 1 ]; - sample.Data()[ entry->second.m_Offset + 2 ] = pElements[ 2 ]; - sample.Data()[ entry->second.m_Offset + 3 ] = pElements[ 3 ]; - sample.Data()[ entry->second.m_Offset + 4 ] = pElements[ 4 ]; - sample.Data()[ entry->second.m_Offset + 5 ] = pElements[ 5 ]; - sample.Data()[ entry->second.m_Offset + 6 ] = pElements[ 6 ]; - sample.Data()[ entry->second.m_Offset + 7 ] = pElements[ 7 ]; - sample.Data()[ entry->second.m_Offset + 8 ] = pElements[ 8 ]; - sample.Data()[ entry->second.m_Offset + 9 ] = pElements[ 9 ]; - sample.Data()[ entry->second.m_Offset + 10 ] = pElements[ 10 ]; - sample.Data()[ entry->second.m_Offset + 11 ] = pElements[ 11 ]; - sample.Data()[ entry->second.m_Offset + 12 ] = pElements[ 12 ]; - sample.Data()[ entry->second.m_Offset + 13 ] = pElements[ 13 ]; - sample.Data()[ entry->second.m_Offset + 14 ] = pElements[ 14 ]; - sample.Data()[ entry->second.m_Offset + 15 ] = pElements[ 15 ]; - break; - } - default: - // left blank to avoid compiler warnings about unhandled - // types - break; - } - } - } -} - - - -void CqOcclusionTree::SampleMPG( CqMicroPolygon* pMPG, const CqBound& bound, bool usingMB, TqFloat time0, TqFloat time1, bool usingDof, TqInt dofboundindex, SqMpgSampleInfo& MpgSampleInfo, bool usingLOD, SqGridInfo& gridInfo) -{ - // Check the current tree level, and if only one leaf, sample the MP, otherwise, pass it down to the left - // and/or right side of the tree if it crosses. - if(NumSamples() == 1) - { - // Sample the MPG - SqSampleData& sample = Sample(); - bool SampleHit; - TqFloat D; - - CqStats::IncI( CqStats::SPL_count ); - SampleHit = pMPG->Sample(sample, D, sample.m_Time, usingDof ); - - if ( SampleHit ) - { - bool Occludes = MpgSampleInfo.m_Occludes; - bool opaque = MpgSampleInfo.m_IsOpaque; - - SqImageSample& currentOpaqueSample = sample.m_OpaqueSample; - static SqImageSample localImageVal; - - SqImageSample& ImageVal = opaque ? currentOpaqueSample : localImageVal; - - std::deque<SqImageSample>& aValues = sample.m_Data; - - // return if the sample is occluded and can be culled. - // TODO: should this only be done if the current sample is opaque? Why? - if(opaque) - { - if((currentOpaqueSample.m_flags & SqImageSample::Flag_Valid) && - currentOpaqueSample.Data()[Sample_Depth] <= D) - { - return; - } - } - - CqStats::IncI( CqStats::SPL_hits ); - pMPG->MarkHit(); - - TqFloat* val = ImageVal.Data(); - const CqColor& col = MpgSampleInfo.m_Colour; - const CqColor& opa = MpgSampleInfo.m_Opacity; - val[ 0 ] = col[0]; - val[ 1 ] = col[1]; - val[ 2 ] = col[2]; - val[ 3 ] = opa[0]; - val[ 4 ] = opa[1]; - val[ 5 ] = opa[2]; - val[ 6 ] = D; - - // Now store any other data types that have been registered. - if(gridInfo.m_UsesDataMap) - { - StoreExtraData(pMPG, ImageVal); - } - - // \note: There used to be a test here to see if the current sample is 'exactly' - // the same depth as the nearest in the list, ostensibly to check for a 'grid line' hit - // but it didn't make sense, so was removed. - - if(pMPG->pGrid()->usesCSG()) - ImageVal.m_pCSGNode = pMPG->pGrid() ->pCSGNode(); - - ImageVal.m_flags = 0; - if ( Occludes ) - { - ImageVal.m_flags |= SqImageSample::Flag_Occludes; - } - if( gridInfo.m_IsMatte ) - { - ImageVal.m_flags |= SqImageSample::Flag_Matte; - } - - if(!opaque) - { - aValues.push_back( ImageVal ); - } - else - { - // mark this sample as having been written into. - ImageVal.m_flags |= SqImageSample::Flag_Valid; - } - } - } - else - { - TqChildArray::iterator child; - TqChildArray::iterator end = m_Children.end(); - for(child = m_Children.begin(); child != end; ++child) - { - if (!*child) - continue; - - if( (!usingDof || ((dofboundindex >= (*child)->m_MinDofBoundIndex) && (dofboundindex <= (*child)->m_MaxDofBoundIndex )) ) - && (!usingMB || ((time0 <= (*child)->m_MaxTime) && (time1 >= (*child)->m_MinTime)) ) - && (!usingLOD || ((gridInfo.m_LodBounds[0] <= (*child)->m_MaxDetailLevel) && (gridInfo.m_LodBounds[1] >= (*child)->m_MinDetailLevel)) ) - && (bound.Intersects((*child)->m_MinSamplePoint, (*child)->m_MaxSamplePoint)) ) - { - //if(bound.vecMin().z() <= (*child)->m_MaxOpaqueZ || !gridInfo.m_IsCullable) - { - (*child)->SampleMPG(pMPG, bound, usingMB, time0, time1, usingDof, dofboundindex, MpgSampleInfo, usingLOD, gridInfo); - } - } - } - } -} - TqFloat CqOcclusionBox::propagateDepths(std::vector<CqOcclusionBox::SqOcclusionNode>::size_type index) { // Check if it's a terminal node. @@ -764,35 +279,5 @@ } -/*void CqOcclusionTree::OutputTree(const char* name) -{ - std::ofstream strFile(name, std::ios_base::out|std::ios_base::app); - - strFile << - "(" << m_Tab << ", " << - "(" << m_MinSamplePoint[0] << ", " << m_MinSamplePoint[1] << "), " << - "(" << m_MaxSamplePoint[0] << ", " << m_MinSamplePoint[1] << "), " << - "(" << m_MaxSamplePoint[0] << ", " << m_MinSamplePoint[1] << "), " << - "(" << m_MaxSamplePoint[0] << ", " << m_MaxSamplePoint[1] << "), " << - "(" << m_MaxSamplePoint[0] << ", " << m_MaxSamplePoint[1] << "), " << - "(" << m_MinSamplePoint[0] << ", " << m_MaxSamplePoint[1] << "), " << - "(" << m_MinSamplePoint[0] << ", " << m_MaxSamplePoint[1] << "), " << - "(" << m_MinSamplePoint[0] << ", " << m_MinSamplePoint[1] << ")" << - "), " << - std::endl; - - TqChildArray::iterator child; - for(child = m_Children.begin(); child != m_Children.end(); ++child) - { - if (*child && (*child)->NumSamples() > 1) - { - m_Tab++; - (*child)->OutputTree(name); - m_Tab--; - } - } -} -*/ - END_NAMESPACE( Aqsis ) Modified: branches/beaker/bucketoverlapcache/renderer/render/occlusion.h =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/occlusion.h 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/occlusion.h 2008-01-29 22:05:15 UTC (rev 1870) @@ -45,118 +45,13 @@ struct SqMpgSampleInfo; struct SqGridInfo; -class CqOcclusionTree; -//typedef boost::shared_ptr<CqOcclusionTree> CqOcclusionTreePtr; -//typedef boost::weak_ptr<CqOcclusionTree> CqOcclusionTreeWeakPtr; -typedef CqOcclusionTree* CqOcclusionTreePtr; -typedef CqOcclusionTree* CqOcclusionTreeWeakPtr; - - -/** \brief The CqOcclusionKDTreeData class - Specialisation of the KDTree data class to support generation of a KDTree - representing the sample data of a bucket. -*/ -class CqOcclusionTree// : public boost::enable_shared_from_this<CqOcclusionTree> -{ - class CqOcclusionTreeComparator - { - public: - CqOcclusionTreeComparator(TqInt dimension) : m_Dim( dimension ) - {} - - bool operator()(const std::pair<TqInt, TqInt>& a, const std::pair<TqInt, TqInt>& b); - - private: - TqInt m_Dim; - }; - - public: - CqOcclusionTree(TqInt dimension = 0); - ~CqOcclusionTree(); - - void SortElements(TqInt dimension) - { - std::sort(m_SampleIndices.begin(), m_SampleIndices.end(), CqOcclusionTreeComparator(dimension) ); - } - TqInt Dimensions() const - { - return(2); - } - - /** - * \todo Review: Unused parameter index; Could this be const? - */ - SqSampleData& Sample(TqInt index = 0) - { - return(CqBucket::ImageElement(m_SampleIndices[0].first).SampleData(m_SampleIndices[0].second)); - } - - void AddSample(const std::pair<TqInt, TqInt>& sample) - { - m_SampleIndices.push_back(sample); - } - void ConstructTree(); - void OutputTree(const char* name); - - void InitialiseBounds(); - void UpdateBounds(); - - void SampleMPG( CqMicroPolygon* pMPG, const CqBound& bound, bool usingMB, TqFloat time0, TqFloat time1, bool usingDof, TqInt dofboundindex, SqMpgSampleInfo& MpgSampleInfo, bool usingLOD, SqGridInfo& gridInfo); - - TqInt NumSamples() const - { - return(m_SampleIndices.size()); - } - - const CqVector2D& MinSamplePoint() const - { - return(m_MinSamplePoint); - } - - const CqVector2D& MaxSamplePoint() const - { - return(m_MaxSamplePoint); - } - - private: - enum { s_ChildrenPerNode = 4 }; - typedef boost::array<CqOcclusionTreePtr,s_ChildrenPerNode> TqChildArray; - - typedef std::vector<std::pair<TqInt, TqInt> > TqSampleIndices; - - void SplitNode(CqOcclusionTreePtr& a, CqOcclusionTreePtr& b); - - CqOcclusionTreeWeakPtr m_Parent; - TqInt m_Dimension; - CqVector2D m_MinSamplePoint; - CqVector2D m_MaxSamplePoint; - TqFloat m_MinTime; - TqFloat m_MaxTime; - TqInt m_MinDofBoundIndex; - TqInt m_MaxDofBoundIndex; - TqFloat m_MinDetailLevel; - TqFloat m_MaxDetailLevel; - TqChildArray m_Children; - TqSampleIndices m_SampleIndices; - - public: - static TqInt m_Tab; -}; - - class CqOcclusionBox { public: - static void DeleteHierarchy(); static void SetupHierarchy( CqBucket* bucket, TqInt xMin, TqInt yMin, TqInt xMax, TqInt yMax ); static bool CanCull( CqBound* bound ); - static CqOcclusionTreePtr& KDTree() - { - return(m_KDTree); - } - struct SqOcclusionNode { SqOcclusionNode(TqFloat D) : depth(D) {} @@ -173,7 +68,6 @@ ~CqOcclusionBox(); static CqBucket* m_Bucket; - static CqOcclusionTreePtr m_KDTree; ///< Tree representing the samples in the bucket. static std::vector<SqOcclusionNode> m_depthTree; static TqLong m_firstTerminalNode; ///< The index in the depth tree of the first terminal node. }; Modified: branches/beaker/bucketoverlapcache/renderer/render/renderer.cpp =================================================================== --- branches/beaker/bucketoverlapcache/renderer/render/renderer.cpp 2008-01-29 16:55:46 UTC (rev 1869) +++ branches/beaker/bucketoverlapcache/renderer/render/renderer.cpp 2008-01-29 22:05:15 UTC (rev 1870) @@ -810,7 +810,6 @@ m_pDDManager = realDDManager; CqTextureMap::FlushCache(); - CqOcclusionBox::DeleteHierarchy(); clippingVolume().clear(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |