]> git.tdb.fi Git - libs/gl.git/commitdiff
Restore user clip planes in a form compatible with modern OpenGL
authorMikko Rasa <tdb@tdb.fi>
Fri, 12 Aug 2016 20:31:47 +0000 (23:31 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 12 Aug 2016 20:38:02 +0000 (23:38 +0300)
They work much the same as lights, with the ability to add uniforms to a
ProgramData object.

source/clipping.cpp [new file with mode: 0644]
source/clipping.h [new file with mode: 0644]
source/clipplane.cpp [new file with mode: 0644]
source/clipplane.h [new file with mode: 0644]
source/clipunit.cpp [new file with mode: 0644]
source/clipunit.h [new file with mode: 0644]

diff --git a/source/clipping.cpp b/source/clipping.cpp
new file mode 100644 (file)
index 0000000..add7bba
--- /dev/null
@@ -0,0 +1,105 @@
+#include <msp/gl/extensions/msp_legacy_features.h>
+#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; i<planes.size(); ++i)
+               if(planes[i])
+                       planes[i]->update_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; i<planes.size(); ++i)
+               {
+                       if(planes[i])
+                               planes[i]->bind_to(i);
+                       else
+                               ClipPlane::unbind_from(i);
+               }
+
+               if(old)
+               {
+                       for(unsigned i=planes.size(); i<old->planes.size(); ++i)
+                               ClipPlane::unbind_from(i);
+               }
+       }
+       else
+       {
+               for(unsigned i=0; i<planes.size(); ++i)
+               {
+                       if(planes[i])
+                               enable(GL_CLIP_PLANE0+i);
+                       else
+                               disable(GL_CLIP_PLANE0+i);
+               }
+
+               if(old)
+               {
+                       for(unsigned i=planes.size(); i<old->planes.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 (file)
index 0000000..2a4330b
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef MSP_GL_CLIPPING_H_
+#define MSP_GL_CLIPPING_H_
+
+#include <vector>
+#include "bindable.h"
+
+namespace Msp {
+namespace GL {
+
+class ClipPlane;
+class Matrix;
+class ProgramData;
+
+class Clipping: public Bindable<Clipping>
+{
+private:
+       std::vector<const ClipPlane *> 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 (file)
index 0000000..04bd6ac
--- /dev/null
@@ -0,0 +1,68 @@
+#include <msp/strings/format.h>
+#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 (file)
index 0000000..cc3efd0
--- /dev/null
@@ -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 (file)
index 0000000..83080bd
--- /dev/null
@@ -0,0 +1,56 @@
+#include <stdexcept>
+#include "clipunit.h"
+#include "gl.h"
+#include "misc.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+vector<ClipUnit> 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<units.size(); ++j)
+                       units[j].index = j;
+       }
+
+       return units[i];
+}
+
+ClipUnit *ClipUnit::find_unit(const ClipPlane *p)
+{
+       for(vector<ClipUnit>::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 (file)
index 0000000..b4af967
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef MSP_GL_CLIPUNIT_H_
+#define MSP_GL_CLIPUNIT_H_
+
+#include <vector>
+
+namespace Msp {
+namespace GL {
+
+class ClipPlane;
+
+class ClipUnit
+{
+private:
+       unsigned index;
+       const ClipPlane *plane;
+
+       static std::vector<ClipUnit> 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