]> git.lizzy.rs Git - minetest.git/blob - src/mapblock_mesh.cpp
VoxelManip cleanups (const ref, const move) + function removal (#6169)
[minetest.git] / src / mapblock_mesh.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "mapblock_mesh.h"
21 #include "light.h"
22 #include "mapblock.h"
23 #include "map.h"
24 #include "profiler.h"
25 #include "nodedef.h"
26 #include "mesh.h"
27 #include "minimap.h"
28 #include "content_mapblock.h"
29 #include "noise.h"
30 #include "shader.h"
31 #include "settings.h"
32 #include "util/directiontables.h"
33 #include "client/renderingengine.h"
34
35 /*
36         MeshMakeData
37 */
38
39 MeshMakeData::MeshMakeData(Client *client, bool use_shaders,
40                 bool use_tangent_vertices):
41         m_client(client),
42         m_use_shaders(use_shaders),
43         m_use_tangent_vertices(use_tangent_vertices)
44 {}
45
46 void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
47 {
48         m_blockpos = blockpos;
49
50         v3s16 blockpos_nodes = m_blockpos*MAP_BLOCKSIZE;
51
52         m_vmanip.clear();
53         VoxelArea voxel_area(blockpos_nodes - v3s16(1,1,1) * MAP_BLOCKSIZE,
54                         blockpos_nodes + v3s16(1,1,1) * MAP_BLOCKSIZE*2-v3s16(1,1,1));
55         m_vmanip.addArea(voxel_area);
56 }
57
58 void MeshMakeData::fillBlockData(const v3s16 &block_offset, MapNode *data)
59 {
60         v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
61         VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));
62
63         v3s16 bp = m_blockpos + block_offset;
64         v3s16 blockpos_nodes = bp * MAP_BLOCKSIZE;
65         m_vmanip.copyFrom(data, data_area, v3s16(0,0,0), blockpos_nodes, data_size);
66 }
67
68 void MeshMakeData::fill(MapBlock *block)
69 {
70         fillBlockDataBegin(block->getPos());
71
72         fillBlockData(v3s16(0,0,0), block->getData());
73
74         // Get map for reading neigbhor blocks
75         Map *map = block->getParent();
76
77         for (u16 i=0; i<26; i++) {
78                 const v3s16 &dir = g_26dirs[i];
79                 v3s16 bp = m_blockpos + dir;
80                 MapBlock *b = map->getBlockNoCreateNoEx(bp);
81                 if(b)
82                         fillBlockData(dir, b->getData());
83         }
84 }
85
86 void MeshMakeData::fillSingleNode(MapNode *node)
87 {
88         m_blockpos = v3s16(0,0,0);
89
90         v3s16 blockpos_nodes = v3s16(0,0,0);
91         VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE,
92                         blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1));
93         s32 volume = area.getVolume();
94         s32 our_node_index = area.index(1,1,1);
95
96         // Allocate this block + neighbors
97         m_vmanip.clear();
98         m_vmanip.addArea(area);
99
100         // Fill in data
101         MapNode *data = new MapNode[volume];
102         for(s32 i = 0; i < volume; i++)
103         {
104                 if(i == our_node_index)
105                 {
106                         data[i] = *node;
107                 }
108                 else
109                 {
110                         data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0);
111                 }
112         }
113         m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent());
114         delete[] data;
115 }
116
117 void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
118 {
119         if(crack_level >= 0)
120                 m_crack_pos_relative = crack_pos - m_blockpos*MAP_BLOCKSIZE;
121 }
122
123 void MeshMakeData::setSmoothLighting(bool smooth_lighting)
124 {
125         m_smooth_lighting = smooth_lighting;
126 }
127
128 /*
129         Light and vertex color functions
130 */
131
132 /*
133         Calculate non-smooth lighting at interior of node.
134         Single light bank.
135 */
136 static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
137                 INodeDefManager *ndef)
138 {
139         u8 light = n.getLight(bank, ndef);
140
141         while(increment > 0)
142         {
143                 light = undiminish_light(light);
144                 --increment;
145         }
146         while(increment < 0)
147         {
148                 light = diminish_light(light);
149                 ++increment;
150         }
151
152         return decode_light(light);
153 }
154
155 /*
156         Calculate non-smooth lighting at interior of node.
157         Both light banks.
158 */
159 u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef)
160 {
161         u16 day = getInteriorLight(LIGHTBANK_DAY, n, increment, ndef);
162         u16 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, ndef);
163         return day | (night << 8);
164 }
165
166 /*
167         Calculate non-smooth lighting at face of node.
168         Single light bank.
169 */
170 static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
171                 v3s16 face_dir, INodeDefManager *ndef)
172 {
173         u8 light;
174         u8 l1 = n.getLight(bank, ndef);
175         u8 l2 = n2.getLight(bank, ndef);
176         if(l1 > l2)
177                 light = l1;
178         else
179                 light = l2;
180
181         // Boost light level for light sources
182         u8 light_source = MYMAX(ndef->get(n).light_source,
183                         ndef->get(n2).light_source);
184         if(light_source > light)
185                 light = light_source;
186
187         return decode_light(light);
188 }
189
190 /*
191         Calculate non-smooth lighting at face of node.
192         Both light banks.
193 */
194 u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef)
195 {
196         u16 day = getFaceLight(LIGHTBANK_DAY, n, n2, face_dir, ndef);
197         u16 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, ndef);
198         return day | (night << 8);
199 }
200
201 /*
202         Calculate smooth lighting at the XYZ- corner of p.
203         Both light banks
204 */
205 static u16 getSmoothLightCombined(const v3s16 &p, MeshMakeData *data)
206 {
207         static const v3s16 dirs8[8] = {
208                 v3s16(0,0,0),
209                 v3s16(0,0,1),
210                 v3s16(0,1,0),
211                 v3s16(0,1,1),
212                 v3s16(1,0,0),
213                 v3s16(1,1,0),
214                 v3s16(1,0,1),
215                 v3s16(1,1,1),
216         };
217
218         INodeDefManager *ndef = data->m_client->ndef();
219
220         u16 ambient_occlusion = 0;
221         u16 light_count = 0;
222         u8 light_source_max = 0;
223         u16 light_day = 0;
224         u16 light_night = 0;
225
226         for (u32 i = 0; i < 8; i++)
227         {
228                 MapNode n = data->m_vmanip.getNodeNoExNoEmerge(p - dirs8[i]);
229
230                 // if it's CONTENT_IGNORE we can't do any light calculations
231                 if (n.getContent() == CONTENT_IGNORE) {
232                         continue;
233                 }
234
235                 const ContentFeatures &f = ndef->get(n);
236                 if (f.light_source > light_source_max)
237                         light_source_max = f.light_source;
238                 // Check f.solidness because fast-style leaves look better this way
239                 if (f.param_type == CPT_LIGHT && f.solidness != 2) {
240                         light_day += decode_light(n.getLightNoChecks(LIGHTBANK_DAY, &f));
241                         light_night += decode_light(n.getLightNoChecks(LIGHTBANK_NIGHT, &f));
242                         light_count++;
243                 } else {
244                         ambient_occlusion++;
245                 }
246         }
247
248         if(light_count == 0)
249                 return 0xffff;
250
251         light_day /= light_count;
252         light_night /= light_count;
253
254         // Boost brightness around light sources
255         bool skip_ambient_occlusion_day = false;
256         if(decode_light(light_source_max) >= light_day) {
257                 light_day = decode_light(light_source_max);
258                 skip_ambient_occlusion_day = true;
259         }
260
261         bool skip_ambient_occlusion_night = false;
262         if(decode_light(light_source_max) >= light_night) {
263                 light_night = decode_light(light_source_max);
264                 skip_ambient_occlusion_night = true;
265         }
266
267         if (ambient_occlusion > 4)
268         {
269                 static thread_local const float ao_gamma = rangelim(
270                         g_settings->getFloat("ambient_occlusion_gamma"), 0.25, 4.0);
271
272                 // Table of gamma space multiply factors.
273                 static const float light_amount[3] = {
274                         powf(0.75, 1.0 / ao_gamma),
275                         powf(0.5,  1.0 / ao_gamma),
276                         powf(0.25, 1.0 / ao_gamma)
277                 };
278
279                 //calculate table index for gamma space multiplier
280                 ambient_occlusion -= 5;
281
282                 if (!skip_ambient_occlusion_day)
283                         light_day = rangelim(core::round32(light_day*light_amount[ambient_occlusion]), 0, 255);
284                 if (!skip_ambient_occlusion_night)
285                         light_night = rangelim(core::round32(light_night*light_amount[ambient_occlusion]), 0, 255);
286         }
287
288         return light_day | (light_night << 8);
289 }
290
291 /*
292         Calculate smooth lighting at the given corner of p.
293         Both light banks.
294 */
295 u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data)
296 {
297         if(corner.X == 1) p.X += 1;
298         // else corner.X == -1
299         if(corner.Y == 1) p.Y += 1;
300         // else corner.Y == -1
301         if(corner.Z == 1) p.Z += 1;
302         // else corner.Z == -1
303
304         return getSmoothLightCombined(p, data);
305 }
306
307 void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){
308         f32 rg = daynight_ratio / 1000.0f - 0.04f;
309         f32 b = (0.98f * daynight_ratio) / 1000.0f + 0.078f;
310         sunlight->r = rg;
311         sunlight->g = rg;
312         sunlight->b = b;
313 }
314
315 void final_color_blend(video::SColor *result,
316                 u16 light, u32 daynight_ratio)
317 {
318         video::SColorf dayLight;
319         get_sunlight_color(&dayLight, daynight_ratio);
320         final_color_blend(result,
321                 encode_light(light, 0), dayLight);
322 }
323
324 void final_color_blend(video::SColor *result,
325                 const video::SColor &data, const video::SColorf &dayLight)
326 {
327         static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f);
328
329         video::SColorf c(data);
330         f32 n = 1 - c.a;
331
332         f32 r = c.r * (c.a * dayLight.r + n * artificialColor.r) * 2.0f;
333         f32 g = c.g * (c.a * dayLight.g + n * artificialColor.g) * 2.0f;
334         f32 b = c.b * (c.a * dayLight.b + n * artificialColor.b) * 2.0f;
335
336         // Emphase blue a bit in darker places
337         // Each entry of this array represents a range of 8 blue levels
338         static const u8 emphase_blue_when_dark[32] = {
339                 1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
340                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
341         };
342
343         b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255),
344                 0, 255) / 8] / 255.0f;
345
346         result->setRed(core::clamp((s32) (r * 255.0f), 0, 255));
347         result->setGreen(core::clamp((s32) (g * 255.0f), 0, 255));
348         result->setBlue(core::clamp((s32) (b * 255.0f), 0, 255));
349 }
350
351 /*
352         Mesh generation helpers
353 */
354
355 /*
356         vertex_dirs: v3s16[4]
357 */
358 static void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs)
359 {
360         /*
361                 If looked from outside the node towards the face, the corners are:
362                 0: bottom-right
363                 1: bottom-left
364                 2: top-left
365                 3: top-right
366         */
367         if(dir == v3s16(0,0,1))
368         {
369                 // If looking towards z+, this is the face that is behind
370                 // the center point, facing towards z+.
371                 vertex_dirs[0] = v3s16(-1,-1, 1);
372                 vertex_dirs[1] = v3s16( 1,-1, 1);
373                 vertex_dirs[2] = v3s16( 1, 1, 1);
374                 vertex_dirs[3] = v3s16(-1, 1, 1);
375         }
376         else if(dir == v3s16(0,0,-1))
377         {
378                 // faces towards Z-
379                 vertex_dirs[0] = v3s16( 1,-1,-1);
380                 vertex_dirs[1] = v3s16(-1,-1,-1);
381                 vertex_dirs[2] = v3s16(-1, 1,-1);
382                 vertex_dirs[3] = v3s16( 1, 1,-1);
383         }
384         else if(dir == v3s16(1,0,0))
385         {
386                 // faces towards X+
387                 vertex_dirs[0] = v3s16( 1,-1, 1);
388                 vertex_dirs[1] = v3s16( 1,-1,-1);
389                 vertex_dirs[2] = v3s16( 1, 1,-1);
390                 vertex_dirs[3] = v3s16( 1, 1, 1);
391         }
392         else if(dir == v3s16(-1,0,0))
393         {
394                 // faces towards X-
395                 vertex_dirs[0] = v3s16(-1,-1,-1);
396                 vertex_dirs[1] = v3s16(-1,-1, 1);
397                 vertex_dirs[2] = v3s16(-1, 1, 1);
398                 vertex_dirs[3] = v3s16(-1, 1,-1);
399         }
400         else if(dir == v3s16(0,1,0))
401         {
402                 // faces towards Y+ (assume Z- as "down" in texture)
403                 vertex_dirs[0] = v3s16( 1, 1,-1);
404                 vertex_dirs[1] = v3s16(-1, 1,-1);
405                 vertex_dirs[2] = v3s16(-1, 1, 1);
406                 vertex_dirs[3] = v3s16( 1, 1, 1);
407         }
408         else if(dir == v3s16(0,-1,0))
409         {
410                 // faces towards Y- (assume Z+ as "down" in texture)
411                 vertex_dirs[0] = v3s16( 1,-1, 1);
412                 vertex_dirs[1] = v3s16(-1,-1, 1);
413                 vertex_dirs[2] = v3s16(-1,-1,-1);
414                 vertex_dirs[3] = v3s16( 1,-1,-1);
415         }
416 }
417
418 struct FastFace
419 {
420         TileLayer layer;
421         video::S3DVertex vertices[4]; // Precalculated vertices
422         /*!
423          * The face is divided into two triangles. If this is true,
424          * vertices 0 and 2 are connected, othervise vertices 1 and 3
425          * are connected.
426          */
427         bool vertex_0_2_connected;
428         u8 layernum;
429 };
430
431 static void makeFastFace(const TileSpec &tile, u16 li0, u16 li1, u16 li2, u16 li3,
432         v3f p, v3s16 dir, v3f scale, std::vector<FastFace> &dest)
433 {
434         // Position is at the center of the cube.
435         v3f pos = p * BS;
436
437         float x0 = 0.0;
438         float y0 = 0.0;
439         float w = 1.0;
440         float h = 1.0;
441
442         v3f vertex_pos[4];
443         v3s16 vertex_dirs[4];
444         getNodeVertexDirs(dir, vertex_dirs);
445
446         v3s16 t;
447         u16 t1;
448         switch (tile.rotation)
449         {
450         case 0:
451                 break;
452         case 1: //R90
453                 t = vertex_dirs[0];
454                 vertex_dirs[0] = vertex_dirs[3];
455                 vertex_dirs[3] = vertex_dirs[2];
456                 vertex_dirs[2] = vertex_dirs[1];
457                 vertex_dirs[1] = t;
458                 t1=li0;
459                 li0=li3;
460                 li3=li2;
461                 li2=li1;
462                 li1=t1;
463                 break;
464         case 2: //R180
465                 t = vertex_dirs[0];
466                 vertex_dirs[0] = vertex_dirs[2];
467                 vertex_dirs[2] = t;
468                 t = vertex_dirs[1];
469                 vertex_dirs[1] = vertex_dirs[3];
470                 vertex_dirs[3] = t;
471                 t1  = li0;
472                 li0 = li2;
473                 li2 = t1;
474                 t1  = li1;
475                 li1 = li3;
476                 li3 = t1;
477                 break;
478         case 3: //R270
479                 t = vertex_dirs[0];
480                 vertex_dirs[0] = vertex_dirs[1];
481                 vertex_dirs[1] = vertex_dirs[2];
482                 vertex_dirs[2] = vertex_dirs[3];
483                 vertex_dirs[3] = t;
484                 t1  = li0;
485                 li0 = li1;
486                 li1 = li2;
487                 li2 = li3;
488                 li3 = t1;
489                 break;
490         case 4: //FXR90
491                 t = vertex_dirs[0];
492                 vertex_dirs[0] = vertex_dirs[3];
493                 vertex_dirs[3] = vertex_dirs[2];
494                 vertex_dirs[2] = vertex_dirs[1];
495                 vertex_dirs[1] = t;
496                 t1  = li0;
497                 li0 = li3;
498                 li3 = li2;
499                 li2 = li1;
500                 li1 = t1;
501                 y0 += h;
502                 h *= -1;
503                 break;
504         case 5: //FXR270
505                 t = vertex_dirs[0];
506                 vertex_dirs[0] = vertex_dirs[1];
507                 vertex_dirs[1] = vertex_dirs[2];
508                 vertex_dirs[2] = vertex_dirs[3];
509                 vertex_dirs[3] = t;
510                 t1  = li0;
511                 li0 = li1;
512                 li1 = li2;
513                 li2 = li3;
514                 li3 = t1;
515                 y0 += h;
516                 h *= -1;
517                 break;
518         case 6: //FYR90
519                 t = vertex_dirs[0];
520                 vertex_dirs[0] = vertex_dirs[3];
521                 vertex_dirs[3] = vertex_dirs[2];
522                 vertex_dirs[2] = vertex_dirs[1];
523                 vertex_dirs[1] = t;
524                 t1  = li0;
525                 li0 = li3;
526                 li3 = li2;
527                 li2 = li1;
528                 li1 = t1;
529                 x0 += w;
530                 w *= -1;
531                 break;
532         case 7: //FYR270
533                 t = vertex_dirs[0];
534                 vertex_dirs[0] = vertex_dirs[1];
535                 vertex_dirs[1] = vertex_dirs[2];
536                 vertex_dirs[2] = vertex_dirs[3];
537                 vertex_dirs[3] = t;
538                 t1  = li0;
539                 li0 = li1;
540                 li1 = li2;
541                 li2 = li3;
542                 li3 = t1;
543                 x0 += w;
544                 w *= -1;
545                 break;
546         case 8: //FX
547                 y0 += h;
548                 h *= -1;
549                 break;
550         case 9: //FY
551                 x0 += w;
552                 w *= -1;
553                 break;
554         default:
555                 break;
556         }
557
558         for(u16 i=0; i<4; i++)
559         {
560                 vertex_pos[i] = v3f(
561                                 BS/2*vertex_dirs[i].X,
562                                 BS/2*vertex_dirs[i].Y,
563                                 BS/2*vertex_dirs[i].Z
564                 );
565         }
566
567         for(u16 i=0; i<4; i++)
568         {
569                 vertex_pos[i].X *= scale.X;
570                 vertex_pos[i].Y *= scale.Y;
571                 vertex_pos[i].Z *= scale.Z;
572                 vertex_pos[i] += pos;
573         }
574
575         f32 abs_scale = 1.0;
576         if     (scale.X < 0.999 || scale.X > 1.001) abs_scale = scale.X;
577         else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y;
578         else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z;
579
580         v3f normal(dir.X, dir.Y, dir.Z);
581
582         u16 li[4] = { li0, li1, li2, li3 };
583         u16 day[4];
584         u16 night[4];
585
586         for (u8 i = 0; i < 4; i++) {
587                 day[i] = li[i] >> 8;
588                 night[i] = li[i] & 0xFF;
589         }
590
591         bool vertex_0_2_connected = abs(day[0] - day[2]) + abs(night[0] - night[2])
592                         < abs(day[1] - day[3]) + abs(night[1] - night[3]);
593
594         v2f32 f[4] = {
595                 core::vector2d<f32>(x0 + w * abs_scale, y0 + h),
596                 core::vector2d<f32>(x0, y0 + h),
597                 core::vector2d<f32>(x0, y0),
598                 core::vector2d<f32>(x0 + w * abs_scale, y0) };
599
600         for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
601                 const TileLayer *layer = &tile.layers[layernum];
602                 if (layer->texture_id == 0)
603                         continue;
604
605                 dest.push_back(FastFace());
606                 FastFace& face = *dest.rbegin();
607
608                 for (u8 i = 0; i < 4; i++) {
609                         video::SColor c = encode_light(li[i], tile.emissive_light);
610                         if (!tile.emissive_light)
611                                 applyFacesShading(c, normal);
612
613                         face.vertices[i] = video::S3DVertex(vertex_pos[i], normal, c, f[i]);
614                 }
615
616                 /*
617                  Revert triangles for nicer looking gradient if the
618                  brightness of vertices 1 and 3 differ less than
619                  the brightness of vertices 0 and 2.
620                  */
621                 face.vertex_0_2_connected = vertex_0_2_connected;
622
623                 face.layer = *layer;
624                 face.layernum = layernum;
625         }
626 }
627
628 /*
629         Nodes make a face if contents differ and solidness differs.
630         Return value:
631                 0: No face
632                 1: Face uses m1's content
633                 2: Face uses m2's content
634         equivalent: Whether the blocks share the same face (eg. water and glass)
635
636         TODO: Add 3: Both faces drawn with backface culling, remove equivalent
637 */
638 static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
639                 INodeDefManager *ndef)
640 {
641         *equivalent = false;
642
643         if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
644                 return 0;
645
646         bool contents_differ = (m1 != m2);
647
648         const ContentFeatures &f1 = ndef->get(m1);
649         const ContentFeatures &f2 = ndef->get(m2);
650
651         // Contents don't differ for different forms of same liquid
652         if(f1.sameLiquid(f2))
653                 contents_differ = false;
654
655         u8 c1 = f1.solidness;
656         u8 c2 = f2.solidness;
657
658         bool solidness_differs = (c1 != c2);
659         bool makes_face = contents_differ && solidness_differs;
660
661         if(makes_face == false)
662                 return 0;
663
664         if(c1 == 0)
665                 c1 = f1.visual_solidness;
666         if(c2 == 0)
667                 c2 = f2.visual_solidness;
668
669         if(c1 == c2){
670                 *equivalent = true;
671                 // If same solidness, liquid takes precense
672                 if(f1.isLiquid())
673                         return 1;
674                 if(f2.isLiquid())
675                         return 2;
676         }
677
678         if(c1 > c2)
679                 return 1;
680         else
681                 return 2;
682 }
683
684 /*
685         Gets nth node tile (0 <= n <= 5).
686 */
687 void getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data, TileSpec &tile)
688 {
689         INodeDefManager *ndef = data->m_client->ndef();
690         const ContentFeatures &f = ndef->get(mn);
691         tile = f.tiles[tileindex];
692         TileLayer *top_layer = NULL;
693         for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
694                 TileLayer *layer = &tile.layers[layernum];
695                 if (layer->texture_id == 0)
696                         continue;
697                 top_layer = layer;
698                 if (!layer->has_color)
699                         mn.getColor(f, &(layer->color));
700         }
701         // Apply temporary crack
702         if (p == data->m_crack_pos_relative)
703                 top_layer->material_flags |= MATERIAL_FLAG_CRACK;
704 }
705
706 /*
707         Gets node tile given a face direction.
708 */
709 void getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data, TileSpec &tile)
710 {
711         INodeDefManager *ndef = data->m_client->ndef();
712
713         // Direction must be (1,0,0), (-1,0,0), (0,1,0), (0,-1,0),
714         // (0,0,1), (0,0,-1) or (0,0,0)
715         assert(dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z <= 1);
716
717         // Convert direction to single integer for table lookup
718         //  0 = (0,0,0)
719         //  1 = (1,0,0)
720         //  2 = (0,1,0)
721         //  3 = (0,0,1)
722         //  4 = invalid, treat as (0,0,0)
723         //  5 = (0,0,-1)
724         //  6 = (0,-1,0)
725         //  7 = (-1,0,0)
726         u8 dir_i = ((dir.X + 2 * dir.Y + 3 * dir.Z) & 7)*2;
727
728         // Get rotation for things like chests
729         u8 facedir = mn.getFaceDir(ndef);
730
731         static const u16 dir_to_tile[24 * 16] =
732         {
733                 // 0     +X    +Y    +Z           -Z    -Y    -X   ->   value=tile,rotation
734                    0,0,  2,0 , 0,0 , 4,0 ,  0,0,  5,0 , 1,0 , 3,0 ,  // rotate around y+ 0 - 3
735                    0,0,  4,0 , 0,3 , 3,0 ,  0,0,  2,0 , 1,1 , 5,0 ,
736                    0,0,  3,0 , 0,2 , 5,0 ,  0,0,  4,0 , 1,2 , 2,0 ,
737                    0,0,  5,0 , 0,1 , 2,0 ,  0,0,  3,0 , 1,3 , 4,0 ,
738
739                    0,0,  2,3 , 5,0 , 0,2 ,  0,0,  1,0 , 4,2 , 3,1 ,  // rotate around z+ 4 - 7
740                    0,0,  4,3 , 2,0 , 0,1 ,  0,0,  1,1 , 3,2 , 5,1 ,
741                    0,0,  3,3 , 4,0 , 0,0 ,  0,0,  1,2 , 5,2 , 2,1 ,
742                    0,0,  5,3 , 3,0 , 0,3 ,  0,0,  1,3 , 2,2 , 4,1 ,
743
744                    0,0,  2,1 , 4,2 , 1,2 ,  0,0,  0,0 , 5,0 , 3,3 ,  // rotate around z- 8 - 11
745                    0,0,  4,1 , 3,2 , 1,3 ,  0,0,  0,3 , 2,0 , 5,3 ,
746                    0,0,  3,1 , 5,2 , 1,0 ,  0,0,  0,2 , 4,0 , 2,3 ,
747                    0,0,  5,1 , 2,2 , 1,1 ,  0,0,  0,1 , 3,0 , 4,3 ,
748
749                    0,0,  0,3 , 3,3 , 4,1 ,  0,0,  5,3 , 2,3 , 1,3 ,  // rotate around x+ 12 - 15
750                    0,0,  0,2 , 5,3 , 3,1 ,  0,0,  2,3 , 4,3 , 1,0 ,
751                    0,0,  0,1 , 2,3 , 5,1 ,  0,0,  4,3 , 3,3 , 1,1 ,
752                    0,0,  0,0 , 4,3 , 2,1 ,  0,0,  3,3 , 5,3 , 1,2 ,
753
754                    0,0,  1,1 , 2,1 , 4,3 ,  0,0,  5,1 , 3,1 , 0,1 ,  // rotate around x- 16 - 19
755                    0,0,  1,2 , 4,1 , 3,3 ,  0,0,  2,1 , 5,1 , 0,0 ,
756                    0,0,  1,3 , 3,1 , 5,3 ,  0,0,  4,1 , 2,1 , 0,3 ,
757                    0,0,  1,0 , 5,1 , 2,3 ,  0,0,  3,1 , 4,1 , 0,2 ,
758
759                    0,0,  3,2 , 1,2 , 4,2 ,  0,0,  5,2 , 0,2 , 2,2 ,  // rotate around y- 20 - 23
760                    0,0,  5,2 , 1,3 , 3,2 ,  0,0,  2,2 , 0,1 , 4,2 ,
761                    0,0,  2,2 , 1,0 , 5,2 ,  0,0,  4,2 , 0,0 , 3,2 ,
762                    0,0,  4,2 , 1,1 , 2,2 ,  0,0,  3,2 , 0,3 , 5,2
763
764         };
765         u16 tile_index=facedir*16 + dir_i;
766         getNodeTileN(mn, p, dir_to_tile[tile_index], data, tile);
767         tile.rotation = dir_to_tile[tile_index + 1];
768 }
769
770 static void getTileInfo(
771                 // Input:
772                 MeshMakeData *data,
773                 const v3s16 &p,
774                 const v3s16 &face_dir,
775                 // Output:
776                 bool &makes_face,
777                 v3s16 &p_corrected,
778                 v3s16 &face_dir_corrected,
779                 u16 *lights,
780                 TileSpec &tile
781         )
782 {
783         VoxelManipulator &vmanip = data->m_vmanip;
784         INodeDefManager *ndef = data->m_client->ndef();
785         v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
786
787         const MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p);
788
789         // Don't even try to get n1 if n0 is already CONTENT_IGNORE
790         if (n0.getContent() == CONTENT_IGNORE) {
791                 makes_face = false;
792                 return;
793         }
794
795         const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir);
796
797         if (n1.getContent() == CONTENT_IGNORE) {
798                 makes_face = false;
799                 return;
800         }
801
802         // This is hackish
803         bool equivalent = false;
804         u8 mf = face_contents(n0.getContent(), n1.getContent(),
805                         &equivalent, ndef);
806
807         if (mf == 0) {
808                 makes_face = false;
809                 return;
810         }
811
812         makes_face = true;
813
814         MapNode n = n0;
815
816         if (mf == 1) {
817                 p_corrected = p;
818                 face_dir_corrected = face_dir;
819         } else {
820                 n = n1;
821                 p_corrected = p + face_dir;
822                 face_dir_corrected = -face_dir;
823         }
824
825         getNodeTile(n, p_corrected, face_dir_corrected, data, tile);
826         const ContentFeatures &f = ndef->get(n);
827         tile.emissive_light = f.light_source;
828
829         // eg. water and glass
830         if (equivalent) {
831                 for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++)
832                         tile.layers[layernum].material_flags |=
833                                 MATERIAL_FLAG_BACKFACE_CULLING;
834         }
835
836         if (!data->m_smooth_lighting) {
837                 lights[0] = lights[1] = lights[2] = lights[3] =
838                                 getFaceLight(n0, n1, face_dir, ndef);
839         }
840         else {
841                 v3s16 vertex_dirs[4];
842                 getNodeVertexDirs(face_dir_corrected, vertex_dirs);
843
844                 v3s16 light_p = blockpos_nodes + p_corrected;
845                 for (u16 i = 0; i < 4; i++) {
846                         lights[i] = getSmoothLight(light_p, vertex_dirs[i], data);
847                 }
848         }
849 }
850
851 /*
852         startpos:
853         translate_dir: unit vector with only one of x, y or z
854         face_dir: unit vector with only one of x, y or z
855 */
856 static void updateFastFaceRow(
857                 MeshMakeData *data,
858                 const v3s16 &&startpos,
859                 v3s16 translate_dir,
860                 const v3f &&translate_dir_f,
861                 const v3s16 &&face_dir,
862                 std::vector<FastFace> &dest)
863 {
864         v3s16 p = startpos;
865
866         u16 continuous_tiles_count = 1;
867
868         bool makes_face = false;
869         v3s16 p_corrected;
870         v3s16 face_dir_corrected;
871         u16 lights[4] = {0,0,0,0};
872         TileSpec tile;
873         getTileInfo(data, p, face_dir,
874                         makes_face, p_corrected, face_dir_corrected,
875                         lights, tile);
876
877         // Unroll this variable which has a significant build cost
878         TileSpec next_tile;
879         for (u16 j = 0; j < MAP_BLOCKSIZE; j++) {
880                 // If tiling can be done, this is set to false in the next step
881                 bool next_is_different = true;
882
883                 v3s16 p_next;
884
885                 bool next_makes_face = false;
886                 v3s16 next_p_corrected;
887                 v3s16 next_face_dir_corrected;
888                 u16 next_lights[4] = {0,0,0,0};
889
890
891                 // If at last position, there is nothing to compare to and
892                 // the face must be drawn anyway
893                 if (j != MAP_BLOCKSIZE - 1) {
894                         p_next = p + translate_dir;
895
896                         getTileInfo(data, p_next, face_dir,
897                                         next_makes_face, next_p_corrected,
898                                         next_face_dir_corrected, next_lights,
899                                         next_tile);
900
901                         if (next_makes_face == makes_face
902                                         && next_p_corrected == p_corrected + translate_dir
903                                         && next_face_dir_corrected == face_dir_corrected
904                                         && memcmp(next_lights, lights, ARRLEN(lights) * sizeof(u16)) == 0
905                                         && next_tile.isTileable(tile)) {
906                                 next_is_different = false;
907                                 continuous_tiles_count++;
908                         }
909                 }
910
911                 if (next_is_different) {
912                         /*
913                                 Create a face if there should be one
914                         */
915                         if (makes_face) {
916                                 // Floating point conversion of the position vector
917                                 v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
918                                 // Center point of face (kind of)
919                                 v3f sp = pf -
920                                         ((f32)continuous_tiles_count / 2.0f - 0.5f) * translate_dir_f;
921                                 v3f scale(1,1,1);
922
923                                 if(translate_dir.X != 0) {
924                                         scale.X = continuous_tiles_count;
925                                 }
926                                 if(translate_dir.Y != 0) {
927                                         scale.Y = continuous_tiles_count;
928                                 }
929                                 if(translate_dir.Z != 0) {
930                                         scale.Z = continuous_tiles_count;
931                                 }
932
933                                 makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
934                                                 sp, face_dir_corrected, scale, dest);
935
936                                 g_profiler->avg("Meshgen: faces drawn by tiling", 0);
937                                 for(int i = 1; i < continuous_tiles_count; i++){
938                                         g_profiler->avg("Meshgen: faces drawn by tiling", 1);
939                                 }
940                         }
941
942                         continuous_tiles_count = 1;
943                 }
944
945                 makes_face = next_makes_face;
946                 p_corrected = next_p_corrected;
947                 face_dir_corrected = next_face_dir_corrected;
948                 std::memcpy(lights, next_lights, ARRLEN(lights) * sizeof(u16));
949                 if (next_is_different)
950                         tile = next_tile;
951                 p = p_next;
952         }
953 }
954
955 static void updateAllFastFaceRows(MeshMakeData *data,
956                 std::vector<FastFace> &dest)
957 {
958         /*
959                 Go through every y,z and get top(y+) faces in rows of x+
960         */
961         for(s16 y = 0; y < MAP_BLOCKSIZE; y++) {
962                 for(s16 z = 0; z < MAP_BLOCKSIZE; z++) {
963                         updateFastFaceRow(data,
964                                         v3s16(0,y,z),
965                                         v3s16(1,0,0), //dir
966                                         v3f  (1,0,0),
967                                         v3s16(0,1,0), //face dir
968                                         dest);
969                 }
970         }
971
972         /*
973                 Go through every x,y and get right(x+) faces in rows of z+
974         */
975         for(s16 x = 0; x < MAP_BLOCKSIZE; x++) {
976                 for(s16 y = 0; y < MAP_BLOCKSIZE; y++) {
977                         updateFastFaceRow(data,
978                                         v3s16(x,y,0),
979                                         v3s16(0,0,1), //dir
980                                         v3f  (0,0,1),
981                                         v3s16(1,0,0), //face dir
982                                         dest);
983                 }
984         }
985
986         /*
987                 Go through every y,z and get back(z+) faces in rows of x+
988         */
989         for(s16 z = 0; z < MAP_BLOCKSIZE; z++) {
990                 for(s16 y = 0; y < MAP_BLOCKSIZE; y++) {
991                         updateFastFaceRow(data,
992                                         v3s16(0,y,z),
993                                         v3s16(1,0,0), //dir
994                                         v3f  (1,0,0),
995                                         v3s16(0,0,1), //face dir
996                                         dest);
997                 }
998         }
999 }
1000
1001 /*
1002         MapBlockMesh
1003 */
1004
1005 MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
1006         m_minimap_mapblock(NULL),
1007         m_tsrc(data->m_client->getTextureSource()),
1008         m_shdrsrc(data->m_client->getShaderSource()),
1009         m_animation_force_timer(0), // force initial animation
1010         m_last_crack(-1),
1011         m_last_daynight_ratio((u32) -1)
1012 {
1013         for (int m = 0; m < MAX_TILE_LAYERS; m++)
1014                 m_mesh[m] = new scene::SMesh();
1015         m_enable_shaders = data->m_use_shaders;
1016         m_use_tangent_vertices = data->m_use_tangent_vertices;
1017         m_enable_vbo = g_settings->getBool("enable_vbo");
1018
1019         if (g_settings->getBool("enable_minimap")) {
1020                 m_minimap_mapblock = new MinimapMapblock;
1021                 m_minimap_mapblock->getMinimapNodes(
1022                         &data->m_vmanip, data->m_blockpos * MAP_BLOCKSIZE);
1023         }
1024
1025         // 4-21ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
1026         // 24-155ms for MAP_BLOCKSIZE=32  (NOTE: probably outdated)
1027         //TimeTaker timer1("MapBlockMesh()");
1028
1029         std::vector<FastFace> fastfaces_new;
1030         fastfaces_new.reserve(512);
1031
1032         /*
1033                 We are including the faces of the trailing edges of the block.
1034                 This means that when something changes, the caller must
1035                 also update the meshes of the blocks at the leading edges.
1036
1037                 NOTE: This is the slowest part of this method.
1038         */
1039         {
1040                 // 4-23ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
1041                 //TimeTaker timer2("updateAllFastFaceRows()");
1042                 updateAllFastFaceRows(data, fastfaces_new);
1043         }
1044         // End of slow part
1045
1046         /*
1047                 Convert FastFaces to MeshCollector
1048         */
1049
1050         MeshCollector collector(m_use_tangent_vertices);
1051
1052         {
1053                 // avg 0ms (100ms spikes when loading textures the first time)
1054                 // (NOTE: probably outdated)
1055                 //TimeTaker timer2("MeshCollector building");
1056
1057                 for (u32 i = 0; i < fastfaces_new.size(); i++) {
1058                         FastFace &f = fastfaces_new[i];
1059
1060                         const u16 indices[] = {0,1,2,2,3,0};
1061                         const u16 indices_alternate[] = {0,1,3,2,3,1};
1062
1063                         if (!f.layer.texture)
1064                                 continue;
1065
1066                         const u16 *indices_p =
1067                                 f.vertex_0_2_connected ? indices : indices_alternate;
1068
1069                         collector.append(f.layer, f.vertices, 4, indices_p, 6,
1070                                 f.layernum);
1071                 }
1072         }
1073
1074         /*
1075                 Add special graphics:
1076                 - torches
1077                 - flowing water
1078                 - fences
1079                 - whatever
1080         */
1081
1082         {
1083                 MapblockMeshGenerator generator(data, &collector);
1084                 generator.generate();
1085         }
1086
1087         collector.applyTileColors();
1088
1089         /*
1090                 Convert MeshCollector to SMesh
1091         */
1092
1093         for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
1094                 for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
1095                 {
1096                         PreMeshBuffer &p = collector.prebuffers[layer][i];
1097
1098                         // Generate animation data
1099                         // - Cracks
1100                         if(p.layer.material_flags & MATERIAL_FLAG_CRACK)
1101                         {
1102                                 // Find the texture name plus ^[crack:N:
1103                                 std::ostringstream os(std::ios::binary);
1104                                 os<<m_tsrc->getTextureName(p.layer.texture_id)<<"^[crack";
1105                                 if(p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
1106                                         os<<"o";  // use ^[cracko
1107                                 os<<":"<<(u32)p.layer.animation_frame_count<<":";
1108                                 m_crack_materials.insert(std::make_pair(std::pair<u8, u32>(layer, i), os.str()));
1109                                 // Replace tile texture with the cracked one
1110                                 p.layer.texture = m_tsrc->getTextureForMesh(
1111                                                 os.str()+"0",
1112                                                 &p.layer.texture_id);
1113                         }
1114                         // - Texture animation
1115                         if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
1116                                 // Add to MapBlockMesh in order to animate these tiles
1117                                 m_animation_tiles[std::pair<u8, u32>(layer, i)] = p.layer;
1118                                 m_animation_frames[std::pair<u8, u32>(layer, i)] = 0;
1119                                 if(g_settings->getBool("desynchronize_mapblock_texture_animation")){
1120                                         // Get starting position from noise
1121                                         m_animation_frame_offsets[std::pair<u8, u32>(layer, i)] = 100000 * (2.0 + noise3d(
1122                                                         data->m_blockpos.X, data->m_blockpos.Y,
1123                                                         data->m_blockpos.Z, 0));
1124                                 } else {
1125                                         // Play all synchronized
1126                                         m_animation_frame_offsets[std::pair<u8, u32>(layer, i)] = 0;
1127                                 }
1128                                 // Replace tile texture with the first animation frame
1129                                 p.layer.texture = p.layer.frames[0].texture;
1130                         }
1131
1132                         if (!m_enable_shaders) {
1133                                 // Extract colors for day-night animation
1134                                 // Dummy sunlight to handle non-sunlit areas
1135                                 video::SColorf sunlight;
1136                                 get_sunlight_color(&sunlight, 0);
1137                                 u32 vertex_count =
1138                                         m_use_tangent_vertices ?
1139                                                 p.tangent_vertices.size() : p.vertices.size();
1140                                 for (u32 j = 0; j < vertex_count; j++) {
1141                                         video::SColor *vc;
1142                                         if (m_use_tangent_vertices) {
1143                                                 vc = &p.tangent_vertices[j].Color;
1144                                         } else {
1145                                                 vc = &p.vertices[j].Color;
1146                                         }
1147                                         video::SColor copy(*vc);
1148                                         if (vc->getAlpha() == 0) // No sunlight - no need to animate
1149                                                 final_color_blend(vc, copy, sunlight); // Finalize color
1150                                         else // Record color to animate
1151                                                 m_daynight_diffs[std::pair<u8, u32>(layer, i)][j] = copy;
1152
1153                                         // The sunlight ratio has been stored,
1154                                         // delete alpha (for the final rendering).
1155                                         vc->setAlpha(255);
1156                                 }
1157                         }
1158
1159                         // Create material
1160                         video::SMaterial material;
1161                         material.setFlag(video::EMF_LIGHTING, false);
1162                         material.setFlag(video::EMF_BACK_FACE_CULLING, true);
1163                         material.setFlag(video::EMF_BILINEAR_FILTER, false);
1164                         material.setFlag(video::EMF_FOG_ENABLE, true);
1165                         material.setTexture(0, p.layer.texture);
1166
1167                         if (m_enable_shaders) {
1168                                 material.MaterialType = m_shdrsrc->getShaderInfo(p.layer.shader_id).material;
1169                                 p.layer.applyMaterialOptionsWithShaders(material);
1170                                 if (p.layer.normal_texture) {
1171                                         material.setTexture(1, p.layer.normal_texture);
1172                                 }
1173                                 material.setTexture(2, p.layer.flags_texture);
1174                         } else {
1175                                 p.layer.applyMaterialOptions(material);
1176                         }
1177
1178                         scene::SMesh *mesh = (scene::SMesh *)m_mesh[layer];
1179
1180                         // Create meshbuffer, add to mesh
1181                         if (m_use_tangent_vertices) {
1182                                 scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
1183                                 // Set material
1184                                 buf->Material = material;
1185                                 // Add to mesh
1186                                 mesh->addMeshBuffer(buf);
1187                                 // Mesh grabbed it
1188                                 buf->drop();
1189                                 buf->append(&p.tangent_vertices[0], p.tangent_vertices.size(),
1190                                         &p.indices[0], p.indices.size());
1191                         } else {
1192                                 scene::SMeshBuffer *buf = new scene::SMeshBuffer();
1193                                 // Set material
1194                                 buf->Material = material;
1195                                 // Add to mesh
1196                                 mesh->addMeshBuffer(buf);
1197                                 // Mesh grabbed it
1198                                 buf->drop();
1199                                 buf->append(&p.vertices[0], p.vertices.size(),
1200                                         &p.indices[0], p.indices.size());
1201                         }
1202                 }
1203
1204
1205                 /*
1206                         Do some stuff to the mesh
1207                 */
1208                 m_camera_offset = camera_offset;
1209                 translateMesh(m_mesh[layer],
1210                         intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
1211
1212                 if (m_use_tangent_vertices) {
1213                         scene::IMeshManipulator* meshmanip =
1214                                 RenderingEngine::get_scene_manager()->getMeshManipulator();
1215                         meshmanip->recalculateTangents(m_mesh[layer], true, false, false);
1216                 }
1217
1218                 if (m_mesh[layer])
1219                 {
1220 #if 0
1221                         // Usually 1-700 faces and 1-7 materials
1222                         std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
1223                                         <<"and uses "<<m_mesh[layer]->getMeshBufferCount()
1224                                         <<" materials (meshbuffers)"<<std::endl;
1225 #endif
1226
1227                         // Use VBO for mesh (this just would set this for ever buffer)
1228                         if (m_enable_vbo) {
1229                                 m_mesh[layer]->setHardwareMappingHint(scene::EHM_STATIC);
1230                         }
1231                 }
1232         }
1233
1234         //std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
1235
1236         // Check if animation is required for this mesh
1237         m_has_animation =
1238                 !m_crack_materials.empty() ||
1239                 !m_daynight_diffs.empty() ||
1240                 !m_animation_tiles.empty();
1241 }
1242
1243 MapBlockMesh::~MapBlockMesh()
1244 {
1245         for (int m = 0; m < MAX_TILE_LAYERS; m++) {
1246                 if (m_enable_vbo && m_mesh[m])
1247                         for (u32 i = 0; i < m_mesh[m]->getMeshBufferCount(); i++) {
1248                                 scene::IMeshBuffer *buf = m_mesh[m]->getMeshBuffer(i);
1249                                 RenderingEngine::get_video_driver()->removeHardwareBuffer(buf);
1250                         }
1251                 m_mesh[m]->drop();
1252                 m_mesh[m] = NULL;
1253         }
1254         delete m_minimap_mapblock;
1255 }
1256
1257 bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio)
1258 {
1259         if(!m_has_animation)
1260         {
1261                 m_animation_force_timer = 100000;
1262                 return false;
1263         }
1264
1265         m_animation_force_timer = myrand_range(5, 100);
1266
1267         // Cracks
1268         if(crack != m_last_crack)
1269         {
1270                 for (std::map<std::pair<u8, u32>, std::string>::iterator i =
1271                                 m_crack_materials.begin(); i != m_crack_materials.end(); ++i) {
1272                         scene::IMeshBuffer *buf = m_mesh[i->first.first]->
1273                                 getMeshBuffer(i->first.second);
1274                         std::string basename = i->second;
1275
1276                         // Create new texture name from original
1277                         std::ostringstream os;
1278                         os<<basename<<crack;
1279                         u32 new_texture_id = 0;
1280                         video::ITexture *new_texture =
1281                                 m_tsrc->getTextureForMesh(os.str(), &new_texture_id);
1282                         buf->getMaterial().setTexture(0, new_texture);
1283
1284                         // If the current material is also animated,
1285                         // update animation info
1286                         std::map<std::pair<u8, u32>, TileLayer>::iterator anim_iter =
1287                                 m_animation_tiles.find(i->first);
1288                         if (anim_iter != m_animation_tiles.end()){
1289                                 TileLayer &tile = anim_iter->second;
1290                                 tile.texture = new_texture;
1291                                 tile.texture_id = new_texture_id;
1292                                 // force animation update
1293                                 m_animation_frames[i->first] = -1;
1294                         }
1295                 }
1296
1297                 m_last_crack = crack;
1298         }
1299
1300         // Texture animation
1301         for (std::map<std::pair<u8, u32>, TileLayer>::iterator i =
1302                         m_animation_tiles.begin(); i != m_animation_tiles.end(); ++i) {
1303                 const TileLayer &tile = i->second;
1304                 // Figure out current frame
1305                 int frameoffset = m_animation_frame_offsets[i->first];
1306                 int frame = (int)(time * 1000 / tile.animation_frame_length_ms
1307                                 + frameoffset) % tile.animation_frame_count;
1308                 // If frame doesn't change, skip
1309                 if(frame == m_animation_frames[i->first])
1310                         continue;
1311
1312                 m_animation_frames[i->first] = frame;
1313
1314                 scene::IMeshBuffer *buf = m_mesh[i->first.first]->
1315                         getMeshBuffer(i->first.second);
1316
1317                 const FrameSpec &animation_frame = tile.frames[frame];
1318                 buf->getMaterial().setTexture(0, animation_frame.texture);
1319                 if (m_enable_shaders) {
1320                         if (animation_frame.normal_texture) {
1321                                 buf->getMaterial().setTexture(1, animation_frame.normal_texture);
1322                         }
1323                         buf->getMaterial().setTexture(2, animation_frame.flags_texture);
1324                 }
1325         }
1326
1327         // Day-night transition
1328         if(!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio))
1329         {
1330                 // Force reload mesh to VBO
1331                 if (m_enable_vbo)
1332                         for (int m = 0; m < MAX_TILE_LAYERS; m++)
1333                                 m_mesh[m]->setDirty();
1334                 video::SColorf day_color;
1335                 get_sunlight_color(&day_color, daynight_ratio);
1336                 for(std::map<std::pair<u8, u32>, std::map<u32, video::SColor > >::iterator
1337                                 i = m_daynight_diffs.begin();
1338                                 i != m_daynight_diffs.end(); ++i)
1339                 {
1340                         scene::IMeshBuffer *buf = m_mesh[i->first.first]->
1341                                 getMeshBuffer(i->first.second);
1342                         video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
1343                         for(std::map<u32, video::SColor >::iterator
1344                                         j = i->second.begin();
1345                                         j != i->second.end(); ++j)
1346                         {
1347                                 final_color_blend(&(vertices[j->first].Color),
1348                                         j->second, day_color);
1349                         }
1350                 }
1351                 m_last_daynight_ratio = daynight_ratio;
1352         }
1353
1354         return true;
1355 }
1356
1357 void MapBlockMesh::updateCameraOffset(v3s16 camera_offset)
1358 {
1359         if (camera_offset != m_camera_offset) {
1360                 for (u8 layer = 0; layer < 2; layer++) {
1361                         translateMesh(m_mesh[layer],
1362                                 intToFloat(m_camera_offset - camera_offset, BS));
1363                         if (m_enable_vbo) {
1364                                 m_mesh[layer]->setDirty();
1365                         }
1366                 }
1367                 m_camera_offset = camera_offset;
1368         }
1369 }
1370
1371 /*
1372         MeshCollector
1373 */
1374
1375 void MeshCollector::append(const TileSpec &tile,
1376                 const video::S3DVertex *vertices, u32 numVertices,
1377                 const u16 *indices, u32 numIndices)
1378 {
1379         for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
1380                 const TileLayer *layer = &tile.layers[layernum];
1381                 if (layer->texture_id == 0)
1382                         continue;
1383                 append(*layer, vertices, numVertices, indices, numIndices,
1384                         layernum);
1385         }
1386 }
1387
1388 void MeshCollector::append(const TileLayer &layer,
1389                 const video::S3DVertex *vertices, u32 numVertices,
1390                 const u16 *indices, u32 numIndices, u8 layernum)
1391 {
1392         if (numIndices > 65535) {
1393                 dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
1394                 return;
1395         }
1396         std::vector<PreMeshBuffer> *buffers = &prebuffers[layernum];
1397
1398         PreMeshBuffer *p = NULL;
1399         for (u32 i = 0; i < buffers->size(); i++) {
1400                 PreMeshBuffer &pp = (*buffers)[i];
1401                 if (pp.layer != layer)
1402                         continue;
1403                 if (pp.indices.size() + numIndices > 65535)
1404                         continue;
1405
1406                 p = &pp;
1407                 break;
1408         }
1409
1410         if (p == NULL) {
1411                 PreMeshBuffer pp;
1412                 pp.layer = layer;
1413                 buffers->push_back(pp);
1414                 p = &(*buffers)[buffers->size() - 1];
1415         }
1416
1417         u32 vertex_count;
1418         if (m_use_tangent_vertices) {
1419                 vertex_count = p->tangent_vertices.size();
1420                 for (u32 i = 0; i < numVertices; i++) {
1421                         video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
1422                                 vertices[i].Color, vertices[i].TCoords);
1423                         p->tangent_vertices.push_back(vert);
1424                 }
1425         } else {
1426                 vertex_count = p->vertices.size();
1427                 for (u32 i = 0; i < numVertices; i++) {
1428                         video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
1429                                 vertices[i].Color, vertices[i].TCoords);
1430                         p->vertices.push_back(vert);
1431                 }
1432         }
1433
1434         for (u32 i = 0; i < numIndices; i++) {
1435                 u32 j = indices[i] + vertex_count;
1436                 p->indices.push_back(j);
1437         }
1438 }
1439
1440 /*
1441         MeshCollector - for meshnodes and converted drawtypes.
1442 */
1443
1444 void MeshCollector::append(const TileSpec &tile,
1445                 const video::S3DVertex *vertices, u32 numVertices,
1446                 const u16 *indices, u32 numIndices,
1447                 v3f pos, video::SColor c, u8 light_source)
1448 {
1449         for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
1450                 const TileLayer *layer = &tile.layers[layernum];
1451                 if (layer->texture_id == 0)
1452                         continue;
1453                 append(*layer, vertices, numVertices, indices, numIndices, pos,
1454                         c, light_source, layernum);
1455         }
1456 }
1457
1458 void MeshCollector::append(const TileLayer &layer,
1459                 const video::S3DVertex *vertices, u32 numVertices,
1460                 const u16 *indices, u32 numIndices,
1461                 v3f pos, video::SColor c, u8 light_source, u8 layernum)
1462 {
1463         if (numIndices > 65535) {
1464                 dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
1465                 return;
1466         }
1467         std::vector<PreMeshBuffer> *buffers = &prebuffers[layernum];
1468
1469         PreMeshBuffer *p = NULL;
1470         for (u32 i = 0; i < buffers->size(); i++) {
1471                 PreMeshBuffer &pp = (*buffers)[i];
1472                 if(pp.layer != layer)
1473                         continue;
1474                 if(pp.indices.size() + numIndices > 65535)
1475                         continue;
1476
1477                 p = &pp;
1478                 break;
1479         }
1480
1481         if (p == NULL) {
1482                 PreMeshBuffer pp;
1483                 pp.layer = layer;
1484                 buffers->push_back(pp);
1485                 p = &(*buffers)[buffers->size() - 1];
1486         }
1487
1488         video::SColor original_c = c;
1489         u32 vertex_count;
1490         if (m_use_tangent_vertices) {
1491                 vertex_count = p->tangent_vertices.size();
1492                 for (u32 i = 0; i < numVertices; i++) {
1493                         if (!light_source) {
1494                                 c = original_c;
1495                                 applyFacesShading(c, vertices[i].Normal);
1496                         }
1497                         video::S3DVertexTangents vert(vertices[i].Pos + pos,
1498                                 vertices[i].Normal, c, vertices[i].TCoords);
1499                         p->tangent_vertices.push_back(vert);
1500                 }
1501         } else {
1502                 vertex_count = p->vertices.size();
1503                 for (u32 i = 0; i < numVertices; i++) {
1504                         if (!light_source) {
1505                                 c = original_c;
1506                                 applyFacesShading(c, vertices[i].Normal);
1507                         }
1508                         video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, c,
1509                                 vertices[i].TCoords);
1510                         p->vertices.push_back(vert);
1511                 }
1512         }
1513
1514         for (u32 i = 0; i < numIndices; i++) {
1515                 u32 j = indices[i] + vertex_count;
1516                 p->indices.push_back(j);
1517         }
1518 }
1519
1520 void MeshCollector::applyTileColors()
1521 {
1522         if (m_use_tangent_vertices)
1523                 for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
1524                         for (auto &pmb : prebuffers[layer]) {
1525                                 video::SColor tc = pmb.layer.color;
1526                                 if (tc == video::SColor(0xFFFFFFFF))
1527                                         continue;
1528                                 for (auto &tangent_vertice : pmb.tangent_vertices) {
1529                                         video::SColor *c = &tangent_vertice.Color;
1530                                         c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255,
1531                                                 c->getGreen() * tc.getGreen() / 255,
1532                                                 c->getBlue() * tc.getBlue() / 255);
1533                                 }
1534                         }
1535                 }
1536         else
1537                 for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
1538                         for (auto &pmb : prebuffers[layer]) {
1539                                 video::SColor tc = pmb.layer.color;
1540                                 if (tc == video::SColor(0xFFFFFFFF))
1541                                         continue;
1542                                 for (auto &vertice : pmb.vertices) {
1543                                         video::SColor *c = &vertice.Color;
1544                                         c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255,
1545                                                 c->getGreen() * tc.getGreen() / 255,
1546                                                 c->getBlue() * tc.getBlue() / 255);
1547                                 }
1548                         }
1549                 }
1550 }
1551
1552 video::SColor encode_light(u16 light, u8 emissive_light)
1553 {
1554         // Get components
1555         u32 day = (light & 0xff);
1556         u32 night = (light >> 8);
1557         // Add emissive light
1558         night += emissive_light * 2.5f;
1559         if (night > 255)
1560                 night = 255;
1561         // Since we don't know if the day light is sunlight or
1562         // artificial light, assume it is artificial when the night
1563         // light bank is also lit.
1564         if (day < night)
1565                 day = 0;
1566         else
1567                 day = day - night;
1568         u32 sum = day + night;
1569         // Ratio of sunlight:
1570         u32 r;
1571         if (sum > 0)
1572                 r = day * 255 / sum;
1573         else
1574                 r = 0;
1575         // Average light:
1576         float b = (day + night) / 2;
1577         return video::SColor(r, b, b, b);
1578 }