optional BoundingBox
This commit is contained in:
parent
2c85e350ee
commit
faad1e333d
|
|
@ -32,6 +32,8 @@
|
|||
#include "bamWriter.h"
|
||||
#include "clockObject.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "config_mathutil.h"
|
||||
|
||||
TypeHandle CollisionNode::_type_handle;
|
||||
|
||||
|
|
@ -309,41 +311,43 @@ set_from_collide_mask(CollideMask mask) {
|
|||
void CollisionNode::
|
||||
compute_internal_bounds(PandaNode::BoundsData *bdata, int pipeline_stage,
|
||||
Thread *current_thread) const {
|
||||
// First, get ourselves a fresh, empty bounding volume.
|
||||
PT(BoundingVolume) bound = new BoundingSphere;
|
||||
|
||||
// Now actually compute the bounding volume by putting it around all
|
||||
// of our solids' bounding volumes.
|
||||
pvector<CPT(BoundingVolume) > child_volumes_ref;
|
||||
pvector<const BoundingVolume *> child_volumes;
|
||||
pvector<CPT(BoundingVolume) > cpt_volumes;
|
||||
bool all_box = true;
|
||||
|
||||
Solids::const_iterator gi;
|
||||
for (gi = _solids.begin(); gi != _solids.end(); ++gi) {
|
||||
CPT(CollisionSolid) solid = (*gi).get_read_pointer();
|
||||
CPT(BoundingVolume) volume = solid->get_bounds();
|
||||
cpt_volumes.push_back(volume);
|
||||
child_volumes.push_back(volume);
|
||||
}
|
||||
|
||||
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";
|
||||
if (!volume->is_empty()) {
|
||||
child_volumes_ref.push_back(volume);
|
||||
child_volumes.push_back(volume);
|
||||
if (!volume->is_exact_type(BoundingBox::get_class_type())) {
|
||||
all_box = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bdata->_internal_bounds = bound;
|
||||
PT(GeometricBoundingVolume) gbv = new BoundingBox;
|
||||
|
||||
if (bounds_type == BoundingVolume::BT_box ||
|
||||
(bounds_type != BoundingVolume::BT_sphere && all_box)) {
|
||||
// If all of the child volumes are a BoundingBox, then our volume
|
||||
// is also a BoundingBox.
|
||||
gbv = new BoundingBox;
|
||||
} else {
|
||||
// Otherwise, it's a sphere.
|
||||
gbv = new BoundingSphere;
|
||||
}
|
||||
|
||||
if (child_volumes.size() > 0) {
|
||||
const BoundingVolume **child_begin = &child_volumes[0];
|
||||
const BoundingVolume **child_end = child_begin + child_volumes.size();
|
||||
((BoundingVolume *)gbv)->around(child_begin, child_end);
|
||||
}
|
||||
|
||||
bdata->_internal_bounds = gbv;
|
||||
bdata->_internal_vertices = 0;
|
||||
bdata->_internal_bounds_stale = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include "collisionSegment.h"
|
||||
#include "config_collide.h"
|
||||
#include "cullTraverserData.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "pointerToArray.h"
|
||||
#include "geomNode.h"
|
||||
#include "geom.h"
|
||||
|
|
@ -386,27 +386,31 @@ write(ostream &out, int indent_level) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
PT(BoundingVolume) CollisionPolygon::
|
||||
compute_internal_bounds() const {
|
||||
// First, get ourselves a fresh, empty bounding volume.
|
||||
PT(BoundingVolume) bound = CollisionSolid::compute_internal_bounds();
|
||||
nassertr(bound != (BoundingVolume*)0L, bound);
|
||||
|
||||
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
|
||||
|
||||
// Now actually compute the bounding volume by putting it around all
|
||||
// of our vertices.
|
||||
LMatrix4f to_3d_mat;
|
||||
rederive_to_3d_mat(to_3d_mat);
|
||||
pvector<LPoint3f> vertices;
|
||||
Points::const_iterator pi;
|
||||
for (pi = _points.begin(); pi != _points.end(); ++pi) {
|
||||
vertices.push_back(to_3d((*pi)._p, to_3d_mat));
|
||||
if (_points.empty()) {
|
||||
return new BoundingBox;
|
||||
}
|
||||
|
||||
const LPoint3f *vertices_begin = &vertices[0];
|
||||
const LPoint3f *vertices_end = vertices_begin + vertices.size();
|
||||
gbv->around(vertices_begin, vertices_end);
|
||||
LMatrix4f to_3d_mat;
|
||||
rederive_to_3d_mat(to_3d_mat);
|
||||
|
||||
return bound;
|
||||
Points::const_iterator pi = _points.begin();
|
||||
LPoint3f p = to_3d((*pi)._p, to_3d_mat);
|
||||
|
||||
LPoint3f x = p;
|
||||
LPoint3f n = p;
|
||||
|
||||
for (++pi; pi != _points.end(); ++pi) {
|
||||
p = to_3d((*pi)._p, to_3d_mat);
|
||||
|
||||
n.set(min(n[0], p[0]),
|
||||
min(n[1], p[1]),
|
||||
min(n[2], p[2]));
|
||||
x.set(max(x[0], p[0]),
|
||||
max(x[1], p[1]),
|
||||
max(x[2], p[2]));
|
||||
}
|
||||
|
||||
return new BoundingBox(n, x);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -450,12 +450,19 @@ center_trackball(const NodePath &object) {
|
|||
// We expect at least a geometric bounding volume around the world.
|
||||
nassertv(volume != (BoundingVolume *)NULL);
|
||||
nassertv(volume->is_of_type(GeometricBoundingVolume::get_class_type()));
|
||||
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, volume);
|
||||
CPT(GeometricBoundingVolume) gbv = DCAST(GeometricBoundingVolume, volume);
|
||||
|
||||
// Determine the bounding sphere around the world. The topmost
|
||||
// BoundingVolume might itself be a sphere (it's likely), but since
|
||||
// it might not, we'll take no chances and make our own sphere.
|
||||
PT(BoundingSphere) sphere = new BoundingSphere;
|
||||
if (object.has_parent()) {
|
||||
CPT(TransformState) net_transform = object.get_parent().get_net_transform();
|
||||
PT(GeometricBoundingVolume) new_gbv = DCAST(GeometricBoundingVolume, gbv->make_copy());
|
||||
new_gbv->xform(net_transform->get_mat());
|
||||
gbv = new_gbv;
|
||||
}
|
||||
|
||||
// Determine the bounding sphere around the object. The
|
||||
// BoundingVolume might be a sphere (it's likely), but since it
|
||||
// might not, we'll take no chances and make our own sphere.
|
||||
PT(BoundingSphere) sphere = new BoundingSphere(gbv->get_approx_center(), 0.0f);
|
||||
if (!sphere->extend_by(gbv)) {
|
||||
framework_cat.warning()
|
||||
<< "Cannot determine bounding volume of " << object << "\n";
|
||||
|
|
@ -497,7 +504,7 @@ center_trackball(const NodePath &object) {
|
|||
distance = radius / ctan(deg_2_rad(min(fov[0], fov[1]) / 2.0f));
|
||||
|
||||
// Ensure the far plane is far enough back to see the entire object.
|
||||
float ideal_far_plane = distance + radius;
|
||||
float ideal_far_plane = distance + radius * 1.5;
|
||||
lens->set_far(max(lens->get_default_far(), ideal_far_plane));
|
||||
|
||||
// And that the near plane is far enough forward.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "mutexHolder.h"
|
||||
#include "config_mathutil.h"
|
||||
|
||||
UpdateSeq Geom::_next_modified;
|
||||
PStatCollector Geom::_draw_primitive_setup_pcollector("Draw:Primitive:Setup");
|
||||
|
|
@ -1074,30 +1076,32 @@ void Geom::
|
|||
compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
||||
int num_vertices = 0;
|
||||
|
||||
// First, get ourselves a fresh, empty bounding volume.
|
||||
PT(BoundingVolume) bound = new BoundingSphere;
|
||||
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
|
||||
|
||||
// Get the vertex data, after animation.
|
||||
CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer();
|
||||
vertex_data = vertex_data->animate_vertices(current_thread);
|
||||
|
||||
// Now actually compute the bounding volume. We do this by using
|
||||
// calc_tight_bounds to determine our minmax first.
|
||||
LPoint3f points[2];
|
||||
// calc_tight_bounds to determine our box first.
|
||||
LPoint3f min, max;
|
||||
bool found_any = false;
|
||||
do_calc_tight_bounds(points[0], points[1], found_any, vertex_data,
|
||||
do_calc_tight_bounds(min, max, found_any, vertex_data,
|
||||
false, LMatrix4f::ident_mat(), cdata, current_thread);
|
||||
|
||||
if (found_any) {
|
||||
// Then we put the bounding volume around both of those points.
|
||||
// Technically, we should put it around the eight points at the
|
||||
// corners of the rectangular solid, but we happen to know that
|
||||
// the two diagonally opposite points is good enough to define any
|
||||
// of our bound volume types.
|
||||
if (bounds_type == BoundingVolume::BT_sphere) {
|
||||
// The user specifically requested a BoundingSphere, so oblige.
|
||||
BoundingBox box(min, max);
|
||||
box.local_object();
|
||||
|
||||
const LPoint3f *points_begin = &points[0];
|
||||
const LPoint3f *points_end = points_begin + 2;
|
||||
gbv->around(points_begin, points_end);
|
||||
PT(BoundingSphere) sphere = new BoundingSphere;
|
||||
sphere->extend_by(&box);
|
||||
cdata->_internal_bounds = sphere;
|
||||
|
||||
} else {
|
||||
// The user requested a BoundingBox, or did not specify.
|
||||
cdata->_internal_bounds = new BoundingBox(min, max);
|
||||
}
|
||||
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = cdata->_primitives.begin();
|
||||
|
|
@ -1106,9 +1110,16 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
||||
num_vertices += prim->get_num_vertices();
|
||||
}
|
||||
|
||||
} else {
|
||||
// No points; empty bounding volume.
|
||||
if (bounds_type == BoundingVolume::BT_sphere) {
|
||||
cdata->_internal_bounds = new BoundingSphere;
|
||||
} else {
|
||||
cdata->_internal_bounds = new BoundingBox;
|
||||
}
|
||||
}
|
||||
|
||||
cdata->_internal_bounds = bound;
|
||||
cdata->_nested_vertices = num_vertices;
|
||||
cdata->_internal_bounds_stale = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@
|
|||
#include "graphicsPipe.h"
|
||||
#include "drawCullHandler.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "geomVertexWriter.h"
|
||||
#include "geomTristrips.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "cullBinManager.h"
|
||||
#include "configVariableInt.h"
|
||||
|
|
@ -115,6 +117,7 @@ PipeOcclusionCullTraverser(GraphicsOutput *host) {
|
|||
_internal_cull_handler = NULL;
|
||||
|
||||
make_sphere();
|
||||
make_box();
|
||||
make_solid_test_state();
|
||||
|
||||
_live = true;
|
||||
|
|
@ -199,8 +202,8 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase) {
|
|||
|
||||
_current_query = NULL;
|
||||
_next_query = NULL;
|
||||
|
||||
make_sphere();
|
||||
|
||||
make_sphere(); // Temporary, so we can experiment with num vertices
|
||||
|
||||
// Begin by rendering all the occluders into our internal scene.
|
||||
PStatTimer timer2(_draw_occlusion_pcollector);
|
||||
|
|
@ -433,7 +436,7 @@ make_sphere() {
|
|||
// static const int num_stacks = 8;
|
||||
|
||||
PT(GeomVertexData) vdata = new GeomVertexData
|
||||
("occlusion", GeomVertexFormat::get_v3(), Geom::UH_static);
|
||||
("occlusion_sphere", GeomVertexFormat::get_v3(), Geom::UH_static);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
|
||||
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
|
||||
|
|
@ -474,6 +477,57 @@ compute_sphere_point(float latitude, float longitude) {
|
|||
return p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipeOcclusionCullTraverser::make_box
|
||||
// Access: Private
|
||||
// Description: Constructs a unit box for testing visibility of
|
||||
// bounding boxes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipeOcclusionCullTraverser::
|
||||
make_box() {
|
||||
PT(GeomVertexData) vdata = new GeomVertexData
|
||||
("occlusion_box", GeomVertexFormat::get_v3(), Geom::UH_static);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
|
||||
vertex.add_data3f(0.0f, 0.0f, 0.0f);
|
||||
vertex.add_data3f(0.0f, 0.0f, 1.0f);
|
||||
vertex.add_data3f(0.0f, 1.0f, 0.0f);
|
||||
vertex.add_data3f(0.0f, 1.0f, 1.0f);
|
||||
vertex.add_data3f(1.0f, 0.0f, 0.0f);
|
||||
vertex.add_data3f(1.0f, 0.0f, 1.0f);
|
||||
vertex.add_data3f(1.0f, 1.0f, 0.0f);
|
||||
vertex.add_data3f(1.0f, 1.0f, 1.0f);
|
||||
|
||||
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
|
||||
tris->add_vertices(0, 4, 5);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(0, 5, 1);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(4, 6, 7);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(4, 7, 5);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(6, 2, 3);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(6, 3, 7);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 0, 1);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 1, 3);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(1, 5, 7);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(1, 7, 3);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 6, 4);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 4, 0);
|
||||
tris->close_primitive();
|
||||
|
||||
_box_geom = new Geom(vdata);
|
||||
_box_geom->add_primitive(tris);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipeOcclusionCullTraverser::make_solid_test_state
|
||||
// Access: Private
|
||||
|
|
@ -514,7 +568,7 @@ get_volume_viz(const BoundingVolume *vol,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (vol->is_of_type(BoundingSphere::get_class_type())) {
|
||||
if (vol->is_exact_type(BoundingSphere::get_class_type())) {
|
||||
const BoundingSphere *sphere = DCAST(BoundingSphere, vol);
|
||||
CPT(TransformState) local_transform =
|
||||
TransformState::make_pos_hpr_scale(sphere->get_center(),
|
||||
|
|
@ -530,14 +584,49 @@ get_volume_viz(const BoundingVolume *vol,
|
|||
// since it's intersecting the near plane.
|
||||
const LPoint3f ¢er = modelview_transform->get_pos();
|
||||
const LVecBase3f &radius = modelview_transform->get_scale();
|
||||
float max_radius = max(max(radius[0], radius[1]), radius[2]);
|
||||
if (center[1] <= max_radius) {
|
||||
if (center[1] - radius[1] < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The sphere looks good.
|
||||
geom = _sphere_geom;
|
||||
return true;
|
||||
|
||||
} else if (vol->is_exact_type(BoundingBox::get_class_type())) {
|
||||
const BoundingBox *box = DCAST(BoundingBox, vol);
|
||||
CPT(TransformState) local_transform =
|
||||
TransformState::make_pos_hpr_scale(box->get_minq(),
|
||||
LVecBase3f(0, 0, 0),
|
||||
box->get_maxq() - box->get_minq());
|
||||
net_transform = net_transform->compose(local_transform);
|
||||
|
||||
modelview_transform = _internal_trav->get_world_transform()->compose(net_transform);
|
||||
|
||||
// See if the bounding box is clipped by the near plane. If it
|
||||
// is, the occlusion test may fail, so we won't bother performing
|
||||
// it for this object. Anyway, it's not occluded by anything,
|
||||
// since it's intersecting the near plane.
|
||||
static const LPoint3f points[8] = {
|
||||
LPoint3f(0.0f, 0.0f, 0.0f),
|
||||
LPoint3f(0.0f, 0.0f, 1.0f),
|
||||
LPoint3f(0.0f, 1.0f, 0.0f),
|
||||
LPoint3f(0.0f, 1.0f, 1.0f),
|
||||
LPoint3f(1.0f, 0.0f, 0.0f),
|
||||
LPoint3f(1.0f, 0.0f, 1.0f),
|
||||
LPoint3f(1.0f, 1.0f, 0.0f),
|
||||
LPoint3f(1.0f, 1.0f, 1.0f),
|
||||
};
|
||||
const LMatrix4f &mat = modelview_transform->get_mat();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
LPoint3f p = points[i] * mat;
|
||||
if (p[1] < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The box looks good.
|
||||
geom = _box_geom;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't have a suitable representation for this bounding volume.
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ protected:
|
|||
private:
|
||||
void make_sphere();
|
||||
static Vertexf compute_sphere_point(float latitude, float longitude);
|
||||
void make_box();
|
||||
|
||||
void make_solid_test_state();
|
||||
|
||||
bool get_volume_viz(const BoundingVolume *vol,
|
||||
|
|
@ -111,6 +113,7 @@ private:
|
|||
PT(OcclusionQueryContext) _next_query;
|
||||
|
||||
PT(Geom) _sphere_geom;
|
||||
PT(Geom) _box_geom;
|
||||
CPT(RenderState) _solid_test_state;
|
||||
|
||||
class PendingObject {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#define SOURCES \
|
||||
boundingHexahedron.I boundingHexahedron.h boundingLine.I \
|
||||
boundingLine.h \
|
||||
boundingBox.I boundingBox.h \
|
||||
boundingPlane.I boundingPlane.h \
|
||||
boundingSphere.I boundingSphere.h \
|
||||
boundingVolume.I boundingVolume.h config_mathutil.h \
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
|
||||
#define INCLUDED_SOURCES \
|
||||
boundingHexahedron.cxx boundingLine.cxx \
|
||||
boundingBox.cxx \
|
||||
boundingPlane.cxx \
|
||||
boundingSphere.cxx \
|
||||
boundingVolume.cxx config_mathutil.cxx fftCompressor.cxx \
|
||||
|
|
@ -59,6 +61,7 @@
|
|||
#define INSTALL_HEADERS \
|
||||
boundingHexahedron.I boundingHexahedron.h boundingLine.I \
|
||||
boundingLine.h \
|
||||
boundingBox.I boundingBox.h \
|
||||
boundingPlane.I boundingPlane.h \
|
||||
boundingSphere.I boundingSphere.h boundingVolume.I \
|
||||
boundingVolume.h config_mathutil.h fftCompressor.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
// Filename: boundingBox.I
|
||||
// Created by: drose (31May07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs an empty box object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingBox::
|
||||
BoundingBox() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs a specific box object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingBox::
|
||||
BoundingBox(const LPoint3f &min, const LPoint3f &max) :
|
||||
_min(min), _max(max)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
_flags = F_empty;
|
||||
nassertv(!_min.is_nan() && !_max.is_nan());
|
||||
nassertv(_min[0] <= _max[0] && _min[1] <= _max[1] && _min[2] <= _max[2]);
|
||||
#endif // NDEBUG
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_minq
|
||||
// Access: Public
|
||||
// Description: An inline accessor for the minimum value. get_min()
|
||||
// would also work, but it is a virtual non-inline
|
||||
// method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL const LPoint3f &BoundingBox::
|
||||
get_minq() const {
|
||||
nassertr(!is_empty(), _min);
|
||||
nassertr(!is_infinite(), _min);
|
||||
return _min;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_maxq
|
||||
// Access: Public
|
||||
// Description: An inline accessor for the maximum value. get_max()
|
||||
// would also work, but it is a virtual non-inline
|
||||
// method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL const LPoint3f &BoundingBox::
|
||||
get_maxq() const {
|
||||
nassertr(!is_empty(), _max);
|
||||
nassertr(!is_infinite(), _max);
|
||||
return _max;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_num_points
|
||||
// Access: Published
|
||||
// Description: Returns 8: the number of vertices of a rectangular solid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL int BoundingBox::
|
||||
get_num_points() const {
|
||||
return 8;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_point
|
||||
// Access: Published
|
||||
// Description: Returns the nth vertex of the rectangular solid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL LPoint3f BoundingBox::
|
||||
get_point(int n) const {
|
||||
nassertr(n >= 0 && n < 8, LPoint3f::zero());
|
||||
|
||||
// We do some trickery assuming that _min and _max are consecutive
|
||||
// in memory.
|
||||
const LPoint3f *a = &_min;
|
||||
return LPoint3f(a[(n>>2)&1][0], a[(n>>1)&1][1], a[(n)&1][2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_num_planes
|
||||
// Access: Published
|
||||
// Description: Returns 6: the number of faces of a rectangular solid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL int BoundingBox::
|
||||
get_num_planes() const {
|
||||
return 6;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_plane
|
||||
// Access: Published
|
||||
// Description: Returns the nth face of the rectangular solid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL Planef BoundingBox::
|
||||
get_plane(int n) const {
|
||||
nassertr(n >= 0 && n < 6, Planef());
|
||||
return Planef(get_point(plane_def[n][0]),
|
||||
get_point(plane_def[n][1]),
|
||||
get_point(plane_def[n][2]));
|
||||
}
|
||||
|
|
@ -0,0 +1,643 @@
|
|||
// Filename: boundingBox.cxx
|
||||
// Created by: drose (31May07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "boundingBox.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingHexahedron.h"
|
||||
#include "boundingLine.h"
|
||||
#include "boundingPlane.h"
|
||||
#include "config_mathutil.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
const int BoundingBox::plane_def[6][3] = {
|
||||
{ 0, 4, 5 },
|
||||
{ 4, 6, 7 },
|
||||
{ 6, 2, 3 },
|
||||
{ 2, 0, 1 },
|
||||
{ 1, 5, 7 },
|
||||
{ 2, 6, 4 },
|
||||
};
|
||||
|
||||
TypeHandle BoundingBox::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingVolume *BoundingBox::
|
||||
make_copy() const {
|
||||
return new BoundingBox(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_min
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingBox::
|
||||
get_min() const {
|
||||
nassertr(!is_empty(), _min);
|
||||
nassertr(!is_infinite(), _min);
|
||||
return _min;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_max
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingBox::
|
||||
get_max() const {
|
||||
nassertr(!is_empty(), _max);
|
||||
nassertr(!is_infinite(), _max);
|
||||
return _max;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_volume
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float BoundingBox::
|
||||
get_volume() const {
|
||||
nassertr(!is_infinite(), 0.0f);
|
||||
if (is_empty()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Volume of a box: width x depth x height
|
||||
return (_max[0] - _min[0]) * (_max[1] - _min[1]) * (_max[2] - _min[2]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::get_approx_center
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingBox::
|
||||
get_approx_center() const {
|
||||
nassertr(!is_empty(), LPoint3f::zero());
|
||||
nassertr(!is_infinite(), LPoint3f::zero());
|
||||
return (_min + _max) * 0.5f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::xform
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingBox::
|
||||
xform(const LMatrix4f &mat) {
|
||||
nassertv(!mat.is_nan());
|
||||
|
||||
if (!is_empty() && !is_infinite()) {
|
||||
// We need to transform the eight corners of the cube, and then
|
||||
// determine the new box.
|
||||
LPoint3f x = get_point(0) * mat;
|
||||
LPoint3f n = x;
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
LPoint3f p = get_point(i) * mat;
|
||||
n.set(min(n[0], p[0]), min(n[1], p[1]), min(n[2], p[2]));
|
||||
x.set(max(x[0], p[0]), max(x[1], p[1]), max(x[2], p[2]));
|
||||
}
|
||||
_max = x;
|
||||
_min = n;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingBox::
|
||||
output(ostream &out) const {
|
||||
if (is_empty()) {
|
||||
out << "bbox, empty";
|
||||
} else if (is_infinite()) {
|
||||
out << "bbox, infinite";
|
||||
} else {
|
||||
out << "bbox, (" << _min << ") to (" << _max << ")";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::extend_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
extend_other(BoundingVolume *other) const {
|
||||
return other->extend_by_box(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::around_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
around_other(BoundingVolume *other,
|
||||
const BoundingVolume **first,
|
||||
const BoundingVolume **last) const {
|
||||
return other->around_boxes(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_other(const BoundingVolume *other) const {
|
||||
return other->contains_box(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::extend_by_point
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
extend_by_point(const LPoint3f &point) {
|
||||
nassertr(!point.is_nan(), false);
|
||||
|
||||
if (is_empty()) {
|
||||
_min = point;
|
||||
_max = point;
|
||||
_flags = 0;
|
||||
|
||||
} else if (!is_infinite()) {
|
||||
_min.set(min(_min[0], point[0]), min(_min[1], point[1]), min(_min[2], point[2]));
|
||||
_max.set(max(_max[0], point[0]), max(_max[1], point[1]), max(_max[2], point[2]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::extend_by_sphere
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
extend_by_sphere(const BoundingSphere *sphere) {
|
||||
return extend_by_finite(sphere);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::extend_by_box
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
extend_by_box(const BoundingBox *box) {
|
||||
nassertr(!box->is_empty() && !box->is_infinite(), false);
|
||||
nassertr(!is_infinite(), false);
|
||||
|
||||
if (is_empty()) {
|
||||
_min = box->_min;
|
||||
_max = box->_max;
|
||||
_flags = 0;
|
||||
|
||||
} else {
|
||||
_min.set(min(_min[0], box->_min[0]),
|
||||
min(_min[1], box->_min[1]),
|
||||
min(_min[2], box->_min[2]));
|
||||
_max.set(max(_max[0], box->_max[0]),
|
||||
max(_max[1], box->_max[1]),
|
||||
max(_max[2], box->_max[2]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::extend_by_hexahedron
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
|
||||
return extend_by_finite(hexahedron);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::extend_by_finite
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
extend_by_finite(const FiniteBoundingVolume *volume) {
|
||||
nassertr(!volume->is_empty(), false);
|
||||
|
||||
LVector3f min1 = volume->get_min();
|
||||
LVector3f max1 = volume->get_max();
|
||||
|
||||
if (is_empty()) {
|
||||
_min = min1;
|
||||
_max = max1;
|
||||
_flags = 0;
|
||||
|
||||
} else {
|
||||
_min.set(min(_min[0], min1[0]),
|
||||
min(_min[1], min1[1]),
|
||||
min(_min[2], min1[2]));
|
||||
_max.set(max(_max[0], max1[0]),
|
||||
max(_max[1], max1[1]),
|
||||
max(_max[2], max1[2]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::around_points
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
around_points(const LPoint3f *first, const LPoint3f *last) {
|
||||
nassertr(first != last, false);
|
||||
|
||||
// Get the minmax of all the points to construct a bounding box.
|
||||
const LPoint3f *p = first;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Skip any NaN points.
|
||||
int skipped_nan = 0;
|
||||
while (p != last && (*p).is_nan()) {
|
||||
++p;
|
||||
++skipped_nan;
|
||||
}
|
||||
if (p == last) {
|
||||
mathutil_cat.warning()
|
||||
<< "BoundingBox around NaN\n";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
_min = *p;
|
||||
_max = *p;
|
||||
++p;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Skip more NaN points.
|
||||
while (p != last && (*p).is_nan()) {
|
||||
++p;
|
||||
++skipped_nan;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (p != last) {
|
||||
#ifndef NDEBUG
|
||||
// Skip more NaN points.
|
||||
if ((*p).is_nan()) {
|
||||
++skipped_nan;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_min.set(min(_min[0], (*p)[0]),
|
||||
min(_min[1], (*p)[1]),
|
||||
min(_min[2], (*p)[2]));
|
||||
_max.set(max(_max[0], (*p)[0]),
|
||||
max(_max[1], (*p)[1]),
|
||||
max(_max[2], (*p)[2]));
|
||||
}
|
||||
++p;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (skipped_nan != 0) {
|
||||
mathutil_cat.warning()
|
||||
<< "BoundingBox ignored " << skipped_nan << " NaN points of "
|
||||
<< (last - first) << " total.\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
_flags = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::around_spheres
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
return around_finite(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::around_boxes
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
around_boxes(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
return around_finite(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::around_hexahedrons
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
return around_finite(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::around_finite
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingBox::
|
||||
around_finite(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
nassertr(first != last, false);
|
||||
|
||||
// We're given a set of bounding volumes, at least the first one of
|
||||
// which is guaranteed to be finite and nonempty. Some others may
|
||||
// not be.
|
||||
|
||||
// First, get the box of all the points to construct a bounding
|
||||
// box.
|
||||
const BoundingVolume **p = first;
|
||||
nassertr(!(*p)->is_empty() && !(*p)->is_infinite(), false);
|
||||
const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p);
|
||||
_min = vol->get_min();
|
||||
_max = vol->get_max();
|
||||
|
||||
for (++p; p != last; ++p) {
|
||||
nassertr(!(*p)->is_infinite(), false);
|
||||
if (!(*p)->is_empty()) {
|
||||
const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p);
|
||||
LPoint3f min1 = vol->get_min();
|
||||
LPoint3f max1 = vol->get_max();
|
||||
_min.set(min(_min[0], min1[0]),
|
||||
min(_min[1], min1[1]),
|
||||
min(_min[2], min1[2]));
|
||||
_max.set(max(_max[0], max1[0]),
|
||||
max(_max[1], max1[1]),
|
||||
max(_max[2], max1[2]));
|
||||
}
|
||||
}
|
||||
|
||||
_flags = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_point
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_point(const LPoint3f &point) const {
|
||||
nassertr(!point.is_nan(), IF_no_intersection);
|
||||
|
||||
if (is_empty()) {
|
||||
return IF_no_intersection;
|
||||
|
||||
} else if (is_infinite()) {
|
||||
return IF_possible | IF_some | IF_all;
|
||||
|
||||
} else {
|
||||
if (point[0] >= _min[0] && point[0] <= _max[0] &&
|
||||
point[1] >= _min[1] && point[1] <= _max[1] &&
|
||||
point[2] >= _min[2] && point[2] <= _max[2]) {
|
||||
return IF_possible | IF_some | IF_all;
|
||||
} else {
|
||||
return IF_no_intersection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_lineseg
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
|
||||
nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection);
|
||||
|
||||
if (a == b) {
|
||||
return contains_point(a);
|
||||
}
|
||||
if (is_empty()) {
|
||||
return IF_no_intersection;
|
||||
|
||||
} else if (is_infinite()) {
|
||||
return IF_possible | IF_some | IF_all;
|
||||
|
||||
} else {
|
||||
// Set a bit for each plane a and b are on the wrong side of.
|
||||
unsigned int a_bits = 0;
|
||||
|
||||
if (a[0] < _min[0]) {
|
||||
a_bits |= 0x01;
|
||||
} else if (a[0] > _max[0]) {
|
||||
a_bits |= 0x02;
|
||||
}
|
||||
|
||||
if (a[1] < _min[1]) {
|
||||
a_bits |= 0x04;
|
||||
} else if (a[1] > _max[1]) {
|
||||
a_bits |= 0x08;
|
||||
}
|
||||
|
||||
if (a[2] < _min[2]) {
|
||||
a_bits |= 0x10;
|
||||
} else if (a[2] > _max[2]) {
|
||||
a_bits |= 0x20;
|
||||
}
|
||||
|
||||
unsigned int b_bits = 0;
|
||||
|
||||
if (b[0] < _min[0]) {
|
||||
b_bits |= 0x01;
|
||||
} else if (b[0] > _max[0]) {
|
||||
b_bits |= 0x02;
|
||||
}
|
||||
|
||||
if (b[1] < _min[1]) {
|
||||
b_bits |= 0x04;
|
||||
} else if (b[1] > _max[1]) {
|
||||
b_bits |= 0x08;
|
||||
}
|
||||
|
||||
if (b[2] < _min[2]) {
|
||||
b_bits |= 0x10;
|
||||
} else if (b[2] > _max[2]) {
|
||||
b_bits |= 0x20;
|
||||
}
|
||||
|
||||
if ((a_bits & b_bits) != 0) {
|
||||
// If there are any bits in common, the segment is wholly
|
||||
// outside the box (both points are on the wrong side of the
|
||||
// same plane).
|
||||
return IF_no_intersection;
|
||||
|
||||
} else if ((a_bits | b_bits) == 0) {
|
||||
// If there are no bits at all, the segment is wholly within the
|
||||
// box.
|
||||
return IF_possible | IF_some | IF_all;
|
||||
|
||||
} else if (a_bits == 0 || b_bits == 0) {
|
||||
// If either point is within the box, the segment is partially
|
||||
// within the box.
|
||||
return IF_possible | IF_some;
|
||||
|
||||
} else {
|
||||
unsigned int differ = (a_bits ^ b_bits);
|
||||
if (differ == 0x03 || differ == 0x0c || differ == 0x30) {
|
||||
// If the line segment stretches straight across the box, the
|
||||
// segment is partially within.
|
||||
return IF_possible | IF_some;
|
||||
|
||||
} else {
|
||||
// Otherwise, it's hard to tell whether it does or doesn't.
|
||||
return IF_possible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_sphere
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a sphere.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_sphere(const BoundingSphere *sphere) const {
|
||||
return contains_finite(sphere);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_box
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a box.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_box(const BoundingBox *box) const {
|
||||
nassertr(!is_empty() && !is_infinite(), 0);
|
||||
nassertr(!box->is_empty() && !box->is_infinite(), 0);
|
||||
|
||||
const LPoint3f &min1 = box->get_minq();
|
||||
const LPoint3f &max1 = box->get_maxq();
|
||||
|
||||
if (min1[0] >= _min[0] && max1[0] <= _max[0] &&
|
||||
min1[1] >= _min[1] && max1[1] <= _max[1] &&
|
||||
min1[2] >= _min[2] && max1[2] <= _max[2]) {
|
||||
// The other volume is completely within this volume.
|
||||
return IF_possible | IF_some | IF_all;
|
||||
|
||||
} else if (max1[0] >= _min[0] && min1[0] <= _max[0] &&
|
||||
max1[1] >= _min[1] && min1[1] <= _max[1] &&
|
||||
max1[2] >= _min[2] && min1[2] <= _max[2]) {
|
||||
// The other volume is partially within this volume.
|
||||
return IF_possible;
|
||||
|
||||
} else {
|
||||
// The other volume is not within this volume.
|
||||
return IF_no_intersection;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_hexahedron
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a hexahedron.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_hexahedron(const BoundingHexahedron *hexahedron) const {
|
||||
return contains_finite(hexahedron);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_line
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a line.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_line(const BoundingLine *line) const {
|
||||
return line->contains_box(this) & ~IF_all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_plane
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a plane.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_plane(const BoundingPlane *plane) const {
|
||||
return plane->contains_box(this) & ~IF_all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingBox::contains_finite
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingBox::
|
||||
contains_finite(const FiniteBoundingVolume *volume) const {
|
||||
nassertr(!is_empty() && !is_infinite(), 0);
|
||||
nassertr(!volume->is_empty() && !volume->is_infinite(), 0);
|
||||
|
||||
LPoint3f min1 = volume->get_min();
|
||||
LPoint3f max1 = volume->get_max();
|
||||
|
||||
if (min1[0] >= _min[0] && max1[0] <= _max[0] &&
|
||||
min1[1] >= _min[1] && max1[1] <= _max[1] &&
|
||||
min1[2] >= _min[2] && max1[2] <= _max[2]) {
|
||||
// The other volume is completely within this volume.
|
||||
return IF_possible | IF_some | IF_all;
|
||||
|
||||
} else if (max1[0] >= _min[0] && min1[0] <= _max[0] &&
|
||||
max1[1] >= _min[1] && min1[1] <= _max[1] &&
|
||||
max1[2] >= _min[2] && min1[2] <= _max[2]) {
|
||||
// The other volume is partially within this volume.
|
||||
return IF_possible;
|
||||
|
||||
} else {
|
||||
// The other volume is not within this volume.
|
||||
return IF_no_intersection;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Filename: boundingBox.h
|
||||
// Created by: drose (31May07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOUNDINGBOX_H
|
||||
#define BOUNDINGBOX_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "finiteBoundingVolume.h"
|
||||
#include "plane.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : BoundingBox
|
||||
// Description : An axis-aligned bounding box; that is, a minimum and
|
||||
// maximum coordinate triple.
|
||||
//
|
||||
// This box is always axis-aligned. If you need a more
|
||||
// general bounding box, try BoundingHexahedron.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA BoundingBox : public FiniteBoundingVolume {
|
||||
PUBLISHED:
|
||||
INLINE_MATHUTIL BoundingBox();
|
||||
INLINE_MATHUTIL BoundingBox(const LPoint3f &min, const LPoint3f &max);
|
||||
ALLOC_DELETED_CHAIN(BoundingBox);
|
||||
|
||||
public:
|
||||
virtual BoundingVolume *make_copy() const;
|
||||
|
||||
virtual LPoint3f get_min() const;
|
||||
virtual LPoint3f get_max() const;
|
||||
virtual float get_volume() const;
|
||||
|
||||
virtual LPoint3f get_approx_center() const;
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE_MATHUTIL int get_num_points() const;
|
||||
INLINE_MATHUTIL LPoint3f get_point(int n) const;
|
||||
INLINE_MATHUTIL int get_num_planes() const;
|
||||
INLINE_MATHUTIL Planef get_plane(int n) const;
|
||||
|
||||
public:
|
||||
// Inline accessors for speed.
|
||||
INLINE_MATHUTIL const LPoint3f &get_minq() const;
|
||||
INLINE_MATHUTIL const LPoint3f &get_maxq() const;
|
||||
|
||||
protected:
|
||||
virtual bool extend_other(BoundingVolume *other) const;
|
||||
virtual bool around_other(BoundingVolume *other,
|
||||
const BoundingVolume **first,
|
||||
const BoundingVolume **last) const;
|
||||
virtual int contains_other(const BoundingVolume *other) const;
|
||||
|
||||
|
||||
virtual bool extend_by_point(const LPoint3f &point);
|
||||
virtual bool extend_by_sphere(const BoundingSphere *sphere);
|
||||
virtual bool extend_by_box(const BoundingBox *box);
|
||||
virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron);
|
||||
bool extend_by_finite(const FiniteBoundingVolume *volume);
|
||||
|
||||
virtual bool around_points(const LPoint3f *first,
|
||||
const LPoint3f *last);
|
||||
virtual bool around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_boxes(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
bool around_finite(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
|
||||
virtual int contains_point(const LPoint3f &point) const;
|
||||
virtual int contains_lineseg(const LPoint3f &a, const LPoint3f &b) const;
|
||||
virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const;
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
virtual int contains_line(const BoundingLine *line) const;
|
||||
virtual int contains_plane(const BoundingPlane *plane) const;
|
||||
int contains_finite(const FiniteBoundingVolume *volume) const;
|
||||
|
||||
private:
|
||||
LPoint3f _min;
|
||||
LPoint3f _max;
|
||||
|
||||
static const int plane_def[6][3];
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
FiniteBoundingVolume::init_type();
|
||||
register_type(_type_handle, "BoundingBox",
|
||||
FiniteBoundingVolume::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class BoundingSphere;
|
||||
};
|
||||
|
||||
#include "boundingBox.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -16,26 +16,52 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingHexahedron::
|
||||
BoundingHexahedron() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_num_points
|
||||
// Access: Published
|
||||
// Description: Returns 8: the number of vertices of a hexahedron.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL int BoundingHexahedron::
|
||||
get_num_points() const {
|
||||
return num_points;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_point
|
||||
// Access: Published
|
||||
// Description: Returns the nth vertex of the hexahedron.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL LPoint3f BoundingHexahedron::
|
||||
get_point(int n) const {
|
||||
nassertr(n >= 0 && n < num_points, LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
nassertr(n >= 0 && n < num_points, LPoint3f::zero());
|
||||
return _points[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_num_planes
|
||||
// Access: Published
|
||||
// Description: Returns 6: the number of faces of a hexahedron.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL int BoundingHexahedron::
|
||||
get_num_planes() const {
|
||||
return num_planes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_plane
|
||||
// Access: Published
|
||||
// Description: Returns the nth face of the hexahedron.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL Planef BoundingHexahedron::
|
||||
get_plane(int n) const {
|
||||
nassertr(n >= 0 && n < num_planes, Planef());
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "boundingHexahedron.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "config_mathutil.h"
|
||||
|
||||
#include <math.h>
|
||||
|
|
@ -25,6 +26,11 @@
|
|||
|
||||
TypeHandle BoundingHexahedron::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingHexahedron::
|
||||
BoundingHexahedron(const Frustumf &frustum, bool is_ortho,
|
||||
CoordinateSystem cs) {
|
||||
|
|
@ -60,6 +66,11 @@ BoundingHexahedron(const Frustumf &frustum, bool is_ortho,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingHexahedron::
|
||||
BoundingHexahedron(const LPoint3f &fll, const LPoint3f &flr,
|
||||
const LPoint3f &fur, const LPoint3f &ful,
|
||||
|
|
@ -79,11 +90,21 @@ BoundingHexahedron(const LPoint3f &fll, const LPoint3f &flr,
|
|||
set_planes();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingVolume *BoundingHexahedron::
|
||||
make_copy() const {
|
||||
return new BoundingHexahedron(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_min
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingHexahedron::
|
||||
get_min() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -98,6 +119,11 @@ get_min() const {
|
|||
return m;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_max
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingHexahedron::
|
||||
get_max() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -112,6 +138,11 @@ get_max() const {
|
|||
return m;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::get_approx_center
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingHexahedron::
|
||||
get_approx_center() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -119,6 +150,11 @@ get_approx_center() const {
|
|||
return _centroid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::xform
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingHexahedron::
|
||||
xform(const LMatrix4f &mat) {
|
||||
if (!is_empty() && !is_infinite()) {
|
||||
|
|
@ -130,6 +166,11 @@ xform(const LMatrix4f &mat) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingHexahedron::
|
||||
output(ostream &out) const {
|
||||
if (is_empty()) {
|
||||
|
|
@ -141,6 +182,11 @@ output(ostream &out) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingHexahedron::
|
||||
write(ostream &out, int indent_level) const {
|
||||
if (is_empty()) {
|
||||
|
|
@ -158,11 +204,21 @@ write(ostream &out, int indent_level) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::extend_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingHexahedron::
|
||||
extend_other(BoundingVolume *other) const {
|
||||
return other->extend_by_hexahedron(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::around_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingHexahedron::
|
||||
around_other(BoundingVolume *other,
|
||||
const BoundingVolume **first,
|
||||
|
|
@ -170,56 +226,21 @@ around_other(BoundingVolume *other,
|
|||
return other->around_hexahedrons(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::contains_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingHexahedron::
|
||||
contains_other(const BoundingVolume *other) const {
|
||||
return other->contains_hexahedron(this);
|
||||
}
|
||||
|
||||
|
||||
bool BoundingHexahedron::
|
||||
extend_by_point(const LPoint3f &) {
|
||||
mathutil_cat.error()
|
||||
<< "BoundingHexahedron::extend_by_point() called\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BoundingHexahedron::
|
||||
extend_by_sphere(const BoundingSphere *) {
|
||||
mathutil_cat.error()
|
||||
<< "BoundingHexahedron::extend_by_sphere() called\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BoundingHexahedron::
|
||||
extend_by_hexahedron(const BoundingHexahedron *) {
|
||||
mathutil_cat.error()
|
||||
<< "BoundingHexahedron::extend_by_hexahedron() called\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BoundingHexahedron::
|
||||
around_points(const LPoint3f *, const LPoint3f *) {
|
||||
mathutil_cat.error()
|
||||
<< "BoundingHexahedron::around_points() called\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BoundingHexahedron::
|
||||
around_spheres(const BoundingVolume **,
|
||||
const BoundingVolume **) {
|
||||
mathutil_cat.error()
|
||||
<< "BoundingHexahedron::around_spheres() called\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BoundingHexahedron::
|
||||
around_hexahedrons(const BoundingVolume **,
|
||||
const BoundingVolume **) {
|
||||
mathutil_cat.error()
|
||||
<< "BoundingHexahedron::around_hexahedrons() called\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::contains_point
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingHexahedron::
|
||||
contains_point(const LPoint3f &point) const {
|
||||
if (is_empty()) {
|
||||
|
|
@ -241,6 +262,11 @@ contains_point(const LPoint3f &point) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::contains_lineseg
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingHexahedron::
|
||||
contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
|
||||
if (is_empty()) {
|
||||
|
|
@ -267,6 +293,11 @@ contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::contains_sphere
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingHexahedron::
|
||||
contains_sphere(const BoundingSphere *sphere) const {
|
||||
nassertr(!is_empty(), 0);
|
||||
|
|
@ -297,37 +328,111 @@ contains_sphere(const BoundingSphere *sphere) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::contains_box
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingHexahedron::
|
||||
contains_hexahedron(const BoundingHexahedron *hexahedron) const {
|
||||
contains_box(const BoundingBox *box) const {
|
||||
nassertr(!is_empty(), 0);
|
||||
nassertr(!hexahedron->is_empty(), 0);
|
||||
nassertr(!box->is_empty(), 0);
|
||||
|
||||
// Check minmax.
|
||||
LPoint3f min1 = get_min();
|
||||
LPoint3f min2 = hexahedron->get_min();
|
||||
LPoint3f max1 = get_max();
|
||||
LPoint3f max2 = hexahedron->get_max();
|
||||
// Put the box inside a sphere for the purpose of this test.
|
||||
const LPoint3f &min = box->get_minq();
|
||||
const LPoint3f &max = box->get_maxq();
|
||||
LPoint3f center = (min + max) * 0.5f;
|
||||
float radius2 = (max - center).length_squared();
|
||||
|
||||
if (min1[0] > max2[0] || min1[1] > max2[1] || min1[2] > max2[2] ||
|
||||
min2[0] > max1[0] || min2[1] > max1[1] || min2[2] > max1[2] ||
|
||||
max1[0] < min2[0] || max1[1] < min2[1] || max1[2] < min2[2] ||
|
||||
max2[0] < min1[0] || max2[1] < min1[1] || max2[2] < min1[2]) {
|
||||
return IF_no_intersection;
|
||||
}
|
||||
int result = IF_possible | IF_some | IF_all;
|
||||
|
||||
int result = IF_possible | IF_all;
|
||||
for (int i = 0; i < num_planes; i++) {
|
||||
const Planef &p = _planes[i];
|
||||
float dist = p.dist_to_plane(center);
|
||||
float dist2 = dist * dist;
|
||||
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
if (contains_point(hexahedron->_points[i])) {
|
||||
result |= IF_some;
|
||||
} else {
|
||||
result &= ~IF_all;
|
||||
if (dist >= 0.0f && dist2 > radius2) {
|
||||
// The sphere is completely in front of this plane; it's thus
|
||||
// completely outside of the hexahedron.
|
||||
return IF_no_intersection;
|
||||
|
||||
} else if (dist < 0.0f && dist2 < radius2) {
|
||||
// The sphere is not completely behind this plane, but some of
|
||||
// it is.
|
||||
|
||||
// Look a little closer.
|
||||
bool all_in = true;
|
||||
for (int i = 0; i < 8 && all_in; ++i) {
|
||||
if (p.dist_to_plane(box->get_point(i)) < 0.0f) {
|
||||
// This point is outside the plane.
|
||||
all_in = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_in) {
|
||||
result &= ~IF_all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::contains_hexahedron
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingHexahedron::
|
||||
contains_hexahedron(const BoundingHexahedron *hexahedron) const {
|
||||
nassertr(!is_empty(), 0);
|
||||
nassertr(!hexahedron->is_empty(), 0);
|
||||
|
||||
// Put the hexahedron inside a sphere for the purposes of this test.
|
||||
LPoint3f min = hexahedron->get_min();
|
||||
LPoint3f max = hexahedron->get_max();
|
||||
LPoint3f center = (min + max) * 0.5f;
|
||||
float radius2 = (max - center).length_squared();
|
||||
|
||||
int result = IF_possible | IF_some | IF_all;
|
||||
|
||||
for (int i = 0; i < num_planes; i++) {
|
||||
const Planef &p = _planes[i];
|
||||
float dist = p.dist_to_plane(center);
|
||||
float dist2 = dist * dist;
|
||||
|
||||
if (dist >= 0.0f && dist2 > radius2) {
|
||||
// The sphere is completely in front of this plane; it's thus
|
||||
// completely outside of the hexahedron.
|
||||
return IF_no_intersection;
|
||||
|
||||
} else if (dist < 0.0f && dist2 < radius2) {
|
||||
// The sphere is not completely behind this plane, but some of
|
||||
// it is.
|
||||
|
||||
// Look a little closer.
|
||||
bool all_in = true;
|
||||
for (int i = 0; i < 8 && all_in; ++i) {
|
||||
if (p.dist_to_plane(hexahedron->get_point(i)) < 0.0f) {
|
||||
// This point is outside the plane.
|
||||
all_in = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_in) {
|
||||
result &= ~IF_all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::set_planes
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingHexahedron::
|
||||
set_planes() {
|
||||
_planes[0] = Planef(_points[0], _points[3], _points[2]);
|
||||
|
|
@ -358,6 +463,11 @@ set_planes() {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingHexahedron::set_centroid
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingHexahedron::
|
||||
set_centroid() {
|
||||
LPoint3f net = _points[0];
|
||||
|
|
|
|||
|
|
@ -32,21 +32,24 @@
|
|||
// Class : BoundingHexahedron
|
||||
// Description : This defines a bounding convex hexahedron. It is
|
||||
// typically used to represent a frustum, but may
|
||||
// represent any enclosing convex hexahedron.
|
||||
//
|
||||
// This class does not support any of the around() or
|
||||
// extend_by() functions, but all other functionality
|
||||
// should be well-defined.
|
||||
// represent any enclosing convex hexahedron, including
|
||||
// simple boxes. However, if all you want is an
|
||||
// axis-aligned bounding box, you may be better off with
|
||||
// the simpler BoundingBox class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA BoundingHexahedron : public FiniteBoundingVolume {
|
||||
public:
|
||||
INLINE_MATHUTIL BoundingHexahedron();
|
||||
|
||||
PUBLISHED:
|
||||
BoundingHexahedron(const Frustumf &frustum, bool is_ortho,
|
||||
CoordinateSystem cs = CS_default);
|
||||
BoundingHexahedron(const LPoint3f &fll, const LPoint3f &flr,
|
||||
const LPoint3f &fur, const LPoint3f &ful,
|
||||
const LPoint3f &nll, const LPoint3f &nlr,
|
||||
const LPoint3f &nur, const LPoint3f &nul);
|
||||
|
||||
public:
|
||||
ALLOC_DELETED_CHAIN(BoundingHexahedron);
|
||||
virtual BoundingVolume *make_copy() const;
|
||||
|
||||
|
|
@ -59,6 +62,7 @@ public:
|
|||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE_MATHUTIL int get_num_points() const;
|
||||
INLINE_MATHUTIL LPoint3f get_point(int n) const;
|
||||
INLINE_MATHUTIL int get_num_planes() const;
|
||||
|
|
@ -71,21 +75,10 @@ protected:
|
|||
const BoundingVolume **last) const;
|
||||
virtual int contains_other(const BoundingVolume *other) const;
|
||||
|
||||
|
||||
virtual bool extend_by_point(const LPoint3f &point);
|
||||
virtual bool extend_by_sphere(const BoundingSphere *sphere);
|
||||
virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron);
|
||||
|
||||
virtual bool around_points(const LPoint3f *first,
|
||||
const LPoint3f *last);
|
||||
virtual bool around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
|
||||
virtual int contains_point(const LPoint3f &point) const;
|
||||
virtual int contains_lineseg(const LPoint3f &a, const LPoint3f &b) const;
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -16,10 +16,21 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingLine::
|
||||
BoundingLine() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingLine::
|
||||
BoundingLine(const LPoint3f &a, const LPoint3f &b) :
|
||||
_origin(a), _vector(b - a)
|
||||
|
|
@ -31,6 +42,11 @@ BoundingLine(const LPoint3f &a, const LPoint3f &b) :
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::get_point_a
|
||||
// Access: Published
|
||||
// Description: Returns the first point that defines the line.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL const LPoint3f &BoundingLine::
|
||||
get_point_a() const {
|
||||
nassertr(!is_empty(), _origin);
|
||||
|
|
@ -38,6 +54,11 @@ get_point_a() const {
|
|||
return _origin;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::get_point_b
|
||||
// Access: Published
|
||||
// Description: Returns the second point that defines the line.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL LPoint3f BoundingLine::
|
||||
get_point_b() const {
|
||||
nassertr(!is_empty(), _origin);
|
||||
|
|
|
|||
|
|
@ -24,11 +24,21 @@
|
|||
|
||||
TypeHandle BoundingLine::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingVolume *BoundingLine::
|
||||
make_copy() const {
|
||||
return new BoundingLine(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::get_approx_center
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingLine::
|
||||
get_approx_center() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -36,6 +46,11 @@ get_approx_center() const {
|
|||
return (get_point_a() + get_point_b()) / 2.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::xform
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingLine::
|
||||
xform(const LMatrix4f &mat) {
|
||||
nassertv(!mat.is_nan());
|
||||
|
|
@ -51,6 +66,11 @@ xform(const LMatrix4f &mat) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingLine::
|
||||
output(ostream &out) const {
|
||||
if (is_empty()) {
|
||||
|
|
@ -62,11 +82,21 @@ output(ostream &out) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::extend_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingLine::
|
||||
extend_other(BoundingVolume *other) const {
|
||||
return other->extend_by_line(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::around_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingLine::
|
||||
around_other(BoundingVolume *other,
|
||||
const BoundingVolume **first,
|
||||
|
|
@ -74,12 +104,21 @@ around_other(BoundingVolume *other,
|
|||
return other->around_lines(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::contains_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingLine::
|
||||
contains_other(const BoundingVolume *other) const {
|
||||
return other->contains_line(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::extend_by_line
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingLine::
|
||||
extend_by_line(const BoundingLine *line) {
|
||||
nassertr(!line->is_empty() && !line->is_infinite(), false);
|
||||
|
|
@ -95,6 +134,11 @@ extend_by_line(const BoundingLine *line) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::contains_sphere
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingLine::
|
||||
contains_sphere(const BoundingSphere *sphere) const {
|
||||
nassertr(!is_empty() && !is_infinite(), 0);
|
||||
|
|
@ -109,6 +153,31 @@ contains_sphere(const BoundingSphere *sphere) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::contains_box
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingLine::
|
||||
contains_box(const BoundingBox *box) const {
|
||||
nassertr(!is_empty() && !is_infinite(), 0);
|
||||
nassertr(!box->is_empty() && !box->is_infinite(), 0);
|
||||
|
||||
LPoint3f center = (box->get_minq() + box->get_maxq()) * 0.5f;
|
||||
float r2 = (box->get_maxq() - box->get_minq()).length_squared() * 0.25f;
|
||||
|
||||
if (r2 >= sqr_dist_to_line(center)) {
|
||||
return IF_possible;
|
||||
} else {
|
||||
return IF_no_intersection;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingLine::sqr_dist_to_line
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float BoundingLine::
|
||||
sqr_dist_to_line(const LPoint3f &point) const {
|
||||
nassertr(!point.is_nan(), 0.0f);
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@
|
|||
// arbitrary points on the line.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA BoundingLine : public GeometricBoundingVolume {
|
||||
PUBLISHED:
|
||||
public:
|
||||
INLINE_MATHUTIL BoundingLine();
|
||||
|
||||
PUBLISHED:
|
||||
INLINE_MATHUTIL BoundingLine(const LPoint3f &a, const LPoint3f &b);
|
||||
ALLOC_DELETED_CHAIN(BoundingLine);
|
||||
|
||||
|
|
@ -62,6 +64,7 @@ protected:
|
|||
virtual bool extend_by_line(const BoundingLine *line);
|
||||
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
|
||||
float sqr_dist_to_line(const LPoint3f &point) const;
|
||||
|
||||
|
|
@ -88,6 +91,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
|
||||
friend class BoundingSphere;
|
||||
friend class BoundingBox;
|
||||
};
|
||||
|
||||
#include "boundingLine.I"
|
||||
|
|
|
|||
|
|
@ -151,3 +151,50 @@ contains_sphere(const BoundingSphere *sphere) const {
|
|||
return IF_no_intersection;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingPlane::contains_box
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingPlane::
|
||||
contains_box(const BoundingBox *box) const {
|
||||
nassertr(!is_empty() && !is_infinite(), 0);
|
||||
nassertr(!box->is_empty() && !box->is_infinite(), 0);
|
||||
|
||||
// Put the box inside a sphere for the purpose of this test.
|
||||
const LPoint3f &min = box->get_minq();
|
||||
const LPoint3f &max = box->get_maxq();
|
||||
LPoint3f center = (min + max) * 0.5f;
|
||||
float radius2 = (max - center).length_squared();
|
||||
|
||||
int result = IF_possible | IF_some | IF_all;
|
||||
|
||||
float dist = _plane.dist_to_plane(center);
|
||||
float dist2 = dist * dist;
|
||||
|
||||
if (dist >= 0.0f && dist2 > radius2) {
|
||||
// The sphere is completely in front of this plane; it's thus
|
||||
// completely outside of the hexahedron.
|
||||
return IF_no_intersection;
|
||||
|
||||
} else if (dist < 0.0f && dist2 < radius2) {
|
||||
// The sphere is not completely behind this plane, but some of
|
||||
// it is.
|
||||
|
||||
// Look a little closer.
|
||||
bool all_in = true;
|
||||
for (int i = 0; i < 8 && all_in; ++i) {
|
||||
if (_plane.dist_to_plane(box->get_point(i)) < 0.0f) {
|
||||
// This point is outside the plane.
|
||||
all_in = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_in) {
|
||||
result &= ~IF_all;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ protected:
|
|||
virtual bool extend_by_plane(const BoundingPlane *plane);
|
||||
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
|
||||
private:
|
||||
Planef _plane;
|
||||
|
|
@ -81,6 +82,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
|
||||
friend class BoundingSphere;
|
||||
friend class BoundingBox;
|
||||
};
|
||||
|
||||
#include "boundingPlane.I"
|
||||
|
|
|
|||
|
|
@ -16,10 +16,21 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs an empty sphere.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingSphere::
|
||||
BoundingSphere() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs a specific sphere.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL BoundingSphere::
|
||||
BoundingSphere(const LPoint3f ¢er, float radius) :
|
||||
_center(center), _radius(radius)
|
||||
|
|
@ -30,6 +41,11 @@ BoundingSphere(const LPoint3f ¢er, float radius) :
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::get_center
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL const LPoint3f &BoundingSphere::
|
||||
get_center() const {
|
||||
nassertr(!is_empty(), _center);
|
||||
|
|
@ -37,6 +53,11 @@ get_center() const {
|
|||
return _center;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::get_radius
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_MATHUTIL float BoundingSphere::
|
||||
get_radius() const {
|
||||
nassertr(!is_empty(), 0.0f);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "boundingHexahedron.h"
|
||||
#include "boundingLine.h"
|
||||
#include "boundingPlane.h"
|
||||
|
|
@ -28,11 +29,21 @@
|
|||
|
||||
TypeHandle BoundingSphere::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingVolume *BoundingSphere::
|
||||
make_copy() const {
|
||||
return new BoundingSphere(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::get_min
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingSphere::
|
||||
get_min() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -42,6 +53,11 @@ get_min() const {
|
|||
_center[2] - _radius);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::get_max
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingSphere::
|
||||
get_max() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -51,6 +67,27 @@ get_max() const {
|
|||
_center[2] + _radius);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::get_volume
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float BoundingSphere::
|
||||
get_volume() const {
|
||||
nassertr(!is_infinite(), 0.0f);
|
||||
if (is_empty()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Volume of a sphere: four-thirds pi r cubed.
|
||||
return 4.0f / 3.0f * MathNumbers::pi_f * _radius * _radius * _radius;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::get_approx_center
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LPoint3f BoundingSphere::
|
||||
get_approx_center() const {
|
||||
nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
|
||||
|
|
@ -58,6 +95,11 @@ get_approx_center() const {
|
|||
return get_center();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::xform
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingSphere::
|
||||
xform(const LMatrix4f &mat) {
|
||||
nassertv(!mat.is_nan());
|
||||
|
|
@ -99,6 +141,11 @@ xform(const LMatrix4f &mat) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingSphere::
|
||||
output(ostream &out) const {
|
||||
if (is_empty()) {
|
||||
|
|
@ -110,11 +157,21 @@ output(ostream &out) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::extend_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
extend_other(BoundingVolume *other) const {
|
||||
return other->extend_by_sphere(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::around_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
around_other(BoundingVolume *other,
|
||||
const BoundingVolume **first,
|
||||
|
|
@ -122,12 +179,22 @@ around_other(BoundingVolume *other,
|
|||
return other->around_spheres(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::contains_other
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingSphere::
|
||||
contains_other(const BoundingVolume *other) const {
|
||||
return other->contains_sphere(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::extend_by_point
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
extend_by_point(const LPoint3f &point) {
|
||||
nassertr(!point.is_nan(), false);
|
||||
|
|
@ -146,6 +213,11 @@ extend_by_point(const LPoint3f &point) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::extend_by_sphere
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
extend_by_sphere(const BoundingSphere *sphere) {
|
||||
nassertr(!sphere->is_empty() && !sphere->is_infinite(), false);
|
||||
|
|
@ -163,39 +235,76 @@ extend_by_sphere(const BoundingSphere *sphere) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::extend_by_box
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
|
||||
return extend_by_finite(hexahedron);
|
||||
}
|
||||
|
||||
bool BoundingSphere::
|
||||
extend_by_finite(const FiniteBoundingVolume *volume) {
|
||||
nassertr(!volume->is_empty(), false);
|
||||
|
||||
LVector3f min1 = volume->get_min();
|
||||
LVector3f max1 = volume->get_max();
|
||||
extend_by_box(const BoundingBox *box) {
|
||||
const LVector3f &min1 = box->get_minq();
|
||||
const LVector3f &max1 = box->get_maxq();
|
||||
|
||||
if (is_empty()) {
|
||||
_center = (min1 + max1) * 0.5f;
|
||||
_radius = length(LVector3f(max1 - _center));
|
||||
_flags = 0;
|
||||
} else {
|
||||
LVector3f v = max1 - _center;
|
||||
float dist2 = dot(v, v);
|
||||
|
||||
if (dist2 > _radius * _radius) {
|
||||
_radius = sqrtf(dist2);
|
||||
} else {
|
||||
// Find the minimum radius necessary to reach the corner.
|
||||
float max_dist2 = -1.0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
float dist2 = (box->get_point(i) - _center).length_squared();
|
||||
if (dist2 > max_dist2) {
|
||||
max_dist2 = dist2;
|
||||
}
|
||||
}
|
||||
if (max_dist2 > _radius * _radius) {
|
||||
_radius = csqrt(max_dist2);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::extend_by_hexahedron
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
|
||||
nassertr(!hexahedron->is_empty(), false);
|
||||
|
||||
BoundingBox box(hexahedron->get_min(), hexahedron->get_max());
|
||||
box.local_object();
|
||||
return extend_by_box(&box);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::extend_by_finite
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
extend_by_finite(const FiniteBoundingVolume *volume) {
|
||||
nassertr(!volume->is_empty(), false);
|
||||
|
||||
BoundingBox box(volume->get_min(), volume->get_max());
|
||||
box.local_object();
|
||||
return extend_by_box(&box);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::around_points
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
around_points(const LPoint3f *first, const LPoint3f *last) {
|
||||
nassertr(first != last, false);
|
||||
|
||||
// First, get the minmax of all the points to construct a bounding
|
||||
// First, get the box of all the points to construct a bounding
|
||||
// box.
|
||||
const LPoint3f *p = first;
|
||||
|
||||
|
|
@ -279,42 +388,66 @@ around_points(const LPoint3f *first, const LPoint3f *last) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::around_spheres
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
return around_finite(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::around_boxes
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
around_boxes(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
return around_finite(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::around_hexahedrons
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
return around_finite(first, last);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::around_finite
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingSphere::
|
||||
around_finite(const BoundingVolume **first,
|
||||
const BoundingVolume **last) {
|
||||
nassertr(first != last, false);
|
||||
|
||||
// We're given a set of bounding volumes, at least the first one of
|
||||
// which is guaranteed to be finite and nonempty. Some others may
|
||||
// not be.
|
||||
// We're given a set of bounding volumes, all of which are finite,
|
||||
// and at least the first one of which is guaranteed to be nonempty.
|
||||
// Some others may not be.
|
||||
|
||||
// First, get the minmax of all the points to construct a bounding
|
||||
// First, get the box of all the points to construct a bounding
|
||||
// box.
|
||||
const BoundingVolume **p = first;
|
||||
nassertr(!(*p)->is_empty() && !(*p)->is_infinite(), false);
|
||||
nassertr((*p)->is_of_type(FiniteBoundingVolume::get_class_type()), false);
|
||||
const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p);
|
||||
LPoint3f min_box = vol->get_min();
|
||||
LPoint3f max_box = vol->get_max();
|
||||
|
||||
bool any_unknown = false;
|
||||
bool any_spheres = vol->is_exact_type(BoundingSphere::get_class_type());
|
||||
|
||||
for (++p; p != last; ++p) {
|
||||
nassertr(!(*p)->is_infinite(), false);
|
||||
if (!(*p)->is_empty() &&
|
||||
(*p)->is_of_type(FiniteBoundingVolume::get_class_type())) {
|
||||
if (!(*p)->is_empty()) {
|
||||
const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p);
|
||||
LPoint3f min1 = vol->get_min();
|
||||
LPoint3f max1 = vol->get_max();
|
||||
|
|
@ -325,8 +458,8 @@ around_finite(const BoundingVolume **first,
|
|||
max(max_box[1], max1[1]),
|
||||
max(max_box[2], max1[2]));
|
||||
|
||||
if (!(*p)->is_of_type(BoundingSphere::get_class_type())) {
|
||||
any_unknown = true;
|
||||
if (vol->is_exact_type(BoundingSphere::get_class_type())) {
|
||||
any_spheres = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -334,27 +467,39 @@ around_finite(const BoundingVolume **first,
|
|||
// Now take the center of the bounding box as the center of the sphere.
|
||||
_center = (min_box + max_box) * 0.5f;
|
||||
|
||||
if (any_unknown) {
|
||||
// If we have any volumes in the list that we don't know what to
|
||||
// do with, we'll have to make the bounding sphere large enough to
|
||||
// enclose the bounding box. Less than ideal, but too bad.
|
||||
if (!any_spheres) {
|
||||
// Since there are no spheres in the list, we have to make this
|
||||
// sphere fully enclose all of the bounding boxes.
|
||||
_radius = length(max_box - _center);
|
||||
|
||||
} else {
|
||||
// Otherwise, we do understand all the volumes in the list; make
|
||||
// the sphere as tight as we can.
|
||||
// We might be able to go tighter, by lopping off the corners of
|
||||
// the spheres.
|
||||
_radius = 0.0f;
|
||||
for (p = first; p != last; ++p) {
|
||||
if (!(*p)->is_empty()) {
|
||||
if ((*p)->is_of_type(BoundingSphere::get_class_type())) {
|
||||
if ((*p)->is_exact_type(BoundingSphere::get_class_type())) {
|
||||
// This is a sphere; consider its corner.
|
||||
const BoundingSphere *sphere = DCAST(BoundingSphere, *p);
|
||||
float dist = length(sphere->_center - _center);
|
||||
_radius = max(_radius, dist + sphere->_radius);
|
||||
|
||||
} else {
|
||||
// Shouldn't get here, unless we missed a type from above.
|
||||
mathutil_cat.error()
|
||||
<< "Unexpected type in BoundingSphere::around_finite()\n";
|
||||
nassertr(false, false);
|
||||
// This is a nonsphere. We fit around it.
|
||||
const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p);
|
||||
|
||||
BoundingBox box(vol->get_min(), vol->get_max());
|
||||
box.local_object();
|
||||
|
||||
// Find the minimum radius necessary to reach the corner.
|
||||
float max_dist2 = -1.0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
float dist2 = (box.get_point(i) - _center).length_squared();
|
||||
if (dist2 > max_dist2) {
|
||||
max_dist2 = dist2;
|
||||
}
|
||||
}
|
||||
_radius = max(_radius, csqrt(max_dist2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -364,6 +509,11 @@ around_finite(const BoundingVolume **first,
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::contains_point
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingSphere::
|
||||
contains_point(const LPoint3f &point) const {
|
||||
nassertr(!point.is_nan(), IF_no_intersection);
|
||||
|
|
@ -382,6 +532,11 @@ contains_point(const LPoint3f &point) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::contains_lineseg
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingSphere::
|
||||
contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
|
||||
nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection);
|
||||
|
|
@ -470,6 +625,18 @@ contains_sphere(const BoundingSphere *sphere) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::contains_box
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a box.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingSphere::
|
||||
contains_box(const BoundingBox *box) const {
|
||||
return box->contains_sphere(this) & ~IF_all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingSphere::contains_hexahedron
|
||||
// Access: Protected, Virtual
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
|
||||
virtual LPoint3f get_min() const;
|
||||
virtual LPoint3f get_max() const;
|
||||
virtual float get_volume() const;
|
||||
|
||||
virtual LPoint3f get_approx_center() const;
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
|
|
@ -60,6 +61,7 @@ protected:
|
|||
|
||||
virtual bool extend_by_point(const LPoint3f &point);
|
||||
virtual bool extend_by_sphere(const BoundingSphere *sphere);
|
||||
virtual bool extend_by_box(const BoundingBox *box);
|
||||
virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron);
|
||||
bool extend_by_finite(const FiniteBoundingVolume *volume);
|
||||
|
||||
|
|
@ -67,6 +69,8 @@ protected:
|
|||
const LPoint3f *last);
|
||||
virtual bool around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_boxes(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
bool around_finite(const BoundingVolume **first,
|
||||
|
|
@ -76,6 +80,7 @@ protected:
|
|||
virtual int contains_lineseg(const LPoint3f &a, const LPoint3f &b) const;
|
||||
virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const;
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
virtual int contains_line(const BoundingLine *line) const;
|
||||
virtual int contains_plane(const BoundingPlane *plane) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ BoundingVolume() {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::is_empty
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Any kind of volume might be empty. This is a
|
||||
// degenerate volume that contains no points; it's not
|
||||
// the same as, for instance, a sphere with radius zero,
|
||||
|
|
@ -42,7 +42,7 @@ is_empty() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::is_infinite
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: The other side of the empty coin is an infinite
|
||||
// volume. This is a degenerate state of a normally
|
||||
// finite volume that contains all points. (Note that
|
||||
|
|
@ -63,7 +63,7 @@ is_infinite() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::set_infinite
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Marks the volume as infinite, even if it is normally
|
||||
// finite. You can think of this as an infinite
|
||||
// extend_by() operation.
|
||||
|
|
@ -75,7 +75,7 @@ set_infinite() {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::extend_by
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Increases the size of the volume to include the given
|
||||
// volume.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -96,7 +96,7 @@ extend_by(const BoundingVolume *vol) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::contains
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the appropriate set of IntersectionFlags to
|
||||
// indicate the amount of intersection with the
|
||||
// indicated volume.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ TypeHandle BoundingVolume::_type_handle;
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::around
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Resets the volume to enclose only the volumes
|
||||
// indicated. Returns true if successful, false if the
|
||||
// volume doesn't know how to do that or can't do that.
|
||||
|
|
@ -72,7 +72,7 @@ around(const BoundingVolume **first, const BoundingVolume **last) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::write
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BoundingVolume::
|
||||
|
|
@ -80,6 +80,27 @@ write(ostream &out, int indent_level) const {
|
|||
indent(out, indent_level) << *this << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::string_bounds_type
|
||||
// Access: Public, Static
|
||||
// Description: Returns the BoundsType corresponding to the indicated
|
||||
// string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingVolume::BoundsType BoundingVolume::
|
||||
string_bounds_type(const string &str) {
|
||||
if (strcmp(str.c_str(), "best") == 0) {
|
||||
return BT_best;
|
||||
|
||||
} else if (strcmp(str.c_str(), "sphere") == 0) {
|
||||
return BT_sphere;
|
||||
|
||||
} else if (strcmp(str.c_str(), "box") == 0) {
|
||||
return BT_box;
|
||||
}
|
||||
|
||||
return BT_invalid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::extend_by_sphere
|
||||
// Access: Protected, Virtual
|
||||
|
|
@ -89,6 +110,23 @@ write(ostream &out, int indent_level) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
extend_by_sphere(const BoundingSphere *) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::extend_by_sphere() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::extend_by_box
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by extend_other()
|
||||
// when the type we're extending by is known to be a
|
||||
// box.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
extend_by_box(const BoundingBox *) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::extend_by_box() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -102,6 +140,8 @@ extend_by_sphere(const BoundingSphere *) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
extend_by_hexahedron(const BoundingHexahedron *) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::extend_by_hexahedron() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -115,6 +155,8 @@ extend_by_hexahedron(const BoundingHexahedron *) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
extend_by_line(const BoundingLine *) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::extend_by_line() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -128,6 +170,8 @@ extend_by_line(const BoundingLine *) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
extend_by_plane(const BoundingPlane *) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::extend_by_plane() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -141,6 +185,23 @@ extend_by_plane(const BoundingPlane *) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
around_spheres(const BoundingVolume **, const BoundingVolume **) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::around_spheres() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::around_boxes
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by around_other()
|
||||
// when the type of the first element in the list is
|
||||
// known to be a nonempty box.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
around_boxes(const BoundingVolume **, const BoundingVolume **) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::around_boxes() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -154,6 +215,8 @@ around_spheres(const BoundingVolume **, const BoundingVolume **) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool BoundingVolume::
|
||||
around_hexahedrons(const BoundingVolume **, const BoundingVolume **) {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::around_hexahedrons() called\n";
|
||||
_flags = F_infinite;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -174,6 +237,9 @@ around_lines(const BoundingVolume **, const BoundingVolume **) {
|
|||
return true;
|
||||
}
|
||||
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::around_lines() called\n";
|
||||
|
||||
// Otherwise, we might do better, and we require each class to
|
||||
// define a function. If we get here, the function isn't defined,
|
||||
// so we return false to indicate this.
|
||||
|
|
@ -196,6 +262,9 @@ around_planes(const BoundingVolume **, const BoundingVolume **) {
|
|||
return true;
|
||||
}
|
||||
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::around_planes() called\n";
|
||||
|
||||
// Otherwise, we might do better, and we require each class to
|
||||
// define a function. If we get here, the function isn't defined,
|
||||
// so we return false to indicate this.
|
||||
|
|
@ -211,6 +280,22 @@ around_planes(const BoundingVolume **, const BoundingVolume **) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingVolume::
|
||||
contains_sphere(const BoundingSphere *) const {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::contains_sphere() called\n";
|
||||
return IF_dont_understand;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BoundingVolume::contains_box
|
||||
// Access: Protected, Virtual
|
||||
// Description: Double-dispatch support: called by contains_other()
|
||||
// when the type we're testing for intersection is known
|
||||
// to be a box.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingVolume::
|
||||
contains_box(const BoundingBox *) const {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::contains_box() called\n";
|
||||
return IF_dont_understand;
|
||||
}
|
||||
|
||||
|
|
@ -223,6 +308,8 @@ contains_sphere(const BoundingSphere *) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingVolume::
|
||||
contains_hexahedron(const BoundingHexahedron *) const {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::contains_hexahedron() called\n";
|
||||
return IF_dont_understand;
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +322,8 @@ contains_hexahedron(const BoundingHexahedron *) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingVolume::
|
||||
contains_line(const BoundingLine *) const {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::contains_line() called\n";
|
||||
return IF_dont_understand;
|
||||
}
|
||||
|
||||
|
|
@ -247,5 +336,42 @@ contains_line(const BoundingLine *) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int BoundingVolume::
|
||||
contains_plane(const BoundingPlane *) const {
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::contains_plane() called\n";
|
||||
return IF_dont_understand;
|
||||
}
|
||||
|
||||
ostream &
|
||||
operator << (ostream &out, BoundingVolume::BoundsType type) {
|
||||
switch (type) {
|
||||
case BoundingVolume::BT_best:
|
||||
return out << "best";
|
||||
|
||||
case BoundingVolume::BT_sphere:
|
||||
return out << "sphere";
|
||||
|
||||
case BoundingVolume::BT_box:
|
||||
return out << "box";
|
||||
|
||||
case BoundingVolume::BT_invalid:
|
||||
return out << "invalid";
|
||||
}
|
||||
|
||||
mathutil_cat.error()
|
||||
<< "Invalid BoundingVolume::BoundsType value: " << (int)type << "\n";
|
||||
nassertr(false, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
istream &
|
||||
operator >> (istream &in, BoundingVolume::BoundsType &type) {
|
||||
string word;
|
||||
in >> word;
|
||||
type = BoundingVolume::string_bounds_type(word);
|
||||
if (type == BoundingVolume::BT_invalid) {
|
||||
mathutil_cat->error()
|
||||
<< "Invalid BoundingVolume::BoundsType string: " << word << "\n";
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "deletedChain.h"
|
||||
|
||||
class BoundingSphere;
|
||||
class BoundingBox;
|
||||
class BoundingHexahedron;
|
||||
class BoundingLine;
|
||||
class BoundingPlane;
|
||||
|
|
@ -42,8 +43,10 @@ class BoundingPlane;
|
|||
// sort.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA BoundingVolume : public TypedReferenceCount {
|
||||
PUBLISHED:
|
||||
public:
|
||||
INLINE_MATHUTIL BoundingVolume();
|
||||
|
||||
PUBLISHED:
|
||||
virtual BoundingVolume *make_copy() const=0;
|
||||
|
||||
INLINE_MATHUTIL bool is_empty() const;
|
||||
|
|
@ -96,6 +99,19 @@ PUBLISHED:
|
|||
virtual void output(ostream &out) const=0;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
// This enum is used to control the automatic generation of bounding
|
||||
// volumes.
|
||||
enum BoundsType {
|
||||
BT_best,
|
||||
BT_sphere,
|
||||
BT_box,
|
||||
|
||||
BT_invalid, // Do not use this one
|
||||
};
|
||||
|
||||
public:
|
||||
static BoundsType string_bounds_type(const string &str);
|
||||
|
||||
protected:
|
||||
enum Flags {
|
||||
F_empty = 0x01,
|
||||
|
|
@ -118,12 +134,15 @@ protected:
|
|||
// These functions are the second dispatch point. They actually do
|
||||
// the work.
|
||||
virtual bool extend_by_sphere(const BoundingSphere *sphere);
|
||||
virtual bool extend_by_box(const BoundingBox *box);
|
||||
virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron);
|
||||
virtual bool extend_by_line(const BoundingLine *line);
|
||||
virtual bool extend_by_plane(const BoundingPlane *plane);
|
||||
|
||||
virtual bool around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_boxes(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_lines(const BoundingVolume **first,
|
||||
|
|
@ -132,6 +151,7 @@ protected:
|
|||
const BoundingVolume **last);
|
||||
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const;
|
||||
virtual int contains_line(const BoundingLine *line) const;
|
||||
virtual int contains_plane(const BoundingPlane *plane) const;
|
||||
|
|
@ -155,6 +175,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
|
||||
friend class BoundingSphere;
|
||||
friend class BoundingBox;
|
||||
friend class BoundingHexahedron;
|
||||
friend class BoundingLine;
|
||||
friend class BoundingPlane;
|
||||
|
|
@ -164,4 +185,7 @@ INLINE_MATHUTIL ostream &operator << (ostream &out, const BoundingVolume &bound)
|
|||
|
||||
#include "boundingVolume.I"
|
||||
|
||||
EXPCL_PANDA ostream &operator << (ostream &out, BoundingVolume::BoundsType type);
|
||||
EXPCL_PANDA istream &operator >> (istream &in, BoundingVolume::BoundsType &type);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "finiteBoundingVolume.h"
|
||||
#include "omniBoundingVolume.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "boundingHexahedron.h"
|
||||
#include "boundingLine.h"
|
||||
#include "boundingPlane.h"
|
||||
|
|
@ -44,9 +45,16 @@ ConfigVariableDouble fft_exponent
|
|||
ConfigVariableDouble fft_error_threshold
|
||||
("fft-error-threshold", 0.2);
|
||||
|
||||
ConfigVariableEnum<BoundingVolume::BoundsType> bounds_type
|
||||
("bounds-type", BoundingVolume::BT_sphere,
|
||||
PRC_DESC("Specify the type of bounding volume that is created automatically "
|
||||
"by Panda to enclose geometry. Use 'sphere' or 'box', or use "
|
||||
"'best' to let Panda decide which is most appropriate."));
|
||||
|
||||
ConfigureFn(config_mathutil) {
|
||||
BoundingHexahedron::init_type();
|
||||
BoundingSphere::init_type();
|
||||
BoundingBox::init_type();
|
||||
BoundingVolume::init_type();
|
||||
FiniteBoundingVolume::init_type();
|
||||
GeometricBoundingVolume::init_type();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "configVariableDouble.h"
|
||||
#include "configVariableEnum.h"
|
||||
#include "boundingVolume.h"
|
||||
|
||||
NotifyCategoryDecl(mathutil, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
||||
|
|
@ -29,6 +31,7 @@ extern ConfigVariableDouble fft_offset;
|
|||
extern ConfigVariableDouble fft_factor;
|
||||
extern ConfigVariableDouble fft_exponent;
|
||||
extern ConfigVariableDouble fft_error_threshold;
|
||||
extern EXPCL_PANDA ConfigVariableEnum<BoundingVolume::BoundsType> bounds_type;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -17,5 +17,28 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "finiteBoundingVolume.h"
|
||||
#include "boundingBox.h"
|
||||
|
||||
TypeHandle FiniteBoundingVolume::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FiniteBoundingVolume::get_volume
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float FiniteBoundingVolume::
|
||||
get_volume() const {
|
||||
nassertr(!is_infinite(), 0.0f);
|
||||
if (is_empty()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
mathutil_cat.warning()
|
||||
<< get_type() << "::get_volume() called\n";
|
||||
|
||||
// We don't know how to compute the volume of this shape correctly;
|
||||
// just calculate the volume of its containing box.
|
||||
BoundingBox box(get_min(), get_max());
|
||||
box.local_object();
|
||||
return box.get_volume();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class EXPCL_PANDA FiniteBoundingVolume : public GeometricBoundingVolume {
|
|||
PUBLISHED:
|
||||
virtual LPoint3f get_min() const=0;
|
||||
virtual LPoint3f get_max() const=0;
|
||||
|
||||
virtual float get_volume() const;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "boundingHexahedron.cxx"
|
||||
#include "boundingLine.cxx"
|
||||
#include "boundingBox.cxx"
|
||||
#include "boundingPlane.cxx"
|
||||
#include "boundingSphere.cxx"
|
||||
#include "boundingVolume.cxx"
|
||||
|
|
|
|||
|
|
@ -117,6 +117,16 @@ extend_by_sphere(const BoundingSphere *) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OmniBoundingVolume::extend_by_box
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool OmniBoundingVolume::
|
||||
extend_by_box(const BoundingBox *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OmniBoundingVolume::extend_by_hexahedron
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -148,6 +158,17 @@ around_spheres(const BoundingVolume **,
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OmniBoundingVolume::around_boxes
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool OmniBoundingVolume::
|
||||
around_boxes(const BoundingVolume **,
|
||||
const BoundingVolume **) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OmniBoundingVolume::around_hexahedrons
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -189,6 +210,16 @@ contains_sphere(const BoundingSphere *) const {
|
|||
return IF_possible | IF_some | IF_all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OmniBoundingVolume::contains_box
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int OmniBoundingVolume::
|
||||
contains_box(const BoundingBox *) const {
|
||||
return IF_possible | IF_some | IF_all;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OmniBoundingVolume::contains_hexahedron
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -50,12 +50,15 @@ protected:
|
|||
|
||||
virtual bool extend_by_point(const LPoint3f &point);
|
||||
virtual bool extend_by_sphere(const BoundingSphere *sphere);
|
||||
virtual bool extend_by_box(const BoundingBox *box);
|
||||
virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron);
|
||||
|
||||
virtual bool around_points(const LPoint3f *first,
|
||||
const LPoint3f *last);
|
||||
virtual bool around_spheres(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_boxes(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
virtual bool around_hexahedrons(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
|
||||
|
|
@ -63,6 +66,7 @@ protected:
|
|||
virtual int contains_lineseg(const LPoint3f &a, const LPoint3f &b) const;
|
||||
virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const;
|
||||
virtual int contains_sphere(const BoundingSphere *sphere) const;
|
||||
virtual int contains_box(const BoundingBox *box) const;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@
|
|||
#include "geomNode.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "boundingHexahedron.h"
|
||||
#include "portalClipper.h"
|
||||
#include "geom.h"
|
||||
#include "geomTristrips.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "geomLinestrips.h"
|
||||
#include "geomVertexWriter.h"
|
||||
|
||||
|
|
@ -426,6 +428,50 @@ make_bounds_viz(const BoundingVolume *vol) {
|
|||
geom = new Geom(vdata);
|
||||
geom->add_primitive(strip);
|
||||
|
||||
} else if (vol->is_of_type(FiniteBoundingVolume::get_class_type())) {
|
||||
const FiniteBoundingVolume *fvol = DCAST(FiniteBoundingVolume, vol);
|
||||
|
||||
BoundingBox box(fvol->get_min(), fvol->get_max());
|
||||
box.local_object();
|
||||
|
||||
PT(GeomVertexData) vdata = new GeomVertexData
|
||||
("bounds", GeomVertexFormat::get_v3(),
|
||||
Geom::UH_stream);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
|
||||
for (int i = 0; i < 8; ++i ) {
|
||||
vertex.add_data3f(box.get_point(i));
|
||||
}
|
||||
|
||||
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_stream);
|
||||
tris->add_vertices(0, 4, 5);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(0, 5, 1);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(4, 6, 7);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(4, 7, 5);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(6, 2, 3);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(6, 3, 7);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 0, 1);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 1, 3);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(1, 5, 7);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(1, 7, 3);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 6, 4);
|
||||
tris->close_primitive();
|
||||
tris->add_vertices(2, 4, 0);
|
||||
tris->close_primitive();
|
||||
|
||||
geom = new Geom(vdata);
|
||||
geom->add_primitive(tris);
|
||||
|
||||
} else {
|
||||
pgraph_cat.warning()
|
||||
<< "Don't know how to draw a representation of "
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "pset.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "boundingBox.h"
|
||||
#include "config_mathutil.h"
|
||||
|
||||
TypeHandle GeomNode::_type_handle;
|
||||
|
||||
|
|
@ -682,30 +684,46 @@ compute_internal_bounds(PandaNode::BoundsData *bdata, int pipeline_stage,
|
|||
Thread *current_thread) const {
|
||||
int num_vertices = 0;
|
||||
|
||||
// First, get ourselves a fresh, empty bounding volume.
|
||||
PT(BoundingVolume) bound = new BoundingSphere;
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
|
||||
// Now actually compute the bounding volume by putting it around all
|
||||
// of our geoms' bounding volumes.
|
||||
pvector<const BoundingVolume *> child_volumes;
|
||||
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
bool all_box = true;
|
||||
|
||||
GeomList::const_iterator gi;
|
||||
CPT(GeomList) geoms = cdata->get_geoms();
|
||||
for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
|
||||
const GeomEntry &entry = (*gi);
|
||||
CPT(Geom) geom = entry._geom.get_read_pointer();
|
||||
child_volumes.push_back(geom->get_bounds());
|
||||
const BoundingVolume *volume = geom->get_bounds();
|
||||
|
||||
if (!volume->is_empty()) {
|
||||
child_volumes.push_back(volume);
|
||||
if (!volume->is_exact_type(BoundingBox::get_class_type())) {
|
||||
all_box = false;
|
||||
}
|
||||
}
|
||||
num_vertices += geom->get_nested_vertices();
|
||||
}
|
||||
|
||||
const BoundingVolume **child_begin = &child_volumes[0];
|
||||
const BoundingVolume **child_end = child_begin + child_volumes.size();
|
||||
PT(GeometricBoundingVolume) gbv;
|
||||
|
||||
bound->around(child_begin, child_end);
|
||||
if (bounds_type == BoundingVolume::BT_box ||
|
||||
(bounds_type != BoundingVolume::BT_sphere && all_box)) {
|
||||
// If all of the child volumes are a BoundingBox, then our volume
|
||||
// is also a BoundingBox.
|
||||
gbv = new BoundingBox;
|
||||
} else {
|
||||
// Otherwise, it's a sphere.
|
||||
gbv = new BoundingSphere;
|
||||
}
|
||||
|
||||
bdata->_internal_bounds = bound;
|
||||
if (child_volumes.size() > 0) {
|
||||
const BoundingVolume **child_begin = &child_volumes[0];
|
||||
const BoundingVolume **child_end = child_begin + child_volumes.size();
|
||||
((BoundingVolume *)gbv)->around(child_begin, child_end);
|
||||
}
|
||||
|
||||
bdata->_internal_bounds = gbv;
|
||||
bdata->_internal_vertices = num_vertices;
|
||||
bdata->_internal_bounds_stale = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ private:
|
|||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
|
||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
#include "accumulatedAttribs.h"
|
||||
#include "clipPlaneAttrib.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "boundingBox.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "config_mathutil.h"
|
||||
|
||||
// This category is just temporary for debugging convenience.
|
||||
NotifyCategoryDecl(drawmask, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
|
@ -3413,10 +3415,17 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
|
|||
pvector<CPT(BoundingVolume) > child_volumes_ref;
|
||||
pvector<const BoundingVolume *> child_volumes;
|
||||
|
||||
bool all_box = true;
|
||||
CPT(BoundingVolume) internal_bounds =
|
||||
get_internal_bounds(pipeline_stage, current_thread);
|
||||
child_volumes_ref.push_back(internal_bounds);
|
||||
child_volumes.push_back(internal_bounds);
|
||||
|
||||
if (!internal_bounds->is_empty()) {
|
||||
child_volumes_ref.push_back(internal_bounds);
|
||||
child_volumes.push_back(internal_bounds);
|
||||
if (!internal_bounds->is_exact_type(BoundingBox::get_class_type())) {
|
||||
all_box = false;
|
||||
}
|
||||
}
|
||||
|
||||
int num_vertices = cdata->_internal_vertices;
|
||||
|
||||
|
|
@ -3466,8 +3475,13 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
|
|||
}
|
||||
|
||||
off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
|
||||
child_volumes_ref.push_back(child_cdataw->_external_bounds);
|
||||
child_volumes.push_back(child_cdataw->_external_bounds);
|
||||
if (!child_cdataw->_external_bounds->is_empty()) {
|
||||
child_volumes_ref.push_back(child_cdataw->_external_bounds);
|
||||
child_volumes.push_back(child_cdataw->_external_bounds);
|
||||
if (!child_cdataw->_external_bounds->is_exact_type(BoundingBox::get_class_type())) {
|
||||
all_box = false;
|
||||
}
|
||||
}
|
||||
num_vertices += child_cdataw->_nested_vertices;
|
||||
|
||||
} else {
|
||||
|
|
@ -3498,8 +3512,13 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
|
|||
}
|
||||
|
||||
off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
|
||||
child_volumes_ref.push_back(child_cdata->_external_bounds);
|
||||
child_volumes.push_back(child_cdata->_external_bounds);
|
||||
if (!child_cdata->_external_bounds->is_empty()) {
|
||||
child_volumes_ref.push_back(child_cdata->_external_bounds);
|
||||
child_volumes.push_back(child_cdata->_external_bounds);
|
||||
if (!child_cdata->_external_bounds->is_exact_type(BoundingBox::get_class_type())) {
|
||||
all_box = false;
|
||||
}
|
||||
}
|
||||
num_vertices += child_cdata->_nested_vertices;
|
||||
}
|
||||
}
|
||||
|
|
@ -3543,21 +3562,33 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
|
|||
cdataw->_off_clip_planes = off_clip_planes;
|
||||
cdataw->_nested_vertices = num_vertices;
|
||||
|
||||
// Compute the bounding sphere around all of our child
|
||||
// volumes.
|
||||
PT(GeometricBoundingVolume) gbv = new BoundingSphere;
|
||||
const BoundingVolume **child_begin = &child_volumes[0];
|
||||
const BoundingVolume **child_end = child_begin + child_volumes.size();
|
||||
((BoundingVolume *)gbv)->around(child_begin, child_end);
|
||||
|
||||
// If we have a transform, apply it to the bounding volume we
|
||||
// just computed.
|
||||
CPT(TransformState) transform = get_transform(current_thread);
|
||||
if (!transform->is_identity()) {
|
||||
gbv->xform(transform->get_mat());
|
||||
}
|
||||
PT(GeometricBoundingVolume) gbv;
|
||||
|
||||
cdataw->_external_bounds = gbv;
|
||||
if (bounds_type == BoundingVolume::BT_box ||
|
||||
(bounds_type != BoundingVolume::BT_sphere && all_box && transform->is_identity())) {
|
||||
// If all of the child volumes are a BoundingBox, and we
|
||||
// have no transform, then our volume is also a
|
||||
// BoundingBox.
|
||||
|
||||
gbv = new BoundingBox;
|
||||
} else {
|
||||
// Otherwise, it's a sphere.
|
||||
gbv = new BoundingSphere;
|
||||
}
|
||||
|
||||
if (child_volumes.size() > 0) {
|
||||
const BoundingVolume **child_begin = &child_volumes[0];
|
||||
const BoundingVolume **child_end = child_begin + child_volumes.size();
|
||||
((BoundingVolume *)gbv)->around(child_begin, child_end);
|
||||
}
|
||||
|
||||
// If we have a transform, apply it to the bounding volume we
|
||||
// just computed.
|
||||
if (!transform->is_identity()) {
|
||||
gbv->xform(transform->get_mat());
|
||||
}
|
||||
cdataw->_external_bounds = gbv;
|
||||
cdataw->_last_update = next_update;
|
||||
|
||||
if (drawmask_cat.is_debug()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue