mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 16:45:53 +08:00
Add function for check whether transformation contain reflection
Extend RayCast hit by square distance Use distance to distiguish closest place on surface when move origin Move origin after job (only on success)
This commit is contained in:
parent
b899d51aba
commit
550ef48fe1
@ -136,6 +136,14 @@ inline std::string to_string(const Vec3d &pt) { return std::string("[") + floa
|
|||||||
std::vector<Vec3f> transform(const std::vector<Vec3f>& points, const Transform3f& t);
|
std::vector<Vec3f> transform(const std::vector<Vec3f>& points, const Transform3f& t);
|
||||||
Pointf3s transform(const Pointf3s& points, const Transform3d& t);
|
Pointf3s transform(const Pointf3s& points, const Transform3d& t);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether transformation matrix contains odd number of mirroring.
|
||||||
|
/// NOTE: In code is sometime function named is_left_handed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="transform">Transformation to check</param>
|
||||||
|
/// <returns>Is positive determinant</returns>
|
||||||
|
inline bool has_reflection(const Transform3d &transform) { return transform.matrix().determinant() < 0; }
|
||||||
|
|
||||||
template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N, 1>;
|
template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N, 1>;
|
||||||
|
|
||||||
class Point : public Vec2crd
|
class Point : public Vec2crd
|
||||||
|
@ -1120,6 +1120,17 @@ static inline void execute_job(std::shared_ptr<Job> j)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace priv {
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate translation of text volume onto surface of model
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume">Text</param>
|
||||||
|
/// <param name="raycast_manager">AABB trees of object. Actualize object containing text</param>
|
||||||
|
/// <param name="selection">Transformation of actual instance</param>
|
||||||
|
/// <returns>Offset of volume in volume coordinate</returns>
|
||||||
|
std::optional<Vec3d> calc_surface_offset(const ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection);
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
bool GLGizmoEmboss::process()
|
bool GLGizmoEmboss::process()
|
||||||
{
|
{
|
||||||
// no volume is selected -> selection from right panel
|
// no volume is selected -> selection from right panel
|
||||||
@ -1160,6 +1171,13 @@ bool GLGizmoEmboss::process()
|
|||||||
if (fix_3mf.has_value())
|
if (fix_3mf.has_value())
|
||||||
text_tr = text_tr * fix_3mf->inverse();
|
text_tr = text_tr * fix_3mf->inverse();
|
||||||
|
|
||||||
|
// when it is new applying of use surface than move origin onto surfaca
|
||||||
|
if (!m_volume->text_configuration->style.prop.use_surface) {
|
||||||
|
auto offset = priv::calc_surface_offset(*m_volume, m_raycast_manager, m_parent.get_selection());
|
||||||
|
if (offset.has_value())
|
||||||
|
text_tr *= Eigen::Translation<double, 3>(*offset);
|
||||||
|
}
|
||||||
|
|
||||||
bool is_outside = m_volume->is_model_part();
|
bool is_outside = m_volume->is_model_part();
|
||||||
// check that there is not unexpected volume type
|
// check that there is not unexpected volume type
|
||||||
assert(is_outside || m_volume->is_negative_volume() ||
|
assert(is_outside || m_volume->is_negative_volume() ||
|
||||||
@ -2231,18 +2249,7 @@ void GLGizmoEmboss::draw_delete_style_button() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace priv {
|
// FIX IT: it should not change volume position before successfull change
|
||||||
/// <summary>
|
|
||||||
/// Transform origin of Text volume onto surface of model.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="volume">Text</param>
|
|
||||||
/// <param name="raycast_manager">AABB trees of object</param>
|
|
||||||
/// <param name="selection">Transformation of actual instance</param>
|
|
||||||
/// <returns>True when transform otherwise false</returns>
|
|
||||||
bool transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection);
|
|
||||||
} // namespace priv
|
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoEmboss::fix_transformation(const FontProp &from,
|
void GLGizmoEmboss::fix_transformation(const FontProp &from,
|
||||||
const FontProp &to)
|
const FontProp &to)
|
||||||
{
|
{
|
||||||
@ -2264,10 +2271,6 @@ void GLGizmoEmboss::fix_transformation(const FontProp &from,
|
|||||||
float t_move = t_move_opt.has_value() ? *t_move_opt : .0f;
|
float t_move = t_move_opt.has_value() ? *t_move_opt : .0f;
|
||||||
do_translate(Vec3d::UnitZ() * (t_move - f_move));
|
do_translate(Vec3d::UnitZ() * (t_move - f_move));
|
||||||
}
|
}
|
||||||
|
|
||||||
// when start using surface than move volume origin onto surface
|
|
||||||
if (!from.use_surface && to.use_surface)
|
|
||||||
priv::transform_on_surface(*m_volume, m_raycast_manager, m_parent.get_selection());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_style_list() {
|
void GLGizmoEmboss::draw_style_list() {
|
||||||
@ -2887,8 +2890,7 @@ void GLGizmoEmboss::do_rotate(float relative_z_angle)
|
|||||||
m_parent.do_rotate(snapshot_name);
|
m_parent.do_rotate(snapshot_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool priv::transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection)
|
std::optional<Vec3d> priv::calc_surface_offset(const ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection) {
|
||||||
{
|
|
||||||
// Move object on surface
|
// Move object on surface
|
||||||
auto cond = RaycastManager::SkipVolume({volume.id().id});
|
auto cond = RaycastManager::SkipVolume({volume.id().id});
|
||||||
raycast_manager.actualize(volume.get_object(), &cond);
|
raycast_manager.actualize(volume.get_object(), &cond);
|
||||||
@ -2901,26 +2903,31 @@ bool priv::transform_on_surface(ModelVolume &volume, RaycastManager &raycast_man
|
|||||||
|
|
||||||
// ray in direction of text projection(from volume zero to z-dir)
|
// ray in direction of text projection(from volume zero to z-dir)
|
||||||
std::optional<RaycastManager::Hit> hit_opt = raycast_manager.unproject(point, direction, &cond);
|
std::optional<RaycastManager::Hit> hit_opt = raycast_manager.unproject(point, direction, &cond);
|
||||||
|
// start point lay on surface could appear slightly behind surface
|
||||||
|
std::optional<RaycastManager::Hit> hit_opt_opposit = raycast_manager.unproject(point, -direction, &cond);
|
||||||
|
if (!hit_opt.has_value() ||
|
||||||
|
(hit_opt_opposit.has_value() && hit_opt->squared_distance > hit_opt_opposit->squared_distance))
|
||||||
|
hit_opt = hit_opt_opposit;
|
||||||
|
|
||||||
|
// Try to find closest point when no hit object in emboss direction
|
||||||
if (!hit_opt.has_value())
|
if (!hit_opt.has_value())
|
||||||
hit_opt = raycast_manager.closest(point);
|
hit_opt = raycast_manager.closest(point);
|
||||||
|
|
||||||
|
// It should NOT appear. Closest point always exists.
|
||||||
if (!hit_opt.has_value())
|
if (!hit_opt.has_value())
|
||||||
return false;
|
return {};
|
||||||
const RaycastManager::Hit &hit = *hit_opt;
|
|
||||||
|
|
||||||
|
// 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);
|
Transform3d hit_tr = raycast_manager.get_transformation(hit.tr_key);
|
||||||
Vec3d hit_world = hit_tr * hit.position.cast<double>();
|
Vec3d hit_world = hit_tr * hit.position.cast<double>();
|
||||||
Vec3d offset_world = hit_world - point; // vector in world
|
Vec3d offset_world = hit_world - point; // vector in world
|
||||||
// TIP: It should be close to only z move
|
// TIP: It should be close to only z move
|
||||||
Vec3d offset_volume = to_world.inverse().linear() * offset_world;
|
Vec3d offset_volume = to_world.inverse().linear() * offset_world;
|
||||||
|
return offset_volume;
|
||||||
// when try to use surface on just loaded text from 3mf
|
|
||||||
auto fix = volume.text_configuration->fix_3mf_tr;
|
|
||||||
if (fix.has_value())
|
|
||||||
offset_volume = fix->linear() * offset_volume;
|
|
||||||
|
|
||||||
volume.set_transformation(volume.get_matrix() * Eigen::Translation<double, 3>(offset_volume));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_advanced()
|
void GLGizmoEmboss::draw_advanced()
|
||||||
@ -2975,8 +2982,6 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
// there should be minimal embossing depth
|
// there should be minimal embossing depth
|
||||||
if (font_prop.emboss < 0.1)
|
if (font_prop.emboss < 0.1)
|
||||||
font_prop.emboss = 1;
|
font_prop.emboss = 1;
|
||||||
|
|
||||||
priv::transform_on_surface(*m_volume, m_raycast_manager, m_parent.get_selection());
|
|
||||||
}
|
}
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,8 @@ static TriangleMesh create_default_mesh();
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mesh">New mesh data</param>
|
/// <param name="mesh">New mesh data</param>
|
||||||
/// <param name="data">Text configuration, ...</param>
|
/// <param name="data">Text configuration, ...</param>
|
||||||
static void update_volume(TriangleMesh &&mesh, const DataUpdate &data);
|
/// <param name="mesh">Transformation of volume</param>
|
||||||
|
static void update_volume(TriangleMesh &&mesh, const DataUpdate &data, Transform3d *tr = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add new volume to object
|
/// Add new volume to object
|
||||||
@ -316,16 +317,8 @@ void CreateSurfaceVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
|
|||||||
// doesn't care about exception when process was canceled by user
|
// doesn't care about exception when process was canceled by user
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
if (priv::process(eptr)) return;
|
if (priv::process(eptr)) return;
|
||||||
|
|
||||||
// TODO: Find better way to Not center volume data when add !!!
|
|
||||||
TriangleMesh mesh = m_result; // Part1: copy
|
|
||||||
|
|
||||||
priv::create_volume(std::move(m_result), m_input.object_id,
|
priv::create_volume(std::move(m_result), m_input.object_id,
|
||||||
m_input.volume_type, m_input.text_tr, m_input);
|
m_input.volume_type, m_input.text_tr, m_input);
|
||||||
|
|
||||||
// Part2: update volume data
|
|
||||||
//auto vol = wxGetApp().plater()->model().objects[m_input.object_idx]->volumes.back();
|
|
||||||
//UpdateJob::update_volume(vol, std::move(mesh), m_input.text_configuration, m_input.volume_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
@ -358,7 +351,11 @@ void UpdateSurfaceVolumeJob::finalize(bool canceled, std::exception_ptr &eptr)
|
|||||||
}
|
}
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
if (priv::process(eptr)) return;
|
if (priv::process(eptr)) return;
|
||||||
priv::update_volume(std::move(m_result), m_input);
|
|
||||||
|
// when start using surface it is wanted to move text origin on surface of model
|
||||||
|
// also when repeteadly move above surface result position should match
|
||||||
|
Transform3d *tr = &m_input.text_tr;
|
||||||
|
priv::update_volume(std::move(m_result), m_input, tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@ -535,31 +532,37 @@ void UpdateJob::update_volume(ModelVolume *volume,
|
|||||||
canvas->reload_scene(refresh_immediately);
|
canvas->reload_scene(refresh_immediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
void priv::update_volume(TriangleMesh &&mesh, const DataUpdate &data)
|
void priv::update_volume(TriangleMesh &&mesh, const DataUpdate &data, Transform3d* tr)
|
||||||
{
|
{
|
||||||
// for sure that some object will be created
|
// for sure that some object will be created
|
||||||
if (mesh.its.empty())
|
if (mesh.its.empty())
|
||||||
return priv::create_message("Empty mesh can't be created.");
|
return create_message("Empty mesh can't be created.");
|
||||||
|
|
||||||
Plater *plater = wxGetApp().plater();
|
Plater *plater = wxGetApp().plater();
|
||||||
GLCanvas3D *canvas = plater->canvas3D();
|
GLCanvas3D *canvas = plater->canvas3D();
|
||||||
|
|
||||||
// Check emboss gizmo is still open
|
// Check emboss gizmo is still open
|
||||||
GLGizmosManager &manager = canvas->get_gizmos_manager();
|
GLGizmosManager &manager = canvas->get_gizmos_manager();
|
||||||
if (manager.get_current_type() != GLGizmosManager::Emboss) return;
|
if (manager.get_current_type() != GLGizmosManager::Emboss)
|
||||||
|
return;
|
||||||
|
|
||||||
std::string snap_name = GUI::format(_L("Text: %1%"), data.text_configuration.text);
|
std::string snap_name = GUI::format(_L("Text: %1%"), data.text_configuration.text);
|
||||||
Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
|
Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
|
||||||
ModelVolume *volume = get_volume(plater->model().objects, data.volume_id);
|
ModelVolume *volume = get_volume(plater->model().objects, data.volume_id);
|
||||||
|
|
||||||
// could appear when user delete edited volume
|
// could appear when user delete edited volume
|
||||||
if (volume == nullptr)
|
if (volume == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// apply fix matrix made by store to .3mf
|
if (tr) {
|
||||||
const auto &tc = volume->text_configuration;
|
volume->set_transformation(*tr);
|
||||||
assert(tc.has_value());
|
} else {
|
||||||
if (tc.has_value() && tc->fix_3mf_tr.has_value())
|
// apply fix matrix made by store to .3mf
|
||||||
volume->set_transformation(volume->get_matrix() * tc->fix_3mf_tr->inverse());
|
const auto &tc = volume->text_configuration;
|
||||||
|
assert(tc.has_value());
|
||||||
|
if (tc.has_value() && tc->fix_3mf_tr.has_value())
|
||||||
|
volume->set_transformation(volume->get_matrix() * tc->fix_3mf_tr->inverse());
|
||||||
|
}
|
||||||
|
|
||||||
UpdateJob::update_volume(volume, std::move(mesh), data.text_configuration, data.volume_name);
|
UpdateJob::update_volume(volume, std::move(mesh), data.text_configuration, data.volume_name);
|
||||||
}
|
}
|
||||||
@ -726,30 +729,48 @@ TriangleMesh priv::cut_surface(DataBase& input1, const SurfaceVolumeData& input2
|
|||||||
biggest_count = its.vertices.size();
|
biggest_count = its.vertices.size();
|
||||||
biggest = &s;
|
biggest = &s;
|
||||||
}
|
}
|
||||||
s_to_itss[&s - &sources.front()] = itss.size();
|
size_t source_index = &s - &sources.front();
|
||||||
|
size_t its_index = itss.size();
|
||||||
|
s_to_itss[source_index] = its_index;
|
||||||
itss.emplace_back(std::move(its));
|
itss.emplace_back(std::move(its));
|
||||||
}
|
}
|
||||||
if (itss.empty())
|
if (itss.empty())
|
||||||
throw JobException(_u8L("There is no volume in projection direction.").c_str());
|
throw JobException(_u8L("There is no volume in projection direction.").c_str());
|
||||||
|
|
||||||
Transform3d tr_inv = biggest->tr.inverse();
|
Transform3d tr_inv = biggest->tr.inverse();
|
||||||
|
Transform3d cut_projection_tr = tr_inv * input2.text_tr;
|
||||||
|
// Cut surface in reflected system?
|
||||||
|
bool use_reflection = Slic3r::has_reflection(cut_projection_tr);
|
||||||
|
if (use_reflection)
|
||||||
|
cut_projection_tr *= Eigen::Scaling(-1., 1., 1.);
|
||||||
|
|
||||||
size_t itss_index = s_to_itss[biggest - &sources.front()];
|
size_t itss_index = s_to_itss[biggest - &sources.front()];
|
||||||
BoundingBoxf3 mesh_bb = bounding_box(itss[itss_index]);
|
BoundingBoxf3 mesh_bb = bounding_box(itss[itss_index]);
|
||||||
for (const SurfaceVolumeData::ModelSource &s : sources) {
|
for (const SurfaceVolumeData::ModelSource &s : sources) {
|
||||||
if (&s == biggest) continue;
|
|
||||||
size_t itss_index = s_to_itss[&s - &sources.front()];
|
size_t itss_index = s_to_itss[&s - &sources.front()];
|
||||||
if (itss_index == std::numeric_limits<size_t>::max()) continue;
|
if (itss_index == std::numeric_limits<size_t>::max()) continue;
|
||||||
Transform3d tr = s.tr * tr_inv;
|
Transform3d tr;
|
||||||
|
if (&s == biggest) {
|
||||||
|
if (!use_reflection)
|
||||||
|
continue;
|
||||||
|
// add reflection for biggest source
|
||||||
|
tr = Eigen::Scaling(-1., 1., 1.);
|
||||||
|
} else {
|
||||||
|
tr = s.tr * tr_inv;
|
||||||
|
if (use_reflection)
|
||||||
|
tr *= Eigen::Scaling(-1., 1., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fix_reflected = true;
|
||||||
indexed_triangle_set &its = itss[itss_index];
|
indexed_triangle_set &its = itss[itss_index];
|
||||||
its_transform(its, tr);
|
its_transform(its, tr, fix_reflected);
|
||||||
BoundingBoxf3 bb = bounding_box(its);
|
BoundingBoxf3 bb = bounding_box(its);
|
||||||
mesh_bb.merge(bb);
|
mesh_bb.merge(bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tr_inv = transformation of mesh inverted
|
// tr_inv = transformation of mesh inverted
|
||||||
Transform3d cut_projection_tr = tr_inv * input2.text_tr;
|
Transform3d emboss_tr = cut_projection_tr.inverse();
|
||||||
Transform3d emboss_tr = cut_projection_tr.inverse();
|
BoundingBoxf3 mesh_bb_tr = mesh_bb.transformed(emboss_tr);
|
||||||
BoundingBoxf3 mesh_bb_tr = mesh_bb.transformed(emboss_tr);
|
|
||||||
std::pair<float, float> z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
|
std::pair<float, float> z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
|
||||||
OrthoProject cut_projection = create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
|
OrthoProject cut_projection = create_projection_for_cut(cut_projection_tr, shape_scale, z_range);
|
||||||
float projection_ratio = (-z_range.first + safe_extension) / (z_range.second - z_range.first + 2 * safe_extension);
|
float projection_ratio = (-z_range.first + safe_extension) / (z_range.second - z_range.first + 2 * safe_extension);
|
||||||
@ -761,9 +782,13 @@ TriangleMesh priv::cut_surface(DataBase& input1, const SurfaceVolumeData& input2
|
|||||||
|
|
||||||
// !! Projection needs to transform cut
|
// !! Projection needs to transform cut
|
||||||
OrthoProject3d projection = create_emboss_projection(input2.is_outside, fp.emboss, emboss_tr, cut);
|
OrthoProject3d projection = create_emboss_projection(input2.is_outside, fp.emboss, emboss_tr, cut);
|
||||||
|
|
||||||
indexed_triangle_set new_its = cut2model(cut, projection);
|
indexed_triangle_set new_its = cut2model(cut, projection);
|
||||||
assert(!new_its.empty());
|
assert(!new_its.empty());
|
||||||
|
if (use_reflection) {
|
||||||
|
// when cut was made in reflected system it must be converted back
|
||||||
|
Transform3d tr(Eigen::Scaling(-1., 1., 1.));
|
||||||
|
its_transform(new_its, tr, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (was_canceled()) return {};
|
if (was_canceled()) return {};
|
||||||
return TriangleMesh(std::move(new_its));
|
return TriangleMesh(std::move(new_its));
|
||||||
|
@ -73,23 +73,10 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
|||||||
m_transformations.erase(m_transformations.begin() + i);
|
m_transformations.erase(m_transformations.begin() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace priv {
|
|
||||||
struct HitWithDistance : public RaycastManager::Hit
|
|
||||||
{
|
|
||||||
double squared_distance;
|
|
||||||
HitWithDistance(double squared_distance,
|
|
||||||
const Hit::Key &key,
|
|
||||||
const SurfacePoint &surface_point)
|
|
||||||
: Hit(key, surface_point.position, surface_point.normal)
|
|
||||||
, squared_distance(squared_distance)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
||||||
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
||||||
{
|
{
|
||||||
std::optional<priv::HitWithDistance> closest;
|
std::optional<Hit> closest;
|
||||||
for (const auto &item : m_transformations) {
|
for (const auto &item : m_transformations) {
|
||||||
const TrKey &key = item.first;
|
const TrKey &key = item.first;
|
||||||
size_t volume_id = key.second;
|
size_t volume_id = key.second;
|
||||||
@ -112,7 +99,7 @@ std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
|||||||
if (closest.has_value() &&
|
if (closest.has_value() &&
|
||||||
closest->squared_distance < squared_distance)
|
closest->squared_distance < squared_distance)
|
||||||
continue;
|
continue;
|
||||||
closest = priv::HitWithDistance(squared_distance, key, surface_point);
|
closest = Hit(key, surface_point, squared_distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!closest.has_value()) return {};
|
//if (!closest.has_value()) return {};
|
||||||
@ -121,7 +108,7 @@ std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
|||||||
|
|
||||||
std::optional<RaycastManager::Hit> RaycastManager::unproject(const Vec3d &point, const Vec3d &direction, const ISkip *skip) const
|
std::optional<RaycastManager::Hit> RaycastManager::unproject(const Vec3d &point, const Vec3d &direction, const ISkip *skip) const
|
||||||
{
|
{
|
||||||
std::optional<priv::HitWithDistance> closest;
|
std::optional<Hit> closest;
|
||||||
for (const auto &item : m_transformations) {
|
for (const auto &item : m_transformations) {
|
||||||
const TrKey &key = item.first;
|
const TrKey &key = item.first;
|
||||||
size_t volume_id = key.second;
|
size_t volume_id = key.second;
|
||||||
@ -144,14 +131,14 @@ std::optional<RaycastManager::Hit> RaycastManager::unproject(const Vec3d &point,
|
|||||||
closest->squared_distance < squared_distance)
|
closest->squared_distance < squared_distance)
|
||||||
continue;
|
continue;
|
||||||
SurfacePoint surface_point(hit.position().cast<float>(), hit.normal().cast<float>());
|
SurfacePoint surface_point(hit.position().cast<float>(), hit.normal().cast<float>());
|
||||||
closest = priv::HitWithDistance(squared_distance, key, surface_point);
|
closest = Hit(key, surface_point, squared_distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RaycastManager::Hit> RaycastManager::closest(const Vec3d &point, const ISkip *skip) const {
|
std::optional<RaycastManager::Hit> RaycastManager::closest(const Vec3d &point, const ISkip *skip) const {
|
||||||
std::optional<priv::HitWithDistance> closest;
|
std::optional<Hit> closest;
|
||||||
for (const auto &item : m_transformations) {
|
for (const auto &item : m_transformations) {
|
||||||
const TrKey &key = item.first;
|
const TrKey &key = item.first;
|
||||||
size_t volume_id = key.second;
|
size_t volume_id = key.second;
|
||||||
@ -172,7 +159,7 @@ std::optional<RaycastManager::Hit> RaycastManager::closest(const Vec3d &point, c
|
|||||||
if (closest.has_value() && closest->squared_distance < squared_distance)
|
if (closest.has_value() && closest->squared_distance < squared_distance)
|
||||||
continue;
|
continue;
|
||||||
SurfacePoint surface_point(p,n);
|
SurfacePoint surface_point(p,n);
|
||||||
closest = priv::HitWithDistance(squared_distance, key, surface_point);
|
closest = Hit(key, surface_point, squared_distance);
|
||||||
}
|
}
|
||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,9 @@ public:
|
|||||||
{
|
{
|
||||||
using Key = TrKey;
|
using Key = TrKey;
|
||||||
Key tr_key;
|
Key tr_key;
|
||||||
Hit(Key tr_key, Vec3f position, Vec3f normal)
|
double squared_distance;
|
||||||
: SurfacePoint(position, normal), tr_key(tr_key)
|
Hit(const Key& tr_key, const SurfacePoint& surface_point, double squared_distance)
|
||||||
|
: SurfacePoint(surface_point), tr_key(tr_key), squared_distance(squared_distance)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user