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