#ifndef POLYGON_H #define POLYGON_H #include "fastmath.hpp" #include struct polygon { vec3 points[3]; decimal delta[9]; bool small = false; decimal baryFactor; decimal bounding[4]; // min x, max x, min y, max y vec3 normals[3]; vec3 colors[3]; vec3 barycentrics; vec3 boundingBarycentrics; polygon(const vec3 &v1, const vec3 &v2, const vec3 &v3) : points{v1, v2, v3}, delta{} {} polygon() : points{}, delta{} {} void calcDelta() { for (int i = 0; i < 3; i++) { int n = (i + 1) % 3; 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(); if (delta[i * 3].i == 0 && delta[i * 3 + 1].i == 0) small = true; } 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(); } baryFactor = (points[1].x() - points[0].x()) * (points[2].y() - points[1].y()) - (points[1].y() - points[0].y()) * (points[2].x() - points[1].x()); if (baryFactor.isSmall()) { small = true; } else baryFactor = decimal(1.0) / baryFactor; // std::cout << baryFactor << std::endl; /*if ((bounding[1].i - bounding[0].i < 1 << HALF_SHIFT) && (bounding[3].i - bounding[2].i < 1 << HALF_SHIFT)) small = true;*/ } vec3 avgNormal() { vec3 result; for (int i = 0; i < 3; i++) { result += normals[i]; } return result * decimal(0.3333); } const bool depContains(const vec3 &p) { // if (skip) // return false; for (int i = 0; i < 3; i++) { if (small) return true; vec3 d = p; if ((d.x() * delta[i * 3] + d.y() * delta[i * 3 + 1] + delta[i * 3 + 2]) > decimal(0.2)) return false; } return true; } const bool contains(const vec3 &p) { if (small) return true; else return (barycentrics[0] >= decimal(-0.01)) && (barycentrics[1] >= decimal(-0.01)) && (barycentrics[2] >= decimal(-0.01)); } friend std::ostream &operator<<(std::ostream &os, const polygon &p) { for (int i = 0; i < 3; i++) { os << p.points[i]; } return os; } vec3 calcNormal() { return normals[0] * boundingBarycentrics[0] + normals[1] * boundingBarycentrics[1] + normals[2] * boundingBarycentrics[2]; } vec3 calcColor() { return colors[0] * boundingBarycentrics[0] + colors[1] * boundingBarycentrics[1] + colors[2] * boundingBarycentrics[2]; } decimal calcDepth() { return points[0].z() * boundingBarycentrics[0] + points[1].z() * boundingBarycentrics[1] + points[2].z() * boundingBarycentrics[2]; } void calcBarycentric(vec3 s) { // if (small) // return vec3(decimal(0.333), decimal(0.333), decimal(0.333)); barycentrics[0] = (points[1].x() - s.x()) * (points[2].y() - s.y()) - (points[2].x() - s.x()) * (points[1].y() - s.y()); barycentrics[1] = (points[2].x() - s.x()) * (points[0].y() - s.y()) - (points[0].x() - s.x()) * (points[2].y() - s.y()); barycentrics = barycentrics * baryFactor; barycentrics[2] = decimal(1.0) - barycentrics[1] - barycentrics[0]; // return result; boundingBarycentrics = vec3::max( vec3::min(barycentrics, vec3(1.0, 1.0, 1.0)), vec3(0.0, 0.0, 0.0)); } }; #endif