Bug Summary

File:src/limn/renderLimn.c
Location:line 397, column 5
Description:Value stored to 'part' is never read

Annotated Source Code

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
25#include "limn.h"
26
27int
28limnObjectRender(limnObject *obj, limnCamera *cam, limnWindow *win) {
29 static const char me[]="limnObjectRender";
30 int E;
31
32 E = 0;
33 if (!E) E |= limnCameraUpdate(cam);
34 /*
35 fprintf(stderr, "%s: true up = %g %g %g\n", me,
36 -cam->V[0], -cam->V[1], -cam->V[2]);
37 fprintf(stderr, "%s: true right = %g %g %g\n", me,
38 cam->U[0], cam->U[1], cam->U[2]);
39 */
40 if (!E) E |= limnObjectWorldHomog(obj);
41 if (!E) E |= limnObjectFaceNormals(obj, limnSpaceWorld);
42 if (!E) E |= limnObjectSpaceTransform(obj, cam, win, limnSpaceView);
43 if (!E) E |= limnObjectSpaceTransform(obj, cam, win, limnSpaceScreen);
44 if (!E) E |= limnObjectFaceNormals(obj, limnSpaceScreen);
45 if (!E) E |= limnObjectSpaceTransform(obj, cam, win, limnSpaceDevice);
46 if (E) {
47 biffAddf(LIMNlimnBiffKey, "%s: trouble", me);
48 return 1;
49 }
50 return 0;
51}
52
53void
54_limnPSPreamble(limnObject *obj, limnCamera *cam, limnWindow *win) {
55
56 AIR_UNUSED(obj)(void)(obj);
57 AIR_UNUSED(cam)(void)(cam);
58 fprintf(win->file, "%%!PS-Adobe-2.0 EPSF-2.0\n");
59 fprintf(win->file, "%%%%Creator: limn\n");
60 fprintf(win->file, "%%%%Pages: 1\n");
61 fprintf(win->file, "%%%%BoundingBox: %d %d %d %d\n",
62 (int)(win->bbox[0]),
63 (int)(win->bbox[1]),
64 (int)(win->bbox[2]),
65 (int)(win->bbox[3]));
66 fprintf(win->file, "%%%%EndComments\n");
67 fprintf(win->file, "%%%%EndProlog\n");
68 fprintf(win->file, "%%%%Page: 1 1\n");
69 fprintf(win->file, "gsave\n");
70 fprintf(win->file, "%g %g moveto\n", win->bbox[0], win->bbox[1]);
71 fprintf(win->file, "%g %g lineto\n", win->bbox[2], win->bbox[1]);
72 fprintf(win->file, "%g %g lineto\n", win->bbox[2], win->bbox[3]);
73 fprintf(win->file, "%g %g lineto\n", win->bbox[0], win->bbox[3]);
74 fprintf(win->file, "closepath\n");
75 if (!win->ps.noBackground) {
76 fprintf(win->file, "gsave %g %g %g setrgbcolor fill grestore\n",
77 win->ps.bg[0], win->ps.bg[1], win->ps.bg[2]);
78 }
79 fprintf(win->file, "clip\n");
80 fprintf(win->file, "gsave newpath\n");
81 fprintf(win->file, "1 setlinejoin\n");
82 fprintf(win->file, "1 setlinecap\n");
83 fprintf(win->file, "/M {moveto} bind def\n");
84 fprintf(win->file, "/L {lineto} bind def\n");
85 fprintf(win->file, "/W {setlinewidth} bind def\n");
86 fprintf(win->file, "/F {fill} bind def\n");
87 fprintf(win->file, "/S {stroke} bind def\n");
88 fprintf(win->file, "/CP {closepath} bind def\n");
89 fprintf(win->file, "/RGB {setrgbcolor} bind def\n");
90 fprintf(win->file, "/Gr {setgray} bind def\n");
91 fprintf(win->file, "\n");
92}
93
94void
95_limnPSEpilogue(limnObject *obj, limnCamera *cam, limnWindow *win) {
96
97 AIR_UNUSED(obj)(void)(obj);
98 AIR_UNUSED(cam)(void)(cam);
99 fprintf(win->file, "grestore\n");
100 fprintf(win->file, "grestore\n");
101 if (win->ps.showpage) {
102 fprintf(win->file, "showpage\n");
103 }
104 fprintf(win->file, "%%%%Trailer\n");
105}
106
107void
108_limnPSDrawFace(limnObject *obj, limnFace *face,
109 limnCamera *cam, Nrrd *nmap, limnWindow *win) {
110 /* static const char me[]="_limnPSDrawFace"; */
111 unsigned int vii;
112 limnVertex *vert;
113 limnLook *look;
114 int qn;
115 float *map, R, G, B;
116
117 AIR_UNUSED(cam)(void)(cam);
118 look = obj->look + face->lookIdx;
119 for (vii=0; vii<face->sideNum; vii++) {
120 vert = obj->vert + face->vertIdx[vii];
121 fprintf(win->file, "%g %g %s\n",
122 vert->coord[0], vert->coord[1], vii ? "L" : "M");
123 }
124 R = look->kads[0]*look->rgba[0];
125 G = look->kads[0]*look->rgba[1];
126 B = look->kads[0]*look->rgba[2];
127 if (nmap) {
128 qn = limnVtoQN_f[limnQN16octa](face->worldNormal);
129 map = (float *)nmap->data;
130 R += look->kads[1]*look->rgba[0]*map[0 + 3*qn];
131 G += look->kads[1]*look->rgba[1]*map[1 + 3*qn];
132 B += look->kads[1]*look->rgba[2]*map[2 + 3*qn];
133 } else {
134 R += look->kads[1]*look->rgba[0];
135 G += look->kads[1]*look->rgba[1];
136 B += look->kads[1]*look->rgba[2];
137 }
138 /* HEY: not evaluating phong specular for now */
139 R = AIR_CLAMP(0, R, 1)((R) < (0) ? (0) : ((R) > (1) ? (1) : (R)));
140 G = AIR_CLAMP(0, G, 1)((G) < (0) ? (0) : ((G) > (1) ? (1) : (G)));
141 B = AIR_CLAMP(0, B, 1)((B) < (0) ? (0) : ((B) > (1) ? (1) : (B)));
142 if (0 && R == G && G == B) {
143 /* As of Sat Mar 1 23:06:14 CST 2014 some version of ghostscript
144 and/or imagemagick will assign (when rasterizing) different
145 colors for RGB color (g,g,g) and graylevel g, which caused
146 strange appearance bugs that were hard to track down. Even if
147 there's a way of preventing this from happening with the right
148 incantation in the EPS header, for now it is simpler to forego
149 the small economy implemented here */
150 fprintf(win->file, "CP %g Gr F\n", R);
151 }
152 else {
153 fprintf(win->file, "CP %g %g %g RGB F\n", R, G, B);
154 }
155}
156
157void
158_limnPSDrawEdge(limnObject *obj, limnEdge *edge,
159 limnCamera *cam, limnWindow *win) {
160 limnVertex *vert0, *vert1;
161 float R, G, B;
162
163 AIR_UNUSED(cam)(void)(cam);
164 if (win->ps.lineWidth[edge->type]) {
165 vert0 = obj->vert + edge->vertIdx[0];
166 vert1 = obj->vert + edge->vertIdx[1];
167 fprintf(win->file, "%g %g M ", vert0->coord[0], vert0->coord[1]);
168 fprintf(win->file, "%g %g L ", vert1->coord[0], vert1->coord[1]);
169 fprintf(win->file, "%g W ", win->ps.lineWidth[edge->type]);
170 R = win->ps.edgeColor[0];
171 G = win->ps.edgeColor[1];
172 B = win->ps.edgeColor[2];
173 if (R == G && G == B) {
174 fprintf(win->file, "%g Gr S\n", R);
175 } else {
176 fprintf(win->file, "%g %g %g RGB S\n", R, G, B);
177 }
178 }
179}
180
181/*
182******** limnObjectPSDraw
183**
184** draws a "rendered" limn object to postscript.
185** limnObjectRender MUST be called first.
186**
187** The current (feeble) justification for using an environment map is
188** that its an expressive way of shading things based on surface
189** normal, in a context where, if flat shading is all you have,
190** correct specular lighting is not possible
191*/
192int
193limnObjectPSDraw(limnObject *obj, limnCamera *cam,
194 Nrrd *nmap, limnWindow *win) {
195 static const char me[]="limnObjectPSDraw";
196 int inside;
197 float angle;
198 limnFace *face, *face0, *face1; unsigned int fii;
199 limnEdge *edge; unsigned int eii;
200 limnPart *part; unsigned int partIdx;
201 limnVertex *vert; unsigned int vii;
202
203 if (limnSpaceDevice != obj->vertSpace) {
204 biffAddf(LIMNlimnBiffKey, "%s: object's verts in %s (not %s) space", me,
205 airEnumStr(limnSpace, obj->vertSpace),
206 airEnumStr(limnSpace, limnSpaceDevice));
207 return 1;
208 }
209 if (nmap) {
210 if (limnEnvMapCheck(nmap)) {
211 biffAddf(LIMNlimnBiffKey, "%s: trouble", me);
212 return 1;
213 }
214 }
215
216 limnObjectDepthSortParts(obj);
217
218 _limnPSPreamble(obj, cam, win);
219
220 for (partIdx=0; partIdx<obj->partNum; partIdx++) {
221 part = obj->part[partIdx];
222
223 /* only draw the parts that are inside the field of view */
224 inside = 0;
225 for (vii=0; vii<part->vertIdxNum; vii++) {
226 vert = obj->vert + part->vertIdx[vii];
227 inside |= (AIR_IN_CL(win->bbox[0], vert->coord[0], win->bbox[2])((win->bbox[0]) <= (vert->coord[0]) && (vert
->coord[0]) <= (win->bbox[2]))
&&
228 AIR_IN_CL(win->bbox[1], vert->coord[1], win->bbox[3])((win->bbox[1]) <= (vert->coord[1]) && (vert
->coord[1]) <= (win->bbox[3]))
);
229 if (inside) {
230 /* at least vertex is in, we know we can't skip this part */
231 break;
232 }
233 }
234 if (!inside) {
235 /* none of the vertices were in, we can skip this part */
236 continue;
237 }
238
239 /* draw the part */
240 if (1 == part->edgeIdxNum) {
241 /* this part is just one lone edge */
242 /* HEY: this is a mess */
243 /*
244 e = &(obj->e[r->eBase]);
245 widthTmp = win->ps.lineWidth[e->type];
246 fprintf(win->file, "%g setgray\n", 1 - win->ps.bg[0]);
247 win->ps.edgeWidth[e->type] = 8;
248 _limnPSDrawEdge(obj, r, e, cam, win);
249 fprintf(win->file, "%g %g %g RGB\n",
250 r->rgba[0], r->rgba[1], r->rgba[2]);
251 win->ps.edgeWidth[e->visible] = 4;
252 _limnPSDrawEdge(obj, r, e, cam, win);
253 win->ps.edgeWidth[e->visible] = widthTmp;
254 */
255 } else {
256 /* this part is either a lone face or a solid:
257 draw the front-facing, shaded faces */
258 for (fii=0; fii<part->faceIdxNum; fii++) {
259 face = obj->face + part->faceIdx[fii];
260 /* The consequence of having a left-handed frame is that world-space
261 CC-wise vertex traversal becomes C-wise screen-space traversal, so
262 all the normals are backwards of what we want */
263 face->visible = (cam->rightHanded
264 ? face->screenNormal[2] < 0
265 : face->screenNormal[2] > 0);
266 if (face->sideNum == part->vertIdxNum && !face->visible) {
267 /* lone faces are always visible */
268 face->visible = AIR_TRUE1;
269 ELL_3V_SCALE(face->worldNormal, -1, face->worldNormal)((face->worldNormal)[0] = (-1)*(face->worldNormal)[0], (
face->worldNormal)[1] = (-1)*(face->worldNormal)[1], (face
->worldNormal)[2] = (-1)*(face->worldNormal)[2])
;
270 }
271 if (!win->ps.wireFrame && face->visible) {
272 _limnPSDrawFace(obj, face, cam, nmap, win);
273 }
274 }
275
276 /* draw ALL edges */
277 for (eii=0; eii<part->edgeIdxNum; eii++) {
278 /* hack to change contour of particular object/glyph
279 if (24 == partIdx) {
280 win->ps.lineWidth[limnEdgeTypeContour] = 1.2;
281 } else {
282 win->ps.lineWidth[limnEdgeTypeContour] = 0.4;
283 }
284 */
285 edge = obj->edge + part->edgeIdx[eii];
286 face0 = obj->face + edge->faceIdx[0];
287 face1 = (-1 == edge->faceIdx[1]
288 ? NULL((void*)0)
289 : obj->face + edge->faceIdx[1]);
290 if (!face1) {
291 edge->type = limnEdgeTypeBorder;
292 } else {
293 angle = AIR_CAST(float,((float)(180/3.14159265358979323846*acos(((face0->worldNormal
)[0]*(face1->worldNormal)[0] + (face0->worldNormal)[1]*
(face1->worldNormal)[1] + (face0->worldNormal)[2]*(face1
->worldNormal)[2]))))
294 180/AIR_PI*acos(ELL_3V_DOT(face0->worldNormal,((float)(180/3.14159265358979323846*acos(((face0->worldNormal
)[0]*(face1->worldNormal)[0] + (face0->worldNormal)[1]*
(face1->worldNormal)[1] + (face0->worldNormal)[2]*(face1
->worldNormal)[2]))))
295 face1->worldNormal)))((float)(180/3.14159265358979323846*acos(((face0->worldNormal
)[0]*(face1->worldNormal)[0] + (face0->worldNormal)[1]*
(face1->worldNormal)[1] + (face0->worldNormal)[2]*(face1
->worldNormal)[2]))))
;
296 if (face0->visible && face1->visible) {
297 edge->type = (angle > win->ps.creaseAngle
298 ? limnEdgeTypeFrontCrease
299 : limnEdgeTypeFrontFacet);
300 } else if (face0->visible ^ face1->visible) {
301 edge->type = limnEdgeTypeContour;
302 } else {
303 edge->type = (angle > win->ps.creaseAngle
304 ? limnEdgeTypeBackCrease
305 : limnEdgeTypeBackFacet);
306 }
307 }
308 _limnPSDrawEdge(obj, edge, cam, win);
309 }
310 }
311 }
312
313 _limnPSEpilogue(obj, cam, win);
314
315 return 0;
316}
317
318/*
319******** limnObjectPSDrawConcave
320**
321** new version of the above, which works per-face instead of per-part,
322** thus better handling self-occlusions, but at the cost of not getting
323** contours near oblique faces correct...
324*/
325int
326limnObjectPSDrawConcave(limnObject *obj, limnCamera *cam,
327 Nrrd *nmap, limnWindow *win) {
328 static const char me[]="limnObjectPSDrawConcave";
329 float angle;
330 limnPart *part;
331 limnFace *face, *face0, *face1; unsigned int faceIdx;
332 limnEdge *edge; unsigned int edgeIdx, eii;
333
334 if (limnSpaceDevice != obj->vertSpace) {
335 biffAddf(LIMNlimnBiffKey, "%s: object's verts in %s (not %s) space", me,
336 airEnumStr(limnSpace, obj->vertSpace),
337 airEnumStr(limnSpace, limnSpaceDevice));
338 return 1;
339 }
340 if (nmap) {
341 if (limnEnvMapCheck(nmap)) {
342 biffAddf(LIMNlimnBiffKey, "%s: trouble", me);
343 return 1;
344 }
345 }
346
347 limnObjectDepthSortFaces(obj);
348
349 _limnPSPreamble(obj, cam, win);
350
351 /* set every face's visibility */
352 for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) {
353 face = obj->face + faceIdx;
354 part = obj->part[face->partIdx];
355 face->visible = (cam->rightHanded
356 ? face->screenNormal[2] < 0
357 : face->screenNormal[2] > 0);
358 if (face->sideNum == part->vertIdxNum && !face->visible) {
359 /* lone faces are always visible */
360 face->visible = AIR_TRUE1;
361 ELL_3V_SCALE(face->worldNormal, -1, face->worldNormal)((face->worldNormal)[0] = (-1)*(face->worldNormal)[0], (
face->worldNormal)[1] = (-1)*(face->worldNormal)[1], (face
->worldNormal)[2] = (-1)*(face->worldNormal)[2])
;
362 }
363 }
364
365 /* categorize all edges by traversing edge array, and looking
366 at each of their two faces */
367 for (edgeIdx=0; edgeIdx<obj->edgeNum; edgeIdx++) {
368 edge = obj->edge + edgeIdx;
369 part = obj->part[edge->partIdx];
370 face0 = obj->face + edge->faceIdx[0];
371 face1 = (-1 == edge->faceIdx[1]
372 ? NULL((void*)0)
373 : obj->face + edge->faceIdx[1]);
374 if (!face1) {
375 edge->type = limnEdgeTypeBorder;
376 } else {
377 angle = AIR_CAST(float, 180/AIR_PI*acos(ELL_3V_DOT(face0->worldNormal,((float)(180/3.14159265358979323846*acos(((face0->worldNormal
)[0]*(face1->worldNormal)[0] + (face0->worldNormal)[1]*
(face1->worldNormal)[1] + (face0->worldNormal)[2]*(face1
->worldNormal)[2]))))
378 face1->worldNormal)))((float)(180/3.14159265358979323846*acos(((face0->worldNormal
)[0]*(face1->worldNormal)[0] + (face0->worldNormal)[1]*
(face1->worldNormal)[1] + (face0->worldNormal)[2]*(face1
->worldNormal)[2]))))
;
379 if (face0->visible && face1->visible) {
380 edge->type = (angle > win->ps.creaseAngle
381 ? limnEdgeTypeFrontCrease
382 : limnEdgeTypeFrontFacet);
383 } else if (face0->visible ^ face1->visible) {
384 edge->type = limnEdgeTypeContour;
385 } else {
386 edge->type = (angle > win->ps.creaseAngle
387 ? limnEdgeTypeBackCrease
388 : limnEdgeTypeBackFacet);
389 }
390 }
391 }
392
393 /* draw front-faces and their edges
394 (contours, front crease, front non-crease) */
395 for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) {
396 face = obj->faceSort[faceIdx];
397 part = obj->part[face->partIdx];
Value stored to 'part' is never read
398 if (!face->visible) {
399 continue;
400 }
401 if (!win->ps.wireFrame) {
402 _limnPSDrawFace(obj, face, cam, nmap, win);
403 }
404 /* draw those edges around the face that won't be seen again by
405 future faces in the depth-first traversal */
406 for (eii=0; eii<face->sideNum; eii++) {
407 edge = obj->edge + face->edgeIdx[eii];
408 if (limnEdgeTypeContour == edge->type) {
409 _limnPSDrawEdge(obj, edge, cam, win);
410 } else if (limnEdgeTypeFrontCrease == edge->type
411 || limnEdgeTypeFrontFacet == edge->type) {
412 if (edge->once) {
413 /* its been seen once already, okay to draw */
414 _limnPSDrawEdge(obj, edge, cam, win);
415 edge->once = AIR_FALSE0;
416 } else {
417 /* we're the first to see it, and we're not the last, don't draw */
418 edge->once = AIR_TRUE1;
419 }
420 }
421 }
422 }
423
424 _limnPSEpilogue(obj, cam, win);
425
426 return 0;
427}