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_ */
#include "gaw.h"
#include "gawswtnl.h"
#include "polyfill.h"
+#include "../util.h"
static struct pimage textures[MAX_TEXTURES];
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_ */
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 <https://www.gnu.org/licenses/>.
+*/
+#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; i<hit->ivcount; 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);
+}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 <https://www.gnu.org/licenses/>.
+*/
+#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_ */
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 <https://www.gnu.org/licenses/>.
+*/
+#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_ */
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#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;
{
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;
}
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; i+=ystep) {
+ h = ystep;
+ if(i + h > rheight) h = rheight - i;
+
for(j=0; j<rwidth; j+=xstep) {
+ primray(&ray, rx + j, ry + i);
+ ray_trace(&ray, max_ray_depth, &color);
+
+ r = cround64(color.x * 255.0f);
+ g = cround64(color.y * 255.0f);
+ b = cround64(color.z * 255.0f);
+
+ if(r > 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);
}
}
}
}
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);
+}
#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_ */
+++ /dev/null
-/*
-RetroRay - integrated standalone vintage modeller/renderer
-Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
-
-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 <https://www.gnu.org/licenses/>.
-*/
-#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; i<hit->ivcount; 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);
-}
+++ /dev/null
-/*
-RetroRay - integrated standalone vintage modeller/renderer
-Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
-
-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 <https://www.gnu.org/licenses/>.
-*/
-#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_ */
#include <stdlib.h>
#include <float.h>
#include "scene.h"
-#include "rt.h"
+#include "geom.h"
#include "darray.h"
#include "logger.h"
#include "app.h"
#include "rtk.h"
#include "scene.h"
-#include "rt.h"
+#include "geom.h"
#include "cmesh.h"
#include "meshgen.h"
#include "font.h"
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);
}
}
-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;
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_ */