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;