Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/zb/buffer is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_zb_buffer
0005 #define tools_zb_buffer
0006 
0007 #include <cfloat> //DBL_MAX
0008 
0009 #include "polygon"
0010 
0011 namespace tools {
0012 namespace zb {
0013 
0014 // ZPos, ZZ defined in point.
0015 
0016 class buffer {
0017 
0018   typedef double ZReal;
0019   static ZReal ZREAL_HUGE() {return DBL_MAX;}
0020 
0021 public:
0022   typedef unsigned int ZPixel;
0023   //NOTE : with X11, bits_per_pixel can't be > 32.
0024 protected:
0025 
0026   class writer {
0027   public:
0028     virtual void write(ZPos,ZPos,ZZ) = 0;
0029   public:
0030     writer(ZPixel a_pixel):m_pixel(a_pixel){}
0031     virtual ~writer(){}
0032   public:
0033     writer(const writer& a_from):m_pixel(a_from.m_pixel){}
0034     writer& operator=(const writer& a_from){
0035       m_pixel = a_from.m_pixel;
0036       return *this;
0037     }
0038   public:
0039     ZPixel m_pixel;
0040   };
0041 
0042   void _write_point(ZPos a_x,ZPos a_y,ZZ a_z,ZPixel a_pixel) {
0043     if((a_x<m_begX) || (a_x>m_endX)) return;
0044     if((a_y<m_begY) || (a_y>m_endY)) return;
0045 
0046     ZReal zpoint = (ZReal)a_z;
0047     unsigned long offset = a_y * m_zbw + a_x;
0048     ZReal* zbuff = m_zbuffer + offset;
0049 
0050     if(m_depth_test) {if(zpoint<*zbuff) return;}
0051 
0052     ZPixel* zimage = m_zimage  + offset;
0053 
0054     *zbuff = zpoint;
0055     blend(*zimage,a_pixel);
0056   }
0057   void write_point(ZPos a_x,ZPos a_y,ZZ a_z,unsigned int a_size,ZPixel a_pixel) {
0058     if(a_size>=1) { //see zb_action::npix().
0059       ZPos x,y;
0060       for(int i=-int(a_size);i<=int(a_size);i++) {
0061         x = a_x + i;
0062         for(int j=-int(a_size);j<=int(a_size);j++) {
0063           y = a_y + j;
0064           _write_point(x,y,a_z,a_pixel);
0065         }
0066       }
0067     } else {
0068       _write_point(a_x,a_y,a_z,a_pixel);
0069     }
0070   }
0071 
0072 public:
0073   buffer()
0074   :m_depth_test(true)
0075   ,m_blend(false)
0076   ,m_zbuffer(0)
0077   //,m_zmin(0),m_zmax(0)
0078   ,m_zimage(0)
0079   ,m_zbw(0),m_zbh(0)
0080   ,m_begX(0),m_begY(0),m_endX(0),m_endY(0)
0081   ,m_scan_pixel(0L)
0082   ,m_planeAC(0),m_planeBC(0),m_planeDC(0)
0083   //,m_zboundPrec(10)
0084   {}
0085   virtual ~buffer(){
0086     cmem_free(m_zbuffer);
0087     cmem_free(m_zimage);
0088     m_zbw = 0;
0089     m_zbh = 0;
0090     m_polygon.clear();
0091   }
0092 protected:
0093   buffer(const buffer& a_from)
0094   :m_depth_test(a_from.m_depth_test)
0095   ,m_blend(a_from.m_blend)
0096   {}
0097   buffer& operator=(const buffer& a_from){
0098     m_depth_test = a_from.m_depth_test;
0099     m_blend = a_from.m_blend;
0100     return *this;
0101   }
0102 public:
0103   void set_depth_test(bool a_on) {m_depth_test = a_on;}
0104   //bool depth_test() const {return m_depth_test;}
0105   
0106   void set_blend(bool a_value) {m_blend = a_value;}
0107 
0108   bool change_size(unsigned int a_width,unsigned int a_height){
0109     if(!a_width||!a_height) return false;
0110 
0111     if(m_zbuffer &&  (m_zbw==a_width)  && (m_zbh==a_height)  ) return true;
0112 
0113     if(m_zbuffer){
0114       cmem_free(m_zbuffer);
0115       cmem_free(m_zimage);
0116     }
0117 
0118     //printf ("debug:ZBufferChangeSize:%d %d\n",a_width,a_height);
0119     m_zbw = a_width;
0120     m_zbh = a_height;
0121     m_zbuffer = cmem_alloc<ZReal>(m_zbw*m_zbh);
0122     if(!m_zbuffer){
0123       m_zbw = 0;
0124       m_zbh = 0;
0125       return false;
0126     }
0127 
0128     m_zimage = cmem_alloc<ZPixel>(m_zbw*m_zbh);
0129     if(!m_zimage){
0130       cmem_free(m_zbuffer);
0131       m_zbw = 0;
0132       m_zbh = 0;
0133       return false;
0134     }
0135 
0136     set_clip_region(0,0,m_zbw,m_zbh);
0137     m_polygon.clear();
0138     return true;
0139   }
0140 
0141   ZPixel* get_color_buffer(unsigned int& a_width,unsigned int& a_height) const {
0142     a_width  = m_zbw;
0143     a_height = m_zbh;
0144     return m_zimage;
0145   }
0146 
0147   void clear_color_buffer(ZPixel a_pixel) {
0148     // Erase acoording clip region.
0149     ZPos row,col;
0150     for(row=m_begY;row<=m_endY;row++){
0151       ZPixel* zimage = m_zimage + row * m_zbw + m_begX;
0152       for(col=m_begX;col<=m_endX;col++,zimage++) *zimage = a_pixel;
0153     }
0154   }
0155 
0156   void clear_depth_buffer() {
0157     // Erase acoording clip region.
0158     ZPos row,col;
0159     //printf("debug:ZBufferClearDepthBuffer: %g.\n",a_depth);
0160 
0161     for(row=m_begY;row<=m_endY;row++) {
0162       ZReal* zbuff = m_zbuffer + row * m_zbw + m_begX;
0163       for(col=m_begX;col<=m_endX;col++,zbuff++){
0164         *zbuff = - ZREAL_HUGE();
0165       }
0166     }
0167   }
0168 
0169   ZPixel* zimage() {return m_zimage;}
0170 
0171   bool get_clipped_pixel(ZPos a_x,ZPos a_y,ZPixel& a_pixel) const {
0172     if((a_x<m_begX) || (a_x>m_endX))  {a_pixel = 0;return false;}
0173     if((a_y<m_begY) || (a_y>m_endY))  {a_pixel = 0;return false;}
0174     a_pixel = *(m_zimage + a_y * m_zbw + a_x);
0175     return true;
0176   }
0177 
0178 public:
0179   void set_clip_region(ZPos a_x,ZPos a_y,unsigned int a_width,unsigned int a_height){
0180     // if a_width or a_height is zero, clip region is empty.
0181 
0182     m_begX      = a_x;
0183     m_begY      = a_y;
0184     m_endX      = a_x + a_width  - 1;
0185     m_endY      = a_y + a_height - 1;
0186 
0187     if(m_begX<0) m_begX = 0;
0188     if(m_begY<0) m_begY = 0;
0189     if(m_endX>ZPos(m_zbw-1)) m_endX = m_zbw-1;
0190     if(m_endY>ZPos(m_zbh-1)) m_endY = m_zbh-1;
0191   }
0192 
0193   void draw_point(const point& a_p,ZPixel a_pixel,unsigned int a_size){
0194     write_point(a_p.x,a_p.y,a_p.z,a_size,a_pixel);
0195   }
0196 
0197   void draw_line(const point& a_beg,const point& a_end,ZPixel a_pixel,unsigned int a_size){
0198     WriteLine(a_beg,a_end,a_size,a_pixel);
0199   }
0200 
0201   void draw_lines(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
0202     for(int count=1;count<a_number;count++) {
0203       WriteLine(a_list[count-1],a_list[count],a_size,a_pixel);
0204     }
0205   }
0206 
0207   void draw_segments(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
0208     int segment_number = a_number/2;
0209     for(int count=0;count<segment_number;count++) {
0210       WriteLine(a_list[2*count],a_list[2*count+1],a_size,a_pixel);
0211     }
0212   }
0213   void draw_markers(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
0214     for(int count=0;count<a_number;count++){
0215       const point& p = a_list[count];
0216       write_point(p.x,p.y,p.z,a_size,a_pixel);
0217     }
0218   }
0219 
0220   void draw_polygon(int a_number,const point* a_list,
0221                     ZZ a_A,ZZ a_B,ZZ a_C,ZZ a_D,
0222                     //ZZ a_zmin,ZZ a_zmax,
0223                     ZPixel a_pixel){
0224     // Assume a_list is closed.
0225     if(a_number<3) return;
0226     if(a_C==0) return; //polygone seen from edge
0227     //if(m_zboundPrec<0) m_zboundPrec = 0;
0228 
0229     m_scan_pixel   = a_pixel;
0230     m_planeAC      = a_A/a_C;
0231     m_planeBC      = a_B/a_C;
0232     m_planeDC      = a_D/a_C;
0233 
0234     //if this polygon A is quite perpandicular to screen and close
0235     //to an other B than |dz| then some pixel of A could overwrite
0236     //pixel of B. Your have then to give a lower m_zboundPrec
0237 
0238     //ZZ dz = m_zboundPrec * (a_zmax - a_zmin)/100.;
0239     //m_zmin = (ZReal)(a_zmin - dz);
0240     //m_zmax = (ZReal)(a_zmax + dz);
0241 
0242     m_polygon.scan(a_number,a_list,0,WriteScanLine,this);
0243 
0244   }
0245 
0246   typedef unsigned char uchar;
0247   static void rgba2pix(float a_r,float a_g,float a_b,float a_a,ZPixel& a_pix) {
0248     uchar* _px = (uchar*)&a_pix;
0249     *_px = (uchar)(255.0F * a_r);_px++;
0250     *_px = (uchar)(255.0F * a_g);_px++;
0251     *_px = (uchar)(255.0F * a_b);_px++;
0252     *_px = (uchar)(255.0F * a_a);_px++;
0253   }
0254   static void pix2rgba(const ZPixel& a_pix,float& a_r,float& a_g,float& a_b,float& a_a) {
0255     uchar* _px = (uchar*)&a_pix;
0256     a_r = (*_px)/255.0f;_px++;
0257     a_g = (*_px)/255.0f;_px++;
0258     a_b = (*_px)/255.0f;_px++;
0259     a_a = (*_px)/255.0f;_px++;
0260   }
0261 protected:
0262   void scan_write_point_1(ZPos a_x,ZPos a_y,ZZ a_z,ZPos /*a_beg*/,unsigned int a_size,ZPixel a_pixel) {
0263     write_point(a_x,a_y,a_z,a_size,a_pixel);
0264   }
0265   void scan_write_point_2(ZPos a_x,ZPos a_y,ZZ a_z,ZPos /*a_beg*/,unsigned int a_size,ZPixel a_pixel) {
0266     write_point(a_y,a_x,a_z,a_size,a_pixel);
0267   }
0268   void scan_write_point_3(ZPos a_x,ZPos a_y,ZZ a_z,ZPos a_beg,unsigned int a_size,ZPixel a_pixel) {
0269     write_point(a_x,2*a_beg-a_y,a_z,a_size,a_pixel);
0270   }
0271   void scan_write_point_4(ZPos a_x,ZPos a_y,ZZ a_z,ZPos a_beg,unsigned int a_size,ZPixel a_pixel) {
0272     write_point(2*a_beg-a_y,a_x,a_z,a_size,a_pixel);
0273   }
0274 
0275   void blend(ZPixel& a_pix,const ZPixel& a_new) {
0276     if(!m_blend) {
0277       a_pix = a_new;
0278       return;
0279     }
0280     float _or,_og,_ob,_oa;
0281     pix2rgba(a_pix,_or,_og,_ob,_oa);
0282     float nr,ng,nb,na;
0283     pix2rgba(a_new,nr,ng,nb,na);
0284     if((0.0f<=na)&&(na<1.0f)) {
0285       // same as glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA):
0286       float one_minus_na = 1.0f-na;
0287       float pr = nr*na+_or*one_minus_na;
0288       float pg = ng*na+_og*one_minus_na;
0289       float pb = nb*na+_ob*one_minus_na;
0290       float pa = 1;
0291       rgba2pix(pr,pg,pb,pa,a_pix);
0292     } else {
0293       a_pix = a_new;
0294     }
0295   }
0296 
0297   static void WriteScanLine(void* a_tag,int a_beg,int a_end,int a_y){
0298     buffer& a_buffer = *((buffer*)a_tag);
0299 
0300     if((a_y<a_buffer.m_begY) || (a_y>a_buffer.m_endY)) return;
0301     if(a_end<=a_beg) return;
0302 
0303     if(a_beg>a_buffer.m_endX) return;
0304     if(a_end<a_buffer.m_begX) return;
0305 
0306     // border clip :
0307     int beg = mx(a_beg,(int)a_buffer.m_begX);
0308     int end = mn(a_end,(int)a_buffer.m_endX);
0309 
0310     unsigned long offset = a_y * a_buffer.m_zbw + beg;
0311     ZReal* zbuff = a_buffer.m_zbuffer + offset;
0312     ZPixel* zimage = a_buffer.m_zimage + offset;
0313 
0314     ZReal zpoint;
0315     for(int x=beg;x<=end;x++){
0316       zpoint =
0317         (ZReal)(- a_buffer.m_planeDC
0318                 - a_buffer.m_planeAC * x
0319                 - a_buffer.m_planeBC * a_y);
0320       if(a_buffer.m_depth_test) {
0321         if((zpoint>=(*zbuff))
0322 //       &&(zpoint>=a_buffer.m_zmin) //for plane quite perpandicular to screen.
0323 //       &&(zpoint<=a_buffer.m_zmax)
0324           ){
0325           *zbuff = zpoint;
0326           a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
0327         }
0328       } else {
0329         *zbuff = zpoint;
0330         a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
0331       }
0332       zbuff  ++;
0333       zimage ++;
0334     }
0335   }
0336 
0337   typedef void(buffer::*scan_write_point_func)(ZPos,ZPos,ZZ,ZPos,unsigned int,ZPixel);
0338   void ScanLine(ZPos a_x,ZPos a_y,ZZ a_z,
0339                 ZPos a_dx,ZPos a_dy,ZZ a_dz,
0340                 unsigned int a_size,ZPixel a_pixel,
0341                 scan_write_point_func a_func){
0342     // Mid point algorithm
0343     // assume 0<dx    0<=dy<=dx
0344 
0345     ZPos end = a_x + a_dx;
0346     ZPos beg = a_y;
0347     ZZ incz = a_dz/(ZZ)a_dx;
0348     if(a_dy==0) {
0349       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0350       while(a_x<end){
0351         a_x++;
0352         a_z += incz;
0353         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0354       }
0355     } else if(a_dy==a_dx) {
0356       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0357       while(a_x<end){
0358         a_x++;
0359         a_y++;
0360         a_z += incz;
0361         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0362       }
0363     } else {
0364       ZPos d = 2 * a_dy - a_dx;
0365       ZPos incrE = 2 * a_dy;
0366       ZPos incrNE = 2 * ( a_dy - a_dx);
0367       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0368       while(a_x<end){
0369         if(d<=0){
0370           d += incrE;
0371           a_x++;
0372         }else{
0373           d += incrNE;
0374           a_x++;
0375           a_y++;
0376         }
0377         a_z += incz;
0378         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0379       }
0380     }
0381   }
0382 
0383   void WriteLine(const point& a_beg,
0384                  const point& a_end,
0385                  unsigned int a_size,ZPixel a_pixel){
0386     ZPos dx = a_end.x - a_beg.x;
0387     ZPos dy = a_end.y - a_beg.y;
0388     ZZ   dz = a_end.z - a_beg.z;
0389 
0390     //  6  2
0391     // 5     1
0392     // 7     3
0393     //  8  4
0394 
0395     if( (dx==0) && (dy==0) ) {
0396       write_point(a_beg.x,a_beg.y,a_beg.z,a_size,a_pixel);
0397       write_point(a_end.x,a_end.y,a_end.z,a_size,a_pixel);
0398 
0399     } else if(dx==0) {
0400       if(dy>0)
0401         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy, dx, dz, a_size,a_pixel,&buffer::scan_write_point_2);
0402       else
0403         ScanLine ( a_end.y, a_end.x,a_end.z,-dy, dx,-dz, a_size,a_pixel,&buffer::scan_write_point_2);
0404 
0405     } else if(dx>0) {
0406            if((0<=dy) && (dy<=dx))  /*1*/
0407         ScanLine ( a_beg.x, a_beg.y,a_beg.z, dx, dy, dz, a_size,a_pixel,&buffer::scan_write_point_1);
0408       else if(dx<dy)                /*2*/
0409         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy, dx, dz, a_size,a_pixel,&buffer::scan_write_point_2);
0410       else if((-dx<=dy) && (dy<0) ) /*3*/
0411         ScanLine ( a_beg.x, a_beg.y,a_beg.z, dx,-dy, dz, a_size,a_pixel,&buffer::scan_write_point_3);
0412       else if(dy<-dx)               /*4*/
0413         ScanLine ( a_end.y, a_end.x,a_end.z,-dy, dx,-dz, a_size,a_pixel,&buffer::scan_write_point_4);
0414 
0415     } else { //dx<0
0416            if((0<=dy) && (dy<=-dx)) /*5*/
0417         ScanLine ( a_end.x, a_end.y,a_end.z,-dx, dy,-dz, a_size,a_pixel,&buffer::scan_write_point_3);
0418       else if(-dx<dy)               /*6*/
0419         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy,-dx, dz, a_size,a_pixel,&buffer::scan_write_point_4);
0420       else if((dx<=dy) && (dy<0) )  /*7*/
0421         ScanLine ( a_end.x, a_end.y,a_end.z,-dx,-dy,-dz, a_size,a_pixel,&buffer::scan_write_point_1);
0422       else if(dy<dx)                /*8*/
0423         ScanLine ( a_end.y, a_end.x,a_end.z,-dy,-dx,-dz, a_size,a_pixel,&buffer::scan_write_point_2);
0424     }
0425 
0426   }
0427 
0428 
0429 protected:
0430   bool         m_depth_test;
0431   bool         m_blend;
0432   ZReal*       m_zbuffer;
0433 //ZReal        m_zmin,m_zmax;
0434 
0435   ZPixel*      m_zimage;
0436 
0437   unsigned int m_zbw,m_zbh;
0438   ZPos         m_begX,m_begY;
0439   ZPos         m_endX,m_endY; //could be <0
0440 
0441   ZPixel       m_scan_pixel;
0442   ZZ           m_planeAC;
0443   ZZ           m_planeBC;
0444   ZZ           m_planeDC;
0445   //int          m_zboundPrec;
0446   polygon      m_polygon;
0447 };
0448 
0449 }}
0450 
0451 #endif