I'm currently implementing few abstractions to represent level-set operations for 3D objects. Basically what is described in this amazing page for GLSL shaders.
To give a brief overview, a 3D object can be described by a function that maps the R^3 domain to a scalar called level-set (or signed-distance-function). For example, for a sphere, the level-set function is defined by phi(X) = X.Norm2() - R*R
where Norm2
represents the squared Euclidean norm of a vector in R^3.
So I came out with a LevelSetObject
class that represents such a concept:
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);
}
Now I wanted to define few operators between LevelSetObject
s. For example the union operator:
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;
}
But I'm experiencing bad memory access when I create a temporary due to, for example, a triple sum (while if I sum the two objects separately as in the commented case, no memory leak is spotted using Valgrind and not SIGSEV). LevelSetSphere
is a derived class of LevelSetObject
where I define specifically the SDF of a sphere (given its center
and its 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);
}
What I suppose is that in the operator+
definition, the std::function
keeps a reference to other
that becomes a dangling reference when I actually call m_SDF
because a temporary is created during the triple sum. I also tried to change the signature of operator+
to operator+(const LevelSetObject other)
, so passing by copy, but the outcome is the same.
Where am I failing? :)