shithub: musw

Download patch

ref: c6cf604ae9113b5384c253f46bbdd34b0db0bbb5
parent: 4a2e2bfe6c3993ed29c593adfb9069f7c50b9ced
author: rodri <rgl@antares-labs.eu>
date: Thu Jun 16 16:10:51 EDT 2022

brought the VModel struct and its routines to loading from a file and drawing.

--- a/vmodeled/main.c
+++ b/vmodeled/main.c
@@ -1,5 +1,6 @@
 #include <u.h>
 #include <libc.h>
+#include <bio.h>
 #include <thread.h>
 #include <draw.h>
 #include <mouse.h>
@@ -6,10 +7,56 @@
 #include <keyboard.h>
 #include "../libgeometry/geometry.h"
 
+/*
+ * Vector model - made out of lines and curves
+ */
+typedef struct VModel VModel;
+struct VModel
+{
+	Point2 *pts;
+	ulong npts;
+	/* WIP
+	 * l(ine) → takes 2 points
+	 * c(urve) → takes 3 points
+	 */
+	char *strokefmt;
+};
+
 RFrame worldrf;
+VModel *model;
 
 void resized(void);
 
+void*
+emalloc(ulong n)
+{
+	void *p;
+
+	p = malloc(n);
+	if(p == nil)
+		sysfatal("malloc: %r");
+	setmalloctag(p, getcallerpc(&n));
+	return p;
+}
+
+void*
+erealloc(void *p, ulong n)
+{
+	void *np;
+
+	np = realloc(p, n);
+	if(np == nil){
+		if(n == 0)
+			return nil;
+		sysfatal("realloc: %r");
+	}
+	if(p == nil)
+		setmalloctag(np, getcallerpc(&p));
+	else
+		setrealloctag(np, getcallerpc(&p));
+	return np;
+}
+
 Point
 toscreen(Point2 p)
 {
@@ -23,13 +70,93 @@
 	return rframexform(Pt2(p.x,p.y,1), worldrf);
 }
 
+VModel *
+readvmodel(char *file)
+{
+	ulong lineno;
+	char *s, *args[2];
+	Biobuf *bin;
+	VModel *mdl;
+
+	bin = Bopen(file, OREAD);
+	if(bin == nil)
+		sysfatal("Bopen: %r");
+
+	mdl = emalloc(sizeof(VModel));
+	mdl->pts = nil;
+	mdl->npts = 0;
+	mdl->strokefmt = nil;
+
+	lineno = 0;
+	while(s = Brdline(bin, '\n')){
+		s[Blinelen(bin)-1] = 0;
+		lineno++;
+
+		switch(*s++){
+		case '#':
+			continue;
+		case 'v':
+			if(tokenize(s, args, nelem(args)) != nelem(args)){
+				werrstr("syntax error: %s:%lud 'v' expects %d args",
+					file, lineno, nelem(args));
+				free(mdl);
+				Bterm(bin);
+				return nil;
+			}
+			mdl->pts = erealloc(mdl->pts, ++mdl->npts*sizeof(Point2));
+			mdl->pts[mdl->npts-1].x = strtod(args[0], nil);
+			mdl->pts[mdl->npts-1].y = strtod(args[1], nil);
+			mdl->pts[mdl->npts-1].w = 1;
+			break;
+		case 'l':
+		case 'c':
+			mdl->strokefmt = strdup(s-1);
+			break;
+		}
+	}
+	Bterm(bin);
+
+	return mdl;
+}
+
 void
+drawvmodel(Image *dst, VModel *mdl)
+{
+	int i;
+	char *s;
+	Point pts[3];
+	Point2 *p;
+
+	p = mdl->pts;
+	for(s = mdl->strokefmt; s != 0 && p-mdl->pts < mdl->npts; s++)
+		switch(*s){
+		case 'l':
+			line(dst, toscreen(p[0]), toscreen(p[1]), 0, 0, 0, display->white, ZP);
+			p += 2;
+			break;
+		case 'c':
+			for(i = 0; i < nelem(pts); i++)
+				pts[i] = toscreen(p[i]);
+			bezspline(dst, pts, nelem(pts), 0, 0, 0, display->white, ZP);
+			p += 3;
+			break;
+		}
+}
+
+void
+drawaxes(void)
+{
+	line(screen, toscreen(Pt2(0,512,1)), toscreen(Pt2(0,-512,1)), 0, 0, 0, display->white, ZP);
+	line(screen, toscreen(Pt2(512,0,1)), toscreen(Pt2(-512,0,1)), 0, 0, 0, display->white, ZP);
+}
+
+void
 redraw(void)
 {
 	lockdisplay(display);
 	draw(screen, screen->r, display->black, nil, ZP);
-	line(screen, toscreen(Pt2(0,512,1)), toscreen(Pt2(0,-512,1)), 0, 0, 0, display->white, ZP);
-	line(screen, toscreen(Pt2(512,0,1)), toscreen(Pt2(-512,0,1)), 0, 0, 0, display->white, ZP);
+	drawaxes();
+	drawvmodel(screen, model);
 	flushimage(display, 1);
 	unlockdisplay(display);
 }
@@ -100,6 +227,10 @@
 	worldrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.max.y-Dy(screen->r)/2,1);
 	worldrf.bx = Vec2(1, 0);
 	worldrf.by = Vec2(0,-1);
+
+	model = readvmodel("../assets/mdl/wedge.vmdl");
+	if(model == nil)
+		sysfatal("readvmodel: %r");
 
 	display->locking = 1;
 	unlockdisplay(display);