vector float sqrtf4 (vector float x) { return _sqrtf4( x ); }
/* tests if ray intersects a given sphere */ int ray_intersect_sphere(const ray_t *ray, const sphere_t* sphere, point_t *pt, float *distance) { vector4_t tmp; /* used to hold scale of ray direction */ float A = 1; /* since we know ray direction is normalized */ float dx = ray->origin.x - sphere->center.x; float dy = ray->origin.y - sphere->center.y; float dz = ray->origin.z - sphere->center.z; float B = 2 * ( ray->direction.x * (dx) + ray->direction.y * (dy) + ray->direction.z * (dz)); float C = (dx * dx + dy * dy + dz * dz) - (sphere->radius * sphere->radius); float det = (B*B) - (4 * A * C); float wOne; /* distance to first intersection */ float wTwo; /* distance to second intersection */ float w = 0.0f; /* least positive w */ #ifdef __SPU__ vector float vTmp; float scalarTmp; #endif if(det < 0.0f) { /* intersection is behind ray so none at all*/ return 0; } else { /* no need to use A since it's 1 */ #ifdef __SPU__ vTmp = spu_promote(det, 0); scalarTmp = spu_extract( _sqrtf4(vTmp), 0); wOne = (-B - scalarTmp) / (2.0f * A); wTwo = (-B + scalarTmp) / (2.0f * A); #else wOne = (-B - sqrt(det)) / (2.0f * A); wTwo = (-B + sqrt(det)) / (2.0f * A); #endif if(det == 0.0f) { /* one root, wOne and wTwo should be equal */ vec4_add(pt, &ray->origin, vec4_scale(&tmp, &ray->direction, wOne)); *distance = wOne; /* pass back distance to intersection */ return 1; } else { if(wOne > 0.0f) w = wOne; if(wTwo > 0.0f && wTwo < w) w = wTwo; /* now w is least positive root */ /* use it to calculate where intersection point is */ vec4_add(pt, &ray->origin, vec4_scale(&tmp, &ray->direction, w)); *distance = w; /* pass back distance to intersection */ return 1; } } /* all code paths above this point should have returned something * but if we've gotten here anyways, assume no intersection occured */ #if defined(_DEBUG) printf("Ray-Sphere intersection test failed!!!\n"); #endif return 0; }