From c64a0d68e1bee56fd8b0375a747a896e8424398b Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 18 Jun 2023 18:04:00 +0300 Subject: [PATCH] foo --- src/app.h | 3 ++ src/gaw/gaw_sw.c | 1 + src/gaw/gawswtnl.h | 25 ---------- src/geom.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/geom.h | 50 +++++++++++++++++++ src/gfxutil.h | 24 +++++++++ src/rend.c | 73 ++++++++++++++++++++++----- src/rend.h | 11 +++++ src/rt.c | 139 ---------------------------------------------------- src/rt.h | 50 ------------------- src/scene.c | 2 +- src/scr_mod.c | 5 +- src/util.h | 24 +++++++++ 13 files changed, 316 insertions(+), 230 deletions(-) create mode 100644 src/geom.c create mode 100644 src/geom.h create mode 100644 src/gfxutil.h delete mode 100644 src/rt.c delete mode 100644 src/rt.h diff --git a/src/app.h b/src/app.h index f6aa490..d09be0b 100644 --- a/src/app.h +++ b/src/app.h @@ -113,4 +113,7 @@ void app_resize(int x, int y); void app_fullscreen(int fs); void app_vsync(int vsync); +/* defined in scr_mod.c for convenience */ +void primray(cgm_ray *ray, int x, int y); + #endif /* APP_H_ */ diff --git a/src/gaw/gaw_sw.c b/src/gaw/gaw_sw.c index 5e4619c..7258d45 100644 --- a/src/gaw/gaw_sw.c +++ b/src/gaw/gaw_sw.c @@ -20,6 +20,7 @@ along with this program. If not, see . #include "gaw.h" #include "gawswtnl.h" #include "polyfill.h" +#include "../util.h" static struct pimage textures[MAX_TEXTURES]; diff --git a/src/gaw/gawswtnl.h b/src/gaw/gawswtnl.h index d016291..0d78f5d 100644 --- a/src/gaw/gawswtnl.h +++ b/src/gaw/gawswtnl.h @@ -129,29 +129,4 @@ void gaw_swtnl_subtex2d(int lvl, int x, int y, int xsz, int ysz, int fmt, void * void gaw_swtnl_drawprim(int prim, struct vertex *v, int vnum); -#if defined(__i386__) || defined(__386__) || defined(MSDOS) - -#ifndef INLINE -#if (__STDC_VERSION__ >= 199901) || defined(__GNUC__) -#define INLINE inline -#else -#define INLINE __inline -#endif -#endif - -/* fast conversion of double -> 32bit int - * for details see: - * - http://chrishecker.com/images/f/fb/Gdmfp.pdf - * - http://stereopsis.com/FPU.html#convert - */ -static INLINE int32_t cround64(double val) -{ - val += 6755399441055744.0; - return *(int32_t*)&val; -} -#else -#define cround64(x) ((int32_t)(x)) -#endif - - #endif /* GAWSWTNL_H_ */ diff --git a/src/geom.c b/src/geom.c new file mode 100644 index 0000000..1a89ccd --- /dev/null +++ b/src/geom.c @@ -0,0 +1,139 @@ +/* +RetroRay - integrated standalone vintage modeller/renderer +Copyright (C) 2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include "geom.h" + +int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit) +{ + struct csghit csghit; + + if(!ray_object_csg(ray, obj, &csghit)) { + return 0; + } + if(hit) { + *hit = csghit.ivlist[0].a; + } + return 1; +} + +int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit) +{ + int i, res; + cgm_ray localray = *ray; + + cgm_rmul_mr(&localray, obj->inv_xform); + + switch(obj->type) { + case OBJ_SPHERE: + res = ray_sphere(ray, (const struct sphere*)obj, hit); + break; + + default: + res = 0; + } + + if(res && hit) { + for(i=0; iivcount; i++) { + cgm_vmul_m4v3(&hit->ivlist[i].a.pos, obj->xform); + cgm_vmul_m3v3(&hit->ivlist[i].a.norm, obj->xform); + cgm_vmul_m4v3(&hit->ivlist[i].b.pos, obj->xform); + cgm_vmul_m3v3(&hit->ivlist[i].b.norm, obj->xform); + } + } + return res; +} + +int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit) +{ + int i; + float a, b, c, d, sqrt_d, t1, t2;/*, invrad;*/ + struct rayhit *rhptr; + + a = cgm_vdot(&ray->dir, &ray->dir); + b = 2.0f * ray->dir.x * (ray->origin.x - sph->pos.x) + + 2.0f * ray->dir.y * (ray->origin.y - sph->pos.y) + + 2.0f * ray->dir.z * (ray->origin.z - sph->pos.z); + c = cgm_vdot(&sph->pos, &sph->pos) + cgm_vdot(&ray->origin, &ray->origin) + + cgm_vdot(&sph->pos, &ray->origin) * -2.0f - sph->rad * sph->rad; + + if((d = b * b - 4.0 * a * c) < 0.0) return 0; + + sqrt_d = sqrt(d); + t1 = (-b + sqrt_d) / (2.0 * a); + t2 = (-b - sqrt_d) / (2.0 * a); + + if((t1 < 1e-6f && t2 < 1e-6f) || (t1 > 1.0f && t2 > 1.0f)) { + return 0; + } + + if(hit) { + if(t1 < 1e-6f || t1 > 1.0f) { + t1 = t2; + } else if(t2 < 1e-6f || t2 > 1.0f) { + t2 = t1; + } + if(t2 < t1) { + float tmp = t1; + t1 = t2; + t2 = tmp; + } + + hit->ivcount = 1; + hit->ivlist[0].a.t = t1; + hit->ivlist[0].b.t = t2; + /*invrad = 1.0f / sph->rad;*/ + + rhptr = &hit->ivlist[0].a; + for(i=0; i<2; i++) { + cgm_raypos(&rhptr->pos, ray, rhptr->t); + rhptr->norm = rhptr->pos; + cgm_vnormalize(&rhptr->norm); + /*rhptr->norm.x = rhptr->pos.x * invrad; + rhptr->norm.y = rhptr->pos.y * invrad; + rhptr->norm.z = rhptr->pos.z * invrad;*/ + rhptr->uv.x = (atan2(rhptr->norm.z, rhptr->norm.x) + CGM_PI) / (2.0 * CGM_PI); + rhptr->uv.y = acos(rhptr->norm.y) / CGM_PI; + rhptr->obj = (struct object*)sph; + rhptr = &hit->ivlist[0].b; + } + } + return 1; +} + +int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit) +{ + return 0; +} + +float ray_object_dist(const cgm_ray *ray, const struct object *obj) +{ + /*struct rayhit hit;*/ + cgm_vec3 norm, pvec; + + /*if(ray_object(ray, obj, &hit)) { + return cgm_vdist(&hit.pos, &ray->origin); + }*/ + + /* if we can't hit the object for some reason, fallback to computing the + * distance of obj->pos from the plane perpendicular to the ray at the origin + */ + norm = ray->dir; + /*cgm_vnormalize(&norm);*/ + pvec = obj->pos; + cgm_vsub(&pvec, &ray->origin); + return cgm_vdot(&pvec, &norm); +} diff --git a/src/geom.h b/src/geom.h new file mode 100644 index 0000000..bfd9b21 --- /dev/null +++ b/src/geom.h @@ -0,0 +1,50 @@ +/* +RetroRay - integrated standalone vintage modeller/renderer +Copyright (C) 2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef GEOM_H_ +#define GEOM_H_ + +#include "cgmath/cgmath.h" +#include "scene.h" + +struct rayhit { + float t; + cgm_vec3 pos; + cgm_vec3 norm; + cgm_vec2 uv; + struct object *obj; +}; + +struct interval { + struct rayhit a, b; +}; + +#define MAX_INTERV 32 +struct csghit { + struct interval ivlist[MAX_INTERV]; + int ivcount; +}; + +int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit); +int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit); + +int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit); +int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit); + +float ray_object_dist(const cgm_ray *ray, const struct object *obj); + +#endif /* GEOM_H_ */ diff --git a/src/gfxutil.h b/src/gfxutil.h new file mode 100644 index 0000000..45fef4a --- /dev/null +++ b/src/gfxutil.h @@ -0,0 +1,24 @@ +/* +RetroRay - integrated standalone vintage modeller/renderer +Copyright (C) 2023 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef GFXUTIL_H_ +#define GFXUTIL_H_ + +#define PACK_RGB32(r, g, b) \ + (0xff000000 | ((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | (uint32_t)(b)) + +#endif /* GFXUTIL_H_ */ diff --git a/src/rend.c b/src/rend.c index 09f7f97..c88277f 100644 --- a/src/rend.c +++ b/src/rend.c @@ -16,10 +16,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "rend.h" -#include "rt.h" +#include "app.h" +#include "geom.h" +#include "util.h" +#include "gfxutil.h" +#include "scene.h" struct img_pixmap renderbuf; -struct img_pixmap dbgimg; + +int max_ray_depth; static int rx, ry, rwidth, rheight; static int roffs; @@ -29,11 +34,9 @@ int rend_init(void) { img_init(&renderbuf); - img_init(&dbgimg); - img_load(&dbgimg, "data/foo.jpg"); - img_convert(&dbgimg, IMG_FMT_RGBA32); - rx = ry = rwidth = rheight = roffs = 0; + + max_ray_depth = 6; return 0; } @@ -91,20 +94,43 @@ static void fillrect(uint32_t *fb, int x, int y, int w, int h, uint32_t c) int render(uint32_t *fb) { - int i, j, offs; - uint32_t *src, *dest; + int i, j, w, h, offs, r, g, b; + uint32_t *dest, pcol; + cgm_vec3 color; + cgm_ray ray; - src = (uint32_t*)dbgimg.pixels + roffs; dest = (uint32_t*)renderbuf.pixels + roffs; if(fb) fb += roffs; + if(xstep < 1) xstep = 1; + if(ystep < 1) ystep = 1; + for(i=0; i rheight) h = rheight - i; + for(j=0; j 255) r = 255; + if(g > 255) g = 255; + if(b > 255) b = 255; + + pcol = PACK_RGB32(r, g, b); + offs = i * renderbuf.width + j; - dest[offs] = src[offs]; + dest[offs] = pcol; + if(fb) { - fb[offs] = src[offs]; - fillrect(fb, j, i, xstep, ystep, src[offs]); + w = xstep; + if(j + w > rwidth) w = rwidth - j; + + fillrect(fb, j, i, w, h, pcol); } } } @@ -117,3 +143,26 @@ int render(uint32_t *fb) } return 0; } + +int ray_trace(const cgm_ray *ray, int maxiter, cgm_vec3 *res) +{ + struct rayhit hit; + + if(!scn_intersect(scn, ray, &hit)) { + *res = bgcolor(ray); + return 0; + } + + *res = shade(ray, &hit, maxiter); + return 1; +} + +cgm_vec3 bgcolor(const cgm_ray *ray) +{ + return cgm_vvec(0, 0, 0); +} + +cgm_vec3 shade(const cgm_ray *ray, const struct rayhit *hit, int maxiter) +{ + return cgm_vvec(1, 0, 0); +} diff --git a/src/rend.h b/src/rend.h index 7508de4..61d5b5f 100644 --- a/src/rend.h +++ b/src/rend.h @@ -18,14 +18,25 @@ along with this program. If not, see . #ifndef REND_H_ #define REND_H_ +#include "cgmath/cgmath.h" +#include "geom.h" #include "sizeint.h" #include "imago2.h" extern struct img_pixmap renderbuf; +extern int max_ray_depth; + +struct scene; int rend_init(void); void rend_size(int xsz, int ysz); void rend_begin(int x, int y, int w, int h); int render(uint32_t *fb); +int ray_trace(const cgm_ray *ray, int maxiter, cgm_vec3 *res); + +cgm_vec3 bgcolor(const cgm_ray *ray); +cgm_vec3 shade(const cgm_ray *ray, const struct rayhit *hit, int maxiter); + + #endif /* REND_H_ */ diff --git a/src/rt.c b/src/rt.c deleted file mode 100644 index f917836..0000000 --- a/src/rt.c +++ /dev/null @@ -1,139 +0,0 @@ -/* -RetroRay - integrated standalone vintage modeller/renderer -Copyright (C) 2023 John Tsiombikas - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#include "rt.h" - -int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit) -{ - struct csghit csghit; - - if(!ray_object_csg(ray, obj, &csghit)) { - return 0; - } - if(hit) { - *hit = csghit.ivlist[0].a; - } - return 1; -} - -int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit) -{ - int i, res; - cgm_ray localray = *ray; - - cgm_rmul_mr(&localray, obj->inv_xform); - - switch(obj->type) { - case OBJ_SPHERE: - res = ray_sphere(ray, (const struct sphere*)obj, hit); - break; - - default: - res = 0; - } - - if(res && hit) { - for(i=0; iivcount; i++) { - cgm_vmul_m4v3(&hit->ivlist[i].a.pos, obj->xform); - cgm_vmul_m3v3(&hit->ivlist[i].a.norm, obj->xform); - cgm_vmul_m4v3(&hit->ivlist[i].b.pos, obj->xform); - cgm_vmul_m3v3(&hit->ivlist[i].b.norm, obj->xform); - } - } - return res; -} - -int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit) -{ - int i; - float a, b, c, d, sqrt_d, t1, t2;/*, invrad;*/ - struct rayhit *rhptr; - - a = cgm_vdot(&ray->dir, &ray->dir); - b = 2.0f * ray->dir.x * (ray->origin.x - sph->pos.x) + - 2.0f * ray->dir.y * (ray->origin.y - sph->pos.y) + - 2.0f * ray->dir.z * (ray->origin.z - sph->pos.z); - c = cgm_vdot(&sph->pos, &sph->pos) + cgm_vdot(&ray->origin, &ray->origin) + - cgm_vdot(&sph->pos, &ray->origin) * -2.0f - sph->rad * sph->rad; - - if((d = b * b - 4.0 * a * c) < 0.0) return 0; - - sqrt_d = sqrt(d); - t1 = (-b + sqrt_d) / (2.0 * a); - t2 = (-b - sqrt_d) / (2.0 * a); - - if((t1 < 1e-6f && t2 < 1e-6f) || (t1 > 1.0f && t2 > 1.0f)) { - return 0; - } - - if(hit) { - if(t1 < 1e-6f || t1 > 1.0f) { - t1 = t2; - } else if(t2 < 1e-6f || t2 > 1.0f) { - t2 = t1; - } - if(t2 < t1) { - float tmp = t1; - t1 = t2; - t2 = tmp; - } - - hit->ivcount = 1; - hit->ivlist[0].a.t = t1; - hit->ivlist[0].b.t = t2; - /*invrad = 1.0f / sph->rad;*/ - - rhptr = &hit->ivlist[0].a; - for(i=0; i<2; i++) { - cgm_raypos(&rhptr->pos, ray, rhptr->t); - rhptr->norm = rhptr->pos; - cgm_vnormalize(&rhptr->norm); - /*rhptr->norm.x = rhptr->pos.x * invrad; - rhptr->norm.y = rhptr->pos.y * invrad; - rhptr->norm.z = rhptr->pos.z * invrad;*/ - rhptr->uv.x = (atan2(rhptr->norm.z, rhptr->norm.x) + CGM_PI) / (2.0 * CGM_PI); - rhptr->uv.y = acos(rhptr->norm.y) / CGM_PI; - rhptr->obj = (struct object*)sph; - rhptr = &hit->ivlist[0].b; - } - } - return 1; -} - -int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit) -{ - return 0; -} - -float ray_object_dist(const cgm_ray *ray, const struct object *obj) -{ - /*struct rayhit hit;*/ - cgm_vec3 norm, pvec; - - /*if(ray_object(ray, obj, &hit)) { - return cgm_vdist(&hit.pos, &ray->origin); - }*/ - - /* if we can't hit the object for some reason, fallback to computing the - * distance of obj->pos from the plane perpendicular to the ray at the origin - */ - norm = ray->dir; - /*cgm_vnormalize(&norm);*/ - pvec = obj->pos; - cgm_vsub(&pvec, &ray->origin); - return cgm_vdot(&pvec, &norm); -} diff --git a/src/rt.h b/src/rt.h deleted file mode 100644 index 9390bd9..0000000 --- a/src/rt.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -RetroRay - integrated standalone vintage modeller/renderer -Copyright (C) 2023 John Tsiombikas - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#ifndef RT_H_ -#define RT_H_ - -#include "cgmath/cgmath.h" -#include "scene.h" - -struct rayhit { - float t; - cgm_vec3 pos; - cgm_vec3 norm; - cgm_vec2 uv; - struct object *obj; -}; - -struct interval { - struct rayhit a, b; -}; - -#define MAX_INTERV 32 -struct csghit { - struct interval ivlist[MAX_INTERV]; - int ivcount; -}; - -int ray_object(const cgm_ray *ray, const struct object *obj, struct rayhit *hit); -int ray_object_csg(const cgm_ray *ray, const struct object *obj, struct csghit *hit); - -int ray_sphere(const cgm_ray *ray, const struct sphere *sph, struct csghit *hit); -int ray_csg(const cgm_ray *ray, const struct csgnode *csg, struct csghit *hit); - -float ray_object_dist(const cgm_ray *ray, const struct object *obj); - -#endif /* RT_H_ */ diff --git a/src/scene.c b/src/scene.c index 0ac2e71..48279cc 100644 --- a/src/scene.c +++ b/src/scene.c @@ -18,7 +18,7 @@ along with this program. If not, see . #include #include #include "scene.h" -#include "rt.h" +#include "geom.h" #include "darray.h" #include "logger.h" diff --git a/src/scr_mod.c b/src/scr_mod.c index 47f0119..65c6384 100644 --- a/src/scr_mod.c +++ b/src/scr_mod.c @@ -20,7 +20,7 @@ along with this program. If not, see . #include "app.h" #include "rtk.h" #include "scene.h" -#include "rt.h" +#include "geom.h" #include "cmesh.h" #include "meshgen.h" #include "font.h" @@ -88,7 +88,6 @@ static void act_addobj(void); static void act_rmobj(void); static void draw_rband(void); -static void primray(cgm_ray *ray, int x, int y); static void moveobj(struct object *obj, int px0, int py0, int px1, int py1); @@ -558,7 +557,7 @@ static void draw_rband(void) } } -static void primray(cgm_ray *ray, int x, int y) +void primray(cgm_ray *ray, int x, int y) { float nx, ny; cgm_vec3 npos, farpt; diff --git a/src/util.h b/src/util.h index 44545d4..cda59bf 100644 --- a/src/util.h +++ b/src/util.h @@ -57,4 +57,28 @@ int match_prefix(const char *str, const char *prefix); void enable_fpexcept(void); void disable_fpexcept(void); +#ifndef INLINE +#if (__STDC_VERSION__ >= 199901) || defined(__GNUC__) +#define INLINE inline +#else +#define INLINE __inline +#endif +#endif + +#if defined(__i386__) || defined(__386__) || defined(MSDOS) + +/* fast conversion of double -> 32bit int + * for details see: + * - http://chrishecker.com/images/f/fb/Gdmfp.pdf + * - http://stereopsis.com/FPU.html#convert + */ +static INLINE int32_t cround64(double val) +{ + val += 6755399441055744.0; + return *(int32_t*)&val; +} +#else +#define cround64(x) ((int32_t)(x)) +#endif + #endif /* UTIL_H_ */ -- 1.7.10.4