Both light banks
*/
static u16 getSmoothLightCombined(const v3s16 &p,
- const std::array<v3s16,8> &dirs, MeshMakeData *data, bool node_solid)
+ const std::array<v3s16,8> &dirs, MeshMakeData *data)
{
INodeDefManager *ndef = data->m_client->ndef();
u16 light_day = 0;
u16 light_night = 0;
- auto add_node = [&] (int i) -> const ContentFeatures& {
+ auto add_node = [&] (u8 i, bool obstructed = false) -> bool {
+ if (obstructed) {
+ ambient_occlusion++;
+ return false;
+ }
MapNode n = data->m_vmanip.getNodeNoExNoEmerge(p + dirs[i]);
+ if (n.getContent() == CONTENT_IGNORE)
+ return true;
const ContentFeatures &f = ndef->get(n);
if (f.light_source > light_source_max)
light_source_max = f.light_source;
} else {
ambient_occlusion++;
}
- return f;
+ return f.light_propagates;
};
- if (node_solid) {
- ambient_occlusion = 3;
- bool corner_obstructed = true;
- for (int i = 0; i < 2; ++i) {
- if (add_node(i).light_propagates)
- corner_obstructed = false;
- }
- add_node(2);
- add_node(3);
- if (corner_obstructed)
- ambient_occlusion++;
- else
- add_node(4);
- } else {
- std::array<bool, 4> obstructed = {{ 1, 1, 1, 1 }};
- add_node(0);
- bool opaque1 = !add_node(1).light_propagates;
- bool opaque2 = !add_node(2).light_propagates;
- bool opaque3 = !add_node(3).light_propagates;
- obstructed[0] = opaque1 && opaque2;
- obstructed[1] = opaque1 && opaque3;
- obstructed[2] = opaque2 && opaque3;
- for (int k = 0; k < 4; ++k) {
- if (obstructed[k])
- ambient_occlusion++;
- else if (add_node(k + 4).light_propagates)
- obstructed[3] = false;
- }
+ std::array<bool, 4> obstructed = {{ 1, 1, 1, 1 }};
+ add_node(0);
+ bool opaque1 = !add_node(1);
+ bool opaque2 = !add_node(2);
+ bool opaque3 = !add_node(3);
+ obstructed[0] = opaque1 && opaque2;
+ obstructed[1] = opaque1 && opaque3;
+ obstructed[2] = opaque2 && opaque3;
+ for (u8 k = 0; k < 3; ++k)
+ if (add_node(k + 4, obstructed[k]))
+ obstructed[3] = false;
+ if (add_node(7, obstructed[3])) { // wrap light around nodes
+ ambient_occlusion -= 3;
+ for (u8 k = 0; k < 3; ++k)
+ add_node(k + 4, !obstructed[k]);
}
if (light_count == 0) {
g_settings->getFloat("ambient_occlusion_gamma"), 0.25, 4.0);
// Table of gamma space multiply factors.
- static const float light_amount[3] = {
+ static thread_local const float light_amount[3] = {
powf(0.75, 1.0 / ao_gamma),
powf(0.5, 1.0 / ao_gamma),
powf(0.25, 1.0 / ao_gamma)
*/
u16 getSmoothLightSolid(const v3s16 &p, const v3s16 &face_dir, const v3s16 &corner, MeshMakeData *data)
{
- v3s16 neighbor_offset1, neighbor_offset2;
-
- /*
- * face_dir, neighbor_offset1 and neighbor_offset2 define an
- * orthonormal basis which is used to define the offsets of the 8
- * surrounding nodes and to differentiate the "distance" (by going only
- * along directly neighboring nodes) relative to the node at p.
- * Apart from the node at p, only the 4 nodes which contain face_dir
- * can contribute light.
- */
- if (face_dir.X != 0) {
- neighbor_offset1 = v3s16(0, corner.Y, 0);
- neighbor_offset2 = v3s16(0, 0, corner.Z);
- } else if (face_dir.Y != 0) {
- neighbor_offset1 = v3s16(0, 0, corner.Z);
- neighbor_offset2 = v3s16(corner.X, 0, 0);
- } else if (face_dir.Z != 0) {
- neighbor_offset1 = v3s16(corner.X,0,0);
- neighbor_offset2 = v3s16(0,corner.Y,0);
- }
-
- const std::array<v3s16,8> dirs = {{
- // Always shine light
- neighbor_offset1 + face_dir,
- neighbor_offset2 + face_dir,
- v3s16(0,0,0),
- face_dir,
-
- // Can be obstructed
- neighbor_offset1 + neighbor_offset2 + face_dir,
-
- // Do not shine light, only for ambient occlusion
- neighbor_offset1,
- neighbor_offset2,
- neighbor_offset1 + neighbor_offset2
- }};
- return getSmoothLightCombined(p, dirs, data, true);
+ return getSmoothLightTransparent(p + face_dir, corner - 2 * face_dir, data);
}
/*
v3s16(0,corner.Y,corner.Z),
v3s16(corner.X,corner.Y,corner.Z)
}};
- return getSmoothLightCombined(p, dirs, data, false);
+ return getSmoothLightCombined(p, dirs, data);
}
void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){
}
}
+static void getNodeTextureCoords(v3f base, const v3f &scale, v3s16 dir, float *u, float *v)
+{
+ if (dir.X > 0 || dir.Y > 0 || dir.Z < 0)
+ base -= scale;
+ if (dir == v3s16(0,0,1)) {
+ *u = -base.X - 1;
+ *v = -base.Y - 1;
+ } else if (dir == v3s16(0,0,-1)) {
+ *u = base.X + 1;
+ *v = -base.Y - 2;
+ } else if (dir == v3s16(1,0,0)) {
+ *u = base.Z + 1;
+ *v = -base.Y - 2;
+ } else if (dir == v3s16(-1,0,0)) {
+ *u = -base.Z - 1;
+ *v = -base.Y - 1;
+ } else if (dir == v3s16(0,1,0)) {
+ *u = base.X + 1;
+ *v = -base.Z - 2;
+ } else if (dir == v3s16(0,-1,0)) {
+ *u = base.X;
+ *v = base.Z;
+ }
+}
+
struct FastFace
{
TileLayer layer;
*/
bool vertex_0_2_connected;
u8 layernum;
+ bool world_aligned;
};
static void makeFastFace(const TileSpec &tile, u16 li0, u16 li1, u16 li2, u16 li3,
- const v3f &p, v3s16 dir, v3f scale, std::vector<FastFace> &dest)
+ v3f tp, v3f p, v3s16 dir, v3f scale, std::vector<FastFace> &dest)
{
// Position is at the center of the cube.
v3f pos = p * BS;
v3f vertex_pos[4];
v3s16 vertex_dirs[4];
getNodeVertexDirs(dir, vertex_dirs);
+ if (tile.world_aligned)
+ getNodeTextureCoords(tp, scale, dir, &x0, &y0);
v3s16 t;
u16 t1;
face.layer = *layer;
face.layernum = layernum;
+
+ face.world_aligned = tile.world_aligned;
}
}
};
u16 tile_index = facedir * 16 + dir_i;
getNodeTileN(mn, p, dir_to_tile[tile_index], data, tile);
- tile.rotation = dir_to_tile[tile_index + 1];
+ tile.rotation = tile.world_aligned ? 0 : dir_to_tile[tile_index + 1];
}
static void getTileInfo(
scale.Z = continuous_tiles_count;
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
- sp, face_dir_corrected, scale, dest);
+ pf, sp, face_dir_corrected, scale, dest);
g_profiler->avg("Meshgen: faces drawn by tiling", 0);
for (int i = 1; i < continuous_tiles_count; i++)
f.vertex_0_2_connected ? indices : indices_alternate;
collector.append(f.layer, f.vertices, 4, indices_p, 6,
- f.layernum);
+ f.layernum, f.world_aligned);
}
}
os << m_tsrc->getTextureName(p.layer.texture_id) << "^[crack";
if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
os << "o"; // use ^[cracko
+ u8 tiles = p.layer.scale;
+ if (tiles > 1)
+ os << ":" << (u32)tiles;
os << ":" << (u32)p.layer.animation_frame_count << ":";
m_crack_materials.insert(std::make_pair(
std::pair<u8, u32>(layer, i), os.str()));
const TileLayer *layer = &tile.layers[layernum];
if (layer->texture_id == 0)
continue;
- append(*layer, vertices, numVertices, indices, numIndices, layernum);
+ append(*layer, vertices, numVertices, indices, numIndices,
+ layernum, tile.world_aligned);
}
}
void MeshCollector::append(const TileLayer &layer,
const video::S3DVertex *vertices, u32 numVertices,
- const u16 *indices, u32 numIndices, u8 layernum)
+ const u16 *indices, u32 numIndices, u8 layernum,
+ bool use_scale)
{
if (numIndices > 65535) {
dstream << "FIXME: MeshCollector::append() called with numIndices="
p = &(*buffers)[buffers->size() - 1];
}
+ f32 scale = 1.0;
+ if (use_scale)
+ scale = 1.0 / layer.scale;
+
u32 vertex_count;
if (m_use_tangent_vertices) {
vertex_count = p->tangent_vertices.size();
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
- vertices[i].Color, vertices[i].TCoords);
+ vertices[i].Color, scale * vertices[i].TCoords);
p->tangent_vertices.push_back(vert);
}
} else {
vertex_count = p->vertices.size();
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
- vertices[i].Color, vertices[i].TCoords);
+ vertices[i].Color, scale * vertices[i].TCoords);
p->vertices.push_back(vert);
}
if (layer->texture_id == 0)
continue;
append(*layer, vertices, numVertices, indices, numIndices, pos,
- c, light_source, layernum);
+ c, light_source, layernum, tile.world_aligned);
}
}
void MeshCollector::append(const TileLayer &layer,
const video::S3DVertex *vertices, u32 numVertices,
const u16 *indices, u32 numIndices,
- v3f pos, video::SColor c, u8 light_source, u8 layernum)
+ v3f pos, video::SColor c, u8 light_source, u8 layernum,
+ bool use_scale)
{
if (numIndices > 65535) {
dstream << "FIXME: MeshCollector::append() called with numIndices="
p = &(*buffers)[buffers->size() - 1];
}
+ f32 scale = 1.0;
+ if (use_scale)
+ scale = 1.0 / layer.scale;
+
video::SColor original_c = c;
u32 vertex_count;
if (m_use_tangent_vertices) {
applyFacesShading(c, vertices[i].Normal);
}
video::S3DVertexTangents vert(vertices[i].Pos + pos,
- vertices[i].Normal, c, vertices[i].TCoords);
+ vertices[i].Normal, c, scale * vertices[i].TCoords);
p->tangent_vertices.push_back(vert);
}
} else {
applyFacesShading(c, vertices[i].Normal);
}
video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, c,
- vertices[i].TCoords);
+ scale * vertices[i].TCoords);
p->vertices.push_back(vert);
}
}