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

View File

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

View File

@ -12,3 +12,12 @@
*/
#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);
INLINE void operator = (bool value);
INLINE operator bool () const;
ALWAYS_INLINE operator bool () const;
INLINE size_t size() const;
INLINE bool operator [] (size_t n) const;
INLINE void set_value(bool value);
INLINE bool get_value() const;
ALWAYS_INLINE bool get_value() const;
INLINE bool get_default_value() const;
MAKE_PROPERTY(value, get_value, set_value);
MAKE_PROPERTY(default_value, get_default_value);
@ -44,8 +44,10 @@ PUBLISHED:
INLINE void set_word(size_t n, bool value);
private:
AtomicAdjust::Integer _local_modified;
bool _cache;
void reload_value() const;
mutable AtomicAdjust::Integer _local_modified;
mutable bool _cache;
};
#include "configVariableBool.I"

View File

@ -70,7 +70,12 @@ is_on(NotifySeverity severity) const {
*/
INLINE bool NotifyCategory::
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);
#endif
}
/**
@ -78,7 +83,12 @@ is_spam() const {
*/
INLINE bool NotifyCategory::
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);
#endif
}
#else
/**

View File

@ -69,7 +69,12 @@ is_on(NotifySeverity severity) {
template<class GetCategory>
INLINE bool NotifyCategoryProxy<GetCategory>::
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();
#endif
}
#else
template<class GetCategory>
@ -86,7 +91,12 @@ is_spam() {
template<class GetCategory>
INLINE bool NotifyCategoryProxy<GetCategory>::
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();
#endif
}
#else
template<class GetCategory>

View File

@ -122,6 +122,13 @@ private:
// constant expressions and compilation will fail if the assertion is not
// 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
#define nassertr(condition, return_value)
@ -131,14 +138,14 @@ private:
#define nassertr_always(condition, return_value) \
{ \
if (!(condition)) { \
if (_nassert_check(condition)) { \
return return_value; \
} \
}
#define nassertv_always(condition) \
{ \
if (!(condition)) { \
if (_nassert_check(condition)) { \
return; \
} \
}
@ -151,7 +158,7 @@ private:
#define nassertr(condition, return_value) \
{ \
if (!(condition)) { \
if (_nassert_check(condition)) { \
if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \
return return_value; \
} \
@ -160,7 +167,7 @@ private:
#define nassertv(condition) \
{ \
if (!(condition)) { \
if (_nassert_check(condition)) { \
if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \
return; \
} \
@ -168,7 +175,7 @@ private:
}
#define nassertd(condition) \
if (!(condition) && \
if (_nassert_check(condition) && \
Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__))
#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 enter_debugger_if(condition) \
if (condition) { \
if (_nassert_check(condition)) { \
Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__); \
__asm { int 3 } \
}

View File

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

View File

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

View File

@ -111,10 +111,12 @@ any_in_bounds() {
}
#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())) {
const GeometricBoundingVolume *node_gbv;
DCAST_INTO_R(node_gbv, node_bv, false);
const GeometricBoundingVolume *node_gbv = (const GeometricBoundingVolume *)node_bv.p();
CollideMask this_mask = pnode->get_net_collide_mask();
int num_colliders = get_num_colliders();
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
// collide bits in common between our collider and this node.
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
// descendants.
if (node() == cnode) {
if (pnode == cnode) {
#ifndef NDEBUG
if (collide_cat.is_spam()) {
indent(collide_cat.spam(false), indent_level)

View File

@ -51,7 +51,7 @@ public:
INLINE CollisionLevelStateBase(const NodePath &node_path);
INLINE CollisionLevelStateBase(const CollisionLevelStateBase &parent,
PandaNode *child);
PandaNode *child);
INLINE CollisionLevelStateBase(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) {
// Determine the previous frame's position, relative to the current
// 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());
if (!transform->is_identity()) {

View File

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

View File

@ -57,7 +57,7 @@ public:
inline bool operator () (int a, int b) const {
const CollisionTraverser::OrderedColliderDef &ocd_a = _trav._ordered_colliders[a];
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;
@ -1117,31 +1117,45 @@ compare_collider_to_node(CollisionEntry &entry,
}
if (within_node_bounds) {
Thread *current_thread = Thread::get_current_thread();
CollisionNode *cnode;
DCAST_INTO_V(cnode, entry._into_node);
int num_solids = cnode->get_num_solids();
collide_cat.spam()
<< "Colliding against CollisionNode " << entry._into_node
<< " which has " << num_solids << " collision solids.\n";
for (int s = 0; s < num_solids; ++s) {
entry._into = cnode->get_solid(s);
if (collide_cat.is_spam()) {
collide_cat.spam()
<< "Colliding against CollisionNode " << entry._into_node
<< " which has " << num_solids << " collision solids.\n";
}
// 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 = NULL;
if (num_solids > 1 &&
solid_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
// Only bother to test against each solid's bounding volume if we have
// more than one solid in the node, as a slight optimization. (If the
// node contains just one solid, then the node's bounding volume,
// which we just tested, is the same as the solid's bounding volume.)
DCAST_INTO_V(solid_gbv, solid_bv);
// Only bother to test against each solid's bounding volume if we have
// more than one solid in the node, as a slight optimization. (If the
// node contains just one solid, then the node's bounding volume, which
// we just tested, is the same as the solid's bounding volume.)
if (num_solids == 1) {
entry._into = cnode->_solids[0].get_read_pointer(current_thread);
Colliders::const_iterator ci;
ci = _colliders.find(entry.get_from_node_path());
nassertv(ci != _colliders.end());
entry.test_intersection((*ci).second, this);
} else {
CollisionNode::Solids::const_iterator si;
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.
xform_data._net_transform = TransformState::make_identity();
xform_data._view_frustum = trav->get_view_frustum();
xform_data.apply_transform_and_state(trav, net_transform,
RenderState::make_empty(),
RenderEffects::make_empty(),
ClipPlaneAttrib::make());
xform_data.apply_transform(net_transform);
// Draw all the collision solids.
Solids::const_iterator si;

View File

@ -903,16 +903,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_identity: {
return &LMatrix4::ident_mat();
}
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_window_size:
case Shader::SMO_pixel_size: {
t = LMatrix4::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0);
LVecBase2i pixel_size = _current_display_region->get_pixel_size();
t = LMatrix4::translate_mat(pixel_size[0], pixel_size[1], 0);
return &t;
}
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 &s = lt->get_specular_color();
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()));
d.normalize();
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 &s = lt->get_specular_color();
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 a = lt->get_attenuation();
PN_stdfloat lnear = lt->get_lens(0)->get_near();
PN_stdfloat lfar = lt->get_lens(0)->get_far();
Lens *lens = lt->get_lens(0);
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);
return &t;
}
@ -1086,7 +1081,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
LColor const &s = lt->get_specular_color();
PN_stdfloat cutoff = ccos(deg_2_rad(lens->get_hfov() * 0.5f));
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 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);
@ -1109,7 +1104,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
Light *light_obj = light.node()->as_light();
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();
}
}
@ -1155,27 +1150,31 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_plane_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat());
LPlane p = DCAST(PlaneNode, np.node())->get_plane();
const PlaneNode *plane_node;
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]);
return &t;
}
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());
if (planenr >= cpa->get_num_on_planes()) {
return &LMatrix4::zeros_mat();
}
const NodePath &np = cpa->get_on_plane(planenr);
nassertr(!np.is_empty(), &LMatrix4::zeros_mat());
nassertr(np.node()->is_of_type(PlaneNode::get_class_type()), &LMatrix4::zeros_mat());
LPlane p (DCAST(PlaneNode, np.node())->get_plane());
const PlaneNode *plane_node;
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
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
return &t;
}
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()) {
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());
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()));
LPlane xformed_plane = plane_node->get_plane() * transform->get_mat();
@ -1206,24 +1205,24 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
return &t;
}
case Shader::SMO_world_to_view: {
return &(get_scene()->get_world_transform()->get_mat());
return &(_scene_setup->get_world_transform()->get_mat());
break;
}
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: {
return &(get_external_transform()->get_mat());
return &(_inv_cs_transform->compose(_internal_transform)->get_mat());
}
case Shader::SMO_model_to_apiview: {
return &(get_internal_transform()->get_mat());
return &(_internal_transform->get_mat());
}
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;
}
case Shader::SMO_apiview_to_model: {
t = get_internal_transform()->get_inverse()->get_mat();
t = _internal_transform->get_inverse()->get_mat();
return &t;
}
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);
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
t = np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
_scene_setup->get_world_transform()->get_mat();
return &t;
}
case Shader::SMO_view_to_view_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
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();
return &t;
}
@ -1283,13 +1282,13 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
_scene_setup->get_world_transform()->get_mat();
return &t;
}
case Shader::SMO_view_to_apiview_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
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() *
LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
return &t;
@ -1297,20 +1296,22 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
case Shader::SMO_clip_x_to_view: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
Lens *lens = DCAST(LensNode, np.node())->get_lens();
const LensNode *node;
DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
const Lens *lens = node->get_lens();
t = lens->get_projection_mat_inv(_current_stereo_channel) *
LMatrix4::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
_scene_setup->get_world_transform()->get_mat();
return &t;
}
case Shader::SMO_view_to_clip_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
Lens *lens = DCAST(LensNode, np.node())->get_lens();
t = get_scene()->get_camera_transform()->get_mat() *
const LensNode *node;
DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
const Lens *lens = node->get_lens();
t = _scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() *
LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
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: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
Lens *lens = DCAST(LensNode, np.node())->get_lens();
const LensNode *node;
DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
const Lens *lens = node->get_lens();
t = calc_projection_mat(lens)->get_inverse()->get_mat() *
get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() *
np.get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
_scene_setup->get_world_transform()->get_mat();
return &t;
}
case Shader::SMO_view_to_apiclip_x: {
const NodePath &np = _target_shader->get_shader_input_nodepath(name);
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
Lens *lens = DCAST(LensNode, np.node())->get_lens();
t = get_scene()->get_camera_transform()->get_mat() *
const LensNode *node;
DCAST_INTO_R(node, np.node(), &LMatrix4::ident_mat());
const Lens *lens = node->get_lens();
t = _scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() *
get_cs_transform_for(lens->get_coordinate_system())->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();
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) {
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_linearAttenuation("linearAttenuation");
static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
static const CPT_InternalName IN_shadowMatrix("shadowMatrix");
static const CPT_InternalName IN_shadowViewMatrix("shadowViewMatrix");
PandaNode *node = NULL;
if (!np.is_empty()) {
@ -1454,7 +1457,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
}
Light *light = node->as_light();
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();
c.componentwise_mult(_light_color_scale);
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();
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.
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
} else {
@ -1493,7 +1496,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
if (np.is_empty()) {
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
return &t;
} else if (node->is_of_type(AmbientLight::get_class_type())) {
} else if (node->is_ambient_light()) {
// Ambient light has no position.
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
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());
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);
return &t;
} else {
@ -1513,7 +1516,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
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()));
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()) {
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
return &t;
} else if (node->is_of_type(AmbientLight::get_class_type())) {
} else if (node->is_ambient_light()) {
// Ambient light has no half-vector.
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
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());
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 += LVector3(0, 0, 1);
dir.normalize();
@ -1549,7 +1552,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
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()));
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) {
t.set_row(3, LVector3(0.0f, 0.0f, -1.0f));
return &t;
} else if (node->is_of_type(AmbientLight::get_class_type())) {
} else if (node->is_ambient_light()) {
// Ambient light has no spot direction.
t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
return &t;
@ -1576,7 +1579,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
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()));
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]));
return &t;
} else if (attrib == IN_shadowMatrix) {
} else if (attrib == IN_shadowViewMatrix) {
static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 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());
Lens *lens = lnode->get_lens();
t = get_external_transform()->get_mat() *
get_scene()->get_camera_transform()->get_mat() *
t = _inv_cs_transform->get_mat() *
_scene_setup->get_camera_transform()->get_mat() *
np.get_net_transform()->get_inverse()->get_mat() *
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();
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) {
PT(Texture) tex = get_shadow_map(light);
if (tex != (Texture *)NULL) {
@ -2663,7 +2666,7 @@ do_issue_light() {
_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 contribution to the current total
cur_ambient_light += light_obj->get_color();
@ -3143,11 +3146,12 @@ async_reload_texture(TextureContext *tc) {
*/
PT(Texture) GraphicsStateGuardian::
get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
light_np.node()->is_of_type(PointLight::get_class_type()) ||
light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
PandaNode *node = light_np.node();
nassertr(node->is_of_type(DirectionalLight::get_class_type()) ||
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) {
// TODO: return dummy shadow map (all white).
return NULL;
@ -3177,11 +3181,12 @@ get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
PT(Texture) GraphicsStateGuardian::
make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
// Make sure everything is valid.
nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
light_np.node()->is_of_type(PointLight::get_class_type()) ||
light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
PandaNode *node = light_np.node();
nassertr(node->is_of_type(DirectionalLight::get_class_type()) ||
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) {
return NULL;
}

View File

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

View File

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

View File

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

View File

@ -489,6 +489,16 @@ MemoryUsage(const MemoryHook &copy) : MemoryHook(copy) {
_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
* exceeds _max_heap_size. It's mainly intended for reporting memory leaks,

View File

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

View File

@ -21,9 +21,7 @@ PointerToBase(To *ptr) {
if (ptr != (To *)NULL) {
ptr->ref();
#ifdef DO_MEMORY_USAGE
if (MemoryUsage::get_track_memory_usage()) {
update_type(ptr);
}
update_type(ptr);
#endif
}
}
@ -38,11 +36,6 @@ PointerToBase(const PointerToBase<T> &copy) {
if (_void_ptr != NULL) {
To *ptr = (To *)_void_ptr;
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;
_void_ptr = (void *)ptr;
if (ptr != (To *)NULL) {
if (ptr != nullptr) {
ptr->ref();
#ifdef DO_MEMORY_USAGE
if (MemoryUsage::get_track_memory_usage()) {
update_type(ptr);
}
update_type(ptr);
#endif
}
// Now delete the old pointer.
if (old_ptr != (To *)NULL) {
if (old_ptr != nullptr) {
unref_delete(old_ptr);
}
}
@ -130,7 +121,24 @@ reassign(To *ptr) {
template<class T>
INLINE void PointerToBase<T>::
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
@ -139,15 +147,17 @@ reassign(const PointerToBase<To> &copy) {
* object, if we know the type ourselves.
*/
template<class T>
void PointerToBase<T>::
INLINE void PointerToBase<T>::
update_type(To *ptr) {
TypeHandle type = get_type_handle(To);
if (type == TypeHandle::none()) {
do_init_type(To);
type = get_type_handle(To);
}
if (type != TypeHandle::none()) {
MemoryUsage::update_type(ptr, type);
if (MemoryUsage::get_track_memory_usage()) {
TypeHandle type = get_type_handle(To);
if (type == TypeHandle::none()) {
do_init_type(To);
type = get_type_handle(To);
}
if (type != TypeHandle::none()) {
MemoryUsage::update_type(ptr, type);
}
}
}
#endif // DO_MEMORY_USAGE

View File

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

View File

@ -399,6 +399,7 @@ unbind() {
void CLP(CgShaderContext)::
set_state_and_transform(const RenderState *target_rs,
const TransformState *modelview_transform,
const TransformState *camera_transform,
const TransformState *projection_transform) {
if (!valid()) {
@ -410,6 +411,10 @@ set_state_and_transform(const RenderState *target_rs,
if (_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;
}
if (_projection_transform != projection_transform) {

View File

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

View File

@ -874,7 +874,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
matrix_name.substr(0, 12) == "LightSource[" &&
sscanf(matrix_name.c_str(), "LightSource[%d].%s", &bind._index, name_buffer) == 2) {
// A matrix member of a p3d_LightSource struct.
if (strncmp(name_buffer, "shadowMatrix", 127) == 0) {
if (strncmp(name_buffer, "shadowViewMatrix", 127) == 0) {
if (inverse) {
// Tack inverse back onto the end.
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._arg[0] = InternalName::make(name_buffer);
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 {
GLCAT.error() << "p3d_LightSource struct does not provide a matrix named " << matrix_name << "!\n";
return;
@ -1163,11 +1181,16 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._index = index;
bind._part[0] = Shader::SMO_light_source_i_attrib;
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._arg[1] = NULL;
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) {
case GL_FLOAT:
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._part[0] = Shader::SMO_world_to_view;
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;
_shader->_mat_spec.push_back(bind);
_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[1] = Shader::SMO_view_to_world;
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_deps |= bind._dep[0] | bind._dep[1];
return;
@ -1383,22 +1406,43 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._id = arg_id;
bind._piece = Shader::SMP_whole;
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);
if (iname->get_parent() != InternalName::get_root()) {
// It might be something like an attribute of a shader input, like a
// light parameter. It might also just be a custom struct
// parameter. We can't know yet, sadly.
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_transform;
if (iname->get_basename() == "shadowMatrix") {
// Special exception for shadowMatrix, which is deprecated,
// 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 {
bind._part[0] = Shader::SMO_mat_constant_x;
bind._arg[0] = InternalName::make(param_name);
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_deps |= bind._dep[0];
return;
@ -1430,9 +1474,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_vec_constant_x_attrib;
bind._arg[0] = iname;
// We need SSD_transform since some attributes (eg. light position)
// have to be transformed to view space.
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_transform;
// We need SSD_view_transform since some attributes (eg. light
// position) have to be transformed to view space.
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_view_transform;
bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL;
bind._dep[1] = Shader::SSD_NONE;
@ -1822,6 +1866,7 @@ unbind() {
void CLP(ShaderContext)::
set_state_and_transform(const RenderState *target_rs,
const TransformState *modelview_transform,
const TransformState *camera_transform,
const TransformState *projection_transform) {
// Find out which state properties have changed.
@ -1829,6 +1874,10 @@ set_state_and_transform(const RenderState *target_rs,
if (_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;
}
if (_projection_transform != projection_transform) {
@ -2440,17 +2489,17 @@ update_shader_texture_bindings(ShaderContext *prev) {
const ParamTextureImage *param = NULL;
Texture *tex;
const ShaderInput *sinp = _glgsg->_target_shader->get_shader_input(input._name);
switch (sinp->get_value_type()) {
const ShaderInput &sinp = _glgsg->_target_shader->get_shader_input(input._name);
switch (sinp.get_value_type()) {
case ShaderInput::M_texture_image:
param = (const ParamTextureImage *)sinp->get_param();
param = (const ParamTextureImage *)sinp.get_param();
tex = param->get_texture();
break;
case ShaderInput::M_texture:
// People find it convenient to be able to pass a texture without
// further ado.
tex = sinp->get_texture();
tex = sinp.get_texture();
break;
case ShaderInput::M_invalid:

View File

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

View File

@ -114,12 +114,16 @@ update_page(AdaptiveLruPage *page) {
update_frames = (_current_frame_identifier - page->_update_frame_identifier);
if (update_frames > 0) {
PN_stdfloat update_average_frame_utilization =
(PN_stdfloat) (page->_update_total_usage) / (PN_stdfloat)update_frames;
if (page->_update_total_usage > 0) {
PN_stdfloat update_average_frame_utilization =
(PN_stdfloat) (page->_update_total_usage) / (PN_stdfloat)update_frames;
page->_average_frame_utilization =
calculate_exponential_moving_average(update_average_frame_utilization,
page->_average_frame_utilization);
page->_average_frame_utilization =
calculate_exponential_moving_average(update_average_frame_utilization,
page->_average_frame_utilization);
} else {
page->_average_frame_utilization *= 1.0f - _weight;
}
target_priority = page->_priority;
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?
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
// max_indices vertices.
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()) {
PT(GeomPrimitive) smaller = prim->make_copy();
smaller->clear_vertices();
while (i < prim->get_num_primitives() &&
smaller->get_num_vertices() + prim->get_primitive_num_vertices(i) < max_indices) {
int start = prim->get_primitive_start(i);
int end = prim->get_primitive_end(i);
for (int n = start; n < end; ++n) {
smaller->add_vertex(prim->get_vertex(n));
while (i < num_primitives) {
PT(GeomPrimitive) smaller = prim->make_copy();
smaller->clear_vertices();
// Since the number of vertices is consistent, we can calculate how
// many primitives will fit, and copy them all in one go.
int copy_primitives = min((num_primitives - i), max_primitives);
int num_vertices = copy_primitives * total_vertices_per_primitive;
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 {
// The prim has few enough vertices; keep it.
cdata->_primitives.push_back(prim);
@ -925,7 +969,8 @@ bool Geom::
check_valid() const {
Thread *current_thread = Thread::get_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();
return geom_reader.check_valid(&data_reader);
}
@ -1212,6 +1257,9 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
InternalName::get_vertex(),
cdata, current_thread);
nassertv(!pmin.is_nan());
nassertv(!pmax.is_nan());
BoundingVolume::BoundsType btype = cdata->_bounds_type;
if (btype == BoundingVolume::BT_default) {
btype = bounds_type;

View File

@ -124,8 +124,19 @@ get_vertex(int i) const {
*/
INLINE int GeomPrimitive::
get_num_primitives() const {
GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
return reader.get_num_primitives();
int num_vertices_per_primitive = get_num_vertices_per_primitive();
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);
int num_primitives = get_num_primitives();
if (num_primitives > 0 &&
requires_unused_vertices() &&
get_num_vertices() == get_primitive_end(num_primitives - 1)) {
// If we are beginning a new primitive, give the derived class a chance to
// insert some degenerate vertices.
if (cdata->_vertices.is_null()) {
do_make_indexed(cdata);
if (requires_unused_vertices()) {
int num_primitives = get_num_primitives();
if (num_primitives > 0 &&
get_num_vertices() == get_primitive_end(num_primitives - 1)) {
// If we are beginning a new primitive, give the derived class a chance to
// insert some degenerate vertices.
if (cdata->_vertices.is_null()) {
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()) {
@ -199,11 +200,28 @@ add_vertex(int vertex) {
do_make_indexed(cdata);
}
PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
GeomVertexWriter index(array_obj, 0);
index.set_row_unsafe(array_obj->get_num_rows());
{
GeomVertexArrayDataHandle handle(cdata->_vertices.get_write_pointer(),
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->_got_minmax = false;
@ -888,21 +906,9 @@ make_points() const {
// First, get a list of all of the vertices referenced by the original
// primitive.
BitArray bits;
int num_vertices = get_num_vertices();
if (is_indexed()) {
CPT(GeomVertexArrayData) vertices = get_vertices();
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);
{
GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
reader.get_referenced_vertices(bits);
}
// Now construct a new index array with just those bits.
@ -2200,9 +2206,21 @@ get_vertex(int i) const {
// The indexed case.
nassertr(i >= 0 && i < get_num_vertices(), -1);
GeomVertexReader index(_vertices, 0);
index.set_row_unsafe(i);
return index.get_data1i();
const unsigned char *ptr = get_read_pointer(true);
switch (_cdata->_index_type) {
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 {
// 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;
int get_vertex(int i) const;
int get_num_primitives() const;
void get_referenced_vertices(BitArray &bits) const;
INLINE int get_min_vertex() const;
INLINE int get_max_vertex() const;
INLINE int get_data_size_bytes() const;

View File

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

View File

@ -432,7 +432,7 @@ public:
INLINE UpdateSeq get_modified() const;
protected:
PT(GeomVertexData) _object;
GeomVertexData *_object;
Thread *_current_thread;
GeomVertexData::CData *_cdata;
};
@ -440,6 +440,8 @@ protected:
/**
* Encapsulates the data from a GeomVertexData, pre-fetched for one stage of
* 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 {
public:
@ -448,7 +450,7 @@ public:
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 void check_array_readers() const;
@ -504,6 +506,8 @@ private:
/**
* Encapsulates the data from a GeomVertexData, pre-fetched for one stage of
* 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 {
public:

View File

@ -178,6 +178,12 @@ private:
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);
/**

View File

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

View File

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

View File

@ -32,7 +32,10 @@ class EXPCL_PANDA_GOBJ ShaderContext: public SavedContext {
public:
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 void bind() {};

View File

@ -464,42 +464,33 @@ void PipeOcclusionCullTraverser::
make_box() {
PT(GeomVertexData) vdata = new GeomVertexData
("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);
vertex.add_data3(0.0f, 1.0f, 0.0f);
vertex.add_data3(0.0f, 1.0f, 1.0f);
vertex.add_data3(1.0f, 0.0f, 0.0f);
vertex.add_data3(1.0f, 0.0f, 1.0f);
vertex.add_data3(1.0f, 1.0f, 0.0f);
vertex.add_data3(1.0f, 1.0f, 1.0f);
{
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
vertex.set_data3(0.0f, 0.0f, 0.0f);
vertex.set_data3(0.0f, 0.0f, 1.0f);
vertex.set_data3(0.0f, 1.0f, 0.0f);
vertex.set_data3(0.0f, 1.0f, 1.0f);
vertex.set_data3(1.0f, 0.0f, 0.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);
tris->add_vertices(0, 4, 5);
tris->close_primitive();
tris->add_vertices(0, 5, 1);
tris->close_primitive();
tris->add_vertices(4, 6, 7);
tris->close_primitive();
tris->add_vertices(4, 7, 5);
tris->close_primitive();
tris->add_vertices(6, 2, 3);
tris->close_primitive();
tris->add_vertices(6, 3, 7);
tris->close_primitive();
tris->add_vertices(2, 0, 1);
tris->close_primitive();
tris->add_vertices(2, 1, 3);
tris->close_primitive();
tris->add_vertices(1, 5, 7);
tris->close_primitive();
tris->add_vertices(1, 7, 3);
tris->close_primitive();
tris->add_vertices(2, 6, 4);
tris->close_primitive();
tris->add_vertices(2, 4, 0);
tris->close_primitive();
_box_geom = new Geom(vdata);
_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);
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(
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(
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(
new ShaderInput("ShaderTerrainMesh.data_texture", _data_texture));
ShaderInput("ShaderTerrainMesh.data_texture", _data_texture));
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(
traversal_data.emitted_chunks);

View File

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

View File

@ -83,6 +83,12 @@ private:
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"
#endif

View File

@ -132,9 +132,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
if (curve != (NurbsCurveEvaluator *)NULL) {
PT(NurbsCurveResult) result;
if (has_matrix()) {
result = curve->evaluate(data._node_path.get_node_path(), get_matrix());
result = curve->evaluate(data.get_node_path(), get_matrix());
} else {
result = curve->evaluate(data._node_path.get_node_path());
result = curve->evaluate(data.get_node_path());
}
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) {
NurbsSurfaceEvaluator *surface = get_surface();
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) {
render_sheet(trav, data, result);

View File

@ -164,7 +164,7 @@ has_adjust_transform() const {
void BillboardEffect::
adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform,
PandaNode *) const {
const PandaNode *) const {
// 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,
// 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 void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform,
PandaNode *node) const;
const PandaNode *node) const;
protected:
virtual int compare_to_impl(const RenderEffect *other) const;

View File

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

View File

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

View File

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

View File

@ -315,11 +315,10 @@ do_cull(int &result, CPT(RenderState) &state,
result =
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;
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
// front of all zero of the clip planes. (This can happen if someone
// directly changes the state during the traversal.)

View File

@ -74,6 +74,12 @@ private:
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"
#endif

View File

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

View File

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

View File

@ -20,7 +20,8 @@ CullTraverserData(const NodePath &start,
const RenderState *state,
GeometricBoundingVolume *view_frustum,
Thread *current_thread) :
_node_path(start),
_next(nullptr),
_start(start._head),
_node_reader(start.node(), current_thread),
_net_transform(net_transform),
_state(state),
@ -34,44 +35,16 @@ CullTraverserData(const NodePath &start,
_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
* node down in the traversal.
*/
INLINE CullTraverserData::
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()),
_net_transform(parent._net_transform),
_state(parent._state),
@ -86,19 +59,12 @@ CullTraverserData(const CullTraverserData &parent, PandaNode *child) :
_node_reader.check_cached(check_bounds);
}
/**
*
*/
INLINE CullTraverserData::
~CullTraverserData() {
}
/**
* Returns the node traversed to so far.
*/
INLINE PandaNode *CullTraverserData::
node() const {
return _node_path.node();
return (PandaNode *)_node_reader.get_node();
}
/**
@ -117,6 +83,18 @@ node_reader() const {
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
* the model.

View File

@ -46,25 +46,33 @@ apply_transform_and_state(CullTraverser *trav) {
}
_node_reader.compose_draw_mask(_draw_mask);
apply_transform_and_state(trav, _node_reader.get_transform(),
MOVE(node_state), _node_reader.get_effects(),
_node_reader.get_off_clip_planes());
const RenderEffects *node_effects = _node_reader.get_effects();
if (!node_effects->has_cull_callback()) {
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
* a node) onto the current data. This also evaluates billboards, etc.
* Applies the indicated transform changes onto the current data.
*/
void CullTraverserData::
apply_transform_and_state(CullTraverser *trav,
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);
}
apply_transform(const TransformState *node_transform) {
if (!node_transform->is_identity()) {
_net_transform = _net_transform->compose(node_transform);
@ -95,15 +103,40 @@ apply_transform_and_state(CullTraverser *trav,
}
}
}
}
_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 *)off_clip_planes,
(const OccluderEffect *)node_effects->get_effect(OccluderEffect::get_class_type()));
/**
* The private, recursive implementation of get_node_path(), this returns the
* NodePathComponent representing the NodePath.
*/
PT(NodePathComponent) CullTraverserData::
r_get_node_path() const {
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()) {
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) {
@ -136,8 +169,7 @@ is_in_view_impl() {
// If we have fake view-frustum culling enabled, instead of actually
// culling an object we simply force it to be drawn in red wireframe.
_view_frustum = (GeometricBoundingVolume *)NULL;
CPT(RenderState) fake_state = get_fake_view_frustum_cull_state();
_state = _state->compose(fake_state);
_state = _state->compose(get_fake_view_frustum_cull_state());
#endif
} else if ((result & BoundingVolume::IF_all) != 0) {
@ -170,7 +202,7 @@ is_in_view_impl() {
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< _node_path << " cull planes cull result = " << hex
<< get_node_path() << " cull planes cull result = " << hex
<< result << dec << "\n";
_cull_planes->write(pgraph_cat.spam(false));
}
@ -182,7 +214,7 @@ is_in_view_impl() {
if (pgraph_cat.is_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);
}
}
@ -196,8 +228,7 @@ is_in_view_impl() {
return false;
}
_cull_planes = CullPlanes::make_empty();
CPT(RenderState) fake_state = get_fake_view_frustum_cull_state();
_state = _state->compose(fake_state);
_state = _state->compose(get_fake_view_frustum_cull_state());
#endif
} 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
* the fake_view_frustum_cull effect.
*/
CPT(RenderState) CullTraverserData::
const RenderState *CullTraverserData::
get_fake_view_frustum_cull_state() {
#ifdef NDEBUG
return NULL;
return nullptr;
#else
// Once someone asks for this pointer, we hold its reference count and never
// free it.
static CPT(RenderState) state = (const RenderState *)NULL;
if (state == (const RenderState *)NULL) {
static CPT(RenderState) state;
if (state == nullptr) {
state = RenderState::make
(ColorAttrib::make_flat(LColor(1.0f, 0.0f, 0.0f, 1.0f)),
TextureAttrib::make_all_off(),

View File

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

View File

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

View File

@ -1080,7 +1080,7 @@ get_sa() const {
*/
INLINE void NodePath::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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());
}
#if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
nassertr(verify_complete(current_thread), RenderState::make_empty());
nassertr(other.verify_complete(current_thread), RenderState::make_empty());
#endif
int a_count, b_count;
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());
}
#if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
nassertr(verify_complete(current_thread), TransformState::make_identity());
nassertr(other.verify_complete(current_thread), TransformState::make_identity());
#endif
int a_count, b_count;
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());
}
#if defined(_DEBUG) || (defined(HAVE_THREADS) && defined(SIMPLE_THREADS))
nassertr(verify_complete(current_thread), TransformState::make_identity());
nassertr(other.verify_complete(current_thread), TransformState::make_identity());
#endif
int a_count, b_count;
if (find_common_ancestor(*this, other, a_count, b_count, current_thread) == (NodePathComponent *)NULL) {
@ -3255,35 +3261,36 @@ get_shader() const {
*
*/
void NodePath::
set_shader_input(const ShaderInput *inp) {
set_shader_input(ShaderInput inp) {
nassertv_always(!is_empty());
PandaNode *pnode = node();
const RenderAttrib *attrib =
node()->get_attrib(ShaderAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) {
const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
node()->set_attrib(sa->set_shader_input(inp));
pnode->get_attrib(ShaderAttrib::get_class_slot());
if (attrib != nullptr) {
const ShaderAttrib *sa = (const ShaderAttrib *)attrib;
pnode->set_attrib(sa->set_shader_input(inp));
} else {
// Create a new ShaderAttrib for this node.
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 {
nassertr_always(!is_empty(), NULL);
nassertr_always(!is_empty(), ShaderInput::get_blank());
const RenderAttrib *attrib =
node()->get_attrib(ShaderAttrib::get_class_slot());
if (attrib != (const RenderAttrib *)NULL) {
const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
if (attrib != nullptr) {
const ShaderAttrib *sa = (const ShaderAttrib *)attrib;
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) {
return TransformState::make_identity();
} else {
PandaNode *node = comp->get_node();
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);
PandaNode *node = comp->get_node();
CPT(TransformState) transform = node->get_transform(current_thread);
CPT(RenderEffects) effects = node->get_effects(current_thread);
if (effects->has_adjust_transform()) {
effects->adjust_transform(net_transform, transform, node);
PandaNode::CDReader node_cdata(node->_cycler, current_thread);
if (!node_cdata->_effects->has_adjust_transform()) {
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) {
return TransformState::make_identity();
} 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;
}
CPT(TransformState) transform = comp->get_node()->get_transform(current_thread);
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);
if (partial == (const TransformState *)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 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, 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);
@ -665,7 +665,7 @@ PUBLISHED:
void set_instance_count(int instance_count);
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;
void set_tex_transform(TextureStage *stage, const TransformState *transform);
@ -1029,6 +1029,7 @@ private:
friend class NodePathCollection;
friend class WorkingNodePath;
friend class WeakNodePath;
friend class CullTraverserData;
};
INLINE ostream &operator << (ostream &out, const NodePath &node_path);

View File

@ -75,6 +75,15 @@ has_key() const {
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) {
comp.output(out);
return out;

View File

@ -92,17 +92,6 @@ get_length(int pipeline_stage, Thread *current_thread) const {
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
* 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
* 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:
NodePathComponent(PandaNode *node, NodePathComponent *next,
int pipeline_stage, Thread *current_thread);
@ -55,7 +55,7 @@ public:
int get_key() 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;
bool fix_length(int pipeline_stage, Thread *current_thread);
@ -125,6 +125,12 @@ private:
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);
#include "nodePathComponent.I"

View File

@ -278,7 +278,7 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
}
CPT_InternalName name(string(buffer, length));
ShaderInput *input = nullptr;
ShaderInput input(nullptr, 0);
if (PyTuple_CheckExact(value)) {
// 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) {
vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i));
}
input = new ShaderInput(name, vec);
input = ShaderInput(move(name), vec);
} else {
LVecBase4i vec(0);
for (Py_ssize_t i = 0; i < size; ++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)) {
@ -314,91 +314,91 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
void *ptr;
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
input = new ShaderInput(name, (ShaderBuffer *)ptr);
input = ShaderInput(move(name), (ShaderBuffer *)ptr);
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) {
input = new ShaderInput(name, (ParamValueBase *)ptr);
input = ShaderInput(move(name), (ParamValueBase *)ptr);
} else {
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)) {
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
} 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
} 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 {
Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
return;
}
attrib->_inputs[move(name)] = input;
attrib->_inputs[input.get_name()] = move(input);
}
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
* planes that have been turned *off* at this level and below.
*/
INLINE CPT(RenderAttrib) PandaNodePipelineReader::
INLINE const RenderAttrib *PandaNodePipelineReader::
get_off_clip_planes() const {
nassertr(_cdata->_last_update == _cdata->_next_update, _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
* the children's bounding volumes.
*/
INLINE CPT(BoundingVolume) PandaNodePipelineReader::
INLINE const BoundingVolume *PandaNodePipelineReader::
get_bounds() const {
nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
return _cdata->_external_bounds;

View File

@ -827,6 +827,7 @@ private:
friend class PandaNodePipelineReader;
friend class EggLoader;
friend class Extension<PandaNode>;
friend class CullTraverserData;
};
/**
@ -877,8 +878,8 @@ public:
INLINE bool has_tag(const string &key) const;
INLINE CollideMask get_net_collide_mask() const;
INLINE CPT(RenderAttrib) get_off_clip_planes() const;
INLINE CPT(BoundingVolume) get_bounds() const;
INLINE const RenderAttrib *get_off_clip_planes() const;
INLINE const BoundingVolume *get_bounds() const;
INLINE int get_nested_vertices() const;
INLINE bool is_final() 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) {
node.output(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
PN_stdfloat light_radius = light->get_radius();
// 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;
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]) {
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,
// light->get_pos());
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_avatar = avatar_position - light_position;
light_camera.normalize();
@ -263,7 +263,7 @@ do_poly_light(const SceneSetup *scene, const CullTraverserData *data, const Tran
if (num_lights) {
// 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)
pgraph_cat.debug() << "num lights = " << num_lights << endl;
@ -320,8 +320,8 @@ do_poly_light(const SceneSetup *scene, const CullTraverserData *data, const Tran
else {
if (was_under_polylight) {
// under no polylight influence...so clear the color scale
// data->_node_path.get_node_path().clear_color_scale();
// data->_node_path.get_node_path().set_color_scale(scene_color);
// data->get_node_path().clear_color_scale();
// data->get_node_path().set_color_scale(scene_color);
was_under_polylight = false;
}
}

View File

@ -119,7 +119,7 @@ private:
LPoint2 _reduced_viewport_max;
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];

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);
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())) {
// remember current clip state, we might change it
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
// are attached to this node)
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() << "frustum before transform " << *temp_bh << endl;

View File

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

View File

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

View File

@ -160,7 +160,7 @@ has_adjust_transform() const {
*/
void RenderEffect::
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 void adjust_transform(CPT(TransformState) &net_transform,
CPT(TransformState) &node_transform,
PandaNode *node) const;
const PandaNode *node) const;
PUBLISHED:
INLINE int compare_to(const RenderEffect &other) const;

View File

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

View File

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

View File

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

View File

@ -40,7 +40,7 @@ LightReMutex *RenderState::_states_lock = NULL;
RenderState::States *RenderState::_states = NULL;
const RenderState *RenderState::_empty_state = NULL;
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::_garbage_collect_pcollector("*:State Cache:Garbage Collect");
@ -75,6 +75,10 @@ RenderState() :
_cache_stats.add_num_states(1);
_read_overrides = 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);
_read_overrides = 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::
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
// collection, just allow the pointer to unref normally.
return ReferenceCount::unref();
@ -774,8 +782,8 @@ get_num_unused_states() {
typedef pmap<const RenderState *, int> StateCount;
StateCount state_count;
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -871,8 +879,8 @@ clear_cache() {
TempStates temp_states;
temp_states.reserve(orig_size);
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -938,27 +946,30 @@ garbage_collect() {
if (_states == (States *)NULL || !garbage_collect_states) {
return num_attribs;
}
bool break_and_uniquify = (auto_break_cycles && uniquify_transforms);
LightReMutexHolder holder(*_states_lock);
PStatTimer timer(_garbage_collect_pcollector);
int orig_size = _states->get_num_entries();
// How many elements to process this pass?
int size = _states->get_size();
int num_this_pass = int(size * garbage_collect_states_rate);
if (num_this_pass <= 0) {
size_t size = _states->get_size();
size_t num_this_pass = int((int)size * garbage_collect_states_rate);
if (size <= 0 || num_this_pass <= 0) {
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;
int si = _garbage_index;
size_t si = _garbage_index;
num_this_pass = min(num_this_pass, size);
size_t stop_at_element = (si + num_this_pass) % (size - 1);
do {
if (_states->has_element(si)) {
++num_elements;
RenderState *state = (RenderState *)_states->get_key(si);
if (auto_break_cycles && uniquify_states) {
if (break_and_uniquify) {
if (state->get_cache_ref_count() > 0 &&
state->get_ref_count() == state->get_cache_ref_count()) {
// 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);
_garbage_index = si;
#ifdef _DEBUG
nassertr(_states->validate(), 0);
#endif
int new_size = _states->get_num_entries();
return orig_size - new_size + num_attribs;
@ -999,8 +1013,8 @@ void RenderState::
clear_munger_cache() {
LightReMutexHolder holder(*_states_lock);
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -1034,8 +1048,8 @@ list_cycles(ostream &out) {
VisitedStates visited;
CompositionCycleDesc cycle_desc;
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -1113,8 +1127,8 @@ list_states(ostream &out) {
out << _states->get_num_entries() << " states:\n";
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -1148,14 +1162,14 @@ validate_states() {
return false;
}
int size = _states->get_size();
int si = 0;
size_t size = _states->get_size();
size_t si = 0;
while (si < size && !_states->has_element(si)) {
++si;
}
nassertr(si < size, false);
nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
int snext = si;
size_t snext = si;
++snext;
while (snext < size && !_states->has_element(snext)) {
++snext;

View File

@ -278,7 +278,7 @@ private:
// This keeps track of our current position through the garbage collection
// cycle.
static int _garbage_index;
static size_t _garbage_index;
static PStatCollector _cache_update_pcollector;
static PStatCollector _garbage_collect_pcollector;
@ -368,6 +368,12 @@ private:
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) {
state.output(out);
return out;

View File

@ -110,7 +110,7 @@ has_shader_input(CPT_InternalName id) const {
*/
INLINE CPT(RenderAttrib) ShaderAttrib::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::
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::

View File

@ -193,13 +193,13 @@ clear_flag(int flag) const {
*
*/
CPT(RenderAttrib) ShaderAttrib::
set_shader_input(const ShaderInput *input) const {
set_shader_input(ShaderInput input) const {
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()) {
result->_inputs.insert(Inputs::value_type(input->get_name(), input));
result->_inputs.insert(Inputs::value_type(input.get_name(), move(input)));
} else {
i->second = input;
i->second = move(input);
}
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
* function does not return NULL --- it returns the "blank" ShaderInput.
*/
const ShaderInput *ShaderAttrib::
const ShaderInput &ShaderAttrib::
get_shader_input(const InternalName *id) const {
Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) {
return ShaderInput::get_blank();
} else {
if (i != _inputs.end()) {
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
* function does not return NULL --- it returns the "blank" ShaderInput.
*/
const ShaderInput *ShaderAttrib::
const ShaderInput &ShaderAttrib::
get_shader_input(const string &id) const {
return get_shader_input(InternalName::make(id));
}
@ -275,20 +275,21 @@ const NodePath &ShaderAttrib::
get_shader_input_nodepath(const InternalName *id) const {
static NodePath resfail;
Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) {
ostringstream strm;
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_nodepath) {
if (i != _inputs.end()) {
const ShaderInput &p = (*i).second;
if (p.get_value_type() == ShaderInput::M_nodepath) {
return ((const ParamNodePath *)p.get_value())->get_value();
} else {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not a nodepath.\n";
nassert_raise(strm.str());
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.
@ -303,19 +304,14 @@ LVecBase4 ShaderAttrib::
get_shader_input_vector(InternalName *id) const {
static LVecBase4 resfail(0,0,0,0);
Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return resfail;
} else {
const ShaderInput *p = (*i).second;
if (i != _inputs.end()) {
const ShaderInput &p = (*i).second;
if (p->get_value_type() == ShaderInput::M_vector) {
return p->get_vector();
if (p.get_value_type() == ShaderInput::M_vector) {
return p.get_vector();
} else if (p->get_value_type() == ShaderInput::M_numeric && p->get_ptr()._size <= 4) {
const Shader::ShaderPtrData &ptr = p->get_ptr();
} else if (p.get_value_type() == ShaderInput::M_numeric && p.get_ptr()._size <= 4) {
const Shader::ShaderPtrData &ptr = p.get_ptr();
switch (ptr._type) {
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
ParamValueBase *param = p->get_param();
TypedWritableReferenceCount *param = p.get_value();
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;
strm << "Shader input " << id->get_name() << " is not a vector.\n";
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::
get_shader_input_ptr(const InternalName *id) const {
Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return NULL;
} else {
const ShaderInput *p = (*i).second;
if (p->get_value_type() != ShaderInput::M_numeric &&
p->get_value_type() != ShaderInput::M_vector) {
if (i != _inputs.end()) {
const ShaderInput &p = (*i).second;
if (p.get_value_type() != ShaderInput::M_numeric &&
p.get_value_type() != ShaderInput::M_vector) {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not a PTA(float/double) type.\n";
nassert_raise(strm.str());
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::
get_shader_input_texture(const InternalName *id, SamplerState *sampler) const {
Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) {
ostringstream strm;
strm << "Shader input " << id->get_name() << " is not present.\n";
nassert_raise(strm.str());
return NULL;
} else {
const ShaderInput *p = (*i).second;
if (p->get_value_type() != ShaderInput::M_texture &&
p->get_value_type() != ShaderInput::M_texture_sampler) {
if (i != _inputs.end()) {
const ShaderInput &p = (*i).second;
switch (p.get_value_type()) {
case ShaderInput::M_texture:
{
Texture *tex = (Texture *)p.get_value();
if (sampler) {
*sampler = tex->get_default_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;
strm << "Shader input " << id->get_name() << " is not a texture.\n";
nassert_raise(strm.str());
return NULL;
}
if (sampler != NULL) {
*sampler = p->get_sampler();
}
return p->get_texture();
} else {
ostringstream strm;
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::
get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const {
Inputs::const_iterator i = _inputs.find(id);
if (i == _inputs.end()) {
ostringstream strm;
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 (i != _inputs.end()) {
const ShaderInput &p = (*i).second;
if (p->get_value_type() == ShaderInput::M_nodepath) {
const NodePath &np = p->get_nodepath();
if (p.get_value_type() == ShaderInput::M_nodepath) {
const NodePath &np = p.get_nodepath();
nassertr(!np.is_empty(), LMatrix4::ident_mat());
return np.get_transform()->get_mat();
} else if (p->get_value_type() == ShaderInput::M_numeric &&
p->get_ptr()._size >= 16 && (p->get_ptr()._size & 15) == 0) {
const Shader::ShaderPtrData &ptr = p->get_ptr();
} else if (p.get_value_type() == ShaderInput::M_numeric &&
p.get_ptr()._size >= 16 && (p.get_ptr()._size & 15) == 0) {
const Shader::ShaderPtrData &ptr = p.get_ptr();
switch (ptr._type) {
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";
nassert_raise(strm.str());
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());
return NULL;
} 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;
DCAST_INTO_R(value, p->_value, NULL);
DCAST_INTO_R(value, p._value, NULL);
return value;
}
@ -615,8 +630,7 @@ get_hash_impl() const {
Inputs::const_iterator ii;
for (ii = _inputs.begin(); ii != _inputs.end(); ++ii) {
hash = pointer_hash::add_hash(hash, (*ii).first);
hash = pointer_hash::add_hash(hash, (*ii).second);
hash = (*ii).second.add_hash(hash);
}
return hash;
@ -649,13 +663,13 @@ compose_impl(const RenderAttrib *other) const {
Inputs::const_iterator iover;
for (iover=over->_inputs.begin(); iover!=over->_inputs.end(); ++iover) {
const InternalName *id = (*iover).first;
const ShaderInput *dover = (*iover).second;
const ShaderInput &dover = (*iover).second;
Inputs::iterator iattr = attr->_inputs.find(id);
if (iattr == attr->_inputs.end()) {
attr->_inputs.insert(Inputs::value_type(id,dover));
} else {
const ShaderInput *dattr = (*iattr).second;
if (dattr->get_priority() <= dover->get_priority()) {
const ShaderInput &dattr = (*iattr).second;
if (dattr.get_priority() <= dover.get_priority()) {
iattr->second = iover->second;
}
}

View File

@ -71,7 +71,7 @@ PUBLISHED:
CPT(RenderAttrib) clear_shader() const;
// 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, const NodePath &np, int priority=0) const;
@ -104,8 +104,8 @@ PUBLISHED:
INLINE bool has_shader_input(CPT_InternalName id) const;
const Shader *get_shader() 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 InternalName *id) const;
const ShaderInput &get_shader_input(const string &id) const;
const NodePath &get_shader_input_nodepath(const InternalName *id) const;
LVecBase4 get_shader_input_vector(InternalName *id) const;
@ -145,7 +145,9 @@ private:
bool _auto_ramp_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;
friend class Extension<NodePath>;

View File

@ -13,13 +13,6 @@
* @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 {
return DCAST(ParamValueBase, _value);
}
/**
*
*/
INLINE TypedWritableReferenceCount *ShaderInput::
get_value() const {
return _value.p();
}

View File

@ -15,18 +15,13 @@
#include "paramNodePath.h"
#include "paramTexture.h"
TypeHandle ShaderInput::_type_handle;
/**
* Returns a static ShaderInput object with name NULL, priority zero, type
* INVALID, and all value-fields cleared.
*/
const ShaderInput *ShaderInput::
const ShaderInput &ShaderInput::
get_blank() {
static CPT(ShaderInput) blank;
if (blank == 0) {
blank = new ShaderInput(NULL, 0);
}
static ShaderInput blank(nullptr, 0);
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()
* is not M_nodepath.

View File

@ -17,7 +17,6 @@
#define SHADERINPUT_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "internalName.h"
#include "paramValue.h"
@ -37,10 +36,7 @@
* This is a small container class that can hold any one of the value types
* that can be passed as input to a shader.
*/
class EXPCL_PANDA_PGRAPH ShaderInput : public TypedWritableReferenceCount {
public:
INLINE ~ShaderInput();
class EXPCL_PANDA_PGRAPH ShaderInput {
PUBLISHED:
// Used when binding texture images.
enum AccessFlags {
@ -49,7 +45,7 @@ PUBLISHED:
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, Texture *tex, int priority=0);
INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0);
@ -102,6 +98,12 @@ PUBLISHED:
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 int get_value_type() const;
@ -114,7 +116,10 @@ PUBLISHED:
const SamplerState &get_sampler() const;
public:
ShaderInput() DEFAULT_CTOR;
INLINE ParamValueBase *get_param() const;
INLINE TypedWritableReferenceCount *get_value() const;
static void register_with_read_factory();
@ -127,26 +132,8 @@ private:
int _type;
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"
#endif // SHADERINPUT_H

View File

@ -29,7 +29,7 @@ TransformState::States *TransformState::_states = NULL;
CPT(TransformState) TransformState::_identity_state;
CPT(TransformState) TransformState::_invalid_state;
UpdateSeq TransformState::_last_cycle_detect;
int TransformState::_garbage_index = 0;
size_t TransformState::_garbage_index = 0;
bool TransformState::_uniquify_matrix = true;
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;
_inv_mat = (LMatrix4 *)NULL;
_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);
}
// Is this composition already cached?
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();
}
}
LightReMutexHolder holder(*_states_lock);
if (result != (TransformState *)NULL) {
// Success!
return result;
// Is this composition already cached?
int index = _composition_cache.find(other);
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
// hold the lock while we do this, or we lose the benefit of
// 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
// a transparent property of the class.
return ((TransformState *)this)->store_compose(other, result);
if (index != -1) {
Composition &comp = _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(_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);
CPT(TransformState) result;
{
LightReMutexHolder holder(*_states_lock);
int index = _invert_composition_cache.find(other);
if (index != -1) {
const Composition &comp = _invert_composition_cache.get_data(index);
result = comp._result;
}
if (result != (TransformState *)NULL) {
int index = _invert_composition_cache.find(other);
if (index != -1) {
const Composition &comp = _invert_composition_cache.get_data(index);
if (comp._result != nullptr) {
// Success!
_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
// hold the lock while we do this, or we lose the benefit of
// 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
// a transparent property of the class.
return ((TransformState *)this)->store_invert_compose(other, result);
// Is this composition already cached?
if (index != -1) {
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::
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
// collection, just allow the pointer to unref normally.
return ReferenceCount::unref();
@ -760,8 +842,8 @@ bool TransformState::
validate_composition_cache() const {
LightReMutexHolder holder(*_states_lock);
int size = _composition_cache.get_size();
for (int i = 0; i < size; ++i) {
size_t size = _composition_cache.get_size();
for (size_t i = 0; i < size; ++i) {
if (!_composition_cache.has_element(i)) {
continue;
}
@ -955,15 +1037,15 @@ get_num_unused_states() {
typedef pmap<const TransformState *, int> StateCount;
StateCount state_count;
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
const TransformState *state = _states->get_key(si);
int i;
int cache_size = state->_composition_cache.get_size();
size_t i;
size_t cache_size = state->_composition_cache.get_size();
for (i = 0; i < cache_size; ++i) {
if (state->_composition_cache.has_element(i)) {
const TransformState *result = state->_composition_cache.get_data(i)._result;
@ -1053,8 +1135,8 @@ clear_cache() {
TempStates temp_states;
temp_states.reserve(orig_size);
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -1116,27 +1198,30 @@ garbage_collect() {
if (_states == (States *)NULL || !garbage_collect_states) {
return 0;
}
bool break_and_uniquify = (auto_break_cycles && uniquify_transforms);
LightReMutexHolder holder(*_states_lock);
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?
int size = _states->get_size();
int num_this_pass = int(size * garbage_collect_states_rate);
if (num_this_pass <= 0) {
size_t size = _states->get_size();
size_t num_this_pass = int(size * garbage_collect_states_rate);
if (size <= 0 || num_this_pass <= 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;
int si = _garbage_index;
size_t si = _garbage_index;
num_this_pass = min(num_this_pass, size);
size_t stop_at_element = (si + num_this_pass) & (size - 1);
do {
if (_states->has_element(si)) {
++num_elements;
TransformState *state = (TransformState *)_states->get_key(si);
if (auto_break_cycles && uniquify_transforms) {
if (break_and_uniquify) {
if (state->get_cache_ref_count() > 0 &&
state->get_ref_count() == state->get_cache_ref_count()) {
// 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);
_garbage_index = si;
#ifdef _DEBUG
nassertr(_states->validate(), 0);
#endif
int new_size = _states->get_num_entries();
return orig_size - new_size;
@ -1193,8 +1281,8 @@ list_cycles(ostream &out) {
VisitedStates visited;
CompositionCycleDesc cycle_desc;
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -1272,8 +1360,8 @@ list_states(ostream &out) {
out << _states->get_num_entries() << " states:\n";
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
size_t size = _states->get_size();
for (size_t si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
@ -1307,14 +1395,14 @@ validate_states() {
return false;
}
int size = _states->get_size();
int si = 0;
size_t size = _states->get_size();
size_t si = 0;
while (si < size && !_states->has_element(si)) {
++si;
}
nassertr(si < size, false);
nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
int snext = si;
size_t snext = si;
++snext;
while (snext < size && !_states->has_element(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().
*/

View File

@ -234,9 +234,7 @@ private:
static CPT(TransformState) return_unique(TransformState *state);
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) store_invert_compose(const TransformState *other, const TransformState *result);
void detect_and_break_cycles();
static bool r_detect_cycles(const TransformState *start_state,
const TransformState *current_state,
@ -288,8 +286,8 @@ private:
};
typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache;
CompositionCache _composition_cache;
CompositionCache _invert_composition_cache;
mutable CompositionCache _composition_cache;
mutable CompositionCache _invert_composition_cache;
// This is used to mark nodes as we visit them to detect cycles.
UpdateSeq _cycle_detect;
@ -297,7 +295,7 @@ private:
// This keeps track of our current position through the garbage collection
// cycle.
static int _garbage_index;
static size_t _garbage_index;
static bool _uniquify_matrix;
@ -408,6 +406,12 @@ private:
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) {
state.output(out);
return out;

View File

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

View File

@ -93,7 +93,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
consider_verify_lods(trav, data);
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 =
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.
*/
INLINE bool LightLensNode::
is_shadow_caster() {
is_shadow_caster() const {
return _shadow_caster;
}

View File

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

View File

@ -41,7 +41,7 @@ void NodeCullCallbackData::
upcall() {
PandaNode *node = _data.node();
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
// 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();
nassertv(light_obj != (PandaNode *)NULL);
if (light_obj->get_type() == AmbientLight::get_class_type()) {
if (light_obj->is_ambient_light()) {
if (_material->has_ambient()) {
LColor a = _material->get_ambient();
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())) {
_lights_np.push_back(light);
_lights.push_back((LightLensNode *)light_obj);
if (DCAST(LightLensNode, light_obj)->is_shadow_caster()) {
if (((const LightLensNode *)light_obj)->is_shadow_caster()) {
_shadows = 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);
#ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif
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);
#ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif
_lock.acquire(current_thread);
return _data[pipeline_stage]._cdata;
@ -278,6 +282,8 @@ elevate_read_stage(int pipeline_stage, const CycleData *pointer,
#ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif
CycleData *new_pointer = write_stage(pipeline_stage, current_thread);
_lock.release();
@ -296,6 +302,8 @@ elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
#ifdef _DEBUG
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif
CycleData *new_pointer =
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(_data[pipeline_stage]._cdata == pointer);
nassertv(_data[pipeline_stage]._writes_outstanding > 0);
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
__builtin_assume(pipeline_stage >= 0);
#endif
--(_data[pipeline_stage]._writes_outstanding);
_lock.release();

View File

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

View File

@ -161,6 +161,12 @@ private:
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"
#endif

View File

@ -235,8 +235,8 @@ get_size() const {
*/
template<class Key, class Value, class Compare>
INLINE bool SimpleHashMap<Key, Value, Compare>::
has_element(int n) const {
nassertr(n >= 0 && n < (int)_table_size, false);
has_element(size_t n) const {
nassertr(n < _table_size, false);
return (get_exists_array()[n] != 0);
}
@ -249,7 +249,7 @@ has_element(int n) const {
*/
template<class Key, class Value, class 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);
return _table[n]._key;
}
@ -263,7 +263,7 @@ get_key(int n) const {
*/
template<class Key, class Value, class 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);
return _table[n]._data;
}
@ -277,7 +277,7 @@ get_data(int n) const {
*/
template<class Key, class Value, class Compare>
INLINE Value &SimpleHashMap<Key, Value, Compare>::
modify_data(int n) {
modify_data(size_t n) {
nassertr(has_element(n), _table[n]._data);
return _table[n]._data;
}
@ -291,7 +291,7 @@ modify_data(int n) {
*/
template<class Key, class Value, class 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));
_table[n]._data = data;
}
@ -305,7 +305,7 @@ set_data(int n, const Value &data) {
*/
template<class Key, class Value, class Compare>
void SimpleHashMap<Key, Value, Compare>::
remove_element(int n) {
remove_element(size_t n) {
nassertv(has_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
// 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);
while (has_element(i)) {
size_t wants_index = get_hash(_table[i]._key);
@ -403,12 +403,14 @@ bool SimpleHashMap<Key, Value, Compare>::
validate() const {
size_t count = 0;
const unsigned char *exists_array = get_exists_array();
for (size_t i = 0; i < _table_size; ++i) {
if (has_element(i)) {
if (exists_array[i] != 0) {
++count;
size_t ideal_index = get_hash(_table[i]._key);
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);
}
if (wants_index != i) {
@ -455,7 +457,7 @@ get_hash(const Key &key) const {
*/
template<class Key, class Value, class 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);
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>
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);
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>
INLINE void SimpleHashMap<Key, Value, Compare>::
clear_element(int n) {
clear_element(size_t n) {
_table[n].~TableEntry();
get_exists_array()[n] = false;
}

View File

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

View File

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

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