diff --git a/polygon.hpp b/polygon.hpp index f30adf1..56609b4 100644 --- a/polygon.hpp +++ b/polygon.hpp @@ -5,37 +5,50 @@ struct polygon { vec3 points[3]; - vec3 delta[3]; + decimal delta[9]; bool skip = false; + decimal bounding[4]; // min x, max x, min y, max y + polygon(const vec3 &v1, const vec3 &v2, const vec3 &v3) - : points{v1, v2, v3} {} - polygon() : points{} {} + : points{v1, v2, v3}, delta{} {} + polygon() : points{}, delta{} {} void calcDelta() { for (int i = 0; i < 3; i++) { int n = (i + 1) % 3; - vec3 d = points[n] - points[i]; - delta[i] = vec3(d.y(), -d.x(), d.z()); - if (delta[i].isSmall()) { - skip = true; - return; - } + delta[i * 3] = points[i].y() - points[n].y(); + delta[i * 3 + 1] = points[n].x() - points[i].x(); + delta[i * 3 + 2] = + points[i].x() * points[n].y() - points[i].y() * points[n].x(); + } + bounding[0] = points[0].x(); + bounding[1] = points[0].x(); + bounding[2] = points[0].y(); + bounding[3] = points[0].y(); + for (int i = 1; i < 3; i++) { + if (bounding[0] > points[i].x()) + bounding[0] = points[i].x(); + if (bounding[1] < points[i].x()) + bounding[1] = points[i].x(); + if (bounding[2] > points[i].y()) + bounding[2] = points[i].y(); + if (bounding[3] < points[i].y()) + bounding[3] = points[i].y(); } } - bool contains(const vec3 &p) { - if (skip) - return false; + const bool contains(const vec3 &p) { + // if (skip) + // return false; for (int i = 0; i < 3; i++) { - int n = (i + 1) % 3; - - vec3 s = p - points[n]; - if (s.isSmall()) - return false; - if (s * delta[i] <= decimal(0.0)) + vec3 d = p; + if ((((d.x().i >> SHIFT_AMOUNT) * delta[i * 3].i + + (d.y().i >> SHIFT_AMOUNT) * delta[i * 3 + 1].i + + delta[i * 3 + 2].i) >> + SHIFT_AMOUNT) > 0) return false; } return true; diff --git a/renderer.hpp b/renderer.hpp index 71e7605..c814c2c 100644 --- a/renderer.hpp +++ b/renderer.hpp @@ -6,8 +6,11 @@ #include "model.hpp" #include "polygon.hpp" #include "rendertarget.hpp" +#include #include +#define SCREEN_SPACE_SIZE 8.0 + class Renderer { public: @@ -16,47 +19,61 @@ class Renderer { bool clearTarget = true; Renderer() : clearTarget(false) {} - void toScreenSpace(polygon *p) { - for (int i = 0; i < 3; i++) { - p->points[i].x() = - p->points[i].x() / p->points[i].z() * decimal(8.0) + - decimal(8.0); - p->points[i].y() = - p->points[i].y() / p->points[i].z() * decimal(8.0) + - decimal(8.0); - p->points[i].z() = decimal(1.0); - } + void toScreenSpace(vec3 *p) { + p->x() = p->x() / p->z() * decimal(SCREEN_SPACE_SIZE) + + decimal(SCREEN_SPACE_SIZE); + p->y() = p->y() / p->z() * decimal(SCREEN_SPACE_SIZE) + + decimal(SCREEN_SPACE_SIZE); + p->z() = decimal(1.0); } void render(const model *model) { - decimal widthScale = decimal(16.0) / decimal((float)target->width); - decimal heightScale = decimal(16.0) / decimal((float)target->height); - // std::cout << widthScale << std::endl; + decimal widthScale = + decimal(SCREEN_SPACE_SIZE * 2) / decimal((float)target->width); + decimal heightScale = + decimal(SCREEN_SPACE_SIZE * 2) / decimal((float)target->height); + + decimal invWidthScale = + decimal((float)(target->width / SCREEN_SPACE_SIZE / 2)); + decimal invHeightScale = + decimal((float)(target->height / SCREEN_SPACE_SIZE / 2)); if (clearTarget) { memset((wchar_t *)target->pixels, 0, target->height * target->width * sizeof(target[0])); } + vec3 verts[model->verts.size()] = {}; + + std::copy(model->verts.begin(), model->verts.end(), verts); + + for (int i = 0; i < model->verts.size(); i++) { + toScreenSpace(verts + i); + } + polygon testP; for (int f = 0; f < model->faces.size(); f += 3) { for (int p = 0; p < 3; p++) { - testP.points[p] = model->verts[model->faces[f + p]]; + testP.points[p] = verts[model->faces[f + p]]; } - toScreenSpace(&testP); - testP.calcDelta(); - vec3 pos = vec3(); - for (int x = 0; x < target->height; x++) { - for (int y = 0; y < target->height; y++) { + + int startX = (testP.bounding[0] * invWidthScale).i >> SHIFT_AMOUNT; + int endX = (testP.bounding[1] * invWidthScale).i >> SHIFT_AMOUNT; + int startY = (testP.bounding[2] * invHeightScale).i >> SHIFT_AMOUNT; + int endY = (testP.bounding[3] * invHeightScale).i >> SHIFT_AMOUNT; + + vec3 pos = vec3(testP.bounding[0], testP.bounding[2], 0.0); + for (int x = startX; x < endX; x++) { + for (int y = startY; y < endY; y++) { if (testP.contains(pos)) { target->set(x, y, vec3(0.0, 255.0, 0.0)); } pos.y() += heightScale; } - pos.y() = decimal(0); + pos.y() = decimal(testP.bounding[2]); pos.x() += widthScale; } }