test triangle rendered?
This commit is contained in:
+45
-3
@@ -6,6 +6,8 @@
|
||||
#define COM_GEM_H
|
||||
|
||||
#include "mat.h"
|
||||
#include "pnt.h"
|
||||
#include "vec.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* Projects vertex position to a clip space via reordered row-major MVP matrix.
|
||||
@@ -37,6 +39,8 @@ static inline com_vec_t com_gem_vec_project_clip(com_mat_t a, com_vec_t b) {
|
||||
/* TODO: If we clip test bounding volume of a model first we can skip
|
||||
* all clipping whatsoever, which might hold true more often, than the cost of
|
||||
* testing the volume. */
|
||||
/* TODO: It should be possible to have results in pixel position, not -1 to 1.
|
||||
*/
|
||||
|
||||
#define COM_GEM_VERTEX_UNCLIPPED (0 << 0)
|
||||
#define COM_GEM_VERTEX_CLIPPED_X (1 << 0)
|
||||
@@ -44,15 +48,53 @@ static inline com_vec_t com_gem_vec_project_clip(com_mat_t a, com_vec_t b) {
|
||||
/* Attempt to project clip space vertex to NDC, reporting which component lies
|
||||
* outside of view. Bit test against those per component. This is needed for
|
||||
* determining new view-lying clipped triangles. */
|
||||
static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_vec_t *out) {
|
||||
static inline uint8_t com_gem_clip_vis_project(com_vec_t a, com_pnt_t *out) {
|
||||
uint8_t mask;
|
||||
if (a.s.x < -a.s.z || a.s.x > a.s.z)
|
||||
mask ^= COM_GEM_VERTEX_CLIPPED_X;
|
||||
if (a.s.y < -a.s.z || a.s.y > a.s.z)
|
||||
mask ^= COM_GEM_VERTEX_CLIPPED_Y;
|
||||
out->a[0] = com_fix_div(a.a[0], a.a[2]);
|
||||
out->a[1] = com_fix_div(a.a[1], a.a[2]);
|
||||
out->a[0] = com_fix_div(a.a[0], a.a[2]) / 480 + 240;
|
||||
out->a[1] = com_fix_div(a.a[1], a.a[2]) / 640 + 320;
|
||||
return mask;
|
||||
}
|
||||
|
||||
static inline void com_gem_draw_triangle(com_pnt_t v0, com_pnt_t v1,
|
||||
com_pnt_t v2, uint8_t *buffer) {
|
||||
// 1. Compute the bounding box of the triangle
|
||||
int minX = com_vec_min(com_vec_from(v0.s.x, v1.s.x, v2.s.x));
|
||||
int minY = com_vec_min(com_vec_from(v0.s.y, v1.s.y, v2.s.y));
|
||||
int maxX = com_vec_max(com_vec_from(v0.s.x, v1.s.x, v2.s.x));
|
||||
int maxY = com_vec_max(com_vec_from(v0.s.y, v1.s.y, v2.s.y));
|
||||
|
||||
// 2. Clip the bounding box against screen dimensions to avoid out-of-bounds
|
||||
// errors
|
||||
// minX = CLAMP(minX, 0, 480 - 1);
|
||||
// minY = CLAMP(minY, 0, HEIGHT - 1);
|
||||
// maxX = CLAMP(maxX, 0, 480 - 1);
|
||||
// maxY = CLAMP(maxY, 0, HEIGHT - 1);
|
||||
|
||||
// 3. Loop over all pixels inside the bounding box
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
com_pnt_t p = {.s = {x, y}};
|
||||
|
||||
// Test the pixel center against all 3 edges
|
||||
int w0 = com_pnt_edge_orient(v1, v2, p);
|
||||
int w1 = com_pnt_edge_orient(v2, v0, p);
|
||||
int w2 = com_pnt_edge_orient(v0, v1, p);
|
||||
|
||||
// If the point is inside or on all edges, draw the pixel
|
||||
// (Assumes Clockwise vertex ordering)
|
||||
if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
|
||||
printf("%i, %i\n", y, x);
|
||||
buffer[(y * 640 + x) * 4 + 0] = '#';
|
||||
buffer[(y * 640 + x) * 4 + 1] = '#';
|
||||
buffer[(y * 640 + x) * 4 + 2] = '#';
|
||||
buffer[(y * 640 + x) * 4 + 3] = '#';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user