mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
fix problem with local transform on occluder; add egg bface support for occluders
This commit is contained in:
parent
b099e2d063
commit
19d52c3221
@ -1320,6 +1320,15 @@ GROUPING ENTRIES
|
|||||||
is constant-color or a related option, this defines the constant
|
is constant-color or a related option, this defines the constant
|
||||||
color that will be used.
|
color that will be used.
|
||||||
|
|
||||||
|
<Scalar> occluder { boolean-value }
|
||||||
|
|
||||||
|
This makes the first (or only) polygon within this group node into
|
||||||
|
an occluder. The polygon must have exactly four vertices. An
|
||||||
|
occluder polygon is invisible. When the occluder is activated
|
||||||
|
with model.set_occluder(occluder), objects that are behind the
|
||||||
|
occluder will not be drawn. This can be a useful rendering
|
||||||
|
optimization for complex scenes, but should not be overused or
|
||||||
|
performance can suffer.
|
||||||
|
|
||||||
OTHER GROUP ATTRIBUTES
|
OTHER GROUP ATTRIBUTES
|
||||||
|
|
||||||
|
@ -233,19 +233,19 @@ write(ostream &out, int indent_level) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(get_scroll_u() != 0) {
|
if(get_scroll_u() != 0) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> scroll_u { " << get_scroll_u() << " }\n";
|
<< "<Scalar> scroll_u { " << get_scroll_u() << " }\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_scroll_v() != 0) {
|
if(get_scroll_v() != 0) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> scroll_v { " << get_scroll_v() << " }\n";
|
<< "<Scalar> scroll_v { " << get_scroll_v() << " }\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_scroll_r() != 0) {
|
if(get_scroll_r() != 0) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> scroll_r { " << get_scroll_r() << " }\n";
|
<< "<Scalar> scroll_r { " << get_scroll_r() << " }\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -257,46 +257,46 @@ write(ostream &out, int indent_level) const {
|
|||||||
write_render_mode(out, indent_level + 2);
|
write_render_mode(out, indent_level + 2);
|
||||||
|
|
||||||
if (get_portal_flag()) {
|
if (get_portal_flag()) {
|
||||||
indent(out, indent_level) << "<Scalar> portal { 1 }\n";
|
indent(out, indent_level + 2) << "<Scalar> portal { 1 }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_occluder_flag()) {
|
if (get_occluder_flag()) {
|
||||||
indent(out, indent_level) << "<Scalar> occluder { 1 }\n";
|
indent(out, indent_level + 2) << "<Scalar> occluder { 1 }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_polylight_flag()) {
|
if (get_polylight_flag()) {
|
||||||
indent(out, indent_level) << "<Scalar> polylight { 1 }\n";
|
indent(out, indent_level + 2) << "<Scalar> polylight { 1 }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_indexed_flag()) {
|
if (has_indexed_flag()) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> indexed { " << get_indexed_flag() << " }\n";
|
<< "<Scalar> indexed { " << get_indexed_flag() << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_blend_mode() != BM_unspecified) {
|
if (get_blend_mode() != BM_unspecified) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blend { " << get_blend_mode() << " }\n";
|
<< "<Scalar> blend { " << get_blend_mode() << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_blend_operand_a() != BO_unspecified) {
|
if (get_blend_operand_a() != BO_unspecified) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blendop-a { " << get_blend_operand_a() << " }\n";
|
<< "<Scalar> blendop-a { " << get_blend_operand_a() << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_blend_operand_b() != BO_unspecified) {
|
if (get_blend_operand_b() != BO_unspecified) {
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blendop-b { " << get_blend_operand_b() << " }\n";
|
<< "<Scalar> blendop-b { " << get_blend_operand_b() << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_blend_color()) {
|
if (has_blend_color()) {
|
||||||
const Colorf &c = get_blend_color();
|
const Colorf &c = get_blend_color();
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blendr { " << c[0] << " }\n";
|
<< "<Scalar> blendr { " << c[0] << " }\n";
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blendg { " << c[1] << " }\n";
|
<< "<Scalar> blendg { " << c[1] << " }\n";
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blendb { " << c[2] << " }\n";
|
<< "<Scalar> blendb { " << c[2] << " }\n";
|
||||||
indent(out, indent_level)
|
indent(out, indent_level + 2)
|
||||||
<< "<Scalar> blenda { " << c[3] << " }\n";
|
<< "<Scalar> blenda { " << c[3] << " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2648,6 +2648,10 @@ set_occluder_polygon(EggGroup *egg_group, OccluderNode *pnode) {
|
|||||||
LCAST(float, v1),
|
LCAST(float, v1),
|
||||||
LCAST(float, v2),
|
LCAST(float, v2),
|
||||||
LCAST(float, v3));
|
LCAST(float, v3));
|
||||||
|
|
||||||
|
if (poly->get_bface_flag()) {
|
||||||
|
pnode->set_double_sided(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "dataGraphTraverser.h"
|
#include "dataGraphTraverser.h"
|
||||||
#include "depthOffsetAttrib.h"
|
#include "depthOffsetAttrib.h"
|
||||||
#include "collisionNode.h"
|
#include "collisionNode.h"
|
||||||
|
#include "occluderNode.h"
|
||||||
#include "config_framework.h"
|
#include "config_framework.h"
|
||||||
#include "graphicsPipeSelection.h"
|
#include "graphicsPipeSelection.h"
|
||||||
#include "nodePathCollection.h"
|
#include "nodePathCollection.h"
|
||||||
@ -712,15 +713,16 @@ set_background_type(WindowFramework::BackgroundType type) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaFramework::hide_collision_solids
|
// Function: PandaFramework::hide_collision_solids
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Hides any collision solids which are visible in the
|
// Description: Hides any collision solids, or occluders, which are
|
||||||
// indicated scene graph. Returns the number of
|
// visible in the indicated scene graph. Returns the
|
||||||
// collision solids hidden.
|
// number of nodes hidden.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int PandaFramework::
|
int PandaFramework::
|
||||||
hide_collision_solids(NodePath node) {
|
hide_collision_solids(NodePath node) {
|
||||||
int num_changed = 0;
|
int num_changed = 0;
|
||||||
|
|
||||||
if (node.node()->is_of_type(CollisionNode::get_class_type())) {
|
if (node.node()->is_of_type(CollisionNode::get_class_type()) ||
|
||||||
|
node.node()->is_of_type(OccluderNode::get_class_type())) {
|
||||||
if (!node.is_hidden()) {
|
if (!node.is_hidden()) {
|
||||||
node.hide();
|
node.hide();
|
||||||
num_changed++;
|
num_changed++;
|
||||||
@ -738,15 +740,16 @@ hide_collision_solids(NodePath node) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaFramework::show_collision_solids
|
// Function: PandaFramework::show_collision_solids
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Shows any collision solids which are directly hidden
|
// Description: Shows any collision solids, or occluders, which are
|
||||||
// in the indicated scene graph. Returns the number of
|
// directly hidden in the indicated scene graph.
|
||||||
// collision solids shown.
|
// Returns the number of nodes shown.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int PandaFramework::
|
int PandaFramework::
|
||||||
show_collision_solids(NodePath node) {
|
show_collision_solids(NodePath node) {
|
||||||
int num_changed = 0;
|
int num_changed = 0;
|
||||||
|
|
||||||
if (node.node()->is_of_type(CollisionNode::get_class_type())) {
|
if (node.node()->is_of_type(CollisionNode::get_class_type()) ||
|
||||||
|
node.node()->is_of_type(OccluderNode::get_class_type())) {
|
||||||
if (node.get_hidden_ancestor() == node) {
|
if (node.get_hidden_ancestor() == node) {
|
||||||
node.show();
|
node.show();
|
||||||
num_changed++;
|
num_changed++;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "cullTraverserData.h"
|
#include "cullTraverserData.h"
|
||||||
#include "clipPlaneAttrib.h"
|
#include "clipPlaneAttrib.h"
|
||||||
#include "occluderEffect.h"
|
#include "occluderEffect.h"
|
||||||
|
#include "boundingBox.h"
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -156,17 +157,48 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compare the occluder node's bounding volume to the view
|
// Compare the occluder node's bounding volume to the view
|
||||||
// frustum.
|
// frustum. We construct a new bounding volume because (a)
|
||||||
PT(GeometricBoundingVolume) occluder_gbv = DCAST(GeometricBoundingVolume, occluder_node->get_internal_bounds()->make_copy());
|
// the node's existing bounding volume is in the coordinate
|
||||||
{
|
// space of its parent, which isn't what we have here, and (b)
|
||||||
CPT(TransformState) composed_transform = occluder_transform->compose(center_transform);
|
// we might as well make a BoundingBox, which is as tight as
|
||||||
occluder_gbv->xform(composed_transform->get_mat());
|
// possible, and creating one isn't any less efficient than
|
||||||
|
// transforming the existing bounding volume.
|
||||||
|
PT(BoundingBox) occluder_gbv;
|
||||||
|
{
|
||||||
|
// Get a transform from the occluder directly to this node's
|
||||||
|
// space for comparing with the current view frustum.
|
||||||
|
CPT(TransformState) composed_transform = center_transform->compose(occluder_transform);
|
||||||
|
const LMatrix4f &composed_mat = composed_transform->get_mat();
|
||||||
|
LPoint3f ccp[4];
|
||||||
|
ccp[0] = occluder_node->get_vertex(0) * composed_mat;
|
||||||
|
ccp[1] = occluder_node->get_vertex(1) * composed_mat;
|
||||||
|
ccp[2] = occluder_node->get_vertex(2) * composed_mat;
|
||||||
|
ccp[3] = occluder_node->get_vertex(3) * composed_mat;
|
||||||
|
|
||||||
|
LPoint3f ccp_min(min(min(ccp[0][0], ccp[1][0]),
|
||||||
|
min(ccp[2][0], ccp[3][0])),
|
||||||
|
min(min(ccp[0][1], ccp[1][1]),
|
||||||
|
min(ccp[2][1], ccp[3][1])),
|
||||||
|
min(min(ccp[0][2], ccp[1][2]),
|
||||||
|
min(ccp[2][2], ccp[3][2])));
|
||||||
|
LPoint3f ccp_max(max(max(ccp[0][0], ccp[1][0]),
|
||||||
|
max(ccp[2][0], ccp[3][0])),
|
||||||
|
max(max(ccp[0][1], ccp[1][1]),
|
||||||
|
max(ccp[2][1], ccp[3][1])),
|
||||||
|
max(max(ccp[0][2], ccp[1][2]),
|
||||||
|
max(ccp[2][2], ccp[3][2])));
|
||||||
|
|
||||||
|
occluder_gbv = new BoundingBox(ccp_min, ccp_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->_view_frustum != (GeometricBoundingVolume *)NULL) {
|
if (data->_view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||||
int occluder_result = data->_view_frustum->contains(occluder_gbv);
|
int occluder_result = data->_view_frustum->contains(occluder_gbv);
|
||||||
if (occluder_result == BoundingVolume::IF_no_intersection) {
|
if (occluder_result == BoundingVolume::IF_no_intersection) {
|
||||||
// This occluder is outside the view frustum; ignore it.
|
// This occluder is outside the view frustum; ignore it.
|
||||||
|
if (pgraph_cat.is_spam()) {
|
||||||
|
pgraph_cat.spam()
|
||||||
|
<< "Ignoring occluder " << occluder << ": outside view frustum.\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,6 +217,10 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
if (is_enclosed) {
|
if (is_enclosed) {
|
||||||
// No reason to add this occluder; it's behind an existing
|
// No reason to add this occluder; it's behind an existing
|
||||||
// occluder.
|
// occluder.
|
||||||
|
if (pgraph_cat.is_spam()) {
|
||||||
|
pgraph_cat.spam()
|
||||||
|
<< "Ignoring occluder " << occluder << ": behind another.\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// TODO: perhaps we should also check whether any existing
|
// TODO: perhaps we should also check whether any existing
|
||||||
@ -192,7 +228,7 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
|
|
||||||
// Get the occluder geometry in cull-center space.
|
// Get the occluder geometry in cull-center space.
|
||||||
const LMatrix4f &occluder_mat = occluder_transform->get_mat();
|
const LMatrix4f &occluder_mat = occluder_transform->get_mat();
|
||||||
Vertexf points_near[4];
|
LPoint3f points_near[4];
|
||||||
points_near[0] = occluder_node->get_vertex(0) * occluder_mat;
|
points_near[0] = occluder_node->get_vertex(0) * occluder_mat;
|
||||||
points_near[1] = occluder_node->get_vertex(1) * occluder_mat;
|
points_near[1] = occluder_node->get_vertex(1) * occluder_mat;
|
||||||
points_near[2] = occluder_node->get_vertex(2) * occluder_mat;
|
points_near[2] = occluder_node->get_vertex(2) * occluder_mat;
|
||||||
@ -206,6 +242,10 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
plane = Planef(points_near[0], points_near[1], points_near[2]);
|
plane = Planef(points_near[0], points_near[1], points_near[2]);
|
||||||
} else {
|
} else {
|
||||||
// This occluder is facing the wrong direction. Ignore it.
|
// This occluder is facing the wrong direction. Ignore it.
|
||||||
|
if (pgraph_cat.is_spam()) {
|
||||||
|
pgraph_cat.spam()
|
||||||
|
<< "Ignoring occluder " << occluder << ": wrong direction.\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,6 +253,10 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
float near_clip = scene->get_lens()->get_near();
|
float near_clip = scene->get_lens()->get_near();
|
||||||
if (plane.dist_to_plane(LPoint3f::zero()) <= near_clip) {
|
if (plane.dist_to_plane(LPoint3f::zero()) <= near_clip) {
|
||||||
// This occluder is behind the camera's near plane. Ignore it.
|
// This occluder is behind the camera's near plane. Ignore it.
|
||||||
|
if (pgraph_cat.is_spam()) {
|
||||||
|
pgraph_cat.spam()
|
||||||
|
<< "Ignoring occluder " << occluder << ": behind near plane.\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +267,10 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
if (d0 <= near_clip && d1 <= near_clip && d2 <= near_clip && d3 <= near_clip) {
|
if (d0 <= near_clip && d1 <= near_clip && d2 <= near_clip && d3 <= near_clip) {
|
||||||
// All four corners of the occluder are behind the camera's
|
// All four corners of the occluder are behind the camera's
|
||||||
// near plane. Ignore it.
|
// near plane. Ignore it.
|
||||||
|
if (pgraph_cat.is_spam()) {
|
||||||
|
pgraph_cat.spam()
|
||||||
|
<< "Ignoring occluder " << occluder << ": behind near plane (test 2).\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,11 +280,15 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
|
|||||||
// proper fix for this is to clip the polygon against the near
|
// proper fix for this is to clip the polygon against the near
|
||||||
// plane, producing a smaller polygon, and use that to
|
// plane, producing a smaller polygon, and use that to
|
||||||
// generate the frustum. But maybe it doesn't matter. In
|
// generate the frustum. But maybe it doesn't matter. In
|
||||||
// lieu of this, we just toss out any polygon with *any*
|
// lieu of this, we just toss out any occluder with *any*
|
||||||
// corner behind the y = 0 plane.
|
// corner behind the y = 0 plane.
|
||||||
if (d0 <= 0.0 || d1 <= 0.0 || d2 <= 0.0 || d3 <= 0.0) {
|
if (d0 <= 0.0 || d1 <= 0.0 || d2 <= 0.0 || d3 <= 0.0) {
|
||||||
// One of the corners is behind the y = 0 plane. We can't
|
// One of the corners is behind the y = 0 plane. We can't
|
||||||
// handle this case. Ignore it.
|
// handle this case. Ignore it.
|
||||||
|
if (pgraph_cat.is_spam()) {
|
||||||
|
pgraph_cat.spam()
|
||||||
|
<< "Ignoring occluder " << occluder << ": partly behind zero plane.\n";
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +126,11 @@ void OccluderNode::
|
|||||||
xform(const LMatrix4f &mat) {
|
xform(const LMatrix4f &mat) {
|
||||||
nassertv(!mat.is_nan());
|
nassertv(!mat.is_nan());
|
||||||
|
|
||||||
|
for (Vertices::iterator vi = _vertices.begin();
|
||||||
|
vi != _vertices.end();
|
||||||
|
++vi) {
|
||||||
|
(*vi) = (*vi) * mat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user