]> git.tdb.fi Git - libs/gl.git/commitdiff
Add WindingTest and support for it in Mesh and Renderer
authorMikko Rasa <tdb@tdb.fi>
Fri, 14 Jan 2011 13:00:05 +0000 (13:00 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 14 Jan 2011 13:00:05 +0000 (13:00 +0000)
source/mesh.cpp
source/mesh.h
source/renderer.cpp
source/renderer.h
source/windingtest.cpp [new file with mode: 0644]
source/windingtest.h [new file with mode: 0644]

index 05be2c3745b8562b32f9c9b5a69e722fb4af5058..67f9698cfa36468d5fb6955f49b5ce5774b95e0f 100644 (file)
@@ -18,13 +18,15 @@ namespace GL {
 Mesh::Mesh():
        vertices(VERTEX3),
        ibuf(0),
-       defer_ibuf(true)
+       defer_ibuf(true),
+       winding(0)
 { }
 
 Mesh::Mesh(const VertexFormat &f):
        vertices(f),
        ibuf(0),
-       defer_ibuf(true)
+       defer_ibuf(true),
+       winding(0)
 { }
 
 Mesh::~Mesh()
@@ -94,12 +96,18 @@ void Mesh::add_batch(const Batch &b)
        }
 }
 
+void Mesh::set_winding(const WindingTest *w)
+{
+       winding = w;
+}
+
 void Mesh::draw() const
 {
        vertices.apply();
 
        if(ibuf)
                ibuf->bind_to(ELEMENT_ARRAY_BUFFER);
+       Bind bind_winding(winding);
 
        for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
                i->draw();
@@ -112,6 +120,7 @@ void Mesh::draw(Renderer &renderer) const
 {
        renderer.set_vertex_array(&vertices);
        renderer.set_element_buffer(ibuf);
+       renderer.set_winding_test(winding);
 
        for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
                renderer.draw(*i);
@@ -121,8 +130,9 @@ void Mesh::draw(Renderer &renderer) const
 Mesh::Loader::Loader(Mesh &m):
        DataFile::ObjectLoader<Mesh>(m)
 {
-       add("vertices", &Loader::vertices);
        add("batch",    &Loader::batch);
+       add("vertices", &Loader::vertices);
+       add("winding",  &Loader::winding);
 }
 
 void Mesh::Loader::vertices(VertexFormat f)
@@ -138,5 +148,13 @@ void Mesh::Loader::batch(PrimitiveType p)
        obj.add_batch(btc);
 }
 
+void Mesh::Loader::winding(FaceWinding w)
+{
+       if(w==CLOCKWISE)
+               obj.winding = &WindingTest::clockwise();
+       else if(w==COUNTERCLOCKWISE)
+               obj.winding = &WindingTest::counterclockwise();
+}
+
 } // namespace GL
 } // namespace Msp
index 1abbefd39746270d6892d83b2fff3f840e22c6de..190d6f9bce80f7ad74af3b7dc3941f9e69fbfcc2 100644 (file)
@@ -11,6 +11,7 @@ Distributed under the LGPL
 #include <msp/datafile/objectloader.h>
 #include "batch.h"
 #include "vertexarray.h"
+#include "windingtest.h"
 
 namespace Msp {
 namespace GL {
@@ -30,6 +31,7 @@ public:
        private:
                void vertices(VertexFormat);
                void batch(PrimitiveType);
+               void winding(FaceWinding);
        };
 
 private:
@@ -37,6 +39,7 @@ private:
        std::list<Batch> batches;
        Buffer *ibuf;
        bool defer_ibuf;
+       const WindingTest *winding;
 
 public:
        Mesh();
@@ -53,6 +56,8 @@ public:
        void add_batch(const Batch &b);
        const std::list<Batch> &get_batches() { return batches; }
 
+       void set_winding(const WindingTest *);
+
        void draw() const;
        void draw(Renderer &) const;
 };
index bfd446e9f42ccc30aa47306d26f6d535fe1b4ea9..2680d9022e9edcfe128cffec1ba246397902cd72 100644 (file)
@@ -16,6 +16,7 @@ Distributed under the LGPL
 #include "texture.h"
 #include "texturing.h"
 #include "vertexarray.h"
+#include "windingtest.h"
 
 using namespace std;
 
@@ -30,7 +31,8 @@ Renderer::Renderer(const Camera *c):
        state(&state_stack.back()),
        vertex_array(0),
        vertex_array_changed(false),
-       element_buffer(0)
+       element_buffer(0),
+       winding_test(0)
 {
        MatrixStack::modelview().push();
        if(camera)
@@ -101,6 +103,11 @@ void Renderer::set_element_buffer(const Buffer *b)
        element_buffer = b;
 }
 
+void Renderer::set_winding_test(const WindingTest *w)
+{
+       winding_test = w;
+}
+
 void Renderer::push_state()
 {
        state_stack.push_back(state_stack.back());
@@ -123,6 +130,7 @@ void Renderer::escape()
 {
        apply_state();
        Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
+       WindingTest::unbind();
 }
 
 void Renderer::draw(const Batch &batch)
@@ -141,6 +149,11 @@ void Renderer::draw(const Batch &batch)
        else
                Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
 
+       if(winding_test)
+               winding_test->bind();
+       else
+               WindingTest::unbind();
+
        batch.draw();
 }
 
index 8dbe779f32b78f6a8e1bf108c084ad7a4f2afba7..d8ace373805e9b85f905033d01a449709af11cf9 100644 (file)
@@ -23,6 +23,7 @@ class ProgramData;
 class Texture;
 class Texturing;
 class VertexArray;
+class WindingTest;
 
 /**
 A class for supervising the rendering process.  While many Renderables (in
@@ -75,6 +76,7 @@ private:
        const VertexArray *vertex_array;
        bool vertex_array_changed;
        const Buffer *element_buffer;
+       const WindingTest *winding_test;
 
 public:
        Renderer(const Camera *);
@@ -91,6 +93,7 @@ public:
        void add_shader_data(const ProgramData *);
        void set_vertex_array(const VertexArray *);
        void set_element_buffer(const Buffer *);
+       void set_winding_test(const WindingTest *);
 
        void push_state();
        void pop_state();
diff --git a/source/windingtest.cpp b/source/windingtest.cpp
new file mode 100644 (file)
index 0000000..b54f712
--- /dev/null
@@ -0,0 +1,66 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "windingtest.h"
+
+namespace Msp {
+namespace GL {
+
+void operator>>(const LexicalConverter &conv, FaceWinding &winding)
+{
+       if(conv.get()=="CLOCKWISE")
+               winding = CLOCKWISE;
+       else if(conv.get()=="COUNTERCLOCKWISE")
+               winding = COUNTERCLOCKWISE;
+       else
+               throw InvalidParameterValue("Invalid FaceWinding");
+}
+
+WindingTest::WindingTest():
+       test(false),
+       winding(COUNTERCLOCKWISE)
+{ }
+
+WindingTest::WindingTest(FaceWinding w):
+       test(true),
+       winding(w)
+{ }
+
+void WindingTest::bind() const
+{
+       if(set_current(this))
+       {
+               if(test)
+               {
+                       glEnable(GL_CULL_FACE);
+                       glFrontFace(winding);
+               }
+               else
+                       glDisable(GL_CULL_FACE);
+       }
+}
+
+void WindingTest::unbind()
+{
+       if(set_current(0))
+               glDisable(GL_CULL_FACE);
+}
+
+WindingTest &WindingTest::clockwise()
+{
+       static WindingTest test(CLOCKWISE);
+       return test;
+}
+
+WindingTest &WindingTest::counterclockwise()
+{
+       static WindingTest test(COUNTERCLOCKWISE);
+       return test;
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/windingtest.h b/source/windingtest.h
new file mode 100644 (file)
index 0000000..948f190
--- /dev/null
@@ -0,0 +1,51 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2011  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef WINDINGTEST_H_
+#define WINDINGTEST_H_
+
+#include <msp/strings/lexicalcast.h>
+#include "bindable.h"
+#include "gl.h"
+
+namespace Msp {
+namespace GL {
+
+enum FaceWinding
+{
+       CLOCKWISE = GL_CW,
+       COUNTERCLOCKWISE = GL_CCW
+};
+
+void operator>>(const LexicalConverter &, FaceWinding &);
+
+/**
+Tests the winding of polygons.  If the order of vertices on screen does not
+match the winding, the polygon is not rendered.
+*/
+class WindingTest: public Bindable<WindingTest>
+{
+private:
+       bool test;
+       FaceWinding winding;
+
+public:
+       WindingTest();
+       WindingTest(FaceWinding);
+
+       void bind() const;
+
+       static void unbind();
+
+       static WindingTest &clockwise();
+       static WindingTest &counterclockwise();
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif