// Copyright 2024 Bytedance Inc. All Rights Reserved. // Author: tianlei.richard@qq.com (tianlei.richard) #include #include "minus_renderer.h" #include "rasterizer.h" #include "spdlog/spdlog.h" MinusRenderer::MinusRenderer(float near, float far, float fov, float aspect_ratio, std::vector &&primitives) : near_(near), far_(far), fov_(fov), aspect_ratio_(aspect_ratio), primitives_(primitives) { spdlog::info("fov: {}, aspect ratio: {}", fov_, aspect_ratio_); } float MinusRenderer::calculate_height(const float fov, const float near) { return std::fabs(near) * std::tan(fov * 0.5) * 2; } float MinusRenderer::calculate_width(const float height, const float ratio) { return height * ratio; } TransformMatrix MinusRenderer::squish_tranform() { // Frustum to Cuboid return TransformMatrix{{near_, 0, 0, 0}, {0, near_, 0, 0}, {0, 0, near_ + far_, -near_ * far_}, {0, 0, 1, 0}}; } TransformMatrix MinusRenderer::orthographic_tranform() { const float height = calculate_height(fov_, near_); const float width = calculate_width(height, aspect_ratio_); const float right = width * 0.5; const float left = -right; const float top = height * 0.5; const float bottom = -top; TransformMatrix m{{1, 0, 0, -0.5 * (right - left)}, {0, 1, 0, -0.5 * (top - bottom)}, {0, 0, 1, -0.5 * (far_ - near_)}, {0, 0, 0, 1}}; m = TransformMatrix{{2 / (right - left), 0, 0, 0}, {0, 2 / (top - bottom), 0, 0}, {0, 0, 2 / std::fabs(far_ - near_), 0}, {0, 0, 0, 1}} * m; return m; } TransformMatrix MinusRenderer::view_port_transform(const float width, const float height) { return TransformMatrix{{width * 0.5, 0, 0, width * 0.5}, {0, height * 0.5, 0, height * 0.5}, {0, 0, 1, 0}, {0, 0, 0, 1}}; } void MinusRenderer::model_transform(const TransformMatrix &m) { for (auto &t : primitives_) { t.affine_transform(m); } } void MinusRenderer::view_transform(const TransformMatrix &m) { for (auto &t : primitives_) { t.affine_transform(m); } } cv::Mat MinusRenderer::render(const int resolution_width, const int resolution_height) { std::vector primitives = primitives_; for (auto &t : primitives) { t.projective_transform(squish_tranform()); t.affine_transform(orthographic_tranform()); t.affine_transform( view_port_transform(resolution_width, resolution_height)); } Rasterizer rasterizer{resolution_width, resolution_height}; const auto &pixels = rasterizer.rasterize(primitives); assert(!pixels.empty()); cv::Mat color_image(pixels.size(), (pixels[0]).size(), CV_8UC3); for (int i = 0; i < pixels.size(); ++i) { const auto &row = pixels[i]; for (int j = 0; j < row.size(); ++j) { auto &pixel_color = color_image.at(pixels.size() - i - 1, j); pixel_color = cv::Vec3b{static_cast( row[j].x() * std::numeric_limits::max()), static_cast( row[j].y() * std::numeric_limits::max()), static_cast( row[j].z() * std::numeric_limits::max())}; } } return color_image; }