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