From 2536db25f45f9df28dee0366e5f570651772767d Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 11 Nov 2003 05:24:56 +0000 Subject: [PATCH] add CollisionSolid::set_effective_normal --- panda/src/collide/collisionPlane.cxx | 7 +-- panda/src/collide/collisionPolygon.cxx | 9 ++- panda/src/collide/collisionRay.cxx | 4 +- panda/src/collide/collisionSegment.cxx | 4 +- panda/src/collide/collisionSolid.I | 69 ++++++++++++++++++--- panda/src/collide/collisionSolid.cxx | 75 +++++++++++++++-------- panda/src/collide/collisionSolid.h | 19 +++++- panda/src/collide/collisionSphere.cxx | 3 +- panda/src/collide/collisionTube.cxx | 6 +- panda/src/collide/collisionVisualizer.cxx | 21 ++++--- panda/src/doc/eggSyntax.txt | 20 +++--- panda/src/egg/eggGroup.cxx | 14 ++--- panda/src/egg/eggGroup.h | 7 +-- panda/src/egg2pg/eggLoader.cxx | 15 ++--- panda/src/putil/bam.h | 3 +- 15 files changed, 176 insertions(+), 100 deletions(-) diff --git a/panda/src/collide/collisionPlane.cxx b/panda/src/collide/collisionPlane.cxx index 367024a577..86c02916d7 100644 --- a/panda/src/collide/collisionPlane.cxx +++ b/panda/src/collide/collisionPlane.cxx @@ -54,8 +54,7 @@ make_copy() { void CollisionPlane:: xform(const LMatrix4f &mat) { _plane = _plane * mat; - mark_viz_stale(); - mark_bound_stale(); + CollisionSolid::xform(mat); } //////////////////////////////////////////////////////////////////// @@ -130,7 +129,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { LVector3f from_normal = get_normal() * entry.get_inv_wrt_mat(); - new_entry->set_surface_normal(get_normal()); + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : get_normal()); new_entry->set_surface_point(from_center - get_normal() * dist); new_entry->set_interior_point(from_center - get_normal() * from_radius); @@ -171,7 +170,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) new_entry = new CollisionEntry(entry); LPoint3f into_intersection_point = from_origin + t * from_direction; - new_entry->set_surface_normal(get_normal()); + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : get_normal()); new_entry->set_surface_point(into_intersection_point); return new_entry; diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index 33f68fdbb6..e9ff37dfd9 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -228,8 +228,7 @@ xform(const LMatrix4f &mat) { setup_points(verts_begin, verts_end); } - mark_viz_stale(); - mark_bound_stale(); + CollisionSolid::xform(mat); } //////////////////////////////////////////////////////////////////// @@ -513,7 +512,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { into_depth = from_radius - dist_to_plane(orig_center); } - new_entry->set_surface_normal(get_normal()); + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : get_normal()); new_entry->set_surface_point(from_center - get_normal() * dist); new_entry->set_interior_point(from_center - get_normal() * (dist + into_depth)); @@ -581,7 +580,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { } PT(CollisionEntry) new_entry = new CollisionEntry(entry); - new_entry->set_surface_normal(get_normal()); + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : get_normal()); new_entry->set_surface_point(plane_point); return new_entry; @@ -650,7 +649,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const { } PT(CollisionEntry) new_entry = new CollisionEntry(entry); - new_entry->set_surface_normal(get_normal()); + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : get_normal()); new_entry->set_surface_point(plane_point); return new_entry; diff --git a/panda/src/collide/collisionRay.cxx b/panda/src/collide/collisionRay.cxx index aab037ceb9..176ab8e33c 100644 --- a/panda/src/collide/collisionRay.cxx +++ b/panda/src/collide/collisionRay.cxx @@ -63,8 +63,8 @@ void CollisionRay:: xform(const LMatrix4f &mat) { _origin = _origin * mat; _direction = _direction * mat; - mark_viz_stale(); - mark_bound_stale(); + + CollisionSolid::xform(mat); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/collide/collisionSegment.cxx b/panda/src/collide/collisionSegment.cxx index 5769100911..dcfe5a95d4 100644 --- a/panda/src/collide/collisionSegment.cxx +++ b/panda/src/collide/collisionSegment.cxx @@ -65,8 +65,8 @@ void CollisionSegment:: xform(const LMatrix4f &mat) { _a = _a * mat; _b = _b * mat; - mark_viz_stale(); - mark_bound_stale(); + + CollisionSolid::xform(mat); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/collide/collisionSolid.I b/panda/src/collide/collisionSolid.I index 3c1cd7a108..0e8bf830b0 100644 --- a/panda/src/collide/collisionSolid.I +++ b/panda/src/collide/collisionSolid.I @@ -19,7 +19,7 @@ //////////////////////////////////////////////////////////////////// // Function: CollisionSolid::set_tangible -// Access: Public +// Access: Published // Description: Sets the current state of the 'tangible' flag. Set // this true to make the solid tangible, so that a // CollisionHandlerPusher will not allow another object @@ -29,15 +29,17 @@ //////////////////////////////////////////////////////////////////// INLINE void CollisionSolid:: set_tangible(bool tangible) { - if (tangible != _tangible) { - _tangible = tangible; - mark_viz_stale(); + if (tangible) { + _flags |= F_tangible; + } else { + _flags &= ~F_tangible; } + mark_viz_stale(); } //////////////////////////////////////////////////////////////////// // Function: CollisionSolid::is_tangible -// Access: Public +// Access: Published // Description: Returns whether the solid is considered 'tangible' or // not. An intangible solid has no effect in a // CollisionHandlerPusher (except to throw an event); @@ -46,7 +48,60 @@ set_tangible(bool tangible) { //////////////////////////////////////////////////////////////////// INLINE bool CollisionSolid:: is_tangible() const { - return _tangible; + return (_flags & F_tangible) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::set_effective_normal +// Access: Published +// Description: Records a false normal for this CollisionSolid that +// will be reported by the collision system with all +// collisions into it, instead of its actual normal. +// This is useful as a workaround for the problem of an +// avatar wanting to stand on a sloping ground; by +// storing a false normal, the ground appears to be +// perfectly level, and the avatar does not tend to +// slide down it. +//////////////////////////////////////////////////////////////////// +INLINE void CollisionSolid:: +set_effective_normal(const LVector3f &effective_normal) { + _effective_normal = effective_normal; + _flags |= F_effective_normal; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::clear_effective_normal +// Access: Published +// Description: Removes the normal previously set by +// set_effective_normal(). +//////////////////////////////////////////////////////////////////// +INLINE void CollisionSolid:: +clear_effective_normal() { + _flags &= ~F_effective_normal; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::has_effective_normal +// Access: Published +// Description: Returns true if a special normal was set by +// set_effective_normal(), false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool CollisionSolid:: +has_effective_normal() const { + return (_flags & F_effective_normal) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::get_effective_normal +// Access: Published +// Description: Returns the normal that was set by +// set_effective_normal(). It is an error to call this +// unless has_effective_normal() returns true. +//////////////////////////////////////////////////////////////////// +INLINE const LVector3f &CollisionSolid:: +get_effective_normal() const { + nassertr(has_effective_normal(), LVector3f::zero()); + return _effective_normal; } //////////////////////////////////////////////////////////////////// @@ -59,5 +114,5 @@ is_tangible() const { //////////////////////////////////////////////////////////////////// INLINE void CollisionSolid:: mark_viz_stale() { - _viz_geom_stale = true; + _flags |= F_viz_geom_stale; } diff --git a/panda/src/collide/collisionSolid.cxx b/panda/src/collide/collisionSolid.cxx index 643db99552..a3979a3ac7 100644 --- a/panda/src/collide/collisionSolid.cxx +++ b/panda/src/collide/collisionSolid.cxx @@ -16,7 +16,6 @@ // //////////////////////////////////////////////////////////////////// - #include "collisionSolid.h" #include "config_collide.h" #include "collisionSphere.h" @@ -43,8 +42,7 @@ TypeHandle CollisionSolid::_type_handle; //////////////////////////////////////////////////////////////////// CollisionSolid:: CollisionSolid() { - _viz_geom_stale = true; - _tangible = true; + _flags = F_viz_geom_stale | F_tangible; } //////////////////////////////////////////////////////////////////// @@ -54,10 +52,10 @@ CollisionSolid() { //////////////////////////////////////////////////////////////////// CollisionSolid:: CollisionSolid(const CollisionSolid ©) : - _tangible(copy._tangible) + _effective_normal(copy._effective_normal), + _flags(copy._flags) { - // Actually, there's not a whole lot here we want to copy. - _viz_geom_stale = true; + _flags &= ~F_viz_geom_stale; } //////////////////////////////////////////////////////////////////// @@ -84,6 +82,21 @@ test_intersection(const CollisionEntry &) const { return NULL; } +//////////////////////////////////////////////////////////////////// +// Function: CollisionSolid::xform +// Access: Public, Virtual +// Description: Transforms the solid by the indicated matrix. +//////////////////////////////////////////////////////////////////// +void CollisionSolid:: +xform(const LMatrix4f &mat) { + if (has_effective_normal()) { + _effective_normal = _effective_normal * mat; + } + + mark_viz_stale(); + mark_bound_stale(); +} + //////////////////////////////////////////////////////////////////// // Function: CollisionSolid::get_viz // Access: Public, Virtual @@ -94,14 +107,14 @@ test_intersection(const CollisionEntry &) const { //////////////////////////////////////////////////////////////////// PT(PandaNode) CollisionSolid:: get_viz(const CullTraverserData &) const { - if (_viz_geom_stale) { + if ((_flags & F_viz_geom_stale) != 0) { if (_viz_geom == (GeomNode *)NULL) { ((CollisionSolid *)this)->_viz_geom = new GeomNode("viz"); } else { _viz_geom->remove_all_geoms(); } ((CollisionSolid *)this)->fill_viz_geom(); - ((CollisionSolid *)this)->_viz_geom_stale = false; + ((CollisionSolid *)this)->_flags &= ~F_viz_geom_stale; } return _viz_geom.p(); } @@ -246,9 +259,13 @@ report_undefined_from_intersection(TypeHandle from_type) { // the particular object to a Datagram //////////////////////////////////////////////////////////////////// void CollisionSolid:: -write_datagram(BamWriter *, Datagram &me) -{ - me.add_uint8(_tangible); +write_datagram(BamWriter *, Datagram &me) { + // For now, we need only 8 bits of flags. If we need to expand this + // later, we will have to increase the bam version. + me.add_uint8(_flags); + if ((_flags & F_effective_normal) != 0) { + _effective_normal.write_datagram(me); + } } //////////////////////////////////////////////////////////////////// @@ -260,9 +277,11 @@ write_datagram(BamWriter *, Datagram &me) // place //////////////////////////////////////////////////////////////////// void CollisionSolid:: -fillin(DatagramIterator& scan, BamReader*) -{ - _tangible = (scan.get_uint8() != 0); +fillin(DatagramIterator &scan, BamReader*) { + _flags = scan.get_uint8(); + if ((_flags & F_effective_normal) != 0) { + _effective_normal.read_datagram(scan); + } } @@ -296,21 +315,29 @@ get_solid_viz_state() { TransparencyAttrib::make(TransparencyAttrib::M_alpha)); } - if (_tangible) { - static CPT(RenderState) tangible_state = (const RenderState *)NULL; - if (tangible_state == (const RenderState *)NULL) { - tangible_state = base_state->add_attrib - (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 0.5f))); - } - return tangible_state; - - } else { + if (!is_tangible()) { static CPT(RenderState) intangible_state = (const RenderState *)NULL; if (intangible_state == (const RenderState *)NULL) { intangible_state = base_state->add_attrib (ColorAttrib::make_flat(Colorf(1.0f, 0.3f, 0.5f, 0.5f))); } return intangible_state; + + } else if (has_effective_normal()) { + static CPT(RenderState) fakenormal_state = (const RenderState *)NULL; + if (fakenormal_state == (const RenderState *)NULL) { + fakenormal_state = base_state->add_attrib + (ColorAttrib::make_flat(Colorf(0.5f, 0.5f, 1.0f, 0.5f))); + } + return fakenormal_state; + + } else { + static CPT(RenderState) tangible_state = (const RenderState *)NULL; + if (tangible_state == (const RenderState *)NULL) { + tangible_state = base_state->add_attrib + (ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 0.5f))); + } + return tangible_state; } } @@ -335,7 +362,7 @@ get_wireframe_viz_state() { TransparencyAttrib::make(TransparencyAttrib::M_none)); } - if (_tangible) { + if (is_tangible()) { static CPT(RenderState) tangible_state = (const RenderState *)NULL; if (tangible_state == (const RenderState *)NULL) { tangible_state = base_state->add_attrib diff --git a/panda/src/collide/collisionSolid.h b/panda/src/collide/collisionSolid.h index f5aaa6c830..8e3d7b0718 100644 --- a/panda/src/collide/collisionSolid.h +++ b/panda/src/collide/collisionSolid.h @@ -62,11 +62,16 @@ PUBLISHED: INLINE void set_tangible(bool tangible); INLINE bool is_tangible() const; + INLINE void set_effective_normal(const LVector3f &effective_normal); + INLINE void clear_effective_normal(); + INLINE bool has_effective_normal() const; + INLINE const LVector3f &get_effective_normal() const; + public: virtual PT(CollisionEntry) test_intersection(const CollisionEntry &entry) const; - virtual void xform(const LMatrix4f &mat)=0; + virtual void xform(const LMatrix4f &mat); virtual PT(PandaNode) get_viz(const CullTraverserData &data) const; @@ -94,8 +99,16 @@ protected: CPT(RenderState) get_other_viz_state(); PT(GeomNode) _viz_geom; - bool _viz_geom_stale; - bool _tangible; + +private: + LVector3f _effective_normal; + + enum Flags { + F_tangible = 0x01, + F_effective_normal = 0x02, + F_viz_geom_stale = 0x04, + }; + int _flags; public: virtual void write_datagram(BamWriter* manager, Datagram &me); diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 409ea87941..b5e5987be4 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -67,7 +67,6 @@ xform(const LMatrix4f &mat) { // non-uniform scale. LVector3f radius_v = LVector3f(_radius, 0.0f, 0.0f) * mat; _radius = length(radius_v); - mark_viz_stale(); mark_bound_stale(); } @@ -156,7 +155,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { surface_normal = vec / vec_length; } - new_entry->set_surface_normal(surface_normal); + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : surface_normal); new_entry->set_surface_point(into_center + surface_normal * into_radius); new_entry->set_interior_point(from_center - surface_normal * from_radius); diff --git a/panda/src/collide/collisionTube.cxx b/panda/src/collide/collisionTube.cxx index 33b2948e5a..837fb34bb3 100644 --- a/panda/src/collide/collisionTube.cxx +++ b/panda/src/collide/collisionTube.cxx @@ -62,6 +62,7 @@ xform(const LMatrix4f &mat) { _radius = length(radius_v); recalc_internals(); + CollisionSolid::xform(mat); } //////////////////////////////////////////////////////////////////// @@ -367,9 +368,6 @@ recalc_internals() { look_at(_mat, direction, LVector3f(0.0f, 0.0f, 1.0f), CS_zup_right); _mat.set_row(3, _a); _inv_mat.invert_from(_mat); - - mark_viz_stale(); - mark_bound_stale(); } //////////////////////////////////////////////////////////////////// @@ -693,8 +691,8 @@ set_intersection_point(CollisionEntry *new_entry, // our collision was tangential. LPoint3f orig_point = into_intersection_point - normal * extra_radius; + new_entry->set_surface_normal(has_effective_normal() ? get_effective_normal() : normal); new_entry->set_surface_point(point); - new_entry->set_surface_normal(normal); new_entry->set_interior_point(orig_point); } diff --git a/panda/src/collide/collisionVisualizer.cxx b/panda/src/collide/collisionVisualizer.cxx index 1b2ebaedce..66a236a141 100644 --- a/panda/src/collide/collisionVisualizer.cxx +++ b/panda/src/collide/collisionVisualizer.cxx @@ -146,19 +146,20 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { const CollisionSolid *solid = (*si).first; const SolidInfo &solid_info = (*si).second; PT(PandaNode) node = solid->get_viz(xform_data); + if (node != (PandaNode *)NULL) { + CullTraverserData next_data(xform_data, node); - CullTraverserData next_data(xform_data, node); + // We don't want to inherit the render state from above for + // these guys. Instead, we choose the state according to + // whether a collision was detected or not. + if (solid_info._detected_count > 0) { + next_data._state = get_detected_state(); + } else { + next_data._state = get_tested_state(); + } - // We don't want to inherit the render state from above for - // these guys. Instead, we choose the state according to - // whether a collision was detected or not. - if (solid_info._detected_count > 0) { - next_data._state = get_detected_state(); - } else { - next_data._state = get_tested_state(); + trav->traverse(next_data); } - - trav->traverse(next_data); } // Now draw all of the detected points. diff --git a/panda/src/doc/eggSyntax.txt b/panda/src/doc/eggSyntax.txt index d87ecf5591..bb2aa23654 100644 --- a/panda/src/doc/eggSyntax.txt +++ b/panda/src/doc/eggSyntax.txt @@ -971,19 +971,6 @@ GROUPING ENTRIES The geometry represents a sphere. The vertices in the group are averaged together to determine the sphere's center and radius. - InverseSphere - - The geometry represents a sphere with the normal inverted, to - make a hollow spherical shell. - - Geode - - The geometry is not a collision surface after all, but is in - fact true geometry. This is intended to be used in conjunction - with one or more flags to define collision properties for normal - geometry. - - The flags may be any zero or more of: @@ -1038,6 +1025,13 @@ GROUPING ENTRIES can go forwards but not back. Presently, this is only implemented for planes, polygons, and polysets. + level + + Stores a special effective normal with the collision solid that + points up, regardless of the actual shape or orientation of the + solid. This can be used to allow an avatar to stand on a + sloping surface without having a tendency to slide downward. + { type } diff --git a/panda/src/egg/eggGroup.cxx b/panda/src/egg/eggGroup.cxx index 1a4792daf8..cdb74e6a17 100644 --- a/panda/src/egg/eggGroup.cxx +++ b/panda/src/egg/eggGroup.cxx @@ -781,10 +781,6 @@ string_cs_type(const string &string) { return CST_polyset; } else if (cmp_nocase_uh(string, "sphere") == 0) { return CST_sphere; - } else if (cmp_nocase_uh(string, "inversesphere") == 0) { - return CST_inverse_sphere; - } else if (cmp_nocase_uh(string, "geode") == 0) { - return CST_geode; } else if (cmp_nocase_uh(string, "tube") == 0) { return CST_tube; } else { @@ -817,6 +813,8 @@ string_collide_flags(const string &string) { return CF_center; } else if (cmp_nocase_uh(string, "turnstile") == 0) { return CF_turnstile; + } else if (cmp_nocase_uh(string, "level") == 0) { + return CF_level; } else { return CF_none; } @@ -1155,10 +1153,6 @@ ostream &operator << (ostream &out, EggGroup::CollisionSolidType t) { return out << "Polyset"; case EggGroup::CST_sphere: return out << "Sphere"; - case EggGroup::CST_inverse_sphere: - return out << "InverseSphere"; - case EggGroup::CST_geode: - return out << "Geode"; case EggGroup::CST_tube: return out << "Tube"; } @@ -1206,5 +1200,9 @@ ostream &operator << (ostream &out, EggGroup::CollideFlags t) { out << space << "turnstile"; space = " "; } + if (bits & EggGroup::CF_level) { + out << space << "level"; + space = " "; + } return out; } diff --git a/panda/src/egg/eggGroup.h b/panda/src/egg/eggGroup.h index c427921cd7..0a962e30d6 100644 --- a/panda/src/egg/eggGroup.h +++ b/panda/src/egg/eggGroup.h @@ -78,9 +78,7 @@ PUBLISHED: CST_polygon = 0x00020000, CST_polyset = 0x00030000, CST_sphere = 0x00040000, - CST_inverse_sphere = 0x00050000, - CST_geode = 0x00060000, - CST_tube = 0x00070000, + CST_tube = 0x00050000, }; enum CollideFlags { // The bits here must correspond to those in Flags, below. @@ -92,6 +90,7 @@ PUBLISHED: CF_solid = 0x00800000, CF_center = 0x01000000, CF_turnstile = 0x02000000, + CF_level = 0x04000000, }; EggGroup(const string &name = ""); @@ -256,7 +255,7 @@ private: F_decal_flag = 0x00002000, F_direct_flag = 0x00004000, F_cs_type = 0x00070000, - F_collide_flags = 0x03f80000, + F_collide_flags = 0x07f80000, }; enum Flags2 { F2_collide_mask = 0x00000001, diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index aeb689e447..5b4b89ddae 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1555,8 +1555,7 @@ make_node(EggGroup *egg_group, PandaNode *parent) { CharacterMaker char_maker(egg_group, *this); node = char_maker.make_node(); - } else if (egg_group->get_cs_type() != EggGroup::CST_none && - egg_group->get_cs_type() != EggGroup::CST_geode) { + } else if (egg_group->get_cs_type() != EggGroup::CST_none) { // A collision group: create collision geometry. node = new CollisionNode(egg_group->get_name()); @@ -1771,18 +1770,9 @@ make_collision_solids(EggGroup *start_group, EggGroup *egg_group, switch (start_group->get_cs_type()) { case EggGroup::CST_none: - case EggGroup::CST_geode: // No collision flags; do nothing. Don't even traverse further. return; - case EggGroup::CST_inverse_sphere: - // These aren't presently supported. - egg2pg_cat.error() - << "Not presently supported: { " - << egg_group->get_cs_type() << " }\n"; - _error = true; - break; - case EggGroup::CST_plane: make_collision_plane(egg_group, cnode, start_group->get_collide_flags()); break; @@ -2159,6 +2149,9 @@ apply_collision_flags(CollisionSolid *solid, if ((flags & EggGroup::CF_intangible) != 0) { solid->set_tangible(false); } + if ((flags & EggGroup::CF_level) != 0) { + solid->set_effective_normal(LVector3f::up()); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 2b33d6d67c..4e54108c84 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -34,13 +34,14 @@ static const unsigned short _bam_major_ver = 4; // Bumped to major version 3 on 12/8/00 to change float64's to float32's. // Bumped to major version 4 on 4/10/02 to store new scene graph. -static const unsigned short _bam_minor_ver = 6; +static const unsigned short _bam_minor_ver = 7; // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse. // Bumped to minor version 2 on 4/12/03 to add num_components to texture. // Bumped to minor version 3 on 4/15/03 to add ImageBuffer::_alpha_file_channel // Bumped to minor version 4 on 6/12/03 to add PandaNode::set_tag(). // Bumped to minor version 5 on 7/09/03 to add rawdata mode to texture. // Bumped to minor version 6 on 7/22/03 to add shear to scene graph and animation data. +// Bumped to minor version 7 on 11/10/03 to add CollisionSolid::_effective_normal #endif