00001 #include "countsrf.h"
00002
00015 #include <glt/rgb.h>
00016 #include <glt/zplane.h>
00017 #include <glt/error.h>
00018
00019 #include <node/shape.h>
00020
00021 #ifdef DEBUG
00022 #include <iostream>
00023 using namespace std;
00024 #endif
00025
00027
00028 void countSurfaces(const GltShape &shape)
00029 {
00030 GLERROR
00031 glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT |
00032 GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
00033
00034
00035
00036 glClearStencil(0);
00037 glStencilMask(~0);
00038 glClear(GL_STENCIL_BUFFER_BIT);
00039
00040
00041
00042 glDepthMask(GL_FALSE);
00043 glDepthFunc(GL_ALWAYS);
00044
00045
00046
00047 glEnable(GL_STENCIL_TEST);
00048 glStencilFunc(GL_ALWAYS,0,~0);
00049 glStencilOp(GL_INCR,GL_INCR,GL_INCR);
00050
00051
00052
00053 glDisable(GL_LIGHTING);
00054 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
00055
00056
00057 shape.draw();
00058
00059 glPopAttrib();
00060 GLERROR
00061 }
00062
00063 GLubyte
00064 countSurfaces
00065 (
00066 const GltShape &shape,
00067 const countSurfacesMode mode
00068 )
00069 {
00070 countSurfaces(shape);
00071
00072 GLERROR
00073
00074
00075
00076 GLuint histogram[256];
00077 GLuint pixels = stencilHistogram(histogram);
00078
00079 GLubyte max = 0;
00080
00081 switch (mode)
00082 {
00083 case COUNT_SURFACES_ALL:
00084 {
00085 for (GLuint p=0; p<256; p++)
00086 if (histogram[p]>0)
00087 max = p;
00088 }
00089 break;
00090
00091 case COUNT_SURFACES_99TH_PERCENTILE:
00092 {
00093 GLuint accum = 0;
00094 for (GLuint p=0; p<256; p++)
00095 {
00096 accum += histogram[p];
00097 if ((double) accum / pixels >= 0.999)
00098 {
00099 max = p;
00100 break;
00101 }
00102 }
00103 }
00104 break;
00105 }
00106
00107 #ifdef DEBUG
00108 GLint stencilSize = 0;
00109 glGetIntegerv(GL_STENCIL_BITS,&stencilSize);
00110
00111 if ( GLubyte(GLubyte(1)<<stencilSize) == max+1 )
00112 cout << "WARNING: Stencil Buffer may be too small for countSurfaces" << endl;
00113 #endif
00114
00115 GLERROR
00116
00117 return max;
00118 }
00119
00121
00123 const GLuint maxColors=8;
00124
00126 const GltColor surfaceColor[maxColors] =
00127 {
00128 red,
00129 green,
00130 blue,
00131 yellow,
00132 cyan,
00133 magenta,
00134 black,
00135 white
00136 };
00137
00138 GLubyte
00139 countSurfacesVisualise(const GltShape &shape)
00140 {
00141 glPushAttrib( GL_ENABLE_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
00142
00143 GLubyte layers = countSurfaces(shape,COUNT_SURFACES_ALL);
00144
00145 glEnable(GL_STENCIL_TEST);
00146 glStencilMask(0xffff);
00147 glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
00148
00149 glEnable(GL_DEPTH_TEST);
00150 glDepthFunc(GL_ALWAYS);
00151 glDepthMask(GL_FALSE);
00152
00153 glDisable(GL_LIGHTING);
00154
00155 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00156
00157 for (GLuint l=0; l<layers && l<maxColors; l++)
00158 {
00159 if (l<layers)
00160 {
00161 glStencilFunc(GL_EQUAL,l+1,0xff);
00162 surfaceColor[l%(maxColors-1)].glColor();
00163 }
00164 else
00165 {
00166 glStencilFunc(GL_GEQUAL,l+1,0xff);
00167 surfaceColor[maxColors-1].glColor();
00168 }
00169
00170 drawZnear();
00171 }
00172
00173 glPopAttrib();
00174
00175 return layers;
00176 }
00177
00179
00180 GLuint
00181 stencilHistogram(GLuint histogram[256])
00182 {
00183
00184
00185 GLuint viewport[4];
00186 glGetIntegerv(GL_VIEWPORT,(GLint *) viewport);
00187
00188
00189
00190 GLuint pixels = viewport[2] * viewport[3];
00191 GLubyte *pixel = new GLubyte[pixels];
00192
00193
00194
00195 glPixelStorei(GL_PACK_ALIGNMENT,sizeof(GLubyte));
00196 glReadPixels(0,0,viewport[2],viewport[3],GL_STENCIL_INDEX,GL_UNSIGNED_BYTE,pixel);
00197
00198
00199
00200 GLuint x;
00201
00202 for (x=0;x<256;x++)
00203 histogram[x] = 0;
00204
00205
00206
00207 for (x=0;x<pixels;x++)
00208 histogram[pixel[x]]++;
00209
00210
00211
00212 delete [] pixel;
00213
00214 return pixels;
00215 }