dont crash if there's infinity or NaN in transformation matrix

felipesanches-svg
don bright 2012-08-21 01:33:13 +02:00
parent 0170923b9b
commit f1d4a52f4c
4 changed files with 44 additions and 1 deletions

View File

@ -241,6 +241,15 @@ Response CGALEvaluator::visit(State &state, const TransformNode &node)
// First union all children
N = applyToChildren(node, CGE_UNION);
if ( matrix_contains_infinity( node.matrix ) ) {
PRINT("Warning: Transformation matrix contains Infinity - removing object.");
N.reset();
}
if ( matrix_contains_nan( node.matrix ) ) {
PRINT("Warning: Transformation matrix contains Not-a-Number - removing object");
N.reset();
}
// Then apply transform
// If there is no geometry under the transform, N will be empty and of dim 0,
// just just silently ignore such nodes
@ -248,7 +257,7 @@ Response CGALEvaluator::visit(State &state, const TransformNode &node)
// Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2
// objects. So we convert in to our internal 2d data format, transform it,
// tesselate it and create a new CGAL_Nef_polyhedron2 from it.. What a hack!
Eigen::Matrix2f testmat;
testmat << node.matrix(0,0), node.matrix(0,1), node.matrix(1,0), node.matrix(1,1);
if (testmat.determinant() == 0) {

View File

@ -1,4 +1,5 @@
#include "linalg.h"
#include <boost/math/special_functions/fpclassify.hpp>
// FIXME: We can achieve better pruning by either:
// o Recalculate the box based on the transformed object
@ -25,3 +26,23 @@ BoundingBox operator*(const Transform3d &m, const BoundingBox &box)
return newbox;
}
bool matrix_contains_infinity( const Eigen::Transform3d &m )
{
for (int i=0;i<m.matrix().rows();i++) {
for (int j=0;j<m.matrix().cols();j++) {
if ((boost::math::isinf)(m(i,j))) return true;
}
}
return false;
}
bool matrix_contains_nan( const Eigen::Transform3d &m )
{
for (int i=0;i<m.matrix().rows();i++) {
for (int j=0;j<m.matrix().cols();j++) {
if ((boost::math::isnan)(m(i,j))) return true;
}
}
return false;
}

View File

@ -14,6 +14,9 @@ using Eigen::Matrix3d;
using Eigen::Matrix4d;
using Eigen::Transform3d;
bool matrix_contains_infinity( const Eigen::Transform3d &m );
bool matrix_contains_nan( const Eigen::Transform3d &m );
BoundingBox operator*(const Transform3d &m, const BoundingBox &box);
class Color4f : public Eigen::Vector4f

View File

@ -0,0 +1,10 @@
// Test translation by NaN and Infinity
// NaN test - cube(2) should not be rendered
cube(1);
angle = asin(1.1);
render()
rotate([0, 0, angle])
cube(2);
// FIXME: how do you test infinity?