void vec4_transform(struct vec4 *dst, const struct vec4 *v, const struct matrix4 *m) { struct vec4 temp; struct matrix4 transpose; matrix4_transpose(&transpose, m); temp.x = vec4_dot(&transpose.x, v); temp.y = vec4_dot(&transpose.y, v); temp.z = vec4_dot(&transpose.z, v); temp.w = vec4_dot(&transpose.t, v); vec4_copy(dst, &temp); }
/* tests if ray intersects a given polygon */ int ray_intersect_polygon(const ray_t *ray, const polygon_t* poly, point_t *pt, float *distance) { float num = -1.0f * ( vec4_dot((vector4_t *)&poly->plane, &ray->origin) + poly->plane.F); float den = vec4_dot((vector4_t *)&poly->plane, &ray->direction); float w; unsigned int i = 0; /* counter variable for loop */ double angleTotal = 0.0; /* running total of angle */ double angleTmp = 0.0; /* angle between current two vectors */ vector4_t tmp; vector4_t tmp2; #ifdef __SPU__ vector float vTmp; #endif /* if denomenator = 0, ray is parallel to plane */ if(den == 0.0f) { /* return no intersection */ return 0; } w = num / den; /* distance to intersection */ /* if w < 0, intersection point is behind ray */ if(w < 0.0f) { /* return no intersection */ return 0; } /* 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 */ /* at this point we at least know the ray intersects the plane. * let's figure out if the point is actually inside the confined * polygonal area */ for(i = 0; i < poly->nVerticies; ++i) { if(i == (poly->nVerticies - 1)) { /* last vertex, compare with first */ /* calculate two vectors */ vec4_sub(&tmp, &poly->vertex[i], pt); vec4_sub(&tmp2, &poly->vertex[0], pt); /* find angle between them - between normal vectors, dot * product is cos of angle between them */ #ifdef __SPU__ vTmp[0] = vec4_costheta(&tmp, &tmp2); vTmp = _acosf4(vTmp); angleTotal += vTmp[0]; #else angleTmp = vec4_costheta(&tmp, &tmp2); /* arccos to get theta */ angleTmp = acos(angleTmp); angleTotal += angleTmp; #endif } else { /* calculate two vectors */ vec4_sub(&tmp, &poly->vertex[i], pt); vec4_sub(&tmp2, &poly->vertex[i+1], pt); /* find angle between them - between normal vectors, dot * product is cos of angle between them */ #ifdef __SPU__ vTmp[0] = vec4_costheta(&tmp, &tmp2); vTmp = _acosf4(vTmp); angleTotal += vTmp[0]; #else angleTmp = vec4_costheta(&tmp, &tmp2); /* arccos to get theta */ angleTmp = acos(angleTmp); angleTotal += angleTmp; #endif } } /* TODO: this comparison is weak, should be refined */ if((angleTotal + .001) > (2.0 * M_PI)) { return 1; } else { return 0; } }