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