From: Mikko Rasa Date: Fri, 12 Aug 2016 20:31:47 +0000 (+0300) Subject: Restore user clip planes in a form compatible with modern OpenGL X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=9b685afdaac3952bab7a49410bdf7f6b3cf67c6f Restore user clip planes in a form compatible with modern OpenGL They work much the same as lights, with the ability to add uniforms to a ProgramData object. --- diff --git a/source/clipping.cpp b/source/clipping.cpp new file mode 100644 index 00000000..add7bba6 --- /dev/null +++ b/source/clipping.cpp @@ -0,0 +1,105 @@ +#include +#include "clipping.h" +#include "clipplane.h" +#include "clipunit.h" +#include "matrix.h" +#include "misc.h" + +using namespace std; + +namespace Msp { +namespace GL { + +bool Clipping::bound_with_legacy = false; + +void Clipping::attach(unsigned i, const ClipPlane &p) +{ + if(i>=ClipUnit::get_n_units()) + throw out_of_range("Clipping::attach"); + + if(i>=planes.size()) + planes.resize(i+1); + + planes[i] = &p; + if(current()==this) + { + if(bound_with_legacy) + p.bind_to(i); + else + glEnable(GL_CLIP_PLANE0+i); + } +} + +void Clipping::detach(unsigned i) +{ + if(i>=planes.size()) + return; + + planes[i] = 0; + if(current()==this) + { + if(bound_with_legacy) + ClipPlane::unbind_from(i); + else + disable(GL_CLIP_PLANE0+i); + } +} + +void Clipping::update_shader_data(ProgramData &shdata, const Matrix &view_matrix) const +{ + Matrix view_inverse = invert(view_matrix); + for(unsigned i=0; iupdate_shader_data(shdata, view_inverse, i); +} + +void Clipping::bind(bool legacy) const +{ + if(legacy) + static Require _req(MSP_legacy_features); + + const Clipping *old = current(); + if(!set_current(this)) + return; + + bound_with_legacy = legacy; + if(legacy) + { + for(unsigned i=0; ibind_to(i); + else + ClipPlane::unbind_from(i); + } + + if(old) + { + for(unsigned i=planes.size(); iplanes.size(); ++i) + ClipPlane::unbind_from(i); + } + } + else + { + for(unsigned i=0; iplanes.size(); ++i) + disable(GL_CLIP_PLANE0+i); + } + } +} + +void Clipping::unbind() +{ +} + +} // namespace GL +} // namespace Msp diff --git a/source/clipping.h b/source/clipping.h new file mode 100644 index 00000000..2a4330ba --- /dev/null +++ b/source/clipping.h @@ -0,0 +1,35 @@ +#ifndef MSP_GL_CLIPPING_H_ +#define MSP_GL_CLIPPING_H_ + +#include +#include "bindable.h" + +namespace Msp { +namespace GL { + +class ClipPlane; +class Matrix; +class ProgramData; + +class Clipping: public Bindable +{ +private: + std::vector planes; + + static bool bound_with_legacy; + +public: + void attach(unsigned, const ClipPlane &); + void detach(unsigned); + + void update_shader_data(ProgramData &, const Matrix &) const; + + void bind(bool legacy = true) const; + + static void unbind(); +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/clipplane.cpp b/source/clipplane.cpp new file mode 100644 index 00000000..04bd6acf --- /dev/null +++ b/source/clipplane.cpp @@ -0,0 +1,68 @@ +#include +#include "clipplane.h" +#include "clipunit.h" +#include "gl.h" +#include "matrix.h" +#include "misc.h" +#include "programdata.h" + +namespace Msp { +namespace GL { + +ClipPlane::ClipPlane(): + eq(0, 0, 0, 1) +{ } + +ClipPlane::ClipPlane(const Vector4 &e): + eq(e) +{ } + +ClipPlane::ClipPlane(const Vector3 &p, const Vector3 &d): + eq(compose(d, -dot(p, d))) +{ } + +void ClipPlane::update(unsigned index) const +{ + double deq[4]; + for(unsigned i=0; i<4; ++i) + deq[i] = eq[i]; + glClipPlane(GL_CLIP_PLANE0+index, deq); +} + +void ClipPlane::set_equation(const Vector4 &e) +{ + eq = e; + if(ClipUnit *unit = ClipUnit::find_unit(this)) + update(unit->get_index()); +} + +void ClipPlane::set_plane(const Vector3 &p, const Vector3 &d) +{ + Vector3 nd = normalize(d); + set_equation(compose(nd, -dot(p, nd))); +} + +void ClipPlane::update_shader_data(ProgramData &shdata, const Matrix &view_inverse, unsigned i) const +{ + shdata.uniform(format("clip_planes[%d].equation", i), eq*view_inverse); +} + +void ClipPlane::bind_to(unsigned i) const +{ + ClipUnit &unit = ClipUnit::get_unit(i); + if(unit.set_plane(this)) + { + enable(GL_CLIP_PLANE0+unit.get_index()); + update(unit.get_index()); + } +} + +void ClipPlane::unbind_from(unsigned i) +{ + ClipUnit &unit = ClipUnit::get_unit(i); + if(unit.set_plane(0)) + disable(GL_CLIP_PLANE0+unit.get_index()); +} + +} // namespace GL +} // namespace Msp diff --git a/source/clipplane.h b/source/clipplane.h new file mode 100644 index 00000000..cc3efd0f --- /dev/null +++ b/source/clipplane.h @@ -0,0 +1,37 @@ +#ifndef MSP_GL_CLIP_H_ +#define MSP_GL_CLIP_H_ + +#include "vector.h" + +namespace Msp { +namespace GL { + +class Matrix; +class ProgramData; + +class ClipPlane +{ +private: + Vector4 eq; + +public: + ClipPlane(); + ClipPlane(const Vector4 &); + ClipPlane(const Vector3 &, const Vector3 &); + +private: + void update(unsigned) const; +public: + void set_equation(const Vector4 &); + void set_plane(const Vector3 &, const Vector3 &); + void update_shader_data(ProgramData &, const Matrix &, unsigned) const; + + void bind_to(unsigned) const; + + static void unbind_from(unsigned); +}; + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/clipunit.cpp b/source/clipunit.cpp new file mode 100644 index 00000000..83080bd7 --- /dev/null +++ b/source/clipunit.cpp @@ -0,0 +1,56 @@ +#include +#include "clipunit.h" +#include "gl.h" +#include "misc.h" + +using namespace std; + +namespace Msp { +namespace GL { + +vector ClipUnit::units; + +ClipUnit::ClipUnit(): + index(0), + plane(0) +{ } + +bool ClipUnit::set_plane(const ClipPlane *p) +{ + bool result = (p!=plane); + plane = p; + return result; +} + +unsigned ClipUnit::get_n_units() +{ + static int count = get_i(GL_MAX_CLIP_PLANES); + return count; +} + +ClipUnit &ClipUnit::get_unit(unsigned i) +{ + if(i>=get_n_units()) + throw out_of_range("ClipUnit::get_unit"); + + if(units.size()<=i) + { + unsigned j = units.size(); + units.resize(i+1, ClipUnit()); + for(; j::iterator i=units.begin(); i!=units.end(); ++i) + if(i->plane==p) + return &*i; + return 0; +} + +} // namespace GL +} // namespace Msp diff --git a/source/clipunit.h b/source/clipunit.h new file mode 100644 index 00000000..b4af9670 --- /dev/null +++ b/source/clipunit.h @@ -0,0 +1,34 @@ +#ifndef MSP_GL_CLIPUNIT_H_ +#define MSP_GL_CLIPUNIT_H_ + +#include + +namespace Msp { +namespace GL { + +class ClipPlane; + +class ClipUnit +{ +private: + unsigned index; + const ClipPlane *plane; + + static std::vector units; + + ClipUnit(); + +public: + unsigned get_index() const { return index; } + bool set_plane(const ClipPlane *); + const ClipPlane *get_plane() const { return plane; } + + static unsigned get_n_units(); + static ClipUnit &get_unit(unsigned); + static ClipUnit *find_unit(const ClipPlane *); +}; + +} // namespace GL +} // namespace Msp + +#endif