]> git.localhorst.tv Git - blank.git/blob - src/world.cpp
3f186ea67b298e753f7b3da49b05a64588ba3f2e
[blank.git] / src / world.cpp
1 #include "world.hpp"
2
3 #include <limits>
4 #include <glm/gtx/transform.hpp>
5
6
7 namespace blank {
8
9 World::World()
10 : blockType()
11 , blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }})
12 , stairShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}, { 0.0f, 0.0f })
13 , slabShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }})
14 , generate(0)
15 , chunks(blockType, generate)
16 , player() {
17         BlockType::Faces block_fill = {  true,  true,  true,  true,  true,  true };
18         BlockType::Faces slab_fill  = { false,  true, false, false, false, false };
19         BlockType::Faces stair_fill = { false,  true, false, false, false,  true };
20
21         { // white block
22                 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape);
23                 type.fill = block_fill;
24                 blockType.Add(type);
25         }
26         { // white slab
27                 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape);
28                 type.fill = slab_fill;
29                 blockType.Add(type);
30         }
31         { // white stair
32                 BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape);
33                 type.fill = stair_fill;
34                 blockType.Add(type);
35         }
36
37         { // red block
38                 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape);
39                 type.fill = block_fill;
40                 blockType.Add(type);
41         }
42         { // red slab
43                 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape);
44                 type.fill = slab_fill;
45                 blockType.Add(type);
46         }
47         { // red stair
48                 BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape);
49                 type.fill = stair_fill;
50                 blockType.Add(type);
51         }
52
53         { // green block
54                 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape);
55                 type.fill = block_fill;
56                 blockType.Add(type);
57         }
58         { // green slab
59                 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape);
60                 type.fill = slab_fill;
61                 blockType.Add(type);
62         }
63         { // green stair
64                 BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape);
65                 type.fill = stair_fill;
66                 blockType.Add(type);
67         }
68
69         { // blue block
70                 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape);
71                 type.fill = block_fill;
72                 blockType.Add(type);
73         }
74         { // blue slab
75                 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape);
76                 type.fill = slab_fill;
77                 blockType.Add(type);
78         }
79         { // blue stair
80                 BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape);
81                 type.fill = stair_fill;
82                 blockType.Add(type);
83         }
84
85         generate.Space(0);
86         generate.Solids({ 1, 4, 7, 10 });
87
88         player = &AddEntity();
89         player->Position({ 4.0f, 4.0f, 4.0f });
90
91         Entity &test_entity = AddEntity();
92         test_entity.Position({ 0.0f, 0.0f, 0.0f });
93         test_entity.SetShape(&blockShape, { 1.0f, 1.0f, 0.0f });
94         test_entity.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
95
96         chunks.Generate({ -4, -4, -4 }, { 5, 5, 5});
97 }
98
99
100 namespace {
101
102 struct Candidate {
103         Chunk *chunk;
104         float dist;
105 };
106
107 std::vector<Candidate> candidates;
108
109 }
110
111 bool World::Intersection(
112                 const Ray &ray,
113                 const glm::mat4 &M,
114                 Chunk **chunk,
115                 int *blkid,
116                 float *dist,
117                 glm::vec3 *normal) {
118         candidates.clear();
119
120         for (Chunk &cur_chunk : chunks.Loaded()) {
121                 float cur_dist;
122                 if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(player->ChunkCoords()), cur_dist)) {
123                         candidates.push_back({ &cur_chunk, cur_dist });
124                 }
125         }
126
127         if (candidates.empty()) return false;
128
129         Chunk *closest_chunk = nullptr;
130         float closest_dist = std::numeric_limits<float>::infinity();
131         int closest_blkid = -1;
132         glm::vec3 closest_normal;
133
134         for (Candidate &cand : candidates) {
135                 if (cand.dist > closest_dist) continue;
136                 int cur_blkid;
137                 float cur_dist;
138                 glm::vec3 cur_normal;
139                 if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_blkid, cur_dist, cur_normal)) {
140                         if (cur_dist < closest_dist) {
141                                 closest_chunk = cand.chunk;
142                                 closest_blkid = cur_blkid;
143                                 closest_dist = cur_dist;
144                                 closest_normal = cur_normal;
145                         }
146                 }
147         }
148
149         if (chunk) {
150                 *chunk = closest_chunk;
151         }
152         if (blkid) {
153                 *blkid = closest_blkid;
154         }
155         if (dist) {
156                 *dist = closest_dist;
157         }
158         if (normal) {
159                 *normal = closest_normal;
160         }
161         return closest_chunk;
162 }
163
164
165 Chunk &World::Next(const Chunk &to, const glm::tvec3<int> &dir) {
166         const Chunk::Pos tgt_pos = to.Position() + dir;
167         return chunks.ForceLoad(tgt_pos);
168 }
169
170
171 void World::Update(int dt) {
172         for (Entity &entity : entities) {
173                 entity.Update(dt);
174         }
175         chunks.Rebase(player->ChunkCoords());
176         chunks.Update();
177 }
178
179
180 void World::Render(DirectionalLighting &program) {
181         program.SetLightDirection({ -1.0f, -3.0f, -2.0f });
182         program.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
183
184         for (Chunk &chunk : chunks.Loaded()) {
185                 glm::mat4 m(chunk.Transform(player->ChunkCoords()));
186                 program.SetM(m);
187                 glm::mat4 mvp(program.GetVP() * m);
188                 if (!CullTest(Chunk::Bounds(), mvp)) {
189                         chunk.Draw();
190                 }
191         }
192
193         for (Entity &entity : entities) {
194                 if (entity.HasShape()) {
195                         program.SetM(entity.Transform(player->ChunkCoords()));
196                         entity.Draw();
197                 }
198         }
199 }
200
201 }