shithub: libgraphics

Download patch

ref: cdfd05b4e5b4ffedae1a4fffa46f1217a88d09ee
parent: 50d107f27c8ee8980693f54d0fadbdd641516e2a
author: rodri <rgl@antares-labs.eu>
date: Fri Sep 27 16:58:01 EDT 2024

implement exportmodel(2).

this writes a model and its assets into a directory.

--- a/graphics.h
+++ b/graphics.h
@@ -82,6 +82,7 @@
 {
 	Memimage *image;
 	int type;
+	char *file;
 };
 
 struct Cubemap
@@ -406,6 +407,7 @@
 /* marshal */
 Model *readmodel(int);
 usize writemodel(int, Model*);
+int exportmodel(char*, Model*);
 
 /* scene */
 Model *newmodel(void);
--- a/marshal.c
+++ b/marshal.c
@@ -56,10 +56,20 @@
 struct Mtltab
 {
 	Mtlentry *mtls[MTLHTSIZ];
-	ulong nmtls;
 	int loaded;			/* was the table loaded into a model already? */
 };
 
+static char *
+estrdup(char *s)
+{
+	char *t;
+
+	if((t = strdup(s)) == nil)
+		sysfatal("strdup: %r");
+	setmalloctag(t, getcallerpc(&s));
+	return t;
+}
+
 static void
 error(Curline *l, char *fmt, ...)
 {
@@ -178,11 +188,9 @@
 		}
 	if(prev == nil){
 		t->mtls[h] = nm;
-		t->nmtls++;
 		return nm;
 	}
 	prev->next = nm;
-	t->nmtls++;
 	return nm;
 }
 
@@ -623,9 +631,7 @@
 			}
 			memset(&mtl, 0, sizeof mtl);
 
-			mtl.name = strdup(f[1]);
-			if(mtl.name == nil)
-				sysfatal("strdup: %r");
+			mtl.name = estrdup(f[1]);
 			inamaterial++;
 		}else{
 			error(&curline, "syntax error");
@@ -825,18 +831,14 @@
 		n += Bprint(b, "%g\n", m->shininess);
 	}
 
-//	if(m->diffusemap != nil){
-//		n += Bprint("\tdiffusemap: ");
-//		n += Bprint(b, "%s\n", m
-//	}
+	if(m->diffusemap != nil && m->diffusemap->file != nil)
+		n += Bprint(b, "\tdiffusemap: %s\n", m->diffusemap->file);
 
-//	if(m->specularmap != nil){
-//		n += Bprint(b, "\tspecularmap: ");
-//		n += Bprint(b, "%s\n", m
-//	}
+	if(m->specularmap != nil && m->specularmap->file != nil)
+		n += Bprint(b, "\tspecularmap: %s\n", m->specularmap->file);
 
-//	if(m->normalmap != nil)
-//		n += Bprint(b, "\tnormals: ");
+	if(m->normalmap != nil && m->normalmap->file != nil)
+		n += Bprint(b, "\tnormals: %s\n", m->normalmap->file);
 
 	n += Bprint(b, "}\n");
 	return n;
@@ -918,4 +920,115 @@
 	rmitemarray(prima);
 	Bterm(out);
 	return n;
+}
+
+static int
+exporttexture(char *path, Texture *t)
+{
+	int fd;
+
+	fd = create(path, OWRITE|OEXCL, 0644);
+	if(fd < 0){
+		werrstr("create: %r");
+		return -1;
+	}
+	if(writememimage(fd, t->image) < 0){
+		close(fd);
+		werrstr("could not write '%s'", path);
+		return -1;
+	}
+	close(fd);
+	return 0;
+}
+
+int
+exportmodel(char *path, Model *m)
+{
+	static char Esmallbuf[] = "buf too small to hold path";
+	Material *mtl;
+	char buf[256], *pe, *me;
+	int fd, idx;
+
+	idx = 0;
+
+	if((pe = seprint(buf, buf + sizeof buf, "%s", path)) == nil)
+		sysfatal(Esmallbuf);
+
+	for(mtl = m->materials; mtl < m->materials+m->nmaterials; mtl++, idx++){
+		if(mtl->name == nil){
+			fprint(2, "warning: material #%d has no name. skipping...\n", idx);
+			continue;
+		}
+
+		if((me = seprint(pe, buf + sizeof buf, "/%s", mtl->name)) == nil)
+			sysfatal(Esmallbuf);
+
+		if(mtl->diffusemap != nil){
+			if(seprint(me, buf + sizeof buf, "_diffuse.pic") == nil)
+				sysfatal(Esmallbuf);
+
+			if(exporttexture(buf, mtl->diffusemap) < 0)
+				return -1;
+
+//			if(mtl->diffusemap->file == nil)
+				mtl->diffusemap->file = estrdup(strrchr(buf, '/')+1);
+		}
+
+		if(mtl->specularmap != nil){
+			if(seprint(me, buf + sizeof buf, "_specular.pic") == nil)
+				sysfatal(Esmallbuf);
+
+			if(exporttexture(buf, mtl->specularmap) < 0)
+				return -1;
+
+//			if(mtl->specularmap->file == nil)
+				mtl->specularmap->file = estrdup(strrchr(buf, '/')+1);
+		}
+
+		if(mtl->normalmap != nil){
+			if(seprint(me, buf + sizeof buf, "_normals.pic") == nil)
+				sysfatal(Esmallbuf);
+
+			if(exporttexture(buf, mtl->normalmap) < 0)
+				return -1;
+
+//			if(mtl->normalmap->file == nil)
+				mtl->normalmap->file = estrdup(strrchr(buf, '/')+1);
+		}
+	}
+
+	if(seprint(pe, buf + sizeof buf, "/main.mdl") == nil)
+		sysfatal(Esmallbuf);
+
+	fd = create(buf, OWRITE|OEXCL, 0644);
+	if(fd < 0){
+		werrstr("create: %r");
+		return -1;
+	}
+	if(writemodel(fd, m) == 0){
+		close(fd);
+		werrstr("writemodel: %r");
+		return -1;
+	}
+	close(fd);
+
+	for(mtl = m->materials; mtl < m->materials+m->nmaterials; mtl++){
+		if(mtl->name == nil)
+			continue;
+
+		if(mtl->diffusemap != nil){
+			free(mtl->diffusemap->file);
+			mtl->diffusemap->file = nil;
+		}
+		if(mtl->specularmap != nil){
+			free(mtl->specularmap->file);
+			mtl->specularmap->file = nil;
+		}
+		if(mtl->normalmap != nil){
+			free(mtl->normalmap->file);
+			mtl->normalmap->file = nil;
+		}
+	}
+
+	return 0;
 }
--- a/texture.c
+++ b/texture.c
@@ -124,6 +124,7 @@
 	Texture *t;
 
 	t = emalloc(sizeof *t);
+	memset(t, 0, sizeof *t);
 	t->image = i;
 	t->type = type;
 	return t;