/*============================================================================= utils.c =============================================================================== Utility functions =============================================================================*/ #include #include #include #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); } } }