コード例 #1
0
ファイル: surface.c プロジェクト: carmi/comp356
static bool sfc_hit_planar(bool is_triangle, 
        point3_t* A, point3_t* B, point3_t* C,
        ray3_t* ray, float t0, float t1, hit_record_t* hit) {

    // Use the notation of Shirley & Marschner, Section 4.4.2.
    float a = A->x - B->x ;
    float b = A->y - B->y ;
    float c = A->z - B->z ;
    float d = A->x - C->x ;
    float e = A->y - C->y ;
    float f = A->z - C->z ;
    float g = ray->dir.x ;
    float h = ray->dir.y ;
    float i = ray->dir.z ;
    float j = A->x - ray->base.x ;
    float k = A->y - ray->base.y ;
    float l = A->z - ray->base.z ;

    float ei = e*i, hf = h*f, gf = g*f, di = d*i, dh = d*h, eg = e*g ;
    float ak = a*k, jb = j*b, jc = j*c, al = a*l, bl = b*l, kc = k*c ;

    float ei_hf = ei-hf, gf_di = gf-di, dh_eg = dh-eg ;
    float ak_jb = ak-jb, jc_al = jc-al, bl_kc = bl-kc ;

    float M = a*ei_hf + b*gf_di + c*dh_eg ;

    float t = -(f*ak_jb + e*jc_al + d*bl_kc)/M ;

    if (t <= t0 || t > t1) return false ;

    float beta = (j*ei_hf + k*gf_di + l*dh_eg)/M ;
    if (is_triangle && (beta < 0 || beta > 1)) return false ;

    float gamma = (i*ak_jb + h*jc_al + g*bl_kc)/M ;

    if (!is_triangle || (0 <= gamma && beta+gamma <= 1)) {
        hit->t = t ;
        vector3_t b_minus_a, c_minus_a ;
        pv_subtract(B, A, &b_minus_a) ;
        pv_subtract(C, A, &c_minus_a) ;
        cross(&b_minus_a, &c_minus_a, &(hit->normal)) ;
        normalize(&(hit->normal)) ;
        multiply(&b_minus_a, beta, &b_minus_a) ;
        multiply(&c_minus_a, gamma, &c_minus_a) ;
        pv_add(A, &b_minus_a, &(hit->hit_pt)) ;
        pv_add(&(hit->hit_pt), &c_minus_a, &(hit->hit_pt)) ;
        return true ;
    }
    else return false ;
}
コード例 #2
0
ファイル: surface.c プロジェクト: carmi/comp356
static bool sfc_hit_sphere(void* data, ray3_t* ray, float t0,
        float t1, hit_record_t* hit) {
    sphere_data_t* sdata = (sphere_data_t*)data ;
    point3_t ctr = sdata->center ;
    float radius = sdata->radius ;

    point3_t* e = &ray->base ;
    vector3_t* d = &ray->dir ;

    // First see if there is any chance we hit the sphere.  We do this
    // by checking whether any part of the sphere is inside the sphere
    // of radius t1 from the base of the ray.  With even just one sphere 
    // in the scene, I found that this check actually slowed down rendering,
    // probably because of all the square-root computations that turn
    // out to give no helpful information (i.e., this test says to
    // continue checking, but then the sphere isn't hit anyway).
    // if (t1 < (dist(e, &ctr) - radius)) return false ;

    vector3_t e_minus_ctr ;
    pv_subtract(e, &ctr, &e_minus_ctr) ;
    float e_minus_ctr2 = dot(&e_minus_ctr, &e_minus_ctr) ;
    float d2 = dot(d, d) ;

    // Compute the discriminant first.
    float b = dot(d, &e_minus_ctr) ;
    float discr = 
        b*b - d2*(e_minus_ctr2 - radius*radius) ;

    // Compute hit position if discr. is >= 0, and also compute
    // the surface normal.
    if (discr < 0) return false ;
    else {
        // Hit position.
        float num = min(-b - sqrt(discr), -b + sqrt(discr)) ;
        float t = num/d2 ;

        if (t < t0 || t > t1) return false ;

        hit->t = t ;

        vector3_t ray_vec = *d ;
        multiply(&ray_vec, hit->t, &ray_vec) ;
        pv_add(e, &ray_vec, &(hit->hit_pt)) ;

        // Surface normal.
        pv_subtract(&(hit->hit_pt), &ctr, &(hit->normal)) ;
        normalize(&(hit->normal)) ;
        return true ;
    }
}
コード例 #3
0
ファイル: prologue-value.c プロジェクト: msmania/gdb
enum pv_boolean
pv_is_array_ref (pv_t addr, CORE_ADDR size,
                 pv_t array_addr, CORE_ADDR array_len,
                 CORE_ADDR elt_size,
                 int *i)
{
    /* Note that, since .k is a CORE_ADDR, and CORE_ADDR is unsigned, if
       addr is *before* the start of the array, then this isn't going to
       be negative...  */
    pv_t offset = pv_subtract (addr, array_addr);

    if (offset.kind == pvk_constant)
    {
        /* This is a rather odd test.  We want to know if the SIZE bytes
           at ADDR don't overlap the array at all, so you'd expect it to
           be an || expression: "if we're completely before || we're
           completely after".  But with unsigned arithmetic, things are
           different: since it's a number circle, not a number line, the
           right values for offset.k are actually one contiguous range.  */
        if (offset.k <= -size
        && offset.k >= array_len * elt_size)
            return pv_definite_no;
        else if (offset.k % elt_size != 0
        || size != elt_size)
            return pv_maybe;
        else
        {
            *i = offset.k / elt_size;
            return pv_definite_yes;
        }
    }
    else
        return pv_maybe;
}
コード例 #4
0
ファイル: final.c プロジェクト: carmi/comp356
/** Compute the eye frame basis from the eye point, look-at point,
 *  and up direction.  The basic algorithm:
 *  -# w <- normalized (eye - look_at)
 *  -# u <- normalized (up x w)
 *  -# v <- w x u.
 */
void compute_eye_frame_basis() {
    pv_subtract(&eye, &look_at, &eye_frame_w);
    normalize(&eye_frame_w);

    cross(&up_dir, &eye_frame_w, &eye_frame_u);
    normalize(&eye_frame_u);

    cross(&eye_frame_w, &eye_frame_u, &eye_frame_v);

    debug("compute_eye_frame_basis():  eye_frame_u = (%f, %f, %f)",
            eye_frame_u.x, eye_frame_u.y, eye_frame_u.z);
    debug("compute_eye_frame_basis():  eye_frame_v = (%f, %f, %f)",
            eye_frame_v.x, eye_frame_v.y, eye_frame_v.z);
    debug("compute_eye_frame_basis():  eye_frame_w = (%f, %f, %f)",
            eye_frame_w.x, eye_frame_w.y, eye_frame_w.z);
}
コード例 #5
0
ファイル: final.c プロジェクト: carmi/comp356
/** Get the shade determined by a given ray.
 *  
 *  @param ray the ray to trace.
 *  @param t0 the start of the interval for which to get a shade.
 *  @param t1 the end of the interval for which to get a shade.
 *  @param depth the maximum number of times a reflect ray will be
 *      cast for objects with non-NULL reflective color.
 *  @param in_trans whether the ray is inside a transparent surface or not.
 * 
 *
 *  @return the color corresponding to the closest object hit by
 *      <code>r</code> in the interval <code>[t0, t1]</code>.
 */
color_t ray_trace(ray3_t ray, float t0, float t1, int depth, bool in_trans) {
    assert(depth >= 0);

    color_t color = {0.0, 0.0, 0.0};

    if (depth == 0) return color;

    hit_record_t hit_rec, closest_hit_rec;

    // Get a hit record for the closest object that is hit.
    bool hit_something = false;
    list356_itr_t* s = lst_iterator(surfaces);
    while (lst_has_next(s)) {
        surface_t* sfc = lst_next(s);
        if (sfc_hit(sfc, &ray, t0, t1, &hit_rec)) {
            if (hit_rec.t < t1) {
                hit_something = true;
                memcpy(&closest_hit_rec, &hit_rec, 
                        sizeof(hit_record_t));
                t1 = hit_rec.t;
            }
            else assert("wrong");
        }
    }
    lst_iterator_free(s);

    // If we hit something, color the pixel.
    if (hit_something) {
        surface_t* sfc = closest_hit_rec.sfc;

        // Specular reflection.
        if (spec_reflection) {
          if (sfc->refl_color != NULL) {
              color_t refl_color = get_specular_refl(&ray,
                      &closest_hit_rec, depth, in_trans);
              add_scaled_color(&color, sfc->refl_color, &refl_color, 1.0f);
          }
        }

        // Tranparency
        if (transparency) {
          if (sfc->refr_index != -1) {
              color_t trans_color = get_transparency(&ray, &closest_hit_rec,
                      depth, !in_trans);
              // Only add returned color, don't multiply by a surface_color.
              color.red += (trans_color.red);
              color.green += (trans_color.green);
              color.blue += (trans_color.blue);
          }
        }

        // Ambient shading.
        if (ambient_shading) {
          add_scaled_color(&color, sfc->ambient_color, &ambient_light, 1.0f);
        }

        // Lighting.
        if (lighting) {
          list356_itr_t* light_itr = lst_iterator(lights);
          while (lst_has_next(light_itr)) {
              light_t* light = lst_next(light_itr);
              vector3_t light_dir;
              pv_subtract(light->position, &(closest_hit_rec.hit_pt),
                      &light_dir);
              normalize(&light_dir);

              // Check for global shadows.
              bool do_lighting = true;

              // Bool for if the shadow is caused by transparent surface.
              bool trans_shadow = false;

              ray3_t light_ray = {closest_hit_rec.hit_pt, light_dir};
              float light_dist = dist(&closest_hit_rec.hit_pt,
                      light->position);
              s = lst_iterator(surfaces);
              while (lst_has_next(s)) {
                  surface_t* sfc = lst_next(s);
                  if (sfc_hit(sfc, &light_ray, EPSILON, light_dist, &hit_rec)) {
                      do_lighting = false;
                      // If shadow is caused by transparent surface, we add
                      // Lambertian shading only so our shadows are not opaque.
                      if (hit_rec.sfc->refr_index != -1) trans_shadow = true;
                      break;
                  }
              }
              lst_iterator_free(s);
              if (!do_lighting) {
                  continue;
              }

              // Lambertian shading.
              if (lambertian_shading) {
                if (!trans_shadow) {
                    float scale = get_lambert_scale(&light_dir, &closest_hit_rec);
                    add_scaled_color(&color, sfc->diffuse_color, light->color,
                            scale);
                }
              }

            // Blin-Phong shading (if shadow is not caused by transparent
            // surface).
            if (blin_phong_shading) {
              if (!trans_shadow) {
                  float phong_scale = get_blinn_phong_scale(&ray, &light_dir,
                          &closest_hit_rec);
                  add_scaled_color(&color, sfc->spec_color, light->color, 
                          phong_scale);
              }
            }
        }

        lst_iterator_free(light_itr);
    }

    }   // if (hit_something)
    return color;
}
コード例 #6
0
ファイル: hw2bp1.c プロジェクト: carmi/comp356
/** Get the shade determined by a given ray.
 *  
 *  @param ray the ray to trace.
 *  @param t0 the start of the interval for which to get a shade.
 *  @param t1 the end of the interval for which to get a shade.
 *  @param depth the maximum number of times a reflect ray will be
 *      cast for objects with non-NULL reflective color.
 *
 *  @return the color corresponding to the closest object hit by
 *      <code>r</code> in the interval <code>[t0, t1]</code>.
 */
color_t ray_trace(ray3_t ray, float t0, float t1, int depth) {
    assert(depth >= 0) ;

    color_t color = {0.0, 0.0, 0.0} ;

    if (depth ==0) return color ;

    hit_record_t hit_rec, closest_hit_rec ;

    // Get a hit record for the closest object that is hit.
    bool hit_something = false ;
    list356_itr_t* s = lst_iterator(surfaces) ;
    while (lst_has_next(s)) {
        surface_t* sfc = lst_next(s) ;
        if (sfc_hit(sfc, &ray, t0, t1, &hit_rec)) {
            if (hit_rec.t < t1) {
                hit_something = true ;
                memcpy(&closest_hit_rec, &hit_rec, 
                        sizeof(hit_record_t)) ;
                t1 = hit_rec.t ;
            }
        }
    }
    lst_iterator_free(s) ;

    // If we hit something, color the pixel.
    if (hit_something) {
        surface_t* sfc = closest_hit_rec.sfc ;

        // Specular reflection.
        if (sfc->refl_color != NULL) {
            color_t refl_color = get_specular_refl(&ray,
                    &closest_hit_rec, depth) ;
            add_scaled_color(&color, sfc->refl_color, &refl_color, 1.0f) ;
        }

        // Ambient shading.
        add_scaled_color(&color, sfc->ambient_color, &ambient_light, 1.0f) ;

        // Lighting.
        list356_itr_t* light_itr = lst_iterator(lights) ;
        while (lst_has_next(light_itr)) {
            light_t* light = lst_next(light_itr) ;
            vector3_t light_dir ;
            pv_subtract(light->position, &(closest_hit_rec.hit_pt), 
                    &light_dir) ;
            normalize(&light_dir) ;

            // Check for global shadows.
            bool do_lighting = true ;
            ray3_t light_ray = {closest_hit_rec.hit_pt, light_dir} ;
            float light_dist = dist(&closest_hit_rec.hit_pt,
                    light->position) ;
            s = lst_iterator(surfaces) ;
            while (lst_has_next(s)) {
                surface_t* sfc = lst_next(s) ;
                if (sfc_hit(sfc, &light_ray, EPSILON, light_dist, &hit_rec)) {
                    do_lighting = false ;
                    break ;
                }
            }
            lst_iterator_free(s) ;
            if (!do_lighting) {
                continue ;
            }

            // Lambertian shading.
            float scale = get_lambert_scale(&light_dir, &closest_hit_rec) ;
            add_scaled_color(&color, sfc->diffuse_color, light->color, scale) ;

            // Blin-Phong shading.
            float phong_scale = get_blinn_phong_scale(&ray, &light_dir,
                    &closest_hit_rec) ;
            add_scaled_color(&color, sfc->spec_color, light->color, 
                    phong_scale) ;
        }   // while(lst_has_next(light_itr))

        lst_iterator_free(light_itr) ;

    }   // if (hit_something)

    return color ;
}