]> Pileus Git - grits/blobdiff - src/roam.c
Revert "Test pure distance based errors"
[grits] / src / roam.c
index 4e5775f2d19cceac4f2804f18e80867a43b51e56..0f4995e0b56593d7bf3dc03f4d65015afb847e8e 100644 (file)
@@ -177,15 +177,17 @@ void roam_point_update_projection(RoamPoint *point, RoamView *view)
  *
  * Returns: the new triangle
  */
-RoamTriangle *roam_triangle_new(RoamPoint *l, RoamPoint *m, RoamPoint *r)
+RoamTriangle *roam_triangle_new(RoamPoint *l, RoamPoint *m, RoamPoint *r,
+               RoamDiamond *parent)
 {
        RoamTriangle *triangle = g_new0(RoamTriangle, 1);
 
-       triangle->error = 0;
-       triangle->p.l   = l;
-       triangle->p.m   = m;
-       triangle->p.r   = r;
-       triangle->split = roam_point_new(
+       triangle->error  = 0;
+       triangle->p.l    = l;
+       triangle->p.m    = m;
+       triangle->p.r    = r;
+       triangle->parent = parent;
+       triangle->split  = roam_point_new(
                (l->lat + r->lat)/2,
                (ABS(l->lat) == 90 ? r->lon :
                 ABS(r->lat) == 90 ? l->lon :
@@ -311,12 +313,12 @@ void roam_triangle_remove(RoamTriangle *triangle, RoamSphere *sphere)
        g_pqueue_remove(sphere->triangles, triangle->handle);
 }
 
-static void roam_triangle_sync_neighbors(RoamTriangle *new, RoamTriangle *old, RoamTriangle *neigh)
+/* (neight->t.? == old) = new */
+static void roam_triangle_sync_neighbors(RoamTriangle *neigh, RoamTriangle *old, RoamTriangle *new)
 {
        if      (neigh->t.l == old) neigh->t.l = new;
        else if (neigh->t.b == old) neigh->t.b = new;
        else if (neigh->t.r == old) neigh->t.r = new;
-       else g_assert_not_reached();
 }
 
 static gboolean roam_triangle_visible(RoamTriangle *triangle, RoamSphere *sphere)
@@ -335,6 +337,20 @@ static gboolean roam_triangle_visible(RoamTriangle *triangle, RoamSphere *sphere
                 l->pz < 1 && m->pz < 1 && r->pz < 1;
 }
 
+static gboolean roam_triangle_backface(RoamTriangle *triangle, RoamSphere *sphere)
+{
+       RoamPoint *l = triangle->p.l;
+       RoamPoint *m = triangle->p.m;
+       RoamPoint *r = triangle->p.r;
+       roam_point_update_projection(l, sphere->view);
+       roam_point_update_projection(m, sphere->view);
+       roam_point_update_projection(r, sphere->view);
+       double size = -( l->px * (m->py - r->py) +
+                        m->px * (r->py - l->py) +
+                        r->px * (l->py - m->py) ) / 2.0;
+       return size < 0;
+}
+
 /**
  * roam_triangle_update_errors:
  * @triangle: the triangle
@@ -372,6 +388,12 @@ void roam_triangle_update_errors(RoamTriangle *triangle, RoamSphere *sphere)
 
                /* Size < 0 == backface */
                triangle->error *= size;
+
+               /* Give some preference to "edge" faces */
+               if (roam_triangle_backface(triangle->t.l, sphere) ||
+                   roam_triangle_backface(triangle->t.b, sphere) ||
+                   roam_triangle_backface(triangle->t.r, sphere))
+                       triangle->error *= 500;
        }
 }
 
@@ -397,12 +419,14 @@ void roam_triangle_split(RoamTriangle *triangle, RoamSphere *sphere)
        RoamTriangle *s = triangle;      // Self
        RoamTriangle *b = triangle->t.b; // Base
 
+       RoamDiamond *dia = roam_diamond_new(s, b);
+
        /* Add new triangles */
        RoamPoint *mid = triangle->split;
-       RoamTriangle *sl = s->kids[0] = roam_triangle_new(s->p.m, mid, s->p.l); // Self Left
-       RoamTriangle *sr = s->kids[1] = roam_triangle_new(s->p.r, mid, s->p.m); // Self Right
-       RoamTriangle *bl = b->kids[0] = roam_triangle_new(b->p.m, mid, b->p.l); // Base Left
-       RoamTriangle *br = b->kids[1] = roam_triangle_new(b->p.r, mid, b->p.m); // Base Right
+       RoamTriangle *sl = s->kids[0] = roam_triangle_new(s->p.m, mid, s->p.l, dia); // Self Left
+       RoamTriangle *sr = s->kids[1] = roam_triangle_new(s->p.r, mid, s->p.m, dia); // Self Right
+       RoamTriangle *bl = b->kids[0] = roam_triangle_new(b->p.m, mid, b->p.l, dia); // Base Left
+       RoamTriangle *br = b->kids[1] = roam_triangle_new(b->p.r, mid, b->p.m, dia); // Base Right
 
        /*                triangle,l,  base,      r,  sphere */
        roam_triangle_add(sl, sr, s->t.l, br, sphere);
@@ -410,19 +434,18 @@ void roam_triangle_split(RoamTriangle *triangle, RoamSphere *sphere)
        roam_triangle_add(bl, br, b->t.l, sr, sphere);
        roam_triangle_add(br, sl, b->t.r, bl, sphere);
 
-       roam_triangle_sync_neighbors(sl, s, s->t.l);
-       roam_triangle_sync_neighbors(sr, s, s->t.r);
-       roam_triangle_sync_neighbors(bl, b, b->t.l);
-       roam_triangle_sync_neighbors(br, b, b->t.r);
+       roam_triangle_sync_neighbors(s->t.l, s, sl);
+       roam_triangle_sync_neighbors(s->t.r, s, sr);
+       roam_triangle_sync_neighbors(b->t.l, b, bl);
+       roam_triangle_sync_neighbors(b->t.r, b, br);
 
        /* Remove old triangles */
        roam_triangle_remove(s, sphere);
        roam_triangle_remove(b, sphere);
 
        /* Add/Remove diamonds */
-       RoamDiamond *diamond = roam_diamond_new(s, b, sl, sr, bl, br);
-       roam_diamond_update_errors(diamond, sphere);
-       roam_diamond_add(diamond, sphere);
+       roam_diamond_update_errors(dia, sphere);
+       roam_diamond_add(dia, sphere);
        roam_diamond_remove(s->parent, sphere);
        roam_diamond_remove(b->parent, sphere);
 }
@@ -483,26 +506,11 @@ void roam_triangle_draw_normal(RoamTriangle *triangle)
  *
  * Returns: the new diamond
  */
-RoamDiamond *roam_diamond_new(
-               RoamTriangle *parent0, RoamTriangle *parent1,
-               RoamTriangle *kid0, RoamTriangle *kid1,
-               RoamTriangle *kid2, RoamTriangle *kid3)
+RoamDiamond *roam_diamond_new(RoamTriangle *parent0, RoamTriangle *parent1)
 {
        RoamDiamond *diamond = g_new0(RoamDiamond, 1);
-
-       diamond->kids[0] = kid0;
-       diamond->kids[1] = kid1;
-       diamond->kids[2] = kid2;
-       diamond->kids[3] = kid3;
-
-       kid0->parent = diamond;
-       kid1->parent = diamond;
-       kid2->parent = diamond;
-       kid3->parent = diamond;
-
        diamond->parents[0] = parent0;
        diamond->parents[1] = parent1;
-
        return diamond;
 }
 
@@ -556,22 +564,27 @@ void roam_diamond_merge(RoamDiamond *diamond, RoamSphere *sphere)
        RoamTriangle *s = diamond->parents[0]; // Self
        RoamTriangle *b = diamond->parents[1]; // Base
 
-       RoamTriangle *sl = diamond->kids[0];
-       RoamTriangle *sr = diamond->kids[1];
-       RoamTriangle *bl = diamond->kids[2];
-       RoamTriangle *br = diamond->kids[3];
+       RoamTriangle *sl = s->kids[0];
+       RoamTriangle *sr = s->kids[1];
+       RoamTriangle *bl = b->kids[0];
+       RoamTriangle *br = b->kids[1];
 
        s->kids[0] = s->kids[1] = NULL;
        b->kids[0] = b->kids[1] = NULL;
 
        /* Add original triangles */
+       roam_triangle_sync_neighbors(s->t.l, sl, s);
+       roam_triangle_sync_neighbors(s->t.r, sr, s);
+       roam_triangle_sync_neighbors(b->t.l, bl, b);
+       roam_triangle_sync_neighbors(b->t.r, br, b);
+
        roam_triangle_add(s, sl->t.b, b, sr->t.b, sphere);
        roam_triangle_add(b, bl->t.b, s, br->t.b, sphere);
 
-       roam_triangle_sync_neighbors(s, sl, sl->t.b);
-       roam_triangle_sync_neighbors(s, sr, sr->t.b);
-       roam_triangle_sync_neighbors(b, bl, bl->t.b);
-       roam_triangle_sync_neighbors(b, br, br->t.b);
+       roam_triangle_sync_neighbors(sl->t.b, sl, s);
+       roam_triangle_sync_neighbors(sr->t.b, sr, s);
+       roam_triangle_sync_neighbors(bl->t.b, bl, b);
+       roam_triangle_sync_neighbors(br->t.b, br, b);
 
        /* Remove child triangles */
        roam_triangle_remove(sl, sphere);
@@ -663,7 +676,8 @@ RoamSphere *roam_sphere_new()
                sphere->roots[i] = roam_triangle_new(
                        vertexes[_triangles[i][0][0]],
                        vertexes[_triangles[i][0][1]],
-                       vertexes[_triangles[i][0][2]]);
+                       vertexes[_triangles[i][0][2]],
+                       NULL);
        for (int i = 0; i < 8; i++)
                roam_triangle_add(sphere->roots[i],
                        sphere->roots[_triangles[i][1][0]],