the perspective transform finally looks right

This commit is contained in:
Trammell hudson 2018-02-28 22:07:51 -05:00
parent 78de86f4a8
commit 8b8097253c
Failed to extract signature
4 changed files with 73 additions and 31 deletions

View File

@ -22,15 +22,14 @@ camera_new(
v3_t eye, v3_t eye,
v3_t lookat, v3_t lookat,
v3_t up, v3_t up,
float fov, float fov
float scale
) )
{ {
camera_t * c = calloc(1, sizeof(*c)); camera_t * c = calloc(1, sizeof(*c));
if (!c) if (!c)
return NULL; return NULL;
camera_setup(c, eye, lookat, up, fov, scale); camera_setup(c, eye, lookat, up, fov);
return c; return c;
} }
@ -41,8 +40,7 @@ camera_setup(
v3_t eye, v3_t eye,
v3_t lookat, v3_t lookat,
v3_t up, v3_t up,
float fov, float fov
float scale
) )
{ {
// compute the basis for the camera // compute the basis for the camera
@ -62,9 +60,9 @@ camera_setup(
{ u.p[2], v.p[2], w.p[2], 0 }, { u.p[2], v.p[2], w.p[2], 0 },
{ -v3_dot(u,eye), -v3_dot(v,eye), -v3_dot(w,eye), 1 }, { -v3_dot(u,eye), -v3_dot(v,eye), -v3_dot(w,eye), 1 },
#else #else
{ u.p[0], u.p[1], u.p[2], -v3_dot(u,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,lookat) }, { 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,lookat) }, { w.p[0], w.p[1], w.p[2], -v3_dot(w,eye) },
{ 0, 0, 0, 1 }, { 0, 0, 0, 1 },
#endif #endif
}; };
@ -80,7 +78,7 @@ camera_setup(
// now compute the perspective projection matrix // now compute the perspective projection matrix
float s = 1.0 / tan(fov * M_PI / 180 / 2); float s = 1.0 / tan(fov * M_PI / 180 / 2);
c->near = 1.0; c->near = 4.0;
c->far = 20; c->far = 20;
float f1 = - c->far / (c->far - c->near); float f1 = - c->far / (c->far - c->near);
float f2 = - c->far * c->near / (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++) for (int j = 0 ; j < 4 ; j++)
p[i] += c->r[i][j] * v[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], v[0], v[1], v[2],
p[0], p[1], p[2], p[3] p[0], p[1], p[2], p[3]
); );
/* /*
for (int i = 0 ; i < 3 ; i++)
p[i] /= p[3];
p[0] *= -1; p[0] *= -1;
p[1] *= -1; p[1] *= -1;
p[2] /= p[3];
*/ */
@ -162,10 +171,6 @@ camera_project(
v_out->p[1] = p[1]; v_out->p[1] = p[1];
v_out->p[2] = p[2]; 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; return 1;
} }

View File

@ -9,8 +9,7 @@ camera_new(
v3_t eye, v3_t eye,
v3_t lookat, v3_t lookat,
v3_t up, v3_t up,
float fov, float fov
float scale
); );
extern void extern void
@ -19,8 +18,7 @@ camera_setup(
v3_t eye, v3_t eye,
v3_t lookat, v3_t lookat,
v3_t up, v3_t up,
float fov, float fov
float scale
); );
/** Transform a XYZ point into a screen point. /** Transform a XYZ point into a screen point.

View File

@ -768,8 +768,10 @@ int onscreen(
{ {
if (p->p[0] < -width/2 || width/2 < p->p[0]) if (p->p[0] < -width/2 || width/2 < p->p[0])
return 0; return 0;
/*
if (p->p[1] < -height/2 || height/2 < p->p[1]) if (p->p[1] < -height/2 || height/2 < p->p[1])
return 0; return 0;
*/
/* /*
if (p->p[0] < 0 || width < p->p[0]) if (p->p[0] < 0 || width < p->p[0])
return 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("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"%.0fpx\" height=\"%.0fpx\" viewbox=\"0 0 %.0f %.0f\">\n", width, height, width, height); printf("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"%.0fpx\" height=\"%.0fpx\" viewbox=\"0 0 %.0f %.0f\">\n", width, height, width, height);
@ -897,18 +900,27 @@ int main(
for(int j = 0 ; j < 3 ; j++) 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) if(debug >= 2)
fprintf(stderr, "%.3f,%.3f,%.3f -> %.1f,%.1f,%.1f\n", for(int j = 0 ; j < 3 ; j++)
stl->p[0].p[0], {
stl->p[0].p[1], fprintf(stderr, "%.3f %.3f %.3f -> %.3f %.3f %.3f\n",
stl->p[0].p[2], stl->p[j].p[0],
s[0].p[0], stl->p[j].p[1],
s[0].p[1], stl->p[j].p[2],
s[0].p[2] s[j].p[0],
); s[j].p[1],
s[j].p[2]
);
}
tri_t * const tri = tri_new(s, stl->p); tri_t * const tri = tri_new(s, stl->p);
@ -962,6 +974,8 @@ tri_print(tri);
reject: reject:
tri_delete(tri); tri_delete(tri);
reject_early:
continue;
} }
if (debug) if (debug)

25
test.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdio.h>
#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");
}
}