From ef7a0d43dea903cd8c2f52adcc263c437b5a0454 Mon Sep 17 00:00:00 2001 From: rodri Date: Wed, 22 May 2024 19:09:52 +0000 Subject: began work on a model editor. add two more models. --- mdl/quad.obj | 10 + mdl/rocket.obj | 143 +++++++++++ med.c | 776 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mkfile | 2 + projtest.c | 103 ++++++++ 5 files changed, 1034 insertions(+) create mode 100644 mdl/quad.obj create mode 100644 mdl/rocket.obj create mode 100644 med.c create mode 100644 projtest.c diff --git a/mdl/quad.obj b/mdl/quad.obj new file mode 100644 index 0000000..4c6dfa5 --- /dev/null +++ b/mdl/quad.obj @@ -0,0 +1,10 @@ +v -100 -100 0 +v 100 -100 0 +v -100 100 0 +v 100 100 0 +vt 0 0 +vt 1 0 +vt 0 1 +vt 1 1 +f 1/1 2/2 3/3 +f 4/4 3/3 2/2 diff --git a/mdl/rocket.obj b/mdl/rocket.obj new file mode 100644 index 0000000..834fdbc --- /dev/null +++ b/mdl/rocket.obj @@ -0,0 +1,143 @@ +# Blender v2.79 (sub 0) OBJ File: '' +# www.blender.org +v -0.334186 0.372621 -0.333268 +v -0.334186 0.370788 0.335102 +v 0.334186 0.370788 0.335102 +v 0.334186 0.372621 -0.333268 +v -0.334186 -0.295749 -0.335102 +v -0.334186 -0.297582 0.333269 +v 0.334186 -0.297582 0.333268 +v 0.334186 -0.295749 -0.335102 +v -0.334186 -0.695815 -0.336199 +v -0.334186 -0.697648 0.332171 +v 0.334186 -0.695815 -0.336199 +v 0.334186 -0.697648 0.332171 +v -0.120197 -0.754088 -0.122369 +v -0.120197 -0.754748 0.118024 +v 0.120197 -0.754088 -0.122369 +v 0.120197 -0.754748 0.118024 +v -0.306281 -1.117213 -0.309450 +v -0.306281 -1.118893 0.303111 +v 0.306281 -1.117213 -0.309450 +v 0.306281 -1.118893 0.303110 +v -0.289248 0.712766 -0.287397 +v -0.289248 0.711179 0.291097 +v 0.289248 0.712766 -0.287397 +v 0.289248 0.711179 0.291097 +v -0.233218 0.885662 -0.230892 +v -0.233218 0.884382 0.235542 +v 0.233218 0.885662 -0.230893 +v 0.233218 0.884382 0.235542 +v -0.165619 1.041305 -0.162866 +v -0.165619 1.040397 0.168371 +v 0.165619 1.041305 -0.162866 +v 0.165619 1.040397 0.168370 +v -0.109259 1.126811 -0.106272 +v -0.109259 1.126212 0.112246 +v 0.109259 1.126811 -0.106272 +v 0.109259 1.126212 0.112246 +v -0.052090 1.177090 -0.048964 +v -0.052090 1.176804 0.055215 +v 0.052090 1.177090 -0.048964 +v 0.052090 1.176804 0.055215 +v -0.026259 1.194980 -0.023084 +v -0.026259 1.194836 0.029434 +v 0.026259 1.194980 -0.023084 +v 0.026259 1.194836 0.029434 +v -0.010547 1.200304 -0.007358 +v -0.010547 1.200246 0.013737 +v 0.010547 1.200304 -0.007358 +v 0.010547 1.200246 0.013737 +s off +f 1 22 21 +f 7 10 12 +f 1 6 2 +f 2 7 3 +f 3 8 4 +f 5 4 8 +f 11 16 15 +f 6 9 10 +f 8 12 11 +f 5 11 9 +f 13 19 17 +f 9 15 13 +f 12 14 16 +f 10 13 14 +f 17 20 18 +f 16 18 20 +f 14 17 18 +f 15 20 19 +f 24 27 28 +f 3 23 24 +f 2 24 22 +f 4 21 23 +f 26 32 30 +f 23 25 27 +f 22 28 26 +f 21 26 25 +f 30 36 34 +f 25 30 29 +f 28 31 32 +f 27 29 31 +f 36 39 40 +f 29 34 33 +f 32 35 36 +f 31 33 35 +f 38 44 42 +f 35 37 39 +f 34 40 38 +f 33 38 37 +f 41 46 45 +f 37 42 41 +f 40 43 44 +f 39 41 43 +f 45 48 47 +f 44 47 48 +f 43 45 47 +f 42 48 46 +f 1 2 22 +f 7 6 10 +f 1 5 6 +f 2 6 7 +f 3 7 8 +f 5 1 4 +f 11 12 16 +f 6 5 9 +f 8 7 12 +f 5 8 11 +f 13 15 19 +f 9 11 15 +f 12 10 14 +f 10 9 13 +f 17 19 20 +f 16 14 18 +f 14 13 17 +f 15 16 20 +f 24 23 27 +f 3 4 23 +f 2 3 24 +f 4 1 21 +f 26 28 32 +f 23 21 25 +f 22 24 28 +f 21 22 26 +f 30 32 36 +f 25 26 30 +f 28 27 31 +f 27 25 29 +f 36 35 39 +f 29 30 34 +f 32 31 35 +f 31 29 33 +f 38 40 44 +f 35 33 37 +f 34 36 40 +f 33 34 38 +f 41 42 46 +f 37 38 42 +f 40 39 43 +f 39 37 41 +f 45 46 48 +f 44 43 47 +f 43 41 45 +f 42 44 48 diff --git a/med.c b/med.c new file mode 100644 index 0000000..7fcdb94 --- /dev/null +++ b/med.c @@ -0,0 +1,776 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "libobj/obj.h" +#include "libgraphics/graphics.h" +#include "fns.h" + +enum { + K↑, + K↓, + K←, + K→, + Krise, + Kfall, + KR↑, + KR↓, + KR←, + KR→, + KR↺, + KR↻, + Kzoomin, + Kzoomout, + Khud, + Kfrustum, + Ke +}; + +enum { + Sfov, + Scampos, + Scambx, Scamby, Scambz, + Sfps, + Sframes, + Se +}; + +typedef struct Camcfg Camcfg; +struct Camcfg +{ + Point3 p, lookat, up; + double fov, clipn, clipf; + int ptype; +}; + +Rune keys[Ke] = { + [K↑] = Kup, + [K↓] = Kdown, + [K←] = Kleft, + [K→] = Kright, + [Krise] = Kpgup, + [Kfall] = Kpgdown, + [KR↑] = 'w', + [KR↓] = 's', + [KR←] = 'a', + [KR→] = 'd', + [KR↺] = 'q', + [KR↻] = 'e', + [Kzoomin] = 'z', + [Kzoomout] = 'x', + [Khud] = 'h', + [Kfrustum] = ' ', +}; +char stats[Se][256]; +Image *screenb; +Mousectl *mctl; +Keyboardctl *kctl; +Channel *drawc; +int kdown; +Scene *scene; +Entity *subject; +Model *model; +Shadertab *shader; +QLock scenelk; +Mouse om; +Quaternion orient = {1,0,0,0}; + +Camera cam; +Camcfg camcfg = { + 0,2,4,1, + 0,0,0,1, + 0,1,0,0, + 40*DEG, 0.01, 10, PERSPECTIVE +}; +Point3 center = {0,0,0,1}; +LightSource light; /* global point light */ + +static int doprof; +static int showhud; +Color (*tsampler)(Memimage*,Point2); + +static int +min(int a, int b) +{ + return a < b? a: b; +} + +static int +max(int a, int b) +{ + return a > b? a: b; +} + +static Point3 +Vecquat(Quaternion q) +{ + return Vec3(q.i, q.j, q.k); +} + +static Point3 +Ptquat(Quaternion q, double w) +{ + return Pt3(q.i, q.j, q.k, w); +} + +void +materializefrustum(void) +{ + Primitive l; + Framebuf *fb; + Point3 p[4]; + int i; + + fb = cam.vp->getfb(cam.vp); + p[0] = Pt3(0,0,1,1); + p[1] = Pt3(Dx(fb->r),0,1,1); + p[2] = Pt3(Dx(fb->r),Dy(fb->r),1,1); + p[3] = Pt3(0,Dy(fb->r),1,1); + memset(&l, 0, sizeof l); + + for(i = 0; i < nelem(p); i++){ + /* front frame */ + l.type = PLine; + l.v[0].p = viewport2world(&cam, p[i]); + l.v[1].p = viewport2world(&cam, p[(i+1)%nelem(p)]); + qlock(&scenelk); + model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims)); + model->prims[model->nprims-1] = l; + qunlock(&scenelk); + + /* middle frame */ + l.v[0].p = viewport2world(&cam, subpt3(p[i], Vec3(0,0,0.5))); + l.v[1].p = viewport2world(&cam, subpt3(p[(i+1)%nelem(p)], Vec3(0,0,0.5))); + qlock(&scenelk); + model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims)); + model->prims[model->nprims-1] = l; + qunlock(&scenelk); + + /* back frame */ + l.v[0].p = viewport2world(&cam, subpt3(p[i], Vec3(0,0,1))); + l.v[1].p = viewport2world(&cam, subpt3(p[(i+1)%nelem(p)], Vec3(0,0,1))); + qlock(&scenelk); + model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims)); + model->prims[model->nprims-1] = l; + qunlock(&scenelk); + + /* struts */ + l.v[1].p = viewport2world(&cam, p[i]); + qlock(&scenelk); + model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims)); + model->prims[model->nprims-1] = l; + qunlock(&scenelk); + } +} + +void +addcube(void) +{ + static Point3 axis[3] = {{0,1,0,0}, {1,0,0,0}, {0,0,1,0}}; + Primitive t[2]; + Point3 p, v1, v2; + int i, j, k; + + memset(t, 0, sizeof t); + t[0].type = t[1].type = PTriangle; + + p = Vec3(-0.5,-0.5,0.5); + v1 = Vec3(1,0,0); + v2 = Vec3(0,1,0); + t[0].v[0].p = addpt3(center, p); + t[0].v[1].p = addpt3(center, addpt3(p, v1)); + t[0].v[2].p = addpt3(center, addpt3(p, addpt3(v1, v2))); + t[1].v[0].p = t[0].v[0].p; + t[1].v[1].p = t[0].v[2].p; + t[1].v[2].p = addpt3(center, addpt3(p, v2)); + + for(i = 0; i < 6; i++){ + for(j = 0; j < 2; j++) + for(k = 0; k < 3; k++){ + if(i > 0) + t[j].v[k].p = qrotate(t[j].v[k].p, axis[i%3], PI/2); + t[j].v[k].n = normvec3(subpt3(t[j].v[k].p, center)); + } + + qlock(&scenelk); + model->prims = erealloc(model->prims, (model->nprims += 2)*sizeof(*model->prims)); + model->prims[model->nprims-2] = t[0]; + model->prims[model->nprims-1] = t[1]; + qunlock(&scenelk); + } +} + +Point3 +gouraudvshader(VSparams *sp) +{ + static double Ka = 0.1; /* ambient factor */ + static double Ks = 0.5; /* specular factor */ + double Kd; /* diffuse factor */ + double spec; + Point3 pos, lightdir, lookdir; + Material m; + Color ambient, diffuse, specular; + + sp->v->n = Vecquat(mulq(mulq(orient, Quatvec(0, sp->v->n)), invq(orient))); + sp->v->p = Ptquat(mulq(mulq(orient, Quatvec(0, sp->v->p)), invq(orient)), sp->v->p.w); + pos = model2world(sp->su->entity, sp->v->p); + if(sp->v->mtl != nil){ + m = *sp->v->mtl; + + ambient = mulpt3(light.c, Ka); + ambient.r *= m.ambient.r; + ambient.g *= m.ambient.g; + ambient.b *= m.ambient.b; + ambient.a *= m.ambient.a; + + lightdir = normvec3(subpt3(light.p, pos)); + Kd = fmax(0, dotvec3(sp->v->n, lightdir)); + diffuse = mulpt3(light.c, Kd); + diffuse.r *= m.diffuse.r; + diffuse.g *= m.diffuse.g; + diffuse.b *= m.diffuse.b; + diffuse.a *= m.diffuse.a; + + lookdir = normvec3(subpt3(cam.p, pos)); + lightdir = qrotate(lightdir, sp->v->n, PI); + spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess); + specular = mulpt3(light.c, spec*Ks); + specular.r *= m.specular.r; + specular.g *= m.specular.g; + specular.b *= m.specular.b; + specular.a *= m.specular.a; + + sp->v->c = addpt3(ambient, addpt3(diffuse, specular)); + } + return world2clip(&cam, pos); +} + +Color +gouraudshader(FSparams *sp) +{ + Color tc, c; + + if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0){ + tc = texture(sp->v.mtl->diffusemap, sp->v.uv, tsampler); + }else if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0) + tc = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler); + else + tc = Pt3(1,1,1,1); + + c.a = 1; + c.b = fclamp(sp->v.c.b*tc.b, 0, 1); + c.g = fclamp(sp->v.c.g*tc.g, 0, 1); + c.r = fclamp(sp->v.c.r*tc.r, 0, 1); + + return c; +} + +Point3 +phongvshader(VSparams *sp) +{ + Point3 pos; + Color a, d, s; + double ss; + + sp->v->n = Vecquat(mulq(mulq(orient, Quatvec(0, sp->v->n)), invq(orient))); + sp->v->p = Ptquat(mulq(mulq(orient, Quatvec(0, sp->v->p)), invq(orient)), sp->v->p.w); + pos = model2world(sp->su->entity, sp->v->p); + addvattr(sp->v, "pos", VAPoint, &pos); + if(sp->v->mtl != nil){ + a = sp->v->mtl->ambient; + d = sp->v->mtl->diffuse; + s = sp->v->mtl->specular; + ss = sp->v->mtl->shininess; + addvattr(sp->v, "ambient", VAPoint, &a); + addvattr(sp->v, "diffuse", VAPoint, &d); + addvattr(sp->v, "specular", VAPoint, &s); + addvattr(sp->v, "shininess", VANumber, &ss); + } + return world2clip(&cam, pos); +} + +Color +phongshader(FSparams *sp) +{ + static double Ka = 0.1; /* ambient factor */ + static double Ks = 0.5; /* specular factor */ + double Kd; /* diffuse factor */ + double spec; + Color ambient, diffuse, specular, tc, c; + Point3 pos, lookdir, lightdir; + Material m; + Vertexattr *va; + + va = getvattr(&sp->v, "pos"); + pos = va->p; + + va = getvattr(&sp->v, "ambient"); + m.ambient = va != nil? va->p: Pt3(1,1,1,1); + va = getvattr(&sp->v, "diffuse"); + m.diffuse = va != nil? va->p: Pt3(1,1,1,1); + va = getvattr(&sp->v, "specular"); + m.specular = va != nil? va->p: Pt3(1,1,1,1); + va = getvattr(&sp->v, "shininess"); + m.shininess = va != nil? va->n: 1; + + ambient = mulpt3(light.c, Ka); + ambient.r *= m.ambient.r; + ambient.g *= m.ambient.g; + ambient.b *= m.ambient.b; + ambient.a *= m.ambient.a; + + lightdir = normvec3(subpt3(light.p, pos)); + Kd = fmax(0, dotvec3(sp->v.n, lightdir)); + diffuse = mulpt3(light.c, Kd); + diffuse.r *= m.diffuse.r; + diffuse.g *= m.diffuse.g; + diffuse.b *= m.diffuse.b; + diffuse.a *= m.diffuse.a; + + lookdir = normvec3(subpt3(cam.p, pos)); + lightdir = qrotate(lightdir, sp->v.n, PI); + spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess); + specular = mulpt3(light.c, spec*Ks); + specular.r *= m.specular.r; + specular.g *= m.specular.g; + specular.b *= m.specular.b; + specular.a *= m.specular.a; + + if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0) + tc = texture(sp->v.mtl->diffusemap, sp->v.uv, tsampler); + else if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0) + tc = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler); + else + tc = Pt3(1,1,1,1); + + c = addpt3(ambient, addpt3(diffuse, specular)); + c.a = 1; + c.b = fclamp(c.b*tc.b, 0, 1); + c.g = fclamp(c.g*tc.g, 0, 1); + c.r = fclamp(c.r*tc.r, 0, 1); + + return c; +} + +Point3 +identvshader(VSparams *sp) +{ + Point3 pos, lightdir; + double intens; + + sp->v->n = Vecquat(mulq(mulq(orient, Quatvec(0, sp->v->n)), invq(orient))); + sp->v->p = Ptquat(mulq(mulq(orient, Quatvec(0, sp->v->p)), invq(orient)), sp->v->p.w); + pos = model2world(sp->su->entity, sp->v->p); + lightdir = normvec3(subpt3(light.p, pos)); + intens = fmax(0, dotvec3(sp->v->n, lightdir)); + addvattr(sp->v, "intensity", VANumber, &intens); + if(sp->v->mtl != nil) + sp->v->c = sp->v->mtl->diffuse; + return world2clip(&cam, pos); +} + +Color +identshader(FSparams *sp) +{ + Color tc, c; + + if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0) + tc = texture(sp->v.mtl->diffusemap, sp->v.uv, tsampler); + else if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0) + tc = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler); + else + tc = Pt3(1,1,1,1); + + c.a = 1; + c.b = fclamp(sp->v.c.b*tc.b, 0, 1); + c.g = fclamp(sp->v.c.g*tc.g, 0, 1); + c.r = fclamp(sp->v.c.r*tc.r, 0, 1); + + return c; +} + +Shadertab shadertab[] = { + { "ident", identvshader, identshader }, + { "gouraud", gouraudvshader, gouraudshader }, + { "phong", phongvshader, phongshader }, +}; +Shadertab * +getshader(char *name) +{ + int i; + + for(i = 0; i < nelem(shadertab); i++) + if(strcmp(shadertab[i].name, name) == 0) + return &shadertab[i]; + return nil; +} + +void +zoomin(void) +{ + cam.fov = fclamp(cam.fov - 1*DEG, 1*DEG, 180*DEG); + reloadcamera(&cam); +} + +void +zoomout(void) +{ + cam.fov = fclamp(cam.fov + 1*DEG, 1*DEG, 180*DEG); + reloadcamera(&cam); +} + +void +drawstats(void) +{ + int i; + + snprint(stats[Sfov], sizeof(stats[Sfov]), "FOV %g°", cam.fov/DEG); + snprint(stats[Scampos], sizeof(stats[Scampos]), "%V", cam.p); + snprint(stats[Scambx], sizeof(stats[Scambx]), "bx %V", cam.bx); + snprint(stats[Scamby], sizeof(stats[Scamby]), "by %V", cam.by); + snprint(stats[Scambz], sizeof(stats[Scambz]), "bz %V", cam.bz); + snprint(stats[Sfps], sizeof(stats[Sfps]), "FPS %.0f/%.0f/%.0f/%.0f", !cam.stats.max? 0: 1e9/cam.stats.max, !cam.stats.avg? 0: 1e9/cam.stats.avg, !cam.stats.min? 0: 1e9/cam.stats.min, !cam.stats.v? 0: 1e9/cam.stats.v); + snprint(stats[Sframes], sizeof(stats[Sframes]), "frame %llud", cam.stats.nframes); + for(i = 0; i < Se; i++) + stringbg(screen, addpt(screen->r.min, Pt(10,10 + i*font->height)), display->black, ZP, font, stats[i], display->white, ZP); +} + +void +redraw(void) +{ + static Image *bg; + + if(bg == nil) + bg = eallocimage(display, UR, RGB24, 1, 0x888888FF); + + lockdisplay(display); + cam.vp->draw(cam.vp, screenb); + draw(screen, screen->r, bg, nil, ZP); + draw(screen, screen->r, screenb, nil, ZP); + if(showhud) + drawstats(); + flushimage(display, 1); + unlockdisplay(display); +} + +void +drawproc(void *) +{ + uvlong t0, Δt; + + threadsetname("drawproc"); + + t0 = nsec(); + for(;;){ + qlock(&scenelk); + shootcamera(&cam, shader); + qunlock(&scenelk); + if(doprof) + fprint(2, "R %llud %llud\nE %llud %llud\nT %llud %llud\nr %llud %llud\n\n", + cam.times.R[cam.times.cur-1].t0, cam.times.R[cam.times.cur-1].t1, + cam.times.E[cam.times.cur-1].t0, cam.times.E[cam.times.cur-1].t1, + cam.times.Tn[cam.times.cur-1].t0, cam.times.Tn[cam.times.cur-1].t1, + cam.times.Rn[cam.times.cur-1].t0, cam.times.Rn[cam.times.cur-1].t1); + Δt = nsec() - t0; + if(Δt > HZ2MS(60)*1000000ULL){ + nbsend(drawc, nil); + t0 += Δt; + } + } +} + +void +lmb(void) +{ + if((om.buttons^mctl->buttons) == 0) + qball(screen->r, om.xy, mctl->xy, &orient, nil); +} + +void +mmb(void) +{ + enum { + TSNEAREST, + TSBILINEAR, + SP, + QUIT, + }; + static char *items[] = { + [TSNEAREST] "use nearest sampler", + [TSBILINEAR] "use bilinear sampler", + [SP] "", + [QUIT] "quit", + nil, + }; + static Menu menu = { .item = items }; + + switch(menuhit(2, mctl, &menu, _screen)){ + case TSNEAREST: + tsampler = neartexsampler; + break; + case TSBILINEAR: + tsampler = bilitexsampler; + break; + case QUIT: + threadexitsall(nil); + } + nbsend(drawc, nil); +} + +static char * +genrmbmenuitem(int idx) +{ + if(idx < nelem(shadertab)) + return shadertab[idx].name; + else if(idx == nelem(shadertab)) + return ""; + else if(idx == nelem(shadertab)+1) + return "add cube"; + return nil; +} + +void +rmb(void) +{ + static Menu menu = { .gen = genrmbmenuitem }; + int idx; + + idx = menuhit(3, mctl, &menu, _screen); + if(idx < 0) + return; + if(idx < nelem(shadertab)){ + shader = &shadertab[idx]; + memset(&cam.stats, 0, sizeof(cam.stats)); + }else if(idx == nelem(shadertab)+1) + addcube(); + nbsend(drawc, nil); +} + +void +mouse(void) +{ + if((mctl->buttons & 1) != 0) + lmb(); + if((mctl->buttons & 2) != 0) + mmb(); + if((mctl->buttons & 4) != 0) + rmb(); + if((mctl->buttons & 8) != 0) + zoomin(); + if((mctl->buttons & 16) != 0) + zoomout(); + om = mctl->Mouse; +} + +void +kbdproc(void *) +{ + Rune r, *a; + char buf[128], *s; + int fd, n; + + threadsetname("kbdproc"); + + if((fd = open("/dev/kbd", OREAD)) < 0) + sysfatal("kbdproc: %r"); + memset(buf, 0, sizeof buf); + + for(;;){ + if(buf[0] != 0){ + n = strlen(buf)+1; + memmove(buf, buf+n, sizeof(buf)-n); + } + if(buf[0] == 0){ + if((n = read(fd, buf, sizeof(buf)-1)) <= 0) + break; + buf[n-1] = 0; + buf[n] = 0; + } + if(buf[0] == 'c'){ + chartorune(&r, buf+1); + if(r == Kdel){ + close(fd); + threadexitsall(nil); + }else + nbsend(kctl->c, &r); + } + if(buf[0] != 'k' && buf[0] != 'K') + continue; + s = buf+1; + kdown = 0; + while(*s){ + s += chartorune(&r, s); + for(a = keys; a < keys+Ke; a++) + if(r == *a){ + kdown |= 1 << a-keys; + break; + } + } + } +} + +void +keyproc(void *c) +{ + threadsetname("keyproc"); + + for(;;){ + nbsend(c, nil); + sleep(HZ2MS(100)); /* key poll rate */ + } +} + +void +handlekeys(void) +{ + static int okdown; + + if(kdown & 1<addent(scene, subject); + + if(memimageinit() != 0) + sysfatal("memimageinit: %r"); + if((rctl = initgraphics()) == nil) + sysfatal("initgraphics: %r"); + if(initdraw(nil, nil, "med") < 0) + sysfatal("initdraw: %r"); + if((mctl = initmouse(nil, screen)) == nil) + sysfatal("initmouse: %r"); + + screenb = eallocimage(display, rectsubpt(screen->r, screen->r.min), RGBA32, 0, DNofill); + v = mkviewport(screenb->r); + placecamera(&cam, camcfg.p, camcfg.lookat, camcfg.up); + configcamera(&cam, v, camcfg.fov, camcfg.clipn, camcfg.clipf, camcfg.ptype); + cam.s = scene; + cam.rctl = rctl; + light.p = Pt3(0,100,100,1); + light.c = Pt3(1,1,1,1); + light.type = LIGHT_POINT; + tsampler = neartexsampler; + + kctl = emalloc(sizeof *kctl); + kctl->c = chancreate(sizeof(Rune), 16); + keyc = chancreate(sizeof(void*), 1); + drawc = chancreate(sizeof(void*), 1); + display->locking = 1; + unlockdisplay(display); + + proccreate(kbdproc, nil, mainstacksize); + proccreate(keyproc, keyc, mainstacksize); + proccreate(drawproc, nil, mainstacksize); + + for(;;){ + enum {MOUSE, RESIZE, KEY, DRAW}; + Alt a[] = { + {mctl->c, &mctl->Mouse, CHANRCV}, + {mctl->resizec, nil, CHANRCV}, + {keyc, nil, CHANRCV}, + {drawc, nil, CHANRCV}, + {nil, nil, CHANEND} + }; + switch(alt(a)){ + case MOUSE: mouse(); break; + case RESIZE: resize(); break; + case KEY: handlekeys(); break; + case DRAW: redraw(); break; + } + } +} diff --git a/mkfile b/mkfile index 2761b48..8cae9d6 100644 --- a/mkfile +++ b/mkfile @@ -3,7 +3,9 @@ BIN=$home/bin/$objtype TARG=\ vis\ + med\ solar\ + projtest\ OFILES=\ alloc.$O\ diff --git a/projtest.c b/projtest.c new file mode 100644 index 0000000..974bb28 --- /dev/null +++ b/projtest.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "libobj/obj.h" +#include "libgraphics/graphics.h" +#include "fns.h" + +Camera cam; + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + Point3 np, fp; + Framebuf *fb; + + GEOMfmtinstall(); + ARGBEGIN{ + default: usage(); + }ARGEND + if(argc != 0) + usage(); + + if(memimageinit() != 0) + sysfatal("memimageinit: %r"); + + placecamera(&cam, Pt3(0,0,1,1), Vec3(0,0,0), Vec3(0,1,0)); + configcamera(&cam, mkviewport(Rect(0,0,640,480)), 40*DEG, 0.01, 10, PERSPECTIVE); + + fb = cam.vp->getfb(cam.vp); + np = Pt3(0,0,-0.01,1); + fp = Pt3(0,0,-10,1); + fprint(2, "near %V\nfar %V\n", np, fp); + np = vcs2clip(&cam, np); + fp = vcs2clip(&cam, fp); + fprint(2, "E → C\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = clip2ndc(np); + fp = clip2ndc(fp); + fprint(2, "C → N\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = ndc2viewport(fb, np); + fp = ndc2viewport(fb, fp); + fprint(2, "N → V\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = viewport2ndc(fb, np); + fp = viewport2ndc(fb, fp); + fprint(2, "V → N\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = ndc2vcs(&cam, np); + fp = ndc2vcs(&cam, fp); + fprint(2, "N → E\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + + fprint(2, "\n"); + + np = Pt3(Dx(fb->r)/2.0,Dy(fb->r)/2.0,1,1); + fp = Pt3(Dx(fb->r)/2.0,Dy(fb->r)/2.0,0,1); + fprint(2, "near %V\nfar %V\n", np, fp); + np = viewport2ndc(fb, np); + fp = viewport2ndc(fb, fp); + fprint(2, "V → N\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = ndc2vcs(&cam, np); + fp = ndc2vcs(&cam, fp); + fprint(2, "N → E\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = vcs2clip(&cam, np); + fp = vcs2clip(&cam, fp); + fprint(2, "E → C\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = clip2ndc(np); + fp = clip2ndc(fp); + fprint(2, "C → N\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + np = ndc2viewport(fb, np); + fp = ndc2viewport(fb, fp); + fprint(2, "N → V\n"); + fprint(2, "near %V\n", np); + fprint(2, "far %V\n", fp); + + exits(nil); +} -- cgit v1.2.3