mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
pgraph: Optimization for GeomNode::add_for_draw()
This commit is contained in:
parent
251d73a47b
commit
2b29c757d9
@ -1294,6 +1294,29 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
return gc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Geom is within the given view frustum.
|
||||
*/
|
||||
bool Geom::
|
||||
is_in_view(const BoundingVolume *view_frustum, Thread *current_thread) const {
|
||||
CDLockedReader cdata(_cycler, current_thread);
|
||||
|
||||
if (cdata->_user_bounds != nullptr) {
|
||||
const GeometricBoundingVolume *gbv = cdata->_user_bounds->as_geometric_bounding_volume();
|
||||
return view_frustum->contains(gbv) != BoundingVolume::IF_no_intersection;
|
||||
}
|
||||
else if (!cdata->_internal_bounds_stale) {
|
||||
const GeometricBoundingVolume *gbv = cdata->_internal_bounds->as_geometric_bounding_volume();
|
||||
return view_frustum->contains(gbv) != BoundingVolume::IF_no_intersection;
|
||||
}
|
||||
else {
|
||||
CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
|
||||
compute_internal_bounds(cdataw, current_thread);
|
||||
const GeometricBoundingVolume *gbv = cdataw->_internal_bounds->as_geometric_bounding_volume();
|
||||
return view_frustum->contains(gbv) != BoundingVolume::IF_no_intersection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually draws the Geom with the indicated GSG, using the indicated vertex
|
||||
* data (which might have been pre-munged to support the GSG's needs).
|
||||
|
@ -157,6 +157,8 @@ PUBLISHED:
|
||||
GraphicsStateGuardianBase *gsg);
|
||||
|
||||
public:
|
||||
bool is_in_view(const BoundingVolume *view_frustum, Thread *current_thread) const;
|
||||
|
||||
bool draw(GraphicsStateGuardianBase *gsg,
|
||||
const GeomVertexData *vertex_data, size_t num_instances,
|
||||
bool force, Thread *current_thread) const;
|
||||
|
@ -516,44 +516,50 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
||||
trav->_geoms_pcollector.add_level(num_geoms);
|
||||
CPT(TransformState) internal_transform = data.get_internal_transform(trav);
|
||||
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
CPT(Geom) geom = geoms.get_geom(i);
|
||||
if (geom->is_empty()) {
|
||||
continue;
|
||||
if (num_geoms == 1) {
|
||||
// If there's only one Geom, we don't need to bother culling each individual
|
||||
// Geom bounding volume against the view frustum, since we've already
|
||||
// checked the one on the GeomNode itself.
|
||||
CPT(Geom) geom = geoms.get_geom(0);
|
||||
if (!geom->is_empty()) {
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(0));
|
||||
if (!state->has_cull_callback() || state->cull_callback(trav, data)) {
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), std::move(internal_transform));
|
||||
object->_instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// More than one Geom.
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
CPT(Geom) geom = geoms.get_geom(i);
|
||||
if (geom->is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
|
||||
// Cull.
|
||||
continue;
|
||||
}
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
|
||||
// Cull.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data._instances != nullptr) {
|
||||
// Draw each individual instance. We don't bother culling each
|
||||
// individual Geom for each instance; that is probably way too slow.
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||
object->_instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
continue;
|
||||
}
|
||||
if (data._instances != nullptr) {
|
||||
// Draw each individual instance. We don't bother culling each
|
||||
// individual Geom for each instance; that is probably way too slow.
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||
object->_instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cull the Geom bounding volume against the view frustum andor 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 != nullptr) {
|
||||
// Cull the individual Geom against the view frustum.
|
||||
CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
|
||||
const GeometricBoundingVolume *geom_gbv =
|
||||
geom_volume->as_geometric_bounding_volume();
|
||||
|
||||
int result = data._view_frustum->contains(geom_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// Cull this Geom.
|
||||
continue;
|
||||
}
|
||||
// Cull the individual Geom against the view frustum.
|
||||
if (data._view_frustum != nullptr &&
|
||||
!geom->is_in_view(data._view_frustum, current_thread)) {
|
||||
// Cull this Geom.
|
||||
continue;
|
||||
}
|
||||
if (!data._cull_planes->is_empty()) {
|
||||
// Also cull the Geom against the cull planes.
|
||||
@ -567,11 +573,11 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user