mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 12:43:44 -04:00
345 lines
12 KiB
C++
345 lines
12 KiB
C++
// Filename: collisionNode.cxx
|
|
// Created by: drose (24Apr00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "collisionNode.h"
|
|
#include "config_collide.h"
|
|
|
|
#include <datagram.h>
|
|
#include <datagramIterator.h>
|
|
#include <bamReader.h>
|
|
#include <bamWriter.h>
|
|
|
|
TypeHandle CollisionNode::_type_handle;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CollisionNode::
|
|
CollisionNode(const string &name) :
|
|
NamedNode(name),
|
|
_from_collide_mask(CollideMask::all_on()),
|
|
_into_collide_mask(CollideMask::all_on()),
|
|
_collide_geom(false)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::Copy Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CollisionNode::
|
|
CollisionNode(const CollisionNode ©) :
|
|
NamedNode(copy),
|
|
_from_collide_mask(copy._from_collide_mask),
|
|
_into_collide_mask(copy._into_collide_mask),
|
|
_collide_geom(copy._collide_geom),
|
|
_solids(copy._solids)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::Copy Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
operator = (const CollisionNode ©) {
|
|
NamedNode::operator = (copy);
|
|
_from_collide_mask = copy._from_collide_mask;
|
|
_into_collide_mask = copy._into_collide_mask;
|
|
_collide_geom = copy._collide_geom;
|
|
_solids = copy._solids;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CollisionNode::
|
|
~CollisionNode() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::make_copy
|
|
// Access: Public, Virtual
|
|
// Description: Returns a newly-allocated Node that is a shallow copy
|
|
// of this one. It will be a different Node pointer,
|
|
// but its internal data may or may not be shared with
|
|
// that of the original Node.
|
|
////////////////////////////////////////////////////////////////////
|
|
Node *CollisionNode::
|
|
make_copy() const {
|
|
return new CollisionNode(*this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::xform
|
|
// Access: Public, Virtual
|
|
// Description: Transforms the contents of this node by the indicated
|
|
// matrix, if it means anything to do so. For most
|
|
// kinds of nodes, this does nothing.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
xform(const LMatrix4f &mat) {
|
|
nassertv(!mat.is_nan());
|
|
|
|
if (mat.almost_equal(LMatrix4f::ident_mat())) {
|
|
return;
|
|
}
|
|
|
|
Solids::iterator si;
|
|
for (si = _solids.begin(); si != _solids.end(); ++si) {
|
|
CollisionSolid *solid = (*si);
|
|
|
|
// We may have to copy each of our solids as we transform them if
|
|
// someone else is sharing their pointers.
|
|
if (solid->get_ref_count() > 1) {
|
|
solid = solid->make_copy();
|
|
(*si) = solid;
|
|
}
|
|
|
|
solid->xform(mat);
|
|
}
|
|
mark_bound_stale();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::combine_with
|
|
// Access: Public, Virtual
|
|
// Description: Collapses this node with the other node, if possible,
|
|
// and returns a pointer to the combined node, or NULL
|
|
// if the two nodes cannot safely be combined.
|
|
//
|
|
// The return value may be this, other, or a new node
|
|
// altogether.
|
|
//
|
|
// This function is called from GraphReducer::flatten(),
|
|
// and need not deal with children; its job is just to
|
|
// decide whether to collapse the two nodes and what the
|
|
// collapsed node should look like.
|
|
////////////////////////////////////////////////////////////////////
|
|
Node *CollisionNode::
|
|
combine_with(Node *other) {
|
|
if (is_exact_type(get_class_type()) &&
|
|
other->is_exact_type(get_class_type())) {
|
|
// Two CollisionNodes can combine, but only if they have the same
|
|
// name.
|
|
CollisionNode *cother = DCAST(CollisionNode, other);
|
|
if (get_name() == cother->get_name()) {
|
|
const PT(CollisionSolid) *solids_begin = &cother->_solids[0];
|
|
const PT(CollisionSolid) *solids_end = solids_begin + cother->_solids.size();
|
|
_solids.insert(_solids.end(), solids_begin, solids_end);
|
|
mark_bound_stale();
|
|
return this;
|
|
}
|
|
|
|
// Two CollisionNodes with different names can't combine.
|
|
return (Node *)NULL;
|
|
}
|
|
|
|
return NamedNode::combine_with(other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::preserve_name
|
|
// Access: Public, Virtual
|
|
// Description: Returns true if the node's name has extrinsic meaning
|
|
// and must be preserved across a flatten operation,
|
|
// false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool CollisionNode::
|
|
preserve_name() const {
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::draw_traverse
|
|
// Access: Public, Virtual
|
|
// Description: This is called by the Draw traversal by virtue of the
|
|
// node's being present in the scene graph. Its job is
|
|
// to make sure the visualization of the collideable
|
|
// geometry is up-to-date.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
draw_traverse() {
|
|
Solids::iterator si;
|
|
for (si = _solids.begin(); si != _solids.end(); ++si) {
|
|
(*si)->update_viz(this);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::output
|
|
// Access: Public, Virtual
|
|
// Description: Writes a brief description of the node to the
|
|
// indicated output stream. This is invoked by the <<
|
|
// operator. It may be overridden in derived classes to
|
|
// include some information relevant to the class.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
output(ostream &out) const {
|
|
NamedNode::output(out);
|
|
out << " (" << _solids.size() << " solids)";
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::recompute_bound
|
|
// Access: Protected, Virtual
|
|
// Description: Recomputes the dynamic bounding volume for this node.
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
recompute_bound() {
|
|
// First, get ourselves a fresh, empty bounding volume.
|
|
BoundedObject::recompute_bound();
|
|
nassertv(_bound != (BoundingVolume *)NULL);
|
|
|
|
// Now actually compute the bounding volume by putting it around all
|
|
// of our solids' bounding volumes.
|
|
pvector<const BoundingVolume *> child_volumes;
|
|
|
|
Solids::const_iterator gi;
|
|
for (gi = _solids.begin(); gi != _solids.end(); ++gi) {
|
|
child_volumes.push_back(&(*gi)->get_bound());
|
|
}
|
|
|
|
const BoundingVolume **child_begin = &child_volumes[0];
|
|
const BoundingVolume **child_end = child_begin + child_volumes.size();
|
|
bool success =
|
|
_bound->around(child_begin, child_end);
|
|
|
|
#ifdef NOTIFY_DEBUG
|
|
if (!success) {
|
|
collide_cat.error()
|
|
<< "Unable to generate bounding volume for " << *this << ":\n"
|
|
<< "Cannot put " << _bound->get_type() << " around:\n";
|
|
for (int i = 0; i < (int)child_volumes.size(); i++) {
|
|
collide_cat.error(false)
|
|
<< " " << *child_volumes[i] << "\n";
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::write_datagram
|
|
// Access: Public
|
|
// Description: Function to write the important information in
|
|
// the particular object to a Datagram
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
write_datagram(BamWriter *manager, Datagram &me)
|
|
{
|
|
int i;
|
|
NamedNode::write_datagram(manager, me);
|
|
me.add_uint16(_solids.size());
|
|
|
|
for(i = 0; i < (int)_solids.size(); i++)
|
|
{
|
|
manager->write_pointer(me, _solids[i]);
|
|
}
|
|
|
|
me.add_uint32(_from_collide_mask.get_word());
|
|
me.add_uint32(_into_collide_mask.get_word());
|
|
me.add_bool(_collide_geom);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::fillin
|
|
// Access: Protected
|
|
// Description: Function that reads out of the datagram (or asks
|
|
// manager to read) all of the data that is needed to
|
|
// re-create this object and stores it in the appropiate
|
|
// place
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
fillin(DatagramIterator& scan, BamReader* manager)
|
|
{
|
|
int i;
|
|
NamedNode::fillin(scan, manager);
|
|
int num_solids = scan.get_uint16();
|
|
_solids.clear();
|
|
_solids.reserve(num_solids);
|
|
|
|
for(i = 0; i < num_solids; i++) {
|
|
manager->read_pointer(scan, this);
|
|
_solids.push_back((CollisionSolid *)NULL);
|
|
}
|
|
|
|
_from_collide_mask.set_word(scan.get_uint32());
|
|
_into_collide_mask.set_word(scan.get_uint32());
|
|
_collide_geom = scan.get_bool();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::complete_pointers
|
|
// Access: Public
|
|
// Description: Takes in a vector of pointes to TypedWritable
|
|
// objects that correspond to all the requests for
|
|
// pointers that this object made to BamReader.
|
|
////////////////////////////////////////////////////////////////////
|
|
int CollisionNode::
|
|
complete_pointers(vector_typedWritable &p_list, BamReader* manager) {
|
|
int num_solids = _solids.size();
|
|
int start = NamedNode::complete_pointers(p_list, manager);
|
|
|
|
for (int i = 0; i < num_solids; i++) {
|
|
_solids[i] = DCAST(CollisionSolid, p_list[start + i]);
|
|
}
|
|
|
|
return start + num_solids;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::make_CollisionNode
|
|
// Access: Protected
|
|
// Description: Factory method to generate a CollisionNode object
|
|
////////////////////////////////////////////////////////////////////
|
|
TypedWritable* CollisionNode::
|
|
make_CollisionNode(const FactoryParams ¶ms)
|
|
{
|
|
CollisionNode *me = new CollisionNode;
|
|
DatagramIterator scan;
|
|
BamReader *manager;
|
|
|
|
parse_params(params, scan, manager);
|
|
me->fillin(scan, manager);
|
|
return me;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CollisionNode::register_with_factory
|
|
// Access: Public, Static
|
|
// Description: Factory method to generate a CollisionNode object
|
|
////////////////////////////////////////////////////////////////////
|
|
void CollisionNode::
|
|
register_with_read_factory(void)
|
|
{
|
|
BamReader::get_factory()->register_factory(get_class_type(), make_CollisionNode);
|
|
}
|
|
|
|
|
|
|
|
|