GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/limn/polyshapes.c Lines: 0 828 0.0 %
Date: 2017-05-26 Branches: 0 366 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) 2010, 2009, 2008  Thomas Schultz
5
  Copyright (C) 2008, 2007, 2006, 2005  Gordon Kindlmann
6
  Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998  University of Utah
7
8
  This library is free software; you can redistribute it and/or
9
  modify it under the terms of the GNU Lesser General Public License
10
  (LGPL) as published by the Free Software Foundation; either
11
  version 2.1 of the License, or (at your option) any later version.
12
  The terms of redistributing and/or modifying this software also
13
  include exceptions to the LGPL that facilitate static linking.
14
15
  This library is distributed in the hope that it will be useful,
16
  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
  Lesser General Public License for more details.
19
20
  You should have received a copy of the GNU Lesser General Public License
21
  along with this library; if not, write to Free Software Foundation, Inc.,
22
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
*/
24
25
26
#include "limn.h"
27
28
int
29
limnPolyDataCube(limnPolyData *pld,
30
                 unsigned int infoBitFlag,
31
                 int sharpEdge) {
32
  static const char me[]="limnPolyDataCube";
33
  unsigned int vertNum, vertIdx, primNum, indxNum, cnum, ci;
34
35
  vertNum = sharpEdge ? 6*4 : 8;
36
  primNum = 1;
37
  indxNum = 6*4;
38
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
39
    biffAddf(LIMN, "%s: couldn't allocate output", me);
40
    return 1;
41
  }
42
  pld->type[0] = limnPrimitiveQuads;
43
  pld->icnt[0] = indxNum;
44
45
  vertIdx = 0;
46
  cnum = sharpEdge ? 3 : 1;
47
  for (ci=0; ci<cnum; ci++) {
48
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,  -1,  -1,  1); vertIdx++;
49
  }
50
  for (ci=0; ci<cnum; ci++) {
51
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,   1,  -1,  1); vertIdx++;
52
  }
53
  for (ci=0; ci<cnum; ci++) {
54
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,   1,  -1,  1); vertIdx++;
55
  }
56
  for (ci=0; ci<cnum; ci++) {
57
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,  -1,  -1,  1); vertIdx++;
58
  }
59
  for (ci=0; ci<cnum; ci++) {
60
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,  -1,   1,  1); vertIdx++;
61
  }
62
  for (ci=0; ci<cnum; ci++) {
63
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,   1,   1,  1); vertIdx++;
64
  }
65
  for (ci=0; ci<cnum; ci++) {
66
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,   1,   1,  1); vertIdx++;
67
  }
68
  for (ci=0; ci<cnum; ci++) {
69
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,  -1,   1,  1); vertIdx++;
70
  }
71
72
  vertIdx = 0;
73
  if (sharpEdge) {
74
    ELL_4V_SET(pld->indx + vertIdx,  0,  3,  6,  9); vertIdx += 4;
75
    ELL_4V_SET(pld->indx + vertIdx,  2, 14, 16,  5); vertIdx += 4;
76
    ELL_4V_SET(pld->indx + vertIdx,  4, 17, 18,  8); vertIdx += 4;
77
    ELL_4V_SET(pld->indx + vertIdx,  7, 19, 21, 10); vertIdx += 4;
78
    ELL_4V_SET(pld->indx + vertIdx,  1, 11, 23, 13); vertIdx += 4;
79
    ELL_4V_SET(pld->indx + vertIdx, 12, 22, 20, 15); vertIdx += 4;
80
  } else {
81
    ELL_4V_SET(pld->indx + vertIdx,  0,  1,  2,  3); vertIdx += 4;
82
    ELL_4V_SET(pld->indx + vertIdx,  0,  4,  5,  1); vertIdx += 4;
83
    ELL_4V_SET(pld->indx + vertIdx,  1,  5,  6,  2); vertIdx += 4;
84
    ELL_4V_SET(pld->indx + vertIdx,  2,  6,  7,  3); vertIdx += 4;
85
    ELL_4V_SET(pld->indx + vertIdx,  0,  3,  7,  4); vertIdx += 4;
86
    ELL_4V_SET(pld->indx + vertIdx,  4,  7,  6,  5); vertIdx += 4;
87
  }
88
89
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
90
    if (sharpEdge) {
91
      ELL_3V_SET(pld->norm +  3*0,  0,  0, -1);
92
      ELL_3V_SET(pld->norm +  3*3,  0,  0, -1);
93
      ELL_3V_SET(pld->norm +  3*6,  0,  0, -1);
94
      ELL_3V_SET(pld->norm +  3*9,  0,  0, -1);
95
      ELL_3V_SET(pld->norm +  3*2, -1,  0,  0);
96
      ELL_3V_SET(pld->norm +  3*5, -1,  0,  0);
97
      ELL_3V_SET(pld->norm + 3*14, -1,  0,  0);
98
      ELL_3V_SET(pld->norm + 3*16, -1,  0,  0);
99
      ELL_3V_SET(pld->norm +  3*4,  0,  1,  0);
100
      ELL_3V_SET(pld->norm +  3*8,  0,  1,  0);
101
      ELL_3V_SET(pld->norm + 3*17,  0,  1,  0);
102
      ELL_3V_SET(pld->norm + 3*18,  0,  1,  0);
103
      ELL_3V_SET(pld->norm +  3*7,  1,  0,  0);
104
      ELL_3V_SET(pld->norm + 3*10,  1,  0,  0);
105
      ELL_3V_SET(pld->norm + 3*19,  1,  0,  0);
106
      ELL_3V_SET(pld->norm + 3*21,  1,  0,  0);
107
      ELL_3V_SET(pld->norm +  3*1,  0, -1,  0);
108
      ELL_3V_SET(pld->norm + 3*11,  0, -1,  0);
109
      ELL_3V_SET(pld->norm + 3*13,  0, -1,  0);
110
      ELL_3V_SET(pld->norm + 3*23,  0, -1,  0);
111
      ELL_3V_SET(pld->norm + 3*12,  0,  0,  1);
112
      ELL_3V_SET(pld->norm + 3*15,  0,  0,  1);
113
      ELL_3V_SET(pld->norm + 3*20,  0,  0,  1);
114
      ELL_3V_SET(pld->norm + 3*22,  0,  0,  1);
115
    } else {
116
      float cn;
117
      cn = AIR_CAST(float, sqrt(3.0));
118
      ELL_3V_SET(pld->norm + 3*0, -cn, -cn, -cn);
119
      ELL_3V_SET(pld->norm + 3*1, -cn,  cn, -cn);
120
      ELL_3V_SET(pld->norm + 3*2,  cn,  cn, -cn);
121
      ELL_3V_SET(pld->norm + 3*3,  cn, -cn, -cn);
122
      ELL_3V_SET(pld->norm + 3*4, -cn, -cn,  cn);
123
      ELL_3V_SET(pld->norm + 3*5, -cn,  cn,  cn);
124
      ELL_3V_SET(pld->norm + 3*6,  cn,  cn,  cn);
125
      ELL_3V_SET(pld->norm + 3*7,  cn, -cn,  cn);
126
    }
127
  }
128
129
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
130
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
131
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
132
    }
133
  }
134
135
  return 0;
136
}
137
138
int
139
limnPolyDataCubeTriangles(limnPolyData *pld,
140
                          unsigned int infoBitFlag,
141
                          int sharpEdge) {
142
  static const char me[]="limnPolyDataCubeTriangles";
143
  unsigned int vertNum, vertIdx, primNum, indxNum, cnum, ci;
144
145
  vertNum = sharpEdge ? 6*4 : 8;
146
  primNum = 1;
147
  indxNum = 6*6;
148
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
149
    biffAddf(LIMN, "%s: couldn't allocate output", me);
150
    return 1;
151
  }
152
  pld->type[0] = limnPrimitiveTriangles;
153
  pld->icnt[0] = indxNum;
154
155
  vertIdx = 0;
156
  cnum = sharpEdge ? 3 : 1;
157
  for (ci=0; ci<cnum; ci++) {
158
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,  -1,   1,  1); vertIdx++;
159
  }
160
  for (ci=0; ci<cnum; ci++) {
161
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,  -1,   1,  1); vertIdx++;
162
  }
163
  for (ci=0; ci<cnum; ci++) {
164
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,   1,   1,  1); vertIdx++;
165
  }
166
  for (ci=0; ci<cnum; ci++) {
167
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,   1,   1,  1); vertIdx++;
168
  }
169
  for (ci=0; ci<cnum; ci++) {
170
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,   1,  -1,  1); vertIdx++;
171
  }
172
  for (ci=0; ci<cnum; ci++) {
173
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,   1,  -1,  1); vertIdx++;
174
  }
175
  for (ci=0; ci<cnum; ci++) {
176
    ELL_4V_SET(pld->xyzw + 4*vertIdx,   1,  -1,  -1,  1); vertIdx++;
177
  }
178
  for (ci=0; ci<cnum; ci++) {
179
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  -1,  -1,  -1,  1); vertIdx++;
180
  }
181
182
  vertIdx = 0;
183
  if (sharpEdge) {
184
    ELL_3V_SET(pld->indx + vertIdx,  0,  6,  3); vertIdx += 3;
185
    ELL_3V_SET(pld->indx + vertIdx,  3,  6,  9); vertIdx += 3;
186
187
    ELL_3V_SET(pld->indx + vertIdx,  7, 12, 10); vertIdx += 3;
188
    ELL_3V_SET(pld->indx + vertIdx, 10, 12, 16); vertIdx += 3;
189
190
    ELL_3V_SET(pld->indx + vertIdx, 11, 15,  4); vertIdx += 3;
191
    ELL_3V_SET(pld->indx + vertIdx,  4, 15, 21); vertIdx += 3;
192
193
    ELL_3V_SET(pld->indx + vertIdx, 17, 14, 22); vertIdx += 3;
194
    ELL_3V_SET(pld->indx + vertIdx, 22, 14, 20); vertIdx += 3;
195
196
    ELL_3V_SET(pld->indx + vertIdx,  2,  5, 19); vertIdx += 3;
197
    ELL_3V_SET(pld->indx + vertIdx, 19,  5, 23); vertIdx += 3;
198
199
    ELL_3V_SET(pld->indx + vertIdx, 13,  8, 18); vertIdx += 3;
200
    ELL_3V_SET(pld->indx + vertIdx, 18,  8,  1); vertIdx += 3;
201
  } else {
202
    ELL_3V_SET(pld->indx + vertIdx, 0, 2, 1); vertIdx += 3;
203
    ELL_3V_SET(pld->indx + vertIdx, 1, 2, 3); vertIdx += 3;
204
205
    ELL_3V_SET(pld->indx + vertIdx, 2, 4, 3); vertIdx += 3;
206
    ELL_3V_SET(pld->indx + vertIdx, 3, 4, 5); vertIdx += 3;
207
208
    ELL_3V_SET(pld->indx + vertIdx, 3, 5, 1); vertIdx += 3;
209
    ELL_3V_SET(pld->indx + vertIdx, 1, 5, 7); vertIdx += 3;
210
211
    ELL_3V_SET(pld->indx + vertIdx, 5, 4, 7); vertIdx += 3;
212
    ELL_3V_SET(pld->indx + vertIdx, 7, 4, 6); vertIdx += 3;
213
214
    ELL_3V_SET(pld->indx + vertIdx, 7, 6, 1); vertIdx += 3;
215
    ELL_3V_SET(pld->indx + vertIdx, 1, 6, 0); vertIdx += 3;
216
217
    ELL_3V_SET(pld->indx + vertIdx, 4, 2, 6); vertIdx += 3;
218
    ELL_3V_SET(pld->indx + vertIdx, 2, 6, 0); vertIdx += 3;
219
  }
220
221
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
222
    if (sharpEdge) {
223
      ELL_3V_SET(pld->norm + 3*14,  0,  0, -1);
224
      ELL_3V_SET(pld->norm + 3*17,  0,  0, -1);
225
      ELL_3V_SET(pld->norm + 3*20,  0,  0, -1);
226
      ELL_3V_SET(pld->norm + 3*22,  0,  0, -1);
227
      ELL_3V_SET(pld->norm + 3* 4, -1,  0,  0);
228
      ELL_3V_SET(pld->norm + 3*11, -1,  0,  0);
229
      ELL_3V_SET(pld->norm + 3*15, -1,  0,  0);
230
      ELL_3V_SET(pld->norm + 3*21, -1,  0,  0);
231
      ELL_3V_SET(pld->norm + 3* 7,  0,  1,  0);
232
      ELL_3V_SET(pld->norm + 3*10,  0,  1,  0);
233
      ELL_3V_SET(pld->norm + 3*12,  0,  1,  0);
234
      ELL_3V_SET(pld->norm + 3*16,  0,  1,  0);
235
      ELL_3V_SET(pld->norm + 3* 1,  1,  0,  0);
236
      ELL_3V_SET(pld->norm + 3* 8,  1,  0,  0);
237
      ELL_3V_SET(pld->norm + 3*13,  1,  0,  0);
238
      ELL_3V_SET(pld->norm + 3*18,  1,  0,  0);
239
      ELL_3V_SET(pld->norm + 3* 2,  0, -1,  0);
240
      ELL_3V_SET(pld->norm + 3* 5,  0, -1,  0);
241
      ELL_3V_SET(pld->norm + 3*19,  0, -1,  0);
242
      ELL_3V_SET(pld->norm + 3*23,  0, -1,  0);
243
      ELL_3V_SET(pld->norm + 3* 0,  0,  0,  1);
244
      ELL_3V_SET(pld->norm + 3* 3,  0,  0,  1);
245
      ELL_3V_SET(pld->norm + 3* 6,  0,  0,  1);
246
      ELL_3V_SET(pld->norm + 3* 9,  0,  0,  1);
247
    } else {
248
      float cn;
249
      cn = AIR_CAST(float, 1.0/sqrt(3.0));
250
      ELL_3V_SET(pld->norm + 3*0,  cn, -cn,  cn);
251
      ELL_3V_SET(pld->norm + 3*1, -cn, -cn,  cn);
252
      ELL_3V_SET(pld->norm + 3*2,  cn,  cn,  cn);
253
      ELL_3V_SET(pld->norm + 3*3, -cn,  cn,  cn);
254
      ELL_3V_SET(pld->norm + 3*4,  cn,  cn, -cn);
255
      ELL_3V_SET(pld->norm + 3*5, -cn,  cn, -cn);
256
      ELL_3V_SET(pld->norm + 3*6,  cn, -cn, -cn);
257
      ELL_3V_SET(pld->norm + 3*7, -cn, -cn, -cn);
258
    }
259
  }
260
261
  if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
262
    if (sharpEdge) {
263
      ELL_2V_SET(pld->tex2 + 2*14,  1,  1);
264
      ELL_2V_SET(pld->tex2 + 2*17,  0,  1);
265
      ELL_2V_SET(pld->tex2 + 2*20,  1,  0);
266
      ELL_2V_SET(pld->tex2 + 2*22,  0,  0);
267
      ELL_2V_SET(pld->tex2 + 2* 4,  1,  0);
268
      ELL_2V_SET(pld->tex2 + 2*11,  0,  0);
269
      ELL_2V_SET(pld->tex2 + 2*15,  0,  1);
270
      ELL_2V_SET(pld->tex2 + 2*21,  1,  1);
271
      ELL_2V_SET(pld->tex2 + 2* 7,  0,  0);
272
      ELL_2V_SET(pld->tex2 + 2*10,  1,  0);
273
      ELL_2V_SET(pld->tex2 + 2*12,  0,  1);
274
      ELL_2V_SET(pld->tex2 + 2*16,  1,  1);
275
      ELL_2V_SET(pld->tex2 + 2* 1,  0,  0);
276
      ELL_2V_SET(pld->tex2 + 2* 8,  1,  0);
277
      ELL_2V_SET(pld->tex2 + 2*13,  1,  1);
278
      ELL_2V_SET(pld->tex2 + 2*18,  0,  1);
279
      ELL_2V_SET(pld->tex2 + 2* 2,  1,  0);
280
      ELL_2V_SET(pld->tex2 + 2* 5,  0,  0);
281
      ELL_2V_SET(pld->tex2 + 2*19,  1,  1);
282
      ELL_2V_SET(pld->tex2 + 2*23,  0,  1);
283
      ELL_2V_SET(pld->tex2 + 2* 0,  1,  1);
284
      ELL_2V_SET(pld->tex2 + 2* 3,  0,  1);
285
      ELL_2V_SET(pld->tex2 + 2* 6,  1,  0);
286
      ELL_2V_SET(pld->tex2 + 2* 9,  0,  0);
287
    } else {
288
      ELL_2V_SET(pld->tex2 + 2*0, 1, 1);
289
      ELL_2V_SET(pld->tex2 + 2*1, 0, 1);
290
      ELL_2V_SET(pld->tex2 + 2*2, 1, 0);
291
      ELL_2V_SET(pld->tex2 + 2*3, 0, 0);
292
      ELL_2V_SET(pld->tex2 + 2*4, 1, 0);
293
      ELL_2V_SET(pld->tex2 + 2*5, 0, 0);
294
      ELL_2V_SET(pld->tex2 + 2*6, 1, 1);
295
      ELL_2V_SET(pld->tex2 + 2*7, 0, 1);
296
    }
297
  }
298
299
  if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
300
    if (sharpEdge) {
301
      ELL_3V_SET(pld->tang + 3*14,  1,  0,  0);
302
      ELL_3V_SET(pld->tang + 3*17,  1,  0,  0);
303
      ELL_3V_SET(pld->tang + 3*20,  1,  0,  0);
304
      ELL_3V_SET(pld->tang + 3*22,  1,  0,  0);
305
      ELL_3V_SET(pld->tang + 3* 4,  0, -1,  0);
306
      ELL_3V_SET(pld->tang + 3*11,  0, -1,  0);
307
      ELL_3V_SET(pld->tang + 3*15,  0, -1,  0);
308
      ELL_3V_SET(pld->tang + 3*21,  0, -1,  0);
309
      ELL_3V_SET(pld->tang + 3* 7, -1,  0,  0);
310
      ELL_3V_SET(pld->tang + 3*10, -1,  0,  0);
311
      ELL_3V_SET(pld->tang + 3*12, -1,  0,  0);
312
      ELL_3V_SET(pld->tang + 3*16, -1,  0,  0);
313
      ELL_3V_SET(pld->tang + 3* 1,  0,  1,  0);
314
      ELL_3V_SET(pld->tang + 3* 8,  0,  1,  0);
315
      ELL_3V_SET(pld->tang + 3*13,  0,  1,  0);
316
      ELL_3V_SET(pld->tang + 3*18,  0,  1,  0);
317
      ELL_3V_SET(pld->tang + 3* 2,  1,  0,  0);
318
      ELL_3V_SET(pld->tang + 3* 5,  1,  0,  0);
319
      ELL_3V_SET(pld->tang + 3*19,  1,  0,  0);
320
      ELL_3V_SET(pld->tang + 3*23,  1,  0,  0);
321
      ELL_3V_SET(pld->tang + 3* 0,  1,  0,  0);
322
      ELL_3V_SET(pld->tang + 3* 3,  1,  0,  0);
323
      ELL_3V_SET(pld->tang + 3* 6,  1,  0,  0);
324
      ELL_3V_SET(pld->tang + 3* 9,  1,  0,  0);
325
    } else {
326
      float sn;
327
      sn = AIR_CAST(float, 1.0/sqrt(2.0));
328
      ELL_3V_SET(pld->tang + 3*0, -sn,  sn,  0);
329
      ELL_3V_SET(pld->tang + 3*1,  sn,  sn,  0);
330
      ELL_3V_SET(pld->tang + 3*2, -sn, -sn,  0);
331
      ELL_3V_SET(pld->tang + 3*3,  sn, -sn,  0);
332
      ELL_3V_SET(pld->tang + 3*4, -sn, -sn,  0);
333
      ELL_3V_SET(pld->tang + 3*5,  sn, -sn,  0);
334
      ELL_3V_SET(pld->tang + 3*6, -sn,  sn,  0);
335
      ELL_3V_SET(pld->tang + 3*7,  sn,  sn,  0);
336
    }
337
  }
338
339
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
340
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
341
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
342
    }
343
  }
344
345
  return 0;
346
}
347
348
int
349
limnPolyDataOctahedron(limnPolyData *pld,
350
                       unsigned int infoBitFlag,
351
                       int sharpEdge) {
352
  static const char me[]="limnPolyDataOctahedron";
353
  unsigned int vertNum, vertIdx, primNum, indxNum, cnum, ci;
354
355
  vertNum = sharpEdge ? 4*6 : 6;
356
  primNum = 1;
357
  indxNum = 8*3;
358
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
359
    biffAddf(LIMN, "%s: couldn't allocate output", me);
360
    return 1;
361
  }
362
  pld->type[0] = limnPrimitiveTriangles;
363
  pld->icnt[0] = indxNum;
364
365
  vertIdx = 0;
366
  cnum = sharpEdge ? 4 : 1;
367
  for (ci=0; ci<cnum; ci++) {
368
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  0,  0,  1,  1); vertIdx++; /* 0 */
369
  }
370
  for (ci=0; ci<cnum; ci++) {
371
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  0,  1,  0,  1); vertIdx++; /* 1 */
372
  }
373
  for (ci=0; ci<cnum; ci++) {
374
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  1,  0,  0,  1); vertIdx++; /* 2 */
375
  }
376
  for (ci=0; ci<cnum; ci++) {
377
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  0, -1,  0,  1); vertIdx++; /* 3 */
378
  }
379
  for (ci=0; ci<cnum; ci++) {
380
    ELL_4V_SET(pld->xyzw + 4*vertIdx, -1,  0,  0,  1); vertIdx++; /* 4 */
381
  }
382
  for (ci=0; ci<cnum; ci++) {
383
    ELL_4V_SET(pld->xyzw + 4*vertIdx,  0,  0, -1,  1); vertIdx++; /* 5 */
384
  }
385
386
  vertIdx = 0;
387
  if (sharpEdge) {
388
    ELL_3V_SET(pld->indx + vertIdx,  0,  8,  4); vertIdx += 3; /* 0 */
389
    ELL_3V_SET(pld->indx + vertIdx,  1, 15,  9); vertIdx += 3; /* 1 */
390
    ELL_3V_SET(pld->indx + vertIdx,  2, 16, 12); vertIdx += 3; /* 2 */
391
    ELL_3V_SET(pld->indx + vertIdx,  3,  6, 19); vertIdx += 3; /* 3 */
392
    ELL_3V_SET(pld->indx + vertIdx,  5, 11, 23); vertIdx += 3; /* 4 */
393
    ELL_3V_SET(pld->indx + vertIdx, 10, 14, 20); vertIdx += 3; /* 5 */
394
    ELL_3V_SET(pld->indx + vertIdx, 17, 21, 13); vertIdx += 3; /* 6 */
395
    ELL_3V_SET(pld->indx + vertIdx,  7, 22, 18); vertIdx += 3; /* 7 */
396
  } else {
397
    ELL_3V_SET(pld->indx + vertIdx,  0,  2,  1); vertIdx += 3; /* 0 */
398
    ELL_3V_SET(pld->indx + vertIdx,  0,  3,  2); vertIdx += 3; /* 1 */
399
    ELL_3V_SET(pld->indx + vertIdx,  0,  4,  3); vertIdx += 3; /* 2 */
400
    ELL_3V_SET(pld->indx + vertIdx,  0,  1,  4); vertIdx += 3; /* 3 */
401
    ELL_3V_SET(pld->indx + vertIdx,  1,  2,  5); vertIdx += 3; /* 4 */
402
    ELL_3V_SET(pld->indx + vertIdx,  2,  3,  5); vertIdx += 3; /* 5 */
403
    ELL_3V_SET(pld->indx + vertIdx,  4,  5,  3); vertIdx += 3; /* 6 */
404
    ELL_3V_SET(pld->indx + vertIdx,  1,  5,  4); vertIdx += 3; /* 7 */
405
  }
406
407
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
408
    if (sharpEdge) {
409
      float cn;
410
      cn = AIR_CAST(float, 1.0/sqrt(3));
411
      /* 0 */
412
      ELL_3V_SET(pld->norm +  3*0,  cn,  cn,  cn);
413
      ELL_3V_SET(pld->norm +  3*8,  cn,  cn,  cn);
414
      ELL_3V_SET(pld->norm +  3*4,  cn,  cn,  cn);
415
      /* 1 */
416
      ELL_3V_SET(pld->norm +  3*1,  cn, -cn,  cn);
417
      ELL_3V_SET(pld->norm + 3*15,  cn, -cn,  cn);
418
      ELL_3V_SET(pld->norm +  3*9,  cn, -cn,  cn);
419
      /* 2 */
420
      ELL_3V_SET(pld->norm +  3*2, -cn, -cn,  cn);
421
      ELL_3V_SET(pld->norm + 3*16, -cn, -cn,  cn);
422
      ELL_3V_SET(pld->norm + 3*12, -cn, -cn,  cn);
423
      /* 3 */
424
      ELL_3V_SET(pld->norm +  3*3, -cn,  cn,  cn);
425
      ELL_3V_SET(pld->norm +  3*6, -cn,  cn,  cn);
426
      ELL_3V_SET(pld->norm + 3*19, -cn,  cn,  cn);
427
      /* 4 */
428
      ELL_3V_SET(pld->norm +  3*5,  cn,  cn, -cn);
429
      ELL_3V_SET(pld->norm + 3*11,  cn,  cn, -cn);
430
      ELL_3V_SET(pld->norm + 3*23,  cn,  cn, -cn);
431
      /* 5 */
432
      ELL_3V_SET(pld->norm + 3*10,  cn, -cn, -cn);
433
      ELL_3V_SET(pld->norm + 3*14,  cn, -cn, -cn);
434
      ELL_3V_SET(pld->norm + 3*20,  cn, -cn, -cn);
435
      /* 6 */
436
      ELL_3V_SET(pld->norm + 3*17, -cn, -cn, -cn);
437
      ELL_3V_SET(pld->norm + 3*21, -cn, -cn, -cn);
438
      ELL_3V_SET(pld->norm + 3*13, -cn, -cn, -cn);
439
      /* 7 */
440
      ELL_3V_SET(pld->norm +  3*7, -cn,  cn, -cn);
441
      ELL_3V_SET(pld->norm + 3*22, -cn,  cn, -cn);
442
      ELL_3V_SET(pld->norm + 3*18, -cn,  cn, -cn);
443
    } else {
444
      ELL_3V_SET(pld->norm + 3*0,  0,  0,  1); /* 0 */
445
      ELL_3V_SET(pld->norm + 3*1,  0,  1,  0); /* 1 */
446
      ELL_3V_SET(pld->norm + 3*2,  1,  0,  0); /* 2 */
447
      ELL_3V_SET(pld->norm + 3*3,  0, -1,  0); /* 3 */
448
      ELL_3V_SET(pld->norm + 3*4, -1,  0,  0); /* 4 */
449
      ELL_3V_SET(pld->norm + 3*5,  0,  0, -1); /* 5 */
450
    }
451
  }
452
453
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
454
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
455
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
456
    }
457
  }
458
  return 0;
459
}
460
461
int
462
limnPolyDataCylinder(limnPolyData *pld,
463
                     unsigned int infoBitFlag,
464
                     unsigned int thetaRes, int sharpEdge) {
465
  static const char me[]="limnPolyDataCylinder";
466
  unsigned int vertNum, primNum, primIdx, indxNum, thetaIdx, vertIdx, blah;
467
  double theta, cth, sth, sq2;
468
469
  /* sanity bounds */
470
  thetaRes = AIR_MAX(3, thetaRes);
471
472
  vertNum = sharpEdge ? 4*thetaRes : 2*thetaRes;
473
  primNum = 3;
474
  indxNum = 2*thetaRes + 2*(thetaRes+1);  /* 2 fans + 1 strip */
475
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
476
    biffAddf(LIMN, "%s: couldn't allocate output", me);
477
    return 1;
478
  }
479
480
  vertIdx = 0;
481
  for (blah=0; blah < (sharpEdge ? 2u : 1u); blah++) {
482
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
483
      theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
484
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
485
                    cos(theta), sin(theta), 1, 1);
486
      /*
487
      fprintf(stderr, "!%s: vert[%u] = %g %g %g\n", me, vertIdx,
488
              (pld->xyzw + 4*vertIdx)[0],
489
              (pld->xyzw + 4*vertIdx)[1],
490
              (pld->xyzw + 4*vertIdx)[2]);
491
      */
492
      ++vertIdx;
493
    }
494
  }
495
  for (blah=0; blah < (sharpEdge ? 2u : 1u); blah++) {
496
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
497
      theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
498
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
499
                    cos(theta), sin(theta), -1, 1);
500
      /*
501
      fprintf(stderr, "!%s: vert[%u] = %g %g %g\n", me, vertIdx,
502
              (pld->xyzw + 4*vertIdx)[0],
503
              (pld->xyzw + 4*vertIdx)[1],
504
              (pld->xyzw + 4*vertIdx)[2]);
505
      */
506
      ++vertIdx;
507
    }
508
  }
509
510
  primIdx = 0;
511
  vertIdx = 0;
512
  /* fan on top */
513
  /* fprintf(stderr, "!%s: fan on top:\n", me); */
514
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
515
    /* fprintf(stderr, "!%s:   indx[%u] = %u\n", me, vertIdx, thetaIdx); */
516
    pld->indx[vertIdx++] = thetaIdx;
517
  }
518
  pld->type[primIdx] = limnPrimitiveTriangleFan;
519
  pld->icnt[primIdx] = thetaRes;
520
  primIdx++;
521
522
  /* single strip around */
523
  /* fprintf(stderr, "!%s: strip around:\n", me); */
524
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
525
    /*
526
    fprintf(stderr, "!%s:   indx[%u] = %u\n", me, vertIdx,
527
            (sharpEdge ? 1 : 0)*thetaRes + thetaIdx);
528
    */
529
    pld->indx[vertIdx++] = (sharpEdge ? 1 : 0)*thetaRes + thetaIdx;
530
    /*
531
    fprintf(stderr, "!%s:   indx[%u] = %u\n", me, vertIdx,
532
            (sharpEdge ? 2 : 1)*thetaRes + thetaIdx);
533
    */
534
    pld->indx[vertIdx++] = (sharpEdge ? 2 : 1)*thetaRes + thetaIdx;
535
  }
536
  /*
537
  fprintf(stderr, "!%s:   indx[%u] = %u\n", me, vertIdx,
538
          (sharpEdge ? 1 : 0)*thetaRes);
539
  */
540
  pld->indx[vertIdx++] = (sharpEdge ? 1 : 0)*thetaRes;
541
  /*
542
  fprintf(stderr, "!%s:   indx[%u] = %u\n", me, vertIdx,
543
          (sharpEdge ? 2 : 1)*thetaRes);
544
  */
545
  pld->indx[vertIdx++] = (sharpEdge ? 2 : 1)*thetaRes;
546
  pld->type[primIdx] = limnPrimitiveTriangleStrip;
547
  pld->icnt[primIdx] = 2*(thetaRes+1);
548
  primIdx++;
549
550
  /* fan on bottom */
551
  /* fprintf(stderr, "!%s: fan on bottom:\n", me); */
552
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
553
    /*
554
    fprintf(stderr, "!%s:   indx[%u] = %u\n", me, vertIdx,
555
            (sharpEdge ? 3 : 1)*thetaRes + thetaIdx);
556
    */
557
    pld->indx[vertIdx++] = (sharpEdge ? 3 : 1)*thetaRes + thetaIdx;
558
  }
559
  pld->type[primIdx] = limnPrimitiveTriangleFan;
560
  pld->icnt[primIdx] = thetaRes;
561
  primIdx++;
562
563
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
564
    sq2 = sqrt(2.0);
565
    if (sharpEdge) {
566
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
567
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
568
        cth = cos(theta);
569
        sth = sin(theta);
570
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 0*thetaRes),
571
                      float, 0, 0, 1);
572
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 1*thetaRes),
573
                      float, cth, sth, 0);
574
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 2*thetaRes),
575
                      float, cth, sth, 0);
576
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 3*thetaRes),
577
                      float, 0, 0, -1);
578
      }
579
    } else {
580
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
581
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
582
        cth = sq2*cos(theta);
583
        sth = sq2*sin(theta);
584
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 0*thetaRes), float,
585
                      cth, sth, sq2);
586
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 1*thetaRes), float,
587
                      cth, sth, -sq2);
588
      }
589
    }
590
  }
591
592
  if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
593
    if (sharpEdge) {
594
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
595
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 1);
596
        ELL_2V_SET_TT(pld->tex2 + 2*(thetaIdx + 0*thetaRes), float, theta, 0);
597
        ELL_2V_SET_TT(pld->tex2 + 2*(thetaIdx + 1*thetaRes), float, theta, 0);
598
        ELL_2V_SET_TT(pld->tex2 + 2*(thetaIdx + 2*thetaRes), float, theta, 1);
599
        ELL_2V_SET_TT(pld->tex2 + 2*(thetaIdx + 3*thetaRes), float, theta, 1);
600
      }
601
    } else {
602
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
603
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 1);
604
        ELL_2V_SET_TT(pld->tex2 + 2*(thetaIdx + 0*thetaRes), float, theta, 0);
605
        ELL_2V_SET_TT(pld->tex2 + 2*(thetaIdx + 1*thetaRes), float, theta, 1);
606
      }
607
    }
608
  }
609
610
  if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
611
    float xx, yy, tang[3], tlen;
612
    if (sharpEdge) {
613
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
614
        xx = (pld->xyzw + 4*(thetaIdx + 0*thetaRes))[0];
615
        yy = (pld->xyzw + 4*(thetaIdx + 0*thetaRes))[1];
616
        ELL_3V_SET(tang, -yy, xx, 0.0);
617
        ELL_3V_NORM_TT(tang, float, tang, tlen);
618
        ELL_3V_COPY(pld->tang + 3*(thetaIdx + 0*thetaRes), tang);
619
        ELL_3V_COPY(pld->tang + 3*(thetaIdx + 1*thetaRes), tang);
620
        ELL_3V_COPY(pld->tang + 3*(thetaIdx + 2*thetaRes), tang);
621
        ELL_3V_COPY(pld->tang + 3*(thetaIdx + 3*thetaRes), tang);
622
      }
623
    } else {
624
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
625
        xx = (pld->xyzw + 4*(thetaIdx + 0*thetaRes))[0];
626
        yy = (pld->xyzw + 4*(thetaIdx + 0*thetaRes))[1];
627
        ELL_3V_SET(tang, -yy, xx, 0.0);
628
        ELL_3V_NORM_TT(tang, float, tang, tlen);
629
        ELL_3V_COPY(pld->tang + 3*(thetaIdx + 0*thetaRes), tang);
630
        ELL_3V_COPY(pld->tang + 3*(thetaIdx + 1*thetaRes), tang);
631
      }
632
    }
633
  }
634
635
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
636
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
637
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
638
    }
639
  }
640
641
  return 0;
642
}
643
644
int
645
limnPolyDataCone(limnPolyData *pld,
646
                 unsigned int infoBitFlag,
647
                 unsigned int thetaRes, int sharpEdge) {
648
  static const char me[]="limnPolyDataCone";
649
  unsigned int vertNum, primNum, primIdx, indxNum, thetaIdx, vertIdx, blah;
650
  double theta, cth, sth;
651
652
  /* sanity bounds */
653
  thetaRes = AIR_MAX(3, thetaRes);
654
655
  vertNum = sharpEdge ? 3*thetaRes : 1 + thetaRes;
656
  primNum = 2;
657
  indxNum = thetaRes + 2*(thetaRes+1);  /* 1 fans + 1 strip */
658
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
659
    biffAddf(LIMN, "%s: couldn't allocate output", me);
660
    return 1;
661
  }
662
663
  /* top point(s) */
664
  vertIdx = 0;
665
  if (sharpEdge) {
666
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
667
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
668
                    0, 0, 1, 1);
669
      ++vertIdx;
670
    }
671
  } else {
672
    ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
673
                  0, 0, 1, 1);
674
    ++vertIdx;
675
  }
676
  /* bottom edge */
677
  for (blah=0; blah < (sharpEdge ? 2u : 1u); blah++) {
678
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
679
      theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
680
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
681
                    cos(theta), sin(theta), -1, 1);
682
      ++vertIdx;
683
    }
684
  }
685
686
  primIdx = 0;
687
  vertIdx = 0;
688
  /* single strip around */
689
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
690
    pld->indx[vertIdx++] = sharpEdge ? thetaIdx : 0;
691
    pld->indx[vertIdx++] = (sharpEdge ? thetaRes : 1) + thetaIdx;
692
  }
693
  pld->indx[vertIdx++] = 0;
694
  pld->indx[vertIdx++] = sharpEdge ? thetaRes : 1;
695
  pld->type[primIdx] = limnPrimitiveTriangleStrip;
696
  pld->icnt[primIdx] = 2*(thetaRes+1);
697
  primIdx++;
698
699
  /* fan on bottom */
700
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
701
    pld->indx[vertIdx++] = (sharpEdge ? 2*thetaRes : 1) + thetaIdx;
702
  }
703
  pld->type[primIdx] = limnPrimitiveTriangleFan;
704
  pld->icnt[primIdx] = thetaRes;
705
  primIdx++;
706
707
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
708
    double isq3;
709
    isq3 = 1/sqrt(3.0);
710
    if (sharpEdge) {
711
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
712
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
713
        cth = cos(theta);
714
        sth = sin(theta);
715
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 0*thetaRes),
716
                      float, cth*isq3, sth*isq3, isq3);
717
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 1*thetaRes),
718
                      float, cth*isq3, sth*isq3, isq3);
719
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 2*thetaRes),
720
                      float, 0, 0, -1);
721
      }
722
    } else {
723
      ELL_3V_SET_TT(pld->norm + 3*(0), float,
724
                    0, 0, 1);
725
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
726
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
727
        cth = cos(theta);
728
        sth = sin(theta);
729
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 1),
730
                      float, cth*isq3, sth*isq3, -isq3); /* close enough */
731
      }
732
    }
733
  }
734
735
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
736
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
737
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
738
    }
739
  }
740
741
  return 0;
742
}
743
744
/*
745
******** limnPolyDataSuperquadric
746
**
747
** makes a superquadric parameterized around the Z axis
748
*/
749
int
750
limnPolyDataSuperquadric(limnPolyData *pld,
751
                         unsigned int infoBitFlag,
752
                         float alpha, float beta,
753
                         unsigned int thetaRes, unsigned int phiRes) {
754
  static const char me[]="limnPolyDataSuperquadric";
755
  unsigned int vertIdx, vertNum, fanNum, stripNum, primNum, indxNum,
756
    thetaIdx, phiIdx, primIdx;
757
  double theta, phi;
758
759
  /* sanity bounds */
760
  thetaRes = AIR_MAX(3u, thetaRes);
761
  phiRes = AIR_MAX(2u, phiRes);
762
  alpha = AIR_MAX(0.00001f, alpha);
763
  beta = AIR_MAX(0.00001f, beta);
764
765
  vertNum = 2 + thetaRes*(phiRes-1);
766
  fanNum = 2;
767
  stripNum = phiRes-2;
768
  primNum = fanNum + stripNum;
769
  indxNum = (thetaRes+2)*fanNum + 2*(thetaRes+1)*stripNum;
770
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
771
    biffAddf(LIMN, "%s: couldn't allocate output", me);
772
    return 1;
773
  }
774
775
  vertIdx = 0;
776
  ELL_4V_SET(pld->xyzw + 4*vertIdx, 0, 0, 1, 1);
777
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
778
    ELL_3V_SET(pld->norm + 3*vertIdx, 0, 0, 1);
779
  }
780
  ++vertIdx;
781
  for (phiIdx=1; phiIdx<phiRes; phiIdx++) {
782
    double cost, sint, cosp, sinp;
783
    phi = AIR_AFFINE(0, phiIdx, phiRes, 0, AIR_PI);
784
    cosp = cos(phi);
785
    sinp = sin(phi);
786
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
787
      theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
788
      cost = cos(theta);
789
      sint = sin(theta);
790
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
791
                    airSgnPow(cost,alpha) * airSgnPow(sinp,beta),
792
                    airSgnPow(sint,alpha) * airSgnPow(sinp,beta),
793
                    airSgnPow(cosp,beta),
794
                    1.0);
795
      if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
796
        if (1 == alpha && 1 == beta) {
797
          ELL_3V_COPY(pld->norm + 3*vertIdx, pld->xyzw + 4*vertIdx);
798
        } else {
799
          ELL_3V_SET_TT(pld->norm + 3*vertIdx, float,
800
                        2*airSgnPow(cost,2-alpha)*airSgnPow(sinp,2-beta)/beta,
801
                        2*airSgnPow(sint,2-alpha)*airSgnPow(sinp,2-beta)/beta,
802
                        2*airSgnPow(cosp,2-beta)/beta);
803
        }
804
      }
805
      ++vertIdx;
806
    }
807
  }
808
  ELL_4V_SET(pld->xyzw + 4*vertIdx, 0, 0, -1, 1);
809
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
810
    ELL_3V_SET(pld->norm + 3*vertIdx, 0, 0, -1);
811
  }
812
  ++vertIdx;
813
814
  /* triangle fan at top */
815
  vertIdx = 0;
816
  primIdx = 0;
817
  pld->indx[vertIdx++] = 0;
818
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
819
    pld->indx[vertIdx++] = thetaIdx + 1;
820
  }
821
  pld->indx[vertIdx++] = 1;
822
  pld->type[primIdx] = limnPrimitiveTriangleFan;
823
  pld->icnt[primIdx++] = thetaRes + 2;
824
825
  /* tristrips around */
826
  for (phiIdx=1; phiIdx<phiRes-1; phiIdx++) {
827
    /*
828
    fprintf(stderr, "!%s: prim[%u] = vert[%u] =", me, primIdx, vertIdx);
829
    */
830
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
831
      /*
832
      fprintf(stderr, " [%u %u] %u %u",
833
              vertIdx, vertIdx + 1,
834
              (phiIdx-1)*thetaRes + thetaIdx + 1,
835
              phiIdx*thetaRes + thetaIdx + 1);
836
      */
837
      pld->indx[vertIdx++] = (phiIdx-1)*thetaRes + thetaIdx + 1;
838
      pld->indx[vertIdx++] = phiIdx*thetaRes + thetaIdx + 1;
839
    }
840
    /*
841
    fprintf(stderr, " [%u %u] %u %u (%u verts)\n",
842
            vertIdx, vertIdx + 1,
843
            (phiIdx-1)*thetaRes + 1,
844
            phiIdx*thetaRes + 1, 2*(thetaRes+1));
845
    */
846
    pld->indx[vertIdx++] = (phiIdx-1)*thetaRes + 1;
847
    pld->indx[vertIdx++] = phiIdx*thetaRes + 1;
848
    pld->type[primIdx] = limnPrimitiveTriangleStrip;
849
    pld->icnt[primIdx++] = 2*(thetaRes+1);
850
  }
851
852
  /* triangle fan at bottom */
853
  pld->indx[vertIdx++] = vertNum-1;
854
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
855
    pld->indx[vertIdx++] = thetaRes*(phiRes-2) + thetaRes - thetaIdx;
856
  }
857
  pld->indx[vertIdx++] = thetaRes*(phiRes-2) + thetaRes;
858
  pld->type[primIdx] = limnPrimitiveTriangleFan;
859
  pld->icnt[primIdx++] = thetaRes + 2;
860
861
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
862
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
863
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
864
    }
865
  }
866
867
  return 0;
868
}
869
870
/*
871
******** limnPolyDataSpiralBetterquadric
872
**
873
** puts a "betterquadric" into a single spiral triangle strip
874
*/
875
int
876
limnPolyDataSpiralBetterquadric(limnPolyData *pld,
877
                                unsigned int infoBitFlag,
878
                                float alpha, float beta, float cee,
879
                                float minRad,
880
                                unsigned int thetaRes, unsigned int phiRes) {
881
  static const char me[]="limnPolyDataSpiralBetterquadric";
882
  unsigned int vertIdx, vertNum, indxNum, thetaIdx, phiIdx;
883
884
  /* sanity bounds */
885
  thetaRes = AIR_MAX(3u, thetaRes);
886
  phiRes = AIR_MAX(2u, phiRes);
887
  alpha = AIR_MAX(0.00001f, alpha);
888
  beta = AIR_MAX(0.00001f, beta);
889
890
  vertNum = thetaRes*phiRes + 1;
891
  indxNum = 2*thetaRes*(phiRes+1) - 2;
892
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, 1)) {
893
    biffAddf(LIMN, "%s: couldn't allocate output", me);
894
    return 1;
895
  }
896
897
  vertIdx = 0;
898
  for (phiIdx=0; phiIdx<phiRes; phiIdx++) {
899
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
900
      double cost, sint, cosp, sinp, xx, yy, zz;
901
      double phi = (AIR_AFFINE(0, phiIdx, phiRes, 0, AIR_PI)
902
                    + AIR_AFFINE(0, thetaIdx, thetaRes, 0, AIR_PI)/phiRes);
903
      double theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0.0, 2*AIR_PI);
904
      cosp = cos(phi);
905
      sinp = sin(phi);
906
      cost = cos(theta);
907
      sint = sin(theta);
908
      xx = airSgnPow(cost,alpha) * airSgnPow(sinp,beta);
909
      yy = airSgnPow(sint,alpha) * airSgnPow(sinp,beta);
910
      zz = airSgnPow(cosp,beta);
911
      if (cee != beta) {
912
        /* expand profile along y axis to match having beta=cee */
913
        double yp, ymax;
914
        yp = airSgnPow(sin(acos(airSgnPow(zz, 1/cee))), cee);
915
        ymax = airSgnPow(sinp, beta);
916
        if (ymax) {
917
          yy *= yp/ymax;
918
        }
919
      }
920
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float, xx, yy, zz, 1.0);
921
      if (minRad > 0.0) {
922
        /* add thickness to small radius */
923
        double rr;
924
        xx = (pld->xyzw + 4*vertIdx)[0];
925
        yy = (pld->xyzw + 4*vertIdx)[1];
926
        rr = sqrt(xx*xx + yy*yy);
927
        if (rr) {
928
          (pld->xyzw + 4*vertIdx)[0] *= AIR_CAST(float, AIR_AFFINE(0, rr, 1, minRad/rr, 1/rr));
929
          (pld->xyzw + 4*vertIdx)[1] *= AIR_CAST(float, AIR_AFFINE(0, rr, 1, minRad/rr, 1/rr));
930
        }
931
      }
932
      if (((1 << limnPolyDataInfoNorm) & infoBitFlag)
933
          || ((1 << limnPolyDataInfoTang) & infoBitFlag)) {
934
        double norm[3], nlen;
935
        if (1 == alpha && 1 == beta) {
936
          ELL_3V_COPY(norm, pld->xyzw + 4*vertIdx);
937
        } else {
938
          if (!vertIdx) {
939
            ELL_3V_SET(norm, 0.0, 0.0, 1.0);
940
          } else {
941
            ELL_3V_SET(norm,
942
                       (2*airSgnPow(cost,2-alpha)*airSgnPow(sinp,2-beta)/beta),
943
                       (2*airSgnPow(sint,2-alpha)*airSgnPow(sinp,2-beta)/beta),
944
                       2*airSgnPow(cosp,2-beta)/beta);
945
          }
946
        }
947
        if ((nlen = ELL_3V_LEN(norm))) {
948
          ELL_3V_SCALE(norm, 1.0/nlen, norm);
949
        } else {
950
          ELL_3V_SET(norm, 0.0, 0.0, 1.0);
951
        }
952
        if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
953
          ELL_3V_COPY_TT(pld->norm + 3*vertIdx, float, norm);
954
        }
955
        if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
956
          double tang[3], tlen;
957
          ELL_3V_SET(tang, -norm[1], norm[0], 0.0);
958
          if ((tlen = ELL_3V_LEN(tang))) {
959
            ELL_3V_SCALE(tang, 1.0/tlen, tang);
960
          } else {
961
            ELL_3V_SET(tang, 1.0, 0.0, 0.0);
962
          }
963
          ELL_3V_COPY_TT(pld->tang + 3*vertIdx, float, tang);
964
        }
965
      }
966
      if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
967
        ELL_2V_SET_TT(pld->tex2 + 2*vertIdx, float,
968
                      AIR_AFFINE(0.0, theta, 2*AIR_PI, 0.0, 1.0),
969
                      AIR_AFFINE(0.0, phi, AIR_PI, 0.0, 1.0));
970
      }
971
      ++vertIdx;
972
    }
973
  }
974
  ELL_4V_SET(pld->xyzw + 4*vertIdx, 0, 0, -1, 1);
975
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
976
    ELL_3V_SET(pld->norm + 3*vertIdx, 0.0, 0.0, -1.0);
977
  }
978
  if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
979
    ELL_2V_SET(pld->tex2 + 2*vertIdx, 0.5, 1.0);
980
  }
981
  if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
982
    ELL_3V_SET(pld->tang + 3*vertIdx, 1.0, 0.0, 0.0);
983
  }
984
  ++vertIdx;
985
986
  /* single triangle strip */
987
  pld->type[0] = limnPrimitiveTriangleStrip;
988
  pld->icnt[0] = indxNum;
989
  vertIdx = 0;
990
  for (thetaIdx=1; thetaIdx<thetaRes; thetaIdx++) {
991
    pld->indx[vertIdx++] = 0;
992
    pld->indx[vertIdx++] = thetaIdx;
993
  }
994
  for (phiIdx=0; phiIdx<phiRes-1; phiIdx++) {
995
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
996
      pld->indx[vertIdx++] = ((phiIdx + 0) * thetaRes) + thetaIdx;
997
      pld->indx[vertIdx++] = ((phiIdx + 1) * thetaRes) + thetaIdx;
998
    }
999
  }
1000
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
1001
    pld->indx[vertIdx++] = (phiRes - 1)*thetaRes + thetaIdx;
1002
    pld->indx[vertIdx++] = (phiRes - 0)*thetaRes;
1003
  }
1004
#if 0
1005
  if ( (cee != beta || minRad > 0.0)
1006
       && ((1 << limnPolyDataInfoNorm) & infoBitFlag) ) {
1007
    /* have deformed object in some way that confounds analytic normals */
1008
    if (limnPolyDataVertexNormals(pld)) {
1009
      biffAddf(LIMN, "%s: trouble getting normals", me); return 1;
1010
    }
1011
  }
1012
#endif
1013
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
1014
    for (vertIdx=0; vertIdx<pld->rgbaNum; vertIdx++) {
1015
      ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
1016
    }
1017
  }
1018
1019
  return 0;
1020
}
1021
1022
/*
1023
******** limnPolyDataSpiralSuperquadric
1024
**
1025
** puts a superquadric into a single spiral triangle strip
1026
*/
1027
int
1028
limnPolyDataSpiralSuperquadric(limnPolyData *pld,
1029
                               unsigned int infoBitFlag,
1030
                               float alpha, float beta,
1031
                               unsigned int thetaRes, unsigned int phiRes) {
1032
  static const char me[]="limnPolyDataSpiralSuperquadric";
1033
1034
  if (limnPolyDataSpiralBetterquadric(pld, infoBitFlag,
1035
                                      alpha, beta, beta, 0.0,
1036
                                      thetaRes, phiRes)) {
1037
    biffAddf(LIMN, "%s: trouble", me); return 1;
1038
  }
1039
  return 0;
1040
}
1041
1042
/*
1043
******** limnPolyDataPolarSphere
1044
**
1045
** makes a unit sphere, centered at the origin, parameterized around Z axis
1046
*/
1047
int
1048
limnPolyDataPolarSphere(limnPolyData *pld,
1049
                        unsigned int infoBitFlag,
1050
                        unsigned int thetaRes, unsigned int phiRes) {
1051
  static const char me[]="limnPolyDataPolarSphere";
1052
1053
  if (limnPolyDataSuperquadric(pld, infoBitFlag,
1054
                               1.0, 1.0, thetaRes, phiRes)) {
1055
    biffAddf(LIMN, "%s: trouble", me);
1056
    return 1;
1057
  }
1058
  return 0;
1059
}
1060
1061
int
1062
limnPolyDataSpiralSphere(limnPolyData *pld,
1063
                         unsigned int infoBitFlag,
1064
                         unsigned int thetaRes,
1065
                         unsigned int phiRes) {
1066
  static const char me[]="limnPolyDataSpiralSphere";
1067
1068
  if (limnPolyDataSpiralSuperquadric(pld, infoBitFlag,
1069
                                     1.0, 1.0, thetaRes, phiRes)) {
1070
    biffAddf(LIMN, "%s: trouble", me);
1071
    return 1;
1072
  }
1073
  return 0;
1074
}
1075
1076
/* Geometry for an icosahedron */
1077
#define ICO_ONE 0.5257311121f
1078
#define ICO_TAU 0.8506508084f
1079
static float icovertices[36] = {
1080
  0.0f, ICO_ONE, ICO_TAU,  0.0f, -ICO_ONE, -ICO_TAU,
1081
  0.0f, -ICO_ONE, ICO_TAU,  0.0f, ICO_ONE, -ICO_TAU,
1082
  ICO_ONE, ICO_TAU, 0.0f,  -ICO_ONE, -ICO_TAU, 0.0f,
1083
  ICO_ONE, -ICO_TAU, 0.0f, -ICO_ONE, ICO_TAU, 0.0f,
1084
  ICO_TAU, 0.0f, ICO_ONE,  -ICO_TAU, 0.0f, -ICO_ONE,
1085
  -ICO_TAU, 0.0f, ICO_ONE,  ICO_TAU, 0.0f, -ICO_ONE
1086
};
1087
#undef ICO_ONE
1088
#undef ICO_TAU
1089
1090
static unsigned int icoedges[60] = {
1091
  0, 2,  1, 3,  0, 4,  1, 5,  0, 8,  1, 9,  0, 10,  1, 11, /* 0-7 */
1092
  0, 7,  1, 6,  2, 6,  3, 7,  2, 8,  3, 9,  2, 10,  3, 11, /* 8-15 */
1093
  2, 5,  3, 4,  4, 8,  5, 9,  4, 7,  5, 6,  4, 11,  5, 10, /* 16-23*/
1094
  6, 8,  7, 9,  6, 11,  7, 10,  8, 11,  9, 10 /* 24-29 */
1095
};
1096
1097
static unsigned int icofaces[60] = {
1098
  0, 4, 12,   1, 5, 13,   0, 6, 14,   1, 7, 15,
1099
  6, 8, 27,   7, 9, 26,   2, 4, 18,   3, 5, 19,
1100
  10, 12, 24,   11, 13, 25,   14, 16, 23,   15, 17, 22,
1101
  2, 8, 20,   3, 9, 21,   10, 16, 21,   11, 17, 20,
1102
  24, 26, 28,   25, 27, 29,   18, 22, 28,   19, 23, 29
1103
};
1104
1105
/*
1106
******** limnPolyDataIcoSphere
1107
**
1108
** Makes a unit sphere, centered at the origin, by refining an icosahedron
1109
** level times. Each refinement step subdivides each edge at its center,
1110
** turning each triangle into four smaller ones.
1111
**
1112
** In the output, vertex 2*i and 2*i+1 are antipodal points, which allows for
1113
** a more efficient implementation of operations that produce the same or
1114
** a mirrored result for antipodal points (e.g., tensor glyphs).
1115
*/
1116
1117
int
1118
limnPolyDataIcoSphere(limnPolyData *pld,
1119
                      unsigned int infoBitFlag,
1120
                      unsigned int level) {
1121
  static const char me[]="limnPolyDataIcoSphere";
1122
  unsigned int vertNum=12, edgeNum=30, faceNum=20, center;
1123
  float *verts, *xyzwp, *vertp;
1124
  unsigned char *rgbap;
1125
  unsigned int *edges, *faces;
1126
  unsigned int i,e,f; /* loop counters */
1127
  airArray *mop; /* free memory in case of allocation error */
1128
1129
  /* sanity checks */
1130
  if (!pld) {
1131
    biffAddf(LIMN, "%s: got NULL pointer", me);
1132
    return 1;
1133
  }
1134
  mop = airMopNew();
1135
1136
  /* x/y/z positions */
1137
  verts = (float *) malloc (sizeof(float)*12*3);
1138
  if (verts==NULL) goto error_and_exit;
1139
  airMopAdd(mop, verts, airFree, airMopAlways);
1140
  memcpy(verts,icovertices,sizeof(float)*12*3);
1141
  /* endpoints for each edge */
1142
  edges = (unsigned int *) malloc (sizeof(unsigned int)*30*2);
1143
  if (edges==NULL) goto error_and_exit;
1144
  airMopAdd(mop, edges, airFree, airMopAlways);
1145
  memcpy(edges,icoedges,sizeof(unsigned int)*60);
1146
  /* vertices of each face */
1147
  faces = (unsigned int *) malloc (sizeof(unsigned int)*20*3);
1148
  if (faces==NULL) goto error_and_exit;
1149
  airMopAdd(mop, faces, airFree, airMopAlways);
1150
  memcpy(faces,icofaces,sizeof(unsigned int)*60);
1151
1152
  for (i=0; i<level; ++i) {
1153
    /* subdivision step */
1154
    unsigned int nvertNum=vertNum+edgeNum;
1155
    unsigned int nedgeNum=2*edgeNum+3*faceNum;
1156
    unsigned int nfaceNum=4*faceNum;
1157
    float *newverts;
1158
    unsigned int *newedges, *newfaces;
1159
    newverts = (float *) malloc(sizeof(float)*3*nvertNum);
1160
    if (newverts==NULL) goto error_and_exit;
1161
    airMopAdd(mop, newverts, airFree, airMopAlways);
1162
    newedges = (unsigned int *) malloc(sizeof(unsigned int)*2*nedgeNum);
1163
    if (newedges==NULL) goto error_and_exit;
1164
    airMopAdd(mop, newedges, airFree, airMopAlways);
1165
    newfaces = (unsigned int *) malloc(sizeof(unsigned int)*3*nfaceNum);
1166
    if (newfaces==NULL) goto error_and_exit;
1167
    airMopAdd(mop, newfaces, airFree, airMopAlways);
1168
    memcpy(newverts, verts, sizeof(float)*3*vertNum);
1169
    for (e=0; e<edgeNum; e+=2) { /* split both edge and anti-edge */
1170
      float norm;
1171
      ELL_3V_ADD2(newverts+3*(vertNum+e), verts+3*(edges[2*e]),
1172
                  verts+3*(edges[2*e+1]));
1173
      /* project new vertex to unit sphere */
1174
      ELL_3V_NORM_TT(newverts+3*(vertNum+e),float,newverts+3*(vertNum+e),norm);
1175
      ELL_3V_SCALE_TT(newverts+3*(vertNum+e+1),float,-1.0,newverts+3*(vertNum+e));
1176
      /* split the edges such that anti-edge follows edge */
1177
      newedges[4*e]=edges[2*e];
1178
      newedges[4*e+1]=vertNum+e;
1179
      newedges[4*e+2]=edges[2*e+2];
1180
      newedges[4*e+3]=vertNum+e+1;
1181
1182
      newedges[4*e+4]=vertNum+e;
1183
      newedges[4*e+5]=edges[2*e+1];
1184
      newedges[4*e+6]=vertNum+e+1;
1185
      newedges[4*e+7]=edges[2*e+3];
1186
    }
1187
    for (f=0; f<faceNum; f+=2) { /* split both face and anti-face */
1188
      unsigned int oldedge11=faces[3*f], oldedge12=faces[3*f+1],
1189
        oldedge13=faces[3*f+2], oldedge21=faces[3*f+3],
1190
        oldedge22=faces[3*f+4], oldedge23=faces[3*f+5];
1191
      unsigned int eidx=2*edgeNum+3*f; /* index of the first edge to add */
1192
      char pol11=0, pol12=0, pol13=0, pol21=0, pol22=0, pol23=0; /* polarity */
1193
      /* add three edges per face - anti-edge has to follow edge! */
1194
      newedges[2*eidx]=newedges[2*eidx+9]=vertNum+oldedge11;
1195
      newedges[2*eidx+1]=newedges[2*eidx+4]=vertNum+oldedge12;
1196
      newedges[2*eidx+5]=newedges[2*eidx+8]=vertNum+oldedge13;
1197
      newedges[2*eidx+2]=newedges[2*eidx+11]=vertNum+oldedge21;
1198
      newedges[2*eidx+3]=newedges[2*eidx+6]=vertNum+oldedge22;
1199
      newedges[2*eidx+7]=newedges[2*eidx+10]=vertNum+oldedge23;
1200
      /* split the faces - we do not have directed half-edges!
1201
       * determine the "polarity" of the edges (0 forward / 2 backward) */
1202
      if (edges[2*oldedge11+1]==edges[2*oldedge13+1] ||
1203
          edges[2*oldedge11+1]==edges[2*oldedge13])
1204
        pol11=2;
1205
      if (edges[2*oldedge12+1]==edges[2*oldedge11+1] ||
1206
          edges[2*oldedge12+1]==edges[2*oldedge11])
1207
        pol12=2;
1208
      if (edges[2*oldedge13+1]==edges[2*oldedge12+1] ||
1209
          edges[2*oldedge13+1]==edges[2*oldedge12])
1210
        pol13=2;
1211
      if (edges[2*oldedge21+1]==edges[2*oldedge23+1] ||
1212
          edges[2*oldedge21+1]==edges[2*oldedge23])
1213
        pol21=2;
1214
      if (edges[2*oldedge22+1]==edges[2*oldedge21+1] ||
1215
          edges[2*oldedge22+1]==edges[2*oldedge21])
1216
        pol22=2;
1217
      if (edges[2*oldedge23+1]==edges[2*oldedge22+1] ||
1218
          edges[2*oldedge23+1]==edges[2*oldedge22])
1219
        pol23=2;
1220
1221
      newfaces[12*f] = 2*oldedge11-(oldedge11%2)+pol11; /* bottom/left */
1222
      newfaces[12*f+1] = eidx+4;
1223
      newfaces[12*f+2] = 2*oldedge13-(oldedge13%2)+2-pol13;
1224
      newfaces[12*f+3] = 2*oldedge21-(oldedge21%2)+pol21; /* anti */
1225
      newfaces[12*f+4] = eidx+5;
1226
      newfaces[12*f+5] = 2*oldedge23-(oldedge23%2)+2-pol23;
1227
1228
      newfaces[12*f+6] = 2*oldedge11-(oldedge11%2)+2-pol11; /* bottom/right */
1229
      newfaces[12*f+7] = 2*oldedge12-(oldedge12%2)+pol12;
1230
      newfaces[12*f+8] = eidx;
1231
      newfaces[12*f+9] = 2*oldedge21-(oldedge21%2)+2-pol21; /* anti */
1232
      newfaces[12*f+10]= 2*oldedge22-(oldedge22%2)+pol22;
1233
      newfaces[12*f+11]= eidx+1;
1234
1235
      newfaces[12*f+12]= 2*oldedge12-(oldedge12%2)+2-pol12; /* top */
1236
      newfaces[12*f+13]= 2*oldedge13-(oldedge13%2)+pol13;
1237
      newfaces[12*f+14]= eidx+2;
1238
      newfaces[12*f+15]= 2*oldedge22-(oldedge22%2)+2-pol22; /* anti */
1239
      newfaces[12*f+16]= 2*oldedge23-(oldedge23%2)+pol23;
1240
      newfaces[12*f+17]= eidx+3;
1241
1242
      newfaces[12*f+18]= eidx; /* center */
1243
      newfaces[12*f+19]= eidx+2;
1244
      newfaces[12*f+20]= eidx+4;
1245
      newfaces[12*f+21]= eidx+1; /* anti */
1246
      newfaces[12*f+22]= eidx+3;
1247
      newfaces[12*f+23]= eidx+5;
1248
    }
1249
    /* make subdivided mesh the current one */
1250
    airMopSub(mop, verts, airFree);
1251
    airMopSub(mop, edges, airFree);
1252
    airMopSub(mop, faces, airFree);
1253
    free(verts); free(edges); free(faces);
1254
    verts=newverts; edges=newedges; faces=newfaces;
1255
    vertNum=nvertNum; edgeNum=nedgeNum; faceNum=nfaceNum;
1256
  }
1257
  /* done; now copy to a limnPolyData struct */
1258
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, 3*faceNum, 1)) {
1259
    biffAddf(LIMN, "%s: couldn't allocate output", me);
1260
    return 1;
1261
  }
1262
  xyzwp=pld->xyzw; vertp=verts;
1263
  for (i=0; i<vertNum; i++) {
1264
    ELL_4V_SET(xyzwp, vertp[0], vertp[1], vertp[2], 1.0);
1265
    xyzwp+=4; vertp+=3;
1266
  }
1267
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
1268
    /* normals equal the vertex coordinates */
1269
    memcpy(pld->norm, verts, sizeof(float)*3*vertNum);
1270
  }
1271
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
1272
    rgbap=pld->rgba; vertp=verts;
1273
    for (i=0; i<vertNum; i++) {
1274
      ELL_4V_SET_TT(rgbap, unsigned char, 255, 255, 255, 255);
1275
      rgbap+=4; vertp+=3;
1276
    }
1277
  }
1278
  if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
1279
    for (i=0; i<vertNum; i++) {
1280
      double rr, xyz[3], phi, theta;
1281
      ELL_3V_COPY(xyz, pld->xyzw + 4*i);
1282
      rr = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1]);
1283
      phi = atan2(rr, xyz[2]);
1284
      theta = atan2(xyz[1], xyz[0]);
1285
      ELL_2V_SET_TT(pld->tex2 + 2*i, float,
1286
                    AIR_AFFINE(-AIR_PI, theta, AIR_PI, 0.0, 1.0),
1287
                    AIR_AFFINE(0.0, phi, AIR_PI, 0.0, 1.0));
1288
    }
1289
  }
1290
  if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
1291
    for (i=0; i<vertNum; i++) {
1292
      double rr, xyz[3], tang[3], len;
1293
      ELL_3V_COPY(xyz, pld->xyzw + 4*i);
1294
      rr = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1]);
1295
      if (rr) {
1296
        ELL_3V_SET(tang, -xyz[1], xyz[0], 0.0);
1297
        ELL_3V_NORM_TT(pld->tang + 3*i, float, tang, len);
1298
      } else {
1299
        ELL_3V_SET(pld->tang + 3*i, 1.0f, 0.0f, 0.0f);
1300
      }
1301
    }
1302
  }
1303
1304
  /* We need to replace reference to edges in faces with references to
1305
   * vertices. Make sure that they are ordered CCW */
1306
  pld->type[0] = limnPrimitiveTriangles;
1307
  pld->icnt[0] = faceNum*3;
1308
  for (f=0; f<faceNum; ++f) {
1309
    unsigned int vertices[3]; /* find the right vertices */
1310
    float diff1[3],diff2[3],cross[3];
1311
    vertices[0]=edges[2*faces[3*f]];
1312
    vertices[1]=edges[2*faces[3*f]+1];
1313
    if (edges[2*faces[3*f+1]]==vertices[0] ||
1314
        edges[2*faces[3*f+1]]==vertices[1])
1315
      vertices[2]=edges[2*faces[3*f+1]+1];
1316
    else
1317
      vertices[2]=edges[2*faces[3*f+1]];
1318
    /* put them into correct order */
1319
    ELL_3V_SUB(diff1,verts+3*vertices[1],verts+3*vertices[0]);
1320
    ELL_3V_SUB(diff2,verts+3*vertices[2],verts+3*vertices[0]);
1321
    ELL_3V_CROSS(cross,diff1,diff2);
1322
    pld->indx[3*f]=vertices[0];
1323
    if (ELL_3V_DOT(cross,verts+3*vertices[0])<0) {
1324
      pld->indx[3*f+1]=vertices[2];
1325
      pld->indx[3*f+2]=vertices[1];
1326
    } else {
1327
      pld->indx[3*f+1]=vertices[1];
1328
      pld->indx[3*f+2]=vertices[2];
1329
    }
1330
  }
1331
  /* re-order the triangles */
1332
  center=3*(faceNum/2);
1333
  for (i=0; i<faceNum/2; i++) {
1334
    ELL_3V_COPY(faces+3*i,pld->indx+6*i);
1335
    ELL_3V_COPY(faces+center+3*i,pld->indx+6*i+3);
1336
  }
1337
  airMopAdd(mop, pld->indx, airFree, airMopAlways);
1338
  airMopSub(mop, faces, airFree);
1339
  pld->indx=faces;
1340
  /* done */
1341
  airMopOkay(mop);
1342
  return 0;
1343
 error_and_exit:
1344
  biffAddf(LIMN, "%s: memory allocation failed", me);
1345
  airMopError(mop);
1346
  return 1;
1347
}
1348
1349
int
1350
limnPolyDataPlane(limnPolyData *pld,
1351
                  unsigned int infoBitFlag,
1352
                  unsigned int uRes, unsigned int vRes) {
1353
  static const char me[]="limnPolyDataPlane";
1354
  unsigned int vertNum, indxNum, primNum, uIdx, vIdx, vertIdx, primIdx;
1355
  float uu, vv;
1356
1357
  /* sanity */
1358
  uRes = AIR_MAX(2, uRes);
1359
  vRes = AIR_MAX(2, vRes);
1360
1361
  vertNum = uRes*vRes;
1362
  primNum = vRes-1;
1363
  indxNum = primNum*2*uRes;
1364
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
1365
    biffAddf(LIMN, "%s: couldn't allocate output", me);
1366
    return 1;
1367
  }
1368
1369
  vertIdx = 0;
1370
  for (vIdx=0; vIdx<vRes; vIdx++) {
1371
    vv = AIR_CAST(float, AIR_AFFINE(0, vIdx, vRes-1, -1.0, 1.0));
1372
    for (uIdx=0; uIdx<uRes; uIdx++) {
1373
      uu = AIR_CAST(float, AIR_AFFINE(0, uIdx, uRes-1, -1.0, 1.0));
1374
      ELL_4V_SET(pld->xyzw + 4*vertIdx, uu, vv, 0.0, 1.0);
1375
      if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
1376
        ELL_3V_SET_TT(pld->norm + 3*vertIdx, float, 0.0, 0.0, 1.0);
1377
      }
1378
      if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
1379
        ELL_4V_SET(pld->rgba + 4*vertIdx, 255, 255, 255, 255);
1380
      }
1381
      if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
1382
        ELL_2V_SET_TT(pld->tex2 + 2*vertIdx, float, (uu+1.0)/2.0, (vv+1.0)/2.0);
1383
      }
1384
      if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
1385
        ELL_3V_SET_TT(pld->tang + 3*vertIdx, float, 1.0, 0.0, 0.0);
1386
      }
1387
      ++vertIdx;
1388
    }
1389
  }
1390
1391
  vertIdx = 0;
1392
  for (primIdx=0; primIdx<primNum; primIdx++) {
1393
    for (uIdx=0; uIdx<uRes; uIdx++) {
1394
      pld->indx[vertIdx++] = uIdx + uRes*(primIdx+1);
1395
      pld->indx[vertIdx++] = uIdx + uRes*(primIdx);
1396
    }
1397
    pld->type[primIdx] = limnPrimitiveTriangleStrip;
1398
    pld->icnt[primIdx] = 2*uRes;
1399
  }
1400
1401
  return 0;
1402
}
1403
1404
int
1405
limnPolyDataSquare(limnPolyData *pld, unsigned int infoBitFlag) {
1406
  static const char me[]="limnPolyDataSquare";
1407
1408
  if (limnPolyDataAlloc(pld, infoBitFlag, 4, 4, 1)) {
1409
    biffAddf(LIMN, "%s: couldn't allocate output", me);
1410
    return 1;
1411
  }
1412
  ELL_4V_SET(pld->xyzw + 4*0, -1.0, -1.0, 0.0, 1.0);
1413
  ELL_4V_SET(pld->xyzw + 4*1,  1.0, -1.0, 0.0, 1.0);
1414
  ELL_4V_SET(pld->xyzw + 4*2, -1.0,  1.0, 0.0, 1.0);
1415
  ELL_4V_SET(pld->xyzw + 4*3,  1.0,  1.0, 0.0, 1.0);
1416
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
1417
    ELL_3V_SET(pld->norm + 3*0, 0.0, 0.0, 1.0);
1418
    ELL_3V_SET(pld->norm + 3*1, 0.0, 0.0, 1.0);
1419
    ELL_3V_SET(pld->norm + 3*2, 0.0, 0.0, 1.0);
1420
    ELL_3V_SET(pld->norm + 3*3, 0.0, 0.0, 1.0);
1421
  }
1422
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
1423
    ELL_4V_SET(pld->rgba + 4*0, 255, 255, 255, 255);
1424
    ELL_4V_SET(pld->rgba + 4*1, 255, 255, 255, 255);
1425
    ELL_4V_SET(pld->rgba + 4*2, 255, 255, 255, 255);
1426
    ELL_4V_SET(pld->rgba + 4*3, 255, 255, 255, 255);
1427
  }
1428
  if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
1429
    ELL_2V_SET(pld->tex2 + 2*0, 0.0, 1.0);
1430
    ELL_2V_SET(pld->tex2 + 2*1, 1.0, 1.0);
1431
    ELL_2V_SET(pld->tex2 + 2*2, 0.0, 0.0);
1432
    ELL_2V_SET(pld->tex2 + 2*3, 1.0, 0.0);
1433
  }
1434
  if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
1435
    ELL_3V_SET(pld->tang + 3*0, 1.0, 0.0, 0.0);
1436
    ELL_3V_SET(pld->tang + 3*1, 1.0, 0.0, 0.0);
1437
    ELL_3V_SET(pld->tang + 3*2, 1.0, 0.0, 0.0);
1438
    ELL_3V_SET(pld->tang + 3*3, 1.0, 0.0, 0.0);
1439
  }
1440
  pld->type[0] = limnPrimitiveTriangleStrip;
1441
  ELL_4V_SET(pld->indx, 0, 1, 2, 3);
1442
  pld->icnt[0] = 4;
1443
1444
  return 0;
1445
}
1446
1447
int
1448
limnPolyDataSuperquadric2D(limnPolyData *pld,
1449
                           unsigned int infoBitFlag,
1450
                           float alpha, unsigned int res) {
1451
  static const char me[]="limnPolyDataSuperquadric2D";
1452
  unsigned int i, vertNum;
1453
  float phi;
1454
1455
  vertNum = res+1; /* initial vertex at origin */
1456
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum,
1457
                        vertNum+1, /* last index wraps around */
1458
                        1)) {
1459
    biffAddf(LIMN, "%s: couldn't allocate output", me);
1460
    return 1;
1461
  }
1462
  /* initial vertex at origin */
1463
  ELL_4V_SET(pld->xyzw + 4*0, 0.0, 0.0, 0.0, 1.0);
1464
  /* printf("!%s: xyzw[0] = %g %g %g %g\n", me, (pld->xyzw + 4*0)[0], (pld->xyzw + 4*0)[1], (pld->xyzw + 4*0)[2], (pld->xyzw + 4*0)[3]); */
1465
  for (i=1; i<vertNum; i++) {
1466
    phi = AIR_AFFINE(1, i, vertNum, 0, 2*AIR_PI);
1467
    ELL_4V_SET(pld->xyzw + 4*i,
1468
               airSgnPow(cos(phi),alpha),
1469
               airSgnPow(sin(phi),alpha),
1470
               0.0, 1.0);
1471
    /* printf("!%s: xyzw[%u] = %g %g %g %g\n", me, i ,(pld->xyzw + 4*i)[0], (pld->xyzw + 4*i)[1], (pld->xyzw + 4*i)[2], (pld->xyzw + 4*i)[3]); */
1472
  }
1473
  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
1474
    for (i=0; i<vertNum; i++) {
1475
      ELL_3V_SET(pld->norm + 3*i, 0.0, 0.0, 1.0);
1476
    }
1477
  }
1478
  if ((1 << limnPolyDataInfoRGBA) & infoBitFlag) {
1479
    for (i=0; i<vertNum; i++) {
1480
      ELL_4V_SET(pld->rgba + 4*i, 255, 255, 255, 255);
1481
    }
1482
  }
1483
  if ((1 << limnPolyDataInfoTex2) & infoBitFlag) {
1484
    /* punting */
1485
    ELL_2V_COPY(pld->tex2 + 2*i, pld->xyzw + 4*i);
1486
  }
1487
  if ((1 << limnPolyDataInfoTang) & infoBitFlag) {
1488
    /* punting */
1489
    ELL_3V_SET(pld->tang + 3*i, 0.0, 0.0, 0.0);
1490
  }
1491
  pld->type[0] = limnPrimitiveTriangleFan;
1492
  for (i=0; i<vertNum; i++) {
1493
    pld->indx[i] = i;
1494
    /* printf("!%s: idx[%u] = %u\n", me, i, pld->indx[i]); */
1495
  }
1496
  /* very last index loops around to first non-origin point */
1497
  pld->indx[i] = 1;
1498
  /* printf("!%s: idx[%u] = %u\n", me, i, pld->indx[i]); */
1499
  pld->icnt[0] = vertNum+1;
1500
1501
  return 0;
1502
}
1503