// Copyright 2024 Bytedance Inc. All Rights Reserved. // Author: tianlei.richard@qq.com (tianlei.richard) #include "rasterizer.h" #include Rasterizer::Rasterizer(const int width, const int height) : width_(width), height_(height), pixels_(std::vector>( height, std::vector( width, PixelProperty{0., 0., 0., std::numeric_limits::infinity()}))) { } void Rasterizer::rasterize(const Triangle &t) { const auto &aabb = t.axis_align_bbox(); const int x_min = aabb.x; const int x_max = aabb.x + aabb.width; const int y_min = aabb.y; const int y_max = aabb.y + aabb.height; for (int i = x_min; i < x_max; ++i) { for (int j = y_min; j < y_max; ++j) { auto &property = pixels_[j][i]; const auto &[is_inside, z_screen] = inside(Point2d{i + 0.5, j + 0.5}, t); if (is_inside && z_screen > property[3]) { property[0] = 1; property[1] = 0; property[2] = 0; property[3] = z_screen; } } } } std::pair Rasterizer::inside(const Point2d &p_screen, const Triangle &t) { const auto points = t.get_points<3>(); const auto plane_normal = t.normal_vector(); const auto plane_point = points[0]; const auto z_screen = plane_point.z() - (plane_normal.x() * (p_screen.x() - plane_point.x()) + plane_normal.y() * (p_screen.y() - plane_point.y())) / plane_normal.z(); const Point3d p{p_screen.x(), p_screen.y(), z_screen}; const auto v1 = points[1] - points[0]; const auto v2 = points[2] - points[1]; const auto v3 = points[0] - points[2]; const auto c1 = v1.cross(p - points[0]).normalized(); const auto c2 = v2.cross(p - points[1]).normalized(); const auto c3 = v3.cross(p - points[2]).normalized(); const auto r1 = c1.dot(c2); const auto r2 = c1.dot(c3); const auto r3 = c2.dot(c3); return {r1 > 0 && r2 > 0 && r3 > 0, z_screen}; }