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