VCRA-SZCZERBACKI-PointBasedRendering/ABuffer.cpp

00001 
00002 #include "ABuffer.h"
00003 
00004 //=======================================================================================
00005 //=======================================================================================
00006 
00007 ABuffer::ABuffer(int w,int h,int subpixels)
00008 {
00009         SS_ASSERT(w > 0);
00010         SS_ASSERT(h > 0);
00011         SS_ASSERT(subpixels > 0);
00012 
00013         m_width                         = w;
00014         m_height                        = h;
00015         m_subpixels                     = subpixels;
00016         m_oofsubpixels          = 1.0f / (float)subpixels;
00017 
00018         m_firstFragments = new int[w*h*subpixels];
00019         m_fragmentsAllocated = 4*w*h*subpixels;
00020         m_fragments.resize(m_fragmentsAllocated);
00021 
00022         m_sortBuffer.resize(100);
00023 
00024         clear();
00025 }
00026 
00027 //=======================================================================================
00028 //=======================================================================================
00029 
00030 ABuffer::~ABuffer(void)
00031 {
00032         if( m_firstFragments )
00033         {
00034                 delete[] m_firstFragments;
00035         }
00036         m_firstFragments = NULL;
00037         m_width = 0;
00038         m_height = 0;
00039         m_subpixels = 0;
00040 }
00041 
00042 //=======================================================================================
00043 //=======================================================================================
00044 
00045 void ABuffer::clear(void)
00046 {
00047         memset(m_firstFragments,-1,sizeof(int)*m_width*m_height*m_subpixels);
00048 
00049         m_firstFreeFragment = 0;
00050         m_averageFragmentsPerPixel = 0;
00051 }
00052 
00053 //=======================================================================================
00054 //=======================================================================================
00055 
00056 void ABuffer::appendFragment(int x, int y, int subpixel, const ABuffer::Fragment &f)
00057 {
00058         SS_ASSERT(x>=0&&x<m_width);
00059         SS_ASSERT(y>=0&&y<m_height);
00060         SS_ASSERT(subpixel>=0&&subpixel<m_subpixels);
00061 
00062         int &stub = m_firstFragments[(y*m_width+x)*m_subpixels+subpixel];
00063 
00064         //allocate new one
00065         if(m_firstFreeFragment == m_fragmentsAllocated)
00066         {
00067                 svPrint("abuffer fragment resize: %d => %d\n",m_fragmentsAllocated,m_fragmentsAllocated*2);
00068                 m_fragmentsAllocated *= 2;
00069                 m_fragments.resize(m_fragmentsAllocated);
00070         }
00071         int newf = m_firstFreeFragment++;
00072         m_fragments[newf] = f;
00073         m_fragments[newf].nextFragment = stub;
00074         stub = newf;
00075 }
00076 
00077 //=======================================================================================
00078 //=======================================================================================
00079 
00080 void ABuffer::collapseToFrameBuffer     (Color* frameBuffer, const Vector4 &background, bool zrange, float zthreshold)
00081 {
00082         int totalFragments = 0;
00083         int totalPixels = 0;
00084 
00085         for(int y=0;y<m_height;y++)
00086         for(int x=0;x<m_width;x++)
00087         {
00088                 Vector4 pixelcolor(0,0,0,0);
00089 
00090                 for(int j=0;j<m_subpixels;++j)
00091                 {
00092                         unsigned int coverageMask = 0;
00093                         Vector4 subpixelcolor(0,0,0,0);
00094 
00095                         //insert fragments into sort buffer
00096                         int fragmentCount = 0;
00097                         int fragmentIndex = m_firstFragments[(y*m_width+x)*m_subpixels+j];
00098                         while(fragmentIndex != -1)
00099                         {
00100                                 if( fragmentCount >= m_sortBuffer.size() )
00101                                 {
00102                                         svPrint("abuffer sortbuffer resize: %d => %d\n",m_sortBuffer.size(),m_sortBuffer.size()*2);
00103                                         m_sortBuffer.resize( fragmentCount * 2 );
00104                                 }
00105                                 m_sortBuffer[fragmentCount] = &m_fragments[fragmentIndex];                              // store fragment pointer
00106                                 fragmentIndex                            = m_fragments[fragmentIndex].nextFragment;     // traverse linked list
00107                                 fragmentCount++;
00108                         }
00109                         //sort fragments (insertion sort)
00110                         for(int i=0;i<fragmentCount-1;i++)
00111                         {
00112                                 for(int k=i+1;k<fragmentCount;k++)
00113                                 {
00114                                         if( (zrange && (m_sortBuffer[i]->zmin > m_sortBuffer[k]->zmin)) ||
00115                                                 (!zrange && (m_sortBuffer[i]->z > m_sortBuffer[k]->z)) )
00116                                         {
00117                                                 swap( m_sortBuffer[i], m_sortBuffer[k]);
00118                                         }
00119                                 }
00120                         }
00121                         if( fragmentCount )
00122                         {
00123                                 totalFragments += fragmentCount;
00124                                 totalPixels++;
00125                         }
00126 
00127                         // outer loop combines separate surfaces
00128                         int i = 0;
00129                         while(i < fragmentCount)
00130                         {
00131                                 const Fragment *f1 = m_sortBuffer[i];
00132                                 i++;
00133 
00134                                 float surfaceweight = f1->weight;
00135                                 Vector4 surfacecolor;
00136                                 f1->color.toVector4( surfacecolor );
00137                                 surfacecolor *= surfaceweight;
00138 
00139                                 // inner loop collects fragments of one connected surface
00140                                 if( !zrange )
00141                                 {
00142                                         //zthreshold comparison
00143                                         float prevz = f1->z;
00144                                         while(i < fragmentCount)
00145                                         {
00146                                                 const Fragment *f2 = m_sortBuffer[i];
00147 
00148                                                 if( f2->dotSign != f1->dotSign ) break; //facing the opposite directions
00149                                                 if( f2->z > prevz + zthreshold ) break; //no depth overlap
00150 
00151                                                 surfacecolor += f2->color.toVector4() * f2->weight;
00152                                                 surfaceweight += f2->weight;
00153 
00154                                                 prevz = f2->z;
00155                                                 i++;
00156                                                 f1 = f2;
00157                                         }
00158                                 }
00159                                 else
00160                                 {
00161                                         //zrange comparison
00162                                         float zmax = f1->zmax;
00163                                         while(i < fragmentCount)
00164                                         {
00165                                                 const Fragment *f2 = m_sortBuffer[i];
00166 
00167                                                 if( f2->dotSign != f1->dotSign ) break; //facing the opposite directions
00168                                                 if( f2->zmin > zmax ) break;    //no depth overlap
00169                                                 if( f2->zmax > zmax ) zmax = f2->zmax;
00170 
00171                                                 surfacecolor += f2->color.toVector4() * f2->weight;
00172                                                 surfaceweight += f2->weight;
00173 
00174                                                 i++;
00175                                                 f1 = f2;
00176                                         }
00177                                 }
00178 
00179                                 surfacecolor *= 1.0f/surfaceweight;     //normalize color
00180 
00181                                 if( surfacecolor.w >= 0.999f )
00182                                 {       //opaque
00183                                         surfacecolor.w = 1.0f;
00184                                         coverageMask = 1;       //surface occludes the rest of the surfaces
00185                                 }
00186 
00187                                 subpixelcolor += surfacecolor * (1.0f - subpixelcolor.w);
00188 
00189                                 if( coverageMask )
00190                                         break;  //no more visible surfaces, so early exit
00191                         }
00192 
00193                         //if no full coverage, blend with the background color
00194                         if( !coverageMask )
00195                                 subpixelcolor += background * (1.0f - subpixelcolor.w);
00196                         pixelcolor += subpixelcolor;
00197                 }
00198                 //write color to frame buffer
00199                 const float oofsubpixels = 1.0f / (float)m_subpixels;
00200                 pixelcolor *= oofsubpixels;
00201                 frameBuffer[y*m_width + x] = pixelcolor;
00202         }
00203 
00204         m_averageFragmentsPerPixel = (float)totalFragments / (float)totalPixels;
00205 }
00206 
00207 //=======================================================================================
00208 //=======================================================================================

Generated on Thu Feb 15 09:09:19 2007 for Surface Splating by  doxygen 1.5.1-p1