static int _llfunc_vec4_add(lua_State *L) { vec4 *a = (vec4*)userdata_get_or_die(L, 1); vec4 *b = (vec4*)userdata_get_or_die(L, 2); vec4 *r = (vec4*)userdata_get_or_new(L, 3, sizeof(vec4)); vec4_add(a, b, r); return 1; }
void make_inv(t_vec4 inv[4], t_vec4 vec[4], t_vec4 faces[6], t_vec4 sign[2]) { inv[0] = vec4_add(vec4_sub(vec4_mul(vec[1], faces[0]), vec4_mul(vec[2], faces[1])), vec4_mul(vec[3], faces[2])); inv[1] = vec4_add(vec4_sub(vec4_mul(vec[0], faces[0]), vec4_mul(vec[2], faces[3])), vec4_mul(vec[3], faces[4])); inv[2] = vec4_add(vec4_sub(vec4_mul(vec[0], faces[1]), vec4_mul(vec[1], faces[3])), vec4_mul(vec[3], faces[5])); inv[3] = vec4_add(vec4_sub(vec4_mul(vec[0], faces[2]), vec4_mul(vec[1], faces[4])), vec4_mul(vec[2], faces[5])); sign[0].s = (t_4dvec){+1, -1, +1, -1}; sign[1].s = (t_4dvec){-1, +1, -1, +1}; }
void point_calc_normal(Point *point, distance_func sdf) { float eps = 0.1e-4; vec4 pos = {point->pos[0], point->pos[1], point->pos[2], 1.0}; vec4 epsX = {eps, 0.f, 0.f, 0.0f}; vec4 epsY = {0.f, eps, 0.f, 0.0f}; vec4 epsZ = {0.f, 0.f, eps, 0.0f}; vec4 ppx, psx, ppy, psy, ppz, psz; vec4_add(ppx, pos, epsX); vec4_add(ppy, pos, epsY); vec4_add(ppz, pos, epsZ); vec4_sub(psx, pos, epsX); vec4_sub(psy, pos, epsY); vec4_sub(psz, pos, epsZ); point->norm[0] = sdf(ppx) - sdf(psx); point->norm[1] = sdf(ppy) - sdf(psy); point->norm[2] = sdf(ppz) - sdf(psz); vec3_norm(point->norm, point->norm); }
/* this function is needed for a serious hack that I really * hate doing. R.I.P. clean code R.I.P. */ ray_t* ray_tinypush(ray_t *rayout, const ray_t *ray) { vector4_t v; vec4_set(&v, (float *)&ray->direction); /* make sure direction was normalized */ vec4_normalize(&v); /* create a tiny displacement vector along direction */ vec4_scale(&v, &v, 0.001f); /* copy the ray */ ray_copy(rayout, ray); /* display the new rays origin */ vec4_add(&rayout->origin, &rayout->origin, &v); return rayout; }
/* reverse the direction and origin of a ray */ ray_t* ray_reverse(ray_t *rayout, const ray_t *ray) { ray_t tmpray; ray_copy(&tmpray, ray); /* scale original direction by magnitude of ray */ vec4_scale(&tmpray.direction, &ray->direction, ray->magnitude); /* origin of new ray is destination of original ray */ vec4_add(&rayout->origin, &tmpray.direction, &ray->origin); /* copy magnitude straight over */ rayout->magnitude = ray->magnitude; /* direction of new ray is reverse that of old ray */ vec4_scale(&rayout->direction, &tmpray.direction, -1.0f); return rayout; }
int main(int argc, char **argv) { SDL_Surface *screen; SDL_Event event; struct vec4 cubeCenter, cube[8]; scalar rota; struct mat4 rot; int i; SDL_Init( SDL_INIT_EVERYTHING ); screen = SDL_SetVideoMode(width, height, 32, 0); proj = proj_perspective(45, (scalar) width / (scalar) height, 1, 10); cubeCenter = vec4_zero(); while(1) { rota = (scalar) SDL_GetTicks() / 1000.0; cubeCenter.z = 5 + sin(rota); rot = mat4_aangle(_vec4(0, 1, 0, 1), rota); cube[0] = vec4_add(mat4_mulv(rot, _vec4( 1, -1, 1, 0)), cubeCenter); cube[1] = vec4_add(mat4_mulv(rot, _vec4(-1, -1, 1, 0)), cubeCenter); cube[2] = vec4_add(mat4_mulv(rot, _vec4(-1, 1, 1, 0)), cubeCenter); cube[3] = vec4_add(mat4_mulv(rot, _vec4( 1, 1, 1, 0)), cubeCenter); cube[4] = vec4_add(mat4_mulv(rot, _vec4( 1, -1, -1, 0)), cubeCenter); cube[5] = vec4_add(mat4_mulv(rot, _vec4(-1, -1, -1, 0)), cubeCenter); cube[6] = vec4_add(mat4_mulv(rot, _vec4(-1, 1, -1, 0)), cubeCenter); cube[7] = vec4_add(mat4_mulv(rot, _vec4( 1, 1, -1, 0)), cubeCenter); SDL_FillRect(screen, 0, 0); drawLine3d(screen, cube[0], cube[1]); drawLine3d(screen, cube[0], cube[3]); drawLine3d(screen, cube[1], cube[2]); drawLine3d(screen, cube[2], cube[3]); drawLine3d(screen, cube[4], cube[5]); drawLine3d(screen, cube[4], cube[7]); drawLine3d(screen, cube[5], cube[6]); drawLine3d(screen, cube[6], cube[7]); drawLine3d(screen, cube[0], cube[4]); drawLine3d(screen, cube[1], cube[5]); drawLine3d(screen, cube[2], cube[6]); drawLine3d(screen, cube[3], cube[7]); SDL_Flip(screen); while(SDL_PollEvent(&event) != 0) { switch(event.type) { case (SDL_QUIT): SDL_Quit(); return 0; default: break; } } } SDL_Quit(); return 0; }
/* 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; } }
/* 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; }