shithub: 3dee

Download patch

ref: ff88c093d0092176e173e1bf6cbcd96df07f7e0c
parent: e66d1694113d84a93d748ad2522411d57eb682f2
author: rodri <rgl@antares-labs.eu>
date: Sat Aug 24 17:48:35 EDT 2024

med: use an orbiting camera. add a 3d compass.

--- a/med.c
+++ b/med.c
@@ -47,6 +47,14 @@
 	int ptype;
 };
 
+typedef struct Compass Compass;
+struct Compass
+{
+	Camera	*cam;
+	Scene	*scn;
+};
+Compass compass;	/* 3d compass */
+
 Rune keys[Ke] = {
  [K↑]		= Kup,
  [K↓]		= Kdown,
@@ -77,7 +85,6 @@
 Shadertab *shader;
 QLock scenelk;
 Mouse om;
-Quaternion orient = {1,0,0,0};
 
 Camera *cam;
 Camcfg camcfg = {
@@ -87,6 +94,12 @@
 	40*DEG, 0.01, 10, PERSPECTIVE
 };
 Point3 center = {0,0,0,1};
+RFrame3 ONF3 = {	/* default orthonormal rframe */
+	0,0,0,1,
+	1,0,0,0,
+	0,1,0,0,
+	0,0,1,0
+};
 LightSource light;		/* global point light */
 
 static int doprof;
@@ -206,7 +219,7 @@
 }
 
 static void
-addbasis(void)
+addbasis(Scene *s)
 {
 	Entity *e;
 	Model *m;
@@ -214,7 +227,7 @@
 
 	m = newmodel();
 	e = newentity("basis", m);
-	e->RFrame3 = subject->RFrame3;
+	e->RFrame3 = ONF3;
 
 	memset(prims, 0, sizeof prims);
 	prims[0].type = prims[1].type = prims[2].type = PLine;
@@ -231,9 +244,26 @@
 	m->addprim(m, prims[1]);
 	m->addprim(m, prims[2]);
 
-	scene->addent(scene, e);
+	s->addent(s, e);
 }
 
+static void
+setupcompass(Compass *c, Rectangle r, Renderer *rctl)
+{
+	static int scale = 3;
+
+	r.max.x = r.min.x + Dx(r)/scale;
+	r.max.y = r.min.y + Dy(r)/scale;
+
+	c->cam = Cam(rectsubpt(r, r.min), rctl, PERSPECTIVE, 30*DEG, 0.1, 10);
+	c->cam->view->p = Pt2(r.min.x,r.min.y,1);
+	c->cam->view->setscale(c->cam->view, scale, scale);
+
+	c->scn = newscene(nil);
+	addbasis(c->scn);
+	placecamera(c->cam, c->scn, camcfg.p, center, Vec3(0,1,0));
+}
+
 Point3
 gouraudvshader(VSparams *sp)
 {
@@ -405,7 +435,7 @@
 Color
 identshader(FSparams *sp)
 {
-	Color tc, c;
+	Color tc;
 
 	if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
 		tc = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
@@ -414,10 +444,7 @@
 	else
 		tc = Pt3(1,1,1,1);
 
-	c = modulapt3(sp->v.c, tc);
-	c.a = 1;
-
-	return c;
+	return modulapt3(sp->v.c, tc);
 }
 
 Shadertab shadertab[] = {
@@ -493,6 +520,7 @@
 		qlock(&scenelk);
 		shootcamera(cam, shader);
 		qunlock(&scenelk);
+		shootcamera(compass.cam, getshader("ident"));
 		if(doprof)
 		fprint(2, "R %llud %llud\nE %llud %llud\nT %llud %llud\nr %llud %llud\n\n",
 			cam->times.R[cam->times.cur-1].t0, cam->times.R[cam->times.cur-1].t1,
@@ -503,6 +531,7 @@
 		if(Δt > HZ2MS(60)*1000000ULL){
 			lockdisplay(display);
 			cam->view->draw(cam->view, screenb);
+			compass.cam->view->draw(compass.cam->view, screenb);
 			unlockdisplay(display);
 			nbsend(drawc, nil);
 			t0 += Δt;
@@ -524,19 +553,28 @@
 void
 lmb(void)
 {
+	static Quaternion orient = {1,0,0,0};
 	Quaternion Δorient;
-	Entity *e;
+	Point3 p;
 
 	if((om.buttons^mctl->buttons) == 0){
 		Δorient = orient;
 		qball(screen->r, om.xy, mctl->xy, &orient, nil);
-		Δorient = mulq(orient, invq(Δorient));
+		Δorient = mulq(Δorient, invq(orient));
 
-		for(e = scene->ents.next; e != &scene->ents; e = e->next){
-			e->bx = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, e->bx))), invq(Δorient))));
-			e->by = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, e->by))), invq(Δorient))));
-			e->bz = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, e->bz))), invq(Δorient))));
-		}
+		/* orbit camera around the center */
+		p = subpt3(cam->p, center);
+		p = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, p))), invq(Δorient))));
+		p.w = cam->p.w;
+		movecamera(cam, p);
+		aimcamera(cam, center);
+
+		/* same for the compass */
+		p = subpt3(compass.cam->p, center);
+		p = vcs2world(compass.cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(compass.cam, p))), invq(Δorient))));
+		p.w = compass.cam->p.w;
+		movecamera(compass.cam, p);
+		aimcamera(compass.cam, center);
 	}
 }
 
@@ -707,18 +745,36 @@
 		movecamera(cam, mulpt3(cam->by, 0.1));
 	if(kdown & 1<<Kfall)
 		movecamera(cam, mulpt3(cam->by, -0.1));
-	if(kdown & 1<<KR↑)
+	if(kdown & 1<<KR↑){
 		rotatecamera(cam, cam->bx, 1*DEG);
-	if(kdown & 1<<KR↓)
+		movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->bx, 1*DEG));
+		rotatecamera(compass.cam, compass.cam->bx, 1*DEG);
+	}
+	if(kdown & 1<<KR↓){
 		rotatecamera(cam, cam->bx, -1*DEG);
-	if(kdown & 1<<KR←)
+		movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->bx, -1*DEG));
+		rotatecamera(compass.cam, compass.cam->bx, -1*DEG);
+	}
+	if(kdown & 1<<KR←){
 		rotatecamera(cam, cam->by, 1*DEG);
-	if(kdown & 1<<KR→)
+		movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->by, 1*DEG));
+		rotatecamera(compass.cam, compass.cam->by, 1*DEG);
+	}
+	if(kdown & 1<<KR→){
 		rotatecamera(cam, cam->by, -1*DEG);
-	if(kdown & 1<<KR↺)
+		movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->by, -1*DEG));
+		rotatecamera(compass.cam, compass.cam->by, -1*DEG);
+	}
+	if(kdown & 1<<KR↺){
 		rotatecamera(cam, cam->bz, 1*DEG);
-	if(kdown & 1<<KR↻)
+		movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->bz, 1*DEG));
+		rotatecamera(compass.cam, compass.cam->bz, 1*DEG);
+	}
+	if(kdown & 1<<KR↻){
 		rotatecamera(cam, cam->bz, -1*DEG);
+		movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->bz, -1*DEG));
+		rotatecamera(compass.cam, compass.cam->bz, -1*DEG);
+	}
 	if(kdown & 1<<Kzoomin)
 		zoomin();
 	if(kdown & 1<<Kzoomout)
@@ -790,7 +846,6 @@
 	model = newmodel();
 	subject = newentity("main", model);
 	scene->addent(scene, subject);
-	addbasis();
 
 	if(memimageinit() != 0)
 		sysfatal("memimageinit: %r");
@@ -808,6 +863,8 @@
 	light.c = Pt3(1,1,1,1);
 	light.type = LightPoint;
 	tsampler = neartexsampler;
+
+	setupcompass(&compass, rectaddpt(Rect(0,0,100,100), subpt(screenb->r.max, Pt(100,100))), rctl);
 
 	kctl = emalloc(sizeof *kctl);
 	kctl->c = chancreate(sizeof(Rune), 16);
--- a/vis.c
+++ b/vis.c
@@ -656,8 +656,8 @@
 void
 lmb(void)
 {
-	Entity *e;
 	Quaternion Δorient;
+	Entity *e;
 
 	if((om.buttons^mctl->buttons) == 0){
 		Δorient = orient;