/* * CS5600 University of Utah * Charles McGarvey * mcgarvey@eng.utah.edu */ #ifndef _ELEMENT_HH_ #define _ELEMENT_HH_ #include "color.hh" #include "contact.hh" #include "light.hh" #include "raster.hh" #include "ray.hh" #include "scene.hh" namespace rt { /* * A base class for an object in a scene. */ class element { color_t kd; raster_t* tx; public: element() : kd(COLOR_WHITE), tx(NULL) {} virtual ~element() {} /* * Determine if a ray intersects this element. */ virtual bool intersect(ray_t ray, contact_t& hit) const = 0; /* * Get the material color of the element at a surface point. */ virtual color_t color(vec_t point) const { return kd; } /* * Get texture-coordinates from a surface point. */ virtual vec_t txcoord(vec_t point) const { return VEC_ZERO; } /* * Cast a ray to this element, returning the correct color value. */ color_t cast(const contact_t& hit, const scene_t* scene) const { color_t kd = txcolor(hit.p); color_t Ia = color_mult(scene_ambient(scene), kd); color_t Id = diffuse(kd, hit, scene); return color_clamp(color_add(Ia, Id)); } /* * Get whether or not a particular surface point is shadowed by other * objects for a given light source. */ bool is_shadowed(const contact_t& hit, const scene_t* scene, const light_t* light) const { #if SHADOWS ray_t ray = ray_normalize(ray_new(hit.p, vec_sub(light->v, hit.p))); for (list_t* i = scene_elements(scene); i; i = i->link) { rt::element* obj = (rt::element*)i->val; contact_t hit; if (this != obj && obj->intersect(ray, hit)) { return true; } } #endif return false; } /* * Get the color of the element at a surface point after diffuse * lighting. */ color_t diffuse(color_t kd, const contact_t& hit, const scene_t* scene) const { vec_t n = vec_normalize(hit.n); color_t c = COLOR_BLACK; for (list_t* i = scene_lights(scene); i; i = i->link) { light_t* l = (light_t*)i->val; if (!is_shadowed(hit, scene, l)) { vec_t I = vec_normalize(vec_sub(l->v, hit.p)); scal_t dot = scal_max(vec_dot(I, n), S(0.0)); color_t Id = color_scale2(kd, l->d, dot); c = color_add(c, Id); } } return c; } color_t txcolor(vec_t point) const { #if TEXTURING if (tx != NULL) { vec_t uv = txcoord(point); #if QUIRKS return raster_uv(tx, uv); #else return color_mult(color(point), raster_uv(tx, uv)); #endif } #endif return color(point); } void material(color_t color) { kd = color; } void texture(raster_t* texture) { tx = texture; } }; } // namespace rt #endif // _ELEMENT_HH_