#ifndef POLYGON_H #define POLYGON_H #include "fastmath.hpp" #include struct polygon { vec3 points[3]; decimal delta[9]; bool small = false; decimal baryFactor; decimal dot00; decimal dot01; decimal dot11; vec2 v0; vec2 v1; decimal bounding[4]; // min x, max x, min y, max y vec3 normals[3]; vec3 colors[3]; vec3 barycentrics; vec3 boundingBarycentrics; 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; // } v0 = vec2(points[2]) - vec2(points[0]); v1 = vec2(points[1]) - vec2(points[0]); dot00 = v0 * v0; dot01 = v1 * v0; dot11 = v1 * v1; 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()); std::cout << dot00 << " " << dot01 << " " << dot11 << std::endl; baryFactor = dot00 * dot11 - dot01 * dot01; std::cout << "baryFactor:" << baryFactor << std::endl; if (baryFactor.i == 0) { 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 = normals[0] + normals[1] + normals[2]; // 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 false; 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.0)) && (barycentrics[1] >= decimal(-0.0)) && (barycentrics[0] + barycentrics[1] <= decimal(1.0)); } 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)); vec2 v2 = vec2(s) - vec2(points[0]); decimal dot02 = v0 * v2; decimal dot12 = v1 * v2; barycentrics = {}; barycentrics[0] = dot11 * dot02 - dot01 * dot12; barycentrics[1] = dot00 * dot12 - dot01 * dot02; // 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]; // 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