1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "RenderView.h"
21 #include "Exceptions.h"
22 #include "PreferenceManager.h"
23 #include "Preferences.h"
24 #include "Renderer/Transformation.h"
25 #include "Renderer/VertexArray.h"
26 #include "Renderer/VertexSpec.h"
27 #include "View/GLContextManager.h"
28 #include "View/wxUtils.h"
29 
30 #include <wx/dcclient.h>
31 #include <wx/settings.h>
32 
33 #include <iostream>
34 
35 namespace TrenchBroom {
36     namespace View {
RenderView(wxWindow * parent,GLContextManager & contextManager,const GLAttribs & attribs)37         RenderView::RenderView(wxWindow* parent, GLContextManager& contextManager, const GLAttribs& attribs) :
38         wxGLCanvas(parent, wxID_ANY, &attribs.front(), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE),
39         m_glContext(contextManager.createContext(this)),
40         m_attribs(attribs),
41         m_initialized(false) {
42             const wxColour color = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
43             m_focusColor = fromWxColor(color);
44 
45             bindEvents();
46         }
47 
OnPaint(wxPaintEvent & event)48         void RenderView::OnPaint(wxPaintEvent& event) {
49             if (IsBeingDeleted()) return;
50 
51             if (m_glContext->SetCurrent(this)) {
52                 if (!m_initialized)
53                     initializeGL();
54 
55                 wxPaintDC paintDC(this);
56                 render();
57                 SwapBuffers();
58             }
59         }
60 
OnSize(wxSizeEvent & event)61         void RenderView::OnSize(wxSizeEvent& event) {
62             if (IsBeingDeleted()) return;
63 
64             updateViewport();
65             event.Skip();
66         }
67 
OnSetFocus(wxFocusEvent & event)68         void RenderView::OnSetFocus(wxFocusEvent& event) {
69             if (IsBeingDeleted()) return;
70 
71             Refresh();
72             event.Skip();
73         }
74 
OnKillFocus(wxFocusEvent & event)75         void RenderView::OnKillFocus(wxFocusEvent& event) {
76             if (IsBeingDeleted()) return;
77 
78             Refresh();
79             event.Skip();
80         }
81 
vertexVbo()82         Renderer::Vbo& RenderView::vertexVbo() {
83             return m_glContext->vertexVbo();
84         }
85 
indexVbo()86         Renderer::Vbo& RenderView::indexVbo() {
87             return m_glContext->indexVbo();
88         }
89 
fontManager()90         Renderer::FontManager& RenderView::fontManager() {
91             return m_glContext->fontManager();
92         }
93 
shaderManager()94         Renderer::ShaderManager& RenderView::shaderManager() {
95             return m_glContext->shaderManager();
96         }
97 
depthBits() const98         int RenderView::depthBits() const {
99             return m_attribs[3];
100         }
101 
multisample() const102         bool RenderView::multisample() const {
103             return m_attribs[4] != 0;
104         }
105 
bindEvents()106         void RenderView::bindEvents() {
107             Bind(wxEVT_PAINT, &RenderView::OnPaint, this);
108             Bind(wxEVT_SIZE, &RenderView::OnSize, this);
109             Bind(wxEVT_SET_FOCUS, &RenderView::OnSetFocus, this);
110             Bind(wxEVT_KILL_FOCUS, &RenderView::OnKillFocus, this);
111         }
112 
initializeGL()113         void RenderView::initializeGL() {
114             const bool firstInitialization = m_glContext->initialize();
115             doInitializeGL(firstInitialization);
116             m_initialized = true;
117         }
118 
updateViewport()119         void RenderView::updateViewport() {
120             const wxSize clientSize = GetClientSize();
121             doUpdateViewport(0, 0, clientSize.x, clientSize.y);
122         }
123 
render()124         void RenderView::render() {
125             clearBackground();
126             doRender();
127             renderFocusIndicator();
128         }
129 
clearBackground()130         void RenderView::clearBackground() {
131             PreferenceManager& prefs = PreferenceManager::instance();
132             const Color& backgroundColor = prefs.get(Preferences::BackgroundColor);
133 
134             glAssert(glClearColor(backgroundColor.r(), backgroundColor.g(), backgroundColor.b(), backgroundColor.a()));
135             glAssert(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
136         }
137 
renderFocusIndicator()138         void RenderView::renderFocusIndicator() {
139             if (!doShouldRenderFocusIndicator() || !HasFocus())
140                 return;
141 
142             const Color& outer = m_focusColor;
143             const Color& inner = m_focusColor;
144 
145             const wxSize clientSize = GetClientSize();
146             const float w = static_cast<float>(clientSize.x);
147             const float h = static_cast<float>(clientSize.y);
148             const float t = 1.0f;
149 
150             typedef Renderer::VertexSpecs::P3C4::Vertex Vertex;
151             Vertex::List vertices(16);
152 
153             // top
154             vertices[ 0] = Vertex(Vec3f(0.0f, 0.0f, 0.0f), outer);
155             vertices[ 1] = Vertex(Vec3f(w, 0.0f, 0.0f), outer);
156             vertices[ 2] = Vertex(Vec3f(w-t, t, 0.0f), inner);
157             vertices[ 3] = Vertex(Vec3f(t, t, 0.0f), inner);
158 
159             // right
160             vertices[ 4] = Vertex(Vec3f(w, 0.0f, 0.0f), outer);
161             vertices[ 5] = Vertex(Vec3f(w, h, 0.0f), outer);
162             vertices[ 6] = Vertex(Vec3f(w-t, h-t, 0.0f), inner);
163             vertices[ 7] = Vertex(Vec3f(w-t, t, 0.0f), inner);
164 
165             // bottom
166             vertices[ 8] = Vertex(Vec3f(w, h, 0.0f), outer);
167             vertices[ 9] = Vertex(Vec3f(0.0f, h, 0.0f), outer);
168             vertices[10] = Vertex(Vec3f(t, h-t, 0.0f), inner);
169             vertices[11] = Vertex(Vec3f(w-t, h-t, 0.0f), inner);
170 
171             // left
172             vertices[12] = Vertex(Vec3f(0.0f, h, 0.0f), outer);
173             vertices[13] = Vertex(Vec3f(0.0f, 0.0f, 0.0f), outer);
174             vertices[14] = Vertex(Vec3f(t, t, 0.0f), inner);
175             vertices[15] = Vertex(Vec3f(t, h-t, 0.0f), inner);
176 
177             glAssert(glViewport(0, 0, clientSize.x, clientSize.y));
178 
179             const Mat4x4f projection = orthoMatrix(-1.0f, 1.0f, 0.0f, 0.0f, w, h);
180             Renderer::Transformation transformation(projection, Mat4x4f::Identity);
181 
182             glAssert(glDisable(GL_DEPTH_TEST));
183             Renderer::VertexArray array = Renderer::VertexArray::swap(vertices);
184 
185             Renderer::ActivateVbo activate(vertexVbo());
186             array.prepare(vertexVbo());
187             array.render(GL_QUADS);
188             glAssert(glEnable(GL_DEPTH_TEST));
189         }
190 
doInitializeGL(const bool firstInitialization)191         void RenderView::doInitializeGL(const bool firstInitialization) {}
192 
doUpdateViewport(const int x,const int y,const int width,const int height)193         void RenderView::doUpdateViewport(const int x, const int y, const int width, const int height) {}
194     }
195 }
196