34 _egg_surface(egg_surface)
36 _nurbs = make_nurbs_surface(_egg_surface, LMatrix4d::ident_mat());
37 _has_vertex_color = _egg_surface->has_vertex_color();
44 _match_u = _match_v =
nullptr;
45 _tess_u = _tess_v = 0;
59 if (_nurbs ==
nullptr) {
63 record_vertex_extras();
65 _nurbs->normalize_u_knots();
66 _nurbs->normalize_v_knots();
67 _nurbs_result = _nurbs->evaluate();
69 _num_u = _nurbs->get_num_u_segments();
70 _num_v = _nurbs->get_num_v_segments();
72 if (QtessGlobals::_respect_egg) {
92 if (_nurbs ==
nullptr) {
97 _u_placer.get_scores(_nurbs->get_num_u_segments() * 100,
98 _nurbs->get_num_v_segments() * 2,
99 ratio, _nurbs_result,
true);
100 _v_placer.get_scores(_nurbs->get_num_v_segments() * 100,
101 _nurbs->get_num_u_segments() * 2,
102 ratio, _nurbs_result,
false);
106 return _u_placer.get_total_score() * _v_placer.get_total_score() * _importance2;
119 PT(
EggGroup) group = do_uniform_tesselate(tris);
120 PT(
EggNode) new_node = group.p();
121 if (new_node ==
nullptr) {
122 new_node =
new EggComment(_egg_surface->get_name(),
123 "Omitted NURBS surface.");
127 nassertr(parent !=
nullptr, 0);
128 parent->remove_child(_egg_surface);
142 if (_tess_u == 0 || _tess_v == 0) {
143 out << get_name() <<
" : omit\n";
145 }
else if (_iso_u.empty() || _iso_v.empty()) {
146 out << get_name() <<
" : " << _tess_u <<
" " << _tess_v <<
"\n";
149 out << get_name() <<
" : " << _iso_u.back() <<
" " << _iso_v.back();
191 _tess_u = (int)_iso_u.size() - 1;
192 _tess_v = (int)_iso_v.size() - 1;
200 if (_num_u == 0 || _num_v == 0) {
204 _tess_u = max(_min_u, (
int)floor(_num_u * _importance * pi + 0.5));
205 _tess_v = max(_min_v, (
int)floor(_num_v * _importance * pi + 0.5));
225 _tess_u = max(_min_u, (
int)floor(_u_placer.get_total_score() * _importance * pi + 0.5));
226 _tess_v = max(_min_v, (
int)floor(_v_placer.get_total_score() * _importance * pi + 0.5));
245 _u_placer.place(u, _iso_u);
246 _v_placer.place(v, _iso_v);
247 _tess_u = (int)_iso_u.size() - 1;
248 _tess_v = (int)_iso_v.size() - 1;
258 record_vertex_extras() {
259 int num_u_vertices = _egg_surface->get_num_u_cvs();
260 int num_v_vertices = _egg_surface->get_num_v_cvs();
262 for (
int ui = 0; ui < num_u_vertices; ui++) {
263 for (
int vi = 0; vi < num_v_vertices; vi++) {
264 int i = _egg_surface->get_vertex_index(ui, vi);
265 EggVertex *egg_vertex = _egg_surface->get_vertex(i);
268 EggVertex::GroupRef::const_iterator gi;
271 int d = get_joint_membership_index(joint);
273 _nurbs->set_extended_vertex(ui, vi, d, membership);
277 EggMorphVertexList::const_iterator dxi;
278 for (dxi = egg_vertex->_dxyzs.begin();
279 dxi != egg_vertex->_dxyzs.end();
281 const string &morph_name = (*dxi).get_name();
282 LVector3 delta = LCAST(PN_stdfloat, (*dxi).get_offset());
283 int d = get_dxyz_index(morph_name);
284 _nurbs->set_extended_vertices(ui, vi, d, delta.get_data(), 3);
288 EggMorphColorList::const_iterator dri;
289 for (dri = egg_vertex->_drgbas.begin();
290 dri != egg_vertex->_drgbas.end();
292 const string &morph_name = (*dri).get_name();
293 const LVector4 &delta = (*dri).get_offset();
294 int d = get_drgba_index(morph_name);
295 _nurbs->set_extended_vertices(ui, vi, d, delta.get_data(), 4);
307 if (_match_u !=
nullptr) {
311 <<
"No surface to match " << get_name() <<
" to in U.\n";
313 if (qtess_cat.is_debug()) {
315 <<
"Matching " << get_name() <<
" in U to " << m->get_name()
316 <<
" in " << (_match_u_to_u?
'U':
'V') <<
".\n";
319 _tess_u = m->_tess_u;
322 _tess_u = m->_tess_v;
328 if (_match_v !=
nullptr) {
332 <<
"No surface to match " << get_name() <<
" in V.\n";
334 if (qtess_cat.is_debug()) {
336 <<
"Matching " << get_name() <<
" in V to " << m->get_name()
337 <<
" in " << (_match_v_to_v?
'V':
'U') <<
".\n";
340 _tess_v = m->_tess_v;
343 _tess_v = m->_tess_u;
355 do_uniform_tesselate(
int &tris)
const {
358 if (_tess_u == 0 || _tess_v == 0) {
360 if (qtess_cat.is_debug()) {
362 << get_name() <<
" : omit\n";
372 int num_u = _tess_u + 1;
373 int num_v = _tess_v + 1;
375 if (qtess_cat.is_debug()) {
376 qtess_cat.debug() << get_name() <<
" : " << tris <<
"\n";
379 assert(_iso_u.empty() || (int)_iso_u.size() == num_u);
380 assert(_iso_v.empty() || (int)_iso_v.size() == num_v);
383 int num_verts = num_u * num_v;
387 group->add_child(vpool);
394 VertexList new_verts;
395 new_verts.reserve(num_verts);
401 NVertexCollection n_collection;
403 for (vi = 0; vi < num_v; vi++) {
404 if (_iso_v.empty()) {
405 v = (double)vi / (
double)(num_v-1);
407 v = _iso_v[vi] / _iso_v.back();
409 for (ui = 0; ui < num_u; ui++) {
410 if (_iso_u.empty()) {
411 u = (double)ui / (
double)(num_u-1);
413 u = _iso_u[ui] / _iso_u.back();
416 PT(
EggVertex) egg_vertex = evaluate_vertex(u, v);
417 vpool->add_vertex(egg_vertex);
418 new_verts.push_back(egg_vertex);
419 n_collection[egg_vertex->
get_pos3()].insert(egg_vertex);
422 nassertr((
int)new_verts.size() == num_verts,
nullptr);
425 for (vi = 1; vi < num_v; vi++) {
426 for (ui = 1; ui < num_u; ui++) {
428 poly->
add_vertex(new_verts[vi*num_u + (ui-1)]);
429 poly->add_vertex(new_verts[(vi-1)*num_u + (ui-1)]);
430 poly->add_vertex(new_verts[(vi-1)*num_u + ui]);
431 poly->add_vertex(new_verts[vi*num_u + ui]);
433 poly->copy_attributes(*_egg_surface);
438 if (poly->recompute_polygon_normal()) {
440 group->add_child(poly);
450 NVertexCollection::const_iterator nci;
451 for (nci = n_collection.begin(); nci != n_collection.end(); ++nci) {
452 const NVertexGroup &group = (*nci).second;
456 LNormald normal = LNormald::zero();
458 NVertexGroup::const_iterator ngi;
459 for (ngi = group.begin(); ngi != group.end(); ++ngi) {
461 EggVertex::PrimitiveRef::const_iterator pri;
466 nassertr(egg_primitive->has_normal(),
nullptr);
467 normal += egg_primitive->get_normal();
473 normal /= (double)num_polys;
478 for (ngi = group.begin(); ngi != group.end(); ++ngi) {
480 if (egg_vertex->has_normal()) {
481 if (normal.dot(egg_vertex->get_normal()) < 0.0) {
483 egg_vertex->set_normal(-egg_vertex->get_normal());
487 egg_vertex->set_normal(normal);
501 evaluate_vertex(
double u,
double v)
const {
506 _nurbs_result->eval_point(u, v, point);
507 _nurbs_result->eval_normal(u, v, normal);
512 PN_stdfloat length = normal.length();
513 if (length > 0.0001f) {
515 egg_vertex->set_normal(LCAST(
double, normal));
518 egg_vertex->
set_pos(LCAST(
double, point));
519 egg_vertex->
set_uv(LVecBase2d(u, v));
522 if (_has_vertex_color) {
524 _nurbs_result->eval_extended_points(u, v, 0, &rgba[0], 4);
525 egg_vertex->set_color(rgba);
529 JointTable::const_iterator jti;
530 for (jti = _joint_table.begin(); jti != _joint_table.end(); ++jti) {
532 int d = (*jti).second;
534 double membership = _nurbs_result->eval_extended_point(u, v, d);
535 if (membership > 0.0) {
541 MorphTable::const_iterator mti;
542 for (mti = _dxyz_table.begin(); mti != _dxyz_table.end(); ++mti) {
543 const string &morph_name = (*mti).first;
544 int d = (*mti).second;
547 _nurbs_result->eval_extended_points(u, v, d, &delta[0], 3);
548 if (!delta.almost_equal(LVector3::zero())) {
553 for (mti = _drgba_table.begin(); mti != _drgba_table.end(); ++mti) {
554 const string &morph_name = (*mti).first;
555 int d = (*mti).second;
558 _nurbs_result->eval_extended_points(u, v, d, &delta[0], 4);
559 if (!delta.almost_equal(LVector4::zero())) {
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
A reference to an EggNurbsSurface in the egg file, and its parameters as set by the user input file a...
GroupRef::const_iterator gref_end() const
Returns an iterator that can, in conjunction with gref_begin(), be used to traverse the entire set of...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL map.
int count_tris() const
Returns the number of triangles that will be generated by the current tesselation parameters.
void set_pos(double pos)
Sets the vertex position.
A base class for nodes in the hierarchy that are not leaf nodes.
int write_qtess_parameter(std::ostream &out)
Writes a line to the given output file telling qtess how this surface should be tesselated uniformly.
int get_v_subdiv() const
Returns the requested number of subdivisions in the U direction, or 0 if no particular subdivisions h...
GroupRef::const_iterator gref_begin() const
Returns an iterator that can, in conjunction with gref_end(), be used to traverse the entire set of g...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
A single <Dxyz> or <Duv> or some such entry.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_closed_v() const
Returns true if the surface appears to be closed in the V direction.
std::pair< iterator, bool > insert(const MorphType &value)
This is similar to the insert() interface for sets, except it does not guarantee that the resulting l...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void tesselate_auto(int u, int v, double ratio)
Sets the surface up to tesselate itself by automatically determining the best place to put the indica...
PrimitiveRef::const_iterator pref_end() const
Returns an iterator that can, in conjunction with pref_begin(), be used to traverse the entire set of...
static void output_extra(std::ostream &out, const pvector< double > &iso, char axis)
This function is used to identify the extra isoparams in the list added by user control.
double get_vertex_membership(const EggVertex *vert) const
Returns the amount of membership of the indicated vertex in this group.
double get_score(double ratio)
Computes the curvature/stretch score for the surface, if it has not been already computed,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void omit()
Sets up the surface to omit itself from the output.
void tesselate_specific(const pvector< double > &u_list, const pvector< double > &v_list)
Sets the surface up to tesselate itself at specific isoparams only.
bool is_closed_u() const
Returns true if the surface appears to be closed in the U direction.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for things that may be directly added into the egg hierarchy.
int tesselate()
Applies the appropriate tesselation to the surface, and replaces its node in the tree with an EggGrou...
A parametric NURBS surface.
void tesselate_per_isoparam(double pi, bool autoplace, double ratio)
Sets the surface up to tesselate itself to a uniform amount per isoparam.
void tesselate_per_score(double pi, bool autoplace, double ratio)
Sets the surface up to tesselate itself according to its computed curvature score in both dimensions.
void ref_vertex(EggVertex *vert, double membership=1.0)
Adds the vertex to the set of those referenced by the group, at the indicated membership level.
This is our own Panda specialization on the default STL set.
PrimitiveRef::const_iterator pref_begin() const
Returns an iterator that can, in conjunction with pref_end(), be used to traverse the entire set of p...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
A collection of vertices.
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
void tesselate_uv(int u, int v, bool autoplace, double ratio)
Sets the surface up to tesselate itself uniformly at u x v, or if autoplace is true,...
int get_u_subdiv() const
Returns the requested number of subdivisions in the U direction, or 0 if no particular subdivisions h...