X-Git-Url: http://pileus.org/git/?p=grits;a=blobdiff_plain;f=src%2Froam.c;h=0f4995e0b56593d7bf3dc03f4d65015afb847e8e;hp=4e5775f2d19cceac4f2804f18e80867a43b51e56;hb=22408daaad6f0c7b4075c2b0a725802b0659cfbe;hpb=624b17b39fd770665aa7300f483314b6245c73c9 diff --git a/src/roam.c b/src/roam.c index 4e5775f..0f4995e 100644 --- a/src/roam.c +++ b/src/roam.c @@ -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]],