fix sequences, egg-optchar flagging in egg loader

This commit is contained in:
David Rose 2005-04-11 18:27:52 +00:00
parent bbcd8efec4
commit d8b71f9395
10 changed files with 148 additions and 23 deletions

View File

@ -135,13 +135,35 @@ collapse_group(const EggGroup *, int) {
// Function: EggBinMaker::get_bin_name
// Access: Public, Virtual
// Description: May be overridden in derived classes to define a name
// for each new bin, based on its bin number.
// for each new bin, based on its bin number, and a
// sample child.
////////////////////////////////////////////////////////////////////
string EggBinMaker::
get_bin_name(int) {
get_bin_name(int, const EggNode *) {
return string();
}
////////////////////////////////////////////////////////////////////
// Function: EggBinMaker::make_bin
// Access: Public, Virtual
// Description: May be overridden in derived classes to construct a
// new EggBin object (or some derived class, if needed),
// and preload some initial data into as required.
//
// child is an arbitrary child of the bin, and
// collapse_from is the group the bin is being collapsed
// with, if any (implying collapse_group() returned
// true), or NULL if not.
////////////////////////////////////////////////////////////////////
PT(EggBin) EggBinMaker::
make_bin(int, const EggNode *, EggGroup *collapse_from) {
if (collapse_from == (EggGroup *)NULL) {
return new EggBin;
} else {
return new EggBin(*collapse_from);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggBinMaker::collect_nodes
// Access: Private
@ -268,8 +290,11 @@ make_bins_for_group(EggGroupNode *group, const Bins &bins) {
}
if (collapse) {
EggBin *bin = new EggBin(*DCAST(EggGroup, group));
setup_bin(bin, bins.front());
const Nodes &nodes = bins.front();
nassertv(!nodes.empty());
int bin_number = get_bin_number(nodes.front());
PT(EggBin) bin = make_bin(bin_number, nodes.front(), DCAST(EggGroup, group));
setup_bin(bin, nodes);
EggGroupNode *parent = group->get_parent();
parent->remove_child(group);
@ -278,8 +303,11 @@ make_bins_for_group(EggGroupNode *group, const Bins &bins) {
} else {
Bins::const_iterator bi;
for (bi = bins.begin(); bi != bins.end(); ++bi) {
EggBin *bin = new EggBin;
setup_bin(bin, *bi);
const Nodes &nodes = (*bi);
nassertv(!nodes.empty());
int bin_number = get_bin_number(nodes.front());
PT(EggBin) bin = make_bin(bin_number, nodes.front(), NULL);
setup_bin(bin, nodes);
group->add_child(bin);
}
@ -299,7 +327,7 @@ setup_bin(EggBin *bin, const Nodes &nodes) {
int bin_number = get_bin_number(nodes.front());
bin->set_bin_number(bin_number);
string bin_name = get_bin_name(bin_number);
string bin_name = get_bin_name(bin_number, nodes.front());
if (!bin_name.empty()) {
bin->set_name(bin_name);
}

View File

@ -190,7 +190,7 @@
// behavior is never to collapse nodes.
//
//
// virtual string get_bin_name(int bin_number);
// virtual string get_bin_name(int bin_number, EggNode *child);
//
// This function is called as each new bin is created, to
// optionally define a name for the new node. If it returns the
@ -275,7 +275,10 @@ PUBLISHED:
collapse_group(const EggGroup *group, int bin_number);
virtual string
get_bin_name(int bin_number);
get_bin_name(int bin_number, const EggNode *child);
virtual PT(EggBin)
make_bin(int bin_number, const EggNode *child, EggGroup *collapse_from);
private:
// The logic is two-pass. First, we make a scene graph traversal

View File

@ -72,6 +72,25 @@ INLINE EggPrimitive::
clear();
}
////////////////////////////////////////////////////////////////////
// Function: EggPrimitive::get_sort_name
// Access: Published
// Description: Returns the name of the primitive for the purposes of
// sorting primitives into different groups, if there is
// one.
//
// Presently, this is defined as the primitive name
// itself, unless it begins with a digit.
////////////////////////////////////////////////////////////////////
INLINE string EggPrimitive::
get_sort_name() const {
const string &name = get_name();
if (!name.empty() && !isdigit(name[0])) {
return name;
}
return string();
}
////////////////////////////////////////////////////////////////////
// Function: EggPrimitive::clear_connected_shading
// Access: Published

View File

@ -87,6 +87,8 @@ PUBLISHED:
virtual EggRenderMode *determine_draw_order();
virtual EggRenderMode *determine_bin();
INLINE string get_sort_name() const;
virtual Shading get_shading() const;
INLINE void clear_connected_shading();
INLINE Shading get_connected_shading() const;

View File

@ -152,7 +152,7 @@ egg_to_index(EggNode *egg_node) const {
// the character's top node.
////////////////////////////////////////////////////////////////////
PandaNode *CharacterMaker::
part_to_node(PartGroup *part) const {
part_to_node(PartGroup *part, const string &name) const {
PandaNode *node = _character_node;
if (part->is_of_type(CharacterJoint::get_class_type())) {
@ -166,18 +166,18 @@ part_to_node(PartGroup *part) const {
// We should always return a GeomNode, so that all polysets
// created at the same level will get added into the same
// GeomNode. Look for a child of this node. If it doesn't have a
// child yet, add a GeomNode and it. Otherwise, if it already has
// a child, return that.
if (node->is_geom_node()) {
// child yet, add a GeomNode and return it. Otherwise, if it
// already has a child, return that.
if (node->is_geom_node() && node->get_name() == name) {
return node;
}
for (int i = 0; i < node->get_num_children(); i++) {
PandaNode *child = node->get_child(i);
if (child->is_geom_node()) {
if (child->is_geom_node() && child->get_name() == name) {
return child;
}
}
PT(GeomNode) geom_node = new GeomNode("");
PT(GeomNode) geom_node = new GeomNode(name);
node->add_child(geom_node);
return geom_node;
@ -404,7 +404,7 @@ make_qpgeometry(EggNode *egg_node) {
is_dynamic = false;
}
PandaNode *parent = part_to_node(egg_to_part(bin_home));
PandaNode *parent = part_to_node(egg_to_part(bin_home), egg_bin->get_name());
LMatrix4d transform =
egg_bin->get_vertex_frame() *
bin_home->get_node_frame_inv();
@ -431,7 +431,7 @@ make_qpgeometry(EggNode *egg_node) {
////////////////////////////////////////////////////////////////////
void CharacterMaker::
make_static_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
PandaNode *node = part_to_node(egg_to_part(prim_home));
PandaNode *node = part_to_node(egg_to_part(prim_home), string());
// We need this funny transform to convert from the coordinate
// space of the original vertices to that of the new joint node.
@ -450,7 +450,7 @@ make_static_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
////////////////////////////////////////////////////////////////////
void CharacterMaker::
make_dynamic_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
PandaNode *node = part_to_node(egg_to_part(prim_home));
PandaNode *node = part_to_node(egg_to_part(prim_home), string());
LMatrix4d transform =
egg_primitive->get_vertex_frame() *

View File

@ -59,7 +59,7 @@ public:
PartGroup *egg_to_part(EggNode *egg_node) const;
VertexTransform *egg_to_transform(EggNode *egg_node);
int egg_to_index(EggNode *egg_node) const;
PandaNode *part_to_node(PartGroup *part) const;
PandaNode *part_to_node(PartGroup *part, const string &name) const;
int create_slider(const string &name);
VertexSlider *egg_to_slider(const string &name);

View File

@ -79,6 +79,21 @@ get_bin_number(const EggNode *node) {
return (int)BN_none;
}
////////////////////////////////////////////////////////////////////
// Function: EggBinner::get_bin_name
// Access: Public, Virtual
// Description: May be overridden in derived classes to define a name
// for each new bin, based on its bin number, and a
// sample child.
////////////////////////////////////////////////////////////////////
string EggBinner::
get_bin_name(int bin_number, const EggNode *child) {
if (bin_number == BN_polyset) {
return DCAST(EggPrimitive, child)->get_sort_name();
}
return string();
}
////////////////////////////////////////////////////////////////////
// Function: EggBinner::sorts_less
@ -96,14 +111,16 @@ sorts_less(int bin_number, const EggNode *a, const EggNode *b) {
// Different render states are binned separately.
const EggRenderState *rsa, *rsb;
DCAST_INTO_R(rsa, a->get_user_data(EggRenderState::get_class_type()), false);
DCAST_INTO_R(rsb, b->get_user_data(EggRenderState::get_class_type()), false);
DCAST_INTO_R(rsa, pa->get_user_data(EggRenderState::get_class_type()), false);
DCAST_INTO_R(rsb, pb->get_user_data(EggRenderState::get_class_type()), false);
int compare = rsa->compare_to(*rsb);
if (compare != 0) {
return (compare < 0);
}
return false;
// Also, if the primitive was given a name (that does not begin
// with a digit), it gets binned with similar-named primitives.
return pa->get_sort_name() < pb->get_sort_name();
}
case BN_lod:

View File

@ -55,6 +55,9 @@ public:
virtual int
get_bin_number(const EggNode *node);
virtual string
get_bin_name(int bin_number, const EggNode *child);
virtual bool
sorts_less(int bin_number, const EggNode *a, const EggNode *b);

View File

@ -176,11 +176,19 @@ build_graph() {
_data->get_connected_shading();
_data->unify_attributes(true, true);
// Sequences and switches have special needs. Make sure that
// primitives parented directly to a sequence or switch are sorted
// into sub-groups first, to prevent them being unified into a
// single polyset.
separate_switches(_data);
// Then bin up the polysets and LOD nodes.
_data->remove_invalid_primitives(true);
EggBinner binner(*this);
binner.make_bins(_data);
// ((EggGroupNode *)_data)->write(cerr, 0);
// Now build up the scene graph.
_root = new ModelRoot(_data->get_egg_filename().get_basename());
make_node(_data, _root);
@ -1471,6 +1479,49 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs,
////////////////////////////////////////////////////////////////////
// Function: EggLoader::separate_switches
// Access: Private
// Description: Walks the tree recursively, looking for EggPrimitives
// that are children of sequence or switch nodes. If
// any are found, they are moved within their own group
// to protect them from being flattened with their
// neighbors.
////////////////////////////////////////////////////////////////////
void EggLoader::
separate_switches(EggNode *egg_node) {
bool parent_has_switch = false;
if (egg_node->is_of_type(EggGroup::get_class_type())) {
EggGroup *egg_group = DCAST(EggGroup, egg_node);
parent_has_switch = egg_group->get_switch_flag();
}
if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
EggGroupNode::iterator ci;
ci = egg_group->begin();
while (ci != egg_group->end()) {
EggGroupNode::iterator cnext;
cnext = ci;
++cnext;
PT(EggNode) child = (*ci);
if (parent_has_switch &&
child->is_of_type(EggPrimitive::get_class_type())) {
// Move this child under a new node.
PT(EggGroup) new_group = new EggGroup(child->get_name());
egg_group->replace(ci, new_group.p());
new_group->add_child(child);
}
separate_switches(child);
ci = cnext;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggLoader::make_node
// Access: Private
@ -1727,7 +1778,7 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
bool all_polysets = false;
bool any_hidden = false;
if (use_qpgeom) {
check_for_polysets(egg_group, all_polysets, any_hidden);
// check_for_polysets(egg_group, all_polysets, any_hidden);
}
if (all_polysets && !any_hidden) {

View File

@ -130,6 +130,8 @@ private:
void setup_bucket(BuilderBucket &bucket, BakeInUVs &bake_in_uvs,
PandaNode *parent, EggPrimitive *egg_prim);
void separate_switches(EggNode *egg_node);
PandaNode *make_node(EggNode *egg_node, PandaNode *parent);
PandaNode *make_node(EggBin *egg_bin, PandaNode *parent);
PandaNode *make_polyset(EggBin *egg_bin, PandaNode *parent);