X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=erebus2020;a=blobdiff_plain;f=liberebus%2Fsrc%2Fsurf.c;fp=liberebus%2Fsrc%2Fsurf.c;h=8f2d4db693746ca975aa60c8879c848dd8837c34;hp=7d8d38aba9007e939b83b33e573c9f5104090490;hb=399df0323dcd1cafe860565fd82598321aff52ee;hpb=2e09068ea0c58f8a464f8584b2bb4e9f23241e95 diff --git a/liberebus/src/surf.c b/liberebus/src/surf.c index 7d8d38a..8f2d4db 100644 --- a/liberebus/src/surf.c +++ b/liberebus/src/surf.c @@ -9,14 +9,17 @@ struct box_data { }; static int null_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +static void null_hitgeom(struct erb_surf *surf, struct erb_hit *hit); static void null_sample(struct erb_surf *surf, cgm_vec3 *pos); static void null_bbox(struct erb_surf *surf, struct erb_aabb *bb); static int sph_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +static void sph_hitgeom(struct erb_surf *surf, struct erb_hit *hit); static void sph_sample(struct erb_surf *surf, cgm_vec3 *pos); static void sph_bbox(struct erb_surf *surf, struct erb_aabb *bb); static int box_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +static void box_hitgeom(struct erb_surf *surf, struct erb_hit *hit); static void box_sample(struct erb_surf *surf, cgm_vec3 *pos); static void box_bbox(struct erb_surf *surf, struct erb_aabb *bb); @@ -30,6 +33,7 @@ struct erb_surf *erb_surface(int datasz) return 0; } surf->isect = null_isect; + surf->hitgeom = null_hitgeom; surf->sample = null_sample; surf->calc_bbox = null_bbox; return surf; @@ -52,6 +56,7 @@ struct erb_surf *erb_surf_sphere(float rad) return 0; } surf->isect = sph_isect; + surf->hitgeom = sph_hitgeom; surf->sample = sph_sample; surf->calc_bbox = sph_bbox; sdata = (struct sph_data*)surf->data; @@ -68,6 +73,7 @@ struct erb_surf *erb_surf_box(float xsz, float ysz, float zsz) return 0; } surf->isect = box_isect; + surf->hitgeom = box_hitgeom; surf->sample = box_sample; surf->calc_bbox = box_bbox; bdata = (struct box_data*)surf->data; @@ -81,6 +87,11 @@ static int null_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit return 0; } +static void null_hitgeom(struct erb_surf *surf, struct erb_hit *hit) +{ + fprintf(stderr, "BUG: null_hitgeom called\n"); +} + static void null_sample(struct erb_surf *surf, cgm_vec3 *pos) { pos->x = pos->y = pos->z = 0; @@ -94,22 +105,102 @@ static void null_bbox(struct erb_surf *surf, struct erb_aabb *bb) static int sph_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit) { - return 0; + float a, b, c, d, sqrt_d, q, t, t0, t1; + cgm_vec3 org, dir; + struct sph_data *sdata = (struct sph_data*)surf->data; + + if(surf->node) { + erb_xform_ray(ray, surf->node->inv_xform, &org, &dir); + } else { + org = ray->o; + dir = ray->d; + } + + a = cgm_vdot(&dir, &dir); + b = 2.0f * cgm_vdot(&org, &dir); + c = cgm_vdot(&org, &org) - sdata->rad * sdata->rad; + + d = b * b - 4.0f * a * c; + if(d <= 0.0f) return 0; + + sqrt_d = sqrt(d); + q = b < 0.0f ? -0.5f * (b - sqrt_d) : -0.5f * (b + sqrt_d); + + t0 = q / a; + t1 = c / q; + if(t1 < t0) { + float ttmp = t0; + t0 = t1; + t1 = ttmp; + } + + if(t0 > ray->tmax || t1 < ray->tmin) { + return 0; + } + t = t0 < ray->tmin ? t1 : t0; + if(t > ray->tmax) { + return 0; + } + + if(hit) { + hit->t = t; + hit->err = 5e-4f * t; /* PBR 3.2.6 */ + hit->surf = surf; + hit->pos = ray->o; + cgm_vadd_scaled(&hit->pos, &ray->d, t); + hit->lpos = org; + cgm_vadd_scaled(&hit->lpos, &dir, t); + hit->total_dist = ray->total_dist + t; + } + + return 1; +} + +static void sph_hitgeom(struct erb_surf *surf, struct erb_hit *hit) +{ + float theta, phi; + + hit->norm = hit->lpos; + cgm_vnormalize(&hit->norm); + + cgm_uvec_to_sph(&theta, &phi, &hit->norm); + + hit->u = (theta + M_PI) / (2.0 * M_PI); + hit->v = phi / M_PI; + + hit->tang.x = hit->norm.z; + hit->tang.y = hit->norm.y; + hit->tang.z = -hit->norm.x; + + if(surf->node) { + cgm_vmul_m3v3(&hit->norm, surf->node->xform); + cgm_vmul_m3v3(&hit->tang, surf->node->xform); + } } static void sph_sample(struct erb_surf *surf, cgm_vec3 *pos) { + /* TODO */ } static void sph_bbox(struct erb_surf *surf, struct erb_aabb *bb) { + struct sph_data *sdata = (struct sph_data*)surf->data; + + cgm_vcons(&bb->pos, 0, 0, 0); + bb->sz.x = bb->sz.y = bb->sz.z = sdata->rad; } +/* TODO boxen */ static int box_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit) { return 0; } +static void box_hitgeom(struct erb_surf *surf, struct erb_hit *hit) +{ +} + static void box_sample(struct erb_surf *surf, cgm_vec3 *pos) { }