15 #include "eggGroupNode.h"
17 #include "eggCoordinateSystem.h"
19 #include "eggFilenameNode.h"
20 #include "eggExternalReference.h"
21 #include "eggPrimitive.h"
23 #include "eggPolygon.h"
24 #include "eggCompositePrimitive.h"
25 #include "eggMesher.h"
26 #include "eggVertexPool.h"
27 #include "eggVertex.h"
28 #include "eggTextureCollection.h"
29 #include "eggMaterialCollection.h"
31 #include "pt_EggTexture.h"
32 #include "pt_EggMaterial.h"
33 #include "config_egg.h"
35 #include "dSearchPath.h"
36 #include "virtualFileSystem.h"
37 #include "deg_2_rad.h"
39 #include "bamCacheRecord.h"
55 <<
"The EggGroupNode copy constructor does not copy children!\n";
68 <<
"The EggGroupNode copy assignment does not copy children!\n";
70 EggNode::operator =(copy);
91 write(ostream &out,
int indent_level)
const {
100 for (i = begin(); i != end(); ++i) {
102 if (!child->is_joint()) {
103 child->write(out, indent_level);
107 for (i = begin(); i != end(); ++i) {
109 if (child->is_joint()) {
110 child->write(out, indent_level);
120 EggGroupNode::iterator EggGroupNode::
122 return _children.begin();
130 EggGroupNode::iterator EggGroupNode::
132 return _children.end();
140 EggGroupNode::reverse_iterator EggGroupNode::
142 return _children.rbegin();
150 EggGroupNode::reverse_iterator EggGroupNode::
152 return _children.rend();
160 EggGroupNode::iterator EggGroupNode::
161 insert(iterator position, PT(
EggNode) x) {
162 prepare_add_child(x);
163 return _children.insert((Children::iterator &)position, x);
171 EggGroupNode::iterator EggGroupNode::
172 erase(iterator position) {
173 prepare_remove_child(*position);
174 return _children.erase((Children::iterator &)position);
182 EggGroupNode::iterator EggGroupNode::
183 erase(iterator first, iterator last) {
185 for (i = first; i != last; ++i) {
186 prepare_remove_child(*i);
188 return _children.erase((Children::iterator &)first,
189 (Children::iterator &)last);
201 nassertv(position != end());
203 prepare_remove_child(*position);
204 prepare_add_child(x);
205 *(Children::iterator &)position = x;
215 return _children.empty();
223 EggGroupNode::size_type EggGroupNode::
225 return _children.size();
235 erase(begin(), end());
251 _gnc_iterator = begin();
272 if (_gnc_iterator != end()) {
273 return *_gnc_iterator++;
289 if (node->_parent != NULL) {
290 node->_parent->remove_child(node);
292 prepare_add_child(node);
293 _children.push_back(node);
307 iterator i = find(begin(), end(), ptnode);
327 Children::iterator ci;
328 for (ci = other._children.begin();
329 ci != other._children.end();
331 other.prepare_remove_child(*ci);
332 prepare_add_child(*ci);
335 _children.splice(_children.end(), other._children);
347 Children::const_iterator ci;
348 for (ci = _children.begin(); ci != _children.end(); ++ci) {
350 if (child->get_name() == name) {
367 Children::const_iterator ci;
368 for (ci = _children.begin();
369 ci != _children.end();
372 if (child->
is_of_type(EggTexture::get_class_type())) {
375 if (egg_cat.is_debug()) {
385 if (egg_cat.is_debug()) {
394 }
else if (child->
is_of_type(EggFilenameNode::get_class_type())) {
397 if (egg_cat.is_debug()) {
405 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
406 if (DCAST(
EggGroupNode, child)->has_absolute_pathnames()) {
427 Children::iterator ci;
428 for (ci = _children.begin();
429 ci != _children.end();
432 if (child->
is_of_type(EggTexture::get_class_type())) {
436 tex->set_filename(tex_filename);
444 }
else if (child->
is_of_type(EggFilenameNode::get_class_type())) {
448 fnode->set_filename(filename);
450 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
451 DCAST(
EggGroupNode, child)->resolve_filenames(searchpath);
466 Children::iterator ci;
467 for (ci = _children.begin();
468 ci != _children.end();
471 if (child->
is_of_type(EggTexture::get_class_type())) {
475 tex->set_filename(
Filename(directory, tex_filename));
485 }
else if (child->
is_of_type(EggFilenameNode::get_class_type())) {
489 fnode->set_filename(
Filename(directory, filename));
492 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
507 Children::iterator ci;
508 for (ci = _children.begin();
509 ci != _children.end();
512 if (child->
is_of_type(EggPrimitive::get_class_type())) {
516 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
547 r_collect_vertex_normals(collection, threshold, cs);
554 double cos_angle = cos(deg_2_rad(threshold));
556 NVertexCollection::iterator ci;
557 for (ci = collection.begin(); ci != collection.end(); ++ci) {
563 NVertexGroup::iterator gi;
565 while (gi != group.end()) {
566 const NVertexReference &base_ref = (*gi);
569 new_group.push_back(base_ref);
572 while (gi != group.end()) {
573 const NVertexReference &ref = (*gi);
574 double dot = base_ref._normal.dot(ref._normal);
575 if (dot > cos_angle) {
577 new_group.push_back(ref);
580 leftover_group.push_back(ref);
587 do_compute_vertex_normals(new_group);
590 group.swap(leftover_group);
617 Children::iterator ci, cnext;
618 ci = _children.begin();
619 while (ci != _children.end()) {
624 if (child->
is_of_type(EggPolygon::get_class_type())) {
629 prepare_remove_child(child);
634 size_t num_vertices = polygon->size();
635 for (
size_t i = 0; i < num_vertices; i++) {
639 if (vertex->has_normal()) {
641 new_vertex.clear_normal();
650 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
651 DCAST(
EggGroupNode, child)->recompute_polygon_normals(cs);
671 Children::iterator ci;
672 for (ci = _children.begin(); ci != _children.end(); ++ci) {
675 if (child->
is_of_type(EggPrimitive::get_class_type())) {
677 prim->clear_normal();
680 size_t num_vertices = prim->size();
681 for (
size_t i = 0; i < num_vertices; i++) {
685 if (vertex->has_normal()) {
687 new_vertex.clear_normal();
695 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
727 r_collect_tangent_binormal(uv_name, collection);
731 TBNVertexCollection::const_iterator ci;
732 for (ci = collection.begin(); ci != collection.end(); ++ci) {
733 const TBNVertexValue &value = (*ci).first;
736 do_compute_tangent_binormal(value, group);
751 bool changed =
false;
753 for (vector_string::const_iterator si = names.begin();
757 nout <<
"Computing tangent and binormal for \"" << uv_name <<
"\"\n";
776 EggTextureCollection::iterator eti;
778 for (eti = texs.begin(); eti != texs.end(); eti++) {
780 if ((eggtex->get_env_type() == EggTexture::ET_normal)||
781 (eggtex->get_env_type() == EggTexture::ET_normal_height)||
782 (eggtex->get_env_type() == EggTexture::ET_normal_gloss)) {
784 vector_string::iterator it = find(names.begin(), names.end(), uv);
785 if (it == names.end()) {
809 int num_produced = 0;
813 Children::iterator ci;
814 for (ci = children_copy.begin();
815 ci != children_copy.end();
819 if (child->
is_of_type(EggPolygon::get_class_type())) {
820 if ((flags & T_polygon) != 0) {
822 poly->triangulate_in_place((flags & T_convex) != 0);
825 }
else if (child->
is_of_type(EggCompositePrimitive::get_class_type())) {
826 if ((flags & T_composite) != 0) {
828 comp->triangulate_in_place();
831 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
832 if ((flags & T_recurse) != 0) {
833 num_produced += DCAST(
EggGroupNode, child)->triangulate_polygons(flags);
838 num_produced += max(0, (
int)(_children.size() - children_copy.size()));
851 mesher.
mesh(
this, (flags & T_flat_shaded) != 0);
853 if ((flags & T_recurse) != 0) {
854 EggGroupNode::iterator ci;
855 for (ci = begin(); ci != end(); ++ci) {
856 if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
878 EggGroupNode::iterator ci;
879 for (ci = begin(); ci != end(); ++ci) {
880 if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
884 }
else if ((*ci)->is_of_type(EggVertexPool::get_class_type())) {
888 if (!prim->empty()) {
889 temp->add_child(prim);
905 for (
unsigned int ni = 0; ni < strip_prefix.size(); ++ni) {
906 string axe_name = strip_prefix[ni];
907 if (this->get_name().substr(0, axe_name.size()) == axe_name) {
908 string new_name = this->get_name().substr(axe_name.size());
910 this->set_name(new_name);
915 EggGroupNode::iterator ci;
916 for (ci = begin(); ci != end(); ++ci) {
917 if ((*ci)->is_of_type(EggGroupNode::get_class_type())) {
919 num_renamed += group_child->
rename_nodes(strip_prefix, recurse);
921 else if ((*ci)->is_of_type(EggNode::get_class_type())) {
923 num_renamed += node_child->
rename_node(strip_prefix);
953 Children::iterator ci, cnext;
954 ci = _children.begin();
955 while (ci != _children.end()) {
960 if (child->
is_of_type(EggVertexPool::get_class_type())) {
964 if (vpool->
empty()) {
970 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
972 num_removed += DCAST(
EggGroupNode, child)->remove_unused_vertices(recurse);
994 Children::iterator ci, cnext;
995 ci = _children.begin();
996 while (ci != _children.end()) {
1001 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1004 _children.erase(ci);
1008 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1010 num_removed += DCAST(
EggGroupNode, child)->remove_invalid_primitives(recurse);
1034 Children::iterator ci;
1035 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1038 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1041 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1057 Children::iterator ci;
1058 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1061 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1064 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1104 Children::iterator ci;
1105 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1108 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1111 EggPrimitive::Shading shading = EggPrimitive::S_per_vertex;
1113 if (allow_per_primitive) {
1115 if (use_connected_shading) {
1122 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1125 (use_connected_shading, allow_per_primitive, recurse);
1147 Children::iterator ci;
1148 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1151 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1154 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1156 DCAST(
EggGroupNode, child)->apply_last_attribute(recurse);
1178 Children::iterator ci;
1179 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1182 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1185 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1187 DCAST(
EggGroupNode, child)->apply_first_attribute(recurse);
1203 Children::iterator ci;
1204 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1207 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1210 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1212 DCAST(
EggGroupNode, child)->post_apply_flat_attribute(recurse);
1227 Children::const_iterator ci;
1228 for (ci = _children.begin();
1229 ci != _children.end();
1231 if ((*ci)->has_primitives()) {
1248 Children::const_iterator ci;
1249 for (ci = _children.begin();
1250 ci != _children.end();
1255 if (child->joint_has_primitives()) {
1273 Children::const_iterator ci;
1274 for (ci = _children.begin();
1275 ci != _children.end();
1277 if ((*ci)->has_normals()) {
1302 Children::iterator ci;
1303 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1306 if (child->
is_of_type(EggPrimitive::get_class_type())) {
1312 EggPrimitive::const_iterator pi;
1313 for (pi = prim->begin(); pi != prim->end(); ++pi) {
1314 vertices.push_back(*pi);
1317 typedef epvector<EggAttributes> Attributes;
1318 Attributes attributes;
1320 if (prim->
is_of_type(EggCompositePrimitive::get_class_type())) {
1326 for (i = 0; i < num_components; i++) {
1336 bool found_pool =
false;
1338 int best_new_vertices = 0;
1340 Vertices new_vertices;
1341 EggVertexPools::iterator vpi;
1342 for (vpi = vertex_pools.begin();
1343 vpi != vertex_pools.end() && !found_pool;
1346 int num_new_vertices = 0;
1348 new_vertices.clear();
1349 new_vertices.reserve(vertices.size());
1351 Vertices::const_iterator vi;
1352 for (vi = vertices.begin();
1353 vi != vertices.end() && !found_pool;
1357 new_vertices.push_back(new_vertex);
1363 if (num_new_vertices == 0) {
1368 }
else if (vertex_pool->
size() + num_new_vertices <= max_vertices) {
1373 num_new_vertices < best_new_vertices) {
1375 best_pool = vertex_pool;
1376 best_new_vertices = num_new_vertices;
1386 vertex_pools.push_back(best_pool);
1389 new_vertices.clear();
1390 new_vertices.reserve(vertices.size());
1392 Vertices::const_iterator vi;
1393 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
1397 new_vertices.push_back(new_vertex);
1401 Vertices::const_iterator vi;
1402 nassertv(new_vertices.size() == vertices.size());
1403 for (vi = new_vertices.begin(); vi != new_vertices.end(); ++vi) {
1405 nassertv(new_vertex != (
EggVertex *)NULL);
1409 if (prim->
is_of_type(EggCompositePrimitive::get_class_type())) {
1414 nassertv(num_components == (
int)attributes.size());
1415 for (i = 0; i < num_components; i++) {
1420 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1422 DCAST(
EggGroupNode, child)->rebuild_vertex_pools(vertex_pools, max_vertices, recurse);
1442 update_under(
int depth_offset) {
1443 EggNode::update_under(depth_offset);
1445 Children::iterator ci;
1446 for (ci = _children.begin();
1447 ci != _children.end();
1449 nassertv((*ci)->get_parent() ==
this);
1450 (*ci)->update_under(depth_offset);
1469 CoordinateSystem to_cs) {
1470 Children::iterator ci;
1471 for (ci = _children.begin();
1472 ci != _children.end();
1474 (*ci)->r_transform(mat, inv, to_cs);
1488 r_transform_vertices(
const LMatrix4d &mat) {
1489 Children::iterator ci;
1490 for (ci = _children.begin();
1491 ci != _children.end();
1493 (*ci)->r_transform_vertices(mat);
1507 r_mark_coordsys(CoordinateSystem cs) {
1508 Children::iterator ci;
1509 for (ci = _children.begin();
1510 ci != _children.end();
1512 (*ci)->r_mark_coordsys(cs);
1522 r_flatten_transforms() {
1523 Children::iterator ci;
1524 for (ci = _children.begin();
1525 ci != _children.end();
1527 (*ci)->r_flatten_transforms();
1538 Children::iterator ci;
1539 for (ci = _children.begin();
1540 ci != _children.end();
1542 (*ci)->r_apply_texmats(textures);
1554 CoordinateSystem EggGroupNode::
1555 find_coordsys_entry() {
1556 CoordinateSystem coordsys = CS_default;
1563 Children::iterator ci, cnext;
1564 ci = _children.begin();
1565 while (ci != _children.end()) {
1570 if (child->
is_of_type(EggCoordinateSystem::get_class_type())) {
1571 CoordinateSystem new_cs =
1575 prepare_remove_child(child);
1576 _children.erase(ci);
1578 if (new_cs != CS_default) {
1579 if (coordsys != CS_default && coordsys != new_cs) {
1580 coordsys = CS_invalid;
1586 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1587 CoordinateSystem new_cs =
1589 if (new_cs != CS_default) {
1590 if (coordsys != CS_default && coordsys != new_cs) {
1591 coordsys = CS_invalid;
1621 Children::iterator ci, cnext;
1622 ci = _children.begin();
1623 while (ci != _children.end()) {
1628 if (child->
is_of_type(EggTexture::get_class_type())) {
1629 PT_EggTexture tex = DCAST(
EggTexture, child);
1632 prepare_remove_child(tex);
1633 _children.erase(ci);
1639 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1667 Children::iterator ci, cnext;
1668 ci = _children.begin();
1669 while (ci != _children.end()) {
1674 if (child->
is_of_type(EggMaterial::get_class_type())) {
1678 prepare_remove_child(tex);
1679 _children.erase(ci);
1685 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1687 DCAST(
EggGroupNode, child)->find_materials(collection);
1706 r_load_externals(
const DSearchPath &searchpath, CoordinateSystem coordsys,
1708 bool success =
true;
1710 Children::iterator ci;
1711 for (ci = _children.begin();
1712 ci != _children.end();
1715 if (child->
is_of_type(EggExternalReference::get_class_type())) {
1720 Filename filename = ref->get_filename();
1722 new
EggGroupNode(filename.get_basename_wo_extension());
1725 if (!
EggData::resolve_egg_filename(filename, searchpath)) {
1727 <<
"Could not locate " << filename <<
" in "
1728 << searchpath <<
"\n";
1735 if (ext_data.
read(filename)) {
1745 new_node->steal_children(ext_data);
1749 }
else if (child->is_of_type(EggGroupNode::get_class_type())) {
1752 group_child->r_load_externals(searchpath, coordsys, record)
1772 prepare_add_child(
EggNode *node) {
1773 nassertv(node != (
EggNode *)NULL);
1777 nassertv(node->get_parent() == NULL);
1779 node->_parent =
this;
1797 prepare_remove_child(
EggNode *node) {
1798 nassertv(node != (
EggNode *)NULL);
1800 nassertv(node->get_parent() ==
this);
1802 node->_parent = NULL;
1819 double threshold, CoordinateSystem cs) {
1825 Children::iterator ci, cnext;
1826 ci = _children.begin();
1827 while (ci != _children.end()) {
1832 if (child->
is_of_type(EggPolygon::get_class_type())) {
1834 polygon->clear_normal();
1836 NVertexReference
ref;
1837 ref._polygon = polygon;
1841 prepare_remove_child(child);
1842 _children.erase(ci);
1847 size_t num_vertices = polygon->size();
1848 for (
size_t i = 0; i < num_vertices; i++) {
1851 collection[vertex->
get_pos3()].push_back(ref);
1855 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
1863 group->r_collect_vertex_normals(collection, threshold, cs);
1881 nassertv(!group.empty());
1886 NVertexGroup::const_iterator gi;
1887 for (gi = group.begin(); gi != group.end(); ++gi) {
1888 const NVertexReference &ref = (*gi);
1889 normal += ref._normal;
1892 normal /= (double)group.size();
1897 for (gi = group.begin(); gi != group.end(); ++gi) {
1898 const NVertexReference &ref = (*gi);
1899 EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
1903 new_vertex.set_normal(normal);
1907 ref._polygon->set_vertex(ref._vertex, unique);
1920 r_collect_tangent_binormal(
const GlobPattern &uv_name,
1922 Children::iterator ci;
1923 for (ci = _children.begin(); ci != _children.end(); ++ci) {
1926 if (child->
is_of_type(EggPolygon::get_class_type())) {
1929 TBNVertexReference
ref;
1930 ref._polygon = polygon;
1934 size_t num_vertices = polygon->size();
1935 for (
size_t i = 0; i < num_vertices; i++) {
1943 if (v1->has_normal() || polygon->has_normal()) {
1949 string name = uv_obj->get_name();
1952 TBNVertexValue value;
1953 value._uv_name = name;
1955 if (v1->has_normal()) {
1956 value._normal = v1->get_normal();
1958 value._normal = polygon->get_normal();
1960 value._uv = v1->
get_uv(name);
1977 value._facing =
is_right(w1 - w2, w3 - w1);
1979 double x1 = p2[0] - p1[0];
1980 double x2 = p3[0] - p1[0];
1981 double y1 = p2[1] - p1[1];
1982 double y2 = p3[1] - p1[1];
1983 double z1 = p2[2] - p1[2];
1984 double z2 = p3[2] - p1[2];
1986 double s1 = w2[0] - w1[0];
1987 double s2 = w3[0] - w1[0];
1988 double t1 = w2[1] - w1[1];
1989 double t2 = w3[1] - w1[1];
1991 double denom = (s1 * t2 - s2 * t1);
1993 ref._sdir.set(0.0, 0.0, 0.0);
1994 ref._tdir.set(0.0, 0.0, 0.0);
1996 double r = 1.0 / denom;
1997 ref._sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
1998 (t2 * z1 - t1 * z2) * r);
1999 ref._tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
2000 (s1 * z2 - s2 * z1) * r);
2005 collection[value].push_back(ref);
2011 }
else if (child->
is_of_type(EggGroupNode::get_class_type())) {
2019 group->r_collect_tangent_binormal(uv_name, collection);
2035 do_compute_tangent_binormal(
const TBNVertexValue &value,
2036 const TBNVertexGroup &group) {
2037 nassertv(!group.empty());
2044 TBNVertexGroup::const_iterator gi;
2045 for (gi = group.begin(); gi != group.end(); ++gi) {
2046 const TBNVertexReference &ref = (*gi);
2055 if (!sdir.normalize()) {
2056 sdir.set(1.0, 0.0, 0.0);
2058 if (!tdir.normalize()) {
2059 tdir = sdir.cross(
LNormald(0.0, 0.0, -1.0));
2062 LNormald tangent = (sdir - value._normal * value._normal.dot(sdir));
2065 LNormald binormal = cross(value._normal, tangent);
2066 if (dot(binormal, tdir) < 0.0f) {
2067 binormal = -binormal;
2075 for (gi = group.begin(); gi != group.end(); ++gi) {
2076 const TBNVertexReference &ref = (*gi);
2077 EggVertex *vertex = ref._polygon->get_vertex(ref._vertex);
2081 EggVertexUV *uv_obj = new_vertex.modify_uv_obj(value._uv_name);
2083 uv_obj->set_tangent(tangent);
2084 uv_obj->set_binormal(binormal);
2089 ref._polygon->set_vertex(ref._vertex, unique);
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
The set of UV's that may or may not be assigned to a vertex.
void strip_normals()
Removes all normals from primitives, and the vertices they reference, at this node and below...
bool test_ref_count_integrity() const
Does some easy checks to make sure that the reference count isn't completely bogus.
void make_point_primitives()
Creates PointLight primitives to reference any otherwise unreferences vertices discovered in this gro...
virtual void unify_attributes(Shading shading)
If the shading property is S_per_vertex, ensures that all vertices have a normal and a color...
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
This is our own Panda specialization on the default STL map.
virtual void write(ostream &out, int indent_level) const
Writes the group and all of its children to the indicated output stream in Egg format.
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
int get_depth() const
Returns the number of nodes above this node in the egg hierarchy.
The base class for primitives such as triangle strips and triangle fans, which include several compon...
This is a 4-by-4 transform matrix.
virtual Shading get_shading() const
Returns the shading properties apparent on this particular primitive.
virtual void apply_first_attribute()
Sets the first vertex of the triangle (or each component) to the primitive normal and/or color...
The <CoordinateSystem> entry at the top of an egg file.
This is an egg node that contains a filename.
bool empty() const
Returns true if the pool is empty.
virtual void apply_last_attribute()
Sets the last vertex of the triangle (or each component) to the primitive normal and/or color...
virtual bool cleanup()
Cleans up modeling errors in whatever context this makes sense.
void unify_attributes(bool use_connected_shading, bool allow_per_primitive, bool recurse)
Applies per-vertex normal and color to all vertices, if they are in fact per-vertex (and different fo...
A base class for nodes in the hierarchy that are not leaf nodes.
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
This is a collection of materials by MRef name.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
int triangulate_polygons(int flags)
Replace all higher-order polygons at this point in the scene graph and below with triangles...
void get_connected_shading()
Queries the connected_shading information on all primitives at this node and below, to ensure that it has been completely filled in before we start mucking around with vertices.
void clear()
Removes all of the vertices from the primitive.
Defines a texture map that may be applied to geometry.
void clear_connected_shading()
Resets the connected_shading information on all primitives at this node and below, so that it may be accurately rederived by the next call to get_connected_shading().
bool is_under_instance() const
Returns true if there is an <Instance> node somewhere in the egg tree at or above this node...
void recompute_polygon_normals(CoordinateSystem cs=CS_default)
Recomputes all the polygon normals for polygon geometry at this group node and below so that they acc...
void set_vertex(int index, EggVertex *vertex)
Replaces a particular vertex based on its index number in the list of vertices.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
bool recompute_tangent_binormal_auto()
This function recomputes the tangent and binormal for any texture coordinate set that affects a norma...
EggNode * find_child(const string &name) const
Returns the child of this node whose name is the indicated string, or NULL if there is no child of th...
bool add_material(EggMaterial *material)
Explicitly adds a new material to the collection.
This is a two-component point in space.
This is a collection of textures by TRef name.
void apply_first_attribute(bool recurse)
Sets the first vertex of the triangle (or each component) to the primitive normal and/or color...
bool matches(const string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
bool add_texture(EggTexture *texture)
Explicitly adds a new texture to the collection.
This is the primary interface into all the egg data, and the root of the egg file structure...
bool has_absolute_pathnames() const
Returns true if any nodes at this level and below include a reference to a file via an absolute pathn...
void set_auto_resolve_externals(bool resolve)
Indicates whether the EggData object will automatically resolve any external references when read() i...
bool is_local() const
Returns true if the filename is local, e.g.
A single point, or a collection of points as defined by a single <PointLight> entry.
void set_coordinate_system(CoordinateSystem coordsys)
Changes the coordinate system of the EggData.
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex...
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex...
virtual bool has_primitives() const
Returns true if there are any primitives (e.g.
This is our own Panda specialization on the default STL vector.
static bool is_right(const LVector2d &v1, const LVector2d &v2)
Returns true if the 2-d v1 is to the right of v2.
void mesh(EggGroupNode *group, bool flat_shaded)
Accepts an EggGroupNode, which contains a set of EggPrimitives–typically, triangles and quads–as chil...
bool normalize()
Normalizes the vector in place.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
void set_alpha_filename(const Filename &filename)
Specifies a separate file that will be loaded in with the 1- or 3-component texture and applied as th...
const string & get_uv_name() const
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
virtual void reverse_vertex_ordering()
Reverses the ordering of the vertices in this primitive, if appropriate, in order to change the direc...
virtual void post_apply_flat_attribute()
Intended as a followup to apply_last_attribute(), this also sets an attribute on the first vertices o...
Collects together unrelated EggPrimitives, determines their edge connectivity, and generates a set of...
The name of a file, such as a texture file or an Egg file.
const EggAttributes * get_component(int i) const
Returns the attributes for the nth component triangle.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
bool has_alpha_filename() const
Returns true if a separate file for the alpha component has been applied, false otherwise.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
int rename_nodes(vector_string strip_prefix, bool recurse)
Rename by stripping out the prefix.
int remove_invalid_primitives(bool recurse)
Removes primitives at this level and below which appear to be degenerate; e.g.
virtual bool joint_has_primitives() const
Returns true if there are any primitives (e.g.
bool load_externals(const DSearchPath &searchpath=DSearchPath())
Loads up all the egg files referenced by <File> entries within the egg structure, and inserts their c...
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
void mesh_triangles(int flags)
Combine triangles together into triangle strips, at this group and below.
bool read(Filename filename, string display_name=string())
Opens the indicated filename and reads the egg data contents from it.
int remove_unused_vertices(bool recurse)
Removes all vertices from VertexPools within this group or below that are not referenced by at least ...
void add_unused_vertices_to_prim(EggPrimitive *prim)
Adds all of the unused vertices in this vertex pool to the indicated primitive, in ascending order...
void apply_last_attribute(bool recurse)
Sets the last vertex of the triangle (or each component) to the primitive normal and/or color...
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
const Filename & get_filename() const
Returns a nonmodifiable reference to the filename.
EggNode * get_next_child()
Returns the next child in the group's list of children since the last call to get_first_child() or ge...
int find_used_textures(EggNode *node)
Walks the egg hierarchy beginning at the indicated node, looking for textures that are referenced by ...
void rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices, bool recurse)
Copies vertices used by the primitives at this group node (and below, if recurse is true) into one or...
size_type size() const
Returns the number of vertices in the pool.
bool recompute_polygon_normal(CoordinateSystem cs=CS_default)
Recalculates the normal according to the order of the vertices, and sets it.
EggVertex * find_matching_vertex(const EggVertex ©)
If the EggVertexPool already has a vertex matching the indicated vertex, returns it; otherwise...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
void replace(iterator position, PT(EggNode) x)
Replaces the node at the indicated position with the indicated node.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
int rename_node(vector_string strip_prefix)
Rename by stripping out the prefix.
void force_filenames(const Filename &directory)
Similar to resolve_filenames, but each non-absolute filename encountered is arbitrarily taken to be i...
const Filename & get_alpha_filename() const
Returns the separate file assigned for the alpha channel.
Shading get_connected_shading() const
Determines what sort of shading properties this primitive's connected neighbors have.
A base class for things that may be directly added into the egg hierarchy.
virtual bool is_joint() const
Returns true if this particular node represents a <Joint> entry or not.
bool calculate_normal(LNormald &result, CoordinateSystem cs=CS_default) const
Calculates the true polygon normal–the vector pointing out of the front of the polygon–based on the v...
EggNode * get_first_child()
Returns the first child in the group's list of children, or NULL if the list of children is empty...
Defines a reference to another egg file which should be inserted at this point.
This class stores a list of directories that can be searched, in order, to locate a particular file...
virtual bool has_normals() const
Returns true if any of the primitives (e.g.
void ref() const
Explicitly increments the reference count.
void add_dependent_file(const Filename &pathname)
Adds the indicated file to the list of files that will be loaded to generate the data in this record...
This is our own Panda specialization on the default STL set.
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
TypeHandle is the identifier used to differentiate C++ class types.
EggVertexPool * get_pool() const
Returns the vertex pool this vertex belongs in.
EggVertex * get_vertex(int index) const
Returns a particular index based on its index number.
void set_component(int i, const EggAttributes *attrib)
Changes the attributes for the nth component triangle.
bool normalize()
Normalizes the vector in place.
void post_apply_flat_attribute(bool recurse)
Intended as a followup to apply_last_attribute(), this also sets an attribute on the first vertices o...
void resolve_filenames(const DSearchPath &searchpath)
Walks the tree and attempts to resolve any filenames encountered.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
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...
virtual string get_default_extension() const
Returns the default extension for this filename type.
void recompute_vertex_normals(double threshold, CoordinateSystem cs=CS_default)
Recomputes all the vertex normals for polygon geometry at this group node and below so that they accu...
void reverse_vertex_ordering()
Reverses the vertex ordering of all polygons defined at this node and below.
void clear_connected_shading()
Resets the connected_shading member in this primitive, so that get_connected_shading() will recompute...
This class can be used to test for string matches against standard Unix-shell filename globbing conve...
bool recompute_tangent_binormal(const GlobPattern &uv_name)
This function recomputes the tangent and binormal for the named texture coordinate set for all vertic...
int get_num_components() const
Returns the number of individual component triangles within the composite.