Inode *cylin_intersect(Prim *p, Ray ro) { double a, b, c, disc, t0, t1, t2, t3; Inode *i0, *i1; int flag[4] = {FALSE, FALSE, FALSE, FALSE}; Ray r = ray_transform(ro, p->ti); Vector3 Sol0, Sol1, Sol2, Sol3; a = SQR(r.d.x) + SQR(r.d.y); b = 2 * (r.o.x * r.d.x + r.o.y * r.d.y); c = SQR(r.o.x) + SQR(r.o.y) - 1; // Case 0: no solution / infinite solutions if ((disc = SQR(b) - 4 * a * c) <= 0) return (Inode *)0; if ( fabs(a) < RAY_EPS ) { return (Inode *)0; } else { t0 = (-b - sqrt(disc)) / (2 * a); t1 = (-b + sqrt(disc)) / (2 * a); Sol0 = ray_point(r, t0); Sol1 = ray_point(r, t1); if (t1 > RAY_EPS && Sol1.z >= 0 && Sol1.z <= 1){ flag[1] = TRUE; } if (t0 > RAY_EPS && Sol0.z >= 0 && Sol0.z <= 1){ flag[0] = TRUE; } } // Ray NOT parallel to base caps --> Cap intersections if ( fabs(r.d.z) > RAY_EPS ){ t2 = - (r.o.z) / (r.d.z); t3 = (1 - (r.o.z)) / (r.d.z); Sol2 = ray_point(r,t2); Sol3 = ray_point(r,t3); if (t2 > RAY_EPS && (SQR(Sol2.x) + SQR(Sol2.y)) <= 1) flag[2] = TRUE; if (t3 > RAY_EPS && (SQR(Sol3.x) + SQR(Sol3.y)) <= 1) flag[3] = TRUE; } int k = 0, nsols = 0; double t[4] = {t0, t1, t2, t3}; while (k < 4 && nsols < 2){ if (flag[k]){ Vector3 n = v3_unit(cylin_gradient(p, ray_point(ro, t[k]))); if ( nsols == 0 ){ i0 = inode_alloc(t[k], n, TRUE); } else { i1 = inode_alloc(t[k], n, FALSE); i0->next = i1; } nsols++; } k++; } return i0; }
Inode *torus_intersect(Prim *p, Ray ro) { double a, b, c, disc, t0, t1; Inode *i0, *i1; Ray r = ray_transform(ro, p->ti); a = v3_sqrnorm(r.d); b = 2 * v3_dot(r.d, r.o); c = v3_sqrnorm(r.o) - 1; if ((disc = SQR(b) - 4 * a * c) <= 0) return (Inode *)0; t0 = (-b - sqrt(disc)) / (2 * a); t1 = (-b + sqrt(disc)) / (2 * a); if (t1 < RAY_EPS) return (Inode *)0; if (t0 < RAY_EPS) { Vector3 n1 = v3_unit(torus_gradient(p, ray_point(r, t1))); return inode_alloc(t1, n1, FALSE); } else { Vector3 n0 = v3_unit(torus_gradient(p, ray_point(ro, t0))); Vector3 n1 = v3_unit(torus_gradient(p, ray_point(ro, t1))); i0 = inode_alloc(t0, n0, TRUE); i1 = inode_alloc(t1, n1, FALSE); i0->next = i1; return i0; } }
main(int argc, char **argv) { Prim *o; Color c; int u, v; Ray r; Inode *l; o = sphere_instance(&sphere_funcs); init_sdl(); s = scene_read(); init_render(); for (v = s->view->sc.ll.y; v < s->view->sc.ur.y; v += 1) { for (u = s->view->sc.ll.x; u < s->view->sc.ur.x; u += 1) { r = ray_unit(ray_transform(ray_view(u, v), mclip)); if ((l = ray_intersect(s->objs, r)) != NULL) c = point_tshade(ray_point(r, l->t), l->n, s->view->center, rc, l->m, o); else c = bgcolor; inode_free(l); img_putc(s->img, u, v, col_dpymap(c)); } } img_write(s->img,"stdout",0); exit(0); }
/** * Calculate the intersection of an object and a ray with * distance within the given bounds. * First triest to find out if the ray intersects the bounding box. * \note The diffrence between this function and the virtual method * object::get_intersection is that this method works in the world * coordinates. */ float object_ray_intersection(struct object *o, const struct ray *r, float lowerBound, float upperBound){ if(!bounding_box_ray_intersection( &(o->boundingBox), r, lowerBound, upperBound)){ return NAN; } struct ray transformed; float ratio = ray_transform(r, &(o->invTransform), &transformed); lowerBound *= ratio; upperBound *= ratio; return (o->get_intersection(o, &transformed, lowerBound, upperBound)) / ratio; }
main(int argc, char **argv) { Color c; int u, v; Ray r; init_sdl(); s = scene_read(); init_render(); for (v = s->view->sc.ll.y; v < s->view->sc.ur.y; v += 1) { for (u = s->view->sc.ll.x; u < s->view->sc.ur.x; u += 1) { r = ray_unit(ray_transform(ray_view(u, v), mclip)); c = ray_shade(0, 1., r, rc, s->objs); img_putc(s->img, u, v, col_dpymap(c)); } } img_write(s->img,"stdout",0); exit(0); }
bool CEntityMiscModel::TestRay( const ray_t *ray, vec_t *dist ) const { vec_t dist_start = *dist; vec_t dist_local = *dist; ray_t ray_local = *ray; if ( aabb_test_ray( &m_BBox, ray ) == 0 ) { return false; } ray_transform( &ray_local, m_inverse_transform ); if ( m_model && m_model->pSelect ) { if ( m_model->pSelect->TestRay( &ray_local, &dist_local ) ) { *dist = dist_local; } } else{ *dist = dist_local; } return *dist < dist_start; }