mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -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 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) {
|
||||
if (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) {
|
||||
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) {
|
||||
// This point is inside the plane.
|
||||
all_out = false;
|
||||
} else {
|
||||
// This point is outside the plane.
|
||||
all_in = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_in) {
|
||||
if (all_out) {
|
||||
return IF_no_intersection;
|
||||
} else if (!all_in) {
|
||||
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 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) {
|
||||
if (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) {
|
||||
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) {
|
||||
// This point is inside the plane.
|
||||
all_out = false;
|
||||
} else {
|
||||
// This point is outside the plane.
|
||||
all_in = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_in) {
|
||||
if (all_out) {
|
||||
return IF_no_intersection;
|
||||
} else if (!all_in) {
|
||||
result &= ~IF_all;
|
||||
}
|
||||
|
||||
} else if (dist >= 0.0f) {
|
||||
// The sphere is completely in front of this plane.
|
||||
return IF_no_intersection;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -260,14 +260,55 @@ traverse_below(CullTraverserData &data) {
|
||||
GeomNode::Geoms geoms = geom_node->get_geoms(_current_thread);
|
||||
int num_geoms = geoms.get_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++) {
|
||||
CullableObject *object = new CullableObject(this, data, geoms, i);
|
||||
if (object->_state->has_cull_callback() &&
|
||||
!object->_state->cull_callback(this, data)) {
|
||||
delete object;
|
||||
} else {
|
||||
_cull_handler->record_object(object, this);
|
||||
const Geom *geom = geoms.get_geom(i);
|
||||
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||
// Cull.
|
||||
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::
|
||||
show_bounds(CullTraverserData &data, bool tight) {
|
||||
PandaNode *node = data.node();
|
||||
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||
|
||||
if (tight) {
|
||||
PT(Geom) bounds_viz = make_tight_bounds_viz(node);
|
||||
@ -373,16 +416,24 @@ show_bounds(CullTraverserData &data, bool tight) {
|
||||
_geoms_pcollector.add_level(1);
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||
data.get_net_transform(this),
|
||||
data.get_modelview_transform(this),
|
||||
net_transform, modelview_transform,
|
||||
get_gsg());
|
||||
_cull_handler->record_object(outer_viz, this);
|
||||
}
|
||||
|
||||
} else {
|
||||
draw_bounding_volume(node->get_bounds(),
|
||||
data.get_net_transform(this),
|
||||
data.get_modelview_transform(this));
|
||||
net_transform, modelview_transform);
|
||||
|
||||
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();
|
||||
int num_geoms = geoms.get_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--) {
|
||||
CullableObject *next_object =
|
||||
new CullableObject(this, data, geoms, i, object);
|
||||
if (next_object->_state->has_cull_callback() &&
|
||||
!next_object->_state->cull_callback(this, data)) {
|
||||
next_object->_next = NULL;
|
||||
delete next_object;
|
||||
} else {
|
||||
object = next_object;
|
||||
const Geom *geom = geoms.get_geom(i);
|
||||
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||
// Cull.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object =
|
||||
new CullableObject(geom, state, net_transform,
|
||||
modelview_transform, internal_transform,
|
||||
object);
|
||||
}
|
||||
|
||||
if (object != separator) {
|
||||
@ -743,16 +833,55 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) {
|
||||
GeomNode::Geoms geoms = geom_node->get_geoms();
|
||||
int num_geoms = geoms.get_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--) {
|
||||
CullableObject *next_decals =
|
||||
new CullableObject(this, data, geoms, i, decals);
|
||||
if (next_decals->_state->has_cull_callback() &&
|
||||
!next_decals->_state->cull_callback(this, data)) {
|
||||
next_decals->_next = NULL;
|
||||
delete next_decals;
|
||||
} else {
|
||||
decals = next_decals;
|
||||
const Geom *geom = geoms.get_geom(i);
|
||||
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||
// Cull.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// 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
|
||||
|
@ -45,15 +45,16 @@ class CullTraverser;
|
||||
class EXPCL_PANDA CullableObject {
|
||||
public:
|
||||
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,
|
||||
const TransformState *net_transform,
|
||||
const TransformState *modelview_transform,
|
||||
const GraphicsStateGuardianBase *gsg,
|
||||
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 void operator = (const CullableObject ©);
|
||||
|
Loading…
x
Reference in New Issue
Block a user