diff options
-rw-r--r-- | fb.c | 20 | ||||
-rw-r--r-- | graphics.h | 15 | ||||
-rw-r--r-- | obj.c | 317 | ||||
-rw-r--r-- | scene.c | 294 | ||||
-rw-r--r-- | viewport.c | 28 |
5 files changed, 359 insertions, 315 deletions
@@ -93,18 +93,18 @@ scale3x_filter(ulong *dst, Framebuf *fb, Point sp) //} static void -framebufctl_draw(Framebufctl *ctl, Image *dst) +framebufctl_draw(Framebufctl *ctl, Image *dst, Point off) { Framebuf *fb; qlock(ctl); fb = ctl->getfb(ctl); - loadimage(dst, rectaddpt(fb->r, dst->r.min), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); + loadimage(dst, rectaddpt(fb->r, addpt(dst->r.min, off)), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); qunlock(ctl); } static void -framebufctl_upscaledraw(Framebufctl *ctl, Image *dst, Point scale) +framebufctl_upscaledraw(Framebufctl *ctl, Image *dst, Point off, Point scale) { void (*filter)(ulong*, Framebuf*, Point); Framebuf *fb; @@ -130,8 +130,8 @@ framebufctl_upscaledraw(Framebufctl *ctl, Image *dst, Point scale) break; } - for(sp.y = fb->r.min.y, dp.y = dst->r.min.y; sp.y < fb->r.max.y; sp.y++, dp.y += scale.y) - for(sp.x = fb->r.min.x, dp.x = dst->r.min.x; sp.x < fb->r.max.x; sp.x++, dp.x += scale.x){ + for(sp.y = fb->r.min.y, dp.y = dst->r.min.y+off.y; sp.y < fb->r.max.y; sp.y++, dp.y += scale.y) + for(sp.x = fb->r.min.x, dp.x = dst->r.min.x+off.x; sp.x < fb->r.max.x; sp.x++, dp.x += scale.x){ if(filter != nil) filter(blk, fb, sp); else @@ -143,18 +143,18 @@ framebufctl_upscaledraw(Framebufctl *ctl, Image *dst, Point scale) } static void -framebufctl_memdraw(Framebufctl *ctl, Memimage *dst) +framebufctl_memdraw(Framebufctl *ctl, Memimage *dst, Point off) { Framebuf *fb; qlock(ctl); fb = ctl->getfb(ctl); - loadmemimage(dst, rectaddpt(fb->r, dst->r.min), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); + loadmemimage(dst, rectaddpt(fb->r, addpt(dst->r.min, off)), (uchar*)fb->cb, Dx(fb->r)*Dy(fb->r)*4); qunlock(ctl); } static void -framebufctl_upscalememdraw(Framebufctl *ctl, Memimage *dst, Point scale) +framebufctl_upscalememdraw(Framebufctl *ctl, Memimage *dst, Point off, Point scale) { void (*filter)(ulong*, Framebuf*, Point); Framebuf *fb; @@ -180,8 +180,8 @@ framebufctl_upscalememdraw(Framebufctl *ctl, Memimage *dst, Point scale) break; } - for(sp.y = fb->r.min.y, dp.y = dst->r.min.y; sp.y < fb->r.max.y; sp.y++, dp.y += scale.y) - for(sp.x = fb->r.min.x, dp.x = dst->r.min.x; sp.x < fb->r.max.x; sp.x++, dp.x += scale.x){ + for(sp.y = fb->r.min.y, dp.y = dst->r.min.y+off.y; sp.y < fb->r.max.y; sp.y++, dp.y += scale.y) + for(sp.x = fb->r.min.x, dp.x = dst->r.min.x+off.x; sp.x < fb->r.max.x; sp.x++, dp.x += scale.x){ if(filter != nil) filter(blk, fb, sp); else @@ -261,10 +261,10 @@ struct Framebufctl uint idx; /* front buffer index */ uint upfilter; /* upscaling filter */ - void (*draw)(Framebufctl*, Image*); - void (*upscaledraw)(Framebufctl*, Image*, Point); - void (*memdraw)(Framebufctl*, Memimage*); - void (*upscalememdraw)(Framebufctl*, Memimage*, Point); + void (*draw)(Framebufctl*, Image*, Point); + void (*upscaledraw)(Framebufctl*, Image*, Point, Point); + void (*memdraw)(Framebufctl*, Memimage*, Point); + void (*upscalememdraw)(Framebufctl*, Memimage*, Point, Point); void (*drawnormals)(Framebufctl*, Image*); void (*swap)(Framebufctl*); void (*reset)(Framebufctl*); @@ -283,6 +283,8 @@ struct Viewport void (*setscale)(Viewport*, double, double); void (*setscalefilter)(Viewport*, int); Framebuf *(*getfb)(Viewport*); + int (*getwidth)(Viewport*); + int (*getheight)(Viewport*); }; struct Camera @@ -344,8 +346,11 @@ Point3 world2model(Entity*, Point3); void perspective(Matrix3, double, double, double, double); void orthographic(Matrix3, double, double, double, double, double, double); -/* scene */ +/* obj */ int loadobjmodel(Model*, OBJ*); +Model *readobjmodel(char*); + +/* scene */ Model *newmodel(void); Model *dupmodel(Model*); void delmodel(Model*); @@ -0,0 +1,317 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <memdraw.h> +#include <geometry.h> +#include "libobj/obj.h" +#include "graphics.h" +#include "internal.h" + +/* + * fan triangulation. + * + * TODO check that the polygon is in fact convex + * try to adapt if not (by finding a convex + * vertex), or discard it. + */ +static int +triangulate(OBJElem **newe, OBJElem *e) +{ + OBJIndexArray *newidxtab; + OBJIndexArray *idxtab; + int i; + + idxtab = &e->indextab[OBJVGeometric]; + for(i = 0; i < idxtab->nindex-2; i++){ + idxtab = &e->indextab[OBJVGeometric]; + newe[i] = emalloc(sizeof **newe); + memset(newe[i], 0, sizeof **newe); + newe[i]->type = OBJEFace; + newe[i]->mtl = e->mtl; + newidxtab = &newe[i]->indextab[OBJVGeometric]; + newidxtab->nindex = 3; + newidxtab->indices = emalloc(newidxtab->nindex*sizeof(*newidxtab->indices)); + newidxtab->indices[0] = idxtab->indices[0]; + newidxtab->indices[1] = idxtab->indices[i+1]; + newidxtab->indices[2] = idxtab->indices[i+2]; + idxtab = &e->indextab[OBJVTexture]; + if(idxtab->nindex > 0){ + newidxtab = &newe[i]->indextab[OBJVTexture]; + newidxtab->nindex = 3; + newidxtab->indices = emalloc(newidxtab->nindex*sizeof(*newidxtab->indices)); + newidxtab->indices[0] = idxtab->indices[0]; + newidxtab->indices[1] = idxtab->indices[i+1]; + newidxtab->indices[2] = idxtab->indices[i+2]; + } + idxtab = &e->indextab[OBJVNormal]; + if(idxtab->nindex > 0){ + newidxtab = &newe[i]->indextab[OBJVNormal]; + newidxtab->nindex = 3; + newidxtab->indices = emalloc(newidxtab->nindex*sizeof(*newidxtab->indices)); + newidxtab->indices[0] = idxtab->indices[0]; + newidxtab->indices[1] = idxtab->indices[i+1]; + newidxtab->indices[2] = idxtab->indices[i+2]; + } + } + + return i; +} + +typedef struct OBJ2MtlEntry OBJ2MtlEntry; +typedef struct OBJ2MtlMap OBJ2MtlMap; + +struct OBJ2MtlEntry +{ + OBJMaterial *objmtl; + ulong idx; + OBJ2MtlEntry *next; +}; + +struct OBJ2MtlMap +{ + OBJ2MtlEntry *head; + Material *mtls; +}; + +static void +addmtlmap(OBJ2MtlMap *map, OBJMaterial *om, ulong idx) +{ + OBJ2MtlEntry *e; + + if(om == nil) + return; + + e = emalloc(sizeof *e); + memset(e, 0, sizeof *e); + e->objmtl = om; + e->idx = idx; + + if(map->head == nil){ + map->head = e; + return; + } + + e->next = map->head; + map->head = e; +} + +static Material * +getmtlmap(OBJ2MtlMap *map, OBJMaterial *om) +{ + OBJ2MtlEntry *e; + + for(e = map->head; e != nil; e = e->next) + if(e->objmtl == om) + return &map->mtls[e->idx]; + return nil; +} + +static void +clrmtlmap(OBJ2MtlMap *map) +{ + OBJ2MtlEntry *e, *ne; + + for(e = map->head; e != nil; e = ne){ + ne = e->next; + free(e); + } +} + +int +loadobjmodel(Model *m, OBJ *obj) +{ + Primitive *p; + OBJVertex *pverts, *tverts, *nverts, *v; /* geometric, texture and normals vertices */ + OBJElem **trielems, *e, *ne; + OBJObject *o; + OBJIndexArray *idxtab; + OBJ2MtlMap mtlmap; + OBJMaterial *objmtl; + Material *mtl; + Point3 n; /* surface normal */ + int i, idx, nt, maxnt, neednormal, gottaclean; + + if(obj == nil) + return 0; + + pverts = obj->vertdata[OBJVGeometric].verts; + tverts = obj->vertdata[OBJVTexture].verts; + nverts = obj->vertdata[OBJVNormal].verts; + trielems = nil; + maxnt = 0; + + if(m->prims != nil){ + free(m->prims); + m->prims = nil; + } + m->nprims = 0; + + mtlmap.head = nil; + for(i = 0; obj->materials != nil && i < nelem(obj->materials->mattab); i++) + for(objmtl = obj->materials->mattab[i]; objmtl != nil; objmtl = objmtl->next){ + mtlmap.mtls = m->materials = erealloc(m->materials, ++m->nmaterials*sizeof(*m->materials)); + mtl = &m->materials[m->nmaterials-1]; + memset(mtl, 0, sizeof *mtl); + + if(objmtl->name != nil){ + mtl->name = strdup(objmtl->name); + if(mtl->name == nil) + sysfatal("strdup: %r"); + } + mtl->ambient = Pt3(objmtl->Ka.r, objmtl->Ka.g, objmtl->Ka.b, 1); + mtl->diffuse = Pt3(objmtl->Kd.r, objmtl->Kd.g, objmtl->Kd.b, 1); + mtl->specular = Pt3(objmtl->Ks.r, objmtl->Ks.g, objmtl->Ks.b, 1); + mtl->shininess = objmtl->Ns; + + if(objmtl->map_Kd != nil){ + mtl->diffusemap = alloctexture(sRGBTexture, nil); + mtl->diffusemap->image = dupmemimage(objmtl->map_Kd); + } + + if(objmtl->norm != nil){ + mtl->normalmap = alloctexture(RAWTexture, nil); + mtl->normalmap->image = dupmemimage(objmtl->norm); + } + + addmtlmap(&mtlmap, objmtl, m->nmaterials-1); + } + + for(i = 0; i < nelem(obj->objtab); i++) + for(o = obj->objtab[i]; o != nil; o = o->next) + for(e = o->child; e != nil; e = ne){ + ne = e->next; + + switch(e->type){ + case OBJEPoint: + m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims)); + p = &m->prims[m->nprims-1]; + memset(p, 0, sizeof *p); + p->type = PPoint; + p->mtl = getmtlmap(&mtlmap, e->mtl); + + idxtab = &e->indextab[OBJVGeometric]; + v = &pverts[idxtab->indices[0]]; + p->v[0].p = Pt3(v->x, v->y, v->z, v->w); + + idxtab = &e->indextab[OBJVTexture]; + if(idxtab->nindex == 1){ + v = &tverts[idxtab->indices[0]]; + p->v[0].uv = Pt2(v->u, v->v, 1); + } + break; + case OBJELine: + m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims)); + p = &m->prims[m->nprims-1]; + memset(p, 0, sizeof *p); + p->type = PLine; + p->mtl = getmtlmap(&mtlmap, e->mtl); + + for(idx = 0; idx < 2; idx++){ + idxtab = &e->indextab[OBJVGeometric]; + v = &pverts[idxtab->indices[idx]]; + p->v[idx].p = Pt3(v->x, v->y, v->z, v->w); + + idxtab = &e->indextab[OBJVTexture]; + if(idxtab->nindex == 2){ + v = &tverts[idxtab->indices[idx]]; + p->v[idx].uv = Pt2(v->u, v->v, 1); + } + } + break; + case OBJEFace: + idxtab = &e->indextab[OBJVGeometric]; + assert(idxtab->nindex >= 3); + gottaclean = 0; + + /* it takes n-2 triangles to fill any given n-gon */ + nt = idxtab->nindex-2; + if(nt > maxnt){ + maxnt = nt; + trielems = erealloc(trielems, maxnt*sizeof(*trielems)); + } + if(nt > 1){ + assert(triangulate(trielems, e) == nt); + gottaclean = 1; + }else + trielems[0] = e; + + while(nt-- > 0){ + e = trielems[nt]; + neednormal = 0; + + m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims)); + p = &m->prims[m->nprims-1]; + memset(p, 0, sizeof *p); + p->type = PTriangle; + p->mtl = getmtlmap(&mtlmap, e->mtl); + + for(idx = 0; idx < 3; idx++){ + idxtab = &e->indextab[OBJVGeometric]; + v = &pverts[idxtab->indices[idx]]; + p->v[idx].p = Pt3(v->x, v->y, v->z, v->w); + + idxtab = &e->indextab[OBJVNormal]; + if(idxtab->nindex == 3){ + v = &nverts[idxtab->indices[idx]]; + p->v[idx].n = normvec3(Vec3(v->i, v->j, v->k)); + }else + neednormal = 1; + + idxtab = &e->indextab[OBJVTexture]; + if(idxtab->nindex == 3){ + v = &tverts[idxtab->indices[idx]]; + p->v[idx].uv = Pt2(v->u, v->v, 1); + } + } + if(p->v[0].uv.w != 0){ + Point3 e0, e1; + Point2 Δuv0, Δuv1; + double det; + + e0 = subpt3(p->v[1].p, p->v[0].p); + e1 = subpt3(p->v[2].p, p->v[0].p); + Δuv0 = subpt2(p->v[1].uv, p->v[0].uv); + Δuv1 = subpt2(p->v[2].uv, p->v[0].uv); + + det = Δuv0.x * Δuv1.y - Δuv1.x * Δuv0.y; + det = det == 0? 0: 1.0/det; + p->tangent.x = det*(Δuv1.y * e0.x - Δuv0.y * e1.x); + p->tangent.y = det*(Δuv1.y * e0.y - Δuv0.y * e1.y); + p->tangent.z = det*(Δuv1.y * e0.z - Δuv0.y * e1.z); + p->tangent = normvec3(p->tangent); + } + if(neednormal){ + n = normvec3(crossvec3(subpt3(p->v[1].p, p->v[0].p), subpt3(p->v[2].p, p->v[0].p))); + p->v[0].n = p->v[1].n = p->v[2].n = n; + } + if(gottaclean){ + free(e->indextab[OBJVGeometric].indices); + free(e->indextab[OBJVNormal].indices); + free(e->indextab[OBJVTexture].indices); + free(e); + } + } + break; + default: continue; + } + } + + free(trielems); + clrmtlmap(&mtlmap); + return m->nprims; +} + +Model * +readobjmodel(char *path) +{ + Model *m; + OBJ *obj; + + m = newmodel(); + if((obj = objparse(path)) == nil) + sysfatal("objparse: %r"); + loadobjmodel(m, obj); + objfree(obj); + return m; +} @@ -8,300 +8,6 @@ #include "graphics.h" #include "internal.h" -/* - * fan triangulation. - * - * TODO check that the polygon is in fact convex - * try to adapt if not (by finding a convex - * vertex), or discard it. - */ -static int -triangulate(OBJElem **newe, OBJElem *e) -{ - OBJIndexArray *newidxtab; - OBJIndexArray *idxtab; - int i; - - idxtab = &e->indextab[OBJVGeometric]; - for(i = 0; i < idxtab->nindex-2; i++){ - idxtab = &e->indextab[OBJVGeometric]; - newe[i] = emalloc(sizeof **newe); - memset(newe[i], 0, sizeof **newe); - newe[i]->type = OBJEFace; - newe[i]->mtl = e->mtl; - newidxtab = &newe[i]->indextab[OBJVGeometric]; - newidxtab->nindex = 3; - newidxtab->indices = emalloc(newidxtab->nindex*sizeof(*newidxtab->indices)); - newidxtab->indices[0] = idxtab->indices[0]; - newidxtab->indices[1] = idxtab->indices[i+1]; - newidxtab->indices[2] = idxtab->indices[i+2]; - idxtab = &e->indextab[OBJVTexture]; - if(idxtab->nindex > 0){ - newidxtab = &newe[i]->indextab[OBJVTexture]; - newidxtab->nindex = 3; - newidxtab->indices = emalloc(newidxtab->nindex*sizeof(*newidxtab->indices)); - newidxtab->indices[0] = idxtab->indices[0]; - newidxtab->indices[1] = idxtab->indices[i+1]; - newidxtab->indices[2] = idxtab->indices[i+2]; - } - idxtab = &e->indextab[OBJVNormal]; - if(idxtab->nindex > 0){ - newidxtab = &newe[i]->indextab[OBJVNormal]; - newidxtab->nindex = 3; - newidxtab->indices = emalloc(newidxtab->nindex*sizeof(*newidxtab->indices)); - newidxtab->indices[0] = idxtab->indices[0]; - newidxtab->indices[1] = idxtab->indices[i+1]; - newidxtab->indices[2] = idxtab->indices[i+2]; - } - } - - return i; -} - -typedef struct OBJ2MtlEntry OBJ2MtlEntry; -typedef struct OBJ2MtlMap OBJ2MtlMap; - -struct OBJ2MtlEntry -{ - OBJMaterial *objmtl; - ulong idx; - OBJ2MtlEntry *next; -}; - -struct OBJ2MtlMap -{ - OBJ2MtlEntry *head; - Material *mtls; -}; - -static void -addmtlmap(OBJ2MtlMap *map, OBJMaterial *om, ulong idx) -{ - OBJ2MtlEntry *e; - - if(om == nil) - return; - - e = emalloc(sizeof *e); - memset(e, 0, sizeof *e); - e->objmtl = om; - e->idx = idx; - - if(map->head == nil){ - map->head = e; - return; - } - - e->next = map->head; - map->head = e; -} - -static Material * -getmtlmap(OBJ2MtlMap *map, OBJMaterial *om) -{ - OBJ2MtlEntry *e; - - for(e = map->head; e != nil; e = e->next) - if(e->objmtl == om) - return &map->mtls[e->idx]; - return nil; -} - -static void -clrmtlmap(OBJ2MtlMap *map) -{ - OBJ2MtlEntry *e, *ne; - - for(e = map->head; e != nil; e = ne){ - ne = e->next; - free(e); - } -} - -int -loadobjmodel(Model *m, OBJ *obj) -{ - Primitive *p; - OBJVertex *pverts, *tverts, *nverts, *v; /* geometric, texture and normals vertices */ - OBJElem **trielems, *e, *ne; - OBJObject *o; - OBJIndexArray *idxtab; - OBJ2MtlMap mtlmap; - OBJMaterial *objmtl; - Material *mtl; - Point3 n; /* surface normal */ - int i, idx, nt, maxnt, neednormal, gottaclean; - - if(obj == nil) - return 0; - - pverts = obj->vertdata[OBJVGeometric].verts; - tverts = obj->vertdata[OBJVTexture].verts; - nverts = obj->vertdata[OBJVNormal].verts; - trielems = nil; - maxnt = 0; - - if(m->prims != nil){ - free(m->prims); - m->prims = nil; - } - m->nprims = 0; - - mtlmap.head = nil; - for(i = 0; obj->materials != nil && i < nelem(obj->materials->mattab); i++) - for(objmtl = obj->materials->mattab[i]; objmtl != nil; objmtl = objmtl->next){ - mtlmap.mtls = m->materials = erealloc(m->materials, ++m->nmaterials*sizeof(*m->materials)); - mtl = &m->materials[m->nmaterials-1]; - memset(mtl, 0, sizeof *mtl); - - if(objmtl->name != nil){ - mtl->name = strdup(objmtl->name); - if(mtl->name == nil) - sysfatal("strdup: %r"); - } - mtl->ambient = Pt3(objmtl->Ka.r, objmtl->Ka.g, objmtl->Ka.b, 1); - mtl->diffuse = Pt3(objmtl->Kd.r, objmtl->Kd.g, objmtl->Kd.b, 1); - mtl->specular = Pt3(objmtl->Ks.r, objmtl->Ks.g, objmtl->Ks.b, 1); - mtl->shininess = objmtl->Ns; - - if(objmtl->map_Kd != nil){ - mtl->diffusemap = alloctexture(sRGBTexture, nil); - mtl->diffusemap->image = dupmemimage(objmtl->map_Kd); - } - - if(objmtl->norm != nil){ - mtl->normalmap = alloctexture(RAWTexture, nil); - mtl->normalmap->image = dupmemimage(objmtl->norm); - } - - addmtlmap(&mtlmap, objmtl, m->nmaterials-1); - } - - for(i = 0; i < nelem(obj->objtab); i++) - for(o = obj->objtab[i]; o != nil; o = o->next) - for(e = o->child; e != nil; e = ne){ - ne = e->next; - - switch(e->type){ - case OBJEPoint: - m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims)); - p = &m->prims[m->nprims-1]; - memset(p, 0, sizeof *p); - p->type = PPoint; - p->mtl = getmtlmap(&mtlmap, e->mtl); - - idxtab = &e->indextab[OBJVGeometric]; - v = &pverts[idxtab->indices[0]]; - p->v[0].p = Pt3(v->x, v->y, v->z, v->w); - - idxtab = &e->indextab[OBJVTexture]; - if(idxtab->nindex == 1){ - v = &tverts[idxtab->indices[0]]; - p->v[0].uv = Pt2(v->u, v->v, 1); - } - break; - case OBJELine: - m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims)); - p = &m->prims[m->nprims-1]; - memset(p, 0, sizeof *p); - p->type = PLine; - p->mtl = getmtlmap(&mtlmap, e->mtl); - - for(idx = 0; idx < 2; idx++){ - idxtab = &e->indextab[OBJVGeometric]; - v = &pverts[idxtab->indices[idx]]; - p->v[idx].p = Pt3(v->x, v->y, v->z, v->w); - - idxtab = &e->indextab[OBJVTexture]; - if(idxtab->nindex == 2){ - v = &tverts[idxtab->indices[idx]]; - p->v[idx].uv = Pt2(v->u, v->v, 1); - } - } - break; - case OBJEFace: - idxtab = &e->indextab[OBJVGeometric]; - assert(idxtab->nindex >= 3); - gottaclean = 0; - - /* it takes n-2 triangles to fill any given n-gon */ - nt = idxtab->nindex-2; - if(nt > maxnt){ - maxnt = nt; - trielems = erealloc(trielems, maxnt*sizeof(*trielems)); - } - if(nt > 1){ - assert(triangulate(trielems, e) == nt); - gottaclean = 1; - }else - trielems[0] = e; - - while(nt-- > 0){ - e = trielems[nt]; - neednormal = 0; - - m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims)); - p = &m->prims[m->nprims-1]; - memset(p, 0, sizeof *p); - p->type = PTriangle; - p->mtl = getmtlmap(&mtlmap, e->mtl); - - for(idx = 0; idx < 3; idx++){ - idxtab = &e->indextab[OBJVGeometric]; - v = &pverts[idxtab->indices[idx]]; - p->v[idx].p = Pt3(v->x, v->y, v->z, v->w); - - idxtab = &e->indextab[OBJVNormal]; - if(idxtab->nindex == 3){ - v = &nverts[idxtab->indices[idx]]; - p->v[idx].n = normvec3(Vec3(v->i, v->j, v->k)); - }else - neednormal = 1; - - idxtab = &e->indextab[OBJVTexture]; - if(idxtab->nindex == 3){ - v = &tverts[idxtab->indices[idx]]; - p->v[idx].uv = Pt2(v->u, v->v, 1); - } - } - if(p->v[0].uv.w != 0){ - Point3 e0, e1; - Point2 Δuv0, Δuv1; - double det; - - e0 = subpt3(p->v[1].p, p->v[0].p); - e1 = subpt3(p->v[2].p, p->v[0].p); - Δuv0 = subpt2(p->v[1].uv, p->v[0].uv); - Δuv1 = subpt2(p->v[2].uv, p->v[0].uv); - - det = Δuv0.x * Δuv1.y - Δuv1.x * Δuv0.y; - det = det == 0? 0: 1.0/det; - p->tangent.x = det*(Δuv1.y * e0.x - Δuv0.y * e1.x); - p->tangent.y = det*(Δuv1.y * e0.y - Δuv0.y * e1.y); - p->tangent.z = det*(Δuv1.y * e0.z - Δuv0.y * e1.z); - p->tangent = normvec3(p->tangent); - } - if(neednormal){ - n = normvec3(crossvec3(subpt3(p->v[1].p, p->v[0].p), subpt3(p->v[2].p, p->v[0].p))); - p->v[0].n = p->v[1].n = p->v[2].n = n; - } - if(gottaclean){ - free(e->indextab[OBJVGeometric].indices); - free(e->indextab[OBJVNormal].indices); - free(e->indextab[OBJVTexture].indices); - free(e); - } - } - break; - default: continue; - } - } - - free(trielems); - clrmtlmap(&mtlmap); - return m->nprims; -} - Model * newmodel(void) { @@ -11,31 +11,33 @@ static void viewport_draw(Viewport *v, Image *dst) { - Point scale; + Point off, scale; + off = Pt(v->p.x, v->p.y); /* no downsampling support yet */ scale.x = max(min(v->bx.x, Dx(dst->r)/Dx(v->r)), 1); scale.y = max(min(v->by.y, Dy(dst->r)/Dy(v->r)), 1); if(scale.x > 1 || scale.y > 1) - v->fbctl->upscaledraw(v->fbctl, dst, scale); + v->fbctl->upscaledraw(v->fbctl, dst, off, scale); else - v->fbctl->draw(v->fbctl, dst); + v->fbctl->draw(v->fbctl, dst, off); } static void viewport_memdraw(Viewport *v, Memimage *dst) { - Point scale; + Point off, scale; + off = Pt(v->p.x, v->p.y); /* no downsampling support yet */ scale.x = max(min(v->bx.x, Dx(dst->r)/Dx(v->r)), 1); scale.y = max(min(v->by.y, Dy(dst->r)/Dy(v->r)), 1); if(scale.x > 1 || scale.y > 1) - v->fbctl->upscalememdraw(v->fbctl, dst, scale); + v->fbctl->upscalememdraw(v->fbctl, dst, off, scale); else - v->fbctl->memdraw(v->fbctl, dst); + v->fbctl->memdraw(v->fbctl, dst, off); } static void @@ -59,6 +61,18 @@ viewport_getfb(Viewport *v) return v->fbctl->getfb(v->fbctl); } +static int +viewport_getwidth(Viewport *v) +{ + return Dx(v->r)*v->bx.x; +} + +static int +viewport_getheight(Viewport *v) +{ + return Dy(v->r)*v->by.y; +} + Viewport * mkviewport(Rectangle r) { @@ -75,6 +89,8 @@ mkviewport(Rectangle r) v->setscale = viewport_setscale; v->setscalefilter = viewport_setscalefilter; v->getfb = viewport_getfb; + v->getwidth = viewport_getwidth; + v->getheight = viewport_getheight; return v; } |