mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -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
|
||||
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
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user