};
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);
return 0;
}
surf->isect = null_isect;
+ surf->hitgeom = null_hitgeom;
surf->sample = null_sample;
surf->calc_bbox = null_bbox;
return surf;
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;
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;
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;
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)
{
}