summaryrefslogtreecommitdiff
path: root/src/modules/ray/ray_render_object_sphere.h
blob: addf1f56e3e81e595c4c151909a6f10171dece97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef _RAY_RENDER_OBJECT_SPHERE_H
#define _RAY_RENDER_OBJECT_SPHERE_H

#include <math.h>

#include "ray_3f.h"
#include "ray_camera.h"
#include "ray_color.h"
#include "ray_object_sphere.h"
#include "ray_object_type.h"
#include "ray_ray.h"
#include "ray_surface.h"


typedef struct ray_render_object_sphere_t {
	ray_object_sphere_t	object;
	ray_3f_t		primary_v;
	float			primary_dot_vv;
	float			r2;
	float			r_inv;
} ray_render_object_sphere_t;


static ray_render_object_sphere_t ray_render_object_sphere_prepare(const ray_object_sphere_t *sphere, const ray_camera_t *camera)
{
	ray_render_object_sphere_t	prepared = { .object = *sphere };

	prepared.primary_v = ray_3f_sub(&sphere->center, &camera->position);
	prepared.primary_dot_vv = ray_3f_dot(&prepared.primary_v, &prepared.primary_v);

	prepared.r2 = sphere->radius * sphere->radius;

	/* to divide by radius via multiplication in ray_object_sphere_normal() */
	prepared.r_inv = 1.0f / sphere->radius;

	return prepared;
}


static inline int ray_render_object_sphere_intersects_ray(ray_render_object_sphere_t *sphere, unsigned depth, ray_ray_t *ray, float *res_distance)
{
	ray_3f_t	v = sphere->primary_v;
	float		dot_vv = sphere->primary_dot_vv;
	float		b, disc;

	if (depth) {
		v = ray_3f_sub(&sphere->object.center, &ray->origin);
		dot_vv = ray_3f_dot(&v, &v);
	}

	b = ray_3f_dot(&v, &ray->direction);
	disc = sphere->r2 - (dot_vv - (b * b));
	if (disc > 0) {
		float	i1, i2;

		disc = sqrtf(disc);

		i1 = b - disc;
		i2 = b + disc;

		if (i2 > 0 && i1 > 0) {
			*res_distance = i1;
			return 1;
		}
	}

	return 0;
}


/* return the normal of the surface at the specified point */
static inline ray_3f_t ray_render_object_sphere_normal(ray_render_object_sphere_t *sphere, ray_3f_t *point)
{
	ray_3f_t	normal;

	normal = ray_3f_sub(point, &sphere->object.center);
	normal = ray_3f_mult_scalar(&normal, sphere->r_inv);	/* normalize without the sqrt() */

	return normal;
}


/* return the surface of the sphere @ point */
static inline ray_surface_t ray_render_object_sphere_surface(ray_render_object_sphere_t *sphere, ray_3f_t *point)
{
	/* uniform solids for now... */
	return sphere->object.surface;
}

#endif
© All Rights Reserved