25 set_program_brief(
"tesselate NURBS surfaces in .egg files");
26 set_program_description
27 (
"egg-qtess reads an egg file, tessellates all of its NURBS surfaces " 28 "using a simple uniform tessellation, and outputs a polygonal " 31 "Characters are supported, soft-skinned and otherwise; joint " 32 "ownership is computed correctly for each new polygon vertex. " 33 "Primitives other than NURBS surfaces appearing in the egg file " 38 "Read the indicated parameter file. Type egg-qtess -H " 39 "to print a description of the parameter file format.",
40 &EggQtess::dispatch_filename,
nullptr, &_qtess_filename);
44 "Specify a uniform subdivision per patch (isoparam). Each NURBS " 45 "surface is made up of N x M patches, each of which is divided " 46 "into subdiv x subdiv quads. A fractional number is allowed.",
47 &EggQtess::dispatch_double,
nullptr, &_uniform_per_isoparam);
51 "Specify a uniform subdivision per surface. Each NURBS " 52 "surface is subdivided into subdiv x subdiv quads, regardless " 53 "of the number of isoparams it has. A fractional number is " 55 &EggQtess::dispatch_int,
nullptr, &_uniform_per_surface);
59 "Specify an approximate number of triangles to produce. This " 60 "is the total number of triangles for the entire egg file, " 61 "including those surfaces that have already been given an " 62 "explicit tessellation by a parameter file.",
63 &EggQtess::dispatch_int,
nullptr, &_total_tris);
67 "Attempt to automatically place tessellation lines where they'll " 68 "do the most good on each surface (once the number of polygons " 69 "for the surface has already been determined).",
70 &EggQtess::dispatch_none, &QtessGlobals::_auto_place);
74 "Attempt to automatically distribute polygons among the surfaces " 75 "where they are most needed according to curvature and size, " 76 "instead of according to the number of isoparams. This only has " 77 "meaning when used in conjunction with -t.",
78 &EggQtess::dispatch_none, &QtessGlobals::_auto_distribute);
82 "Specify the ratio of dominance of size to curvature for -ap and " 83 "-ad. A value of 0 forces placement by curvature only; a very " 84 "large value (like 1000) forces placement by size only. The " 86 &EggQtess::dispatch_double,
nullptr, &QtessGlobals::_curvature_ratio);
90 "Respect subdivision parameters given in the egg file. If this " 91 "is specified, the egg file may define the effective number of " 92 "patches of each NURBS entry. This can be used alone or in " 93 "conjunction with -u or -t to fine-tune the uniform tessellation " 94 "on a per-surface basis. (This is ignored if -ad is in effect.)",
95 &EggQtess::dispatch_none, &QtessGlobals::_respect_egg);
99 "Instead of writing an egg file, generate a parameter file " 101 &EggQtess::dispatch_none, &_qtess_output);
105 "Describe the format of the parameter file specified with -f.",
106 &EggQtess::dispatch_none, &_describe_qtess);
108 _uniform_per_isoparam = 0.0;
109 _uniform_per_surface = 0;
120 if (_describe_qtess) {
121 describe_qtess_format();
125 return EggFilter::handle_args(args);
133 bool read_qtess =
false;
134 if (!_qtess_filename.empty()) {
135 if (!_qtess_file.
read(_qtess_filename)) {
141 find_surfaces(_data);
144 if (!read_qtess || default_entry.get_num_surfaces() == 0) {
145 nout << _surfaces.size() <<
" NURBS surfaces found.\n";
148 nout << _surfaces.size() <<
" NURBS surfaces found; " 149 << default_entry.get_num_surfaces()
150 <<
" unaccounted for by input file.\n";
155 if (_total_tris != 0) {
158 int extra_tris = std::max(0, _total_tris - num_tris);
159 if (read_qtess && default_entry.get_num_surfaces() != 0) {
160 std::cerr << extra_tris <<
" triangles unaccounted for.\n";
163 default_entry.set_num_tris(extra_tris);
165 }
else if (_uniform_per_isoparam!=0.0) {
166 default_entry.set_per_isoparam(_uniform_per_isoparam);
168 }
else if (_uniform_per_surface!=0.0) {
169 default_entry.set_uv(_uniform_per_surface, _uniform_per_surface);
172 default_entry.set_per_isoparam(1.0);
184 Surfaces::const_iterator si;
185 for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
186 tris += (*si)->write_qtess_parameter(out);
189 std::cerr << tris <<
" tris generated.\n";
195 Surfaces::const_iterator si;
196 for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
197 tris += (*si)->tesselate();
200 std::cerr << tris <<
" tris generated.\n";
206 _data->remove_unused_vertices(
true);
215 describe_qtess_format() {
217 "An egg-qtess parameter file consists of lines of the form:\n\n" 219 "name [name...] : parameters\n\n" 221 "Where name is a string (possibly including wildcard characters " 222 "such as * and ?) that matches one or more surface " 223 "names, and parameters is a tesselation specification, described below. " 224 "The colon must be followed by at least one space to differentiate it " 225 "from a colon character in the name(s). Multiple names " 226 "may be combined on one line.\n\n\n" 229 "The parameters may be any of the following. Lowercase letters are " 230 "literal. NUM is any number.\n\n";
233 "Remove the surface from the output.\n\n");
236 "Try to achieve the indicated number of triangles over all the " 237 "surfaces matched by this line.\n\n");
239 show_text(
" NUM NUM [[!]u# [!]u# ...] [[!]v# [!]v# ...]", 10,
240 "Tesselate to NUM x NUM quads. If u# or v# appear, they indicate " 241 "additional isoparams to insert (or remove if preceded by an " 242 "exclamation point). The range is [0, 1].\n\n");
245 "Subdivision amount per isoparam. Equivalent to the command-line " 246 "option -u NUM.\n\n");
249 "This is a special parameter. This does not request any specific " 250 "tesselation for the named surfaces, but instead gives a relative " 251 "importance for them when they appear with other surfaces in a " 252 "later entry (or are tesselated via -t on the command line). In " 253 "general, a surface with a weight of 25% will be given a quarter " 254 "of the share of the polygons it otherwise would have received; " 255 "a weight of 150% will give the surface 50% more than its fair " 259 "This is a special parameter that indicates that two or more " 260 "surfaces share a common edge, and must be tesselated the " 262 "along that edge. Specifically, matchvu means that the V " 263 "tesselation of the first named surface will be applied to the U " 264 "tesselation of the second (and later) named surface(s). Similar " 265 "definitions exist for matchuv, matchuu, and matchvv.\n\n");
268 "This is another special parameter that specifies a " 269 "minimum tesselation for all these surfaces in " 270 "the U direction. This is " 271 "the number of quads across the dimension the surface will be " 272 "broken into. The default is 1 for an open surface, and 3 for " 273 "a closed surface.\n\n");
276 "Similar to minv, in the V direction.\n\n");
279 "In addition, the following optional parameters may appear. If they appear, " 280 "they override similar parameters given on the command line; if they do not " 281 "appear, the defaults are taken from the command line:\n\n";
284 "Automatically place tesselation lines on each surface where they " 285 "seem to be needed most.\n\n");
288 "Do not move lines automatically; use a strict uniform " 292 "Automatically distribute polygons to the surfaces that seem to " 293 "need them the most.\n\n");
296 "Do not automatically distribute polygons; distribute " 297 "them according to the number of isoparams of each surface.\n\n");
300 "Specify the ratio of dominance of size to curvature.\n\n");
303 "The hash symbol '#' begins a comment if it is preceded by whitespace or at the " 304 "beginning of a line. The backslash character at the end of a line can be used " 305 "to indicate a continuation.\n\n";
312 find_surfaces(
EggNode *egg_node) {
313 if (egg_node->
is_of_type(EggNurbsSurface::get_class_type())) {
316 if (surface->is_valid()) {
317 _surfaces.push_back(surface);
318 QtessInputEntry::Type match_type = _qtess_file.
match(surface);
319 nassertv(match_type != QtessInputEntry::T_undefined);
323 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
325 EggGroupNode::const_iterator ci;
326 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
332 int main(
int argc,
char *argv[]) {
A reference to an EggNurbsSurface in the egg file, and its parameters as set by the user input file a...
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
A base class for nodes in the hierarchy that are not leaf nodes.
int count_tris(double tri_factor=1.0, int attempts=0)
Determines the tesselation u,v amounts of each attached surface, and stores this information in the s...
void add_normals_options()
Adds -no, -np, etc.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Stores one entry in the qtess input file.
void write_egg_file()
Writes out the egg file as the normal result of the program.
A base class for things that may be directly added into the egg hierarchy.
A parametric NURBS surface.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
A program to tesselate NURBS surfaces appearing within an egg file into polygons, using variations on...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout,...
void show_text(const std::string &text)
Formats the indicated text to stderr with the known _terminal_width.