Network protocol: Document settable player collisionbox (#6168)
[oweals/minetest.git] / src / mapblock_mesh.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "mapblock_mesh.h"
21 #include "light.h"
22 #include "mapblock.h"
23 #include "map.h"
24 #include "profiler.h"
25 #include "nodedef.h"
26 #include "mesh.h"
27 #include "minimap.h"
28 #include "content_mapblock.h"
29 #include "noise.h"
30 #include "shader.h"
31 #include "settings.h"
32 #include "util/directiontables.h"
33 #include "client/renderingengine.h"
34
35 /*
36         MeshMakeData
37 */
38
39 MeshMakeData::MeshMakeData(Client *client, bool use_shaders,
40                 bool use_tangent_vertices):
41         m_client(client),
42         m_use_shaders(use_shaders),
43         m_use_tangent_vertices(use_tangent_vertices)
44 {}
45
46 void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
47 {
48         m_blockpos = blockpos;
49
50         v3s16 blockpos_nodes = m_blockpos*MAP_BLOCKSIZE;
51
52         m_vmanip.clear();
53         VoxelArea voxel_area(blockpos_nodes - v3s16(1,1,1) * MAP_BLOCKSIZE,
54                         blockpos_nodes + v3s16(1,1,1) * MAP_BLOCKSIZE*2-v3s16(1,1,1));
55         m_vmanip.addArea(voxel_area);
56 }
57
58 void MeshMakeData::fillBlockData(const v3s16 &block_offset, MapNode *data)
59 {
60         v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
61         VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));
62
63         v3s16 bp = m_blockpos + block_offset;
64         v3s16 blockpos_nodes = bp * MAP_BLOCKSIZE;
65         m_vmanip.copyFrom(data, data_area, v3s16(0,0,0), blockpos_nodes, data_size);
66 }
67
68 void MeshMakeData::fill(MapBlock *block)
69 {
70         fillBlockDataBegin(block->getPos());
71
72         fillBlockData(v3s16(0,0,0), block->getData());
73
74         // Get map for reading neigbhor blocks
75         Map *map = block->getParent();
76
77         for (u16 i=0; i<26; i++) {
78                 const v3s16 &dir = g_26dirs[i];
79                 v3s16 bp = m_blockpos + dir;
80                 MapBlock *b = map->getBlockNoCreateNoEx(bp);
81                 if(b)
82                         fillBlockData(dir, b->getData());
83         }
84 }
85
86 void MeshMakeData::fillSingleNode(MapNode *node)
87 {
88         m_blockpos = v3s16(0,0,0);
89
90         v3s16 blockpos_nodes = v3s16(0,0,0);
91         VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE,
92                         blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1));
93         s32 volume = area.getVolume();
94         s32 our_node_index = area.index(1,1,1);
95
96         // Allocate this block + neighbors
97         m_vmanip.clear();
98         m_vmanip.addArea(area);
99
100         // Fill in data
101         MapNode *data = new MapNode[volume];
102         for(s32 i = 0; i < volume; i++)
103         {
104                 if(i == our_node_index)
105                 {
106                         data[i] = *node;
107                 }
108                 else
109                 {
110                         data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0);
111                 }
112         }
113         m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent());
114         delete[] data;
115 }
116
117 void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
118 {
119         if(crack_level >= 0)
120                 m_crack_pos_relative = crack_pos - m_blockpos*MAP_BLOCKSIZE;
121 }
122
123 void MeshMakeData::setSmoothLighting(bool smooth_lighting)
124 {
125         m_smooth_lighting = smooth_lighting;
126 }
127
128 /*
129         Light and vertex color functions
130 */
131
132 /*
133         Calculate non-smooth lighting at interior of node.
134         Single light bank.
135 */
136 static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
137                 INodeDefManager *ndef)
138 {
139         u8 light = n.getLight(bank, ndef);
140
141         while(increment > 0)
142         {
143                 light = undiminish_light(light);
144                 --increment;
145         }
146         while(increment < 0)
147         {
148                 light = diminish_light(light);
149                 ++increment;
150         }
151
152         return decode_light(light);
153 }
154
155 /*
156         Calculate non-smooth lighting at interior of node.
157         Both light banks.
158 */
159 u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef)
160 {
161         u16 day = getInteriorLight(LIGHTBANK_DAY, n, increment, ndef);
162         u16 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, ndef);
163         return day | (night << 8);
164 }
165
166 /*
167         Calculate non-smooth lighting at face of node.
168         Single light bank.
169 */
170 static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
171                 v3s16 face_dir, INodeDefManager *ndef)
172 {
173         u8 light;
174         u8 l1 = n.getLight(bank, ndef);
175         u8 l2 = n2.getLight(bank, ndef);
176         if(l1 > l2)
177                 light = l1;
178         else
179                 light = l2;
180
181         // Boost light level for light sources
182         u8 light_source = MYMAX(ndef->get(n).light_source,
183                         ndef->get(n2).light_source);
184         if(light_source > light)
185                 light = light_source;
186
187         return decode_light(light);
188 }
189
190 /*
191         Calculate non-smooth lighting at face of node.
192         Both light banks.
193 */
194 u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef)
195 {
196         u16 day = getFaceLight(LIGHTBANK_DAY, n, n2, face_dir, ndef);
197         u16 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, ndef);
198         return day | (night << 8);
199 }
200
201 /*
202         Calculate smooth lighting at the XYZ- corner of p.
203         Both light banks
204 */
205 static u16 getSmoothLightCombined(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_tsrc(data->m_client->getTextureSource()),
1012         m_shdrsrc(data->m_client->getShaderSource()),
1013         m_animation_force_timer(0), // force initial animation
1014         m_last_crack(-1),
1015         m_last_daynight_ratio((u32) -1)
1016 {
1017         for (int m = 0; m < MAX_TILE_LAYERS; m++)
1018                 m_mesh[m] = new scene::SMesh();
1019         m_enable_shaders = data->m_use_shaders;
1020         m_use_tangent_vertices = data->m_use_tangent_vertices;
1021         m_enable_vbo = g_settings->getBool("enable_vbo");
1022
1023         if (g_settings->getBool("enable_minimap")) {
1024                 m_minimap_mapblock = new MinimapMapblock;
1025                 m_minimap_mapblock->getMinimapNodes(
1026                         &data->m_vmanip, data->m_blockpos * MAP_BLOCKSIZE);
1027         }
1028
1029         // 4-21ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
1030         // 24-155ms for MAP_BLOCKSIZE=32  (NOTE: probably outdated)
1031         //TimeTaker timer1("MapBlockMesh()");
1032
1033         std::vector<FastFace> fastfaces_new;
1034         fastfaces_new.reserve(512);
1035
1036         /*
1037                 We are including the faces of the trailing edges of the block.
1038                 This means that when something changes, the caller must
1039                 also update the meshes of the blocks at the leading edges.
1040
1041                 NOTE: This is the slowest part of this method.
1042         */
1043         {
1044                 // 4-23ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
1045                 //TimeTaker timer2("updateAllFastFaceRows()");
1046                 updateAllFastFaceRows(data, fastfaces_new);
1047         }
1048         // End of slow part
1049
1050         /*
1051                 Convert FastFaces to MeshCollector
1052         */
1053
1054         MeshCollector collector(m_use_tangent_vertices);
1055
1056         {
1057                 // avg 0ms (100ms spikes when loading textures the first time)
1058                 // (NOTE: probably outdated)
1059                 //TimeTaker timer2("MeshCollector building");
1060
1061                 for (u32 i = 0; i < fastfaces_new.size(); i++) {
1062                         FastFace &f = fastfaces_new[i];
1063
1064                         const u16 indices[] = {0,1,2,2,3,0};
1065                         const u16 indices_alternate[] = {0,1,3,2,3,1};
1066
1067                         if (!f.layer.texture)
1068                                 continue;
1069
1070                         const u16 *indices_p =
1071                                 f.vertex_0_2_connected ? indices : indices_alternate;
1072
1073                         collector.append(f.layer, f.vertices, 4, indices_p, 6,
1074                                 f.layernum);
1075                 }
1076         }
1077
1078         /*
1079                 Add special graphics:
1080                 - torches
1081                 - flowing water
1082                 - fences
1083                 - whatever
1084         */
1085
1086         {
1087                 MapblockMeshGenerator generator(data, &collector);
1088                 generator.generate();
1089         }
1090
1091         collector.applyTileColors();
1092
1093         /*
1094                 Convert MeshCollector to SMesh
1095         */
1096
1097         for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
1098                 for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
1099                 {
1100                         PreMeshBuffer &p = collector.prebuffers[layer][i];
1101
1102                         // Generate animation data
1103                         // - Cracks
1104                         if(p.layer.material_flags & MATERIAL_FLAG_CRACK)
1105                         {
1106                                 // Find the texture name plus ^[crack:N:
1107                                 std::ostringstream os(std::ios::binary);
1108                                 os<<m_tsrc->getTextureName(p.layer.texture_id)<<"^[crack";
1109                                 if(p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
1110                                         os<<"o";  // use ^[cracko
1111                                 os<<":"<<(u32)p.layer.animation_frame_count<<":";
1112                                 m_crack_materials.insert(std::make_pair(std::pair<u8, u32>(layer, i), os.str()));
1113                                 // Replace tile texture with the cracked one
1114                                 p.layer.texture = m_tsrc->getTextureForMesh(
1115                                                 os.str()+"0",
1116                                                 &p.layer.texture_id);
1117                         }
1118                         // - Texture animation
1119                         if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
1120                                 // Add to MapBlockMesh in order to animate these tiles
1121                                 m_animation_tiles[std::pair<u8, u32>(layer, i)] = p.layer;
1122                                 m_animation_frames[std::pair<u8, u32>(layer, i)] = 0;
1123                                 if(g_settings->getBool("desynchronize_mapblock_texture_animation")){
1124                                         // Get starting position from noise
1125                                         m_animation_frame_offsets[std::pair<u8, u32>(layer, i)] = 100000 * (2.0 + noise3d(
1126                                                         data->m_blockpos.X, data->m_blockpos.Y,
1127                                                         data->m_blockpos.Z, 0));
1128                                 } else {
1129                                         // Play all synchronized
1130                                         m_animation_frame_offsets[std::pair<u8, u32>(layer, i)] = 0;
1131                                 }
1132                                 // Replace tile texture with the first animation frame
1133                                 p.layer.texture = p.layer.frames[0].texture;
1134                         }
1135
1136                         if (!m_enable_shaders) {
1137                                 // Extract colors for day-night animation
1138                                 // Dummy sunlight to handle non-sunlit areas
1139                                 video::SColorf sunlight;
1140                                 get_sunlight_color(&sunlight, 0);
1141                                 u32 vertex_count =
1142                                         m_use_tangent_vertices ?
1143                                                 p.tangent_vertices.size() : p.vertices.size();
1144                                 for (u32 j = 0; j < vertex_count; j++) {
1145                                         video::SColor *vc;
1146                                         if (m_use_tangent_vertices) {
1147                                                 vc = &p.tangent_vertices[j].Color;
1148                                         } else {
1149                                                 vc = &p.vertices[j].Color;
1150                                         }
1151                                         video::SColor copy(*vc);
1152                                         if (vc->getAlpha() == 0) // No sunlight - no need to animate
1153                                                 final_color_blend(vc, copy, sunlight); // Finalize color
1154                                         else // Record color to animate
1155                                                 m_daynight_diffs[std::pair<u8, u32>(layer, i)][j] = copy;
1156
1157                                         // The sunlight ratio has been stored,
1158                                         // delete alpha (for the final rendering).
1159                                         vc->setAlpha(255);
1160                                 }
1161                         }
1162
1163                         // Create material
1164                         video::SMaterial material;
1165                         material.setFlag(video::EMF_LIGHTING, false);
1166                         material.setFlag(video::EMF_BACK_FACE_CULLING, true);
1167                         material.setFlag(video::EMF_BILINEAR_FILTER, false);
1168                         material.setFlag(video::EMF_FOG_ENABLE, true);
1169                         material.setTexture(0, p.layer.texture);
1170
1171                         if (m_enable_shaders) {
1172                                 material.MaterialType = m_shdrsrc->getShaderInfo(p.layer.shader_id).material;
1173                                 p.layer.applyMaterialOptionsWithShaders(material);
1174                                 if (p.layer.normal_texture) {
1175                                         material.setTexture(1, p.layer.normal_texture);
1176                                 }
1177                                 material.setTexture(2, p.layer.flags_texture);
1178                         } else {
1179                                 p.layer.applyMaterialOptions(material);
1180                         }
1181
1182                         scene::SMesh *mesh = (scene::SMesh *)m_mesh[layer];
1183
1184                         // Create meshbuffer, add to mesh
1185                         if (m_use_tangent_vertices) {
1186                                 scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
1187                                 // Set material
1188                                 buf->Material = material;
1189                                 // Add to mesh
1190                                 mesh->addMeshBuffer(buf);
1191                                 // Mesh grabbed it
1192                                 buf->drop();
1193                                 buf->append(&p.tangent_vertices[0], p.tangent_vertices.size(),
1194                                         &p.indices[0], p.indices.size());
1195                         } else {
1196                                 scene::SMeshBuffer *buf = new scene::SMeshBuffer();
1197                                 // Set material
1198                                 buf->Material = material;
1199                                 // Add to mesh
1200                                 mesh->addMeshBuffer(buf);
1201                                 // Mesh grabbed it
1202                                 buf->drop();
1203                                 buf->append(&p.vertices[0], p.vertices.size(),
1204                                         &p.indices[0], p.indices.size());
1205                         }
1206                 }
1207
1208
1209                 /*
1210                         Do some stuff to the mesh
1211                 */
1212                 m_camera_offset = camera_offset;
1213                 translateMesh(m_mesh[layer],
1214                         intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
1215
1216                 if (m_use_tangent_vertices) {
1217                         scene::IMeshManipulator* meshmanip =
1218                                 RenderingEngine::get_scene_manager()->getMeshManipulator();
1219                         meshmanip->recalculateTangents(m_mesh[layer], true, false, false);
1220                 }
1221
1222                 if (m_mesh[layer])
1223                 {
1224 #if 0
1225                         // Usually 1-700 faces and 1-7 materials
1226                         std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
1227                                         <<"and uses "<<m_mesh[layer]->getMeshBufferCount()
1228                                         <<" materials (meshbuffers)"<<std::endl;
1229 #endif
1230
1231                         // Use VBO for mesh (this just would set this for ever buffer)
1232                         if (m_enable_vbo) {
1233                                 m_mesh[layer]->setHardwareMappingHint(scene::EHM_STATIC);
1234                         }
1235                 }
1236         }
1237
1238         //std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
1239
1240         // Check if animation is required for this mesh
1241         m_has_animation =
1242                 !m_crack_materials.empty() ||
1243                 !m_daynight_diffs.empty() ||
1244                 !m_animation_tiles.empty();
1245 }
1246
1247 MapBlockMesh::~MapBlockMesh()
1248 {
1249         for (int m = 0; m < MAX_TILE_LAYERS; m++) {
1250                 if (m_enable_vbo && m_mesh[m])
1251                         for (u32 i = 0; i < m_mesh[m]->getMeshBufferCount(); i++) {
1252                                 scene::IMeshBuffer *buf = m_mesh[m]->getMeshBuffer(i);
1253                                 RenderingEngine::get_video_driver()->removeHardwareBuffer(buf);
1254                         }
1255                 m_mesh[m]->drop();
1256                 m_mesh[m] = NULL;
1257         }
1258         delete m_minimap_mapblock;
1259 }
1260
1261 bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio)
1262 {
1263         if(!m_has_animation)
1264         {
1265                 m_animation_force_timer = 100000;
1266                 return false;
1267         }
1268
1269         m_animation_force_timer = myrand_range(5, 100);
1270
1271         // Cracks
1272         if(crack != m_last_crack)
1273         {
1274                 for (std::map<std::pair<u8, u32>, std::string>::iterator i =
1275                                 m_crack_materials.begin(); i != m_crack_materials.end(); ++i) {
1276                         scene::IMeshBuffer *buf = m_mesh[i->first.first]->
1277                                 getMeshBuffer(i->first.second);
1278                         std::string basename = i->second;
1279
1280                         // Create new texture name from original
1281                         std::ostringstream os;
1282                         os<<basename<<crack;
1283                         u32 new_texture_id = 0;
1284                         video::ITexture *new_texture =
1285                                 m_tsrc->getTextureForMesh(os.str(), &new_texture_id);
1286                         buf->getMaterial().setTexture(0, new_texture);
1287
1288                         // If the current material is also animated,
1289                         // update animation info
1290                         std::map<std::pair<u8, u32>, TileLayer>::iterator anim_iter =
1291                                 m_animation_tiles.find(i->first);
1292                         if (anim_iter != m_animation_tiles.end()){
1293                                 TileLayer &tile = anim_iter->second;
1294                                 tile.texture = new_texture;
1295                                 tile.texture_id = new_texture_id;
1296                                 // force animation update
1297                                 m_animation_frames[i->first] = -1;
1298                         }
1299                 }
1300
1301                 m_last_crack = crack;
1302         }
1303
1304         // Texture animation
1305         for (std::map<std::pair<u8, u32>, TileLayer>::iterator i =
1306                         m_animation_tiles.begin(); i != m_animation_tiles.end(); ++i) {
1307                 const TileLayer &tile = i->second;
1308                 // Figure out current frame
1309                 int frameoffset = m_animation_frame_offsets[i->first];
1310                 int frame = (int)(time * 1000 / tile.animation_frame_length_ms
1311                                 + frameoffset) % tile.animation_frame_count;
1312                 // If frame doesn't change, skip
1313                 if(frame == m_animation_frames[i->first])
1314                         continue;
1315
1316                 m_animation_frames[i->first] = frame;
1317
1318                 scene::IMeshBuffer *buf = m_mesh[i->first.first]->
1319                         getMeshBuffer(i->first.second);
1320
1321                 const FrameSpec &animation_frame = tile.frames[frame];
1322                 buf->getMaterial().setTexture(0, animation_frame.texture);
1323                 if (m_enable_shaders) {
1324                         if (animation_frame.normal_texture) {
1325                                 buf->getMaterial().setTexture(1, animation_frame.normal_texture);
1326                         }
1327                         buf->getMaterial().setTexture(2, animation_frame.flags_texture);
1328                 }
1329         }
1330
1331         // Day-night transition
1332         if(!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio))
1333         {
1334                 // Force reload mesh to VBO
1335                 if (m_enable_vbo)
1336                         for (int m = 0; m < MAX_TILE_LAYERS; m++)
1337                                 m_mesh[m]->setDirty();
1338                 video::SColorf day_color;
1339                 get_sunlight_color(&day_color, daynight_ratio);
1340                 for(std::map<std::pair<u8, u32>, std::map<u32, video::SColor > >::iterator
1341                                 i = m_daynight_diffs.begin();
1342                                 i != m_daynight_diffs.end(); ++i)
1343                 {
1344                         scene::IMeshBuffer *buf = m_mesh[i->first.first]->
1345                                 getMeshBuffer(i->first.second);
1346                         video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
1347                         for(std::map<u32, video::SColor >::iterator
1348                                         j = i->second.begin();
1349                                         j != i->second.end(); ++j)
1350                         {
1351                                 final_color_blend(&(vertices[j->first].Color),
1352                                         j->second, day_color);
1353                         }
1354                 }
1355                 m_last_daynight_ratio = daynight_ratio;
1356         }
1357
1358         return true;
1359 }
1360
1361 void MapBlockMesh::updateCameraOffset(v3s16 camera_offset)
1362 {
1363         if (camera_offset != m_camera_offset) {
1364                 for (u8 layer = 0; layer < 2; layer++) {
1365                         translateMesh(m_mesh[layer],
1366                                 intToFloat(m_camera_offset - camera_offset, BS));
1367                         if (m_enable_vbo) {
1368                                 m_mesh[layer]->setDirty();
1369                         }
1370                 }
1371                 m_camera_offset = camera_offset;
1372         }
1373 }
1374
1375 /*
1376         MeshCollector
1377 */
1378
1379 void MeshCollector::append(const TileSpec &tile,
1380                 const video::S3DVertex *vertices, u32 numVertices,
1381                 const u16 *indices, u32 numIndices)
1382 {
1383         for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
1384                 const TileLayer *layer = &tile.layers[layernum];
1385                 if (layer->texture_id == 0)
1386                         continue;
1387                 append(*layer, vertices, numVertices, indices, numIndices,
1388                         layernum);
1389         }
1390 }
1391
1392 void MeshCollector::append(const TileLayer &layer,
1393                 const video::S3DVertex *vertices, u32 numVertices,
1394                 const u16 *indices, u32 numIndices, u8 layernum)
1395 {
1396         if (numIndices > 65535) {
1397                 dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
1398                 return;
1399         }
1400         std::vector<PreMeshBuffer> *buffers = &prebuffers[layernum];
1401
1402         PreMeshBuffer *p = NULL;
1403         for (u32 i = 0; i < buffers->size(); i++) {
1404                 PreMeshBuffer &pp = (*buffers)[i];
1405                 if (pp.layer != layer)
1406                         continue;
1407                 if (pp.indices.size() + numIndices > 65535)
1408                         continue;
1409
1410                 p = &pp;
1411                 break;
1412         }
1413
1414         if (p == NULL) {
1415                 PreMeshBuffer pp;
1416                 pp.layer = layer;
1417                 buffers->push_back(pp);
1418                 p = &(*buffers)[buffers->size() - 1];
1419         }
1420
1421         u32 vertex_count;
1422         if (m_use_tangent_vertices) {
1423                 vertex_count = p->tangent_vertices.size();
1424                 for (u32 i = 0; i < numVertices; i++) {
1425                         video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
1426                                 vertices[i].Color, vertices[i].TCoords);
1427                         p->tangent_vertices.push_back(vert);
1428                 }
1429         } else {
1430                 vertex_count = p->vertices.size();
1431                 for (u32 i = 0; i < numVertices; i++) {
1432                         video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
1433                                 vertices[i].Color, vertices[i].TCoords);
1434                         p->vertices.push_back(vert);
1435                 }
1436         }
1437
1438         for (u32 i = 0; i < numIndices; i++) {
1439                 u32 j = indices[i] + vertex_count;
1440                 p->indices.push_back(j);
1441         }
1442 }
1443
1444 /*
1445         MeshCollector - for meshnodes and converted drawtypes.
1446 */
1447
1448 void MeshCollector::append(const TileSpec &tile,
1449                 const video::S3DVertex *vertices, u32 numVertices,
1450                 const u16 *indices, u32 numIndices,
1451                 v3f pos, video::SColor c, u8 light_source)
1452 {
1453         for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
1454                 const TileLayer *layer = &tile.layers[layernum];
1455                 if (layer->texture_id == 0)
1456                         continue;
1457                 append(*layer, vertices, numVertices, indices, numIndices, pos,
1458                         c, light_source, layernum);
1459         }
1460 }
1461
1462 void MeshCollector::append(const TileLayer &layer,
1463                 const video::S3DVertex *vertices, u32 numVertices,
1464                 const u16 *indices, u32 numIndices,
1465                 v3f pos, video::SColor c, u8 light_source, u8 layernum)
1466 {
1467         if (numIndices > 65535) {
1468                 dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
1469                 return;
1470         }
1471         std::vector<PreMeshBuffer> *buffers = &prebuffers[layernum];
1472
1473         PreMeshBuffer *p = NULL;
1474         for (u32 i = 0; i < buffers->size(); i++) {
1475                 PreMeshBuffer &pp = (*buffers)[i];
1476                 if(pp.layer != layer)
1477                         continue;
1478                 if(pp.indices.size() + numIndices > 65535)
1479                         continue;
1480
1481                 p = &pp;
1482                 break;
1483         }
1484
1485         if (p == NULL) {
1486                 PreMeshBuffer pp;
1487                 pp.layer = layer;
1488                 buffers->push_back(pp);
1489                 p = &(*buffers)[buffers->size() - 1];
1490         }
1491
1492         video::SColor original_c = c;
1493         u32 vertex_count;
1494         if (m_use_tangent_vertices) {
1495                 vertex_count = p->tangent_vertices.size();
1496                 for (u32 i = 0; i < numVertices; i++) {
1497                         if (!light_source) {
1498                                 c = original_c;
1499                                 applyFacesShading(c, vertices[i].Normal);
1500                         }
1501                         video::S3DVertexTangents vert(vertices[i].Pos + pos,
1502                                 vertices[i].Normal, c, vertices[i].TCoords);
1503                         p->tangent_vertices.push_back(vert);
1504                 }
1505         } else {
1506                 vertex_count = p->vertices.size();
1507                 for (u32 i = 0; i < numVertices; i++) {
1508                         if (!light_source) {
1509                                 c = original_c;
1510                                 applyFacesShading(c, vertices[i].Normal);
1511                         }
1512                         video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, c,
1513                                 vertices[i].TCoords);
1514                         p->vertices.push_back(vert);
1515                 }
1516         }
1517
1518         for (u32 i = 0; i < numIndices; i++) {
1519                 u32 j = indices[i] + vertex_count;
1520                 p->indices.push_back(j);
1521         }
1522 }
1523
1524 void MeshCollector::applyTileColors()
1525 {
1526         if (m_use_tangent_vertices)
1527                 for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
1528                         std::vector<PreMeshBuffer> *p = &prebuffers[layer];
1529                         for (std::vector<PreMeshBuffer>::iterator it = p->begin();
1530                                         it != p->end(); ++it) {
1531                                 video::SColor tc = it->layer.color;
1532                                 if (tc == video::SColor(0xFFFFFFFF))
1533                                         continue;
1534                                 for (u32 index = 0; index < it->tangent_vertices.size(); index++) {
1535                                         video::SColor *c = &it->tangent_vertices[index].Color;
1536                                         c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255,
1537                                                 c->getGreen() * tc.getGreen() / 255,
1538                                                 c->getBlue() * tc.getBlue() / 255);
1539                                 }
1540                         }
1541                 }
1542         else
1543                 for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
1544                         std::vector<PreMeshBuffer> *p = &prebuffers[layer];
1545                         for (std::vector<PreMeshBuffer>::iterator it = p->begin();
1546                                         it != p->end(); ++it) {
1547                                 video::SColor tc = it->layer.color;
1548                                 if (tc == video::SColor(0xFFFFFFFF))
1549                                         continue;
1550                                 for (u32 index = 0; index < it->vertices.size(); index++) {
1551                                         video::SColor *c = &it->vertices[index].Color;
1552                                         c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255,
1553                                                 c->getGreen() * tc.getGreen() / 255,
1554                                                 c->getBlue() * tc.getBlue() / 255);
1555                                 }
1556                         }
1557                 }
1558 }
1559
1560 video::SColor encode_light(u16 light, u8 emissive_light)
1561 {
1562         // Get components
1563         u32 day = (light & 0xff);
1564         u32 night = (light >> 8);
1565         // Add emissive light
1566         night += emissive_light * 2.5f;
1567         if (night > 255)
1568                 night = 255;
1569         // Since we don't know if the day light is sunlight or
1570         // artificial light, assume it is artificial when the night
1571         // light bank is also lit.
1572         if (day < night)
1573                 day = 0;
1574         else
1575                 day = day - night;
1576         u32 sum = day + night;
1577         // Ratio of sunlight:
1578         u32 r;
1579         if (sum > 0)
1580                 r = day * 255 / sum;
1581         else
1582                 r = 0;
1583         // Average light:
1584         float b = (day + night) / 2;
1585         return video::SColor(r, b, b, b);
1586 }