diff options
Diffstat (limited to 'generator/pamtris/utils.c')
-rw-r--r-- | generator/pamtris/utils.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/generator/pamtris/utils.c b/generator/pamtris/utils.c new file mode 100644 index 00000000..a6b6e7d4 --- /dev/null +++ b/generator/pamtris/utils.c @@ -0,0 +1,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); + } + } +} + + |