mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 23:06:13 +08:00
Move over surface with relative transformation
This commit is contained in:
parent
67155e8da0
commit
b82f1fe818
@ -1540,8 +1540,28 @@ std::optional<Vec2d> Emboss::ProjectZ::unproject(const Vec3d &p, double *depth)
|
|||||||
return Vec2d(p.x() / SHAPE_SCALE, p.y() / SHAPE_SCALE);
|
return Vec2d(p.x() / SHAPE_SCALE, p.y() / SHAPE_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform3d Emboss::create_transformation_onto_surface(const Vec3f &position,
|
|
||||||
const Vec3f &normal,
|
Vec3d Emboss::suggest_up(const Vec3d normal, double up_limit)
|
||||||
|
{
|
||||||
|
// Normal must be 1
|
||||||
|
assert(is_approx(normal.norm(), 1.));
|
||||||
|
|
||||||
|
// wanted up direction of result
|
||||||
|
Vec3d wanted_up_side =
|
||||||
|
(std::fabs(normal.z()) > up_limit)?
|
||||||
|
Vec3d::UnitY() : Vec3d::UnitZ();
|
||||||
|
|
||||||
|
// create perpendicular unit vector to surface triangle normal vector
|
||||||
|
// lay on surface of triangle and define up vector for text
|
||||||
|
Vec3d wanted_up_dir = normal.cross(wanted_up_side).cross(normal);
|
||||||
|
// normal3d is NOT perpendicular to normal_up_dir
|
||||||
|
wanted_up_dir.normalize();
|
||||||
|
|
||||||
|
return wanted_up_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d Emboss::create_transformation_onto_surface(const Vec3d &position,
|
||||||
|
const Vec3d &normal,
|
||||||
float up_limit)
|
float up_limit)
|
||||||
{
|
{
|
||||||
// up and emboss direction for generated model
|
// up and emboss direction for generated model
|
||||||
@ -1552,28 +1572,27 @@ Transform3d Emboss::create_transformation_onto_surface(const Vec3f &position,
|
|||||||
Vec3d wanted_up_side = Vec3d::UnitZ();
|
Vec3d wanted_up_side = Vec3d::UnitZ();
|
||||||
if (std::fabs(normal.z()) > up_limit) wanted_up_side = Vec3d::UnitY();
|
if (std::fabs(normal.z()) > up_limit) wanted_up_side = Vec3d::UnitY();
|
||||||
|
|
||||||
Vec3d wanted_emboss_dir = normal.cast<double>();
|
|
||||||
// after cast from float it needs to be normalized again
|
// after cast from float it needs to be normalized again
|
||||||
wanted_emboss_dir.normalize();
|
assert(is_approx(normal.norm(), 1.));
|
||||||
|
|
||||||
// create perpendicular unit vector to surface triangle normal vector
|
// create perpendicular unit vector to surface triangle normal vector
|
||||||
// lay on surface of triangle and define up vector for text
|
// lay on surface of triangle and define up vector for text
|
||||||
Vec3d wanted_up_dir = wanted_emboss_dir
|
Vec3d wanted_up_dir = normal
|
||||||
.cross(wanted_up_side)
|
.cross(wanted_up_side)
|
||||||
.cross(wanted_emboss_dir);
|
.cross(normal);
|
||||||
// normal3d is NOT perpendicular to normal_up_dir
|
// normal3d is NOT perpendicular to normal_up_dir
|
||||||
wanted_up_dir.normalize();
|
wanted_up_dir.normalize();
|
||||||
|
|
||||||
// perpendicular to emboss vector of text and normal
|
// perpendicular to emboss vector of text and normal
|
||||||
Vec3d axis_view;
|
Vec3d axis_view;
|
||||||
double angle_view;
|
double angle_view;
|
||||||
if (wanted_emboss_dir == -Vec3d::UnitZ()) {
|
if (normal == -Vec3d::UnitZ()) {
|
||||||
// text_emboss_dir has opposit direction to wanted_emboss_dir
|
// text_emboss_dir has opposit direction to wanted_emboss_dir
|
||||||
axis_view = Vec3d::UnitY();
|
axis_view = Vec3d::UnitY();
|
||||||
angle_view = M_PI;
|
angle_view = M_PI;
|
||||||
} else {
|
} else {
|
||||||
axis_view = text_emboss_dir.cross(wanted_emboss_dir);
|
axis_view = text_emboss_dir.cross(normal);
|
||||||
angle_view = std::acos(text_emboss_dir.dot(wanted_emboss_dir)); // in rad
|
angle_view = std::acos(text_emboss_dir.dot(normal)); // in rad
|
||||||
axis_view.normalize();
|
axis_view.normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1593,7 +1612,7 @@ Transform3d Emboss::create_transformation_onto_surface(const Vec3f &position,
|
|||||||
Eigen::AngleAxis up_rot(angle_up, text_emboss_dir);
|
Eigen::AngleAxis up_rot(angle_up, text_emboss_dir);
|
||||||
|
|
||||||
Transform3d transform = Transform3d::Identity();
|
Transform3d transform = Transform3d::Identity();
|
||||||
transform.translate(position.cast<double>());
|
transform.translate(position);
|
||||||
transform.rotate(view_rot);
|
transform.rotate(view_rot);
|
||||||
transform.rotate(up_rot);
|
transform.rotate(up_rot);
|
||||||
return transform;
|
return transform;
|
||||||
|
@ -273,7 +273,15 @@ namespace Emboss
|
|||||||
/// <param name="projection">Define transformation from 2d to 3d(orientation, position, scale, ...)</param>
|
/// <param name="projection">Define transformation from 2d to 3d(orientation, position, scale, ...)</param>
|
||||||
/// <returns>Projected shape into space</returns>
|
/// <returns>Projected shape into space</returns>
|
||||||
indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProjection& projection);
|
indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProjection& projection);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Suggest wanted up vector of embossed text by emboss direction
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="normal">Normalized vector of emboss direction in world</param>
|
||||||
|
/// <param name="up_limit">Is compared with normal.z to suggest up direction</param>
|
||||||
|
/// <returns>Wanted up vector</returns>
|
||||||
|
Vec3d suggest_up(const Vec3d normal, double up_limit = 0.9);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create transformation for emboss text object to lay on surface point
|
/// Create transformation for emboss text object to lay on surface point
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -282,7 +290,7 @@ namespace Emboss
|
|||||||
/// <param name="up_limit">Is compared with normal.z to suggest up direction</param>
|
/// <param name="up_limit">Is compared with normal.z to suggest up direction</param>
|
||||||
/// <returns>Transformation onto surface point</returns>
|
/// <returns>Transformation onto surface point</returns>
|
||||||
Transform3d create_transformation_onto_surface(
|
Transform3d create_transformation_onto_surface(
|
||||||
const Vec3f &position, const Vec3f &normal, float up_limit = 0.9f);
|
const Vec3d &position, const Vec3d &normal, float up_limit = 0.9f);
|
||||||
|
|
||||||
class ProjectZ : public IProjection
|
class ProjectZ : public IProjection
|
||||||
{
|
{
|
||||||
|
@ -828,42 +828,38 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
Vec2d mouse_pos = mouse_coord.cast<double>();
|
Vec2d mouse_pos = mouse_coord.cast<double>();
|
||||||
Vec2d offseted_mouse = mouse_pos + m_surface_drag->mouse_offset;
|
Vec2d offseted_mouse = mouse_pos + m_surface_drag->mouse_offset;
|
||||||
const Camera &camera = wxGetApp().plater()->get_camera();
|
const Camera &camera = wxGetApp().plater()->get_camera();
|
||||||
auto hit = m_raycast_manager.unproject(offseted_mouse, camera, &m_surface_drag->condition);
|
auto hit = m_raycast_manager.ray_from_camera(offseted_mouse, camera, &m_surface_drag->condition);
|
||||||
m_surface_drag->exist_hit = hit.has_value();
|
m_surface_drag->exist_hit = hit.has_value();
|
||||||
if (!hit.has_value()) {
|
if (!hit.has_value()) {
|
||||||
// cross hair need redraw
|
// cross hair need redraw
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Calculate offset: transformation to wanted position
|
|
||||||
Transform3d hit_to_world = m_raycast_manager.get_transformation(hit->tr_key);
|
|
||||||
Transform3d hit_to_instance = hit_to_world * m_surface_drag->instance_inv;
|
|
||||||
Transform3d hit_to_volume = hit_to_instance * m_surface_drag->volume_tr.inverse();
|
|
||||||
|
|
||||||
Vec3d hit_position = hit->position.cast<double>();
|
|
||||||
Vec3d offset_volume = hit_to_volume * hit_position;
|
|
||||||
Transform3d translate{Eigen::Translation<double, 3>(offset_volume)};
|
|
||||||
|
|
||||||
Transform3d rotate;
|
|
||||||
// normal transformed to volume
|
|
||||||
Vec3d hit_normal = hit->normal.cast<double>();
|
|
||||||
Vec3d z_t = hit_to_volume.linear() * hit_normal;
|
|
||||||
bool exist_rotate = priv::allign_z(z_t, rotate);
|
|
||||||
// Edit position from right
|
|
||||||
Transform3d volume_new = m_surface_drag->volume_tr * translate * rotate;
|
|
||||||
|
|
||||||
const Transform3d &instance = m_surface_drag->gl_volume->get_instance_transformation().get_matrix();
|
const Transform3d &instance = m_surface_drag->gl_volume->get_instance_transformation().get_matrix();
|
||||||
const Transform3d &volume = m_surface_drag->volume_tr;
|
const Transform3d &volume = m_surface_drag->volume_tr;
|
||||||
|
|
||||||
Vec3d hit_position_world = hit_to_world * hit_position;
|
// Calculate offset: transformation to wanted position
|
||||||
Vec3d hit_normal_world = hit_to_world.linear() * hit_normal;
|
Transform3d text_to_world_old = instance * volume;
|
||||||
|
{
|
||||||
|
// Reset skew of the text Z axis:
|
||||||
|
// Project the old Z axis into a new Z axis, which is perpendicular to the old XY plane.
|
||||||
|
Vec3d old_z = text_to_world_old.linear().col(2);
|
||||||
|
Vec3d new_z = text_to_world_old.linear().col(0).cross(text_to_world_old.linear().col(1));
|
||||||
|
text_to_world_old.linear().col(2) = new_z * (old_z.dot(new_z) / new_z.squaredNorm());
|
||||||
|
}
|
||||||
|
|
||||||
// REWRITE transformation
|
// normal transformed to volume
|
||||||
Transform3d volume_R = priv::surface_transformR(hit_position_world, hit_normal_world, volume, instance);
|
Vec3d text_z_world = text_to_world_old.linear() * Vec3d::UnitZ();
|
||||||
Transform3d volume_L = priv::surface_transformL(hit_position_world, hit_normal_world, volume, instance);
|
auto z_rotation = Eigen::Quaternion<double, Eigen::DontAlign>::FromTwoVectors(text_z_world, hit->normal);
|
||||||
Transform3d volume_2 = priv::surface_transform2(hit_position_world, hit_normal_world, volume, instance);
|
Transform3d text_to_world_new = z_rotation * text_to_world_old;
|
||||||
Transform3d volume_3 = priv::surface_transform3(hit_position_world, hit_normal_world, volume, instance);
|
|
||||||
volume_new = volume_R;
|
// Fix up vector ??
|
||||||
|
//auto y_rotation = Eigen::Quaternion<double, Eigen::DontAlign>::FromTwoVectors(text_y_world, hit->normal);
|
||||||
|
|
||||||
|
// Edit position from right
|
||||||
|
Transform3d volume_new{Eigen::Translation<double, 3>(m_surface_drag->instance_inv * hit->position)};
|
||||||
|
volume_new.linear() = instance.linear().inverse() * text_to_world_new.linear();
|
||||||
|
|
||||||
assert(volume_new.matrix()(0, 0) == volume_new.matrix()(0, 0)); // Check valid transformation not a NAN
|
assert(volume_new.matrix()(0, 0) == volume_new.matrix()(0, 0)); // Check valid transformation not a NAN
|
||||||
if (volume_new.matrix()(0, 0) != volume_new.matrix()(0, 0))
|
if (volume_new.matrix()(0, 0) != volume_new.matrix()(0, 0))
|
||||||
@ -871,14 +867,8 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
|
|
||||||
// Check scale in world
|
// Check scale in world
|
||||||
// Calculate Scale to keep size after move over scaled surface
|
// Calculate Scale to keep size after move over scaled surface
|
||||||
Transform3d current_world = instance * volume;
|
m_surface_drag->y_scale = priv::calc_scale(text_to_world_old.linear(), text_to_world_new.linear(), Vec3d::UnitY());
|
||||||
auto current_world_linear = current_world.linear();
|
m_surface_drag->z_scale = priv::calc_scale(text_to_world_old.linear(), text_to_world_new.linear(), Vec3d::UnitZ());
|
||||||
|
|
||||||
Transform3d wanted_world = instance * volume_new;
|
|
||||||
auto wanted_world_linear = wanted_world.linear();
|
|
||||||
|
|
||||||
m_surface_drag->y_scale = priv::calc_scale(current_world_linear, wanted_world_linear, Vec3d::UnitY());
|
|
||||||
m_surface_drag->z_scale = priv::calc_scale(current_world_linear, wanted_world_linear, Vec3d::UnitZ());
|
|
||||||
|
|
||||||
// recalculate rotation for scaled volume
|
// recalculate rotation for scaled volume
|
||||||
//Transform3d hit_to_volume2 = hit_to_instance * (m_surface_drag->volume_tr*scale).inverse();
|
//Transform3d hit_to_volume2 = hit_to_instance * (m_surface_drag->volume_tr*scale).inverse();
|
||||||
@ -4245,7 +4235,7 @@ bool priv::start_create_volume_on_surface_job(
|
|||||||
raycaster.actualize(obj, &cond);
|
raycaster.actualize(obj, &cond);
|
||||||
|
|
||||||
const Camera &camera = plater->get_camera();
|
const Camera &camera = plater->get_camera();
|
||||||
std::optional<RaycastManager::Hit> hit = raycaster.unproject(screen_coor, camera);
|
std::optional<RaycastManager::Hit> hit = raycaster.ray_from_camera(screen_coor, camera, &cond);
|
||||||
|
|
||||||
// context menu for add text could be open only by right click on an
|
// context menu for add text could be open only by right click on an
|
||||||
// object. After right click, object is selected and object_idx is set
|
// object. After right click, object is selected and object_idx is set
|
||||||
@ -4253,15 +4243,14 @@ bool priv::start_create_volume_on_surface_job(
|
|||||||
if (!hit.has_value())
|
if (!hit.has_value())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Transform3d hit_to_world = raycaster.get_transformation(hit->tr_key);
|
|
||||||
// priv::reset_skew(hit_to_world);
|
// priv::reset_skew(hit_to_world);
|
||||||
Transform3d instance = gl_volume->get_instance_transformation().get_matrix();
|
Transform3d instance = gl_volume->get_instance_transformation().get_matrix();
|
||||||
|
|
||||||
// Create result volume transformation
|
// Create result volume transformation
|
||||||
Transform3d surface_trmat = create_transformation_onto_surface(hit->position.cast<float>(), hit->normal.cast<float>());
|
Transform3d surface_trmat = create_transformation_onto_surface(hit->position, hit->normal);
|
||||||
const FontProp &font_prop = emboss_data.text_configuration.style.prop;
|
const FontProp &font_prop = emboss_data.text_configuration.style.prop;
|
||||||
apply_transformation(font_prop, surface_trmat);
|
apply_transformation(font_prop, surface_trmat);
|
||||||
Transform3d world_new = hit_to_world * surface_trmat;
|
Transform3d world_new = surface_trmat;
|
||||||
|
|
||||||
// Reset skew
|
// Reset skew
|
||||||
priv::reset_skew_respect_z(world_new);
|
priv::reset_skew_respect_z(world_new);
|
||||||
|
@ -19,14 +19,6 @@ static bool is_lower_key(const RaycastManager::TrKey &k1, const RaycastManager::
|
|||||||
return k1.first < k2.first || k1.first == k2.first && k1.second < k2.second; }
|
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) {
|
static bool is_lower(const RaycastManager::TrItem &i1, const RaycastManager::TrItem &i2) {
|
||||||
return is_lower_key(i1.first, i2.first); };
|
return is_lower_key(i1.first, i2.first); };
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
void RaycastManager::actualize(const ModelObject *object, const ISkip *skip)
|
||||||
@ -108,11 +100,21 @@ void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip)
|
|||||||
if (need_sort)
|
if (need_sort)
|
||||||
std::sort(m_transformations.begin(), m_transformations.end(), priv::is_lower);
|
std::sort(m_transformations.begin(), m_transformations.end(), priv::is_lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
std::optional<RaycastManager::Hit> RaycastManager::ray_from_camera(
|
||||||
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip) const
|
||||||
{
|
{
|
||||||
std::optional<Hit> closest;
|
// Improve it is not neccessaru to use AABBMesh and calc normal in
|
||||||
|
|
||||||
|
struct Result
|
||||||
|
{
|
||||||
|
const AABBMesh *mesh = nullptr;
|
||||||
|
double squared_distance;
|
||||||
|
int face;
|
||||||
|
Vec3d hit_world;
|
||||||
|
const Transform3d *tramsformation;
|
||||||
|
const TrKey *key;
|
||||||
|
}result;
|
||||||
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;
|
||||||
@ -120,18 +122,46 @@ std::optional<RaycastManager::Hit> RaycastManager::unproject(
|
|||||||
const AABBMesh *mesh = priv::get_mesh(m_meshes, volume_id);
|
const AABBMesh *mesh = priv::get_mesh(m_meshes, volume_id);
|
||||||
if (mesh == nullptr) continue;
|
if (mesh == nullptr) continue;
|
||||||
const Transform3d &transformation = item.second;
|
const Transform3d &transformation = item.second;
|
||||||
auto surface_point_opt =
|
|
||||||
priv::unproject_on_mesh(*mesh, mouse_pos, transformation, camera);
|
Vec3d point;
|
||||||
if (!surface_point_opt.has_value())
|
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 = mesh->query_ray_hits(point, direction);
|
||||||
|
if (hits.empty()) continue; // no intersection found
|
||||||
|
|
||||||
|
const AABBMesh::hit_result &hit = hits.front();
|
||||||
|
|
||||||
|
// convert to world
|
||||||
|
Vec3d hit_world = transformation * hit.position();
|
||||||
|
double squared_distance = (camera.get_position() - hit_world).squaredNorm();
|
||||||
|
if (result.mesh != nullptr &&
|
||||||
|
result.squared_distance < squared_distance)
|
||||||
continue;
|
continue;
|
||||||
Vec3d act_hit_tr = transformation * surface_point_opt->position.cast<double>();
|
|
||||||
double squared_distance = (camera.get_position() - act_hit_tr).squaredNorm();
|
result.mesh = mesh;
|
||||||
if (closest.has_value() &&
|
result.squared_distance = squared_distance;
|
||||||
closest->squared_distance < squared_distance)
|
result.face = hit.face();
|
||||||
continue;
|
result.hit_world = hit_world;
|
||||||
closest = Hit{*surface_point_opt, key, squared_distance};
|
result.tramsformation = &transformation;
|
||||||
|
result.key = &key;
|
||||||
}
|
}
|
||||||
return closest;
|
|
||||||
|
if (result.mesh == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const Vec3i tri = result.mesh->indices(result.face);
|
||||||
|
Vec3d pts[3];
|
||||||
|
auto tr = result.tramsformation->linear();
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
pts[i] = tr * result.mesh->vertices(tri[i]).cast<double>();
|
||||||
|
Vec3d normal_world = (pts[1] - pts[0]).cross(pts[2] - pts[1]);
|
||||||
|
normal_world.normalize();
|
||||||
|
|
||||||
|
SurfacePoint<double> point_world{result.hit_world, normal_world};
|
||||||
|
return RaycastManager::Hit{point_world, *result.key, result.squared_distance};
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -241,26 +271,6 @@ void priv::actualize(RaycastManager::Meshes &meshes, const ModelVolumePtrs &volu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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 is_lower_index = [](const RaycastManager::Mesh &m, size_t i) -> bool { return m.first < i; };
|
||||||
|
@ -114,10 +114,9 @@ public:
|
|||||||
/// <param name="mouse_pos">Position of mouse on screen</param>
|
/// <param name="mouse_pos">Position of mouse on screen</param>
|
||||||
/// <param name="camera">Projection params</param>
|
/// <param name="camera">Projection params</param>
|
||||||
/// <param name="skip">Define which caster will be skipped, null mean no skip</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>
|
/// <returns>Position on surface, normal direction in world coorinate
|
||||||
std::optional<Hit> unproject(const Vec2d &mouse_pos,
|
/// + key, to know hitted instance and volume</returns>
|
||||||
const Camera &camera,
|
std::optional<Hit> ray_from_camera(const Vec2d &mouse_pos, const Camera &camera, const ISkip *skip = nullptr) const;
|
||||||
const ISkip *skip = nullptr) const;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unproject Ray(point direction) on mesh by MeshRaycasters
|
/// Unproject Ray(point direction) on mesh by MeshRaycasters
|
||||||
|
Loading…
x
Reference in New Issue
Block a user