2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
20 int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit)
24 if(!ray_object_csg(ray, obj, &csghit)) {
28 *hit = csghit.ivlist[0].a;
33 int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit)
36 cgm_ray localray = *ray;
38 cgm_rmul_mr(&localray, obj->inv_xform);
42 res = ray_sphere(&localray, (const struct sphere*)obj, hit);
50 for(i=0; i<hit->ivcount; i++) {
51 cgm_vmul_m4v3(&hit->ivlist[i].a.pos, obj->xform);
52 cgm_vmul_m3v3(&hit->ivlist[i].a.norm, obj->xform);
53 cgm_vmul_m4v3(&hit->ivlist[i].b.pos, obj->xform);
54 cgm_vmul_m3v3(&hit->ivlist[i].b.norm, obj->xform);
62 int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit)
65 float a, b, c, d, sqrt_d, t1, t2;/*, invrad;*/
68 a = cgm_vdot(&ray->dir, &ray->dir);
69 b = 2.0f * ray->dir.x * ray->origin.x +
70 2.0f * ray->dir.y * ray->origin.y +
71 2.0f * ray->dir.z * ray->origin.z;
72 c = cgm_vdot(&ray->origin, &ray->origin) - sph->rad * sph->rad;
74 if((d = b * b - 4.0 * a * c) < 0.0) return 0;
77 t1 = (-b + sqrt_d) / (2.0 * a);
78 t2 = (-b - sqrt_d) / (2.0 * a);
80 if((t1 < EPSILON && t2 < EPSILON) || (t1 > 1.0f && t2 > 1.0f)) {
85 if(t1 < EPSILON || t1 > 1.0f) {
87 } else if(t2 < EPSILON || t2 > 1.0f) {
97 hit->ivlist[0].a.t = t1;
98 hit->ivlist[0].b.t = t2;
99 /*invrad = 1.0f / sph->rad;*/
101 rhptr = &hit->ivlist[0].a;
103 cgm_raypos(&rhptr->pos, ray, rhptr->t);
104 rhptr->norm = rhptr->pos;
105 cgm_vnormalize(&rhptr->norm);
106 /*rhptr->norm.x = rhptr->pos.x * invrad;
107 rhptr->norm.y = rhptr->pos.y * invrad;
108 rhptr->norm.z = rhptr->pos.z * invrad;*/
109 rhptr->uv.x = (atan2(rhptr->norm.z, rhptr->norm.x) + CGM_PI) / (2.0 * CGM_PI);
110 rhptr->uv.y = acos(rhptr->norm.y) / CGM_PI;
111 rhptr->obj = (struct object*)sph;
112 rhptr = &hit->ivlist[0].b;
118 int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit)
123 float ray_object_dist(const cgm_ray *ray, const struct object *obj)
125 /*struct rayhit hit;*/
128 /*if(ray_object(ray, obj, &hit)) {
129 return cgm_vdist(&hit.pos, &ray->origin);
132 /* if we can't hit the object for some reason, fallback to computing the
133 * distance of obj->pos from the plane perpendicular to the ray at the origin
136 /*cgm_vnormalize(&norm);*/
138 cgm_vsub(&pvec, &ray->origin);
139 return cgm_vdot(&pvec, &norm);