1 #pragma once 2 #include <glm/glm.hpp> 3 #include "common/common.hpp" 4 #include "canvas_mesh.hpp" 5 #include "canvas/appearance.hpp" 6 #include "util/uuid.hpp" 7 #include <mutex> 8 #include "cover_renderer.hpp" 9 #include "face_renderer.hpp" 10 #include "wall_renderer.hpp" 11 #include "background_renderer.hpp" 12 #include "point_renderer.hpp" 13 #include "import_step/import.hpp" 14 #include "point.hpp" 15 #include <sigc++/sigc++.h> 16 #include <variant> 17 18 namespace horizon { 19 20 class Canvas3DBase { 21 public: 22 Canvas3DBase(); 23 friend class CoverRenderer; 24 friend class WallRenderer; 25 friend class FaceRenderer; 26 friend class BackgroundRenderer; 27 friend class PointRenderer; 28 Color get_layer_color(int layer) const; 29 30 enum class Projection { PERSP, ORTHO }; 31 32 #define GET_SET_X(x_, t_, f_) \ 33 const auto &get_##x_() const \ 34 { \ 35 return x_; \ 36 } \ 37 void set_##x_(const t_ &c) \ 38 { \ 39 x_ = c; \ 40 redraw(); \ 41 f_ \ 42 } 43 44 #define GET_SET(x_, t_) GET_SET_X(x_, t_, ) 45 #define GET_SET_PICK(x_, t_) GET_SET_X(x_, t_, invalidate_pick();) 46 GET_SET(background_top_color,Color)47 GET_SET(background_top_color, Color) 48 GET_SET(background_bottom_color, Color) 49 GET_SET_PICK(show_solder_mask, bool) 50 GET_SET_PICK(show_silkscreen, bool) 51 GET_SET_PICK(show_substrate, bool) 52 GET_SET_PICK(show_models, bool) 53 GET_SET_PICK(show_dnp_models, bool) 54 GET_SET_PICK(show_solder_paste, bool) 55 GET_SET_PICK(show_copper, bool) 56 GET_SET_PICK(show_points, bool) 57 GET_SET(use_layer_colors, bool) 58 GET_SET(solder_mask_color, Color) 59 GET_SET(silkscreen_color, Color) 60 GET_SET(substrate_color, Color) 61 GET_SET_PICK(explode, float) 62 GET_SET_PICK(cam_distance, float) 63 GET_SET_PICK(cam_fov, float) 64 GET_SET_PICK(center, glm::vec2) 65 GET_SET_PICK(projection, Projection) 66 67 #undef GET_SET 68 #undef GET_SET_X 69 #undef GET_SET_PICK 70 71 const float &get_cam_elevation() const 72 { 73 return cam_elevation; 74 } 75 void set_cam_elevation(const float &ele); 76 get_cam_azimuth() const77 const float &get_cam_azimuth() const 78 { 79 return cam_azimuth; 80 } 81 void set_cam_azimuth(const float &az); 82 83 84 void view_all(); 85 void clear_3d_models(); 86 void set_point_transform(const glm::dmat4 &mat); 87 void set_points(const std::vector<Point3D> &points); 88 89 struct BBox { 90 float xl, yl, zl, xh, yh, zh; 91 }; 92 93 BBox get_model_bbox(const std::string &filename) const; 94 95 typedef sigc::signal<void> type_signal_view_changed; signal_view_changed()96 type_signal_view_changed signal_view_changed() 97 { 98 return s_signal_view_changed; 99 } 100 101 bool model_is_loaded(const std::string &filename); 102 103 protected: 104 CanvasMesh ca; 105 106 Appearance appearance; 107 108 Color background_top_color; 109 Color background_bottom_color; 110 bool show_solder_mask = true; 111 bool show_silkscreen = true; 112 bool show_substrate = true; 113 bool show_models = true; 114 bool show_dnp_models = false; 115 bool show_solder_paste = true; 116 bool use_layer_colors = false; 117 bool show_copper = true; 118 bool show_points = false; 119 Color solder_mask_color = {0, .5, 0}; 120 Color silkscreen_color = {1, 1, 1}; 121 Color substrate_color = {.2, .15, 0}; 122 float explode = 0; 123 float highlight_intensity = .5; 124 125 float cam_azimuth = 90; 126 float cam_elevation = 45; 127 float cam_distance = 20; 128 float cam_fov = 45; 129 glm::vec2 center; 130 131 Projection projection = Projection::PERSP; 132 133 134 int width = 100; 135 int height = 100; 136 137 CoverRenderer cover_renderer; 138 WallRenderer wall_renderer; 139 FaceRenderer face_renderer; 140 BackgroundRenderer background_renderer; 141 PointRenderer point_renderer; 142 143 void a_realize(); 144 void resize_buffers(); 145 void push(); 146 enum class RenderBackground { YES, NO }; 147 void render(RenderBackground mode = RenderBackground::YES); 148 virtual int a_get_scale_factor() const; redraw()149 virtual void redraw() 150 { 151 } 152 void invalidate_pick(); 153 void prepare(); 154 void prepare_packages(); 155 156 unsigned int num_samples = 1; 157 158 const class Board *brd = nullptr; 159 160 std::set<UUID> packages_highlight; 161 162 void load_3d_model(const std::string &filename, const std::string &filename_abs); 163 164 std::map<std::string, std::string> get_model_filenames(class IPool &pool); 165 166 std::mutex models_loading_mutex; 167 168 void update_max_package_height(); 169 170 void queue_pick(); 171 typedef sigc::signal<void> type_signal_pick_ready; signal_pick_ready()172 type_signal_pick_ready signal_pick_ready() 173 { 174 return s_signal_pick_ready; 175 } 176 std::variant<UUID, glm::dvec3> pick_package_or_point(unsigned int x, unsigned int y) const; 177 178 virtual STEPImporter::Faces import_step(const std::string &filename_rel, const std::string &filename_abs); 179 180 private: 181 class FaceVertex { 182 public: FaceVertex(float ix,float iy,float iz,float inx,float iny,float inz,uint8_t ir,uint8_t ig,uint8_t ib)183 FaceVertex(float ix, float iy, float iz, float inx, float iny, float inz, uint8_t ir, uint8_t ig, uint8_t ib) 184 : x(ix), y(iy), z(iz), nx(inx), ny(iny), nz(inz), r(ir), g(ig), b(ib), _pad(0) 185 { 186 } 187 float x; 188 float y; 189 float z; 190 float nx; 191 float ny; 192 float nz; 193 194 uint8_t r; 195 uint8_t g; 196 uint8_t b; 197 uint8_t _pad; 198 } __attribute__((packed)); 199 200 class ModelTransform { 201 public: ModelTransform(float ix,float iy,float a,bool flip,bool highlight)202 ModelTransform(float ix, float iy, float a, bool flip, bool highlight) 203 : x(ix), y(iy), angle(a), flags(flip | (highlight << 1)) 204 { 205 } 206 float x; 207 float y; 208 uint16_t angle; 209 uint16_t flags; 210 211 float model_x = 0; 212 float model_y = 0; 213 float model_z = 0; 214 uint16_t model_roll = 0; 215 uint16_t model_pitch = 0; 216 uint16_t model_yaw = 0; 217 } __attribute__((packed)); 218 219 float get_layer_offset(int layer) const; 220 float get_layer_thickness(int layer) const; 221 bool layer_is_visible(int layer) const; 222 223 std::pair<glm::vec3, glm::vec3> bbox; 224 225 GLuint renderbuffer; 226 GLuint fbo; 227 GLuint depthrenderbuffer; 228 GLuint pickrenderbuffer; 229 230 GLuint fbo_downsampled; 231 GLuint pickrenderbuffer_downsampled; 232 233 enum class PickState { QUEUED, CURRENT, INVALID }; 234 PickState pick_state = PickState::INVALID; 235 236 glm::mat4 viewmat; 237 glm::mat4 projmat; 238 glm::vec3 cam_normal; 239 240 float package_height_max = 0; 241 std::vector<FaceVertex> face_vertex_buffer; // vertices of all models, sequentially 242 std::vector<unsigned int> face_index_buffer; // indexes face_vertex_buffer to form triangles 243 244 class ModelInfo { 245 public: ModelInfo(size_t o,size_t n)246 ModelInfo(size_t o, size_t n) : face_index_offset(o), count(n) 247 { 248 } 249 const size_t face_index_offset; // offset in face_index_buffer 250 const size_t count; // number of items in face_index_buffer 251 bool pushed = false; 252 }; 253 std::map<std::string, ModelInfo> models; // key: filename 254 255 std::vector<ModelTransform> package_transforms; // position and rotation of 256 // all board packages, 257 // grouped by package 258 259 struct PackageInfo { 260 size_t offset; // in package_transforms 261 size_t n_packages; 262 unsigned int pick_base; 263 std::vector<UUID> pkg; 264 }; 265 266 std::map<std::pair<std::string, bool>, PackageInfo> package_infos; // key: first: model filename second: nopopulate 267 std::vector<uint16_t> pick_buf; 268 269 uint16_t point_pick_base = 0; 270 std::vector<Point3D> points; 271 glm::dmat4 point_mat; 272 size_t n_points = 0; 273 274 float get_magic_number() const; 275 276 type_signal_pick_ready s_signal_pick_ready; 277 type_signal_view_changed s_signal_view_changed; 278 }; 279 280 } // namespace horizon 281