Warning, /include/Geant4/tools/sg/tex_quadrilateral 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_tex_quadrilateral
0005 #define tools_sg_tex_quadrilateral
0006
0007 #include "node"
0008 #include "mf"
0009 #include "render_action"
0010 #include "pick_action"
0011 #include "bbox_action"
0012 #include "event_action"
0013 #include "render_manager"
0014 #include "gstos"
0015 #include "base_tex"
0016
0017 #include "../num2s"
0018
0019 namespace tools {
0020 namespace sg {
0021
0022 class tex_quadrilateral : public node, public gstos, public base_tex {
0023 TOOLS_NODE_NO_CAST(tex_quadrilateral,tools::sg::tex_quadrilateral,node)
0024 public:
0025 virtual void* cast(const std::string& a_class) const {
0026 {if(void* p = cmp_cast<tex_quadrilateral>(this,a_class)) return p;}
0027 {if(void* p = base_tex::cast(a_class)) return p;}
0028 return parent::cast(a_class);
0029 }
0030 public:
0031 sf<bool> show_border;
0032 mf_vec<vec3f,float> corners;
0033 public:
0034 virtual const desc_fields& node_desc_fields() const {
0035 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::tex_quadrilateral)
0036 static const desc_fields s_v(parent::node_desc_fields(),6, //WARNING : take care of count.
0037 TOOLS_ARG_FIELD_DESC(img),
0038 TOOLS_ARG_FIELD_DESC(back_color),
0039 TOOLS_ARG_FIELD_DESC(expand),
0040 TOOLS_ARG_FIELD_DESC(limit),
0041 TOOLS_ARG_FIELD_DESC(show_border),
0042 TOOLS_ARG_FIELD_DESC(corners)
0043 );
0044 return s_v;
0045 }
0046 private:
0047 void add_fields(){
0048 add_field(&img);
0049 add_field(&back_color);
0050 add_field(&expand);
0051 add_field(&limit);
0052 add_field(&show_border);
0053 add_field(&corners);
0054 }
0055 public:
0056 virtual void render(render_action& a_action) {
0057 //NOTE : we draw border (show_border is true) and background even if
0058 // gen_texture() failed.
0059
0060 if(touched()) {
0061 update_sg(a_action.out());
0062 reset_touched();
0063 }
0064 if(m_img.is_empty()) return;
0065 if(corners.size()!=4) return;
0066
0067 unsigned int _id = get_tex_id(a_action.out(),a_action.render_manager(),m_img,nearest.value());
0068
0069 const state& state = a_action.state();
0070
0071 //image must be 2^n,2^m in size !
0072 // exa : 128x64
0073
0074 f12 xyzs,nms;
0075
0076 if(show_border.value()) {
0077 _front(xyzs,nms/*,0.01f*/); //have to revisit a_epsil.
0078
0079 a_action.color4f(1,0,0,1);
0080 a_action.line_width(1);
0081
0082 a_action.draw_vertex_array(gl::line_loop(),12,xyzs);
0083
0084 //pushes back the filled polygons to avoid z-fighting with lines
0085 a_action.set_polygon_offset(true);
0086
0087 a_action.color4f(state.m_color);
0088 a_action.line_width(state.m_line_width);
0089 }
0090
0091 //draw a back face pointing toward negative z :
0092 {a_action.color4f(back_color.value());
0093 f18 tris,_nms;
0094 _tris(tris,_nms);
0095 a_action.draw_vertex_normal_array(gl::triangles(),18,tris,_nms);
0096 a_action.color4f(state.m_color);}
0097
0098 if(_id) {
0099 _front(xyzs,nms);
0100 float tcs[8];
0101 set_tcs(tcs);
0102 a_action.draw_vertex_normal_array_texture(gl::triangle_fan(),12,xyzs,nms,_id,tcs);
0103 }
0104 a_action.set_polygon_offset(state.m_GL_POLYGON_OFFSET_FILL);
0105 }
0106 virtual void pick(pick_action& a_action) {
0107 if(touched()) {
0108 update_sg(a_action.out());
0109 reset_touched();
0110 }
0111 if(m_pick_bbox_check_image) {if(m_img.is_empty()) return;}
0112 if(corners.size()!=4) return;
0113 f12 xyzs,nms;
0114 _front(xyzs,nms);
0115 a_action.add__primitive(*this,gl::triangle_fan(),12,xyzs,true);
0116 }
0117
0118 virtual void bbox(bbox_action& a_action) {
0119 if(touched()) {
0120 update_sg(a_action.out());
0121 reset_touched();
0122 }
0123 if(m_pick_bbox_check_image) if(m_img.is_empty()) return;
0124 if(corners.size()!=4) return;
0125 f12 xyzs,nms;
0126 _front(xyzs,nms);
0127 a_action.add_points(12,xyzs);
0128 }
0129 public:
0130 virtual bool intersect_value(std::ostream&,intersect_type,const line<vec3f>& a_line,std::string& a_s) const {
0131 // a_line is in local world coordinate.
0132 float x,y;
0133 if(!line_2_img_ndc(a_line,x,y)) {a_s.clear();return false;}
0134 return img_ndc_value(x,y,a_s);
0135 }
0136 public:
0137 tex_quadrilateral()
0138 :parent()
0139 ,base_tex()
0140 ,show_border(false)
0141 ,corners()
0142 ,m_pick_bbox_check_image(true)
0143 {
0144 add_fields();
0145 corners.add(vec3f(-1,-1,0));
0146 corners.add(vec3f( 1,-1,0));
0147 corners.add(vec3f( 1, 1,0));
0148 corners.add(vec3f(-1, 1,0));
0149 }
0150 virtual ~tex_quadrilateral(){}
0151 public:
0152 tex_quadrilateral(const tex_quadrilateral& a_from)
0153 :parent(a_from)
0154 ,gstos(a_from)
0155 ,base_tex(a_from)
0156 ,show_border(a_from.show_border)
0157 ,corners(a_from.corners)
0158 ,m_pick_bbox_check_image(a_from.m_pick_bbox_check_image)
0159 {
0160 add_fields();
0161 }
0162 tex_quadrilateral& operator=(const tex_quadrilateral& a_from){
0163 parent::operator=(a_from);
0164 gstos::operator=(a_from);
0165 base_tex::operator=(a_from);
0166 if(&a_from==this) return *this;
0167 show_border = a_from.show_border;
0168 corners = a_from.corners;
0169 m_pick_bbox_check_image = a_from.m_pick_bbox_check_image;
0170 return *this;
0171 }
0172 protected:
0173 void update_sg(std::ostream& a_out) {
0174 plane<vec3f> plane(corners[0],corners[1],corners[3]);
0175 m_normal = plane.normal();
0176 clean_gstos(); //must reset for all render_manager.
0177 base_tex::_update_sg_(a_out);
0178 }
0179 protected:
0180 bool img_ndc_value(float a_x,float a_y,std::string& a_s) const {
0181 const img_byte& _img = img.value();
0182 if(_img.is_empty()) {a_s.clear();return false;}
0183
0184 int ix = int(float(_img.width())*a_x);
0185 int iy = int(float(_img.height())*a_y);
0186
0187 //rgb of pixel :
0188 std::vector<unsigned char> pixel;
0189 if((ix<0)||(iy<0)||!_img.pixel(ix,iy,pixel)) {a_s.clear();return false;}
0190
0191 a_s.clear();
0192 for(unsigned int ipix=0;ipix<pixel.size();ipix++) {
0193 if(ipix) a_s += " ";
0194 if(!numas<float>(float(pixel[ipix])/255.0f,a_s)){}
0195 }
0196
0197 return true;
0198 }
0199
0200 bool point_2_img_ndc(const vec3f& a_point,float& a_x,float& a_y) const {
0201 // a_point is assumed to be in the corners[0,1,3] plane.
0202
0203 if(corners.size()!=4) {a_x = 0;a_y = 0;return false;}
0204 // In fact, in the below corners[2] is not used.
0205
0206 // we assume that :
0207 // corners[0] is the bottom-left of image
0208 // corners[1] is the bottom-right of image
0209 // corners[2] is the top-right of image
0210 // corners[3] is the top-left of image
0211 vec3f x_axis = corners[1]-corners[0];
0212 float l_01 = x_axis.normalize();
0213 if(l_01==0.0f) {a_x = 0;a_y = 0;return false;}
0214 vec3f y_axis = corners[3]-corners[0];
0215 float l_03 = y_axis.normalize();
0216 if(l_03==0.0f) {a_x = 0;a_y = 0;return false;}
0217
0218 float alpha = x_axis.dot(y_axis);
0219 float alpha_sq = alpha*alpha;
0220 if(alpha_sq==1.0f) {a_x = 0;a_y = 0;return false;}
0221
0222 vec3f Op = a_point-corners[0];
0223
0224 float px = Op.dot(x_axis);
0225 float py = Op.dot(y_axis);
0226
0227 float lambda = (px-alpha*py)/(1.0f-alpha_sq);
0228 float mu = (py-alpha*px)/(1-alpha_sq);
0229
0230 // We must have : Op = lambda*x_axis+mu*y_axis;
0231
0232 a_x = lambda/l_01;
0233 a_y = mu/l_03;
0234
0235 return true;
0236 }
0237
0238 bool line_2_img_ndc(const line<vec3f>& a_line,float& a_x,float& a_y) const {
0239 // a_line is in local world coordinate.
0240 if(corners.size()!=4) {a_x = 0;a_y = 0;return false;}
0241 // In fact corners[2] is not used, only [0,1,3].
0242 plane<vec3f> plane(corners[0],corners[1],corners[3]);
0243 vec3f p;
0244 if(!plane.intersect(a_line,p)) {a_x = 0;a_y = 0;return false;}
0245 return point_2_img_ndc(p,a_x,a_y);
0246 }
0247
0248 bool img_ndc_2_point(float a_x,float a_y,vec3f& a_point) const {
0249 if(corners.size()!=4) {a_point.set_value(0,0,0);return false;}
0250 // In fact, in the below corners[2] is not used.
0251
0252 // we assume that :
0253 // corners[0] is the bottom-left of image
0254 // corners[1] is the bottom-right of image
0255 // corners[2] is the top-right of image
0256 // corners[3] is the top-left of image
0257 vec3f x_axis = corners[1]-corners[0];
0258 float l_01 = x_axis.normalize();
0259 if(l_01==0.0f) {a_point.set_value(0,0,0);return false;}
0260 vec3f y_axis = corners[3]-corners[0];
0261 float l_03 = y_axis.normalize();
0262 if(l_03==0.0f) {a_point.set_value(0,0,0);return false;}
0263
0264 float alpha = x_axis.dot(y_axis);
0265
0266 float lambda = a_x*l_01;
0267 float mu = a_y*l_03;
0268
0269 float px = lambda+mu*alpha;
0270 float py = lambda*alpha+mu;
0271
0272 vec3f Op = px*x_axis+py*y_axis;
0273
0274 a_point = Op+corners[0];
0275
0276 return true;
0277 }
0278
0279 typedef float f12[12];
0280 void _front(f12& a_front,f12& a_nms,float a_epsil = 0.0f) {
0281 const std::vector<vec3f>& cs = corners.values();
0282
0283 a_front[0] = cs[0].x()-a_epsil;
0284 a_front[1] = cs[0].y()-a_epsil;
0285 a_front[2] = cs[0].z();
0286
0287 a_front[3] = cs[1].x()+a_epsil;
0288 a_front[4] = cs[1].y()-a_epsil;
0289 a_front[5] = cs[1].z();
0290
0291 a_front[6] = cs[2].x()+a_epsil;
0292 a_front[7] = cs[2].y()+a_epsil;
0293 a_front[8] = cs[2].z();
0294
0295 a_front[ 9] = cs[3].x()-a_epsil;
0296 a_front[10] = cs[3].y()+a_epsil;
0297 a_front[11] = cs[3].z();
0298
0299 a_nms[0] = m_normal.x();
0300 a_nms[1] = m_normal.y();
0301 a_nms[2] = m_normal.z();
0302
0303 a_nms[3] = m_normal.x();
0304 a_nms[4] = m_normal.y();
0305 a_nms[5] = m_normal.z();
0306
0307 a_nms[6] = m_normal.x();
0308 a_nms[7] = m_normal.y();
0309 a_nms[8] = m_normal.z();
0310
0311 a_nms[9] = m_normal.x();
0312 a_nms[10] = m_normal.y();
0313 a_nms[11] = m_normal.z();
0314 }
0315
0316 void _back(f12& a_back) {
0317 const std::vector<vec3f>& cs = corners.values();
0318
0319 a_back[0] = cs[1].x();
0320 a_back[1] = cs[1].y();
0321 a_back[2] = cs[1].z();
0322
0323 a_back[3] = cs[0].x();
0324 a_back[4] = cs[0].y();
0325 a_back[5] = cs[0].z();
0326
0327 a_back[6] = cs[3].x();
0328 a_back[7] = cs[3].y();
0329 a_back[8] = cs[3].z();
0330
0331 a_back[ 9] = cs[2].x();
0332 a_back[10] = cs[2].y();
0333 a_back[11] = cs[2].z();
0334 }
0335
0336 typedef float f18[18];
0337 void _tris(f18& a_tris,f18& a_nms){
0338 f12 back;
0339 _back(back);
0340
0341 a_tris[0] = back[0];
0342 a_tris[1] = back[1];
0343 a_tris[2] = back[2];
0344
0345 a_tris[3] = back[3];
0346 a_tris[4] = back[4];
0347 a_tris[5] = back[5];
0348
0349 a_tris[6] = back[6];
0350 a_tris[7] = back[7];
0351 a_tris[8] = back[8];
0352 //
0353 a_tris[9] = back[6];
0354 a_tris[10] = back[7];
0355 a_tris[11] = back[8];
0356
0357 a_tris[12] = back[9];
0358 a_tris[13] = back[10];
0359 a_tris[14] = back[11];
0360
0361 a_tris[15] = back[0];
0362 a_tris[16] = back[1];
0363 a_tris[17] = back[2];
0364
0365 ///////////////////// back
0366 a_nms[0] = -m_normal.x();
0367 a_nms[1] = -m_normal.y();
0368 a_nms[2] = -m_normal.z();
0369
0370 a_nms[3] = -m_normal.x();
0371 a_nms[4] = -m_normal.y();
0372 a_nms[5] = -m_normal.z();
0373
0374 a_nms[6] = -m_normal.x();
0375 a_nms[7] = -m_normal.y();
0376 a_nms[8] = -m_normal.z();
0377 //
0378 a_nms[9] = -m_normal.x();
0379 a_nms[10] = -m_normal.y();
0380 a_nms[11] = -m_normal.z();
0381
0382 a_nms[12] = -m_normal.x();
0383 a_nms[13] = -m_normal.y();
0384 a_nms[14] = -m_normal.z();
0385
0386 a_nms[15] = -m_normal.x();
0387 a_nms[16] = -m_normal.y();
0388 a_nms[17] = -m_normal.z();
0389 }
0390 protected:
0391 vec3f m_normal;
0392 bool m_pick_bbox_check_image; //for SDSS_image.
0393 };
0394
0395 }}
0396
0397 #endif