add camera class to behalf view projection.

This commit is contained in:
tianlei.richard 2024-03-07 14:29:24 +08:00
parent 502a48ebdf
commit a806f5151e
6 changed files with 74 additions and 20 deletions

24
src/camera.cc Normal file
View File

@ -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;
}

23
src/camera.h Normal file
View File

@ -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_;
};

View File

@ -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 <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#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<std::chrono::milliseconds>(
@ -33,10 +35,15 @@ int main(int argc, char *argv[]) {
.count();
TransformMatrix m{
Eigen::Transform<double, 3, Eigen::Affine>(
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);

View File

@ -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<Triangle> &&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<Triangle> primitives;
for (const auto &t : primitives_) {
primitives.push_back(t);
}
std::vector<Triangle> primitives = primitives_;
for (auto &t : primitives) {
t.projective_transform(squish_tranform());
t.affine_transform(orthographic_tranform());

View File

@ -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<Triangle> primitives_;
};

View File

@ -25,7 +25,7 @@ Rasterizer::rasterize(const std::vector<Triangle> &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];