From 8b8097253cd39e938ab04fda3582892f0216ccd8 Mon Sep 17 00:00:00 2001 From: Trammell hudson Date: Wed, 28 Feb 2018 22:07:51 -0500 Subject: [PATCH] the perspective transform finally looks right --- camera.c | 39 ++++++++++++++++++++++----------------- camera.h | 6 ++---- hiddenwire.c | 34 ++++++++++++++++++++++++---------- test.c | 25 +++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 test.c diff --git a/camera.c b/camera.c index 8ac8eba..cfee7e3 100644 --- a/camera.c +++ b/camera.c @@ -22,15 +22,14 @@ camera_new( v3_t eye, v3_t lookat, v3_t up, - float fov, - float scale + float fov ) { camera_t * c = calloc(1, sizeof(*c)); if (!c) return NULL; - camera_setup(c, eye, lookat, up, fov, scale); + camera_setup(c, eye, lookat, up, fov); return c; } @@ -41,8 +40,7 @@ camera_setup( v3_t eye, v3_t lookat, v3_t up, - float fov, - float scale + float fov ) { // compute the basis for the camera @@ -62,9 +60,9 @@ camera_setup( { u.p[2], v.p[2], w.p[2], 0 }, { -v3_dot(u,eye), -v3_dot(v,eye), -v3_dot(w,eye), 1 }, #else - { u.p[0], u.p[1], u.p[2], -v3_dot(u,lookat) }, - { v.p[0], v.p[1], v.p[2], -v3_dot(v,lookat) }, - { w.p[0], w.p[1], w.p[2], -v3_dot(w,lookat) }, + { u.p[0], u.p[1], u.p[2], -v3_dot(u,eye) }, + { v.p[0], v.p[1], v.p[2], -v3_dot(v,eye) }, + { w.p[0], w.p[1], w.p[2], -v3_dot(w,eye) }, { 0, 0, 0, 1 }, #endif }; @@ -80,7 +78,7 @@ camera_setup( // now compute the perspective projection matrix float s = 1.0 / tan(fov * M_PI / 180 / 2); - c->near = 1.0; + c->near = 4.0; c->far = 20; float f1 = - c->far / (c->far - c->near); float f2 = - c->far * c->near / (c->far - c->near); @@ -142,17 +140,28 @@ camera_project( for (int j = 0 ; j < 4 ; j++) p[i] += c->r[i][j] * v[j]; - if(1) fprintf(stderr, "%.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", + // what if p->p[4] == 0? + // pz < 0 == The point is behind us; do not display? + //if (p[2] < c->near || p[2] > c->far) + if (p[2] < 0) + return 0; + + p[0] /= p[3]; + p[1] /= p[3]; +/* + for (int i = 0 ; i < 3 ; i++) + p[i] /= p[3]; + p[2] /= p[3]; +*/ + + if(0) fprintf(stderr, "%.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", v[0], v[1], v[2], p[0], p[1], p[2], p[3] ); /* - for (int i = 0 ; i < 3 ; i++) - p[i] /= p[3]; p[0] *= -1; p[1] *= -1; - p[2] /= p[3]; */ @@ -162,10 +171,6 @@ camera_project( v_out->p[1] = p[1]; v_out->p[2] = p[2]; - // what if p->p[4] == 0? - // pz < 0 == The point is behind us; do not display? - if (p[2] < c->near || p[2] > c->far) - return 0; return 1; } diff --git a/camera.h b/camera.h index 8f64bbd..6aaf22c 100644 --- a/camera.h +++ b/camera.h @@ -9,8 +9,7 @@ camera_new( v3_t eye, v3_t lookat, v3_t up, - float fov, - float scale + float fov ); extern void @@ -19,8 +18,7 @@ camera_setup( v3_t eye, v3_t lookat, v3_t up, - float fov, - float scale + float fov ); /** Transform a XYZ point into a screen point. diff --git a/hiddenwire.c b/hiddenwire.c index 3ba18e4..bf1898e 100644 --- a/hiddenwire.c +++ b/hiddenwire.c @@ -768,8 +768,10 @@ int onscreen( { 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; @@ -868,7 +870,8 @@ int main( } - const camera_t * const cam = camera_new(eye, lookat, up, fov, scale); + (void) scale; + const camera_t * const cam = camera_new(eye, lookat, up, fov); printf("\n", width, height, width, height); @@ -897,18 +900,27 @@ int main( for(int j = 0 ; j < 3 ; j++) { - camera_project(cam, &stl->p[j], &s[j]); + // if any points are behind us, reject + // this one + if (!camera_project(cam, &stl->p[j], &s[j])) + { + behind++; + goto reject_early; + } } if(debug >= 2) - fprintf(stderr, "%.3f,%.3f,%.3f -> %.1f,%.1f,%.1f\n", - stl->p[0].p[0], - stl->p[0].p[1], - stl->p[0].p[2], - s[0].p[0], - s[0].p[1], - s[0].p[2] - ); + for(int j = 0 ; j < 3 ; j++) + { + fprintf(stderr, "%.3f %.3f %.3f -> %.3f %.3f %.3f\n", + stl->p[j].p[0], + stl->p[j].p[1], + stl->p[j].p[2], + s[j].p[0], + s[j].p[1], + s[j].p[2] + ); + } tri_t * const tri = tri_new(s, stl->p); @@ -962,6 +974,8 @@ tri_print(tri); reject: tri_delete(tri); +reject_early: + continue; } if (debug) diff --git a/test.c b/test.c new file mode 100644 index 0000000..eabcd18 --- /dev/null +++ b/test.c @@ -0,0 +1,25 @@ +#include +#include "camera.h" +#include "v3.h" + +int main(void) +{ + v3_t lookat = {{0,0,0}}; + v3_t eye = {{0,-20,0}}; + v3_t up = {{0,0,1}}; + float fov = 20; + + camera_t * camera = camera_new(eye, lookat, up, fov); + + for (float x = -5 ; x <= 5 ; x += 5) + for (float y = -25 ; y < 55 ; y += 5 ) + { + v3_t v_in = {{ x, y, 5 }}; + v3_t v_out; + int onscreen = camera_project(camera, &v_in, &v_out); + if (!onscreen && y > eye.p[1]) + fprintf(stderr, "false positive\n"); + if (onscreen && y < eye.p[1]) + fprintf(stderr, "false negative\n"); + } +}