16 #include "qtessGlobals.h" 29 set_program_brief(
"tesselate NURBS surfaces in .egg files");
30 set_program_description
31 (
"egg-qtess reads an egg file, tessellates all of its NURBS surfaces " 32 "using a simple uniform tessellation, and outputs a polygonal " 35 "Characters are supported, soft-skinned and otherwise; joint " 36 "ownership is computed correctly for each new polygon vertex. " 37 "Primitives other than NURBS surfaces appearing in the egg file " 42 "Read the indicated parameter file. Type egg-qtess -H " 43 "to print a description of the parameter file format.",
44 &EggQtess::dispatch_filename, NULL, &_qtess_filename);
48 "Specify a uniform subdivision per patch (isoparam). Each NURBS " 49 "surface is made up of N x M patches, each of which is divided " 50 "into subdiv x subdiv quads. A fractional number is allowed.",
51 &EggQtess::dispatch_double, NULL, &_uniform_per_isoparam);
55 "Specify a uniform subdivision per surface. Each NURBS " 56 "surface is subdivided into subdiv x subdiv quads, regardless " 57 "of the number of isoparams it has. A fractional number is " 59 &EggQtess::dispatch_int, NULL, &_uniform_per_surface);
63 "Specify an approximate number of triangles to produce. This " 64 "is the total number of triangles for the entire egg file, " 65 "including those surfaces that have already been given an " 66 "explicit tessellation by a parameter file.",
67 &EggQtess::dispatch_int, NULL, &_total_tris);
71 "Attempt to automatically place tessellation lines where they'll " 72 "do the most good on each surface (once the number of polygons " 73 "for the surface has already been determined).",
74 &EggQtess::dispatch_none, &QtessGlobals::_auto_place);
78 "Attempt to automatically distribute polygons among the surfaces " 79 "where they are most needed according to curvature and size, " 80 "instead of according to the number of isoparams. This only has " 81 "meaning when used in conjunction with -t.",
82 &EggQtess::dispatch_none, &QtessGlobals::_auto_distribute);
86 "Specify the ratio of dominance of size to curvature for -ap and " 87 "-ad. A value of 0 forces placement by curvature only; a very " 88 "large value (like 1000) forces placement by size only. The " 90 &EggQtess::dispatch_double, NULL, &QtessGlobals::_curvature_ratio);
94 "Respect subdivision parameters given in the egg file. If this " 95 "is specified, the egg file may define the effective number of " 96 "patches of each NURBS entry. This can be used alone or in " 97 "conjunction with -u or -t to fine-tune the uniform tessellation " 98 "on a per-surface basis. (This is ignored if -ad is in effect.)",
99 &EggQtess::dispatch_none, &QtessGlobals::_respect_egg);
103 "Instead of writing an egg file, generate a parameter file " 105 &EggQtess::dispatch_none, &_qtess_output);
109 "Describe the format of the parameter file specified with -f.",
110 &EggQtess::dispatch_none, &_describe_qtess);
112 _uniform_per_isoparam = 0.0;
113 _uniform_per_surface = 0;
127 if (_describe_qtess) {
128 describe_qtess_format();
132 return EggFilter::handle_args(args);
142 bool read_qtess =
false;
143 if (!_qtess_filename.empty()) {
144 if (!_qtess_file.
read(_qtess_filename)) {
150 find_surfaces(_data);
153 if (!read_qtess || default_entry.get_num_surfaces() == 0) {
154 nout << _surfaces.size() <<
" NURBS surfaces found.\n";
157 nout << _surfaces.size() <<
" NURBS surfaces found; " 158 << default_entry.get_num_surfaces()
159 <<
" unaccounted for by input file.\n";
164 if (_total_tris != 0) {
167 int extra_tris = max(0, _total_tris - num_tris);
168 if (read_qtess && default_entry.get_num_surfaces() != 0) {
169 cerr << extra_tris <<
" triangles unaccounted for.\n";
172 default_entry.set_num_tris(extra_tris);
174 }
else if (_uniform_per_isoparam!=0.0) {
175 default_entry.set_per_isoparam(_uniform_per_isoparam);
177 }
else if (_uniform_per_surface!=0.0) {
178 default_entry.set_uv(_uniform_per_surface, _uniform_per_surface);
181 default_entry.set_per_isoparam(1.0);
193 Surfaces::const_iterator si;
194 for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
195 tris += (*si)->write_qtess_parameter(out);
198 cerr << tris <<
" tris generated.\n";
204 Surfaces::const_iterator si;
205 for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
206 tris += (*si)->tesselate();
209 cerr << tris <<
" tris generated.\n";
216 _data->remove_unused_vertices(
true);
227 describe_qtess_format() {
229 "An egg-qtess parameter file consists of lines of the form:\n\n" 231 "name [name...] : parameters\n\n" 233 "Where name is a string (possibly including wildcard characters " 234 "such as * and ?) that matches one or more surface " 235 "names, and parameters is a tesselation specification, described below. " 236 "The colon must be followed by at least one space to differentiate it " 237 "from a colon character in the name(s). Multiple names " 238 "may be combined on one line.\n\n\n" 241 "The parameters may be any of the following. Lowercase letters are " 242 "literal. NUM is any number.\n\n";
245 "Remove the surface from the output.\n\n");
248 "Try to achieve the indicated number of triangles over all the " 249 "surfaces matched by this line.\n\n");
251 show_text(
" NUM NUM [[!]u# [!]u# ...] [[!]v# [!]v# ...]", 10,
252 "Tesselate to NUM x NUM quads. If u# or v# appear, they indicate " 253 "additional isoparams to insert (or remove if preceded by an " 254 "exclamation point). The range is [0, 1].\n\n");
257 "Subdivision amount per isoparam. Equivalent to the command-line " 258 "option -u NUM.\n\n");
261 "This is a special parameter. This does not request any specific " 262 "tesselation for the named surfaces, but instead gives a relative " 263 "importance for them when they appear with other surfaces in a " 264 "later entry (or are tesselated via -t on the command line). In " 265 "general, a surface with a weight of 25% will be given a quarter " 266 "of the share of the polygons it otherwise would have received; " 267 "a weight of 150% will give the surface 50% more than its fair " 271 "This is a special parameter that indicates that two or more " 272 "surfaces share a common edge, and must be tesselated the " 274 "along that edge. Specifically, matchvu means that the V " 275 "tesselation of the first named surface will be applied to the U " 276 "tesselation of the second (and later) named surface(s). Similar " 277 "definitions exist for matchuv, matchuu, and matchvv.\n\n");
280 "This is another special parameter that specifies a " 281 "minimum tesselation for all these surfaces in " 282 "the U direction. This is " 283 "the number of quads across the dimension the surface will be " 284 "broken into. The default is 1 for an open surface, and 3 for " 285 "a closed surface.\n\n");
288 "Similar to minv, in the V direction.\n\n");
291 "In addition, the following optional parameters may appear. If they appear, " 292 "they override similar parameters given on the command line; if they do not " 293 "appear, the defaults are taken from the command line:\n\n";
296 "Automatically place tesselation lines on each surface where they " 297 "seem to be needed most.\n\n");
300 "Do not move lines automatically; use a strict uniform " 304 "Automatically distribute polygons to the surfaces that seem to " 305 "need them the most.\n\n");
308 "Do not automatically distribute polygons; distribute " 309 "them according to the number of isoparams of each surface.\n\n");
312 "Specify the ratio of dominance of size to curvature.\n\n");
315 "The hash symbol '#' begins a comment if it is preceded by whitespace or at the " 316 "beginning of a line. The backslash character at the end of a line can be used " 317 "to indicate a continuation.\n\n";
327 find_surfaces(
EggNode *egg_node) {
328 if (egg_node->
is_of_type(EggNurbsSurface::get_class_type())) {
331 if (surface->is_valid()) {
332 _surfaces.push_back(surface);
333 QtessInputEntry::Type match_type = _qtess_file.
match(surface);
334 nassertv(match_type != QtessInputEntry::T_undefined);
338 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
340 EggGroupNode::const_iterator ci;
341 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
347 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.
void show_text(const string &text)
Formats the indicated text to stderr with the known _terminal_width.
Stores one entry in the qtess input file.
void write_egg_file()
Writes out the egg file as the normal result of the program.
ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout...
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...