fix list insertion bug and try to trim to a viewport
This commit is contained in:
parent
9c44ea9c58
commit
d48ffe52b4
137
hiddenwire.c
137
hiddenwire.c
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user