complete phone shading impl.
This commit is contained in:
parent
af09ed9311
commit
acd472bacf
44
src/mesh.cc
44
src/mesh.cc
|
@ -11,31 +11,39 @@
|
||||||
#define OBJL_VEC3_TO_EIGEN_VECTOR(objl_v) \
|
#define OBJL_VEC3_TO_EIGEN_VECTOR(objl_v) \
|
||||||
Eigen::Vector3d { objl_v.X, objl_v.Y, objl_v.Z }
|
Eigen::Vector3d { objl_v.X, objl_v.Y, objl_v.Z }
|
||||||
|
|
||||||
Mesh::Mesh(const std::vector<std::shared_ptr<Vertex>> &vertices,
|
Mesh::Mesh(const std::vector<Vertex> &vertices,
|
||||||
const std::vector<Triangle> &primitives,
|
const std::vector<std::array<size_t, 3>> &indices,
|
||||||
const std::shared_ptr<PhoneMaterial> &phone_material)
|
const std::shared_ptr<PhoneMaterial> &phone_material)
|
||||||
: vertices_(vertices), primitives_(primitives), material_(phone_material) {}
|
: vertices_(vertices), indices_(indices), material_(phone_material) {}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Vertex>>::size_type Mesh::get_vertex_size() const {
|
std::vector<Vertex> &Mesh::get_vertices() { return vertices_; }
|
||||||
|
|
||||||
|
std::vector<Vertex>::size_type Mesh::get_vertex_size() const {
|
||||||
return vertices_.size();
|
return vertices_.size();
|
||||||
};
|
};
|
||||||
|
|
||||||
const decltype(Vertex::texture_coordinate) &
|
const decltype(Vertex::texture_coordinate) &
|
||||||
Mesh::get_texture_coordinate(const unsigned int index) const {
|
Mesh::get_texture_coordinate(const unsigned int index) const {
|
||||||
return (vertices_[index])->texture_coordinate;
|
return (vertices_[index]).texture_coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point3d Mesh::get_normal_vector(const unsigned int index) const {
|
Point3d Mesh::get_normal_vector(const unsigned int index) const {
|
||||||
return (vertices_[index])->normal;
|
return (vertices_[index]).normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Triangle> &Mesh::get_primitives() const {
|
std::vector<Triangle> Mesh::get_primitives() const {
|
||||||
return primitives_;
|
std::vector<Triangle> primitives;
|
||||||
};
|
for (const auto &idx : indices_) {
|
||||||
|
primitives.push_back(Triangle(vertices_, idx[0], idx[1], idx[2]));
|
||||||
|
}
|
||||||
|
return primitives;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Triangle> &Mesh::get_primitives() { return primitives_; };
|
Triangle Mesh::get_primitive(const size_t index) const {
|
||||||
|
assert(index >= 0 && index < indices_.size());
|
||||||
std::shared_ptr<PhoneMaterial> &Mesh::get_material() { return material_; }
|
return Triangle(vertices_, indices_[index][0], indices_[index][1],
|
||||||
|
indices_[index][2]);
|
||||||
|
}
|
||||||
|
|
||||||
const std::shared_ptr<PhoneMaterial> &Mesh::get_material() const {
|
const std::shared_ptr<PhoneMaterial> &Mesh::get_material() const {
|
||||||
return material_;
|
return material_;
|
||||||
|
@ -54,19 +62,19 @@ std::vector<Mesh> Mesh::load_mesh(
|
||||||
for (const auto &mesh : loader.LoadedMeshes) {
|
for (const auto &mesh : loader.LoadedMeshes) {
|
||||||
spdlog::info("Current mesh has {} vertices.", mesh.Vertices.size());
|
spdlog::info("Current mesh has {} vertices.", mesh.Vertices.size());
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Vertex>> vertices;
|
std::vector<Vertex> vertices;
|
||||||
for (decltype(mesh.Vertices)::size_type i = 0; i < mesh.Vertices.size();
|
for (decltype(mesh.Vertices)::size_type i = 0; i < mesh.Vertices.size();
|
||||||
i++) {
|
i++) {
|
||||||
vertices.push_back(std::make_shared<Vertex>(
|
vertices.push_back(Vertex(
|
||||||
OBJL_VEC3_TO_EIGEN_VECTOR(mesh.Vertices[i].Position),
|
OBJL_VEC3_TO_EIGEN_VECTOR(mesh.Vertices[i].Position),
|
||||||
OBJL_VEC3_TO_EIGEN_VECTOR(mesh.Vertices[i].Normal),
|
OBJL_VEC3_TO_EIGEN_VECTOR(mesh.Vertices[i].Normal),
|
||||||
OBJL_VEC2_TO_EIGEN_VECTOR(mesh.Vertices[i].TextureCoordinate)));
|
OBJL_VEC2_TO_EIGEN_VECTOR(mesh.Vertices[i].TextureCoordinate)));
|
||||||
}
|
}
|
||||||
std::vector<Triangle> primitives;
|
std::vector<std::array<size_t, 3>> indices;
|
||||||
for (decltype(mesh.Indices)::size_type i = 0; i < mesh.Indices.size();
|
for (decltype(mesh.Indices)::size_type i = 0; i < mesh.Indices.size();
|
||||||
i += 3) {
|
i += 3) {
|
||||||
primitives.push_back(Triangle(vertices, mesh.Indices[i],
|
indices.push_back(
|
||||||
mesh.Indices[i + 1], mesh.Indices[i + 2]));
|
{mesh.Indices[i], mesh.Indices[i + 1], mesh.Indices[i + 2]});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<Texture::TextureType, std::shared_ptr<Texture>> textures;
|
std::unordered_map<Texture::TextureType, std::shared_ptr<Texture>> textures;
|
||||||
|
@ -82,7 +90,7 @@ std::vector<Mesh> Mesh::load_mesh(
|
||||||
auto material = std::make_shared<PhoneMaterial>(
|
auto material = std::make_shared<PhoneMaterial>(
|
||||||
textures, std::make_shared<Lamp>(Point3d{}, 16.));
|
textures, std::make_shared<Lamp>(Point3d{}, 16.));
|
||||||
|
|
||||||
res.push_back(Mesh(vertices, primitives, material));
|
res.push_back(Mesh(vertices, indices, material));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
18
src/mesh.h
18
src/mesh.h
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
@ -12,8 +13,8 @@
|
||||||
|
|
||||||
class Mesh {
|
class Mesh {
|
||||||
public:
|
public:
|
||||||
Mesh(const std::vector<std::shared_ptr<Vertex>> &vertices,
|
Mesh(const std::vector<Vertex> &vertices,
|
||||||
const std::vector<Triangle> &primitives,
|
const std::vector<std::array<size_t, 3>> &indices,
|
||||||
const std::shared_ptr<PhoneMaterial> &phone_material);
|
const std::shared_ptr<PhoneMaterial> &phone_material);
|
||||||
|
|
||||||
static std::vector<Mesh> load_mesh(
|
static std::vector<Mesh> load_mesh(
|
||||||
|
@ -21,22 +22,23 @@ public:
|
||||||
const std::unordered_map<Texture::TextureType, std::string> textures);
|
const std::unordered_map<Texture::TextureType, std::string> textures);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<std::shared_ptr<Vertex>>::size_type get_vertex_size() const;
|
std::vector<Vertex> &get_vertices();
|
||||||
|
|
||||||
|
std::vector<Vertex>::size_type get_vertex_size() const;
|
||||||
|
|
||||||
const decltype(Vertex::texture_coordinate) &
|
const decltype(Vertex::texture_coordinate) &
|
||||||
get_texture_coordinate(const unsigned int index) const;
|
get_texture_coordinate(const unsigned int index) const;
|
||||||
|
|
||||||
Point3d get_normal_vector(const unsigned int index) const;
|
Point3d get_normal_vector(const unsigned int index) const;
|
||||||
|
|
||||||
const std::vector<Triangle> &get_primitives() const;
|
std::vector<Triangle> get_primitives() const;
|
||||||
std::vector<Triangle> &get_primitives();
|
Triangle get_primitive(const size_t index) const;
|
||||||
|
|
||||||
std::shared_ptr<PhoneMaterial> &get_material();
|
|
||||||
const std::shared_ptr<PhoneMaterial> &get_material() const;
|
const std::shared_ptr<PhoneMaterial> &get_material() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<Vertex>> vertices_;
|
std::vector<Vertex> vertices_;
|
||||||
std::vector<Triangle> primitives_;
|
std::vector<std::array<size_t, 3>> indices_;
|
||||||
|
|
||||||
std::shared_ptr<PhoneMaterial> material_;
|
std::shared_ptr<PhoneMaterial> material_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,8 +19,6 @@ MinusRenderer::MinusRenderer(float near, float far, float fov,
|
||||||
|
|
||||||
void MinusRenderer::set_meshes(const std::vector<Mesh> &meshes) {
|
void MinusRenderer::set_meshes(const std::vector<Mesh> &meshes) {
|
||||||
meshes_ = meshes;
|
meshes_ = meshes;
|
||||||
spdlog::info("Mesh size: {}, the primitives size of the first mesh: {}",
|
|
||||||
meshes_.size(), meshes_.front().get_primitives().size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float MinusRenderer::calculate_height(const float fov, const float near) {
|
float MinusRenderer::calculate_height(const float fov, const float near) {
|
||||||
|
@ -94,35 +92,38 @@ MinusRenderer::construct_transform(const int resolution_width,
|
||||||
|
|
||||||
std::tuple<double, double, double>
|
std::tuple<double, double, double>
|
||||||
MinusRenderer::calculate_barycentric_coordinate(const Triangle &t,
|
MinusRenderer::calculate_barycentric_coordinate(const Triangle &t,
|
||||||
const Point2d &p) {
|
const Point3d &p) {
|
||||||
const auto &points = t.get_vertex_position();
|
const auto &points = t.get_vertex_position();
|
||||||
const auto &A = (points[0]).head(2);
|
const auto &pa = points[0];
|
||||||
const auto &B = (points[1]).head(2);
|
const auto &pb = points[1];
|
||||||
const auto &C = (points[2]).head(2);
|
const auto &pc = points[2];
|
||||||
double alpha =
|
const auto &triangle_normal = t.normal_vector();
|
||||||
(-(p.x() - B.x()) * (C.y() - B.y()) + (p.y() - B.y()) * (C.x() - B.x())) /
|
|
||||||
(-(A.x() - B.x()) * (C.y() - B.y()) + (A.y() - B.y()) * (C.x() - B.x()));
|
const double squared_area = triangle_normal.norm() * triangle_normal.norm();
|
||||||
double beta =
|
const double alpha =
|
||||||
(-(p.x() - C.x()) * (A.y() - C.y()) + (p.y() - C.y()) * (A.x() - C.x())) /
|
(triangle_normal.dot((pc - pb).cross(p - pb))) / squared_area;
|
||||||
(-(B.x() - C.x()) * (A.y() - C.y()) + (B.y() - C.y()) * (A.x() - C.x()));
|
const double beta =
|
||||||
double gamma = 1. - alpha - beta;
|
(triangle_normal.dot((pa - pc).cross(p - pc))) / squared_area;
|
||||||
|
const double gamma =
|
||||||
|
(triangle_normal.dot((pb - pa).cross(p - pa))) / squared_area;
|
||||||
|
|
||||||
return {alpha, beta, gamma};
|
return {alpha, beta, gamma};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinusRenderer::model_transform(const TransformMatrix &mtx) {
|
void MinusRenderer::model_transform(const TransformMatrix &mtx) {
|
||||||
for (auto &m : meshes_) {
|
for (auto &m : meshes_) {
|
||||||
for (auto &t : m.get_primitives()) {
|
for (auto &v : m.get_vertices()) {
|
||||||
const auto &[res, _] = apply_transform(mtx, t.get_vertex_position());
|
v.position = (mtx * v.position.homogeneous()).hnormalized();
|
||||||
t.set_points(res);
|
v.normal = (mtx * v.normal.homogeneous()).hnormalized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinusRenderer::view_transform(const TransformMatrix &mtx) {
|
void MinusRenderer::view_transform(const TransformMatrix &mtx) {
|
||||||
for (auto &m : meshes_) {
|
for (auto &m : meshes_) {
|
||||||
for (auto &t : m.get_primitives()) {
|
for (auto &v : m.get_vertices()) {
|
||||||
const auto &[res, _] = apply_transform(mtx, t.get_vertex_position());
|
v.position = (mtx * v.position.homogeneous()).hnormalized();
|
||||||
t.set_points(res);
|
v.normal = (mtx * v.normal.homogeneous()).hnormalized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,22 +134,16 @@ cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
const auto [ss_transform, inv_ss_transform] =
|
const auto [ss_transform, inv_ss_transform] =
|
||||||
construct_transform(resolution_width, resolution_height);
|
construct_transform(resolution_width, resolution_height);
|
||||||
|
|
||||||
// 主要为了把顶点坐标拷贝一份,否则 camera space 的坐标被变换到 screen space,
|
|
||||||
// 下次渲染时拿到的就不是 camera space 的坐标
|
|
||||||
std::vector<Mesh> meshes = meshes_;
|
|
||||||
Rasterizer rasterizer{resolution_width, resolution_height};
|
Rasterizer rasterizer{resolution_width, resolution_height};
|
||||||
for (int mesh_index = 0; mesh_index < meshes.size(); ++mesh_index) {
|
for (int mesh_index = 0; mesh_index < meshes_.size(); ++mesh_index) {
|
||||||
auto &mesh = meshes[mesh_index];
|
auto primitives = (meshes_[mesh_index]).get_primitives();
|
||||||
auto &primitives = mesh.get_primitives();
|
for (auto &t : primitives) {
|
||||||
for (int i = 0; i < primitives.size(); ++i) {
|
t.set_points(apply_transform(ss_transform, t.get_vertex_position()));
|
||||||
auto &t = primitives[i];
|
|
||||||
const auto &triangle_vertices = t.get_vertex_position();
|
|
||||||
const auto &[res, _] =
|
|
||||||
apply_transform(ss_transform, t.get_vertex_position());
|
|
||||||
t.set_points(res);
|
|
||||||
}
|
}
|
||||||
|
rasterizer.rasterize(mesh_index, primitives);
|
||||||
}
|
}
|
||||||
const auto &shading_points = rasterizer.rasterize(meshes);
|
|
||||||
|
const auto &shading_points = rasterizer.get_shading_points();
|
||||||
assert(!shading_points.empty());
|
assert(!shading_points.empty());
|
||||||
cv::Mat color_image(shading_points.size(), (shading_points[0]).size(),
|
cv::Mat color_image(shading_points.size(), (shading_points[0]).size(),
|
||||||
CV_8UC3);
|
CV_8UC3);
|
||||||
|
@ -162,23 +157,16 @@ cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
if (fragment.triangle.mesh_index >= 0 &&
|
if (fragment.triangle.mesh_index >= 0 &&
|
||||||
fragment.triangle.mesh_index < meshes_.size()) {
|
fragment.triangle.mesh_index < meshes_.size()) {
|
||||||
const auto &mesh = meshes_[fragment.triangle.mesh_index];
|
const auto &mesh = meshes_[fragment.triangle.mesh_index];
|
||||||
const auto &primitives = mesh.get_primitives();
|
if (fragment.depth > -std::numeric_limits<double>::infinity()) {
|
||||||
if (fragment.triangle.triangle_index >= 0 &&
|
|
||||||
fragment.triangle.triangle_index < primitives.size()) {
|
|
||||||
const Point3d &position =
|
const Point3d &position =
|
||||||
(inv_ss_transform *
|
(inv_ss_transform *
|
||||||
(Point3d{x + 0.5, y + 0.5, fragment.depth}.homogeneous()))
|
(Point3d{x + 0.5, y + 0.5, fragment.depth}.homogeneous()))
|
||||||
.hnormalized();
|
.hnormalized();
|
||||||
spdlog::trace("Screen space potions: ({}, {}, {}), camera space "
|
|
||||||
"position: ({}, {}, {})",
|
|
||||||
x + 0.5, y + 0.5, fragment.depth, position.x(),
|
|
||||||
position.y(), position.z());
|
|
||||||
|
|
||||||
const auto &triangle = primitives[fragment.triangle.triangle_index];
|
const auto &triangle =
|
||||||
|
mesh.get_primitive(fragment.triangle.triangle_index);
|
||||||
const auto &[alpha, beta, gamma] =
|
const auto &[alpha, beta, gamma] =
|
||||||
calculate_barycentric_coordinate(triangle, position.head(2));
|
calculate_barycentric_coordinate(triangle, position);
|
||||||
spdlog::trace("barycentric coordinate: ({}, {}, {})", alpha, beta,
|
|
||||||
gamma);
|
|
||||||
|
|
||||||
std::vector<Point2d> triangle_uv;
|
std::vector<Point2d> triangle_uv;
|
||||||
std::vector<Point3d> triangle_normal;
|
std::vector<Point3d> triangle_normal;
|
||||||
|
@ -191,9 +179,7 @@ cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
gamma * triangle_uv[2].x(),
|
gamma * triangle_uv[2].x(),
|
||||||
alpha * triangle_uv[0].y() + beta * triangle_uv[1].y() +
|
alpha * triangle_uv[0].y() + beta * triangle_uv[1].y() +
|
||||||
gamma * triangle_uv[2].y()};
|
gamma * triangle_uv[2].y()};
|
||||||
spdlog::trace("UV: ({}, {}, {})", uv.x(), uv.y());
|
const auto &normal = -1. * Point3d(alpha * triangle_normal[0].x() +
|
||||||
|
|
||||||
const auto &normal = Point3d{alpha * triangle_normal[0].x() +
|
|
||||||
beta * triangle_normal[1].x() +
|
beta * triangle_normal[1].x() +
|
||||||
gamma * triangle_normal[2].x(),
|
gamma * triangle_normal[2].x(),
|
||||||
alpha * triangle_normal[0].y() +
|
alpha * triangle_normal[0].y() +
|
||||||
|
@ -201,12 +187,10 @@ cv::Mat MinusRenderer::render(const int resolution_width,
|
||||||
gamma * triangle_normal[2].y(),
|
gamma * triangle_normal[2].y(),
|
||||||
alpha * triangle_normal[0].z() +
|
alpha * triangle_normal[0].z() +
|
||||||
beta * triangle_normal[1].z() +
|
beta * triangle_normal[1].z() +
|
||||||
gamma * triangle_normal[2].z()}
|
gamma * triangle_normal[2].z())
|
||||||
.normalized();
|
.normalized();
|
||||||
spdlog::trace("Normal: ({}, {}, {})", normal.x(), normal.y(),
|
|
||||||
normal.z());
|
|
||||||
|
|
||||||
auto &material = mesh.get_material();
|
const auto &material = mesh.get_material();
|
||||||
pixel_color =
|
pixel_color =
|
||||||
material->shade(Vertex{position, normal, uv}, Point3d{});
|
material->shade(Vertex{position, normal, uv}, Point3d{});
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ private:
|
||||||
static float calculate_height(const float fov, const float near);
|
static float calculate_height(const float fov, const float near);
|
||||||
static float calculate_width(const float height, const float ratio);
|
static float calculate_width(const float height, const float ratio);
|
||||||
static std::tuple<double, double, double>
|
static std::tuple<double, double, double>
|
||||||
calculate_barycentric_coordinate(const Triangle &t, const Point2d &p);
|
calculate_barycentric_coordinate(const Triangle &t, const Point3d &p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::pair<TransformMatrix, TransformMatrix>
|
std::pair<TransformMatrix, TransformMatrix>
|
||||||
|
|
|
@ -10,19 +10,19 @@ PhoneMaterial::PhoneMaterial(
|
||||||
const std::unordered_map<Texture::TextureType, std::shared_ptr<Texture>>
|
const std::unordered_map<Texture::TextureType, std::shared_ptr<Texture>>
|
||||||
&textures,
|
&textures,
|
||||||
const std::shared_ptr<Lamp> &lamp)
|
const std::shared_ptr<Lamp> &lamp)
|
||||||
: point_lamp_(lamp), textures_(textures), Ka(cv::Vec3b{32, 32, 32}),
|
: point_lamp_(lamp), textures_(textures), Ka(cv::Vec3b{24, 24, 24}),
|
||||||
Ks(cv::Vec3b(64, 64, 64)),
|
Ks(cv::Vec3b(48, 48, 48)),
|
||||||
specular_attenuation_factor_(defaultAttenuationFactor) {
|
specular_attenuation_factor_(defaultAttenuationFactor) {
|
||||||
spdlog::info("Specular attenuation factor: {}", specular_attenuation_factor_);
|
spdlog::info("Specular attenuation factor: {}", specular_attenuation_factor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Vec3b PhoneMaterial::shade(const Vertex &shading_point,
|
cv::Vec3b PhoneMaterial::shade(const Vertex &shading_point,
|
||||||
const Point3d &view_point) {
|
const Point3d &view_point) const {
|
||||||
cv::Vec3b shading_res{0, 0, 0};
|
cv::Vec3b shading_res{0, 0, 0};
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
assert(textures_.find(Texture::DiffuseMap) != textures_.end());
|
assert(textures_.find(Texture::DiffuseMap) != textures_.end());
|
||||||
const auto &diffuse_map = textures_[Texture::DiffuseMap];
|
const auto &diffuse_map = textures_.at(Texture::DiffuseMap);
|
||||||
const auto &Kd = diffuse_map->sample(shading_point.texture_coordinate);
|
const auto &Kd = diffuse_map->sample(shading_point.texture_coordinate);
|
||||||
|
|
||||||
const auto &point2light_vector =
|
const auto &point2light_vector =
|
||||||
|
|
|
@ -17,10 +17,10 @@ public:
|
||||||
std::shared_ptr<Texture>> &textures,
|
std::shared_ptr<Texture>> &textures,
|
||||||
const std::shared_ptr<Lamp> &lamp);
|
const std::shared_ptr<Lamp> &lamp);
|
||||||
|
|
||||||
cv::Vec3b shade(const Vertex &shading_point, const Point3d &view_point);
|
cv::Vec3b shade(const Vertex &shading_point, const Point3d &view_point) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int defaultAttenuationFactor = 16;
|
static constexpr int defaultAttenuationFactor = 12;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Lamp> point_lamp_;
|
std::shared_ptr<Lamp> point_lamp_;
|
||||||
|
|
|
@ -13,11 +13,8 @@ Rasterizer::Rasterizer(const int width, const int height)
|
||||||
shading_points_(std::vector<std::vector<RasterizerResult>>(
|
shading_points_(std::vector<std::vector<RasterizerResult>>(
|
||||||
height, std::vector<RasterizerResult>(width, RasterizerResult{}))) {}
|
height, std::vector<RasterizerResult>(width, RasterizerResult{}))) {}
|
||||||
|
|
||||||
std::vector<std::vector<RasterizerResult>>
|
void Rasterizer::rasterize(const int mesh_idx,
|
||||||
Rasterizer::rasterize(const std::vector<Mesh> &meshes) {
|
const std::vector<Triangle> &primitives) {
|
||||||
for (int m_id = 0; m_id < meshes.size(); ++m_id) {
|
|
||||||
const auto &primitives = (meshes[m_id]).get_primitives();
|
|
||||||
|
|
||||||
const int thread_num = 8;
|
const int thread_num = 8;
|
||||||
std::vector<std::thread> rasterize_threads;
|
std::vector<std::thread> rasterize_threads;
|
||||||
for (int begin = 0, offset = primitives.size() / thread_num,
|
for (int begin = 0, offset = primitives.size() / thread_num,
|
||||||
|
@ -29,18 +26,16 @@ Rasterizer::rasterize(const std::vector<Mesh> &meshes) {
|
||||||
remainer -= 1;
|
remainer -= 1;
|
||||||
}
|
}
|
||||||
rasterize_threads.push_back(std::thread(
|
rasterize_threads.push_back(std::thread(
|
||||||
[this, m_id](const std::vector<Triangle> &primitives, const int begin,
|
[this, mesh_idx](const std::vector<Triangle> &primitives,
|
||||||
const int end) {
|
const int begin, const int end) {
|
||||||
this->rasterize(m_id, primitives, begin, end);
|
this->rasterize(mesh_idx, primitives, begin, end);
|
||||||
},
|
},
|
||||||
(meshes[m_id]).get_primitives(), begin, end));
|
primitives, begin, end));
|
||||||
begin = end;
|
begin = end;
|
||||||
}
|
}
|
||||||
for (auto &t : rasterize_threads) {
|
for (auto &t : rasterize_threads) {
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return shading_points_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::rasterize(const int mesh_idx,
|
void Rasterizer::rasterize(const int mesh_idx,
|
||||||
|
@ -71,6 +66,11 @@ void Rasterizer::rasterize(const int mesh_idx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<std::vector<RasterizerResult>> &
|
||||||
|
Rasterizer::get_shading_points() const {
|
||||||
|
return shading_points_;
|
||||||
|
}
|
||||||
|
|
||||||
void Rasterizer::reset() {
|
void Rasterizer::reset() {
|
||||||
shading_points_ = std::vector<std::vector<RasterizerResult>>(
|
shading_points_ = std::vector<std::vector<RasterizerResult>>(
|
||||||
height_, std::vector<RasterizerResult>(width_, RasterizerResult{}));
|
height_, std::vector<RasterizerResult>(width_, RasterizerResult{}));
|
||||||
|
@ -80,7 +80,7 @@ std::pair<bool, double> Rasterizer::inside(const Point2d &p_screen,
|
||||||
const Triangle &t) {
|
const Triangle &t) {
|
||||||
const auto points = t.get_vertex_position();
|
const auto points = t.get_vertex_position();
|
||||||
|
|
||||||
const auto plane_normal = t.normal_vector();
|
const auto plane_normal = t.unit_normal_vector();
|
||||||
const auto plane_point = points[0];
|
const auto plane_point = points[0];
|
||||||
const auto z_screen =
|
const auto z_screen =
|
||||||
plane_point.z() - (plane_normal.x() * (p_screen.x() - plane_point.x()) +
|
plane_point.z() - (plane_normal.x() * (p_screen.x() - plane_point.x()) +
|
||||||
|
|
|
@ -21,9 +21,9 @@ public:
|
||||||
Rasterizer(const int width, const int height);
|
Rasterizer(const int width, const int height);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<std::vector<RasterizerResult>>
|
void rasterize(const int mesh_idx, const std::vector<Triangle> &primitives);
|
||||||
rasterize(const std::vector<Mesh> &meshes);
|
|
||||||
|
|
||||||
|
const std::vector<std::vector<RasterizerResult>> &get_shading_points() const;
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -9,11 +9,11 @@ Triangle::Triangle(const Point3d &a, unsigned int idx_a, const Point3d &b,
|
||||||
unsigned int idx_b, const Point3d &c, unsigned int idx_c)
|
unsigned int idx_b, const Point3d &c, unsigned int idx_c)
|
||||||
: indices_({idx_a, idx_b, idx_c}), vertices_({a, b, c}) {}
|
: indices_({idx_a, idx_b, idx_c}), vertices_({a, b, c}) {}
|
||||||
|
|
||||||
Triangle::Triangle(const std::vector<std::shared_ptr<Vertex>> &vertices,
|
Triangle::Triangle(const std::vector<Vertex> &vertices, unsigned int idx_a,
|
||||||
unsigned int idx_a, unsigned int idx_b, unsigned int idx_c)
|
unsigned int idx_b, unsigned int idx_c)
|
||||||
: indices_({idx_a, idx_b, idx_c}),
|
: indices_({idx_a, idx_b, idx_c}),
|
||||||
vertices_({(vertices[idx_a])->position, (vertices[idx_b])->position,
|
vertices_({(vertices[idx_a]).position, (vertices[idx_b]).position,
|
||||||
(vertices[idx_c])->position}) {}
|
(vertices[idx_c]).position}) {}
|
||||||
|
|
||||||
std::vector<unsigned int> Triangle::get_vertex_index() const {
|
std::vector<unsigned int> Triangle::get_vertex_index() const {
|
||||||
return {indices_[0], indices_[1], indices_[2]};
|
return {indices_[0], indices_[1], indices_[2]};
|
||||||
|
@ -45,8 +45,12 @@ BBox Triangle::axis_align_bbox() const {
|
||||||
return BBox{x_min, y_min, (x_max - x_min + 1), (y_max - y_min + 1)};
|
return BBox{x_min, y_min, (x_max - x_min + 1), (y_max - y_min + 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3d Triangle::unit_normal_vector() const {
|
||||||
|
return normal_vector().normalized();
|
||||||
|
}
|
||||||
|
|
||||||
Vector3d Triangle::normal_vector() const {
|
Vector3d Triangle::normal_vector() const {
|
||||||
const auto v1 = vertices_[1] - vertices_[0];
|
const auto v1 = vertices_[1] - vertices_[0];
|
||||||
const auto v2 = vertices_[2] - vertices_[1];
|
const auto v2 = vertices_[2] - vertices_[1];
|
||||||
return v1.cross(v2).normalized();
|
return v1.cross(v2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ class Triangle {
|
||||||
public:
|
public:
|
||||||
Triangle(const Point3d &a, unsigned int idx_a, const Point3d &b,
|
Triangle(const Point3d &a, unsigned int idx_a, const Point3d &b,
|
||||||
unsigned int idx_b, const Point3d &c, unsigned int idx_c);
|
unsigned int idx_b, const Point3d &c, unsigned int idx_c);
|
||||||
Triangle(const std::vector<std::shared_ptr<Vertex>> &vertices,
|
Triangle(const std::vector<Vertex> &vertices, unsigned int idx_a,
|
||||||
unsigned int idx_a, unsigned int idx_b, unsigned int idx_c);
|
unsigned int idx_b, unsigned int idx_c);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<unsigned int> get_vertex_index() const;
|
std::vector<unsigned int> get_vertex_index() const;
|
||||||
|
@ -22,6 +22,7 @@ public:
|
||||||
public:
|
public:
|
||||||
BBox axis_align_bbox() const;
|
BBox axis_align_bbox() const;
|
||||||
Vector3d normal_vector() const;
|
Vector3d normal_vector() const;
|
||||||
|
Vector3d unit_normal_vector() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<unsigned int, 3> indices_;
|
std::array<unsigned int, 3> indices_;
|
||||||
|
|
|
@ -11,14 +11,21 @@ bool fequal(const FloatType a, const FloatType b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int d>
|
template <int d>
|
||||||
std::pair<std::vector<Eigen::Vector<double, d>>, std::vector<double>>
|
std::vector<Eigen::Vector<double, d>>
|
||||||
apply_transform(const TransformMatrix &mtx,
|
apply_transform(const TransformMatrix &mtx,
|
||||||
const std::vector<Eigen::Vector<double, d>> &points) {
|
const std::vector<Eigen::Vector<double, d>> &points) {
|
||||||
std::pair<std::vector<Eigen::Vector<double, d>>, std::vector<double>> res{};
|
std::vector<Eigen::Vector<double, d>> res{};
|
||||||
for (const auto &p : points) {
|
for (const auto &p : points) {
|
||||||
const auto &transform_res = mtx * p.homogeneous();
|
const auto &transform_res = mtx * p.homogeneous();
|
||||||
res.first.push_back(transform_res.hnormalized());
|
res.push_back(transform_res.hnormalized());
|
||||||
res.second.push_back(transform_res.w());
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <int d>
|
||||||
|
void apply_transform_in_place(const TransformMatrix &mtx,
|
||||||
|
std::vector<Eigen::Vector<double, d>> &points) {
|
||||||
|
for (auto &p : points) {
|
||||||
|
p = mtx * p.homogeneous().hnormalized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue