shithub: libgraphics

Download patch

ref: aa277571f316168d7ccf043c76bd2abd97e5bacd
parent: 82888bed1931e83ed1401485033cb9f7acdadc94
author: rodri <rgl@antares-labs.eu>
date: Sat Jul 13 16:50:13 EDT 2024

new camera interface.

--- a/camera.c
+++ b/camera.c
@@ -106,14 +106,42 @@
 	assert(c->clip.n > 0 && c->clip.n < c->clip.f);
 }
 
-/* TODO the current camera abstraction is quite dirty, not pleasant to work with. make it better. */
-//Camera *
-//Cam(Camcfg cfg)
-//{
-//	
-//}
+Camera *
+Cam(Rectangle vr, Renderer *r, Projection p, double fov, double clipn, double clipf)
+{
+	Camera *c;
 
+	c = newcamera();
+	c->vp = mkviewport(vr);
+	c->rctl = r;
+	c->projtype = p;
+	c->fov = fov;
+	c->clip.n = clipn;
+	c->clip.f = clipf;
+	reloadcamera(c);
+	return c;
+}
+
+Camera *
+newcamera(void)
+{
+	Camera *c;
+
+	c = emalloc(sizeof *c);
+	memset(c, 0, sizeof *c);
+	return c;
+}
+
 void
+delcamera(Camera *c)
+{
+	if(c == nil)
+		return;
+	rmviewport(c->vp);
+	free(c);
+}
+
+void
 reloadcamera(Camera *c)
 {
 	double a;
@@ -120,16 +148,17 @@
 	double l, r, b, t;
 
 	verifycfg(c);
+
 	switch(c->projtype){
 	case ORTHOGRAPHIC:
-		r = Dx(c->vp->fbctl->fb[0]->r)/2;
-		t = Dy(c->vp->fbctl->fb[0]->r)/2;
+		r = Dx(c->vp->r)/2;
+		t = Dy(c->vp->r)/2;
 		l = -r;
 		b = -t;
 		orthographic(c->proj, l, r, b, t, c->clip.n, c->clip.f);
 		break;
 	case PERSPECTIVE:
-		a = (double)Dx(c->vp->fbctl->fb[0]->r)/Dy(c->vp->fbctl->fb[0]->r);
+		a = (double)Dx(c->vp->r)/Dy(c->vp->r);
 		perspective(c->proj, c->fov, a, c->clip.n, c->clip.f);
 		break;
 	default: sysfatal("unknown projection type");
@@ -137,19 +166,19 @@
 }
 
 void
-configcamera(Camera *c, Viewport *v, double fov, double n, double f, Projection p)
+configcamera(Camera *c, Projection p, double fov, double n, double f)
 {
-	c->vp = v;
+	c->projtype = p;
 	c->fov = fov;
 	c->clip.n = n;
 	c->clip.f = f;
-	c->projtype = p;
 	reloadcamera(c);
 }
 
 void
-placecamera(Camera *c, Point3 p, Point3 focus, Point3 up)
+placecamera(Camera *c, Scene *s, Point3 p, Point3 focus, Point3 up)
 {
+	c->scene = s;
 	c->p = p;
 	c->bz = focus.w == 0? focus: normvec3(subpt3(c->p, focus));
 	c->bx = normvec3(crossvec3(up, c->bz));
@@ -157,9 +186,25 @@
 }
 
 void
+movecamera(Camera *c, Point3 p)
+{
+	c->p = p.w == 0? addpt3(c->p, p): p;
+}
+
+void
+rotatecamera(Camera *c, Point3 axis, double θ)
+{
+	c->bx = qrotate(c->bx, axis, θ);
+	c->by = qrotate(c->by, axis, θ);
+	c->bz = qrotate(c->bz, axis, θ);
+}
+
+void
 aimcamera(Camera *c, Point3 focus)
 {
-	placecamera(c, c->p, focus, c->by);
+	c->bz = focus.w == 0? focus: normvec3(subpt3(c->p, focus));
+	c->bx = normvec3(crossvec3(c->by, c->bz));
+	c->by = crossvec3(c->bz, c->bx);
 }
 
 void
@@ -167,16 +212,19 @@
 {
 	static Scene *skyboxscene;
 	static Shadertab skyboxshader = { nil, skyboxvs, skyboxfs };
+	Camera cam;
 	Model *mdl;
 	Renderjob *job;
 	uvlong t0, t1;
 
+	assert(c->vp != nil && c->rctl != nil && s != nil);
+
 	job = emalloc(sizeof *job);
 	memset(job, 0, sizeof *job);
 	job->fb = c->vp->fbctl->getbb(c->vp->fbctl);
-	job->camera = emalloc(sizeof *c);
-	*job->camera = *c;
-	job->scene = dupscene(c->scene);	/* take a snapshot */
+	cam = *c;
+	job->camera = &cam;
+	job->scene = dupscene(c->scene);	/* take a snapshot */	
 	job->shaders = s;
 	job->donec = chancreate(sizeof(void*), 0);
 
@@ -209,6 +257,5 @@
 	updatetimes(c, job);
 
 	chanfree(job->donec);
-	free(job->camera);
 	free(job);
 }
--- a/graphics.h
+++ b/graphics.h
@@ -267,6 +267,7 @@
 {
 	RFrame;
 	Framebufctl *fbctl;
+	Rectangle r;
 
 	void (*draw)(Viewport*, Image*);
 	void (*memdraw)(Viewport*, Memimage*);
@@ -298,9 +299,14 @@
 };
 
 /* camera */
+Camera *Cam(Rectangle, Renderer*, Projection, double, double, double);
+Camera *newcamera(void);
+void delcamera(Camera*);
 void reloadcamera(Camera*);
-void configcamera(Camera*, Viewport*, double, double, double, Projection);
-void placecamera(Camera*, Point3, Point3, Point3);
+void configcamera(Camera*, Projection, double, double, double);
+void placecamera(Camera*, Scene*, Point3, Point3, Point3);
+void movecamera(Camera*, Point3);
+void rotatecamera(Camera*, Point3, double);
 void aimcamera(Camera*, Point3);
 void shootcamera(Camera*, Shadertab*);
 
--- a/viewport.c
+++ b/viewport.c
@@ -36,6 +36,7 @@
 	v->bx = Vec2(1,0);
 	v->by = Vec2(0,1);
 	v->fbctl = mkfbctl(r);
+	v->r = r;
 	v->draw = viewport_draw;
 	v->memdraw = viewport_memdraw;
 	v->getfb = viewport_getfb;