- Main Page
- Namespaces
- Classes
- Files

# 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 //=======================================================================================