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