mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
cull to geoms; fix box culling
This commit is contained in:
parent
1ca36eedd9
commit
fe951a35fd
@ -351,27 +351,32 @@ contains_box(const BoundingBox *box) const {
|
|||||||
float dist = p.dist_to_plane(center);
|
float dist = p.dist_to_plane(center);
|
||||||
float dist2 = dist * dist;
|
float dist2 = dist * dist;
|
||||||
|
|
||||||
if (dist >= 0.0f && dist2 > radius2) {
|
if (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
|
// The sphere is not completely behind this plane, but some of
|
||||||
// it is.
|
// it is.
|
||||||
|
|
||||||
// Look a little closer.
|
// Look a little closer.
|
||||||
bool all_in = true;
|
bool all_in = true;
|
||||||
for (int i = 0; i < 8 && all_in; ++i) {
|
bool all_out = true;
|
||||||
|
for (int i = 0; i < 8 && (all_in || all_out) ; ++i) {
|
||||||
if (p.dist_to_plane(box->get_point(i)) < 0.0f) {
|
if (p.dist_to_plane(box->get_point(i)) < 0.0f) {
|
||||||
|
// This point is inside the plane.
|
||||||
|
all_out = false;
|
||||||
|
} else {
|
||||||
// This point is outside the plane.
|
// This point is outside the plane.
|
||||||
all_in = false;
|
all_in = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!all_in) {
|
if (all_out) {
|
||||||
|
return IF_no_intersection;
|
||||||
|
} else if (!all_in) {
|
||||||
result &= ~IF_all;
|
result &= ~IF_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (dist >= 0.0f) {
|
||||||
|
// The sphere is completely in front of this plane.
|
||||||
|
return IF_no_intersection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,27 +173,32 @@ contains_box(const BoundingBox *box) const {
|
|||||||
float dist = _plane.dist_to_plane(center);
|
float dist = _plane.dist_to_plane(center);
|
||||||
float dist2 = dist * dist;
|
float dist2 = dist * dist;
|
||||||
|
|
||||||
if (dist >= 0.0f && dist2 > radius2) {
|
if (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
|
// The sphere is not completely behind this plane, but some of
|
||||||
// it is.
|
// it is.
|
||||||
|
|
||||||
// Look a little closer.
|
// Look a little closer.
|
||||||
bool all_in = true;
|
bool all_in = true;
|
||||||
for (int i = 0; i < 8 && all_in; ++i) {
|
bool all_out = true;
|
||||||
|
for (int i = 0; i < 8 && (all_in || all_out) ; ++i) {
|
||||||
if (_plane.dist_to_plane(box->get_point(i)) < 0.0f) {
|
if (_plane.dist_to_plane(box->get_point(i)) < 0.0f) {
|
||||||
|
// This point is inside the plane.
|
||||||
|
all_out = false;
|
||||||
|
} else {
|
||||||
// This point is outside the plane.
|
// This point is outside the plane.
|
||||||
all_in = false;
|
all_in = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!all_in) {
|
if (all_out) {
|
||||||
|
return IF_no_intersection;
|
||||||
|
} else if (!all_in) {
|
||||||
result &= ~IF_all;
|
result &= ~IF_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (dist >= 0.0f) {
|
||||||
|
// The sphere is completely in front of this plane.
|
||||||
|
return IF_no_intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -260,14 +260,55 @@ traverse_below(CullTraverserData &data) {
|
|||||||
GeomNode::Geoms geoms = geom_node->get_geoms(_current_thread);
|
GeomNode::Geoms geoms = geom_node->get_geoms(_current_thread);
|
||||||
int num_geoms = geoms.get_num_geoms();
|
int num_geoms = geoms.get_num_geoms();
|
||||||
_geoms_pcollector.add_level(num_geoms);
|
_geoms_pcollector.add_level(num_geoms);
|
||||||
|
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||||
|
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||||
|
CPT(TransformState) internal_transform = get_gsg()->get_cs_transform()->compose(modelview_transform);
|
||||||
|
|
||||||
for (int i = 0; i < num_geoms; i++) {
|
for (int i = 0; i < num_geoms; i++) {
|
||||||
CullableObject *object = new CullableObject(this, data, geoms, i);
|
const Geom *geom = geoms.get_geom(i);
|
||||||
if (object->_state->has_cull_callback() &&
|
|
||||||
!object->_state->cull_callback(this, data)) {
|
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||||
delete object;
|
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||||
} else {
|
// Cull.
|
||||||
_cull_handler->record_object(object, this);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cull the Geom bounding volume against the view frustum
|
||||||
|
// and/or the cull planes. Don't bother unless we've got more
|
||||||
|
// than one Geom, since otherwise the bounding volume of the
|
||||||
|
// GeomNode is (probably) the same as that of the one Geom,
|
||||||
|
// and we've already culled against that.
|
||||||
|
if (num_geoms > 1) {
|
||||||
|
if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||||
|
// Cull the individual Geom against the view frustum.
|
||||||
|
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||||
|
const GeometricBoundingVolume *geom_gbv =
|
||||||
|
DCAST(GeometricBoundingVolume, geom_volume);
|
||||||
|
|
||||||
|
int result = data._view_frustum->contains(geom_gbv);
|
||||||
|
if (result == BoundingVolume::IF_no_intersection) {
|
||||||
|
// Cull this Geom.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data._cull_planes->is_empty()) {
|
||||||
|
// Also cull the Geom against the cull planes.
|
||||||
|
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||||
|
const GeometricBoundingVolume *geom_gbv =
|
||||||
|
DCAST(GeometricBoundingVolume, geom_volume);
|
||||||
|
int result;
|
||||||
|
data._cull_planes->do_cull(result, state, geom_gbv);
|
||||||
|
if (result == BoundingVolume::IF_no_intersection) {
|
||||||
|
// Cull.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CullableObject *object =
|
||||||
|
new CullableObject(geom, state, net_transform,
|
||||||
|
modelview_transform, internal_transform);
|
||||||
|
_cull_handler->record_object(object, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,6 +406,8 @@ is_in_view(CullTraverserData &data) {
|
|||||||
void CullTraverser::
|
void CullTraverser::
|
||||||
show_bounds(CullTraverserData &data, bool tight) {
|
show_bounds(CullTraverserData &data, bool tight) {
|
||||||
PandaNode *node = data.node();
|
PandaNode *node = data.node();
|
||||||
|
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||||
|
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||||
|
|
||||||
if (tight) {
|
if (tight) {
|
||||||
PT(Geom) bounds_viz = make_tight_bounds_viz(node);
|
PT(Geom) bounds_viz = make_tight_bounds_viz(node);
|
||||||
@ -373,16 +416,24 @@ show_bounds(CullTraverserData &data, bool tight) {
|
|||||||
_geoms_pcollector.add_level(1);
|
_geoms_pcollector.add_level(1);
|
||||||
CullableObject *outer_viz =
|
CullableObject *outer_viz =
|
||||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||||
data.get_net_transform(this),
|
net_transform, modelview_transform,
|
||||||
data.get_modelview_transform(this),
|
|
||||||
get_gsg());
|
get_gsg());
|
||||||
_cull_handler->record_object(outer_viz, this);
|
_cull_handler->record_object(outer_viz, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
draw_bounding_volume(node->get_bounds(),
|
draw_bounding_volume(node->get_bounds(),
|
||||||
data.get_net_transform(this),
|
net_transform, modelview_transform);
|
||||||
data.get_modelview_transform(this));
|
|
||||||
|
if (node->is_geom_node()) {
|
||||||
|
// Also show the bounding volumes of included Geoms.
|
||||||
|
GeomNode *gnode = DCAST(GeomNode, node);
|
||||||
|
int num_geoms = gnode->get_num_geoms();
|
||||||
|
for (int i = 0; i < num_geoms; ++i) {
|
||||||
|
draw_bounding_volume(gnode->get_geom(i)->get_bounds(),
|
||||||
|
net_transform, modelview_transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,16 +724,55 @@ start_decal(const CullTraverserData &data) {
|
|||||||
GeomNode::Geoms geoms = geom_node->get_geoms();
|
GeomNode::Geoms geoms = geom_node->get_geoms();
|
||||||
int num_geoms = geoms.get_num_geoms();
|
int num_geoms = geoms.get_num_geoms();
|
||||||
_geoms_pcollector.add_level(num_geoms);
|
_geoms_pcollector.add_level(num_geoms);
|
||||||
|
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||||
|
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||||
|
CPT(TransformState) internal_transform = get_gsg()->get_cs_transform()->compose(modelview_transform);
|
||||||
|
|
||||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||||
CullableObject *next_object =
|
const Geom *geom = geoms.get_geom(i);
|
||||||
new CullableObject(this, data, geoms, i, object);
|
|
||||||
if (next_object->_state->has_cull_callback() &&
|
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||||
!next_object->_state->cull_callback(this, data)) {
|
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||||
next_object->_next = NULL;
|
// Cull.
|
||||||
delete next_object;
|
continue;
|
||||||
} else {
|
|
||||||
object = next_object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cull the Geom bounding volume against the view frustum
|
||||||
|
// and/or the cull planes. Don't bother unless we've got more
|
||||||
|
// than one Geom, since otherwise the bounding volume of the
|
||||||
|
// GeomNode is (probably) the same as that of the one Geom,
|
||||||
|
// and we've already culled against that.
|
||||||
|
if (num_geoms > 1) {
|
||||||
|
if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||||
|
// Cull the individual Geom against the view frustum.
|
||||||
|
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||||
|
const GeometricBoundingVolume *geom_gbv =
|
||||||
|
DCAST(GeometricBoundingVolume, geom_volume);
|
||||||
|
|
||||||
|
int result = data._view_frustum->contains(geom_gbv);
|
||||||
|
if (result == BoundingVolume::IF_no_intersection) {
|
||||||
|
// Cull this Geom.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data._cull_planes->is_empty()) {
|
||||||
|
// Also cull the Geom against the cull planes.
|
||||||
|
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||||
|
const GeometricBoundingVolume *geom_gbv =
|
||||||
|
DCAST(GeometricBoundingVolume, geom_volume);
|
||||||
|
int result;
|
||||||
|
data._cull_planes->do_cull(result, state, geom_gbv);
|
||||||
|
if (result == BoundingVolume::IF_no_intersection) {
|
||||||
|
// Cull.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object =
|
||||||
|
new CullableObject(geom, state, net_transform,
|
||||||
|
modelview_transform, internal_transform,
|
||||||
|
object);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object != separator) {
|
if (object != separator) {
|
||||||
@ -743,16 +833,55 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) {
|
|||||||
GeomNode::Geoms geoms = geom_node->get_geoms();
|
GeomNode::Geoms geoms = geom_node->get_geoms();
|
||||||
int num_geoms = geoms.get_num_geoms();
|
int num_geoms = geoms.get_num_geoms();
|
||||||
_geoms_pcollector.add_level(num_geoms);
|
_geoms_pcollector.add_level(num_geoms);
|
||||||
|
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||||
|
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||||
|
CPT(TransformState) internal_transform = get_gsg()->get_cs_transform()->compose(modelview_transform);
|
||||||
|
|
||||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||||
CullableObject *next_decals =
|
const Geom *geom = geoms.get_geom(i);
|
||||||
new CullableObject(this, data, geoms, i, decals);
|
|
||||||
if (next_decals->_state->has_cull_callback() &&
|
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||||
!next_decals->_state->cull_callback(this, data)) {
|
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||||
next_decals->_next = NULL;
|
// Cull.
|
||||||
delete next_decals;
|
continue;
|
||||||
} else {
|
|
||||||
decals = next_decals;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cull the Geom bounding volume against the view frustum
|
||||||
|
// and/or the cull planes. Don't bother unless we've got more
|
||||||
|
// than one Geom, since otherwise the bounding volume of the
|
||||||
|
// GeomNode is (probably) the same as that of the one Geom,
|
||||||
|
// and we've already culled against that.
|
||||||
|
if (num_geoms > 1) {
|
||||||
|
if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||||
|
// Cull the individual Geom against the view frustum.
|
||||||
|
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||||
|
const GeometricBoundingVolume *geom_gbv =
|
||||||
|
DCAST(GeometricBoundingVolume, geom_volume);
|
||||||
|
|
||||||
|
int result = data._view_frustum->contains(geom_gbv);
|
||||||
|
if (result == BoundingVolume::IF_no_intersection) {
|
||||||
|
// Cull this Geom.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data._cull_planes->is_empty()) {
|
||||||
|
// Also cull the Geom against the cull planes.
|
||||||
|
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||||
|
const GeometricBoundingVolume *geom_gbv =
|
||||||
|
DCAST(GeometricBoundingVolume, geom_volume);
|
||||||
|
int result;
|
||||||
|
data._cull_planes->do_cull(result, state, geom_gbv);
|
||||||
|
if (result == BoundingVolume::IF_no_intersection) {
|
||||||
|
// Cull.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decals =
|
||||||
|
new CullableObject(geom, state, net_transform,
|
||||||
|
modelview_transform, internal_transform,
|
||||||
|
decals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,26 +28,6 @@ CullableObject(CullableObject *next) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: CullableObject::Constructor
|
|
||||||
// Access: Public
|
|
||||||
// Description: Creates a CullableObject based on the ith Geom from
|
|
||||||
// the indicated GeomNode, with the render state from
|
|
||||||
// the indicated CullTraverserData.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE CullableObject::
|
|
||||||
CullableObject(const CullTraverser *trav, const CullTraverserData &data,
|
|
||||||
const GeomNode::Geoms &geoms, int i,
|
|
||||||
CullableObject *next) :
|
|
||||||
_geom(geoms.get_geom(i)),
|
|
||||||
_state(data._state->compose(geoms.get_geom_state(i))),
|
|
||||||
_net_transform(data.get_net_transform(trav)),
|
|
||||||
_modelview_transform(data.get_modelview_transform(trav)),
|
|
||||||
_internal_transform(trav->get_gsg()->get_cs_transform()->compose(_modelview_transform)),
|
|
||||||
_next(next)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CullableObject::Constructor
|
// Function: CullableObject::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -69,6 +49,27 @@ CullableObject(const Geom *geom, const RenderState *state,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CullableObject::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description: Creates a CullableObject based the indicated geom,
|
||||||
|
// with the indicated render state and transform.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE CullableObject::
|
||||||
|
CullableObject(const Geom *geom, const RenderState *state,
|
||||||
|
const TransformState *net_transform,
|
||||||
|
const TransformState *modelview_transform,
|
||||||
|
const TransformState *internal_transform,
|
||||||
|
CullableObject *next) :
|
||||||
|
_geom(geom),
|
||||||
|
_state(state),
|
||||||
|
_net_transform(net_transform),
|
||||||
|
_modelview_transform(modelview_transform),
|
||||||
|
_internal_transform(internal_transform),
|
||||||
|
_next(next)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CullableObject::Copy Constructor
|
// Function: CullableObject::Copy Constructor
|
||||||
|
@ -45,15 +45,16 @@ class CullTraverser;
|
|||||||
class EXPCL_PANDA CullableObject {
|
class EXPCL_PANDA CullableObject {
|
||||||
public:
|
public:
|
||||||
INLINE CullableObject(CullableObject *next = NULL);
|
INLINE CullableObject(CullableObject *next = NULL);
|
||||||
INLINE CullableObject(const CullTraverser *trav,
|
|
||||||
const CullTraverserData &data,
|
|
||||||
const GeomNode::Geoms &geoms, int i,
|
|
||||||
CullableObject *next = NULL);
|
|
||||||
INLINE CullableObject(const Geom *geom, const RenderState *state,
|
INLINE CullableObject(const Geom *geom, const RenderState *state,
|
||||||
const TransformState *net_transform,
|
const TransformState *net_transform,
|
||||||
const TransformState *modelview_transform,
|
const TransformState *modelview_transform,
|
||||||
const GraphicsStateGuardianBase *gsg,
|
const GraphicsStateGuardianBase *gsg,
|
||||||
CullableObject *next = NULL);
|
CullableObject *next = NULL);
|
||||||
|
INLINE CullableObject(const Geom *geom, const RenderState *state,
|
||||||
|
const TransformState *net_transform,
|
||||||
|
const TransformState *modelview_transform,
|
||||||
|
const TransformState *internal_transform,
|
||||||
|
CullableObject *next = NULL);
|
||||||
|
|
||||||
INLINE CullableObject(const CullableObject ©);
|
INLINE CullableObject(const CullableObject ©);
|
||||||
INLINE void operator = (const CullableObject ©);
|
INLINE void operator = (const CullableObject ©);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user