mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
Cull improvements: tighter sphere generation
This commit is contained in:
parent
c04cd29246
commit
b9899ba747
@ -386,7 +386,8 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
Thread *current_thread) const {
|
Thread *current_thread) const {
|
||||||
CDReader cdata(_cycler, current_thread);
|
CDReader cdata(_cycler, current_thread);
|
||||||
|
|
||||||
do_calc_tight_bounds(min_point, max_point, found_any,
|
PN_stdfloat sq_radius;
|
||||||
|
do_calc_tight_bounds(min_point, max_point, sq_radius, found_any,
|
||||||
vertex_data, got_mat, mat,
|
vertex_data, got_mat, mat,
|
||||||
InternalName::get_vertex(),
|
InternalName::get_vertex(),
|
||||||
cdata, current_thread);
|
cdata, current_thread);
|
||||||
@ -408,6 +409,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
INLINE void Geom::
|
INLINE void Geom::
|
||||||
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
||||||
bool &found_any, Thread *current_thread) const {
|
bool &found_any, Thread *current_thread) const {
|
||||||
|
|
||||||
calc_tight_bounds(min_point, max_point, found_any,
|
calc_tight_bounds(min_point, max_point, found_any,
|
||||||
get_vertex_data(current_thread), false,
|
get_vertex_data(current_thread), false,
|
||||||
LMatrix4::ident_mat(),
|
LMatrix4::ident_mat(),
|
||||||
@ -429,7 +431,8 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
Thread *current_thread) const {
|
Thread *current_thread) const {
|
||||||
CDReader cdata(_cycler, current_thread);
|
CDReader cdata(_cycler, current_thread);
|
||||||
|
|
||||||
do_calc_tight_bounds(min_point, max_point, found_any,
|
PN_stdfloat sq_radius;
|
||||||
|
do_calc_tight_bounds(min_point, max_point, sq_radius, found_any,
|
||||||
vertex_data, got_mat, mat,
|
vertex_data, got_mat, mat,
|
||||||
column_name, cdata, current_thread);
|
column_name, cdata, current_thread);
|
||||||
}
|
}
|
||||||
|
@ -1304,10 +1304,11 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
|
|
||||||
// Now actually compute the bounding volume. We do this by using
|
// Now actually compute the bounding volume. We do this by using
|
||||||
// calc_tight_bounds to determine our box first.
|
// calc_tight_bounds to determine our box first.
|
||||||
LPoint3 min, max;
|
LPoint3 pmin, pmax;
|
||||||
|
PN_stdfloat sq_center_dist;
|
||||||
bool found_any = false;
|
bool found_any = false;
|
||||||
do_calc_tight_bounds(min, max, found_any, vertex_data,
|
do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
|
||||||
false, LMatrix4::ident_mat(),
|
vertex_data, false, LMatrix4::ident_mat(),
|
||||||
InternalName::get_vertex(),
|
InternalName::get_vertex(),
|
||||||
cdata, current_thread);
|
cdata, current_thread);
|
||||||
|
|
||||||
@ -1318,18 +1319,79 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
|
|
||||||
if (found_any) {
|
if (found_any) {
|
||||||
// Then we put the bounding volume around both of those points.
|
// Then we put the bounding volume around both of those points.
|
||||||
if (btype == BoundingVolume::BT_sphere) {
|
PN_stdfloat avg_box_area;
|
||||||
// The user specifically requested a BoundingSphere, so oblige.
|
switch (btype) {
|
||||||
BoundingBox box(min, max);
|
case BoundingVolume::BT_best:
|
||||||
box.local_object();
|
case BoundingVolume::BT_fastest:
|
||||||
|
case BoundingVolume::BT_default:
|
||||||
|
{
|
||||||
|
// When considering a box, calculate (roughly) the average area
|
||||||
|
// of the sides. We will use this to determine whether a sphere
|
||||||
|
// or box is a better fit.
|
||||||
|
PN_stdfloat min_extent = min(pmax[0] - pmin[0],
|
||||||
|
min(pmax[1] - pmin[1],
|
||||||
|
pmax[2] - pmin[2]));
|
||||||
|
PN_stdfloat max_extent = max(pmax[0] - pmin[0],
|
||||||
|
max(pmax[1] - pmin[1],
|
||||||
|
pmax[2] - pmin[2]));
|
||||||
|
avg_box_area = ((min_extent * min_extent) + (max_extent * max_extent)) / 2;
|
||||||
|
}
|
||||||
|
// Fall through
|
||||||
|
case BoundingVolume::BT_sphere:
|
||||||
|
{
|
||||||
|
// Determine the best radius for a bounding sphere.
|
||||||
|
LPoint3 aabb_center = (pmin + pmax) * 0.5f;
|
||||||
|
PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
|
||||||
|
|
||||||
PT(BoundingSphere) sphere = new BoundingSphere;
|
if (btype != BoundingVolume::BT_fastest &&
|
||||||
sphere->extend_by(&box);
|
aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
|
||||||
cdata->_internal_bounds = sphere;
|
// Hmm, this is an off-center model. Maybe we can do a better
|
||||||
|
// job by calculating the bounding sphere from the AABB center.
|
||||||
|
|
||||||
} else {
|
PN_stdfloat better_sq_radius;
|
||||||
// The user requested a BoundingBox, or did not specify.
|
bool found_any = false;
|
||||||
cdata->_internal_bounds = new BoundingBox(min, max);
|
do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
|
||||||
|
vertex_data, cdata, current_thread);
|
||||||
|
|
||||||
|
if (found_any && better_sq_radius <= best_sq_radius) {
|
||||||
|
// Great. This is as good a sphere as we're going to get.
|
||||||
|
if (btype == BoundingVolume::BT_best &&
|
||||||
|
avg_box_area < better_sq_radius * MathNumbers::pi) {
|
||||||
|
// But the box is better, anyway. Use that instead.
|
||||||
|
cdata->_internal_bounds = new BoundingBox(pmin, pmax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cdata->_internal_bounds =
|
||||||
|
new BoundingSphere(aabb_center, csqrt(better_sq_radius));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btype != BoundingVolume::BT_sphere &&
|
||||||
|
avg_box_area < sq_center_dist * MathNumbers::pi) {
|
||||||
|
// A box is probably a tighter fit.
|
||||||
|
cdata->_internal_bounds = new BoundingBox(pmin, pmax);
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (sq_center_dist <= best_sq_radius) {
|
||||||
|
// No, but a sphere centered on the origin is apparently
|
||||||
|
// still better than a sphere around the bounding box.
|
||||||
|
cdata->_internal_bounds =
|
||||||
|
new BoundingSphere(LPoint3::origin(), csqrt(sq_center_dist));
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (btype == BoundingVolume::BT_sphere) {
|
||||||
|
// This is the worst sphere we can make, which is why we will only
|
||||||
|
// do it when the user specifically requests a sphere.
|
||||||
|
cdata->_internal_bounds =
|
||||||
|
new BoundingSphere(aabb_center, csqrt(best_sq_radius));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fall through.
|
||||||
|
|
||||||
|
case BoundingVolume::BT_box:
|
||||||
|
cdata->_internal_bounds = new BoundingBox(pmin, pmax);
|
||||||
}
|
}
|
||||||
|
|
||||||
Primitives::const_iterator pi;
|
Primitives::const_iterator pi;
|
||||||
@ -1360,7 +1422,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void Geom::
|
void Geom::
|
||||||
do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
||||||
bool &found_any,
|
PN_stdfloat &sq_center_dist, bool &found_any,
|
||||||
const GeomVertexData *vertex_data,
|
const GeomVertexData *vertex_data,
|
||||||
bool got_mat, const LMatrix4 &mat,
|
bool got_mat, const LMatrix4 &mat,
|
||||||
const InternalName *column_name,
|
const InternalName *column_name,
|
||||||
@ -1370,8 +1432,28 @@ do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
pi != cdata->_primitives.end();
|
pi != cdata->_primitives.end();
|
||||||
++pi) {
|
++pi) {
|
||||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
||||||
prim->calc_tight_bounds(min_point, max_point, found_any, vertex_data,
|
prim->calc_tight_bounds(min_point, max_point, sq_center_dist,
|
||||||
got_mat, mat, column_name, current_thread);
|
found_any, vertex_data, got_mat, mat,
|
||||||
|
column_name, current_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Geom::do_calc_sphere_radius
|
||||||
|
// Access: Private
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Geom::
|
||||||
|
do_calc_sphere_radius(const LPoint3 ¢er, PN_stdfloat &sq_radius,
|
||||||
|
bool &found_any, const GeomVertexData *vertex_data,
|
||||||
|
const CData *cdata, Thread *current_thread) const {
|
||||||
|
Primitives::const_iterator pi;
|
||||||
|
for (pi = cdata->_primitives.begin();
|
||||||
|
pi != cdata->_primitives.end();
|
||||||
|
++pi) {
|
||||||
|
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
||||||
|
prim->calc_sphere_radius(center, sq_radius, found_any,
|
||||||
|
vertex_data, current_thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,12 +174,17 @@ private:
|
|||||||
void compute_internal_bounds(CData *cdata, Thread *current_thread) const;
|
void compute_internal_bounds(CData *cdata, Thread *current_thread) const;
|
||||||
|
|
||||||
void do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
void do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
||||||
bool &found_any,
|
PN_stdfloat &sq_center_dist, bool &found_any,
|
||||||
const GeomVertexData *vertex_data,
|
const GeomVertexData *vertex_data,
|
||||||
bool got_mat, const LMatrix4 &mat,
|
bool got_mat, const LMatrix4 &mat,
|
||||||
const InternalName *column_name,
|
const InternalName *column_name,
|
||||||
const CData *cdata, Thread *current_thread) const;
|
const CData *cdata, Thread *current_thread) const;
|
||||||
|
|
||||||
|
void do_calc_sphere_radius(const LPoint3 ¢er,
|
||||||
|
PN_stdfloat &sq_radius, bool &found_any,
|
||||||
|
const GeomVertexData *vertex_data,
|
||||||
|
const CData *cdata, Thread *current_thread) const;
|
||||||
|
|
||||||
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
||||||
bool check_will_be_valid(const GeomVertexData *vertex_data) const;
|
bool check_will_be_valid(const GeomVertexData *vertex_data) const;
|
||||||
|
|
||||||
|
@ -1699,10 +1699,14 @@ get_strip_cut_index(NumericType index_type) {
|
|||||||
// points are found. It is the caller's responsibility
|
// points are found. It is the caller's responsibility
|
||||||
// to initialize min_point, max_point, and found_any
|
// to initialize min_point, max_point, and found_any
|
||||||
// before calling this function.
|
// before calling this function.
|
||||||
|
// It also sets sq_center_dist, which is the square of
|
||||||
|
// the maximum distance of the points to the center.
|
||||||
|
// This can be useful when deciding whether a sphere
|
||||||
|
// volume might be more appropriate.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GeomPrimitive::
|
void GeomPrimitive::
|
||||||
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
||||||
bool &found_any,
|
PN_stdfloat &sq_center_dist, bool &found_any,
|
||||||
const GeomVertexData *vertex_data,
|
const GeomVertexData *vertex_data,
|
||||||
bool got_mat, const LMatrix4 &mat,
|
bool got_mat, const LMatrix4 &mat,
|
||||||
const InternalName *column_name,
|
const InternalName *column_name,
|
||||||
@ -1714,54 +1718,84 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CDReader cdata(_cycler, current_thread);
|
CDReader cdata(_cycler, current_thread);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
if (cdata->_vertices.is_null()) {
|
if (cdata->_vertices.is_null()) {
|
||||||
// Nonindexed case.
|
// Nonindexed case.
|
||||||
nassertv(cdata->_num_vertices != -1);
|
nassertv(cdata->_num_vertices != -1);
|
||||||
|
if (cdata->_num_vertices == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (got_mat) {
|
if (got_mat) {
|
||||||
for (int i = 0; i < cdata->_num_vertices; i++) {
|
if (!found_any) {
|
||||||
|
reader.set_row_unsafe(cdata->_first_vertex);
|
||||||
|
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
||||||
|
min_point = first_vertex;
|
||||||
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
|
found_any = true;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < cdata->_num_vertices; ++i) {
|
||||||
reader.set_row_unsafe(cdata->_first_vertex + i);
|
reader.set_row_unsafe(cdata->_first_vertex + i);
|
||||||
LPoint3 vertex = mat.xform_point(reader.get_data3());
|
LPoint3 vertex = mat.xform_point(reader.get_data3());
|
||||||
|
|
||||||
if (found_any) {
|
|
||||||
min_point.set(min(min_point[0], vertex[0]),
|
min_point.set(min(min_point[0], vertex[0]),
|
||||||
min(min_point[1], vertex[1]),
|
min(min_point[1], vertex[1]),
|
||||||
min(min_point[2], vertex[2]));
|
min(min_point[2], vertex[2]));
|
||||||
max_point.set(max(max_point[0], vertex[0]),
|
max_point.set(max(max_point[0], vertex[0]),
|
||||||
max(max_point[1], vertex[1]),
|
max(max_point[1], vertex[1]),
|
||||||
max(max_point[2], vertex[2]));
|
max(max_point[2], vertex[2]));
|
||||||
|
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
min_point = vertex;
|
if (!found_any) {
|
||||||
max_point = vertex;
|
reader.set_row_unsafe(cdata->_first_vertex);
|
||||||
|
const LVecBase3 &first_vertex = reader.get_data3();
|
||||||
|
min_point = first_vertex;
|
||||||
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
found_any = true;
|
found_any = true;
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
for (; i < cdata->_num_vertices; ++i) {
|
||||||
for (int i = 0; i < cdata->_num_vertices; i++) {
|
|
||||||
reader.set_row_unsafe(cdata->_first_vertex + i);
|
reader.set_row_unsafe(cdata->_first_vertex + i);
|
||||||
const LVecBase3 &vertex = reader.get_data3();
|
const LVecBase3 &vertex = reader.get_data3();
|
||||||
|
|
||||||
if (found_any) {
|
|
||||||
min_point.set(min(min_point[0], vertex[0]),
|
min_point.set(min(min_point[0], vertex[0]),
|
||||||
min(min_point[1], vertex[1]),
|
min(min_point[1], vertex[1]),
|
||||||
min(min_point[2], vertex[2]));
|
min(min_point[2], vertex[2]));
|
||||||
max_point.set(max(max_point[0], vertex[0]),
|
max_point.set(max(max_point[0], vertex[0]),
|
||||||
max(max_point[1], vertex[1]),
|
max(max_point[1], vertex[1]),
|
||||||
max(max_point[2], vertex[2]));
|
max(max_point[2], vertex[2]));
|
||||||
} else {
|
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
||||||
min_point = vertex;
|
|
||||||
max_point = vertex;
|
|
||||||
found_any = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Indexed case.
|
// Indexed case.
|
||||||
GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
|
GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
|
||||||
|
if (index.is_at_end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int strip_cut_index = get_strip_cut_index(cdata->_index_type);
|
int strip_cut_index = get_strip_cut_index(cdata->_index_type);
|
||||||
|
|
||||||
if (got_mat) {
|
if (got_mat) {
|
||||||
|
if (!found_any) {
|
||||||
|
int first_index = index.get_data1i();
|
||||||
|
nassertv(first_index != strip_cut_index);
|
||||||
|
reader.set_row_unsafe(first_index);
|
||||||
|
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
||||||
|
min_point = first_vertex;
|
||||||
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
|
|
||||||
while (!index.is_at_end()) {
|
while (!index.is_at_end()) {
|
||||||
int ii = index.get_data1i();
|
int ii = index.get_data1i();
|
||||||
if (ii == strip_cut_index) {
|
if (ii == strip_cut_index) {
|
||||||
@ -1770,20 +1804,26 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
reader.set_row_unsafe(ii);
|
reader.set_row_unsafe(ii);
|
||||||
LPoint3 vertex = mat.xform_point(reader.get_data3());
|
LPoint3 vertex = mat.xform_point(reader.get_data3());
|
||||||
|
|
||||||
if (found_any) {
|
|
||||||
min_point.set(min(min_point[0], vertex[0]),
|
min_point.set(min(min_point[0], vertex[0]),
|
||||||
min(min_point[1], vertex[1]),
|
min(min_point[1], vertex[1]),
|
||||||
min(min_point[2], vertex[2]));
|
min(min_point[2], vertex[2]));
|
||||||
max_point.set(max(max_point[0], vertex[0]),
|
max_point.set(max(max_point[0], vertex[0]),
|
||||||
max(max_point[1], vertex[1]),
|
max(max_point[1], vertex[1]),
|
||||||
max(max_point[2], vertex[2]));
|
max(max_point[2], vertex[2]));
|
||||||
|
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
min_point = vertex;
|
if (!found_any) {
|
||||||
max_point = vertex;
|
int first_index = index.get_data1i();
|
||||||
|
nassertv(first_index != strip_cut_index);
|
||||||
|
reader.set_row_unsafe(first_index);
|
||||||
|
const LVecBase3 &first_vertex = reader.get_data3();
|
||||||
|
min_point = first_vertex;
|
||||||
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
found_any = true;
|
found_any = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (!index.is_at_end()) {
|
while (!index.is_at_end()) {
|
||||||
int ii = index.get_data1i();
|
int ii = index.get_data1i();
|
||||||
if (ii == strip_cut_index) {
|
if (ii == strip_cut_index) {
|
||||||
@ -1792,19 +1832,77 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
reader.set_row_unsafe(ii);
|
reader.set_row_unsafe(ii);
|
||||||
const LVecBase3 &vertex = reader.get_data3();
|
const LVecBase3 &vertex = reader.get_data3();
|
||||||
|
|
||||||
if (found_any) {
|
|
||||||
min_point.set(min(min_point[0], vertex[0]),
|
min_point.set(min(min_point[0], vertex[0]),
|
||||||
min(min_point[1], vertex[1]),
|
min(min_point[1], vertex[1]),
|
||||||
min(min_point[2], vertex[2]));
|
min(min_point[2], vertex[2]));
|
||||||
max_point.set(max(max_point[0], vertex[0]),
|
max_point.set(max(max_point[0], vertex[0]),
|
||||||
max(max_point[1], vertex[1]),
|
max(max_point[1], vertex[1]),
|
||||||
max(max_point[2], vertex[2]));
|
max(max_point[2], vertex[2]));
|
||||||
} else {
|
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
||||||
min_point = vertex;
|
}
|
||||||
max_point = vertex;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomPrimitive::calc_sphere_radius
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Expands radius so that a sphere with the given
|
||||||
|
// center point fits all of the vertices.
|
||||||
|
//
|
||||||
|
// The center point is assumed to already have been
|
||||||
|
// transformed by the matrix, if one is given.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomPrimitive::
|
||||||
|
calc_sphere_radius(const LPoint3 ¢er, PN_stdfloat &sq_radius,
|
||||||
|
bool &found_any, const GeomVertexData *vertex_data,
|
||||||
|
Thread *current_thread) const {
|
||||||
|
GeomVertexReader reader(vertex_data, InternalName::get_vertex(), current_thread);
|
||||||
|
if (!reader.has_column()) {
|
||||||
|
// No vertex data.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_any) {
|
||||||
|
sq_radius = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CDReader cdata(_cycler, current_thread);
|
||||||
|
|
||||||
|
if (cdata->_vertices.is_null()) {
|
||||||
|
// Nonindexed case.
|
||||||
|
nassertv(cdata->_num_vertices != -1);
|
||||||
|
if (cdata->_num_vertices == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
found_any = true;
|
found_any = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < cdata->_num_vertices; ++i) {
|
||||||
|
reader.set_row_unsafe(cdata->_first_vertex + i);
|
||||||
|
const LVecBase3 &vertex = reader.get_data3();
|
||||||
|
|
||||||
|
sq_radius = max(sq_radius, (vertex - center).length_squared());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Indexed case.
|
||||||
|
GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
|
||||||
|
if (index.is_at_end()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
found_any = true;
|
||||||
|
|
||||||
|
int strip_cut_index = get_strip_cut_index(cdata->_index_type);
|
||||||
|
|
||||||
|
while (!index.is_at_end()) {
|
||||||
|
int ii = index.get_data1i();
|
||||||
|
if (ii == strip_cut_index) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
reader.set_row_unsafe(ii);
|
||||||
|
const LVecBase3 &vertex = reader.get_data3();
|
||||||
|
|
||||||
|
sq_radius = max(sq_radius, (vertex - center).length_squared());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,12 +207,17 @@ public:
|
|||||||
bool force) const=0;
|
bool force) const=0;
|
||||||
|
|
||||||
void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
||||||
bool &found_any,
|
PN_stdfloat &sq_center_dist, bool &found_any,
|
||||||
const GeomVertexData *vertex_data,
|
const GeomVertexData *vertex_data,
|
||||||
bool got_mat, const LMatrix4 &mat,
|
bool got_mat, const LMatrix4 &mat,
|
||||||
const InternalName *column_name,
|
const InternalName *column_name,
|
||||||
Thread *current_thread) const;
|
Thread *current_thread) const;
|
||||||
|
|
||||||
|
void calc_sphere_radius(const LPoint3 ¢er,
|
||||||
|
PN_stdfloat &sq_radius, bool &found_any,
|
||||||
|
const GeomVertexData *vertex_data,
|
||||||
|
Thread *current_thread) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual CPT(GeomPrimitive) decompose_impl() const;
|
virtual CPT(GeomPrimitive) decompose_impl() const;
|
||||||
virtual CPT(GeomVertexArrayData) rotate_impl() const;
|
virtual CPT(GeomVertexArrayData) rotate_impl() const;
|
||||||
|
@ -182,6 +182,9 @@ string_bounds_type(const string &str) {
|
|||||||
} else if (strcmp(str.c_str(), "best") == 0) {
|
} else if (strcmp(str.c_str(), "best") == 0) {
|
||||||
return BT_best;
|
return BT_best;
|
||||||
|
|
||||||
|
} else if (strcmp(str.c_str(), "fastest") == 0) {
|
||||||
|
return BT_fastest;
|
||||||
|
|
||||||
} else if (strcmp(str.c_str(), "sphere") == 0) {
|
} else if (strcmp(str.c_str(), "sphere") == 0) {
|
||||||
return BT_sphere;
|
return BT_sphere;
|
||||||
|
|
||||||
@ -521,6 +524,9 @@ operator << (ostream &out, BoundingVolume::BoundsType type) {
|
|||||||
case BoundingVolume::BT_best:
|
case BoundingVolume::BT_best:
|
||||||
return out << "best";
|
return out << "best";
|
||||||
|
|
||||||
|
case BoundingVolume::BT_fastest:
|
||||||
|
return out << "fastest";
|
||||||
|
|
||||||
case BoundingVolume::BT_sphere:
|
case BoundingVolume::BT_sphere:
|
||||||
return out << "sphere";
|
return out << "sphere";
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ PUBLISHED:
|
|||||||
BT_best,
|
BT_best,
|
||||||
BT_sphere,
|
BT_sphere,
|
||||||
BT_box,
|
BT_box,
|
||||||
|
BT_fastest,
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -50,7 +50,9 @@ ConfigVariableEnum<BoundingVolume::BoundsType> bounds_type
|
|||||||
("bounds-type", BoundingVolume::BT_sphere,
|
("bounds-type", BoundingVolume::BT_sphere,
|
||||||
PRC_DESC("Specify the type of bounding volume that is created automatically "
|
PRC_DESC("Specify the type of bounding volume that is created automatically "
|
||||||
"by Panda to enclose geometry. Use 'sphere' or 'box', or use "
|
"by Panda to enclose geometry. Use 'sphere' or 'box', or use "
|
||||||
"'best' to let Panda decide which is most appropriate."));
|
"'best' to let Panda decide which is most appropriate. You can "
|
||||||
|
"also use 'fastest' if you don't want Panda to waste much time "
|
||||||
|
"computing the most optimal bounding volume."));
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: init_libmathutil
|
// Function: init_libmathutil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user