fix calc_tight_bounds(), add NodePath::show_tight_bounds()

This commit is contained in:
David Rose 2005-04-29 23:06:27 +00:00
parent 9946ffe1ab
commit 5e8855ebc8
12 changed files with 171 additions and 48 deletions

View File

@ -1142,7 +1142,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
if (got_mat) {
for (int i = 0; i < cdata->_num_vertices; i++) {
reader.set_row(cdata->_first_vertex + i);
const LVecBase3f &vertex = reader.get_data3f();
LPoint3f vertex = mat.xform_point(reader.get_data3f());
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
@ -1160,7 +1160,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
} else {
for (int i = 0; i < cdata->_num_vertices; i++) {
reader.set_row(cdata->_first_vertex + i);
LPoint3f vertex = mat.xform_point(reader.get_data3f());
const LVecBase3f &vertex = reader.get_data3f();
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
@ -1184,7 +1184,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
if (got_mat) {
while (!index.is_at_end()) {
reader.set_row(index.get_data1i());
const LVecBase3f &vertex = reader.get_data3f();
LPoint3f vertex = mat.xform_point(reader.get_data3f());
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
@ -1202,7 +1202,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
} else {
while (!index.is_at_end()) {
reader.set_row(index.get_data1i());
LPoint3f vertex = mat.xform_point(reader.get_data3f());
const LVecBase3f &vertex = reader.get_data3f();
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),

View File

@ -35,6 +35,7 @@
#include "portalClipper.h"
#include "qpgeom.h"
#include "qpgeomTristrips.h"
#include "qpgeomLinestrips.h"
#include "qpgeomVertexWriter.h"
PStatCollector CullTraverser::_nodes_pcollector("Nodes");
@ -166,7 +167,7 @@ traverse(CullTraverserData &data) {
if (node_effects->has_show_bounds()) {
// If we should show the bounding volume for this node, make it
// up now.
show_bounds(data);
show_bounds(data, node_effects->has_show_tight_bounds());
}
data.apply_transform_and_state(this);
@ -267,21 +268,35 @@ traverse_below(CullTraverserData &data) {
// external bounding volume.
////////////////////////////////////////////////////////////////////
void CullTraverser::
show_bounds(CullTraverserData &data) {
show_bounds(CullTraverserData &data, bool tight) {
PandaNode *node = data.node();
PT(Geom) bounds_viz = make_bounds_viz(node->get_bound());
if (bounds_viz != (Geom *)NULL) {
_geoms_pcollector.add_level(2);
CullableObject *outer_viz =
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
data._render_transform);
_cull_handler->record_object(outer_viz, this);
if (tight) {
PT(Geom) bounds_viz = make_tight_bounds_viz(node);
CullableObject *inner_viz =
new CullableObject(bounds_viz, get_bounds_inner_viz_state(),
data._render_transform);
_cull_handler->record_object(inner_viz, this);
if (bounds_viz != (Geom *)NULL) {
_geoms_pcollector.add_level(1);
CullableObject *outer_viz =
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
data._render_transform);
_cull_handler->record_object(outer_viz, this);
}
} else {
PT(Geom) bounds_viz = make_bounds_viz(node->get_bound());
if (bounds_viz != (Geom *)NULL) {
_geoms_pcollector.add_level(2);
CullableObject *outer_viz =
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
data._render_transform);
_cull_handler->record_object(outer_viz, this);
CullableObject *inner_viz =
new CullableObject(bounds_viz, get_bounds_inner_viz_state(),
data._render_transform);
_cull_handler->record_object(inner_viz, this);
}
}
}
@ -305,7 +320,7 @@ make_bounds_viz(const BoundingVolume &vol) {
static const int num_stacks = 8;
PT(qpGeomVertexData) vdata = new qpGeomVertexData
("collision", qpGeomVertexFormat::get_v3(),
("bounds", qpGeomVertexFormat::get_v3(),
qpGeom::UH_stream);
qpGeomVertexWriter vertex(vdata, InternalName::get_vertex());
@ -350,6 +365,67 @@ make_bounds_viz(const BoundingVolume &vol) {
return geom;
}
////////////////////////////////////////////////////////////////////
// Function: CullTraverser::make_tight_bounds_viz
// Access: Private
// Description: Returns a bounding-box visualization of the indicated
// node's "tight" bounding volume.
////////////////////////////////////////////////////////////////////
PT(Geom) CullTraverser::
make_tight_bounds_viz(PandaNode *node) {
PT(Geom) geom;
NodePath np = NodePath::any_path(node);
LPoint3f n, x;
bool found_any = false;
node->calc_tight_bounds(n, x, found_any, TransformState::make_identity());
if (found_any) {
PT(qpGeomVertexData) vdata = new qpGeomVertexData
("bounds", qpGeomVertexFormat::get_v3(),
qpGeom::UH_stream);
qpGeomVertexWriter vertex(vdata, InternalName::get_vertex());
vertex.add_data3f(n[0], n[1], n[2]);
vertex.add_data3f(n[0], n[1], x[2]);
vertex.add_data3f(n[0], x[1], n[2]);
vertex.add_data3f(n[0], x[1], x[2]);
vertex.add_data3f(x[0], n[1], n[2]);
vertex.add_data3f(x[0], n[1], x[2]);
vertex.add_data3f(x[0], x[1], n[2]);
vertex.add_data3f(x[0], x[1], x[2]);
PT(qpGeomLinestrips) strip = new qpGeomLinestrips(qpGeom::UH_stream);
// We wind one long linestrip around the wireframe cube. This
// does require backtracking a few times here and there.
strip->add_vertex(0);
strip->add_vertex(1);
strip->add_vertex(3);
strip->add_vertex(2);
strip->add_vertex(0);
strip->add_vertex(4);
strip->add_vertex(5);
strip->add_vertex(7);
strip->add_vertex(6);
strip->add_vertex(4);
strip->add_vertex(6);
strip->add_vertex(2);
strip->add_vertex(3);
strip->add_vertex(7);
strip->add_vertex(5);
strip->add_vertex(1);
strip->close_primitive();
PT(qpGeom) qpgeom = new qpGeom;
qpgeom->set_vertex_data(vdata);
qpgeom->add_primitive(strip);
geom = qpgeom.p();
}
return geom;
}
////////////////////////////////////////////////////////////////////
// Function: CullTraverser::compute_point
// Access: Private, Static
@ -508,7 +584,7 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) {
if (node_effects->has_show_bounds()) {
// If we should show the bounding volume for this node, make it
// up now.
show_bounds(data);
show_bounds(data, node_effects->has_show_tight_bounds());
}
data.apply_transform_and_state(this);

View File

@ -95,8 +95,9 @@ public:
static PStatCollector _geoms_pcollector;
private:
void show_bounds(CullTraverserData &data);
void show_bounds(CullTraverserData &data, bool tight);
PT(Geom) make_bounds_viz(const BoundingVolume &vol);
PT(Geom) make_tight_bounds_viz(PandaNode *node);
static Vertexf compute_point(const BoundingSphere *sphere,
float latitude, float longitude);
CPT(RenderState) get_bounds_outer_viz_state();

View File

@ -358,7 +358,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
const qpGeom *qpgeom = DCAST(qpGeom, geom);
qpgeom->calc_tight_bounds(min_point, max_point, found_any,
qpgeom->get_vertex_data()->animate_vertices(),
!transform->is_identity(), mat);
!next_transform->is_identity(), mat);
} else {
Geom::VertexIterator vi = geom->make_vertex_iterator();

View File

@ -4710,7 +4710,23 @@ prepare_scene(GraphicsStateGuardianBase *gsg) {
void NodePath::
show_bounds() {
nassertv_always(!is_empty());
node()->set_effect(ShowBoundsEffect::make());
node()->set_effect(ShowBoundsEffect::make(false));
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::show_tight_bounds
// Access: Published
// Description: Similar to show_bounds(), this draws a bounding box
// representing the "tight" bounds of this node and all
// of its descendants. The bounding box is recomputed
// every frame by reexamining all of the vertices; this
// is far from efficient, but this is intended for
// debugging.
////////////////////////////////////////////////////////////////////
void NodePath::
show_tight_bounds() {
nassertv_always(!is_empty());
node()->set_effect(ShowBoundsEffect::make(true));
}
////////////////////////////////////////////////////////////////////

View File

@ -703,6 +703,7 @@ PUBLISHED:
void prepare_scene(GraphicsStateGuardianBase *gsg);
void show_bounds();
void show_tight_bounds();
void hide_bounds();
PT(BoundingVolume) get_bounds() const;
void force_recompute_bounds();

View File

@ -183,6 +183,23 @@ has_show_bounds() const {
return ((_flags & F_has_show_bounds) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::has_show_tight_bounds
// Access: Public
// Description: If has_show_bounds() returns true, this will return
// true if the ShowBoundsEffect in question requests
// showing a "tight" bound.
////////////////////////////////////////////////////////////////////
INLINE bool RenderEffects::
has_show_tight_bounds() const {
if ((_flags & F_checked_show_bounds) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal show_bounds cache.
((RenderEffects *)this)->determine_show_bounds();
}
return ((_flags & F_has_show_tight_bounds) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::has_cull_callback
// Access: Public

View File

@ -592,6 +592,10 @@ determine_show_bounds() {
const RenderEffect *effect = get_effect(ShowBoundsEffect::get_class_type());
if (effect != (const RenderEffect *)NULL) {
_flags |= F_has_show_bounds;
const ShowBoundsEffect *sba = DCAST(ShowBoundsEffect, effect);
if (sba->get_tight()) {
_flags |= F_has_show_tight_bounds;
}
}
_flags |= F_checked_show_bounds;
}

View File

@ -97,6 +97,7 @@ PUBLISHED:
public:
INLINE bool has_decal() const;
INLINE bool has_show_bounds() const;
INLINE bool has_show_tight_bounds() const;
INLINE bool has_cull_callback() const;
void cull_callback(CullTraverser *trav, CullTraverserData &data,
@ -148,10 +149,11 @@ private:
F_has_decal = 0x0002,
F_checked_show_bounds = 0x0004,
F_has_show_bounds = 0x0008,
F_checked_cull_callback = 0x0010,
F_has_cull_callback = 0x0020,
F_checked_adjust_transform = 0x0040,
F_has_adjust_transform = 0x0080,
F_has_show_tight_bounds = 0x0010,
F_checked_cull_callback = 0x0020,
F_has_cull_callback = 0x0040,
F_checked_adjust_transform = 0x0080,
F_has_adjust_transform = 0x0100,
};
int _flags;

View File

@ -24,5 +24,19 @@
// ShowBoundsEffect object.
////////////////////////////////////////////////////////////////////
INLINE ShowBoundsEffect::
ShowBoundsEffect() {
ShowBoundsEffect() :
_tight(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: ShowBoundsEffect::get_tight
// Access: Published
// Description: Returns true if the "tight" flag was set, meaning the
// effect should compute and draw the tight bounding-box
// of the node's vertices every frame.
////////////////////////////////////////////////////////////////////
INLINE bool ShowBoundsEffect::
get_tight() const {
return _tight;
}

View File

@ -30,8 +30,9 @@ TypeHandle ShowBoundsEffect::_type_handle;
// Description: Constructs a new ShowBoundsEffect object.
////////////////////////////////////////////////////////////////////
CPT(RenderEffect) ShowBoundsEffect::
make() {
make(bool tight) {
ShowBoundsEffect *effect = new ShowBoundsEffect;
effect->_tight = tight;
return return_new(effect);
}
@ -64,25 +65,10 @@ safe_to_combine() const {
////////////////////////////////////////////////////////////////////
int ShowBoundsEffect::
compare_to_impl(const RenderEffect *other) const {
// All ShowBoundsEffects are equivalent--there are no properties to
// store.
return 0;
}
const ShowBoundsEffect *ta;
DCAST_INTO_R(ta, other, 0);
////////////////////////////////////////////////////////////////////
// Function: ShowBoundsEffect::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived ShowBoundsEffect
// types to specify what the default property for a
// ShowBoundsEffect of this type should be.
//
// This should return a newly-allocated ShowBoundsEffect of
// the same type that corresponds to whatever the
// standard default for this kind of ShowBoundsEffect is.
////////////////////////////////////////////////////////////////////
RenderEffect *ShowBoundsEffect::
make_default_impl() const {
return new ShowBoundsEffect;
return (int)_tight - (int)ta->_tight;
}
////////////////////////////////////////////////////////////////////
@ -105,6 +91,7 @@ register_with_read_factory() {
void ShowBoundsEffect::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderEffect::write_datagram(manager, dg);
dg.add_bool(_tight);
}
////////////////////////////////////////////////////////////////////
@ -137,4 +124,5 @@ make_from_bam(const FactoryParams &params) {
void ShowBoundsEffect::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderEffect::fillin(scan, manager);
_tight = scan.get_bool();
}

View File

@ -37,12 +37,16 @@ private:
INLINE ShowBoundsEffect();
PUBLISHED:
static CPT(RenderEffect) make();
static CPT(RenderEffect) make(bool tight = false);
INLINE bool get_tight() const;
protected:
virtual bool safe_to_combine() const;
virtual int compare_to_impl(const RenderEffect *other) const;
virtual RenderEffect *make_default_impl() const;
private:
bool _tight;
public:
static void register_with_read_factory();