// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_sg_primitive_visitor #define tools_sg_primitive_visitor #include "../glprims" // for texture : #include "../lina/vec2f" #include "../lina/vec3f" #include "../img" #include "../lina/geom2" namespace tools { namespace sg { class primitive_visitor { protected: virtual bool project(float& a_x,float& a_y,float& a_z,float& a_w) = 0; virtual bool add_point(float,float,float,float) = 0; //xyzw virtual bool add_point(float,float,float,float, float,float,float,float) = 0; //xyzw & rgbas virtual bool add_line(float,float,float,float, float,float,float,float) = 0; // 2 xyzw virtual bool add_line(float,float,float,float, float,float,float,float, float,float,float,float, float,float,float,float) = 0; // 2 (xyzw & rgba) virtual bool add_triangle(float,float,float,float, float,float,float,float, float,float,float,float) = 0; // 3 xyzw virtual bool add_triangle(float,float,float,float, float,float,float,float, float,float,float,float, float,float,float,float, float,float,float,float, float,float,float,float) = 0; // 3 (xywz & rgba) virtual bool project_normal(float& a_x,float& a_y,float& a_z) = 0; virtual bool add_point_normal(float,float,float,float, float,float,float) = 0; virtual bool add_point_normal(float,float,float,float, float,float,float, float,float,float,float) = 0; virtual bool add_line_normal(float,float,float,float, float,float,float, float,float,float,float, float,float,float) = 0; virtual bool add_line_normal(float,float,float,float, float,float,float, float,float,float,float, float,float,float,float, float,float,float, float,float,float,float) = 0; virtual bool add_triangle_normal(float,float,float,float, float,float,float, float,float,float,float, float,float,float, float,float,float,float, float,float,float) = 0; virtual bool add_triangle_normal(float,float,float,float, float,float,float, float,float,float,float, float,float,float,float, float,float,float, float,float,float,float, float,float,float,float, float,float,float, float,float,float,float) = 0; public: primitive_visitor():m_mode(gl::points()){} virtual ~primitive_visitor(){} public: primitive_visitor(const primitive_visitor&):m_mode(gl::points()){} primitive_visitor& operator=(const primitive_visitor&){return *this;} public: void add_one_point(float a_x,float a_y,float a_z) { float w; project(a_x,a_y,a_z,w); add_point(a_x,a_y,a_z,w); } void add_one_point(float a_x,float a_y,float a_z,float a_r,float a_g,float a_b,float a_a) { float w; project(a_x,a_y,a_z,w); add_point(a_x,a_y,a_z,w,a_r,a_g,a_b,a_a); } bool add_triangle_fan(size_t a_floatn,const float* a_xyzs,bool a_stop = false){ size_t num = a_floatn/3; if(num<3) return false; m_mode = gl::triangle_fan(); float p1x,p1y,p1z,w1=1; float p2x,p2y,p2z,w2=1; float p3x,p3y,p3z,w3=1; const float* pos1 = a_xyzs+3*0; p1x = *(pos1+0); p1y = *(pos1+1); p1z = *(pos1+2); project(p1x,p1y,p1z,w1); const float* pos2 = a_xyzs+3*1; p2x = *(pos2+0); p2y = *(pos2+1); p2z = *(pos2+2); project(p2x,p2y,p2z,w2); for(size_t index=2;index& a_xyzs,bool a_stop = false){ const float* _xyzs = a_xyzs.data(); return add_primitive(a_mode,a_xyzs.size(),_xyzs,a_stop); } bool add_primitive_xy(gl::mode_t a_mode,const std::vector& a_xys,bool a_stop = false,bool a_triangle_revert = false){ const float* _xys = a_xys.data(); return add_primitive_xy(a_mode,a_xys.size(),_xys,a_stop,a_triangle_revert); } bool add_line_strip(const std::vector& a_xyzs,bool a_stop = false){ const float* _xyzs = a_xyzs.data(); return add_line_strip(a_xyzs.size(),_xyzs,a_stop); } bool add_line_loop(const std::vector& a_xyzs,bool a_stop = false){ const float* _xyzs = a_xyzs.data(); return add_line_loop(a_xyzs.size(),_xyzs,a_stop); } bool add_lines(const std::vector& a_xyzs,bool a_stop = false){ const float* _xyzs = a_xyzs.data(); return add_lines(a_xyzs.size(),_xyzs,a_stop); } bool add_points(const std::vector& a_xyzs,bool a_stop = false){ const float* _xyzs = a_xyzs.data(); return add_points(a_xyzs.size(),_xyzs,a_stop); } bool add_triangle_strip(const std::vector& a_xyzs,bool a_stop = false){ const float* _xyzs = a_xyzs.data(); return add_triangle_strip(a_xyzs.size(),_xyzs,a_stop); } bool add_points_xy(const std::vector& a_xys,bool a_stop = false){ const float* _xys = a_xys.data(); return add_points_xy(a_xys.size(),_xys,a_stop); } bool add_lines_xy(const std::vector& a_xys,bool a_stop = false){ const float* _xys = a_xys.data(); return add_lines_xy(a_xys.size(),_xys,a_stop); } bool add_triangle_strip_xy(const std::vector& a_xys,bool a_stop = false){ const float* _xys = a_xys.data(); return add_triangle_strip_xy(a_xys.size(),_xys,a_stop); } public: bool add_triangle_fan_texture_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms,unsigned int,const float*){ return add_triangle_fan_normal(a_floatn,a_xyzs,a_nms,false); } bool add_triangle_strip_texture_normal(size_t a_floatn,const float* a_xyzs,const float* a_nms,unsigned int,const float*){ return add_triangle_strip_normal(a_floatn,a_xyzs,a_nms,false); } bool add_triangle_strip_as_triangles(size_t a_floatn,const float* a_xyzs,const float* a_nms) { //used in sg::sphere, icosahedron_sphere. return add_triangle_strip_normal(a_floatn,a_xyzs,a_nms,false); //already do a per triangle treatement. } public: void add_texture(std::ostream& a_out,size_t a_xyzn,const float* a_xyzs,const img_byte& a_img,const float* a_tcs) { if(a_img.is_empty()) return; unsigned int imw = a_img.width(); unsigned int imh = a_img.height(); unsigned int imn = a_img.bytes_per_pixel(); if((imn!=3)&&(imn!=4)) { a_out << "tools::sg::primitive_visitor::add_texture :" << " not a 3 or 4 bytes per pixel image." << std::endl; return; } if(a_xyzn!=12) { a_out << "tools::sg::primitive_visitor::add_texture :" << " primitive has not four points." << std::endl; return; } vec3f p1(a_xyzs[0],a_xyzs[ 1],a_xyzs[ 2]); vec3f p2(a_xyzs[3],a_xyzs[ 4],a_xyzs[ 5]); vec3f p4(a_xyzs[9],a_xyzs[10],a_xyzs[11]); vec3f dx = p2-p1; vec3f dy = p4-p1; vec2f t1(a_tcs[0],a_tcs[1]); vec2f t2(a_tcs[2],a_tcs[3]); vec2f t3(a_tcs[4],a_tcs[5]); vec2f t4(a_tcs[6],a_tcs[7]); vec2f tdx = t2-t1; vec2f tdy = t4-t1; if(!tdx.length()) { a_out << "tools::sg::primitive_visitor::add_texture :" << " tdx is null." << std::endl; return; } if(!tdy.length()) { a_out << "tools::sg::primitive_visitor::add_texture :" << " tdy is null." << std::endl; return; } std::vector poly; poly.push_back(t1); poly.push_back(t2); poly.push_back(t3); poly.push_back(t4); poly.push_back(t1); {float r,g,b,a,tx,ty; vec3f p; vec2f t; unsigned char* pos = (unsigned char*)a_img.buffer(); for(unsigned int row=0;row