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
#4  0x0806a3df in PathTracer::computeRadiance (this=0xbffff220, 
    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?

Is there any more information you need please ask for it.

Regards
Sajjad

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

   if(d < mRadius)
      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;

   }

Let me know if you need any more information.

Regards
Sajjad

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
Sajjad

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.