Есть ли библиотека / фрагмент кода, который может преобразовывать сетки в формат sdf в векторном представлении для точного представления субвокселей? - PullRequest
0 голосов
/ 31 мая 2019

Мне нужно сгенерировать sdf на сетке из 2D-сетки, чтобы представить сетку как замкнутое тело в cinder.

Мой первый подход состоял в том, чтобы использовать функцию расстояния (евклидово), чтобы проверить, является ли точка сеткинаходится близко к точке сетки, а затем установите значение - или +, но это привело к плохому разрешению.Затем я попытался сложить расстояния, чтобы получить непрерывное поле расстояний.в результате чего взорвался объект.Я не уверен, как изобразить расстояние до замкнутого объекта, описываемого сеткой (вогнутой или выпуклой).Мой текущий подход описан в приведенном ниже коде.


#include <iostream>
#include <fstream>
#include <string>
#include <Eigen/Dense>
#include <vector>
#include <algorithm>
#include <random>

using namespace std;
using namespace Eigen;
typedef Eigen::Matrix<double, 2, 1> Vector2;
typedef Eigen::Matrix<double, 3, 2> Vector32;
typedef std::vector<Vector2, Eigen::aligned_allocator<Vector2> > Vector2List;
typedef std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i> > Vector3iList;
typedef std::vector<Vector32> Vector32List;
typedef Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic> grid_t;


void f( Vector2List vertices, Vector3iList triangles)
{ // each entry of triangles describe which vertice point belongs
  // to a triangle of the mesh 
grid_t sdf  = grid_t::Zero(resolution, resolution);
for (int x = 0; x < resolution; ++x) {
        for (int y = 0; y < resolution; ++y) {
            Vector2d pos((x + 0.5) / resolution, (y + 0.5) / resolution);
            double dist = 1 / double(resolution*resolution);
            double check = 100;
            double val = 0;
for (std::vector<Vector2>::iterator mean = vertices.begin(); mean != vertices.end(); ++mean) {
        //try sdf with euclidian distance function
                check = (pos - *mean).squaredNorm();
                if (check < dist) {
                    val = -1; break;
                }
                else {
                    val = 20;
                }

            }

            val *= resolution;
            static const double epsilon = 0.01;
            if (abs(val) < epsilon) {
                val = 0;
                numberOfClamped++;
            }
            sdf(x,  y) = val; //
        }
    }
}

1 Ответ

0 голосов
/ 31 мая 2019

Кажется, что у вас есть небольшое недопонимание того, что на самом деле является SDF.Итак, позвольте мне начать с этого.

Функция расстояния со знаком - это функция в двухмерном пространстве, которая дает вам расстояние от соответствующей точки до ближайшей точки на сетке.Расстояние положительное для точек вне сетки и отрицательное для точек внутри (или наоборот).Естественно, точки непосредственно на сетке будут иметь нулевое расстояние.Мы можем представить эту функцию формально как:

sdf(x, y) = distance

Это непрерывная функция, и нам нужно дискретное представление, с которым мы можем работать.Распространенным выбором является использование единой сетки, подобной той, которую вы хотите использовать.Затем мы сэмплируем SDF в точках сетки.Как только у нас есть значения расстояний для всех наших точек сетки, мы можем интерполировать SDF между ними, чтобы получить SDF везде.Обратите внимание, что каждый образец соответствует одной точке, а не области (например, ячейка).

Учитывая это, давайте посмотрим на ваш код:

Vector2d pos((x + 0.5) / resolution, (y + 0.5) / resolution);

Этозависит от того, как индексы точек сетки отображаются на глобальные координаты.Это может быть правильно.Однако это выглядит так, как будто предполагается, что выборочные позиции расположены в середине соответствующих ячеек.Опять же, это может быть правильно, но я предполагаю, что + 0.5 следует оставить в стороне.

for (std::vector<Vector2>::iterator mean = vertices.begin(); mean != vertices.end(); ++mean)

Это приближение SDF.Он вычисляет ближайшую вершину сетки, а не ближайшую точку (которая может лежать на ребре).Для плотных сеток это должно быть хорошо.Если у вас есть грубые сетки, вы должны перебрать края и вычислить ближайшие точки на них.

if (check < dist) {
    val = -1; break;
} else {
    val = 20;
}

Я действительно не знаю, что это такое.Как объяснено выше, значение SDF - это расстояние со знаком.Не какое-то произвольное значение.Также знак не должен соответствовать тому, находится ли сетка близко к позиции сетки.Итак, что вы должны были сделать вместо этого:

if(check < val * val) {
    //this point is closer than the current closest point
    val = std::sqrt(check); //set to absolute distance
    if(*mean is inside the mesh)
        val *= -1; //invert the sign
}

И, наконец, эта часть:

val *= resolution;
static const double epsilon = 0.01;
if (abs(val) < epsilon) {
    val = 0;
    numberOfClamped++;
}

Опять же, я не знаю, что это должно делать.Просто оставь это.

...