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_quadrilateral 5 #define tools_sg_tex_quadrilateral 6 7 #include "node" 8 #include "mf" 9 #include "render_action" 10 #include "pick_action" 11 #include "bbox_action" 12 #include "event_action" 13 #include "render_manager" 14 #include "gstos" 15 #include "base_tex" 16 17 #include "../pointer" 18 #include "../num2s" 19 20 namespace tools { 21 namespace sg { 22 23 class tex_quadrilateral : public node, public gstos, public base_tex { 24 TOOLS_NODE_NO_CAST(tex_quadrilateral,tools::sg::tex_quadrilateral,node) 25 public: 26 virtual void* cast(const std::string& a_class) const { 27 {if(void* p = cmp_cast<tex_quadrilateral>(this,a_class)) return p;} 28 {if(void* p = base_tex::cast(a_class)) return p;} 29 return parent::cast(a_class); 30 } 31 public: 32 sf<bool> show_border; 33 mf_vec<vec3f,float> corners; 34 public: 35 virtual const desc_fields& node_desc_fields() const { 36 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::tex_quadrilateral) 37 static const desc_fields s_v(parent::node_desc_fields(),6, //WARNING : take care of count. 38 TOOLS_ARG_FIELD_DESC(img), 39 TOOLS_ARG_FIELD_DESC(back_color), 40 TOOLS_ARG_FIELD_DESC(expand), 41 TOOLS_ARG_FIELD_DESC(limit), 42 TOOLS_ARG_FIELD_DESC(show_border), 43 TOOLS_ARG_FIELD_DESC(corners) 44 ); 45 return s_v; 46 } 47 private: 48 void add_fields(){ 49 add_field(&img); 50 add_field(&back_color); 51 add_field(&expand); 52 add_field(&limit); 53 add_field(&show_border); 54 add_field(&corners); 55 } 56 public: 57 virtual void render(render_action& a_action) { 58 //a_action.out() << "tools::tex_quadrilateral::render : " << std::endl; 59 60 //NOTE : we draw border (show_border is true) and background even if 61 // gen_texture() failed. 62 63 if(touched()) { 64 update_sg(a_action.out()); 65 reset_touched(); 66 } 67 if(m_img.is_empty()) return; 68 if(corners.size()!=4) return; 69 70 unsigned int _id = get_tex_id(a_action.out(),a_action.render_manager(),m_img,nearest.value()); 71 72 const state& state = a_action.state(); 73 74 //image must be 2^n,2^m in size ! 75 // exa : 128x64 76 77 f12 xyzs,nms; 78 79 if(show_border.value()) { 80 _front(xyzs,nms/*,0.01f*/); //have to revisit a_epsil. 81 82 a_action.color4f(1,0,0,1); 83 //a_action.line_width(4); 84 a_action.line_width(1); 85 86 a_action.draw_vertex_array(gl::line_loop(),12,xyzs); 87 88 //pushes back the filled polygons to avoid z-fighting with lines 89 a_action.set_polygon_offset(true); 90 91 a_action.color4f(state.m_color); 92 a_action.line_width(state.m_line_width); 93 } 94 95 //draw a back face pointing toward negative z : 96 {a_action.color4f(back_color.value()); 97 f18 tris,_nms; 98 _tris(tris,_nms); 99 a_action.draw_vertex_normal_array(gl::triangles(),18,tris,_nms); 100 a_action.color4f(state.m_color);} 101 102 if(_id) { 103 //a_action.color4f(back_color.value()); //do we want that ? 104 _front(xyzs,nms); 105 float tcs[8]; 106 set_tcs(tcs); 107 a_action.draw_vertex_normal_array_texture(gl::triangle_fan(),12,xyzs,nms,_id,tcs); 108 //a_action.color4f(state.m_color); 109 } 110 a_action.set_polygon_offset(state.m_GL_POLYGON_OFFSET_FILL); 111 } 112 virtual void pick(pick_action& a_action) { 113 if(touched()) { 114 update_sg(a_action.out()); 115 reset_touched(); 116 } 117 if(m_pick_bbox_check_image) {if(m_img.is_empty()) return;} 118 if(corners.size()!=4) return; 119 f12 xyzs,nms; 120 _front(xyzs,nms); 121 a_action.add__primitive(*this,gl::triangle_fan(),12,xyzs,true); 122 } 123 124 virtual void bbox(bbox_action& a_action) { 125 if(touched()) { 126 update_sg(a_action.out()); 127 reset_touched(); 128 } 129 if(m_pick_bbox_check_image) if(m_img.is_empty()) return; 130 if(corners.size()!=4) return; 131 f12 xyzs,nms; 132 _front(xyzs,nms); 133 a_action.add_points(12,xyzs); 134 } 135 public: 136 virtual bool intersect_value(std::ostream&,intersect_type,const line<vec3f>& a_line,std::string& a_s) const { 137 // a_line is in local world coordinate. 138 float x,y; 139 if(!line_2_img_ndc(a_line,x,y)) {a_s.clear();return false;} 140 return img_ndc_value(x,y,a_s); 141 } 142 public: 143 tex_quadrilateral() 144 :parent() 145 ,base_tex() 146 ,show_border(false) 147 ,corners() 148 ,m_pick_bbox_check_image(true) 149 { 150 add_fields(); 151 corners.add(vec3f(-1,-1,0)); 152 corners.add(vec3f( 1,-1,0)); 153 corners.add(vec3f( 1, 1,0)); 154 corners.add(vec3f(-1, 1,0)); 155 } 156 virtual ~tex_quadrilateral(){} 157 public: 158 tex_quadrilateral(const tex_quadrilateral& a_from) 159 :parent(a_from) 160 ,gstos(a_from) 161 ,base_tex(a_from) 162 ,show_border(a_from.show_border) 163 ,corners(a_from.corners) 164 ,m_pick_bbox_check_image(a_from.m_pick_bbox_check_image) 165 { 166 add_fields(); 167 } 168 tex_quadrilateral& operator=(const tex_quadrilateral& a_from){ 169 parent::operator=(a_from); 170 gstos::operator=(a_from); 171 base_tex::operator=(a_from); 172 if(&a_from==this) return *this; 173 show_border = a_from.show_border; 174 corners = a_from.corners; 175 m_pick_bbox_check_image = a_from.m_pick_bbox_check_image; 176 return *this; 177 } 178 public: 179 180 //const img_byte& rendered_img() const {return m_img;} 181 182 protected: 183 void update_sg(std::ostream& a_out) { 184 plane<vec3f> plane(corners[0],corners[1],corners[3]); 185 m_normal = plane.normal(); 186 clean_gstos(); //must reset for all render_manager. 187 base_tex::_update_sg_(a_out); 188 } 189 protected: 190 bool img_ndc_value(float a_x,float a_y,std::string& a_s) const { 191 const img_byte& _img = img.value(); 192 if(_img.is_empty()) {a_s.clear();return false;} 193 194 int ix = int(float(_img.width())*a_x); 195 int iy = int(float(_img.height())*a_y); 196 197 //rgb of pixel : 198 std::vector<unsigned char> pixel; 199 if((ix<0)||(iy<0)||!_img.pixel(ix,iy,pixel)) {a_s.clear();return false;} 200 201 a_s.clear(); 202 for(unsigned int ipix=0;ipix<pixel.size();ipix++) { 203 if(ipix) a_s += " "; 204 if(!numas<float>(float(pixel[ipix])/255.0f,a_s)){} 205 } 206 207 return true; 208 } 209 210 bool point_2_img_ndc(const vec3f& a_point,float& a_x,float& a_y) const { 211 // a_point is assumed to be in the corners[0,1,3] plane. 212 213 if(corners.size()!=4) {a_x = 0;a_y = 0;return false;} 214 // In fact, in the below corners[2] is not used. 215 216 // we assume that : 217 // corners[0] is the bottom-left of image 218 // corners[1] is the bottom-right of image 219 // corners[2] is the top-right of image 220 // corners[3] is the top-left of image 221 vec3f x_axis = corners[1]-corners[0]; 222 float l_01 = x_axis.normalize(); 223 if(l_01==0.0f) {a_x = 0;a_y = 0;return false;} 224 vec3f y_axis = corners[3]-corners[0]; 225 float l_03 = y_axis.normalize(); 226 if(l_03==0.0f) {a_x = 0;a_y = 0;return false;} 227 228 float alpha = x_axis.dot(y_axis); 229 float alpha_sq = alpha*alpha; 230 if(alpha_sq==1.0f) {a_x = 0;a_y = 0;return false;} 231 232 vec3f Op = a_point-corners[0]; 233 234 float px = Op.dot(x_axis); 235 float py = Op.dot(y_axis); 236 237 float lambda = (px-alpha*py)/(1.0f-alpha_sq); 238 float mu = (py-alpha*px)/(1-alpha_sq); 239 240 // We must have : Op = lambda*x_axis+mu*y_axis; 241 242 a_x = lambda/l_01; 243 a_y = mu/l_03; 244 245 return true; 246 } 247 248 bool line_2_img_ndc(const line<vec3f>& a_line,float& a_x,float& a_y) const { 249 // a_line is in local world coordinate. 250 if(corners.size()!=4) {a_x = 0;a_y = 0;return false;} 251 // In fact corners[2] is not used, only [0,1,3]. 252 plane<vec3f> plane(corners[0],corners[1],corners[3]); 253 vec3f p; 254 if(!plane.intersect(a_line,p)) {a_x = 0;a_y = 0;return false;} 255 return point_2_img_ndc(p,a_x,a_y); 256 } 257 258 bool img_ndc_2_point(float a_x,float a_y,vec3f& a_point) const { 259 if(corners.size()!=4) {a_point.set_value(0,0,0);return false;} 260 // In fact, in the below corners[2] is not used. 261 262 // we assume that : 263 // corners[0] is the bottom-left of image 264 // corners[1] is the bottom-right of image 265 // corners[2] is the top-right of image 266 // corners[3] is the top-left of image 267 vec3f x_axis = corners[1]-corners[0]; 268 float l_01 = x_axis.normalize(); 269 if(l_01==0.0f) {a_point.set_value(0,0,0);return false;} 270 vec3f y_axis = corners[3]-corners[0]; 271 float l_03 = y_axis.normalize(); 272 if(l_03==0.0f) {a_point.set_value(0,0,0);return false;} 273 274 float alpha = x_axis.dot(y_axis); 275 //float alpha_sq = alpha*alpha; 276 //if(alpha_sq==1.0f) {a_point.set_value(0,0,0);return false;} 277 278 float lambda = a_x*l_01; 279 float mu = a_y*l_03; 280 281 // px-alpha*py = lambda*(1.0f-alpha_sq); 282 // py-alpha*px = mu*(1-alpha_sq); 283 284 // px-alpha*(alpha*px+mu*(1-alpha_sq)) = lambda*(1-alpha_sq) 285 // px*(1-alpha_sq)-mu*alpha*(1-alpha_sq)) = lambda*(1-alpha_sq) 286 // px*(1-alpha_sq) = lambda*(1-alpha_sq)+mu*alpha*(1-alpha_sq)); 287 // px = lambda+mu*alpha; 288 289 // py = lambda*alpha+mu; 290 291 float px = lambda+mu*alpha; 292 float py = lambda*alpha+mu; 293 294 vec3f Op = px*x_axis+py*y_axis; 295 296 a_point = Op+corners[0]; 297 298 return true; 299 } 300 301 /* 302 float max_height() const { 303 const std::vector<vec3f>& cs = corners.values(); 304 float _mn = cs[0].y(); 305 _mn = mn<float>(_mn,cs[1].y()); 306 _mn = mn<float>(_mn,cs[2].y()); 307 _mn = mn<float>(_mn,cs[3].y()); 308 float _mx = cs[0].y(); 309 _mx = mx<float>(_mx,cs[1].y()); 310 _mx = mx<float>(_mx,cs[2].y()); 311 _mx = mx<float>(_mx,cs[3].y()); 312 return (_mx-_mn); 313 } 314 315 float max_width() const { 316 const std::vector<vec3f>& cs = corners.values(); 317 float _mn = cs[0].x(); 318 _mn = mn<float>(_mn,cs[1].x()); 319 _mn = mn<float>(_mn,cs[2].x()); 320 _mn = mn<float>(_mn,cs[3].x()); 321 float _mx = cs[0].x(); 322 _mx = mx<float>(_mx,cs[1].x()); 323 _mx = mx<float>(_mx,cs[2].x()); 324 _mx = mx<float>(_mx,cs[3].x()); 325 return (_mx-_mn); 326 } 327 */ 328 329 typedef float f12[12]; 330 void _front(f12& a_front,f12& a_nms,float a_epsil = 0.0f) { 331 const std::vector<vec3f>& cs = corners.values(); 332 333 a_front[0] = cs[0].x()-a_epsil; 334 a_front[1] = cs[0].y()-a_epsil; 335 a_front[2] = cs[0].z(); 336 337 a_front[3] = cs[1].x()+a_epsil; 338 a_front[4] = cs[1].y()-a_epsil; 339 a_front[5] = cs[1].z(); 340 341 a_front[6] = cs[2].x()+a_epsil; 342 a_front[7] = cs[2].y()+a_epsil; 343 a_front[8] = cs[2].z(); 344 345 a_front[ 9] = cs[3].x()-a_epsil; 346 a_front[10] = cs[3].y()+a_epsil; 347 a_front[11] = cs[3].z(); 348 349 a_nms[0] = m_normal.x(); 350 a_nms[1] = m_normal.y(); 351 a_nms[2] = m_normal.z(); 352 353 a_nms[3] = m_normal.x(); 354 a_nms[4] = m_normal.y(); 355 a_nms[5] = m_normal.z(); 356 357 a_nms[6] = m_normal.x(); 358 a_nms[7] = m_normal.y(); 359 a_nms[8] = m_normal.z(); 360 361 a_nms[9] = m_normal.x(); 362 a_nms[10] = m_normal.y(); 363 a_nms[11] = m_normal.z(); 364 } 365 366 void _back(f12& a_back) { 367 const std::vector<vec3f>& cs = corners.values(); 368 369 a_back[0] = cs[1].x(); 370 a_back[1] = cs[1].y(); 371 a_back[2] = cs[1].z(); 372 373 a_back[3] = cs[0].x(); 374 a_back[4] = cs[0].y(); 375 a_back[5] = cs[0].z(); 376 377 a_back[6] = cs[3].x(); 378 a_back[7] = cs[3].y(); 379 a_back[8] = cs[3].z(); 380 381 a_back[ 9] = cs[2].x(); 382 a_back[10] = cs[2].y(); 383 a_back[11] = cs[2].z(); 384 } 385 386 typedef float f18[18]; 387 void _tris(f18& a_tris,f18& a_nms){ 388 f12 back; 389 _back(back); 390 391 a_tris[0] = back[0]; 392 a_tris[1] = back[1]; 393 a_tris[2] = back[2]; 394 395 a_tris[3] = back[3]; 396 a_tris[4] = back[4]; 397 a_tris[5] = back[5]; 398 399 a_tris[6] = back[6]; 400 a_tris[7] = back[7]; 401 a_tris[8] = back[8]; 402 // 403 a_tris[9] = back[6]; 404 a_tris[10] = back[7]; 405 a_tris[11] = back[8]; 406 407 a_tris[12] = back[9]; 408 a_tris[13] = back[10]; 409 a_tris[14] = back[11]; 410 411 a_tris[15] = back[0]; 412 a_tris[16] = back[1]; 413 a_tris[17] = back[2]; 414 415 ///////////////////// back 416 a_nms[0] = -m_normal.x(); 417 a_nms[1] = -m_normal.y(); 418 a_nms[2] = -m_normal.z(); 419 420 a_nms[3] = -m_normal.x(); 421 a_nms[4] = -m_normal.y(); 422 a_nms[5] = -m_normal.z(); 423 424 a_nms[6] = -m_normal.x(); 425 a_nms[7] = -m_normal.y(); 426 a_nms[8] = -m_normal.z(); 427 // 428 a_nms[9] = -m_normal.x(); 429 a_nms[10] = -m_normal.y(); 430 a_nms[11] = -m_normal.z(); 431 432 a_nms[12] = -m_normal.x(); 433 a_nms[13] = -m_normal.y(); 434 a_nms[14] = -m_normal.z(); 435 436 a_nms[15] = -m_normal.x(); 437 a_nms[16] = -m_normal.y(); 438 a_nms[17] = -m_normal.z(); 439 } 440 protected: 441 vec3f m_normal; 442 bool m_pick_bbox_check_image; //for SDSS_image. 443 }; 444 445 }} 446 447 #endif