Кажется, что у вас есть небольшое недопонимание того, что на самом деле является 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++;
}
Опять же, я не знаю, что это должно делать.Просто оставь это.