fix list insertion bug and try to trim to a viewport

This commit is contained in:
Trammell hudson 2018-02-28 21:14:52 -05:00
parent 9c44ea9c58
commit d48ffe52b4
Failed to extract signature

View File

@ -102,7 +102,7 @@ svg_line(
float thick float thick
) )
{ {
printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"%s\" stroke-width=\"%.1fpx\"/>\n", printf("<line x1=\"%fpx\" y1=\"%fpx\" x2=\"%fpx\" y2=\"%fpx\" stroke=\"%s\" stroke-width=\"%.1fpx\"/>\n",
p1[0], p1[0],
p1[1], p1[1],
p2[0], p2[0],
@ -287,6 +287,7 @@ tri_insert(
// either we reached the end of the list, // either we reached the end of the list,
// or we have found where our new triangle is sorted // or we have found where our new triangle is sorted
t->next = *zlist; t->next = *zlist;
t->prev = zlist;
*zlist = t; *zlist = t;
if (t->next) if (t->next)
t->next->prev = &t->next; t->next->prev = &t->next;
@ -448,6 +449,8 @@ tri_coplanar(
* setting t0 to 0, this becomes: * setting t0 to 0, this becomes:
* p = a * t1 + b * t2 * p = a * t1 + b * t2
* which is two equations with two unknowns * which is two equations with two unknowns
*
* Returns true if the point is inside the triangle
*/ */
int int
tri_find_z( tri_find_z(
@ -702,6 +705,48 @@ return;
} }
/*
* Fast check to see if t2 is entire occluded by t.
*/
int
tri_behind(
const tri_t * const t,
const tri_t * const t2
)
{
float z0, z1, z2;
int inside0 = tri_find_z(t, &t2->p[0], &z0);
int inside1 = tri_find_z(t, &t2->p[1], &z1);
int inside2 = tri_find_z(t, &t2->p[2], &z2);
// easy check -- if none of the points are inside,
// t2 is not entirely occluded
if (!inside0 || !inside1 || !inside2)
return 0;
// are all of the intersection points ahead of t2?
int behind0 = t2->p[0].p[2] >= z0;
int behind1 = t2->p[1].p[2] >= z1;
int behind2 = t2->p[2].p[2] >= z2;
if (behind0 && behind1 && behind2)
return 1;
// it is a STL violation if they are not all on the
// same side (this would indicate that t and t2 intersect
// go ahead and prune since it will cause problems
if (behind0 || behind1 || behind2)
{
fprintf(stderr, "WARNING: triangles intersect %.0f %.0f %.0f inside %d %d %d behind %d %d %d\n", z0, z1, z2, inside0, inside1, inside2, behind0, behind1, behind2);
tri_print(t);
tri_print(t2);
return 1;
}
// they are all on the same side
return 0;
}
int v3_parse(v3_t * out, const char * str) int v3_parse(v3_t * out, const char * str)
{ {
int rc = sscanf(str, "%f,%f,%f", int rc = sscanf(str, "%f,%f,%f",
@ -715,6 +760,26 @@ int v3_parse(v3_t * out, const char * str)
} }
int onscreen(
const v3_t * const p,
const float width,
const float height
)
{
if (p->p[0] < -width/2 || width/2 < p->p[0])
return 0;
if (p->p[1] < -height/2 || height/2 < p->p[1])
return 0;
/*
if (p->p[0] < 0 || width < p->p[0])
return 0;
if (p->p[1] < 0 || height < p->p[1])
return 0;
*/
return 1;
}
int main( int main(
int argc, int argc,
char ** argv char ** argv
@ -736,6 +801,8 @@ int main(
float scale = 1; float scale = 1;
float fov = 45; float fov = 45;
float prune = 0.1; float prune = 0.1;
float width = 4096;
float height = 2048;
while((opt = getopt_long(argc, argv ,"h?vBCHc:l:s:u:p:F:", long_options, NULL)) != -1) while((opt = getopt_long(argc, argv ,"h?vBCHc:l:s:u:p:F:", long_options, NULL)) != -1)
{ {
@ -803,10 +870,10 @@ int main(
const camera_t * const cam = camera_new(eye, lookat, up, fov, scale); const camera_t * const cam = camera_new(eye, lookat, up, fov, scale);
printf("<svg xmlns=\"http://www.w3.org/2000/svg\">\n"); printf("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"%.0fpx\" height=\"%.0fpx\" viewbox=\"0 0 %.0f %.0f\">\n", width, height, width, height);
float off_x = 0; float off_x = 0; // width/2;
float off_y = 0; float off_y = 0; // height/2;
printf("<g transform=\"translate(%f %f)\">\n", off_x, off_y); printf("<g transform=\"translate(%f %f)\">\n", off_x, off_y);
int rejected = 0; int rejected = 0;
@ -815,6 +882,10 @@ int main(
seg_t * slist_visible = NULL; seg_t * slist_visible = NULL;
int retained = 0; int retained = 0;
int backface = 0;
int small_area = 0;
int behind = 0;
int offscreen = 0;
// transform the stl by the camera projection and generate // transform the stl by the camera projection and generate
// a z-sorted list of triangles // a z-sorted list of triangles
@ -825,7 +896,9 @@ int main(
v3_t s[3]; v3_t s[3];
for(int j = 0 ; j < 3 ; j++) for(int j = 0 ; j < 3 ; j++)
{
camera_project(cam, &stl->p[j], &s[j]); camera_project(cam, &stl->p[j], &s[j]);
}
if(debug >= 2) if(debug >= 2)
fprintf(stderr, "%.3f,%.3f,%.3f -> %.1f,%.1f,%.1f\n", fprintf(stderr, "%.3f,%.3f,%.3f -> %.1f,%.1f,%.1f\n",
@ -841,32 +914,82 @@ int main(
// reject this face if any of the vertices are behind us // reject this face if any of the vertices are behind us
if (tri->min[2] < 0) if (tri->min[2] < 0)
{
behind++;
goto reject; goto reject;
}
// do a back-face cull to determine if this triangle // do a back-face cull to determine if this triangle
// is not facing us. we have to determine the orientation // is not facing us. we have to determine the orientation
// from the winding of the new projection // from the winding of the new projection
if (do_backface && tri->normal.p[2] <= 0) if (do_backface && tri->normal.p[2] <= 0)
{
backface++;
goto reject; goto reject;
}
// if it has any off-screen coords, reject it
if (!onscreen(&tri->p[0], width, height)
|| !onscreen(&tri->p[1], width, height)
|| !onscreen(&tri->p[2], width, height))
{
tri_print(tri);
offscreen++;
goto reject;
}
// prune the small triangles in the screen space // prune the small triangles in the screen space
if (tri_area_2d(tri) < prune) if (tri_area_2d(tri) < prune)
{
small_area++;
goto reject; goto reject;
}
retained++; const float a = v3_dist_2d(&tri->p[0], &tri->p[1]);
const float b = v3_dist_2d(&tri->p[1], &tri->p[2]);
const float c = v3_dist_2d(&tri->p[2], &tri->p[0]);
if( a < prune || b < prune || c < prune)
{
small_area++;
goto reject;
}
// it passes the first tests, so insert the triangle // it passes the first tests, so insert the triangle
// into the list and the three line segments // into the list and the three line segments
tri_insert(&zlist, tri); tri_insert(&zlist, tri);
retained++;
continue; continue;
reject: reject:
tri_delete(tri); tri_delete(tri);
rejected++;
} }
if (debug) if (debug)
fprintf(stderr, "Retained %d, rejected %d triangles\n", retained, rejected); fprintf(stderr, "Retained %d triangles, rejected %d behind, %d offscreen, %d backface, %d small\n", retained, behind, offscreen, backface, small_area);
// drop any triangles that are totally occluded by another
// triangle. this reduces the amount of work for later
rejected = 0;
for(tri_t * t = zlist ; t ; t = t->next)
{
tri_t * t2_next;
for(tri_t * t2 = zlist ; t2 ; t2 = t2_next)
{
t2_next = t2->next;
if (t == t2)
continue;
if (!tri_behind(t, t2))
continue;
// t2 is occluded by t, remove it from the list
rejected++;
tri_delete(t2);
}
}
if (debug)
fprintf(stderr, "Rejected %d fully occluded triangles\n", rejected);
// generate a list of segments, dropping any coplanar ones // generate a list of segments, dropping any coplanar ones