]> git.localhorst.tv Git - blobs.git/blob - src/world/world.cpp
simple planet render
[blobs.git] / src / world / world.cpp
1 #include "Body.hpp"
2 #include "Planet.hpp"
3 #include "Sun.hpp"
4 #include "Tile.hpp"
5
6 #include "../app/Assets.hpp"
7 #include "../graphics/Viewport.hpp"
8
9 #include <algorithm>
10
11
12 namespace blobs {
13 namespace world {
14
15 Body::Body()
16 : parent(nullptr)
17 , children()
18 , mass(1.0)
19 , radius(1.0) {
20 }
21
22 Body::~Body() {
23 }
24
25 void Body::SetParent(Body &p) {
26         if (HasParent()) {
27                 UnsetParent();
28         }
29         parent = &p;
30         parent->AddChild(*this);
31 }
32
33 void Body::UnsetParent() {
34         if (!HasParent()) return;
35         parent->RemoveChild(*this);
36         parent = nullptr;
37 }
38
39 void Body::AddChild(Body &c) {
40         children.push_back(&c);
41 }
42
43 void Body::RemoveChild(Body &c) {
44         auto entry = std::find(children.begin(), children.end(), &c);
45         if (entry != children.end()) {
46                 children.erase(entry);
47         }
48 }
49
50
51 Planet::Planet(int sidelength)
52 : Body()
53 , sidelength(sidelength)
54 , tiles(new Tile[TilesTotal()])
55 , vao() {
56 }
57
58 Planet::~Planet() {
59 }
60
61 void Planet::BuildVAOs() {
62         vao.Bind();
63         vao.BindAttributes();
64         vao.EnableAttribute(0);
65         vao.EnableAttribute(1);
66         vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
67         vao.AttributePointer<glm::vec3>(1, false, offsetof(Attributes, tex_coord));
68         vao.ReserveAttributes(TilesTotal() * 4, GL_STATIC_DRAW);
69         {
70                 auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
71                 float offset = sidelength * 0.5f;
72
73                 for (int index = 0, surface = 0; surface < 6; ++surface) {
74                         for (int y = 0; y < sidelength; ++y) {
75                                 for (int x = 0; x < sidelength; ++x, ++index) {
76                                         float tex = TileAt(surface, x, y).type;
77                                         attrib[4 * index + 0].position[(surface + 0) % 3] = x + 0 - offset;
78                                         attrib[4 * index + 0].position[(surface + 1) % 3] = y + 0 - offset;
79                                         attrib[4 * index + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
80                                         attrib[4 * index + 0].tex_coord[0] = 0.0f;
81                                         attrib[4 * index + 0].tex_coord[1] = 0.0f;
82                                         attrib[4 * index + 0].tex_coord[2] = tex;
83
84                                         attrib[4 * index + 1].position[(surface + 0) % 3] = x + 0 - offset;
85                                         attrib[4 * index + 1].position[(surface + 1) % 3] = y + 1 - offset;
86                                         attrib[4 * index + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
87                                         attrib[4 * index + 1].tex_coord[0] = 0.0f;
88                                         attrib[4 * index + 1].tex_coord[1] = 1.0f;
89                                         attrib[4 * index + 1].tex_coord[2] = tex;
90
91                                         attrib[4 * index + 2].position[(surface + 0) % 3] = x + 1 - offset;
92                                         attrib[4 * index + 2].position[(surface + 1) % 3] = y + 0 - offset;
93                                         attrib[4 * index + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
94                                         attrib[4 * index + 2].tex_coord[0] = 1.0f;
95                                         attrib[4 * index + 2].tex_coord[1] = 0.0f;
96                                         attrib[4 * index + 2].tex_coord[2] = tex;
97
98                                         attrib[4 * index + 3].position[(surface + 0) % 3] = x + 1 - offset;
99                                         attrib[4 * index + 3].position[(surface + 1) % 3] = y + 1 - offset;
100                                         attrib[4 * index + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
101                                         attrib[4 * index + 3].tex_coord[0] = 1.0f;
102                                         attrib[4 * index + 3].tex_coord[1] = 1.0f;
103                                         attrib[4 * index + 3].tex_coord[2] = tex;
104                                 }
105                         }
106                 }
107         }
108         vao.BindElements();
109         vao.ReserveElements(TilesTotal() * 6, GL_STATIC_DRAW);
110         {
111                 auto element = vao.MapElements(GL_WRITE_ONLY);
112                 for (int index = 0, surface = 0; surface < 6; ++surface) {
113                         for (int y = 0; y < sidelength; ++y) {
114                                 for (int x = 0; x < sidelength; ++x, ++index) {
115                                         element[6 * index + 0] = 4 * index + 0;
116                                         element[6 * index + 1] = 4 * index + 1;
117                                         element[6 * index + 2] = 4 * index + 2;
118                                         element[6 * index + 3] = 4 * index + 2;
119                                         element[6 * index + 4] = 4 * index + 1;
120                                         element[6 * index + 5] = 4 * index + 3;
121                                 }
122                         }
123                 }
124         }
125         vao.Unbind();
126 }
127
128 void Planet::Draw(app::Assets &assets, graphics::Viewport &viewport) {
129         vao.Bind();
130         // TODO: premultiply normal with model matrix (i.e. just take it from M)
131         assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, 0.0f, 1.0f));
132         vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 0);
133         assets.shaders.planet_surface.SetNormal(glm::vec3(1.0f, 0.0f, 0.0f));
134         vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 1);
135         assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, 1.0f, 0.0f));
136         vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 2);
137         assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, 0.0f, -1.0f));
138         vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 3);
139         assets.shaders.planet_surface.SetNormal(glm::vec3(-1.0f, 0.0f, 0.0f));
140         vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 4);
141         assets.shaders.planet_surface.SetNormal(glm::vec3(0.0f, -1.0f, 0.0f));
142         vao.DrawTriangles(TilesTotal() * 4, TilesTotal() * 4 * 5);
143 }
144
145
146 void GenerateTest(Planet &p) {
147         for (int surface = 0; surface <= 5; ++surface) {
148                 for (int y = 0; y < p.SideLength(); ++y) {
149                         for (int x = 0; x < p.SideLength(); ++x) {
150                                 p.TileAt(surface, x, y).type = (x == p.SideLength()/2) + (y == p.SideLength()/2);
151                         }
152                 }
153         }
154         p.BuildVAOs();
155 }
156
157
158 Sun::Sun()
159 : Body() {
160 }
161
162 Sun::~Sun() {
163 }
164
165 }
166 }