*** empty log message ***

This commit is contained in:
David Rose 2001-04-06 23:54:38 +00:00
parent f4756996f4
commit 66e460dbaf
17 changed files with 220 additions and 105 deletions

View File

@ -493,9 +493,14 @@ strip_normals() {
// the scene graph and below with triangles. Returns
// the total number of new triangles produced, less
// degenerate polygons removed.
//
// If convex_also is true, both concave and convex
// polygons will be subdivided into triangles;
// otherwise, only concave polygons will be subdivided,
// and convex polygons will be largely unchanged.
////////////////////////////////////////////////////////////////////
int EggGroupNode::
triangulate_polygons() {
triangulate_polygons(bool convex_also) {
int num_produced = 0;
Children children_copy = _children;
@ -508,10 +513,10 @@ triangulate_polygons() {
if (child->is_of_type(EggPolygon::get_class_type())) {
EggPolygon *poly = DCAST(EggPolygon, child);
poly->triangulate_in_place();
poly->triangulate_in_place(convex_also);
} else if (child->is_of_type(EggGroupNode::get_class_type())) {
num_produced += DCAST(EggGroupNode, child)->triangulate_polygons();
num_produced += DCAST(EggGroupNode, child)->triangulate_polygons(convex_also);
}
}

View File

@ -101,7 +101,7 @@ public:
void recompute_polygon_normals();
void strip_normals();
int triangulate_polygons();
int triangulate_polygons(bool convex_also);
int remove_unused_vertices();
int remove_invalid_primitives();

View File

@ -65,8 +65,15 @@ recompute_polygon_normal() {
// Returns true if the triangulation is successful, or
// false if there was some error (in which case the
// container may contain some partial triangulation).
//
// If convex_also is true, both concave and convex
// polygons will be subdivided into triangles;
// otherwise, only concave polygons will be subdivided,
// and convex polygons will be copied unchanged into the
// container.
////////////////////////////////////////////////////////////////////
INLINE bool EggPolygon::
triangulate_into(EggGroupNode *container) const {
return triangulate_poly(container);
triangulate_into(EggGroupNode *container, bool convex_also) const {
EggPolygon *copy = new EggPolygon(*this);
return copy->triangulate_poly(container, convex_also);
}

View File

@ -95,18 +95,21 @@ calculate_normal(Normald &result) const {
// triangles to the parent group node in place of the
// original polygon. Returns a pointer to the original
// polygon, which is likely about to be destructed.
//
// If convex_also is true, both concave and convex
// polygons will be subdivided into triangles;
// otherwise, only concave polygons will be subdivided,
// and convex polygons will be copied unchanged into the
// container.
////////////////////////////////////////////////////////////////////
PT(EggPolygon) EggPolygon::
triangulate_in_place() {
triangulate_in_place(bool convex_also) {
EggGroupNode *parent = get_parent();
nassertr(parent != (EggGroupNode *)NULL, this);
PT(EggPolygon) save_me = this;
parent->remove_child(this);
if (cleanup()) {
triangulate_into(parent);
}
triangulate_poly(parent, convex_also);
return save_me;
}
@ -253,13 +256,16 @@ decomp_concave(EggGroupNode *container, int asum, int x, int y) const {
} else {
// Here's a triangle to output.
EggPolygon *triangle = new EggPolygon(*this);
container->add_child(triangle);
PT(EggPolygon) triangle = new EggPolygon(*this);
triangle->clear();
triangle->add_vertex(get_vertex(p0->index));
triangle->add_vertex(get_vertex(p1->index));
triangle->add_vertex(get_vertex(p2->index));
if (triangle->cleanup()) {
container->add_child(triangle.p());
}
p0->next = p1->next;
p1 = p2;
p2 = p2->next;
@ -273,13 +279,16 @@ decomp_concave(EggGroupNode *container, int asum, int x, int y) const {
}
// One more triangle to output.
EggPolygon *triangle = new EggPolygon(*this);
container->add_child(triangle);
PT(EggPolygon) triangle = new EggPolygon(*this);
triangle->clear();
triangle->add_vertex(get_vertex(p0->index));
triangle->add_vertex(get_vertex(p1->index));
triangle->add_vertex(get_vertex(p2->index));
if (triangle->cleanup()) {
container->add_child(triangle.p());
}
return true;
}
@ -292,18 +301,27 @@ decomp_concave(EggGroupNode *container, int asum, int x, int y) const {
// container up with EggPolygons that represent the
// triangles. Returns true if successful, false on
// failure.
//
// If convex_also is true, both concave and convex
// polygons will be subdivided into triangles;
// otherwise, only concave polygons will be subdivided,
// and convex polygons will be copied unchanged into the
// container.
////////////////////////////////////////////////////////////////////
bool EggPolygon::
triangulate_poly(EggGroupNode *container) const {
triangulate_poly(EggGroupNode *container, bool convex_also) {
LPoint3d p0, p1, as;
double dx1, dy1, dx2, dy2, max;
int i, flag, asum, csum, index, x, y, v0, v1, v, even;
if (!cleanup()) {
return false;
}
// First see if the polygon is already a triangle
int num_verts = size();
if (num_verts == 3) {
EggPolygon *triangle = new EggPolygon(*this);
container->add_child(triangle);
container->add_child(this);
return true;
@ -386,10 +404,18 @@ triangulate_poly(EggGroupNode *container) const {
csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
if (csum ^ asum) {
// It's a concave polygon. This is a little harder.
return decomp_concave(container, flag, x, y);
}
}
// It's a convex polygon.
if (!convex_also) {
container->add_child(this);
return true;
}
v0 = 0;
v1 = 1;
v = num_verts - 1;
@ -402,24 +428,30 @@ triangulate_poly(EggGroupNode *container) const {
*/
for (i = 0; i < num_verts - 2; i++) {
if (even) {
EggPolygon *triangle = new EggPolygon(*this);
container->add_child(triangle);
PT(EggPolygon) triangle = new EggPolygon(*this);
triangle->clear();
triangle->add_vertex(get_vertex(v0));
triangle->add_vertex(get_vertex(v1));
triangle->add_vertex(get_vertex(v));
if (triangle->cleanup()) {
container->add_child(triangle.p());
}
v0 = v1;
v1 = v;
v = v0 + 1;
} else {
EggPolygon *triangle = new EggPolygon(*this);
container->add_child(triangle);
PT(EggPolygon) triangle = new EggPolygon(*this);
triangle->clear();
triangle->add_vertex(get_vertex(v1));
triangle->add_vertex(get_vertex(v0));
triangle->add_vertex(get_vertex(v));
if (triangle->cleanup()) {
container->add_child(triangle.p());
}
v0 = v1;
v1 = v;
v = v0 - 1;

View File

@ -25,14 +25,14 @@ public:
bool calculate_normal(Normald &result) const;
INLINE bool recompute_polygon_normal();
INLINE bool triangulate_into(EggGroupNode *container) const;
PT(EggPolygon) triangulate_in_place();
INLINE bool triangulate_into(EggGroupNode *container, bool convex_also) const;
PT(EggPolygon) triangulate_in_place(bool convex_also);
virtual void write(ostream &out, int indent_level) const;
private:
bool decomp_concave(EggGroupNode *container, int asum, int x, int y) const;
bool triangulate_poly(EggGroupNode *container) const;
bool triangulate_poly(EggGroupNode *container, bool convex_also);
public:

View File

@ -55,6 +55,12 @@ bool egg_keep_texture_pathnames = config_egg2sg.GetBool("egg-keep-texture-pathna
// actually a NurbsPPCurve object.
bool egg_load_classic_nurbs_curves = config_egg2sg.GetBool("egg-load-classic-nurbs-curves", false);
// When this is true, certain kinds of recoverable errors (not syntax
// errors) in an egg file will be allowed and ignored when an egg file
// is loaded. When it is false, only perfectly pristine egg files may
// be loaded.
bool egg_accept_errors = config_egg2sg.GetBool("egg-accept-errors", true);
CoordinateSystem egg_coordinate_system;
ConfigureFn(config_egg2sg) {

View File

@ -41,6 +41,7 @@ extern EXPCL_PANDAEGG bool egg_flatten_siblings;
extern EXPCL_PANDAEGG bool egg_show_collision_solids;
extern EXPCL_PANDAEGG bool egg_keep_texture_pathnames;
extern EXPCL_PANDAEGG bool egg_load_classic_nurbs_curves;
extern EXPCL_PANDAEGG bool egg_accept_errors;
extern EXPCL_PANDAEGG void init_libegg2sg();

View File

@ -99,6 +99,7 @@ EggLoader::
EggLoader() {
// We need to enforce whatever coordinate system the user asked for.
_data.set_coordinate_system(egg_coordinate_system);
_error = false;
}
////////////////////////////////////////////////////////////////////
@ -110,6 +111,7 @@ EggLoader::
EggLoader(const EggData &data) :
_data(data)
{
_error = false;
}
@ -1578,7 +1580,7 @@ make_collision_plane(EggGroup *egg_group, CollisionNode *cnode,
for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
CollisionPlane *csplane =
create_collision_plane(DCAST(EggPolygon, *ci));
create_collision_plane(DCAST(EggPolygon, *ci), egg_group);
if (csplane != (CollisionPlane *)NULL) {
apply_collision_flags(csplane, flags);
cnode->add_solid(csplane);
@ -1604,13 +1606,8 @@ make_collision_polygon(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::const_iterator ci;
for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
CollisionPolygon *cspoly =
create_collision_polygon(DCAST(EggPolygon, *ci));
if (cspoly != (CollisionPolygon *)NULL) {
apply_collision_flags(cspoly, flags);
cnode->add_solid(cspoly);
return;
}
create_collision_polygons(cnode, DCAST(EggPolygon, *ci),
egg_group, flags);
}
}
}
@ -1630,12 +1627,8 @@ make_collision_polyset(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::const_iterator ci;
for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
CollisionPolygon *cspoly =
create_collision_polygon(DCAST(EggPolygon, *ci));
if (cspoly != (CollisionPolygon *)NULL) {
apply_collision_flags(cspoly, flags);
cnode->add_solid(cspoly);
}
create_collision_polygons(cnode, DCAST(EggPolygon, *ci),
egg_group, flags);
}
}
}
@ -1775,8 +1768,12 @@ find_collision_geometry(EggGroup *egg_group) {
// EggPolygon.
////////////////////////////////////////////////////////////////////
CollisionPlane *EggLoader::
create_collision_plane(EggPolygon *egg_poly) {
create_collision_plane(EggPolygon *egg_poly, EggGroup *parent_group) {
if (!egg_poly->cleanup()) {
egg2sg_cat.warning()
<< "Degenerate collision plane in " << parent_group->get_name()
<< "\n";
_error = true;
return NULL;
}
@ -1809,44 +1806,68 @@ create_collision_plane(EggPolygon *egg_poly) {
}
////////////////////////////////////////////////////////////////////
// Function: EggLoader::create_collision_polygon
// Function: EggLoader::create_collision_polygons
// Access: Private
// Description: Creates a single CollisionPolygon from the indicated
// EggPolygon.
// Description: Creates one or more CollisionPolygons from the
// indicated EggPolygon, and adds them to the indicated
// CollisionNode.
////////////////////////////////////////////////////////////////////
CollisionPolygon *EggLoader::
create_collision_polygon(EggPolygon *egg_poly) {
if (!egg_poly->cleanup()) {
return NULL;
void EggLoader::
create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
EggGroup *parent_group,
EggGroup::CollideFlags flags) {
PT(EggGroup) group = new EggGroup;
if (!egg_poly->triangulate_into(group, false)) {
egg2sg_cat.warning()
<< "Degenerate collision polygon in " << parent_group->get_name()
<< "\n";
_error = true;
return;
}
vector<Vertexf> vertices;
if (!egg_poly->empty()) {
EggPolygon::const_iterator vi;
vi = egg_poly->begin();
if (group->size() != 1) {
egg2sg_cat.warning()
<< "Concave collision polygon in " << parent_group->get_name()
<< "\n";
_error = true;
}
Vertexd vert = (*vi)->get_pos3();
vertices.push_back(LCAST(float, vert));
Vertexd last_vert = vert;
++vi;
while (vi != egg_poly->end()) {
vert = (*vi)->get_pos3();
if (!vert.almost_equal(last_vert)) {
vertices.push_back(LCAST(float, vert));
}
EggGroup::iterator ci;
for (ci = group->begin(); ci != group->end(); ++ci) {
EggPolygon *poly = DCAST(EggPolygon, *ci);
last_vert = vert;
vector<Vertexf> vertices;
if (!poly->empty()) {
EggPolygon::const_iterator vi;
vi = poly->begin();
Vertexd vert = (*vi)->get_pos3();
vertices.push_back(LCAST(float, vert));
Vertexd last_vert = vert;
++vi;
while (vi != poly->end()) {
vert = (*vi)->get_pos3();
if (!vert.almost_equal(last_vert)) {
vertices.push_back(LCAST(float, vert));
}
last_vert = vert;
++vi;
}
}
if (vertices.size() >= 3) {
CollisionPolygon *cspoly =
new CollisionPolygon(vertices.begin(), vertices.end());
apply_collision_flags(cspoly, flags);
cnode->add_solid(cspoly);
}
}
if (vertices.size() < 3) {
return NULL;
}
return new CollisionPolygon(vertices.begin(), vertices.end());
}
////////////////////////////////////////////////////////////////////
// Function: EggLoader::apply_deferred_arcs
// Access: Private

View File

@ -53,7 +53,6 @@ public:
void reparent_decals();
void reset_directs();
void make_nonindexed_primitive(EggPrimitive *egg_prim, NamedNode *parent,
const LMatrix4d *transform = NULL);
@ -100,8 +99,11 @@ private:
void apply_collision_flags(CollisionSolid *solid,
EggGroup::CollideFlags flags);
EggGroup *find_collision_geometry(EggGroup *egg_group);
CollisionPlane *create_collision_plane(EggPolygon *egg_poly);
CollisionPolygon *create_collision_polygon(EggPolygon *egg_poly);
CollisionPlane *create_collision_plane(EggPolygon *egg_poly,
EggGroup *parent_group);
void create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
EggGroup *parent_group,
EggGroup::CollideFlags flags);
void apply_deferred_arcs(Node *root);
@ -125,6 +127,7 @@ private:
public:
PT_NamedNode _root;
EggData _data;
bool _error;
};

View File

@ -16,6 +16,12 @@ load_from_loader(EggLoader &loader) {
loader.build_graph();
if (loader._error && !egg_accept_errors) {
egg2sg_cat.error()
<< "Errors in egg file.\n";
return NULL;
}
if (loader._root != (NamedNode *)NULL && egg_flatten) {
SceneGraphReducer gr(RenderRelation::get_class_type());
int num_reduced = gr.flatten(loader._root, egg_flatten_siblings);

View File

@ -126,11 +126,12 @@ issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
const GLGraphicsStateGuardian *glgsg = DCAST(GLGraphicsStateGuardian, gsg);
const Colorf &color = geom->get_next_color(citerator);
//This is a little cheat here just for a slight bit of
//efficiency. We don't want/need to transform the alpha by the color
//matrix, so use a Vertexf (which is only 3 component) and multiply
//this by the matrix, that will by us 1 dot product
Vertexf temp(color[0], color[1], color[2]);
// To be truly general, we really need a 5x5 matrix to transform a
// 4-component color. Rather than messing with that, we instead
// treat the color as a 3-component RGB, which can be transformed by
// the ordinary 4x4 matrix, and a separate alpha value, which can be
// scaled and offsetted.
LPoint3f temp(color[0], color[1], color[2]);
temp = temp * glgsg->get_current_color_mat();
float alpha = (color[3] * glgsg->get_current_alpha_scale()) +
glgsg->get_current_alpha_offset();

View File

@ -112,7 +112,9 @@ invert() const {
if (_matrix.almost_equal(Matrix::ident_mat())) {
return (MatrixTransition<Matrix> *)this;
}
return make_with_matrix(::invert(_matrix));
Matrix inverted;
inverted.invert_from(_matrix);
return make_with_matrix(inverted);
}
////////////////////////////////////////////////////////////////////

View File

@ -136,18 +136,7 @@ INLINE NodePath::
////////////////////////////////////////////////////////////////////
INLINE bool NodePath::
operator == (const NodePath &other) const {
// If either is a singleton, they must both be the same singleton.
if (_head == (ArcComponent *)NULL ||
other._head == (ArcComponent *)NULL) {
if (_head != (ArcComponent *)NULL ||
other._head != (ArcComponent *)NULL ||
_top_node != other._top_node) {
return false;
}
}
// If both has at least one arc, check the list of arcs.
return r_equiv(_head, other._head);
return compare_to(other) == 0;
}
////////////////////////////////////////////////////////////////////

View File

@ -47,6 +47,27 @@ public:
GraphicsStateGuardianBase *_gsg;
};
////////////////////////////////////////////////////////////////////
// Function: NodePath::compare_to
// Access: Public
// Description: Returns a number less than zero if this NodePath
// sorts before the indicated NodePath in an arbitrary
// lexicographical comparision, greater than zero if
// this one sorts after the other one, or zero if the
// two NodePaths are equivalent.
////////////////////////////////////////////////////////////////////
int NodePath::
compare_to(const NodePath &other) const {
if (_head == (ArcComponent *)NULL && other._head == (ArcComponent *)NULL) {
// If both are singletons, compare the pointers.
return _top_node - other._top_node;
} else {
// Otherwise, compare the arc chains.
return r_compare_to(_head, other._head);
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::extend_by
// Access: Public
@ -2430,24 +2451,29 @@ write_bounds(ostream &out) const {
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::r_equiv
// Access: Private
// Description: The recursive implementation of operator ==. Returns
// true if the list of arcs is equivalent, false
// otherwise.
// Function: NodePath::r_compare_to
// Access: Private, Static
// Description: The recursive implementation of compare_to(). Returns
// < 0 if a sorts before b, > 0 if b sorts before a, or
// == 0 if they are equivalent.
////////////////////////////////////////////////////////////////////
bool NodePath::
r_equiv(const ArcComponent *next, const ArcComponent *other) const {
if (next == (const ArcComponent *)NULL) {
nassertr(other == (const ArcComponent *)NULL, false);
return true;
int NodePath::
r_compare_to(const ArcComponent *a, const ArcComponent *b) {
if (a == b) {
return 0;
} else if (a == (const ArcComponent *)NULL) {
return -1;
} else if (b == (const ArcComponent *)NULL) {
return 1;
} else if (a->_arc != b->_arc) {
return a->_arc - b->_arc;
} else {
return r_compare_to(a->_next, b->_next);
}
nassertr(next != (const ArcComponent *)NULL, false);
nassertr(other != (const ArcComponent *)NULL, false);
return (next == other ||
(next->_arc == other->_arc && r_equiv(next->_next, other->_next)));
}
////////////////////////////////////////////////////////////////////

View File

@ -122,6 +122,7 @@ PUBLISHED:
INLINE bool operator == (const NodePath &other) const;
INLINE bool operator != (const NodePath &other) const;
int compare_to(const NodePath &other) const;
INLINE void set_graph_type(TypeHandle graph_type);
INLINE TypeHandle get_graph_type() const;
@ -465,7 +466,7 @@ public:
};
private:
bool r_equiv(const ArcComponent *next, const ArcComponent *other) const;
static int r_compare_to(const ArcComponent *a, const ArcComponent *v);
bool r_extend_by(const ArcComponent *other);
int r_as_string(const ArcComponent *comp, string &result,
int skip_nodes) const;

View File

@ -221,6 +221,20 @@ get_path(int index) const {
return NodePath(_node_paths[index]);
}
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::operator []
// Access: Published
// Description: Returns the nth NodePath in the collection. This is
// the same as get_path(), but it may be a more
// convenient way to access it.
////////////////////////////////////////////////////////////////////
NodePath NodePathCollection::
operator [] (int index) const {
nassertr(index >= 0 && index < (int)_node_paths.size(), NodePath());
return NodePath(_node_paths[index]);
}
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::ls
// Access: Published

View File

@ -41,6 +41,7 @@ PUBLISHED:
bool is_empty() const;
int get_num_paths() const;
NodePath get_path(int index) const;
NodePath operator [] (int index) const;
// Handy operations on many NodePaths at once.
INLINE void ls() const;