fix problem with local transform on occluder; add egg bface support for occluders

This commit is contained in:
David Rose 2011-03-18 19:02:46 +00:00
parent b099e2d063
commit 19d52c3221
6 changed files with 102 additions and 29 deletions

View File

@ -1320,6 +1320,15 @@ GROUPING ENTRIES
is constant-color or a related option, this defines the constant
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

View File

@ -233,19 +233,19 @@ write(ostream &out, int indent_level) const {
}
if(get_scroll_u() != 0) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> scroll_u { " << get_scroll_u() << " }\n";
}
if(get_scroll_v() != 0) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> scroll_v { " << get_scroll_v() << " }\n";
}
if(get_scroll_r() != 0) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<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);
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()) {
indent(out, indent_level) << "<Scalar> occluder { 1 }\n";
indent(out, indent_level + 2) << "<Scalar> occluder { 1 }\n";
}
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()) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> indexed { " << get_indexed_flag() << " }\n";
}
if (get_blend_mode() != BM_unspecified) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blend { " << get_blend_mode() << " }\n";
}
if (get_blend_operand_a() != BO_unspecified) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blendop-a { " << get_blend_operand_a() << " }\n";
}
if (get_blend_operand_b() != BO_unspecified) {
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blendop-b { " << get_blend_operand_b() << " }\n";
}
if (has_blend_color()) {
const Colorf &c = get_blend_color();
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blendr { " << c[0] << " }\n";
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blendg { " << c[1] << " }\n";
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blendb { " << c[2] << " }\n";
indent(out, indent_level)
indent(out, indent_level + 2)
<< "<Scalar> blenda { " << c[3] << " }\n";
}

View File

@ -2648,6 +2648,10 @@ set_occluder_polygon(EggGroup *egg_group, OccluderNode *pnode) {
LCAST(float, v1),
LCAST(float, v2),
LCAST(float, v3));
if (poly->get_bface_flag()) {
pnode->set_double_sided(true);
}
}
}
}

View File

@ -19,6 +19,7 @@
#include "dataGraphTraverser.h"
#include "depthOffsetAttrib.h"
#include "collisionNode.h"
#include "occluderNode.h"
#include "config_framework.h"
#include "graphicsPipeSelection.h"
#include "nodePathCollection.h"
@ -712,15 +713,16 @@ set_background_type(WindowFramework::BackgroundType type) {
////////////////////////////////////////////////////////////////////
// Function: PandaFramework::hide_collision_solids
// Access: Public
// Description: Hides any collision solids which are visible in the
// indicated scene graph. Returns the number of
// collision solids hidden.
// Description: Hides any collision solids, or occluders, which are
// visible in the indicated scene graph. Returns the
// number of nodes hidden.
////////////////////////////////////////////////////////////////////
int PandaFramework::
hide_collision_solids(NodePath node) {
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()) {
node.hide();
num_changed++;
@ -738,15 +740,16 @@ hide_collision_solids(NodePath node) {
////////////////////////////////////////////////////////////////////
// Function: PandaFramework::show_collision_solids
// Access: Public
// Description: Shows any collision solids which are directly hidden
// in the indicated scene graph. Returns the number of
// collision solids shown.
// Description: Shows any collision solids, or occluders, which are
// directly hidden in the indicated scene graph.
// Returns the number of nodes shown.
////////////////////////////////////////////////////////////////////
int PandaFramework::
show_collision_solids(NodePath node) {
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) {
node.show();
num_changed++;

View File

@ -16,6 +16,7 @@
#include "cullTraverserData.h"
#include "clipPlaneAttrib.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
// frustum.
PT(GeometricBoundingVolume) occluder_gbv = DCAST(GeometricBoundingVolume, occluder_node->get_internal_bounds()->make_copy());
{
CPT(TransformState) composed_transform = occluder_transform->compose(center_transform);
occluder_gbv->xform(composed_transform->get_mat());
// frustum. We construct a new bounding volume because (a)
// the node's existing bounding volume is in the coordinate
// space of its parent, which isn't what we have here, and (b)
// we might as well make a BoundingBox, which is as tight as
// 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) {
int occluder_result = data->_view_frustum->contains(occluder_gbv);
if (occluder_result == BoundingVolume::IF_no_intersection) {
// 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;
}
}
@ -185,6 +217,10 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
if (is_enclosed) {
// No reason to add this occluder; it's behind an existing
// occluder.
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< "Ignoring occluder " << occluder << ": behind another.\n";
}
continue;
}
// 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.
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[1] = occluder_node->get_vertex(1) * 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]);
} else {
// This occluder is facing the wrong direction. Ignore it.
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< "Ignoring occluder " << occluder << ": wrong direction.\n";
}
continue;
}
}
@ -213,6 +253,10 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data,
float near_clip = scene->get_lens()->get_near();
if (plane.dist_to_plane(LPoint3f::zero()) <= near_clip) {
// 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;
}
@ -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) {
// All four corners of the occluder are behind the camera's
// near plane. Ignore it.
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< "Ignoring occluder " << occluder << ": behind near plane (test 2).\n";
}
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
// plane, producing a smaller polygon, and use that to
// 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.
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
// handle this case. Ignore it.
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< "Ignoring occluder " << occluder << ": partly behind zero plane.\n";
}
continue;
}

View File

@ -126,6 +126,11 @@ void OccluderNode::
xform(const LMatrix4f &mat) {
nassertv(!mat.is_nan());
for (Vertices::iterator vi = _vertices.begin();
vi != _vertices.end();
++vi) {
(*vi) = (*vi) * mat;
}
}
////////////////////////////////////////////////////////////////////