|
From: <kin...@us...> - 2004-02-09 07:09:31
|
Update of /cvsroot/teem/teem/src/limn In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28564 Modified Files: env.c io.c limn.h methodsLimn.c obj.c qn.c renderLimn.c transform.c Log Message: changed spelling of QN stuff: limnQN_xxx --> limnQNxxx added a few more checker-based normal quantization methods added simple and incomplete readers and writers for OFF file format added long-overdue enum for edge types (front vs. back, crease vs. non-crease, etc...) starting to add functionality to correctly draw non-convex objects and parts Index: env.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/env.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** env.c 7 Jan 2004 15:34:30 -0000 1.4 --- env.c 9 Feb 2004 07:06:18 -0000 1.5 *************** *** 31,40 **** biffAdd(LIMN, err); return 1; } ! if (!AIR_IN_OP(limnQN_Unknown, qnMethod, limnQN_Last)) { sprintf(err, "%s: QN method %d invalid", me, qnMethod); biffAdd(LIMN, err); return 1; } switch(qnMethod) { ! case limnQN_16checker: sx = sy = 256; if (nrrdMaybeAlloc(map, nrrdTypeFloat, 3, 3, sx, sy)) { --- 31,40 ---- biffAdd(LIMN, err); return 1; } ! if (!AIR_IN_OP(limnQNUnknown, qnMethod, limnQNLast)) { sprintf(err, "%s: QN method %d invalid", me, qnMethod); biffAdd(LIMN, err); return 1; } switch(qnMethod) { ! case limnQN16checker: sx = sy = 256; if (nrrdMaybeAlloc(map, nrrdTypeFloat, 3, 3, sx, sy)) { *************** *** 44,48 **** mapData = map->data; for (qn=0; qn<=sx*sy-1; qn++) { ! limnQNtoV[limnQN_16checker](vec, qn); cb(mapData + 3*qn, vec, data); } --- 44,48 ---- mapData = map->data; for (qn=0; qn<=sx*sy-1; qn++) { ! limnQNtoV_f[limnQN16checker](vec, qn); cb(mapData + 3*qn, vec, data); } Index: io.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/io.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** io.c 7 Jan 2004 15:34:30 -0000 1.7 --- io.c 9 Feb 2004 07:06:18 -0000 1.8 *************** *** 62,63 **** --- 62,186 ---- return 0; } + + int + limnObjOFFWrite(FILE *file, limnObj *obj) { + char me[]="limnObjOFFWrite", err[AIR_STRLEN_MED]; + int ii, vi; + limnPoint *p; + limnFace *f; + + if (!( obj && file )) { + sprintf(err, "%s: got NULL pointer", me); + biffAdd(LIMN, err); return 1; + } + fprintf(file, "OFF\n"); + fprintf(file, "%d %d -1\n", obj->pA->len, obj->fA->len); + for (ii=0; ii<obj->pA->len; ii++) { + p = obj->p + ii; + fprintf(file, "%g %g %g", + p->w[0]/p->w[3], p->w[1]/p->w[3], p->w[2]/p->w[3]); + if (p->sp) { + /* its a non-default color */ + fprintf(file, " %g %g %g", obj->s[p->sp].rgba[0], + obj->s[p->sp].rgba[1], obj->s[p->sp].rgba[2]); + } + fprintf(file, "\n"); + } + for (ii=0; ii<obj->fA->len; ii++) { + f = obj->f + ii; + fprintf(file, "%d", f->vNum); + for (vi=0; vi<f->vNum; vi++) { + fprintf(file, " %d", obj->v[vi + f->vBase]); + } + if (f->sp) { + fprintf(file, " %g %g %g", obj->s[f->sp].rgba[0], + obj->s[f->sp].rgba[1], obj->s[f->sp].rgba[2]); + } + fprintf(file, "\n"); + } + return 0; + } + + int + limnObjOFFRead(limnObj *obj, FILE *file) { + char me[]="limnObjOFFRead", err[AIR_STRLEN_MED]; + double vert[6]; + char line[AIR_STRLEN_LARGE]; /* HEY: bad bad Gordon */ + int si, lret, nvert, nface, ii, got, ibuff[512]; /* HEY: bad bad Gordon */ + float fbuff[512]; /* HEY: bad bad Gordon */ + + if (!( obj && file )) { + sprintf(err, "%s: got NULL pointer", me); + biffAdd(LIMN, err); return 1; + } + got = 0; + do { + if (!airOneLine(file, line, AIR_STRLEN_LARGE)) { + sprintf(err, "%s: hit EOF before getting #vert #face #edge line", me); + biffAdd(LIMN, err); return 1; + } + got = airParseStrI(ibuff, line, AIR_WHITESPACE, 3); + } while (3 != got); + nvert = ibuff[0]; + nface = ibuff[1]; + limnObjPartStart(obj); + for (ii=0; ii<nvert; ii++) { + do { + lret = airOneLine(file, line, AIR_STRLEN_LARGE); + } while (1 == lret); + if (!lret) { + sprintf(err, "%s: hit EOF trying to read vert %d (of %d)", + me, ii, nvert); + biffAdd(LIMN, err); return 1; + } + if (3 != airParseStrD(vert, line, AIR_WHITESPACE, 3)) { + sprintf(err, "%s: couldn't parse 3 doubles from \"%s\" " + "for vert %d (of %d)", + me, line, ii, nvert); + biffAdd(LIMN, err); return 1; + } + if (6 == airParseStrD(vert, line, AIR_WHITESPACE, 6)) { + /* we could also parse an RGB color */ + si = limnObjSPAdd(obj); + ELL_4V_SET(obj->s[si].rgba, vert[3], vert[4], vert[5], 1); + } else { + si = 0; + } + limnObjPointAdd(obj, si, vert[0], vert[1], vert[2]); + } + for (ii=0; ii<nface; ii++) { + do { + lret = airOneLine(file, line, AIR_STRLEN_LARGE); + } while (1 == lret); + if (!lret) { + sprintf(err, "%s: hit EOF trying to read face %d (of %d)", + me, ii, nface); + biffAdd(LIMN, err); return 1; + } + if (1 != sscanf(line, "%d", &nvert)) { + sprintf(err, "%s: can't get first int (#verts) from \"%s\" " + "for face %d (of %d)", + me, line, ii, nface); + biffAdd(LIMN, err); return 1; + } + if (nvert+1 != airParseStrI(ibuff, line, AIR_WHITESPACE, nvert+1)) { + sprintf(err, "%s: couldn't parse %d ints from \"%s\" " + "for face %d (of %d)", + me, nvert+1, line, ii, nface); + biffAdd(LIMN, err); return 1; + } + if (nvert+1+3 == airParseStrF(fbuff, line, AIR_WHITESPACE, nvert+1+3)) { + /* could also parse color */ + si = limnObjSPAdd(obj); + ELL_4V_SET(obj->s[si].rgba, + fbuff[nvert+1+0], fbuff[nvert+1+1], fbuff[nvert+1+2], 1); + } else { + si = 0; + } + limnObjFaceAdd(obj, si, nvert, ibuff+1); + } + limnObjPartFinish(obj); + + return 0; + } + Index: limn.h =================================================================== RCS file: /cvsroot/teem/teem/src/limn/limn.h,v retrieving revision 1.44 retrieving revision 1.45 diff -C2 -d -r1.44 -r1.45 *** limn.h 7 Jan 2004 15:34:30 -0000 1.44 --- limn.h 9 Feb 2004 07:06:18 -0000 1.45 *************** *** 125,137 **** }; typedef struct { ! float edgeWidth[5], /* different line thickness for different edge types: ! 0 : non-crease edge, backfacing ! 1 : crease edge, backfacing ! 2 : silhouette edge (crease or non-crease) ! 3 : crease edge: front-facing ! 4 : non-crease edge, front-facing */ ! creaseAngle, ! bg[3]; /* background color */ } limnOptsPS; --- 125,148 ---- }; + enum { + limnEdgeTypeUnknown, /* 0 */ + limnEdgeTypeBackFacet, /* 1: back-facing non-crease */ + limnEdgeTypeBackCrease, /* 2: back-facing crease */ + limnEdgeTypeContour, /* 3: silhoette edge */ + limnEdgeTypeFrontCrease, /* 4: front-facing crease */ + limnEdgeTypeFrontFacet, /* 5: front-facing non-crease */ + limnEdgeTypeBorder, /* 6: attached to only one face */ + limnEdgeTypeLone, /* 7: attached to no other faces */ + limnEdgeTypeLast + }; + #define LIMN_EDGE_TYPE_MAX 5 + typedef struct { ! float lineWidth[LIMN_EDGE_TYPE_MAX+1], ! haloWidth[LIMN_EDGE_TYPE_MAX+1], ! creaseAngle, /* difference between crease and facet, in *degrees* */ ! bg[3]; /* background color */ ! int showpage, /* finish with "showpage" */ ! wireFrame; /* just render wire-frame */ } limnOptsPS; *************** *** 181,185 **** sp; /* index into parent's SP list */ ! int visib; /* is edge currently visible (or active) */ } limnEdge; --- 192,196 ---- sp; /* index into parent's SP list */ ! int type; /* from the limnEdgeType enum */ } limnEdge; *************** *** 197,201 **** sp; /* index into parent's SP list, "s" */ ! int visib; /* is face currently visible */ float z; /* for depth ordering */ } limnFace; --- 208,212 ---- sp; /* index into parent's SP list, "s" */ ! int visib; /* is face currently visible (AIR_TRUE or AIR_FALSE) */ float z; /* for depth ordering */ } limnFace; *************** *** 211,220 **** pBase, pNum, /* start and length in parent's limnPoint array, "p" */ origIdx; /* initial part index of this part */ ! float z; /* assuming that the occlusion graph between whole parts is acyclic, one depth value is good enough for painter's algorithm ordering of drawing */ ! float rgba[4]; } limnPart; --- 222,231 ---- pBase, pNum, /* start and length in parent's limnPoint array, "p" */ origIdx; /* initial part index of this part */ ! float z; /* assuming that the occlusion graph between whole parts is acyclic, one depth value is good enough for painter's algorithm ordering of drawing */ ! int sp; /* index into parent's SP list, "s" */ } limnPart; *************** *** 249,252 **** --- 260,264 ---- limnFace *f; /* array of face structs */ airArray *fA; /* airArray around "f" */ + int *fSort; /* indices into "f", sorted by depth */ limnPart *r; /* array of part structs */ *************** *** 267,278 **** */ enum { ! limnQN_Unknown, /* 0 */ ! limnQN_16checker, /* 1 */ ! limnQN_16simple, /* 2 */ ! limnQN_16border1, /* 3 */ ! limnQN_15checker, /* 4 */ ! limnQN_Last }; ! #define LIMN_QN_MAX 4 enum { --- 279,292 ---- */ enum { ! limnQNUnknown, /* 0 */ ! limnQN16checker, /* 1 */ ! limnQN16simple, /* 2 */ ! limnQN16border1, /* 3 */ ! limnQN15checker, /* 4 */ ! limnQN14checker, /* 5 */ ! limnQN12checker, /* 6 */ ! limnQNLast }; ! #define LIMN_QN_MAX 6 enum { *************** *** 347,353 **** /* qn.c */ ! extern limn_export int limnQNBytes[LIMN_QN_MAX+1]; ! extern limn_export void (*limnQNtoV[LIMN_QN_MAX+1])(float *vec, int qn); ! extern limn_export int (*limnVtoQN[LIMN_QN_MAX+1])(float *vec); /* light.c */ --- 361,370 ---- /* qn.c */ ! extern limn_export int limnQNBins[LIMN_QN_MAX+1]; ! extern limn_export void (*limnQNtoV_f[LIMN_QN_MAX+1])(float *vec, int qn); ! extern limn_export void (*limnQNtoV_d[LIMN_QN_MAX+1])(double *vec, int qn); ! extern limn_export int (*limnVtoQN_f[LIMN_QN_MAX+1])(float *vec); ! extern limn_export int (*limnVtoQN_d[LIMN_QN_MAX+1])(double *vec); ! /* light.c */ *************** *** 404,407 **** --- 421,426 ---- /* io.c */ extern int limnObjDescribe(FILE *file, limnObj *obj); + extern int limnObjOFFRead(limnObj *obj, FILE *file); + extern int limnObjOFFWrite(FILE *file, limnObj *obj); /* shapes.c */ *************** *** 424,430 **** --- 443,452 ---- extern int limnObjPartTransform(limnObj *obj, int ri, float tx[16]); extern int limnObjDepthSortParts(limnObj *obj); + extern int limnObjDepthSortFaces(limnObj *obj); /* renderLimn.c */ extern int limnObjRender(limnObj *obj, limnCamera *cam, limnWin *win); + extern int limnObjPSDrawOld(limnObj *obj, limnCamera *cam, + Nrrd *envMap, limnWin *win); extern int limnObjPSDraw(limnObj *obj, limnCamera *cam, Nrrd *envMap, limnWin *win); Index: methodsLimn.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/methodsLimn.c,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** methodsLimn.c 7 Jan 2004 15:34:30 -0000 1.9 --- methodsLimn.c 9 Feb 2004 07:06:18 -0000 1.10 *************** *** 71,80 **** _limnOptsPSDefaults(limnOptsPS *ps) { ! ps->edgeWidth[0] = 0.0; ! ps->edgeWidth[1] = 0.0; ! ps->edgeWidth[2] = 2.0; ! ps->edgeWidth[3] = 1.0; ! ps->edgeWidth[4] = 0.0; ps->creaseAngle = 46; ELL_3V_SET(ps->bg, 1, 1, 1); } --- 71,93 ---- _limnOptsPSDefaults(limnOptsPS *ps) { ! ps->lineWidth[limnEdgeTypeUnknown] = AIR_NAN; ! ps->lineWidth[limnEdgeTypeBackFacet] = 0.0; ! ps->lineWidth[limnEdgeTypeBackCrease] = 0.0; ! ps->lineWidth[limnEdgeTypeContour] = 2.0; ! ps->lineWidth[limnEdgeTypeFrontCrease] = 1.0; ! ps->lineWidth[limnEdgeTypeFrontFacet] = 0.0; ! ps->lineWidth[limnEdgeTypeBorder] = 1.0; ! ps->lineWidth[limnEdgeTypeLone] = 1.0; ! ps->haloWidth[limnEdgeTypeUnknown] = AIR_NAN; ! ps->haloWidth[limnEdgeTypeBackFacet] = 0.0; ! ps->haloWidth[limnEdgeTypeBackCrease] = 0.0; ! ps->haloWidth[limnEdgeTypeContour] = 0.0; ! ps->haloWidth[limnEdgeTypeFrontCrease] = 0.0; ! ps->haloWidth[limnEdgeTypeFrontFacet] = 0.0; ! ps->haloWidth[limnEdgeTypeBorder] = 0.0; ! ps->haloWidth[limnEdgeTypeLone] = 0.0; ps->creaseAngle = 46; + ps->showpage = AIR_FALSE; + ps->wireFrame = AIR_FALSE; ELL_3V_SET(ps->bg, 1, 1, 1); } Index: obj.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/obj.c,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** obj.c 7 Jan 2004 15:34:30 -0000 1.14 --- obj.c 9 Feb 2004 07:06:18 -0000 1.15 *************** *** 30,33 **** --- 30,34 ---- obj->e = NULL; obj->f = NULL; + obj->fSort = NULL; obj->r = NULL; obj->s = NULL; *************** *** 60,63 **** --- 61,65 ---- airArrayNuke(obj->eA); airArrayNuke(obj->fA); + airFree(obj->fSort); airArrayNuke(obj->rA); airArrayNuke(obj->sA); *************** *** 77,81 **** r->pBase = obj->pA->len; r->pNum = 0; r->origIdx = rBase; ! ELL_4V_SET(r->rgba, 1.0, 1.0, 1.0, 1.0); obj->rCurr = r; --- 79,83 ---- r->pBase = obj->pA->len; r->pNum = 0; r->origIdx = rBase; ! r->sp = 0; obj->rCurr = r; *************** *** 109,113 **** e->f1 = -1; e->sp = sp; ! e->visib = 0; } --- 111,115 ---- e->f1 = -1; e->sp = sp; ! e->type = limnEdgeTypeUnknown; } *************** *** 184,189 **** int limnObjSPAdd(limnObj *obj) { ! return airArrayIncrLen(obj->sA, 1); } - --- 186,197 ---- int limnObjSPAdd(limnObj *obj) { + int sBase; + limnSP *s; ! sBase = airArrayIncrLen(obj->sA, 1); ! s = &(obj->s[sBase]); ! ELL_4V_SET(s->rgba, 1, 1, 1, 1); ! ELL_3V_SET(s->k, 0.5, 0.5, 0.0); ! s->spec = 50; ! return sBase; } Index: qn.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/qn.c,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** qn.c 7 Jan 2004 15:34:30 -0000 1.16 --- qn.c 9 Feb 2004 07:06:18 -0000 1.17 *************** *** 31,46 **** */ - int - limnQNBytes[LIMN_QN_MAX+1] = { - 0, /* limnQN_Unknown */ - 2, /* limnQN_16checker */ - 2, /* limnQN_16simple */ - 2, /* limnQN_16border1 */ - 2 /* limnQN_15checker */ - }; - - void ! _limnQN_16simple_QNtoV(float *vec, int qn) { int xi, yi; float x, y, z, n; --- 31,36 ---- */ void ! _limnQN16simple_QNtoV_f(float *vec, int qn) { int xi, yi; float x, y, z, n; *************** *** 65,69 **** int ! _limnQN_16simple_VtoQN(float *vec) { float x, y, z, L, w; int sgn = 0; --- 55,59 ---- int ! _limnQN16simple_VtoQN_f(float *vec) { float x, y, z, L, w; int sgn = 0; *************** *** 116,165 **** the error due to quantization is unbiased */ void ! _limnQN_16checker_QNtoV(float *vec, int qn) { int ui, vi; ! float u, v, x, y, z, n; ! ui = qn & 0xFF; ! vi = (qn >> 8) & 0xFF; ! u = AIR_AFFINE(0, ui, 255, -0.5, 0.5); ! v = AIR_AFFINE(0, vi, 255, -0.5, 0.5); ! x = u + v; ! y = u - v; ! z = 1 - AIR_ABS(x) - AIR_ABS(y); ! /* would this be better served by a branch? */ ! z *= (((ui ^ vi) & 0x01) << 1) - 1; ! n = 1.0/sqrt(x*x + y*y + z*z); ! vec[0] = x*n; ! vec[1] = y*n; ! vec[2] = z*n; } int ! _limnQN_16checker_VtoQN(float *vec) { ! float L, x, y, z; int xi, yi, ui, vi; ! ! x = vec[0]; ! y = vec[1]; ! z = vec[2]; ! L = AIR_ABS(x) + AIR_ABS(y) + AIR_ABS(z); ! if (!L) { ! return 0; ! } ! x /= L; ! y /= L; ! if (z > 0) { ! AIR_INDEX(-1.0, x, 1.0, 255, xi); ! AIR_INDEX(-1.0 - 1.0/255, y, 1.0 + 1.0/255, 256, yi); ! ui = xi + yi - 127; ! vi = xi - yi + 128; ! } ! else { ! AIR_INDEX(-1.0 - 1.0/255, x, 1.0 + 1.0/255, 256, xi); ! AIR_INDEX(-1, y, 1, 255, yi); ! ui = xi + yi - 127; ! vi = xi - yi + 127; ! } return (vi << 8) | ui; } --- 106,178 ---- the error due to quantization is unbiased */ + #define _16_QtoV(vec, qn) \ + ui = (qn) & 0xFF; \ + vi = ((qn) >> 8) & 0xFF; \ + u = AIR_AFFINE(0, ui, 255, -0.5, 0.5); \ + v = AIR_AFFINE(0, vi, 255, -0.5, 0.5); \ + x = u + v; \ + y = u - v; \ + z = 1 - AIR_ABS(x) - AIR_ABS(y); \ + /* would this be better served by a branch? */ \ + z *= (((ui ^ vi) & 0x01) << 1) - 1; \ + n = 1.0/sqrt(x*x + y*y + z*z); \ + (vec)[0] = x*n; \ + (vec)[1] = y*n; \ + (vec)[2] = z*n + void ! _limnQN16checker_QNtoV_f(float *vec, int qn) { int ui, vi; ! double u, v, x, y, z, n; ! _16_QtoV(vec, qn); } + void + _limnQN16checker_QNtoV_d(double *vec, int qn) { + int ui, vi; + double u, v, x, y, z, n; + + _16_QtoV(vec, qn); + } + + #define _16_VtoQ(vec) \ + x = (vec)[0]; \ + y = (vec)[1]; \ + z = (vec)[2]; \ + L = AIR_ABS(x) + AIR_ABS(y) + AIR_ABS(z); \ + if (!L) { \ + return 0; \ + } \ + x /= L; \ + y /= L; \ + if (z > 0) { \ + AIR_INDEX(-1.0, x, 1.0, 255, xi); \ + AIR_INDEX(-1.0 - 1.0/255, y, 1.0 + 1.0/255, 256, yi); \ + ui = xi + yi - 127; \ + vi = xi - yi + 128; \ + } \ + else { \ + AIR_INDEX(-1.0 - 1.0/255, x, 1.0 + 1.0/255, 256, xi); \ + AIR_INDEX(-1, y, 1, 255, yi); \ + ui = xi + yi - 127; \ + vi = xi - yi + 127; \ + } + int ! _limnQN16checker_VtoQN_f(float *vec) { ! double L, x, y, z; int xi, yi, ui, vi; ! ! _16_VtoQ(vec); ! return (vi << 8) | ui; ! } ! ! int ! _limnQN16checker_VtoQN_d(double *vec) { ! double L, x, y, z; ! int xi, yi, ui, vi; ! ! _16_VtoQ(vec); return (vi << 8) | ui; } *************** *** 168,172 **** void ! _limnQN_16border1_QNtoV(float *vec, int qn) { int ui, vi; float u, v, x, y, z, n; --- 181,185 ---- void ! _limnQN16border1_QNtoV_f(float *vec, int qn) { int ui, vi; float u, v, x, y, z, n; *************** *** 187,191 **** int ! _limnQN_16border1_VtoQN(float *vec) { float L, u, v, x, y, z; int ui, vi, zi; --- 200,204 ---- int ! _limnQN16border1_VtoQN_f(float *vec) { float L, u, v, x, y, z; int ui, vi, zi; *************** *** 225,229 **** void ! _limnQN_15checker_QNtoV(float *vec, int qn) { int ui, vi, zi; float u, v, x, y, z, n; --- 238,242 ---- void ! _limnQN15checker_QNtoV_f(float *vec, int qn) { int ui, vi, zi; float u, v, x, y, z, n; *************** *** 245,249 **** int ! _limnQN_15checker_VtoQN(float *vec) { float L, u, v, x, y, z; int ui, vi, zi; --- 258,262 ---- int ! _limnQN15checker_VtoQN_f(float *vec) { float L, u, v, x, y, z; int ui, vi, zi; *************** *** 266,283 **** } ! void (*limnQNtoV[LIMN_QN_MAX+1])(float *, int) = { NULL, ! _limnQN_16checker_QNtoV, ! _limnQN_16simple_QNtoV, ! _limnQN_16border1_QNtoV, ! _limnQN_15checker_QNtoV }; ! int (*limnVtoQN[LIMN_QN_MAX+1])(float *vec) = { NULL, ! _limnQN_16checker_VtoQN, ! _limnQN_16simple_VtoQN, ! _limnQN_16border1_VtoQN, ! _limnQN_15checker_VtoQN }; --- 279,484 ---- } ! /* ----------------------------------------------------------- */ ! ! #define _14_QNtoV(vec, qn) \ ! ui = (qn) & 0x7F; \ ! vi = ((qn) >> 7) & 0x7F; \ ! u = AIR_AFFINE(0, ui, 127, -0.5, 0.5); \ ! v = AIR_AFFINE(0, vi, 127, -0.5, 0.5); \ ! x = u + v; \ ! y = u - v; \ ! z = 1 - AIR_ABS(x) - AIR_ABS(y); \ ! /* would this be better served by a branch? */ \ ! z *= (((ui ^ vi) & 0x01) << 1) - 1; \ ! n = 1.0/sqrt(x*x + y*y + z*z); \ ! (vec)[0] = x*n; \ ! (vec)[1] = y*n; \ ! (vec)[2] = z*n ! ! void ! _limnQN14checker_QNtoV_f(float *vec, int qn) { ! int ui, vi; ! double u, v, x, y, z, n; ! ! _14_QNtoV(vec, qn); ! } ! ! void ! _limnQN14checker_QNtoV_d(double *vec, int qn) { ! int ui, vi; ! double u, v, x, y, z, n; ! ! _14_QNtoV(vec, qn); ! } ! ! #define _14_VtoQN(vec) \ ! x = (vec)[0]; \ ! y = (vec)[1]; \ ! z = (vec)[2]; \ ! L = AIR_ABS(x) + AIR_ABS(y) + AIR_ABS(z); \ ! if (!L) { \ ! return 0; \ ! } \ ! x /= L; \ ! y /= L; \ ! if (z > 0) { \ ! AIR_INDEX(-1.0, x, 1.0, 127, xi); \ ! AIR_INDEX(-1.0 - 1.0/127, y, 1.0 + 1.0/127, 128, yi); \ ! ui = xi + yi - 63; \ ! vi = xi - yi + 64; \ ! } \ ! else { \ ! AIR_INDEX(-1.0 - 1.0/127, x, 1.0 + 1.0/127, 128, xi); \ ! AIR_INDEX(-1, y, 1, 127, yi); \ ! ui = xi + yi - 63; \ ! vi = xi - yi + 63; \ ! } ! ! int ! _limnQN14checker_VtoQN_f(float *vec) { ! double L, x, y, z; ! int xi, yi, ui, vi; ! ! _14_VtoQN(vec); ! return (vi << 7) | ui; ! } ! ! int ! _limnQN14checker_VtoQN_d(double *vec) { ! double L, x, y, z; ! int xi, yi, ui, vi; ! ! _14_VtoQN(vec); ! return (vi << 7) | ui; ! } ! ! /* ----------------------------------------------------------- */ ! ! #define _12_QNtoV(vec, qn) \ ! ui = (qn) & 0x3F; \ ! vi = ((qn) >> 6) & 0x3F; \ ! u = AIR_AFFINE(0, ui, 63, -0.5, 0.5); \ ! v = AIR_AFFINE(0, vi, 63, -0.5, 0.5); \ ! x = u + v; \ ! y = u - v; \ ! z = 1 - AIR_ABS(x) - AIR_ABS(y); \ ! /* would this be better served by a branch? */ \ ! z *= (((ui ^ vi) & 0x01) << 1) - 1; \ ! n = 1.0/sqrt(x*x + y*y + z*z); \ ! (vec)[0] = x*n; \ ! (vec)[1] = y*n; \ ! (vec)[2] = z*n ! ! void ! _limnQN12checker_QNtoV_f(float *vec, int qn) { ! int ui, vi; ! double u, v, x, y, z, n; ! ! _12_QNtoV(vec, qn); ! } ! ! void ! _limnQN12checker_QNtoV_d(double *vec, int qn) { ! int ui, vi; ! double u, v, x, y, z, n; ! ! _12_QNtoV(vec, qn); ! } ! ! #define _12_VtoQN(vec) \ ! x = vec[0]; \ ! y = vec[1]; \ ! z = vec[2]; \ ! L = AIR_ABS(x) + AIR_ABS(y) + AIR_ABS(z); \ ! if (!L) { \ ! return 0; \ ! } \ ! x /= L; \ ! y /= L; \ ! if (z > 0) { \ ! AIR_INDEX(-1.0, x, 1.0, 63, xi); \ ! AIR_INDEX(-1.0 - 1.0/63, y, 1.0 + 1.0/63, 64, yi); \ ! ui = xi + yi - 31; \ ! vi = xi - yi + 32; \ ! } \ ! else { \ ! AIR_INDEX(-1.0 - 1.0/63, x, 1.0 + 1.0/63, 64, xi); \ ! AIR_INDEX(-1, y, 1, 63, yi); \ ! ui = xi + yi - 31; \ ! vi = xi - yi + 31; \ ! } ! ! int ! _limnQN12checker_VtoQN_f(float *vec) { ! double L, x, y, z; ! int xi, yi, ui, vi; ! ! _12_VtoQN(vec); ! return (vi << 6) | ui; ! } ! ! int ! _limnQN12checker_VtoQN_d(double *vec) { ! double L, x, y, z; ! int xi, yi, ui, vi; ! ! _12_VtoQN(vec); ! return (vi << 6) | ui; ! } ! ! /* ----------------------------------------------------------- */ ! ! void (* ! limnQNtoV_f[LIMN_QN_MAX+1])(float *, int) = { NULL, ! _limnQN16checker_QNtoV_f, ! _limnQN16simple_QNtoV_f, ! _limnQN16border1_QNtoV_f, ! _limnQN15checker_QNtoV_f, ! _limnQN14checker_QNtoV_f, ! _limnQN12checker_QNtoV_f }; ! void (* ! limnQNtoV_d[LIMN_QN_MAX+1])(double *, int) = { NULL, ! _limnQN16checker_QNtoV_d, ! NULL, ! NULL, ! NULL, ! _limnQN14checker_QNtoV_d, ! _limnQN12checker_QNtoV_d ! }; ! ! int (* ! limnVtoQN_f[LIMN_QN_MAX+1])(float *vec) = { ! NULL, ! _limnQN16checker_VtoQN_f, ! _limnQN16simple_VtoQN_f, ! _limnQN16border1_VtoQN_f, ! _limnQN15checker_VtoQN_f, ! _limnQN14checker_VtoQN_f, ! _limnQN12checker_VtoQN_f ! }; ! ! int (* ! limnVtoQN_d[LIMN_QN_MAX+1])(double *vec) = { ! NULL, ! _limnQN16checker_VtoQN_d, ! NULL, ! NULL, ! NULL, ! _limnQN14checker_VtoQN_d, ! _limnQN12checker_VtoQN_d ! }; ! ! int ! limnQNBins[LIMN_QN_MAX+1] = { ! -1, ! (1 << 16), ! (1 << 16), ! (1 << 15), ! (1 << 14), ! (1 << 12) }; Index: renderLimn.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/renderLimn.c,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** renderLimn.c 7 Jan 2004 15:34:30 -0000 1.15 --- renderLimn.c 9 Feb 2004 07:06:18 -0000 1.16 *************** *** 87,91 **** fprintf(win->file, "grestore\n"); fprintf(win->file, "grestore\n"); ! /* fprintf(win->file, "showpage\n"); */ fprintf(win->file, "%%%%Trailer\n"); } --- 87,93 ---- fprintf(win->file, "grestore\n"); fprintf(win->file, "grestore\n"); ! if (win->ps.showpage) { ! fprintf(win->file, "showpage\n"); ! } fprintf(win->file, "%%%%Trailer\n"); } *************** *** 109,124 **** fprintf(stderr, "RGB = %g %g %g ->", r->rgba[0], r->rgba[1], r->rgba[2]); */ ! R = sp->k[0]*r->rgba[0]; ! G = sp->k[0]*r->rgba[1]; ! B = sp->k[0]*r->rgba[2]; /* fprintf(stderr, "RGB = %g %g %g ->", R, G, B); */ if (nmap) { ! qn = limnVtoQN[limnQN_16checker](f->wn); map = nmap->data; ! R += sp->k[1]*r->rgba[0]*map[0 + 3*qn]; ! G += sp->k[1]*r->rgba[1]*map[1 + 3*qn]; ! B += sp->k[1]*r->rgba[2]*map[2 + 3*qn]; } /* HEY: not evaluating phong specular for now */ --- 111,130 ---- fprintf(stderr, "RGB = %g %g %g ->", r->rgba[0], r->rgba[1], r->rgba[2]); */ ! R = sp->k[0]*sp->rgba[0]; ! G = sp->k[0]*sp->rgba[1]; ! B = sp->k[0]*sp->rgba[2]; /* fprintf(stderr, "RGB = %g %g %g ->", R, G, B); */ if (nmap) { ! qn = limnVtoQN_f[limnQN16checker](f->wn); map = nmap->data; ! R += sp->k[1]*sp->rgba[0]*map[0 + 3*qn]; ! G += sp->k[1]*sp->rgba[1]*map[1 + 3*qn]; ! B += sp->k[1]*sp->rgba[2]*map[2 + 3*qn]; ! } else { ! R += sp->k[1]*sp->rgba[0]; ! G += sp->k[1]*sp->rgba[1]; ! B += sp->k[1]*sp->rgba[2]; } /* HEY: not evaluating phong specular for now */ *************** *** 145,154 **** limnPoint *p0, *p1; ! if (win->ps.edgeWidth[e->visib]) { p0 = obj->p + e->v0; p1 = obj->p + e->v1; fprintf(win->file, "%g %g M ", p0->d[0], p0->d[1]); fprintf(win->file, "%g %g L ", p1->d[0], p1->d[1]); ! fprintf(win->file, "%g W ", win->ps.edgeWidth[e->visib]); fprintf(win->file, "S\n"); } --- 151,160 ---- limnPoint *p0, *p1; ! if (win->ps.lineWidth[e->type]) { p0 = obj->p + e->v0; p1 = obj->p + e->v1; fprintf(win->file, "%g %g M ", p0->d[0], p0->d[1]); fprintf(win->file, "%g %g L ", p1->d[0], p1->d[1]); ! fprintf(win->file, "%g W ", win->ps.lineWidth[e->type]); fprintf(win->file, "S\n"); } *************** *** 156,160 **** /* ! ******** limnObjPSDraw ** ** draws a "rendered" limn object to postscript. --- 162,166 ---- /* ! ******** limnObjPSDrawOld ** ** draws a "rendered" limn object to postscript. *************** *** 167,174 **** */ int ! limnObjPSDraw(limnObj *obj, limnCamera *cam, Nrrd *nmap, limnWin *win) { char me[]="limnObjPSDraw", err[AIR_STRLEN_MED]; ! int vis0, vis1, inside; ! float angle, widthTmp; limnFace *f, *f0, *f1; int fi; limnEdge *e; int ei; --- 173,180 ---- */ int ! limnObjPSDrawOld(limnObj *obj, limnCamera *cam, Nrrd *nmap, limnWin *win) { char me[]="limnObjPSDraw", err[AIR_STRLEN_MED]; ! int inside; ! float angle; limnFace *f, *f0, *f1; int fi; limnEdge *e; int ei; *************** *** 190,193 **** --- 196,200 ---- r = &(obj->r[ri]); + /* only draw the parts that are inside the field of view */ inside = 0; for (pi=0; pi<r->pNum; pi++) { *************** *** 201,214 **** break; } - if (!inside) continue; if (1 == r->eNum) { /* this part is just one lone edge */ e = &(obj->e[r->eBase]); ! widthTmp = win->ps.edgeWidth[e->visib]; fprintf(win->file, "%g setgray\n", 1 - win->ps.bg[0]); ! win->ps.edgeWidth[e->visib] = 8; _limnPSDrawEdge(obj, r, e, cam, win); fprintf(win->file, "%g %g %g RGB\n", --- 208,223 ---- break; } if (!inside) continue; + /* draw the part */ if (1 == r->eNum) { /* this part is just one lone edge */ + /* HEY: this is a mess */ + /* e = &(obj->e[r->eBase]); ! widthTmp = win->ps.lineWidth[e->type]; fprintf(win->file, "%g setgray\n", 1 - win->ps.bg[0]); ! win->ps.edgeWidth[e->type] = 8; _limnPSDrawEdge(obj, r, e, cam, win); fprintf(win->file, "%g %g %g RGB\n", *************** *** 217,222 **** --- 226,234 ---- _limnPSDrawEdge(obj, r, e, cam, win); win->ps.edgeWidth[e->visib] = widthTmp; + */ } else { /* this part is either a lone face or a solid */ + + /* draw the front-facing, shaded faces */ for (fi=0; fi<r->fNum; fi++) { f = &(obj->f[r->fBase + fi]); *************** *** 234,244 **** ELL_3V_SCALE(f->wn, -1, f->wn); } ! if (f->visib) { _limnPSDrawFace(obj, r, f, cam, nmap, win); } } fprintf(win->file, "0 setgray\n"); - for (ei=0; ei<r->eNum; ei++) { e = &(obj->e[r->eBase + ei]); --- 246,256 ---- ELL_3V_SCALE(f->wn, -1, f->wn); } ! if (!win->ps.wireFrame && f->visib) { _limnPSDrawFace(obj, r, f, cam, nmap, win); } } + /* draw ALL edges */ fprintf(win->file, "0 setgray\n"); for (ei=0; ei<r->eNum; ei++) { e = &(obj->e[r->eBase + ei]); *************** *** 246,262 **** f1 = e->f1 != -1 ? &(obj->f[e->f1]) : NULL; if (!f1) { ! /* not clear what to do with perimeter of lone faces; ! for now: front-facing non-crease edge */ ! e->visib = 4; } else { - vis0 = f0->visib; - vis1 = f1->visib; angle = 180/M_PI*acos(ELL_3V_DOT(f0->wn, f1->wn)); ! if (vis0 && vis1) { ! e->visib = 4 - (angle > win->ps.creaseAngle); ! } else if (!!vis0 ^ !!vis1) { ! e->visib = 2; } else { ! e->visib = (angle > win->ps.creaseAngle); } } --- 258,274 ---- f1 = e->f1 != -1 ? &(obj->f[e->f1]) : NULL; if (!f1) { ! e->type = limnEdgeTypeBorder; } else { angle = 180/M_PI*acos(ELL_3V_DOT(f0->wn, f1->wn)); ! if (f0->visib && f1->visib) { ! e->type = (angle > win->ps.creaseAngle ! ? limnEdgeTypeFrontCrease ! : limnEdgeTypeFrontFacet); ! } else if (f0->visib ^ f1->visib) { ! e->type = limnEdgeTypeContour; } else { ! e->type = (angle > win->ps.creaseAngle ! ? limnEdgeTypeBackCrease ! : limnEdgeTypeBackFacet); } } *************** *** 270,271 **** --- 282,401 ---- return 0; } + + void + _limnPSDrawPointPair(limnObj *obj, limnPart *r, + int v0, int v1, int type, + limnCamera *cam, limnWin *win) { + + if (win->ps.lineWidth[type]) { + fprintf(win->file, "%g %g M ", obj->p[v0].d[0], obj->p[v0].d[1]); + fprintf(win->file, "%g %g L ", obj->p[v1].d[0], obj->p[v1].d[1]); + fprintf(win->file, "%g W ", win->ps.lineWidth[type]); + fprintf(win->file, "S\n"); + } + } + + /* + ** HEY: drawing non-convex objects has to be done one face at a time, + ** and faces are responsible for drawing their edges. The STUPID + ** thing about limn right now is that faces do not have a list of + ** their edges; only a list of their vertex indices... + */ + + /* + ******** limnObjPSDraw + ** + ** new version of the above, which works per-face instead of per-part + */ + int + limnObjPSDraw(limnObj *obj, limnCamera *cam, Nrrd *nmap, limnWin *win) { + char me[]="limnObjPSDraw", err[AIR_STRLEN_MED]; + int inside, vi, psize, v0, v1; + float angle; + limnFace *f, *f0, *f1; int fi; + limnEdge *e; int ei; + limnPart *r; int ri; + limnPoint *p; int pi; + Nrrd *neinfo; + unsigned char *einfo; + airArray *mop; + + if (nmap) { + if (limnEnvMapCheck(nmap)) { + sprintf(err, "%s: trouble", me); + biffAdd(LIMN, err); return 1; + } + } + + mop = airMopNew(); + neinfo = nrrdNew(); + airMopAdd(mop, neinfo, (airMopper)nrrdNuke, airMopAlways); + psize = obj->pA->len; + if (nrrdMaybeAlloc(neinfo, nrrdTypeUChar, 2, psize, psize)) { + sprintf(err, "%s: couldn't allocate %d x %d array of point pairs", + me, obj->pA->len, obj->pA->len); + biffMove(LIMN, err, NRRD); return 1; + } + einfo = (unsigned char*)(neinfo->data); + + limnObjDepthSortFaces(obj); + + _limnPSPreamble(obj, cam, win); + + /* categorize all edges by traversing edge array, and storing + edge type information in einfo[] */ + for (ei=0; ei<obj->eA->len; ei++) { + e = obj->e + ei; + if (e->v0 < e->v1) { + v0 = e->v0; + v1 = e->v1; + } else { + v0 = e->v1; + v1 = e->v0; + } + f0 = &(obj->f[e->f0]); + f1 = e->f1 != -1 ? &(obj->f[e->f1]) : NULL; + if (!f1) { + einfo[v0 + psize*v1] = limnEdgeTypeBorder; + } else { + angle = 180/M_PI*acos(ELL_3V_DOT(f0->wn, f1->wn)); + if (f0->visib && f1->visib) { + einfo[v0 + psize*v1] = (angle > win->ps.creaseAngle + ? limnEdgeTypeFrontCrease + : limnEdgeTypeFrontFacet); + } else if (f0->visib ^ f1->visib) { + einfo[v0 + psize*v1] = limnEdgeTypeContour; + } else { + einfo[v0 + psize*v1] = (angle > win->ps.creaseAngle + ? limnEdgeTypeBackCrease + : limnEdgeTypeBackFacet); + } + } + } + + /* draw front-faces and non-back edges */ + for (fi=0; fi<obj->fA->len; fi++) { + f = obj->f + obj->fSort[fi]; + f->visib = (cam->rightHanded + ? f->sn[2] < 0 + : f->sn[2] > 0); + if (f->vNum == r->pNum && !f->visib) { + f->visib = AIR_TRUE; + ELL_3V_SCALE(f->wn, -1, f->wn); + } + if (!win->ps.wireFrame && f->visib) { + _limnPSDrawFace(obj, r, f, cam, nmap, win); + } + /* + for (vi=0; vi<f->vNum; vi++) { + p = obj->p + obj->v[vi + f->vBase]; + fprintf(win->file, "%g %g %s\n", + p->d[0], p->d[1], vi ? "L" : "M"); + } + */ + } + + _limnPSEpilogue(obj, cam, win); + + return 0; + } Index: transform.c =================================================================== RCS file: /cvsroot/teem/teem/src/limn/transform.c,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** transform.c 7 Jan 2004 15:34:30 -0000 1.16 --- transform.c 9 Feb 2004 07:06:18 -0000 1.17 *************** *** 266,267 **** --- 266,304 ---- return 0; } + + limnFace *_limnFaceHack; + + int + _limnFaceDepthCompare(const void *_a, const void *_b) { + int *a; + int *b; + + a = (int *)_a; + b = (int *)_b; + return -AIR_COMPARE(_limnFaceHack[*a].z, _limnFaceHack[*b].z); + } + + int + limnObjDepthSortFaces(limnObj *obj) { + limnFace *f; + limnPoint *p; + int fi, vi; + + obj->fSort = (int*)calloc(obj->fA->len, sizeof(int)); + for (fi=0; fi<obj->fA->len; fi++) { + f = obj->f + fi; + f->z = 0; + for (vi=f->vBase; vi<f->vBase+f->vNum; vi++) { + p = obj->p + obj->v[vi]; + f->z += p->s[2]; + } + f->z /= f->vNum; + obj->fSort[fi] = fi; + } + + _limnFaceHack = obj->f; + qsort(obj->fSort, obj->fA->len, sizeof(int), _limnFaceDepthCompare); + + return 0; + } + |