for loops where rays are spawned
and shot through the image lattice), declare an STL
std::vector of pointers to photons, where each
photon is of type photon_t*.
model_t,
e.g., write a routine
void model_t::shoot(std::vector<photon_t* >& photons)
whose job it is to fill up the std::vector array
with photons that "stick" to surfaces. This routine emits two types
of photons
(say 20,000 global photons and 5,000 caustic
photons). Each of the photons are emitted from the
the position of each light in the scene (e.g., the photon constructor
accepts the position from where the photon is emitted).
rand(), basically).
photon_t class from the
ray_t class:
class photon_t : public ray_t
{
...
};
The only additional private data member that photon requires is
a vec_t to store the photon's power, initialized
to (50.0,50.0,50.0).
Take care to re-write the ray_t's private:
data members as protected:.
Don't forget to provide the C++ "big three" as well as overriding
the
friend std::ostream& operator<<()
and
friend std::istream& operator>>()
operators (you'll need both to output and input photons for
visualization purposes).
dis, pos, and dir)
contained in the parent ray_t class must be
initialized—call the parent constructor with the position
received by the photon_t constructor, but set the
direction to the vec_t returned by the following routine:
vec_t photon_t::genrand_hemisphere(const vec_t& normal)
{
double azimuth = genrand(0.0,2.0*M_PI);
double elevation = genrand(0.0,2.0*M_PI);
double sinA = sin(azimuth), sinE = sin(elevation);
double cosA = cos(azimuth), cosE = cos(elevation);
vec_t dir, vup, out;
dir[0] = -sinA*cosE; vup[0] = sinA*sinE;
dir[1] = sinE; vup[1] = cosE;
dir[2] = cosA*cosE; vup[2] = -cosA*sinE;
out = (dir + vup).norm();
return(out.dot(normal) >= 0) ? out : -out;
}
where genrand() is declared as:
double genrand(double lo,double hi)
{ return( (double)(((double)rand()/(double)RAND_MAX)*hi + lo) ); }
Both can be made public or private
to the photon_t class.
photon_t member functions:
bool photon_t::caustic(model_t& model, int bounce);
bool photon_t::global(model_t& model, int bounce);
Both functions are similar to the ray_t::trace()
routine, except that they return a bool variable.
The caustic function sends the photon through a
transmissive object if one is encountered, otherwise the photon
sticks to the hit surface. A photon shoots itself recursively
through a transparent object by resetting its position and direction
to the hit point and transmission ray direction. If an object is
hit that is not transmissive, the caustic routine
returns true. If nothing is hit (distance is equal
to or less than 0), return false.
The caustic routine refracts photons in the same way
as rays, i.e.,
(n1/n2)(u - cosθ1N) - cosθ2N
The global function does one of three things,
based on the value of a randomly generated number between
0 and 1, e.g.,
roulette = genrand(0.0,1.0), follwing this algorithm:
where
if( (0.0 < roulette) && (roulette < Kd) ) {
// diffuse reflection:
// set pos and dir to hit and genrand_hemisphere().norm();
// reflect this photon
} else if( (Kd < roulette) && (roulette < Kd+Ks) ) {
// specular reflection:
// set pos and dir to hit and dir.reflect(N);
// reflect this photon
} else if( (Kd+Ks < roulette) && (roulette < 1.0) ) {
// absorbtion ("stick" photon):
// set pos to hit
// return true
just the average of the material surface properties.
Kd = (diffuse[0] + diffuse[1] + diffuse[2])/3.0;
Ks = (specular[0] + specular[1] + specular[2])/3.0;
main() once you have everything else put together,
and have shot all photons, write them all out to a file so that
each photon's x, y, z values are written out per line.
cbox.txt used previously to exercise photon
transmission. The photons focused beneath the transparent sphere
should show up, as seen below, rendered by the Qt
visualizer developed in lab.
cbox.txt file that is used for grading
purposes, come up with your own scene(s)—feel free to
try different materials, colors, arrangements of objects in
the scene.
README.
tar.gz
archive of your asg##/ directory, including:
README file containing
Makefile
.h headers and .cpp source)
make clean before tar)
handin notes