Hello forum,

I believe that i have the design problem that i need to discuss about.

Intersectable is the super-class; Triangle and Sphere are the sub-classes of the Intersectable

i believe that you already realized class inheritance structure. I have the following pure virtual functions declared inside the INTERSECTABLE

``````   virtual bool sampleDirection(const Intersection&,Vector3D&) = 0;

virtual float getPDF(const Intersection&,
const Intersection&) = 0;
``````

Each of the sub-classes are defining the above functions.

There is another class called AreaLight that contains a std::vector as follows:

``````   class LuminaireProbability
{
public:

LuminaireProbability() : mIntersectable(0),mMaterial(0),mLuminaireProbabilityValue(0.0f),
mCumulativeDistributionValue(0.0f)
{
}

~LuminaireProbability()
{
mIntersectable = 0;
mMaterial = 0;
}

//luminaire as an intersectable
Intersectable *mIntersectable;
//material of the intersectable
Material *mMaterial;
//probability of choosing the luminaire
float mLuminaireProbabilityValue;

//cumulative distribution value
float mCumulativeDistributionValue;

};

//the area light contains the reference
//to the geometric object to be the light source
//the geometric object in turn contains the emissive material
//thus providing the illumination
//in this way the type of geometric object automatically determines
//the type of light, in principle it allows any type of the geometric
//object to be a light source
//SOME OF THE ABOVE STATEMENTS DEMANS CHANGE
std::vector<LuminaireProbability*> mLightIntersectables;

//store the selected lumianire from the vector
LuminaireProbability *mSelectedLuminaire;
``````

I have the std::vector populated with a pointer of intersectables of type triangle or sphere along with some other trivial information. Now i have the following function

``````//calcualate the world position based on the intersection point
bool AreaLight::calculateSampleDirection(const Intersection &intersection,Vector3D &sampleVector)
{

//choose the light intersectables based on the weight of the probaiblity
//that we have calculated in the prepare() function

float selectionProbability = 0.0f;

//create a random instance
RandomGenerator random = RandomGenerator::getRandomInstance();

//create a canonical random number between 0 and 1
selectionProbability = static_cast<float>(random.generateDouble(0,1));

CompareToCDF cdf;
//store the canonical random value
cdf.mRandomValue = selectionProbability;

//   CompareAreaLight cmpAreaLight;

//   //sort the light intersectables based on the luminaire probability value
//   std::sort(mLightIntersectables.begin(),mLightIntersectables.end(),cmpAreaLight);

std::vector<LuminaireProbability*>::iterator it;

it = std::find_if(mLightIntersectables.begin(),mLightIntersectables.end(),cdf);

assert(it != mLightIntersectables.end());

//store the selected luminaire
mSelectedLuminaire = *it;

//I AM GETTING A SEGMENTATION FAULT IN THE FOLLOWING FUNCTION - !!!!!
mSelectedLuminaire->mIntersectable->sampleDirection(intersection,sampleVector);

return true;
}
``````

As mentioned in the code i am getting the segmentation fault that the debugger is not even giving any hint of.

I hope you will be able to help me find out the issue here that i am missing.
Is there any logical mistake i am doing here?

I tried the following as follows , but till i am having the segmentation fault .

``````...................
if(mSelectedLuminaire != 0)
{
if(mSelectedLuminaire->mIntersectable != 0)
mSelectedLuminaire->mIntersectable->sampleDirection(intersection,sampleVector);
}
......................
``````

Then i ran the GDB and it gave me the following information.

``````(gdb) backtrace
#0  0x2efd85ba in ?? ()
#1  0x0804e018 in AreaLight::calculateSampleDirection (this=0x80c4d60,
intersection=..., sampleVector=...) at arealight.cpp:151
#2  0x080556ed in Intersection::getShadowRay (this=0xbfffedfc, light=0x80c4d60)
at intersection.cpp:152
#3  0x08069787 in PathTracer::computeDirectIllumination (this=0xbffff220,
intersection=...) at pathtracer.cpp:179
intersection=..., depth=5) at pathtracer.cpp:141
#5  0x0806a63f in PathTracer::trace (this=0xbffff220, ray=..., E=1)
at pathtracer.cpp:127
#6  0x0806a8e0 in PathTracer::tracePixel (this=0xbffff220, x=0, y=1)
at pathtracer.cpp:95
#7  0x0806aa14 in PathTracer::computeImage() [clone ._omp_fn.0] ()
at pathtracer.cpp:53
#8  0x0806ac46 in PathTracer::computeImage (this=0xbffff220)
at pathtracer.cpp:47
#9  0x0804c397 in main (argc=1, argv=0xbffff304) at main.cpp:504
(gdb)
``````

I hope some one in the forum wil be able to help me to debug this issue.

Where should i look into now?

Regards

## All 4 Replies

can you post the code for sampleDirection()?

Hi

Since Sphere and Triangle are both the sub-class of intersectables , both of them is defining the sampleDirection() function as follows:

``````//get the sample point from the sphere
//based intersection point
bool Sphere::sampleDirection(const Intersection &intersection,Vector3D &sampleDirection)
{
//get the random instance
//to generate the canonical random number [0,1)
RandomGenerator random = RandomGenerator::getRandomInstance();

//declare a sphere center
Point3D center = Point3D(0.0f,0.0f,0.0f);
//transform the sphere center in the world space
Point3D centerWorld = mWorldTransform * center;

//get the intersection position in the world space
Point3D intersectionPoint = intersection.mPosition ;

//create a point from the intersection point to the center of the sphere
Point3D intersectionToCenter =  centerWorld - intersectionPoint;

//create the coordinate system for sampling - w, u, and v
//initialize a vector from the difference of points
Vector3D w = Vector3D(intersectionToCenter);

//get the length between the intersection point and
//sphere center
float d = w.length();

//if the length is less than the radius then return false

return false;

float sin_alpha_max = mRadius / d;
float cos_alpha_max = sqrt(std::max(1 - sin_alpha_max * sin_alpha_max,0.0f));

//generate two canonical numbers
float eps1 = random.generateDouble(0,1);
float eps2 = random.generateDouble(0,1);

float cos_alpha = 1 + eps1 * cos_alpha_max - eps1;
float sin_alpha = sqrt(std::max(1 - cos_alpha * cos_alpha,0.0f));
float phi = 2 * M_PI * eps2;

float cos_phi = cos(phi);
float sin_phi = sin(phi);

//the cos_phi and sin_phi azimuthal and polar angles in the local
//local coordinate system
//the sampling direction is in the local coordinate system
w.normalize();

/*
// FIRST OPTION
Vector3D v = w.cross(intersection.mNormal);
v.normalize();

Vector3D u = v.cross(w);
u.normalize();
*/

//SECOND OPTION - is better than the FIRST ONE
//i managed to remove those artifacts from the surface
//of the luminaire
Vector3D n(1.0f,0.0f,0.0f);
Vector3D m(0.0f,1.0f,0.0f);

Vector3D u = w.cross(n);

if(u.length() < ONB_EPSILON)
u = w.cross(m);

u.normalize();

Vector3D v = w.cross(u);
v.normalize();

//get the vector to the light source
Vector3D l = (u * cos_phi * sin_alpha) +
(v * sin_phi * sin_alpha) +
(w * cos_alpha);

//normalize the light direction
l.normalize();

//store the direction to the light
sampleDirection = l;

//sample found , so return true
return true;
}
``````

And the for the Triangle

``````bool Triangle::sampleDirection(const Intersection &intersection,Vector3D &sampleDirection)
{
//create a random instance
//get the random instance
//to generate the canonical random number [0,1)
RandomGenerator random = RandomGenerator::getRandomInstance();

float temp =  sqrtf(1.0f - random.generateDouble(0,1));
float beta =  (1.0f - temp);
float gamma = random.generateDouble(0,1);

//now calculate the point on the light
Point3D lightPoint =  getVtxPosition(0) * (1 - beta - gamma)  +
getVtxPosition(1) * beta + getVtxPosition(2) * gamma;

Point3D intersectionToLightPoint = lightPoint - intersection.mPosition;

Vector3D toLight(intersectionToLightPoint);

toLight.normalize();

sampleDirection = toLight;

return true;

}
``````

Regards

Where do you initialize the mIntersectable member of the mSelectedLuminaire object? You are dereferencing it, but not verifying that it is not null.

I think mSelectedLuminaire is of type
`LuminaireProbability *mSelectedLuminire`

I m not instantiating any object with it from the beginning . mSelectedLuminaire is initialized to NULL in the constructor of arealight.

And i think i am checking it before de-referencing it as follows:

``````...................
if(mSelectedLuminaire != 0)
{
if(mSelectedLuminaire->mIntersectable != 0)
mSelectedLuminaire->mIntersectable->sampleDirection(intersection,sampleVector);
}
......................
``````

Is there anything else i have to check here ? I m calling the sampleDirection() only after i am sure that they are not null

Thanks