@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
28
28
#include " content_mapblock.h"
29
29
#include " util/directiontables.h"
30
30
#include " client/renderingengine.h"
31
+ #include < array>
31
32
32
33
/*
33
34
MeshMakeData
@@ -68,7 +69,7 @@ void MeshMakeData::fill(MapBlock *block)
68
69
69
70
fillBlockData (v3s16 (0 ,0 ,0 ), block->getData ());
70
71
71
- // Get map for reading neigbhor blocks
72
+ // Get map for reading neighbor blocks
72
73
Map *map = block->getParent ();
73
74
74
75
for (const v3s16 &dir : g_26dirs) {
@@ -194,19 +195,9 @@ u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef)
194
195
Calculate smooth lighting at the XYZ- corner of p.
195
196
Both light banks
196
197
*/
197
- static u16 getSmoothLightCombined (const v3s16 &p, MeshMakeData *data)
198
+ static u16 getSmoothLightCombined (const v3s16 &p,
199
+ const std::array<v3s16,8 > &dirs, MeshMakeData *data, bool node_solid)
198
200
{
199
- static const v3s16 dirs8[8 ] = {
200
- v3s16 (0 ,0 ,0 ),
201
- v3s16 (0 ,0 ,1 ),
202
- v3s16 (0 ,1 ,0 ),
203
- v3s16 (0 ,1 ,1 ),
204
- v3s16 (1 ,0 ,0 ),
205
- v3s16 (1 ,1 ,0 ),
206
- v3s16 (1 ,0 ,1 ),
207
- v3s16 (1 ,1 ,1 ),
208
- };
209
-
210
201
INodeDefManager *ndef = data->m_client ->ndef ();
211
202
212
203
u16 ambient_occlusion = 0 ;
@@ -215,32 +206,58 @@ static u16 getSmoothLightCombined(const v3s16 &p, MeshMakeData *data)
215
206
u16 light_day = 0 ;
216
207
u16 light_night = 0 ;
217
208
218
- for (const v3s16 &dir : dirs8) {
219
- MapNode n = data->m_vmanip .getNodeNoExNoEmerge (p - dir);
220
-
221
- // if it's CONTENT_IGNORE we can't do any light calculations
222
- if (n.getContent () == CONTENT_IGNORE)
223
- continue ;
224
-
209
+ auto add_node = [&] (int i) -> const ContentFeatures& {
210
+ MapNode n = data->m_vmanip .getNodeNoExNoEmerge (p + dirs[i]);
225
211
const ContentFeatures &f = ndef->get (n);
226
212
if (f.light_source > light_source_max)
227
213
light_source_max = f.light_source ;
228
214
// Check f.solidness because fast-style leaves look better this way
229
215
if (f.param_type == CPT_LIGHT && f.solidness != 2 ) {
230
216
light_day += decode_light (n.getLightNoChecks (LIGHTBANK_DAY, &f));
231
- light_night += decode_light (
232
- n.getLightNoChecks (LIGHTBANK_NIGHT, &f));
217
+ light_night += decode_light (n.getLightNoChecks (LIGHTBANK_NIGHT, &f));
233
218
light_count++;
234
219
} else {
235
220
ambient_occlusion++;
236
221
}
237
- }
222
+ return f;
223
+ };
238
224
239
- if (light_count == 0 )
240
- return 0xffff ;
225
+ if (node_solid) {
226
+ ambient_occlusion = 3 ;
227
+ bool corner_obstructed = true ;
228
+ for (int i = 0 ; i < 2 ; ++i) {
229
+ if (add_node (i).light_propagates )
230
+ corner_obstructed = false ;
231
+ }
232
+ add_node (2 );
233
+ add_node (3 );
234
+ if (corner_obstructed)
235
+ ambient_occlusion++;
236
+ else
237
+ add_node (4 );
238
+ } else {
239
+ std::array<bool , 4 > obstructed = {{ 1 , 1 , 1 , 1 }};
240
+ add_node (0 );
241
+ bool opaque1 = !add_node (1 ).light_propagates ;
242
+ bool opaque2 = !add_node (2 ).light_propagates ;
243
+ bool opaque3 = !add_node (3 ).light_propagates ;
244
+ obstructed[0 ] = opaque1 && opaque2;
245
+ obstructed[1 ] = opaque1 && opaque3;
246
+ obstructed[2 ] = opaque2 && opaque3;
247
+ for (int k = 0 ; k < 4 ; ++k) {
248
+ if (obstructed[k])
249
+ ambient_occlusion++;
250
+ else if (add_node (k + 4 ).light_propagates )
251
+ obstructed[3 ] = false ;
252
+ }
253
+ }
241
254
242
- light_day /= light_count;
243
- light_night /= light_count;
255
+ if (light_count == 0 ) {
256
+ light_day = light_night = 0 ;
257
+ } else {
258
+ light_day /= light_count;
259
+ light_night /= light_count;
260
+ }
244
261
245
262
// Boost brightness around light sources
246
263
bool skip_ambient_occlusion_day = false ;
@@ -283,20 +300,70 @@ static u16 getSmoothLightCombined(const v3s16 &p, MeshMakeData *data)
283
300
/*
284
301
Calculate smooth lighting at the given corner of p.
285
302
Both light banks.
303
+ Node at p is solid, and thus the lighting is face-dependent.
286
304
*/
287
- u16 getSmoothLight ( v3s16 p, v3s16 corner, MeshMakeData *data)
305
+ u16 getSmoothLightSolid ( const v3s16 & p, const v3s16 &face_dir, const v3s16 & corner, MeshMakeData *data)
288
306
{
289
- if (corner.X == 1 )
290
- ++p.X ;
291
- // else corner.X == -1
292
- if (corner.Y == 1 )
293
- ++p.Y ;
294
- // else corner.Y == -1
295
- if (corner.Z == 1 )
296
- ++p.Z ;
297
- // else corner.Z == -1
298
-
299
- return getSmoothLightCombined (p, data);
307
+ v3s16 neighbor_offset1, neighbor_offset2;
308
+
309
+ /*
310
+ * face_dir, neighbor_offset1 and neighbor_offset2 define an
311
+ * orthonormal basis which is used to define the offsets of the 8
312
+ * surrounding nodes and to differentiate the "distance" (by going only
313
+ * along directly neighboring nodes) relative to the node at p.
314
+ * Apart from the node at p, only the 4 nodes which contain face_dir
315
+ * can contribute light.
316
+ */
317
+ if (face_dir.X != 0 ) {
318
+ neighbor_offset1 = v3s16 (0 , corner.Y , 0 );
319
+ neighbor_offset2 = v3s16 (0 , 0 , corner.Z );
320
+ } else if (face_dir.Y != 0 ) {
321
+ neighbor_offset1 = v3s16 (0 , 0 , corner.Z );
322
+ neighbor_offset2 = v3s16 (corner.X , 0 , 0 );
323
+ } else if (face_dir.Z != 0 ) {
324
+ neighbor_offset1 = v3s16 (corner.X ,0 ,0 );
325
+ neighbor_offset2 = v3s16 (0 ,corner.Y ,0 );
326
+ }
327
+
328
+ const std::array<v3s16,8 > dirs = {{
329
+ // Always shine light
330
+ neighbor_offset1 + face_dir,
331
+ neighbor_offset2 + face_dir,
332
+ v3s16 (0 ,0 ,0 ),
333
+ face_dir,
334
+
335
+ // Can be obstructed
336
+ neighbor_offset1 + neighbor_offset2 + face_dir,
337
+
338
+ // Do not shine light, only for ambient occlusion
339
+ neighbor_offset1,
340
+ neighbor_offset2,
341
+ neighbor_offset1 + neighbor_offset2
342
+ }};
343
+ return getSmoothLightCombined (p, dirs, data, true );
344
+ }
345
+
346
+ /*
347
+ Calculate smooth lighting at the given corner of p.
348
+ Both light banks.
349
+ Node at p is not solid, and the lighting is not face-dependent.
350
+ */
351
+ u16 getSmoothLightTransparent (const v3s16 &p, const v3s16 &corner, MeshMakeData *data)
352
+ {
353
+ const std::array<v3s16,8 > dirs = {{
354
+ // Always shine light
355
+ v3s16 (0 ,0 ,0 ),
356
+ v3s16 (corner.X ,0 ,0 ),
357
+ v3s16 (0 ,corner.Y ,0 ),
358
+ v3s16 (0 ,0 ,corner.Z ),
359
+
360
+ // Can be obstructed
361
+ v3s16 (corner.X ,corner.Y ,0 ),
362
+ v3s16 (corner.X ,0 ,corner.Z ),
363
+ v3s16 (0 ,corner.Y ,corner.Z ),
364
+ v3s16 (corner.X ,corner.Y ,corner.Z )
365
+ }};
366
+ return getSmoothLightCombined (p, dirs, data, false );
300
367
}
301
368
302
369
void get_sunlight_color (video::SColorf *sunlight, u32 daynight_ratio){
@@ -816,7 +883,7 @@ static void getTileInfo(
816
883
817
884
v3s16 light_p = blockpos_nodes + p_corrected;
818
885
for (u16 i = 0 ; i < 4 ; i++)
819
- lights[i] = getSmoothLight (light_p, vertex_dirs[i], data);
886
+ lights[i] = getSmoothLightSolid (light_p, face_dir_corrected , vertex_dirs[i], data);
820
887
}
821
888
}
822
889
0 commit comments