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