Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/sg/zb_action 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_sg_zb_action
0005 #define tools_sg_zb_action
0006 
0007 #include "zb_manager"
0008 
0009 #include "render_action"
0010 #include "primitive_visitor"
0011 #include "../glprims"
0012 
0013 #include "../zb/buffer"
0014 
0015 #include "../colorfs"
0016 #include "../lina/plane"
0017 #include "../mathf"
0018 #include "../lina/vec3d" //ZZ=double
0019 
0020 namespace tools {
0021 namespace sg {
0022 
0023 class zb_action : public render_action {
0024   TOOLS_ACTION(zb_action,tools::sg::zb_action,render_action)
0025 private:  
0026   zb_action& get_me() {return *this;}
0027 public:
0028   virtual void draw_vertex_array(gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs){
0029     m_pv.add_primitive(a_mode,a_floatn,a_xyzs);
0030   }
0031 
0032   virtual void draw_vertex_array_xy(gl::mode_t a_mode,size_t a_floatn,const float* a_xys){
0033     m_pv.add_primitive_xy(a_mode,a_floatn,a_xys);
0034   }
0035 
0036   virtual void draw_vertex_color_array(gl::mode_t a_mode,size_t a_floatn,
0037                                        const float* a_xyzs,const float* a_rgbas){
0038     m_pv.add_primitive_rgba(a_mode,a_floatn,a_xyzs,a_rgbas);
0039   }
0040 
0041   virtual void draw_vertex_normal_array(gl::mode_t a_mode,size_t a_floatn,
0042                                         const float* a_xyzs,const float* a_nms){
0043     m_pv.add_primitive_normal(a_mode,a_floatn,a_xyzs,a_nms);
0044   }
0045 
0046   virtual void draw_vertex_color_normal_array(gl::mode_t a_mode,size_t a_floatn,
0047                                               const float* a_xyzs,const float* a_rgbas,const float* a_nms){
0048     // We expect a_nms of size : 3*(a_floatn/3)
0049     // (then one normal per 3D point).
0050     m_pv.add_primitive_normal_rgba(a_mode,a_floatn,a_xyzs,a_nms,a_rgbas);
0051   }
0052 
0053   virtual void clear_color(float a_r,float a_g,float a_b,float a_a){
0054     zb::buffer::ZPixel pix;
0055     zb::buffer::rgba2pix(a_r,a_g,a_b,a_a,pix);
0056     m_zb.clear_color_buffer(pix);
0057   }
0058   virtual void color4f(float a_r,float a_g,float a_b,float a_a){
0059     m_rgba.set_value(a_r,a_g,a_b,a_a);
0060   }
0061   virtual void line_width(float a_v){m_line_width = a_v;}
0062   virtual void point_size(float a_v) {m_point_size = a_v;}
0063   virtual void set_polygon_offset(bool a_v) {m_POLYGON_OFFSET_FILL = a_v;}
0064   virtual void normal(float a_x,float a_y,float a_z) {
0065     m_normal.set_value(a_x,a_y,a_z);
0066   }
0067 
0068   virtual void set_winding(winding_type a_v) {
0069     m_ccw = (a_v==winding_ccw?true:false);
0070   }
0071   virtual void set_shade_model(shade_type) {}
0072 
0073   virtual void set_depth_test(bool a_on) {m_DEPTH_TEST = a_on;}
0074 
0075   virtual void set_cull_face(bool a_on) {m_CULL_FACE = a_on;}
0076   virtual void set_point_smooth(bool a_on) {m_POINT_SMOOTH = a_on;}
0077   virtual void set_line_smooth(bool a_on) {m_LINE_SMOOTH = a_on;}
0078 
0079   virtual void load_proj_matrix(const mat4f& a_mtx) {
0080     m_proj = a_mtx;
0081   }
0082 
0083   virtual void load_model_matrix(const mat4f& a_mtx) {
0084     m_model = a_mtx;
0085     set_normal_matrix();
0086   }
0087 
0088   virtual unsigned int max_lights() {return 1000;}
0089 
0090   virtual void enable_light(unsigned int,
0091                             float a_dx,float a_dy,float a_dz,
0092                             float a_r,float a_g,float a_b,float a_a,
0093                             float a_ar,float a_ag,float a_ab,float a_aa){
0094     m_light_color.set_value(a_r,a_g,a_b,a_a);
0095     m_light_ambient.set_value(a_ar,a_ag,a_ab,a_aa);
0096     m_light_direction.set_value(a_dx,a_dy,a_dz);
0097     m_light_direction.normalize();
0098     m_light_on = true;
0099   }
0100 
0101   virtual void set_lighting(bool a_value) {m_light_on = a_value;}
0102   virtual void set_blend(bool a_value) {m_blend = a_value;}
0103 
0104   virtual void restore_state(unsigned int /*a_ret_num_light*/) {
0105     const sg::state& _state = state();
0106     m_proj = _state.m_proj;
0107     m_model = _state.m_model;
0108     set_normal_matrix();
0109 
0110     m_rgba = _state.m_color;
0111     m_normal = _state.m_normal;
0112 
0113     m_ccw = (_state.m_winding==winding_ccw?true:false);
0114     m_POLYGON_OFFSET_FILL = _state.m_GL_POLYGON_OFFSET_FILL;
0115     m_CULL_FACE = _state.m_GL_CULL_FACE;
0116     m_POINT_SMOOTH = _state.m_GL_POINT_SMOOTH;
0117     m_LINE_SMOOTH = _state.m_GL_LINE_SMOOTH;
0118     m_line_width = _state.m_line_width;
0119     m_point_size = _state.m_point_size;
0120     m_light_on = _state.m_GL_LIGHTING;
0121     m_DEPTH_TEST = _state.m_GL_DEPTH_TEST;
0122     m_blend = _state.m_GL_BLEND;
0123 
0124 /*
0125     if(_state.m_GL_TEXTURE_2D) ::glEnable(GL_TEXTURE_2D);
0126     else                       ::glDisable(GL_TEXTURE_2D);
0127 
0128     // The "return of separator" state had ret_num_light.
0129     // The restored state has m_light.
0130     // We have to glDisable lights with index in [m_light,ret_num_light-1]
0131     for(unsigned int index=_state.m_light;index<a_ret_num_light;index++) {
0132       ::glDisable(GL_LIGHT0+index);
0133     }
0134 */
0135   }
0136 
0137   /////////////////////////////////////////////////////////////////
0138   /// texture /////////////////////////////////////////////////////
0139   /////////////////////////////////////////////////////////////////
0140   virtual void draw_vertex_array_texture(gl::mode_t,size_t a_xyzn,const float* a_xyzs,
0141                                          gstoid a_id,const float* a_tcs) {
0142     //::printf("debug : zb_action : 000 : %d\n",a_id);
0143     img_byte img;
0144     if(!m_mgr.find(a_id,img)) return;
0145     m_pv.add_texture(m_out,a_xyzn,a_xyzs,img,a_tcs);
0146   }
0147 
0148   virtual void draw_vertex_normal_array_texture(gl::mode_t a_mode,
0149                                                 size_t a_xyzn,const float* a_xyzs,const float* /*a_nms*/,
0150                                                 gstoid a_id,const float* a_tcs) {
0151     draw_vertex_array_texture(a_mode,a_xyzn,a_xyzs,a_id,a_tcs);
0152   }
0153 
0154   /////////////////////////////////////////////////////////////////
0155   /// VBO /////////////////////////////////////////////////////////
0156   /////////////////////////////////////////////////////////////////
0157   virtual void begin_gsto(gstoid) {}
0158   virtual void draw_gsto_v(gl::mode_t,size_t,bufpos){}
0159   virtual void draw_gsto_vc(gl::mode_t,size_t,bufpos,bufpos) {}
0160   virtual void draw_gsto_vn(gl::mode_t,size_t,bufpos,bufpos) {}
0161   virtual void draw_gsto_vcn(gl::mode_t,size_t,bufpos,bufpos,bufpos) {}
0162   virtual void end_gsto() {}
0163   /////////////////////////////////////////////////////////////////
0164   /////////////////////////////////////////////////////////////////
0165   /////////////////////////////////////////////////////////////////
0166   virtual sg::render_manager& render_manager() {return m_mgr;}
0167 public:
0168   zb_action(zb_manager& a_mgr,std::ostream& a_out,unsigned int a_ww,unsigned int a_wh)
0169   :parent(a_out,a_ww,a_wh)
0170   ,m_mgr(a_mgr)
0171   ,m_pv(get_me())
0172   ,m_light_color(colorf_white())
0173   ,m_light_ambient(colorf_black())
0174   ,m_light_direction(vec3f(0,0,-1))
0175   ,m_normal(0,0,1)
0176 
0177   ,m_ccw(true)
0178   ,m_POLYGON_OFFSET_FILL(false)
0179   ,m_CULL_FACE(true)
0180   ,m_POINT_SMOOTH(false)
0181   ,m_LINE_SMOOTH(false)
0182   ,m_line_width(1)
0183   ,m_point_size(1)
0184   ,m_light_on(false)
0185   ,m_DEPTH_TEST(true)
0186   ,m_blend(false)
0187   {
0188     m_vp_mtx.set_identity();
0189     m_vp_mtx.mul_translate(float(m_ww)/2,float(m_wh)/2,0);
0190     m_vp_mtx.mul_scale(float(m_ww)/2,float(m_wh)/2,1);
0191 
0192     m_zb.change_size(a_ww,a_wh);
0193   //m_zb.clear_color_buffer(0);
0194   //m_zb.clear_depth_buffer();
0195 
0196     m_proj.set_identity();
0197     m_model.set_identity();
0198     m_normal_matrix.set_identity();
0199   }
0200   virtual ~zb_action(){}
0201 protected:
0202   zb_action(const zb_action& a_from)
0203   :parent(a_from)
0204   ,m_mgr(a_from.m_mgr)
0205   ,m_vp_mtx(a_from.m_vp_mtx)
0206   ,m_pv(a_from.m_pv)
0207   ,m_light_color(a_from.m_light_color)
0208   ,m_light_ambient(a_from.m_light_ambient)
0209   ,m_light_direction(a_from.m_light_direction)
0210   ,m_normal(a_from.m_normal)
0211 
0212   ,m_proj(a_from.m_proj)
0213   ,m_model(a_from.m_model)
0214   ,m_normal_matrix(a_from.m_normal_matrix)
0215   ,m_rgba(a_from.m_rgba)
0216   ,m_ccw(a_from.m_ccw)
0217   ,m_POLYGON_OFFSET_FILL(a_from.m_POLYGON_OFFSET_FILL)
0218   ,m_CULL_FACE(a_from.m_CULL_FACE)
0219   ,m_POINT_SMOOTH(a_from.m_POINT_SMOOTH)
0220   ,m_LINE_SMOOTH(a_from.m_LINE_SMOOTH)
0221   ,m_line_width(a_from.m_line_width)
0222   ,m_point_size(a_from.m_point_size)
0223   ,m_light_on(a_from.m_light_on)
0224   ,m_DEPTH_TEST(a_from.m_DEPTH_TEST)
0225   ,m_blend(a_from.m_blend)
0226   {}
0227   zb_action& operator=(const zb_action& a_from){
0228     parent::operator=(a_from);
0229     m_vp_mtx = a_from.m_vp_mtx;
0230     m_pv = a_from.m_pv;
0231     m_light_color = a_from.m_light_color;
0232     m_light_ambient = a_from.m_light_ambient;
0233     m_light_direction = a_from.m_light_direction;
0234     m_normal = a_from.m_normal;
0235 
0236     m_proj = a_from.m_proj;
0237     m_model = a_from.m_model;
0238     m_normal_matrix = a_from.m_normal_matrix;
0239     m_rgba = a_from.m_rgba;
0240     m_ccw = a_from.m_ccw;
0241     m_POLYGON_OFFSET_FILL = a_from.m_POLYGON_OFFSET_FILL;
0242     m_CULL_FACE = a_from.m_CULL_FACE;
0243     m_POINT_SMOOTH = a_from.m_POINT_SMOOTH;
0244     m_LINE_SMOOTH = a_from.m_LINE_SMOOTH;
0245     m_line_width = a_from.m_line_width;
0246     m_point_size = a_from.m_point_size;
0247     m_light_on = a_from.m_light_on;
0248     m_DEPTH_TEST = a_from.m_DEPTH_TEST;
0249     m_blend = a_from.m_blend;
0250     return *this;
0251   }
0252 public:
0253   void clear_color_buffer(float a_r,float a_g,float a_b,float a_a){
0254     clear_color(a_r,a_g,a_b,a_a);
0255   }
0256   void clear_color_buffer(const colorf& a_color){
0257     clear_color(a_color.r(),a_color.g(),a_color.b(),a_color.a());
0258   }
0259   
0260   void clear_depth_buffer() {m_zb.clear_depth_buffer();}
0261 protected:
0262   typedef unsigned char uchar;
0263 protected:
0264   static void color2pix(const colorf& a_rgba,zb::buffer::ZPixel& a_pix) {
0265     zb::buffer::rgba2pix(a_rgba.r(),a_rgba.g(),a_rgba.b(),a_rgba.a(),a_pix);
0266   }
0267 public:
0268   zb::buffer::ZPixel* get_color_buffer(unsigned int& a_width,unsigned int& a_height) const {return m_zb.get_color_buffer(a_width,a_height);}
0269 
0270   bool get_rgbs(bool a_top_to_bottom,std::vector<uchar>& a_buffer) {
0271     a_buffer.clear();
0272     if(!m_ww || !m_wh) return false;
0273     size_t sz = 3 * m_ww * m_wh;
0274     a_buffer.resize(sz);
0275     uchar* pos = vec_data(a_buffer);
0276     zb::buffer::ZPixel pix;
0277     uchar* _pix = 0;
0278     for(unsigned int row=0;row<m_wh;row++) {
0279       for(unsigned int col=0;col<m_ww;col++) {
0280         if(!m_zb.get_clipped_pixel(col,a_top_to_bottom?row:m_wh-1-row,pix)){
0281           m_out << "tools::sg::zb_action::get_rgbs : can't get zbuffer pixel" << std::endl;
0282           *pos = 0xFF;pos++;
0283           *pos = 0x00;pos++;
0284           *pos = 0x00;pos++;
0285         } else {
0286           _pix = (uchar*)&pix;
0287           *pos = *_pix;_pix++;pos++;
0288           *pos = *_pix;_pix++;pos++;
0289           *pos = *_pix;_pix++;pos++;
0290         }
0291       }
0292     }
0293     return true;
0294   }
0295 
0296   bool get_rgbas(bool a_top_to_bottom,std::vector<uchar>& a_buffer) {
0297     a_buffer.clear();
0298     if(!m_ww || !m_wh) return false;
0299     size_t sz = 4 * m_ww * m_wh;
0300     a_buffer.resize(sz);
0301     if(a_top_to_bottom) {
0302       ::memcpy(vec_data(a_buffer),m_zb.zimage(),sz);
0303       return true;
0304     }
0305     size_t stride = m_ww*4;
0306     uchar* zpos = ((uchar*)m_zb.zimage())+sz-stride;
0307     uchar* pos = vec_data(a_buffer);
0308     for(unsigned int row=0;row<m_wh;row++,pos+=stride,zpos-=stride) ::memcpy(pos,zpos,stride);
0309     return true;
0310   }
0311   bool get_rgbas_cocoa(unsigned int a_factor,std::vector<uchar>& a_buffer) {
0312     a_buffer.clear();
0313     if(!m_ww || !m_wh) return false;
0314     if(!a_factor) return false;
0315     size_t bpp = 4;
0316     a_buffer.resize(a_factor* m_ww * a_factor * m_wh * bpp);
0317     uchar* zbuffer = (uchar*)m_zb.zimage();
0318     uchar* abuffer = vec_data(a_buffer);
0319     size_t zstride = m_ww*bpp;
0320     size_t astride = a_factor*m_ww*bpp;
0321     size_t i,j,ar,ac,ipix;
0322     uchar* zpos;uchar* apos;
0323     for(j=0;j<m_wh;j++) {
0324       for(i=0;i<m_ww;i++) {
0325         //position in the original image.
0326         zpos = zbuffer + (m_wh-1-j) * zstride + i*bpp;  //top_to_bottom.
0327 
0328         for(ar=0;ar<a_factor;ar++) {
0329           for(ac=0;ac<a_factor;ac++) {
0330             //position in the new image.
0331             apos = abuffer + (j*a_factor+ar) * astride + (i*a_factor+ac)*bpp;
0332             for(ipix=0;ipix<bpp;ipix++) {
0333               *(apos+ipix) = *(zpos+ipix);
0334             }
0335           }
0336         }
0337 
0338       }
0339     }
0340 
0341     return true;
0342   }
0343 
0344   bool get_bgras(bool a_top_to_bottom,std::vector<uchar>& a_buffer) {
0345     a_buffer.clear();
0346     if(!m_ww || !m_wh) return false;
0347     size_t sz = 4 * m_ww * m_wh;
0348     a_buffer.resize(sz);
0349     if(a_top_to_bottom) {
0350       uchar* pos = vec_data(a_buffer);
0351       uchar* zpos = ((uchar*)m_zb.zimage());
0352       for(size_t count=0;count<sz;count+=4,pos+=4,zpos+=4) {
0353         *(pos+0) = *(zpos+2);
0354         *(pos+1) = *(zpos+1);
0355         *(pos+2) = *(zpos+0);
0356         *(pos+3) = *(zpos+3);
0357       }
0358     } else {
0359       size_t stride = m_ww*4;
0360       uchar* pos_line = vec_data(a_buffer);
0361       uchar* zpos_line = ((uchar*)m_zb.zimage())+sz-stride;
0362       uchar* pos;
0363       uchar* zpos;
0364       size_t count;
0365       for(unsigned int row=0;row<m_wh;row++,pos_line+=stride,zpos_line-=stride) {
0366         pos = pos_line;
0367         zpos = zpos_line;
0368         for(count=0;count<m_ww;count++,pos+=4,zpos+=4) {
0369           *(pos+0) = *(zpos+2);
0370           *(pos+1) = *(zpos+1);
0371           *(pos+2) = *(zpos+0);
0372           *(pos+3) = *(zpos+3);
0373         }
0374       }
0375     }
0376     return true;
0377   }
0378 public:
0379   static bool get_rgb(void* a_tag,unsigned int a_col,unsigned int a_row,float& a_r,float& a_g,float& a_b){
0380     //used with wps.
0381     zb_action* rzb = (zb_action*)a_tag;
0382     zb::buffer::ZPixel pix;
0383     if(!rzb->m_zb.get_clipped_pixel(a_col,rzb->wh()-1-a_row,pix)){
0384       rzb->out() << "tools::sg;:zb_action::get_rgb: can't get zbuffer pixel" << std::endl;
0385       a_r = 1;
0386       a_g = 0;
0387       a_b = 0;
0388       return false;
0389     }
0390     float a;
0391     zb::buffer::pix2rgba(pix,a_r,a_g,a_b,a);
0392     return true;
0393   }
0394 protected:
0395   void set_normal_matrix() {
0396     mat4f tmp(m_model);
0397     tmp.no_translate();
0398     if(!tmp.invert(m_normal_matrix)) {
0399       m_out << "tools::sg::zb_action::set_normal_matrix : can't invert model matrix." << std::endl;
0400     }
0401     m_normal_matrix.transpose();
0402   }
0403   
0404   bool project_point(float& a_x,float& a_y,float& a_z,float& a_w) {
0405     a_w = 1;
0406     m_model.mul_4f_opt(a_x,a_y,a_z,a_w,m_tmp);
0407     m_proj.mul_4f_opt(a_x,a_y,a_z,a_w,m_tmp);
0408     if(a_w==0) return false;
0409     a_x /= a_w;
0410     a_y /= a_w;
0411     a_z /= a_w;
0412     return true;
0413   }
0414 //  bool project_normal(float& a_x,float& a_y,float& a_z) {
0415 //    m_model.mul_dir_3f(a_x,a_y,a_z);
0416 //    m_proj.mul_dir_3f(a_x,a_y,a_z);
0417 //    return true;
0418 //  }
0419 
0420   class primvis : public primitive_visitor {
0421   protected:
0422     virtual bool project(float& a_x,float& a_y,float& a_z,float& a_w) {
0423       return m_this.project_point(a_x,a_y,a_z,a_w);
0424     }
0425     virtual bool add_point(float a_x,float a_y,float a_z,float) {
0426       return _add_point(a_x,a_y,a_z,m_this.m_rgba.r(),m_this.m_rgba.g(),m_this.m_rgba.b(),m_this.m_rgba.a());
0427     }
0428 
0429     virtual bool add_point(float a_x,float a_y,float a_z,float,
0430                            float a_r,float a_g,float a_b,float a_a) {
0431       return _add_point(a_x,a_y,a_z,a_r,a_g,a_b,a_a);
0432     }
0433 
0434     virtual bool add_line(float a_bx,float a_by,float a_bz,float,
0435                           float a_ex,float a_ey,float a_ez,float) {
0436       m_this.m_vp_mtx.mul_3f_opt(a_bx,a_by,a_bz,m_tmp);
0437       m_this.m_vp_mtx.mul_3f_opt(a_ex,a_ey,a_ez,m_tmp);
0438       a_bz *= -1;
0439       a_ez *= -1;
0440 
0441       zb::point beg;
0442       zinit(beg,a_bx,a_by,a_bz);
0443 
0444       zb::point end;
0445       zinit(end,a_ex,a_ey,a_ez);
0446 
0447       m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
0448       m_this.m_zb.set_blend(m_this.m_blend);
0449 
0450       zb::buffer::ZPixel pix;
0451       color2pix(m_this.m_rgba,pix);
0452       m_this.m_zb.draw_line(beg,end,pix,npix(m_this.m_line_width));
0453 
0454       return true;
0455     }
0456 
0457     virtual bool add_line(float a_bx,float a_by,float a_bz,float,
0458                           float a_br,float a_bg,float a_bb,float a_ba,
0459                           float a_ex,float a_ey,float a_ez,float,
0460                           float,float,float,float) {
0461       m_this.m_vp_mtx.mul_3f_opt(a_bx,a_by,a_bz,m_tmp);
0462       m_this.m_vp_mtx.mul_3f_opt(a_ex,a_ey,a_ez,m_tmp);
0463       a_bz *= -1;
0464       a_ez *= -1;
0465 
0466       zb::point beg;
0467       zinit(beg,a_bx,a_by,a_bz);
0468 
0469       zb::point end;
0470       zinit(end,a_ex,a_ey,a_ez);
0471 
0472       m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
0473       m_this.m_zb.set_blend(m_this.m_blend);
0474 
0475       // interpolate color with beg,end ?
0476       zb::buffer::ZPixel pix;
0477       zb::buffer::rgba2pix(a_br,a_bg,a_bb,a_ba,pix);
0478       m_this.m_zb.draw_line(beg,end,pix,npix(m_this.m_line_width));
0479 
0480       return true;
0481     }
0482 
0483     virtual bool add_triangle(float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0484                               float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0485                               float a_p3x,float a_p3y,float a_p3z,float a_p3w){
0486       return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0487                            m_this.m_normal.x(),
0488                            m_this.m_normal.y(),
0489                            m_this.m_normal.z(),
0490                            a_p2x,a_p2y,a_p2z,a_p2w,
0491                            m_this.m_normal.x(),
0492                            m_this.m_normal.y(),
0493                            m_this.m_normal.z(),
0494                            a_p3x,a_p3y,a_p3z,a_p3w,
0495                            m_this.m_normal.x(),
0496                            m_this.m_normal.y(),
0497                            m_this.m_normal.z(),
0498                            m_this.m_rgba);
0499     }
0500 
0501     virtual bool add_triangle(
0502       float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0503       float a_r1,float a_g1,float a_b1,float a_a1,
0504       float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0505       float a_r2,float a_g2,float a_b2,float a_a2,
0506       float a_p3x,float a_p3y,float a_p3z,float a_p3w,
0507       float a_r3,float a_g3,float a_b3,float a_a3){
0508 
0509       float r = (a_r1+a_r2+a_r3)/3.0f;
0510       float g = (a_g1+a_g2+a_g3)/3.0f;
0511       float b = (a_b1+a_b2+a_b3)/3.0f;
0512       float a = (a_a1+a_a2+a_a3)/3.0f;
0513       colorf col(r,g,b,a);
0514 
0515       return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0516                            m_this.m_normal.x(),
0517                            m_this.m_normal.y(),
0518                            m_this.m_normal.z(),
0519                            a_p2x,a_p2y,a_p2z,a_p2w,
0520                            m_this.m_normal.x(),
0521                            m_this.m_normal.y(),
0522                            m_this.m_normal.z(),
0523                            a_p3x,a_p3y,a_p3z,a_p3w,
0524                            m_this.m_normal.x(),
0525                            m_this.m_normal.y(),
0526                            m_this.m_normal.z(),
0527                            col);
0528     }
0529 
0530     virtual bool project_normal(float&,float&,float&) {
0531       //return m_this.project_normal(a_x,a_y,a_z);
0532       return true;
0533     }
0534     virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
0535                                   float /*a_nx*/,float /*a_ny*/,float /*a_nz*/) {
0536       add_point(a_x,a_y,a_z,a_w);
0537       return true;
0538     }
0539     virtual bool add_point_normal(float a_x,float a_y,float a_z,float a_w,
0540                                   float /*a_nx*/,float /*a_ny*/,float /*a_nz*/,
0541                                   float a_r,float a_g,float a_b,float a_a) {
0542       add_point(a_x,a_y,a_z,a_w,a_r,a_g,a_b,a_a);
0543       return true;
0544     }
0545     virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw,
0546                                  float /*a_bnx*/,float /*a_bny*/,float /*a_bnz*/,
0547                                  float a_ex,float a_ey,float a_ez,float a_ew,
0548                                  float /*a_enx*/,float /*a_eny*/,float /*a_enz*/) {
0549       add_line(a_bx,a_by,a_bz,a_bw, a_ex,a_ey,a_ez,a_ew);
0550       return true;
0551     }
0552     virtual bool add_line_normal(float a_bx,float a_by,float a_bz,float a_bw,
0553                                  float /*a_bnx*/,float /*a_bny*/,float /*a_bnz*/,
0554                                  float a_br,float a_bg,float a_bb,float a_ba,
0555                                  float a_ex,float a_ey,float a_ez,float a_ew,
0556                                  float /*a_enx*/,float /*a_eny*/,float /*a_enz*/,
0557                                  float a_er,float a_eg,float a_eb,float a_ea){
0558       add_line(a_bx,a_by,a_bz,a_bw, a_br,a_bg,a_bb,a_ba, a_ex,a_ey,a_ez,a_ew, a_er,a_eg,a_eb,a_ea);
0559       return true;
0560     }
0561     virtual bool add_triangle_normal(
0562       float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0563       float a_n1x,float a_n1y,float a_n1z,
0564       float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0565       float a_n2x,float a_n2y,float a_n2z,
0566       float a_p3x,float a_p3y,float a_p3z,float a_p3w,
0567       float a_n3x,float a_n3y,float a_n3z) {
0568       
0569       return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0570                            a_n1x,a_n1y,a_n1z,
0571                            a_p2x,a_p2y,a_p2z,a_p2w,
0572                            a_n2x,a_n2y,a_n2z,
0573                            a_p3x,a_p3y,a_p3z,a_p3w,
0574                            a_n3x,a_n3y,a_n3z,
0575                            m_this.m_rgba);
0576       return true;
0577     }
0578     virtual bool add_triangle_normal(
0579       float a_p1x,float a_p1y,float a_p1z,float a_p1w,
0580       float a_n1x,float a_n1y,float a_n1z,
0581       float a_r1,float a_g1,float a_b1,float a_a1,
0582       float a_p2x,float a_p2y,float a_p2z,float a_p2w,
0583       float a_n2x,float a_n2y,float a_n2z,
0584       float a_r2,float a_g2,float a_b2,float a_a2,
0585       float a_p3x,float a_p3y,float a_p3z,float a_p3w,
0586       float a_n3x,float a_n3y,float a_n3z,
0587       float a_r3,float a_g3,float a_b3,float a_a3){
0588       
0589       float r = (a_r1+a_r2+a_r3)/3.0f;
0590       float g = (a_g1+a_g2+a_g3)/3.0f;
0591       float b = (a_b1+a_b2+a_b3)/3.0f;
0592       float a = (a_a1+a_a2+a_a3)/3.0f;
0593       colorf col(r,g,b,a);
0594 
0595       return _add_triangle(a_p1x,a_p1y,a_p1z,a_p1w,
0596                            a_n1x,a_n1y,a_n1z,
0597                            a_p2x,a_p2y,a_p2z,a_p2w,
0598                            a_n2x,a_n2y,a_n2z,
0599                            a_p3x,a_p3y,a_p3z,a_p3w,
0600                            a_n3x,a_n3y,a_n3z,
0601                            col);
0602       return true;
0603     }
0604   public:
0605     primvis(zb_action& a_zb):m_this(a_zb){}
0606     virtual ~primvis(){}
0607   public:
0608     primvis(const primvis& a_from)
0609     :primitive_visitor(a_from)
0610     ,m_this(a_from.m_this)
0611     {}
0612     primvis& operator=(const primvis& a_from){
0613       primitive_visitor::operator=(a_from);
0614       return *this;
0615     }
0616   protected:
0617     static void zinit(zb::point& a_p,float a_x,float a_y,float a_z) {
0618       a_p.x = fround(a_x); //float -> int
0619       a_p.y = fround(a_y); //float -> int
0620       a_p.z = (zb::ZZ)a_z; //float -> double
0621     }
0622 
0623     unsigned int npix(float a_size) {
0624       // 0 -> 0
0625       // 1 -> 0
0626       // 2 -> 1    3x3
0627       // 3 -> 1    3x3
0628       // 4 -> 2    5x5
0629       // 5 -> 2    5x5
0630       // 6 -> 3    7x7
0631       unsigned int num = (unsigned int)a_size;
0632       unsigned int num_2 = num/2;
0633       if(2*num_2==num) {num++;num_2 = num/2;}
0634       return num_2;
0635     }
0636 
0637     bool _add_point(float a_x,float a_y,float a_z,float a_r,float a_g,float a_b,float a_a){
0638       m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
0639       m_this.m_zb.set_blend(m_this.m_blend);
0640 
0641       m_this.m_vp_mtx.mul_3f_opt(a_x,a_y,a_z,m_tmp);
0642       a_z *= -1;
0643 
0644       zb::point p;
0645       zinit(p,a_x,a_y,a_z);
0646 
0647       zb::buffer::ZPixel pix;
0648       zb::buffer::rgba2pix(a_r,a_g,a_b,a_a,pix);
0649       m_this.m_zb.draw_point(p,pix,npix(m_this.m_point_size));
0650 
0651       return true;
0652     }
0653 
0654     bool _add_triangle(float a_p1x,float a_p1y,float a_p1z,float /*a_p1w*/,
0655                        float a_n1x,float a_n1y,float a_n1z,
0656                        float a_p2x,float a_p2y,float a_p2z,float /*a_p2w*/,
0657                        float a_n2x,float a_n2y,float a_n2z,
0658                        float a_p3x,float a_p3y,float a_p3z,float /*a_p3w*/,
0659                        float a_n3x,float a_n3y,float a_n3z,
0660                        const colorf& a_color){
0661 
0662       float p1x = a_p1x;float p1y = a_p1y;float p1z = a_p1z;//float p1w = a_p1w;
0663       float p2x = a_p2x;float p2y = a_p2y;float p2z = a_p2z;//float p2w = a_p2w;
0664       float p3x = a_p3x;float p3y = a_p3y;float p3z = a_p3z;//float p3w = a_p3w;
0665 
0666       m_this.m_vp_mtx.mul_3f_opt(p1x,p1y,p1z,m_tmp);
0667       m_this.m_vp_mtx.mul_3f_opt(p2x,p2y,p2z,m_tmp);
0668       m_this.m_vp_mtx.mul_3f_opt(p3x,p3y,p3z,m_tmp);
0669       p1z *= -1;
0670       p2z *= -1;
0671       p3z *= -1;
0672 
0673       if(m_this.m_POLYGON_OFFSET_FILL){
0674         //note : gopaw pawex9,14,15,21 with "lego" (drawing cubes) are sensitive to the below epsil.
0675         // zs are in [-1,1]
0676         float epsil = 1e-4f;
0677         p1z -= epsil;
0678         p2z -= epsil;
0679         p3z -= epsil;
0680       }
0681 
0682       typedef zb::ZZ ZZ; //double
0683 
0684       plane<vec3d> pn(
0685         vec3<ZZ>(p1x,p1y,p1z),
0686         vec3<ZZ>(p2x,p2y,p2z),
0687         vec3<ZZ>(p3x,p3y,p3z)
0688       );
0689       if(!pn.is_valid()) return true;
0690 
0691       // norm[0]*x+norm[1]*y+norm[2]*z = dist
0692       // A*x+B*y+C*z+D = 0
0693 
0694       ZZ C = pn.normal()[2];
0695 
0696       if(m_this.m_CULL_FACE){
0697         if(m_this.m_ccw) {
0698           if(C<=0) return true;
0699         } else {
0700           if(C>=0) return true;
0701         }
0702       }
0703 
0704       ZZ A = pn.normal()[0];
0705       ZZ B = pn.normal()[1];
0706       ZZ D = -pn.distance_from_origin();
0707 
0708       //ZZ zmn = mn<ZZ>(mn<ZZ>(p1z,p2z),p3z);
0709       //ZZ zmx = mx<ZZ>(mx<ZZ>(p1z,p2z),p3z);
0710 
0711       zb::point list[3];
0712       zinit(list[0],p1x,p1y,p1z);
0713       zinit(list[1],p2x,p2y,p2z);
0714       zinit(list[2],p3x,p3y,p3z);
0715 
0716       m_this.m_zb.set_depth_test(m_this.m_DEPTH_TEST);
0717       m_this.m_zb.set_blend(m_this.m_blend);
0718 
0719       colorf frag_color = a_color;
0720 
0721       if(m_this.m_light_on) {  // same logic as toolx/wasm/webgl.js:
0722 
0723         float nx = (a_n1x+a_n2x+a_n3x)/3.0f;
0724         float ny = (a_n1y+a_n2y+a_n3y)/3.0f;
0725         float nz = (a_n1z+a_n2z+a_n3z)/3.0f;
0726 
0727         m_this.m_normal_matrix.mul_dir_3f_opt(nx,ny,nz,m_tmp);
0728 
0729         vec3f _normal(nx,ny,nz);_normal.normalize();
0730 
0731         float _dot = _normal.dot(m_this.m_light_direction);
0732 
0733         if(_dot<0.0f) {
0734           _dot *= -1.0f;
0735 
0736           colorf _tmp = m_this.m_light_color;
0737           _tmp *= _dot;
0738 //        _tmp *= 1.4f;  //to have same intensity as GL on desktops.
0739           _tmp += m_this.m_light_ambient;
0740 
0741           frag_color *= _tmp;
0742 
0743         } else {
0744           frag_color *= m_this.m_light_ambient;
0745         }
0746 
0747         frag_color.clamp();
0748         frag_color.set_a(a_color.a());
0749 
0750       }
0751 
0752       zb::buffer::ZPixel pix;
0753       color2pix(frag_color,pix);
0754       m_this.m_zb.draw_polygon(3,list,A,B,C,D,pix);
0755 
0756       return true;
0757     }
0758   protected:
0759     zb_action& m_this;
0760   private:  //optimize:
0761     float m_tmp[3];
0762   };
0763 
0764 protected:
0765   zb_manager& m_mgr;
0766   mat4f m_vp_mtx;
0767   zb::buffer m_zb;
0768   primvis m_pv;
0769   colorf m_light_color;
0770   colorf m_light_ambient;
0771   vec3f m_light_direction;
0772   vec3f m_normal;
0773 
0774   // to be restored in restore_state() :
0775   mat4f m_proj;
0776   mat4f m_model;
0777   mat4f m_normal_matrix;
0778   colorf m_rgba;
0779   bool m_ccw;
0780   bool m_POLYGON_OFFSET_FILL;
0781   bool m_CULL_FACE;
0782   bool m_POINT_SMOOTH;
0783   bool m_LINE_SMOOTH;
0784   float m_line_width;
0785   float m_point_size;
0786   bool m_light_on;
0787   bool m_DEPTH_TEST;
0788   bool m_blend;
0789 private:  //optimize:
0790   float m_tmp[4];
0791 };
0792 
0793 }}
0794 
0795 #endif