Big patch full of performance improvements

This particularly benefits applications with a lot of nodes.
This commit is contained in:
rdb 2017-04-02 23:24:22 +02:00
parent e1c916cdc3
commit 6f8b379bda
102 changed files with 1410 additions and 1009 deletions

View File

@ -45,7 +45,9 @@ get_memory_usage(MemoryClass memory_class) const {
void TypeHandle:: void TypeHandle::
inc_memory_usage(MemoryClass memory_class, size_t size) { inc_memory_usage(MemoryClass memory_class, size_t size) {
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
#ifdef _DEBUG
assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit); assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
#endif
if ((*this) != TypeHandle::none()) { if ((*this) != TypeHandle::none()) {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL); TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
assert(rnode != (TypeRegistryNode *)NULL); assert(rnode != (TypeRegistryNode *)NULL);
@ -67,7 +69,9 @@ inc_memory_usage(MemoryClass memory_class, size_t size) {
void TypeHandle:: void TypeHandle::
dec_memory_usage(MemoryClass memory_class, size_t size) { dec_memory_usage(MemoryClass memory_class, size_t size) {
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
#ifdef _DEBUG
assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit); assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
#endif
if ((*this) != TypeHandle::none()) { if ((*this) != TypeHandle::none()) {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL); TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
assert(rnode != (TypeRegistryNode *)NULL); assert(rnode != (TypeRegistryNode *)NULL);

View File

@ -67,7 +67,7 @@ operator = (bool value) {
/** /**
* Returns the variable's value. * Returns the variable's value.
*/ */
INLINE ConfigVariableBool:: ALWAYS_INLINE ConfigVariableBool::
operator bool () const { operator bool () const {
return get_value(); return get_value();
} }
@ -100,12 +100,11 @@ set_value(bool value) {
/** /**
* Returns the variable's value. * Returns the variable's value.
*/ */
INLINE bool ConfigVariableBool:: ALWAYS_INLINE bool ConfigVariableBool::
get_value() const { get_value() const {
TAU_PROFILE("bool ConfigVariableBool::get_value() const", " ", TAU_USER); TAU_PROFILE("bool ConfigVariableBool::get_value() const", " ", TAU_USER);
if (!is_cache_valid(_local_modified)) { if (!is_cache_valid(_local_modified)) {
mark_cache_valid(((ConfigVariableBool *)this)->_local_modified); reload_value();
((ConfigVariableBool *)this)->_cache = get_bool_word(0);
} }
return _cache; return _cache;
} }

View File

@ -12,3 +12,12 @@
*/ */
#include "configVariableBool.h" #include "configVariableBool.h"
/**
* Refreshes the cached value.
*/
void ConfigVariableBool::
reload_value() const {
mark_cache_valid(_local_modified);
_cache = get_bool_word(0);
}

View File

@ -29,13 +29,13 @@ PUBLISHED:
const string &description = string(), int flags = 0); const string &description = string(), int flags = 0);
INLINE void operator = (bool value); INLINE void operator = (bool value);
INLINE operator bool () const; ALWAYS_INLINE operator bool () const;
INLINE size_t size() const; INLINE size_t size() const;
INLINE bool operator [] (size_t n) const; INLINE bool operator [] (size_t n) const;
INLINE void set_value(bool value); INLINE void set_value(bool value);
INLINE bool get_value() const; ALWAYS_INLINE bool get_value() const;
INLINE bool get_default_value() const; INLINE bool get_default_value() const;
MAKE_PROPERTY(value, get_value, set_value); MAKE_PROPERTY(value, get_value, set_value);
MAKE_PROPERTY(default_value, get_default_value); MAKE_PROPERTY(default_value, get_default_value);
@ -44,8 +44,10 @@ PUBLISHED:
INLINE void set_word(size_t n, bool value); INLINE void set_word(size_t n, bool value);
private: private:
AtomicAdjust::Integer _local_modified; void reload_value() const;
bool _cache;
mutable AtomicAdjust::Integer _local_modified;
mutable bool _cache;
}; };
#include "configVariableBool.I" #include "configVariableBool.I"

View File

@ -70,7 +70,12 @@ is_on(NotifySeverity severity) const {
*/ */
INLINE bool NotifyCategory:: INLINE bool NotifyCategory::
is_spam() const { is_spam() const {
// Instruct the compiler to optimize for the usual case.
#ifdef __GNUC__
return __builtin_expect(is_on(NS_spam), 0);
#else
return is_on(NS_spam); return is_on(NS_spam);
#endif
} }
/** /**
@ -78,7 +83,12 @@ is_spam() const {
*/ */
INLINE bool NotifyCategory:: INLINE bool NotifyCategory::
is_debug() const { is_debug() const {
// Instruct the compiler to optimize for the usual case.
#ifdef __GNUC__
return __builtin_expect(is_on(NS_debug), 0);
#else
return is_on(NS_debug); return is_on(NS_debug);
#endif
} }
#else #else
/** /**

View File

@ -69,7 +69,12 @@ is_on(NotifySeverity severity) {
template<class GetCategory> template<class GetCategory>
INLINE bool NotifyCategoryProxy<GetCategory>:: INLINE bool NotifyCategoryProxy<GetCategory>::
is_spam() { is_spam() {
// Instruct the compiler to optimize for the usual case.
#ifdef __GNUC__
return __builtin_expect(get_unsafe_ptr()->is_spam(), 0);
#else
return get_unsafe_ptr()->is_spam(); return get_unsafe_ptr()->is_spam();
#endif
} }
#else #else
template<class GetCategory> template<class GetCategory>
@ -86,7 +91,12 @@ is_spam() {
template<class GetCategory> template<class GetCategory>
INLINE bool NotifyCategoryProxy<GetCategory>:: INLINE bool NotifyCategoryProxy<GetCategory>::
is_debug() { is_debug() {
// Instruct the compiler to optimize for the usual case.
#ifdef __GNUC__
return __builtin_expect(get_unsafe_ptr()->is_debug(), 0);
#else
return get_unsafe_ptr()->is_debug(); return get_unsafe_ptr()->is_debug();
#endif
} }
#else #else
template<class GetCategory> template<class GetCategory>

View File

@ -122,6 +122,13 @@ private:
// constant expressions and compilation will fail if the assertion is not // constant expressions and compilation will fail if the assertion is not
// true. // true.
#ifdef __GNUC__
// Tell the optimizer to optimize for the case where the condition is true.
#define _nassert_check(condition) (__builtin_expect(!(condition), 0))
#else
#define _nassert_check(condition) (!(condition))
#endif
#ifdef NDEBUG #ifdef NDEBUG
#define nassertr(condition, return_value) #define nassertr(condition, return_value)
@ -131,14 +138,14 @@ private:
#define nassertr_always(condition, return_value) \ #define nassertr_always(condition, return_value) \
{ \ { \
if (!(condition)) { \ if (_nassert_check(condition)) { \
return return_value; \ return return_value; \
} \ } \
} }
#define nassertv_always(condition) \ #define nassertv_always(condition) \
{ \ { \
if (!(condition)) { \ if (_nassert_check(condition)) { \
return; \ return; \
} \ } \
} }
@ -151,7 +158,7 @@ private:
#define nassertr(condition, return_value) \ #define nassertr(condition, return_value) \
{ \ { \
if (!(condition)) { \ if (_nassert_check(condition)) { \
if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \ if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \
return return_value; \ return return_value; \
} \ } \
@ -160,7 +167,7 @@ private:
#define nassertv(condition) \ #define nassertv(condition) \
{ \ { \
if (!(condition)) { \ if (_nassert_check(condition)) { \
if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \ if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \
return; \ return; \
} \ } \
@ -168,7 +175,7 @@ private:
} }
#define nassertd(condition) \ #define nassertd(condition) \
if (!(condition) && \ if (_nassert_check(condition) && \
Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__))
#define nassertr_always(condition, return_value) nassertr(condition, return_value) #define nassertr_always(condition, return_value) nassertr(condition, return_value)
@ -177,7 +184,7 @@ private:
#define nassert_raise(message) Notify::ptr()->assert_failure(message, __LINE__, __FILE__) #define nassert_raise(message) Notify::ptr()->assert_failure(message, __LINE__, __FILE__)
#define enter_debugger_if(condition) \ #define enter_debugger_if(condition) \
if (condition) { \ if (_nassert_check(condition)) { \
Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__); \ Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__); \
__asm { int 3 } \ __asm { int 3 } \
} }

View File

@ -122,8 +122,10 @@ void CharacterJointEffect::
cull_callback(CullTraverser *trav, CullTraverserData &data, cull_callback(CullTraverser *trav, CullTraverserData &data,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
CPT(RenderState) &) const { CPT(RenderState) &) const {
CPT(TransformState) dummy_transform = TransformState::make_identity(); if (_character.is_valid_pointer()) {
adjust_transform(dummy_transform, node_transform, data.node()); _character->update();
}
node_transform = data.node()->get_transform();
} }
/** /**
@ -147,7 +149,7 @@ has_adjust_transform() const {
void CharacterJointEffect:: void CharacterJointEffect::
adjust_transform(CPT(TransformState) &net_transform, adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const { const PandaNode *node) const {
if (_character.is_valid_pointer()) { if (_character.is_valid_pointer()) {
_character->update(); _character->update();
} }

View File

@ -53,7 +53,7 @@ public:
virtual bool has_adjust_transform() const; virtual bool has_adjust_transform() const;
virtual void adjust_transform(CPT(TransformState) &net_transform, virtual void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const; const PandaNode *node) const;
protected: protected:
virtual int compare_to_impl(const RenderEffect *other) const; virtual int compare_to_impl(const RenderEffect *other) const;

View File

@ -111,10 +111,12 @@ any_in_bounds() {
} }
#endif // NDEBUG #endif // NDEBUG
CPT(BoundingVolume) node_bv = node()->get_bounds(); PandaNode *pnode = node();
CPT(BoundingVolume) node_bv = pnode->get_bounds();
if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) { if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
const GeometricBoundingVolume *node_gbv; const GeometricBoundingVolume *node_gbv = (const GeometricBoundingVolume *)node_bv.p();
DCAST_INTO_R(node_gbv, node_bv, false); CollideMask this_mask = pnode->get_net_collide_mask();
int num_colliders = get_num_colliders(); int num_colliders = get_num_colliders();
for (int c = 0; c < num_colliders; c++) { for (int c = 0; c < num_colliders; c++) {
@ -125,10 +127,10 @@ any_in_bounds() {
// Don't even bother testing the bounding volume if there are no // Don't even bother testing the bounding volume if there are no
// collide bits in common between our collider and this node. // collide bits in common between our collider and this node.
CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask; CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask;
if (!(from_mask & node()->get_net_collide_mask()).is_zero()) { if (!(from_mask & this_mask).is_zero()) {
// Also don't test a node with itself, or with any of its // Also don't test a node with itself, or with any of its
// descendants. // descendants.
if (node() == cnode) { if (pnode == cnode) {
#ifndef NDEBUG #ifndef NDEBUG
if (collide_cat.is_spam()) { if (collide_cat.is_spam()) {
indent(collide_cat.spam(false), indent_level) indent(collide_cat.spam(false), indent_level)

View File

@ -51,7 +51,7 @@ public:
INLINE CollisionLevelStateBase(const NodePath &node_path); INLINE CollisionLevelStateBase(const NodePath &node_path);
INLINE CollisionLevelStateBase(const CollisionLevelStateBase &parent, INLINE CollisionLevelStateBase(const CollisionLevelStateBase &parent,
PandaNode *child); PandaNode *child);
INLINE CollisionLevelStateBase(const CollisionLevelStateBase &copy); INLINE CollisionLevelStateBase(const CollisionLevelStateBase &copy);
INLINE void operator = (const CollisionLevelStateBase &copy); INLINE void operator = (const CollisionLevelStateBase &copy);

View File

@ -196,7 +196,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
if (respect_prev_transform) { if (respect_prev_transform) {
// Determine the previous frame's position, relative to the current // Determine the previous frame's position, relative to the current
// position. // position.
NodePath node_path = data._node_path.get_node_path(); NodePath node_path = data.get_node_path();
CPT(TransformState) transform = node_path.get_net_transform()->invert_compose(node_path.get_net_prev_transform()); CPT(TransformState) transform = node_path.get_net_transform()->invert_compose(node_path.get_net_prev_transform());
if (!transform->is_identity()) { if (!transform->is_identity()) {

View File

@ -93,6 +93,8 @@ private:
typedef pvector< COWPT(CollisionSolid) > Solids; typedef pvector< COWPT(CollisionSolid) > Solids;
Solids _solids; Solids _solids;
friend class CollisionTraverser;
public: public:
static void register_with_read_factory(); static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg); virtual void write_datagram(BamWriter *manager, Datagram &dg);

View File

@ -57,7 +57,7 @@ public:
inline bool operator () (int a, int b) const { inline bool operator () (int a, int b) const {
const CollisionTraverser::OrderedColliderDef &ocd_a = _trav._ordered_colliders[a]; const CollisionTraverser::OrderedColliderDef &ocd_a = _trav._ordered_colliders[a];
const CollisionTraverser::OrderedColliderDef &ocd_b = _trav._ordered_colliders[b]; const CollisionTraverser::OrderedColliderDef &ocd_b = _trav._ordered_colliders[b];
return DCAST(CollisionNode, ocd_a._node_path.node())->get_collider_sort() < DCAST(CollisionNode, ocd_b._node_path.node())->get_collider_sort(); return ((const CollisionNode *)ocd_a._node_path.node())->get_collider_sort() < ((const CollisionNode *)ocd_b._node_path.node())->get_collider_sort();
} }
const CollisionTraverser &_trav; const CollisionTraverser &_trav;
@ -1117,31 +1117,45 @@ compare_collider_to_node(CollisionEntry &entry,
} }
if (within_node_bounds) { if (within_node_bounds) {
Thread *current_thread = Thread::get_current_thread();
CollisionNode *cnode; CollisionNode *cnode;
DCAST_INTO_V(cnode, entry._into_node); DCAST_INTO_V(cnode, entry._into_node);
int num_solids = cnode->get_num_solids(); int num_solids = cnode->get_num_solids();
collide_cat.spam() if (collide_cat.is_spam()) {
<< "Colliding against CollisionNode " << entry._into_node collide_cat.spam()
<< " which has " << num_solids << " collision solids.\n"; << "Colliding against CollisionNode " << entry._into_node
for (int s = 0; s < num_solids; ++s) { << " which has " << num_solids << " collision solids.\n";
entry._into = cnode->get_solid(s); }
// We should allow a collision test for solid into itself, because the // Only bother to test against each solid's bounding volume if we have
// solid might be simply instanced into multiple different // more than one solid in the node, as a slight optimization. (If the
// CollisionNodes. We are already filtering out tests for a // node contains just one solid, then the node's bounding volume, which
// CollisionNode into itself. // we just tested, is the same as the solid's bounding volume.)
CPT(BoundingVolume) solid_bv = entry._into->get_bounds(); if (num_solids == 1) {
const GeometricBoundingVolume *solid_gbv = NULL; entry._into = cnode->_solids[0].get_read_pointer(current_thread);
if (num_solids > 1 && Colliders::const_iterator ci;
solid_bv->is_of_type(GeometricBoundingVolume::get_class_type())) { ci = _colliders.find(entry.get_from_node_path());
// Only bother to test against each solid's bounding volume if we have nassertv(ci != _colliders.end());
// more than one solid in the node, as a slight optimization. (If the entry.test_intersection((*ci).second, this);
// node contains just one solid, then the node's bounding volume, } else {
// which we just tested, is the same as the solid's bounding volume.) CollisionNode::Solids::const_iterator si;
DCAST_INTO_V(solid_gbv, solid_bv); for (si = cnode->_solids.begin(); si != cnode->_solids.end(); ++si) {
entry._into = (*si).get_read_pointer(current_thread);
// We should allow a collision test for solid into itself, because the
// solid might be simply instanced into multiple different
// CollisionNodes. We are already filtering out tests for a
// CollisionNode into itself.
CPT(BoundingVolume) solid_bv = entry._into->get_bounds();
const GeometricBoundingVolume *solid_gbv = nullptr;
if (solid_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
solid_gbv = (const GeometricBoundingVolume *)solid_bv.p();
}
compare_collider_to_solid(entry, from_node_gbv, solid_gbv);
} }
compare_collider_to_solid(entry, from_node_gbv, solid_gbv);
} }
} }
} }

View File

@ -111,10 +111,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
// its objects according to their appropriate net transform. // its objects according to their appropriate net transform.
xform_data._net_transform = TransformState::make_identity(); xform_data._net_transform = TransformState::make_identity();
xform_data._view_frustum = trav->get_view_frustum(); xform_data._view_frustum = trav->get_view_frustum();
xform_data.apply_transform_and_state(trav, net_transform, xform_data.apply_transform(net_transform);
RenderState::make_empty(),
RenderEffects::make_empty(),
ClipPlaneAttrib::make());
// Draw all the collision solids. // Draw all the collision solids.
Solids::const_iterator si; Solids::const_iterator si;

View File

@ -903,16 +903,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_identity: { case Shader::SMO_identity: {
return &LMatrix4::ident_mat(); return &LMatrix4::ident_mat();
} }
case Shader::SMO_window_size: { case Shader::SMO_window_size:
t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0);
return &t;
}
case Shader::SMO_pixel_size: { case Shader::SMO_pixel_size: {
t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(), LVecBase2i pixel_size = _current_display_region->get_pixel_size();
_current_display_region->get_pixel_height(), t = LMatrix4::translate_mat(pixel_size[0], pixel_size[1], 0);
0.0);
return &t; return &t;
} }
case Shader::SMO_frame_time: { case Shader::SMO_frame_time: {
@ -1049,7 +1043,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
LColor const &c = lt->get_color(); LColor const &c = lt->get_color();
LColor const &s = lt->get_specular_color(); LColor const &s = lt->get_specular_color();
t = np.get_net_transform()->get_mat() * t = np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
LVecBase3 d = -(t.xform_vec(lt->get_direction())); LVecBase3 d = -(t.xform_vec(lt->get_direction()));
d.normalize(); d.normalize();
LVecBase3 h = d + LVecBase3(0,-1,0); LVecBase3 h = d + LVecBase3(0,-1,0);
@ -1066,11 +1060,12 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
LColor const &c = lt->get_color(); LColor const &c = lt->get_color();
LColor const &s = lt->get_specular_color(); LColor const &s = lt->get_specular_color();
t = np.get_net_transform()->get_mat() * t = np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
LVecBase3 p = (t.xform_point(lt->get_point())); LVecBase3 p = (t.xform_point(lt->get_point()));
LVecBase3 a = lt->get_attenuation(); LVecBase3 a = lt->get_attenuation();
PN_stdfloat lnear = lt->get_lens(0)->get_near(); Lens *lens = lt->get_lens(0);
PN_stdfloat lfar = lt->get_lens(0)->get_far(); PN_stdfloat lnear = lens->get_near();
PN_stdfloat lfar = lens->get_far();
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],lnear,a[0],a[1],a[2],lfar); t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],lnear,a[0],a[1],a[2],lfar);
return &t; return &t;
} }
@ -1086,7 +1081,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
LColor const &s = lt->get_specular_color(); LColor const &s = lt->get_specular_color();
PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f)); PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
t = np.get_net_transform()->get_mat() * t = np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
LVecBase3 p = t.xform_point(lens->get_nodal_point()); LVecBase3 p = t.xform_point(lens->get_nodal_point());
LVecBase3 d = -(t.xform_vec(lens->get_view_vector())); LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff); t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff);
@ -1109,7 +1104,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
Light *light_obj = light.node()->as_light(); Light *light_obj = light.node()->as_light();
nassertr(light_obj != (Light *)NULL, &LMatrix4::zeros_mat()); nassertr(light_obj != (Light *)NULL, &LMatrix4::zeros_mat());
if (light_obj->get_type() == AmbientLight::get_class_type()) { if (light_obj->is_ambient_light()) {
cur_ambient_light += light_obj->get_color(); cur_ambient_light += light_obj->get_color();
} }
} }
@ -1155,27 +1150,31 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_plane_x: { case Shader::SMO_plane_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::zeros_mat()); nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat()); const PlaneNode *plane_node;
LPlane p = DCAST(PlaneNode, np.node())->get_plane(); DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
LPlane p = plane_node->get_plane();
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
return &t; return &t;
} }
case Shader::SMO_clipplane_x: { case Shader::SMO_clipplane_x: {
const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot())); const ClipPlaneAttrib *cpa;
_target_rs->get_attrib_def(cpa);
int planenr = atoi(name->get_name().c_str()); int planenr = atoi(name->get_name().c_str());
if (planenr >= cpa->get_num_on_planes()) { if (planenr >= cpa->get_num_on_planes()) {
return &LMatrix4::zeros_mat(); return &LMatrix4::zeros_mat();
} }
const NodePath &np = cpa->get_on_plane(planenr); const NodePath &np = cpa->get_on_plane(planenr);
nassertr(!np.is_empty(), &LMatrix4::zeros_mat()); nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat()); const PlaneNode *plane_node;
LPlane p (DCAST(PlaneNode, np.node())->get_plane()); DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
LPlane p (plane_node->get_plane());
p.xform(np.get_net_transform()->get_mat()); // World-space p.xform(np.get_net_transform()->get_mat()); // World-space
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
return &t; return &t;
} }
case Shader::SMO_apiview_clipplane_i: { case Shader::SMO_apiview_clipplane_i: {
const ClipPlaneAttrib *cpa = DCAST(ClipPlaneAttrib, _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot())); const ClipPlaneAttrib *cpa;
_target_rs->get_attrib_def(cpa);
if (index >= cpa->get_num_on_planes()) { if (index >= cpa->get_num_on_planes()) {
return &LMatrix4::zeros_mat(); return &LMatrix4::zeros_mat();
} }
@ -1186,7 +1185,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
DCAST_INTO_R(plane_node, plane.node(), &LMatrix4::zeros_mat()); DCAST_INTO_R(plane_node, plane.node(), &LMatrix4::zeros_mat());
CPT(TransformState) transform = CPT(TransformState) transform =
get_scene()->get_cs_world_transform()->compose( _scene_setup->get_cs_world_transform()->compose(
plane.get_transform(_scene_setup->get_scene_root().get_parent())); plane.get_transform(_scene_setup->get_scene_root().get_parent()));
LPlane xformed_plane = plane_node->get_plane() * transform->get_mat(); LPlane xformed_plane = plane_node->get_plane() * transform->get_mat();
@ -1206,24 +1205,24 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
return &t; return &t;
} }
case Shader::SMO_world_to_view: { case Shader::SMO_world_to_view: {
return &(get_scene()->get_world_transform()->get_mat()); return &(_scene_setup->get_world_transform()->get_mat());
break; break;
} }
case Shader::SMO_view_to_world: { case Shader::SMO_view_to_world: {
return &(get_scene()->get_camera_transform()->get_mat()); return &(_scene_setup->get_camera_transform()->get_mat());
} }
case Shader::SMO_model_to_view: { case Shader::SMO_model_to_view: {
return &(get_external_transform()->get_mat()); return &(_inv_cs_transform->compose(_internal_transform)->get_mat());
} }
case Shader::SMO_model_to_apiview: { case Shader::SMO_model_to_apiview: {
return &(get_internal_transform()->get_mat()); return &(_internal_transform->get_mat());
} }
case Shader::SMO_view_to_model: { case Shader::SMO_view_to_model: {
t = get_external_transform()->get_inverse()->get_mat(); t = _internal_transform->invert_compose(_cs_transform)->get_mat();
return &t; return &t;
} }
case Shader::SMO_apiview_to_model: { case Shader::SMO_apiview_to_model: {
t = get_internal_transform()->get_inverse()->get_mat(); t = _internal_transform->get_inverse()->get_mat();
return &t; return &t;
} }
case Shader::SMO_apiview_to_view: { case Shader::SMO_apiview_to_view: {
@ -1268,13 +1267,13 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
t = np.get_net_transform()->get_mat() * t = np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
return &t; return &t;
} }
case Shader::SMO_view_to_view_x: { case Shader::SMO_view_to_view_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
t = get_scene()->get_camera_transform()->get_mat() * t = _scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat(); np.get_net_transform()->get_inverse()->get_mat();
return &t; return &t;
} }
@ -1283,13 +1282,13 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) * t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
np.get_net_transform()->get_mat() * np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
return &t; return &t;
} }
case Shader::SMO_view_to_apiview_x: { case Shader::SMO_view_to_apiview_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
t = (get_scene()->get_camera_transform()->get_mat() * t = (_scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() * np.get_net_transform()->get_inverse()->get_mat() *
LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system)); LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
return &t; return &t;
@ -1297,20 +1296,22 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_clip_x_to_view: { case Shader::SMO_clip_x_to_view: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); const LensNode *node;
Lens *lens = DCAST(LensNode, np.node())->get_lens(); DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
const Lens *lens = node->get_lens();
t = lens->get_projection_mat_inv(_current_stereo_channel) * t = lens->get_projection_mat_inv(_current_stereo_channel) *
LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) * LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
np.get_net_transform()->get_mat() * np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
return &t; return &t;
} }
case Shader::SMO_view_to_clip_x: { case Shader::SMO_view_to_clip_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); const LensNode *node;
Lens *lens = DCAST(LensNode, np.node())->get_lens(); DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
t = get_scene()->get_camera_transform()->get_mat() * const Lens *lens = node->get_lens();
t = _scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() * np.get_net_transform()->get_inverse()->get_mat() *
LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) * LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
lens->get_projection_mat(_current_stereo_channel); lens->get_projection_mat(_current_stereo_channel);
@ -1319,20 +1320,22 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_apiclip_x_to_view: { case Shader::SMO_apiclip_x_to_view: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); const LensNode *node;
Lens *lens = DCAST(LensNode, np.node())->get_lens(); DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
const Lens *lens = node->get_lens();
t = calc_projection_mat(lens)->get_inverse()->get_mat() * t = calc_projection_mat(lens)->get_inverse()->get_mat() *
get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() * get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() *
np.get_net_transform()->get_mat() * np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat(); _scene_setup->get_world_transform()->get_mat();
return &t; return &t;
} }
case Shader::SMO_view_to_apiclip_x: { case Shader::SMO_view_to_apiclip_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name); const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat()); nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); const LensNode *node;
Lens *lens = DCAST(LensNode, np.node())->get_lens(); DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
t = get_scene()->get_camera_transform()->get_mat() * const Lens *lens = node->get_lens();
t = _scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() * np.get_net_transform()->get_inverse()->get_mat() *
get_cs_transform_for(lens->get_coordinate_system())->get_mat() * get_cs_transform_for(lens->get_coordinate_system())->get_mat() *
calc_projection_mat(lens)->get_mat(); calc_projection_mat(lens)->get_mat();
@ -1383,7 +1386,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
Light *light_obj = light.node()->as_light(); Light *light_obj = light.node()->as_light();
nassertr(light_obj != (Light *)NULL, &LMatrix4::ident_mat()); nassertr(light_obj != (Light *)NULL, &LMatrix4::ident_mat());
if (light_obj->get_type() != AmbientLight::get_class_type()) { if (!light_obj->is_ambient_light()) {
if (i++ == index) { if (i++ == index) {
return fetch_specified_member(light, name, t); return fetch_specified_member(light, name, t);
} }
@ -1430,7 +1433,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
static const CPT_InternalName IN_constantAttenuation("constantAttenuation"); static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
static const CPT_InternalName IN_linearAttenuation("linearAttenuation"); static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation"); static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
static const CPT_InternalName IN_shadowMatrix("shadowMatrix"); static const CPT_InternalName IN_shadowViewMatrix("shadowViewMatrix");
PandaNode *node = NULL; PandaNode *node = NULL;
if (!np.is_empty()) { if (!np.is_empty()) {
@ -1454,7 +1457,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
} }
Light *light = node->as_light(); Light *light = node->as_light();
nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
if (node->is_of_type(AmbientLight::get_class_type())) { if (node->is_ambient_light()) {
LColor c = light->get_color(); LColor c = light->get_color();
c.componentwise_mult(_light_color_scale); c.componentwise_mult(_light_color_scale);
t.set_row(3, c); t.set_row(3, c);
@ -1470,7 +1473,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
} }
Light *light = node->as_light(); Light *light = node->as_light();
nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
if (node->is_of_type(AmbientLight::get_class_type())) { if (node->is_ambient_light()) {
// Ambient light has no diffuse color. // Ambient light has no diffuse color.
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f)); t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
} else { } else {
@ -1493,7 +1496,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
if (np.is_empty()) { if (np.is_empty()) {
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
return &t; return &t;
} else if (node->is_of_type(AmbientLight::get_class_type())) { } else if (node->is_ambient_light()) {
// Ambient light has no position. // Ambient light has no position.
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
return &t; return &t;
@ -1503,7 +1506,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent()); CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
LVector3 dir = -(light->get_direction() * transform->get_mat()); LVector3 dir = -(light->get_direction() * transform->get_mat());
dir *= get_scene()->get_cs_world_transform()->get_mat(); dir *= _scene_setup->get_cs_world_transform()->get_mat();
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
return &t; return &t;
} else { } else {
@ -1513,7 +1516,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
CPT(TransformState) transform = CPT(TransformState) transform =
get_scene()->get_cs_world_transform()->compose( _scene_setup->get_cs_world_transform()->compose(
np.get_transform(_scene_setup->get_scene_root().get_parent())); np.get_transform(_scene_setup->get_scene_root().get_parent()));
const LMatrix4 &light_mat = transform->get_mat(); const LMatrix4 &light_mat = transform->get_mat();
@ -1526,7 +1529,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
if (np.is_empty()) { if (np.is_empty()) {
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
return &t; return &t;
} else if (node->is_of_type(AmbientLight::get_class_type())) { } else if (node->is_ambient_light()) {
// Ambient light has no half-vector. // Ambient light has no half-vector.
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
return &t; return &t;
@ -1536,7 +1539,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent()); CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
LVector3 dir = -(light->get_direction() * transform->get_mat()); LVector3 dir = -(light->get_direction() * transform->get_mat());
dir *= get_scene()->get_cs_world_transform()->get_mat(); dir *= _scene_setup->get_cs_world_transform()->get_mat();
dir.normalize(); dir.normalize();
dir += LVector3(0, 0, 1); dir += LVector3(0, 0, 1);
dir.normalize(); dir.normalize();
@ -1549,7 +1552,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
CPT(TransformState) transform = CPT(TransformState) transform =
get_scene()->get_cs_world_transform()->compose( _scene_setup->get_cs_world_transform()->compose(
np.get_transform(_scene_setup->get_scene_root().get_parent())); np.get_transform(_scene_setup->get_scene_root().get_parent()));
const LMatrix4 &light_mat = transform->get_mat(); const LMatrix4 &light_mat = transform->get_mat();
@ -1565,7 +1568,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
if (node == (PandaNode *)NULL) { if (node == (PandaNode *)NULL) {
t.set_row(3, LVector3(0.0f, 0.0f, -1.0f)); t.set_row(3, LVector3(0.0f, 0.0f, -1.0f));
return &t; return &t;
} else if (node->is_of_type(AmbientLight::get_class_type())) { } else if (node->is_ambient_light()) {
// Ambient light has no spot direction. // Ambient light has no spot direction.
t.set_row(3, LVector3(0.0f, 0.0f, 0.0f)); t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
return &t; return &t;
@ -1576,7 +1579,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
CPT(TransformState) transform = CPT(TransformState) transform =
get_scene()->get_cs_world_transform()->compose( _scene_setup->get_cs_world_transform()->compose(
np.get_transform(_scene_setup->get_scene_root().get_parent())); np.get_transform(_scene_setup->get_scene_root().get_parent()));
const LMatrix4 &light_mat = transform->get_mat(); const LMatrix4 &light_mat = transform->get_mat();
@ -1670,7 +1673,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
t.set_row(3, LVecBase4(light->get_attenuation()[2])); t.set_row(3, LVecBase4(light->get_attenuation()[2]));
return &t; return &t;
} else if (attrib == IN_shadowMatrix) { } else if (attrib == IN_shadowViewMatrix) {
static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f, static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
@ -1684,8 +1687,8 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
DCAST_INTO_R(lnode, node, &LMatrix4::ident_mat()); DCAST_INTO_R(lnode, node, &LMatrix4::ident_mat());
Lens *lens = lnode->get_lens(); Lens *lens = lnode->get_lens();
t = get_external_transform()->get_mat() * t = _inv_cs_transform->get_mat() *
get_scene()->get_camera_transform()->get_mat() * _scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() * np.get_net_transform()->get_inverse()->get_mat() *
LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()); LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system());
@ -1785,7 +1788,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
Light *light_obj = light.node()->as_light(); Light *light_obj = light.node()->as_light();
nassertr(light_obj != (Light *)NULL, NULL); nassertr(light_obj != (Light *)NULL, NULL);
if (light_obj->get_type() != AmbientLight::get_class_type()) { if (!light_obj->is_ambient_light()) {
if (i++ == spec._stage) { if (i++ == spec._stage) {
PT(Texture) tex = get_shadow_map(light); PT(Texture) tex = get_shadow_map(light);
if (tex != (Texture *)NULL) { if (tex != (Texture *)NULL) {
@ -2663,7 +2666,7 @@ do_issue_light() {
_lighting_enabled = true; _lighting_enabled = true;
} }
if (light_obj->get_type() == AmbientLight::get_class_type()) { if (light_obj->is_ambient_light()) {
// Ambient lights don't require specific light ids; simply add in the // Ambient lights don't require specific light ids; simply add in the
// ambient contribution to the current total // ambient contribution to the current total
cur_ambient_light += light_obj->get_color(); cur_ambient_light += light_obj->get_color();
@ -3143,11 +3146,12 @@ async_reload_texture(TextureContext *tc) {
*/ */
PT(Texture) GraphicsStateGuardian:: PT(Texture) GraphicsStateGuardian::
get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) { get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) || PandaNode *node = light_np.node();
light_np.node()->is_of_type(PointLight::get_class_type()) || nassertr(node->is_of_type(DirectionalLight::get_class_type()) ||
light_np.node()->is_of_type(Spotlight::get_class_type()), NULL); node->is_of_type(PointLight::get_class_type()) ||
node->is_of_type(Spotlight::get_class_type()), NULL);
PT(LightLensNode) light = DCAST(LightLensNode, light_np.node()); LightLensNode *light = (LightLensNode *)node;
if (light == NULL || !light->_shadow_caster) { if (light == NULL || !light->_shadow_caster) {
// TODO: return dummy shadow map (all white). // TODO: return dummy shadow map (all white).
return NULL; return NULL;
@ -3177,11 +3181,12 @@ get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
PT(Texture) GraphicsStateGuardian:: PT(Texture) GraphicsStateGuardian::
make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) { make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
// Make sure everything is valid. // Make sure everything is valid.
nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) || PandaNode *node = light_np.node();
light_np.node()->is_of_type(PointLight::get_class_type()) || nassertr(node->is_of_type(DirectionalLight::get_class_type()) ||
light_np.node()->is_of_type(Spotlight::get_class_type()), NULL); node->is_of_type(PointLight::get_class_type()) ||
node->is_of_type(Spotlight::get_class_type()), NULL);
PT(LightLensNode) light = DCAST(LightLensNode, light_np.node()); LightLensNode *light = (LightLensNode *)node;
if (light == NULL || !light->_shadow_caster) { if (light == NULL || !light->_shadow_caster) {
return NULL; return NULL;
} }

View File

@ -286,7 +286,7 @@ PUBLISHED:
MAKE_PROPERTY(driver_shader_version_minor, get_driver_shader_version_minor); MAKE_PROPERTY(driver_shader_version_minor, get_driver_shader_version_minor);
bool set_scene(SceneSetup *scene_setup); bool set_scene(SceneSetup *scene_setup);
virtual SceneSetup *get_scene() const; virtual SceneSetup *get_scene() const FINAL;
MAKE_PROPERTY(scene, get_scene, set_scene); MAKE_PROPERTY(scene, get_scene, set_scene);
public: public:

View File

@ -103,7 +103,7 @@ make_copy() const {
bool ProjectionScreen:: bool ProjectionScreen::
cull_callback(CullTraverser *, CullTraverserData &data) { cull_callback(CullTraverser *, CullTraverserData &data) {
if (_auto_recompute) { if (_auto_recompute) {
recompute_if_stale(data._node_path.get_node_path()); recompute_if_stale(data.get_node_path());
} }
return true; return true;
} }

View File

@ -295,10 +295,13 @@ show_trend_ages() {
*/ */
INLINE MemoryUsage *MemoryUsage:: INLINE MemoryUsage *MemoryUsage::
get_global_ptr() { get_global_ptr() {
if (_global_ptr == (MemoryUsage *)NULL) { #ifdef __GNUC__
init_memory_hook(); // Tell the compiler that this is an unlikely branch.
_global_ptr = new MemoryUsage(*memory_hook); if (__builtin_expect(_global_ptr == nullptr, 0)) {
memory_hook = _global_ptr; #else
if (_global_ptr == nullptr) {
#endif
init_memory_usage();
} }
return _global_ptr; return _global_ptr;

View File

@ -489,6 +489,16 @@ MemoryUsage(const MemoryHook &copy) : MemoryHook(copy) {
_total_size = 0; _total_size = 0;
} }
/**
* Initializes the global MemoryUsage pointer.
*/
void MemoryUsage::
init_memory_usage() {
init_memory_hook();
_global_ptr = new MemoryUsage(*memory_hook);
memory_hook = _global_ptr;
}
/** /**
* This callback method is called whenever the total allocated heap size * This callback method is called whenever the total allocated heap size
* exceeds _max_heap_size. It's mainly intended for reporting memory leaks, * exceeds _max_heap_size. It's mainly intended for reporting memory leaks,

View File

@ -95,6 +95,8 @@ private:
MemoryUsage(const MemoryHook &copy); MemoryUsage(const MemoryHook &copy);
INLINE static MemoryUsage *get_global_ptr(); INLINE static MemoryUsage *get_global_ptr();
static void init_memory_usage();
void ns_record_pointer(ReferenceCount *ptr); void ns_record_pointer(ReferenceCount *ptr);
void ns_update_type(ReferenceCount *ptr, TypeHandle type); void ns_update_type(ReferenceCount *ptr, TypeHandle type);
void ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr); void ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr);

View File

@ -21,9 +21,7 @@ PointerToBase(To *ptr) {
if (ptr != (To *)NULL) { if (ptr != (To *)NULL) {
ptr->ref(); ptr->ref();
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
if (MemoryUsage::get_track_memory_usage()) { update_type(ptr);
update_type(ptr);
}
#endif #endif
} }
} }
@ -38,11 +36,6 @@ PointerToBase(const PointerToBase<T> &copy) {
if (_void_ptr != NULL) { if (_void_ptr != NULL) {
To *ptr = (To *)_void_ptr; To *ptr = (To *)_void_ptr;
ptr->ref(); ptr->ref();
#ifdef DO_MEMORY_USAGE
if (MemoryUsage::get_track_memory_usage()) {
update_type(ptr);
}
#endif
} }
} }
@ -108,17 +101,15 @@ reassign(To *ptr) {
To *old_ptr = (To *)_void_ptr; To *old_ptr = (To *)_void_ptr;
_void_ptr = (void *)ptr; _void_ptr = (void *)ptr;
if (ptr != (To *)NULL) { if (ptr != nullptr) {
ptr->ref(); ptr->ref();
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
if (MemoryUsage::get_track_memory_usage()) { update_type(ptr);
update_type(ptr);
}
#endif #endif
} }
// Now delete the old pointer. // Now delete the old pointer.
if (old_ptr != (To *)NULL) { if (old_ptr != nullptr) {
unref_delete(old_ptr); unref_delete(old_ptr);
} }
} }
@ -130,7 +121,24 @@ reassign(To *ptr) {
template<class T> template<class T>
INLINE void PointerToBase<T>:: INLINE void PointerToBase<T>::
reassign(const PointerToBase<To> &copy) { reassign(const PointerToBase<To> &copy) {
reassign((To *)copy._void_ptr); if (copy._void_ptr != _void_ptr) {
// First save the old pointer; we won't delete it until we have assigned
// the new one. We do this just in case there are cascading effects from
// deleting this pointer that might inadvertently delete the new one.
// (Don't laugh--it's happened!)
To *old_ptr = (To *)_void_ptr;
To *new_ptr = (To *)copy._void_ptr;
_void_ptr = copy._void_ptr;
if (new_ptr != nullptr) {
new_ptr->ref();
}
// Now delete the old pointer.
if (old_ptr != nullptr) {
unref_delete(old_ptr);
}
}
} }
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
@ -139,15 +147,17 @@ reassign(const PointerToBase<To> &copy) {
* object, if we know the type ourselves. * object, if we know the type ourselves.
*/ */
template<class T> template<class T>
void PointerToBase<T>:: INLINE void PointerToBase<T>::
update_type(To *ptr) { update_type(To *ptr) {
TypeHandle type = get_type_handle(To); if (MemoryUsage::get_track_memory_usage()) {
if (type == TypeHandle::none()) { TypeHandle type = get_type_handle(To);
do_init_type(To); if (type == TypeHandle::none()) {
type = get_type_handle(To); do_init_type(To);
} type = get_type_handle(To);
if (type != TypeHandle::none()) { }
MemoryUsage::update_type(ptr, type); if (type != TypeHandle::none()) {
MemoryUsage::update_type(ptr, type);
}
} }
} }
#endif // DO_MEMORY_USAGE #endif // DO_MEMORY_USAGE

View File

@ -45,7 +45,7 @@ protected:
INLINE void reassign(const PointerToBase<To> &copy); INLINE void reassign(const PointerToBase<To> &copy);
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
void update_type(To *ptr); INLINE void update_type(To *ptr);
#endif // DO_MEMORY_USAGE #endif // DO_MEMORY_USAGE
// No assignment or retrieval functions are declared in PointerToBase, // No assignment or retrieval functions are declared in PointerToBase,

View File

@ -399,6 +399,7 @@ unbind() {
void CLP(CgShaderContext):: void CLP(CgShaderContext)::
set_state_and_transform(const RenderState *target_rs, set_state_and_transform(const RenderState *target_rs,
const TransformState *modelview_transform, const TransformState *modelview_transform,
const TransformState *camera_transform,
const TransformState *projection_transform) { const TransformState *projection_transform) {
if (!valid()) { if (!valid()) {
@ -410,6 +411,10 @@ set_state_and_transform(const RenderState *target_rs,
if (_modelview_transform != modelview_transform) { if (_modelview_transform != modelview_transform) {
_modelview_transform = modelview_transform; _modelview_transform = modelview_transform;
altered |= (Shader::SSD_transform & ~Shader::SSD_view_transform);
}
if (_camera_transform != camera_transform) {
_camera_transform = camera_transform;
altered |= Shader::SSD_transform; altered |= Shader::SSD_transform;
} }
if (_projection_transform != projection_transform) { if (_projection_transform != projection_transform) {

View File

@ -25,7 +25,7 @@ class CLP(GraphicsStateGuardian);
/** /**
* xyz * xyz
*/ */
class EXPCL_GL CLP(CgShaderContext) : public ShaderContext { class EXPCL_GL CLP(CgShaderContext) FINAL : public ShaderContext {
public: public:
friend class CLP(GraphicsStateGuardian); friend class CLP(GraphicsStateGuardian);
@ -39,7 +39,8 @@ public:
void set_state_and_transform(const RenderState *state, void set_state_and_transform(const RenderState *state,
const TransformState *modelview_transform, const TransformState *modelview_transform,
const TransformState *projection_transform); const TransformState *camera_transform,
const TransformState *projection_transform) OVERRIDE;
void issue_parameters(int altered) OVERRIDE; void issue_parameters(int altered) OVERRIDE;
void update_transform_table(const TransformTable *table); void update_transform_table(const TransformTable *table);
@ -77,6 +78,7 @@ private:
WCPT(RenderState) _state_rs; WCPT(RenderState) _state_rs;
CPT(TransformState) _modelview_transform; CPT(TransformState) _modelview_transform;
CPT(TransformState) _camera_transform;
CPT(TransformState) _projection_transform; CPT(TransformState) _projection_transform;
GLint _frame_number; GLint _frame_number;
@ -93,10 +95,10 @@ public:
register_type(_type_handle, CLASSPREFIX_QUOTED "CgShaderContext", register_type(_type_handle, CLASSPREFIX_QUOTED "CgShaderContext",
ShaderContext::get_class_type()); ShaderContext::get_class_type());
} }
virtual TypeHandle get_type() const { virtual TypeHandle get_type() const OVERRIDE {
return get_class_type(); return get_class_type();
} }
virtual TypeHandle force_init_type() {init_type(); return get_class_type();} virtual TypeHandle force_init_type() OVERRIDE {init_type(); return get_class_type();}
private: private:
static TypeHandle _type_handle; static TypeHandle _type_handle;

View File

@ -10350,7 +10350,7 @@ set_state_and_transform(const RenderState *target,
// Update all of the state that is bound to the shader program. // Update all of the state that is bound to the shader program.
if (_current_shader_context != NULL) { if (_current_shader_context != NULL) {
_current_shader_context->set_state_and_transform(target, transform, _projection_mat); _current_shader_context->set_state_and_transform(target, transform, _scene_setup->get_camera_transform(), _projection_mat);
} }
#endif #endif

View File

@ -874,7 +874,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
matrix_name.substr(0, 12) == "LightSource[" && matrix_name.substr(0, 12) == "LightSource[" &&
sscanf(matrix_name.c_str(), "LightSource[%d].%s", &bind._index, name_buffer) == 2) { sscanf(matrix_name.c_str(), "LightSource[%d].%s", &bind._index, name_buffer) == 2) {
// A matrix member of a p3d_LightSource struct. // A matrix member of a p3d_LightSource struct.
if (strncmp(name_buffer, "shadowMatrix", 127) == 0) { if (strncmp(name_buffer, "shadowViewMatrix", 127) == 0) {
if (inverse) { if (inverse) {
// Tack inverse back onto the end. // Tack inverse back onto the end.
strcpy(name_buffer + strlen(name_buffer), "Inverse"); strcpy(name_buffer + strlen(name_buffer), "Inverse");
@ -884,7 +884,25 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = Shader::SMO_light_source_i_attrib; bind._part[0] = Shader::SMO_light_source_i_attrib;
bind._arg[0] = InternalName::make(name_buffer); bind._arg[0] = InternalName::make(name_buffer);
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL;
} else if (strncmp(name_buffer, "shadowMatrix", 127) == 0) {
// Only supported for backward compatibility: includes the model
// matrix. Not very efficient to do this.
bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_model_to_apiview;
bind._arg[0] = NULL;
bind._part[1] = Shader::SMO_light_source_i_attrib;
bind._arg[1] = InternalName::make("shadowViewMatrix");
static bool warned = false;
if (!warned) {
warned = true;
GLCAT.warning()
<< "p3d_LightSource[].shadowMatrix is deprecated; use "
"shadowViewMatrix instead, which transforms from view space "
"instead of model space.\n";
}
} else { } else {
GLCAT.error() << "p3d_LightSource struct does not provide a matrix named " << matrix_name << "!\n"; GLCAT.error() << "p3d_LightSource struct does not provide a matrix named " << matrix_name << "!\n";
return; return;
@ -1163,11 +1181,16 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._index = index; bind._index = index;
bind._part[0] = Shader::SMO_light_source_i_attrib; bind._part[0] = Shader::SMO_light_source_i_attrib;
bind._arg[0] = InternalName::make(member_name); bind._arg[0] = InternalName::make(member_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_light | Shader::SSD_frame | Shader::SSD_transform; bind._dep[0] = Shader::SSD_general | Shader::SSD_light | Shader::SSD_frame;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL; bind._arg[1] = NULL;
bind._dep[1] = Shader::SSD_NONE; bind._dep[1] = Shader::SSD_NONE;
if (member_name == "position" || member_name == "halfVector" ||
member_name == "spotDirection") {
bind._dep[0] |= Shader::SSD_view_transform;
}
switch (param_type) { switch (param_type) {
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_row3x1; bind._piece = Shader::SMP_row3x1;
@ -1250,7 +1273,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_world_to_view; bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_view_to_apiview; bind._part[1] = Shader::SMO_view_to_apiview;
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; bind._dep[0] = Shader::SSD_general | Shader::SSD_view_transform;
bind._dep[1] = Shader::SSD_general; bind._dep[1] = Shader::SSD_general;
_shader->_mat_spec.push_back(bind); _shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1]; _shader->_mat_deps |= bind._dep[0] | bind._dep[1];
@ -1262,7 +1285,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = Shader::SMO_apiview_to_view; bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_world; bind._part[1] = Shader::SMO_view_to_world;
bind._dep[0] = Shader::SSD_general; bind._dep[0] = Shader::SSD_general;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; bind._dep[1] = Shader::SSD_general | Shader::SSD_view_transform;
_shader->_mat_spec.push_back(bind); _shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0] | bind._dep[1]; _shader->_mat_deps |= bind._dep[0] | bind._dep[1];
return; return;
@ -1383,22 +1406,43 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._id = arg_id; bind._id = arg_id;
bind._piece = Shader::SMP_whole; bind._piece = Shader::SMP_whole;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL;
bind._dep[1] = Shader::SSD_NONE;
PT(InternalName) iname = InternalName::make(param_name); PT(InternalName) iname = InternalName::make(param_name);
if (iname->get_parent() != InternalName::get_root()) { if (iname->get_parent() != InternalName::get_root()) {
// It might be something like an attribute of a shader input, like a // It might be something like an attribute of a shader input, like a
// light parameter. It might also just be a custom struct // light parameter. It might also just be a custom struct
// parameter. We can't know yet, sadly. // parameter. We can't know yet, sadly.
bind._part[0] = Shader::SMO_mat_constant_x_attrib; if (iname->get_basename() == "shadowMatrix") {
bind._arg[0] = InternalName::make(param_name); // Special exception for shadowMatrix, which is deprecated,
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_transform; // because it includes the model transformation. It is far more
// efficient to do that in the shader instead.
static bool warned = false;
if (!warned) {
warned = true;
GLCAT.warning()
<< "light.shadowMatrix inputs are deprecated; use "
"shadowViewMatrix instead, which transforms from view "
"space instead of model space.\n";
}
bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_model_to_apiview;
bind._arg[0] = NULL;
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._part[1] = Shader::SMO_mat_constant_x_attrib;
bind._arg[1] = InternalName::make("shadowViewMatrix");
bind._dep[1] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
} else {
bind._part[0] = Shader::SMO_mat_constant_x_attrib;
bind._arg[0] = InternalName::make(param_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
}
} else { } else {
bind._part[0] = Shader::SMO_mat_constant_x; bind._part[0] = Shader::SMO_mat_constant_x;
bind._arg[0] = InternalName::make(param_name); bind._arg[0] = InternalName::make(param_name);
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
} }
bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL;
bind._dep[1] = Shader::SSD_NONE;
_shader->_mat_spec.push_back(bind); _shader->_mat_spec.push_back(bind);
_shader->_mat_deps |= bind._dep[0]; _shader->_mat_deps |= bind._dep[0];
return; return;
@ -1430,9 +1474,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_vec_constant_x_attrib; bind._part[0] = Shader::SMO_vec_constant_x_attrib;
bind._arg[0] = iname; bind._arg[0] = iname;
// We need SSD_transform since some attributes (eg. light position) // We need SSD_view_transform since some attributes (eg. light
// have to be transformed to view space. // position) have to be transformed to view space.
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_transform; bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL; bind._arg[1] = NULL;
bind._dep[1] = Shader::SSD_NONE; bind._dep[1] = Shader::SSD_NONE;
@ -1822,6 +1866,7 @@ unbind() {
void CLP(ShaderContext):: void CLP(ShaderContext)::
set_state_and_transform(const RenderState *target_rs, set_state_and_transform(const RenderState *target_rs,
const TransformState *modelview_transform, const TransformState *modelview_transform,
const TransformState *camera_transform,
const TransformState *projection_transform) { const TransformState *projection_transform) {
// Find out which state properties have changed. // Find out which state properties have changed.
@ -1829,6 +1874,10 @@ set_state_and_transform(const RenderState *target_rs,
if (_modelview_transform != modelview_transform) { if (_modelview_transform != modelview_transform) {
_modelview_transform = modelview_transform; _modelview_transform = modelview_transform;
altered |= (Shader::SSD_transform & ~Shader::SSD_view_transform);
}
if (_camera_transform != camera_transform) {
_camera_transform = camera_transform;
altered |= Shader::SSD_transform; altered |= Shader::SSD_transform;
} }
if (_projection_transform != projection_transform) { if (_projection_transform != projection_transform) {
@ -2440,17 +2489,17 @@ update_shader_texture_bindings(ShaderContext *prev) {
const ParamTextureImage *param = NULL; const ParamTextureImage *param = NULL;
Texture *tex; Texture *tex;
const ShaderInput *sinp = _glgsg->_target_shader->get_shader_input(input._name); const ShaderInput &sinp = _glgsg->_target_shader->get_shader_input(input._name);
switch (sinp->get_value_type()) { switch (sinp.get_value_type()) {
case ShaderInput::M_texture_image: case ShaderInput::M_texture_image:
param = (const ParamTextureImage *)sinp->get_param(); param = (const ParamTextureImage *)sinp.get_param();
tex = param->get_texture(); tex = param->get_texture();
break; break;
case ShaderInput::M_texture: case ShaderInput::M_texture:
// People find it convenient to be able to pass a texture without // People find it convenient to be able to pass a texture without
// further ado. // further ado.
tex = sinp->get_texture(); tex = sinp.get_texture();
break; break;
case ShaderInput::M_invalid: case ShaderInput::M_invalid:

View File

@ -26,7 +26,7 @@ class CLP(GraphicsStateGuardian);
/** /**
* xyz * xyz
*/ */
class EXPCL_GL CLP(ShaderContext) : public ShaderContext { class EXPCL_GL CLP(ShaderContext) FINAL : public ShaderContext {
public: public:
friend class CLP(GraphicsStateGuardian); friend class CLP(GraphicsStateGuardian);
@ -41,18 +41,19 @@ public:
bool get_sampler_texture_type(int &out, GLenum param_type); bool get_sampler_texture_type(int &out, GLenum param_type);
INLINE bool valid(void); INLINE bool valid(void);
void bind(); void bind() OVERRIDE;
void unbind(); void unbind() OVERRIDE;
void set_state_and_transform(const RenderState *state, void set_state_and_transform(const RenderState *state,
const TransformState *modelview_transform, const TransformState *modelview_transform,
const TransformState *projection_transform); const TransformState *camera_transform,
const TransformState *projection_transform) OVERRIDE;
void issue_parameters(int altered); void issue_parameters(int altered) OVERRIDE;
void update_transform_table(const TransformTable *table); void update_transform_table(const TransformTable *table);
void update_slider_table(const SliderTable *table); void update_slider_table(const SliderTable *table);
void disable_shader_vertex_arrays(); void disable_shader_vertex_arrays() OVERRIDE;
bool update_shader_vertex_arrays(ShaderContext *prev, bool force); bool update_shader_vertex_arrays(ShaderContext *prev, bool force) OVERRIDE;
void disable_shader_texture_bindings() OVERRIDE; void disable_shader_texture_bindings() OVERRIDE;
void update_shader_texture_bindings(ShaderContext *prev) OVERRIDE; void update_shader_texture_bindings(ShaderContext *prev) OVERRIDE;
void update_shader_buffer_bindings(ShaderContext *prev) OVERRIDE; void update_shader_buffer_bindings(ShaderContext *prev) OVERRIDE;
@ -68,6 +69,7 @@ private:
WCPT(RenderState) _state_rs; WCPT(RenderState) _state_rs;
CPT(TransformState) _modelview_transform; CPT(TransformState) _modelview_transform;
CPT(TransformState) _camera_transform;
CPT(TransformState) _projection_transform; CPT(TransformState) _projection_transform;
/* /*
@ -126,10 +128,10 @@ public:
register_type(_type_handle, CLASSPREFIX_QUOTED "ShaderContext", register_type(_type_handle, CLASSPREFIX_QUOTED "ShaderContext",
ShaderContext::get_class_type()); ShaderContext::get_class_type());
} }
virtual TypeHandle get_type() const { virtual TypeHandle get_type() const OVERRIDE {
return get_class_type(); return get_class_type();
} }
virtual TypeHandle force_init_type() {init_type(); return get_class_type();} virtual TypeHandle force_init_type() OVERRIDE {init_type(); return get_class_type();}
private: private:
static TypeHandle _type_handle; static TypeHandle _type_handle;

View File

@ -114,12 +114,16 @@ update_page(AdaptiveLruPage *page) {
update_frames = (_current_frame_identifier - page->_update_frame_identifier); update_frames = (_current_frame_identifier - page->_update_frame_identifier);
if (update_frames > 0) { if (update_frames > 0) {
PN_stdfloat update_average_frame_utilization = if (page->_update_total_usage > 0) {
(PN_stdfloat) (page->_update_total_usage) / (PN_stdfloat)update_frames; PN_stdfloat update_average_frame_utilization =
(PN_stdfloat) (page->_update_total_usage) / (PN_stdfloat)update_frames;
page->_average_frame_utilization = page->_average_frame_utilization =
calculate_exponential_moving_average(update_average_frame_utilization, calculate_exponential_moving_average(update_average_frame_utilization,
page->_average_frame_utilization); page->_average_frame_utilization);
} else {
page->_average_frame_utilization *= 1.0f - _weight;
}
target_priority = page->_priority; target_priority = page->_priority;
if (page->_average_frame_utilization >= 1.0f) { if (page->_average_frame_utilization >= 1.0f) {

View File

@ -655,28 +655,72 @@ unify_in_place(int max_indices, bool preserve_order) {
// Should we split it up again to satisfy max_indices? // Should we split it up again to satisfy max_indices?
if (prim->get_num_vertices() > max_indices) { if (prim->get_num_vertices() > max_indices) {
// Copy prim into smaller prims, no one of which has more than
// max_indices vertices.
GeomPrimitivePipelineReader reader(prim, current_thread);
// Copy prim into smaller prims, no one of which has more than // Copy prim into smaller prims, no one of which has more than
// max_indices vertices. // max_indices vertices.
int i = 0; int i = 0;
int num_primitives = reader.get_num_primitives();
int num_vertices_per_primitive = prim->get_num_vertices_per_primitive();
int num_unused_vertices_per_primitive = prim->get_num_unused_vertices_per_primitive();
if (num_vertices_per_primitive != 0) {
// This is a simple primitive type like a triangle, where all the
// primitives share the same number of vertices.
int total_vertices_per_primitive = num_vertices_per_primitive + num_unused_vertices_per_primitive;
int max_primitives = max_indices / total_vertices_per_primitive;
const unsigned char *ptr = reader.get_read_pointer(true);
size_t stride = reader.get_index_stride();
while (i < prim->get_num_primitives()) { while (i < num_primitives) {
PT(GeomPrimitive) smaller = prim->make_copy(); PT(GeomPrimitive) smaller = prim->make_copy();
smaller->clear_vertices(); smaller->clear_vertices();
while (i < prim->get_num_primitives() &&
smaller->get_num_vertices() + prim->get_primitive_num_vertices(i) < max_indices) { // Since the number of vertices is consistent, we can calculate how
int start = prim->get_primitive_start(i); // many primitives will fit, and copy them all in one go.
int end = prim->get_primitive_end(i); int copy_primitives = min((num_primitives - i), max_primitives);
for (int n = start; n < end; ++n) { int num_vertices = copy_primitives * total_vertices_per_primitive;
smaller->add_vertex(prim->get_vertex(n)); nassertv(num_vertices > 0);
{
GeomVertexArrayDataHandle writer(smaller->modify_vertices(), current_thread);
writer.unclean_set_num_rows(num_vertices);
memcpy(writer.get_write_pointer(), ptr, stride * (size_t)(num_vertices - num_unused_vertices_per_primitive));
} }
smaller->close_primitive();
++i; cdata->_primitives.push_back(smaller.p());
ptr += stride * (size_t)num_vertices;
i += copy_primitives;
} }
} else {
// This is a complex primitive type like a triangle strip.
CPTA_int ends = reader.get_ends();
int start = 0;
int end = ends[0];
cdata->_primitives.push_back(smaller.p()); while (i < num_primitives) {
PT(GeomPrimitive) smaller = prim->make_copy();
smaller->clear_vertices();
while (smaller->get_num_vertices() + (end - start) < max_indices) {
for (int n = start; n < end; ++n) {
smaller->add_vertex(reader.get_vertex(n));
}
smaller->close_primitive();
++i;
if (i >= num_primitives) {
break;
}
start = end + num_unused_vertices_per_primitive;
end = ends[i];
}
cdata->_primitives.push_back(smaller.p());
}
} }
} else { } else {
// The prim has few enough vertices; keep it. // The prim has few enough vertices; keep it.
cdata->_primitives.push_back(prim); cdata->_primitives.push_back(prim);
@ -925,7 +969,8 @@ bool Geom::
check_valid() const { check_valid() const {
Thread *current_thread = Thread::get_current_thread(); Thread *current_thread = Thread::get_current_thread();
GeomPipelineReader geom_reader(this, current_thread); GeomPipelineReader geom_reader(this, current_thread);
GeomVertexDataPipelineReader data_reader(geom_reader.get_vertex_data(), current_thread); CPT(GeomVertexData) vertex_data = geom_reader.get_vertex_data();
GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
return geom_reader.check_valid(&data_reader); return geom_reader.check_valid(&data_reader);
} }
@ -1212,6 +1257,9 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
InternalName::get_vertex(), InternalName::get_vertex(),
cdata, current_thread); cdata, current_thread);
nassertv(!pmin.is_nan());
nassertv(!pmax.is_nan());
BoundingVolume::BoundsType btype = cdata->_bounds_type; BoundingVolume::BoundsType btype = cdata->_bounds_type;
if (btype == BoundingVolume::BT_default) { if (btype == BoundingVolume::BT_default) {
btype = bounds_type; btype = bounds_type;

View File

@ -124,8 +124,19 @@ get_vertex(int i) const {
*/ */
INLINE int GeomPrimitive:: INLINE int GeomPrimitive::
get_num_primitives() const { get_num_primitives() const {
GeomPrimitivePipelineReader reader(this, Thread::get_current_thread()); int num_vertices_per_primitive = get_num_vertices_per_primitive();
return reader.get_num_primitives();
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each primitive
// uses a different number of vertices.
CDReader cdata(_cycler);
return cdata->_ends.size();
} else {
// This is a simple primitive type like a triangle: each primitive uses
// the same number of vertices.
return (get_num_vertices() / num_vertices_per_primitive);
}
} }
/** /**

View File

@ -165,16 +165,17 @@ add_vertex(int vertex) {
consider_elevate_index_type(cdata, vertex); consider_elevate_index_type(cdata, vertex);
int num_primitives = get_num_primitives(); if (requires_unused_vertices()) {
if (num_primitives > 0 && int num_primitives = get_num_primitives();
requires_unused_vertices() && if (num_primitives > 0 &&
get_num_vertices() == get_primitive_end(num_primitives - 1)) { get_num_vertices() == get_primitive_end(num_primitives - 1)) {
// If we are beginning a new primitive, give the derived class a chance to // If we are beginning a new primitive, give the derived class a chance to
// insert some degenerate vertices. // insert some degenerate vertices.
if (cdata->_vertices.is_null()) { if (cdata->_vertices.is_null()) {
do_make_indexed(cdata); do_make_indexed(cdata);
}
append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex);
} }
append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex);
} }
if (cdata->_vertices.is_null()) { if (cdata->_vertices.is_null()) {
@ -199,11 +200,28 @@ add_vertex(int vertex) {
do_make_indexed(cdata); do_make_indexed(cdata);
} }
PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer(); {
GeomVertexWriter index(array_obj, 0); GeomVertexArrayDataHandle handle(cdata->_vertices.get_write_pointer(),
index.set_row_unsafe(array_obj->get_num_rows()); Thread::get_current_thread());
int num_rows = handle.get_num_rows();
handle.set_num_rows(num_rows + 1);
index.add_data1i(vertex); unsigned char *ptr = handle.get_write_pointer();
switch (cdata->_index_type) {
case GeomEnums::NT_uint8:
((uint8_t *)ptr)[num_rows] = vertex;
break;
case GeomEnums::NT_uint16:
((uint16_t *)ptr)[num_rows] = vertex;
break;
case GeomEnums::NT_uint32:
((uint32_t *)ptr)[num_rows] = vertex;
break;
default:
nassertv(false);
break;
}
}
cdata->_modified = Geom::get_next_modified(); cdata->_modified = Geom::get_next_modified();
cdata->_got_minmax = false; cdata->_got_minmax = false;
@ -888,21 +906,9 @@ make_points() const {
// First, get a list of all of the vertices referenced by the original // First, get a list of all of the vertices referenced by the original
// primitive. // primitive.
BitArray bits; BitArray bits;
int num_vertices = get_num_vertices(); {
if (is_indexed()) { GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
CPT(GeomVertexArrayData) vertices = get_vertices(); reader.get_referenced_vertices(bits);
int strip_cut_index = get_strip_cut_index();
GeomVertexReader index(vertices, 0);
for (int vi = 0; vi < num_vertices; ++vi) {
nassertr(!index.is_at_end(), NULL);
int vertex = index.get_data1i();
if (vertex != strip_cut_index) {
bits.set_bit(vertex);
}
}
} else {
int first_vertex = get_first_vertex();
bits.set_range(first_vertex, num_vertices);
} }
// Now construct a new index array with just those bits. // Now construct a new index array with just those bits.
@ -2200,9 +2206,21 @@ get_vertex(int i) const {
// The indexed case. // The indexed case.
nassertr(i >= 0 && i < get_num_vertices(), -1); nassertr(i >= 0 && i < get_num_vertices(), -1);
GeomVertexReader index(_vertices, 0); const unsigned char *ptr = get_read_pointer(true);
index.set_row_unsafe(i); switch (_cdata->_index_type) {
return index.get_data1i(); case GeomEnums::NT_uint8:
return ((uint8_t *)ptr)[i];
break;
case GeomEnums::NT_uint16:
return ((uint16_t *)ptr)[i];
break;
case GeomEnums::NT_uint32:
return ((uint32_t *)ptr)[i];
break;
default:
nassertr(false, -1);
return -1;
}
} else { } else {
// The nonindexed case. // The nonindexed case.
@ -2229,6 +2247,52 @@ get_num_primitives() const {
} }
} }
/**
* Turns on all the bits corresponding to the vertices that are referenced
* by this GeomPrimitive.
*/
void GeomPrimitivePipelineReader::
get_referenced_vertices(BitArray &bits) const {
int num_vertices = get_num_vertices();
if (is_indexed()) {
int strip_cut_index = get_strip_cut_index();
const unsigned char *ptr = get_read_pointer(true);
switch (get_index_type()) {
case GeomEnums::NT_uint8:
for (int vi = 0; vi < num_vertices; ++vi) {
int index = ((const uint8_t *)ptr)[vi];
if (index != strip_cut_index) {
bits.set_bit(index);
}
}
break;
case GeomEnums::NT_uint16:
for (int vi = 0; vi < num_vertices; ++vi) {
int index = ((const uint16_t *)ptr)[vi];
if (index != strip_cut_index) {
bits.set_bit(index);
}
}
break;
case GeomEnums::NT_uint32:
for (int vi = 0; vi < num_vertices; ++vi) {
int index = ((const uint32_t *)ptr)[vi];
if (index != strip_cut_index) {
bits.set_bit(index);
}
}
break;
default:
nassertv(false);
break;
}
} else {
// Nonindexed case.
bits.set_range(get_first_vertex(), num_vertices);
}
}
/** /**
* *
*/ */

View File

@ -371,6 +371,7 @@ public:
INLINE int get_num_vertices() const; INLINE int get_num_vertices() const;
int get_vertex(int i) const; int get_vertex(int i) const;
int get_num_primitives() const; int get_num_primitives() const;
void get_referenced_vertices(BitArray &bits) const;
INLINE int get_min_vertex() const; INLINE int get_min_vertex() const;
INLINE int get_max_vertex() const; INLINE int get_max_vertex() const;
INLINE int get_data_size_bytes() const; INLINE int get_data_size_bytes() const;

View File

@ -756,7 +756,7 @@ GeomVertexDataPipelineReader(const GeomVertexData *object,
* *
*/ */
INLINE void GeomVertexDataPipelineReader:: INLINE void GeomVertexDataPipelineReader::
set_object(CPT(GeomVertexData) object) { set_object(const GeomVertexData *object) {
#ifdef DO_PIPELINING #ifdef DO_PIPELINING
if (_cdata != NULL) { if (_cdata != NULL) {
unref_delete((CycleData *)_cdata); unref_delete((CycleData *)_cdata);
@ -764,7 +764,7 @@ set_object(CPT(GeomVertexData) object) {
#endif // DO_PIPELINING #endif // DO_PIPELINING
_array_readers.clear(); _array_readers.clear();
_object.swap(object); _object = (GeomVertexData *)object;
_cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread); _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
_got_array_readers = false; _got_array_readers = false;

View File

@ -432,7 +432,7 @@ public:
INLINE UpdateSeq get_modified() const; INLINE UpdateSeq get_modified() const;
protected: protected:
PT(GeomVertexData) _object; GeomVertexData *_object;
Thread *_current_thread; Thread *_current_thread;
GeomVertexData::CData *_cdata; GeomVertexData::CData *_cdata;
}; };
@ -440,6 +440,8 @@ protected:
/** /**
* Encapsulates the data from a GeomVertexData, pre-fetched for one stage of * Encapsulates the data from a GeomVertexData, pre-fetched for one stage of
* the pipeline. * the pipeline.
* Does not hold a reference to the GeomVertexData, so make sure it does not
* go out of scope.
*/ */
class EXPCL_PANDA_GOBJ GeomVertexDataPipelineReader : public GeomVertexDataPipelineBase { class EXPCL_PANDA_GOBJ GeomVertexDataPipelineReader : public GeomVertexDataPipelineBase {
public: public:
@ -448,7 +450,7 @@ public:
ALLOC_DELETED_CHAIN(GeomVertexDataPipelineReader); ALLOC_DELETED_CHAIN(GeomVertexDataPipelineReader);
INLINE void set_object(CPT(GeomVertexData) object); INLINE void set_object(const GeomVertexData *object);
INLINE const GeomVertexData *get_object() const; INLINE const GeomVertexData *get_object() const;
INLINE void check_array_readers() const; INLINE void check_array_readers() const;
@ -504,6 +506,8 @@ private:
/** /**
* Encapsulates the data from a GeomVertexData, pre-fetched for one stage of * Encapsulates the data from a GeomVertexData, pre-fetched for one stage of
* the pipeline. * the pipeline.
* Does not hold a reference to the GeomVertexData, so make sure it does not
* go out of scope.
*/ */
class EXPCL_PANDA_GOBJ GeomVertexDataPipelineWriter : public GeomVertexDataPipelineBase { class EXPCL_PANDA_GOBJ GeomVertexDataPipelineWriter : public GeomVertexDataPipelineBase {
public: public:

View File

@ -178,6 +178,12 @@ private:
static TypeHandle _texcoord_type_handle; static TypeHandle _texcoord_type_handle;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<InternalName>::update_type(To *ptr) {}
#endif
INLINE ostream &operator << (ostream &out, const InternalName &tcn); INLINE ostream &operator << (ostream &out, const InternalName &tcn);
/** /**

View File

@ -390,8 +390,10 @@ cp_dependency(ShaderMatInput inp) {
if ((inp == SMO_model_to_view) || if ((inp == SMO_model_to_view) ||
(inp == SMO_view_to_model) || (inp == SMO_view_to_model) ||
(inp == SMO_model_to_apiview) || (inp == SMO_model_to_apiview) ||
(inp == SMO_apiview_to_model) || (inp == SMO_apiview_to_model)) {
(inp == SMO_view_to_world) || dep |= SSD_transform;
}
if ((inp == SMO_view_to_world) ||
(inp == SMO_world_to_view) || (inp == SMO_world_to_view) ||
(inp == SMO_view_x_to_view) || (inp == SMO_view_x_to_view) ||
(inp == SMO_view_to_view_x) || (inp == SMO_view_to_view_x) ||
@ -404,7 +406,7 @@ cp_dependency(ShaderMatInput inp) {
(inp == SMO_dlight_x) || (inp == SMO_dlight_x) ||
(inp == SMO_plight_x) || (inp == SMO_plight_x) ||
(inp == SMO_slight_x)) { (inp == SMO_slight_x)) {
dep |= SSD_transform; dep |= SSD_view_transform;
} }
if ((inp == SMO_texpad_x) || if ((inp == SMO_texpad_x) ||
(inp == SMO_texpix_x) || (inp == SMO_texpix_x) ||
@ -449,7 +451,7 @@ cp_dependency(ShaderMatInput inp) {
(inp == SMO_light_source_i_attrib)) { (inp == SMO_light_source_i_attrib)) {
dep |= SSD_light; dep |= SSD_light;
if (inp == SMO_light_source_i_attrib) { if (inp == SMO_light_source_i_attrib) {
dep |= SSD_transform; dep |= SSD_view_transform;
} }
} }
if ((inp == SMO_light_product_i_ambient) || if ((inp == SMO_light_product_i_ambient) ||

View File

@ -287,7 +287,7 @@ public:
enum ShaderStateDep { enum ShaderStateDep {
SSD_NONE = 0x000, SSD_NONE = 0x000,
SSD_general = 0x001, SSD_general = 0x001,
SSD_transform = 0x002, SSD_transform = 0x2002,
SSD_color = 0x004, SSD_color = 0x004,
SSD_colorscale = 0x008, SSD_colorscale = 0x008,
SSD_material = 0x010, SSD_material = 0x010,
@ -299,6 +299,7 @@ public:
SSD_frame = 0x400, SSD_frame = 0x400,
SSD_projection = 0x800, SSD_projection = 0x800,
SSD_texture = 0x1000, SSD_texture = 0x1000,
SSD_view_transform= 0x2000,
}; };
enum ShaderBug { enum ShaderBug {

View File

@ -32,7 +32,10 @@ class EXPCL_PANDA_GOBJ ShaderContext: public SavedContext {
public: public:
INLINE ShaderContext(Shader *se); INLINE ShaderContext(Shader *se);
INLINE virtual void set_state_and_transform(const RenderState *, const TransformState *, const TransformState*) {}; virtual void set_state_and_transform(const RenderState *,
const TransformState *,
const TransformState *,
const TransformState *) {};
INLINE virtual bool valid() { return false; } INLINE virtual bool valid() { return false; }
INLINE virtual void bind() {}; INLINE virtual void bind() {};

View File

@ -464,42 +464,33 @@ void PipeOcclusionCullTraverser::
make_box() { make_box() {
PT(GeomVertexData) vdata = new GeomVertexData PT(GeomVertexData) vdata = new GeomVertexData
("occlusion_box", GeomVertexFormat::get_v3(), Geom::UH_static); ("occlusion_box", GeomVertexFormat::get_v3(), Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex()); vdata->unclean_set_num_rows(8);
vertex.add_data3(0.0f, 0.0f, 0.0f); {
vertex.add_data3(0.0f, 0.0f, 1.0f); GeomVertexWriter vertex(vdata, InternalName::get_vertex());
vertex.add_data3(0.0f, 1.0f, 0.0f); vertex.set_data3(0.0f, 0.0f, 0.0f);
vertex.add_data3(0.0f, 1.0f, 1.0f); vertex.set_data3(0.0f, 0.0f, 1.0f);
vertex.add_data3(1.0f, 0.0f, 0.0f); vertex.set_data3(0.0f, 1.0f, 0.0f);
vertex.add_data3(1.0f, 0.0f, 1.0f); vertex.set_data3(0.0f, 1.0f, 1.0f);
vertex.add_data3(1.0f, 1.0f, 0.0f); vertex.set_data3(1.0f, 0.0f, 0.0f);
vertex.add_data3(1.0f, 1.0f, 1.0f); vertex.set_data3(1.0f, 0.0f, 1.0f);
vertex.set_data3(1.0f, 1.0f, 0.0f);
vertex.set_data3(1.0f, 1.0f, 1.0f);
}
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static); PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
tris->add_vertices(0, 4, 5); tris->add_vertices(0, 4, 5);
tris->close_primitive();
tris->add_vertices(0, 5, 1); tris->add_vertices(0, 5, 1);
tris->close_primitive();
tris->add_vertices(4, 6, 7); tris->add_vertices(4, 6, 7);
tris->close_primitive();
tris->add_vertices(4, 7, 5); tris->add_vertices(4, 7, 5);
tris->close_primitive();
tris->add_vertices(6, 2, 3); tris->add_vertices(6, 2, 3);
tris->close_primitive();
tris->add_vertices(6, 3, 7); tris->add_vertices(6, 3, 7);
tris->close_primitive();
tris->add_vertices(2, 0, 1); tris->add_vertices(2, 0, 1);
tris->close_primitive();
tris->add_vertices(2, 1, 3); tris->add_vertices(2, 1, 3);
tris->close_primitive();
tris->add_vertices(1, 5, 7); tris->add_vertices(1, 5, 7);
tris->close_primitive();
tris->add_vertices(1, 7, 3); tris->add_vertices(1, 7, 3);
tris->close_primitive();
tris->add_vertices(2, 6, 4); tris->add_vertices(2, 6, 4);
tris->close_primitive();
tris->add_vertices(2, 4, 0); tris->add_vertices(2, 4, 0);
tris->close_primitive();
_box_geom = new Geom(vdata); _box_geom = new Geom(vdata);
_box_geom->add_primitive(tris); _box_geom->add_primitive(tris);

View File

@ -513,15 +513,15 @@ void ShaderTerrainMesh::add_for_draw(CullTraverser *trav, CullTraverserData &dat
nassertv(current_shader_attrib != NULL); nassertv(current_shader_attrib != NULL);
current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input(
new ShaderInput("ShaderTerrainMesh.terrain_size", LVecBase2i(_size)) ); ShaderInput("ShaderTerrainMesh.terrain_size", LVecBase2i(_size)));
current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input(
new ShaderInput("ShaderTerrainMesh.chunk_size", LVecBase2i(_chunk_size))); ShaderInput("ShaderTerrainMesh.chunk_size", LVecBase2i(_chunk_size)));
current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input(
new ShaderInput("ShaderTerrainMesh.view_index", LVecBase2i(_current_view_index))); ShaderInput("ShaderTerrainMesh.view_index", LVecBase2i(_current_view_index)));
current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input(
new ShaderInput("ShaderTerrainMesh.data_texture", _data_texture)); ShaderInput("ShaderTerrainMesh.data_texture", _data_texture));
current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input(
new ShaderInput("ShaderTerrainMesh.heightfield", _heightfield_tex)); ShaderInput("ShaderTerrainMesh.heightfield", _heightfield_tex));
current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_instance_count( current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_instance_count(
traversal_data.emitted_chunks); traversal_data.emitted_chunks);

View File

@ -16,6 +16,9 @@
*/ */
INLINE_MATHUTIL GeometricBoundingVolume:: INLINE_MATHUTIL GeometricBoundingVolume::
GeometricBoundingVolume() { GeometricBoundingVolume() {
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif
} }
/** /**

View File

@ -83,6 +83,12 @@ private:
static TypeHandle _type_handle; static TypeHandle _type_handle;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<GeometricBoundingVolume>::update_type(To *ptr) {}
#endif
#include "geometricBoundingVolume.I" #include "geometricBoundingVolume.I"
#endif #endif

View File

@ -132,9 +132,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
if (curve != (NurbsCurveEvaluator *)NULL) { if (curve != (NurbsCurveEvaluator *)NULL) {
PT(NurbsCurveResult) result; PT(NurbsCurveResult) result;
if (has_matrix()) { if (has_matrix()) {
result = curve->evaluate(data._node_path.get_node_path(), get_matrix()); result = curve->evaluate(data.get_node_path(), get_matrix());
} else { } else {
result = curve->evaluate(data._node_path.get_node_path()); result = curve->evaluate(data.get_node_path());
} }
if (result->get_num_segments() > 0) { if (result->get_num_segments() > 0) {

View File

@ -129,7 +129,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
if (get_num_u_subdiv() > 0 && get_num_v_subdiv() > 0) { if (get_num_u_subdiv() > 0 && get_num_v_subdiv() > 0) {
NurbsSurfaceEvaluator *surface = get_surface(); NurbsSurfaceEvaluator *surface = get_surface();
if (surface != (NurbsSurfaceEvaluator *)NULL) { if (surface != (NurbsSurfaceEvaluator *)NULL) {
PT(NurbsSurfaceResult) result = surface->evaluate(data._node_path.get_node_path()); PT(NurbsSurfaceResult) result = surface->evaluate(data.get_node_path());
if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) { if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) {
render_sheet(trav, data, result); render_sheet(trav, data, result);

View File

@ -164,7 +164,7 @@ has_adjust_transform() const {
void BillboardEffect:: void BillboardEffect::
adjust_transform(CPT(TransformState) &net_transform, adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *) const { const PandaNode *) const {
// A BillboardEffect can only affect the net transform when it is to a // A BillboardEffect can only affect the net transform when it is to a
// particular node. A billboard to a camera is camera-dependent, of course, // particular node. A billboard to a camera is camera-dependent, of course,
// so it has no effect in the absence of any particular camera viewing it. // so it has no effect in the absence of any particular camera viewing it.

View File

@ -60,7 +60,7 @@ public:
virtual bool has_adjust_transform() const; virtual bool has_adjust_transform() const;
virtual void adjust_transform(CPT(TransformState) &net_transform, virtual void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const; const PandaNode *node) const;
protected: protected:
virtual int compare_to_impl(const RenderEffect *other) const; virtual int compare_to_impl(const RenderEffect *other) const;

View File

@ -157,7 +157,7 @@ has_adjust_transform() const {
void CompassEffect:: void CompassEffect::
adjust_transform(CPT(TransformState) &net_transform, adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *) const { const PandaNode *) const {
if (_properties == 0) { if (_properties == 0) {
// Nothing to do. // Nothing to do.
return; return;

View File

@ -78,7 +78,7 @@ public:
virtual bool has_adjust_transform() const; virtual bool has_adjust_transform() const;
virtual void adjust_transform(CPT(TransformState) &net_transform, virtual void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const; const PandaNode *node) const;
protected: protected:
virtual int compare_to_impl(const RenderEffect *other) const; virtual int compare_to_impl(const RenderEffect *other) const;

View File

@ -78,7 +78,6 @@
#include "scissorAttrib.h" #include "scissorAttrib.h"
#include "scissorEffect.h" #include "scissorEffect.h"
#include "shadeModelAttrib.h" #include "shadeModelAttrib.h"
#include "shaderInput.h"
#include "shaderAttrib.h" #include "shaderAttrib.h"
#include "shader.h" #include "shader.h"
#include "showBoundsEffect.h" #include "showBoundsEffect.h"
@ -449,7 +448,6 @@ init_libpgraph() {
ScissorAttrib::init_type(); ScissorAttrib::init_type();
ScissorEffect::init_type(); ScissorEffect::init_type();
ShadeModelAttrib::init_type(); ShadeModelAttrib::init_type();
ShaderInput::init_type();
ShaderAttrib::init_type(); ShaderAttrib::init_type();
ShowBoundsEffect::init_type(); ShowBoundsEffect::init_type();
StateMunger::init_type(); StateMunger::init_type();
@ -502,7 +500,6 @@ init_libpgraph() {
ScissorAttrib::register_with_read_factory(); ScissorAttrib::register_with_read_factory();
ScissorEffect::register_with_read_factory(); ScissorEffect::register_with_read_factory();
ShadeModelAttrib::register_with_read_factory(); ShadeModelAttrib::register_with_read_factory();
ShaderInput::register_with_read_factory();
ShaderAttrib::register_with_read_factory(); ShaderAttrib::register_with_read_factory();
ShowBoundsEffect::register_with_read_factory(); ShowBoundsEffect::register_with_read_factory();
TexMatrixAttrib::register_with_read_factory(); TexMatrixAttrib::register_with_read_factory();

View File

@ -315,11 +315,10 @@ do_cull(int &result, CPT(RenderState) &state,
result = result =
BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some; BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
CPT(ClipPlaneAttrib) orig_cpa = DCAST(ClipPlaneAttrib, state->get_attrib(ClipPlaneAttrib::get_class_slot()));
CPT(CullPlanes) new_planes = this; CPT(CullPlanes) new_planes = this;
if (orig_cpa == (ClipPlaneAttrib *)NULL) { const ClipPlaneAttrib *orig_cpa;
if (!state->get_attrib(orig_cpa)) {
// If there are no clip planes in the state, the node is completely in // If there are no clip planes in the state, the node is completely in
// front of all zero of the clip planes. (This can happen if someone // front of all zero of the clip planes. (This can happen if someone
// directly changes the state during the traversal.) // directly changes the state during the traversal.)

View File

@ -74,6 +74,12 @@ private:
Occluders _occluders; Occluders _occluders;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<CullPlanes>::update_type(To *ptr) {}
#endif
#include "cullPlanes.I" #include "cullPlanes.I"
#endif #endif

View File

@ -200,20 +200,14 @@ do_traverse(CullTraverserData &data) {
if (is_in_view(data)) { if (is_in_view(data)) {
if (pgraph_cat.is_spam()) { if (pgraph_cat.is_spam()) {
pgraph_cat.spam() pgraph_cat.spam()
<< "\n" << data._node_path << "\n" << data.get_node_path()
<< " " << data._draw_mask << "\n"; << " " << data._draw_mask << "\n";
} }
PandaNodePipelineReader *node_reader = data.node_reader(); PandaNodePipelineReader *node_reader = data.node_reader();
int fancy_bits = node_reader->get_fancy_bits(); int fancy_bits = node_reader->get_fancy_bits();
if ((fancy_bits & (PandaNode::FB_transform | if (fancy_bits == 0 && data._cull_planes->is_empty()) {
PandaNode::FB_state |
PandaNode::FB_effects |
PandaNode::FB_tag |
PandaNode::FB_draw_mask |
PandaNode::FB_cull_callback)) == 0 &&
data._cull_planes->is_empty()) {
// Nothing interesting in this node; just move on. // Nothing interesting in this node; just move on.
} else { } else {

View File

@ -113,10 +113,8 @@ traverse(const NodePath &root) {
GeometricBoundingVolume *local_frustum = NULL; GeometricBoundingVolume *local_frustum = NULL;
PT(BoundingVolume) bv = _scene_setup->get_lens()->make_bounds(); PT(BoundingVolume) bv = _scene_setup->get_lens()->make_bounds();
if (bv != (BoundingVolume *)NULL && if (bv != nullptr) {
bv->is_of_type(GeometricBoundingVolume::get_class_type())) { local_frustum = bv->as_geometric_bounding_volume();
local_frustum = DCAST(GeometricBoundingVolume, bv);
} }
// This local_frustum is in camera space // This local_frustum is in camera space
@ -199,19 +197,18 @@ traverse_below(CullTraverserData &data) {
PandaNode::Children children = node_reader->get_children(); PandaNode::Children children = node_reader->get_children();
node_reader->release(); node_reader->release();
int num_children = children.get_num_children(); int num_children = children.get_num_children();
if (node->has_selective_visibility()) { if (!node->has_selective_visibility()) {
for (int i = 0; i < num_children; ++i) {
CullTraverserData next_data(data, children.get_child(i));
do_traverse(next_data);
}
} else {
int i = node->get_first_visible_child(); int i = node->get_first_visible_child();
while (i < num_children) { while (i < num_children) {
CullTraverserData next_data(data, children.get_child(i)); CullTraverserData next_data(data, children.get_child(i));
do_traverse(next_data); do_traverse(next_data);
i = node->get_next_visible_child(i); i = node->get_next_visible_child(i);
} }
} else {
for (int i = 0; i < num_children; i++) {
CullTraverserData next_data(data, children.get_child(i));
do_traverse(next_data);
}
} }
} }
@ -235,12 +232,12 @@ draw_bounding_volume(const BoundingVolume *vol,
if (bounds_viz != (Geom *)NULL) { if (bounds_viz != (Geom *)NULL) {
_geoms_pcollector.add_level(2); _geoms_pcollector.add_level(2);
CullableObject *outer_viz = CullableObject *outer_viz =
new CullableObject(bounds_viz, get_bounds_outer_viz_state(), new CullableObject(move(bounds_viz), get_bounds_outer_viz_state(),
internal_transform); internal_transform);
_cull_handler->record_object(outer_viz, this); _cull_handler->record_object(outer_viz, this);
CullableObject *inner_viz = CullableObject *inner_viz =
new CullableObject(bounds_viz, get_bounds_inner_viz_state(), new CullableObject(move(bounds_viz), get_bounds_inner_viz_state(),
internal_transform); internal_transform);
_cull_handler->record_object(inner_viz, this); _cull_handler->record_object(inner_viz, this);
} }
@ -270,7 +267,7 @@ show_bounds(CullTraverserData &data, bool tight) {
if (bounds_viz != (Geom *)NULL) { if (bounds_viz != (Geom *)NULL) {
_geoms_pcollector.add_level(1); _geoms_pcollector.add_level(1);
CullableObject *outer_viz = CullableObject *outer_viz =
new CullableObject(bounds_viz, get_bounds_outer_viz_state(), new CullableObject(move(bounds_viz), get_bounds_outer_viz_state(),
internal_transform); internal_transform);
_cull_handler->record_object(outer_viz, this); _cull_handler->record_object(outer_viz, this);
} }
@ -281,7 +278,7 @@ show_bounds(CullTraverserData &data, bool tight) {
if (node->is_geom_node()) { if (node->is_geom_node()) {
// Also show the bounding volumes of included Geoms. // Also show the bounding volumes of included Geoms.
internal_transform = internal_transform->compose(node->get_transform()); internal_transform = internal_transform->compose(node->get_transform());
GeomNode *gnode = DCAST(GeomNode, node); GeomNode *gnode = (GeomNode *)node;
int num_geoms = gnode->get_num_geoms(); int num_geoms = gnode->get_num_geoms();
for (int i = 0; i < num_geoms; ++i) { 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(),
@ -334,29 +331,31 @@ make_bounds_viz(const BoundingVolume *vol) {
const BoundingHexahedron *fvol = DCAST(BoundingHexahedron, vol); const BoundingHexahedron *fvol = DCAST(BoundingHexahedron, vol);
PT(GeomVertexData) vdata = new GeomVertexData PT(GeomVertexData) vdata = new GeomVertexData
("bounds", GeomVertexFormat::get_v3(), ("bounds", GeomVertexFormat::get_v3(), Geom::UH_stream);
Geom::UH_stream); vdata->unclean_set_num_rows(8);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
for (int i = 0; i < 8; ++i ) { {
vertex.add_data3(fvol->get_point(i)); GeomVertexWriter vertex(vdata, InternalName::get_vertex());
for (int i = 0; i < 8; ++i) {
vertex.set_data3(fvol->get_point(i));
}
} }
PT(GeomLines) lines = new GeomLines(Geom::UH_stream); PT(GeomLines) lines = new GeomLines(Geom::UH_stream);
lines->add_vertices(0, 1); lines->close_primitive(); lines->add_vertices(0, 1);
lines->add_vertices(1, 2); lines->close_primitive(); lines->add_vertices(1, 2);
lines->add_vertices(2, 3); lines->close_primitive(); lines->add_vertices(2, 3);
lines->add_vertices(3, 0); lines->close_primitive(); lines->add_vertices(3, 0);
lines->add_vertices(4, 5); lines->close_primitive(); lines->add_vertices(4, 5);
lines->add_vertices(5, 6); lines->close_primitive(); lines->add_vertices(5, 6);
lines->add_vertices(6, 7); lines->close_primitive(); lines->add_vertices(6, 7);
lines->add_vertices(7, 4); lines->close_primitive(); lines->add_vertices(7, 4);
lines->add_vertices(0, 4); lines->close_primitive(); lines->add_vertices(0, 4);
lines->add_vertices(1, 5); lines->close_primitive(); lines->add_vertices(1, 5);
lines->add_vertices(2, 6); lines->close_primitive(); lines->add_vertices(2, 6);
lines->add_vertices(3, 7); lines->close_primitive(); lines->add_vertices(3, 7);
geom = new Geom(vdata); geom = new Geom(vdata);
geom->add_primitive(lines); geom->add_primitive(lines);
@ -368,39 +367,29 @@ make_bounds_viz(const BoundingVolume *vol) {
box.local_object(); box.local_object();
PT(GeomVertexData) vdata = new GeomVertexData PT(GeomVertexData) vdata = new GeomVertexData
("bounds", GeomVertexFormat::get_v3(), ("bounds", GeomVertexFormat::get_v3(), Geom::UH_stream);
Geom::UH_stream); vdata->unclean_set_num_rows(8);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
for (int i = 0; i < 8; ++i ) { {
vertex.add_data3(box.get_point(i)); GeomVertexWriter vertex(vdata, InternalName::get_vertex());
for (int i = 0; i < 8; ++i) {
vertex.set_data3(box.get_point(i));
}
} }
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_stream); PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_stream);
tris->add_vertices(0, 4, 5); tris->add_vertices(0, 4, 5);
tris->close_primitive();
tris->add_vertices(0, 5, 1); tris->add_vertices(0, 5, 1);
tris->close_primitive();
tris->add_vertices(4, 6, 7); tris->add_vertices(4, 6, 7);
tris->close_primitive();
tris->add_vertices(4, 7, 5); tris->add_vertices(4, 7, 5);
tris->close_primitive();
tris->add_vertices(6, 2, 3); tris->add_vertices(6, 2, 3);
tris->close_primitive();
tris->add_vertices(6, 3, 7); tris->add_vertices(6, 3, 7);
tris->close_primitive();
tris->add_vertices(2, 0, 1); tris->add_vertices(2, 0, 1);
tris->close_primitive();
tris->add_vertices(2, 1, 3); tris->add_vertices(2, 1, 3);
tris->close_primitive();
tris->add_vertices(1, 5, 7); tris->add_vertices(1, 5, 7);
tris->close_primitive();
tris->add_vertices(1, 7, 3); tris->add_vertices(1, 7, 3);
tris->close_primitive();
tris->add_vertices(2, 6, 4); tris->add_vertices(2, 6, 4);
tris->close_primitive();
tris->add_vertices(2, 4, 0); tris->add_vertices(2, 4, 0);
tris->close_primitive();
geom = new Geom(vdata); geom = new Geom(vdata);
geom->add_primitive(tris); geom->add_primitive(tris);
@ -430,19 +419,21 @@ make_tight_bounds_viz(PandaNode *node) const {
_current_thread); _current_thread);
if (found_any) { if (found_any) {
PT(GeomVertexData) vdata = new GeomVertexData PT(GeomVertexData) vdata = new GeomVertexData
("bounds", GeomVertexFormat::get_v3(), ("bounds", GeomVertexFormat::get_v3(), Geom::UH_stream);
Geom::UH_stream); vdata->unclean_set_num_rows(8);
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]); GeomVertexWriter vertex(vdata, InternalName::get_vertex(),
vertex.add_data3(n[0], x[1], n[2]); _current_thread);
vertex.add_data3(n[0], x[1], x[2]); vertex.set_data3(n[0], n[1], n[2]);
vertex.add_data3(x[0], n[1], n[2]); vertex.set_data3(n[0], n[1], x[2]);
vertex.add_data3(x[0], n[1], x[2]); vertex.set_data3(n[0], x[1], n[2]);
vertex.add_data3(x[0], x[1], n[2]); vertex.set_data3(n[0], x[1], x[2]);
vertex.add_data3(x[0], x[1], x[2]); vertex.set_data3(x[0], n[1], n[2]);
vertex.set_data3(x[0], n[1], x[2]);
vertex.set_data3(x[0], x[1], n[2]);
vertex.set_data3(x[0], x[1], x[2]);
}
PT(GeomLinestrips) strip = new GeomLinestrips(Geom::UH_stream); PT(GeomLinestrips) strip = new GeomLinestrips(Geom::UH_stream);

View File

@ -20,7 +20,8 @@ CullTraverserData(const NodePath &start,
const RenderState *state, const RenderState *state,
GeometricBoundingVolume *view_frustum, GeometricBoundingVolume *view_frustum,
Thread *current_thread) : Thread *current_thread) :
_node_path(start), _next(nullptr),
_start(start._head),
_node_reader(start.node(), current_thread), _node_reader(start.node(), current_thread),
_net_transform(net_transform), _net_transform(net_transform),
_state(state), _state(state),
@ -34,44 +35,16 @@ CullTraverserData(const NodePath &start,
_node_reader.check_cached(check_bounds); _node_reader.check_cached(check_bounds);
} }
/**
*
*/
INLINE CullTraverserData::
CullTraverserData(const CullTraverserData &copy) :
_node_path(copy._node_path),
_node_reader(copy._node_reader),
_net_transform(copy._net_transform),
_state(copy._state),
_view_frustum(copy._view_frustum),
_cull_planes(copy._cull_planes),
_draw_mask(copy._draw_mask),
_portal_depth(copy._portal_depth)
{
}
/**
*
*/
INLINE void CullTraverserData::
operator = (const CullTraverserData &copy) {
_node_path = copy._node_path;
_node_reader = copy._node_reader;
_net_transform = copy._net_transform;
_state = copy._state;
_view_frustum = copy._view_frustum;
_cull_planes = copy._cull_planes;
_draw_mask = copy._draw_mask;
_portal_depth = copy._portal_depth;
}
/** /**
* This constructor creates a CullTraverserData object that reflects the next * This constructor creates a CullTraverserData object that reflects the next
* node down in the traversal. * node down in the traversal.
*/ */
INLINE CullTraverserData:: INLINE CullTraverserData::
CullTraverserData(const CullTraverserData &parent, PandaNode *child) : CullTraverserData(const CullTraverserData &parent, PandaNode *child) :
_node_path(parent._node_path, child), _next(&parent),
#ifdef _DEBUG
_start(nullptr),
#endif
_node_reader(child, parent._node_reader.get_current_thread()), _node_reader(child, parent._node_reader.get_current_thread()),
_net_transform(parent._net_transform), _net_transform(parent._net_transform),
_state(parent._state), _state(parent._state),
@ -86,19 +59,12 @@ CullTraverserData(const CullTraverserData &parent, PandaNode *child) :
_node_reader.check_cached(check_bounds); _node_reader.check_cached(check_bounds);
} }
/**
*
*/
INLINE CullTraverserData::
~CullTraverserData() {
}
/** /**
* Returns the node traversed to so far. * Returns the node traversed to so far.
*/ */
INLINE PandaNode *CullTraverserData:: INLINE PandaNode *CullTraverserData::
node() const { node() const {
return _node_path.node(); return (PandaNode *)_node_reader.get_node();
} }
/** /**
@ -117,6 +83,18 @@ node_reader() const {
return &_node_reader; return &_node_reader;
} }
/**
* Constructs and returns an actual NodePath that represents the same path we
* have just traversed.
*/
INLINE NodePath CullTraverserData::
get_node_path() const {
NodePath result;
result._head = r_get_node_path();
nassertr(result._head != nullptr, NodePath::fail());
return result;
}
/** /**
* Returns the modelview transform: the relative transform from the camera to * Returns the modelview transform: the relative transform from the camera to
* the model. * the model.

View File

@ -46,25 +46,33 @@ apply_transform_and_state(CullTraverser *trav) {
} }
_node_reader.compose_draw_mask(_draw_mask); _node_reader.compose_draw_mask(_draw_mask);
apply_transform_and_state(trav, _node_reader.get_transform(), const RenderEffects *node_effects = _node_reader.get_effects();
MOVE(node_state), _node_reader.get_effects(), if (!node_effects->has_cull_callback()) {
_node_reader.get_off_clip_planes()); apply_transform(_node_reader.get_transform());
} else {
// The cull callback may decide to modify the node_transform.
CPT(TransformState) node_transform = _node_reader.get_transform();
node_effects->cull_callback(trav, *this, node_transform, node_state);
apply_transform(node_transform);
}
if (!node_state->is_empty()) {
_state = _state->compose(node_state);
}
if (clip_plane_cull) {
_cull_planes = _cull_planes->apply_state(trav, this,
(const ClipPlaneAttrib *)node_state->get_attrib(ClipPlaneAttrib::get_class_slot()),
(const ClipPlaneAttrib *)_node_reader.get_off_clip_planes(),
(const OccluderEffect *)node_effects->get_effect(OccluderEffect::get_class_type()));
}
} }
/** /**
* Applies the indicated transform and state changes (e.g. as extracted from * Applies the indicated transform changes onto the current data.
* a node) onto the current data. This also evaluates billboards, etc.
*/ */
void CullTraverserData:: void CullTraverserData::
apply_transform_and_state(CullTraverser *trav, apply_transform(const TransformState *node_transform) {
CPT(TransformState) node_transform,
CPT(RenderState) node_state,
CPT(RenderEffects) node_effects,
const RenderAttrib *off_clip_planes) {
if (node_effects->has_cull_callback()) {
node_effects->cull_callback(trav, *this, node_transform, node_state);
}
if (!node_transform->is_identity()) { if (!node_transform->is_identity()) {
_net_transform = _net_transform->compose(node_transform); _net_transform = _net_transform->compose(node_transform);
@ -95,15 +103,40 @@ apply_transform_and_state(CullTraverser *trav,
} }
} }
} }
}
_state = _state->compose(node_state); /**
* The private, recursive implementation of get_node_path(), this returns the
if (clip_plane_cull) { * NodePathComponent representing the NodePath.
_cull_planes = _cull_planes->apply_state(trav, this, */
(const ClipPlaneAttrib *)node_state->get_attrib(ClipPlaneAttrib::get_class_slot()), PT(NodePathComponent) CullTraverserData::
(const ClipPlaneAttrib *)off_clip_planes, r_get_node_path() const {
(const OccluderEffect *)node_effects->get_effect(OccluderEffect::get_class_type())); if (_next == nullptr) {
nassertr(_start != nullptr, nullptr);
return _start;
} }
#ifdef _DEBUG
nassertr(_start == nullptr, nullptr);
#endif
nassertr(node() != nullptr, nullptr);
PT(NodePathComponent) comp = _next->r_get_node_path();
nassertr(comp != nullptr, nullptr);
Thread *current_thread = Thread::get_current_thread();
int pipeline_stage = current_thread->get_pipeline_stage();
PT(NodePathComponent) result =
PandaNode::get_component(comp, node(), pipeline_stage, current_thread);
if (result == nullptr) {
// This means we found a disconnected chain in the CullTraverserData's
// ancestry: the node above this node isn't connected. In this case,
// don't attempt to go higher; just truncate the NodePath at the bottom of
// the disconnect.
return PandaNode::get_top_component(node(), true, pipeline_stage, current_thread);
}
return result;
} }
/** /**
@ -121,7 +154,7 @@ is_in_view_impl() {
if (pgraph_cat.is_spam()) { if (pgraph_cat.is_spam()) {
pgraph_cat.spam() pgraph_cat.spam()
<< _node_path << " cull result = " << hex << result << dec << "\n"; << get_node_path() << " cull result = " << hex << result << dec << "\n";
} }
if (result == BoundingVolume::IF_no_intersection) { if (result == BoundingVolume::IF_no_intersection) {
@ -136,8 +169,7 @@ is_in_view_impl() {
// If we have fake view-frustum culling enabled, instead of actually // If we have fake view-frustum culling enabled, instead of actually
// culling an object we simply force it to be drawn in red wireframe. // culling an object we simply force it to be drawn in red wireframe.
_view_frustum = (GeometricBoundingVolume *)NULL; _view_frustum = (GeometricBoundingVolume *)NULL;
CPT(RenderState) fake_state = get_fake_view_frustum_cull_state(); _state = _state->compose(get_fake_view_frustum_cull_state());
_state = _state->compose(fake_state);
#endif #endif
} else if ((result & BoundingVolume::IF_all) != 0) { } else if ((result & BoundingVolume::IF_all) != 0) {
@ -170,7 +202,7 @@ is_in_view_impl() {
if (pgraph_cat.is_spam()) { if (pgraph_cat.is_spam()) {
pgraph_cat.spam() pgraph_cat.spam()
<< _node_path << " cull planes cull result = " << hex << get_node_path() << " cull planes cull result = " << hex
<< result << dec << "\n"; << result << dec << "\n";
_cull_planes->write(pgraph_cat.spam(false)); _cull_planes->write(pgraph_cat.spam(false));
} }
@ -182,7 +214,7 @@ is_in_view_impl() {
if (pgraph_cat.is_spam()) { if (pgraph_cat.is_spam()) {
pgraph_cat.spam() pgraph_cat.spam()
<< _node_path << " is_final, cull planes disabled, state:\n"; << get_node_path() << " is_final, cull planes disabled, state:\n";
_state->write(pgraph_cat.spam(false), 2); _state->write(pgraph_cat.spam(false), 2);
} }
} }
@ -196,8 +228,7 @@ is_in_view_impl() {
return false; return false;
} }
_cull_planes = CullPlanes::make_empty(); _cull_planes = CullPlanes::make_empty();
CPT(RenderState) fake_state = get_fake_view_frustum_cull_state(); _state = _state->compose(get_fake_view_frustum_cull_state());
_state = _state->compose(fake_state);
#endif #endif
} else if ((result & BoundingVolume::IF_all) != 0) { } else if ((result & BoundingVolume::IF_all) != 0) {
@ -215,15 +246,15 @@ is_in_view_impl() {
* Returns a RenderState for rendering stuff in red wireframe, strictly for * Returns a RenderState for rendering stuff in red wireframe, strictly for
* the fake_view_frustum_cull effect. * the fake_view_frustum_cull effect.
*/ */
CPT(RenderState) CullTraverserData:: const RenderState *CullTraverserData::
get_fake_view_frustum_cull_state() { get_fake_view_frustum_cull_state() {
#ifdef NDEBUG #ifdef NDEBUG
return NULL; return nullptr;
#else #else
// Once someone asks for this pointer, we hold its reference count and never // Once someone asks for this pointer, we hold its reference count and never
// free it. // free it.
static CPT(RenderState) state = (const RenderState *)NULL; static CPT(RenderState) state;
if (state == (const RenderState *)NULL) { if (state == nullptr) {
state = RenderState::make state = RenderState::make
(ColorAttrib::make_flat(LColor(1.0f, 0.0f, 0.0f, 1.0f)), (ColorAttrib::make_flat(LColor(1.0f, 0.0f, 0.0f, 1.0f)),
TextureAttrib::make_all_off(), TextureAttrib::make_all_off(),

View File

@ -44,11 +44,8 @@ public:
const RenderState *state, const RenderState *state,
GeometricBoundingVolume *view_frustum, GeometricBoundingVolume *view_frustum,
Thread *current_thread); Thread *current_thread);
INLINE CullTraverserData(const CullTraverserData &copy);
INLINE void operator = (const CullTraverserData &copy);
INLINE CullTraverserData(const CullTraverserData &parent, INLINE CullTraverserData(const CullTraverserData &parent,
PandaNode *child); PandaNode *child);
INLINE ~CullTraverserData();
PUBLISHED: PUBLISHED:
INLINE PandaNode *node() const; INLINE PandaNode *node() const;
@ -57,6 +54,8 @@ public:
INLINE PandaNodePipelineReader *node_reader(); INLINE PandaNodePipelineReader *node_reader();
INLINE const PandaNodePipelineReader *node_reader() const; INLINE const PandaNodePipelineReader *node_reader() const;
INLINE NodePath get_node_path() const;
PUBLISHED: PUBLISHED:
INLINE CPT(TransformState) get_modelview_transform(const CullTraverser *trav) const; INLINE CPT(TransformState) get_modelview_transform(const CullTraverser *trav) const;
INLINE CPT(TransformState) get_internal_transform(const CullTraverser *trav) const; INLINE CPT(TransformState) get_internal_transform(const CullTraverser *trav) const;
@ -66,14 +65,15 @@ PUBLISHED:
INLINE bool is_this_node_hidden(const DrawMask &camera_mask) const; INLINE bool is_this_node_hidden(const DrawMask &camera_mask) const;
void apply_transform_and_state(CullTraverser *trav); void apply_transform_and_state(CullTraverser *trav);
void apply_transform_and_state(CullTraverser *trav, void apply_transform(const TransformState *node_transform);
CPT(TransformState) node_transform,
CPT(RenderState) node_state, private:
CPT(RenderEffects) node_effects, // We store a chain leading all the way to the root, so that we can compose
const RenderAttrib *off_clip_planes); // a NodePath. We may be able to eliminate this requirement in the future.
const CullTraverserData *_next;
NodePathComponent *_start;
public: public:
WorkingNodePath _node_path;
PandaNodePipelineReader _node_reader; PandaNodePipelineReader _node_reader;
CPT(TransformState) _net_transform; CPT(TransformState) _net_transform;
CPT(RenderState) _state; CPT(RenderState) _state;
@ -83,8 +83,10 @@ public:
int _portal_depth; int _portal_depth;
private: private:
PT(NodePathComponent) r_get_node_path() const;
bool is_in_view_impl(); bool is_in_view_impl();
static CPT(RenderState) get_fake_view_frustum_cull_state(); static const RenderState *get_fake_view_frustum_cull_state();
}; };
/* okcircular */ /* okcircular */

View File

@ -151,7 +151,7 @@ transform_vertices(GeomNode *node, const LMatrix4 &mat) {
GeomNode::GeomEntry &entry = (*gi); GeomNode::GeomEntry &entry = (*gi);
PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy(); PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
if (transform_vertices(new_geom, mat)) { if (transform_vertices(new_geom, mat)) {
entry._geom = new_geom; entry._geom = move(new_geom);
any_changed = true; any_changed = true;
} }
} }
@ -1439,13 +1439,8 @@ remove_unused_vertices(const GeomVertexData *vdata) {
any_referenced = true; any_referenced = true;
int num_primitives = geom->get_num_primitives(); int num_primitives = geom->get_num_primitives();
for (int i = 0; i < num_primitives; ++i) { for (int i = 0; i < num_primitives; ++i) {
CPT(GeomPrimitive) prim = geom->get_primitive(i); GeomPrimitivePipelineReader reader(geom->get_primitive(i), current_thread);
reader.get_referenced_vertices(referenced_vertices);
GeomPrimitivePipelineReader reader(prim, current_thread);
int num_vertices = reader.get_num_vertices();
for (int vi = 0; vi < num_vertices; ++vi) {
referenced_vertices.set_bit(reader.get_vertex(vi));
}
} }
} }

View File

@ -1080,7 +1080,7 @@ get_sa() const {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_float &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_float &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1088,7 +1088,7 @@ set_shader_input(CPT_InternalName id, const PTA_float &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_double &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_double &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1096,7 +1096,7 @@ set_shader_input(CPT_InternalName id, const PTA_double &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_int &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_int &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1104,7 +1104,7 @@ set_shader_input(CPT_InternalName id, const PTA_int &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LVecBase4 &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LVecBase4 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1112,7 +1112,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase4 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LVecBase3 &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LVecBase3 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
@ -1121,7 +1121,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase3 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LVecBase2 &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LVecBase2 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1129,7 +1129,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase2 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LVecBase4 &v, int priority) { set_shader_input(CPT_InternalName id, const LVecBase4 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1137,7 +1137,7 @@ set_shader_input(CPT_InternalName id, const LVecBase4 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LVecBase3 &v, int priority) { set_shader_input(CPT_InternalName id, const LVecBase3 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1145,7 +1145,7 @@ set_shader_input(CPT_InternalName id, const LVecBase3 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LVecBase2 &v, int priority) { set_shader_input(CPT_InternalName id, const LVecBase2 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1153,7 +1153,7 @@ set_shader_input(CPT_InternalName id, const LVecBase2 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LVecBase4i &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LVecBase4i &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1161,7 +1161,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase4i &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LVecBase3i &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LVecBase3i &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
@ -1170,7 +1170,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase3i &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LVecBase2i &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LVecBase2i &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1178,7 +1178,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase2i &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LVecBase4i &v, int priority) { set_shader_input(CPT_InternalName id, const LVecBase4i &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1186,7 +1186,7 @@ set_shader_input(CPT_InternalName id, const LVecBase4i &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LVecBase3i &v, int priority) { set_shader_input(CPT_InternalName id, const LVecBase3i &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1194,7 +1194,7 @@ set_shader_input(CPT_InternalName id, const LVecBase3i &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LVecBase2i &v, int priority) { set_shader_input(CPT_InternalName id, const LVecBase2i &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1202,7 +1202,7 @@ set_shader_input(CPT_InternalName id, const LVecBase2i &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LMatrix4 &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LMatrix4 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1210,7 +1210,7 @@ set_shader_input(CPT_InternalName id, const PTA_LMatrix4 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const PTA_LMatrix3 &v, int priority) { set_shader_input(CPT_InternalName id, const PTA_LMatrix3 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1218,7 +1218,7 @@ set_shader_input(CPT_InternalName id, const PTA_LMatrix3 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LMatrix4 &v, int priority) { set_shader_input(CPT_InternalName id, const LMatrix4 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1226,7 +1226,7 @@ set_shader_input(CPT_InternalName id, const LMatrix4 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority) { set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority) {
set_shader_input(new ShaderInput(id, v, priority)); set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -1234,7 +1234,7 @@ set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, Texture *tex, int priority) { set_shader_input(CPT_InternalName id, Texture *tex, int priority) {
set_shader_input(new ShaderInput(id, tex, priority)); set_shader_input(ShaderInput(move(id), tex, priority));
} }
/** /**
@ -1242,7 +1242,7 @@ set_shader_input(CPT_InternalName id, Texture *tex, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler, int priority) { set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler, int priority) {
set_shader_input(new ShaderInput(id, tex, sampler, priority)); set_shader_input(ShaderInput(move(id), tex, sampler, priority));
} }
/** /**
@ -1250,7 +1250,7 @@ set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler,
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z, int n, int priority) { set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z, int n, int priority) {
set_shader_input(new ShaderInput(id, tex, read, write, z, n, priority)); set_shader_input(ShaderInput(move(id), tex, read, write, z, n, priority));
} }
/** /**
@ -1258,7 +1258,7 @@ set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, ShaderBuffer *buf, int priority) { set_shader_input(CPT_InternalName id, ShaderBuffer *buf, int priority) {
set_shader_input(new ShaderInput(id, buf, priority)); set_shader_input(ShaderInput(move(id), buf, priority));
} }
/** /**
@ -1266,7 +1266,7 @@ set_shader_input(CPT_InternalName id, ShaderBuffer *buf, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, const NodePath &np, int priority) { set_shader_input(CPT_InternalName id, const NodePath &np, int priority) {
set_shader_input(new ShaderInput(id, np, priority)); set_shader_input(ShaderInput(move(id), np, priority));
} }
/** /**
@ -1274,7 +1274,7 @@ set_shader_input(CPT_InternalName id, const NodePath &np, int priority) {
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, int n1, int n2, int n3, int n4, int priority) { set_shader_input(CPT_InternalName id, int n1, int n2, int n3, int n4, int priority) {
set_shader_input(new ShaderInput(id, LVecBase4i(n1, n2, n3, n4), priority)); set_shader_input(ShaderInput(move(id), LVecBase4i(n1, n2, n3, n4), priority));
} }
/** /**
@ -1282,7 +1282,7 @@ set_shader_input(CPT_InternalName id, int n1, int n2, int n3, int n4, int priori
*/ */
INLINE void NodePath:: INLINE void NodePath::
set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) { set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) {
set_shader_input(new ShaderInput(id, LVecBase4(n1, n2, n3, n4), priority)); set_shader_input(ShaderInput(move(id), LVecBase4(n1, n2, n3, n4), priority));
} }
/** /**

View File

@ -697,8 +697,10 @@ get_state(const NodePath &other, Thread *current_thread) const {
return other.get_net_state(current_thread)->invert_compose(RenderState::make_empty()); return other.get_net_state(current_thread)->invert_compose(RenderState::make_empty());
} }
#if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
nassertr(verify_complete(current_thread), RenderState::make_empty()); nassertr(verify_complete(current_thread), RenderState::make_empty());
nassertr(other.verify_complete(current_thread), RenderState::make_empty()); nassertr(other.verify_complete(current_thread), RenderState::make_empty());
#endif
int a_count, b_count; int a_count, b_count;
if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) { if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) {
@ -767,8 +769,10 @@ get_transform(const NodePath &other, Thread *current_thread) const {
return other.get_net_transform(current_thread)->invert_compose(TransformState::make_identity()); return other.get_net_transform(current_thread)->invert_compose(TransformState::make_identity());
} }
#if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
nassertr(verify_complete(current_thread), TransformState::make_identity()); nassertr(verify_complete(current_thread), TransformState::make_identity());
nassertr(other.verify_complete(current_thread), TransformState::make_identity()); nassertr(other.verify_complete(current_thread), TransformState::make_identity());
#endif
int a_count, b_count; int a_count, b_count;
if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) { if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) {
@ -852,8 +856,10 @@ get_prev_transform(const NodePath &other, Thread *current_thread) const {
return other.get_net_prev_transform(current_thread)->invert_compose(TransformState::make_identity()); return other.get_net_prev_transform(current_thread)->invert_compose(TransformState::make_identity());
} }
#if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
nassertr(verify_complete(current_thread), TransformState::make_identity()); nassertr(verify_complete(current_thread), TransformState::make_identity());
nassertr(other.verify_complete(current_thread), TransformState::make_identity()); nassertr(other.verify_complete(current_thread), TransformState::make_identity());
#endif
int a_count, b_count; int a_count, b_count;
if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) { if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) {
@ -3255,35 +3261,36 @@ get_shader() const {
* *
*/ */
void NodePath:: void NodePath::
set_shader_input(const ShaderInput *inp) { set_shader_input(ShaderInput inp) {
nassertv_always(!is_empty()); nassertv_always(!is_empty());
PandaNode *pnode = node();
const RenderAttrib *attrib = const RenderAttrib *attrib =
node()->get_attrib(ShaderAttrib::get_class_slot()); pnode->get_attrib(ShaderAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) { if (attrib != nullptr) {
const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib); const ShaderAttrib *sa = (const ShaderAttrib *)attrib;
node()->set_attrib(sa->set_shader_input(inp)); pnode->set_attrib(sa->set_shader_input(inp));
} else { } else {
// Create a new ShaderAttrib for this node. // Create a new ShaderAttrib for this node.
CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make()); CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make());
node()->set_attrib(sa->set_shader_input(inp)); pnode->set_attrib(sa->set_shader_input(inp));
} }
} }
/** /**
* *
*/ */
const ShaderInput *NodePath:: ShaderInput NodePath::
get_shader_input(CPT_InternalName id) const { get_shader_input(CPT_InternalName id) const {
nassertr_always(!is_empty(), NULL); nassertr_always(!is_empty(), ShaderInput::get_blank());
const RenderAttrib *attrib = const RenderAttrib *attrib =
node()->get_attrib(ShaderAttrib::get_class_slot()); node()->get_attrib(ShaderAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) { if (attrib != nullptr) {
const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib); const ShaderAttrib *sa = (const ShaderAttrib *)attrib;
return sa->get_shader_input(id); return sa->get_shader_input(id);
} }
return NULL; return ShaderInput::get_blank();
} }
/** /**
@ -5786,17 +5793,22 @@ r_get_net_transform(NodePathComponent *comp, Thread *current_thread) const {
if (comp == (NodePathComponent *)NULL) { if (comp == (NodePathComponent *)NULL) {
return TransformState::make_identity(); return TransformState::make_identity();
} else { } else {
PandaNode *node = comp->get_node();
int pipeline_stage = current_thread->get_pipeline_stage(); int pipeline_stage = current_thread->get_pipeline_stage();
CPT(TransformState) net_transform = r_get_net_transform(comp->get_next(pipeline_stage, current_thread), current_thread); CPT(TransformState) net_transform = r_get_net_transform(comp->get_next(pipeline_stage, current_thread), current_thread);
PandaNode *node = comp->get_node();
CPT(TransformState) transform = node->get_transform(current_thread);
CPT(RenderEffects) effects = node->get_effects(current_thread); PandaNode::CDReader node_cdata(node->_cycler, current_thread);
if (effects->has_adjust_transform()) { if (!node_cdata->_effects->has_adjust_transform()) {
effects->adjust_transform(net_transform, transform, node); if (node_cdata->_transform->is_identity()) {
return net_transform;
} else {
return net_transform->compose(node_cdata->_transform);
}
} else {
CPT(TransformState) transform = node_cdata->_transform.p();
node_cdata->_effects->adjust_transform(net_transform, transform, node);
return net_transform->compose(transform);
} }
return net_transform->compose(transform);
} }
} }
@ -5814,16 +5826,21 @@ r_get_partial_transform(NodePathComponent *comp, int n,
if (n == 0 || comp == (NodePathComponent *)NULL) { if (n == 0 || comp == (NodePathComponent *)NULL) {
return TransformState::make_identity(); return TransformState::make_identity();
} else { } else {
if (comp->get_node()->get_effects(current_thread)->has_adjust_transform()) { PandaNode *node = comp->get_node();
PandaNode::CDReader node_cdata(node->_cycler, current_thread);
if (node_cdata->_effects->has_adjust_transform()) {
return NULL; return NULL;
} }
CPT(TransformState) transform = comp->get_node()->get_transform(current_thread);
int pipeline_stage = current_thread->get_pipeline_stage(); int pipeline_stage = current_thread->get_pipeline_stage();
CPT(TransformState) partial = r_get_partial_transform(comp->get_next(pipeline_stage, current_thread), n - 1, current_thread); CPT(TransformState) partial = r_get_partial_transform(comp->get_next(pipeline_stage, current_thread), n - 1, current_thread);
if (partial == (const TransformState *)NULL) { if (partial == (const TransformState *)NULL) {
return NULL; return NULL;
} }
return partial->compose(transform); if (node_cdata->_transform->is_identity()) {
return partial;
} else {
return partial->compose(node_cdata->_transform);
}
} }
} }

View File

@ -629,7 +629,7 @@ PUBLISHED:
void set_shader_auto(BitMask32 shader_switch, int priority=0); void set_shader_auto(BitMask32 shader_switch, int priority=0);
void clear_shader(); void clear_shader();
void set_shader_input(const ShaderInput *inp); void set_shader_input(ShaderInput input);
INLINE void set_shader_input(CPT_InternalName id, Texture *tex, int priority=0); INLINE void set_shader_input(CPT_InternalName id, Texture *tex, int priority=0);
INLINE void set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler, int priority=0); INLINE void set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler, int priority=0);
INLINE void set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); INLINE void set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0);
@ -665,7 +665,7 @@ PUBLISHED:
void set_instance_count(int instance_count); void set_instance_count(int instance_count);
const Shader *get_shader() const; const Shader *get_shader() const;
const ShaderInput *get_shader_input(CPT_InternalName id) const; ShaderInput get_shader_input(CPT_InternalName id) const;
int get_instance_count() const; int get_instance_count() const;
void set_tex_transform(TextureStage *stage, const TransformState *transform); void set_tex_transform(TextureStage *stage, const TransformState *transform);
@ -1029,6 +1029,7 @@ private:
friend class NodePathCollection; friend class NodePathCollection;
friend class WorkingNodePath; friend class WorkingNodePath;
friend class WeakNodePath; friend class WeakNodePath;
friend class CullTraverserData;
}; };
INLINE ostream &operator << (ostream &out, const NodePath &node_path); INLINE ostream &operator << (ostream &out, const NodePath &node_path);

View File

@ -75,6 +75,15 @@ has_key() const {
return (_key != 0); return (_key != 0);
} }
/**
* Returns the next component in the path.
*/
INLINE NodePathComponent *NodePathComponent::
get_next(int pipeline_stage, Thread *current_thread) const {
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
return cdata->_next;
}
INLINE ostream &operator << (ostream &out, const NodePathComponent &comp) { INLINE ostream &operator << (ostream &out, const NodePathComponent &comp) {
comp.output(out); comp.output(out);
return out; return out;

View File

@ -92,17 +92,6 @@ get_length(int pipeline_stage, Thread *current_thread) const {
return cdata->_length; return cdata->_length;
} }
/**
* Returns the next component in the path.
*/
NodePathComponent *NodePathComponent::
get_next(int pipeline_stage, Thread *current_thread) const {
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
NodePathComponent *next = cdata->_next;
return next;
}
/** /**
* Checks that the length indicated by the component is one more than the * Checks that the length indicated by the component is one more than the
* length of its predecessor. If this is broken, fixes it and returns true * length of its predecessor. If this is broken, fixes it and returns true

View File

@ -39,7 +39,7 @@
* graph, and the NodePathComponents are stored in the nodes themselves to * graph, and the NodePathComponents are stored in the nodes themselves to
* allow the nodes to keep these up to date as the scene graph is manipulated. * allow the nodes to keep these up to date as the scene graph is manipulated.
*/ */
class EXPCL_PANDA_PGRAPH NodePathComponent : public ReferenceCount { class EXPCL_PANDA_PGRAPH NodePathComponent FINAL : public ReferenceCount {
private: private:
NodePathComponent(PandaNode *node, NodePathComponent *next, NodePathComponent(PandaNode *node, NodePathComponent *next,
int pipeline_stage, Thread *current_thread); int pipeline_stage, Thread *current_thread);
@ -55,7 +55,7 @@ public:
int get_key() const; int get_key() const;
bool is_top_node(int pipeline_stage, Thread *current_thread) const; bool is_top_node(int pipeline_stage, Thread *current_thread) const;
NodePathComponent *get_next(int pipeline_stage, Thread *current_thread) const; INLINE NodePathComponent *get_next(int pipeline_stage, Thread *current_thread) const;
int get_length(int pipeline_stage, Thread *current_thread) const; int get_length(int pipeline_stage, Thread *current_thread) const;
bool fix_length(int pipeline_stage, Thread *current_thread); bool fix_length(int pipeline_stage, Thread *current_thread);
@ -125,6 +125,12 @@ private:
friend class NodePath; friend class NodePath;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<NodePathComponent>::update_type(To *ptr) {}
#endif
INLINE ostream &operator << (ostream &out, const NodePathComponent &comp); INLINE ostream &operator << (ostream &out, const NodePathComponent &comp);
#include "nodePathComponent.I" #include "nodePathComponent.I"

View File

@ -278,7 +278,7 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
} }
CPT_InternalName name(string(buffer, length)); CPT_InternalName name(string(buffer, length));
ShaderInput *input = nullptr; ShaderInput input(nullptr, 0);
if (PyTuple_CheckExact(value)) { if (PyTuple_CheckExact(value)) {
// A tuple is interpreted as a vector. // A tuple is interpreted as a vector.
@ -300,13 +300,13 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
for (Py_ssize_t i = 0; i < size; ++i) { for (Py_ssize_t i = 0; i < size; ++i) {
vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i)); vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i));
} }
input = new ShaderInput(name, vec); input = ShaderInput(move(name), vec);
} else { } else {
LVecBase4i vec(0); LVecBase4i vec(0);
for (Py_ssize_t i = 0; i < size; ++i) { for (Py_ssize_t i = 0; i < size; ++i) {
vec[i] = (int)PyLong_AsLong(PyTuple_GET_ITEM(value, i)); vec[i] = (int)PyLong_AsLong(PyTuple_GET_ITEM(value, i));
} }
input = new ShaderInput(name, vec); input = ShaderInput(move(name), vec);
} }
} else if (DtoolCanThisBeAPandaInstance(value)) { } else if (DtoolCanThisBeAPandaInstance(value)) {
@ -314,91 +314,91 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
void *ptr; void *ptr;
if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) { if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) {
input = new ShaderInput(name, (Texture *)ptr); input = ShaderInput(move(name), (Texture *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) {
input = new ShaderInput(name, *(const NodePath *)ptr); input = ShaderInput(move(name), *(const NodePath *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) {
input = new ShaderInput(name, *(const PTA_float *)ptr); input = ShaderInput(move(name), *(const PTA_float *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) {
input = new ShaderInput(name, *(const PTA_double *)ptr); input = ShaderInput(move(name), *(const PTA_double *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) {
input = new ShaderInput(name, *(const PTA_int *)ptr); input = ShaderInput(move(name), *(const PTA_int *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) {
input = new ShaderInput(name, *(const PTA_LVecBase4f *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase4f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) {
input = new ShaderInput(name, *(const PTA_LVecBase3f *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase3f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) {
input = new ShaderInput(name, *(const PTA_LVecBase2f *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase2f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) {
input = new ShaderInput(name, *(const PTA_LMatrix4f *)ptr); input = ShaderInput(move(name), *(const PTA_LMatrix4f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) {
input = new ShaderInput(name, *(const PTA_LMatrix3f *)ptr); input = ShaderInput(move(name), *(const PTA_LMatrix3f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) {
input = new ShaderInput(name, *(const PTA_LVecBase4d *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase4d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) {
input = new ShaderInput(name, *(const PTA_LVecBase3d *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase3d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) {
input = new ShaderInput(name, *(const PTA_LVecBase2d *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase2d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) {
input = new ShaderInput(name, *(const PTA_LMatrix4d *)ptr); input = ShaderInput(move(name), *(const PTA_LMatrix4d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) {
input = new ShaderInput(name, *(const PTA_LMatrix3d *)ptr); input = ShaderInput(move(name), *(const PTA_LMatrix3d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) {
input = new ShaderInput(name, *(const PTA_LVecBase4i *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase4i *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) {
input = new ShaderInput(name, *(const PTA_LVecBase3i *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase3i *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) {
input = new ShaderInput(name, *(const PTA_LVecBase2i *)ptr); input = ShaderInput(move(name), *(const PTA_LVecBase2i *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) {
input = new ShaderInput(name, *(const LVecBase4f *)ptr); input = ShaderInput(move(name), *(const LVecBase4f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) {
input = new ShaderInput(name, *(const LVecBase3f *)ptr); input = ShaderInput(move(name), *(const LVecBase3f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) {
input = new ShaderInput(name, *(const LVecBase2f *)ptr); input = ShaderInput(move(name), *(const LVecBase2f *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) {
input = new ShaderInput(name, *(const LVecBase4d *)ptr); input = ShaderInput(move(name), *(const LVecBase4d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) {
input = new ShaderInput(name, *(const LVecBase3d *)ptr); input = ShaderInput(move(name), *(const LVecBase3d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) {
input = new ShaderInput(name, *(const LVecBase2d *)ptr); input = ShaderInput(move(name), *(const LVecBase2d *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) {
input = new ShaderInput(name, *(const LVecBase4i *)ptr); input = ShaderInput(move(name), *(const LVecBase4i *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) {
input = new ShaderInput(name, *(const LVecBase3i *)ptr); input = ShaderInput(move(name), *(const LVecBase3i *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) {
input = new ShaderInput(name, *(const LVecBase2i *)ptr); input = ShaderInput(move(name), *(const LVecBase2i *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) {
input = new ShaderInput(name, (ShaderBuffer *)ptr); input = ShaderInput(move(name), (ShaderBuffer *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) { } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) {
input = new ShaderInput(name, (ParamValueBase *)ptr); input = ShaderInput(move(name), (ParamValueBase *)ptr);
} else { } else {
Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs"); Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
@ -406,22 +406,22 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
} }
} else if (PyFloat_Check(value)) { } else if (PyFloat_Check(value)) {
input = new ShaderInput(name, LVecBase4(PyFloat_AS_DOUBLE(value), 0, 0, 0)); input = ShaderInput(move(name), LVecBase4(PyFloat_AS_DOUBLE(value), 0, 0, 0));
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
} else if (PyInt_Check(value)) { } else if (PyInt_Check(value)) {
input = new ShaderInput(name, LVecBase4i((int)PyInt_AS_LONG(value), 0, 0, 0)); input = ShaderInput(move(name), LVecBase4i((int)PyInt_AS_LONG(value), 0, 0, 0));
#endif #endif
} else if (PyLong_Check(value)) { } else if (PyLong_Check(value)) {
input = new ShaderInput(name, LVecBase4i((int)PyLong_AsLong(value), 0, 0, 0)); input = ShaderInput(move(name), LVecBase4i((int)PyLong_AsLong(value), 0, 0, 0));
} else { } else {
Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs"); Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
return; return;
} }
attrib->_inputs[move(name)] = input; attrib->_inputs[input.get_name()] = move(input);
} }
node->set_attrib(ShaderAttrib::return_new(attrib)); node->set_attrib(ShaderAttrib::return_new(attrib));

View File

@ -1482,7 +1482,7 @@ get_net_collide_mask() const {
* Returns a ClipPlaneAttrib which represents the union of all of the clip * Returns a ClipPlaneAttrib which represents the union of all of the clip
* planes that have been turned *off* at this level and below. * planes that have been turned *off* at this level and below.
*/ */
INLINE CPT(RenderAttrib) PandaNodePipelineReader:: INLINE const RenderAttrib *PandaNodePipelineReader::
get_off_clip_planes() const { get_off_clip_planes() const {
nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_off_clip_planes); nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_off_clip_planes);
return _cdata->_off_clip_planes; return _cdata->_off_clip_planes;
@ -1493,7 +1493,7 @@ get_off_clip_planes() const {
* contains the user bounding volume, the internal bounding volume, and all of * contains the user bounding volume, the internal bounding volume, and all of
* the children's bounding volumes. * the children's bounding volumes.
*/ */
INLINE CPT(BoundingVolume) PandaNodePipelineReader:: INLINE const BoundingVolume *PandaNodePipelineReader::
get_bounds() const { get_bounds() const {
nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds); nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
return _cdata->_external_bounds; return _cdata->_external_bounds;

View File

@ -827,6 +827,7 @@ private:
friend class PandaNodePipelineReader; friend class PandaNodePipelineReader;
friend class EggLoader; friend class EggLoader;
friend class Extension<PandaNode>; friend class Extension<PandaNode>;
friend class CullTraverserData;
}; };
/** /**
@ -877,8 +878,8 @@ public:
INLINE bool has_tag(const string &key) const; INLINE bool has_tag(const string &key) const;
INLINE CollideMask get_net_collide_mask() const; INLINE CollideMask get_net_collide_mask() const;
INLINE CPT(RenderAttrib) get_off_clip_planes() const; INLINE const RenderAttrib *get_off_clip_planes() const;
INLINE CPT(BoundingVolume) get_bounds() const; INLINE const BoundingVolume *get_bounds() const;
INLINE int get_nested_vertices() const; INLINE int get_nested_vertices() const;
INLINE bool is_final() const; INLINE bool is_final() const;
INLINE int get_fancy_bits() const; INLINE int get_fancy_bits() const;
@ -906,6 +907,12 @@ private:
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<PandaNode>::update_type(To *ptr) {}
#endif
INLINE ostream &operator << (ostream &out, const PandaNode &node) { INLINE ostream &operator << (ostream &out, const PandaNode &node) {
node.output(out); node.output(out);
return out; return out;

View File

@ -136,9 +136,9 @@ do_poly_light(const SceneSetup *scene, const CullTraverserData *data, const Tran
if (light->is_enabled()) { // if enabled get all the properties if (light->is_enabled()) { // if enabled get all the properties
PN_stdfloat light_radius = light->get_radius(); PN_stdfloat light_radius = light->get_radius();
// Calculate the distance of the node from the light dist = // Calculate the distance of the node from the light dist =
// light_iter->second->get_distance(data->_node_path.get_node_path()); // light_iter->second->get_distance(data->get_node_path());
const NodePath lightnp = *light_iter; const NodePath lightnp = *light_iter;
LPoint3 relative_point = data->_node_path.get_node_path().get_relative_point(lightnp, light->get_pos()); LPoint3 relative_point = data->get_node_path().get_relative_point(lightnp, light->get_pos());
if (_effect_center[2]) { if (_effect_center[2]) {
dist = (relative_point - _effect_center).length(); // this counts height difference dist = (relative_point - _effect_center).length(); // this counts height difference
@ -155,7 +155,7 @@ do_poly_light(const SceneSetup *scene, const CullTraverserData *data, const Tran
// LPoint3 camera_position = camera.get_relative_point(lightnp, // LPoint3 camera_position = camera.get_relative_point(lightnp,
// light->get_pos()); // light->get_pos());
LPoint3 camera_position = lightnp.get_relative_point(camera, LPoint3(0,0,0)); LPoint3 camera_position = lightnp.get_relative_point(camera, LPoint3(0,0,0));
LPoint3 avatar_position = lightnp.get_relative_point(data->_node_path.get_node_path(), LPoint3(0,0,0)); LPoint3 avatar_position = lightnp.get_relative_point(data->get_node_path(), LPoint3(0,0,0));
LVector3 light_camera = camera_position - light_position; LVector3 light_camera = camera_position - light_position;
LVector3 light_avatar = avatar_position - light_position; LVector3 light_avatar = avatar_position - light_position;
light_camera.normalize(); light_camera.normalize();
@ -263,7 +263,7 @@ do_poly_light(const SceneSetup *scene, const CullTraverserData *data, const Tran
if (num_lights) { if (num_lights) {
// was_under_polylight = true; // was_under_polylight = true;
// data->_node_path.get_node_path().set_color_scale_off(); // data->get_node_path().set_color_scale_off();
if (polylight_info) if (polylight_info)
pgraph_cat.debug() << "num lights = " << num_lights << endl; pgraph_cat.debug() << "num lights = " << num_lights << endl;
@ -320,8 +320,8 @@ do_poly_light(const SceneSetup *scene, const CullTraverserData *data, const Tran
else { else {
if (was_under_polylight) { if (was_under_polylight) {
// under no polylight influence...so clear the color scale // under no polylight influence...so clear the color scale
// data->_node_path.get_node_path().clear_color_scale(); // data->get_node_path().clear_color_scale();
// data->_node_path.get_node_path().set_color_scale(scene_color); // data->get_node_path().set_color_scale(scene_color);
was_under_polylight = false; was_under_polylight = false;
} }
} }

View File

@ -119,7 +119,7 @@ private:
LPoint2 _reduced_viewport_max; LPoint2 _reduced_viewport_max;
CPT(RenderState) _clip_state; // each portal node needs to know the clip state of its "parent" portal Node CPT(RenderState) _clip_state; // each portal node needs to know the clip state of its "parent" portal Node
PortalNode *_portal_node; // current working portal for dereference ease const PortalNode *_portal_node; // current working portal for dereference ease
// int _num_vert; LVertex _coords[4]; // int _num_vert; LVertex _coords[4];

View File

@ -213,7 +213,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
portal_viewer->get_reduced_viewport(old_reduced_viewport_min, old_reduced_viewport_max); portal_viewer->get_reduced_viewport(old_reduced_viewport_min, old_reduced_viewport_max);
PT(BoundingHexahedron) old_bh = portal_viewer->get_reduced_frustum(); PT(BoundingHexahedron) old_bh = portal_viewer->get_reduced_frustum();
if (portal_viewer->prepare_portal(data._node_path.get_node_path())) { if (portal_viewer->prepare_portal(data.get_node_path())) {
if ((reduced_frustum = portal_viewer->get_reduced_frustum())) { if ((reduced_frustum = portal_viewer->get_reduced_frustum())) {
// remember current clip state, we might change it // remember current clip state, we might change it
CPT(RenderState) old_clip_state = portal_viewer->get_clip_state(); CPT(RenderState) old_clip_state = portal_viewer->get_clip_state();
@ -241,7 +241,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
// camera space to this portal node's space (because the clip planes // camera space to this portal node's space (because the clip planes
// are attached to this node) // are attached to this node)
PT(BoundingHexahedron) temp_bh = DCAST(BoundingHexahedron, vf->make_copy()); PT(BoundingHexahedron) temp_bh = DCAST(BoundingHexahedron, vf->make_copy());
CPT(TransformState) temp_frustum_transform = data._node_path.get_node_path().get_net_transform()->invert_compose(portal_viewer->_scene_setup->get_cull_center().get_net_transform()); CPT(TransformState) temp_frustum_transform = data.get_node_path().get_net_transform()->invert_compose(portal_viewer->_scene_setup->get_cull_center().get_net_transform());
portal_cat.spam() << "clipping plane frustum transform " << *temp_frustum_transform << endl; portal_cat.spam() << "clipping plane frustum transform " << *temp_frustum_transform << endl;
portal_cat.spam() << "frustum before transform " << *temp_bh << endl; portal_cat.spam() << "frustum before transform " << *temp_bh << endl;

View File

@ -22,7 +22,7 @@ LightReMutex *RenderAttrib::_attribs_lock = NULL;
RenderAttrib::Attribs *RenderAttrib::_attribs = NULL; RenderAttrib::Attribs *RenderAttrib::_attribs = NULL;
TypeHandle RenderAttrib::_type_handle; TypeHandle RenderAttrib::_type_handle;
int RenderAttrib::_garbage_index = 0; size_t RenderAttrib::_garbage_index = 0;
PStatCollector RenderAttrib::_garbage_collect_pcollector("*:State Cache:Garbage Collect"); PStatCollector RenderAttrib::_garbage_collect_pcollector("*:State Cache:Garbage Collect");
@ -195,8 +195,8 @@ list_attribs(ostream &out) {
LightReMutexHolder holder(*_attribs_lock); LightReMutexHolder holder(*_attribs_lock);
out << _attribs->get_num_entries() << " attribs:\n"; out << _attribs->get_num_entries() << " attribs:\n";
int size = _attribs->get_size(); size_t size = _attribs->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_attribs->has_element(si)) { if (!_attribs->has_element(si)) {
continue; continue;
} }
@ -219,7 +219,9 @@ garbage_collect() {
PStatTimer timer(_garbage_collect_pcollector); PStatTimer timer(_garbage_collect_pcollector);
int orig_size = _attribs->get_num_entries(); int orig_size = _attribs->get_num_entries();
#ifdef _DEBUG
nassertr(_attribs->validate(), 0); nassertr(_attribs->validate(), 0);
#endif
// How many elements to process this pass? // How many elements to process this pass?
int size = _attribs->get_size(); int size = _attribs->get_size();
@ -230,11 +232,9 @@ garbage_collect() {
num_this_pass = min(num_this_pass, size); num_this_pass = min(num_this_pass, size);
int stop_at_element = (_garbage_index + num_this_pass) % size; int stop_at_element = (_garbage_index + num_this_pass) % size;
int num_elements = 0; size_t si = _garbage_index;
int si = _garbage_index;
do { do {
if (_attribs->has_element(si)) { if (_attribs->has_element(si)) {
++num_elements;
RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si); RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
if (attrib->get_ref_count() == 1) { if (attrib->get_ref_count() == 1) {
// This attrib has recently been unreffed to 1 (the one we added when // This attrib has recently been unreffed to 1 (the one we added when
@ -250,9 +250,12 @@ garbage_collect() {
si = (si + 1) % size; si = (si + 1) % size;
} while (si != stop_at_element); } while (si != stop_at_element);
_garbage_index = si; _garbage_index = si;
nassertr(_attribs->validate(), 0);
int new_size = _attribs->get_num_entries(); #ifdef _DEBUG
nassertr(_attribs->validate(), 0);
#endif
size_t new_size = _attribs->get_num_entries();
return orig_size - new_size; return orig_size - new_size;
} }
@ -272,8 +275,8 @@ validate_attribs() {
pgraph_cat.error() pgraph_cat.error()
<< "RenderAttrib::_attribs cache is invalid!\n"; << "RenderAttrib::_attribs cache is invalid!\n";
int size = _attribs->get_size(); size_t size = _attribs->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_attribs->has_element(si)) { if (!_attribs->has_element(si)) {
continue; continue;
} }
@ -285,14 +288,14 @@ validate_attribs() {
return false; return false;
} }
int size = _attribs->get_size(); size_t size = _attribs->get_size();
int si = 0; size_t si = 0;
while (si < size && !_attribs->has_element(si)) { while (si < size && !_attribs->has_element(si)) {
++si; ++si;
} }
nassertr(si < size, false); nassertr(si < size, false);
nassertr(_attribs->get_key(si)->get_ref_count() >= 0, false); nassertr(_attribs->get_key(si)->get_ref_count() >= 0, false);
int snext = si; size_t snext = si;
++snext; ++snext;
while (snext < size && !_attribs->has_element(snext)) { while (snext < size && !_attribs->has_element(snext)) {
++snext; ++snext;

View File

@ -196,7 +196,7 @@ private:
// This keeps track of our current position through the garbage collection // This keeps track of our current position through the garbage collection
// cycle. // cycle.
static int _garbage_index; static size_t _garbage_index;
static PStatCollector _garbage_collect_pcollector; static PStatCollector _garbage_collect_pcollector;

View File

@ -160,7 +160,7 @@ has_adjust_transform() const {
*/ */
void RenderEffect:: void RenderEffect::
adjust_transform(CPT(TransformState) &, CPT(TransformState) &, adjust_transform(CPT(TransformState) &, CPT(TransformState) &,
PandaNode *) const { const PandaNode *) const {
} }
/** /**

View File

@ -68,7 +68,7 @@ public:
virtual bool has_adjust_transform() const; virtual bool has_adjust_transform() const;
virtual void adjust_transform(CPT(TransformState) &net_transform, virtual void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const; const PandaNode *node) const;
PUBLISHED: PUBLISHED:
INLINE int compare_to(const RenderEffect &other) const; INLINE int compare_to(const RenderEffect &other) const;

View File

@ -492,7 +492,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data,
void RenderEffects:: void RenderEffects::
adjust_transform(CPT(TransformState) &net_transform, adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const { const PandaNode *node) const {
Effects::const_iterator ei; Effects::const_iterator ei;
for (ei = _effects.begin(); ei != _effects.end(); ++ei) { for (ei = _effects.begin(); ei != _effects.end(); ++ei) {
(*ei)._effect->adjust_transform(net_transform, node_transform, node); (*ei)._effect->adjust_transform(net_transform, node_transform, node);

View File

@ -102,7 +102,7 @@ public:
INLINE bool has_adjust_transform() const; INLINE bool has_adjust_transform() const;
void adjust_transform(CPT(TransformState) &net_transform, void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform, CPT(TransformState) &node_transform,
PandaNode *node) const; const PandaNode *node) const;
static void init_states(); static void init_states();

View File

@ -522,7 +522,8 @@ INLINE void RenderState::
check_hash() const { check_hash() const {
// This pretends to be a const function, even though it's not, because it // This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value. // only updates a transparent cache value.
if ((_flags & F_hash_known) == 0) { if ((_flags & F_hash_known) != 0) {
} else {
((RenderState *)this)->calc_hash(); ((RenderState *)this)->calc_hash();
} }
} }

View File

@ -40,7 +40,7 @@ LightReMutex *RenderState::_states_lock = NULL;
RenderState::States *RenderState::_states = NULL; RenderState::States *RenderState::_states = NULL;
const RenderState *RenderState::_empty_state = NULL; const RenderState *RenderState::_empty_state = NULL;
UpdateSeq RenderState::_last_cycle_detect; UpdateSeq RenderState::_last_cycle_detect;
int RenderState::_garbage_index = 0; size_t RenderState::_garbage_index = 0;
PStatCollector RenderState::_cache_update_pcollector("*:State Cache:Update"); PStatCollector RenderState::_cache_update_pcollector("*:State Cache:Update");
PStatCollector RenderState::_garbage_collect_pcollector("*:State Cache:Garbage Collect"); PStatCollector RenderState::_garbage_collect_pcollector("*:State Cache:Garbage Collect");
@ -75,6 +75,10 @@ RenderState() :
_cache_stats.add_num_states(1); _cache_stats.add_num_states(1);
_read_overrides = NULL; _read_overrides = NULL;
_generated_shader = NULL; _generated_shader = NULL;
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif
} }
/** /**
@ -97,6 +101,10 @@ RenderState(const RenderState &copy) :
_cache_stats.add_num_states(1); _cache_stats.add_num_states(1);
_read_overrides = NULL; _read_overrides = NULL;
_generated_shader = NULL; _generated_shader = NULL;
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif
} }
/** /**
@ -617,7 +625,7 @@ adjust_all_priorities(int adjustment) const {
*/ */
bool RenderState:: bool RenderState::
unref() const { unref() const {
if (!state_cache || garbage_collect_states) { if (garbage_collect_states || !state_cache) {
// If we're not using the cache at all, or if we're relying on garbage // If we're not using the cache at all, or if we're relying on garbage
// collection, just allow the pointer to unref normally. // collection, just allow the pointer to unref normally.
return ReferenceCount::unref(); return ReferenceCount::unref();
@ -774,8 +782,8 @@ get_num_unused_states() {
typedef pmap<const RenderState *, int> StateCount; typedef pmap<const RenderState *, int> StateCount;
StateCount state_count; StateCount state_count;
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -871,8 +879,8 @@ clear_cache() {
TempStates temp_states; TempStates temp_states;
temp_states.reserve(orig_size); temp_states.reserve(orig_size);
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -938,27 +946,30 @@ garbage_collect() {
if (_states == (States *)NULL || !garbage_collect_states) { if (_states == (States *)NULL || !garbage_collect_states) {
return num_attribs; return num_attribs;
} }
bool break_and_uniquify = (auto_break_cycles && uniquify_transforms);
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
PStatTimer timer(_garbage_collect_pcollector); PStatTimer timer(_garbage_collect_pcollector);
int orig_size = _states->get_num_entries(); int orig_size = _states->get_num_entries();
// How many elements to process this pass? // How many elements to process this pass?
int size = _states->get_size(); size_t size = _states->get_size();
int num_this_pass = int(size * garbage_collect_states_rate); size_t num_this_pass = int((int)size * garbage_collect_states_rate);
if (num_this_pass <= 0) { if (size <= 0 || num_this_pass <= 0) {
return num_attribs; return num_attribs;
} }
num_this_pass = min(num_this_pass, size);
int stop_at_element = (_garbage_index + num_this_pass) % size;
int num_elements = 0; size_t si = _garbage_index;
int si = _garbage_index;
num_this_pass = min(num_this_pass, size);
size_t stop_at_element = (si + num_this_pass) % (size - 1);
do { do {
if (_states->has_element(si)) { if (_states->has_element(si)) {
++num_elements;
RenderState *state = (RenderState *)_states->get_key(si); RenderState *state = (RenderState *)_states->get_key(si);
if (auto_break_cycles && uniquify_states) { if (break_and_uniquify) {
if (state->get_cache_ref_count() > 0 && if (state->get_cache_ref_count() > 0 &&
state->get_ref_count() == state->get_cache_ref_count()) { state->get_ref_count() == state->get_cache_ref_count()) {
// If we have removed all the references to this state not in the // If we have removed all the references to this state not in the
@ -982,10 +993,13 @@ garbage_collect() {
} }
} }
si = (si + 1) % size; si = (si + 1) & (size - 1);
} while (si != stop_at_element); } while (si != stop_at_element);
_garbage_index = si; _garbage_index = si;
#ifdef _DEBUG
nassertr(_states->validate(), 0); nassertr(_states->validate(), 0);
#endif
int new_size = _states->get_num_entries(); int new_size = _states->get_num_entries();
return orig_size - new_size + num_attribs; return orig_size - new_size + num_attribs;
@ -999,8 +1013,8 @@ void RenderState::
clear_munger_cache() { clear_munger_cache() {
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -1034,8 +1048,8 @@ list_cycles(ostream &out) {
VisitedStates visited; VisitedStates visited;
CompositionCycleDesc cycle_desc; CompositionCycleDesc cycle_desc;
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -1113,8 +1127,8 @@ list_states(ostream &out) {
out << _states->get_num_entries() << " states:\n"; out << _states->get_num_entries() << " states:\n";
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -1148,14 +1162,14 @@ validate_states() {
return false; return false;
} }
int size = _states->get_size(); size_t size = _states->get_size();
int si = 0; size_t si = 0;
while (si < size && !_states->has_element(si)) { while (si < size && !_states->has_element(si)) {
++si; ++si;
} }
nassertr(si < size, false); nassertr(si < size, false);
nassertr(_states->get_key(si)->get_ref_count() >= 0, false); nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
int snext = si; size_t snext = si;
++snext; ++snext;
while (snext < size && !_states->has_element(snext)) { while (snext < size && !_states->has_element(snext)) {
++snext; ++snext;

View File

@ -278,7 +278,7 @@ private:
// This keeps track of our current position through the garbage collection // This keeps track of our current position through the garbage collection
// cycle. // cycle.
static int _garbage_index; static size_t _garbage_index;
static PStatCollector _cache_update_pcollector; static PStatCollector _cache_update_pcollector;
static PStatCollector _garbage_collect_pcollector; static PStatCollector _garbage_collect_pcollector;
@ -368,6 +368,12 @@ private:
friend class Extension<RenderState>; friend class Extension<RenderState>;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<RenderState>::update_type(To *ptr) {}
#endif
INLINE ostream &operator << (ostream &out, const RenderState &state) { INLINE ostream &operator << (ostream &out, const RenderState &state) {
state.output(out); state.output(out);
return out; return out;

View File

@ -110,7 +110,7 @@ has_shader_input(CPT_InternalName id) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_float &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_float &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -118,7 +118,7 @@ set_shader_input(CPT_InternalName id, const PTA_float &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_double &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_double &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -126,7 +126,7 @@ set_shader_input(CPT_InternalName id, const PTA_double &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_LVecBase4 &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_LVecBase4 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -134,7 +134,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase4 &v, int priority) cons
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_LVecBase3 &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_LVecBase3 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
@ -143,7 +143,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase3 &v, int priority) cons
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_LVecBase2 &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_LVecBase2 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -151,7 +151,7 @@ set_shader_input(CPT_InternalName id, const PTA_LVecBase2 &v, int priority) cons
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const LVecBase4 &v, int priority) const { set_shader_input(CPT_InternalName id, const LVecBase4 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -159,7 +159,7 @@ set_shader_input(CPT_InternalName id, const LVecBase4 &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const LVecBase3 &v, int priority) const { set_shader_input(CPT_InternalName id, const LVecBase3 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -167,7 +167,7 @@ set_shader_input(CPT_InternalName id, const LVecBase3 &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const LVecBase2 &v, int priority) const { set_shader_input(CPT_InternalName id, const LVecBase2 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -175,7 +175,7 @@ set_shader_input(CPT_InternalName id, const LVecBase2 &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_LMatrix4 &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_LMatrix4 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -183,7 +183,7 @@ set_shader_input(CPT_InternalName id, const PTA_LMatrix4 &v, int priority) const
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const PTA_LMatrix3 &v, int priority) const { set_shader_input(CPT_InternalName id, const PTA_LMatrix3 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -191,7 +191,7 @@ set_shader_input(CPT_InternalName id, const PTA_LMatrix3 &v, int priority) const
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const LMatrix4 &v, int priority) const { set_shader_input(CPT_InternalName id, const LMatrix4 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -199,7 +199,7 @@ set_shader_input(CPT_InternalName id, const LMatrix4 &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority) const { set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), v, priority)); return set_shader_input(ShaderInput(move(id), v, priority));
} }
/** /**
@ -207,7 +207,7 @@ set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, Texture *tex, int priority) const { set_shader_input(CPT_InternalName id, Texture *tex, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), tex, priority)); return set_shader_input(ShaderInput(move(id), tex, priority));
} }
/** /**
@ -215,7 +215,7 @@ set_shader_input(CPT_InternalName id, Texture *tex, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, const NodePath &np, int priority) const { set_shader_input(CPT_InternalName id, const NodePath &np, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), np, priority)); return set_shader_input(ShaderInput(move(id), np, priority));
} }
/** /**
@ -223,7 +223,7 @@ set_shader_input(CPT_InternalName id, const NodePath &np, int priority) const {
*/ */
INLINE CPT(RenderAttrib) ShaderAttrib:: INLINE CPT(RenderAttrib) ShaderAttrib::
set_shader_input(CPT_InternalName id, double n1, double n2, double n3, double n4, int priority) const { set_shader_input(CPT_InternalName id, double n1, double n2, double n3, double n4, int priority) const {
return set_shader_input(new ShaderInput(MOVE(id), LVecBase4((PN_stdfloat)n1, (PN_stdfloat)n2, (PN_stdfloat)n3, (PN_stdfloat)n4), priority)); return set_shader_input(ShaderInput(move(id), LVecBase4((PN_stdfloat)n1, (PN_stdfloat)n2, (PN_stdfloat)n3, (PN_stdfloat)n4), priority));
} }
INLINE bool ShaderAttrib:: INLINE bool ShaderAttrib::

View File

@ -193,13 +193,13 @@ clear_flag(int flag) const {
* *
*/ */
CPT(RenderAttrib) ShaderAttrib:: CPT(RenderAttrib) ShaderAttrib::
set_shader_input(const ShaderInput *input) const { set_shader_input(ShaderInput input) const {
ShaderAttrib *result = new ShaderAttrib(*this); ShaderAttrib *result = new ShaderAttrib(*this);
Inputs::iterator i = result->_inputs.find(input->get_name()); Inputs::iterator i = result->_inputs.find(input.get_name());
if (i == result->_inputs.end()) { if (i == result->_inputs.end()) {
result->_inputs.insert(Inputs::value_type(input->get_name(), input)); result->_inputs.insert(Inputs::value_type(input.get_name(), move(input)));
} else { } else {
i->second = input; i->second = move(input);
} }
return return_new(result); return return_new(result);
} }
@ -248,13 +248,13 @@ clear_all_shader_inputs() const {
* Returns the ShaderInput of the given name. If no such name is found, this * Returns the ShaderInput of the given name. If no such name is found, this
* function does not return NULL --- it returns the "blank" ShaderInput. * function does not return NULL --- it returns the "blank" ShaderInput.
*/ */
const ShaderInput *ShaderAttrib:: const ShaderInput &ShaderAttrib::
get_shader_input(const InternalName *id) const { get_shader_input(const InternalName *id) const {
Inputs::const_iterator i = _inputs.find(id); Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) { if (i != _inputs.end()) {
return ShaderInput::get_blank();
} else {
return (*i).second; return (*i).second;
} else {
return ShaderInput::get_blank();
} }
} }
@ -262,7 +262,7 @@ get_shader_input(const InternalName *id) const {
* Returns the ShaderInput of the given name. If no such name is found, this * Returns the ShaderInput of the given name. If no such name is found, this
* function does not return NULL --- it returns the "blank" ShaderInput. * function does not return NULL --- it returns the "blank" ShaderInput.
*/ */
const ShaderInput *ShaderAttrib:: const ShaderInput &ShaderAttrib::
get_shader_input(const string &id) const { get_shader_input(const string &id) const {
return get_shader_input(InternalName::make(id)); return get_shader_input(InternalName::make(id));
} }
@ -275,20 +275,21 @@ const NodePath &ShaderAttrib::
get_shader_input_nodepath(const InternalName *id) const { get_shader_input_nodepath(const InternalName *id) const {
static NodePath resfail; static NodePath resfail;
Inputs::const_iterator i = _inputs.find(id); Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) { if (i != _inputs.end()) {
ostringstream strm; const ShaderInput &p = (*i).second;
strm << "Shader input " << id->get_name() << " is not present.\n"; if (p.get_value_type() == ShaderInput::M_nodepath) {
nassert_raise(strm.str()); return ((const ParamNodePath *)p.get_value())->get_value();
return resfail; } else {
} else {
const ShaderInput *p = (*i).second;
if (p->get_value_type() != ShaderInput::M_nodepath) {
ostringstream strm; ostringstream strm;
strm << "Shader input " << id->get_name() << " is not a nodepath.\n"; strm << "Shader input " << id->get_name() << " is not a nodepath.\n";
nassert_raise(strm.str()); nassert_raise(strm.str());
return resfail; return resfail;
} }
return p->get_nodepath(); } else {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return resfail;
} }
// Satisfy compiler. // Satisfy compiler.
@ -303,19 +304,14 @@ LVecBase4 ShaderAttrib::
get_shader_input_vector(InternalName *id) const { get_shader_input_vector(InternalName *id) const {
static LVecBase4 resfail(0,0,0,0); static LVecBase4 resfail(0,0,0,0);
Inputs::const_iterator i = _inputs.find(id); Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) { if (i != _inputs.end()) {
ostringstream strm; const ShaderInput &p = (*i).second;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return resfail;
} else {
const ShaderInput *p = (*i).second;
if (p->get_value_type() == ShaderInput::M_vector) { if (p.get_value_type() == ShaderInput::M_vector) {
return p->get_vector(); return p.get_vector();
} else if (p->get_value_type() == ShaderInput::M_numeric && p->get_ptr()._size <= 4) { } else if (p.get_value_type() == ShaderInput::M_numeric && p.get_ptr()._size <= 4) {
const Shader::ShaderPtrData &ptr = p->get_ptr(); const Shader::ShaderPtrData &ptr = p.get_ptr();
switch (ptr._type) { switch (ptr._type) {
case Shader::SPT_float: case Shader::SPT_float:
@ -339,19 +335,23 @@ get_shader_input_vector(InternalName *id) const {
} }
} }
} else if (p->get_value_type() == ShaderInput::M_param) { } else if (p.get_value_type() == ShaderInput::M_param) {
// Temporary solution until the new param system // Temporary solution until the new param system
ParamValueBase *param = p->get_param(); TypedWritableReferenceCount *param = p.get_value();
if (param != NULL && param->is_of_type(ParamVecBase4::get_class_type())) { if (param != NULL && param->is_of_type(ParamVecBase4::get_class_type())) {
return ((const ParamVecBase4 *) param)->get_value(); return ((const ParamVecBase4 *)param)->get_value();
} }
} }
ostringstream strm; ostringstream strm;
strm << "Shader input " << id->get_name() << " is not a vector.\n"; strm << "Shader input " << id->get_name() << " is not a vector.\n";
nassert_raise(strm.str()); nassert_raise(strm.str());
return resfail; } else {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
} }
return resfail;
} }
/** /**
@ -361,21 +361,21 @@ get_shader_input_vector(InternalName *id) const {
const Shader::ShaderPtrData *ShaderAttrib:: const Shader::ShaderPtrData *ShaderAttrib::
get_shader_input_ptr(const InternalName *id) const { get_shader_input_ptr(const InternalName *id) const {
Inputs::const_iterator i = _inputs.find(id); Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) { if (i != _inputs.end()) {
ostringstream strm; const ShaderInput &p = (*i).second;
strm << "Shader input " << id->get_name() << " is not present.\n"; if (p.get_value_type() != ShaderInput::M_numeric &&
nassert_raise(strm.str()); p.get_value_type() != ShaderInput::M_vector) {
return NULL;
} else {
const ShaderInput *p = (*i).second;
if (p->get_value_type() != ShaderInput::M_numeric &&
p->get_value_type() != ShaderInput::M_vector) {
ostringstream strm; ostringstream strm;
strm << "Shader input " << id->get_name() << " is not a PTA(float/double) type.\n"; strm << "Shader input " << id->get_name() << " is not a PTA(float/double) type.\n";
nassert_raise(strm.str()); nassert_raise(strm.str());
return NULL; return NULL;
} }
return &(p->get_ptr()); return &(p.get_ptr());
} else {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return NULL;
} }
} }
@ -389,24 +389,39 @@ get_shader_input_ptr(const InternalName *id) const {
Texture *ShaderAttrib:: Texture *ShaderAttrib::
get_shader_input_texture(const InternalName *id, SamplerState *sampler) const { get_shader_input_texture(const InternalName *id, SamplerState *sampler) const {
Inputs::const_iterator i = _inputs.find(id); Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) { if (i != _inputs.end()) {
ostringstream strm; const ShaderInput &p = (*i).second;
strm << "Shader input " << id->get_name() << " is not present.\n"; switch (p.get_value_type()) {
nassert_raise(strm.str()); case ShaderInput::M_texture:
return NULL; {
} else { Texture *tex = (Texture *)p.get_value();
const ShaderInput *p = (*i).second; if (sampler) {
if (p->get_value_type() != ShaderInput::M_texture && *sampler = tex->get_default_sampler();
p->get_value_type() != ShaderInput::M_texture_sampler) { }
return tex;
}
case ShaderInput::M_texture_sampler:
{
const ParamTextureSampler *param = (const ParamTextureSampler *)p.get_value();
if (sampler) {
*sampler = param->get_sampler();
}
return param->get_texture();
}
default:
ostringstream strm; ostringstream strm;
strm << "Shader input " << id->get_name() << " is not a texture.\n"; strm << "Shader input " << id->get_name() << " is not a texture.\n";
nassert_raise(strm.str()); nassert_raise(strm.str());
return NULL; return NULL;
} }
if (sampler != NULL) {
*sampler = p->get_sampler(); } else {
} ostringstream strm;
return p->get_texture(); strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return NULL;
} }
} }
@ -417,22 +432,17 @@ get_shader_input_texture(const InternalName *id, SamplerState *sampler) const {
const LMatrix4 &ShaderAttrib:: const LMatrix4 &ShaderAttrib::
get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const { get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const {
Inputs::const_iterator i = _inputs.find(id); Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) { if (i != _inputs.end()) {
ostringstream strm; const ShaderInput &p = (*i).second;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return LMatrix4::ident_mat();
} else {
const ShaderInput *p = (*i).second;
if (p->get_value_type() == ShaderInput::M_nodepath) { if (p.get_value_type() == ShaderInput::M_nodepath) {
const NodePath &np = p->get_nodepath(); const NodePath &np = p.get_nodepath();
nassertr(!np.is_empty(), LMatrix4::ident_mat()); nassertr(!np.is_empty(), LMatrix4::ident_mat());
return np.get_transform()->get_mat(); return np.get_transform()->get_mat();
} else if (p->get_value_type() == ShaderInput::M_numeric && } else if (p.get_value_type() == ShaderInput::M_numeric &&
p->get_ptr()._size >= 16 && (p->get_ptr()._size & 15) == 0) { p.get_ptr()._size >= 16 && (p.get_ptr()._size & 15) == 0) {
const Shader::ShaderPtrData &ptr = p->get_ptr(); const Shader::ShaderPtrData &ptr = p.get_ptr();
switch (ptr._type) { switch (ptr._type) {
case Shader::SPT_float: { case Shader::SPT_float: {
@ -460,6 +470,11 @@ get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const {
strm << "Shader input " << id->get_name() << " is not a NodePath, LMatrix4 or PTA_LMatrix4.\n"; strm << "Shader input " << id->get_name() << " is not a NodePath, LMatrix4 or PTA_LMatrix4.\n";
nassert_raise(strm.str()); nassert_raise(strm.str());
return LMatrix4::ident_mat(); return LMatrix4::ident_mat();
} else {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return LMatrix4::ident_mat();
} }
} }
@ -476,11 +491,11 @@ get_shader_input_buffer(const InternalName *id) const {
nassert_raise(strm.str()); nassert_raise(strm.str());
return NULL; return NULL;
} else { } else {
const ShaderInput *p = (*i).second; const ShaderInput &p = (*i).second;
if (p->get_value_type() == ShaderInput::M_buffer) { if (p.get_value_type() == ShaderInput::M_buffer) {
ShaderBuffer *value; ShaderBuffer *value;
DCAST_INTO_R(value, p->_value, NULL); DCAST_INTO_R(value, p._value, NULL);
return value; return value;
} }
@ -615,8 +630,7 @@ get_hash_impl() const {
Inputs::const_iterator ii; Inputs::const_iterator ii;
for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) { for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
hash = pointer_hash::add_hash(hash, (*ii).first); hash = (*ii).second.add_hash(hash);
hash = pointer_hash::add_hash(hash, (*ii).second);
} }
return hash; return hash;
@ -649,13 +663,13 @@ compose_impl(const RenderAttrib *other) const {
Inputs::const_iterator iover; Inputs::const_iterator iover;
for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) { for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
const InternalName *id = (*iover).first; const InternalName *id = (*iover).first;
const ShaderInput *dover = (*iover).second; const ShaderInput &dover = (*iover).second;
Inputs::iterator iattr = attr->_inputs.find(id); Inputs::iterator iattr = attr->_inputs.find(id);
if (iattr == attr->_inputs.end()) { if (iattr == attr->_inputs.end()) {
attr->_inputs.insert(Inputs::value_type(id,dover)); attr->_inputs.insert(Inputs::value_type(id,dover));
} else { } else {
const ShaderInput *dattr = (*iattr).second; const ShaderInput &dattr = (*iattr).second;
if (dattr->get_priority() <= dover->get_priority()) { if (dattr.get_priority() <= dover.get_priority()) {
iattr->second = iover->second; iattr->second = iover->second;
} }
} }

View File

@ -71,7 +71,7 @@ PUBLISHED:
CPT(RenderAttrib) clear_shader() const; CPT(RenderAttrib) clear_shader() const;
// Shader Inputs // Shader Inputs
CPT(RenderAttrib) set_shader_input(const ShaderInput *inp) const; CPT(RenderAttrib) set_shader_input(ShaderInput input) const;
INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, Texture *tex, int priority=0) const; INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, Texture *tex, int priority=0) const;
INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, const NodePath &np, int priority=0) const; INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, const NodePath &np, int priority=0) const;
@ -104,8 +104,8 @@ PUBLISHED:
INLINE bool has_shader_input(CPT_InternalName id) const; INLINE bool has_shader_input(CPT_InternalName id) const;
const Shader *get_shader() const; const Shader *get_shader() const;
const ShaderInput *get_shader_input(const InternalName *id) const; const ShaderInput &get_shader_input(const InternalName *id) const;
const ShaderInput *get_shader_input(const string &id) const; const ShaderInput &get_shader_input(const string &id) const;
const NodePath &get_shader_input_nodepath(const InternalName *id) const; const NodePath &get_shader_input_nodepath(const InternalName *id) const;
LVecBase4 get_shader_input_vector(InternalName *id) const; LVecBase4 get_shader_input_vector(InternalName *id) const;
@ -145,7 +145,9 @@ private:
bool _auto_ramp_on; bool _auto_ramp_on;
bool _auto_shadow_on; bool _auto_shadow_on;
typedef pmap<CPT_InternalName, CPT(ShaderInput)> Inputs; // We don't keep a reference to the InternalName, since this is also already
// stored on the ShaderInput object.
typedef pmap<const InternalName *, ShaderInput> Inputs;
Inputs _inputs; Inputs _inputs;
friend class Extension<NodePath>; friend class Extension<NodePath>;

View File

@ -13,13 +13,6 @@
* @date 2010-04-06 * @date 2010-04-06
*/ */
/**
*
*/
INLINE ShaderInput::
~ShaderInput() {
}
/** /**
* *
*/ */
@ -424,6 +417,81 @@ ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority) :
{ {
} }
/**
*
*/
INLINE bool ShaderInput::
operator == (const ShaderInput &other) const {
if (_type != other._type || _name != other._name || _priority != other._priority) {
return false;
}
switch (_type) {
case M_invalid:
return true;
case M_vector:
return _stored_vector == other._stored_vector;
case M_numeric:
return _stored_ptr._ptr == other._stored_ptr._ptr;
default:
return _value == other._value;
}
}
/**
*
*/
INLINE bool ShaderInput::
operator != (const ShaderInput &other) const {
if (_type != other._type || _name != other._name || _priority != other._priority) {
return true;
}
switch (_type) {
case M_invalid:
return false;
case M_vector:
return _stored_vector != other._stored_vector;
case M_numeric:
return _stored_ptr._ptr != other._stored_ptr._ptr;
default:
return _value != other._value;
}
}
/**
*
*/
INLINE bool ShaderInput::
operator < (const ShaderInput &other) const {
if (_type != other._type) {
return (_type < other._type);
}
if (_name != other._name) {
return (_name < other._name);
}
if (_priority != other._priority) {
return (_priority < other._priority);
}
switch (_type) {
case M_invalid:
return false;
case M_vector:
return _stored_vector < other._stored_vector;
case M_numeric:
return _stored_ptr._ptr < other._stored_ptr._ptr;
default:
return _value < other._value;
}
}
/** /**
* *
*/ */
@ -471,3 +539,11 @@ INLINE ParamValueBase *ShaderInput::
get_param() const { get_param() const {
return DCAST(ParamValueBase, _value); return DCAST(ParamValueBase, _value);
} }
/**
*
*/
INLINE TypedWritableReferenceCount *ShaderInput::
get_value() const {
return _value.p();
}

View File

@ -15,18 +15,13 @@
#include "paramNodePath.h" #include "paramNodePath.h"
#include "paramTexture.h" #include "paramTexture.h"
TypeHandle ShaderInput::_type_handle;
/** /**
* Returns a static ShaderInput object with name NULL, priority zero, type * Returns a static ShaderInput object with name NULL, priority zero, type
* INVALID, and all value-fields cleared. * INVALID, and all value-fields cleared.
*/ */
const ShaderInput *ShaderInput:: const ShaderInput &ShaderInput::
get_blank() { get_blank() {
static CPT(ShaderInput) blank; static ShaderInput blank(nullptr, 0);
if (blank == 0) {
blank = new ShaderInput(NULL, 0);
}
return blank; return blank;
} }
@ -66,6 +61,30 @@ ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, in
{ {
} }
/**
*
*/
size_t ShaderInput::
add_hash(size_t hash) const {
hash = int_hash::add_hash(hash, _type);
hash = pointer_hash::add_hash(hash, _name);
hash = int_hash::add_hash(hash, _priority);
switch (_type) {
case M_invalid:
return hash;
case M_vector:
return _stored_vector.add_hash(hash);
case M_numeric:
return pointer_hash::add_hash(hash, _stored_ptr._ptr);
default:
return pointer_hash::add_hash(hash, _value);
}
}
/** /**
* Warning: no error checking is done. This *will* crash if get_value_type() * Warning: no error checking is done. This *will* crash if get_value_type()
* is not M_nodepath. * is not M_nodepath.

View File

@ -17,7 +17,6 @@
#define SHADERINPUT_H #define SHADERINPUT_H
#include "pandabase.h" #include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h" #include "pointerTo.h"
#include "internalName.h" #include "internalName.h"
#include "paramValue.h" #include "paramValue.h"
@ -37,10 +36,7 @@
* This is a small container class that can hold any one of the value types * This is a small container class that can hold any one of the value types
* that can be passed as input to a shader. * that can be passed as input to a shader.
*/ */
class EXPCL_PANDA_PGRAPH ShaderInput : public TypedWritableReferenceCount { class EXPCL_PANDA_PGRAPH ShaderInput {
public:
INLINE ~ShaderInput();
PUBLISHED: PUBLISHED:
// Used when binding texture images. // Used when binding texture images.
enum AccessFlags { enum AccessFlags {
@ -49,7 +45,7 @@ PUBLISHED:
A_layered = 0x04, A_layered = 0x04,
}; };
static const ShaderInput *get_blank(); static const ShaderInput &get_blank();
INLINE ShaderInput(CPT_InternalName name, int priority=0); INLINE ShaderInput(CPT_InternalName name, int priority=0);
INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0); INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0);
INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0); INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0);
@ -102,6 +98,12 @@ PUBLISHED:
M_buffer, M_buffer,
}; };
INLINE bool operator == (const ShaderInput &other) const;
INLINE bool operator != (const ShaderInput &other) const;
INLINE bool operator < (const ShaderInput &other) const;
size_t add_hash(size_t hash) const;
INLINE const InternalName *get_name() const; INLINE const InternalName *get_name() const;
INLINE int get_value_type() const; INLINE int get_value_type() const;
@ -114,7 +116,10 @@ PUBLISHED:
const SamplerState &get_sampler() const; const SamplerState &get_sampler() const;
public: public:
ShaderInput() DEFAULT_CTOR;
INLINE ParamValueBase *get_param() const; INLINE ParamValueBase *get_param() const;
INLINE TypedWritableReferenceCount *get_value() const;
static void register_with_read_factory(); static void register_with_read_factory();
@ -127,26 +132,8 @@ private:
int _type; int _type;
friend class ShaderAttrib; friend class ShaderAttrib;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "ShaderInput",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
}; };
#include "shaderInput.I" #include "shaderInput.I"
#endif // SHADERINPUT_H #endif // SHADERINPUT_H

View File

@ -29,7 +29,7 @@ TransformState::States *TransformState::_states = NULL;
CPT(TransformState) TransformState::_identity_state; CPT(TransformState) TransformState::_identity_state;
CPT(TransformState) TransformState::_invalid_state; CPT(TransformState) TransformState::_invalid_state;
UpdateSeq TransformState::_last_cycle_detect; UpdateSeq TransformState::_last_cycle_detect;
int TransformState::_garbage_index = 0; size_t TransformState::_garbage_index = 0;
bool TransformState::_uniquify_matrix = true; bool TransformState::_uniquify_matrix = true;
PStatCollector TransformState::_cache_update_pcollector("*:State Cache:Update"); PStatCollector TransformState::_cache_update_pcollector("*:State Cache:Update");
@ -62,6 +62,10 @@ TransformState() : _lock("TransformState") {
_flags = F_is_identity | F_singular_known | F_is_2d; _flags = F_is_identity | F_singular_known | F_is_2d;
_inv_mat = (LMatrix4 *)NULL; _inv_mat = (LMatrix4 *)NULL;
_cache_stats.add_num_states(1); _cache_stats.add_num_states(1);
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif
} }
/** /**
@ -608,33 +612,74 @@ compose(const TransformState *other) const {
return do_compose(other); return do_compose(other);
} }
// Is this composition already cached? LightReMutexHolder holder(*_states_lock);
CPT(TransformState) result;
{
LightReMutexHolder holder(*_states_lock);
int index = _composition_cache.find(other);
if (index != -1) {
const Composition &comp = _composition_cache.get_data(index);
result = comp._result;
}
if (result != (TransformState *)NULL) {
_cache_stats.inc_hits();
}
}
if (result != (TransformState *)NULL) { // Is this composition already cached?
// Success! int index = _composition_cache.find(other);
return result; if (index != -1) {
const Composition &comp = _composition_cache.get_data(index);
if (comp._result != nullptr) {
// Success!
_cache_stats.inc_hits();
return comp._result;
}
} }
// Not in the cache. Compute a new result. It's important that we don't // Not in the cache. Compute a new result. It's important that we don't
// hold the lock while we do this, or we lose the benefit of // hold the lock while we do this, or we lose the benefit of
// parallelization. // parallelization.
result = do_compose(other); CPT(TransformState) result = do_compose(other);
// It's OK to cast away the constness of this pointer, because the cache is if (index != -1) {
// a transparent property of the class. Composition &comp = _composition_cache.modify_data(index);
return ((TransformState *)this)->store_compose(other, result); // Well, it wasn't cached already, but we already had an entry (probably
// created for the reverse direction), so use the same entry to store
// the new result.
comp._result = result;
if (result != (const TransformState *)this) {
// See the comments below about the need to up the reference count
// only when the result is not the same as this.
result->cache_ref();
}
// Here's the cache!
_cache_stats.inc_hits();
return result;
}
_cache_stats.inc_misses();
// We need to make a new cache entry, both in this object and in the other
// object. We make both records so the other TransformState object will
// know to delete the entry from this object when it destructs, and vice-
// versa.
// The cache entry in this object is the only one that indicates the result;
// the other will be NULL for now.
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(_composition_cache.get_size() == 0);
_composition_cache[other]._result = result;
if (other != this) {
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(other->_composition_cache.get_size() == 0);
other->_composition_cache[this]._result = NULL;
}
if (result != (TransformState *)this) {
// If the result of do_compose() is something other than this, explicitly
// increment the reference count. We have to be sure to decrement it
// again later, when the composition entry is removed from the cache.
result->cache_ref();
// (If the result was just this again, we still store the result, but we
// don't increment the reference count, since that would be a self-
// referential leak.)
}
_cache_stats.maybe_report("TransformState");
return result;
} }
/** /**
@ -676,32 +721,69 @@ invert_compose(const TransformState *other) const {
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
CPT(TransformState) result; int index = _invert_composition_cache.find(other);
{ if (index != -1) {
LightReMutexHolder holder(*_states_lock); const Composition &comp = _invert_composition_cache.get_data(index);
int index = _invert_composition_cache.find(other); if (comp._result != nullptr) {
if (index != -1) { // Success!
const Composition &comp = _invert_composition_cache.get_data(index);
result = comp._result;
}
if (result != (TransformState *)NULL) {
_cache_stats.inc_hits(); _cache_stats.inc_hits();
return comp._result;
} }
} }
if (result != (TransformState *)NULL) {
// Success!
return result;
}
// Not in the cache. Compute a new result. It's important that we don't // Not in the cache. Compute a new result. It's important that we don't
// hold the lock while we do this, or we lose the benefit of // hold the lock while we do this, or we lose the benefit of
// parallelization. // parallelization.
result = do_invert_compose(other); CPT(TransformState) result = do_invert_compose(other);
// It's OK to cast away the constness of this pointer, because the cache is // Is this composition already cached?
// a transparent property of the class. if (index != -1) {
return ((TransformState *)this)->store_invert_compose(other, result); Composition &comp = _invert_composition_cache.modify_data(index);
// Well, it wasn't cached already, but we already had an entry (probably
// created for the reverse direction), so use the same entry to store
// the new result.
comp._result = result;
if (result != (const TransformState *)this) {
// See the comments below about the need to up the reference count
// only when the result is not the same as this.
result->cache_ref();
}
// Here's the cache!
_cache_stats.inc_hits();
return result;
}
_cache_stats.inc_misses();
// We need to make a new cache entry, both in this object and in the other
// object. We make both records so the other TransformState object will
// know to delete the entry from this object when it destructs, and vice-
// versa.
// The cache entry in this object is the only one that indicates the result;
// the other will be NULL for now.
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(_invert_composition_cache.get_size() == 0);
_invert_composition_cache[other]._result = result;
if (other != this) {
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(other->_invert_composition_cache.get_size() == 0);
other->_invert_composition_cache[this]._result = NULL;
}
if (result != (TransformState *)this) {
// If the result of compose() is something other than this, explicitly
// increment the reference count. We have to be sure to decrement it
// again later, when the composition entry is removed from the cache.
result->cache_ref();
// (If the result was just this again, we still store the result, but we
// don't increment the reference count, since that would be a self-
// referential leak.)
}
return result;
} }
/** /**
@ -712,7 +794,7 @@ invert_compose(const TransformState *other) const {
*/ */
bool TransformState:: bool TransformState::
unref() const { unref() const {
if (!transform_cache || garbage_collect_states) { if (garbage_collect_states || !transform_cache) {
// If we're not using the cache at all, or if we're relying on garbage // If we're not using the cache at all, or if we're relying on garbage
// collection, just allow the pointer to unref normally. // collection, just allow the pointer to unref normally.
return ReferenceCount::unref(); return ReferenceCount::unref();
@ -760,8 +842,8 @@ bool TransformState::
validate_composition_cache() const { validate_composition_cache() const {
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
int size = _composition_cache.get_size(); size_t size = _composition_cache.get_size();
for (int i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
if (!_composition_cache.has_element(i)) { if (!_composition_cache.has_element(i)) {
continue; continue;
} }
@ -955,15 +1037,15 @@ get_num_unused_states() {
typedef pmap<const TransformState *, int> StateCount; typedef pmap<const TransformState *, int> StateCount;
StateCount state_count; StateCount state_count;
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
const TransformState *state = _states->get_key(si); const TransformState *state = _states->get_key(si);
int i; size_t i;
int cache_size = state->_composition_cache.get_size(); size_t cache_size = state->_composition_cache.get_size();
for (i = 0; i < cache_size; ++i) { for (i = 0; i < cache_size; ++i) {
if (state->_composition_cache.has_element(i)) { if (state->_composition_cache.has_element(i)) {
const TransformState *result = state->_composition_cache.get_data(i)._result; const TransformState *result = state->_composition_cache.get_data(i)._result;
@ -1053,8 +1135,8 @@ clear_cache() {
TempStates temp_states; TempStates temp_states;
temp_states.reserve(orig_size); temp_states.reserve(orig_size);
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -1116,27 +1198,30 @@ garbage_collect() {
if (_states == (States *)NULL || !garbage_collect_states) { if (_states == (States *)NULL || !garbage_collect_states) {
return 0; return 0;
} }
bool break_and_uniquify = (auto_break_cycles && uniquify_transforms);
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
PStatTimer timer(_garbage_collect_pcollector); PStatTimer timer(_garbage_collect_pcollector);
int orig_size = _states->get_num_entries(); size_t orig_size = _states->get_num_entries();
// How many elements to process this pass? // How many elements to process this pass?
int size = _states->get_size(); size_t size = _states->get_size();
int num_this_pass = int(size * garbage_collect_states_rate); size_t num_this_pass = int(size * garbage_collect_states_rate);
if (num_this_pass <= 0) { if (size <= 0 || num_this_pass <= 0) {
return 0; return 0;
} }
num_this_pass = min(num_this_pass, size);
int stop_at_element = (_garbage_index + num_this_pass) % size;
int num_elements = 0; size_t si = _garbage_index;
int si = _garbage_index;
num_this_pass = min(num_this_pass, size);
size_t stop_at_element = (si + num_this_pass) & (size - 1);
do { do {
if (_states->has_element(si)) { if (_states->has_element(si)) {
++num_elements;
TransformState *state = (TransformState *)_states->get_key(si); TransformState *state = (TransformState *)_states->get_key(si);
if (auto_break_cycles && uniquify_transforms) { if (break_and_uniquify) {
if (state->get_cache_ref_count() > 0 && if (state->get_cache_ref_count() > 0 &&
state->get_ref_count() == state->get_cache_ref_count()) { state->get_ref_count() == state->get_cache_ref_count()) {
// If we have removed all the references to this state not in the // If we have removed all the references to this state not in the
@ -1160,10 +1245,13 @@ garbage_collect() {
} }
} }
si = (si + 1) % size; si = (si + 1) & (size - 1);
} while (si != stop_at_element); } while (si != stop_at_element);
_garbage_index = si; _garbage_index = si;
#ifdef _DEBUG
nassertr(_states->validate(), 0); nassertr(_states->validate(), 0);
#endif
int new_size = _states->get_num_entries(); int new_size = _states->get_num_entries();
return orig_size - new_size; return orig_size - new_size;
@ -1193,8 +1281,8 @@ list_cycles(ostream &out) {
VisitedStates visited; VisitedStates visited;
CompositionCycleDesc cycle_desc; CompositionCycleDesc cycle_desc;
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -1272,8 +1360,8 @@ list_states(ostream &out) {
out << _states->get_num_entries() << " states:\n"; out << _states->get_num_entries() << " states:\n";
int size = _states->get_size(); size_t size = _states->get_size();
for (int si = 0; si < size; ++si) { for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) { if (!_states->has_element(si)) {
continue; continue;
} }
@ -1307,14 +1395,14 @@ validate_states() {
return false; return false;
} }
int size = _states->get_size(); size_t size = _states->get_size();
int si = 0; size_t si = 0;
while (si < size && !_states->has_element(si)) { while (si < size && !_states->has_element(si)) {
++si; ++si;
} }
nassertr(si < size, false); nassertr(si < size, false);
nassertr(_states->get_key(si)->get_ref_count() >= 0, false); nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
int snext = si; size_t snext = si;
++snext; ++snext;
while (snext < size && !_states->has_element(snext)) { while (snext < size && !_states->has_element(snext)) {
++snext; ++snext;
@ -1533,150 +1621,6 @@ do_compose(const TransformState *other) const {
} }
} }
/**
* Stores the result of a composition in the cache. Returns the stored result
* (it may be a different object than the one passed in, due to another thread
* having computed the composition first).
*/
CPT(TransformState) TransformState::
store_compose(const TransformState *other, const TransformState *result) {
// Identity should have already been screened.
nassertr(!is_identity(), other);
nassertr(!other->is_identity(), this);
// So should have validity.
nassertr(!is_invalid(), this);
nassertr(!other->is_invalid(), other);
LightReMutexHolder holder(*_states_lock);
// Is this composition already cached?
int index = _composition_cache.find(other);
if (index != -1) {
Composition &comp = _composition_cache.modify_data(index);
if (comp._result == (const TransformState *)NULL) {
// Well, it wasn't cached already, but we already had an entry (probably
// created for the reverse direction), so use the same entry to store
// the new result.
comp._result = result;
if (result != (const TransformState *)this) {
// See the comments below about the need to up the reference count
// only when the result is not the same as this.
result->cache_ref();
}
}
// Here's the cache!
_cache_stats.inc_hits();
return comp._result;
}
_cache_stats.inc_misses();
// We need to make a new cache entry, both in this object and in the other
// object. We make both records so the other TransformState object will
// know to delete the entry from this object when it destructs, and vice-
// versa.
// The cache entry in this object is the only one that indicates the result;
// the other will be NULL for now.
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(_composition_cache.get_size() == 0);
_composition_cache[other]._result = result;
if (other != this) {
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(other->_composition_cache.get_size() == 0);
((TransformState *)other)->_composition_cache[this]._result = NULL;
}
if (result != (TransformState *)this) {
// If the result of do_compose() is something other than this, explicitly
// increment the reference count. We have to be sure to decrement it
// again later, when the composition entry is removed from the cache.
result->cache_ref();
// (If the result was just this again, we still store the result, but we
// don't increment the reference count, since that would be a self-
// referential leak.)
}
_cache_stats.maybe_report("TransformState");
return result;
}
/**
* Stores the result of a composition in the cache. Returns the stored result
* (it may be a different object than the one passed in, due to another thread
* having computed the composition first).
*/
CPT(TransformState) TransformState::
store_invert_compose(const TransformState *other, const TransformState *result) {
// Identity should have already been screened.
nassertr(!is_identity(), other);
// So should have validity.
nassertr(!is_invalid(), this);
nassertr(!other->is_invalid(), other);
nassertr(other != this, make_identity());
LightReMutexHolder holder(*_states_lock);
// Is this composition already cached?
int index = _invert_composition_cache.find(other);
if (index != -1) {
Composition &comp = ((TransformState *)this)->_invert_composition_cache.modify_data(index);
if (comp._result == (const TransformState *)NULL) {
// Well, it wasn't cached already, but we already had an entry (probably
// created for the reverse direction), so use the same entry to store
// the new result.
comp._result = result;
if (result != (const TransformState *)this) {
// See the comments below about the need to up the reference count
// only when the result is not the same as this.
result->cache_ref();
}
}
// Here's the cache!
_cache_stats.inc_hits();
return comp._result;
}
_cache_stats.inc_misses();
// We need to make a new cache entry, both in this object and in the other
// object. We make both records so the other TransformState object will
// know to delete the entry from this object when it destructs, and vice-
// versa.
// The cache entry in this object is the only one that indicates the result;
// the other will be NULL for now.
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(_invert_composition_cache.get_size() == 0);
_invert_composition_cache[other]._result = result;
if (other != this) {
_cache_stats.add_total_size(1);
_cache_stats.inc_adds(other->_invert_composition_cache.get_size() == 0);
((TransformState *)other)->_invert_composition_cache[this]._result = NULL;
}
if (result != (TransformState *)this) {
// If the result of compose() is something other than this, explicitly
// increment the reference count. We have to be sure to decrement it
// again later, when the composition entry is removed from the cache.
result->cache_ref();
// (If the result was just this again, we still store the result, but we
// don't increment the reference count, since that would be a self-
// referential leak.)
}
return result;
}
/** /**
* The private implemention of invert_compose(). * The private implemention of invert_compose().
*/ */

View File

@ -234,9 +234,7 @@ private:
static CPT(TransformState) return_unique(TransformState *state); static CPT(TransformState) return_unique(TransformState *state);
CPT(TransformState) do_compose(const TransformState *other) const; CPT(TransformState) do_compose(const TransformState *other) const;
CPT(TransformState) store_compose(const TransformState *other, const TransformState *result);
CPT(TransformState) do_invert_compose(const TransformState *other) const; CPT(TransformState) do_invert_compose(const TransformState *other) const;
CPT(TransformState) store_invert_compose(const TransformState *other, const TransformState *result);
void detect_and_break_cycles(); void detect_and_break_cycles();
static bool r_detect_cycles(const TransformState *start_state, static bool r_detect_cycles(const TransformState *start_state,
const TransformState *current_state, const TransformState *current_state,
@ -288,8 +286,8 @@ private:
}; };
typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache; typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache;
CompositionCache _composition_cache; mutable CompositionCache _composition_cache;
CompositionCache _invert_composition_cache; mutable CompositionCache _invert_composition_cache;
// This is used to mark nodes as we visit them to detect cycles. // This is used to mark nodes as we visit them to detect cycles.
UpdateSeq _cycle_detect; UpdateSeq _cycle_detect;
@ -297,7 +295,7 @@ private:
// This keeps track of our current position through the garbage collection // This keeps track of our current position through the garbage collection
// cycle. // cycle.
static int _garbage_index; static size_t _garbage_index;
static bool _uniquify_matrix; static bool _uniquify_matrix;
@ -408,6 +406,12 @@ private:
friend class Extension<TransformState>; friend class Extension<TransformState>;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<TransformState>::update_type(To *ptr) {}
#endif
INLINE ostream &operator << (ostream &out, const TransformState &state) { INLINE ostream &operator << (ostream &out, const TransformState &state) {
state.output(out); state.output(out);
return out; return out;

View File

@ -33,7 +33,7 @@ protected:
public: public:
virtual PandaNode *make_copy() const; virtual PandaNode *make_copy() const;
virtual void write(ostream &out, int indent_level) const; virtual void write(ostream &out, int indent_level) const;
virtual bool is_ambient_light() const; virtual bool is_ambient_light() const FINAL;
PUBLISHED: PUBLISHED:
virtual int get_class_priority() const; virtual int get_class_priority() const;

View File

@ -93,7 +93,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
consider_verify_lods(trav, data); consider_verify_lods(trav, data);
Camera *camera = trav->get_scene()->get_camera_node(); Camera *camera = trav->get_scene()->get_camera_node();
NodePath this_np = data._node_path.get_node_path(); NodePath this_np = data.get_node_path();
FadeLODNodeData *ldata = FadeLODNodeData *ldata =
DCAST(FadeLODNodeData, camera->get_aux_scene_data(this_np)); DCAST(FadeLODNodeData, camera->get_aux_scene_data(this_np));

View File

@ -15,7 +15,7 @@
* Returns whether this light is configured to cast shadows or not. * Returns whether this light is configured to cast shadows or not.
*/ */
INLINE bool LightLensNode:: INLINE bool LightLensNode::
is_shadow_caster() { is_shadow_caster() const {
return _shadow_caster; return _shadow_caster;
} }

View File

@ -34,7 +34,7 @@ PUBLISHED:
LightLensNode(const string &name, Lens *lens = new PerspectiveLens()); LightLensNode(const string &name, Lens *lens = new PerspectiveLens());
virtual ~LightLensNode(); virtual ~LightLensNode();
INLINE bool is_shadow_caster(); INLINE bool is_shadow_caster() const;
INLINE void set_shadow_caster(bool caster); INLINE void set_shadow_caster(bool caster);
INLINE void set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int sort = -10); INLINE void set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int sort = -10);

View File

@ -330,7 +330,7 @@ compute_child(CullTraverser *trav, CullTraverserData &data) {
* trav->get_scene()->get_camera_node()->get_lod_scale())) { * trav->get_scene()->get_camera_node()->get_lod_scale())) {
if (pgraph_cat.is_debug()) { if (pgraph_cat.is_debug()) {
pgraph_cat.debug() pgraph_cat.debug()
<< data._node_path << " at distance " << sqrt(dist2) << data.get_node_path() << " at distance " << sqrt(dist2)
<< ", selected child " << index << "\n"; << ", selected child " << index << "\n";
} }
@ -340,7 +340,7 @@ compute_child(CullTraverser *trav, CullTraverserData &data) {
if (pgraph_cat.is_debug()) { if (pgraph_cat.is_debug()) {
pgraph_cat.debug() pgraph_cat.debug()
<< data._node_path << " at distance " << sqrt(dist2) << data.get_node_path() << " at distance " << sqrt(dist2)
<< ", no children in range.\n"; << ", no children in range.\n";
} }
@ -393,20 +393,14 @@ show_switches_cull_callback(CullTraverser *trav, CullTraverserData &data) {
// And draw the spindle in this color. // And draw the spindle in this color.
CullTraverserData next_data2(data, sw.get_spindle_viz()); CullTraverserData next_data2(data, sw.get_spindle_viz());
next_data2.apply_transform_and_state(trav, viz_transform, next_data2.apply_transform(viz_transform);
RenderState::make_empty(),
RenderEffects::make_empty(),
ClipPlaneAttrib::make());
trav->traverse(next_data2); trav->traverse(next_data2);
} }
// Draw the rings for this switch level. We do this after we have drawn // Draw the rings for this switch level. We do this after we have drawn
// the geometry and the spindle. // the geometry and the spindle.
CullTraverserData next_data(data, sw.get_ring_viz()); CullTraverserData next_data(data, sw.get_ring_viz());
next_data.apply_transform_and_state(trav, viz_transform, next_data.apply_transform(viz_transform);
RenderState::make_empty(),
RenderEffects::make_empty(),
ClipPlaneAttrib::make());
trav->traverse(next_data); trav->traverse(next_data);
} }
} }
@ -650,7 +644,7 @@ do_auto_verify_lods(CullTraverser *trav, CullTraverserData &data) {
const Switch &sw = cdata->_switch_vector[index]; const Switch &sw = cdata->_switch_vector[index];
ostringstream strm; ostringstream strm;
strm strm
<< "Level " << index << " geometry of " << data._node_path << "Level " << index << " geometry of " << data.get_node_path()
<< " is larger than its switch radius; suggest radius of " << " is larger than its switch radius; suggest radius of "
<< suggested_radius << " instead of " << sw.get_in() << suggested_radius << " instead of " << sw.get_in()
<< " (configure verify-lods 0 to ignore this error)"; << " (configure verify-lods 0 to ignore this error)";

View File

@ -41,7 +41,7 @@ void NodeCullCallbackData::
upcall() { upcall() {
PandaNode *node = _data.node(); PandaNode *node = _data.node();
if (node->is_of_type(CallbackNode::get_class_type())) { if (node->is_of_type(CallbackNode::get_class_type())) {
CallbackNode *cbnode = DCAST(CallbackNode, _data.node()); CallbackNode *cbnode = (CallbackNode *)node;
// OK, render this node. Rendering a CallbackNode means creating a // OK, render this node. Rendering a CallbackNode means creating a
// CullableObject for the draw_callback, if any. We don't need to pass // CullableObject for the draw_callback, if any. We don't need to pass

View File

@ -284,7 +284,7 @@ analyze_renderstate(const RenderState *rs) {
PandaNode *light_obj = light.node(); PandaNode *light_obj = light.node();
nassertv(light_obj != (PandaNode *)NULL); nassertv(light_obj != (PandaNode *)NULL);
if (light_obj->get_type() == AmbientLight::get_class_type()) { if (light_obj->is_ambient_light()) {
if (_material->has_ambient()) { if (_material->has_ambient()) {
LColor a = _material->get_ambient(); LColor a = _material->get_ambient();
if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) { if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
@ -298,7 +298,7 @@ analyze_renderstate(const RenderState *rs) {
} else if (light_obj->is_of_type(LightLensNode::get_class_type())) { } else if (light_obj->is_of_type(LightLensNode::get_class_type())) {
_lights_np.push_back(light); _lights_np.push_back(light);
_lights.push_back((LightLensNode *)light_obj); _lights.push_back((LightLensNode *)light_obj);
if (DCAST(LightLensNode, light_obj)->is_shadow_caster()) { if (((const LightLensNode *)light_obj)->is_shadow_caster()) {
_shadows = true; _shadows = true;
} }
_lighting = true; _lighting = true;

View File

@ -231,6 +231,8 @@ read_stage_unlocked(int pipeline_stage) const {
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER); TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER);
#ifdef _DEBUG #ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL); nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif #endif
return _data[pipeline_stage]._cdata; return _data[pipeline_stage]._cdata;
} }
@ -248,6 +250,8 @@ read_stage(int pipeline_stage, Thread *current_thread) const {
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER); TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER);
#ifdef _DEBUG #ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL); nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif #endif
_lock.acquire(current_thread); _lock.acquire(current_thread);
return _data[pipeline_stage]._cdata; return _data[pipeline_stage]._cdata;
@ -278,6 +282,8 @@ elevate_read_stage(int pipeline_stage, const CycleData *pointer,
#ifdef _DEBUG #ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL); nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
nassertr(_data[pipeline_stage]._cdata == pointer, NULL); nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif #endif
CycleData *new_pointer = write_stage(pipeline_stage, current_thread); CycleData *new_pointer = write_stage(pipeline_stage, current_thread);
_lock.release(); _lock.release();
@ -296,6 +302,8 @@ elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
#ifdef _DEBUG #ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL); nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
nassertr(_data[pipeline_stage]._cdata == pointer, NULL); nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif #endif
CycleData *new_pointer = CycleData *new_pointer =
write_stage_upstream(pipeline_stage, force_to_0, current_thread); write_stage_upstream(pipeline_stage, force_to_0, current_thread);
@ -313,6 +321,8 @@ release_write_stage(int pipeline_stage, CycleData *pointer) {
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages); nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
nassertv(_data[pipeline_stage]._cdata == pointer); nassertv(_data[pipeline_stage]._cdata == pointer);
nassertv(_data[pipeline_stage]._writes_outstanding > 0); nassertv(_data[pipeline_stage]._writes_outstanding > 0);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif #endif
--(_data[pipeline_stage]._writes_outstanding); --(_data[pipeline_stage]._writes_outstanding);
_lock.release(); _lock.release();

View File

@ -78,7 +78,7 @@ get_pipeline_stage() const {
// However, since we guarantee that this is never less than zero, clang // However, since we guarantee that this is never less than zero, clang
// offers a nice way to avoid that. // offers a nice way to avoid that.
int pipeline_stage = _pipeline_stage; int pipeline_stage = _pipeline_stage;
__builtin_assume(_pipeline_stage >= 0); __builtin_assume(pipeline_stage >= 0);
return pipeline_stage; return pipeline_stage;
#else #else
return _pipeline_stage; return _pipeline_stage;

View File

@ -161,6 +161,12 @@ private:
static TypeHandle _type_handle; static TypeHandle _type_handle;
}; };
#ifdef DO_MEMORY_USAGE
// We can safely redefine this as a no-op.
template<>
INLINE void PointerToBase<CopyOnWriteObject>::update_type(To *ptr) {}
#endif
#include "copyOnWriteObject.I" #include "copyOnWriteObject.I"
#endif #endif

View File

@ -235,8 +235,8 @@ get_size() const {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE bool SimpleHashMap<Key, Value, Compare>:: INLINE bool SimpleHashMap<Key, Value, Compare>::
has_element(int n) const { has_element(size_t n) const {
nassertr(n >= 0 && n < (int)_table_size, false); nassertr(n < _table_size, false);
return (get_exists_array()[n] != 0); return (get_exists_array()[n] != 0);
} }
@ -249,7 +249,7 @@ has_element(int n) const {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE const Key &SimpleHashMap<Key, Value, Compare>:: INLINE const Key &SimpleHashMap<Key, Value, Compare>::
get_key(int n) const { get_key(size_t n) const {
nassertr(has_element(n), _table[n]._key); nassertr(has_element(n), _table[n]._key);
return _table[n]._key; return _table[n]._key;
} }
@ -263,7 +263,7 @@ get_key(int n) const {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE const Value &SimpleHashMap<Key, Value, Compare>:: INLINE const Value &SimpleHashMap<Key, Value, Compare>::
get_data(int n) const { get_data(size_t n) const {
nassertr(has_element(n), _table[n]._data); nassertr(has_element(n), _table[n]._data);
return _table[n]._data; return _table[n]._data;
} }
@ -277,7 +277,7 @@ get_data(int n) const {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE Value &SimpleHashMap<Key, Value, Compare>:: INLINE Value &SimpleHashMap<Key, Value, Compare>::
modify_data(int n) { modify_data(size_t n) {
nassertr(has_element(n), _table[n]._data); nassertr(has_element(n), _table[n]._data);
return _table[n]._data; return _table[n]._data;
} }
@ -291,7 +291,7 @@ modify_data(int n) {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE void SimpleHashMap<Key, Value, Compare>:: INLINE void SimpleHashMap<Key, Value, Compare>::
set_data(int n, const Value &data) { set_data(size_t n, const Value &data) {
nassertv(has_element(n)); nassertv(has_element(n));
_table[n]._data = data; _table[n]._data = data;
} }
@ -305,7 +305,7 @@ set_data(int n, const Value &data) {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
void SimpleHashMap<Key, Value, Compare>:: void SimpleHashMap<Key, Value, Compare>::
remove_element(int n) { remove_element(size_t n) {
nassertv(has_element(n)); nassertv(has_element(n));
clear_element(n); clear_element(n);
@ -314,7 +314,7 @@ remove_element(int n) {
// Now we have put a hole in the table. If there was a hash conflict in the // Now we have put a hole in the table. If there was a hash conflict in the
// slot following this one, we have to move it down to close the hole. // slot following this one, we have to move it down to close the hole.
size_t i = (size_t)n; size_t i = n;
i = (i + 1) & (_table_size - 1); i = (i + 1) & (_table_size - 1);
while (has_element(i)) { while (has_element(i)) {
size_t wants_index = get_hash(_table[i]._key); size_t wants_index = get_hash(_table[i]._key);
@ -403,12 +403,14 @@ bool SimpleHashMap<Key, Value, Compare>::
validate() const { validate() const {
size_t count = 0; size_t count = 0;
const unsigned char *exists_array = get_exists_array();
for (size_t i = 0; i < _table_size; ++i) { for (size_t i = 0; i < _table_size; ++i) {
if (has_element(i)) { if (exists_array[i] != 0) {
++count; ++count;
size_t ideal_index = get_hash(_table[i]._key); size_t ideal_index = get_hash(_table[i]._key);
size_t wants_index = ideal_index; size_t wants_index = ideal_index;
while (wants_index != i && has_element(wants_index)) { while (wants_index != i && exists_array[wants_index] != 0) {
wants_index = (wants_index + 1) & (_table_size - 1); wants_index = (wants_index + 1) & (_table_size - 1);
} }
if (wants_index != i) { if (wants_index != i) {
@ -455,7 +457,7 @@ get_hash(const Key &key) const {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE bool SimpleHashMap<Key, Value, Compare>:: INLINE bool SimpleHashMap<Key, Value, Compare>::
is_element(int n, const Key &key) const { is_element(size_t n, const Key &key) const {
nassertr(has_element(n), false); nassertr(has_element(n), false);
return _comp.is_equal(_table[n]._key, key); return _comp.is_equal(_table[n]._key, key);
} }
@ -466,7 +468,7 @@ is_element(int n, const Key &key) const {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE void SimpleHashMap<Key, Value, Compare>:: INLINE void SimpleHashMap<Key, Value, Compare>::
store_new_element(int n, const Key &key, const Value &data) { store_new_element(size_t n, const Key &key, const Value &data) {
new(&_table[n]) TableEntry(key, data); new(&_table[n]) TableEntry(key, data);
get_exists_array()[n] = true; get_exists_array()[n] = true;
} }
@ -476,7 +478,7 @@ store_new_element(int n, const Key &key, const Value &data) {
*/ */
template<class Key, class Value, class Compare> template<class Key, class Value, class Compare>
INLINE void SimpleHashMap<Key, Value, Compare>:: INLINE void SimpleHashMap<Key, Value, Compare>::
clear_element(int n) { clear_element(size_t n) {
_table[n].~TableEntry(); _table[n].~TableEntry();
get_exists_array()[n] = false; get_exists_array()[n] = false;
} }

View File

@ -42,12 +42,12 @@ public:
INLINE Value &operator [] (const Key &key); INLINE Value &operator [] (const Key &key);
INLINE size_t get_size() const; INLINE size_t get_size() const;
INLINE bool has_element(int n) const; INLINE bool has_element(size_t n) const;
INLINE const Key &get_key(int n) const; INLINE const Key &get_key(size_t n) const;
INLINE const Value &get_data(int n) const; INLINE const Value &get_data(size_t n) const;
INLINE Value &modify_data(int n); INLINE Value &modify_data(size_t n);
INLINE void set_data(int n, const Value &data); INLINE void set_data(size_t n, const Value &data);
void remove_element(int n); void remove_element(size_t n);
INLINE size_t get_num_entries() const; INLINE size_t get_num_entries() const;
INLINE bool is_empty() const; INLINE bool is_empty() const;
@ -61,9 +61,9 @@ private:
INLINE size_t get_hash(const Key &key) const; INLINE size_t get_hash(const Key &key) const;
INLINE bool is_element(int n, const Key &key) const; INLINE bool is_element(size_t n, const Key &key) const;
INLINE void store_new_element(int n, const Key &key, const Value &data); INLINE void store_new_element(size_t n, const Key &key, const Value &data);
INLINE void clear_element(int n); INLINE void clear_element(size_t n);
INLINE unsigned char *get_exists_array() const; INLINE unsigned char *get_exists_array() const;
void new_table(); void new_table();

View File

@ -61,6 +61,11 @@ private:
static TypeHandle _type_handle; static TypeHandle _type_handle;
}; };
#ifdef DO_MEMORY_USAGE
template<>
INLINE void PointerToBase<TypedWritableReferenceCount>::update_type(To *ptr) {}
#endif
#include "typedWritableReferenceCount.I" #include "typedWritableReferenceCount.I"
#endif #endif

Some files were not shown because too many files have changed in this diff Show More