int main(int argc, char *argv[]) { Nrrd *map, *ppm; NrrdRange *range; AIR_UNUSED(argc); me = argv[0]; if (limnEnvMapFill(map=nrrdNew(), cb, limnQN16checker, NULL)) { fprintf(stderr, "%s: trouble:\n%s", me, biffGet(LIMN)); exit(1); } range = nrrdRangeNew(0, 1); if (nrrdQuantize(ppm=nrrdNew(), map, range, 8)) { fprintf(stderr, "%s: trouble:\n%s", me, biffGet(NRRD)); exit(1); } if (nrrdSave("map.ppm", ppm, NULL)) { fprintf(stderr, "%s: trouble:\n%s", me, biffGet(NRRD)); exit(1); } nrrdNuke(map); nrrdNuke(ppm); nrrdRangeNix(range); exit(0); }
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); } } }