mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 18:31:55 -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
|
// Function: EggBinMaker::get_bin_name
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
// Description: May be overridden in derived classes to define a name
|
// 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::
|
string EggBinMaker::
|
||||||
get_bin_name(int) {
|
get_bin_name(int, const EggNode *) {
|
||||||
return string();
|
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
|
// Function: EggBinMaker::collect_nodes
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -268,8 +290,11 @@ make_bins_for_group(EggGroupNode *group, const Bins &bins) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (collapse) {
|
if (collapse) {
|
||||||
EggBin *bin = new EggBin(*DCAST(EggGroup, group));
|
const Nodes &nodes = bins.front();
|
||||||
setup_bin(bin, 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();
|
EggGroupNode *parent = group->get_parent();
|
||||||
parent->remove_child(group);
|
parent->remove_child(group);
|
||||||
@ -278,8 +303,11 @@ make_bins_for_group(EggGroupNode *group, const Bins &bins) {
|
|||||||
} else {
|
} else {
|
||||||
Bins::const_iterator bi;
|
Bins::const_iterator bi;
|
||||||
for (bi = bins.begin(); bi != bins.end(); ++bi) {
|
for (bi = bins.begin(); bi != bins.end(); ++bi) {
|
||||||
EggBin *bin = new EggBin;
|
const Nodes &nodes = (*bi);
|
||||||
setup_bin(bin, *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);
|
group->add_child(bin);
|
||||||
}
|
}
|
||||||
@ -299,7 +327,7 @@ setup_bin(EggBin *bin, const Nodes &nodes) {
|
|||||||
int bin_number = get_bin_number(nodes.front());
|
int bin_number = get_bin_number(nodes.front());
|
||||||
bin->set_bin_number(bin_number);
|
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()) {
|
if (!bin_name.empty()) {
|
||||||
bin->set_name(bin_name);
|
bin->set_name(bin_name);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@
|
|||||||
// behavior is never to collapse nodes.
|
// 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
|
// This function is called as each new bin is created, to
|
||||||
// optionally define a name for the new node. If it returns the
|
// 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);
|
collapse_group(const EggGroup *group, int bin_number);
|
||||||
|
|
||||||
virtual string
|
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:
|
private:
|
||||||
// The logic is two-pass. First, we make a scene graph traversal
|
// The logic is two-pass. First, we make a scene graph traversal
|
||||||
|
@ -72,6 +72,25 @@ INLINE EggPrimitive::
|
|||||||
clear();
|
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
|
// Function: EggPrimitive::clear_connected_shading
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -87,6 +87,8 @@ PUBLISHED:
|
|||||||
virtual EggRenderMode *determine_draw_order();
|
virtual EggRenderMode *determine_draw_order();
|
||||||
virtual EggRenderMode *determine_bin();
|
virtual EggRenderMode *determine_bin();
|
||||||
|
|
||||||
|
INLINE string get_sort_name() const;
|
||||||
|
|
||||||
virtual Shading get_shading() const;
|
virtual Shading get_shading() const;
|
||||||
INLINE void clear_connected_shading();
|
INLINE void clear_connected_shading();
|
||||||
INLINE Shading get_connected_shading() const;
|
INLINE Shading get_connected_shading() const;
|
||||||
|
@ -152,7 +152,7 @@ egg_to_index(EggNode *egg_node) const {
|
|||||||
// the character's top node.
|
// the character's top node.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PandaNode *CharacterMaker::
|
PandaNode *CharacterMaker::
|
||||||
part_to_node(PartGroup *part) const {
|
part_to_node(PartGroup *part, const string &name) const {
|
||||||
PandaNode *node = _character_node;
|
PandaNode *node = _character_node;
|
||||||
|
|
||||||
if (part->is_of_type(CharacterJoint::get_class_type())) {
|
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
|
// We should always return a GeomNode, so that all polysets
|
||||||
// created at the same level will get added into the same
|
// 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
|
// 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
|
// child yet, add a GeomNode and return it. Otherwise, if it
|
||||||
// a child, return that.
|
// already has a child, return that.
|
||||||
if (node->is_geom_node()) {
|
if (node->is_geom_node() && node->get_name() == name) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < node->get_num_children(); i++) {
|
for (int i = 0; i < node->get_num_children(); i++) {
|
||||||
PandaNode *child = node->get_child(i);
|
PandaNode *child = node->get_child(i);
|
||||||
if (child->is_geom_node()) {
|
if (child->is_geom_node() && child->get_name() == name) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PT(GeomNode) geom_node = new GeomNode("");
|
PT(GeomNode) geom_node = new GeomNode(name);
|
||||||
node->add_child(geom_node);
|
node->add_child(geom_node);
|
||||||
return geom_node;
|
return geom_node;
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ make_qpgeometry(EggNode *egg_node) {
|
|||||||
is_dynamic = false;
|
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 =
|
LMatrix4d transform =
|
||||||
egg_bin->get_vertex_frame() *
|
egg_bin->get_vertex_frame() *
|
||||||
bin_home->get_node_frame_inv();
|
bin_home->get_node_frame_inv();
|
||||||
@ -431,7 +431,7 @@ make_qpgeometry(EggNode *egg_node) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void CharacterMaker::
|
void CharacterMaker::
|
||||||
make_static_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
|
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
|
// We need this funny transform to convert from the coordinate
|
||||||
// space of the original vertices to that of the new joint node.
|
// 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::
|
void CharacterMaker::
|
||||||
make_dynamic_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
|
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 =
|
LMatrix4d transform =
|
||||||
egg_primitive->get_vertex_frame() *
|
egg_primitive->get_vertex_frame() *
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
PartGroup *egg_to_part(EggNode *egg_node) const;
|
PartGroup *egg_to_part(EggNode *egg_node) const;
|
||||||
VertexTransform *egg_to_transform(EggNode *egg_node);
|
VertexTransform *egg_to_transform(EggNode *egg_node);
|
||||||
int egg_to_index(EggNode *egg_node) const;
|
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);
|
int create_slider(const string &name);
|
||||||
VertexSlider *egg_to_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;
|
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
|
// 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.
|
// Different render states are binned separately.
|
||||||
const EggRenderState *rsa, *rsb;
|
const EggRenderState *rsa, *rsb;
|
||||||
DCAST_INTO_R(rsa, a->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, b->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);
|
int compare = rsa->compare_to(*rsb);
|
||||||
if (compare != 0) {
|
if (compare != 0) {
|
||||||
return (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:
|
case BN_lod:
|
||||||
|
@ -55,6 +55,9 @@ public:
|
|||||||
virtual int
|
virtual int
|
||||||
get_bin_number(const EggNode *node);
|
get_bin_number(const EggNode *node);
|
||||||
|
|
||||||
|
virtual string
|
||||||
|
get_bin_name(int bin_number, const EggNode *child);
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
sorts_less(int bin_number, const EggNode *a, const EggNode *b);
|
sorts_less(int bin_number, const EggNode *a, const EggNode *b);
|
||||||
|
|
||||||
|
@ -176,11 +176,19 @@ build_graph() {
|
|||||||
_data->get_connected_shading();
|
_data->get_connected_shading();
|
||||||
_data->unify_attributes(true, true);
|
_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.
|
// Then bin up the polysets and LOD nodes.
|
||||||
_data->remove_invalid_primitives(true);
|
_data->remove_invalid_primitives(true);
|
||||||
EggBinner binner(*this);
|
EggBinner binner(*this);
|
||||||
binner.make_bins(_data);
|
binner.make_bins(_data);
|
||||||
|
|
||||||
|
// ((EggGroupNode *)_data)->write(cerr, 0);
|
||||||
|
|
||||||
// Now build up the scene graph.
|
// Now build up the scene graph.
|
||||||
_root = new ModelRoot(_data->get_egg_filename().get_basename());
|
_root = new ModelRoot(_data->get_egg_filename().get_basename());
|
||||||
make_node(_data, _root);
|
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
|
// Function: EggLoader::make_node
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -1727,7 +1778,7 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
|
|||||||
bool all_polysets = false;
|
bool all_polysets = false;
|
||||||
bool any_hidden = false;
|
bool any_hidden = false;
|
||||||
if (use_qpgeom) {
|
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) {
|
if (all_polysets && !any_hidden) {
|
||||||
|
@ -130,6 +130,8 @@ private:
|
|||||||
void setup_bucket(BuilderBucket &bucket, BakeInUVs &bake_in_uvs,
|
void setup_bucket(BuilderBucket &bucket, BakeInUVs &bake_in_uvs,
|
||||||
PandaNode *parent, EggPrimitive *egg_prim);
|
PandaNode *parent, EggPrimitive *egg_prim);
|
||||||
|
|
||||||
|
void separate_switches(EggNode *egg_node);
|
||||||
|
|
||||||
PandaNode *make_node(EggNode *egg_node, PandaNode *parent);
|
PandaNode *make_node(EggNode *egg_node, PandaNode *parent);
|
||||||
PandaNode *make_node(EggBin *egg_bin, PandaNode *parent);
|
PandaNode *make_node(EggBin *egg_bin, PandaNode *parent);
|
||||||
PandaNode *make_polyset(EggBin *egg_bin, PandaNode *parent);
|
PandaNode *make_polyset(EggBin *egg_bin, PandaNode *parent);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user