diff --git a/pandatool/src/eggprogs/Sources.pp b/pandatool/src/eggprogs/Sources.pp index f83f49212a..ce894040ed 100644 --- a/pandatool/src/eggprogs/Sources.pp +++ b/pandatool/src/eggprogs/Sources.pp @@ -1,7 +1,9 @@ #define LOCAL_LIBS \ converter eggbase progbase #define OTHER_LIBS \ - egg:c linmath:c putil:c express:c pandaegg:m panda:m pandaexpress:m \ + egg:c pandaegg:m \ + pnmimagetypes:c pnmimage:c linmath:c putil:c panda:m \ + express:c pandaexpress:m \ dtoolutil:c dconfig:c dtoolconfig:m dtool:m pystub #define UNIX_SYS_LIBS m diff --git a/pandatool/src/eggprogs/eggTextureCards.cxx b/pandatool/src/eggprogs/eggTextureCards.cxx index 81521b7e71..7f3dd6a7cf 100644 --- a/pandatool/src/eggprogs/eggTextureCards.cxx +++ b/pandatool/src/eggprogs/eggTextureCards.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -39,9 +40,22 @@ EggTextureCards() : EggWriter(true, true) { ("g", "left,right,bottom,top", 0, "Specifies the geometry of each polygon. The default is a unit polygon " "centered on the origin: -0.5,0.5,-0.5,0.5. Polygons are always created " - "on the X-Y plane.", + "on the X-Y plane. If -p is not also specified, all polygons will be " + "the same size and shape.", &EggTextureCards::dispatch_double_quad, NULL, &_polygon_geometry[0]); + add_option + ("p", "xpixels,ypixels", 0, + "Indicates that polygons should be sized in proportion to the pixel " + "size of the texture image. This will potentially create a " + "different size and shape polygon for each texture. The coordinate " + "pair represents the image size in " + "pixels that will exactly fill up the polygon described with -g (or the " + "default polygon if -g is not specified); smaller images will be " + "given proportionately smaller polygons, and larger images will be " + "given proportionately larger polygons.", + &EggTextureCards::dispatch_double_pair, &_got_pixel_scale, &_pixel_scale[0]); + add_option ("c", "r,g,b[,a]", 0, "Specifies the color of each polygon. The default is white: 1,1,1,1.", @@ -112,6 +126,67 @@ dispatch_wrap_mode(const string &opt, const string &arg, void *var) { return true; } + +//////////////////////////////////////////////////////////////////// +// Function: EggTextureCards::scan_texture +// Access: Private +// Description: Reads the texture image header to determine its size, +// and based on this size, computes the appropriate +// left,right,bottom,top geometry of the card that +// correspond to this texture. +// +// Returns true if successful, or false if the texture +// cannot be read. +//////////////////////////////////////////////////////////////////// +bool EggTextureCards:: +scan_texture(const Filename &filename, LVecBase4d &geometry) { + PNMImageHeader header; + if (!header.read_header(filename)) { + nout << "Unable to read image " << filename << "\n"; + return false; + } + + double xscale = header.get_x_size() / _pixel_scale[0]; + double yscale = header.get_y_size() / _pixel_scale[1]; + + geometry.set(_polygon_geometry[0] * xscale, + _polygon_geometry[1] * xscale, + _polygon_geometry[2] * yscale, + _polygon_geometry[3] * yscale); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggTextureCards::make_vertices +// Access: Private +// Description: Creates a set of four vertices for the polygon +// according to the left,right,bottom,top geometry. +//////////////////////////////////////////////////////////////////// +void EggTextureCards:: +make_vertices(const LPoint4d &geometry, EggVertexPool *vpool, + EggVertex *&v1, EggVertex *&v2, EggVertex *&v3, EggVertex *&v4) { + // + // 1 4 + // + // + // 2 3 + // + + v1 = vpool->make_new_vertex + (LPoint3d(geometry[0], geometry[3], 0.0)); + v2 = vpool->make_new_vertex + (LPoint3d(geometry[0], geometry[2], 0.0)); + v3 = vpool->make_new_vertex + (LPoint3d(geometry[1], geometry[2], 0.0)); + v4 = vpool->make_new_vertex + (LPoint3d(geometry[1], geometry[3], 0.0)); + + v1->set_uv(TexCoordd(0.0, 1.0)); + v2->set_uv(TexCoordd(0.0, 0.0)); + v3->set_uv(TexCoordd(1.0, 0.0)); + v4->set_uv(TexCoordd(1.0, 1.0)); +} + //////////////////////////////////////////////////////////////////// // Function: EggTextureCards::run // Access: Public @@ -133,53 +208,52 @@ run() { EggVertexPool *vpool = new EggVertexPool("vpool"); group->add_child(vpool); - // - // 1 4 - // - // - // 2 3 - // + EggVertex *v1, *v2, *v3, *v4; - EggVertex *v1 = vpool->make_new_vertex - (LPoint3d(_polygon_geometry[0], _polygon_geometry[3], 0.0)); - EggVertex *v2 = vpool->make_new_vertex - (LPoint3d(_polygon_geometry[0], _polygon_geometry[2], 0.0)); - EggVertex *v3 = vpool->make_new_vertex - (LPoint3d(_polygon_geometry[1], _polygon_geometry[2], 0.0)); - EggVertex *v4 = vpool->make_new_vertex - (LPoint3d(_polygon_geometry[1], _polygon_geometry[3], 0.0)); - - v1->set_uv(TexCoordd(0.0, 1.0)); - v2->set_uv(TexCoordd(0.0, 0.0)); - v3->set_uv(TexCoordd(1.0, 0.0)); - v4->set_uv(TexCoordd(1.0, 1.0)); + if (!_got_pixel_scale) { + // If we don't have a per-texture pixel scale, all the polygons + // will be the same size, and hence may all share the same four + // vertices. + make_vertices(_polygon_geometry, vpool, v1, v2, v3, v4); + } // Now, create a texture reference and a polygon for each texture. - // We don't really care whether the texture files actually exist at - // this point yet. vector_string::const_iterator ti; for (ti = _texture_names.begin(); ti != _texture_names.end(); ++ti) { Filename filename = (*ti); string name = filename.get_basename_wo_extension(); - EggTexture *tref = new EggTexture(name, filename); - tref->set_wrap_mode(_wrap_mode); - group->add_child(tref); + bool texture_ok = true; + if (_got_pixel_scale) { + // If we have a per-texture pixel scale, we have to read in the + // texture header and determine its size. + LVecBase4d geometry; + texture_ok = scan_texture(filename, geometry); + if (texture_ok) { + make_vertices(geometry, vpool, v1, v2, v3, v4); + } + } - // Each polygon gets placed in its own sub-group. This will make - // pulling them out by name at runtime possible. - EggGroup *sub_group = new EggGroup(name); - group->add_child(sub_group); - EggPolygon *poly = new EggPolygon(); - sub_group->add_child(poly); - poly->set_texture(tref); - poly->set_color(_polygon_color); - - poly->add_vertex(v1); - poly->add_vertex(v2); - poly->add_vertex(v3); - poly->add_vertex(v4); + if (texture_ok) { + EggTexture *tref = new EggTexture(name, filename); + tref->set_wrap_mode(_wrap_mode); + group->add_child(tref); + + // Each polygon gets placed in its own sub-group. This will make + // pulling them out by name at runtime possible. + EggGroup *sub_group = new EggGroup(name); + group->add_child(sub_group); + EggPolygon *poly = new EggPolygon(); + sub_group->add_child(poly); + poly->set_texture(tref); + poly->set_color(_polygon_color); + + poly->add_vertex(v1); + poly->add_vertex(v2); + poly->add_vertex(v3); + poly->add_vertex(v4); + } } // Done! diff --git a/pandatool/src/eggprogs/eggTextureCards.h b/pandatool/src/eggprogs/eggTextureCards.h index 5d242479d5..34598d9f79 100644 --- a/pandatool/src/eggprogs/eggTextureCards.h +++ b/pandatool/src/eggprogs/eggTextureCards.h @@ -12,6 +12,9 @@ #include #include +class EggVertexPool; +class EggVertex; + //////////////////////////////////////////////////////////////////// // Class : EggTextureCards // Description : Generates an egg file featuring a number of polygons, @@ -27,10 +30,17 @@ protected: static bool dispatch_wrap_mode(const string &opt, const string &arg, void *var); +private: + bool scan_texture(const Filename &filename, LVecBase4d &geometry); + void make_vertices(const LPoint4d &geometry, EggVertexPool *vpool, + EggVertex *&v1, EggVertex *&v2, EggVertex *&v3, EggVertex *&v4); + public: void run(); LVecBase4d _polygon_geometry; + LVecBase2d _pixel_scale; + bool _got_pixel_scale; Colorf _polygon_color; vector_string _texture_names; EggTexture::WrapMode _wrap_mode;