From d7c1ab11917a180124b827c15c9e0a26536f4413 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Wed, 24 Oct 2012 23:40:25 -0400 Subject: [PATCH] support for extrapolating values when doing cubic spline interpolation --- include/mitsuba/core/util.h | 42 +++++++++++++++++++++++--------- include/mitsuba/render/trimesh.h | 11 +++++++-- src/libcore/util.cpp | 24 +++++++++--------- src/librender/trimesh.cpp | 7 +++--- 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/include/mitsuba/core/util.h b/include/mitsuba/core/util.h index 46089548..c31e6df7 100644 --- a/include/mitsuba/core/util.h +++ b/include/mitsuba/core/util.h @@ -358,11 +358,14 @@ extern MTS_EXPORT_CORE bool solveQuadraticDouble(double a, double b, * Position of the last knot * \param size * Denotes the size of the \c data array + * \param extrapolate + * Extrapolate data values when \c x is out of range? (default: \c false) * \return - * The interpolated value or zero when \c x lies outside of [\c min, \c max] + * The interpolated value or zero when extrapolate=falsett> + * and \c x lies outside of [\c min, \c max] */ extern MTS_EXPORT_CORE Float interpCubic1D(Float x, const Float *data, - Float min, Float max, size_t size); + Float min, Float max, size_t size, bool extrapolate = false); /** * \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 1D function @@ -382,11 +385,14 @@ extern MTS_EXPORT_CORE Float interpCubic1D(Float x, const Float *data, * the entries of \c nodes. * \param size * Denotes the size of the \c data array + * \param extrapolate + * Extrapolate data values when \c x is out of range? (default: \c false) * \return - * The interpolated value or zero when \c x lies outside of \a [\c min, \c max] + * The interpolated value or zero when extrapolate=falsett> + * and \c x lies outside of \a [\c min, \c max] */ extern MTS_EXPORT Float interpCubic1DIrregular(Float x, const Float *nodes, - const Float *data, size_t size); + const Float *data, size_t size, bool extrapolate = false); /** * \brief Evaluate a cubic spline interpolant of a regularly sampled 2D function @@ -407,11 +413,14 @@ extern MTS_EXPORT Float interpCubic1DIrregular(Float x, const Float *nodes, * Position of the last knot on each dimension * \param size * Denotes the size of the \c data array (along each dimension) + * \param extrapolate + * Extrapolate data values when \c p is out of range? (default: \c false) * \return - * The interpolated value or zero when \c p lies outside of the knot range + * The interpolated value or zero when extrapolate=falsett> and + * \c p lies outside of the knot range */ extern MTS_EXPORT_CORE Float interpCubic2D(const Point2 &p, const Float *data, - const Point2 &min, const Point2 &max, const Size2 &size); + const Point2 &min, const Point2 &max, const Size2 &size, bool extrapolate = false); /** * \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 2D function @@ -435,11 +444,14 @@ extern MTS_EXPORT_CORE Float interpCubic2D(const Point2 &p, const Float *data, * Consecutive entries of this array correspond to increments in the 'x' coordinate. * \param size * Denotes the size of the \c data array (along each dimension) + * \param extrapolate + * Extrapolate data values when \c p is out of range? (default: \c false) * \return - * The interpolated value or zero when \c p lies outside of the knot range + * The interpolated value or zero when extrapolate=falsett> and + * \c p lies outside of the knot range */ extern MTS_EXPORT_CORE Float interpCubic2DIrregular(const Point2 &p, const Float **nodes, - const Float *data, const Size2 &size); + const Float *data, const Size2 &size, bool extrapolate = false); /** * \brief Evaluate a cubic spline interpolant of a regularly sampled 3D function @@ -461,11 +473,14 @@ extern MTS_EXPORT_CORE Float interpCubic2DIrregular(const Point2 &p, const Float * Position of the last knot on each dimension * \param size * Denotes the size of the \c data array (along each dimension) + * \param extrapolate + * Extrapolate data values when \c p is out of range? (default: \c false) * \return - * The interpolated value or zero when \c p lies outside of the knot range + * The interpolated value or zero when extrapolate=falsett> and + * \c p lies outside of the knot range */ extern MTS_EXPORT_CORE Float interpCubic3D(const Point3 &p, const Float *data, - const Point3 &min, const Point3 &max, const Size3 &size); + const Point3 &min, const Point3 &max, const Size3 &size, bool extrapolate = false); /** * \brief Evaluate a cubic spline interpolant of an \a irregularly sampled 3D function @@ -490,11 +505,14 @@ extern MTS_EXPORT_CORE Float interpCubic3D(const Point3 &p, const Float *data, * then 'y', and finally 'z' increments. * \param size * Denotes the size of the \c data array (along each dimension) + * \param extrapolate + * Extrapolate data values when \c p is out of range? (default: \c false) * \return - * The interpolated value or zero when \c p lies outside of the knot range + * The interpolated value or zero when extrapolate=falsett> and + * \c p lies outside of the knot range */ extern MTS_EXPORT_CORE Float interpCubic3DIrregular(const Point3 &p, const Float **nodes, - const Float *data, const Size3 &size); + const Float *data, const Size3 &size, bool extrapolate = false); //// Convert radians to degrees inline Float radToDeg(Float value) { return value * (180.0f / M_PI); } diff --git a/include/mitsuba/render/trimesh.h b/include/mitsuba/render/trimesh.h index c4d62365..a68535cd 100644 --- a/include/mitsuba/render/trimesh.h +++ b/include/mitsuba/render/trimesh.h @@ -206,8 +206,15 @@ public: */ void computeUVTangents(); - /// Generate surface normals - void computeNormals(); + /** + * \brief Generate smooth vertex normals? + * + * \param force + * When this parameter is set to true, the function + * generates normals even when there are + * already existing ones. + */ + void computeNormals(bool force = false); /** * \brief Rebuild the mesh so that adjacent faces diff --git a/src/libcore/util.cpp b/src/libcore/util.cpp index 3f2bf951..fcadfb84 100644 --- a/src/libcore/util.cpp +++ b/src/libcore/util.cpp @@ -469,9 +469,9 @@ bool solveLinearSystem2x2(const Float a[2][2], const Float b[2], Float x[2]) { return true; } -Float interpCubic1D(Float x, const Float *data, Float min, Float max, size_t size) { +Float interpCubic1D(Float x, const Float *data, Float min, Float max, size_t size, bool extrapolate) { /* Give up when given an out-of-range or NaN argument */ - if (!(x >= min && x <= max)) + if (!(x >= min && x <= max) && !extrapolate) return 0.0f; /* Transform 'x' so that knots lie at integer positions */ @@ -508,9 +508,9 @@ Float interpCubic1D(Float x, const Float *data, Float min, Float max, size_t siz ( t3 - t2) * d1; } -Float interpCubic1DIrregular(Float x, const Float *nodes, const Float *data, size_t size) { +Float interpCubic1DIrregular(Float x, const Float *nodes, const Float *data, size_t size, bool extrapolate) { /* Give up when given an out-of-range or NaN argument */ - if (!(x >= nodes[0] && x <= nodes[size-1])) + if (!(x >= nodes[0] && x <= nodes[size-1]) && !extrapolate) return 0.0f; size_t k = (size_t) std::max((ptrdiff_t) 0, std::min((ptrdiff_t) size - 2, @@ -545,7 +545,7 @@ Float interpCubic1DIrregular(Float x, const Float *nodes, const Float *data, siz Float interpCubic2D(const Point2 &p, const Float *data, - const Point2 &min, const Point2 &max, const Size2 &size) { + const Point2 &min, const Point2 &max, const Size2 &size, bool extrapolate) { Float knotWeights[2][4]; Size2 knot; @@ -553,7 +553,7 @@ Float interpCubic2D(const Point2 &p, const Float *data, for (int dim=0; dim<2; ++dim) { Float *weights = knotWeights[dim]; /* Give up when given an out-of-range or NaN argument */ - if (!(p[dim] >= min[dim] && p[dim] <= max[dim])) + if (!(p[dim] >= min[dim] && p[dim] <= max[dim]) && !extrapolate) return 0.0f; /* Transform 'p' so that knots lie at integer positions */ @@ -615,7 +615,7 @@ Float interpCubic2D(const Point2 &p, const Float *data, } Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_, - const Float *data, const Size2 &size) { + const Float *data, const Size2 &size, bool extrapolate) { Float knotWeights[2][4]; Size2 knot; @@ -625,7 +625,7 @@ Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_, Float *weights = knotWeights[dim]; /* Give up when given an out-of-range or NaN argument */ - if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1])) + if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1]) && !extrapolate) return 0.0f; /* Find the index of the left knot in the queried subinterval, be @@ -689,7 +689,7 @@ Float interpCubic2DIrregular(const Point2 &p, const Float **nodes_, } Float interpCubic3D(const Point3 &p, const Float *data, - const Point3 &min, const Point3 &max, const Size3 &size) { + const Point3 &min, const Point3 &max, const Size3 &size, bool extrapolate) { Float knotWeights[3][4]; Size3 knot; @@ -697,7 +697,7 @@ Float interpCubic3D(const Point3 &p, const Float *data, for (int dim=0; dim<3; ++dim) { Float *weights = knotWeights[dim]; /* Give up when given an out-of-range or NaN argument */ - if (!(p[dim] >= min[dim] && p[dim] <= max[dim])) + if (!(p[dim] >= min[dim] && p[dim] <= max[dim]) && !extrapolate) return 0.0f; /* Transform 'p' so that knots lie at integer positions */ @@ -763,7 +763,7 @@ Float interpCubic3D(const Point3 &p, const Float *data, } Float interpCubic3DIrregular(const Point3 &p, const Float **nodes_, - const Float *data, const Size3 &size) { + const Float *data, const Size3 &size, bool extrapolate) { Float knotWeights[3][4]; Size3 knot; @@ -773,7 +773,7 @@ Float interpCubic3DIrregular(const Point3 &p, const Float **nodes_, Float *weights = knotWeights[dim]; /* Give up when given an out-of-range or NaN argument */ - if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1])) + if (!(p[dim] >= nodes[0] && p[dim] <= nodes[size[dim]-1]) && !extrapolate) return 0.0f; /* Find the index of the left knot in the queried subinterval, be diff --git a/src/librender/trimesh.cpp b/src/librender/trimesh.cpp index 56b747c4..98e7f757 100644 --- a/src/librender/trimesh.cpp +++ b/src/librender/trimesh.cpp @@ -542,7 +542,7 @@ void TriMesh::rebuildTopology(Float maxAngle) { configure(); } -void TriMesh::computeNormals() { +void TriMesh::computeNormals(bool force) { int invalidNormals = 0; if (m_faceNormals) { if (m_normals) { @@ -558,7 +558,7 @@ void TriMesh::computeNormals() { } } } else { - if (m_normals) { + if (m_normals && !force) { if (m_flipNormals) { for (size_t i=0; i