diff --git a/src/camera.cc b/src/camera.cc new file mode 100644 index 0000000..201215d --- /dev/null +++ b/src/camera.cc @@ -0,0 +1,24 @@ +// Copyright 2024 Bytedance Inc. All Rights Reserved. +// Author: tianlei.richard@qq.com (tianlei.richard) + +#include "camera.h" + +Camera::Camera(const Vector3d &up) + : position_(Point3d::Identity()), gaze_(Vector3d::Identity()), up_(up) {} + +TransformMatrix Camera::get_view_transform() const { + // Move camera to origin + TransformMatrix m{{1, 0, 0, -position_.x()}, + {0, 1, 0, -position_.y()}, + {0, 0, 1, -position_.z()}, + {0, 0, 0, 1}}; + // Adjust to fit xyz + const Vector3d &x_camera{(gaze_.cross(up_)).normalized()}; + m = TransformMatrix{{x_camera.x(), x_camera.y(), x_camera.z(), 0}, + {up_.x(), up_.y(), up_.z(), 0}, + {-gaze_.x(), -gaze_.y(), -gaze_.z(), 0}, + {0, 0, 0, 1}} * + m; + + return m; +} diff --git a/src/camera.h b/src/camera.h new file mode 100644 index 0000000..9b37f0c --- /dev/null +++ b/src/camera.h @@ -0,0 +1,23 @@ +// Copyright 2024 Bytedance Inc. All Rights Reserved. +// Author: tianlei.richard@qq.com (tianlei.richard) + +#include "common.h" + +class Camera { +public: + explicit Camera(const Vector3d &up); + +public: + TransformMatrix get_view_transform() const; + +public: + void set_position(const Point3d &position) { + position_ = position.normalized(); + } + void set_gaze(const Vector3d &gaze) { gaze_ = gaze.normalized(); } + +private: + Point3d position_; + Vector3d gaze_; + Vector3d up_; +}; diff --git a/src/main.cc b/src/main.cc index cbc55aa..901b71f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,11 +1,12 @@ // Copyright 2024 Bytedance Inc. All Rights Reserved. -// Author: tianlei.richard@bytedance.com (tianlei.richard) +// Author: tianlei.richard@qq.com (tianlei.richard) #include #include #include "spdlog/spdlog.h" +#include "camera.h" #include "common.h" #include "minus_renderer.h" #include "triangle.h" @@ -26,6 +27,7 @@ int main(int argc, char *argv[]) { cv::namedWindow("MinusRenderer", cv::WINDOW_AUTOSIZE); const auto start = std::chrono::steady_clock::now(); + Camera camera{Vector3d{0, 1, 0}}; MinusRenderer renderer{near, far, fov, aspect_ratio, std::move(primitives)}; do { const auto elapse = std::chrono::duration_cast( @@ -33,10 +35,15 @@ int main(int argc, char *argv[]) { .count(); TransformMatrix m{ Eigen::Transform( - Eigen::AngleAxisd(0.125 * M_PI, Eigen::Vector3d::UnitZ()) + Eigen::AngleAxisd(0.03125 * M_PI, Eigen::Vector3d::UnitZ()) .toRotationMatrix()) .matrix()}; renderer.model_transform(m); + + camera.set_position(Point3d{0, 0, 0}); + camera.set_gaze(Vector3d{0, 0, -1}); + renderer.view_transform(camera.get_view_transform()); + const auto &color_image = renderer.render(resolution_width, resolution_height); cv::imshow("MinusRenderer", color_image); diff --git a/src/minus_renderer.cc b/src/minus_renderer.cc index be5f7d7..5fbf3e9 100644 --- a/src/minus_renderer.cc +++ b/src/minus_renderer.cc @@ -5,17 +5,14 @@ #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), - height_(calculate_height(fov, near)), - width_(calculate_width(height_, aspect_ratio)), primitives_(primitives) { - spdlog::info("fov: {}, aspect ratio: {}, width: {}, height: {}", fov_, - aspect_ratio_, width_, height_); + primitives_(primitives) { + spdlog::info("fov: {}, aspect ratio: {}", fov_, aspect_ratio_); } float MinusRenderer::calculate_height(const float fov, const float near) { @@ -35,10 +32,12 @@ TransformMatrix MinusRenderer::squish_tranform() { } TransformMatrix MinusRenderer::orthographic_tranform() { - const auto right = width_ * 0.5; - const auto left = -right; - const auto top = height_ * 0.5; - const auto bottom = -top; + 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)}, @@ -68,12 +67,15 @@ void MinusRenderer::model_transform(const TransformMatrix &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; - for (const auto &t : primitives_) { - primitives.push_back(t); - } + std::vector primitives = primitives_; for (auto &t : primitives) { t.projective_transform(squish_tranform()); t.affine_transform(orthographic_tranform()); diff --git a/src/minus_renderer.h b/src/minus_renderer.h index b1d58ba..f127097 100644 --- a/src/minus_renderer.h +++ b/src/minus_renderer.h @@ -1,5 +1,5 @@ // Copyright 2024 Bytedance Inc. All Rights Reserved. -// Author: tianlei.richard@bytedance.com (tianlei.richard) +// Author: tianlei.richard@qq.com (tianlei.richard) #pragma once @@ -16,6 +16,7 @@ public: public: void model_transform(const TransformMatrix &m); + void view_transform(const TransformMatrix &m); private: static float calculate_height(const float fov, const float near); @@ -33,8 +34,5 @@ private: float fov_; // In radian float aspect_ratio_; - float height_; - float width_; - std::vector primitives_; }; diff --git a/src/rasterizer.cc b/src/rasterizer.cc index 091e7a5..090104b 100644 --- a/src/rasterizer.cc +++ b/src/rasterizer.cc @@ -25,7 +25,7 @@ Rasterizer::rasterize(const std::vector &primitives) { const int y_min = std::min(std::max(0, aabb.y), height_); const int y_max = std::min(std::max(0, aabb.y + aabb.height), height_); - spdlog::info("Triangle range, ({},{},{},{})", x_min, x_max, y_min, y_max); + // spdlog::info("Range, ({},{},{},{})", x_min, x_max, y_min, y_max); for (int i = y_min; i < y_max; ++i) { for (int j = x_min; j < x_max; ++j) { auto &property = pixels_[i][j];