mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
gobj: better handle NaNs in vertex data when calculating bounds
This commit is contained in:
parent
7995d483ab
commit
73452957ee
@ -1338,7 +1338,7 @@ 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 pmin, pmax;
|
LPoint3 pmin, pmax;
|
||||||
PN_stdfloat sq_center_dist;
|
PN_stdfloat sq_center_dist = 0.0f;
|
||||||
bool found_any = false;
|
bool found_any = false;
|
||||||
do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
|
do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any,
|
||||||
vertex_data, false, LMatrix4::ident_mat(),
|
vertex_data, false, LMatrix4::ident_mat(),
|
||||||
@ -1379,7 +1379,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
LPoint3 aabb_center = (pmin + pmax) * 0.5f;
|
LPoint3 aabb_center = (pmin + pmax) * 0.5f;
|
||||||
PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
|
PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared();
|
||||||
|
|
||||||
if (btype != BoundingVolume::BT_fastest &&
|
if (btype != BoundingVolume::BT_fastest && best_sq_radius > 0.0f &&
|
||||||
aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
|
aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) {
|
||||||
// Hmm, this is an off-center model. Maybe we can do a better job
|
// Hmm, this is an off-center model. Maybe we can do a better job
|
||||||
// by calculating the bounding sphere from the AABB center.
|
// by calculating the bounding sphere from the AABB center.
|
||||||
@ -1389,7 +1389,8 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
|
do_calc_sphere_radius(aabb_center, better_sq_radius, found_any,
|
||||||
vertex_data, cdata, current_thread);
|
vertex_data, cdata, current_thread);
|
||||||
|
|
||||||
if (found_any && better_sq_radius <= best_sq_radius) {
|
if (found_any && better_sq_radius > 0.0f &&
|
||||||
|
better_sq_radius <= best_sq_radius) {
|
||||||
// Great. This is as good a sphere as we're going to get.
|
// Great. This is as good a sphere as we're going to get.
|
||||||
if (btype == BoundingVolume::BT_best &&
|
if (btype == BoundingVolume::BT_best &&
|
||||||
avg_box_area < better_sq_radius * MathNumbers::pi) {
|
avg_box_area < better_sq_radius * MathNumbers::pi) {
|
||||||
@ -1409,7 +1410,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
cdata->_internal_bounds = new BoundingBox(pmin, pmax);
|
cdata->_internal_bounds = new BoundingBox(pmin, pmax);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else if (sq_center_dist <= best_sq_radius) {
|
} else if (sq_center_dist >= 0.0f && sq_center_dist <= best_sq_radius) {
|
||||||
// No, but a sphere centered on the origin is apparently still
|
// No, but a sphere centered on the origin is apparently still
|
||||||
// better than a sphere around the bounding box.
|
// better than a sphere around the bounding box.
|
||||||
cdata->_internal_bounds =
|
cdata->_internal_bounds =
|
||||||
@ -1420,7 +1421,8 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||||||
// This is the worst sphere we can make, which is why we will only
|
// This is the worst sphere we can make, which is why we will only
|
||||||
// do it when the user specifically requests a sphere.
|
// do it when the user specifically requests a sphere.
|
||||||
cdata->_internal_bounds =
|
cdata->_internal_bounds =
|
||||||
new BoundingSphere(aabb_center, csqrt(best_sq_radius));
|
new BoundingSphere(aabb_center,
|
||||||
|
(best_sq_radius > 0.0f) ? csqrt(best_sq_radius) : 0.0f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1607,13 +1607,16 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (got_mat) {
|
if (got_mat) {
|
||||||
if (!found_any) {
|
// Find the first non-NaN vertex.
|
||||||
reader.set_row_unsafe(cdata->_first_vertex);
|
while (!found_any && i < cdata->_num_vertices) {
|
||||||
|
reader.set_row(cdata->_first_vertex + i);
|
||||||
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
||||||
min_point = first_vertex;
|
if (!first_vertex.is_nan()) {
|
||||||
max_point = first_vertex;
|
min_point = first_vertex;
|
||||||
sq_center_dist = first_vertex.length_squared();
|
max_point = first_vertex;
|
||||||
found_any = true;
|
sq_center_dist = first_vertex.length_squared();
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1630,13 +1633,16 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!found_any) {
|
// Find the first non-NaN vertex.
|
||||||
reader.set_row_unsafe(cdata->_first_vertex);
|
while (!found_any && i < cdata->_num_vertices) {
|
||||||
const LVecBase3 &first_vertex = reader.get_data3();
|
reader.set_row(cdata->_first_vertex + i);
|
||||||
min_point = first_vertex;
|
LPoint3 first_vertex = reader.get_data3();
|
||||||
max_point = first_vertex;
|
if (!first_vertex.is_nan()) {
|
||||||
sq_center_dist = first_vertex.length_squared();
|
min_point = first_vertex;
|
||||||
found_any = true;
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1664,15 +1670,19 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
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) {
|
// Find the first non-NaN vertex.
|
||||||
int first_index = index.get_data1i();
|
while (!found_any && !index.is_at_end()) {
|
||||||
nassertv(first_index != strip_cut_index);
|
int ii = index.get_data1i();
|
||||||
reader.set_row_unsafe(first_index);
|
if (ii != strip_cut_index) {
|
||||||
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
reader.set_row(ii);
|
||||||
min_point = first_vertex;
|
LPoint3 first_vertex = mat.xform_point(reader.get_data3());
|
||||||
max_point = first_vertex;
|
if (!first_vertex.is_nan()) {
|
||||||
sq_center_dist = first_vertex.length_squared();
|
min_point = first_vertex;
|
||||||
found_any = true;
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!index.is_at_end()) {
|
while (!index.is_at_end()) {
|
||||||
@ -1692,15 +1702,19 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||||||
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
sq_center_dist = max(sq_center_dist, vertex.length_squared());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!found_any) {
|
// Find the first non-NaN vertex.
|
||||||
int first_index = index.get_data1i();
|
while (!found_any && !index.is_at_end()) {
|
||||||
nassertv(first_index != strip_cut_index);
|
int ii = index.get_data1i();
|
||||||
reader.set_row_unsafe(first_index);
|
if (ii != strip_cut_index) {
|
||||||
const LVecBase3 &first_vertex = reader.get_data3();
|
reader.set_row(ii);
|
||||||
min_point = first_vertex;
|
LVecBase3 first_vertex = reader.get_data3();
|
||||||
max_point = first_vertex;
|
if (!first_vertex.is_nan()) {
|
||||||
sq_center_dist = first_vertex.length_squared();
|
min_point = first_vertex;
|
||||||
found_any = true;
|
max_point = first_vertex;
|
||||||
|
sq_center_dist = first_vertex.length_squared();
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!index.is_at_end()) {
|
while (!index.is_at_end()) {
|
||||||
|
@ -40,3 +40,45 @@ def test_geom_decompose():
|
|||||||
|
|
||||||
# Old primitive should still be unchanged
|
# Old primitive should still be unchanged
|
||||||
assert prim == geom.get_primitive(0)
|
assert prim == geom.get_primitive(0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_geom_calc_sphere_bounds():
|
||||||
|
# Ensure that it ignores NaN
|
||||||
|
data = core.GeomVertexData("", core.GeomVertexFormat.get_v3(), core.Geom.UH_static)
|
||||||
|
vertex = core.GeomVertexWriter(data, "vertex")
|
||||||
|
vertex.add_data3((float("NaN"), 0, 0))
|
||||||
|
vertex.add_data3((1, 1, 1))
|
||||||
|
vertex.add_data3((1, 1, 2))
|
||||||
|
|
||||||
|
prim = core.GeomPoints(core.Geom.UH_static)
|
||||||
|
prim.add_next_vertices(3)
|
||||||
|
|
||||||
|
geom = core.Geom(data)
|
||||||
|
geom.add_primitive(prim)
|
||||||
|
geom.set_bounds_type(core.BoundingVolume.BT_sphere)
|
||||||
|
|
||||||
|
bounds = geom.get_bounds()
|
||||||
|
assert isinstance(bounds, core.BoundingSphere)
|
||||||
|
assert bounds.get_center() == (1, 1, 1.5)
|
||||||
|
assert bounds.get_radius() == 0.5
|
||||||
|
|
||||||
|
|
||||||
|
def test_geom_calc_box_bounds():
|
||||||
|
# Ensure that it ignores NaN
|
||||||
|
data = core.GeomVertexData("", core.GeomVertexFormat.get_v3(), core.Geom.UH_static)
|
||||||
|
vertex = core.GeomVertexWriter(data, "vertex")
|
||||||
|
vertex.add_data3((float("NaN"), 0, 0))
|
||||||
|
vertex.add_data3((1, 1, 1))
|
||||||
|
vertex.add_data3((1, 1, 2))
|
||||||
|
|
||||||
|
prim = core.GeomPoints(core.Geom.UH_static)
|
||||||
|
prim.add_next_vertices(3)
|
||||||
|
|
||||||
|
geom = core.Geom(data)
|
||||||
|
geom.add_primitive(prim)
|
||||||
|
geom.set_bounds_type(core.BoundingVolume.BT_box)
|
||||||
|
|
||||||
|
bounds = geom.get_bounds()
|
||||||
|
assert isinstance(bounds, core.BoundingBox)
|
||||||
|
assert bounds.get_min() == (1, 1, 1)
|
||||||
|
assert bounds.get_max() == (1, 1, 2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user