// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_sg_base_tex #define tools_sg_base_tex #include "../platform" #include "../img" #include "../lina/line" #include "../lina/vec3f" #include "sf_vec" #include "sf_img" #include "../colorfs" namespace tools { namespace sg { class base_tex { public: TOOLS_SCLASS(tools::sg::base_tex) public: virtual void* cast(const std::string& a_class) const { if(void* p = cmp_cast(this,a_class)) return p; return 0; } public: sf_img img; sf_vec back_color; sf expand; sf limit; sf nearest; //for glTexParameteri. See exlib/sg/GL_manager. default=true for astro images. public: enum intersect_type { intersect_down, intersect_move, intersect_up }; virtual bool intersect_value(std::ostream&,intersect_type a_type,const line& a_line,std::string& a_s) const = 0; public: base_tex() :img(img_byte()) ,back_color(colorf_white()) ,expand(false) ,limit(device::tex_mem_limit()) //OpenGL-ES glTex limitation. ,nearest(true) ,m_img() {} virtual ~base_tex(){} public: base_tex(const base_tex& a_from) :img(a_from.img) ,back_color(a_from.back_color) ,expand(a_from.expand) ,limit(a_from.limit) ,nearest(a_from.nearest) ,m_img() {} base_tex& operator=(const base_tex& a_from){ img = a_from.img; back_color = a_from.back_color; expand = a_from.expand; limit = a_from.limit; nearest = a_from.nearest; m_img.make_empty(); return *this; } protected: void _update_sg_(std::ostream& a_out) { //clean_texs(); //must reset for all render_manager. const img_byte& _img = img.value(); //::printf("debug : base_tex::_update_sg : size = %d, w = %d, h = %d, bpp %d\n", // _img.size(),_img.width(),_img.height(),_img.bpp()); if(_img.is_empty()) { m_img.make_empty(); return; } unsigned int bpp = _img.bpp(); if((bpp!=1)&&(bpp!=3)&&(bpp!=4)) { a_out << "tools::sg::tex_rect::update_sg :" << " bpp " << bpp << " not handled." << std::endl; m_img.make_empty(); return; } //a_out << "debug : tools::sg::tex_rect::update_sg :" // << " this " << inlib::p2s(this) // << std::endl; // image must be power of two in width and height. const colorf& bc = back_color.value(); //::printf("debug : back_color %g %g %g %g\n",bc.r(),bc.g(),bc.b(),bc.a()); byte pixel[4]; pixel[0] = bc.ruchar(); pixel[1] = bc.guchar(); pixel[2] = bc.buchar(); pixel[3] = bc.auchar(); //dump(a_out,"debug : 0000 :",_img); if((back_color.value().a()!=1)&&(bpp!=4)) { //transparent background. //NOTE : the node must be rendered after the "behind nodes" so that // transparency be taken into account for the "behind nodes". img_byte img4; if(!_img.rgb2rgba(img4,255)){ a_out << "tools::sg::tex_rect::update_sg :" << " rgb2rgba failed." << std::endl; m_img.make_empty(); return; } if(!img4.to_texture(expand.value(),pixel,m_img)){ a_out << "tools::sg::tex_rect::update_sg :" << " problem with inlib::tex_rect::to_texture." << std::endl; m_img.make_empty(); return; } } else { if(!_img.to_texture(expand.value(),pixel,m_img)){ a_out << "tools::sg::tex_rect::update_sg :" << " problem with inlib::tex_rect::to_texture." << std::endl; m_img.make_empty(); return; } } //a_out << "debug : limit : 000 : " << limit.value() << std::endl; if(limit.value()) { unsigned int tw = m_img.width(); unsigned int th = m_img.height(); if((tw*th*m_img.bpp())>limit.value()) { //a_out << "debug : trunc " << (tw*th) << std::endl; unsigned int fac = 2; while(true) { unsigned int pw = tw/fac; unsigned int ph = th/fac; if((pw*ph)iw) { float part = float(iw)/float(rw); ax = part; bx = 0.5f*(1-part); } if(rh>ih) { float part = float(ih)/float(rh); ay = part; by = 0.5f*(1-part); }} {unsigned int num = 12/3; for(unsigned int index=0;index