54 <<
"The EggGroupNode copy constructor does not copy children!\n";
65 <<
"The EggGroupNode copy assignment does not copy children!\n";
67 EggNode::operator =(copy);
84 write(std::ostream &out,
int indent_level)
const {
92 for (i = begin(); i != end(); ++i) {
94 if (!child->is_joint()) {
95 child->write(out, indent_level);
99 for (i = begin(); i != end(); ++i) {
101 if (child->is_joint()) {
102 child->write(out, indent_level);
110 EggGroupNode::iterator EggGroupNode::
112 return _children.begin();
118 EggGroupNode::iterator EggGroupNode::
120 return _children.end();
126 EggGroupNode::reverse_iterator EggGroupNode::
128 return _children.rbegin();
134 EggGroupNode::reverse_iterator EggGroupNode::
136 return _children.rend();
142 EggGroupNode::iterator EggGroupNode::
143 insert(iterator position,
PT(
EggNode) x) {
144 prepare_add_child(x);
145 return _children.insert((Children::iterator &)position, x);
151 EggGroupNode::iterator EggGroupNode::
152 erase(iterator position) {
153 prepare_remove_child(*position);
154 return _children.erase((Children::iterator &)position);
160 EggGroupNode::iterator EggGroupNode::
161 erase(iterator first, iterator last) {
163 for (i = first; i != last; ++i) {
164 prepare_remove_child(*i);
166 return _children.erase((Children::iterator &)first,
167 (Children::iterator &)last);
176 nassertv(position != end());
178 prepare_remove_child(*position);
179 prepare_add_child(x);
180 *(Children::iterator &)position = x;
188 return _children.empty();
194 EggGroupNode::size_type EggGroupNode::
196 return _children.size();
204 erase(begin(), end());
216 _gnc_iterator = begin();
232 if (_gnc_iterator != end()) {
233 return *_gnc_iterator++;
246 if (node->_parent !=
nullptr) {
247 node->_parent->remove_child(node);
249 prepare_add_child(node);
250 _children.push_back(node);
261 iterator i = find(begin(), end(), ptnode);
279 Children::iterator ci;
280 for (ci = other._children.begin();
281 ci != other._children.end();
283 other.prepare_remove_child(*ci);
284 prepare_add_child(*ci);
287 _children.splice(_children.end(), other._children);
297 Children::const_iterator ci;
298 for (ci = _children.begin(); ci != _children.end(); ++ci) {
300 if (child->get_name() == name) {
314 Children::const_iterator ci;
315 for (ci = _children.begin();
316 ci != _children.end();
319 if (child->
is_of_type(EggTexture::get_class_type())) {
322 if (egg_cat.is_debug()) {
332 if (egg_cat.is_debug()) {
341 }
else if (child->
is_of_type(EggFilenameNode::get_class_type())) {
344 if (egg_cat.is_debug()) {
352 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
371 Children::iterator ci;
372 for (ci = _children.begin();
373 ci != _children.end();
376 if (child->
is_of_type(EggTexture::get_class_type())) {
380 tex->set_filename(tex_filename);
388 }
else if (child->
is_of_type(EggFilenameNode::get_class_type())) {
392 fnode->set_filename(filename);
394 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
395 DCAST(
EggGroupNode, child)->resolve_filenames(searchpath);
407 Children::iterator ci;
408 for (ci = _children.begin();
409 ci != _children.end();
412 if (child->
is_of_type(EggTexture::get_class_type())) {
416 tex->set_filename(
Filename(directory, tex_filename));
426 }
else if (child->
is_of_type(EggFilenameNode::get_class_type())) {
430 fnode->set_filename(
Filename(directory, filename));
433 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
445 Children::iterator ci;
446 for (ci = _children.begin();
447 ci != _children.end();
450 if (child->
is_of_type(EggPrimitive::get_class_type())) {
454 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
478 r_collect_vertex_normals(collection, threshold, cs);
484 double cos_angle = cos(deg_2_rad(threshold));
486 NVertexCollection::iterator ci;
487 for (ci = collection.begin(); ci != collection.end(); ++ci) {
493 NVertexGroup::iterator gi;
495 while (gi != group.end()) {
496 const NVertexReference &base_ref = (*gi);
499 new_group.push_back(base_ref);
502 while (gi != group.end()) {
503 const NVertexReference &
ref = (*gi);
504 double dot = base_ref._normal.dot(
ref._normal);
505 if (dot > cos_angle) {
507 new_group.push_back(
ref);
510 leftover_group.push_back(
ref);
517 do_compute_vertex_normals(new_group);
520 group.swap(leftover_group);
542 Children::iterator ci, cnext;
543 ci = _children.begin();
544 while (ci != _children.end()) {
549 if (child->
is_of_type(EggPolygon::get_class_type())) {
554 prepare_remove_child(child);
559 size_t num_vertices = polygon->size();
560 for (
size_t i = 0; i < num_vertices; i++) {
564 if (vertex->has_normal()) {
566 new_vertex.clear_normal();
575 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
576 DCAST(
EggGroupNode, child)->recompute_polygon_normals(cs);
593 Children::iterator ci;
594 for (ci = _children.begin(); ci != _children.end(); ++ci) {
597 if (child->
is_of_type(EggPrimitive::get_class_type())) {
599 prim->clear_normal();
602 size_t num_vertices = prim->size();
603 for (
size_t i = 0; i < num_vertices; i++) {
607 if (vertex->has_normal()) {
609 new_vertex.clear_normal();
617 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
642 r_collect_tangent_binormal(uv_name, collection);
646 TBNVertexCollection::const_iterator ci;
647 for (ci = collection.begin(); ci != collection.end(); ++ci) {
648 const TBNVertexValue &value = (*ci).first;
651 do_compute_tangent_binormal(value, group);
663 bool changed =
false;
665 for (vector_string::const_iterator si = names.begin();
669 nout <<
"Computing tangent and binormal for \"" << uv_name <<
"\"\n";
686 EggTextureCollection::iterator eti;
688 for (eti = texs.begin(); eti != texs.end(); eti++) {
690 if ((eggtex->get_env_type() == EggTexture::ET_normal)||
691 (eggtex->get_env_type() == EggTexture::ET_normal_height)||
692 (eggtex->get_env_type() == EggTexture::ET_normal_gloss)) {
694 vector_string::iterator it = find(names.begin(), names.end(), uv);
695 if (it == names.end()) {
714 int num_produced = 0;
718 Children::iterator ci;
719 for (ci = children_copy.begin();
720 ci != children_copy.end();
724 if (child->
is_of_type(EggPolygon::get_class_type())) {
725 if ((flags & T_polygon) != 0) {
727 poly->triangulate_in_place((flags & T_convex) != 0);
730 }
else if (child->
is_of_type(EggCompositePrimitive::get_class_type())) {
731 if ((flags & T_composite) != 0) {
733 comp->triangulate_in_place();
736 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
737 if ((flags & T_recurse) != 0) {
738 num_produced += DCAST(
EggGroupNode, child)->triangulate_polygons(flags);
743 num_produced += std::max(0, (
int)(_children.size() - children_copy.size()));
753 mesher.
mesh(
this, (flags & T_flat_shaded) != 0);
755 if ((flags & T_recurse) != 0) {
756 EggGroupNode::iterator ci;
757 for (ci = begin(); ci != end(); ++ci) {
758 if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
777 EggGroupNode::iterator ci;
778 for (ci = begin(); ci != end(); ++ci) {
779 if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
783 }
else if ((*ci)->is_of_type(EggVertexPool::get_class_type())) {
787 if (!prim->empty()) {
788 temp->add_child(prim);
800 rename_nodes(vector_string strip_prefix,
bool recurse) {
802 for (
unsigned int ni = 0; ni < strip_prefix.size(); ++ni) {
803 string axe_name = strip_prefix[ni];
804 if (this->get_name().substr(0, axe_name.size()) == axe_name) {
805 string new_name = this->get_name().substr(axe_name.size());
807 this->set_name(new_name);
812 EggGroupNode::iterator ci;
813 for (ci = begin(); ci != end(); ++ci) {
814 if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
816 num_renamed += group_child->
rename_nodes(strip_prefix, recurse);
818 else if ((*ci)->is_of_type(EggNode::get_class_type())) {
820 num_renamed += node_child->
rename_node(strip_prefix);
844 Children::iterator ci, cnext;
845 ci = _children.begin();
846 while (ci != _children.end()) {
851 if (child->
is_of_type(EggVertexPool::get_class_type())) {
855 if (vpool->
empty()) {
861 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
863 num_removed += DCAST(
EggGroupNode, child)->remove_unused_vertices(recurse);
882 Children::iterator ci, cnext;
883 ci = _children.begin();
884 while (ci != _children.end()) {
889 if (child->
is_of_type(EggPrimitive::get_class_type())) {
896 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
898 num_removed += DCAST(
EggGroupNode, child)->remove_invalid_primitives(recurse);
918 Children::iterator ci;
919 for (ci = _children.begin(); ci != _children.end(); ++ci) {
922 if (child->
is_of_type(EggPrimitive::get_class_type())) {
925 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
938 Children::iterator ci;
939 for (ci = _children.begin(); ci != _children.end(); ++ci) {
942 if (child->
is_of_type(EggPrimitive::get_class_type())) {
945 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
976 Children::iterator ci;
977 for (ci = _children.begin(); ci != _children.end(); ++ci) {
980 if (child->
is_of_type(EggPrimitive::get_class_type())) {
983 EggPrimitive::Shading shading = EggPrimitive::S_per_vertex;
985 if (allow_per_primitive) {
987 if (use_connected_shading) {
994 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
997 (use_connected_shading, allow_per_primitive, recurse);
1014 Children::iterator ci;
1015 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1018 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1021 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1023 DCAST(
EggGroupNode, child)->apply_last_attribute(recurse);
1040 Children::iterator ci;
1041 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1044 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1047 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1049 DCAST(
EggGroupNode, child)->apply_first_attribute(recurse);
1062 Children::iterator ci;
1063 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1066 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1069 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1071 DCAST(
EggGroupNode, child)->post_apply_flat_attribute(recurse);
1083 Children::const_iterator ci;
1084 for (ci = _children.begin();
1085 ci != _children.end();
1087 if ((*ci)->has_primitives()) {
1101 Children::const_iterator ci;
1102 for (ci = _children.begin();
1103 ci != _children.end();
1108 if (child->joint_has_primitives()) {
1123 Children::const_iterator ci;
1124 for (ci = _children.begin();
1125 ci != _children.end();
1127 if ((*ci)->has_normals()) {
1147 Children::iterator ci;
1148 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1151 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1157 EggPrimitive::const_iterator pi;
1158 for (pi = prim->begin(); pi != prim->end(); ++pi) {
1159 vertices.push_back(*pi);
1162 typedef epvector<EggAttributes> Attributes;
1163 Attributes attributes;
1165 if (prim->
is_of_type(EggCompositePrimitive::get_class_type())) {
1171 for (i = 0; i < num_components; i++) {
1181 bool found_pool =
false;
1183 int best_new_vertices = 0;
1185 Vertices new_vertices;
1186 EggVertexPools::iterator vpi;
1187 for (vpi = vertex_pools.begin();
1188 vpi != vertex_pools.end() && !found_pool;
1191 int num_new_vertices = 0;
1193 new_vertices.clear();
1194 new_vertices.reserve(vertices.size());
1196 Vertices::const_iterator vi;
1197 for (vi = vertices.begin();
1198 vi != vertices.end() && !found_pool;
1202 new_vertices.push_back(new_vertex);
1203 if (new_vertex ==
nullptr) {
1208 if (num_new_vertices == 0) {
1213 }
else if (vertex_pool->
size() + num_new_vertices <= max_vertices) {
1217 if (best_pool ==
nullptr ||
1218 num_new_vertices < best_new_vertices) {
1220 best_pool = vertex_pool;
1221 best_new_vertices = num_new_vertices;
1227 if (best_pool ==
nullptr) {
1231 vertex_pools.push_back(best_pool);
1234 new_vertices.clear();
1235 new_vertices.reserve(vertices.size());
1237 Vertices::const_iterator vi;
1238 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
1242 new_vertices.push_back(new_vertex);
1246 Vertices::const_iterator vi;
1247 nassertv(new_vertices.size() == vertices.size());
1248 for (vi = new_vertices.begin(); vi != new_vertices.end(); ++vi) {
1250 nassertv(new_vertex !=
nullptr);
1254 if (prim->
is_of_type(EggCompositePrimitive::get_class_type())) {
1259 nassertv(num_components == (
int)attributes.size());
1260 for (i = 0; i < num_components; i++) {
1265 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1267 DCAST(
EggGroupNode, child)->rebuild_vertex_pools(vertex_pools, max_vertices, recurse);
1283 update_under(
int depth_offset) {
1284 EggNode::update_under(depth_offset);
1286 Children::iterator ci;
1287 for (ci = _children.begin();
1288 ci != _children.end();
1290 nassertv((*ci)->get_parent() ==
this);
1291 (*ci)->update_under(depth_offset);
1305 r_transform(
const LMatrix4d &mat,
const LMatrix4d &inv,
1306 CoordinateSystem to_cs) {
1307 Children::iterator ci;
1308 for (ci = _children.begin();
1309 ci != _children.end();
1311 (*ci)->r_transform(mat, inv, to_cs);
1322 r_transform_vertices(
const LMatrix4d &mat) {
1323 Children::iterator ci;
1324 for (ci = _children.begin();
1325 ci != _children.end();
1327 (*ci)->r_transform_vertices(mat);
1338 r_mark_coordsys(CoordinateSystem cs) {
1339 Children::iterator ci;
1340 for (ci = _children.begin();
1341 ci != _children.end();
1343 (*ci)->r_mark_coordsys(cs);
1351 r_flatten_transforms() {
1352 Children::iterator ci;
1353 for (ci = _children.begin();
1354 ci != _children.end();
1356 (*ci)->r_flatten_transforms();
1365 Children::iterator ci;
1366 for (ci = _children.begin();
1367 ci != _children.end();
1369 (*ci)->r_apply_texmats(textures);
1378 CoordinateSystem EggGroupNode::
1379 find_coordsys_entry() {
1380 CoordinateSystem coordsys = CS_default;
1386 Children::iterator ci, cnext;
1387 ci = _children.begin();
1388 while (ci != _children.end()) {
1393 if (child->
is_of_type(EggCoordinateSystem::get_class_type())) {
1394 CoordinateSystem new_cs =
1398 prepare_remove_child(child);
1399 _children.erase(ci);
1401 if (new_cs != CS_default) {
1402 if (coordsys != CS_default && coordsys != new_cs) {
1403 coordsys = CS_invalid;
1409 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1410 CoordinateSystem new_cs =
1412 if (new_cs != CS_default) {
1413 if (coordsys != CS_default && coordsys != new_cs) {
1414 coordsys = CS_invalid;
1440 Children::iterator ci, cnext;
1441 ci = _children.begin();
1442 while (ci != _children.end()) {
1447 if (child->
is_of_type(EggTexture::get_class_type())) {
1448 PT_EggTexture tex = DCAST(
EggTexture, child);
1451 prepare_remove_child(tex);
1452 _children.erase(ci);
1458 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1482 Children::iterator ci, cnext;
1483 ci = _children.begin();
1484 while (ci != _children.end()) {
1489 if (child->
is_of_type(EggMaterial::get_class_type())) {
1493 prepare_remove_child(tex);
1494 _children.erase(ci);
1500 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1502 DCAST(
EggGroupNode, child)->find_materials(collection);
1518 r_load_externals(
const DSearchPath &searchpath, CoordinateSystem coordsys,
1520 bool success =
true;
1522 Children::iterator ci;
1523 for (ci = _children.begin();
1524 ci != _children.end();
1527 if (child->
is_of_type(EggExternalReference::get_class_type())) {
1539 <<
"Could not locate " << filename <<
" in "
1540 << searchpath <<
"\n";
1547 if (ext_data.
read(filename)) {
1550 if (record !=
nullptr) {
1561 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1564 group_child->r_load_externals(searchpath, coordsys, record)
1581 prepare_add_child(
EggNode *node) {
1582 nassertv(node !=
nullptr);
1586 nassertv(node->get_parent() ==
nullptr);
1588 node->_parent =
this;
1603 prepare_remove_child(
EggNode *node) {
1604 nassertv(node !=
nullptr);
1606 nassertv(node->get_parent() ==
this);
1608 node->_parent =
nullptr;
1622 double threshold, CoordinateSystem cs) {
1627 Children::iterator ci, cnext;
1628 ci = _children.begin();
1629 while (ci != _children.end()) {
1634 if (child->
is_of_type(EggPolygon::get_class_type())) {
1636 polygon->clear_normal();
1638 NVertexReference
ref;
1639 ref._polygon = polygon;
1643 prepare_remove_child(child);
1644 _children.erase(ci);
1648 size_t num_vertices = polygon->size();
1649 for (
size_t i = 0; i < num_vertices; i++) {
1656 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1664 group->r_collect_vertex_normals(collection, threshold, cs);
1678 do_compute_vertex_normals(
const NVertexGroup &group) {
1679 nassertv(!group.empty());
1683 LNormald normal(0.0, 0.0, 0.0);
1684 NVertexGroup::const_iterator gi;
1685 for (gi = group.begin(); gi != group.end(); ++gi) {
1686 const NVertexReference &
ref = (*gi);
1687 normal +=
ref._normal;
1690 normal /= (double)group.size();
1695 for (gi = group.begin(); gi != group.end(); ++gi) {
1696 const NVertexReference &
ref = (*gi);
1701 new_vertex.set_normal(normal);
1705 ref._polygon->set_vertex(
ref._vertex, unique);
1715 r_collect_tangent_binormal(
const GlobPattern &uv_name,
1717 Children::iterator ci;
1718 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1721 if (child->
is_of_type(EggPolygon::get_class_type())) {
1724 TBNVertexReference
ref;
1725 ref._polygon = polygon;
1728 size_t num_vertices = polygon->size();
1729 for (
size_t i = 0; i < num_vertices; i++) {
1737 if (v1->has_normal() || polygon->has_normal()) {
1743 string name = uv_obj->get_name();
1746 TBNVertexValue value;
1747 value._uv_name = name;
1749 if (v1->has_normal()) {
1750 value._normal = v1->get_normal();
1752 value._normal = polygon->get_normal();
1754 value._uv = v1->
get_uv(name);
1761 LTexCoordd w1 = v1->
get_uv(name);
1762 LTexCoordd w2 = v2->
get_uv(name);
1763 LTexCoordd w3 = v3->
get_uv(name);
1771 value._facing =
is_right(w1 - w2, w3 - w1);
1773 double x1 = p2[0] - p1[0];
1774 double x2 = p3[0] - p1[0];
1775 double y1 = p2[1] - p1[1];
1776 double y2 = p3[1] - p1[1];
1777 double z1 = p2[2] - p1[2];
1778 double z2 = p3[2] - p1[2];
1780 double s1 = w2[0] - w1[0];
1781 double s2 = w3[0] - w1[0];
1782 double t1 = w2[1] - w1[1];
1783 double t2 = w3[1] - w1[1];
1785 double denom = (s1 * t2 - s2 * t1);
1787 ref._sdir.set(0.0, 0.0, 0.0);
1788 ref._tdir.set(0.0, 0.0, 0.0);
1790 double r = 1.0 / denom;
1791 ref._sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
1792 (t2 * z1 - t1 * z2) * r);
1793 ref._tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
1794 (s1 * z2 - s2 * z1) * r);
1799 collection[value].push_back(
ref);
1805 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1813 group->r_collect_tangent_binormal(uv_name, collection);
1825 do_compute_tangent_binormal(
const TBNVertexValue &value,
1826 const TBNVertexGroup &group) {
1827 nassertv(!group.empty());
1831 LNormald sdir(0.0, 0.0, 0.0);
1832 LNormald tdir(0.0, 0.0, 0.0);
1834 TBNVertexGroup::const_iterator gi;
1835 for (gi = group.begin(); gi != group.end(); ++gi) {
1836 const TBNVertexReference &
ref = (*gi);
1845 if (!sdir.normalize()) {
1846 sdir.set(1.0, 0.0, 0.0);
1848 if (!tdir.normalize()) {
1849 tdir = sdir.cross(LNormald(0.0, 0.0, -1.0));
1852 LNormald tangent = (sdir - value._normal * value._normal.dot(sdir));
1853 tangent.normalize();
1855 LNormald binormal = cross(value._normal, tangent);
1856 if (dot(binormal, tdir) < 0.0f) {
1857 binormal = -binormal;
1860 binormal.normalize();
1865 for (gi = group.begin(); gi != group.end(); ++gi) {
1866 const TBNVertexReference &
ref = (*gi);
1871 EggVertexUV *uv_obj = new_vertex.modify_uv_obj(value._uv_name);
1872 nassertv(uv_obj !=
nullptr);
1873 uv_obj->set_tangent(tangent);
1874 uv_obj->set_binormal(binormal);
1879 ref._polygon->set_vertex(
ref._vertex, unique);