int miteRenderBegin(miteRender **mrrP, miteUser *muu) { static const char me[]="miteRenderBegin"; gagePerVolume *pvl; int E, T, pvlIdx; gageQuery queryScl, queryVec, queryTen; gageItemSpec isp; unsigned int axi, thr; if (!(mrrP && muu)) { biffAddf(MITE, "%s: got NULL pointer", me); return 1; } if (_miteUserCheck(muu)) { biffAddf(MITE, "%s: problem with user-set parameters", me); return 1; } if (!( *mrrP = _miteRenderNew() )) { biffAddf(MITE, "%s: couldn't alloc miteRender", me); return 1; } if (_miteNtxfAlphaAdjust(*mrrP, muu)) { biffAddf(MITE, "%s: trouble copying and alpha-adjusting txfs", me); return 1; } GAGE_QUERY_RESET(queryScl); GAGE_QUERY_RESET(queryVec); GAGE_QUERY_RESET(queryTen); GAGE_QUERY_RESET((*mrrP)->queryMite); for (T=0; T<muu->ntxfNum; T++) { for (axi=1; axi<muu->ntxf[T]->dim; axi++) { miteVariableParse(&isp, muu->ntxf[T]->axis[axi].label); miteQueryAdd(queryScl, queryVec, queryTen, (*mrrP)->queryMite, &isp); } } miteVariableParse((*mrrP)->normalSpec, muu->normalStr); miteQueryAdd(queryScl, queryVec, queryTen, (*mrrP)->queryMite, (*mrrP)->normalSpec); miteShadeSpecParse((*mrrP)->shadeSpec, muu->shadeStr); miteShadeSpecQueryAdd(queryScl, queryVec, queryTen, (*mrrP)->queryMite, (*mrrP)->shadeSpec); (*mrrP)->queryMiteNonzero = GAGE_QUERY_NONZERO((*mrrP)->queryMite); E = 0; pvlIdx = 0; if (muu->nsin) { if (!E) E |= !(pvl = gagePerVolumeNew(muu->gctx0, muu->nsin, gageKindScl)); if (!E) E |= gageQuerySet(muu->gctx0, pvl, queryScl); if (!E) E |= gagePerVolumeAttach(muu->gctx0, pvl); if (!E) (*mrrP)->sclPvlIdx = pvlIdx++; } if (muu->nvin) { if (!E) E |= !(pvl = gagePerVolumeNew(muu->gctx0, muu->nvin, gageKindVec)); if (!E) E |= gageQuerySet(muu->gctx0, pvl, queryVec); if (!E) E |= gagePerVolumeAttach(muu->gctx0, pvl); if (!E) (*mrrP)->vecPvlIdx = pvlIdx++; } if (muu->ntin) { if (!E) E |= !(pvl = gagePerVolumeNew(muu->gctx0, muu->ntin, tenGageKind)); if (!E) E |= gageQuerySet(muu->gctx0, pvl, queryTen); if (!E) E |= gagePerVolumeAttach(muu->gctx0, pvl); if (!E) (*mrrP)->tenPvlIdx = pvlIdx++; } if (!E) E |= gageKernelSet(muu->gctx0, gageKernel00, muu->ksp[gageKernel00]->kernel, muu->ksp[gageKernel00]->parm); if (!E) E |= gageKernelSet(muu->gctx0, gageKernel11, muu->ksp[gageKernel11]->kernel, muu->ksp[gageKernel11]->parm); if (!E) E |= gageKernelSet(muu->gctx0, gageKernel22, muu->ksp[gageKernel22]->kernel, muu->ksp[gageKernel22]->parm); if (!E) E |= gageUpdate(muu->gctx0); if (E) { biffMovef(MITE, GAGE, "%s: gage trouble", me); return 1; } fprintf(stderr, "!%s: kernel support = %d^3 samples\n", me, 2*muu->gctx0->radius); if (nrrdMaybeAlloc_va(muu->nout, mite_nt, 3, AIR_CAST(size_t, 5) /* RGBAZ */ , AIR_CAST(size_t, muu->hctx->imgSize[0]), AIR_CAST(size_t, muu->hctx->imgSize[1]))) { biffMovef(MITE, NRRD, "%s: nrrd trouble", me); return 1; } muu->nout->axis[1].center = nrrdCenterCell; muu->nout->axis[1].min = muu->hctx->cam->uRange[0]; muu->nout->axis[1].max = muu->hctx->cam->uRange[1]; muu->nout->axis[2].center = nrrdCenterCell; muu->nout->axis[2].min = muu->hctx->cam->vRange[0]; muu->nout->axis[2].max = muu->hctx->cam->vRange[1]; for (thr=0; thr<muu->hctx->numThreads; thr++) { (*mrrP)->tt[thr] = miteThreadNew(); if (!((*mrrP)->tt[thr])) { biffAddf(MITE, "%s: couldn't allocate thread[%d]", me, thr); return 1; } airMopAdd((*mrrP)->rmop, (*mrrP)->tt[thr], (airMopper)miteThreadNix, airMopAlways); } (*mrrP)->time0 = airTime(); return 0; }
/* ** _miteStageSet ** ** ALLOCATES and initializes stage array in a miteThread */ int _miteStageSet(miteThread *mtt, miteRender *mrr) { static const char me[]="_miteStageSet"; char *value; int ni, di, stageIdx, rii, stageNum, ilog2; Nrrd *ntxf; miteStage *stage; gageItemSpec isp; char rc; stageNum = _miteStageNum(mrr); /* fprintf(stderr, "!%s: stageNum = %d\n", me, stageNum); */ mtt->stage = AIR_CALLOC(stageNum, miteStage); if (!mtt->stage) { biffAddf(MITE, "%s: couldn't alloc array of %d stages", me, stageNum); return 1; } airMopAdd(mtt->rmop, mtt->stage, airFree, airMopAlways); mtt->stageNum = stageNum; stageIdx = 0; for (ni=0; ni<mrr->ntxfNum; ni++) { ntxf = mrr->ntxf[ni]; for (di=ntxf->dim-1; di>=1; di--) { stage = mtt->stage + stageIdx; _miteStageInit(stage); miteVariableParse(&isp, ntxf->axis[di].label); stage->val = _miteAnswerPointer(mtt, &isp); stage->label = ntxf->axis[di].label; /* fprintf(stderr, "!%s: ans=%p + offset[%d]=%d == %p\n", me, mtt->ans, dom, kind->ansOffset[dom], stage->val); */ stage->size = ntxf->axis[di].size; stage->min = ntxf->axis[di].min; stage->max = ntxf->axis[di].max; if (di > 1) { stage->data = NULL; } else { stage->data = (mite_t *)ntxf->data; value = nrrdKeyValueGet(ntxf, "miteStageOp"); if (value) { stage->op = airEnumVal(miteStageOp, value); if (miteStageOpUnknown == stage->op) { stage->op = miteStageOpMultiply; } } else { stage->op = miteStageOpMultiply; } if (1 == isp.kind->table[isp.item].answerLength) { stage->qn = NULL; } else if (3 == isp.kind->table[isp.item].answerLength) { char stmp[AIR_STRLEN_SMALL]; ilog2 = airLog2(ntxf->axis[di].size); switch(ilog2) { case 8: stage->qn = limnVtoQN_d[ limnQN8octa]; break; case 9: stage->qn = limnVtoQN_d[ limnQN9octa]; break; case 10: stage->qn = limnVtoQN_d[limnQN10octa]; break; case 11: stage->qn = limnVtoQN_d[limnQN11octa]; break; case 12: stage->qn = limnVtoQN_d[limnQN12octa]; break; case 13: stage->qn = limnVtoQN_d[limnQN13octa]; break; case 14: stage->qn = limnVtoQN_d[limnQN14octa]; break; case 15: stage->qn = limnVtoQN_d[limnQN15octa]; break; case 16: stage->qn = limnVtoQN_d[limnQN16octa]; break; default: biffAddf(MITE, "%s: txf axis %d size %s not usable for " "vector txf domain variable %s", me, di, airSprintSize_t(stmp, ntxf->axis[di].size), ntxf->axis[di].label); return 1; break; } } else { biffAddf(MITE, "%s: %s not scalar or vector (len = %d): can't be " "a txf domain variable", me, ntxf->axis[di].label, isp.kind->table[isp.item].answerLength); return 1; } stage->rangeNum = ntxf->axis[0].size; for (rii=0; rii<stage->rangeNum; rii++) { rc = ntxf->axis[0].label[rii]; stage->rangeIdx[rii] = strchr(miteRangeChar, rc) - miteRangeChar; /* fprintf(stderr, "!%s: range: %c -> %d\n", "_miteStageSet", ntxf->axis[0].label[rii], stage->rangeIdx[rii]); */ } } stageIdx++; } } return 0; }
/* ******** miteShadeSpecParse ** ** set up a miteShadeSpec based on a string. Valid forms are: ** ** none ** phong:<vector> ** litten:<vector>,<vector>,<scalar>,<scalar> ** ** where <vector> and <scalar> are specifications of 3-vector and scalar ** parsable by miteVariableParse */ int miteShadeSpecParse(miteShadeSpec *shpec, char *shadeStr) { static const char me[]="miteShadeSpecParse"; char *buff, *qstr, *tok, *state; airArray *mop; int ansLength; mop = airMopNew(); if (!( shpec && airStrlen(shadeStr) )) { biffAddf(MITE, "%s: got NULL pointer and/or empty string", me); airMopError(mop); return 1; } buff = airToLower(airStrdup(shadeStr)); if (!buff) { biffAddf(MITE, "%s: couldn't strdup shading spec", me); airMopError(mop); return 1; } airMopAdd(mop, buff, airFree, airMopAlways); shpec->method = miteShadeMethodUnknown; if (!strcmp("none", buff)) { shpec->method = miteShadeMethodNone; } else if (buff == strstr(buff, "phong:")) { shpec->method = miteShadeMethodPhong; qstr = buff + strlen("phong:"); if (miteVariableParse(shpec->vec0, qstr)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as shading vector", me, qstr); airMopError(mop); return 1; } ansLength = shpec->vec0->kind->table[shpec->vec0->item].answerLength; if (3 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a vector (answer length is %d, not 3)", me, qstr, ansLength); airMopError(mop); return 1; } shpec->method = miteShadeMethodPhong; } else if (buff == strstr(buff, "litten:")) { qstr = buff + strlen("litten:"); /* ---- first vector */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->vec0, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as first lit-tensor vector", me, tok); airMopError(mop); return 1; } ansLength = shpec->vec0->kind->table[shpec->vec0->item].answerLength; if (3 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a vector (answer length is %d, not 3)", me, qstr, ansLength); airMopError(mop); return 1; } /* ---- second vector */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->vec1, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as second lit-tensor vector", me, tok); airMopError(mop); return 1; } ansLength = shpec->vec1->kind->table[shpec->vec1->item].answerLength; if (3 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a vector (answer length is %d, not 3)", me, qstr, ansLength); airMopError(mop); return 1; } /* ---- first scalar */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->scl0, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as first lit-tensor scalar", me, tok); airMopError(mop); return 1; } ansLength = shpec->scl0->kind->table[shpec->scl0->item].answerLength; if (1 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a scalar (answer length is %d, not 1)", me, qstr, ansLength); airMopError(mop); return 1; } /* ---- second scalar */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->scl1, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as second lit-tensor scalar", me, tok); airMopError(mop); return 1; } ansLength = shpec->scl1->kind->table[shpec->scl1->item].answerLength; if (1 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a scalar (answer length is %d, not 1)", me, qstr, ansLength); airMopError(mop); return 1; } shpec->method = miteShadeMethodLitTen; } else { biffAddf(MITE, "%s: shading specification \"%s\" not understood", me, shadeStr); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
int miteNtxfCheck(const Nrrd *ntxf) { static const char me[]="miteNtxfCheck"; char *rangeStr, *domStr; gageItemSpec isp; unsigned int rii, axi; int ilog2; if (nrrdCheck(ntxf)) { biffMovef(MITE, NRRD, "%s: basic nrrd validity check failed", me); return 1; } if (!( nrrdTypeFloat == ntxf->type || nrrdTypeDouble == ntxf->type || nrrdTypeUChar == ntxf->type )) { biffAddf(MITE, "%s: need a type %s, %s or %s nrrd (not %s)", me, airEnumStr(nrrdType, nrrdTypeFloat), airEnumStr(nrrdType, nrrdTypeDouble), airEnumStr(nrrdType, nrrdTypeUChar), airEnumStr(nrrdType, ntxf->type)); return 1; } if (!( 2 <= ntxf->dim )) { biffAddf(MITE, "%s: nrrd dim (%d) isn't at least 2 (for a 1-D txf)", me, ntxf->dim); return 1; } rangeStr = ntxf->axis[0].label; if (0 == airStrlen(rangeStr)) { biffAddf(MITE, "%s: axis[0]'s label doesn't specify txf range", me); return 1; } if (airStrlen(rangeStr) != ntxf->axis[0].size) { char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL]; biffAddf(MITE, "%s: axis[0]'s size %s, but label specifies %s values", me, airSprintSize_t(stmp1, ntxf->axis[0].size), airSprintSize_t(stmp2, airStrlen(rangeStr))); return 1; } for (rii=0; rii<airStrlen(rangeStr); rii++) { if (!strchr(miteRangeChar, rangeStr[rii])) { biffAddf(MITE, "%s: char %d of axis[0]'s label (\"%c\") isn't a valid " "transfer function range specifier (not in \"%s\")", me, rii, rangeStr[rii], miteRangeChar); return 1; } } for (axi=1; axi<ntxf->dim; axi++) { if (1 == ntxf->axis[axi].size) { biffAddf(MITE, "%s: # samples on axis %d must be > 1", me, axi); return 1; } domStr = ntxf->axis[axi].label; if (0 == airStrlen(domStr)) { biffAddf(MITE, "%s: axis[%d] of txf didn't specify a domain variable", me, axi); return 1; } if (miteVariableParse(&isp, domStr)) { biffAddf(MITE, "%s: couldn't parse txf domain \"%s\" for axis %d\n", me, domStr, axi); return 1; } if (!( 1 == isp.kind->table[isp.item].answerLength || 3 == isp.kind->table[isp.item].answerLength )) { biffAddf(MITE, "%s: %s (item %d) not a scalar or vector " "(answerLength = %d): " "can't be a txf domain variable", me, domStr, isp.item, isp.kind->table[isp.item].answerLength); return 1; } if (3 == isp.kind->table[isp.item].answerLength) { /* has to be right length for one of the quantization schemes */ ilog2 = airLog2(ntxf->axis[axi].size); if (-1 == ilog2) { char stmp[AIR_STRLEN_SMALL]; biffAddf(MITE, "%s: txf axis size for %s must be power of 2 (not %s)", me, domStr, airSprintSize_t(stmp, ntxf->axis[axi].size)); return 1; } else { if (!( AIR_IN_CL(8, ilog2, 16) )) { biffAddf(MITE, "%s: log_2 of txf axis size for %s should be in " "range [8,16] (not %d)", me, domStr, ilog2); return 1; } } } else { if (!( AIR_EXISTS(ntxf->axis[axi].min) && AIR_EXISTS(ntxf->axis[axi].max) )) { biffAddf(MITE, "%s: min and max of axis %d aren't both set", me, axi); return 1; } if (!( ntxf->axis[axi].min < ntxf->axis[axi].max )) { biffAddf(MITE, "%s: min (%g) not less than max (%g) on axis %d", me, ntxf->axis[axi].min, ntxf->axis[axi].max, axi); return 1; } } } return 0; }
int _miteUserCheck(miteUser *muu) { char me[]="miteUserCheck", err[BIFF_STRLEN]; int T, gotOpac; gageItemSpec isp; gageQuery queryScl, queryVec, queryTen, queryMite; miteShadeSpec *shpec; airArray *mop; unsigned int axi; if (!muu) { sprintf(err, "%s: got NULL pointer", me); biffAdd(MITE, err); return 1; } mop = airMopNew(); if (!( muu->ntxfNum >= 1 )) { sprintf(err, "%s: need at least one transfer function", me); biffAdd(MITE, err); airMopError(mop); return 1; } gotOpac = AIR_FALSE; GAGE_QUERY_RESET(queryScl); GAGE_QUERY_RESET(queryVec); GAGE_QUERY_RESET(queryTen); GAGE_QUERY_RESET(queryMite); /* not actually used here */ /* add on all queries associated with transfer functions */ for (T=0; T<muu->ntxfNum; T++) { if (miteNtxfCheck(muu->ntxf[T])) { sprintf(err, "%s: ntxf[%d] (%d of %d) can't be used as a txf", me, T, T+1, muu->ntxfNum); biffAdd(MITE, err); airMopError(mop); return 1; } /* NOTE: no error checking because miteNtxfCheck succeeded */ for (axi=1; axi<muu->ntxf[T]->dim; axi++) { miteVariableParse(&isp, muu->ntxf[T]->axis[axi].label); miteQueryAdd(queryScl, queryVec, queryTen, queryMite, &isp); } gotOpac |= !!strchr(muu->ntxf[T]->axis[0].label, 'A'); } if (!gotOpac) { fprintf(stderr, "\n\n%s: ****************************************" "************************\n", me); fprintf(stderr, "%s: !!! WARNING !!! opacity (\"A\") not set " "by any transfer function\n", me); fprintf(stderr, "%s: ****************************************" "************************\n\n\n", me); } /* add on "normal"-based queries */ if (airStrlen(muu->normalStr)) { miteVariableParse(&isp, muu->normalStr); if (miteValGageKind == isp.kind) { sprintf(err, "%s: normalStr \"%s\" refers to a miteVal " "(normal must be data-intrinsic)", me, muu->normalStr); biffAdd(MITE, err); airMopError(mop); return 1; } if (3 != isp.kind->table[isp.item].answerLength) { sprintf(err, "%s: %s not a vector: can't be used as normal", me, muu->normalStr); biffAdd(MITE, err); return 1; } miteQueryAdd(queryScl, queryVec, queryTen, queryMite, &isp); } /* add on shading-based queries */ shpec = miteShadeSpecNew(); airMopAdd(mop, shpec, (airMopper)miteShadeSpecNix, airMopAlways); if (miteShadeSpecParse(shpec, muu->shadeStr)) { sprintf(err, "%s: couldn't parse shading spec \"%s\"", me, muu->shadeStr); biffAdd(MITE, err); airMopError(mop); return 1; } miteShadeSpecQueryAdd(queryScl, queryVec, queryTen, queryMite, shpec); /* see if anyone asked for an unspecified normal */ if ((GAGE_QUERY_ITEM_TEST(queryMite, miteValNdotV) || GAGE_QUERY_ITEM_TEST(queryMite, miteValNdotL) || GAGE_QUERY_ITEM_TEST(queryMite, miteValVrefN)) && !airStrlen(muu->normalStr)) { sprintf(err, "%s: txf or shading requested a miteVal's use of the " "\"normal\", but one has not been specified in muu->normalStr", me); biffAdd(MITE, err); airMopError(mop); return 1; } /* see if we have volumes for requested queries */ if (GAGE_QUERY_NONZERO(queryScl) && !(muu->nsin)) { sprintf(err, "%s: txf or shading require %s volume, but don't have one", me, gageKindScl->name); biffAdd(MITE, err); airMopError(mop); return 1; } if (GAGE_QUERY_NONZERO(queryVec) && !(muu->nvin)) { sprintf(err, "%s: txf or shading require %s volume, but don't have one", me, gageKindVec->name); biffAdd(MITE, err); airMopError(mop); return 1; } if (GAGE_QUERY_NONZERO(queryTen) && !(muu->ntin)) { sprintf(err, "%s: txf or shading require %s volume, but don't have one", me, tenGageKind->name); biffAdd(MITE, err); airMopError(mop); return 1; } /* check appropriateness of given volumes */ if (muu->nsin) { if (gageVolumeCheck(muu->gctx0, muu->nsin, gageKindScl)) { sprintf(err, "%s: trouble with input %s volume", me, gageKindScl->name); biffMove(MITE, err, GAGE); airMopError(mop); return 1; } } if (muu->nvin) { if (gageVolumeCheck(muu->gctx0, muu->nvin, gageKindVec)) { sprintf(err, "%s: trouble with input %s volume", me, gageKindVec->name); biffMove(MITE, err, GAGE); airMopError(mop); return 1; } } if (muu->ntin) { if (gageVolumeCheck(muu->gctx0, muu->ntin, tenGageKind)) { sprintf(err, "%s: trouble with input %s volume", me, tenGageKind->name); biffMove(MITE, err, GAGE); airMopError(mop); return 1; } } if (!muu->nout) { sprintf(err, "%s: rendered image nrrd is NULL", me); biffAdd(MITE, err); airMopError(mop); return 1; } airMopOkay(mop); return 0; }