From 635d00bc1a9ba43ef1224681a14d0710a098cf87 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 14 Jan 2011 13:00:05 +0000 Subject: [PATCH] Add WindingTest and support for it in Mesh and Renderer --- source/mesh.cpp | 24 +++++++++++++-- source/mesh.h | 5 ++++ source/renderer.cpp | 15 +++++++++- source/renderer.h | 3 ++ source/windingtest.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++ source/windingtest.h | 51 ++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 source/windingtest.cpp create mode 100644 source/windingtest.h diff --git a/source/mesh.cpp b/source/mesh.cpp index 05be2c37..67f9698c 100644 --- a/source/mesh.cpp +++ b/source/mesh.cpp @@ -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::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::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(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 diff --git a/source/mesh.h b/source/mesh.h index 1abbefd3..190d6f9b 100644 --- a/source/mesh.h +++ b/source/mesh.h @@ -11,6 +11,7 @@ Distributed under the LGPL #include #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 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 &get_batches() { return batches; } + void set_winding(const WindingTest *); + void draw() const; void draw(Renderer &) const; }; diff --git a/source/renderer.cpp b/source/renderer.cpp index bfd446e9..2680d902 100644 --- a/source/renderer.cpp +++ b/source/renderer.cpp @@ -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(); } diff --git a/source/renderer.h b/source/renderer.h index 8dbe779f..d8ace373 100644 --- a/source/renderer.h +++ b/source/renderer.h @@ -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 index 00000000..b54f7121 --- /dev/null +++ b/source/windingtest.cpp @@ -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 index 00000000..948f190b --- /dev/null +++ b/source/windingtest.h @@ -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 +#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 +{ +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 -- 2.45.2