mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -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;
|
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
|
* 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).
|
* data (which might have been pre-munged to support the GSG's needs).
|
||||||
|
@ -157,6 +157,8 @@ PUBLISHED:
|
|||||||
GraphicsStateGuardianBase *gsg);
|
GraphicsStateGuardianBase *gsg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool is_in_view(const BoundingVolume *view_frustum, Thread *current_thread) const;
|
||||||
|
|
||||||
bool draw(GraphicsStateGuardianBase *gsg,
|
bool draw(GraphicsStateGuardianBase *gsg,
|
||||||
const GeomVertexData *vertex_data, size_t num_instances,
|
const GeomVertexData *vertex_data, size_t num_instances,
|
||||||
bool force, Thread *current_thread) const;
|
bool force, Thread *current_thread) const;
|
||||||
|
@ -516,44 +516,50 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||||||
trav->_geoms_pcollector.add_level(num_geoms);
|
trav->_geoms_pcollector.add_level(num_geoms);
|
||||||
CPT(TransformState) internal_transform = data.get_internal_transform(trav);
|
CPT(TransformState) internal_transform = data.get_internal_transform(trav);
|
||||||
|
|
||||||
for (int i = 0; i < num_geoms; i++) {
|
if (num_geoms == 1) {
|
||||||
CPT(Geom) geom = geoms.get_geom(i);
|
// If there's only one Geom, we don't need to bother culling each individual
|
||||||
if (geom->is_empty()) {
|
// Geom bounding volume against the view frustum, since we've already
|
||||||
continue;
|
// 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));
|
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||||
if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
|
if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
|
||||||
// Cull.
|
// Cull.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data._instances != nullptr) {
|
if (data._instances != nullptr) {
|
||||||
// Draw each individual instance. We don't bother culling each
|
// Draw each individual instance. We don't bother culling each
|
||||||
// individual Geom for each instance; that is probably way too slow.
|
// individual Geom for each instance; that is probably way too slow.
|
||||||
CullableObject *object =
|
CullableObject *object =
|
||||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||||
object->_instances = data._instances;
|
object->_instances = data._instances;
|
||||||
trav->get_cull_handler()->record_object(object, trav);
|
trav->get_cull_handler()->record_object(object, trav);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cull the Geom bounding volume against the view frustum andor the cull
|
// Cull the individual Geom against the view frustum.
|
||||||
// planes. Don't bother unless we've got more than one Geom, since
|
if (data._view_frustum != nullptr &&
|
||||||
// otherwise the bounding volume of the GeomNode is (probably) the same as
|
!geom->is_in_view(data._view_frustum, current_thread)) {
|
||||||
// that of the one Geom, and we've already culled against that.
|
// Cull this Geom.
|
||||||
if (num_geoms > 1) {
|
continue;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!data._cull_planes->is_empty()) {
|
if (!data._cull_planes->is_empty()) {
|
||||||
// Also cull the Geom against the cull planes.
|
// Also cull the Geom against the cull planes.
|
||||||
@ -567,11 +573,11 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CullableObject *object =
|
CullableObject *object =
|
||||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||||
trav->get_cull_handler()->record_object(object, trav);
|
trav->get_cull_handler()->record_object(object, trav);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user