mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
pgraphnodes: Support hardware instancing for LODNode
LODNode will now correctly calculate LOD for individual instances. It turns out implementing it for FadeLODNode is hard (wrt. tracking state for individual instances) so I have not bothered with supporting it - FadeLODNode instead calculates a single switch level for all instances based on the centroid of the visible instances.
This commit is contained in:
parent
e13756f43e
commit
615502aef6
@ -143,18 +143,22 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
|||||||
CDReader cdata(_cycler);
|
CDReader cdata(_cycler);
|
||||||
|
|
||||||
CPT(TransformState) rel_transform = get_rel_transform(trav, data);
|
CPT(TransformState) rel_transform = get_rel_transform(trav, data);
|
||||||
|
PN_stdfloat lod_scale = cdata->_lod_scale *
|
||||||
|
trav->get_scene()->get_camera_node()->get_lod_scale();
|
||||||
|
|
||||||
|
int num_children = std::min(get_num_children(), (int)cdata->_switch_vector.size());
|
||||||
|
|
||||||
|
if (data._instances == nullptr || cdata->_got_force_switch) {
|
||||||
LPoint3 center = cdata->_center * rel_transform->get_mat();
|
LPoint3 center = cdata->_center * rel_transform->get_mat();
|
||||||
PN_stdfloat dist2 = center.dot(center);
|
PN_stdfloat dist2 = center.dot(center);
|
||||||
|
|
||||||
int num_children = std::min(get_num_children(), (int)cdata->_switch_vector.size());
|
|
||||||
for (int index = 0; index < num_children; ++index) {
|
for (int index = 0; index < num_children; ++index) {
|
||||||
const Switch &sw = cdata->_switch_vector[index];
|
const Switch &sw = cdata->_switch_vector[index];
|
||||||
bool in_range;
|
bool in_range;
|
||||||
if (cdata->_got_force_switch) {
|
if (cdata->_got_force_switch) {
|
||||||
in_range = (cdata->_force_switch == index);
|
in_range = (cdata->_force_switch == index);
|
||||||
} else {
|
} else {
|
||||||
in_range = sw.in_range_2(dist2 * cdata->_lod_scale
|
in_range = sw.in_range_2(dist2 * lod_scale);
|
||||||
* trav->get_scene()->get_camera_node()->get_lod_scale());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_range) {
|
if (in_range) {
|
||||||
@ -166,6 +170,40 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Figure out which instances in which switch levels should be visible.
|
||||||
|
size_t num_instances = data._instances->size();
|
||||||
|
std::unique_ptr<BitArray[]> in_range(new BitArray[num_children]);
|
||||||
|
|
||||||
|
for (size_t ii = 0; ii < num_instances; ++ii) {
|
||||||
|
LPoint3 inst_center = cdata->_center *
|
||||||
|
rel_transform->compose((*data._instances)[ii].get_transform())->get_mat();
|
||||||
|
PN_stdfloat dist2 = inst_center.dot(inst_center);
|
||||||
|
|
||||||
|
for (int index = 0; index < num_children; ++index) {
|
||||||
|
const Switch &sw = cdata->_switch_vector[index];
|
||||||
|
if (!sw.in_range_2(dist2 * lod_scale)) {
|
||||||
|
in_range[index].set_bit(ii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < num_children; ++index) {
|
||||||
|
const Switch &sw = cdata->_switch_vector[index];
|
||||||
|
|
||||||
|
CPT(InstanceList) instances = data._instances->without(in_range[index]);
|
||||||
|
if (!instances->empty()) {
|
||||||
|
// At least one instance is visible in this switch level.
|
||||||
|
PandaNode *child = get_child(index);
|
||||||
|
if (child != nullptr) {
|
||||||
|
CullTraverserData next_data(data, child);
|
||||||
|
next_data._instances = instances;
|
||||||
|
trav->traverse(next_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now return false indicating that we have already taken care of the
|
// Now return false indicating that we have already taken care of the
|
||||||
// traversal from here.
|
// traversal from here.
|
||||||
@ -321,13 +359,30 @@ compute_child(CullTraverser *trav, CullTraverserData &data) {
|
|||||||
return cdata->_force_switch;
|
return cdata->_force_switch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PN_stdfloat lod_scale = cdata->_lod_scale *
|
||||||
|
trav->get_scene()->get_camera_node()->get_lod_scale();
|
||||||
|
|
||||||
CPT(TransformState) rel_transform = get_rel_transform(trav, data);
|
CPT(TransformState) rel_transform = get_rel_transform(trav, data);
|
||||||
LPoint3 center = cdata->_center * rel_transform->get_mat();
|
LPoint3 center;
|
||||||
|
|
||||||
|
if (data._instances == nullptr) {
|
||||||
|
center = cdata->_center * rel_transform->get_mat();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Can't really do much with instancing in FadeLODNode; let's instead
|
||||||
|
// just calculate the centroid of the visible instances.
|
||||||
|
center = LPoint3(0);
|
||||||
|
for (const InstanceList::Instance &instance : *data._instances) {
|
||||||
|
center += cdata->_center *
|
||||||
|
rel_transform->compose(instance.get_transform())->get_mat();
|
||||||
|
}
|
||||||
|
center *= 1.0 / data._instances->size();
|
||||||
|
}
|
||||||
|
|
||||||
PN_stdfloat dist2 = center.dot(center);
|
PN_stdfloat dist2 = center.dot(center);
|
||||||
|
|
||||||
for (int index = 0; index < (int)cdata->_switch_vector.size(); ++index) {
|
for (int index = 0; index < (int)cdata->_switch_vector.size(); ++index) {
|
||||||
if (cdata->_switch_vector[index].in_range_2(dist2 * cdata->_lod_scale
|
if (cdata->_switch_vector[index].in_range_2(dist2 * lod_scale)) {
|
||||||
* trav->get_scene()->get_camera_node()->get_lod_scale())) {
|
|
||||||
if (pgraph_cat.is_debug()) {
|
if (pgraph_cat.is_debug()) {
|
||||||
pgraph_cat.debug()
|
pgraph_cat.debug()
|
||||||
<< data.get_node_path() << " at distance " << sqrt(dist2)
|
<< data.get_node_path() << " at distance " << sqrt(dist2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user