30 if (empty ==
nullptr) {
45 xform(
const LMatrix4 &mat)
const {
53 for (Planes::iterator pi = new_planes->_planes.begin();
54 pi != new_planes->_planes.end();
56 if ((*pi).second->get_ref_count() != 1) {
57 (*pi).second = DCAST(
BoundingPlane, (*pi).second->make_copy());
59 (*pi).second->xform(mat);
62 for (Occluders::iterator oi = new_planes->_occluders.begin();
63 oi != new_planes->_occluders.end();
65 if ((*oi).second->get_ref_count() != 1) {
68 (*oi).second->xform(mat);
87 if (net_attrib ==
nullptr && node_effect ==
nullptr) {
100 if (net_attrib !=
nullptr) {
102 for (
int i = 0; i < num_on_planes; ++i) {
104 Planes::const_iterator pi = new_planes->_planes.find(clip_plane);
105 if (pi == new_planes->_planes.end()) {
109 if (net_transform ==
nullptr) {
110 net_transform = data->get_net_transform(trav);
115 net_transform->invert_compose(clip_plane.get_net_transform());
117 LPlane plane = plane_node->
get_plane() * new_transform->get_mat();
124 if (node_effect !=
nullptr) {
131 for (
int i = 0; i < num_on_occluders; ++i) {
133 Occluders::const_iterator oi = new_planes->_occluders.find(occluder);
134 if (oi == new_planes->_occluders.end()) {
143 if (center_transform ==
nullptr) {
144 if (net_transform ==
nullptr) {
145 net_transform = data->get_net_transform(trav);
148 center_transform = net_transform->invert_compose(scene->
get_cull_center().get_net_transform());
160 CPT(
TransformState) composed_transform = center_transform->compose(occluder_transform);
161 const LMatrix4 &composed_mat = composed_transform->get_mat();
163 ccp[0] = occluder_node->
get_vertex(0) * composed_mat;
164 ccp[1] = occluder_node->
get_vertex(1) * composed_mat;
165 ccp[2] = occluder_node->
get_vertex(2) * composed_mat;
166 ccp[3] = occluder_node->
get_vertex(3) * composed_mat;
168 LPoint3 ccp_min(min(min(ccp[0][0], ccp[1][0]),
169 min(ccp[2][0], ccp[3][0])),
170 min(min(ccp[0][1], ccp[1][1]),
171 min(ccp[2][1], ccp[3][1])),
172 min(min(ccp[0][2], ccp[1][2]),
173 min(ccp[2][2], ccp[3][2])));
174 LPoint3 ccp_max(max(max(ccp[0][0], ccp[1][0]),
175 max(ccp[2][0], ccp[3][0])),
176 max(max(ccp[0][1], ccp[1][1]),
177 max(ccp[2][1], ccp[3][1])),
178 max(max(ccp[0][2], ccp[1][2]),
179 max(ccp[2][2], ccp[3][2])));
183 if (data->_view_frustum !=
nullptr) {
184 int occluder_result = data->_view_frustum->contains(occluder_gbv);
185 if (occluder_result == BoundingVolume::IF_no_intersection) {
187 if (pgraph_cat.is_spam()) {
189 <<
"Ignoring occluder " << occluder <<
": outside view frustum.\n";
196 const LMatrix4 &occluder_mat_cull = occluder_transform->
get_mat();
197 LPoint3 points_near[4];
198 points_near[0] = occluder_node->
get_vertex(0) * occluder_mat_cull;
199 points_near[1] = occluder_node->
get_vertex(1) * occluder_mat_cull;
200 points_near[2] = occluder_node->
get_vertex(2) * occluder_mat_cull;
201 points_near[3] = occluder_node->
get_vertex(3) * occluder_mat_cull;
202 LPlane plane(points_near[0], points_near[1], points_near[2]);
204 if (plane.get_normal().dot(LVector3::forward()) >= 0.0) {
206 std::swap(points_near[0], points_near[3]);
207 std::swap(points_near[1], points_near[2]);
208 plane = LPlane(points_near[0], points_near[1], points_near[2]);
211 if (pgraph_cat.is_spam()) {
213 <<
"Ignoring occluder " << occluder <<
": wrong direction.\n";
221 lens->
project(points_near[0], coords[0]);
222 lens->
project(points_near[1], coords[1]);
223 lens->
project(points_near[2], coords[2]);
224 lens->
project(points_near[3], coords[3]);
225 coords[0][0] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[0][0]));
226 coords[0][1] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[0][1]));
227 coords[1][0] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[1][0]));
228 coords[1][1] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[1][1]));
229 coords[2][0] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[2][0]));
230 coords[2][1] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[2][1]));
231 coords[3][0] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[3][0]));
232 coords[3][1] = max((PN_stdfloat)-1.0, min((PN_stdfloat)1.0, coords[3][1]));
233 PN_stdfloat coverage = ((coords[0] - coords[1]).cross(coords[0] - coords[2]).length()
234 + (coords[3] - coords[1]).cross(coords[3] - coords[2]).length())
236 if (coverage < occluder_node->get_min_coverage()) {
238 if (pgraph_cat.is_spam()) {
240 <<
"Ignoring occluder " << occluder <<
": coverage less than minimum.\n";
248 bool is_enclosed =
false;
249 Occluders::const_iterator oi;
250 for (oi = _occluders.begin(); oi != _occluders.end(); ++oi) {
251 int occluder_result = (*oi).second->contains(occluder_gbv);
252 if ((occluder_result & BoundingVolume::IF_all) != 0) {
259 if (pgraph_cat.is_spam()) {
261 <<
"Ignoring occluder " << occluder <<
": behind another.\n";
269 const LMatrix4 &occluder_mat = occluder.get_net_transform()->
get_mat();
270 points_near[0] = occluder_node->
get_vertex(0) * occluder_mat;
271 points_near[1] = occluder_node->
get_vertex(1) * occluder_mat;
272 points_near[2] = occluder_node->
get_vertex(2) * occluder_mat;
273 points_near[3] = occluder_node->
get_vertex(3) * occluder_mat;
279 LPoint3 points_far[4];
280 points_far[0] = normalize(points_near[0] - center) * far_clip + points_near[0];
281 points_far[1] = normalize(points_near[1] - center) * far_clip + points_near[1];
282 points_far[2] = normalize(points_near[2] - center) * far_clip + points_near[2];
283 points_far[3] = normalize(points_near[3] - center) * far_clip + points_near[3];
289 points_near[1], points_near[2], points_near[3], points_near[0]);
291 new_planes->_occluders[occluder] = frustum;
293 if (show_occluder_volumes) {
295 nassertr(net_transform !=
nullptr, new_planes);
319 BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
324 if (!state->get_attrib(orig_cpa)) {
329 planes->_occluders = _occluders;
335 Planes::const_iterator pi;
336 for (pi = _planes.begin(); pi != _planes.end(); ++pi) {
337 int plane_result = (*pi).second->contains(node_gbv);
338 if (plane_result == BoundingVolume::IF_no_intersection) {
342 result = plane_result;
344 }
else if ((plane_result & BoundingVolume::IF_all) != 0) {
347 new_planes = new_planes->remove_plane((*pi).first);
348 nassertr(new_planes !=
this, new_planes);
349 new_cpa = DCAST(
ClipPlaneAttrib, new_cpa->remove_on_plane((*pi).first));
352 result &= plane_result;
355 if (new_cpa != orig_cpa) {
356 if (new_cpa->is_identity()) {
357 state = state->remove_attrib(ClipPlaneAttrib::get_class_slot());
359 state = state->add_attrib(new_cpa);
364 Occluders::const_iterator oi;
365 for (oi = _occluders.begin(); oi != _occluders.end(); ++oi) {
366 int occluder_result = (*oi).second->contains(node_gbv);
367 if (occluder_result == BoundingVolume::IF_no_intersection) {
374 occluder_result = BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
375 new_planes = new_planes->remove_occluder((*oi).first);
376 nassertr(new_planes !=
this, new_planes);
378 }
else if ((occluder_result & BoundingVolume::IF_all) != 0) {
381 result = BoundingVolume::IF_no_intersection;
385 result &= occluder_result;
396 remove_plane(
const NodePath &clip_plane)
const {
404 Planes::iterator pi = new_planes->_planes.find(clip_plane);
405 nassertr(pi != new_planes->_planes.end(), new_planes);
406 new_planes->_planes.erase(pi);
416 remove_occluder(
const NodePath &occluder)
const {
424 Occluders::iterator pi = new_planes->_occluders.find(occluder);
425 nassertr(pi != new_planes->_occluders.end(), new_planes);
426 new_planes->_occluders.erase(pi);
435 write(std::ostream &out)
const {
436 out <<
"CullPlanes (" << _planes.size() <<
" planes and "
437 << _occluders.size() <<
" occluders):\n";
438 Planes::const_iterator pi;
439 for (pi = _planes.begin(); pi != _planes.end(); ++pi) {
440 out <<
" " << (*pi).first <<
" : " << *(*pi).second <<
"\n";
443 Occluders::const_iterator oi;
444 for (oi = _occluders.begin(); oi != _occluders.end(); ++oi) {
445 out <<
" " << (*oi).first <<
" : " << *(*oi).second <<
"\n";