mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 04:45:53 +08:00
RaycastManager use directly AABBMesh instead of MeshRayCaster
This commit is contained in:
parent
6d0d24eecf
commit
67155e8da0
@ -559,7 +559,7 @@ void reset_skew_respect_z(Transform3d &m)
|
||||
|
||||
Transform3d rot; // = Transform3d::Identity();
|
||||
if (priv::allign_vec(z_after, z_before, rot))
|
||||
m = rot * m;
|
||||
m = m * rot;
|
||||
}
|
||||
|
||||
// Multiply from right
|
||||
@ -3489,21 +3489,33 @@ std::optional<Vec3d> priv::calc_surface_offset(const ModelVolume &volume, Raycas
|
||||
std::optional<RaycastManager::Hit> hit_opt = raycast_manager.unproject(point, direction, &cond);
|
||||
|
||||
// Try to find closest point when no hit object in emboss direction
|
||||
if (!hit_opt.has_value())
|
||||
hit_opt = raycast_manager.closest(point);
|
||||
if (!hit_opt.has_value()) {
|
||||
std::optional<RaycastManager::ClosePoint> close_point_opt = raycast_manager.closest(point);
|
||||
|
||||
// It should NOT appear. Closest point always exists.
|
||||
if (!hit_opt.has_value())
|
||||
return {};
|
||||
// It should NOT appear. Closest point always exists.
|
||||
assert(close_point_opt.has_value());
|
||||
if (!close_point_opt.has_value())
|
||||
return {};
|
||||
|
||||
// It is no neccesary to move with origin by very small value
|
||||
if (close_point_opt->squared_distance < EPSILON)
|
||||
return {};
|
||||
|
||||
const RaycastManager::ClosePoint &close_point = *close_point_opt;
|
||||
Transform3d hit_tr = raycast_manager.get_transformation(close_point.tr_key);
|
||||
Vec3d hit_world = hit_tr * close_point.point;
|
||||
Vec3d offset_world = hit_world - point; // vector in world
|
||||
Vec3d offset_volume = to_world.inverse().linear() * offset_world;
|
||||
return offset_volume;
|
||||
}
|
||||
|
||||
// It is no neccesary to move with origin by very small value
|
||||
if (hit_opt->squared_distance < EPSILON)
|
||||
return {};
|
||||
|
||||
const RaycastManager::Hit &hit = *hit_opt;
|
||||
Transform3d hit_tr = raycast_manager.get_transformation(hit.tr_key);
|
||||
Vec3d hit_world = hit_tr * hit.position.cast<double>();
|
||||
Vec3d offset_world = hit_world - point; // vector in world
|
||||
if (hit.squared_distance < EPSILON)
|
||||
return {};
|
||||
Transform3d hit_tr = raycast_manager.get_transformation(hit.tr_key);
|
||||
Vec3d hit_world = hit_tr * hit.position;
|
||||
Vec3d offset_world = hit_world - point; // vector in world
|
||||
// TIP: It should be close to only z move
|
||||
Vec3d offset_volume = to_world.inverse().linear() * offset_world;
|
||||
return offset_volume;
|
||||
@ -4246,7 +4258,7 @@ bool priv::start_create_volume_on_surface_job(
|
||||
Transform3d instance = gl_volume->get_instance_transformation().get_matrix();
|
||||
|
||||
// Create result volume transformation
|
||||
Transform3d surface_trmat = create_transformation_onto_surface(hit->position, hit->normal);
|
||||
Transform3d surface_trmat = create_transformation_onto_surface(hit->position.cast<float>(), hit->normal.cast<float>());
|
||||
const FontProp &font_prop = emboss_data.text_configuration.style.prop;
|
||||
apply_transformation(font_prop, surface_trmat);
|
||||
Transform3d world_new = hit_to_world * surface_trmat;
|
||||
|
@ -3,69 +3,50 @@
|
||||
|
||||
// include for earn camera
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/CameraUtils.hpp"
|
||||
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
namespace priv {
|
||||
|
||||
using namespace Slic3r;
|
||||
// copied from private part of RaycastManager.hpp
|
||||
using Raycaster = std::pair<size_t, std::unique_ptr<MeshRaycaster> >;
|
||||
// ModelVolume.id
|
||||
static void actualize(RaycastManager::Meshes &meshes, const ModelVolumePtrs &volumes, const RaycastManager::ISkip *skip);
|
||||
static const AABBMesh * get_mesh(const RaycastManager::Meshes &meshes, size_t volume_id);
|
||||
static RaycastManager::TrKey create_key(const ModelVolume* volume, const ModelInstance* instance){
|
||||
return std::make_pair(instance->id().id, volume->id().id); }
|
||||
static RaycastManager::TrItems::iterator find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key);
|
||||
static bool is_lower_key(const RaycastManager::TrKey &k1, const RaycastManager::TrKey &k2) {
|
||||
return k1.first < k2.first || k1.first == k2.first && k1.second < k2.second; }
|
||||
static bool is_lower(const RaycastManager::TrItem &i1, const RaycastManager::TrItem &i2) {
|
||||
return is_lower_key(i1.first, i2.first); };
|
||||
|
||||
using Raycasters = std::vector<Raycaster>;
|
||||
// Copy functionality from MeshRaycaster::unproject_on_mesh without filtering
|
||||
using SurfacePoint = RaycastManager::SurfacePoint<double>;
|
||||
static std::optional<SurfacePoint> unproject_on_mesh(const AABBMesh &aabb_mesh,
|
||||
const Vec2d &mouse_pos,
|
||||
const Transform3d &transformation,
|
||||
const Camera &camera);
|
||||
|
||||
static void actualize(Raycasters &casters, const ModelVolumePtrs &volumes, const RaycastManager::ISkip *skip)
|
||||
{
|
||||
// check if volume was removed
|
||||
std::vector<bool> removed_casters(casters.size(), {true});
|
||||
// actualize MeshRaycaster
|
||||
for (const ModelVolume *volume : volumes) {
|
||||
size_t oid = volume->id().id;
|
||||
if (skip != nullptr && skip->skip(oid))
|
||||
continue;
|
||||
auto item = std::find_if(casters.begin(), casters.end(),
|
||||
[oid](const Raycaster &it) -> bool { return oid == it.first; });
|
||||
if (item == casters.end()) {
|
||||
// add new raycaster
|
||||
auto raycaster = std::make_unique<MeshRaycaster>(volume->get_mesh_shared_ptr());
|
||||
casters.emplace_back(std::make_pair(oid, std::move(raycaster)));
|
||||
} else {
|
||||
size_t index = item - casters.begin();
|
||||
removed_casters[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// clean other raycasters
|
||||
for (int i = removed_casters.size() - 1; i >= 0; --i)
|
||||
if (removed_casters[i])
|
||||
casters.erase(casters.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
||||
{
|
||||
// actualize MeshRaycaster
|
||||
priv::actualize(m_raycasters, object->volumes, skip);
|
||||
priv::actualize(m_meshes, object->volumes, skip);
|
||||
|
||||
// check if inscance was removed
|
||||
std::vector<bool> removed_transf(m_transformations.size(), {true});
|
||||
|
||||
|
||||
bool need_sort = false;
|
||||
// actualize transformation matrices
|
||||
for (const ModelVolume *volume : object->volumes) {
|
||||
if (skip != nullptr && skip->skip(volume->id().id)) continue;
|
||||
const Transform3d &volume_tr = volume->get_matrix();
|
||||
for (const ModelInstance *instance : object->instances) {
|
||||
const Transform3d &instrance_tr = instance->get_matrix();
|
||||
Transform3d transformation = instrance_tr * volume_tr;
|
||||
TrKey tr_key = std::make_pair(instance->id().id, volume->id().id);
|
||||
auto item = std::find_if(m_transformations.begin(),
|
||||
m_transformations.end(),
|
||||
[&tr_key](const TrItem &it) -> bool {
|
||||
return it.first == tr_key;
|
||||
});
|
||||
const Transform3d &instrance_tr = instance->get_matrix();
|
||||
Transform3d transformation = instrance_tr * volume_tr;
|
||||
TrKey key = priv::create_key(volume, instance);
|
||||
auto item = priv::find(m_transformations, key);
|
||||
if (item != m_transformations.end()) {
|
||||
// actualize transformation all the time
|
||||
item->second = transformation;
|
||||
@ -73,8 +54,8 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
||||
removed_transf[index] = false;
|
||||
} else {
|
||||
// add new transformation
|
||||
m_transformations.emplace_back(
|
||||
std::make_pair(tr_key, transformation));
|
||||
m_transformations.emplace_back(std::make_pair(key, transformation));
|
||||
need_sort = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,17 +64,21 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
||||
for (int i = removed_transf.size() - 1; i >= 0; --i)
|
||||
if (removed_transf[i])
|
||||
m_transformations.erase(m_transformations.begin() + i);
|
||||
|
||||
if (need_sort)
|
||||
std::sort(m_transformations.begin(), m_transformations.end(), priv::is_lower);
|
||||
}
|
||||
|
||||
void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip) {
|
||||
const ModelVolumePtrs &volumes = instance->get_object()->volumes;
|
||||
|
||||
// actualize MeshRaycaster
|
||||
priv::actualize(m_raycasters, volumes, skip);
|
||||
priv::actualize(m_meshes, volumes, skip);
|
||||
|
||||
// check if inscance was removed
|
||||
std::vector<bool> removed_transf(m_transformations.size(), {true});
|
||||
|
||||
bool need_sort = false;
|
||||
// actualize transformation matrices
|
||||
for (const ModelVolume *volume : volumes) {
|
||||
if (skip != nullptr && skip->skip(volume->id().id))
|
||||
@ -101,9 +86,8 @@ void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip)
|
||||
const Transform3d &volume_tr = volume->get_matrix();
|
||||
const Transform3d &instrance_tr = instance->get_matrix();
|
||||
Transform3d transformation = instrance_tr * volume_tr;
|
||||
TrKey tr_key = std::make_pair(instance->id().id, volume->id().id);
|
||||
auto item = std::find_if(m_transformations.begin(), m_transformations.end(),
|
||||
[&tr_key](const TrItem &it) -> bool { return it.first == tr_key; });
|
||||
TrKey key = priv::create_key(volume, instance);
|
||||
auto item = priv::find(m_transformations, key);
|
||||
if (item != m_transformations.end()) {
|
||||
// actualize transformation all the time
|
||||
item->second = transformation;
|
||||
@ -111,7 +95,8 @@ void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip)
|
||||
removed_transf[index] = false;
|
||||
} else {
|
||||
// add new transformation
|
||||
m_transformations.emplace_back(std::make_pair(tr_key, transformation));
|
||||
m_transformations.emplace_back(std::make_pair(key, transformation));
|
||||
need_sort = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,65 +104,33 @@ void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip)
|
||||
for (int i = removed_transf.size() - 1; i >= 0; --i)
|
||||
if (removed_transf[i])
|
||||
m_transformations.erase(m_transformations.begin() + i);
|
||||
|
||||
if (need_sort)
|
||||
std::sort(m_transformations.begin(), m_transformations.end(), priv::is_lower);
|
||||
}
|
||||
|
||||
#include "slic3r/GUI/CameraUtils.hpp"
|
||||
namespace priv {
|
||||
|
||||
// Copy functionality from MeshRaycaster::unproject_on_mesh without filtering
|
||||
static std::optional<RaycastManager::SurfacePoint> unproject_on_mesh(const MeshRaycaster &raycaster,
|
||||
const Vec2d &mouse_pos, const Transform3d &transformation, const Camera &camera) {
|
||||
|
||||
Vec3d point;
|
||||
Vec3d direction;
|
||||
CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
|
||||
Transform3d inv = transformation.inverse();
|
||||
point = inv*point;
|
||||
direction = inv.linear()*direction;
|
||||
|
||||
const AABBMesh &aabb_mesh = raycaster.get_aabb_mesh();
|
||||
std::vector<AABBMesh::hit_result> hits = aabb_mesh.query_ray_hits(point, direction);
|
||||
|
||||
if (hits.empty())
|
||||
return {}; // no intersection found
|
||||
|
||||
const AABBMesh::hit_result &hit = hits.front();
|
||||
return RaycastManager::SurfacePoint(
|
||||
hit.position().cast<float>(),
|
||||
hit.normal().cast<float>()
|
||||
);
|
||||
}
|
||||
} // namespace priv
|
||||
|
||||
std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
||||
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
||||
{
|
||||
std::optional<Hit> closest;
|
||||
for (const auto &item : m_transformations) {
|
||||
const TrKey &key = item.first;
|
||||
size_t volume_id = key.second;
|
||||
size_t volume_id = key.second;
|
||||
if (skip != nullptr && skip->skip(volume_id)) continue;
|
||||
const AABBMesh *mesh = priv::get_mesh(m_meshes, volume_id);
|
||||
if (mesh == nullptr) continue;
|
||||
const Transform3d &transformation = item.second;
|
||||
auto raycaster_it =
|
||||
std::find_if(m_raycasters.begin(), m_raycasters.end(),
|
||||
[volume_id](const RaycastManager::Raycaster &it)
|
||||
-> bool { return volume_id == it.first; });
|
||||
if (raycaster_it == m_raycasters.end()) continue;
|
||||
const MeshRaycaster &raycaster = *(raycaster_it->second);
|
||||
std::optional<SurfacePoint> surface_point_opt = priv::unproject_on_mesh(
|
||||
raycaster, mouse_pos, transformation, camera);
|
||||
auto surface_point_opt =
|
||||
priv::unproject_on_mesh(*mesh, mouse_pos, transformation, camera);
|
||||
if (!surface_point_opt.has_value())
|
||||
continue;
|
||||
const SurfacePoint &surface_point = *surface_point_opt;
|
||||
Vec3d act_hit_tr = transformation * surface_point.position.cast<double>();
|
||||
Vec3d act_hit_tr = transformation * surface_point_opt->position.cast<double>();
|
||||
double squared_distance = (camera.get_position() - act_hit_tr).squaredNorm();
|
||||
if (closest.has_value() &&
|
||||
closest->squared_distance < squared_distance)
|
||||
continue;
|
||||
closest = Hit(key, surface_point, squared_distance);
|
||||
closest = Hit{*surface_point_opt, key, squared_distance};
|
||||
}
|
||||
|
||||
//if (!closest.has_value()) return {};
|
||||
return closest;
|
||||
}
|
||||
|
||||
@ -186,16 +139,11 @@ std::optional<RaycastManager::Hit> RaycastManager::unproject(const Vec3d &point,
|
||||
std::optional<Hit> closest;
|
||||
for (const auto &item : m_transformations) {
|
||||
const TrKey &key = item.first;
|
||||
size_t volume_id = key.second;
|
||||
size_t volume_id = key.second;
|
||||
if (skip != nullptr && skip->skip(volume_id)) continue;
|
||||
const Transform3d &transformation = item.second;
|
||||
auto raycaster_it =
|
||||
std::find_if(m_raycasters.begin(), m_raycasters.end(),
|
||||
[volume_id](const RaycastManager::Raycaster &it)
|
||||
-> bool { return volume_id == it.first; });
|
||||
if (raycaster_it == m_raycasters.end()) continue;
|
||||
const MeshRaycaster &raycaster = *(raycaster_it->second);
|
||||
const AABBMesh& mesh = raycaster.get_aabb_mesh();
|
||||
const AABBMesh *mesh = priv::get_mesh(m_meshes, volume_id);
|
||||
if (mesh == nullptr) continue;
|
||||
Transform3d tr_inv = transformation.inverse();
|
||||
Vec3d mesh_point = tr_inv * point;
|
||||
Vec3d mesh_direction = tr_inv.linear() * direction;
|
||||
@ -205,49 +153,50 @@ std::optional<RaycastManager::Hit> RaycastManager::unproject(const Vec3d &point,
|
||||
Vec3d point_negative = mesh_point + mesh_direction;
|
||||
|
||||
// Throw ray to both directions of ray
|
||||
std::vector<AABBMesh::hit_result> hits = mesh.query_ray_hits(point_positive, mesh_direction);
|
||||
std::vector<AABBMesh::hit_result> hits_neg = mesh.query_ray_hits(point_negative, -mesh_direction);
|
||||
std::vector<AABBMesh::hit_result> hits = mesh->query_ray_hits(point_positive, mesh_direction);
|
||||
std::vector<AABBMesh::hit_result> hits_neg = mesh->query_ray_hits(point_negative, -mesh_direction);
|
||||
hits.insert(hits.end(), std::make_move_iterator(hits_neg.begin()), std::make_move_iterator(hits_neg.end()));
|
||||
for (const AABBMesh::hit_result &hit : hits) {
|
||||
double squared_distance = (mesh_point - hit.position()).squaredNorm();
|
||||
if (closest.has_value() &&
|
||||
closest->squared_distance < squared_distance)
|
||||
continue;
|
||||
SurfacePoint surface_point(hit.position().cast<float>(), hit.normal().cast<float>());
|
||||
closest = Hit(key, surface_point, squared_distance);
|
||||
closest = Hit{{hit.position(), hit.normal()}, key, squared_distance};
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
std::optional<RaycastManager::Hit> RaycastManager::closest(const Vec3d &point, const ISkip *skip) const {
|
||||
std::optional<Hit> closest;
|
||||
std::optional<RaycastManager::ClosePoint> RaycastManager::closest(const Vec3d &point, const ISkip *skip) const
|
||||
{
|
||||
std::optional<ClosePoint> closest;
|
||||
for (const auto &item : m_transformations) {
|
||||
const TrKey &key = item.first;
|
||||
size_t volume_id = key.second;
|
||||
if (skip != nullptr && skip->skip(volume_id))
|
||||
continue;
|
||||
auto raycaster_it = std::find_if(m_raycasters.begin(), m_raycasters.end(),
|
||||
[volume_id](const RaycastManager::Raycaster &it) -> bool { return volume_id == it.first; });
|
||||
if (raycaster_it == m_raycasters.end())
|
||||
continue;
|
||||
const MeshRaycaster &raycaster = *(raycaster_it->second);
|
||||
const AABBMesh *mesh = priv::get_mesh(m_meshes, volume_id);
|
||||
if (mesh == nullptr) continue;
|
||||
const Transform3d &transformation = item.second;
|
||||
Transform3d tr_inv = transformation.inverse();
|
||||
Vec3d mesh_point_d = tr_inv * point;
|
||||
Vec3f mesh_point_f = mesh_point_d.cast<float>();
|
||||
Vec3f n;
|
||||
Vec3f p = raycaster.get_closest_point(mesh_point_f, &n);
|
||||
double squared_distance = (mesh_point_f - p).squaredNorm();
|
||||
Vec3d mesh_point = tr_inv * point;
|
||||
|
||||
int face_idx = 0;
|
||||
Vec3d closest_point;
|
||||
Vec3d pointd = point.cast<double>();
|
||||
mesh->squared_distance(pointd, face_idx, closest_point);
|
||||
|
||||
double squared_distance = (mesh_point - closest_point).squaredNorm();
|
||||
if (closest.has_value() && closest->squared_distance < squared_distance)
|
||||
continue;
|
||||
SurfacePoint surface_point(p,n);
|
||||
closest = Hit(key, surface_point, squared_distance);
|
||||
|
||||
closest = ClosePoint{key, closest_point, squared_distance};
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
Slic3r::Transform3d RaycastManager::get_transformation(const TrKey &tr_key) const {
|
||||
// TODO: transformations are sorted use lower bound
|
||||
auto item = std::find_if(m_transformations.begin(),
|
||||
m_transformations.end(),
|
||||
[&tr_key](const TrItem &it) -> bool {
|
||||
@ -255,4 +204,78 @@ Slic3r::Transform3d RaycastManager::get_transformation(const TrKey &tr_key) cons
|
||||
});
|
||||
if (item == m_transformations.end()) return Transform3d::Identity();
|
||||
return item->second;
|
||||
}
|
||||
}
|
||||
|
||||
void priv::actualize(RaycastManager::Meshes &meshes, const ModelVolumePtrs &volumes, const RaycastManager::ISkip *skip)
|
||||
{
|
||||
// check if volume was removed
|
||||
std::vector<bool> removed_meshes(meshes.size(), {true});
|
||||
bool need_sort = false;
|
||||
// actualize MeshRaycaster
|
||||
for (const ModelVolume *volume : volumes) {
|
||||
size_t oid = volume->id().id;
|
||||
if (skip != nullptr && skip->skip(oid))
|
||||
continue;
|
||||
auto item = std::find_if(meshes.begin(), meshes.end(), [oid](const RaycastManager::Mesh &it) -> bool { return oid == it.first; });
|
||||
if (item == meshes.end()) {
|
||||
// add new raycaster
|
||||
bool calculate_epsilon = true;
|
||||
auto mesh = std::make_unique<AABBMesh>(volume->mesh(), calculate_epsilon);
|
||||
meshes.emplace_back(std::make_pair(oid, std::move(mesh)));
|
||||
need_sort = true;
|
||||
} else {
|
||||
size_t index = item - meshes.begin();
|
||||
removed_meshes[index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// clean other raycasters
|
||||
for (int i = removed_meshes.size() - 1; i >= 0; --i)
|
||||
if (removed_meshes[i])
|
||||
meshes.erase(meshes.begin() + i);
|
||||
|
||||
// All the time meshes must be sorted by volume id - for faster search
|
||||
if (need_sort) {
|
||||
auto is_lower = [](const RaycastManager::Mesh &m1, const RaycastManager::Mesh &m2) { return m1.first < m2.first; };
|
||||
std::sort(meshes.begin(), meshes.end(), is_lower);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<priv::SurfacePoint> priv::unproject_on_mesh(const AABBMesh &aabb_mesh,
|
||||
const Vec2d &mouse_pos,
|
||||
const Transform3d &transformation,
|
||||
const Camera &camera)
|
||||
{
|
||||
Vec3d point;
|
||||
Vec3d direction;
|
||||
CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
|
||||
Transform3d inv = transformation.inverse();
|
||||
point = inv * point;
|
||||
direction = inv.linear() * direction;
|
||||
std::vector<AABBMesh::hit_result> hits = aabb_mesh.query_ray_hits(point, direction);
|
||||
|
||||
if (hits.empty())
|
||||
return {}; // no intersection found
|
||||
|
||||
const AABBMesh::hit_result &hit = hits.front();
|
||||
return priv::SurfacePoint{hit.position(), hit.normal()};
|
||||
}
|
||||
|
||||
const Slic3r::AABBMesh *priv::get_mesh(const RaycastManager::Meshes &meshes, size_t volume_id)
|
||||
{
|
||||
auto is_lower_index = [](const RaycastManager::Mesh &m, size_t i) -> bool { return m.first < i; };
|
||||
auto it = std::lower_bound(meshes.begin(), meshes.end(), volume_id, is_lower_index);
|
||||
if (it == meshes.end() || it->first != volume_id)
|
||||
return nullptr;
|
||||
return &(*(it->second));
|
||||
}
|
||||
|
||||
RaycastManager::TrItems::iterator priv::find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key) {
|
||||
auto fnc = [](const RaycastManager::TrItem &it, const RaycastManager::TrKey &key)->bool {
|
||||
return priv::is_lower_key(it.first, key);
|
||||
};
|
||||
auto it = std::lower_bound(items.begin(), items.end(), key, fnc);
|
||||
if (it == items.end() || it->first != key)
|
||||
return items.end();
|
||||
return it;
|
||||
}
|
||||
|
@ -2,12 +2,12 @@
|
||||
#define slic3r_RaycastManager_hpp_
|
||||
|
||||
#include <memory> // unique_ptr
|
||||
#include <optional> // unique_ptr
|
||||
#include <map>
|
||||
#include "slic3r/GUI/MeshUtils.hpp" // MeshRaycaster
|
||||
#include <optional>
|
||||
#include "libslic3r/AABBMesh.hpp" // Structure to cast rays
|
||||
#include "libslic3r/Point.hpp" // Transform3d
|
||||
#include "libslic3r/ObjectID.hpp"
|
||||
#include "libslic3r/Model.hpp" // ModelObjectPtrs, ModelObject, ModelInstance, ModelVolume
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
|
||||
namespace Slic3r::GUI{
|
||||
|
||||
@ -17,19 +17,22 @@ namespace Slic3r::GUI{
|
||||
/// </summary>
|
||||
class RaycastManager
|
||||
{
|
||||
// ModelVolume.id
|
||||
using Raycaster = std::pair<size_t, std::unique_ptr<MeshRaycaster> >;
|
||||
std::vector<Raycaster> m_raycasters;
|
||||
// Public structures used by RaycastManager
|
||||
public:
|
||||
|
||||
// Key for transformation consist of unique volume and instance
|
||||
// ModelVolume.id
|
||||
using Mesh = std::pair<size_t, std::unique_ptr<AABBMesh> >;
|
||||
using Meshes = std::vector<Mesh>;
|
||||
|
||||
// Key for transformation consist of unique volume and instance id ... ObjectId()
|
||||
// ModelInstance, ModelVolume
|
||||
using TrKey = std::pair<size_t, size_t>;
|
||||
using TrItem = std::pair<TrKey, Transform3d>;
|
||||
std::vector<TrItem> m_transformations;
|
||||
using TrItems = std::vector<TrItem>;
|
||||
|
||||
// should contain shared pointer to camera but it is not shared pointer so it need it every time when casts rays
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Interface for identify allowed volumes to cast rays.
|
||||
/// </summary>
|
||||
class ISkip{
|
||||
public:
|
||||
virtual ~ISkip() = default;
|
||||
@ -42,6 +45,39 @@ public:
|
||||
virtual bool skip(const size_t &model_volume_id) const { return false; }
|
||||
};
|
||||
|
||||
// TODO: it is more general object move outside of this class
|
||||
template<typename T>
|
||||
struct SurfacePoint {
|
||||
using Vec3 = Eigen::Matrix<T, 3, 1, Eigen::DontAlign>;
|
||||
Vec3 position = Vec3::Zero();
|
||||
Vec3 normal = Vec3::UnitZ();
|
||||
};
|
||||
|
||||
struct Hit : public SurfacePoint<double>
|
||||
{
|
||||
TrKey tr_key;
|
||||
double squared_distance;
|
||||
};
|
||||
|
||||
struct ClosePoint
|
||||
{
|
||||
TrKey tr_key;
|
||||
Vec3d point;
|
||||
double squared_distance;
|
||||
};
|
||||
|
||||
// Members
|
||||
private:
|
||||
// Keep structure to fast cast rays
|
||||
// meshes are sorted by volume_id for faster search
|
||||
Meshes m_meshes;
|
||||
|
||||
// Keep transformation of meshes
|
||||
TrItems m_transformations;
|
||||
// Note: one mesh could have more transformations ... instances
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Actualize raycasters + transformation
|
||||
/// Detection of removed object
|
||||
@ -53,27 +89,6 @@ public:
|
||||
void actualize(const ModelObject *object, const ISkip *skip = nullptr);
|
||||
void actualize(const ModelInstance *instance, const ISkip *skip = nullptr);
|
||||
|
||||
// TODO: it is more general object move outside of this class
|
||||
struct SurfacePoint
|
||||
{
|
||||
Vec3f position = Vec3f::Zero();
|
||||
Vec3f normal = Vec3f::UnitZ();
|
||||
SurfacePoint() = default;
|
||||
SurfacePoint(Vec3f position, Vec3f normal)
|
||||
: position(position), normal(normal)
|
||||
{}
|
||||
};
|
||||
|
||||
struct Hit: public SurfacePoint
|
||||
{
|
||||
using Key = TrKey;
|
||||
Key tr_key;
|
||||
double squared_distance;
|
||||
Hit(const Key& tr_key, const SurfacePoint& surface_point, double squared_distance)
|
||||
: SurfacePoint(surface_point), tr_key(tr_key), squared_distance(squared_distance)
|
||||
{}
|
||||
};
|
||||
|
||||
class SkipVolume: public ISkip
|
||||
{
|
||||
size_t volume_id;
|
||||
@ -95,7 +110,6 @@ public:
|
||||
|
||||
/// <summary>
|
||||
/// Unproject on mesh by Mesh raycasters
|
||||
/// Note: Function use current camera position from wxGetApp()
|
||||
/// </summary>
|
||||
/// <param name="mouse_pos">Position of mouse on screen</param>
|
||||
/// <param name="camera">Projection params</param>
|
||||
@ -121,7 +135,7 @@ public:
|
||||
/// <param name="point">Point</param>
|
||||
/// <param name="skip">Define which caster will be skipped, null mean no skip</param>
|
||||
/// <returns></returns>
|
||||
std::optional<Hit> closest(const Vec3d &point, const ISkip *skip = nullptr) const;
|
||||
std::optional<ClosePoint> closest(const Vec3d &point, const ISkip *skip = nullptr) const;
|
||||
|
||||
/// <summary>
|
||||
/// Getter on transformation from hitted volume to world
|
||||
|
Loading…
x
Reference in New Issue
Block a user