Compare commits

...

5 Commits

Author SHA1 Message Date
mckay b04bfcf403 refactor(cylinder_face): use geometric hash based on world_to_local transform 1 week ago
mckay 987d3fb127 fix: replace local_to_world matrix usage with fetch_aabb in mark_primitive_boundings 1 week ago
mckay 03f33d01c4 fix: refactor translation handling in apply_transform to use Eigen::Translation3d 1 week ago
mckay 2046b9ba6a Revert "fix: Make get_identity_local_to_world virtual to support primitives with multiple subfaces (e.g., cylinder)." 1 week ago
mckay 95f6594bb9 fix: update matrix references in hasher for cylinder and plane to use local_to_world. Hash of plane changed to col 0 and 3 2 weeks ago
  1. 3
      network_process/src/prim_gen/extract_vertex_infos.cpp
  2. 12
      primitive_process/interface/base/primitive.hpp
  3. 9
      primitive_process/interface/primitive/simple/cylinder.hpp
  4. 16
      primitive_process/interface/subface/simple/cylinder_face.hpp
  5. 7
      primitive_process/interface/subface/simple/plane.hpp
  6. 21
      primitive_process/src/base/primitive.cpp
  7. 5
      primitive_process/src/base/subface.cpp
  8. 5
      primitive_process/src/primitive/simple/cylinder.cpp

3
network_process/src/prim_gen/extract_vertex_infos.cpp

@ -10,8 +10,7 @@ aabb_t mark_primitive_boundings(double aabb_margin, const baked_blobtree_t& tree
aabb_t scene_aabb{}; aabb_t scene_aabb{};
for (const auto [primitive_ptr, _] : tree.primitives) { for (const auto [primitive_ptr, _] : tree.primitives) {
const auto& primitive = *primitive_ptr; const auto& primitive = *primitive_ptr;
auto local_to_world_matrix = primitive.get_identity_local_to_world(); aabb_t primitive_aabb = primitive.fetch_aabb();
aabb_t primitive_aabb = aabb_unit.transformed(local_to_world_matrix);
primitive_aabb.min().array() -= aabb_margin; primitive_aabb.min().array() -= aabb_margin;
primitive_aabb.max().array() += aabb_margin; primitive_aabb.max().array() += aabb_margin;
scene_aabb.extend(primitive_aabb); scene_aabb.extend(primitive_aabb);

12
primitive_process/interface/base/primitive.hpp

@ -12,6 +12,7 @@
template <typename T> template <typename T>
using marked_subface_ptr_t = marked_ptr<T, 1>; using marked_subface_ptr_t = marked_ptr<T, 1>;
using aabb_t = Eigen::AlignedBox<double, 3>;
enum class sign_t : uint8_t { positive = 1, negative = 2, zero = 0 }; enum class sign_t : uint8_t { positive = 1, negative = 2, zero = 0 };
@ -52,19 +53,14 @@ EXTERN_C struct PE_API primitive {
virtual primitive_type get_type() const = 0; virtual primitive_type get_type() const = 0;
virtual marked_subface_ptr_t<subface> *get_subface() const = 0; virtual marked_subface_ptr_t<subface> *get_subface() const = 0;
virtual size_t get_subface_count() const = 0; virtual size_t get_subface_count() const = 0;
aabb_t m_aabb = aabb_t(Eigen::Vector3d(-1, -1, -1), Eigen::Vector3d(1, 1, 1));
// sign_t judge_sign_by_subface_sdf(const std::vector<double> &) const; // sign_t judge_sign_by_subface_sdf(const std::vector<double> &) const;
// sign_t judge_sign_by_subface_sdf_sign(const std::vector<sign_t> &) const; // sign_t judge_sign_by_subface_sdf_sign(const std::vector<sign_t> &) const;
dynamic_bitset_mp<> judge_sign_by_subface_sign(stl_vector_mp<dynamic_bitset_mp<>>) const; dynamic_bitset_mp<> judge_sign_by_subface_sign(stl_vector_mp<dynamic_bitset_mp<>>) const;
// for simple primitive: sphere, cylinder, cone, box
// we use world_to_local as OBB and judge inside/outside by [-1, 1]^3 aabb_t fetch_aabb() const;
// so we don't need to fetch aabb anymore
// aabb fetch_aabb() const;
// CAUTION: keep characteristics local_to_world as the first subface's part
// why virtual? for special primitive like cylinder, it may have multiple parts, the part
// with index 0 may not be the identity transform. e.g., cylinder face has no z translation.
virtual const internal::transform_block &get_identity_local_to_world() const;
void apply_transform(internal::transform_type, Eigen::Vector4d); void apply_transform(internal::transform_type, Eigen::Vector4d);

9
primitive_process/interface/primitive/simple/cylinder.hpp

@ -16,15 +16,6 @@ struct cylinder_t final : primitive {
marked_subface_ptr_t<internal::plane_t> bottom_plane{}; marked_subface_ptr_t<internal::plane_t> bottom_plane{};
marked_subface_ptr_t<internal::plane_t> top_plane{}; marked_subface_ptr_t<internal::plane_t> top_plane{};
// why virtual? For special primitives like cylinder, it may have multiple parts.
// The part with index 0 may not be the identity transform.
// For example, the cylinder face has no z translation.
// Note: The AABB of a cylinder is defined by the side surface, and z-axis scaling does not affect the side surface's radius.
// The degeneracy (simplification) check for a cylinder only considers the first two rows of the transform matrix (x/y directions),
// because scaling along z does not change the essential geometry of the cylinder side surface.
// TODO: the better way is to redefine cylinder, make identity transform as the first part.
const internal::transform_block &get_identity_local_to_world() const override;
protected: protected:
void initialize(primitive_data_center_t &, const std::vector<std::pair<internal::paired_model_matrix *, bool>> &) override; void initialize(primitive_data_center_t &, const std::vector<std::pair<internal::paired_model_matrix *, bool>> &) override;

16
primitive_process/interface/subface/simple/cylinder_face.hpp

@ -34,8 +34,20 @@ template <>
struct hasher<internal::cylinder_paired_model_matrix> { struct hasher<internal::cylinder_paired_model_matrix> {
size_t operator()(const internal::cylinder_paired_model_matrix &block) const size_t operator()(const internal::cylinder_paired_model_matrix &block) const
{ {
Eigen::Matrix<double, 2, 4> character_rows = block.data->world_to_local.matrix().topRows<2>(); const auto& mat = block.data->local_to_world.matrix(); // 3x4
return XXH3_64bits(character_rows.data(), sizeof(decltype(character_rows))); Eigen::Matrix3d A = mat.block<3,3>(0,0);
Eigen::Vector3d b = mat.col(3);
Eigen::Matrix3d B = A.inverse();
Eigen::Matrix<double, 2, 3> R = B.topRows<2>();
Eigen::Matrix3d G = R.transpose() * R;
Eigen::Vector2d zero_proj = R * b;
size_t h = XXH3_64bits(G.data(), sizeof(Eigen::Matrix3d));
h ^= XXH3_64bits(zero_proj.data(), sizeof(Eigen::Vector2d));
return h;
} }
}; };

7
primitive_process/interface/subface/simple/plane.hpp

@ -34,8 +34,11 @@ template <>
struct hasher<internal::plane_paired_model_matrix> { struct hasher<internal::plane_paired_model_matrix> {
size_t operator()(const internal::plane_paired_model_matrix &block) const size_t operator()(const internal::plane_paired_model_matrix &block) const
{ {
Eigen::Vector4d character_row = block.data->world_to_local.matrix().row(0); const auto& mat = block.data->local_to_world.matrix();
return XXH3_64bits(character_row.data(), sizeof(Eigen::Vector4d)); Eigen::Matrix<double, 3, 2> character_col;
character_col.col(0) = mat.col(0);
character_col.col(1) = mat.col(3);
return XXH3_64bits(character_col.data(), sizeof(Eigen::Matrix<double, 3, 2>));
} }
}; };

21
primitive_process/src/base/primitive.cpp

@ -42,9 +42,9 @@ dynamic_bitset_mp<> primitive::judge_sign_by_subface_sign(stl_vector_mp<dynamic_
return res; return res;
} }
const internal::transform_block &primitive::get_identity_local_to_world() const aabb_t primitive::fetch_aabb() const
{ {
return get_subface()[0].get_ptr()->raw_local_to_world(); return m_aabb;
} }
void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d param) void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d param)
@ -59,5 +59,22 @@ void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d p
new_model_matrices.emplace_back(subface_ptr->apply_transform(type, param)); new_model_matrices.emplace_back(subface_ptr->apply_transform(type, param));
} }
// aabb
Eigen::Affine3d affine = Eigen::Affine3d::Identity();
switch (type) {
case internal::transform_type::scale: {
affine.linear() = param.head<3>().asDiagonal();
} break;
case internal::transform_type::rotation: {
affine.linear() = Eigen::Quaterniond(param).toRotationMatrix();
} break;
case internal::transform_type::translation: {
Eigen::Translation3d translation(param.head<3>());
affine = Eigen::Affine3d(translation);
} break;
default: throw std::invalid_argument("Invalid transform type");
}
m_aabb = m_aabb.transformed(affine);
initialize(*subfaces[0].get_ptr()->data_center, new_model_matrices); initialize(*subfaces[0].get_ptr()->data_center, new_model_matrices);
} }

5
primitive_process/src/base/subface.cpp

@ -31,8 +31,9 @@ std::pair<internal::paired_model_matrix *, bool> subface::apply_transform(intern
temp.world_to_local.linear() = temp.world_to_local.linear() * rotation_matrix.transpose(); temp.world_to_local.linear() = temp.world_to_local.linear() * rotation_matrix.transpose();
} break; } break;
case internal::transform_type::translation: { case internal::transform_type::translation: {
temp.local_to_world.translation() += param.head<3>(); Eigen::Translation3d translation(param.head<3>());
temp.world_to_local.translation() -= param.head<3>(); temp.local_to_world = translation * temp.local_to_world;
temp.world_to_local = temp.world_to_local * translation.inverse();
} break; } break;
default: throw std::invalid_argument("Invalid transform type"); default: throw std::invalid_argument("Invalid transform type");
} }

5
primitive_process/src/primitive/simple/cylinder.cpp

@ -61,9 +61,4 @@ void cylinder_t::initialize(primitive_data_center_t
data_center.planes.release(plane_paired_model_matrix{old_model_matrices[2]}); data_center.planes.release(plane_paired_model_matrix{old_model_matrices[2]});
} }
} }
const internal::transform_block &cylinder_t::get_identity_local_to_world() const
{
return get_subface()[1].get_ptr()->raw_local_to_world();
}
} // namespace internal } // namespace internal
Loading…
Cancel
Save