about summary refs log tree commit diff
path: root/generator/pamtris/utils.c
blob: a6b6e7d4b6c27e06df30f822cda786aa8295321a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*=============================================================================
                              utils.c
===============================================================================
   Utility functions
=============================================================================*/

#include <stdlib.h>
#include <stdint.h>
#include <math.h>

#include "limits_pamtris.h"
#include "varying.h"

#include "utils.h"



void
prepare_for_interpolation(const varying * const begin,
                          const varying * const end,
                          varying *       const out,
                          int32_t               num_steps,
                          uint8_t         const elements) {

    double inverse_num_steps;
    unsigned int i;

    if (num_steps < 1) {
        num_steps = 1;
    }

    inverse_num_steps = 1.0 / num_steps;

    for (i = 0; i < elements; i++) {
        out[i].v = begin[i].v;
        out[i].s = (end[i].v - begin[i].v) * inverse_num_steps;
    }
}



varying
compute_varying_z(int32_t const input_z) {

    varying retval;

    retval.v = 1.0 / (1 + input_z - MIN_COORD);
    retval.s = 0.0;

    return retval;
}



void
multiply_varying_array_by_varying(varying * const vars,
                                  varying   const multiplier,
                                  uint8_t   const elements) {

    unsigned int i;

    for (i = 0; i < elements; i++) {
        vars[i].v *= multiplier.v;
	vars[i].s  = 0.0;
    }
}


void
divide_varying_array_by_varying(varying * const vars,
                                varying   const divisor,
                                uint8_t   const elements) {

    double const inverse_divisor = 1.0 / divisor.v;

    unsigned int i;

    for (i = 0; i < elements; i++) {
        vars[i].v *= inverse_divisor;
	vars[i].s  = 0.0;
    }
}



varying
inverse_varying(varying const var) {

    varying retval;

    retval.v = 1.0 / var.v;
    retval.s = 0.0;

    return retval;
}



varying
multiply_varyings(varying const a,
                  varying const b) {

    varying retval;

    retval.v = a.v * b.v;
    retval.s = 0.0;

    return retval;
}



void
step_up(varying * const vars,
        uint8_t   const elements) {

    unsigned int i;

    for (i = 0; i < elements; i++) {
        vars[i].v += vars[i].s;
    }
}



void
multi_step_up(varying * const vars,
              int32_t   const times,
              uint8_t   const elements) {

    unsigned int i;

    for (i = 0; i < elements; i++) {
        vars[i].v += times * vars[i].s;
    }
}



void
int32_to_varying_array(const int32_t * const in,
                       varying *       const out,
                       uint8_t         const elements) {

    unsigned int i;

    for (i = 0; i < elements; i++) {
        out[i].v = in[i];
        out[i].s = 0.0;
    }
}



/* static int64_t
abs64(int64_t x)
{

    int64_t const nm = ~geq_mask64(x, 0);

    return (-x & nm) | (x & ~nm);
} */



int32_t
round_varying(varying const var) {

    return round(var.v);
}



int64_t
geq_mask64(int64_t a, int64_t b) {

    uint64_t const diff = a - b;

    return -((~diff) >> 63);
}



static void
swap(uint8_t * const a,
     uint8_t * const b) {
/*----------------------------------------------------------------------------
  Swap the contents pointed to by a and b.
-----------------------------------------------------------------------------*/
    uint8_t const temp = *a;

    *a = *b;
    *b = temp;
}



void
sort3(uint8_t *       const index_array,
      const int32_t * const y_array,
      const int32_t * const x_array) {
/*----------------------------------------------------------------------------
  Sort an index array of 3 elements. This function is used to sort vertices
  with regard to relative row from top to bottom, but instead of sorting
  an array of vertices with all their coordinates, we simply sort their
  indices. Each element in the array pointed to by "index_array" should
  contain one of the numbers 0, 1 or 2, and each one of them should be
  different. "y_array" should point to an array containing the corresponding
  Y coordinates (row) of each vertex and "x_array" should point to an array
  containing the corresponding X coordinates (column) of each vertex.

  If the Y coordinates are all equal, the indices are sorted with regard to
  relative X coordinate from left to right. If only the top two vertex have
  the same Y coordinate, the array is sorted normally with regard to relative
  Y coordinate, but the first two indices are then sorted with regard to
  relative X coordinate. Finally, If only the bottom two vertex have the same
  Y coordinate, the array is sorted normally with regard to relative Y
  coordinate, but the last two indices are then sorted with regard to relative
  X coordinate.
-----------------------------------------------------------------------------*/
    uint8_t * const ia = index_array;

    const int32_t * ya;
    const int32_t * xa;

    ya = y_array;  /* initial value */
    xa = x_array;  /* initial value */

    if (ya[0] == ya[1] && ya[1] == ya[2]) {
        /* In case the vertices represent a degenerate horizontal triangle, we
           sort according to relative X coordinate, as opposed to Y.
        */
        ya = xa;
    }

    if (ya[ia[2]] < ya[ia[1]]) {
        swap(ia, ia + 2);
        if (ya[ia[2]] < ya[ia[1]]) {
            swap(ia + 1, ia + 2);
            if (ya[ia[1]] < ya[ia[0]]) {
                swap(ia, ia + 1);
            }
        }
    } else if (ya[ia[1]] < ya[ia[0]]) {
        swap(ia, ia + 1);
        if (ya[ia[2]] < ya[ia[1]]) {
            swap(ia + 1, ia + 2);
        }
    }

    if (ya == xa) {
        return;
    }

    if (ya[ia[0]] == ya[ia[1]]) {
        if (xa[ia[1]] < xa[ia[0]]) {
            swap(ia, ia + 1);
        }
    } else if (ya[ia[1]] == ya[ia[2]]) {
        if (xa[ia[2]] < xa[ia[1]]) {
            swap(ia + 1, ia + 2);
        }
    }
}