В настоящее время я реализую несколько абстракций для представления операций установки уровня для трехмерных объектов. В основном то, что описано в этой удивительной странице для шейдеров GLSL.
Чтобы дать краткий обзор, трехмерный объект может быть описан функцией, которая отображает домен R ^ 3 в скаляр, называемый уровнем-набором (или функцией со знаком-расстоянием). Например, для сферы функция установки уровня определяется как phi(X) = X.Norm2() - R*R
, где Norm2
представляет квадратную евклидову норму вектора в R ^ 3.
Итак, я вышел с классом LevelSetObject
, который представляет такую концепцию:
class LevelSetObject
{
using SDFFunction = std::function<double(double, double, double)>;
protected:
SDFFunction m_SDF;
public:
double SDF(double x, double y, double z) const {
return m_SDF(x, y, z);
}
Теперь я хотел определить несколько операторов между LevelSetObject
с. Например, оператор union :
LevelSetObject LevelSetObject::operator+(const LevelSetObject& other) const {
LevelSetObject outObj;
outObj.m_SDF = [this, other]
(double x, double y, double z) {
return std::min(m_SDF(x, y, z), other.m_SDF(x, y, z));
};
return outObj;
}
Но я испытываю плохой доступ к памяти, когда создаю временную, например, из-за тройной суммы (хотя, если я суммирую два объекта по отдельности, как в закомментированном случае, утечка памяти не будет обнаружена с помощью Valgrind, а не SIGSEV ). LevelSetSphere
является производным классом LevelSetObject
, где я определяю конкретно SDF сферы (учитывая ее center
и radius
)
int main(int argc, char* argv[]) {
// Generate the central sphere
double radius = 1.0;
SimpleVector center(2, 2, 2);
LevelSetSphere sphere(radius, center);
// Generate the ears spheres
LevelSetSphere ear1(radius/2, SimpleVector(1, 1, 2));
LevelSetSphere ear2(radius/2, SimpleVector(3, 1, 2));
// Combine objects
auto mickeyMouse = sphere + ear1 + ear2;
//auto first = sphere + ear1;
//auto mickeyMouse = first + ear2;
// Materialize in the domain
mickeyMouse.SDF(0.0, 0.0, 0.0);
}
Я предполагаю, что в определении operator+
, std::function
сохраняет ссылку на other
, которая становится висячей ссылкой, когда я на самом деле вызываю m_SDF
, потому что временное значение создается во время тройной суммы. Я также пытался изменить сигнатуру operator+
на operator+(const LevelSetObject other)
, поэтому передавал копию, но результат тот же.
Где я терплю неудачу? :)