diff options
author | rodri <rgl@antares-labs.eu> | 2024-07-13 10:23:52 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2024-07-13 10:23:52 +0000 |
commit | 04d50b8bbe324fdb7a8a1e724fbc59c4050862f0 (patch) | |
tree | 285be4b648747346d96e5e0c87d0abec9f80d6a5 /scene.c | |
parent | 45c21bb2483adf0ad1dd2f9950681f6a07a14b24 (diff) | |
download | libgraphics-04d50b8bbe324fdb7a8a1e724fbc59c4050862f0.tar.gz libgraphics-04d50b8bbe324fdb7a8a1e724fbc59c4050862f0.tar.bz2 libgraphics-04d50b8bbe324fdb7a8a1e724fbc59c4050862f0.zip |
fix the geometry glitches when moving things around.
it's possible for interactive programs to keep updating
the geometry of the scene during rendering, which caused
primitives to look deformed or shattered in the final
image.
to avoid this we take a snapshot of the current state of
things (scene and camera), and render based on that copy.
Diffstat (limited to 'scene.c')
-rw-r--r-- | scene.c | 125 |
1 files changed, 92 insertions, 33 deletions
@@ -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); } |