Project text origin on object surface when use surface is set. When no intersection thans closest point is selected
(@vojta wants it)
This commit is contained in:
parent
043c4c5e90
commit
e8e50b50f1
@ -1,5 +1,6 @@
|
|||||||
#include "CameraUtils.hpp"
|
#include "CameraUtils.hpp"
|
||||||
#include <igl/project.h> // projecting points
|
#include <igl/project.h> // projecting points
|
||||||
|
#include <igl/unproject.h>
|
||||||
|
|
||||||
#include "slic3r/GUI/3DScene.hpp" // GLVolume
|
#include "slic3r/GUI/3DScene.hpp" // GLVolume
|
||||||
#include "libslic3r/Geometry/ConvexHull.hpp"
|
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||||
@ -79,37 +80,48 @@ Slic3r::Polygon CameraUtils::create_hull2d(const Camera & camera,
|
|||||||
return Geometry::convex_hull(vertices_2d);
|
return Geometry::convex_hull(vertices_2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <igl/unproject.h>
|
void CameraUtils::ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction) {
|
||||||
Vec3d CameraUtils::create_ray(const Camera &camera, const Vec2d &coor) {
|
switch (camera.get_type()) {
|
||||||
if (camera.get_type() == Camera::EType::Ortho)
|
case Camera::EType::Ortho: return ray_from_ortho_screen_pos(camera, position, point, direction);
|
||||||
return camera.get_dir_forward();
|
case Camera::EType::Perspective: return ray_from_persp_screen_pos(camera, position, point, direction);
|
||||||
// check that it is known camera no other tha ORTHO or Persepective
|
default: break;
|
||||||
assert(camera.get_type() == Camera::EType::Perspective);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d CameraUtils::screen_point(const Camera &camera, const Vec2d &position)
|
||||||
|
{
|
||||||
|
double height = camera.get_viewport().data()[3];
|
||||||
|
// Y coordinate has opposit direction
|
||||||
|
return Vec3d(position.x(), height - position.y(), 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraUtils::ray_from_ortho_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
|
||||||
|
{
|
||||||
|
assert(camera.get_type() == Camera::EType::Ortho);
|
||||||
|
Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||||
|
Matrix4d projection = camera.get_projection_matrix().matrix();
|
||||||
|
Vec4i viewport(camera.get_viewport().data());
|
||||||
|
igl::unproject(screen_point(camera,position), modelview, projection, viewport, point);
|
||||||
|
direction = camera.get_dir_forward();
|
||||||
|
}
|
||||||
|
void CameraUtils::ray_from_persp_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
|
||||||
|
{
|
||||||
|
assert(camera.get_type() == Camera::EType::Perspective);
|
||||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||||
Matrix4d projection = camera.get_projection_matrix().matrix();
|
Matrix4d projection = camera.get_projection_matrix().matrix();
|
||||||
Vec4i viewport(camera.get_viewport().data());
|
Vec4i viewport(camera.get_viewport().data());
|
||||||
|
|
||||||
Vec3d scene_point(coor.x(), viewport[3] - coor.y(), 0.);
|
|
||||||
Vec3d unprojected_point;
|
Vec3d unprojected_point;
|
||||||
igl::unproject(scene_point, modelview, projection, viewport, unprojected_point);
|
igl::unproject(screen_point(camera, position), modelview, projection, viewport, unprojected_point);
|
||||||
|
|
||||||
Vec3d p0 = camera.get_position();
|
point = camera.get_position();
|
||||||
Vec3d dir = unprojected_point - p0;
|
direction = unprojected_point - point;
|
||||||
dir.normalize();
|
|
||||||
return dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2d CameraUtils::get_z0_position(const Camera &camera, const Vec2d & coor)
|
Vec2d CameraUtils::get_z0_position(const Camera &camera, const Vec2d & coor)
|
||||||
{
|
{
|
||||||
Vec3d dir = CameraUtils::create_ray(camera, coor);
|
Vec3d p0, dir;
|
||||||
Vec3d p0 = camera.get_position();
|
ray_from_screen_pos(camera, coor, p0, dir);
|
||||||
if (camera.get_type() == Camera::EType::Ortho) {
|
|
||||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
|
||||||
Matrix4d projection = camera.get_projection_matrix().matrix();
|
|
||||||
Vec4i viewport(camera.get_viewport().data());
|
|
||||||
igl::unproject(Vec3d(coor.x(), viewport[3] - coor.y(), 0.), modelview, projection, viewport, p0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// is approx zero
|
// is approx zero
|
||||||
if ((fabs(dir.z()) - 1e-4) < 0)
|
if ((fabs(dir.z()) - 1e-4) < 0)
|
||||||
|
@ -36,12 +36,15 @@ public:
|
|||||||
static Polygon create_hull2d(const Camera &camera, const GLVolume &volume);
|
static Polygon create_hull2d(const Camera &camera, const GLVolume &volume);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unproject screen coordinate to scene direction start from camera position
|
/// Create ray(point and direction) for screen coordinate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="camera">Projection params</param>
|
/// <param name="camera">Definition of camera</param>
|
||||||
/// <param name="coor">Coordinate on screen</param>
|
/// <param name="position">Position on screen(aka mouse position) </param>
|
||||||
/// <returns>Scene direction</returns>
|
/// <param name="point">OUT start of ray</param>
|
||||||
static Vec3d create_ray(const Camera &camera, const Vec2d &coor);
|
/// <param name="direction">OUT direction of ray</param>
|
||||||
|
static void ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction);
|
||||||
|
static void ray_from_ortho_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction);
|
||||||
|
static void ray_from_persp_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unproject mouse coordinate to get position in space where z coor is zero
|
/// Unproject mouse coordinate to get position in space where z coor is zero
|
||||||
@ -52,6 +55,14 @@ public:
|
|||||||
/// <returns>Position on platter under mouse</returns>
|
/// <returns>Position on platter under mouse</returns>
|
||||||
static Vec2d get_z0_position(const Camera &camera, const Vec2d &coor);
|
static Vec2d get_z0_position(const Camera &camera, const Vec2d &coor);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create 3d screen point from 2d position
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="camera">Define camera viewport</param>
|
||||||
|
/// <param name="position">Position on screen(aka mouse position)</param>
|
||||||
|
/// <returns>Point represented screen coor in 3d</returns>
|
||||||
|
static Vec3d screen_point(const Camera &camera, const Vec2d &position);
|
||||||
|
|
||||||
};
|
};
|
||||||
} // Slic3r::GUI
|
} // Slic3r::GUI
|
||||||
|
|
||||||
|
@ -506,7 +506,8 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
if (!hit.has_value())
|
if (!hit.has_value())
|
||||||
return false;
|
return false;
|
||||||
TextConfiguration &tc = *m_volume->text_configuration;
|
TextConfiguration &tc = *m_volume->text_configuration;
|
||||||
// hide common dragging of object
|
// INFO: GLVolume is transformed by common movement but we need move over surface
|
||||||
|
// so hide common dragging of object
|
||||||
m_parent.toggle_model_objects_visibility(false, m_volume->get_object(), gl_volume->instance_idx(), m_volume);
|
m_parent.toggle_model_objects_visibility(false, m_volume->get_object(), gl_volume->instance_idx(), m_volume);
|
||||||
|
|
||||||
// Calculate temporary position
|
// Calculate temporary position
|
||||||
@ -519,7 +520,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
if (tc.fix_3mf_tr.has_value())
|
if (tc.fix_3mf_tr.has_value())
|
||||||
trmat = trmat * (*tc.fix_3mf_tr);
|
trmat = trmat * (*tc.fix_3mf_tr);
|
||||||
|
|
||||||
// temp is in wolrld coors
|
// temp is in world coors
|
||||||
m_temp_transformation = object_trmat * trmat;
|
m_temp_transformation = object_trmat * trmat;
|
||||||
} else if (mouse_event.LeftUp()) {
|
} else if (mouse_event.LeftUp()) {
|
||||||
// Added because of weird case after double click into scene
|
// Added because of weird case after double click into scene
|
||||||
@ -2849,6 +2850,44 @@ void GLGizmoEmboss::do_rotate(float relative_z_angle)
|
|||||||
// snapshot_name = L("Set text rotation");
|
// snapshot_name = L("Set text rotation");
|
||||||
m_parent.do_rotate(snapshot_name);
|
m_parent.do_rotate(snapshot_name);
|
||||||
}
|
}
|
||||||
|
namespace priv {
|
||||||
|
bool transform_on_surface(ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection)
|
||||||
|
{
|
||||||
|
// Move object on surface
|
||||||
|
auto cond = RaycastManager::SkipVolume({volume.id().id});
|
||||||
|
raycast_manager.actualize(volume.get_object(), &cond);
|
||||||
|
|
||||||
|
//const Selection &selection = m_parent.get_selection();
|
||||||
|
const GLVolume *gl_volume = priv::get_gl_volume(selection);
|
||||||
|
Transform3d to_world = priv::world_matrix(gl_volume, selection.get_model());
|
||||||
|
Vec3d point = to_world * Vec3d::Zero();
|
||||||
|
Vec3d direction = to_world.linear() * (-Vec3d::UnitZ());
|
||||||
|
//direction.normalize();
|
||||||
|
|
||||||
|
// ray in direction of text projection(from volume zero to z-dir)
|
||||||
|
std::optional<RaycastManager::Hit> hit_opt = raycast_manager.unproject(point, direction, &cond);
|
||||||
|
if (!hit_opt.has_value())
|
||||||
|
hit_opt = raycast_manager.closest(point);
|
||||||
|
|
||||||
|
if (!hit_opt.has_value())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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
|
||||||
|
// TIP: It should be close to only z move
|
||||||
|
Vec3d offset_volume = to_world.inverse().linear() * offset_world;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_advanced()
|
void GLGizmoEmboss::draw_advanced()
|
||||||
{
|
{
|
||||||
@ -2903,7 +2942,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
if (font_prop.emboss < 0.1)
|
if (font_prop.emboss < 0.1)
|
||||||
font_prop.emboss = 1;
|
font_prop.emboss = 1;
|
||||||
|
|
||||||
// TODO: project an origin on surface
|
priv::transform_on_surface(*m_volume, m_raycast_manager, m_parent.get_selection());
|
||||||
}
|
}
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/Camera.hpp"
|
#include "slic3r/GUI/Camera.hpp"
|
||||||
|
#include "slic3r/GUI/CameraUtils.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
@ -340,36 +341,24 @@ Vec3f MeshRaycaster::get_triangle_normal(size_t facet_idx) const
|
|||||||
return m_normals[facet_idx];
|
return m_normals[facet_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, Vec3d& point, Vec3d& direction)
|
||||||
Vec3d& point, Vec3d& direction)
|
|
||||||
{
|
{
|
||||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
|
||||||
Matrix4d projection= camera.get_projection_matrix().matrix();
|
|
||||||
Vec4i viewport(camera.get_viewport().data());
|
|
||||||
|
|
||||||
Vec3d pt1;
|
|
||||||
Vec3d pt2;
|
|
||||||
igl::unproject(Vec3d(mouse_pos.x(), viewport[3] - mouse_pos.y(), 0.),
|
|
||||||
modelview, projection, viewport, pt1);
|
|
||||||
igl::unproject(Vec3d(mouse_pos.x(), viewport[3] - mouse_pos.y(), 1.),
|
|
||||||
modelview, projection, viewport, pt2);
|
|
||||||
|
|
||||||
Transform3d inv = trafo.inverse();
|
Transform3d inv = trafo.inverse();
|
||||||
pt1 = inv * pt1;
|
point = inv*point;
|
||||||
pt2 = inv * pt2;
|
direction = inv.linear()*direction;
|
||||||
|
|
||||||
point = pt1;
|
|
||||||
direction = pt2-pt1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||||
Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane,
|
Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane,
|
||||||
size_t* facet_idx) const
|
size_t* facet_idx) const
|
||||||
{
|
{
|
||||||
Vec3d point;
|
Vec3d point;
|
||||||
Vec3d direction;
|
Vec3d direction;
|
||||||
line_from_mouse_pos(mouse_pos, trafo, camera, point, direction);
|
CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
|
||||||
|
Transform3d inv = trafo.inverse();
|
||||||
|
point = inv*point;
|
||||||
|
direction = inv.linear()*direction;
|
||||||
|
|
||||||
std::vector<AABBMesh::hit_result> hits = m_emesh.query_ray_hits(point, direction);
|
std::vector<AABBMesh::hit_result> hits = m_emesh.query_ray_hits(point, direction);
|
||||||
|
|
||||||
|
@ -145,6 +145,7 @@ public:
|
|||||||
assert(m_mesh != nullptr);
|
assert(m_mesh != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRICATED - use CameraUtils::ray_from_screen_pos
|
||||||
static void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
static void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||||
Vec3d& point, Vec3d& direction);
|
Vec3d& point, Vec3d& direction);
|
||||||
|
|
||||||
@ -159,6 +160,8 @@ public:
|
|||||||
size_t* facet_idx = nullptr // index of the facet hit
|
size_t* facet_idx = nullptr // index of the facet hit
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
const AABBMesh &get_aabb_mesh() const { return m_emesh; }
|
||||||
|
|
||||||
bool is_valid_intersection(Vec3d point, Vec3d direction, const Transform3d& trafo) const;
|
bool is_valid_intersection(Vec3d point, Vec3d direction, const Transform3d& trafo) const;
|
||||||
|
|
||||||
// Given a vector of points in woorld coordinates, this returns vector
|
// Given a vector of points in woorld coordinates, this returns vector
|
||||||
|
@ -73,20 +73,23 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
|||||||
m_transformations.erase(m_transformations.begin() + i);
|
m_transformations.erase(m_transformations.begin() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
namespace priv {
|
||||||
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
struct HitWithDistance : public RaycastManager::Hit
|
||||||
{
|
|
||||||
struct HitWithDistance: public Hit
|
|
||||||
{
|
{
|
||||||
double squared_distance;
|
double squared_distance;
|
||||||
HitWithDistance(double squared_distance,
|
HitWithDistance(double squared_distance,
|
||||||
const TrKey & key,
|
const Hit::Key &key,
|
||||||
const SurfacePoint &surface_point)
|
const SurfacePoint &surface_point)
|
||||||
: Hit(key, surface_point.position, surface_point.normal)
|
: Hit(key, surface_point.position, surface_point.normal)
|
||||||
, squared_distance(squared_distance)
|
, squared_distance(squared_distance)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
std::optional<HitWithDistance> closest;
|
}
|
||||||
|
|
||||||
|
std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
||||||
|
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
||||||
|
{
|
||||||
|
std::optional<priv::HitWithDistance> 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;
|
||||||
@ -109,13 +112,69 @@ 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 = HitWithDistance(squared_distance, key, surface_point);
|
closest = priv::HitWithDistance(squared_distance, key, surface_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!closest.has_value()) return {};
|
//if (!closest.has_value()) return {};
|
||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<RaycastManager::Hit> RaycastManager::unproject(const Vec3d &point, const Vec3d &direction, const ISkip *skip) const
|
||||||
|
{
|
||||||
|
std::optional<priv::HitWithDistance> 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;
|
||||||
|
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 Transform3d & tr_inv = transformation.inverse();
|
||||||
|
Vec3d mesh_point = tr_inv * point;
|
||||||
|
Vec3d mesh_direction = tr_inv.linear() * direction;
|
||||||
|
std::vector<AABBMesh::hit_result> hits = mesh.query_ray_hits(mesh_point, mesh_direction);
|
||||||
|
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 = priv::HitWithDistance(squared_distance, key, surface_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<RaycastManager::Hit> RaycastManager::closest(const Vec3d &point, const ISkip *skip) const {
|
||||||
|
Vec3f point_f = point.cast<float>();
|
||||||
|
std::optional<priv::HitWithDistance> 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;
|
||||||
|
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);
|
||||||
|
Vec3f n;
|
||||||
|
Vec3f p = raycaster.get_closest_point(point_f, &n);
|
||||||
|
double squared_distance = (point_f - p).squaredNorm();
|
||||||
|
if (closest.has_value() && closest->squared_distance < squared_distance)
|
||||||
|
continue;
|
||||||
|
SurfacePoint surface_point(p,n);
|
||||||
|
closest = priv::HitWithDistance(squared_distance, key, surface_point);
|
||||||
|
}
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
Slic3r::Transform3d RaycastManager::get_transformation(const TrKey &tr_key) const {
|
Slic3r::Transform3d RaycastManager::get_transformation(const TrKey &tr_key) const {
|
||||||
auto item = std::find_if(m_transformations.begin(),
|
auto item = std::find_if(m_transformations.begin(),
|
||||||
m_transformations.end(),
|
m_transformations.end(),
|
||||||
|
@ -65,8 +65,9 @@ public:
|
|||||||
|
|
||||||
struct Hit: public SurfacePoint
|
struct Hit: public SurfacePoint
|
||||||
{
|
{
|
||||||
TrKey tr_key;
|
using Key = TrKey;
|
||||||
Hit(TrKey tr_key, Vec3f position, Vec3f normal)
|
Key tr_key;
|
||||||
|
Hit(Key tr_key, Vec3f position, Vec3f normal)
|
||||||
: SurfacePoint(position, normal), tr_key(tr_key)
|
: SurfacePoint(position, normal), tr_key(tr_key)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@ -102,6 +103,23 @@ public:
|
|||||||
const Camera &camera,
|
const Camera &camera,
|
||||||
const ISkip *skip = nullptr) const;
|
const ISkip *skip = nullptr) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unproject Ray(point direction) on mesh by MeshRaycasters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="point">Start point for ray</param>
|
||||||
|
/// <param name="direction">Direction of ray</param>
|
||||||
|
/// <param name="skip">Define which caster will be skipped, null mean no skip</param>
|
||||||
|
/// <returns>Position on surface, normal direction and transformation key, which define hitted object instance</returns>
|
||||||
|
std::optional<Hit> unproject(const Vec3d &point, const Vec3d &direction, const ISkip *skip = nullptr) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search of closest point
|
||||||
|
/// </summary>
|
||||||
|
/// <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;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Getter on transformation
|
/// Getter on transformation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user