]> git.localhorst.tv Git - blank.git/blob - src/graphics/mesh.cpp
avoid zero vertex draw calls
[blank.git] / src / graphics / mesh.cpp
1 #include "BlockMesh.hpp"
2 #include "EntityMesh.hpp"
3 #include "PrimitiveMesh.hpp"
4 #include "SkyBoxMesh.hpp"
5 #include "SpriteMesh.hpp"
6
7 #include "../geometry/primitive.hpp"
8
9 #include <algorithm>
10 #include <iostream>
11
12
13 namespace blank {
14
15 void EntityMesh::Update(const Buffer &buf) noexcept {
16 #ifndef NDEBUG
17         if (buf.tex_coords.size() < buf.vertices.size()) {
18                 std::cerr << "EntityMesh: not enough tex coords!" << std::endl;
19         }
20         if (buf.hsl_mods.size() < buf.vertices.size()) {
21                 std::cerr << "EntityMesh: not enough HSL modifiers!" << std::endl;
22         }
23         if (buf.rgb_mods.size() < buf.vertices.size()) {
24                 std::cerr << "EntityMesh: not enough RGB modifiers!" << std::endl;
25         }
26         if (buf.normals.size() < buf.vertices.size()) {
27                 std::cerr << "EntityMesh: not enough normals!" << std::endl;
28         }
29 #endif
30
31         vao.Bind();
32         vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
33         vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords);
34         vao.PushAttribute(ATTRIB_HSL, buf.hsl_mods, true);
35         vao.PushAttribute(ATTRIB_RGB, buf.rgb_mods, true);
36         vao.PushAttribute(ATTRIB_NORMAL, buf.normals);
37         vao.PushIndices(ATTRIB_INDEX, buf.indices);
38 }
39
40
41 void BlockMesh::Update(const Buffer &buf) noexcept {
42 #ifndef NDEBUG
43         if (buf.tex_coords.size() < buf.vertices.size()) {
44                 std::cerr << "BlockMesh: not enough tex coords!" << std::endl;
45         }
46         if (buf.hsl_mods.size() < buf.vertices.size()) {
47                 std::cerr << "BlockMesh: not enough HSL modifiers!" << std::endl;
48         }
49         if (buf.rgb_mods.size() < buf.vertices.size()) {
50                 std::cerr << "BlockMesh: not enough RGB modifiers!" << std::endl;
51         }
52         if (buf.lights.size() < buf.vertices.size()) {
53                 std::cerr << "BlockMesh: not enough lights!" << std::endl;
54         }
55 #endif
56
57         vao.Bind();
58         vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
59         vao.PushAttribute(ATTRIB_TEXCOORD, buf.tex_coords);
60         vao.PushAttribute(ATTRIB_HSL, buf.hsl_mods, true);
61         vao.PushAttribute(ATTRIB_RGB, buf.rgb_mods, true);
62         vao.PushAttribute(ATTRIB_LIGHT, buf.lights);
63         vao.PushIndices(ATTRIB_INDEX, buf.indices);
64 }
65
66
67 void PrimitiveMesh::Buffer::FillRect(
68         float w, float h,
69         const Color &color,
70         const glm::vec2 &pivot
71 ) {
72         Clear();
73         Reserve(4, 6);
74
75         vertices.emplace_back( -pivot.x,  -pivot.y, 0.0f);
76         vertices.emplace_back(w-pivot.x,  -pivot.y, 0.0f);
77         vertices.emplace_back( -pivot.x, h-pivot.y, 0.0f);
78         vertices.emplace_back(w-pivot.x, h-pivot.y, 0.0f);
79
80         colors.resize(4, color);
81
82         indices.assign({ 0, 2, 1, 1, 2, 3 });
83 }
84
85 void PrimitiveMesh::Buffer::OutlineBox(const AABB &box, const Color &color) {
86         Clear();
87         Reserve(8, 24);
88
89         vertices.emplace_back(box.min.x, box.min.y, box.min.z);
90         vertices.emplace_back(box.min.x, box.min.y, box.max.z);
91         vertices.emplace_back(box.min.x, box.max.y, box.min.z);
92         vertices.emplace_back(box.min.x, box.max.y, box.max.z);
93         vertices.emplace_back(box.max.x, box.min.y, box.min.z);
94         vertices.emplace_back(box.max.x, box.min.y, box.max.z);
95         vertices.emplace_back(box.max.x, box.max.y, box.min.z);
96         vertices.emplace_back(box.max.x, box.max.y, box.max.z);
97
98         colors.resize(8, color);
99
100         indices.assign({
101                 0, 1, 1, 3, 3, 2, 2, 0, // left
102                 4, 5, 5, 7, 7, 6, 6, 4, // right
103                 0, 4, 1, 5, 3, 7, 2, 6, // others
104         });
105 }
106
107
108 void PrimitiveMesh::Update(const Buffer &buf) noexcept {
109 #ifndef NDEBUG
110         if (buf.colors.size() < buf.vertices.size()) {
111                 std::cerr << "PrimitiveMesh: not enough colors!" << std::endl;
112         }
113 #endif
114
115         vao.Bind();
116         vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
117         vao.PushAttribute(ATTRIB_COLOR, buf.colors, true);
118         vao.PushIndices(ATTRIB_INDEX, buf.indices);
119 }
120
121
122 void PrimitiveMesh::DrawLines() const noexcept {
123         glEnable(GL_LINE_SMOOTH);
124         glLineWidth(2.0f);
125         vao.DrawLineElements();
126 }
127
128
129 void SkyBoxMesh::LoadUnitBox() {
130         Buffer buffer;
131         buffer.vertices = {
132                 {  1.0f,  1.0f,  1.0f },
133                 {  1.0f,  1.0f, -1.0f },
134                 {  1.0f, -1.0f,  1.0f },
135                 {  1.0f, -1.0f, -1.0f },
136                 { -1.0f,  1.0f,  1.0f },
137                 { -1.0f,  1.0f, -1.0f },
138                 { -1.0f, -1.0f,  1.0f },
139                 { -1.0f, -1.0f, -1.0f },
140         };
141         buffer.indices = {
142                 5, 7, 3,  3, 1, 5,
143                 6, 7, 5,  5, 4, 6,
144                 3, 2, 0,  0, 1, 3,
145                 6, 4, 0,  0, 2, 6,
146                 5, 1, 0,  0, 4, 5,
147                 7, 6, 3,  3, 6, 2,
148         };
149         Update(buffer);
150 }
151
152 void SkyBoxMesh::Update(const Buffer &buf) noexcept {
153         vao.Bind();
154         vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
155         vao.PushIndices(ATTRIB_INDEX, buf.indices);
156 }
157
158
159 void SpriteMesh::Buffer::LoadRect(
160         float w, float h,
161         const glm::vec2 &pivot,
162         const glm::vec2 &tex_begin,
163         const glm::vec2 &tex_end
164 ) {
165         Clear();
166         Reserve(4, 6);
167
168         vertices.emplace_back( -pivot.x,  -pivot.y, 0.0f);
169         vertices.emplace_back(w-pivot.x,  -pivot.y, 0.0f);
170         vertices.emplace_back( -pivot.x, h-pivot.y, 0.0f);
171         vertices.emplace_back(w-pivot.x, h-pivot.y, 0.0f);
172
173         coords.emplace_back(tex_begin.x, tex_begin.y);
174         coords.emplace_back(tex_end.x,   tex_begin.y);
175         coords.emplace_back(tex_begin.x, tex_end.y);
176         coords.emplace_back(tex_end.x,   tex_end.y);
177
178         indices.assign({ 0, 2, 1, 1, 2, 3 });
179 }
180
181
182 void SpriteMesh::Update(const Buffer &buf) noexcept {
183 #ifndef NDEBUG
184         if (buf.coords.size() < buf.vertices.size()) {
185                 std::cerr << "SpriteMesh: not enough coords!" << std::endl;
186         }
187 #endif
188
189         vao.Bind();
190         vao.PushAttribute(ATTRIB_VERTEX, buf.vertices);
191         vao.PushAttribute(ATTRIB_TEXCOORD, buf.coords);
192         vao.PushIndices(ATTRIB_INDEX, buf.indices);
193 }
194
195 }