Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/zb/buffer

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  2 // See the file tools.license for terms.
  3 
  4 #ifndef tools_zb_buffer
  5 #define tools_zb_buffer
  6 
  7 #include <cfloat> //DBL_MAX
  8 
  9 #include "polygon"
 10 
 11 namespace tools {
 12 namespace zb {
 13 
 14 // ZPos, ZZ defined in point.
 15 
 16 class buffer {
 17 
 18   typedef double ZReal;
 19   static ZReal ZREAL_HUGE() {return DBL_MAX;}
 20 
 21 public:
 22   typedef unsigned int ZPixel;
 23   //NOTE : with X11, bits_per_pixel can't be > 32.
 24 protected:
 25 
 26   class writer {
 27   public:
 28     virtual void write(ZPos,ZPos,ZZ) = 0;
 29   public:
 30     writer(ZPixel a_pixel):m_pixel(a_pixel){}
 31     virtual ~writer(){}
 32   public:
 33     writer(const writer& a_from):m_pixel(a_from.m_pixel){}
 34     writer& operator=(const writer& a_from){
 35       m_pixel = a_from.m_pixel;
 36       return *this;
 37     }
 38   public:
 39     ZPixel m_pixel;
 40   };
 41 
 42   void _write_point(ZPos a_x,ZPos a_y,ZZ a_z,ZPixel a_pixel) {
 43     if((a_x<m_begX) || (a_x>m_endX)) return;
 44     if((a_y<m_begY) || (a_y>m_endY)) return;
 45 
 46     ZReal zpoint = (ZReal)a_z;
 47     unsigned long offset = a_y * m_zbw + a_x;
 48     ZReal* zbuff = m_zbuffer + offset;
 49 
 50     if(m_depth_test) {if(zpoint<*zbuff) return;}
 51 
 52     ZPixel* zimage = m_zimage  + offset;
 53 
 54     *zbuff = zpoint;
 55     blend(*zimage,a_pixel);
 56   }
 57   void write_point(ZPos a_x,ZPos a_y,ZZ a_z,unsigned int a_size,ZPixel a_pixel) {
 58     if(a_size>=1) { //see zb_action::npix().
 59       ZPos x,y;
 60       for(int i=-int(a_size);i<=int(a_size);i++) {
 61         x = a_x + i;
 62         for(int j=-int(a_size);j<=int(a_size);j++) {
 63           y = a_y + j;
 64           _write_point(x,y,a_z,a_pixel);
 65         }
 66       }
 67     } else {
 68       _write_point(a_x,a_y,a_z,a_pixel);
 69     }
 70   }
 71 
 72 public:
 73   buffer()
 74   :m_depth_test(true)
 75   ,m_blend(false)
 76   ,m_zbuffer(0)
 77   //,m_zmin(0),m_zmax(0)
 78   ,m_zimage(0)
 79   ,m_zbw(0),m_zbh(0)
 80   ,m_begX(0),m_begY(0),m_endX(0),m_endY(0)
 81   ,m_scan_pixel(0L)
 82   ,m_planeAC(0),m_planeBC(0),m_planeDC(0)
 83   //,m_zboundPrec(10)
 84   {}
 85   virtual ~buffer(){
 86     cmem_free(m_zbuffer);
 87     cmem_free(m_zimage);
 88     m_zbw = 0;
 89     m_zbh = 0;
 90     m_polygon.clear();
 91   }
 92 protected:
 93   buffer(const buffer& a_from)
 94   :m_depth_test(a_from.m_depth_test)
 95   ,m_blend(a_from.m_blend)
 96   {}
 97   buffer& operator=(const buffer& a_from){
 98     m_depth_test = a_from.m_depth_test;
 99     m_blend = a_from.m_blend;
100     return *this;
101   }
102 public:
103   void set_depth_test(bool a_on) {m_depth_test = a_on;}
104   //bool depth_test() const {return m_depth_test;}
105   
106   void set_blend(bool a_value) {m_blend = a_value;}
107 
108   bool change_size(unsigned int a_width,unsigned int a_height){
109     if(!a_width||!a_height) return false;
110 
111     if(m_zbuffer &&  (m_zbw==a_width)  && (m_zbh==a_height)  ) return true;
112 
113     if(m_zbuffer){
114       cmem_free(m_zbuffer);
115       cmem_free(m_zimage);
116     }
117 
118     //printf ("debug:ZBufferChangeSize:%d %d\n",a_width,a_height);
119     m_zbw = a_width;
120     m_zbh = a_height;
121     m_zbuffer = cmem_alloc<ZReal>(m_zbw*m_zbh);
122     if(!m_zbuffer){
123       m_zbw = 0;
124       m_zbh = 0;
125       return false;
126     }
127 
128     m_zimage = cmem_alloc<ZPixel>(m_zbw*m_zbh);
129     if(!m_zimage){
130       cmem_free(m_zbuffer);
131       m_zbw = 0;
132       m_zbh = 0;
133       return false;
134     }
135 
136     set_clip_region(0,0,m_zbw,m_zbh);
137     m_polygon.clear();
138     return true;
139   }
140 
141   ZPixel* get_color_buffer(unsigned int& a_width,unsigned int& a_height) const {
142     a_width  = m_zbw;
143     a_height = m_zbh;
144     return m_zimage;
145   }
146 
147   void clear_color_buffer(ZPixel a_pixel) {
148     // Erase acoording clip region.
149     ZPos row,col;
150     for(row=m_begY;row<=m_endY;row++){
151       ZPixel* zimage = m_zimage + row * m_zbw + m_begX;
152       for(col=m_begX;col<=m_endX;col++,zimage++) *zimage = a_pixel;
153     }
154   }
155 
156   void clear_depth_buffer() {
157     // Erase acoording clip region.
158     ZPos row,col;
159     //printf("debug:ZBufferClearDepthBuffer: %g.\n",a_depth);
160 
161     for(row=m_begY;row<=m_endY;row++) {
162       ZReal* zbuff = m_zbuffer + row * m_zbw + m_begX;
163       for(col=m_begX;col<=m_endX;col++,zbuff++){
164         *zbuff = - ZREAL_HUGE();
165       }
166     }
167   }
168 
169   ZPixel* zimage() {return m_zimage;}
170 
171   bool get_clipped_pixel(ZPos a_x,ZPos a_y,ZPixel& a_pixel) const {
172     if((a_x<m_begX) || (a_x>m_endX))  {a_pixel = 0;return false;}
173     if((a_y<m_begY) || (a_y>m_endY))  {a_pixel = 0;return false;}
174     a_pixel = *(m_zimage + a_y * m_zbw + a_x);
175     return true;
176   }
177 
178 public:
179   void set_clip_region(ZPos a_x,ZPos a_y,unsigned int a_width,unsigned int a_height){
180     // if a_width or a_height is zero, clip region is empty.
181 
182     m_begX      = a_x;
183     m_begY      = a_y;
184     m_endX      = a_x + a_width  - 1;
185     m_endY      = a_y + a_height - 1;
186 
187     if(m_begX<0) m_begX = 0;
188     if(m_begY<0) m_begY = 0;
189     if(m_endX>ZPos(m_zbw-1)) m_endX = m_zbw-1;
190     if(m_endY>ZPos(m_zbh-1)) m_endY = m_zbh-1;
191   }
192 
193   void draw_point(const point& a_p,ZPixel a_pixel,unsigned int a_size){
194     write_point(a_p.x,a_p.y,a_p.z,a_size,a_pixel);
195   }
196 
197   void draw_line(const point& a_beg,const point& a_end,ZPixel a_pixel,unsigned int a_size){
198     WriteLine(a_beg,a_end,a_size,a_pixel);
199   }
200 
201   void draw_lines(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
202     for(int count=1;count<a_number;count++) {
203       WriteLine(a_list[count-1],a_list[count],a_size,a_pixel);
204     }
205   }
206 
207   void draw_segments(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
208     int segment_number = a_number/2;
209     for(int count=0;count<segment_number;count++) {
210       WriteLine(a_list[2*count],a_list[2*count+1],a_size,a_pixel);
211     }
212   }
213   void draw_markers(int a_number,const point* a_list,ZPixel a_pixel,unsigned int a_size){
214     for(int count=0;count<a_number;count++){
215       const point& p = a_list[count];
216       write_point(p.x,p.y,p.z,a_size,a_pixel);
217     }
218   }
219 
220   void draw_polygon(int a_number,const point* a_list,
221                     ZZ a_A,ZZ a_B,ZZ a_C,ZZ a_D,
222                     //ZZ a_zmin,ZZ a_zmax,
223                     ZPixel a_pixel){
224     // Assume a_list is closed.
225     if(a_number<3) return;
226     if(a_C==0) return; //polygone seen from edge
227     //if(m_zboundPrec<0) m_zboundPrec = 0;
228 
229     m_scan_pixel   = a_pixel;
230     m_planeAC      = a_A/a_C;
231     m_planeBC      = a_B/a_C;
232     m_planeDC      = a_D/a_C;
233 
234     //if this polygon A is quite perpandicular to screen and close
235     //to an other B than |dz| then some pixel of A could overwrite
236     //pixel of B. Your have then to give a lower m_zboundPrec
237 
238     //ZZ dz = m_zboundPrec * (a_zmax - a_zmin)/100.;
239     //m_zmin = (ZReal)(a_zmin - dz);
240     //m_zmax = (ZReal)(a_zmax + dz);
241 
242     m_polygon.scan(a_number,a_list,0,WriteScanLine,this);
243 
244   }
245 
246   typedef unsigned char uchar;
247   static void rgba2pix(float a_r,float a_g,float a_b,float a_a,ZPixel& a_pix) {
248     uchar* _px = (uchar*)&a_pix;
249     *_px = (uchar)(255.0F * a_r);_px++;
250     *_px = (uchar)(255.0F * a_g);_px++;
251     *_px = (uchar)(255.0F * a_b);_px++;
252     *_px = (uchar)(255.0F * a_a);_px++;
253   }
254   static void pix2rgba(const ZPixel& a_pix,float& a_r,float& a_g,float& a_b,float& a_a) {
255     uchar* _px = (uchar*)&a_pix;
256     a_r = (*_px)/255.0f;_px++;
257     a_g = (*_px)/255.0f;_px++;
258     a_b = (*_px)/255.0f;_px++;
259     a_a = (*_px)/255.0f;_px++;
260   }
261 protected:
262   void scan_write_point_1(ZPos a_x,ZPos a_y,ZZ a_z,ZPos /*a_beg*/,unsigned int a_size,ZPixel a_pixel) {
263     write_point(a_x,a_y,a_z,a_size,a_pixel);
264   }
265   void scan_write_point_2(ZPos a_x,ZPos a_y,ZZ a_z,ZPos /*a_beg*/,unsigned int a_size,ZPixel a_pixel) {
266     write_point(a_y,a_x,a_z,a_size,a_pixel);
267   }
268   void scan_write_point_3(ZPos a_x,ZPos a_y,ZZ a_z,ZPos a_beg,unsigned int a_size,ZPixel a_pixel) {
269     write_point(a_x,2*a_beg-a_y,a_z,a_size,a_pixel);
270   }
271   void scan_write_point_4(ZPos a_x,ZPos a_y,ZZ a_z,ZPos a_beg,unsigned int a_size,ZPixel a_pixel) {
272     write_point(2*a_beg-a_y,a_x,a_z,a_size,a_pixel);
273   }
274 
275   void blend(ZPixel& a_pix,const ZPixel& a_new) {
276     if(!m_blend) {
277       a_pix = a_new;
278       return;
279     }
280     float _or,_og,_ob,_oa;
281     pix2rgba(a_pix,_or,_og,_ob,_oa);
282     float nr,ng,nb,na;
283     pix2rgba(a_new,nr,ng,nb,na);
284     if((0.0f<=na)&&(na<1.0f)) {
285       // same as glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA):
286       float one_minus_na = 1.0f-na;
287       float pr = nr*na+_or*one_minus_na;
288       float pg = ng*na+_og*one_minus_na;
289       float pb = nb*na+_ob*one_minus_na;
290       float pa = 1;
291       rgba2pix(pr,pg,pb,pa,a_pix);
292     } else {
293       a_pix = a_new;
294     }
295   }
296 
297   static void WriteScanLine(void* a_tag,int a_beg,int a_end,int a_y){
298     buffer& a_buffer = *((buffer*)a_tag);
299 
300     if((a_y<a_buffer.m_begY) || (a_y>a_buffer.m_endY)) return;
301     if(a_end<=a_beg) return;
302 
303     if(a_beg>a_buffer.m_endX) return;
304     if(a_end<a_buffer.m_begX) return;
305 
306     // border clip :
307     int beg = mx(a_beg,(int)a_buffer.m_begX);
308     int end = mn(a_end,(int)a_buffer.m_endX);
309 
310     unsigned long offset = a_y * a_buffer.m_zbw + beg;
311     ZReal* zbuff = a_buffer.m_zbuffer + offset;
312     ZPixel* zimage = a_buffer.m_zimage + offset;
313 
314     ZReal zpoint;
315     for(int x=beg;x<=end;x++){
316       zpoint =
317         (ZReal)(- a_buffer.m_planeDC
318                 - a_buffer.m_planeAC * x
319                 - a_buffer.m_planeBC * a_y);
320       if(a_buffer.m_depth_test) {
321         if((zpoint>=(*zbuff))
322 //       &&(zpoint>=a_buffer.m_zmin) //for plane quite perpandicular to screen.
323 //       &&(zpoint<=a_buffer.m_zmax)
324           ){
325           *zbuff = zpoint;
326           a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
327         }
328       } else {
329         *zbuff = zpoint;
330         a_buffer.blend(*zimage,a_buffer.m_scan_pixel);
331       }
332       zbuff  ++;
333       zimage ++;
334     }
335   }
336 
337   typedef void(buffer::*scan_write_point_func)(ZPos,ZPos,ZZ,ZPos,unsigned int,ZPixel);
338   void ScanLine(ZPos a_x,ZPos a_y,ZZ a_z,
339                 ZPos a_dx,ZPos a_dy,ZZ a_dz,
340                 unsigned int a_size,ZPixel a_pixel,
341                 scan_write_point_func a_func){
342     // Mid point algorithm
343     // assume 0<dx    0<=dy<=dx
344 
345     ZPos end = a_x + a_dx;
346     ZPos beg = a_y;
347     ZZ incz = a_dz/(ZZ)a_dx;
348     if(a_dy==0) {
349       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
350       while(a_x<end){
351         a_x++;
352         a_z += incz;
353         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
354       }
355     } else if(a_dy==a_dx) {
356       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
357       while(a_x<end){
358         a_x++;
359         a_y++;
360         a_z += incz;
361         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
362       }
363     } else {
364       ZPos d = 2 * a_dy - a_dx;
365       ZPos incrE = 2 * a_dy;
366       ZPos incrNE = 2 * ( a_dy - a_dx);
367       (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
368       while(a_x<end){
369         if(d<=0){
370           d += incrE;
371           a_x++;
372         }else{
373           d += incrNE;
374           a_x++;
375           a_y++;
376         }
377         a_z += incz;
378         (this->*a_func)(a_x,a_y,a_z,beg,a_size,a_pixel);
379       }
380     }
381   }
382 
383   void WriteLine(const point& a_beg,
384                  const point& a_end,
385                  unsigned int a_size,ZPixel a_pixel){
386     ZPos dx = a_end.x - a_beg.x;
387     ZPos dy = a_end.y - a_beg.y;
388     ZZ   dz = a_end.z - a_beg.z;
389 
390     //  6  2
391     // 5     1
392     // 7     3
393     //  8  4
394 
395     if( (dx==0) && (dy==0) ) {
396       write_point(a_beg.x,a_beg.y,a_beg.z,a_size,a_pixel);
397       write_point(a_end.x,a_end.y,a_end.z,a_size,a_pixel);
398 
399     } else if(dx==0) {
400       if(dy>0)
401         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy, dx, dz, a_size,a_pixel,&buffer::scan_write_point_2);
402       else
403         ScanLine ( a_end.y, a_end.x,a_end.z,-dy, dx,-dz, a_size,a_pixel,&buffer::scan_write_point_2);
404 
405     } else if(dx>0) {
406            if((0<=dy) && (dy<=dx))  /*1*/
407         ScanLine ( a_beg.x, a_beg.y,a_beg.z, dx, dy, dz, a_size,a_pixel,&buffer::scan_write_point_1);
408       else if(dx<dy)                /*2*/
409         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy, dx, dz, a_size,a_pixel,&buffer::scan_write_point_2);
410       else if((-dx<=dy) && (dy<0) ) /*3*/
411         ScanLine ( a_beg.x, a_beg.y,a_beg.z, dx,-dy, dz, a_size,a_pixel,&buffer::scan_write_point_3);
412       else if(dy<-dx)               /*4*/
413         ScanLine ( a_end.y, a_end.x,a_end.z,-dy, dx,-dz, a_size,a_pixel,&buffer::scan_write_point_4);
414 
415     } else { //dx<0
416            if((0<=dy) && (dy<=-dx)) /*5*/
417         ScanLine ( a_end.x, a_end.y,a_end.z,-dx, dy,-dz, a_size,a_pixel,&buffer::scan_write_point_3);
418       else if(-dx<dy)               /*6*/
419         ScanLine ( a_beg.y, a_beg.x,a_beg.z, dy,-dx, dz, a_size,a_pixel,&buffer::scan_write_point_4);
420       else if((dx<=dy) && (dy<0) )  /*7*/
421         ScanLine ( a_end.x, a_end.y,a_end.z,-dx,-dy,-dz, a_size,a_pixel,&buffer::scan_write_point_1);
422       else if(dy<dx)                /*8*/
423         ScanLine ( a_end.y, a_end.x,a_end.z,-dy,-dx,-dz, a_size,a_pixel,&buffer::scan_write_point_2);
424     }
425 
426   }
427 
428 
429 protected:
430   bool         m_depth_test;
431   bool         m_blend;
432   ZReal*       m_zbuffer;
433 //ZReal        m_zmin,m_zmax;
434 
435   ZPixel*      m_zimage;
436 
437   unsigned int m_zbw,m_zbh;
438   ZPos         m_begX,m_begY;
439   ZPos         m_endX,m_endY; //could be <0
440 
441   ZPixel       m_scan_pixel;
442   ZZ           m_planeAC;
443   ZZ           m_planeBC;
444   ZZ           m_planeDC;
445   //int          m_zboundPrec;
446   polygon      m_polygon;
447 };
448 
449 }}
450 
451 #endif