about summary refs log tree commit diff
path: root/generator/pamtris/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'generator/pamtris/utils.c')
-rw-r--r--generator/pamtris/utils.c266
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);
+        }
+    }
+}
+
+