00001 #ifndef MODULES_ADVANCED_OPENGL_PAINTERS_ATTIC_VBO_H
00002 #define MODULES_ADVANCED_OPENGL_PAINTERS_ATTIC_VBO_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00027 #include <list>
00028 #include <map>
00029 #include <set>
00030
00031 #include <k3dsdk/gl.h>
00032 #include <k3dsdk/imesh_painter_gl.h>
00033 #include <k3dsdk/iproperty.h>
00034 #include <k3dsdk/mesh.h>
00035 #include <k3dsdk/property.h>
00036 #include <k3dsdk/subdivision_surface/catmull_clark.h>
00037
00038 #include "cached_triangulation.h"
00039 #include "painter_cache.h"
00040 #include "sds_cache.h"
00041 #include "selection_cache.h"
00042
00043 #include <boost/ptr_container/ptr_map.hpp>
00044
00045 #include <stdexcept>
00046
00047 namespace module
00048 {
00049
00050 namespace opengl
00051 {
00052
00053 namespace painters
00054 {
00055
00056 typedef std::map<size_t, size_t> indexmap_t;
00057 typedef std::multimap<size_t, size_t> indexmultimap_t;
00058 typedef std::list<size_t> indexlist_t;
00059
00061 class vbo_exception : public std::runtime_error
00062 {
00063 typedef std::runtime_error base;
00064 public:
00065 vbo_exception(const std::string& Message) : base("VBO error: " + Message) {}
00066 };
00067
00069 class vbo
00070 {
00071 public:
00072 vbo();
00073 ~vbo();
00075 operator GLuint() const;
00076 private:
00077 vbo(const vbo&);
00078 vbo& operator=(const vbo&);
00079
00080 GLuint m_name;
00081 };
00082
00083 typedef boost::ptr_map<const k3d::mesh::primitive*, vbo> vbos_t;
00084
00086 class point_vbo : public scheduler
00087 {
00088 public:
00089 point_vbo(const k3d::mesh* const Mesh) : m_vbo(0) {}
00091 void bind();
00092 protected:
00094 void on_schedule(k3d::inode* Painter);
00095 void on_schedule(k3d::hint::mesh_geometry_changed* Hint, k3d::inode* Painter);
00096
00098 virtual void on_execute(const k3d::mesh& Mesh, k3d::inode* Painter);
00099 private:
00101 vbo* m_vbo;
00102
00104 k3d::mesh::indices_t m_indices;
00105 };
00106
00108 class edge_vbo : public scheduler
00109 {
00110 public:
00111 edge_vbo(const k3d::mesh* const Mesh) {}
00113 void bind(const k3d::mesh::primitive* Primitive);
00114 protected:
00115 void on_schedule(k3d::inode* Painter);
00117 virtual void on_execute(const k3d::mesh& Mesh, k3d::inode* Painter);
00118 private:
00120 vbos_t m_vbos;
00121 };
00122
00124 class triangle_vbo : public scheduler
00125 {
00126 public:
00127 triangle_vbo(const k3d::mesh* const Mesh) : m_point_vbo(0), m_index_vbo(0), m_normal_vbo(0), m_mesh(Mesh) {}
00128 ~triangle_vbo()
00129 {
00130 delete m_point_vbo;
00131 delete m_normal_vbo;
00132 delete m_index_vbo;
00133 }
00134
00136 void bind();
00137
00139 void draw_range(k3d::uint_t Start, k3d::uint_t End, k3d::inode* Painter);
00140 protected:
00141 void on_schedule(k3d::inode* Painter);
00142 void on_schedule(k3d::hint::mesh_geometry_changed* Hint, k3d::inode* Painter);
00143 void on_execute(const k3d::mesh& Mesh, k3d::inode* Painter);
00144 private:
00145 vbo* m_point_vbo;
00146 vbo* m_index_vbo;
00147 vbo* m_normal_vbo;
00148 k3d::mesh::indices_t m_indices;
00149
00150 k3d::mesh::indices_t m_corner_to_face;
00151 const k3d::mesh* const m_mesh;
00152 };
00153
00155 template<class component_t> class sds_vbo : public scheduler
00156 {
00157 public:
00158 sds_vbo(const k3d::mesh* const Mesh) : m_mesh(Mesh) {}
00159
00160 ~sds_vbo()
00161 {
00162 for (typename connections_t::iterator connection = m_changed_connections.begin(); connection != m_changed_connections.end(); ++connection)
00163 {
00164 connection->second.disconnect();
00165 m_deleted_connections[connection->first].disconnect();
00166 }
00167 m_changed_connections.clear();
00168 m_deleted_connections.clear();
00169 }
00170
00172 void bind(k3d::uint_t Level, k3d::inode* Painter, const k3d::mesh::primitive* Primitive)
00173 {
00174 cache(Level, Painter, Primitive).bind();
00175 }
00176
00178 component_t& cache(k3d::uint_t Level, k3d::inode* Painter, const k3d::mesh::primitive* Primitive)
00179 {
00180 caches_per_level_t& caches = m_caches[Primitive];
00181 std::pair<typename caches_per_level_t::iterator, bool> result = caches.insert(std::make_pair(Level, component_t()));
00182 if (result.second)
00183 result.first->second.update(Primitive, Level, get_data<sds_cache>(m_mesh, Painter));
00184 return caches[Level];
00185 }
00186
00187 protected:
00188
00189 void on_execute(const k3d::mesh& Mesh, k3d::inode* Painter)
00190 {
00191 return_if_fail(Painter);
00192 k3d::int32_t level = k3d::property::pipeline_value<k3d::int32_t>(*Painter, "levels");
00193 sds_cache& cache = get_data<sds_cache>(&Mesh, Painter);
00194 for(k3d::mesh::primitives_t::const_iterator primitive = Mesh.primitives.begin(); primitive != Mesh.primitives.end(); ++primitive)
00195 {
00196 boost::scoped_ptr<k3d::polyhedron::const_primitive> polyhedron(k3d::polyhedron::validate(Mesh, **primitive));
00197 if(!polyhedron.get() || !k3d::polyhedron::is_sds(*polyhedron))
00198 continue;
00199 caches_per_level_t& caches = m_caches[primitive->get()];
00200 caches.insert(std::make_pair(level, component_t())).first->second.update(primitive->get(), level, cache);
00201 }
00202 }
00203
00204 void on_schedule(k3d::inode* Painter)
00205 {
00206 clear();
00207 register_painter(Painter);
00208 schedule_data<sds_cache>(m_mesh, 0, Painter);
00209 }
00210 void on_schedule(k3d::hint::mesh_geometry_changed* Hint, k3d::inode* Painter)
00211 {
00212 register_painter(Painter);
00213 schedule_data<sds_cache>(m_mesh, Hint, Painter);
00214 }
00215 void on_schedule(k3d::hint::selection_changed* Hint, k3d::inode* Painter)
00216 {
00217 register_painter(Painter);
00218 schedule_data<sds_cache>(m_mesh, Hint, Painter);
00219 }
00220 private:
00221 void clear(k3d::ihint* Hint = 0)
00222 {
00223 m_caches.clear();
00224 }
00225
00226 void register_painter(k3d::inode* Painter)
00227 {
00228 k3d::iproperty* property = k3d::property::get(*Painter, "levels");
00229 if (property)
00230 {
00231 if (m_changed_connections.find(Painter) == m_changed_connections.end())
00232 m_changed_connections[Painter] = property->property_changed_signal().connect(sigc::mem_fun(*this, &sds_vbo::clear));
00233 if (m_deleted_connections.find(Painter) == m_deleted_connections.end())
00234 m_deleted_connections[Painter] = Painter->deleted_signal().connect(sigc::bind(sigc::mem_fun(*this, &sds_vbo::remove_painter), Painter));
00235 }
00236 else
00237 {
00238 k3d::log() << error << "sds_cache: failed to register property \"levels\"" << std::endl;
00239 }
00240 }
00241
00242 void remove_painter(k3d::inode* Painter)
00243 {
00244 m_changed_connections[Painter].disconnect();
00245 m_deleted_connections[Painter].disconnect();
00246 m_changed_connections.erase(Painter);
00247 m_deleted_connections.erase(Painter);
00248 clear();
00249 }
00250
00251
00252 typedef std::map<k3d::inode*, sigc::connection> connections_t;
00253 connections_t m_changed_connections;
00254 connections_t m_deleted_connections;
00255 typedef std::map<k3d::uint_t, component_t> caches_per_level_t;
00256 typedef std::map<const k3d::mesh::primitive*, caches_per_level_t> caches_t;
00257 caches_t m_caches;
00258 const k3d::mesh* const m_mesh;
00259 };
00260
00262 class sds_face_vbo
00263 {
00264 public:
00265 sds_face_vbo() : m_point_vbo(0), m_index_vbo(0), m_normal_vbo(0) {}
00266 ~sds_face_vbo()
00267 {
00268 delete m_point_vbo;
00269 delete m_normal_vbo;
00270 delete m_index_vbo;
00271 }
00272
00274 void update(const k3d::mesh::primitive* Primitive, const k3d::uint_t Level, sds_cache& Cache);
00275
00277 void bind();
00278
00280 k3d::mesh::indices_t face_starts;
00281
00283 k3d::uint_t index_size;
00284
00286 k3d::mesh::bools_t boundary_faces;
00287
00288 private:
00289 vbo* m_point_vbo;
00290 vbo* m_index_vbo;
00291 vbo* m_normal_vbo;
00292 k3d::mesh::indices_t m_companions;
00293 k3d::mesh::bools_t m_boundary_edges;
00294 };
00295
00297 class sds_edge_vbo
00298 {
00299 public:
00300 sds_edge_vbo() : m_point_vbo(0) {}
00301 ~sds_edge_vbo()
00302 {
00303 delete m_point_vbo;
00304 }
00305
00307 void update(const k3d::mesh::primitive* Primitive, const k3d::uint_t Level, sds_cache& Cache);
00308
00310 void bind();
00311
00313 k3d::mesh::indices_t edge_starts;
00314
00316 k3d::uint_t index_size;
00317
00318 private:
00319 vbo* m_point_vbo;
00320 };
00321
00323 class sds_point_vbo
00324 {
00325 public:
00326 sds_point_vbo() : m_point_vbo(0) {}
00327 ~sds_point_vbo()
00328 {
00329 delete m_point_vbo;
00330 }
00331
00333 void update(const k3d::mesh::primitive* Primitive, const k3d::uint_t Level, sds_cache& Cache);
00334
00336 void bind();
00337
00339 k3d::uint_t index_size;
00340
00341 private:
00342 vbo* m_point_vbo;
00343 };
00344
00346
00348
00350 void clean_vbo_state();
00351
00352 }
00353
00354 }
00355
00356 }
00357
00358 #endif // !MODULES_ADVANCED_OPENGL_PAINTERS_ATTIC_VBO_H