diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 8d12ace4252..ddb4a1ee2cf 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -135,15 +135,29 @@ void Mesh::compute_bounds() size_t verts_size = verts.size(); size_t curve_keys_size = curve_keys.size(); - for(size_t i = 0; i < verts_size; i++) - bnds.grow(verts[i]); + if(verts_size + curve_keys_size > 0) { + for(size_t i = 0; i < verts_size; i++) + bnds.grow(verts[i]); - for(size_t i = 0; i < curve_keys_size; i++) - bnds.grow(curve_keys[i].co, curve_keys[i].radius); + for(size_t i = 0; i < curve_keys_size; i++) + bnds.grow(curve_keys[i].co, curve_keys[i].radius); - /* happens mostly on empty meshes */ - if(!bnds.valid()) + if(!bnds.valid()) { + bnds = BoundBox::empty; + + /* skip nan or inf coordinates */ + for(size_t i = 0; i < verts_size; i++) + bnds.grow_safe(verts[i]); + + for(size_t i = 0; i < curve_keys_size; i++) + bnds.grow_safe(curve_keys[i].co, curve_keys[i].radius); + } + } + + if(!bnds.valid()) { + /* empty mesh */ bnds.grow(make_float3(0.0f, 0.0f, 0.0f)); + } bounds = bnds; } diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index 7564c1f3c5c..3ee35b992f7 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -80,6 +80,31 @@ public: grow(bbox.max); } + __forceinline void grow_safe(const float3& pt) + { + /* the order of arguments to min is such that if pt is nan, it will not + * influence the resulting bounding box */ + if(isfinite(pt.x) && isfinite(pt.y) && isfinite(pt.z)) { + min = ccl::min(pt, min); + max = ccl::max(pt, max); + } + } + + __forceinline void grow_safe(const float3& pt, float border) + { + if(isfinite(pt.x) && isfinite(pt.y) && isfinite(pt.z) && isfinite(border)) { + float3 shift = {border, border, border, 0.0f}; + min = ccl::min(pt - shift, min); + max = ccl::max(pt + shift, max); + } + } + + __forceinline void grow_safe(const BoundBox& bbox) + { + grow_safe(bbox.min); + grow_safe(bbox.max); + } + __forceinline void intersect(const BoundBox& bbox) { min = ccl::max(min, bbox.min); @@ -120,7 +145,7 @@ public: { return max - min; } - + __forceinline bool valid() const { return (min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z) &&