Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_sg_tex_rect 5 #define tools_sg_tex_rect 6 7 // node to render an RGB tools::img_byte with ::glTexImage2D. 8 9 //#define TOOLS_SG_TEX_RECT_DEBUG 10 11 #include "node" 12 #include "render_action" 13 #include "pick_action" 14 #include "bbox_action" 15 #include "event_action" 16 #include "render_manager" 17 #include "gstos" 18 #include "base_tex" 19 20 #include "../pointer" 21 #include "../num2s" 22 23 namespace tools { 24 namespace sg { 25 26 class tex_rect : public node, public gstos, public base_tex { 27 TOOLS_NODE_NO_CAST(tex_rect,tools::sg::tex_rect,node) 28 public: 29 virtual void* cast(const std::string& a_class) const { 30 {if(void* p = cmp_cast<tex_rect>(this,a_class)) return p;} 31 {if(void* p = base_tex::cast(a_class)) return p;} 32 return parent::cast(a_class); 33 } 34 public: 35 sf<bool> show_border; 36 sf<float> height; 37 public: 38 virtual const desc_fields& node_desc_fields() const { 39 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::tex_rect) 40 static const desc_fields s_v(parent::node_desc_fields(),6, //WARNING : take care of count. 41 TOOLS_ARG_FIELD_DESC(img), 42 TOOLS_ARG_FIELD_DESC(back_color), 43 TOOLS_ARG_FIELD_DESC(expand), 44 TOOLS_ARG_FIELD_DESC(limit), 45 TOOLS_ARG_FIELD_DESC(show_border), 46 TOOLS_ARG_FIELD_DESC(height) 47 ); 48 return s_v; 49 } 50 private: 51 void add_fields(){ 52 add_field(&img); 53 add_field(&back_color); 54 add_field(&expand); 55 add_field(&limit); 56 add_field(&show_border); 57 add_field(&height); 58 } 59 public: 60 virtual void render(render_action& a_action) { 61 #ifdef TOOLS_SG_TEX_RECT_DEBUG 62 a_action.out() << "tools::tex_rect::render : begin : 001 : " << std::endl; 63 #endif 64 65 //NOTE : we draw border (show_border is true) and background even if 66 // gen_texture() failed. 67 68 if(touched()) { 69 #ifdef TOOLS_SG_TEX_RECT_DEBUG 70 a_action.out() << "tools::tex_rect::render : touched." << std::endl; 71 #endif 72 update_sg(a_action.out()); 73 reset_touched(); 74 } 75 if(m_img.is_empty()) { 76 #ifdef TOOLS_SG_TEX_RECT_DEBUG 77 a_action.out() << "tools::tex_rect::render : m_img is empty." << std::endl; 78 #endif 79 return; 80 } 81 82 #ifdef TOOLS_SG_TEX_RECT_DEBUG 83 a_action.out() << "tools::tex_rect::render : have a m_img. get_tex_id ..." << std::endl; 84 #endif 85 86 unsigned int _id = get_tex_id(a_action.out(),a_action.render_manager(),m_img,nearest.value()); 87 88 #ifdef TOOLS_SG_TEX_RECT_DEBUG 89 a_action.out() << "tools::tex_rect::render : get_tex_id : " << _id << "." << std::endl; 90 #endif 91 92 const state& state = a_action.state(); 93 94 //image must be 2^n,2^m in size ! 95 // exa : 128x64 96 97 f12 xyzs; 98 99 if(show_border.value()) { 100 #ifdef TOOLS_SG_TEX_RECT_DEBUG 101 a_action.out() << "tools::tex_rect::render : show_border." << std::endl; 102 #endif 103 f12 nms; 104 _front(xyzs,nms,0.01f); 105 106 a_action.color4f(1,0,0,1); 107 a_action.line_width(4); 108 109 a_action.draw_vertex_array(gl::line_loop(),12,xyzs); 110 111 //pushes back the filled polygons to avoid z-fighting with lines 112 a_action.set_polygon_offset(true); 113 114 a_action.color4f(state.m_color); 115 a_action.line_width(state.m_line_width); 116 } 117 118 #ifdef TOOLS_SG_TEX_RECT_DEBUG 119 a_action.out() << "tools::tex_rect::render : draw back face." << std::endl; 120 #endif 121 122 //draw a back face pointing toward negative z : 123 {a_action.color4f(back_color.value()); 124 f18 tris,nms; 125 _tris(tris,nms); 126 a_action.draw_vertex_normal_array(gl::triangles(),18,tris,nms); 127 a_action.color4f(state.m_color);} 128 129 if(_id) { 130 #ifdef TOOLS_SG_TEX_RECT_DEBUG 131 a_action.out() << "tools::tex_rect::render : draw_vertex_normal_array_texture." << std::endl; 132 #endif 133 f12 nms; 134 _front(xyzs,nms); 135 float tcs[8]; 136 set_tcs(tcs); 137 a_action.draw_vertex_normal_array_texture(gl::triangle_fan(),12,xyzs,nms,_id,tcs); 138 } 139 a_action.set_polygon_offset(state.m_GL_POLYGON_OFFSET_FILL); 140 } 141 virtual void pick(pick_action& a_action) { 142 if(touched()) { 143 update_sg(a_action.out()); 144 reset_touched(); 145 } 146 if(m_img.is_empty()) return; 147 f12 xyzs,nms; 148 _front(xyzs,nms); 149 a_action.add__primitive(*this,gl::triangle_fan(),12,xyzs,true); 150 } 151 152 virtual void bbox(bbox_action& a_action) { 153 if(touched()) { 154 update_sg(a_action.out()); 155 reset_touched(); 156 } 157 if(m_img.is_empty()) return; 158 f12 xyzs,nms; 159 _front(xyzs,nms); 160 a_action.add_points(12,xyzs); 161 } 162 public: 163 virtual bool intersect_value(std::ostream&,intersect_type,const line<vec3f>& a_line,std::string& a_s) const { 164 // a_line is in local world coordinate. 165 166 const img_byte& _img = img.value(); 167 if(_img.is_empty()) {a_s.clear();return false;} 168 169 float aspect = float(_img.width())/float(_img.height()); 170 float h2 = height.value()*0.5f; 171 float w2 = aspect*h2; 172 173 plane<vec3f> plane(vec3f(w2,h2,0),vec3f(-w2,h2,0),vec3f(-w2,-h2,0)); 174 vec3f p; 175 if(!plane.intersect(a_line,p)) {a_s.clear();return false;} 176 177 float imw = (float)_img.width(); 178 float imh = (float)_img.height(); 179 180 //image coordinates : 181 int ix = int((imw*p.x()/w2+imw)*0.5f); 182 int iy = int((imh*p.y()/h2+imh)*0.5f); 183 184 //rgb of pixel : 185 std::vector<unsigned char> pixel; 186 if((ix<0)||(iy<0)||!_img.pixel(ix,iy,pixel)) {a_s.clear();return false;} 187 188 a_s.clear(); 189 for(unsigned int ipix=0;ipix<pixel.size();ipix++) { 190 if(ipix) a_s += " "; 191 if(!numas<float>(float(pixel[ipix])/255.0f,a_s)){} 192 } 193 194 return true; 195 } 196 public: 197 tex_rect() 198 :parent() 199 ,base_tex() 200 ,show_border(false) 201 ,height(1) 202 { 203 add_fields(); 204 } 205 virtual ~tex_rect(){} 206 public: 207 tex_rect(const tex_rect& a_from) 208 :parent(a_from) 209 ,gstos(a_from) 210 ,base_tex(a_from) 211 ,show_border(a_from.show_border) 212 ,height(a_from.height) 213 { 214 add_fields(); 215 } 216 tex_rect& operator=(const tex_rect& a_from){ 217 parent::operator=(a_from); 218 gstos::operator=(a_from); 219 base_tex::operator=(a_from); 220 if(&a_from==this) return *this; 221 show_border = a_from.show_border; 222 height = a_from.height; 223 return *this; 224 } 225 public: 226 227 //const img_byte& rendered_img() const {return m_img;} 228 229 void rendered_size(std::ostream& a_out,unsigned int& a_w,unsigned int& a_h) { 230 update_sg(a_out); 231 reset_touched(); 232 a_w = m_img.width(); 233 a_h = m_img.height(); 234 } 235 236 protected: 237 //virtual //NOTE : virtual for diaporama node. (but warning with clang -g4flags). 238 void update_sg(std::ostream& a_out) { 239 clean_gstos(); //must reset for all render_manager. 240 if(height.value()<=0) { 241 m_img.make_empty(); 242 return; 243 } 244 base_tex::_update_sg_(a_out); 245 } 246 protected: 247 248 typedef float f12[12]; 249 void _front(f12& front,f12& nms,float a_epsil = 0.0f) { //[12] 250 float aspect = float(img.value().width())/float(img.value().height()); 251 float h2 = height*0.5f; 252 float w2 = aspect*h2; 253 254 h2 += a_epsil; 255 w2 += a_epsil; 256 257 front[0] = -w2; 258 front[1] = -h2; 259 front[2] = 0; 260 261 front[3] = w2; 262 front[4] = -h2; 263 front[5] = 0; 264 265 front[6] = w2; 266 front[7] = h2; 267 front[8] = 0; 268 269 front[ 9] = -w2; 270 front[10] = h2; 271 front[11] = 0; 272 273 nms[0] = 0; 274 nms[1] = 0; 275 nms[2] = 1; 276 277 nms[3] = 0; 278 nms[4] = 0; 279 nms[5] = 1; 280 281 nms[6] = 0; 282 nms[7] = 0; 283 nms[8] = 1; 284 285 nms[9] = 0; 286 nms[10] = 0; 287 nms[11] = 1; 288 } 289 290 void _back(f12& back) { //[12] 291 float aspect = float(img.value().width())/float(img.value().height()); 292 float h2 = height*0.5f; 293 float w2 = aspect*h2; 294 float d2 = 0; 295 296 back[0] = w2;back[ 1] = -h2;back[ 2] = d2; 297 back[3] = -w2;back[ 4] = -h2;back[ 5] = d2; 298 back[6] = -w2;back[ 7] = h2;back[ 8] = d2; 299 back[9] = w2;back[10] = h2;back[11] = d2; 300 } 301 302 typedef float f18[18]; 303 void _tris(f18& tris,f18& nms){ 304 f12 back; 305 _back(back); 306 307 tris[0] = back[0]; 308 tris[1] = back[1]; 309 tris[2] = back[2]; 310 311 tris[3] = back[3]; 312 tris[4] = back[4]; 313 tris[5] = back[5]; 314 315 tris[6] = back[6]; 316 tris[7] = back[7]; 317 tris[8] = back[8]; 318 // 319 tris[9] = back[6]; 320 tris[10] = back[7]; 321 tris[11] = back[8]; 322 323 tris[12] = back[9]; 324 tris[13] = back[10]; 325 tris[14] = back[11]; 326 327 tris[15] = back[0]; 328 tris[16] = back[1]; 329 tris[17] = back[2]; 330 331 ///////////////////// back 332 nms[0] = 0; 333 nms[1] = 0; 334 nms[2] = -1; 335 336 nms[3] = 0; 337 nms[4] = 0; 338 nms[5] = -1; 339 340 nms[6] = 0; 341 nms[7] = 0; 342 nms[8] = -1; 343 // 344 nms[9] = 0; 345 nms[10] = 0; 346 nms[11] = -1; 347 348 nms[12] = 0; 349 nms[13] = 0; 350 nms[14] = -1; 351 352 nms[15] = 0; 353 nms[16] = 0; 354 nms[17] = -1; 355 } 356 }; 357 358 }} 359 360 #endif