NEW:add section view at assemble_view

Change-Id: I05b77e96e0d382b34ef80f622c71deca1eeb93b8
This commit is contained in:
liz.li 2022-09-27 15:56:08 +08:00 committed by Lane.Wei
parent c02dd81c61
commit 143c0f3750
7 changed files with 377 additions and 23 deletions

View file

@ -541,5 +541,172 @@ void SupportsClipper::render_cut() const
}
using namespace AssembleViewDataObjects;
AssembleViewDataPool::AssembleViewDataPool(GLCanvas3D* canvas)
: m_canvas(canvas)
{
using c = AssembleViewDataID;
m_data[c::ModelObjectsInfo].reset(new ModelObjectsInfo(this));
m_data[c::ModelObjectsClipper].reset(new ModelObjectsClipper(this));
}
void AssembleViewDataPool::update(AssembleViewDataID required)
{
assert(check_dependencies(required));
for (auto& [id, data] : m_data) {
if (int(required) & int(AssembleViewDataID(id)))
data->update();
else
if (data->is_valid())
data->release();
}
}
ModelObjectsInfo* AssembleViewDataPool::model_objects_info() const
{
ModelObjectsInfo* sel_info = dynamic_cast<ModelObjectsInfo*>(m_data.at(AssembleViewDataID::ModelObjectsInfo).get());
assert(sel_info);
return sel_info->is_valid() ? sel_info : nullptr;
}
ModelObjectsClipper* AssembleViewDataPool::model_objects_clipper() const
{
ModelObjectsClipper* oc = dynamic_cast<ModelObjectsClipper*>(m_data.at(AssembleViewDataID::ModelObjectsClipper).get());
// ObjectClipper is used from outside the gizmos to report current clipping plane.
// This function can be called when oc is nullptr.
return (oc && oc->is_valid()) ? oc : nullptr;
}
#ifndef NDEBUG
// Check the required resources one by one and return true if all
// dependencies are met.
bool AssembleViewDataPool::check_dependencies(AssembleViewDataID required) const
{
// This should iterate over currently required data. Each of them should
// be asked about its dependencies and it must check that all dependencies
// are also in required and before the current one.
for (auto& [id, data] : m_data) {
// in case we don't use this, the deps are irrelevant
if (!(int(required) & int(AssembleViewDataID(id))))
continue;
AssembleViewDataID deps = data->get_dependencies();
assert(int(deps) == (int(deps) & int(required)));
}
return true;
}
#endif // NDEBUG
void ModelObjectsInfo::on_update()
{
if (!get_pool()->get_canvas()->get_model()->objects.empty()) {
m_model_objects = get_pool()->get_canvas()->get_model()->objects;
}
}
void ModelObjectsInfo::on_release()
{
m_model_objects.clear();
}
//int ModelObjectsInfo::get_active_instance() const
//{
// const Selection& selection = get_pool()->get_canvas()->get_selection();
// return selection.get_instance_idx();
//}
void ModelObjectsClipper::on_update()
{
const ModelObjectPtrs model_objects = get_pool()->model_objects_info()->model_objects();
if (model_objects.empty())
return;
// which mesh should be cut?
std::vector<const TriangleMesh*> meshes;
if (meshes.empty())
for (auto mo : model_objects) {
for (const ModelVolume* mv : mo->volumes)
meshes.push_back(&mv->mesh());
}
if (meshes != m_old_meshes) {
m_clippers.clear();
for (const TriangleMesh* mesh : meshes) {
m_clippers.emplace_back(new MeshClipper);
m_clippers.back()->set_mesh(*mesh);
}
m_old_meshes = meshes;
m_active_inst_bb_radius = get_pool()->get_canvas()->volumes_bounding_box().radius();
}
}
void ModelObjectsClipper::on_release()
{
m_clippers.clear();
m_old_meshes.clear();
m_clp.reset();
m_clp_ratio = 0.;
}
void ModelObjectsClipper::render_cut() const
{
if (m_clp_ratio == 0.)
return;
const ModelObjectPtrs model_objects = get_pool()->model_objects_info()->model_objects();
size_t clipper_id = 0;
for (const ModelObject* mo : model_objects) {
Geometry::Transformation assemble_objects_trafo = mo->instances[0]->get_assemble_transformation();
auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly();
for (const ModelVolume* mv : mo->volumes) {
Geometry::Transformation vol_trafo = mv->get_transformation();
Geometry::Transformation trafo = assemble_objects_trafo * vol_trafo;
trafo.set_offset(trafo.get_offset() + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0) + offset_to_assembly * (GLVolume::explosion_ratio - 1.0));
auto& clipper = m_clippers[clipper_id];
clipper->set_plane(*m_clp);
clipper->set_transformation(trafo);
glsafe(::glPushMatrix());
// BBS
glsafe(::glColor3f(0.25f, 0.25f, 0.25f));
clipper->render_cut();
glsafe(::glPopMatrix());
++clipper_id;
}
}
}
void ModelObjectsClipper::set_position(double pos, bool keep_normal)
{
Vec3d camera_dir = wxGetApp().plater()->get_camera().get_dir_forward();
Vec3d normal = -camera_dir;
const Vec3d& center = get_pool()->get_canvas()->volumes_bounding_box().center();
float dist = normal.dot(center);
if (pos < 0.)
pos = m_clp_ratio;
m_clp_ratio = pos;
m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius * GLVolume::explosion_ratio) - m_clp_ratio * 2 * m_active_inst_bb_radius * GLVolume::explosion_ratio)));
get_pool()->get_canvas()->set_as_dirty();
}
} // namespace GUI
} // namespace Slic3r

View file

@ -39,6 +39,7 @@ enum class SLAGizmoEventType : unsigned char {
class CommonGizmosDataBase;
class AssembleViewDataBase;
namespace CommonGizmosDataObjects {
class SelectionInfo;
class InstancesHider;
@ -48,6 +49,11 @@ namespace CommonGizmosDataObjects {
class SupportsClipper;
}
namespace AssembleViewDataObjects {
class ModelObjectsInfo;
class ModelObjectsClipper;
}
// Some of the gizmos use the same data that need to be updated ocassionally.
// It is also desirable that the data are not recalculated when the gizmos
// are just switched, but on the other hand, they should be released when
@ -306,9 +312,120 @@ private:
} // namespace CommonGizmosDataObjects
enum class AssembleViewDataID {
None = 0,
ModelObjectsInfo = 1 << 0,
ModelObjectsClipper = 1 << 4,
};
class AssembleViewDataPool {
public:
AssembleViewDataPool(GLCanvas3D* canvas);
// Update all resources and release what is not used.
// Accepts a bitmask of currently required resources.
void update(AssembleViewDataID required);
// Getters for the data that need to be accessed from the gizmos directly.
AssembleViewDataObjects::ModelObjectsInfo* model_objects_info() const;
AssembleViewDataObjects::ModelObjectsClipper* model_objects_clipper() const;
GLCanvas3D* get_canvas() const { return m_canvas; }
private:
std::map<AssembleViewDataID, std::unique_ptr<AssembleViewDataBase>> m_data;
GLCanvas3D* m_canvas;
#ifndef NDEBUG
bool check_dependencies(AssembleViewDataID required) const;
#endif
};
// Base class for a wrapper object managing a single resource.
// Each of the enum values above (safe None) will have an object of this kind.
class AssembleViewDataBase {
public:
// Pass a backpointer to the pool, so the individual
// objects can communicate with one another.
explicit AssembleViewDataBase(AssembleViewDataPool* cgdp)
: m_common{ cgdp } {}
virtual ~AssembleViewDataBase() {}
// Update the resource.
void update() { on_update(); m_is_valid = true; }
// Release any data that are stored internally.
void release() { on_release(); m_is_valid = false; }
// Returns whether the resource is currently maintained.
bool is_valid() const { return m_is_valid; }
#ifndef NDEBUG
// Return a bitmask of all resources that this one relies on.
// The dependent resource must have higher ID than the one
// it depends on.
virtual AssembleViewDataID get_dependencies() const { return AssembleViewDataID::None; }
#endif // NDEBUG
protected:
virtual void on_release() = 0;
virtual void on_update() = 0;
AssembleViewDataPool* get_pool() const { return m_common; }
private:
bool m_is_valid = false;
AssembleViewDataPool* m_common = nullptr;
};
namespace AssembleViewDataObjects
{
class ModelObjectsInfo : public AssembleViewDataBase
{
public:
explicit ModelObjectsInfo(AssembleViewDataPool* cgdp)
: AssembleViewDataBase(cgdp) {}
ModelObjectPtrs model_objects() const { return m_model_objects; }
//int get_active_instance() const;
float get_sla_shift() const { return m_z_shift; }
protected:
void on_update() override;
void on_release() override;
private:
ModelObjectPtrs m_model_objects;
float m_z_shift = 0.f;
};
class ModelObjectsClipper : public AssembleViewDataBase
{
public:
explicit ModelObjectsClipper(AssembleViewDataPool* cgdp)
: AssembleViewDataBase(cgdp) {}
#ifndef NDEBUG
AssembleViewDataID get_dependencies() const override { return AssembleViewDataID::ModelObjectsInfo; }
#endif // NDEBUG
void set_position(double pos, bool keep_normal);
double get_position() const { return m_clp_ratio; }
ClippingPlane* get_clipping_plane() const { return m_clp.get(); }
void render_cut() const;
protected:
void on_update() override;
void on_release() override;
private:
std::vector<const TriangleMesh*> m_old_meshes;
std::vector<std::unique_ptr<MeshClipper>> m_clippers;
std::unique_ptr<ClippingPlane> m_clp;
double m_clp_ratio = 0.;
double m_active_inst_bb_radius = 0.;
};
}
} // namespace GUI
} // namespace Slic3r

View file

@ -155,6 +155,7 @@ bool GLGizmosManager::init()
//m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++));
m_common_gizmos_data.reset(new CommonGizmosDataPool(&m_parent));
m_assemble_view_data.reset(new AssembleViewDataPool(&m_parent));
for (auto& gizmo : m_gizmos) {
if (! gizmo->init()) {
@ -341,6 +342,16 @@ void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos)
curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos));
}
void GLGizmosManager::update_assemble_view_data()
{
if (m_assemble_view_data) {
if (m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView)
m_assemble_view_data->update(AssembleViewDataID(0));
else
m_assemble_view_data->update(AssembleViewDataID((int)AssembleViewDataID::ModelObjectsInfo | (int)AssembleViewDataID::ModelObjectsClipper));
}
}
void GLGizmosManager::update_data()
{
if (!m_enabled)
@ -359,10 +370,11 @@ void GLGizmosManager::update_data()
enable_grabber(Scale, i, enable_scale_xyz);
}
if (m_common_gizmos_data)
if (m_common_gizmos_data) {
m_common_gizmos_data->update(get_current()
? get_current()->get_requirements()
: CommonGizmosDataID(0));
? get_current()->get_requirements()
: CommonGizmosDataID(0));
}
if (selection.is_single_full_instance())
{
@ -587,6 +599,18 @@ ClippingPlane GLGizmosManager::get_clipping_plane() const
}
}
ClippingPlane GLGizmosManager::get_assemble_view_clipping_plane() const
{
if (!m_assemble_view_data
|| !m_assemble_view_data->model_objects_clipper()
|| m_assemble_view_data->model_objects_clipper()->get_position() == 0.)
return ClippingPlane::ClipsNothing();
else {
const ClippingPlane& clp = *m_assemble_view_data->model_objects_clipper()->get_clipping_plane();
return ClippingPlane(-clp.get_normal(), clp.get_data()[3]);
}
}
bool GLGizmosManager::wants_reslice_supports_on_undo() const
{
return (m_current == SlaSupports
@ -614,6 +638,12 @@ void GLGizmosManager::render_painter_gizmo() const
gizmo->render_painter_gizmo();
}
void GLGizmosManager::render_painter_assemble_view() const
{
if (m_assemble_view_data)
m_assemble_view_data->model_objects_clipper()->render_cut();
}
void GLGizmosManager::render_current_gizmo_for_picking_pass() const
{
if (! m_enabled || m_current == Undefined)

View file

@ -146,6 +146,7 @@ private:
std::map<int, void*> icon_list;
public:
std::unique_ptr<AssembleViewDataPool> m_assemble_view_data;
enum MENU_ICON_NAME {
IC_TOOLBAR_RESET = 0,
IC_TOOLBAR_RESET_HOVER,
@ -222,6 +223,7 @@ public:
void update(const Linef3& mouse_ray, const Point& mouse_pos);
void update_data();
void update_assemble_view_data();
EType get_current_type() const { return m_current; }
GLGizmoBase* get_current() const;
@ -265,6 +267,7 @@ public:
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
ClippingPlane get_clipping_plane() const;
ClippingPlane get_assemble_view_clipping_plane() const;
bool wants_reslice_supports_on_undo() const;
bool is_in_editing_mode(bool error_notification = false) const;
@ -273,6 +276,7 @@ public:
void render_current_gizmo() const;
void render_current_gizmo_for_picking_pass() const;
void render_painter_gizmo() const;
void render_painter_assemble_view() const;
void render_overlay() const;