int main(int argc, char *argv[]) { char *me; hestOpt *hopt=NULL; airArray *mop; pushEnergySpec *ensp; unsigned int pi, xi, nn; double xx, supp, del; mop = airMopNew(); me = argv[0]; hestOptAdd(&hopt, "energy", "spec", airTypeOther, 1, 1, &ensp, NULL, "specification of force function to use", NULL, NULL, pushHestEnergySpec); 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); fprintf(stderr, "%s: parsed energy \"%s\", with %u parms.\n", me, ensp->energy->name, ensp->energy->parmNum); for (pi=0; pi<ensp->energy->parmNum; pi++) { fprintf(stderr, "%u: %g\n", pi, ensp->parm[pi]); } fprintf(stderr, "\n"); nn = 600; supp = ensp->energy->support(ensp->parm); del = AIR_DELTA(0, 2, nn, 0, supp); for (xi=1; xi<nn; xi++) { double x0, x1, ee, ff, e0, e1, dummy; xx = AIR_AFFINE(0, xi, nn, 0, supp); x1 = AIR_AFFINE(0, xi+1, nn, 0, supp); x0 = AIR_AFFINE(0, xi-1, nn, 0, supp); ensp->energy->eval(&e1, &dummy, x1, ensp->parm); ensp->energy->eval(&e0, &dummy, x0, ensp->parm); ensp->energy->eval(&ee, &ff, xx, ensp->parm); printf("%g %g %g %g\n", xx, ee, ff, (e1 - e0)/del); } airMopOkay(mop); return 0; }
void * _hooverThreadBody(void *_arg) { _hooverThreadArg *arg; void *thread; int ret, /* to catch return values from callbacks */ sampleI, /* which sample we're on */ inside, /* we're inside the volume */ vI, uI; /* integral coords in image */ double tmp, mm, /* lowest position in index space, for all axes */ Mx, My, Mz, /* highest position in index space on each axis */ u, v, /* floating-point coords in image */ uvScale, /* how to scale (u,v) to go from image to near plane, according to ortho or perspective */ lx, ly, lz, /* half edge-lengths of volume */ rayLen=0, /* length of segment formed by ray line intersecting the near and far clipping planes */ rayT, /* current position along ray (world-space) */ rayDirW[3], /* unit-length ray direction (world-space) */ rayDirI[3], /* rayDirW transformed into index space; not unit length, but a unit change in world space along rayDirW translates to this change in index space along rayDirI */ rayPosW[3], /* current ray location (world-space) */ rayPosI[3], /* current ray location (index-space) */ rayStartW[3], /* ray start on near plane (world-space) */ rayStartI[3], /* ray start on near plane (index-space) */ rayStep, /* distance between samples (world-space) */ vOff[3], uOff[3]; /* offsets in arg->ec->wU and arg->ec->wV directions towards start of ray */ arg = (_hooverThreadArg *)_arg; if ( (ret = (arg->ctx->threadBegin)(&thread, arg->render, arg->ctx->user, arg->whichThread)) ) { arg->errCode = ret; arg->whichErr = hooverErrThreadBegin; return arg; } lx = arg->ec->volHLen[0]; ly = arg->ec->volHLen[1]; lz = arg->ec->volHLen[2]; if (nrrdCenterNode == arg->ctx->volCentering) { mm = 0; Mx = arg->ctx->volSize[0]-1; My = arg->ctx->volSize[1]-1; Mz = arg->ctx->volSize[2]-1; } else { mm = -0.5; Mx = arg->ctx->volSize[0]-0.5; My = arg->ctx->volSize[1]-0.5; Mz = arg->ctx->volSize[2]-0.5; } if (arg->ctx->cam->orthographic) { ELL_3V_COPY(rayDirW, arg->ctx->cam->N); rayDirI[0] = AIR_DELTA(-lx, rayDirW[0], lx, mm, Mx); rayDirI[1] = AIR_DELTA(-ly, rayDirW[1], ly, mm, My); rayDirI[2] = AIR_DELTA(-lz, rayDirW[2], lz, mm, Mz); rayLen = arg->ctx->cam->vspFaar - arg->ctx->cam->vspNeer; uvScale = 1.0; } else { uvScale = arg->ctx->cam->vspNeer/arg->ctx->cam->vspDist; } while (1) { /* the work assignment is simply the next scanline to be rendered: the result of all this is setting vI */ if (arg->ctx->workMutex) { airThreadMutexLock(arg->ctx->workMutex); } vI = arg->ctx->workIdx; if (arg->ctx->workIdx < arg->ctx->imgSize[1]) { arg->ctx->workIdx += 1; } if (arg->ctx->workMutex) { airThreadMutexUnlock(arg->ctx->workMutex); } if (vI == arg->ctx->imgSize[1]) { /* we're done! */ break; } if (nrrdCenterCell == arg->ctx->imgCentering) { v = uvScale*AIR_AFFINE(-0.5, vI, arg->ctx->imgSize[1]-0.5, arg->ctx->cam->vRange[0], arg->ctx->cam->vRange[1]); } else { v = uvScale*AIR_AFFINE(0.0, vI, arg->ctx->imgSize[1]-1.0, arg->ctx->cam->vRange[0], arg->ctx->cam->vRange[1]); } ELL_3V_SCALE(vOff, v, arg->ctx->cam->V); for (uI=0; uI<arg->ctx->imgSize[0]; uI++) { if (nrrdCenterCell == arg->ctx->imgCentering) { u = uvScale*AIR_AFFINE(-0.5, uI, arg->ctx->imgSize[0]-0.5, arg->ctx->cam->uRange[0], arg->ctx->cam->uRange[1]); } else { u = uvScale*AIR_AFFINE(0.0, uI, arg->ctx->imgSize[0]-1.0, arg->ctx->cam->uRange[0], arg->ctx->cam->uRange[1]); } ELL_3V_SCALE(uOff, u, arg->ctx->cam->U); ELL_3V_ADD3(rayStartW, uOff, vOff, arg->ec->rayZero); rayStartI[0] = AIR_AFFINE(-lx, rayStartW[0], lx, mm, Mx); rayStartI[1] = AIR_AFFINE(-ly, rayStartW[1], ly, mm, My); rayStartI[2] = AIR_AFFINE(-lz, rayStartW[2], lz, mm, Mz); if (!arg->ctx->cam->orthographic) { ELL_3V_SUB(rayDirW, rayStartW, arg->ctx->cam->from); ELL_3V_NORM(rayDirW, rayDirW, tmp); rayDirI[0] = AIR_DELTA(-lx, rayDirW[0], lx, mm, Mx); rayDirI[1] = AIR_DELTA(-ly, rayDirW[1], ly, mm, My); rayDirI[2] = AIR_DELTA(-lz, rayDirW[2], lz, mm, Mz); rayLen = ((arg->ctx->cam->vspFaar - arg->ctx->cam->vspNeer)/ ELL_3V_DOT(rayDirW, arg->ctx->cam->N)); } if ( (ret = (arg->ctx->rayBegin)(thread, arg->render, arg->ctx->user, uI, vI, rayLen, rayStartW, rayStartI, rayDirW, rayDirI)) ) { arg->errCode = ret; arg->whichErr = hooverErrRayBegin; return arg; } sampleI = 0; rayT = 0; while (1) { ELL_3V_SCALE_ADD2(rayPosW, 1.0, rayStartW, rayT, rayDirW); ELL_3V_SCALE_ADD2(rayPosI, 1.0, rayStartI, rayT, rayDirI); inside = (AIR_IN_CL(mm, rayPosI[0], Mx) && AIR_IN_CL(mm, rayPosI[1], My) && AIR_IN_CL(mm, rayPosI[2], Mz)); rayStep = (arg->ctx->sample)(thread, arg->render, arg->ctx->user, sampleI, rayT, inside, rayPosW, rayPosI); if (!AIR_EXISTS(rayStep)) { /* sampling failed */ arg->errCode = 0; arg->whichErr = hooverErrSample; return arg; } if (!rayStep) { /* ray decided to finish itself */ break; } /* else we moved to a new location along the ray */ rayT += rayStep; if (!AIR_IN_CL(0, rayT, rayLen)) { /* ray stepped outside near-far clipping region, its done. */ break; } sampleI++; } if ( (ret = (arg->ctx->rayEnd)(thread, arg->render, arg->ctx->user)) ) { arg->errCode = ret; arg->whichErr = hooverErrRayEnd; return arg; } } /* end this scanline */ } /* end while(1) assignment of scanlines */ if ( (ret = (arg->ctx->threadEnd)(thread, arg->render, arg->ctx->user)) ) { arg->errCode = ret; arg->whichErr = hooverErrThreadEnd; return arg; } /* returning NULL actually indicates that there was NOT an error */ return NULL; }