Ejemplo n.º 1
0
/*
******** limnLightUpdate()
**
** copies information from the _dir vectors to the dir vectors. This
** needs to be called even if there are no viewspace lights, so that
** the dir vectors are set and normalized.  If there are no viewspace
** lights, "cam" can actually be passed as NULL, but don't get carried
** away...
** 
** returns 1 if there was a problem in the camera, otherwise 0.
*/
int
limnLightUpdate(limnLight *lit, limnCamera *cam) {
  char me[]="limnLightUpdate", err[BIFF_STRLEN];
  double dir[3], _dir[3], uvn[9]={0,0,0,0,0,0,0,0,0}, norm;
  int i;
  
  if (cam) {
    if (limnCameraUpdate(cam)) {
      sprintf(err, "%s: trouble in camera", me);
      biffAdd(LIMN, err); return 1;
    }
    ELL_34M_EXTRACT(uvn, cam->V2W);
  }
  for (i=0; i<LIMN_LIGHT_NUM; i++) {
    ELL_3V_COPY(_dir, lit->_dir[i]);
    if (cam && lit->vsp[i]) {
      ELL_3MV_MUL(dir, uvn, _dir);
    } else {
      ELL_3V_COPY(dir, _dir);
    }
    ELL_3V_NORM(dir, dir, norm);
    ELL_4V_SET_TT(lit->dir[i], float, dir[0], dir[1], dir[2], 0.0);
  }
  return 0;
}
Ejemplo n.º 2
0
Archivo: tcam.c Proyecto: BRAINSia/teem
int
main(int argc, const char *argv[]) {
  const char *me;
  char *err;
  limnCamera *cam;
  float mat[16];
  hestOpt *hopt=NULL;
  airArray *mop;

  mop = airMopNew();
  cam = limnCameraNew();
  airMopAdd(mop, cam, (airMopper)limnCameraNix, airMopAlways);

  me = argv[0];
  hestOptAdd(&hopt, "fr", "eye pos", airTypeDouble, 3, 3, cam->from,
             NULL, "camera eye point");
  hestOptAdd(&hopt, "at", "at pos", airTypeDouble, 3, 3, cam->at,
             "0 0 0", "camera look-at point");
  hestOptAdd(&hopt, "up", "up dir", airTypeDouble, 3, 3, cam->up,
             "0 0 1", "camera pseudo up vector");
  hestOptAdd(&hopt, "rh", NULL, airTypeInt, 0, 0, &(cam->rightHanded), NULL,
             "use a right-handed UVN frame (V points down)");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  cam->neer = -1;
  cam->dist = 0;
  cam->faar = 1;
  cam->atRelative = AIR_TRUE;

  if (limnCameraUpdate(cam)) {
    fprintf(stderr, "%s: trouble:\n%s\n", me, err = biffGet(LIMN));
    free(err);
    return 1;
  }

  printf("%s: W2V:\n", me);
  ELL_4M_COPY(mat, cam->W2V);
  ell_4m_print_f(stdout, mat);

  printf("\n");
  printf("%s: V2W:\n", me);
  ELL_4M_COPY(mat, cam->V2W);
  ell_4m_print_f(stdout, mat);

  airMopOkay(mop);
  return 0;
}
Ejemplo n.º 3
0
int
hooverContextCheck(hooverContext *ctx) {
    static const char me[]="hooverContextCheck";
    int sxe, sye, sze, minSize, centr;

    if (!ctx) {
        biffAddf(HOOVER, "%s: got NULL pointer", me);
        return 1;
    }
    if (airEnumValCheck(nrrdCenter, ctx->imgCentering)) {
        biffAddf(HOOVER, "%s: pixel centering (%d) invalid",
                 me, ctx->imgCentering);
        return 1;
    }
    centr = (ctx->shape ? ctx->shape->center : ctx->volCentering);
    if (airEnumValCheck(nrrdCenter, centr)) {
        biffAddf(HOOVER, "%s: voxel centering (%d) invalid", me, centr);
        return 1;
    }
    if (limnCameraAspectSet(ctx->cam,
                            ctx->imgSize[0], ctx->imgSize[1], ctx->imgCentering)
            || limnCameraUpdate(ctx->cam)) {
        biffMovef(HOOVER, LIMN, "%s: trouble setting up camera", me);
        return 1;
    }
    if (ctx->shape) {
        if (!ELL_4M_EXISTS(ctx->shape->ItoW)) {
            biffAddf(HOOVER, "%s: given shape doesn't seem to be set", me);
            return 1;
        }
    } else {
        minSize = (nrrdCenterCell == centr ? 1 : 2);
        if (!(ctx->volSize[0] >= minSize
                && ctx->volSize[1] >= minSize
                && ctx->volSize[2] >= minSize)) {
            biffAddf(HOOVER, "%s: volume dimensions (%dx%dx%d) too small", me,
                     ctx->volSize[0], ctx->volSize[1], ctx->volSize[2]);
            return 1;
        }
        sxe = AIR_EXISTS(ctx->volSpacing[0]);
        sye = AIR_EXISTS(ctx->volSpacing[1]);
        sze = AIR_EXISTS(ctx->volSpacing[2]);
        if (!sxe && !sye && !sze) {
            /* none of the incoming spacings existed, we'll go out on a limb
               and assume unit spacing */
            ctx->volSpacing[0] = nrrdDefaultSpacing;
            ctx->volSpacing[1] = ctx->volSpacing[2] = ctx->volSpacing[0];
            fprintf(stderr, "%s: WARNING: assuming spacing %g for all axes\n",
                    me, ctx->volSpacing[0]);
            /* HEY : nrrdDefaultSpacing need not be the same as gageParm's
               defaultSpacing, but we don't know anything about gage here,
               so what else can we do? */
        } else if (sxe && sye && sze) {
            /* all existed */
            if (!(ctx->volSpacing[0] > 0.0
                    && ctx->volSpacing[1] > 0.0
                    && ctx->volSpacing[2] > 0.0)) {
                biffAddf(HOOVER, "%s: volume spacing (%gx%gx%g) invalid", me,
                         ctx->volSpacing[0], ctx->volSpacing[1], ctx->volSpacing[2]);
                return 1;
            }
        } else {
            /* some existed, some didn't */
            biffAddf(HOOVER, "%s: spacings %g, %g, %g don't all exist or not", me,
                     ctx->volSpacing[0], ctx->volSpacing[1], ctx->volSpacing[2]);
            return 1;
        }
    }
    if (!(ctx->imgSize[0] > 0 && ctx->imgSize[1] > 0)) {
        biffAddf(HOOVER, "%s: image dimensions (%dx%d) invalid", me,
                 ctx->imgSize[0], ctx->imgSize[1]);
        return 1;
    }
    if (!(ctx->numThreads >= 1)) {
        biffAddf(HOOVER, "%s: number threads (%d) invalid", me, ctx->numThreads);
        return 1;
    }
    if (!(ctx->numThreads <= HOOVER_THREAD_MAX)) {
        biffAddf(HOOVER, "%s: sorry, number threads (%d) > max (%d)", me,
                 ctx->numThreads, HOOVER_THREAD_MAX);
        return 1;
    }
    if (!ctx->renderBegin) {
        biffAddf(HOOVER, "%s: need a non-NULL begin rendering callback", me);
        return 1;
    }
    if (!ctx->rayBegin) {
        biffAddf(HOOVER, "%s: need a non-NULL begin ray callback", me);
        return 1;
    }
    if (!ctx->threadBegin) {
        biffAddf(HOOVER, "%s: need a non-NULL begin thread callback", me);
        return 1;
    }
    if (!ctx->sample) {
        biffAddf(HOOVER, "%s: need a non-NULL sampler callback function", me);
        return 1;
    }
    if (!ctx->rayEnd) {
        biffAddf(HOOVER, "%s: need a non-NULL end ray callback", me);
        return 1;
    }
    if (!ctx->threadEnd) {
        biffAddf(HOOVER, "%s: need a non-NULL end thread callback", me);
        return 1;
    }
    if (!ctx->renderEnd) {
        biffAddf(HOOVER, "%s: need a non-NULL end render callback", me);
        return 1;
    }

    return 0;
}
Ejemplo n.º 4
0
Archivo: cam.c Proyecto: BRAINSia/teem
/*
******** limnCameraPathMake
**
** uses limnSplines to do camera paths based on key-frames
**
** output: cameras at all "numFrames" frames are set in the
** PRE-ALLOCATED array of output cameras, "cam".
**
** input:
** keycam: array of keyframe cameras
** time: times associated with the key frames
** ---> both of these arrays are length "numKeys" <---
** trackWhat: takes values from the limnCameraPathTrack* enum
** quatType: spline to control camera orientations. This is needed for
**          tracking at or from, but not needed for limnCameraPathTrackBoth.
**          This is the only limnSplineTypeSpec* argument that can be NULL.
** posType: spline to control whichever of from, at, and up are needed for
**          the given style of tracking.
** distType: spline to control neer, faar, dist: positions of near clipping,
**          far clipping, and image plane, as well as the
**          distance between from and at (which is used if not doing
**          limnCameraPathTrackBoth)
** viewType: spline to control fov (and aspect, if you're crazy)
**
** NOTE: The "atRelative", "orthographic", and "rightHanded" fields
** are copied from keycam[0] into all output cam[i], but you still need
** to correctly set them for all keycam[i] for limnCameraUpdate to work
** as expected.  Also, for the sake of simplicity, this function only works
** with fov and aspect, instead of {u,v}Range, and hence both "fov" and
** "aspect" need to set in *all* the keycams, even if neither of them
** ever changes!
*/
int
limnCameraPathMake(limnCamera *cam, int numFrames,
                   limnCamera *keycam, double *time, int numKeys,
                   int trackWhat,
                   limnSplineTypeSpec *quatType,
                   limnSplineTypeSpec *posType,
                   limnSplineTypeSpec *distType,
                   limnSplineTypeSpec *viewType) {
  static const char me[]="limnCameraPathMake";
  char which[AIR_STRLEN_MED];
  airArray *mop;
  Nrrd *nquat, *nfrom, *natpt, *nupvc, *ndist, *nfova, *ntime, *nsample;
  double fratVec[3], *quat, *from, *atpt, *upvc, *dist, *fova,
    W2V[9], N[3], fratDist;
  limnSpline *timeSpline, *quatSpline, *fromSpline, *atptSpline, *upvcSpline,
    *distSpline, *fovaSpline;
  limnSplineTypeSpec *timeType;
  int ii, E;

  if (!( cam && keycam && time && posType && distType && viewType )) {
    biffAddf(LIMN, "%s: got NULL pointer", me);
    return 1;
  }
  if (!( AIR_IN_OP(limnCameraPathTrackUnknown, trackWhat,
                   limnCameraPathTrackLast) )) {
    biffAddf(LIMN, "%s: trackWhat %d not in valid range [%d,%d]", me,
             trackWhat, limnCameraPathTrackUnknown+1,
             limnCameraPathTrackLast-1);
    return 1;
  }
  if (limnCameraPathTrackBoth != trackWhat && !quatType) {
    biffAddf(LIMN, "%s: need the quaternion limnSplineTypeSpec if not "
             "doing trackBoth", me);
    return 1;
  }

  /* create and allocate nrrds.  For the time being, we're allocating
     more different nrrds, and filling their contents, than we need
     to-- nquat is not needed if we're doing limnCameraPathTrackBoth,
     for example.  However, we do make an effort to only do the spline
     evaluation on the things we actually need to know. */
  mop = airMopNew();
  airMopAdd(mop, nquat = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nfrom = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, natpt = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nupvc = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, ndist = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nfova = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, ntime = nrrdNew(), (airMopper)nrrdNix, airMopAlways);
  if (nrrdWrap_va(ntime, time, nrrdTypeDouble, 1,
                  AIR_CAST(size_t, numKeys))) {
    biffMovef(LIMN, NRRD, "%s: trouble wrapping time values", me);
    airMopError(mop); return 1;
  }
  airMopAdd(mop, nsample = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  timeType = limnSplineTypeSpecNew(limnSplineTypeTimeWarp);
  airMopAdd(mop, timeType, (airMopper)limnSplineTypeSpecNix, airMopAlways);
  if (nrrdMaybeAlloc_va(nquat, nrrdTypeDouble, 2,
                        AIR_CAST(size_t, 4), AIR_CAST(size_t, numKeys))
      || nrrdMaybeAlloc_va(nfrom, nrrdTypeDouble, 2,
                           AIR_CAST(size_t, 3), AIR_CAST(size_t, numKeys))
      || nrrdMaybeAlloc_va(natpt, nrrdTypeDouble, 2,
                           AIR_CAST(size_t, 3), AIR_CAST(size_t, numKeys))
      || nrrdMaybeAlloc_va(nupvc, nrrdTypeDouble, 2,
                           AIR_CAST(size_t, 3), AIR_CAST(size_t, numKeys))
      || nrrdMaybeAlloc_va(ndist, nrrdTypeDouble, 2,
                           AIR_CAST(size_t, 4), AIR_CAST(size_t, numKeys))
      || nrrdMaybeAlloc_va(nfova, nrrdTypeDouble, 2,
                           AIR_CAST(size_t, 2), AIR_CAST(size_t, numKeys))) {
    biffMovef(LIMN, NRRD, "%s: couldn't allocate buffer nrrds", me);
    airMopError(mop); return 1;
  }
  quat = (double*)(nquat->data);
  from = (double*)(nfrom->data);
  atpt = (double*)(natpt->data);
  upvc = (double*)(nupvc->data);
  dist = (double*)(ndist->data);
  fova = (double*)(nfova->data);

  /* check cameras, and put camera information into nrrds */
  for (ii=0; ii<numKeys; ii++) {
    if (limnCameraUpdate(keycam + ii)) {
      biffAddf(LIMN, "%s: trouble with camera at keyframe %d\n", me, ii);
      airMopError(mop); return 1;
    }
    if (!( AIR_EXISTS(keycam[ii].fov) && AIR_EXISTS(keycam[ii].aspect) )) {
      biffAddf(LIMN, "%s: fov, aspect not both defined on keyframe %d",
               me, ii);
      airMopError(mop); return 1;
    }
    ell_4m_to_q_d(quat + 4*ii, keycam[ii].W2V);
    if (ii) {
      if (0 > ELL_4V_DOT(quat + 4*ii, quat + 4*(ii-1))) {
        ELL_4V_SCALE(quat + 4*ii, -1, quat + 4*ii);
      }
    }
    ELL_3V_COPY(from + 3*ii, keycam[ii].from);
    ELL_3V_COPY(atpt + 3*ii, keycam[ii].at);
    ELL_3V_COPY(upvc + 3*ii, keycam[ii].up);
    ELL_3V_SUB(fratVec, keycam[ii].from, keycam[ii].at);
    fratDist = ELL_3V_LEN(fratVec);
    ELL_4V_SET(dist + 4*ii, fratDist,
               keycam[ii].neer, keycam[ii].dist, keycam[ii].faar);
    ELL_2V_SET(fova + 2*ii, keycam[ii].fov, keycam[ii].aspect);
  }

  /* create splines from nrrds */
  if (!( (strcpy(which, "quaternion"), quatSpline =
          limnSplineCleverNew(nquat, limnSplineInfoQuaternion, quatType))
         && (strcpy(which, "from point"), fromSpline =
             limnSplineCleverNew(nfrom, limnSplineInfo3Vector, posType))
         && (strcpy(which, "at point"), atptSpline =
             limnSplineCleverNew(natpt, limnSplineInfo3Vector, posType))
         && (strcpy(which, "up vector"), upvcSpline =
             limnSplineCleverNew(nupvc, limnSplineInfo3Vector, posType))
         && (strcpy(which, "plane distances"), distSpline =
             limnSplineCleverNew(ndist, limnSplineInfo4Vector, distType))
         && (strcpy(which, "field-of-view"), fovaSpline =
             limnSplineCleverNew(nfova, limnSplineInfo2Vector, viewType))
         && (strcpy(which, "time warp"), timeSpline =
             limnSplineCleverNew(ntime, limnSplineInfoScalar, timeType)) )) {
    biffAddf(LIMN, "%s: trouble creating %s spline", me, which);
    airMopError(mop); return 1;
  }
  airMopAdd(mop, quatSpline, (airMopper)limnSplineNix, airMopAlways);
  airMopAdd(mop, fromSpline, (airMopper)limnSplineNix, airMopAlways);
  airMopAdd(mop, atptSpline, (airMopper)limnSplineNix, airMopAlways);
  airMopAdd(mop, upvcSpline, (airMopper)limnSplineNix, airMopAlways);
  airMopAdd(mop, distSpline, (airMopper)limnSplineNix, airMopAlways);
  airMopAdd(mop, fovaSpline, (airMopper)limnSplineNix, airMopAlways);
  airMopAdd(mop, timeSpline, (airMopper)limnSplineNix, airMopAlways);

  /* evaluate splines */
  E = AIR_FALSE;
  if (!E) E |= limnSplineSample(nsample, timeSpline,
                                limnSplineMinT(timeSpline), numFrames,
                                limnSplineMaxT(timeSpline));
  quat = NULL;
  from = NULL;
  atpt = NULL;
  upvc = NULL;
  switch(trackWhat) {
  case limnCameraPathTrackAt:
    if (!E) E |= limnSplineNrrdEvaluate(natpt, atptSpline, nsample);
    if (!E) atpt = (double*)(natpt->data);
    if (!E) E |= limnSplineNrrdEvaluate(nquat, quatSpline, nsample);
    if (!E) quat = (double*)(nquat->data);
    break;
  case limnCameraPathTrackFrom:
    if (!E) E |= limnSplineNrrdEvaluate(nfrom, fromSpline, nsample);
    if (!E) from = (double*)(nfrom->data);
    if (!E) E |= limnSplineNrrdEvaluate(nquat, quatSpline, nsample);
    if (!E) quat = (double*)(nquat->data);
    break;
  case limnCameraPathTrackBoth:
    if (!E) E |= limnSplineNrrdEvaluate(nfrom, fromSpline, nsample);
    if (!E) from = (double*)(nfrom->data);
    if (!E) E |= limnSplineNrrdEvaluate(natpt, atptSpline, nsample);
    if (!E) atpt = (double*)(natpt->data);
    if (!E) E |= limnSplineNrrdEvaluate(nupvc, upvcSpline, nsample);
    if (!E) upvc = (double*)(nupvc->data);
    break;
  }
  dist = NULL;
  if (!E) E |= limnSplineNrrdEvaluate(ndist, distSpline, nsample);
  if (!E) dist = (double*)(ndist->data);
  fova = NULL;
  if (!E) E |= limnSplineNrrdEvaluate(nfova, fovaSpline, nsample);
  if (!E) fova = (double*)(nfova->data);
  if (E) {
    biffAddf(LIMN, "%s: trouble evaluating splines", me);
    airMopError(mop); return 1;
  }

  /* copy information from nrrds back into cameras */
  for (ii=0; ii<numFrames; ii++) {
    cam[ii].atRelative = keycam[0].atRelative;
    cam[ii].orthographic = keycam[0].orthographic;
    cam[ii].rightHanded = keycam[0].rightHanded;
    if (limnCameraPathTrackBoth == trackWhat) {
      ELL_3V_COPY(cam[ii].from, from + 3*ii);
      ELL_3V_COPY(cam[ii].at, atpt + 3*ii);
      ELL_3V_COPY(cam[ii].up, upvc + 3*ii);
    } else {
      fratDist = (dist + 4*ii)[0];
      ell_q_to_3m_d(W2V, quat + 4*ii);
      ELL_3MV_ROW1_GET(cam[ii].up, W2V);
      if (cam[ii].rightHanded) {
        ELL_3V_SCALE(cam[ii].up, -1, cam[ii].up);
      }
      ELL_3MV_ROW2_GET(N, W2V);
      if (limnCameraPathTrackFrom == trackWhat) {
        ELL_3V_COPY(cam[ii].from, from + 3*ii);
        ELL_3V_SCALE_ADD2(cam[ii].at, 1.0, cam[ii].from, fratDist, N);
      } else {
        ELL_3V_COPY(cam[ii].at, atpt + 3*ii);
        ELL_3V_SCALE_ADD2(cam[ii].from, 1.0, cam[ii].at, -fratDist, N);
      }
    }
    cam[ii].neer = (dist + 4*ii)[1];
    cam[ii].dist = (dist + 4*ii)[2];
    cam[ii].faar = (dist + 4*ii)[3];
    cam[ii].fov = (fova + 2*ii)[0];
    cam[ii].aspect = (fova + 2*ii)[1];
    if (limnCameraUpdate(cam + ii)) {
      biffAddf(LIMN, "%s: trouble with output camera %d\n", me, ii);
      airMopError(mop); return 1;
    }
  }

  airMopOkay(mop);
  return 0;
}
Ejemplo n.º 5
0
Archivo: emap.c Proyecto: BRAINSia/teem
int
main(int argc, const char *argv[]) {
    hestOpt *hopt=NULL;
    hestParm *hparm;
    Nrrd *nlight, *nmap, *ndebug;
    const char *me;
    char *outS, *errS, *debugS;
    airArray *mop;
    float amb[3], *linfo, *debug, *map, vscl;
    unsigned li, ui, vi;
    int qn, bits, method, doerr;
    limnLight *light;
    limnCamera *cam;
    double u, v, r, w, V2W[9], diff, WW[3], VV[3];

    me = argv[0];
    mop = airMopNew();
    hparm = hestParmNew();
    airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
    hparm->elideSingleEmptyStringDefault = AIR_TRUE;
    cam = limnCameraNew();
    airMopAdd(mop, cam, (airMopper)limnCameraNix, airMopAlways);
    hestOptAdd(&hopt, "i", "nlight", airTypeOther, 1, 1, &nlight, NULL,
               "input nrrd containing light information",
               NULL, NULL, nrrdHestNrrd);
    hestOptAdd(&hopt, "b", "# bits", airTypeInt, 1, 1, &bits, "16",
               "number of bits to use for normal quantization, "
               "between 8 and 16 inclusive. ");
    hestOptAdd(&hopt, "amb", "ambient RGB", airTypeFloat, 3, 3, amb, "0 0 0",
               "ambient light color");
    hestOptAdd(&hopt, "fr", "from point", airTypeDouble, 3, 3, cam->from,"1 0 0",
               "position of camera, used to determine view vector");
    hestOptAdd(&hopt, "at", "at point", airTypeDouble, 3, 3, cam->at, "0 0 0",
               "camera look-at point, used to determine view vector");
    hestOptAdd(&hopt, "up", "up vector", airTypeDouble, 3, 3, cam->up, "0 0 1",
               "camera pseudo-up vector, used to determine view coordinates");
    hestOptAdd(&hopt, "rh", NULL, airTypeInt, 0, 0, &(cam->rightHanded), NULL,
               "use a right-handed UVN frame (V points down)");
    hestOptAdd(&hopt, "vs", "view-dir scaling", airTypeFloat, 1, 1, &vscl, "1",
               "scaling along view-direction of location of "
               "view-space lights");
    hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, NULL,
               "file to write output envmap to");
    hestOptAdd(&hopt, "d", "filename", airTypeString, 1, 1, &debugS, "",
               "Use this option to save out (to the given filename) a rendering "
               "of the front (on the left) and back (on the right) of a sphere "
               "as shaded with the new environment map.  U increases "
               "right-ward, V increases downward.  The back sphere half is "
               "rendered as though the front half was removed");
    hestOptAdd(&hopt, "err", NULL, airTypeInt, 0, 0, &doerr, NULL,
               "If using \"-d\", make the image represent the error between the "
               "real and quantized vector");
    hestParseOrDie(hopt, argc-1, argv+1, hparm, me, emapInfo,
                   AIR_TRUE, AIR_TRUE, AIR_TRUE);
    airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
    airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

    switch(bits) {
    case 16:
        method = limnQN16octa;
        break;
    case 15:
        method = limnQN15octa;
        break;
    case 14:
        method = limnQN14octa;
        break;
    case 13:
        method = limnQN13octa;
        break;
    case 12:
        method = limnQN12octa;
        break;
    case 11:
        method = limnQN11octa;
        break;
    case 10:
        method = limnQN10octa;
        break;
    case 9:
        method = limnQN9octa;
        break;
    case 8:
        method = limnQN8octa;
        break;
    default:
        fprintf(stderr, "%s: requested #bits (%d) not in valid range [8,16]\n",
                me, bits);
        airMopError(mop);
        return 1;
    }

    if (!(nrrdTypeFloat == nlight->type &&
            2 == nlight->dim &&
            7 == nlight->axis[0].size &&
            LIMN_LIGHT_NUM >= nlight->axis[1].size)) {
        fprintf(stderr, "%s: nlight isn't valid format for light specification, "
                "must be: float type, 2-dimensional, 7\tx\tN size, N <= %d\n",
                me, LIMN_LIGHT_NUM);
        airMopError(mop);
        return 1;
    }

    cam->neer = -0.000000001;
    cam->dist = 0;
    cam->faar = 0.0000000001;
    cam->atRelative = AIR_TRUE;
    if (limnCameraUpdate(cam)) {
        airMopAdd(mop, errS = biffGetDone(LIMN), airFree, airMopAlways);
        fprintf(stderr, "%s: problem with camera:\n%s\n", me, errS);
        airMopError(mop);
        return 1;
    }

    light = limnLightNew();
    airMopAdd(mop, light, (airMopper)limnLightNix, airMopAlways);
    limnLightAmbientSet(light, amb[0], amb[1], amb[2]);
    for (li=0; li<nlight->axis[1].size; li++) {
        int vsp;
        float lxyz[3];
        linfo = (float *)(nlight->data) + 7*li;
        vsp = !!linfo[0];
        ELL_3V_COPY(lxyz, linfo + 4);
        if (vsp) {
            lxyz[2] *= vscl;
        }
        limnLightSet(light, li, vsp,
                     linfo[1], linfo[2], linfo[3], lxyz[0], lxyz[1], lxyz[2]);
    }
    if (limnLightUpdate(light, cam)) {
        airMopAdd(mop, errS = biffGetDone(LIMN), airFree, airMopAlways);
        fprintf(stderr, "%s: problem with lights:\n%s\n", me, errS);
        airMopError(mop);
        return 1;
    }

    nmap=nrrdNew();
    airMopAdd(mop, nmap, (airMopper)nrrdNuke, airMopAlways);
    if (limnEnvMapFill(nmap, limnLightDiffuseCB, method, light)) {
        airMopAdd(mop, errS = biffGetDone(LIMN), airFree, airMopAlways);
        fprintf(stderr, "%s: problem making environment map:\n%s\n", me, errS);
        airMopError(mop);
        return 1;
    }
    map = (float *)nmap->data;

    if (nrrdSave(outS, nmap, NULL)) {
        fprintf(stderr, "%s: trouble:\n%s", me, errS = biffGetDone(NRRD));
        free(errS);
        return 1;
    }

    if (airStrlen(debugS)) {
        ELL_34M_EXTRACT(V2W, cam->V2W);
        ndebug = nrrdNew();
        nrrdMaybeAlloc_va(ndebug, nrrdTypeFloat, 3,
                          AIR_CAST(size_t, 3),
                          AIR_CAST(size_t, 1024),
                          AIR_CAST(size_t, 512));
        airMopAdd(mop, ndebug, (airMopper)nrrdNuke, airMopAlways);
        debug = (float *)ndebug->data;
        for (vi=0; vi<=511; vi++) {
            v = AIR_AFFINE(0, vi, 511, -0.999, 0.999);
            for (ui=0; ui<=511; ui++) {
                u = AIR_AFFINE(0, ui, 511, -0.999, 0.999);
                r = sqrt(u*u + v*v);
                if (r > 1) {
                    continue;
                }
                w = sqrt(1 - r*r);

                /* first, the near side of the sphere */
                ELL_3V_SET(VV, u, v, -w);
                ELL_3MV_MUL(WW, V2W, VV);
                qn = limnVtoQN_d[method](WW);
                if (doerr) {
                    limnQNtoV_d[method](VV, qn);
                    ELL_3V_SUB(WW, WW, VV);
                    diff = ELL_3V_LEN(WW);
                    ELL_3V_SET_TT(debug + 3*(ui + 1024*vi), float,
                                  diff, diff, diff);
                } else {
                    ELL_3V_COPY(debug + 3*(ui + 1024*vi), map + 3*qn);
                }

                /* second, the far side of the sphere */
                ELL_3V_SET(VV, u, v, w);
                ELL_3MV_MUL(WW, V2W, VV);
                qn = limnVtoQN_d[method](WW);
                if (doerr) {
                    limnQNtoV_d[method](VV, qn);
                    ELL_3V_SUB(WW, WW, VV);
                    diff = ELL_3V_LEN(WW);
                    ELL_3V_SET_TT(debug + 3*(ui + 512 + 1024*vi), float,
                                  diff, diff, diff);
                } else {
                    ELL_3V_COPY(debug + 3*(ui + 512 + 1024*vi), map + 3*qn);
                }
            }
        }
Ejemplo n.º 6
0
int
main(int argc, const char *argv[]) {
  const char *me;
  char *err, *inS, *outS;
  limnCamera *cam;
  float bg[3], winscale, edgeWidth[5], creaseAngle;
  hestOpt *hopt=NULL;
  airArray *mop;
  limnObject *obj;
  limnLook *look; unsigned int lookIdx;
  limnWindow *win;
  Nrrd *nmap;
  FILE *file;
  int wire, concave, describe, reverse, nobg;

  mop = airMopNew();
  cam = limnCameraNew();
  airMopAdd(mop, cam, (airMopper)limnCameraNix, airMopAlways);

  me = argv[0];
  hestOptAdd(&hopt, "i", "input OFF", airTypeString, 1, 1, &inS, NULL,
             "input OFF file");
  hestOptAdd(&hopt, "fr", "from point", airTypeDouble, 3, 3, cam->from,"4 4 4",
             "position of camera, used to determine view vector");
  hestOptAdd(&hopt, "at", "at point", airTypeDouble, 3, 3, cam->at, "0 0 0",
             "camera look-at point, used to determine view vector");
  hestOptAdd(&hopt, "up", "up vector", airTypeDouble, 3, 3, cam->up, "0 0 1",
             "camera pseudo-up vector, used to determine view coordinates");
  hestOptAdd(&hopt, "rh", NULL, airTypeInt, 0, 0, &(cam->rightHanded), NULL,
             "use a right-handed UVN frame (V points down)");
  hestOptAdd(&hopt, "or", NULL, airTypeInt, 0, 0, &(cam->orthographic), NULL,
             "use orthogonal projection");
  hestOptAdd(&hopt, "ur", "uMin uMax", airTypeDouble, 2, 2, cam->uRange,
             "-1 1", "range in U direction of image plane");
  hestOptAdd(&hopt, "vr", "vMin vMax", airTypeDouble, 2, 2, cam->vRange,
             "-1 1", "range in V direction of image plane");
  hestOptAdd(&hopt, "e", "envmap", airTypeOther, 1, 1, &nmap, "",
             "16octa-based environment map",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "ws", "winscale", airTypeFloat, 1, 1, &winscale,
             "200", "world to points (PostScript) scaling");
  hestOptAdd(&hopt, "wire", NULL, airTypeInt, 0, 0, &wire, NULL,
             "just do wire-frame rendering");
  hestOptAdd(&hopt, "concave", NULL, airTypeInt, 0, 0, &concave, NULL,
             "use slightly buggy rendering method suitable for "
             "concave or self-occluding objects");
  hestOptAdd(&hopt, "reverse", NULL, airTypeInt, 0, 0, &reverse, NULL,
             "reverse ordering of vertices per face (needed if they "
             "specified in clockwise order)");
  hestOptAdd(&hopt, "describe", NULL, airTypeInt, 0, 0, &describe, NULL,
             "for debugging: list object definition of OFF read");
  hestOptAdd(&hopt, "bg", "background", airTypeFloat, 3, 3, bg, "1 1 1",
             "background RGB color; each component in range [0.0,1.0]");
  hestOptAdd(&hopt, "nobg", NULL, airTypeInt, 0, 0, &nobg, NULL,
             "don't initially fill with background color");
  hestOptAdd(&hopt, "wd", "5 widths", airTypeFloat, 5, 5, edgeWidth,
             "0.0 0.0 3.0 2.0 0.0",
             "width of edges drawn for five kinds of "
             "edges: back non-crease, back crease, "
             "silohuette, front crease, front non-crease");
  hestOptAdd(&hopt, "ca", "angle", airTypeFloat, 1, 1, &creaseAngle, "30",
             "dihedral angles greater than this are creases");
  hestOptAdd(&hopt, "o", "output PS", airTypeString, 1, 1, &outS, "out.ps",
             "output file to render postscript into");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  cam->neer = -0.000000001;
  cam->dist = 0;
  cam->faar = 0.0000000001;
  cam->atRelative = AIR_TRUE;

  if (limnCameraUpdate(cam)) {
    fprintf(stderr, "%s: trouble:\n%s\n", me, err = biffGet(LIMN));
    free(err);
    return 1;
  }

  obj = limnObjectNew(10, AIR_TRUE);
  airMopAdd(mop, obj, (airMopper)limnObjectNix, airMopAlways);
  if (!(file = airFopen(inS, stdin, "r"))) {
    fprintf(stderr, "%s: couldn't open \"%s\" for reading\n", me, inS);
    airMopError(mop); return 1;
  }
  airMopAdd(mop, file, (airMopper)airFclose, airMopAlways);
  if (limnObjectReadOFF(obj, file)) {
    airMopAdd(mop, err = biffGetDone(LIMN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }
  if (describe) {
    fprintf(stdout, "----------------- POST-READ -----------------\n");
    limnObjectDescribe(stdout, obj);
    fprintf(stdout, "----------------- POST-READ -----------------\n");
  }
  if (reverse) {
    if (limnObjectFaceReverse(obj)) {
      airMopAdd(mop, err = biffGetDone(LIMN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
  }
  if (describe) {
    fprintf(stdout, "----------------- POST-REVERSE -----------------\n");
    limnObjectDescribe(stdout, obj);
    fprintf(stdout, "----------------- POST-REVERSE -----------------\n");
  }
  win = limnWindowNew(limnDevicePS);
  win->ps.lineWidth[limnEdgeTypeBackFacet] = edgeWidth[0];
  win->ps.lineWidth[limnEdgeTypeBackCrease] = edgeWidth[1];
  win->ps.lineWidth[limnEdgeTypeContour] = edgeWidth[2];
  win->ps.lineWidth[limnEdgeTypeFrontCrease] = edgeWidth[3];
  win->ps.lineWidth[limnEdgeTypeFrontFacet] = edgeWidth[4];

  win->ps.wireFrame = wire;
  win->ps.creaseAngle = creaseAngle;
  win->ps.noBackground = nobg;
  ELL_3V_COPY(win->ps.bg, bg);

  win->file = airFopen(outS, stdout, "w");
  airMopAdd(mop, win, (airMopper)limnWindowNix, airMopAlways);
  win->scale = winscale;

  for (lookIdx=0; lookIdx<obj->lookNum; lookIdx++) {
    look = obj->look + lookIdx;
    /* earlier version of limn/test/soid used (0.2,0.8,0.0), I think.
       Now we assume that any useful shading is happening in the emap */
    ELL_3V_SET(look->kads, 0.2, 0.8, 0);
  }

  if (limnObjectRender(obj, cam, win)
      || (concave
          ? limnObjectPSDrawConcave(obj, cam, nmap, win)
          : limnObjectPSDraw(obj, cam, nmap, win))) {
    airMopAdd(mop, err = biffGetDone(LIMN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }
  fclose(win->file);

  if (describe) {
    fprintf(stdout, "----------------- POST-RENDER -----------------\n");
    limnObjectDescribe(stdout, obj);
    fprintf(stdout, "----------------- POST-RENDER -----------------\n");
  }

  airMopOkay(mop);
  return 0;
}
Ejemplo n.º 7
0
int
main(int argc, char *argv[]) {
    char *me, *err, *outS;
    limnCamera *cam;
    float matA[16], matB[16], winscale, edgeWidth[5];
    hestOpt *hopt=NULL;
    airArray *mop;
    limnObject *obj;
    limnLook *look;
    int lookIdx;
    limnWindow *win;
    int partIdx, wire, concave;
    Nrrd *nmap;

    mop = airMopNew();
    cam = limnCameraNew();
    airMopAdd(mop, cam, (airMopper)limnCameraNix, airMopAlways);

    me = argv[0];
    hestOptAdd(&hopt, "fr", "from point", airTypeDouble, 3, 3, cam->from,"4 4 4",
               "position of camera, used to determine view vector");
    hestOptAdd(&hopt, "at", "at point", airTypeDouble, 3, 3, cam->at, "0 0 0",
               "camera look-at point, used to determine view vector");
    hestOptAdd(&hopt, "up", "up vector", airTypeDouble, 3, 3, cam->up, "0 0 1",
               "camera pseudo-up vector, used to determine view coordinates");
    hestOptAdd(&hopt, "rh", NULL, airTypeInt, 0, 0, &(cam->rightHanded), NULL,
               "use a right-handed UVN frame (V points down)");
    hestOptAdd(&hopt, "or", NULL, airTypeInt, 0, 0, &(cam->orthographic), NULL,
               "use orthogonal projection");
    hestOptAdd(&hopt, "ur", "uMin uMax", airTypeDouble, 2, 2, cam->uRange,
               "-1 1", "range in U direction of image plane");
    hestOptAdd(&hopt, "vr", "vMin vMax", airTypeDouble, 2, 2, cam->vRange,
               "-1 1", "range in V direction of image plane");
    hestOptAdd(&hopt, "e", "envmap", airTypeOther, 1, 1, &nmap, NULL,
               "16checker-based environment map",
               NULL, NULL, nrrdHestNrrd);
    hestOptAdd(&hopt, "ws", "winscale", airTypeFloat, 1, 1, &winscale,
               "200", "world to points (PostScript) scaling");
    hestOptAdd(&hopt, "wire", NULL, airTypeInt, 0, 0, &wire, NULL,
               "just do wire-frame rendering");
    hestOptAdd(&hopt, "concave", NULL, airTypeInt, 0, 0, &concave, NULL,
               "use slightly buggy rendering method suitable for "
               "concave or self-occluding objects");
    hestOptAdd(&hopt, "wd", "5 widths", airTypeFloat, 5, 5, edgeWidth,
               "0.0 0.0 3.0 2.0 0.0",
               "width of edges drawn for five kinds of "
               "edges: back non-crease, back crease, "
               "silohuette, front crease, front non-crease");
    hestOptAdd(&hopt, "o", "output PS", airTypeString, 1, 1, &outS, "out.ps",
               "output file to render postscript into");
    hestParseOrDie(hopt, argc-1, argv+1, NULL,
                   me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
    airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
    airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

    cam->neer = -0.000000001;
    cam->dist = 0;
    cam->faar = 0.0000000001;
    cam->atRelative = AIR_TRUE;

    if (limnCameraUpdate(cam)) {
        fprintf(stderr, "%s: trouble:\n%s\n", me, err = biffGet(LIMN));
        free(err);
        return 1;
    }
    obj = limnObjectNew(10, AIR_TRUE);
    airMopAdd(mop, obj, (airMopper)limnObjectNix, airMopAlways);

    /* create limnLooks for diffuse (#0) and flat (#1) shading */
    lookIdx = airArrayLenIncr(obj->lookArr, 2);
    look = obj->look + lookIdx + 0;
    ELL_4V_SET(look->rgba, 1, 1, 1, 1);
    ELL_3V_SET(look->kads, 0, 1, 0);
    look->spow = 0;
    look = obj->look + lookIdx + 1;
    ELL_4V_SET(look->rgba, 1, 1, 1, 1);
    ELL_3V_SET(look->kads, 1, 0, 0);
    look->spow = 0;

    /* X axis: rod */
    partIdx = limnObjectCylinderAdd(obj, 0, 0, 16);
    ELL_4M_IDENTITY_SET(matA);
    ELL_4M_SCALE_SET(matB, 1, 0.2, 0.2);
    ell_4m_post_mul_f(matA, matB);
    ELL_4M_TRANSLATE_SET(matB, 1.3, 0.0, 0.0);
    ell_4m_post_mul_f(matA, matB);
    limnObjectPartTransform(obj, partIdx, matA);

    /* Y axis: rod + ball */
    partIdx = limnObjectCylinderAdd(obj, 0, 1, 16);
    ELL_4M_IDENTITY_SET(matA);
    ELL_4M_SCALE_SET(matB, 0.2, 1, 0.2);
    ell_4m_post_mul_f(matA, matB);
    ELL_4M_TRANSLATE_SET(matB, 0.0, 1.3, 0.0);
    ell_4m_post_mul_f(matA, matB);
    limnObjectPartTransform(obj, partIdx, matA);

    partIdx = limnObjectPolarSphereAdd(obj, 0, 0, 32, 16);
    ELL_4M_IDENTITY_SET(matA);
    ELL_4M_SCALE_SET(matB, 0.28, 0.28, 0.28);
    ell_4m_post_mul_f(matA, matB);
    ELL_4M_TRANSLATE_SET(matB, 0.0, 2.6, 0.0);
    ell_4m_post_mul_f(matA, matB);
    limnObjectPartTransform(obj, partIdx, matA);

    /* Z axis: rod + ball + ball */
    partIdx = limnObjectCylinderAdd(obj, 0, 2, 16);
    ELL_4M_IDENTITY_SET(matA);
    ELL_4M_SCALE_SET(matB, 0.2, 0.2, 1);
    ell_4m_post_mul_f(matA, matB);
    ELL_4M_TRANSLATE_SET(matB, 0.0, 0.0, 1.3);
    ell_4m_post_mul_f(matA, matB);
    limnObjectPartTransform(obj, partIdx, matA);

    partIdx = limnObjectPolarSphereAdd(obj, 0, 1, 32, 16);
    ELL_4M_IDENTITY_SET(matA);
    ELL_4M_SCALE_SET(matB, 0.28, 0.28, 0.28);
    ell_4m_post_mul_f(matA, matB);
    ELL_4M_TRANSLATE_SET(matB, 0.0, 0.0, 2.6);
    ell_4m_post_mul_f(matA, matB);
    limnObjectPartTransform(obj, partIdx, matA);

    partIdx = limnObjectPolarSphereAdd(obj, 0, 2, 32, 16);
    ELL_4M_IDENTITY_SET(matA);
    ELL_4M_SCALE_SET(matB, 0.28, 0.28, 0.28);
    ell_4m_post_mul_f(matA, matB);
    ELL_4M_TRANSLATE_SET(matB, 0.0, 0.0, 3.2);
    ell_4m_post_mul_f(matA, matB);
    limnObjectPartTransform(obj, partIdx, matA);

    win = limnWindowNew(limnDevicePS);
    win->scale = winscale;
    win->ps.wireFrame = wire;
    win->ps.lineWidth[limnEdgeTypeBackFacet] = edgeWidth[0];
    win->ps.lineWidth[limnEdgeTypeBackCrease] = edgeWidth[1];
    win->ps.lineWidth[limnEdgeTypeContour] = edgeWidth[2];
    win->ps.lineWidth[limnEdgeTypeFrontCrease] = edgeWidth[3];
    win->ps.lineWidth[limnEdgeTypeFrontFacet] = edgeWidth[4];

    win->file = fopen(outS, "w");
    airMopAdd(mop, win, (airMopper)limnWindowNix, airMopAlways);

    if (limnObjectRender(obj, cam, win)
            || (concave
                ? limnObjectPSDrawConcave(obj, cam, nmap, win)
                : limnObjectPSDraw(obj, cam, nmap, win))) {
        airMopAdd(mop, err = biffGetDone(LIMN), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble:\n%s\n", me, err);
        airMopError(mop);
        return 1;
    }
    fclose(win->file);

    airMopOkay(mop);
    return 0;
}