mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
fix sequences, egg-optchar flagging in egg loader
This commit is contained in:
parent
bbcd8efec4
commit
d8b71f9395
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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() *
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user