#ifndef slic3r_RaycastManager_hpp_ #define slic3r_RaycastManager_hpp_ #include // unique_ptr #include #include "libslic3r/SLA/IndexedMesh.hpp" //#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 namespace Slic3r::GUI{ /// /// Cast rays from camera to scene /// Used for find hit point on model volume under mouse cursor /// class RaycastManager { // Public structures used by RaycastManager public: // ModelVolume.id using Mesh = std::pair >;//AABBMesh using Meshes = std::vector; // Key for transformation consist of unique volume and instance id ... ObjectId() // ModelInstance, ModelVolume using TrKey = std::pair; using TrItem = std::pair; using TrItems = std::vector; /// /// Interface for identify allowed volumes to cast rays. /// class ISkip{ public: virtual ~ISkip() = default; /// /// Condition to not process model volume /// /// ObjectID of model volume to not process /// True on skip otherwise false virtual bool skip(const size_t &model_volume_id) const { return false; } }; // TODO: it is more general object move outside of this class template struct SurfacePoint { using Vec3 = Eigen::Matrix; Vec3 position = Vec3::Zero(); Vec3 normal = Vec3::UnitZ(); }; struct Hit : public SurfacePoint { TrKey tr_key; double squared_distance; }; struct ClosePoint { TrKey tr_key; Vec3d point; double squared_distance; }; const Meshes& get_meshes() { return m_meshes; } // 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: /// /// Actualize raycasters + transformation /// Detection of removed object /// Detection of removed instance /// Detection of removed volume /// /// Model representation /// Condifiton for skip actualization /// Speed up for already created AABBtrees void actualize(const ModelObject &object, const ISkip *skip = nullptr, Meshes *meshes = nullptr); void actualize(const ModelInstance &instance, const ISkip *skip = nullptr, Meshes* meshes = nullptr); class SkipVolume: public ISkip { size_t volume_id; public: SkipVolume(size_t volume_id) : volume_id(volume_id) {} bool skip(const size_t &model_volume_id) const override { return model_volume_id == volume_id; } }; class AllowVolumes: public ISkip { std::vector allowed_id; public: AllowVolumes() = default; AllowVolumes(std::vector allowed_id) : allowed_id(allowed_id) {} void clear() { allowed_id.clear(); } bool skip(const size_t &model_volume_id) const override { if (allowed_id.size() == 0) { return false; } auto it = std::find(allowed_id.begin(), allowed_id.end(), model_volume_id); return it == allowed_id.end(); } }; /// /// Unproject on mesh and return closest hit to point in given direction /// /// Position in space /// Casted ray direction /// Define which caster will be skipped, null mean no skip /// Position on surface, normal direction in world coorinate /// + key, to know hitted instance and volume std::optional first_hit(const Vec3d &point, const Vec3d &direction, const ISkip *skip = nullptr) const; /// /// Unproject Ray(point direction) on mesh to find closest hit of surface in given direction /// NOTE: It inspect also oposit direction of ray !! /// /// Start point for ray /// Direction of ray, orientation doesn't matter, both are used /// Define which caster will be skipped, null mean no skip /// Position on surface, normal direction and transformation key, which define hitted object instance std::optional closest_hit(const Vec3d &point, const Vec3d &direction, const ISkip *skip = nullptr) const; /// /// Search of closest point /// /// Point /// Define which caster will be skipped, null mean no skip /// std::optional closest(const Vec3d &point, const ISkip *skip = nullptr) const; /// /// Getter on transformation from hitted volume to world /// /// Define transformation /// Transformation for key Transform3d get_transformation(const TrKey &tr_key) const; void clear(); }; class GLCanvas3D; /// /// Use scene Raycasters and prepare data for actualize RaycasterManager /// /// contain Scene raycasters /// Limit for scene casters /// Meshes RaycastManager::Meshes create_meshes(GLCanvas3D &canvas, const RaycastManager::AllowVolumes &condition); struct Camera; /// /// Unproject on mesh by Mesh raycasters /// /// Position of mouse on screen /// Projection params /// Define which caster will be skipped, null mean no skip /// Position on surface, normal direction in world coorinate /// + key, to know hitted instance and volume std::optional ray_from_camera(const RaycastManager &raycaster, const Vec2d &mouse_pos, const Camera &camera, const RaycastManager::ISkip *skip); /// /// Create condition to allowe only parts from volumes without one given /// /// List of allowed volumes included one which is dissalowed and non parts /// Disallowed volume /// Condition RaycastManager::AllowVolumes create_condition(const ModelVolumePtrs &volumes, const ObjectID &disallowed_volume_id); } // namespace Slic3r::GUI #endif // slic3r_RaycastManager_hpp_