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_zimage(0)
0078   ,m_zbw(0),m_zbh(0)
0079   ,m_begX(0),m_begY(0),m_endX(0),m_endY(0)
0080   ,m_scan_pixel(0L)
0081   ,m_planeAC(0),m_planeBC(0),m_planeDC(0)
0082   {}
0083   virtual ~buffer(){
0084     cmem_free(m_zbuffer);
0085     cmem_free(m_zimage);
0086     m_zbw = 0;
0087     m_zbh = 0;
0088     m_polygon.clear();
0089   }
0090 protected:
0091   buffer(const buffer& a_from)
0092   :m_depth_test(a_from.m_depth_test)
0093   ,m_blend(a_from.m_blend)
0094   {}
0095   buffer& operator=(const buffer& a_from){
0096     m_depth_test = a_from.m_depth_test;
0097     m_blend = a_from.m_blend;
0098     return *this;
0099   }
0100 public:
0101   void set_depth_test(bool a_on) {m_depth_test = a_on;}
0102   
0103   void set_blend(bool a_value) {m_blend = a_value;}
0104 
0105   bool change_size(unsigned int a_width,unsigned int a_height){
0106     if(!a_width||!a_height) return false;
0107 
0108     if(m_zbuffer &&  (m_zbw==a_width)  && (m_zbh==a_height)  ) return true;
0109 
0110     if(m_zbuffer){
0111       cmem_free(m_zbuffer);
0112       cmem_free(m_zimage);
0113     }
0114 
0115     m_zbw = a_width;
0116     m_zbh = a_height;
0117     m_zbuffer = cmem_alloc<ZReal>(m_zbw*m_zbh);
0118     if(!m_zbuffer){
0119       m_zbw = 0;
0120       m_zbh = 0;
0121       return false;
0122     }
0123 
0124     m_zimage = cmem_alloc<ZPixel>(m_zbw*m_zbh);
0125     if(!m_zimage){
0126       cmem_free(m_zbuffer);
0127       m_zbw = 0;
0128       m_zbh = 0;
0129       return false;
0130     }
0131 
0132     set_clip_region(0,0,m_zbw,m_zbh);
0133     m_polygon.clear();
0134     return true;
0135   }
0136 
0137   ZPixel* get_color_buffer(unsigned int& a_width,unsigned int& a_height) const {
0138     a_width  = m_zbw;
0139     a_height = m_zbh;
0140     return m_zimage;
0141   }
0142 
0143   void clear_color_buffer(ZPixel a_pixel) {
0144     // Erase acoording clip region.
0145     ZPos row,col;
0146     for(row=m_begY;row<=m_endY;row++){
0147       ZPixel* zimage = m_zimage + row * m_zbw + m_begX;
0148       for(col=m_begX;col<=m_endX;col++,zimage++) *zimage = a_pixel;
0149     }
0150   }
0151 
0152   void clear_depth_buffer() {
0153     // Erase acoording clip region.
0154     ZPos row,col;
0155 
0156     for(row=m_begY;row<=m_endY;row++) {
0157       ZReal* zbuff = m_zbuffer + row * m_zbw + m_begX;
0158       for(col=m_begX;col<=m_endX;col++,zbuff++){
0159         *zbuff = - ZREAL_HUGE();
0160       }
0161     }
0162   }
0163 
0164   ZPixel* zimage() {return m_zimage;}
0165 
0166   bool get_clipped_pixel(ZPos a_x,ZPos a_y,ZPixel& a_pixel) const {
0167     if((a_x<m_begX) || (a_x>m_endX))  {a_pixel = 0;return false;}
0168     if((a_y<m_begY) || (a_y>m_endY))  {a_pixel = 0;return false;}
0169     a_pixel = *(m_zimage + a_y * m_zbw + a_x);
0170     return true;
0171   }
0172 
0173 public:
0174   void set_clip_region(ZPos a_x,ZPos a_y,unsigned int a_width,unsigned int a_height){
0175     // if a_width or a_height is zero, clip region is empty.
0176 
0177     m_begX      = a_x;
0178     m_begY      = a_y;
0179     m_endX      = a_x + a_width  - 1;
0180     m_endY      = a_y + a_height - 1;
0181 
0182     if(m_begX<0) m_begX = 0;
0183     if(m_begY<0) m_begY = 0;
0184     if(m_endX>ZPos(m_zbw-1)) m_endX = m_zbw-1;
0185     if(m_endY>ZPos(m_zbh-1)) m_endY = m_zbh-1;
0186   }
0187 
0188   void draw_point(const point& a_p,ZPixel a_pixel,unsigned int a_size){
0189     write_point(a_p.x,a_p.y,a_p.z,a_size,a_pixel);
0190   }
0191 
0192   void draw_line(const point& a_beg,const point& a_end,ZPixel a_pixel,unsigned int a_size){
0193     WriteLine(a_beg,a_end,a_size,a_pixel);
0194   }
0195 
0196   void draw_lines(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
0197     for(int count=1;count<a_number;count++) {
0198       WriteLine(a_list[count-1],a_list[count],a_size,a_pixel);
0199     }
0200   }
0201 
0202   void draw_segments(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
0203     int segment_number = a_number/2;
0204     for(int count=0;count<segment_number;count++) {
0205       WriteLine(a_list[2*count],a_list[2*count+1],a_size,a_pixel);
0206     }
0207   }
0208   void draw_markers(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
0209     for(int count=0;count<a_number;count++){
0210       const point& p = a_list[count];
0211       write_point(p.x,p.y,p.z,a_size,a_pixel);
0212     }
0213   }
0214 
0215   void draw_polygon(int a_number,const point* a_list,
0216                     ZZ a_A,ZZ a_B,ZZ a_C,ZZ a_D,
0217                     //ZZ a_zmin,ZZ a_zmax,
0218                     ZPixel a_pixel){
0219     // Assume a_list is closed.
0220     if(a_number<3) return;
0221     if(a_C==0) return; //polygone seen from edge
0222 
0223     m_scan_pixel   = a_pixel;
0224     m_planeAC      = a_A/a_C;
0225     m_planeBC      = a_B/a_C;
0226     m_planeDC      = a_D/a_C;
0227 
0228     //if this polygon A is quite perpandicular to screen and close
0229     //to an other B than |dz| then some pixel of A could overwrite
0230     //pixel of B. Your have then to give a lower m_zboundPrec
0231 
0232     m_polygon.scan(a_number,a_list,0,WriteScanLine,this,m_zbw,m_zbh);
0233 
0234 
0235   }
0236 
0237   typedef unsigned char uchar;
0238   static void rgba2pix(float a_r,float a_g,float a_b,float a_a,ZPixel& a_pix) {
0239     uchar* _px = (uchar*)&a_pix;
0240     *_px = (uchar)(255.0F * a_r);_px++;
0241     *_px = (uchar)(255.0F * a_g);_px++;
0242     *_px = (uchar)(255.0F * a_b);_px++;
0243     *_px = (uchar)(255.0F * a_a);_px++;
0244   }
0245   static void pix2rgba(const ZPixel& a_pix,float& a_r,float& a_g,float& a_b,float& a_a) {
0246     uchar* _px = (uchar*)&a_pix;
0247     a_r = (*_px)/255.0f;_px++;
0248     a_g = (*_px)/255.0f;_px++;
0249     a_b = (*_px)/255.0f;_px++;
0250     a_a = (*_px)/255.0f;_px++;
0251   }
0252 protected:
0253   void scan_write_point_1(ZPos a_x,ZPos a_y,ZZ a_z,ZPos /*a_beg*/,unsigned int a_size,ZPixel a_pixel) {
0254     write_point(a_x,a_y,a_z,a_size,a_pixel);
0255   }
0256   void scan_write_point_2(ZPos a_x,ZPos a_y,ZZ a_z,ZPos /*a_beg*/,unsigned int a_size,ZPixel a_pixel) {
0257     write_point(a_y,a_x,a_z,a_size,a_pixel);
0258   }
0259   void scan_write_point_3(ZPos a_x,ZPos a_y,ZZ a_z,ZPos a_beg,unsigned int a_size,ZPixel a_pixel) {
0260     write_point(a_x,2*a_beg-a_y,a_z,a_size,a_pixel);
0261   }
0262   void scan_write_point_4(ZPos a_x,ZPos a_y,ZZ a_z,ZPos a_beg,unsigned int a_size,ZPixel a_pixel) {
0263     write_point(2*a_beg-a_y,a_x,a_z,a_size,a_pixel);
0264   }
0265 
0266   void blend(ZPixel& a_pix,const ZPixel& a_new) {
0267     if(!m_blend) {
0268       a_pix = a_new;
0269       return;
0270     }
0271     float _or,_og,_ob,_oa;
0272     pix2rgba(a_pix,_or,_og,_ob,_oa);
0273     float nr,ng,nb,na;
0274     pix2rgba(a_new,nr,ng,nb,na);
0275     if((0.0f<=na)&&(na<1.0f)) {
0276       // same as glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA):
0277       float one_minus_na = 1.0f-na;
0278       float pr = nr*na+_or*one_minus_na;
0279       float pg = ng*na+_og*one_minus_na;
0280       float pb = nb*na+_ob*one_minus_na;
0281       float pa = 1;
0282       rgba2pix(pr,pg,pb,pa,a_pix);
0283     } else {
0284       a_pix = a_new;
0285     }
0286   }
0287 
0288   static void WriteScanLine(void* a_tag,int a_beg,int a_end,int a_y){
0289     buffer& a_buffer = *((buffer*)a_tag);
0290 
0291     if((a_y<a_buffer.m_begY) || (a_y>a_buffer.m_endY)) return;
0292     if(a_end<=a_beg) return;
0293 
0294     if(a_beg>a_buffer.m_endX) return;
0295     if(a_end<a_buffer.m_begX) return;
0296 
0297     // border clip :
0298     int beg = max_of(a_beg,(int)a_buffer.m_begX);
0299     int end = min_of(a_end,(int)a_buffer.m_endX);
0300 
0301     unsigned long offset = a_y * a_buffer.m_zbw + beg;
0302     ZReal* zbuff = a_buffer.m_zbuffer + offset;
0303     ZPixel* zimage = a_buffer.m_zimage + offset;
0304 
0305     ZReal zpoint;
0306     for(int x=beg;x<=end;x++){
0307       zpoint =
0308         (ZReal)(- a_buffer.m_planeDC
0309                 - a_buffer.m_planeAC * x
0310                 - a_buffer.m_planeBC * a_y);
0311       if(a_buffer.m_depth_test) {
0312         if((zpoint>=(*zbuff))
0313           ){
0314           *zbuff = zpoint;
0315           a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
0316         }
0317       } else {
0318         *zbuff = zpoint;
0319         a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
0320       }
0321       zbuff  ++;
0322       zimage ++;
0323     }
0324   }
0325 
0326   typedef void(buffer::*scan_write_point_func)(ZPos,ZPos,ZZ,ZPos,unsigned int,ZPixel);
0327   void ScanLine(ZPos a_x,ZPos a_y,ZZ a_z,
0328                 ZPos a_dx,ZPos a_dy,ZZ a_dz,
0329                 unsigned int a_size,ZPixel a_pixel,
0330                 scan_write_point_func a_func){
0331     // Mid point algorithm
0332     // assume 0<dx    0<=dy<=dx
0333 
0334     ZPos end = a_x + a_dx;
0335     ZPos beg = a_y;
0336     ZZ incz = a_dz/(ZZ)a_dx;
0337     if(a_dy==0) {
0338       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0339       while(a_x<end){
0340         a_x++;
0341         a_z += incz;
0342         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0343       }
0344     } else if(a_dy==a_dx) {
0345       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0346       while(a_x<end){
0347         a_x++;
0348         a_y++;
0349         a_z += incz;
0350         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0351       }
0352     } else {
0353       ZPos d = 2 * a_dy - a_dx;
0354       ZPos incrE = 2 * a_dy;
0355       ZPos incrNE = 2 * ( 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         if(d<=0){
0359           d += incrE;
0360           a_x++;
0361         }else{
0362           d += incrNE;
0363           a_x++;
0364           a_y++;
0365         }
0366         a_z += incz;
0367         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
0368       }
0369     }
0370   }
0371 
0372   void WriteLine(const point& a_beg,
0373                  const point& a_end,
0374                  unsigned int a_size,ZPixel a_pixel){
0375     ZPos dx = a_end.x - a_beg.x;
0376     ZPos dy = a_end.y - a_beg.y;
0377     ZZ   dz = a_end.z - a_beg.z;
0378 
0379     //  6  2
0380     // 5     1
0381     // 7     3
0382     //  8  4
0383 
0384     if( (dx==0) && (dy==0) ) {
0385       write_point(a_beg.x,a_beg.y,a_beg.z,a_size,a_pixel);
0386       write_point(a_end.x,a_end.y,a_end.z,a_size,a_pixel);
0387 
0388     } else if(dx==0) {
0389       if(dy>0)
0390         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy, dx, dz, a_size,a_pixel,&buffer::scan_write_point_2);
0391       else
0392         ScanLine ( a_end.y, a_end.x,a_end.z,-dy, dx,-dz, a_size,a_pixel,&buffer::scan_write_point_2);
0393 
0394     } else if(dx>0) {
0395            if((0<=dy) && (dy<=dx))  /*1*/
0396         ScanLine ( a_beg.x, a_beg.y,a_beg.z, dx, dy, dz, a_size,a_pixel,&buffer::scan_write_point_1);
0397       else if(dx<dy)                /*2*/
0398         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy, dx, dz, a_size,a_pixel,&buffer::scan_write_point_2);
0399       else if((-dx<=dy) && (dy<0) ) /*3*/
0400         ScanLine ( a_beg.x, a_beg.y,a_beg.z, dx,-dy, dz, a_size,a_pixel,&buffer::scan_write_point_3);
0401       else if(dy<-dx)               /*4*/
0402         ScanLine ( a_end.y, a_end.x,a_end.z,-dy, dx,-dz, a_size,a_pixel,&buffer::scan_write_point_4);
0403 
0404     } else { //dx<0
0405            if((0<=dy) && (dy<=-dx)) /*5*/
0406         ScanLine ( a_end.x, a_end.y,a_end.z,-dx, dy,-dz, a_size,a_pixel,&buffer::scan_write_point_3);
0407       else if(-dx<dy)               /*6*/
0408         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy,-dx, dz, a_size,a_pixel,&buffer::scan_write_point_4);
0409       else if((dx<=dy) && (dy<0) )  /*7*/
0410         ScanLine ( a_end.x, a_end.y,a_end.z,-dx,-dy,-dz, a_size,a_pixel,&buffer::scan_write_point_1);
0411       else if(dy<dx)                /*8*/
0412         ScanLine ( a_end.y, a_end.x,a_end.z,-dy,-dx,-dz, a_size,a_pixel,&buffer::scan_write_point_2);
0413     }
0414 
0415   }
0416 
0417 
0418 protected:
0419   bool         m_depth_test;
0420   bool         m_blend;
0421   ZReal*       m_zbuffer;
0422 
0423   ZPixel*      m_zimage;
0424 
0425   unsigned int m_zbw,m_zbh;
0426   ZPos         m_begX,m_begY;
0427   ZPos         m_endX,m_endY; //could be <0
0428 
0429   ZPixel       m_scan_pixel;
0430   ZZ           m_planeAC;
0431   ZZ           m_planeBC;
0432   ZZ           m_planeDC;
0433   polygon      m_polygon;
0434 };
0435 
0436 }}
0437 
0438 #endif