shithub: 3dee

Download patch

ref: 263444216730830b712a4f8f3a087513c5ac93e9
parent: a435467f81a1d9d429109f3a34988c642bed6035
author: rodri <rgl@antares-labs.eu>
date: Fri Mar 6 16:05:07 EST 2020

redesign of the camera abstraction. general unused/useless data cleaning.

--- a/dat.h
+++ b/dat.h
@@ -26,16 +26,3 @@
 	Scambx, Scamby, Scambz,
 	Se
 };
-
-typedef struct Mesh Mesh;
-typedef struct TTriangle3 TTriangle3;
-
-struct Mesh {
-	Triangle3 *tris;
-	int ntri;
-};
-
-struct TTriangle3 {
-	Triangle3;
-	Image *tx;
-};
--- a/graphics.h
+++ b/graphics.h
@@ -10,23 +10,28 @@
 struct Vertex {
 	Point3 p;	/* position */
 	Point3 n;	/* surface normal */
-	//Image tx;	/* (?) */
 };
 
+struct Viewport
+{
+	RFrame;
+	Memimage *fb;
+};
+
 struct Camera {
 	RFrame3;		/* VCS */
-	Image *viewport;
+	Viewport viewport;
 	double fov;		/* vertical FOV */
-	struct {
-		double n, f;	/* near and far clipping planes */
-	} clip;
+	double clipn;
+	double clipf;
 	Matrix3 proj;		/* VCS to NDC xform */
 	Projection ptype;
+
+	void (*updatefb)(Camera*, Rectangle, ulong);
 };
 
 /* Camera */
-void perspective(Matrix3, double, double, double, double);
-void orthographic(Matrix3, double, double, double, double, double, double);
+Camera *alloccamera(Rectangle, ulong);
 void configcamera(Camera*, Image*, double, double, double, Projection);
 void placecamera(Camera*, Point3, Point3, Point3);
 void aimcamera(Camera*, Point3);
@@ -33,12 +38,14 @@
 void reloadcamera(Camera*);
 
 /* rendering */
-#define FPS2MS(n)	(1000/(n))
+#define FPS2MS(n)		(1000/(n))
 #define WORLD2VCS(cp, p)	(rframexform3((p), *(cp)))
-#define VCS2NDC(cp, p)	(xform3((p), (cp)->proj))
+#define VCS2NDC(cp, p)		(xform3((p), (cp)->proj))
 #define WORLD2NDC(cp, p)	(VCS2NDC((cp), WORLD2VCS((cp), (p))))
 int isclipping(Point3);
 Point toviewport(Camera*, Point3);
 Point2 fromviewport(Camera*, Point);
-void line3(Camera *c, Point3 p0, Point3 p1, int end0, int end1, Image *src);
-Point string3(Camera *c, Point3 p, Image *src, Font *f, char *s);
+void perspective(Matrix3, double, double, double, double);
+void orthographic(Matrix3, double, double, double, double, double, double);
+void line3(Camera*, Point3, Point3, int, int, Image*);
+Point string3(Camera*, Point3, Image*, Font*, char*);
--- a/libgraphics/camera.c
+++ b/libgraphics/camera.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <libc.h>
 #include <draw.h>
+#include <memdraw.h>
 #include "../geometry.h"
 #include "../graphics.h"
 
@@ -13,45 +14,45 @@
 static void
 verifycfg(Camera *c)
 {
-	assert(c->viewport != nil);
+	assert(c->viewport.fb != nil);
 	if(c->ptype == Ppersp)
-		assert(c->fov >= 1 && c->fov < 360);
-	assert(c->clip.n > 0 && c->clip.n < c->clip.f);
+		assert(c->fov > 0 && c->fov < 360);
+	assert(c->clipn > 0 && c->clipn < c->clipf);
 }
 
-void
-perspective(Matrix3 m, double fov, double a, double n, double f)
+static void
+updatefb(Camera *c, Rectangle r, ulong chan)
 {
-	double cotan;
+	Memimage *fb;
 
-	cotan = 1/tan(fov/2*DEG);
-	identity3(m);
-	m[0][0] =  cotan/a;
-	m[1][1] =  cotan;
-	m[2][2] = -(f+n)/(f-n);
-	m[2][3] = -2*f*n/(f-n);
-	m[3][2] = -1;
+	fb = allocmemimage(r, chan);
+	if(fb == nil)
+		sysfatal("allocmemimage: %r");
+	c->viewport.fb = fb;
+	c->viewport.p = Pt2(r.min.x,r.max.y,1);
 }
 
-void
-orthographic(Matrix3 m, double l, double r, double b, double t, double n, double f)
+Camera*
+alloccamera(Rectangle r, ulong chan)
 {
-	identity3(m);
-	m[0][0] =  2/(r - l);
-	m[1][1] =  2/(t - b);
-	m[2][2] = -2/(f - n);
-	m[0][3] = -(r + l)/(r - l);
-	m[1][3] = -(t + b)/(t - b);
-	m[2][3] = -(f + n)/(f - n);
+	Camera *c;
+
+	c = malloc(sizeof(Camera));
+	if(c == nil)
+		sysfatal("malloc: %r");
+	memset(c, 0, sizeof *c);
+	c->viewport.bx = Vec2(1,0);
+	c->viewport.by = Vec2(0,-1);
+	updatefb(c, r, chan);
+	c->updatefb = updatefb;
 }
 
 void
-configcamera(Camera *c, Image *v, double fov, double n, double f, Projection p)
+configcamera(Camera *c, double fov, double n, double f, Projection p)
 {
-	c->viewport = v;
 	c->fov = fov;
-	c->clip.n = n;
-	c->clip.f = f;
+	c->clipn = n;
+	c->clipf = f;
 	c->ptype = p;
 	reloadcamera(c);
 }
@@ -84,19 +85,19 @@
 	switch(c->ptype){
 	case Portho:
 		/*
-		r = Dx(c->viewport->r)/2;
-		t = Dy(c->viewport->r)/2;
+		r = Dx(c->viewport.fb->r)/2;
+		t = Dy(c->viewport.fb->r)/2;
 		l = -r;
 		b = -t;
 		*/
 		l = t = 0;
-		r = Dx(c->viewport->r);
-		b = Dy(c->viewport->r);
-		orthographic(c->proj, l, r, b, t, c->clip.n, c->clip.f);
+		r = Dx(c->viewport.fb->r);
+		b = Dy(c->viewport.fb->r);
+		orthographic(c->proj, l, r, b, t, c->clipn, c->clipf);
 		break;
 	case Ppersp:
-		a = (double)Dx(c->viewport->r)/Dy(c->viewport->r);
-		perspective(c->proj, c->fov, a, c->clip.n, c->clip.f);
+		a = (double)Dx(c->viewport.fb->r)/Dy(c->viewport.fb->r);
+		perspective(c->proj, c->fov, a, c->clipn, c->clipf);
 		break;
 	default: sysfatal("unknown projection type");
 	}
--- a/libgraphics/render.c
+++ b/libgraphics/render.c
@@ -41,13 +41,8 @@
 toviewport(Camera *c, Point3 p)
 {
 	Point2 p2;
-	RFrame rf = {
-		c->viewport->r.min.x, c->viewport->r.max.y, 1,
-		1,  0, 0,
-		0, -1, 0
-	};
 
-	p2 = invrframexform(flatten(c, p), rf);
+	p2 = invrframexform(flatten(c, p), c->viewport);
 	return (Point){p2.x, p2.y};
 }
 
@@ -54,13 +49,33 @@
 Point2
 fromviewport(Camera *c, Point p)
 {
-	RFrame rf = {
-		c->viewport->r.min.x, c->viewport->r.max.y, 1,
-		1,  0, 0,
-		0, -1, 0
-	};
+	return rframexform(Pt2(p.x,p.y,1), c->viewport);
+}
 
-	return rframexform(Pt2(p.x, p.y, 1), rf);
+void
+perspective(Matrix3 m, double fov, double a, double n, double f)
+{
+	double cotan;
+
+	cotan = 1/tan(fov/2*DEG);
+	identity3(m);
+	m[0][0] =  cotan/a;
+	m[1][1] =  cotan;
+	m[2][2] = -(f+n)/(f-n);
+	m[2][3] = -2*f*n/(f-n);
+	m[3][2] = -1;
+}
+
+void
+orthographic(Matrix3 m, double l, double r, double b, double t, double n, double f)
+{
+	identity3(m);
+	m[0][0] =  2/(r - l);
+	m[1][1] =  2/(t - b);
+	m[2][2] = -2/(f - n);
+	m[0][3] = -(r + l)/(r - l);
+	m[1][3] = -(t + b)/(t - b);
+	m[2][3] = -(f + n)/(f - n);
 }
 
 void
--- a/main.c
+++ b/main.c
@@ -10,6 +10,15 @@
 #include "dat.h"
 #include "fns.h"
 
+typedef struct Camcfg Camcfg;
+
+struct Camcfg
+{
+	Point3 p, lookat, up;
+	double fov, clipn, clipf;
+	int ptype;
+};
+
 Rune keys[Ke] = {
  [K↑]		= Kup,
  [K↓]		= Kdown,
@@ -37,11 +46,24 @@
 int kdown;
 vlong t0, t;
 double Δt;
-Mesh model;
+//Mesh model;
 char *mdlpath = "../threedee/mdl/rocket.obj";
 
-Camera cams[4], *maincam;
+Camera *cams[4], *maincam;
+Camcfg camcfgs[4] = {
+	Pt3(2,0,-4,1), Pt3(0,0,0,1), Vec3(0,1,0),
+	90, 0.1, 100, Ppersp,
 
+	Pt3(-2,0,-4,1), Pt3(0,0,0,1), Vec3(0,1,0),
+	120, 0.1, 100, Ppersp,
+
+	Pt3(-2,0,4,1), Pt3(0,0,0,1), Vec3(0,1,0),
+	90, 0.1, 100, Ppersp,
+
+	Pt3(2,0,4,1), Pt3(0,0,0,1), Vec3(0,1,0),
+	120, 0.1, 100, Ppersp
+};
+
 #pragma varargck type "v" Point2
 int
 vfmt(Fmt *f)
@@ -120,7 +142,7 @@
 {
 	int i;
 
-	snprint(stats[Scamno], sizeof(stats[Scamno]), "CAM %lld", maincam-cams+1);
+	snprint(stats[Scamno], sizeof(stats[Scamno]), "CAM %lld", maincam-cams[0]+1);
 	snprint(stats[Sfov], sizeof(stats[Sfov]), "FOV %g°", maincam->fov);
 	snprint(stats[Scampos], sizeof(stats[Scampos]), "%V", maincam->p);
 	snprint(stats[Scambx], sizeof(stats[Scambx]), "bx %V", maincam->bx);
@@ -127,67 +149,67 @@
 	snprint(stats[Scamby], sizeof(stats[Scamby]), "by %V", maincam->by);
 	snprint(stats[Scambz], sizeof(stats[Scambz]), "bz %V", maincam->bz);
 	for(i = 0; i < Se; i++)
-		stringn(maincam->viewport, addpt(screen->r.min, Pt(10, 10 + i*font->height)), display->black, ZP, font, stats[i], sizeof(stats[i]));
+		stringn(maincam->viewport, addpt(screen->r.min, Pt(10,10 + i*font->height)), display->black, ZP, font, stats[i], sizeof(stats[i]));
 }
 
 void
 redraw(void)
 {
-	Triangle3 tmp;
-	static TTriangle3 *vistris;
-	static int nallocvistri;
-	Triangle trit;
-	Point3 n;
-	u8int c;
-	int i, nvistri;
-
-	nvistri = 0;
-	if(nallocvistri == 0 && vistris == nil){
-		nallocvistri = model.ntri/2;
-		vistris = emalloc(nallocvistri*sizeof(TTriangle3));
-	}
-	for(i = 0; i < model.ntri; i++){
-		/* world to camera */
-		tmp.p0 = WORLD2VCS(maincam, model.tris[i].p0);
-		tmp.p1 = WORLD2VCS(maincam, model.tris[i].p1);
-		tmp.p2 = WORLD2VCS(maincam, model.tris[i].p2);
-		/* back-face culling */
-		n = normvec3(crossvec3(subpt3(tmp.p1, tmp.p0), subpt3(tmp.p2, tmp.p0)));
-		if(dotvec3(n, mulpt3(tmp.p0, -1)) <= 0)
-			continue;
-		/* camera to projected ndc */
-		tmp.p0 = VCS2NDC(maincam, tmp.p0);
-		tmp.p1 = VCS2NDC(maincam, tmp.p1);
-		tmp.p2 = VCS2NDC(maincam, tmp.p2);
-		/* clipping */
-		/*
-		 * no clipping for now, the whole triangle is ignored
-		 * if any of its vertices gets outside the fustrum.
-		 */
-		if(isclipping(tmp.p0) || isclipping(tmp.p1) || isclipping(tmp.p2))
-			continue;
-		if(nvistri >= nallocvistri){
-			nallocvistri += model.ntri/3;
-			vistris = erealloc(vistris, nallocvistri*sizeof(TTriangle3));
-		}
-		vistris[nvistri] = (TTriangle3)tmp;
-		c = 0xff*fabs(dotvec3(n, Vec3(0, 0, 1)));
-		vistris[nvistri].tx = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, c<<24|c<<16|c<<8|0xff);
-		nvistri++;
-	}
-	qsort(vistris, nvistri, sizeof(TTriangle3), depthcmp);
+//	Triangle3 tmp;
+//	static TTriangle3 *vistris;
+//	static int nallocvistri;
+//	Triangle trit;
+//	Point3 n;
+//	u8int c;
+//	int i, nvistri;
+//
+//	nvistri = 0;
+//	if(nallocvistri == 0 && vistris == nil){
+//		nallocvistri = model.ntri/2;
+//		vistris = emalloc(nallocvistri*sizeof(TTriangle3));
+//	}
+//	for(i = 0; i < model.ntri; i++){
+//		/* world to camera */
+//		tmp.p0 = WORLD2VCS(maincam, model.tris[i].p0);
+//		tmp.p1 = WORLD2VCS(maincam, model.tris[i].p1);
+//		tmp.p2 = WORLD2VCS(maincam, model.tris[i].p2);
+//		/* back-face culling */
+//		n = normvec3(crossvec3(subpt3(tmp.p1, tmp.p0), subpt3(tmp.p2, tmp.p0)));
+//		if(dotvec3(n, mulpt3(tmp.p0, -1)) <= 0)
+//			continue;
+//		/* camera to projected ndc */
+//		tmp.p0 = VCS2NDC(maincam, tmp.p0);
+//		tmp.p1 = VCS2NDC(maincam, tmp.p1);
+//		tmp.p2 = VCS2NDC(maincam, tmp.p2);
+//		/* clipping */
+//		/*
+//		 * no clipping for now, the whole triangle is ignored
+//		 * if any of its vertices gets outside the fustrum.
+//		 */
+//		if(isclipping(tmp.p0) || isclipping(tmp.p1) || isclipping(tmp.p2))
+//			continue;
+//		if(nvistri >= nallocvistri){
+//			nallocvistri += model.ntri/3;
+//			vistris = erealloc(vistris, nallocvistri*sizeof(TTriangle3));
+//		}
+//		vistris[nvistri] = (TTriangle3)tmp;
+//		c = 0xff*fabs(dotvec3(n, Vec3(0,0,1)));
+//		vistris[nvistri].tx = allocimage(display, Rect(0,0,1,1), screen->chan, 1, c<<24|c<<16|c<<8|0xff);
+//		nvistri++;
+//	}
+//	qsort(vistris, nvistri, sizeof(TTriangle3), depthcmp);
 	lockdisplay(display);
 	draw(maincam->viewport, maincam->viewport->r, display->white, nil, ZP);
 	drawaxis();
-	for(i = 0; i < nvistri; i++){
-		/* ndc to screen */
-		trit.p0 = toviewport(maincam, vistris[i].p0);
-		trit.p1 = toviewport(maincam, vistris[i].p1);
-		trit.p2 = toviewport(maincam, vistris[i].p2);
-		filltriangle(maincam->viewport, trit, vistris[i].tx, ZP);
-		triangle(maincam->viewport, trit, 0, display->black, ZP);
-		freeimage(vistris[i].tx);
-	}
+//	for(i = 0; i < nvistri; i++){
+//		/* ndc to screen */
+//		trit.p0 = toviewport(maincam, vistris[i].p0);
+//		trit.p1 = toviewport(maincam, vistris[i].p1);
+//		trit.p2 = toviewport(maincam, vistris[i].p2);
+//		filltriangle(maincam->viewport, trit, vistris[i].tx, ZP);
+//		triangle(maincam->viewport, trit, 0, display->black, ZP);
+//		freeimage(vistris[i].tx);
+//	}
 	drawstats();
 	flushimage(display, 1);
 	unlockdisplay(display);
@@ -310,13 +332,13 @@
 	if(kdown & 1<<KR↻)
 		placecamera(maincam, maincam->p, maincam->bz, qrotate(maincam->by, maincam->bz, -5*DEG));
 	if(kdown & 1<<Kcam0)
-		maincam = &cams[0];
+		maincam = cams[0];
 	if(kdown & 1<<Kcam1)
-		maincam = &cams[1];
+		maincam = cams[1];
 	if(kdown & 1<<Kcam2)
-		maincam = &cams[2];
+		maincam = cams[2];
 	if(kdown & 1<<Kcam3)
-		maincam = &cams[3];
+		maincam = cams[3];
 	if(kdown & 1<<Kscrshot)
 		screenshot();
 }
@@ -328,8 +350,7 @@
 	if(getwindow(display, Refnone) < 0)
 		fprint(2, "can't reattach to window\n");
 	unlockdisplay(display);
-	maincam->viewport = screen;
-	reloadcamera(maincam);
+	maincam->updatefb(maincam, screen->r, screen->chan);
 }
 
 void
@@ -343,6 +364,7 @@
 threadmain(int argc, char *argv[])
 {
 	OBJ *objmesh;
+	int i;
 
 	fmtinstall('V', Vfmt);
 	fmtinstall('v', vfmt);
@@ -358,15 +380,12 @@
 		sysfatal("initdraw: %r");
 	if((mctl = initmouse(nil, screen)) == nil)
 		sysfatal("initmouse: %r");
-	placecamera(&cams[0], Pt3(2, 0, -4, 1), Pt3(0, 0, 0, 1), Vec3(0, 1, 0));
-	configcamera(&cams[0], screen, 90, 0.1, 100, Ppersp);
-	placecamera(&cams[1], Pt3(-2, 0, -4, 1), Pt3(0, 0, 0, 1), Vec3(0, 1, 0));
-	configcamera(&cams[1], screen, 120, 0.1, 100, Ppersp);
-	placecamera(&cams[2], Pt3(-2, 0, 4, 1), Pt3(0, 0, 0, 1), Vec3(0, 1, 0));
-	configcamera(&cams[2], screen, 90, 0.1, 100, Ppersp);
-	placecamera(&cams[3], Pt3(2, 0, 4, 1), Pt3(0, 0, 0, 1), Vec3(0, 1, 0));
-	configcamera(&cams[3], screen, 120, 0.1, 100, Ppersp);
-	maincam = &cams[0];
+	for(i = 0; i < nelem(cams); i++){
+		cams[i] = alloccamera(screen->r, screen->chan);
+		placecamera(cams[i], camcfgs[i].p, camcfgs[i].lookat, camcfgs[i].up);
+		configcamera(cams[i], camcfgs[i].fov, camcfgs[i].clipn, camcfgs[i].clipf, camcfgs[i].ptype);
+	}
+	maincam = cams[0];
 	if((objmesh = objparse(mdlpath)) == nil)
 		sysfatal("objparse: %r");
 	drawc = chancreate(1, 0);