Program Listing for File SDFFunctions.cpp

Return to documentation for file (SPlisHSPlasH/Utilities/SDFFunctions.cpp)

#include "SDFFunctions.h"
#include "Utilities/Timing.h"
#include "Utilities/OBJLoader.h"

using namespace Eigen;
using namespace std;
using namespace Utilities;

AlignedBox3r SDFFunctions::computeBoundingBox(const unsigned int numVertices, const Vector3r *vertices)
{
    AlignedBox3r box;

    // compute bounding box
    box.min() = vertices[0];
    box.max() = box.min();
    box.setEmpty();
    for (unsigned int i = 1; i < numVertices; ++i)
    {
        const Vector3r& p = vertices[i];
        box.extend(p);
    }
    return box;
}

double SDFFunctions::distance(Discregrid::CubicLagrangeDiscreteGrid* sdf, const Vector3r &x,
    const Real thickness, Vector3r &normal, Vector3r &nextSurfacePoint)
{
    Eigen::Vector3d n;
    const double dist = sdf->interpolate(0, x.template cast<double>(), &n);
    if (dist == std::numeric_limits<double>::max())
        return dist;
    normal.normalize();
    normal = n.template cast<Real>();

    nextSurfacePoint = (x - dist * normal);

    return dist - thickness;
}

double SDFFunctions::distance(Discregrid::CubicLagrangeDiscreteGrid* sdf, const Vector3r &x,
    const Real thickness)
{
    const double dist = sdf->interpolate(0, x.template cast<double>());
    if (dist == std::numeric_limits<double>::max())
        return dist;
    return dist - thickness;
}

Discregrid::CubicLagrangeDiscreteGrid* SDFFunctions::generateSDF(const unsigned int numVertices,
    const Vector3r *vertices, const unsigned int numFaces, const unsigned int *faces,
    const AlignedBox3r &bbox, const std::array<unsigned int, 3> &resolution, const bool invert)
{
    START_TIMING("SDF Generation");
    // Generate distance field of object using Discregrid
#ifdef USE_DOUBLE
    Discregrid::TriangleMesh sdfMesh(&vertices[0][0], faces, numVertices, numFaces);
#else
    // if type is float, copy vector to double vector
    std::vector<double> doubleVec;
    doubleVec.resize(3 * numVertices);
    for (unsigned int i = 0; i < numVertices; i++)
        for (unsigned int j = 0; j < 3; j++)
            doubleVec[3 * i + j] = vertices[i][j];
    Discregrid::TriangleMesh sdfMesh(&doubleVec[0], faces, numVertices, numFaces);
#endif

    Discregrid::TriangleMeshDistance md(sdfMesh);
    Eigen::AlignedBox3d domain;
    domain.extend(bbox.min().cast<double>());
    domain.extend(bbox.max().cast<double>());
    domain.max() += 1.0e-3 * domain.diagonal().norm() * Eigen::Vector3d::Ones();
    domain.min() -= 1.0e-3 * domain.diagonal().norm() * Eigen::Vector3d::Ones();

    Discregrid::CubicLagrangeDiscreteGrid *distanceField = new Discregrid::CubicLagrangeDiscreteGrid(domain, resolution);
    auto func = Discregrid::DiscreteGrid::ContinuousFunction{};
    Real factor = 1.0;
    if (invert)
        factor = -1.0;
    func = [&md,&factor](Eigen::Vector3d const& xi) {return factor * md.signed_distance(xi).distance; };

    distanceField->addFunction(func, false);
    STOP_TIMING_PRINT;

    return distanceField;
}