add CollisionSolid::set_effective_normal

This commit is contained in:
David Rose 2003-11-11 05:24:56 +00:00
parent bfd4e276c3
commit 2536db25f4
15 changed files with 176 additions and 100 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
////////////////////////////////////////////////////////////////////

View File

@ -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);
}
////////////////////////////////////////////////////////////////////

View File

@ -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;
}

View File

@ -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 &copy) :
_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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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.

View File

@ -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.
<ObjectType> { type }

View File

@ -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;
}

View File

@ -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,

View File

@ -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: <Collide> { "
<< 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());
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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