// Copyright (c) 2022 GeometryFactory Sarl (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s): Guillaume Damiand // Mostafa Ashraf #ifndef CGAL_GRAPHICS_SCENE_H #define CGAL_GRAPHICS_SCENE_H // TODO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { //------------------------------------------------------------------------------ inline CGAL::IO::Color get_random_color(CGAL::Random& random) { CGAL::IO::Color res; do { res=CGAL::IO::Color(random.get_int(0,256), random.get_int(0,256), random.get_int(0,256)); } while(res.red()==255 && res.green()==255 && res.blue()==255); return res; } //------------------------------------------------------------------------------ // This class is responsible for dealing with available CGAL data structures and // handling buffers. class Graphics_scene { public: using BufferType=float; typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; typedef Local_kernel::Point_3 Local_point; typedef Local_kernel::Vector_3 Local_vector; Graphics_scene() : m_buffer_for_mono_points(&arrays[POS_MONO_POINTS], nullptr, &m_bounding_box, nullptr, nullptr, nullptr), m_buffer_for_colored_points(&arrays[POS_COLORED_POINTS], nullptr, &m_bounding_box, &arrays[COLOR_POINTS], nullptr, nullptr), m_buffer_for_mono_segments(&arrays[POS_MONO_SEGMENTS], nullptr, &m_bounding_box, nullptr, nullptr, nullptr), m_buffer_for_colored_segments(&arrays[POS_COLORED_SEGMENTS], nullptr, &m_bounding_box, &arrays[COLOR_SEGMENTS], nullptr, nullptr), m_buffer_for_mono_rays(&arrays[POS_MONO_RAYS], nullptr, &m_bounding_box, nullptr, nullptr), m_buffer_for_colored_rays(&arrays[POS_COLORED_RAYS], nullptr, &m_bounding_box, &arrays[COLOR_RAYS], nullptr, nullptr), m_buffer_for_mono_lines(&arrays[POS_MONO_RAYS], nullptr, &m_bounding_box, nullptr, nullptr), m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], nullptr, &m_bounding_box, &arrays[COLOR_LINES], nullptr, nullptr), m_buffer_for_mono_faces( &arrays[POS_MONO_FACES], nullptr, &m_bounding_box, nullptr, &arrays[FLAT_NORMAL_MONO_FACES], &arrays[SMOOTH_NORMAL_MONO_FACES]), m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES], nullptr, &m_bounding_box, &arrays[COLOR_FACES], &arrays[FLAT_NORMAL_COLORED_FACES], &arrays[SMOOTH_NORMAL_COLORED_FACES]) {} const Buffer_for_vao &get_buffer_for_mono_points() const { return m_buffer_for_mono_points; } const Buffer_for_vao &get_buffer_for_colored_points() const { return m_buffer_for_colored_points; } const Buffer_for_vao &get_buffer_for_mono_segments() const { return m_buffer_for_mono_segments; } const Buffer_for_vao &get_buffer_for_colored_segments() const { return m_buffer_for_colored_segments; } const Buffer_for_vao &get_buffer_for_mono_rays() const { return m_buffer_for_mono_rays; } const Buffer_for_vao &get_buffer_for_colored_rays() const { return m_buffer_for_colored_rays; } const Buffer_for_vao &get_buffer_for_mono_lines() const { return m_buffer_for_mono_lines; } const Buffer_for_vao &get_buffer_for_colored_lines() const { return m_buffer_for_colored_lines; } const Buffer_for_vao &get_buffer_for_mono_faces() const { return m_buffer_for_mono_faces; } const Buffer_for_vao &get_buffer_for_colored_faces() const { return m_buffer_for_colored_faces; } const CGAL::Bbox_3 &bounding_box() const { return m_bounding_box; } const std::vector &get_array_of_index(int index) const { assert(index(arrays[index].size()*sizeof(BufferType)); } unsigned int number_of_elements(int index) const { return static_cast(arrays[index].size()/3); } void initiate_bounding_box(const CGAL::Bbox_3& new_bounding_box) { m_bounding_box = new_bounding_box; } void update_bounding_box(const CGAL::Bbox_3 &box) { m_bounding_box+=box; } template void update_bounding_box_for_ray(const KPoint &p, const KVector &v) { Local_point lp = get_local_point(p); Local_vector lv = get_local_vector(v); update_bounding_box((lp + lv).bbox()); } template void update_bounding_box_for_line(const KPoint &p, const KVector &v, const KVector &pv) { Local_point lp = get_local_point(p); Local_vector lv = get_local_vector(v); Local_vector lpv = get_local_vector(pv); update_bounding_box(lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox()); } void reverse_all_normals() const { m_buffer_for_mono_faces.negate_normals(); m_buffer_for_colored_faces.negate_normals(); } template void add_point(const KPoint &p) { m_buffer_for_mono_points.add_point(p); } template void add_point(const KPoint &p, const CGAL::IO::Color &acolor) { m_buffer_for_colored_points.add_point(p, acolor); } template void add_segment(const KPoint &p1, const KPoint &p2) { m_buffer_for_mono_segments.add_segment(p1, p2); } template void add_segment(const KPoint &p1, const KPoint &p2, const CGAL::IO::Color &acolor) { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } template void add_ray(const KPoint &p, const KVector &v) { double bigNumber = 1e30; m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber)*v)); } template void add_ray(const KPoint &p, const KVector &v, const CGAL::IO::Color &acolor) { double bigNumber = 1e30; m_buffer_for_colored_rays.add_ray_segment(p, (p + (bigNumber)*v), acolor); } template void add_line(const KPoint &p, const KVector &v) { double bigNumber = 1e30; m_buffer_for_mono_lines.add_line_segment((p - (bigNumber)*v), (p + (bigNumber)*v)); } template void add_line(const KPoint &p, const KVector &v, const CGAL::IO::Color &acolor) { double bigNumber = 1e30; m_buffer_for_colored_lines.add_line_segment((p - (bigNumber)*v), (p + (bigNumber)*v), acolor); } template bool add_point_in_face(const KPoint &kp) { if (m_buffer_for_mono_faces.is_a_face_started()) { return m_buffer_for_mono_faces.add_point_in_face(kp); } else if (m_buffer_for_colored_faces.is_a_face_started()) { return m_buffer_for_colored_faces.add_point_in_face(kp); } return false; } template bool add_point_in_face(const KPoint &kp, const KVector &p_normal) { if (m_buffer_for_mono_faces.is_a_face_started()) { return m_buffer_for_mono_faces.add_point_in_face(kp, p_normal); } else if (m_buffer_for_colored_faces.is_a_face_started()) { return m_buffer_for_colored_faces.add_point_in_face(kp, p_normal); } return false; } bool a_face_started() const { return m_buffer_for_mono_faces.is_a_face_started() || m_buffer_for_colored_faces.is_a_face_started(); } void face_begin() { if (a_face_started()) { std::cerr << "You cannot start a new face before to finish the previous one." << std::endl; } else { m_buffer_for_mono_faces.face_begin(); } } void face_begin(const CGAL::IO::Color &acolor) { if (a_face_started()) { std::cerr << "You cannot start a new face before to finish the previous one." << std::endl; } else { m_buffer_for_colored_faces.face_begin(acolor); } } void face_end() { if (m_buffer_for_mono_faces.is_a_face_started()) { m_buffer_for_mono_faces.face_end(); } else if (m_buffer_for_colored_faces.is_a_face_started()) { m_buffer_for_colored_faces.face_end(); } } template void add_text(const KPoint &kp, const std::string &txt) { Local_point p = get_local_point(kp); m_texts.push_back(std::make_tuple(p, txt)); } template void add_text(const KPoint &kp, const char *txt) { add_text(kp, std::string(txt)); } bool empty() const { return (m_buffer_for_mono_points.is_empty() && m_buffer_for_colored_points.is_empty() && m_buffer_for_mono_segments.is_empty() && m_buffer_for_colored_segments.is_empty() && m_buffer_for_mono_rays.is_empty() && m_buffer_for_colored_rays.is_empty() && m_buffer_for_mono_lines.is_empty() && m_buffer_for_colored_lines.is_empty() && m_buffer_for_mono_faces.is_empty() && m_buffer_for_colored_faces.is_empty()); } bool has_zero_x() const { return m_buffer_for_mono_points.has_zero_x() && m_buffer_for_colored_points.has_zero_x() && m_buffer_for_mono_segments.has_zero_x() && m_buffer_for_colored_segments.has_zero_x() && m_buffer_for_mono_faces.has_zero_x() && m_buffer_for_colored_faces.has_zero_x() && m_buffer_for_mono_rays.has_zero_x() && m_buffer_for_colored_rays.has_zero_x() && m_buffer_for_mono_lines.has_zero_x() && m_buffer_for_colored_lines.has_zero_x(); } bool has_zero_y() const { return m_buffer_for_mono_points.has_zero_y() && m_buffer_for_colored_points.has_zero_y() && m_buffer_for_mono_segments.has_zero_y() && m_buffer_for_colored_segments.has_zero_y() && m_buffer_for_mono_faces.has_zero_y() && m_buffer_for_colored_faces.has_zero_y() && m_buffer_for_mono_rays.has_zero_y() && m_buffer_for_colored_rays.has_zero_y() && m_buffer_for_mono_lines.has_zero_y() && m_buffer_for_colored_lines.has_zero_y(); } bool has_zero_z() const { return m_buffer_for_mono_points.has_zero_z() && m_buffer_for_colored_points.has_zero_z() && m_buffer_for_mono_segments.has_zero_z() && m_buffer_for_colored_segments.has_zero_z() && m_buffer_for_mono_faces.has_zero_z() && m_buffer_for_colored_faces.has_zero_z() && m_buffer_for_mono_rays.has_zero_z() && m_buffer_for_colored_rays.has_zero_z() && m_buffer_for_mono_lines.has_zero_z() && m_buffer_for_colored_lines.has_zero_z(); } // Returns true if the data structure lies on a XY or XZ or YZ plane bool is_two_dimensional() const { return (!empty() && (has_zero_x() || has_zero_y() || has_zero_z())); } void clear() { m_buffer_for_mono_points.clear(); m_buffer_for_colored_points.clear(); m_buffer_for_mono_segments.clear(); m_buffer_for_colored_segments.clear(); m_buffer_for_mono_rays.clear(); m_buffer_for_colored_rays.clear(); m_buffer_for_mono_lines.clear(); m_buffer_for_colored_lines.clear(); m_buffer_for_mono_faces.clear(); m_buffer_for_colored_faces.clear(); m_texts.clear(); m_bounding_box=CGAL::Bbox_3(); } template static Local_point get_local_point(const KPoint &p) { return internal::Geom_utils::Kernel, Local_kernel>::get_local_point(p); } template static Local_vector get_local_vector(const KVector &v) { return internal::Geom_utils::Kernel, Local_kernel>::get_local_vector(v); } void m_texts_clear() { m_texts.clear(); } std::size_t m_texts_size() const { return m_texts.size(); } const std::vector>& get_m_texts() const { return m_texts; } public: // The following enum gives the indices of different elements of arrays // vectors. enum Buffers { BEGIN_POS = 0, POS_MONO_POINTS = BEGIN_POS, POS_COLORED_POINTS, POS_MONO_SEGMENTS, POS_COLORED_SEGMENTS, POS_MONO_RAYS, POS_COLORED_RAYS, POS_MONO_LINES, POS_COLORED_LINES, POS_MONO_FACES, POS_COLORED_FACES, END_POS, BEGIN_COLOR = END_POS, COLOR_POINTS = BEGIN_COLOR, COLOR_SEGMENTS, COLOR_RAYS, COLOR_LINES, COLOR_FACES, END_COLOR, BEGIN_NORMAL = END_COLOR, SMOOTH_NORMAL_MONO_FACES = BEGIN_NORMAL, FLAT_NORMAL_MONO_FACES, SMOOTH_NORMAL_COLORED_FACES, FLAT_NORMAL_COLORED_FACES, END_NORMAL, LAST_INDEX = END_NORMAL }; protected: Buffer_for_vao m_buffer_for_mono_points; Buffer_for_vao m_buffer_for_colored_points; Buffer_for_vao m_buffer_for_mono_segments; Buffer_for_vao m_buffer_for_colored_segments; Buffer_for_vao m_buffer_for_mono_rays; Buffer_for_vao m_buffer_for_colored_rays; Buffer_for_vao m_buffer_for_mono_lines; Buffer_for_vao m_buffer_for_colored_lines; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; std::vector> m_texts; std::vector arrays[LAST_INDEX]; CGAL::Bbox_3 m_bounding_box; }; } // namespace CGAL #endif // CGAL_GRAPHICS_SCENE_H