mirror of
https://github.com/panda3d/panda3d.git
synced 2026-03-03 05:29:58 -06:00
Remove old decal system to simplify cull/draw process a bit more
This commit is contained in:
@@ -257,12 +257,12 @@ ConfigVariableBool retransform_sprites
|
||||
"necessary in order for fog to work correctly on the sprites."));
|
||||
|
||||
ConfigVariableBool depth_offset_decals
|
||||
("depth-offset-decals", false,
|
||||
("depth-offset-decals", true,
|
||||
PRC_DESC("Set this true to allow decals to be implemented via the advanced "
|
||||
"depth offset feature, if supported, instead of via the traditional "
|
||||
"(and slower) two-pass approach. This is false by default "
|
||||
"because it appears that many graphics drivers have issues with "
|
||||
"their depth offset implementation."));
|
||||
"(and slower) two-pass approach. This is currently the only method "
|
||||
"by which decals are implemented in Panda3D, and as such, this "
|
||||
"setting is ignored."));
|
||||
|
||||
ConfigVariableInt max_collect_vertices
|
||||
("max-collect-vertices", 65534,
|
||||
|
||||
@@ -27,7 +27,7 @@ TypeHandle CullBin::_type_handle;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBin::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBin::
|
||||
~CullBin() {
|
||||
@@ -115,7 +115,7 @@ check_flash_color() {
|
||||
} else {
|
||||
_has_flash_color = false;
|
||||
pgraph_cat.warning()
|
||||
<< "Invalid value for flash-bin-" << _name << ": "
|
||||
<< "Invalid value for flash-bin-" << _name << ": "
|
||||
<< flash_bin.get_string_value() << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
@@ -124,7 +124,7 @@ check_flash_color() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBin::ResultGraphBuilder::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBin::ResultGraphBuilder::
|
||||
ResultGraphBuilder(PandaNode *root_node) :
|
||||
@@ -142,9 +142,8 @@ ResultGraphBuilder(PandaNode *root_node) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBin::ResultGraphBuilder::
|
||||
add_object(CullableObject *object) {
|
||||
if (_current_transform != object->_modelview_transform ||
|
||||
_current_state != object->_state ||
|
||||
object->is_fancy()) {
|
||||
if (_current_transform != object->_modelview_transform ||
|
||||
_current_state != object->_state) {
|
||||
// Create a new GeomNode to hold the net transform and state. We
|
||||
// choose to create a new GeomNode for each new state, to make it
|
||||
// clearer to the observer when the state changes.
|
||||
@@ -157,57 +156,13 @@ add_object(CullableObject *object) {
|
||||
}
|
||||
|
||||
record_one_object(_current_node, object);
|
||||
|
||||
if (object->get_next() != (CullableObject *)NULL) {
|
||||
// Collect the decal base pieces.
|
||||
CullableObject *base = object->get_next();
|
||||
while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
|
||||
record_one_object(_current_node, base);
|
||||
base = base->get_next();
|
||||
}
|
||||
|
||||
if (base != (CullableObject *)NULL) {
|
||||
// Now, collect all the decals.
|
||||
_current_node->set_effect(DecalEffect::make());
|
||||
int decal_index = 0;
|
||||
|
||||
CPT(TransformState) transform;
|
||||
CPT(RenderState) state;
|
||||
PT(GeomNode) decal_node;
|
||||
CullableObject *decal = base->get_next();
|
||||
while (decal != (CullableObject *)NULL) {
|
||||
if (transform != decal->_modelview_transform ||
|
||||
state != decal->_state ||
|
||||
decal->get_next() != (CullableObject *)NULL) {
|
||||
// Create a new GeomNode to hold the net transform.
|
||||
transform = decal->_modelview_transform;
|
||||
state = decal->_state;
|
||||
decal_node = new GeomNode("decal_" + format_string(decal_index));
|
||||
_current_node->add_child(decal_node);
|
||||
decal_node->set_transform(transform);
|
||||
decal_node->set_state(state);
|
||||
}
|
||||
|
||||
record_one_object(decal_node, decal);
|
||||
decal = decal->get_next();
|
||||
++decal_index;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the current node pointer for next time so the decal root
|
||||
// will remain in its own node.
|
||||
_current_node.clear();
|
||||
_current_transform.clear();
|
||||
_current_state.clear();
|
||||
}
|
||||
|
||||
++_object_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBin::ResultGraphBuilder::record_one_object
|
||||
// Access: Private
|
||||
// Description: Records a single object, without regard to decalling.
|
||||
// Description: Records a single object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBin::ResultGraphBuilder::
|
||||
record_one_object(GeomNode *node, CullableObject *object) {
|
||||
|
||||
@@ -57,7 +57,7 @@ static const double bin_color_flash_rate = 1.0; // 1 state change per second
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullResult::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullResult::
|
||||
CullResult(GraphicsStateGuardianBase *gsg,
|
||||
@@ -87,7 +87,7 @@ make_next() const {
|
||||
|
||||
for (size_t i = 0; i < _bins.size(); ++i) {
|
||||
CullBin *old_bin = _bins[i];
|
||||
if (old_bin == (CullBin *)NULL ||
|
||||
if (old_bin == (CullBin *)NULL ||
|
||||
old_bin->get_bin_type() != bin_manager->get_bin_type(i)) {
|
||||
new_result->_bins.push_back((CullBin *)NULL);
|
||||
} else {
|
||||
@@ -166,21 +166,19 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
// later. This means we must copy the object and add it to
|
||||
// both bins. We can only do this if we do not have an
|
||||
// explicit bin already applied; otherwise, M_dual falls back
|
||||
// to M_alpha.
|
||||
// to M_alpha.
|
||||
{
|
||||
const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, state->get_attrib(CullBinAttrib::get_class_slot()));
|
||||
if (bin_attrib == (CullBinAttrib *)NULL ||
|
||||
if (bin_attrib == (CullBinAttrib *)NULL ||
|
||||
bin_attrib->get_bin_name().empty()) {
|
||||
// We make a copy of the object to draw the transparent part
|
||||
// without decals; this gets placed in the transparent bin.
|
||||
// We make a copy of the object to draw the transparent part;
|
||||
// this gets placed in the transparent bin.
|
||||
#ifndef NDEBUG
|
||||
if (m_dual_transparent)
|
||||
if (m_dual_transparent)
|
||||
#endif
|
||||
{
|
||||
CullableObject *transparent_part = new CullableObject(*object);
|
||||
CPT(RenderState) transparent_state = object->has_decals() ?
|
||||
get_dual_transparent_state_decals() :
|
||||
get_dual_transparent_state();
|
||||
CPT(RenderState) transparent_state = get_dual_transparent_state();
|
||||
transparent_part->_state = state->compose(transparent_state);
|
||||
if (transparent_part->munge_geom
|
||||
(_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread),
|
||||
@@ -195,9 +193,9 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
delete transparent_part;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we can draw the opaque part, with decals. This will
|
||||
// end up in the opaque bin.
|
||||
|
||||
// Now we can draw the opaque part. This will end up in
|
||||
// the opaque bin.
|
||||
object->_state = state->compose(get_dual_opaque_state());
|
||||
#ifndef NDEBUG
|
||||
if (!m_dual_opaque) {
|
||||
@@ -210,7 +208,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
// M_alpha.
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// Other kinds of transparency need no special handling.
|
||||
break;
|
||||
@@ -443,8 +441,6 @@ check_flash_transparency(CPT(RenderState) &state, const LColor &transparency) {
|
||||
// Access: Private
|
||||
// Description: Returns a RenderState that renders only the
|
||||
// transparent parts of an object, in support of M_dual.
|
||||
// This state is suitable only for objects that do not
|
||||
// contain decals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) CullResult::
|
||||
get_dual_transparent_state() {
|
||||
@@ -454,10 +450,7 @@ get_dual_transparent_state() {
|
||||
// and hence filling up the depth buffer with large empty spaces
|
||||
// that may obscure other things. However, this does mean we draw
|
||||
// pixels twice where the alpha == 1.0 (since they were already
|
||||
// drawn in the opaque pass). This is not normally a problem,
|
||||
// except when we are using decals; in the case of decals, we
|
||||
// don't want to draw the 1.0 pixels again, since these are the
|
||||
// ones that may have been decaled onto.
|
||||
// drawn in the opaque pass). This is not normally a problem.
|
||||
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
|
||||
TransparencyAttrib::make(TransparencyAttrib::M_alpha),
|
||||
DepthWriteAttrib::make(DepthWriteAttrib::M_off),
|
||||
@@ -487,47 +480,6 @@ get_dual_transparent_state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullResult::get_dual_transparent_state_decals
|
||||
// Access: Private
|
||||
// Description: Returns a RenderState that renders only the
|
||||
// transparent parts of an object, but suitable for
|
||||
// objects that contain decals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) CullResult::
|
||||
get_dual_transparent_state_decals() {
|
||||
static CPT(RenderState) state = NULL;
|
||||
if (state == (const RenderState *)NULL) {
|
||||
// This is exactly the same as above except here we make the alpha
|
||||
// test of < 1.0 instead of > 0.0. This makes us draw big empty
|
||||
// pixels where the alpha values are 0.0, but we don't overwrite
|
||||
// the decals where the pixels are 1.0.
|
||||
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, dual_opaque_level),
|
||||
TransparencyAttrib::make(TransparencyAttrib::M_alpha),
|
||||
DepthWriteAttrib::make(DepthWriteAttrib::M_off),
|
||||
RenderState::get_max_priority());
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (m_dual_flash) {
|
||||
int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
|
||||
if ((cycle & 1) == 0) {
|
||||
static CPT(RenderState) flash_state = NULL;
|
||||
if (flash_state == (const RenderState *)NULL) {
|
||||
flash_state = state->add_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.2, 0.2, 1.0f)),
|
||||
RenderState::get_max_priority());
|
||||
flash_state = flash_state->add_attrib(ColorScaleAttrib::make(LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)),
|
||||
RenderState::get_max_priority());
|
||||
|
||||
}
|
||||
return flash_state;
|
||||
}
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullResult::get_dual_opaque_state
|
||||
// Access: Private
|
||||
|
||||
@@ -72,12 +72,11 @@ private:
|
||||
static CPT(RenderState) get_alpha_state();
|
||||
static CPT(RenderState) get_binary_state();
|
||||
static CPT(RenderState) get_dual_transparent_state();
|
||||
static CPT(RenderState) get_dual_transparent_state_decals();
|
||||
static CPT(RenderState) get_dual_opaque_state();
|
||||
|
||||
GraphicsStateGuardianBase *_gsg;
|
||||
PStatCollector _draw_region_pcollector;
|
||||
|
||||
|
||||
typedef pvector< PT(CullBin) > Bins;
|
||||
Bins _bins;
|
||||
|
||||
@@ -90,7 +89,7 @@ public:
|
||||
register_type(_type_handle, "CullResult",
|
||||
ReferenceCount::get_class_type());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
@@ -99,5 +98,3 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -110,12 +110,12 @@ get_initial_state() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::get_depth_offset_decals
|
||||
// Access: Published
|
||||
// Description: Returns the depth_offset_decals flag. See
|
||||
// set_depth_offset_decals().
|
||||
// Description: Returns true, as depth offsets are the only way
|
||||
// that we implement decals nowadays.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CullTraverser::
|
||||
get_depth_offset_decals() const {
|
||||
return _depth_offset_decals;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -199,7 +199,7 @@ get_cull_handler() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::set_portal_clipper
|
||||
// Access: Published
|
||||
// Description: Specifies _portal_clipper object pointer that
|
||||
// Description: Specifies _portal_clipper object pointer that
|
||||
// subsequent traverse() or traverse_below may use.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullTraverser::
|
||||
|
||||
@@ -47,7 +47,7 @@ TypeHandle CullTraverser::_type_handle;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullTraverser::
|
||||
CullTraverser() :
|
||||
@@ -65,7 +65,7 @@ CullTraverser() :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::Copy Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullTraverser::
|
||||
CullTraverser(const CullTraverser ©) :
|
||||
@@ -76,7 +76,6 @@ CullTraverser(const CullTraverser ©) :
|
||||
_has_tag_state_key(copy._has_tag_state_key),
|
||||
_tag_state_key(copy._tag_state_key),
|
||||
_initial_state(copy._initial_state),
|
||||
_depth_offset_decals(copy._depth_offset_decals),
|
||||
_view_frustum(copy._view_frustum),
|
||||
_cull_handler(copy._cull_handler),
|
||||
_portal_clipper(copy._portal_clipper),
|
||||
@@ -98,7 +97,6 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsg,
|
||||
_gsg = gsg;
|
||||
|
||||
_initial_state = scene_setup->get_initial_state();
|
||||
_depth_offset_decals = _gsg->depth_offset_decals() && depth_offset_decals;
|
||||
|
||||
_current_thread = Thread::get_current_thread();
|
||||
|
||||
@@ -129,43 +127,43 @@ traverse(const NodePath &root) {
|
||||
PT(BoundingVolume) bv = _scene_setup->get_lens()->make_bounds();
|
||||
if (bv != (BoundingVolume *)NULL &&
|
||||
bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
|
||||
|
||||
|
||||
local_frustum = DCAST(GeometricBoundingVolume, bv);
|
||||
}
|
||||
|
||||
|
||||
// This local_frustum is in camera space
|
||||
PortalClipper portal_viewer(local_frustum, _scene_setup);
|
||||
if (debug_portal_cull) {
|
||||
portal_viewer.draw_camera_frustum();
|
||||
}
|
||||
|
||||
|
||||
// Store this pointer in this
|
||||
set_portal_clipper(&portal_viewer);
|
||||
|
||||
CullTraverserData data(root, TransformState::make_identity(),
|
||||
_initial_state, _view_frustum,
|
||||
_initial_state, _view_frustum,
|
||||
_current_thread);
|
||||
|
||||
|
||||
traverse(data);
|
||||
|
||||
|
||||
// Finally add the lines to be drawn
|
||||
if (debug_portal_cull) {
|
||||
portal_viewer.draw_lines();
|
||||
}
|
||||
|
||||
|
||||
// Render the frustum relative to the cull center.
|
||||
NodePath cull_center = _scene_setup->get_cull_center();
|
||||
CPT(TransformState) transform = cull_center.get_transform(root);
|
||||
|
||||
|
||||
CullTraverserData my_data(data, portal_viewer._previous);
|
||||
my_data._net_transform = my_data._net_transform->compose(transform);
|
||||
traverse(my_data);
|
||||
|
||||
} else {
|
||||
CullTraverserData data(root, TransformState::make_identity(),
|
||||
_initial_state, _view_frustum,
|
||||
_initial_state, _view_frustum,
|
||||
_current_thread);
|
||||
|
||||
|
||||
traverse(data);
|
||||
}
|
||||
}
|
||||
@@ -181,7 +179,7 @@ void CullTraverser::
|
||||
traverse(CullTraverserData &data) {
|
||||
if (is_in_view(data)) {
|
||||
if (pgraph_cat.is_spam()) {
|
||||
pgraph_cat.spam()
|
||||
pgraph_cat.spam()
|
||||
<< "\n" << data._node_path
|
||||
<< " " << data._draw_mask << "\n";
|
||||
}
|
||||
@@ -207,9 +205,9 @@ traverse(CullTraverserData &data) {
|
||||
// up now.
|
||||
show_bounds(data, node_effects->has_show_tight_bounds());
|
||||
}
|
||||
|
||||
|
||||
data.apply_transform_and_state(this);
|
||||
|
||||
|
||||
const FogAttrib *fog = DCAST(FogAttrib, node_reader->get_state()->get_attrib(FogAttrib::get_class_slot()));
|
||||
if (fog != (const FogAttrib *)NULL && fog->get_fog() != (Fog *)NULL) {
|
||||
// If we just introduced a FogAttrib here, call adjust_to_camera()
|
||||
@@ -218,7 +216,7 @@ traverse(CullTraverserData &data) {
|
||||
// need for it.
|
||||
fog->get_fog()->adjust_to_camera(get_camera_transform());
|
||||
}
|
||||
|
||||
|
||||
if (fancy_bits & PandaNode::FB_cull_callback) {
|
||||
PandaNode *node = data.node();
|
||||
if (!node->cull_callback(this, data)) {
|
||||
@@ -247,47 +245,41 @@ traverse_below(CullTraverserData &data) {
|
||||
|
||||
const RenderEffects *node_effects = node_reader->get_effects();
|
||||
bool has_decal = !this_node_hidden && node_effects->has_decal();
|
||||
if (has_decal && !_depth_offset_decals) {
|
||||
// Start the three-pass decal rendering if we're not using
|
||||
// DepthOffsetAttribs to implement decals.
|
||||
start_decal(data);
|
||||
|
||||
} else {
|
||||
if (!this_node_hidden) {
|
||||
node->add_for_draw(this, data);
|
||||
}
|
||||
|
||||
if (has_decal) {
|
||||
// If we *are* implementing decals with DepthOffsetAttribs,
|
||||
// apply it now, so that each child of this node gets offset by
|
||||
// a tiny amount.
|
||||
data._state = data._state->compose(get_depth_offset_state());
|
||||
if (!this_node_hidden) {
|
||||
node->add_for_draw(this, data);
|
||||
}
|
||||
|
||||
if (has_decal) {
|
||||
// If we *are* implementing decals with DepthOffsetAttribs,
|
||||
// apply it now, so that each child of this node gets offset by
|
||||
// a tiny amount.
|
||||
data._state = data._state->compose(get_depth_offset_state());
|
||||
#ifndef NDEBUG
|
||||
// This is just a sanity check message.
|
||||
if (!node->is_geom_node()) {
|
||||
pgraph_cat.error()
|
||||
<< "DecalEffect applied to " << *node << ", not a GeomNode.\n";
|
||||
}
|
||||
// This is just a sanity check message.
|
||||
if (!node->is_geom_node()) {
|
||||
pgraph_cat.error()
|
||||
<< "DecalEffect applied to " << *node << ", not a GeomNode.\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Now visit all the node's children.
|
||||
PandaNode::Children children = node_reader->get_children();
|
||||
node_reader->release();
|
||||
int num_children = children.get_num_children();
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
CullTraverserData next_data(data, children.get_child(i));
|
||||
traverse(next_data);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
// Now visit all the node's children.
|
||||
PandaNode::Children children = node_reader->get_children();
|
||||
node_reader->release();
|
||||
int num_children = children.get_num_children();
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
CullTraverserData next_data(data, children.get_child(i));
|
||||
traverse(next_data);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
CullTraverserData next_data(data, children.get_child(i));
|
||||
traverse(next_data);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
CullTraverserData next_data(data, children.get_child(i));
|
||||
traverse(next_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,20 +303,20 @@ end_traverse() {
|
||||
// bounding volume.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullTraverser::
|
||||
draw_bounding_volume(const BoundingVolume *vol,
|
||||
draw_bounding_volume(const BoundingVolume *vol,
|
||||
const TransformState *net_transform,
|
||||
const TransformState *modelview_transform) const {
|
||||
PT(Geom) bounds_viz = make_bounds_viz(vol);
|
||||
|
||||
|
||||
if (bounds_viz != (Geom *)NULL) {
|
||||
_geoms_pcollector.add_level(2);
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||
net_transform, modelview_transform, get_scene());
|
||||
_cull_handler->record_object(outer_viz, this);
|
||||
|
||||
CullableObject *inner_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_inner_viz_state(),
|
||||
|
||||
CullableObject *inner_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_inner_viz_state(),
|
||||
net_transform, modelview_transform, get_scene());
|
||||
_cull_handler->record_object(inner_viz, this);
|
||||
}
|
||||
@@ -360,13 +352,13 @@ show_bounds(CullTraverserData &data, bool tight) {
|
||||
|
||||
if (bounds_viz != (Geom *)NULL) {
|
||||
_geoms_pcollector.add_level(1);
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||
net_transform, modelview_transform,
|
||||
get_scene());
|
||||
_cull_handler->record_object(outer_viz, this);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
draw_bounding_volume(node->get_bounds(),
|
||||
net_transform, modelview_transform);
|
||||
@@ -378,7 +370,7 @@ show_bounds(CullTraverserData &data, bool tight) {
|
||||
GeomNode *gnode = DCAST(GeomNode, node);
|
||||
int num_geoms = gnode->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; ++i) {
|
||||
draw_bounding_volume(gnode->get_geom(i)->get_bounds(),
|
||||
draw_bounding_volume(gnode->get_geom(i)->get_bounds(),
|
||||
net_transform, modelview_transform);
|
||||
}
|
||||
}
|
||||
@@ -407,7 +399,7 @@ make_bounds_viz(const BoundingVolume *vol) {
|
||||
("bounds", GeomVertexFormat::get_v3(),
|
||||
Geom::UH_stream);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
|
||||
|
||||
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
|
||||
for (int sl = 0; sl < num_slices; ++sl) {
|
||||
PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices;
|
||||
@@ -419,11 +411,11 @@ make_bounds_viz(const BoundingVolume *vol) {
|
||||
vertex.add_data3(compute_point(sphere, latitude, longitude1));
|
||||
}
|
||||
vertex.add_data3(compute_point(sphere, 1.0, longitude0));
|
||||
|
||||
|
||||
strip->add_next_vertices(num_stacks * 2);
|
||||
strip->close_primitive();
|
||||
}
|
||||
|
||||
|
||||
geom = new Geom(vdata);
|
||||
geom->add_primitive(strip);
|
||||
|
||||
@@ -438,7 +430,7 @@ make_bounds_viz(const BoundingVolume *vol) {
|
||||
for (int i = 0; i < 8; ++i ) {
|
||||
vertex.add_data3(fvol->get_point(i));
|
||||
}
|
||||
|
||||
|
||||
PT(GeomLines) lines = new GeomLines(Geom::UH_stream);
|
||||
lines->add_vertices(0, 1); lines->close_primitive();
|
||||
lines->add_vertices(1, 2); lines->close_primitive();
|
||||
@@ -472,7 +464,7 @@ make_bounds_viz(const BoundingVolume *vol) {
|
||||
for (int i = 0; i < 8; ++i ) {
|
||||
vertex.add_data3(box.get_point(i));
|
||||
}
|
||||
|
||||
|
||||
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_stream);
|
||||
tris->add_vertices(0, 4, 5);
|
||||
tris->close_primitive();
|
||||
@@ -533,7 +525,7 @@ make_tight_bounds_viz(PandaNode *node) const {
|
||||
Geom::UH_stream);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex(),
|
||||
_current_thread);
|
||||
|
||||
|
||||
vertex.add_data3(n[0], n[1], n[2]);
|
||||
vertex.add_data3(n[0], n[1], x[2]);
|
||||
vertex.add_data3(n[0], x[1], n[2]);
|
||||
@@ -542,7 +534,7 @@ make_tight_bounds_viz(PandaNode *node) const {
|
||||
vertex.add_data3(x[0], n[1], x[2]);
|
||||
vertex.add_data3(x[0], x[1], n[2]);
|
||||
vertex.add_data3(x[0], x[1], x[2]);
|
||||
|
||||
|
||||
PT(GeomLinestrips) strip = new GeomLinestrips(Geom::UH_stream);
|
||||
|
||||
// We wind one long linestrip around the wireframe cube. This
|
||||
@@ -564,7 +556,7 @@ make_tight_bounds_viz(PandaNode *node) const {
|
||||
strip->add_vertex(5);
|
||||
strip->add_vertex(1);
|
||||
strip->close_primitive();
|
||||
|
||||
|
||||
geom = new Geom(vdata);
|
||||
geom->add_primitive(strip);
|
||||
}
|
||||
@@ -576,10 +568,10 @@ make_tight_bounds_viz(PandaNode *node) const {
|
||||
// Function: CullTraverser::compute_point
|
||||
// Access: Private, Static
|
||||
// Description: Returns a point on the surface of the sphere.
|
||||
// latitude and longitude range from 0.0 to 1.0.
|
||||
// latitude and longitude range from 0.0 to 1.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVertex CullTraverser::
|
||||
compute_point(const BoundingSphere *sphere,
|
||||
compute_point(const BoundingSphere *sphere,
|
||||
PN_stdfloat latitude, PN_stdfloat longitude) {
|
||||
PN_stdfloat s1, c1;
|
||||
csincos(latitude * MathNumbers::pi, &s1, &c1);
|
||||
@@ -648,231 +640,3 @@ get_depth_offset_state() {
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::start_decal
|
||||
// Access: Private
|
||||
// Description: Collects a base node and all of the decals applied to
|
||||
// it. This involves recursing below the base GeomNode
|
||||
// to find all the decal geoms.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullTraverser::
|
||||
start_decal(const CullTraverserData &data) {
|
||||
PandaNode *node = data.node();
|
||||
if (!node->is_geom_node()) {
|
||||
pgraph_cat.error()
|
||||
<< "DecalEffect applied to " << *node << ", not a GeomNode.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
const PandaNodePipelineReader *node_reader = data.node_reader();
|
||||
|
||||
// Build a chain of CullableObjects. The head of the chain will be
|
||||
// all of the base Geoms in order, followed by an empty
|
||||
// CullableObject node, followed by all of the decal Geoms, in
|
||||
// order.
|
||||
|
||||
// Since the CullableObject is a linked list which gets built in
|
||||
// LIFO order, we start with the decals.
|
||||
CullableObject *decals = (CullableObject *)NULL;
|
||||
PandaNode::Children cr = node_reader->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
CullTraverserData next_data(data, cr.get_child(i));
|
||||
decals = r_get_decals(next_data, decals);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = num_children - 1; i >= 0; i--) {
|
||||
CullTraverserData next_data(data, cr.get_child(i));
|
||||
decals = r_get_decals(next_data, decals);
|
||||
}
|
||||
}
|
||||
|
||||
// Now create a new, empty CullableObject to separate the decals
|
||||
// from the non-decals.
|
||||
CullableObject *separator = new CullableObject;
|
||||
separator->set_next(decals);
|
||||
|
||||
// And now get the base Geoms, again in reverse order.
|
||||
CullableObject *object = separator;
|
||||
GeomNode *geom_node = DCAST(GeomNode, node);
|
||||
GeomNode::Geoms geoms = geom_node->get_geoms();
|
||||
int num_geoms = geoms.get_num_geoms();
|
||||
_geoms_pcollector.add_level(num_geoms);
|
||||
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||
CPT(TransformState) internal_transform = _scene_setup->get_cs_transform()->compose(modelview_transform);
|
||||
|
||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||
const Geom *geom = geoms.get_geom(i);
|
||||
if (geom->is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||
// Cull.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cull the Geom bounding volume against the view frustum
|
||||
// and/or the cull planes. Don't bother unless we've got more
|
||||
// than one Geom, since otherwise the bounding volume of the
|
||||
// GeomNode is (probably) the same as that of the one Geom,
|
||||
// and we've already culled against that.
|
||||
if (num_geoms > 1) {
|
||||
if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
// Cull the individual Geom against the view frustum.
|
||||
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||
const GeometricBoundingVolume *geom_gbv =
|
||||
DCAST(GeometricBoundingVolume, geom_volume);
|
||||
|
||||
int result = data._view_frustum->contains(geom_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// Cull this Geom.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!data._cull_planes->is_empty()) {
|
||||
// Also cull the Geom against the cull planes.
|
||||
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||
const GeometricBoundingVolume *geom_gbv =
|
||||
DCAST(GeometricBoundingVolume, geom_volume);
|
||||
int result;
|
||||
data._cull_planes->do_cull(result, state, geom_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// Cull.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CullableObject *next = object;
|
||||
object =
|
||||
new CullableObject(geom, state, net_transform,
|
||||
modelview_transform, internal_transform);
|
||||
object->set_next(next);
|
||||
}
|
||||
|
||||
if (object != separator) {
|
||||
// Finally, send the whole list down to the CullHandler for
|
||||
// processing. The first Geom in the node now represents the
|
||||
// overall state.
|
||||
_cull_handler->record_object(object, this);
|
||||
} else {
|
||||
// Never mind; there's nothing to render.
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::r_get_decals
|
||||
// Access: Private
|
||||
// Description: Recursively gets all the decals applied to a
|
||||
// particular GeomNode. These are built into a
|
||||
// CullableObject list in LIFO order (so that the
|
||||
// traversing the list will extract them in the order
|
||||
// they were encountered in the scene graph).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullableObject *CullTraverser::
|
||||
r_get_decals(CullTraverserData &data, CullableObject *decals) {
|
||||
if (is_in_view(data)) {
|
||||
PandaNodePipelineReader *node_reader = data.node_reader();
|
||||
PandaNode *node = data.node();
|
||||
|
||||
const RenderEffects *node_effects = node_reader->get_effects();
|
||||
if (node_effects->has_show_bounds()) {
|
||||
// If we should show the bounding volume for this node, make it
|
||||
// up now.
|
||||
show_bounds(data, node_effects->has_show_tight_bounds());
|
||||
}
|
||||
|
||||
data.apply_transform_and_state(this);
|
||||
|
||||
// First, visit all of the node's children.
|
||||
int num_children = node_reader->get_num_children();
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
CullTraverserData next_data(data, node_reader->get_child(i));
|
||||
decals = r_get_decals(next_data, decals);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = num_children - 1; i >= 0; i--) {
|
||||
CullTraverserData next_data(data, node_reader->get_child(i));
|
||||
decals = r_get_decals(next_data, decals);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, tack on any geoms within the node.
|
||||
if (node->is_geom_node()) {
|
||||
GeomNode *geom_node = DCAST(GeomNode, node);
|
||||
GeomNode::Geoms geoms = geom_node->get_geoms();
|
||||
int num_geoms = geoms.get_num_geoms();
|
||||
_geoms_pcollector.add_level(num_geoms);
|
||||
CPT(TransformState) net_transform = data.get_net_transform(this);
|
||||
CPT(TransformState) modelview_transform = data.get_modelview_transform(this);
|
||||
CPT(TransformState) internal_transform = _scene_setup->get_cs_transform()->compose(modelview_transform);
|
||||
|
||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||
const Geom *geom = geoms.get_geom(i);
|
||||
if (geom->is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
|
||||
if (state->has_cull_callback() && !state->cull_callback(this, data)) {
|
||||
// Cull.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cull the Geom bounding volume against the view frustum
|
||||
// and/or the cull planes. Don't bother unless we've got more
|
||||
// than one Geom, since otherwise the bounding volume of the
|
||||
// GeomNode is (probably) the same as that of the one Geom,
|
||||
// and we've already culled against that.
|
||||
if (num_geoms > 1) {
|
||||
if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
// Cull the individual Geom against the view frustum.
|
||||
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||
const GeometricBoundingVolume *geom_gbv =
|
||||
DCAST(GeometricBoundingVolume, geom_volume);
|
||||
|
||||
int result = data._view_frustum->contains(geom_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// Cull this Geom.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!data._cull_planes->is_empty()) {
|
||||
// Also cull the Geom against the cull planes.
|
||||
CPT(BoundingVolume) geom_volume = geom->get_bounds();
|
||||
const GeometricBoundingVolume *geom_gbv =
|
||||
DCAST(GeometricBoundingVolume, geom_volume);
|
||||
int result;
|
||||
data._cull_planes->do_cull(result, state, geom_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// Cull.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CullableObject *next = decals;
|
||||
decals =
|
||||
new CullableObject(geom, state, net_transform,
|
||||
modelview_transform, internal_transform);
|
||||
decals->set_next(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decals;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ PUBLISHED:
|
||||
|
||||
INLINE static void flush_level();
|
||||
|
||||
void draw_bounding_volume(const BoundingVolume *vol,
|
||||
void draw_bounding_volume(const BoundingVolume *vol,
|
||||
const TransformState *net_transform,
|
||||
const TransformState *modelview_transform) const;
|
||||
|
||||
@@ -105,7 +105,7 @@ private:
|
||||
void show_bounds(CullTraverserData &data, bool tight);
|
||||
static PT(Geom) make_bounds_viz(const BoundingVolume *vol);
|
||||
PT(Geom) make_tight_bounds_viz(PandaNode *node) const;
|
||||
static LVertex compute_point(const BoundingSphere *sphere,
|
||||
static LVertex compute_point(const BoundingSphere *sphere,
|
||||
PN_stdfloat latitude, PN_stdfloat longitude);
|
||||
static CPT(RenderState) get_bounds_outer_viz_state();
|
||||
static CPT(RenderState) get_bounds_inner_viz_state();
|
||||
@@ -121,12 +121,11 @@ private:
|
||||
bool _has_tag_state_key;
|
||||
string _tag_state_key;
|
||||
CPT(RenderState) _initial_state;
|
||||
bool _depth_offset_decals;
|
||||
PT(GeometricBoundingVolume) _view_frustum;
|
||||
CullHandler *_cull_handler;
|
||||
PortalClipper *_portal_clipper;
|
||||
bool _effective_incomplete_render;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
@@ -150,4 +149,4 @@ private:
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Constructor
|
||||
// Access: Public
|
||||
@@ -19,9 +20,7 @@
|
||||
// filled in later.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullableObject::
|
||||
CullableObject() :
|
||||
_fancy(false)
|
||||
{
|
||||
CullableObject() {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
#endif
|
||||
@@ -42,8 +41,7 @@ CullableObject(const Geom *geom, const RenderState *state,
|
||||
_state(state),
|
||||
_net_transform(net_transform),
|
||||
_modelview_transform(modelview_transform),
|
||||
_internal_transform(scene_setup->get_cs_transform()->compose(modelview_transform)),
|
||||
_fancy(false)
|
||||
_internal_transform(scene_setup->get_cs_transform()->compose(modelview_transform))
|
||||
{
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
@@ -65,20 +63,17 @@ CullableObject(const Geom *geom, const RenderState *state,
|
||||
_state(state),
|
||||
_net_transform(net_transform),
|
||||
_modelview_transform(modelview_transform),
|
||||
_internal_transform(internal_transform),
|
||||
_fancy(false)
|
||||
_internal_transform(internal_transform)
|
||||
{
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Copy Constructor
|
||||
// Access: Public
|
||||
// Description: Copies the CullableObject, but does not copy its
|
||||
// children (decals).
|
||||
// Description: Copies the CullableObject.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullableObject::
|
||||
CullableObject(const CullableObject ©) :
|
||||
@@ -88,8 +83,7 @@ CullableObject(const CullableObject ©) :
|
||||
_state(copy._state),
|
||||
_net_transform(copy._net_transform),
|
||||
_modelview_transform(copy._modelview_transform),
|
||||
_internal_transform(copy._internal_transform),
|
||||
_fancy(false)
|
||||
_internal_transform(copy._internal_transform)
|
||||
{
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
@@ -99,12 +93,10 @@ CullableObject(const CullableObject ©) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description: Copies the CullableObject, but does not copy its
|
||||
// children (decals).
|
||||
// Description: Copies the CullableObject.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullableObject::
|
||||
operator = (const CullableObject ©) {
|
||||
nassertv(!_fancy);
|
||||
_geom = copy._geom;
|
||||
_munger = copy._munger;
|
||||
_munged_data = copy._munged_data;
|
||||
@@ -112,29 +104,7 @@ operator = (const CullableObject ©) {
|
||||
_net_transform = copy._net_transform;
|
||||
_modelview_transform = copy._modelview_transform;
|
||||
_internal_transform = copy._internal_transform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::is_fancy
|
||||
// Access: Public
|
||||
// Description: Returns true if the object has something fancy to it:
|
||||
// decals, maybe, or a draw_callback, that prevents it
|
||||
// from being rendered inline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CullableObject::
|
||||
is_fancy() const {
|
||||
return _fancy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::has_decals
|
||||
// Access: Public
|
||||
// Description: Returns true if the object has decals associated with
|
||||
// it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CullableObject::
|
||||
has_decals() const {
|
||||
return _fancy && (_next != (CullableObject *)NULL);
|
||||
_draw_callback = copy._draw_callback;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -146,8 +116,17 @@ has_decals() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullableObject::
|
||||
draw(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread) {
|
||||
if (_fancy) {
|
||||
draw_fancy(gsg, force, current_thread);
|
||||
if (_draw_callback != (CallbackObject *)NULL) {
|
||||
// It has a callback associated.
|
||||
gsg->clear_before_callback();
|
||||
gsg->set_state_and_transform(_state, _internal_transform);
|
||||
GeomDrawCallbackData cbdata(this, gsg, force);
|
||||
_draw_callback->do_callback(&cbdata);
|
||||
if (cbdata.get_lost_state()) {
|
||||
// Tell the GSG to forget its state.
|
||||
gsg->clear_state_and_transform();
|
||||
}
|
||||
// Now the callback has taken care of drawing.
|
||||
} else {
|
||||
nassertv(_geom != (Geom *)NULL);
|
||||
gsg->set_state_and_transform(_state, _internal_transform);
|
||||
@@ -184,43 +163,7 @@ request_resident() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullableObject::
|
||||
set_draw_callback(CallbackObject *draw_callback) {
|
||||
make_fancy();
|
||||
if (draw_callback != _draw_callback) {
|
||||
if (_draw_callback != (CallbackObject *)NULL) {
|
||||
unref_delete(_draw_callback);
|
||||
}
|
||||
_draw_callback = draw_callback;
|
||||
if (_draw_callback != (CallbackObject *)NULL) {
|
||||
_draw_callback->ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::set_next
|
||||
// Access: Public
|
||||
// Description: Sets the next object in the decal chain. This next
|
||||
// object will be destructed when this object destructs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullableObject::
|
||||
set_next(CullableObject *next) {
|
||||
make_fancy();
|
||||
nassertv(_next == (CullableObject *)NULL);
|
||||
_next = next;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::get_next
|
||||
// Access: Public
|
||||
// Description: Returns the next object in the decal chain, or NULL
|
||||
// for the end of the chain.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullableObject *CullableObject::
|
||||
get_next() const {
|
||||
if (_fancy) {
|
||||
return _next;
|
||||
}
|
||||
return NULL;
|
||||
_draw_callback = draw_callback;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -233,23 +176,6 @@ flush_level() {
|
||||
_sw_sprites_pcollector.flush_level();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::make_fancy
|
||||
// Access: Private
|
||||
// Description: Elevates this object to "fancy" status. This means
|
||||
// that the additional pointers, like _next and
|
||||
// _draw_callback, have meaningful values and should be
|
||||
// examined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullableObject::
|
||||
make_fancy() {
|
||||
if (!_fancy) {
|
||||
_fancy = true;
|
||||
_draw_callback = NULL;
|
||||
_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::draw_inline
|
||||
// Access: Private
|
||||
@@ -266,7 +192,7 @@ draw_inline(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::SortPoints::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullableObject::SortPoints::
|
||||
SortPoints(const CullableObject::PointData *array) :
|
||||
@@ -288,7 +214,7 @@ operator () (unsigned short a, unsigned short b) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::SourceFormat::operator <
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CullableObject::SourceFormat::
|
||||
operator < (const CullableObject::SourceFormat &other) const {
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "geomTriangles.h"
|
||||
#include "light.h"
|
||||
#include "lightMutexHolder.h"
|
||||
#include "geomDrawCallbackData.h"
|
||||
|
||||
CullableObject::FormatMap CullableObject::_format_map;
|
||||
LightMutex CullableObject::_format_lock;
|
||||
@@ -180,41 +179,13 @@ munge_geom(GraphicsStateGuardianBase *gsg,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_fancy) {
|
||||
// Only check the _next pointer if the _fancy flag is set.
|
||||
if (_next != (CullableObject *)NULL) {
|
||||
if (_next->_state != (RenderState *)NULL) {
|
||||
_next->munge_geom(gsg, gsg->get_geom_munger(_next->_state, current_thread),
|
||||
traverser, force);
|
||||
} else {
|
||||
_next->munge_geom(gsg, munger, traverser, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Destructor
|
||||
// Access: Public
|
||||
// Description: Automatically deletes the whole chain of these things.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullableObject::
|
||||
~CullableObject() {
|
||||
if (_fancy) {
|
||||
// Only check the _next pointer if the _fancy flag is set.
|
||||
if (_next != (CullableObject *)NULL) {
|
||||
delete _next;
|
||||
}
|
||||
set_draw_callback(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullableObject::
|
||||
output(ostream &out) const {
|
||||
@@ -225,7 +196,6 @@ output(ostream &out) const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::munge_points_to_quads
|
||||
// Access: Private
|
||||
@@ -642,7 +612,7 @@ munge_texcoord_light_vector(const CullTraverser *traverser, bool force) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_munged_data->has_column(InternalName::get_vertex()) ||
|
||||
if (!_munged_data->has_column(InternalName::get_vertex()) ||
|
||||
!_munged_data->has_column(InternalName::get_normal())) {
|
||||
// No vertex or normal; can't compute light vector.
|
||||
return true;
|
||||
@@ -775,97 +745,15 @@ get_flash_hardware_state() {
|
||||
return flash_hardware_state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::draw_fancy
|
||||
// Access: Private
|
||||
// Description: Something fancy about this object. Draw it properly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullableObject::
|
||||
draw_fancy(GraphicsStateGuardianBase *gsg, bool force,
|
||||
Thread *current_thread) {
|
||||
nassertv(_fancy);
|
||||
if (_draw_callback != (CallbackObject *)NULL) {
|
||||
// It has a callback associated.
|
||||
gsg->clear_before_callback();
|
||||
gsg->set_state_and_transform(_state, _internal_transform);
|
||||
GeomDrawCallbackData cbdata(this, gsg, force);
|
||||
_draw_callback->do_callback(&cbdata);
|
||||
if (cbdata.get_lost_state()) {
|
||||
// Tell the GSG to forget its state.
|
||||
gsg->clear_state_and_transform();
|
||||
}
|
||||
// Now the callback has taken care of drawing.
|
||||
|
||||
} else if (_next != (CullableObject *)NULL) {
|
||||
// It has decals.
|
||||
draw_with_decals(gsg, force, current_thread);
|
||||
|
||||
} else {
|
||||
// Huh, nothing fancy after all. Somehow the _fancy flag got set
|
||||
// incorrectly; that's a bug.
|
||||
gsg->set_state_and_transform(_state, _internal_transform);
|
||||
draw_inline(gsg, force, current_thread);
|
||||
nassertv(false);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::draw_with_decals
|
||||
// Access: Private
|
||||
// Description: Draws the current CullableObject, assuming it has
|
||||
// attached decals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullableObject::
|
||||
draw_with_decals(GraphicsStateGuardianBase *gsg, bool force,
|
||||
Thread *current_thread) {
|
||||
nassertv(_fancy && _next != (CullableObject *)NULL);
|
||||
// We draw with a three-step process.
|
||||
|
||||
// First, render all of the base geometry for the first pass.
|
||||
CPT(RenderState) state = gsg->begin_decal_base_first();
|
||||
|
||||
CullableObject *base = this;
|
||||
while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
|
||||
gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
|
||||
base->draw_inline(gsg, force, current_thread);
|
||||
|
||||
base = base->_next;
|
||||
}
|
||||
|
||||
if (base != (CullableObject *)NULL) {
|
||||
// Now, draw all the decals.
|
||||
state = gsg->begin_decal_nested();
|
||||
|
||||
CullableObject *decal = base->_next;
|
||||
while (decal != (CullableObject *)NULL) {
|
||||
gsg->set_state_and_transform(decal->_state->compose(state), decal->_internal_transform);
|
||||
decal->draw_inline(gsg, force, current_thread);
|
||||
decal = decal->_next;
|
||||
}
|
||||
}
|
||||
|
||||
// And now, re-draw the base geometry, if required.
|
||||
state = gsg->begin_decal_base_second();
|
||||
if (state != (const RenderState *)NULL) {
|
||||
base = this;
|
||||
while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
|
||||
gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
|
||||
base->draw_inline(gsg, force, current_thread);
|
||||
|
||||
base = base->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::SourceFormat::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullableObject::SourceFormat::
|
||||
SourceFormat(const GeomVertexFormat *format, bool sprite_texcoord) :
|
||||
_format(format),
|
||||
_sprite_texcoord(sprite_texcoord)
|
||||
_sprite_texcoord(sprite_texcoord)
|
||||
{
|
||||
_retransform_sprites = retransform_sprites;
|
||||
}
|
||||
|
||||
@@ -32,17 +32,17 @@
|
||||
#include "sceneSetup.h"
|
||||
#include "lightMutex.h"
|
||||
#include "callbackObject.h"
|
||||
#include "geomDrawCallbackData.h"
|
||||
|
||||
class CullTraverser;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CullableObject
|
||||
// Description : The smallest atom of cull. This is normally just a
|
||||
// Geom and its associated state, but it also represent
|
||||
// a number of Geoms to be drawn together, with a number
|
||||
// of Geoms decalled onto them.
|
||||
// Geom and its associated state, but it also contain
|
||||
// a draw callback.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PGRAPH CullableObject
|
||||
class EXPCL_PANDA_PGRAPH CullableObject
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
: public ReferenceCount // We inherit from ReferenceCount just to get the memory type tracking that MemoryUsage provides.
|
||||
#endif // DO_MEMORY_USAGE
|
||||
@@ -57,13 +57,10 @@ public:
|
||||
const TransformState *net_transform,
|
||||
const TransformState *modelview_transform,
|
||||
const TransformState *internal_transform);
|
||||
|
||||
|
||||
INLINE CullableObject(const CullableObject ©);
|
||||
INLINE void operator = (const CullableObject ©);
|
||||
|
||||
INLINE bool is_fancy() const;
|
||||
INLINE bool has_decals() const;
|
||||
|
||||
bool munge_geom(GraphicsStateGuardianBase *gsg,
|
||||
GeomMunger *munger, const CullTraverser *traverser,
|
||||
bool force);
|
||||
@@ -74,11 +71,8 @@ public:
|
||||
INLINE static void flush_level();
|
||||
|
||||
INLINE void set_draw_callback(CallbackObject *draw_callback);
|
||||
INLINE void set_next(CullableObject *next);
|
||||
INLINE CullableObject *get_next() const;
|
||||
|
||||
public:
|
||||
~CullableObject();
|
||||
ALLOC_DELETED_CHAIN(CullableObject);
|
||||
|
||||
void output(ostream &out) const;
|
||||
@@ -91,17 +85,9 @@ public:
|
||||
CPT(TransformState) _net_transform;
|
||||
CPT(TransformState) _modelview_transform;
|
||||
CPT(TransformState) _internal_transform;
|
||||
PT(CallbackObject) _draw_callback;
|
||||
|
||||
private:
|
||||
bool _fancy;
|
||||
|
||||
// Fancy things below. These pointers are only meaningful if
|
||||
// _fancy, above, is true.
|
||||
CallbackObject *_draw_callback;
|
||||
CullableObject *_next; // for decals
|
||||
|
||||
private:
|
||||
INLINE void make_fancy();
|
||||
bool munge_points_to_quads(const CullTraverser *traverser, bool force);
|
||||
bool munge_texcoord_light_vector(const CullTraverser *traverser, bool force);
|
||||
|
||||
@@ -110,10 +96,6 @@ private:
|
||||
|
||||
INLINE void draw_inline(GraphicsStateGuardianBase *gsg,
|
||||
bool force, Thread *current_thread);
|
||||
void draw_fancy(GraphicsStateGuardianBase *gsg, bool force,
|
||||
Thread *current_thread);
|
||||
void draw_with_decals(GraphicsStateGuardianBase *gsg, bool force,
|
||||
Thread *current_thread);
|
||||
|
||||
private:
|
||||
// This class is used internally by munge_points_to_quads().
|
||||
|
||||
Reference in New Issue
Block a user