GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/limn/transform.c Lines: 0 151 0.0 %
Date: 2017-05-26 Branches: 0 80 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
25
#include "limn.h"
26
27
int
28
limnObjectWorldHomog(limnObject *obj) {
29
  static const char me[]="limnObjectWorldHomog";
30
  unsigned int vertIdx;
31
  limnVertex *vert;
32
  float h;
33
34
  if (!obj) {
35
    biffAddf(LIMN, "%s: got NULL pointer", me);
36
    return 1;
37
  }
38
  for (vertIdx=0; vertIdx<obj->vertNum; vertIdx++) {
39
    vert = obj->vert + vertIdx;
40
    h = AIR_CAST(float, 1.0/vert->world[3]);
41
    ELL_3V_SCALE(vert->world, h, vert->world);
42
    vert->world[3] = 1.0;
43
    ELL_3V_NORM_TT(vert->worldNormal, float, vert->worldNormal, h);
44
  }
45
46
  return 0;
47
}
48
49
int
50
limnObjectFaceNormals(limnObject *obj, int space) {
51
  static const char me[]="limnObjectFaceNormals";
52
  unsigned int vii, faceIdx;
53
  limnFace *face;
54
  limnVertex *vert0, *vert1, *vert2;
55
  float vec1[3], vec2[3], cross[3], nn[3], norm;
56
57
  if (space != limnSpaceWorld && space != obj->vertSpace) {
58
    biffAddf(LIMN, "%s: desired (%s) != object (%s) space", me,
59
             airEnumStr(limnSpace, space),
60
             airEnumStr(limnSpace, obj->vertSpace));
61
    return 1;
62
  }
63
  for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) {
64
    face = obj->face + faceIdx;
65
    /* add up cross products at all vertices */
66
    ELL_3V_SET(nn, 0, 0, 0);
67
    for (vii=0; vii<face->sideNum; vii++) {
68
      vert0 = obj->vert + face->vertIdx[vii];
69
      vert1 = (obj->vert
70
               + face->vertIdx[AIR_MOD((int)vii+1, (int)face->sideNum)]);
71
      vert2 = (obj->vert
72
               + face->vertIdx[AIR_MOD((int)vii-1, (int)face->sideNum)]);
73
      if (limnSpaceWorld == space) {
74
        ELL_3V_SUB(vec1, vert1->world, vert0->world);
75
        ELL_3V_SUB(vec2, vert2->world, vert0->world);
76
      }
77
      else {
78
        ELL_3V_SUB(vec1, vert1->coord, vert0->coord);
79
        ELL_3V_SUB(vec2, vert2->coord, vert0->coord);
80
      }
81
      ELL_3V_CROSS(cross, vec1, vec2);
82
      ELL_3V_ADD2(nn, nn, cross);
83
    }
84
85
    if (limnSpaceWorld == space) {
86
      ELL_3V_NORM_TT(face->worldNormal, float, nn, norm);
87
      /*
88
      printf("%s: worldNormal[%d] = %g %g %g\n", me, faceIdx,
89
             face->worldNormal[0], face->worldNormal[1],
90
             face->worldNormal[2]);
91
      */
92
    }
93
    else {
94
      ELL_3V_NORM_TT(face->screenNormal, float, nn, norm);
95
      /*
96
      printf("%s: sn[%d] = %g %g %g\n", me, faceIdx,
97
             f->sn[0], f->sn[1], f->sn[2]);
98
      */
99
    }
100
  }
101
102
  return 0;
103
}
104
105
int
106
limnObjectVertexNormals(limnObject *obj) {
107
  /* static const char me[]="limnObjectVertexNormals"; */
108
  unsigned int vertIdx, vertIdxIdx, faceIdx;
109
  limnVertex *vert;
110
  limnFace *face;
111
  double norm;
112
113
  for (vertIdx=0; vertIdx<obj->vertNum; vertIdx++) {
114
    vert = obj->vert + vertIdx;
115
    ELL_3V_SET(vert->worldNormal, 0, 0, 0);
116
  }
117
  for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) {
118
    face = obj->face + faceIdx;
119
    for (vertIdxIdx=0; vertIdxIdx<face->sideNum; vertIdxIdx++) {
120
      vert = obj->vert + face->vertIdx[vertIdxIdx];
121
      ELL_3V_INCR(vert->worldNormal, face->worldNormal);
122
    }
123
  }
124
  for (vertIdx=0; vertIdx<obj->vertNum; vertIdx++) {
125
    vert = obj->vert + vertIdx;
126
    ELL_3V_NORM_TT(vert->worldNormal, float, vert->worldNormal, norm);
127
  }
128
  return 0;
129
}
130
131
int
132
_limnObjectViewTransform(limnObject *obj, limnCamera *cam) {
133
  unsigned int vertIdx;
134
  limnVertex *vert;
135
  float d;
136
137
  for (vertIdx=0; vertIdx<obj->vertNum; vertIdx++) {
138
    vert = obj->vert + vertIdx;
139
    ELL_4MV_MUL_TT(vert->coord, float, cam->W2V, vert->world);
140
    d = AIR_CAST(float, 1.0/vert->world[3]);
141
    ELL_4V_SCALE(vert->coord, d, vert->coord);
142
    /*
143
    printf("%s: w[%d] = %g %g %g %g --> v = %g %g %g\n",
144
           "_limnObjectVTransform",
145
           pi, p->w[0], p->w[1], p->w[2], p->w[3], p->v[0], p->v[1], p->v[2]);
146
    */
147
  }
148
  obj->vertSpace = limnSpaceView;
149
  return 0;
150
}
151
152
int
153
_limnObjectScreenTransform(limnObject *obj, limnCamera *cam) {
154
  static const char me[]="_limnObjectScreenTransform";
155
  unsigned int vertIdx;
156
  limnVertex *vert;
157
  float d;
158
159
  if (limnSpaceView != obj->vertSpace) {
160
    biffAddf(LIMN, "%s: object's verts in %s (not %s) space", me,
161
             airEnumStr(limnSpace, obj->vertSpace),
162
             airEnumStr(limnSpace, limnSpaceView));
163
    return 1;
164
  }
165
  for (vertIdx=0; vertIdx<obj->vertNum; vertIdx++) {
166
    vert = obj->vert + vertIdx;
167
    d = (cam->orthographic
168
         ? 1.0f
169
         : AIR_CAST(float, cam->vspDist/vert->coord[2]));
170
    vert->coord[0] *= d;
171
    vert->coord[1] *= d;
172
    /* coord[2] unchanged */
173
    /*
174
    printf("%s: v[%d] = %g %g %g --> s = %g %g %g\n", "_limnObjectSTransform",
175
           pi, p->v[0], p->v[1], p->v[2], p->s[0], p->s[1], p->s[2]);
176
    */
177
  }
178
  obj->vertSpace = limnSpaceScreen;
179
  return 0;
180
}
181
182
int
183
_limnObjectDeviceTransform(limnObject *obj, limnCamera *cam,
184
                           limnWindow *win) {
185
  static const char me[]="_limnObjectDeviceTransform";
186
  unsigned int vertIdx;
187
  limnVertex *vert;
188
  float wy0, wy1, wx0, wx1, t;
189
190
  if (limnSpaceScreen != obj->vertSpace) {
191
    biffAddf(LIMN, "%s: object's verts in %s (not %s) space", me,
192
             airEnumStr(limnSpace, obj->vertSpace),
193
             airEnumStr(limnSpace, limnSpaceScreen));
194
    return 1;
195
  }
196
  wx0 = 0;
197
  wx1 = AIR_CAST(float, (cam->uRange[1] - cam->uRange[0])*win->scale);
198
  wy0 = 0;
199
  wy1 = AIR_CAST(float, (cam->vRange[1] - cam->vRange[0])*win->scale);
200
  ELL_4V_SET(win->bbox, wx0, wy0, wx1, wy1);
201
  if (win->yFlip) {
202
    ELL_SWAP2(wy0, wy1, t);
203
  }
204
  for (vertIdx=0; vertIdx<obj->vertNum; vertIdx++) {
205
    vert = obj->vert + vertIdx;
206
    vert->coord[0] = AIR_CAST(float, AIR_AFFINE(cam->uRange[0], vert->coord[0],
207
                                                cam->uRange[1], wx0, wx1));
208
    vert->coord[1] = AIR_CAST(float, AIR_AFFINE(cam->vRange[0], vert->coord[1],
209
                                                cam->vRange[1], wy0, wy1));
210
    /* coord[2] unchanged */
211
    /*
212
    printf("%s: s[%d] = %g %g --> s = %g %g\n", "_limnObjectDTransform",
213
           pi, p->s[0], p->s[1], p->d[0], p->d[1]);
214
    */
215
  }
216
  obj->vertSpace = limnSpaceDevice;
217
  return 0;
218
}
219
220
int
221
limnObjectSpaceTransform(limnObject *obj, limnCamera *cam,
222
                      limnWindow *win, int space) {
223
  static const char me[]="limnObjectSpaceTransform";
224
  int E=0;
225
226
  /* HEY: deal with cam->orthographic */
227
  switch(space) {
228
  case limnSpaceView:
229
    E = _limnObjectViewTransform(obj, cam);
230
    break;
231
  case limnSpaceScreen:
232
    E = _limnObjectScreenTransform(obj, cam);
233
    break;
234
  case limnSpaceDevice:
235
    E = _limnObjectDeviceTransform(obj, cam, win);
236
    break;
237
  default:
238
    biffAddf(LIMN, "%s: space %d unknown or unimplemented\n", me, space);
239
    return 1;
240
    break;
241
  }
242
  if (E) {
243
    biffAddf(LIMN, "%s: trouble", me);
244
    return 1;
245
  }
246
247
  return 0;
248
}
249
250
int
251
limnObjectPartTransform(limnObject *obj, unsigned int partIdx,
252
                        float xform[16]) {
253
  unsigned int vertIdxIdx;
254
  limnPart *part;
255
  limnVertex *vert;
256
  float tmp[4];
257
258
  part= obj->part[partIdx];
259
  for (vertIdxIdx=0; vertIdxIdx<part->vertIdxNum; vertIdxIdx++) {
260
    vert = obj->vert + part->vertIdx[vertIdxIdx];
261
    ELL_4MV_MUL(tmp, xform, vert->world);
262
    ELL_4V_COPY(vert->world, tmp);
263
  }
264
265
  return 0;
266
}
267
268
int
269
_limnPartDepthCompare(const void *_a, const void *_b) {
270
  limnPart *const *a;
271
  limnPart *const *b;
272
273
  a = (limnPart *const *)_a;
274
  b = (limnPart *const *)_b;
275
  return AIR_COMPARE((*b)->depth, (*a)->depth);
276
}
277
278
int
279
limnObjectDepthSortParts(limnObject *obj) {
280
  limnPart *part;
281
  limnVertex *vert;
282
  limnFace *face;
283
  limnEdge *edge;
284
  unsigned int partIdx, ii;
285
286
  for (partIdx=0; partIdx<obj->partNum; partIdx++) {
287
    part = obj->part[partIdx];
288
    part->depth = 0;
289
    for (ii=0; ii<part->vertIdxNum; ii++) {
290
      vert = obj->vert + part->vertIdx[ii];
291
      part->depth += vert->coord[2];
292
    }
293
    part->depth /= part->vertIdxNum;
294
  }
295
296
  qsort(obj->part, obj->partNum, sizeof(limnPart*), _limnPartDepthCompare);
297
298
  /* re-assign partIdx, post-sorting */
299
  for (partIdx=0; partIdx<obj->partNum; partIdx++) {
300
    part = obj->part[partIdx];
301
    for (ii=0; ii<part->edgeIdxNum; ii++) {
302
      edge = obj->edge + part->edgeIdx[ii];
303
      edge->partIdx = partIdx;
304
    }
305
    for (ii=0; ii<part->faceIdxNum; ii++) {
306
      face = obj->face + part->faceIdx[ii];
307
      face->partIdx = partIdx;
308
    }
309
  }
310
311
  return 0;
312
}
313
314
int
315
_limnFaceDepthCompare(const void *_a, const void *_b) {
316
  limnFace *const*a;
317
  limnFace *const*b;
318
319
  a = (limnFace *const*)_a;
320
  b = (limnFace *const*)_b;
321
  return -AIR_COMPARE((*a)->depth, (*b)->depth);
322
}
323
324
int
325
limnObjectDepthSortFaces(limnObject *obj) {
326
  limnFace *face;
327
  limnVertex *vert;
328
  unsigned int faceIdx, vii;
329
330
  obj->faceSort = AIR_MALLOC(obj->faceNum, limnFace *);
331
  for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) {
332
    face = obj->face + faceIdx;
333
    face->depth = 0;
334
    for (vii=0; vii<face->sideNum; vii++) {
335
      vert = obj->vert + face->vertIdx[vii];
336
      face->depth += vert->coord[2];
337
    }
338
    face->depth /= face->sideNum;
339
    obj->faceSort[faceIdx] = face;
340
  }
341
342
  qsort(obj->faceSort, obj->faceNum,
343
        sizeof(limnFace *), _limnFaceDepthCompare);
344
345
  return 0;
346
}
347
348
int
349
limnObjectFaceReverse(limnObject *obj) {
350
  static const char me[]="limnObjectFaceReverse";
351
  limnFace *face;
352
  unsigned int faceIdx, sii;
353
  int *buff;
354
355
  if (!obj) {
356
    biffAddf(LIMN, "%s: got NULL pointer", me);
357
    return 1;
358
  }
359
  buff = NULL;
360
  for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) {
361
    face = obj->face + faceIdx;
362
    buff = (int *)calloc(face->sideNum, sizeof(int));
363
    if (!(buff)) {
364
      biffAddf(LIMN, "%s: couldn't allocate %d side buffer for face %d\n",
365
               me, face->sideNum, faceIdx);
366
      return 1;
367
    }
368
    memcpy(buff, face->vertIdx, face->sideNum*sizeof(int));
369
    for (sii=0; sii<face->sideNum; sii++) {
370
      face->vertIdx[sii] = buff[face->sideNum-1-sii];
371
    }
372
    memcpy(buff, face->edgeIdx, face->sideNum*sizeof(int));
373
    for (sii=0; sii<face->sideNum; sii++) {
374
      face->edgeIdx[sii] = buff[face->sideNum-1-sii];
375
    }
376
    free(buff);
377
  }
378
  return 0;
379
}