summaryrefslogtreecommitdiff
path: root/scene.c
diff options
context:
space:
mode:
Diffstat (limited to 'scene.c')
-rw-r--r--scene.c125
1 files changed, 92 insertions, 33 deletions
diff --git a/scene.c b/scene.c
index ba30de9..95c6203 100644
--- a/scene.c
+++ b/scene.c
@@ -166,18 +166,12 @@ loadobjmodel(Model *m, OBJ *obj)
if(objmtl->map_Kd != nil){
mtl->diffusemap = alloctexture(sRGBTexture, nil);
- mtl->diffusemap->image = allocmemimaged(objmtl->map_Kd->r, objmtl->map_Kd->chan, objmtl->map_Kd->data);
- if(mtl->diffusemap->image == nil)
- sysfatal("allocmemimaged: %r");
- mtl->diffusemap->image->data->ref++;
+ mtl->diffusemap->image = dupmemimage(objmtl->map_Kd);
}
if(objmtl->norm != nil){
mtl->normalmap = alloctexture(RAWTexture, nil);
- mtl->normalmap->image = allocmemimaged(objmtl->norm->r, objmtl->norm->chan, objmtl->norm->data);
- if(mtl->normalmap->image == nil)
- sysfatal("allocmemimaged: %r");
- mtl->normalmap->image->data->ref++;
+ mtl->normalmap->image = dupmemimage(objmtl->norm);
}
addmtlmap(&mtlmap, objmtl, m->nmaterials-1);
@@ -318,29 +312,61 @@ newmodel(void)
return m;
}
-void
-delmodel(Model *m)
+Model *
+dupmodel(Model *m)
{
+ Model *nm;
+ int i;
+
if(m == nil)
- return;
+ return nil;
+
+ nm = newmodel();
if(m->tex != nil)
- freetexture(m->tex);
+ nm->tex = duptexture(m->tex);
if(m->nmaterials > 0){
- while(m->nmaterials--){
- freetexture(m->materials[m->nmaterials].diffusemap);
- freetexture(m->materials[m->nmaterials].normalmap);
- free(m->materials[m->nmaterials].name);
+ nm->nmaterials = m->nmaterials;
+ nm->materials = emalloc(nm->nmaterials*sizeof(*nm->materials));
+ for(i = 0; i < m->nmaterials; i++){
+ nm->materials[i] = m->materials[i];
+ nm->materials[i].diffusemap = duptexture(m->materials[i].diffusemap);
+ nm->materials[i].normalmap = duptexture(m->materials[i].normalmap);
+ nm->materials[i].name = strdup(m->materials[i].name);
+ if(nm->materials[i].name == nil)
+ sysfatal("strdup: %r");
}
- free(m->materials);
}
- if(m->nprims > 0)
- free(m->prims);
- memset(m, 0, sizeof *m);
+ if(m->nprims > 0){
+ nm->nprims = m->nprims;
+ nm->prims = emalloc(nm->nprims*sizeof(*nm->prims));
+ for(i = 0; i < m->nprims; i++){
+ nm->prims[i] = m->prims[i];
+ if(nm->nmaterials > 0 && m->prims[i].mtl != nil)
+ nm->prims[i].mtl = &nm->materials[m->prims[i].mtl - m->materials];
+ }
+ }
+ return nm;
+}
+
+void
+delmodel(Model *m)
+{
+ if(m == nil)
+ return;
+
+ freetexture(m->tex);
+ while(m->nmaterials--){
+ freetexture(m->materials[m->nmaterials].diffusemap);
+ freetexture(m->materials[m->nmaterials].normalmap);
+ free(m->materials[m->nmaterials].name);
+ }
+ free(m->materials);
+ free(m->prims);
free(m);
}
Entity *
-newentity(Model *m)
+newentity(char *name, Model *m)
{
Entity *e;
@@ -349,19 +375,37 @@ newentity(Model *m)
e->bx = Vec3(1,0,0);
e->by = Vec3(0,1,0);
e->bz = Vec3(0,0,1);
+ e->name = name == nil? nil: strdup(name);
e->mdl = m;
e->prev = e->next = nil;
return e;
}
+Entity *
+dupentity(Entity *e)
+{
+ Entity *ne;
+
+ if(e == nil)
+ return nil;
+
+ ne = newentity(nil, nil);
+ *ne = *e;
+ if(e->name != nil)
+ ne->name = strdup(e->name);
+ ne->mdl = dupmodel(e->mdl);
+ ne->prev = ne->next = nil;
+ return ne;
+}
+
void
delentity(Entity *e)
{
if(e == nil)
return;
- if(e->mdl != nil)
- delmodel(e->mdl);
- memset(e, 0, sizeof *e);
+
+ delmodel(e->mdl);
+ free(e->name);
free(e);
}
@@ -399,15 +443,20 @@ newscene(char *name)
return s;
}
-void
-delscene(Scene *s)
+Scene *
+dupscene(Scene *s)
{
+ Scene *ns;
+ Entity *e;
+
if(s == nil)
- return;
- clearscene(s);
- free(s->name);
- memset(s, 0, sizeof *s);
- free(s);
+ return nil;
+
+ ns = newscene(s->name);
+ if(s->nents > 0)
+ for(e = s->ents.next; e != &s->ents; e = e->next)
+ ns->addent(ns, dupentity(e));
+ return ns;
}
void
@@ -420,6 +469,16 @@ clearscene(Scene *s)
s->delent(s, e);
delentity(e);
}
- if(s->skybox != nil)
- freecubemap(s->skybox);
+ freecubemap(s->skybox);
+}
+
+void
+delscene(Scene *s)
+{
+ if(s == nil)
+ return;
+
+ clearscene(s);
+ free(s->name);
+ free(s);
}