shithub: 3dee

Download patch

ref: ee357201e019605091a5f9c8c05aca061bd8fe61
parent: cbffc87d15cbdc9a023f851f30fa45b16e58d954
author: rodri <rgl@antares-labs.eu>
date: Thu Apr 24 18:14:03 EDT 2025

solar, vis: add scene locks to avoid tearing

i recently changed libgraphics to avoid duplicating the scene
every time shootcamera() is called. this causes tearing in the
resulting picture, unless we take care to update the world
between its rendering.

--- a/solar.c
+++ b/solar.c
@@ -153,6 +153,7 @@
 Tm date;
 char datestr[16];
 Scene *scene;
+QLock scenelk;
 
 Camera *camera;
 Camcfg cameracfg = {
@@ -287,10 +288,12 @@
 	if(p == oldp)
 		return;
 
+	qlock(&scenelk);
 	oldp = selplanet = p;
 	esel = scene->getent(scene, "selection");
 	if(esel != nil)
 		scene->delent(scene, esel);
+	qunlock(&scenelk);
 
 	lockdisplay(display);
 	freeinfobox(infobox);
@@ -351,7 +354,9 @@
 		msel->addprim(msel, l);
 	}
 
+	qlock(&scenelk);
 	scene->addent(scene, esel);
+	qunlock(&scenelk);
 }
 
 static void
@@ -423,6 +428,7 @@
 	int i;
 
 	fprint(2, "loading planet states...\n");
+	qlock(&scenelk);
 	for(i = 1; i < nelem(planets); i++){
 		s = getplanetstate(planets[i].id, &date);
 		if(s == nil){
@@ -440,6 +446,7 @@
 		free(s);
 		fprint(2, "%s ready\n", planets[i].name);
 	}
+	qunlock(&scenelk);
 }
 
 static Planet *
@@ -557,7 +564,10 @@
 
 	t0 = nanosec();
 	for(;;){
+		qlock(&scenelk);
 		shootcamera(camera, &shader);
+		qunlock(&scenelk);
+
 		Δt = nanosec() - t0;
 		if(Δt > HZ2NS(60)){
 			lockdisplay(display);
--- a/vis.c
+++ b/vis.c
@@ -75,6 +75,7 @@
 Mouse om;
 Quaternion orient = {1,0,0,0};
 AABB scenebbox;
+QLock scenelk;
 
 Camera *cams[4], *maincam;
 Camcfg camcfgs[4] = {
@@ -236,7 +237,9 @@
 	for(;;){
 		setuniform(shader, "time", VANumber, &time);
 
+		qlock(&scenelk);
 		shootcamera(maincam, shader);
+		qunlock(&scenelk);
 
 		Δt = nanosec() - t0;
 		if(Δt > HZ2NS(60)){
@@ -281,11 +284,13 @@
 		qball(screen->r, om.xy, mctl->xy, &orient, nil);
 		Δorient = mulq(orient, invq(Δorient));
 
+		qlock(&scenelk);
 		for(e = scene->ents.next; e != &scene->ents; e = e->next){
 			e->bx = vcs2world(maincam, qsandwichpt3(Δorient, world2vcs(maincam, e->bx)));
 			e->by = vcs2world(maincam, qsandwichpt3(Δorient, world2vcs(maincam, e->by)));
 			e->bz = vcs2world(maincam, qsandwichpt3(Δorient, world2vcs(maincam, e->bz)));
 		}
+		qunlock(&scenelk);
 	}else{	/* DBG only */
 		Framebuf *fb;
 		Viewport *v;
@@ -380,6 +385,7 @@
 	lockdisplay(display);
 	switch(menuhit(2, mctl, &menu, _screen)){
 	case MOVELIGHT:
+		qlock(&scenelk);
 		snprint(buf, sizeof buf, "%g %g %g", lights[0]->p.x, lights[0]->p.y, lights[0]->p.z);
 		if(enter("light pos", buf, sizeof buf, mctl, kctl, nil) <= 0)
 			break;
@@ -389,6 +395,7 @@
 		lights[0]->p.x = strtod(f[0], nil);
 		lights[0]->p.y = strtod(f[1], nil);
 		lights[0]->p.z = strtod(f[2], nil);
+		qunlock(&scenelk);
 		break;
 	case TSNEAREST:
 		tsampler = neartexsampler;
--