GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/bin/miter.c Lines: 0 158 0.0 %
Date: 2017-05-26 Branches: 0 42 0.0 %

Line Branch Exec Source
1
/*
2
  Teem: Tools to process and visualize scientific data and images             .
3
  Copyright (C) 2013, 2012, 2011, 2010, 2009  University of Chicago
4
  Copyright (C) 2008, 2007, 2006, 2005  Gordon Kindlmann
5
  Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998  University of Utah
6
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public License
9
  (LGPL) as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
  The terms of redistributing and/or modifying this software also
12
  include exceptions to the LGPL that facilitate static linking.
13
14
  This library is distributed in the hope that it will be useful,
15
  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
  Lesser General Public License for more details.
18
19
  You should have received a copy of the GNU Lesser General Public License
20
  along with this library; if not, write to Free Software Foundation, Inc.,
21
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
*/
23
24
#include <teem/air.h>
25
#include <teem/biff.h>
26
#include <teem/ell.h>
27
#include <teem/nrrd.h>
28
#include <teem/limn.h>
29
#include <teem/hoover.h>
30
#include <teem/mite.h>
31
32
static const char *miteInfo =
33
  ("A simple but effective little volume renderer.");
34
35
int
36
main(int argc, const char *argv[]) {
37
  airArray *mop;
38
  hestOpt *hopt=NULL;
39
  hestParm *hparm=NULL;
40
  miteUser *muu;
41
  const char *me;
42
  char *errS, *outS, *shadeStr, *normalStr, debugStr[AIR_STRLEN_MED];
43
  int renorm, baseDim, verbPix[2], offfr;
44
  int E, Ecode, Ethread;
45
  float ads[3], isScale;
46
  double turn, eye[3], eyedist, gmc;
47
  double v[NRRD_SPACE_DIM_MAX];
48
  Nrrd *nin;
49
50
  me = argv[0];
51
  mop = airMopNew();
52
  hparm = hestParmNew();
53
  airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
54
  muu = miteUserNew();
55
  airMopAdd(mop, muu, (airMopper)miteUserNix, airMopAlways);
56
57
  hparm->respFileEnable = AIR_TRUE;
58
  hparm->elideMultipleNonExistFloatDefault = AIR_TRUE;
59
  hestOptAdd(&hopt, "i", "nsin", airTypeOther, 1, 1, &(muu->nsin), "",
60
             "input scalar volume to render", NULL, NULL, nrrdHestNrrd);
61
  hestOptAdd(&hopt, "vi", "nvin", airTypeOther, 1, 1, &(muu->nvin), "",
62
             "input vector volume to render", NULL, NULL, nrrdHestNrrd);
63
  hestOptAdd(&hopt, "ti", "ntin", airTypeOther, 1, 1, &(muu->ntin), "",
64
             "input tensor volume to render", NULL, NULL, nrrdHestNrrd);
65
  hestOptAdd(&hopt, "txf", "nin", airTypeOther, 1, -1, &(muu->ntxf), NULL,
66
             "one or more transfer functions",
67
             &(muu->ntxfNum), NULL, nrrdHestNrrd);
68
  limnHestCameraOptAdd(&hopt, muu->hctx->cam,
69
                       NULL, "0 0 0", "0 0 1",
70
                       NULL, NULL, NULL,
71
                       "nan nan", "nan nan", "20");
72
  hestOptAdd(&hopt, "offfr", NULL, airTypeInt, 0, 0, &offfr, NULL,
73
             "the given eye point (\"-fr\") is to be interpreted "
74
             "as an offset from the at point.");
75
  hestOptAdd(&hopt, "ffr", "fake from", airTypeDouble, 3, 3,
76
             &(muu->fakeFrom), "nan nan nan",
77
             "eye point to use for view-dependent transfer functions. "
78
             "By default (not using this option), the point used is the "
79
             "normally specified camera eye point.");
80
  hestOptAdd(&hopt, "turn", "angle", airTypeDouble, 1, 1, &turn, "0.0",
81
             "angle (degrees) by which to rotate the from point around "
82
             "true up, for making stereo pairs.  Positive means move "
83
             "towards positive U (the right)");
84
  hestOptAdd(&hopt, "am", "ambient", airTypeFloat, 3, 3, muu->lit->amb,
85
             "1 1 1", "ambient light color");
86
  hestOptAdd(&hopt, "ld", "light pos", airTypeFloat, 3, 3, muu->lit->_dir[0],
87
             "0 0 -1", "view space light position (extended to infinity)");
88
  hestOptAdd(&hopt, "is", "image size", airTypeInt, 2, 2, muu->hctx->imgSize,
89
             "256 256", "image dimensions");
90
  hestOptAdd(&hopt, "iss", "scale", airTypeFloat, 1, 1, &isScale, "1.0",
91
             "scaling of image size (from \"is\")");
92
  hestOptAdd(&hopt, "ads", "ka kd ks", airTypeFloat, 3, 3, ads,
93
             "0.1 0.6 0.3", "phong components");
94
  hestOptAdd(&hopt, "sp", "spec pow", mite_at, 1, 1,
95
             &(muu->rangeInit[miteRangeSP]), "30", "phong specular power");
96
  hestOptAdd(&hopt, "k00", "kernel", airTypeOther, 1, 1,
97
             &(muu->ksp[gageKernel00]),
98
             "tent", "value reconstruction kernel",
99
             NULL, NULL, nrrdHestKernelSpec);
100
  hestOptAdd(&hopt, "k11", "kernel", airTypeOther, 1, 1,
101
             &(muu->ksp[gageKernel11]),
102
             "cubicd:1,0", "first derivative kernel",
103
             NULL, NULL, nrrdHestKernelSpec);
104
  hestOptAdd(&hopt, "k22", "kernel", airTypeOther, 1, 1,
105
             &(muu->ksp[gageKernel22]),
106
             "cubicdd:1,0",  "second derivative kernel",
107
             NULL, NULL, nrrdHestKernelSpec);
108
  hestOptAdd(&hopt, "ss", "shading spec", airTypeString, 1, 1, &shadeStr,
109
             "phong:gage(scalar:n)", "how to do shading");
110
  hestOptAdd(&hopt, "ns", "normal spec", airTypeString, 1, 1, &normalStr,
111
             "", "\"normal\" to use for those miteVal's that need one");
112
  hestOptAdd(&hopt, "side", "normal side", airTypeInt, 1, 1,
113
             &(muu->normalSide),
114
             "1", "how to interpret gradients as normals:\n "
115
             "\b\bo \"1\": normal points to lower values (higher == "
116
             "more \"inside\")\n "
117
             "\b\bo \"0\": \"two-sided\": dot-products are abs()'d\n "
118
             "\b\bo \"-1\": normal points to higher values (lower == "
119
             "more \"inside\")");
120
  hestOptAdd(&hopt, "rn", NULL, airTypeBool, 0, 0, &renorm, NULL,
121
             "renormalize kernel weights at each new sample location. "
122
             "\"Accurate\" kernels don't need this; doing it always "
123
             "makes things go slower");
124
  hestOptAdd(&hopt, "gmc", "min gradmag", airTypeDouble, 1, 1, &gmc, "0.0",
125
             "For curvature-based transfer functions, set curvature to "
126
             "zero when gradient magnitude is below this");
127
  hestOptAdd(&hopt, "step", "size", airTypeDouble, 1, 1, &(muu->rayStep),
128
             "0.01", "step size along ray in world space");
129
  hestOptAdd(&hopt, "ref", "size", airTypeDouble, 1, 1, &(muu->refStep),
130
             "0.01", "\"reference\" step size (world space) for doing "
131
             "opacity correction in compositing");
132
  hestOptAdd(&hopt, "vp", "verbose pixel", airTypeInt, 2, 2, verbPix,
133
             "-1 -1", "pixel for which to turn on verbose messages");
134
  hestOptAdd(&hopt, "n1", "near1", airTypeDouble, 1, 1, &(muu->opacNear1),
135
             "0.99", "opacity close enough to 1.0 to terminate ray");
136
  hestOptAdd(&hopt, "nt", "# threads", airTypeInt, 1, 1,
137
             &(muu->hctx->numThreads), "1",
138
             (airThreadCapable
139
              ? "number of threads hoover should use"
140
              : "if pthreads where enabled in this Teem build, this is how "
141
              "you would control the number of threads hoover should use"));
142
  hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS,
143
             NULL, "file to write output nrrd to");
144
  hestParseOrDie(hopt, argc-1, argv+1, hparm,
145
                 me, miteInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
146
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
147
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
148
149
  if (muu->nsin) {
150
    nin = muu->nsin;
151
    baseDim = 0;
152
  } else if (muu->nvin) {
153
    nin = muu->nvin;
154
    baseDim = 1;
155
  } else if (muu->ntin) {
156
    nin = muu->ntin;
157
    baseDim = 1;
158
  } else {
159
    fprintf(stderr, "%s: didn't get any volumes to render!\n", me);
160
    airMopError(mop);
161
    return 1;
162
  }
163
164
  /* finish processing command-line args */
165
  muu->rangeInit[miteRangeKa] = ads[0];
166
  muu->rangeInit[miteRangeKd] = ads[1];
167
  muu->rangeInit[miteRangeKs] = ads[2];
168
  gageParmSet(muu->gctx0, gageParmGradMagCurvMin, gmc);
169
  gageParmSet(muu->gctx0, gageParmRenormalize,
170
              renorm ? AIR_TRUE : AIR_FALSE);
171
  muu->verbUi = verbPix[0];
172
  muu->verbVi = verbPix[1];
173
  if (offfr) {
174
    ELL_3V_INCR(muu->hctx->cam->from, muu->hctx->cam->at);
175
  }
176
  muu->hctx->imgSize[0] = AIR_CAST(int, isScale*muu->hctx->imgSize[0]);
177
  muu->hctx->imgSize[1] = AIR_CAST(int, isScale*muu->hctx->imgSize[1]);
178
179
  muu->nout = nrrdNew();
180
  airMopAdd(mop, muu->nout, (airMopper)nrrdNuke, airMopAlways);
181
  ELL_3V_SET(muu->lit->col[0], 1, 1, 1);
182
  muu->lit->on[0] = AIR_TRUE;
183
  muu->lit->vsp[0] = AIR_TRUE;
184
  if (AIR_EXISTS(muu->hctx->cam->uRange[0])
185
      && AIR_EXISTS(muu->hctx->cam->uRange[1])
186
      && AIR_EXISTS(muu->hctx->cam->vRange[0])
187
      && AIR_EXISTS(muu->hctx->cam->vRange[1])) {
188
    /* someone went to the trouble of setting the U,V minmax, which
189
       means they probably don't want the "fov"-based view window,
190
       whether or not the "fov" value came from the command-line or
191
       from the (unavoidable) default */
192
    muu->hctx->cam->fov = AIR_NAN;
193
  }
194
  if (limnCameraAspectSet(muu->hctx->cam,
195
                          muu->hctx->imgSize[0], muu->hctx->imgSize[1],
196
                          nrrdCenterCell)
197
      || limnCameraUpdate(muu->hctx->cam)
198
      || limnLightUpdate(muu->lit, muu->hctx->cam)) {
199
    airMopAdd(mop, errS = biffGetDone(LIMN), airFree, airMopAlways);
200
    fprintf(stderr, "%s: trouble setting camera:\n%s\n", me, errS);
201
    airMopError(mop);
202
    return 1;
203
  }
204
  if (turn) {
205
    turn *= AIR_PI/180;
206
    ELL_3V_SUB(eye, muu->hctx->cam->from, muu->hctx->cam->at);
207
    ELL_3V_NORM(eye, eye, eyedist);
208
    ELL_3V_SCALE_ADD2(muu->hctx->cam->from,
209
                      cos(turn), eye,
210
                      sin(turn), muu->hctx->cam->U);
211
    ELL_3V_SCALE(muu->hctx->cam->from, eyedist, muu->hctx->cam->from);
212
    if (limnCameraUpdate(muu->hctx->cam)) {
213
      airMopAdd(mop, errS = biffGetDone(LIMN), airFree, airMopAlways);
214
      fprintf(stderr, "%s: trouble setting camera (again):\n%s\n", me, errS);
215
      airMopError(mop);
216
      return 1;
217
    }
218
  }
219
  /*
220
    fprintf(stderr, "%s: camera info\n", me);
221
    fprintf(stderr, "    U = {%g,%g,%g}\n",
222
    muu->hctx->cam->U[0], muu->hctx->cam->U[1], muu->hctx->cam->U[2]);
223
    fprintf(stderr, "    V = {%g,%g,%g}\n",
224
    muu->hctx->cam->V[0], muu->hctx->cam->V[1], muu->hctx->cam->V[2]);
225
    fprintf(stderr, "    N = {%g,%g,%g}\n",
226
    muu->hctx->cam->N[0], muu->hctx->cam->N[1], muu->hctx->cam->N[2]);
227
  */
228
  airStrcpy(muu->shadeStr, AIR_STRLEN_MED, shadeStr);
229
  airStrcpy(muu->normalStr, AIR_STRLEN_MED, normalStr);
230
  if (0) {
231
    muu->hctx->volSize[0] = nin->axis[baseDim+0].size;
232
    muu->hctx->volSize[1] = nin->axis[baseDim+1].size;
233
    muu->hctx->volSize[2] = nin->axis[baseDim+2].size;
234
    /* Get the proper spacing from the NRRD volume */
235
    nrrdSpacingCalculate ( nin, baseDim+0, &(muu->hctx->volSpacing[0]), v );
236
    nrrdSpacingCalculate ( nin, baseDim+1, &(muu->hctx->volSpacing[1]), v );
237
    nrrdSpacingCalculate ( nin, baseDim+2, &(muu->hctx->volSpacing[2]), v );
238
  } else {
239
    if (gageShapeSet(muu->shape, nin, baseDim)) {
240
      fprintf(stderr, "%s: problem with shape:\n%s\n",
241
              me, errS = biffGetDone(GAGE)); free(errS);
242
      airMopError(mop);
243
      return 1;
244
    }
245
    muu->hctx->shape = muu->shape;
246
  }
247
  muu->hctx->user = muu;
248
  muu->hctx->renderBegin = (hooverRenderBegin_t *)miteRenderBegin;
249
  muu->hctx->threadBegin = (hooverThreadBegin_t *)miteThreadBegin;
250
  muu->hctx->rayBegin = (hooverRayBegin_t *)miteRayBegin;
251
  muu->hctx->sample = (hooverSample_t *)miteSample;
252
  muu->hctx->rayEnd = (hooverRayEnd_t *)miteRayEnd;
253
  muu->hctx->threadEnd = (hooverThreadEnd_t *)miteThreadEnd;
254
  muu->hctx->renderEnd = (hooverRenderEnd_t *)miteRenderEnd;
255
256
  if (!airThreadCapable && 1 != muu->hctx->numThreads) {
257
    fprintf(stderr, "%s: This Teem not compiled with "
258
            "multi-threading support.\n", me);
259
    fprintf(stderr, "%s: ==> can't use %d threads; only using 1\n",
260
            me, muu->hctx->numThreads);
261
    muu->hctx->numThreads = 1;
262
  }
263
264
  fprintf(stderr, "%s: rendering ... ", me); fflush(stderr);
265
266
  E = hooverRender(muu->hctx, &Ecode, &Ethread);
267
  if (E) {
268
    if (hooverErrInit == E) {
269
      errS = biffGetDone(HOOVER);
270
    } else {
271
      errS = biffGetDone(MITE);
272
    }
273
    airMopAdd(mop, errS, airFree, airMopAlways);
274
    fprintf(stderr, "%s: %s error (code %d, thread %d):\n%s\n",
275
            me, airEnumStr(hooverErr, E), Ecode, Ethread, errS);
276
    airMopError(mop);
277
    return 1;
278
  }
279
  fprintf(stderr, "\n");
280
  fprintf(stderr, "%s: rendering time = %g secs\n", me, muu->rendTime);
281
  fprintf(stderr, "%s: sampling rate = %g Khz\n", me, muu->sampRate);
282
  if (muu->ndebug) {
283
    /* if its been generated, we should save it */
284
    sprintf(debugStr, "%04d-%04d-debug.nrrd", verbPix[0], verbPix[1]);
285
    if (nrrdSave(debugStr, muu->ndebug, NULL)) {
286
      airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
287
      fprintf(stderr, "%s: trouble saving ray debug:\n%s\n", me, errS);
288
      airMopError(mop);
289
      return 1;
290
    }
291
  }
292
  if (nrrdSave(outS, muu->nout, NULL)) {
293
    airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
294
    fprintf(stderr, "%s: trouble saving image:\n%s\n", me, errS);
295
    airMopError(mop);
296
    return 1;
297
  }
298
299
  airMopOkay(mop);
300
  return 0;
301
}
302