diff options
Diffstat (limited to 'src/client/content_mapblock.cpp')
-rw-r--r-- | src/client/content_mapblock.cpp | 975 |
1 files changed, 563 insertions, 412 deletions
diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 3d06584c4..c97963ede 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -45,14 +45,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #define FRAMED_NEIGHBOR_COUNT 18 static const v3s16 light_dirs[8] = { - v3s16(-1, -1, -1), - v3s16(-1, -1, 1), - v3s16(-1, 1, -1), - v3s16(-1, 1, 1), - v3s16( 1, -1, -1), - v3s16( 1, -1, 1), - v3s16( 1, 1, -1), - v3s16( 1, 1, 1), + v3s16(-1, -1, -1), + v3s16(-1, -1, 1), + v3s16(-1, 1, -1), + v3s16(-1, 1, 1), + v3s16(1, -1, -1), + v3s16(1, -1, 1), + v3s16(1, 1, -1), + v3s16(1, 1, 1), }; // Standard index set to make a quad on 4 vertices @@ -62,14 +62,15 @@ const std::string MapblockMeshGenerator::raillike_groupname = "connect_to_railli MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output) { - data = input; + data = input; collector = output; - nodedef = data->m_client->ndef(); + nodedef = data->m_client->ndef(); meshmanip = RenderingEngine::get_scene_manager()->getMeshManipulator(); enable_mesh_cache = g_settings->getBool("enable_mesh_cache") && - !data->m_smooth_lighting; // Mesh cache is not supported with smooth lighting + !data->m_smooth_lighting; // Mesh cache is not supported with + // smooth lighting blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE; } @@ -120,11 +121,11 @@ void MapblockMeshGenerator::getSpecialTile(int index, TileSpec *tile, bool apply top_layer->material_flags |= MATERIAL_FLAG_CRACK; } -void MapblockMeshGenerator::drawQuad(v3f *coords, const v3s16 &normal, - float vertical_tiling) +void MapblockMeshGenerator::drawQuad( + v3f *coords, const v3s16 &normal, float vertical_tiling) { - const v2f tcoords[4] = {v2f(0.0, 0.0), v2f(1.0, 0.0), - v2f(1.0, vertical_tiling), v2f(0.0, vertical_tiling)}; + const v2f tcoords[4] = {v2f(0.0, 0.0), v2f(1.0, 0.0), v2f(1.0, vertical_tiling), + v2f(0.0, vertical_tiling)}; video::S3DVertex vertices[4]; bool shade_face = !f->light_source && (normal != v3s16(0, 0, 0)); v3f normal2(normal.X, normal.Y, normal.Z); @@ -152,8 +153,8 @@ void MapblockMeshGenerator::drawQuad(v3f *coords, const v3s16 &normal, // should be (2+2)*6=24 values in the list. The order of // the faces in the list is up-down-right-left-back-front // (compatible with ContentFeatures). -void MapblockMeshGenerator::drawCuboid(const aabb3f &box, - TileSpec *tiles, int tilecount, const LightInfo *lights, const f32 *txc) +void MapblockMeshGenerator::drawCuboid(const aabb3f &box, TileSpec *tiles, int tilecount, + const LightInfo *lights, const f32 *txc) { assert(tilecount >= 1 && tilecount <= 6); // pre-condition @@ -176,46 +177,64 @@ void MapblockMeshGenerator::drawCuboid(const aabb3f &box, } video::S3DVertex vertices[24] = { - // top - video::S3DVertex(min.X, max.Y, max.Z, 0, 1, 0, colors[0], txc[0], txc[1]), - video::S3DVertex(max.X, max.Y, max.Z, 0, 1, 0, colors[0], txc[2], txc[1]), - video::S3DVertex(max.X, max.Y, min.Z, 0, 1, 0, colors[0], txc[2], txc[3]), - video::S3DVertex(min.X, max.Y, min.Z, 0, 1, 0, colors[0], txc[0], txc[3]), - // bottom - video::S3DVertex(min.X, min.Y, min.Z, 0, -1, 0, colors[1], txc[4], txc[5]), - video::S3DVertex(max.X, min.Y, min.Z, 0, -1, 0, colors[1], txc[6], txc[5]), - video::S3DVertex(max.X, min.Y, max.Z, 0, -1, 0, colors[1], txc[6], txc[7]), - video::S3DVertex(min.X, min.Y, max.Z, 0, -1, 0, colors[1], txc[4], txc[7]), - // right - video::S3DVertex(max.X, max.Y, min.Z, 1, 0, 0, colors[2], txc[ 8], txc[9]), - video::S3DVertex(max.X, max.Y, max.Z, 1, 0, 0, colors[2], txc[10], txc[9]), - video::S3DVertex(max.X, min.Y, max.Z, 1, 0, 0, colors[2], txc[10], txc[11]), - video::S3DVertex(max.X, min.Y, min.Z, 1, 0, 0, colors[2], txc[ 8], txc[11]), - // left - video::S3DVertex(min.X, max.Y, max.Z, -1, 0, 0, colors[3], txc[12], txc[13]), - video::S3DVertex(min.X, max.Y, min.Z, -1, 0, 0, colors[3], txc[14], txc[13]), - video::S3DVertex(min.X, min.Y, min.Z, -1, 0, 0, colors[3], txc[14], txc[15]), - video::S3DVertex(min.X, min.Y, max.Z, -1, 0, 0, colors[3], txc[12], txc[15]), - // back - video::S3DVertex(max.X, max.Y, max.Z, 0, 0, 1, colors[4], txc[16], txc[17]), - video::S3DVertex(min.X, max.Y, max.Z, 0, 0, 1, colors[4], txc[18], txc[17]), - video::S3DVertex(min.X, min.Y, max.Z, 0, 0, 1, colors[4], txc[18], txc[19]), - video::S3DVertex(max.X, min.Y, max.Z, 0, 0, 1, colors[4], txc[16], txc[19]), - // front - video::S3DVertex(min.X, max.Y, min.Z, 0, 0, -1, colors[5], txc[20], txc[21]), - video::S3DVertex(max.X, max.Y, min.Z, 0, 0, -1, colors[5], txc[22], txc[21]), - video::S3DVertex(max.X, min.Y, min.Z, 0, 0, -1, colors[5], txc[22], txc[23]), - video::S3DVertex(min.X, min.Y, min.Z, 0, 0, -1, colors[5], txc[20], txc[23]), + // top + video::S3DVertex(min.X, max.Y, max.Z, 0, 1, 0, colors[0], txc[0], + txc[1]), + video::S3DVertex(max.X, max.Y, max.Z, 0, 1, 0, colors[0], txc[2], + txc[1]), + video::S3DVertex(max.X, max.Y, min.Z, 0, 1, 0, colors[0], txc[2], + txc[3]), + video::S3DVertex(min.X, max.Y, min.Z, 0, 1, 0, colors[0], txc[0], + txc[3]), + // bottom + video::S3DVertex(min.X, min.Y, min.Z, 0, -1, 0, colors[1], txc[4], + txc[5]), + video::S3DVertex(max.X, min.Y, min.Z, 0, -1, 0, colors[1], txc[6], + txc[5]), + video::S3DVertex(max.X, min.Y, max.Z, 0, -1, 0, colors[1], txc[6], + txc[7]), + video::S3DVertex(min.X, min.Y, max.Z, 0, -1, 0, colors[1], txc[4], + txc[7]), + // right + video::S3DVertex(max.X, max.Y, min.Z, 1, 0, 0, colors[2], txc[8], + txc[9]), + video::S3DVertex(max.X, max.Y, max.Z, 1, 0, 0, colors[2], txc[10], + txc[9]), + video::S3DVertex(max.X, min.Y, max.Z, 1, 0, 0, colors[2], txc[10], + txc[11]), + video::S3DVertex(max.X, min.Y, min.Z, 1, 0, 0, colors[2], txc[8], + txc[11]), + // left + video::S3DVertex(min.X, max.Y, max.Z, -1, 0, 0, colors[3], + txc[12], txc[13]), + video::S3DVertex(min.X, max.Y, min.Z, -1, 0, 0, colors[3], + txc[14], txc[13]), + video::S3DVertex(min.X, min.Y, min.Z, -1, 0, 0, colors[3], + txc[14], txc[15]), + video::S3DVertex(min.X, min.Y, max.Z, -1, 0, 0, colors[3], + txc[12], txc[15]), + // back + video::S3DVertex(max.X, max.Y, max.Z, 0, 0, 1, colors[4], txc[16], + txc[17]), + video::S3DVertex(min.X, max.Y, max.Z, 0, 0, 1, colors[4], txc[18], + txc[17]), + video::S3DVertex(min.X, min.Y, max.Z, 0, 0, 1, colors[4], txc[18], + txc[19]), + video::S3DVertex(max.X, min.Y, max.Z, 0, 0, 1, colors[4], txc[16], + txc[19]), + // front + video::S3DVertex(min.X, max.Y, min.Z, 0, 0, -1, colors[5], + txc[20], txc[21]), + video::S3DVertex(max.X, max.Y, min.Z, 0, 0, -1, colors[5], + txc[22], txc[21]), + video::S3DVertex(max.X, min.Y, min.Z, 0, 0, -1, colors[5], + txc[22], txc[23]), + video::S3DVertex(min.X, min.Y, min.Z, 0, 0, -1, colors[5], + txc[20], txc[23]), }; - static const u8 light_indices[24] = { - 3, 7, 6, 2, - 0, 4, 5, 1, - 6, 7, 5, 4, - 3, 2, 0, 1, - 7, 3, 1, 5, - 2, 6, 4, 0 - }; + static const u8 light_indices[24] = {3, 7, 6, 2, 0, 4, 5, 1, 6, 7, 5, 4, 3, 2, 0, + 1, 7, 3, 1, 5, 2, 6, 4, 0}; for (int face = 0; face < 6; face++) { int tileindex = MYMIN(face, tilecount - 1); @@ -267,8 +286,9 @@ void MapblockMeshGenerator::drawCuboid(const aabb3f &box, for (int j = 0; j < 24; ++j) { video::S3DVertex &vertex = vertices[j]; vertex.Color = encode_light( - lights[light_indices[j]].getPair(MYMAX(0.0f, vertex.Normal.Y)), - f->light_source); + lights[light_indices[j]].getPair( + MYMAX(0.0f, vertex.Normal.Y)), + f->light_source); if (!f->light_source) applyFacesShading(vertex.Color, vertex.Normal); } @@ -287,7 +307,8 @@ void MapblockMeshGenerator::getSmoothLightFrame() for (int k = 0; k < 8; ++k) frame.sunlight[k] = false; for (int k = 0; k < 8; ++k) { - LightPair light(getSmoothLightTransparent(blockpos_nodes + p, light_dirs[k], data)); + LightPair light(getSmoothLightTransparent( + blockpos_nodes + p, light_dirs[k], data)); frame.lightsDay[k] = light.lightDay; frame.lightsNight[k] = light.lightNight; // If there is direct sunlight and no ambient occlusion at some corner, @@ -306,9 +327,12 @@ LightInfo MapblockMeshGenerator::blendLight(const v3f &vertex_pos) // Light levels at (logical) node corners are known. Here, // trilinear interpolation is used to calculate light level // at a given point in the node. - f32 x = core::clamp(vertex_pos.X / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, 1.0 + SMOOTH_LIGHTING_OVERSIZE); - f32 y = core::clamp(vertex_pos.Y / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, 1.0 + SMOOTH_LIGHTING_OVERSIZE); - f32 z = core::clamp(vertex_pos.Z / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, 1.0 + SMOOTH_LIGHTING_OVERSIZE); + f32 x = core::clamp(vertex_pos.X / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, + 1.0 + SMOOTH_LIGHTING_OVERSIZE); + f32 y = core::clamp(vertex_pos.Y / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, + 1.0 + SMOOTH_LIGHTING_OVERSIZE); + f32 z = core::clamp(vertex_pos.Z / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, + 1.0 + SMOOTH_LIGHTING_OVERSIZE); f32 lightDay = 0.0; // daylight f32 lightNight = 0.0; f32 lightBoosted = 0.0; // daylight + direct sunlight, if any @@ -334,11 +358,12 @@ video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos) return encode_light(light.getPair(), f->light_source); } -video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos, - const v3f &vertex_normal) +video::SColor MapblockMeshGenerator::blendLightColor( + const v3f &vertex_pos, const v3f &vertex_normal) { LightInfo light = blendLight(vertex_pos); - video::SColor color = encode_light(light.getPair(MYMAX(0.0f, vertex_normal.Y)), f->light_source); + video::SColor color = encode_light( + light.getPair(MYMAX(0.0f, vertex_normal.Y)), f->light_source); if (!f->light_source) applyFacesShading(color, vertex_normal); return color; @@ -353,19 +378,19 @@ void MapblockMeshGenerator::generateCuboidTextureCoords(const aabb3f &box, f32 * f32 ty2 = (box.MaxEdge.Y / BS) + 0.5; f32 tz2 = (box.MaxEdge.Z / BS) + 0.5; f32 txc[24] = { - tx1, 1 - tz2, tx2, 1 - tz1, // up - tx1, tz1, tx2, tz2, // down - tz1, 1 - ty2, tz2, 1 - ty1, // right - 1 - tz2, 1 - ty2, 1 - tz1, 1 - ty1, // left - 1 - tx2, 1 - ty2, 1 - tx1, 1 - ty1, // back - tx1, 1 - ty2, tx2, 1 - ty1, // front + tx1, 1 - tz2, tx2, 1 - tz1, // up + tx1, tz1, tx2, tz2, // down + tz1, 1 - ty2, tz2, 1 - ty1, // right + 1 - tz2, 1 - ty2, 1 - tz1, 1 - ty1, // left + 1 - tx2, 1 - ty2, 1 - tx1, 1 - ty1, // back + tx1, 1 - ty2, tx2, 1 - ty1, // front }; for (int i = 0; i != 24; ++i) coords[i] = txc[i]; } -void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc, - TileSpec *tiles, int tile_count) +void MapblockMeshGenerator::drawAutoLightedCuboid( + aabb3f box, const f32 *txc, TileSpec *tiles, int tile_count) { bool scale = std::fabs(f->visual_scale - 1.0f) > 1e-3f; f32 texture_coord_buf[24]; @@ -413,12 +438,16 @@ void MapblockMeshGenerator::prepareLiquidNodeDrawing() getSpecialTile(0, &tile_liquid_top); getSpecialTile(1, &tile_liquid); - MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(p.X, p.Y + 1, p.Z)); - MapNode nbottom = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(p.X, p.Y - 1, p.Z)); + MapNode ntop = data->m_vmanip.getNodeNoEx( + blockpos_nodes + v3s16(p.X, p.Y + 1, p.Z)); + MapNode nbottom = data->m_vmanip.getNodeNoEx( + blockpos_nodes + v3s16(p.X, p.Y - 1, p.Z)); c_flowing = f->liquid_alternative_flowing_id; c_source = f->liquid_alternative_source_id; - top_is_same_liquid = (ntop.getContent() == c_flowing) || (ntop.getContent() == c_source); - draw_liquid_bottom = (nbottom.getContent() != c_flowing) && (nbottom.getContent() != c_source); + top_is_same_liquid = (ntop.getContent() == c_flowing) || + (ntop.getContent() == c_source); + draw_liquid_bottom = (nbottom.getContent() != c_flowing) && + (nbottom.getContent() != c_source); if (draw_liquid_bottom) { const ContentFeatures &f2 = nodedef->get(nbottom.getContent()); if (f2.solidness > 1) @@ -432,7 +461,8 @@ void MapblockMeshGenerator::prepareLiquidNodeDrawing() // If this liquid emits light and doesn't contain light, draw // it at what it emits, for an increased effect u8 e = decode_light(f->light_source); - light = LightPair(std::max(e, light.lightDay), std::max(e, light.lightNight)); + light = LightPair(std::max(e, light.lightDay), + std::max(e, light.lightNight)); } else if (nodedef->get(ntop).param_type == CPT_LIGHT) { // Otherwise, use the light of the node on top if possible light = LightPair(getInteriorLight(ntop, 0, nodedef)); @@ -447,46 +477,47 @@ void MapblockMeshGenerator::getLiquidNeighborhood() u8 range = rangelim(nodedef->get(c_flowing).liquid_range, 1, 8); for (int w = -1; w <= 1; w++) - for (int u = -1; u <= 1; u++) { - NeighborData &neighbor = liquid_neighbors[w + 1][u + 1]; - v3s16 p2 = p + v3s16(u, 0, w); - MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - neighbor.content = n2.getContent(); - neighbor.level = -0.5 * BS; - neighbor.is_same_liquid = false; - neighbor.top_is_same_liquid = false; - - if (neighbor.content == CONTENT_IGNORE) - continue; + for (int u = -1; u <= 1; u++) { + NeighborData &neighbor = liquid_neighbors[w + 1][u + 1]; + v3s16 p2 = p + v3s16(u, 0, w); + MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); + neighbor.content = n2.getContent(); + neighbor.level = -0.5 * BS; + neighbor.is_same_liquid = false; + neighbor.top_is_same_liquid = false; + + if (neighbor.content == CONTENT_IGNORE) + continue; - if (neighbor.content == c_source) { - neighbor.is_same_liquid = true; - neighbor.level = 0.5 * BS; - } else if (neighbor.content == c_flowing) { - neighbor.is_same_liquid = true; - u8 liquid_level = (n2.param2 & LIQUID_LEVEL_MASK); - if (liquid_level <= LIQUID_LEVEL_MAX + 1 - range) - liquid_level = 0; - else - liquid_level -= (LIQUID_LEVEL_MAX + 1 - range); - neighbor.level = (-0.5 + (liquid_level + 0.5) / range) * BS; - } + if (neighbor.content == c_source) { + neighbor.is_same_liquid = true; + neighbor.level = 0.5 * BS; + } else if (neighbor.content == c_flowing) { + neighbor.is_same_liquid = true; + u8 liquid_level = (n2.param2 & LIQUID_LEVEL_MASK); + if (liquid_level <= LIQUID_LEVEL_MAX + 1 - range) + liquid_level = 0; + else + liquid_level -= (LIQUID_LEVEL_MAX + 1 - range); + neighbor.level = (-0.5 + (liquid_level + 0.5) / range) * + BS; + } - // Check node above neighbor. - // NOTE: This doesn't get executed if neighbor - // doesn't exist - p2.Y++; - n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if (n2.getContent() == c_source || n2.getContent() == c_flowing) - neighbor.top_is_same_liquid = true; - } + // Check node above neighbor. + // NOTE: This doesn't get executed if neighbor + // doesn't exist + p2.Y++; + n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); + if (n2.getContent() == c_source || n2.getContent() == c_flowing) + neighbor.top_is_same_liquid = true; + } } void MapblockMeshGenerator::calculateCornerLevels() { for (int k = 0; k < 2; k++) - for (int i = 0; i < 2; i++) - corner_levels[k][i] = getCornerLevel(i, k); + for (int i = 0; i < 2; i++) + corner_levels[k][i] = getCornerLevel(i, k); } f32 MapblockMeshGenerator::getCornerLevel(int i, int k) @@ -495,59 +526,58 @@ f32 MapblockMeshGenerator::getCornerLevel(int i, int k) int count = 0; int air_count = 0; for (int dk = 0; dk < 2; dk++) - for (int di = 0; di < 2; di++) { - NeighborData &neighbor_data = liquid_neighbors[k + dk][i + di]; - content_t content = neighbor_data.content; - - // If top is liquid, draw starting from top of node - if (neighbor_data.top_is_same_liquid) - return 0.5 * BS; - - // Source always has the full height - if (content == c_source) - return 0.5 * BS; - - // Flowing liquid has level information - if (content == c_flowing) { - sum += neighbor_data.level; - count++; - } else if (content == CONTENT_AIR) { - air_count++; - if (air_count >= 2) - return -0.5 * BS + 0.2; + for (int di = 0; di < 2; di++) { + NeighborData &neighbor_data = liquid_neighbors[k + dk][i + di]; + content_t content = neighbor_data.content; + + // If top is liquid, draw starting from top of node + if (neighbor_data.top_is_same_liquid) + return 0.5 * BS; + + // Source always has the full height + if (content == c_source) + return 0.5 * BS; + + // Flowing liquid has level information + if (content == c_flowing) { + sum += neighbor_data.level; + count++; + } else if (content == CONTENT_AIR) { + air_count++; + if (air_count >= 2) + return -0.5 * BS + 0.2; + } } - } if (count > 0) return sum / count; return 0; } -namespace { - struct LiquidFaceDesc { - v3s16 dir; // XZ - v3s16 p[2]; // XZ only; 1 means +, 0 means - - }; - struct UV { - int u, v; - }; - static const LiquidFaceDesc liquid_base_faces[4] = { - {v3s16( 1, 0, 0), {v3s16(1, 0, 1), v3s16(1, 0, 0)}}, - {v3s16(-1, 0, 0), {v3s16(0, 0, 0), v3s16(0, 0, 1)}}, - {v3s16( 0, 0, 1), {v3s16(0, 0, 1), v3s16(1, 0, 1)}}, - {v3s16( 0, 0, -1), {v3s16(1, 0, 0), v3s16(0, 0, 0)}}, - }; - static const UV liquid_base_vertices[4] = { - {0, 1}, - {1, 1}, - {1, 0}, - {0, 0} - }; +namespace +{ +struct LiquidFaceDesc +{ + v3s16 dir; // XZ + v3s16 p[2]; // XZ only; 1 means +, 0 means - +}; +struct UV +{ + int u, v; +}; +static const LiquidFaceDesc liquid_base_faces[4] = { + {v3s16(1, 0, 0), {v3s16(1, 0, 1), v3s16(1, 0, 0)}}, + {v3s16(-1, 0, 0), {v3s16(0, 0, 0), v3s16(0, 0, 1)}}, + {v3s16(0, 0, 1), {v3s16(0, 0, 1), v3s16(1, 0, 1)}}, + {v3s16(0, 0, -1), {v3s16(1, 0, 0), v3s16(0, 0, 0)}}, +}; +static const UV liquid_base_vertices[4] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}}; } void MapblockMeshGenerator::drawLiquidSides() { for (const auto &face : liquid_base_faces) { - const NeighborData &neighbor = liquid_neighbors[face.dir.Z + 1][face.dir.X + 1]; + const NeighborData &neighbor = + liquid_neighbors[face.dir.Z + 1][face.dir.X + 1]; // No face between nodes of the same liquid, unless there is node // at the top to which it should be connected. Again, unless the face @@ -574,7 +604,9 @@ void MapblockMeshGenerator::drawLiquidSides() pos.X = (base.X - 0.5f) * BS; pos.Z = (base.Z - 0.5f) * BS; if (vertex.v) { - pos.Y = neighbor.is_same_liquid ? corner_levels[base.Z][base.X] : -0.5f * BS; + pos.Y = neighbor.is_same_liquid + ? corner_levels[base.Z][base.X] + : -0.5f * BS; } else if (top_is_same_liquid) { pos.Y = 0.5f * BS; } else { @@ -585,7 +617,8 @@ void MapblockMeshGenerator::drawLiquidSides() if (data->m_smooth_lighting) color = blendLightColor(pos); pos += origin; - vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, 0, 0, 0, color, vertex.u, v); + vertices[j] = video::S3DVertex( + pos.X, pos.Y, pos.Z, 0, 0, 0, color, vertex.u, v); }; collector->append(tile_liquid, vertices, 4, quad_indices, 6); } @@ -599,10 +632,14 @@ void MapblockMeshGenerator::drawLiquidTop() static const int corner_resolve[4][2] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}}; video::S3DVertex vertices[4] = { - video::S3DVertex(-BS / 2, 0, BS / 2, 0, 0, 0, color_liquid_top, 0, 1), - video::S3DVertex( BS / 2, 0, BS / 2, 0, 0, 0, color_liquid_top, 1, 1), - video::S3DVertex( BS / 2, 0, -BS / 2, 0, 0, 0, color_liquid_top, 1, 0), - video::S3DVertex(-BS / 2, 0, -BS / 2, 0, 0, 0, color_liquid_top, 0, 0), + video::S3DVertex(-BS / 2, 0, BS / 2, 0, 0, 0, color_liquid_top, 0, + 1), + video::S3DVertex(BS / 2, 0, BS / 2, 0, 0, 0, color_liquid_top, 1, + 1), + video::S3DVertex(BS / 2, 0, -BS / 2, 0, 0, 0, color_liquid_top, 1, + 0), + video::S3DVertex(-BS / 2, 0, -BS / 2, 0, 0, 0, color_liquid_top, + 0, 0), }; for (int i = 0; i < 4; i++) { @@ -619,10 +656,10 @@ void MapblockMeshGenerator::drawLiquidTop() // Rotate texture to make animation go in flow direction // Positive if liquid moves towards +Z f32 dz = (corner_levels[0][0] + corner_levels[0][1]) - - (corner_levels[1][0] + corner_levels[1][1]); + (corner_levels[1][0] + corner_levels[1][1]); // Positive if liquid moves towards +X f32 dx = (corner_levels[0][0] + corner_levels[1][0]) - - (corner_levels[0][1] + corner_levels[1][1]); + (corner_levels[0][1] + corner_levels[1][1]); f32 tcoord_angle = atan2(dz, dx) * core::RADTODEG; v2f tcoord_center(0.5, 0.5); v2f tcoord_translate(blockpos_nodes.Z + p.Z, blockpos_nodes.X + p.X); @@ -643,10 +680,14 @@ void MapblockMeshGenerator::drawLiquidTop() void MapblockMeshGenerator::drawLiquidBottom() { video::S3DVertex vertices[4] = { - video::S3DVertex(-BS / 2, -BS / 2, -BS / 2, 0, 0, 0, color_liquid_top, 0, 0), - video::S3DVertex( BS / 2, -BS / 2, -BS / 2, 0, 0, 0, color_liquid_top, 1, 0), - video::S3DVertex( BS / 2, -BS / 2, BS / 2, 0, 0, 0, color_liquid_top, 1, 1), - video::S3DVertex(-BS / 2, -BS / 2, BS / 2, 0, 0, 0, color_liquid_top, 0, 1), + video::S3DVertex(-BS / 2, -BS / 2, -BS / 2, 0, 0, 0, + color_liquid_top, 0, 0), + video::S3DVertex(BS / 2, -BS / 2, -BS / 2, 0, 0, 0, + color_liquid_top, 1, 0), + video::S3DVertex(BS / 2, -BS / 2, BS / 2, 0, 0, 0, + color_liquid_top, 1, 1), + video::S3DVertex(-BS / 2, -BS / 2, BS / 2, 0, 0, 0, + color_liquid_top, 0, 1), }; for (int i = 0; i < 4; i++) { @@ -684,26 +725,32 @@ void MapblockMeshGenerator::drawGlasslikeNode() continue; // Face at Z- v3f vertices[4] = { - v3f(-BS / 2, BS / 2, -BS / 2), - v3f( BS / 2, BS / 2, -BS / 2), - v3f( BS / 2, -BS / 2, -BS / 2), - v3f(-BS / 2, -BS / 2, -BS / 2), + v3f(-BS / 2, BS / 2, -BS / 2), + v3f(BS / 2, BS / 2, -BS / 2), + v3f(BS / 2, -BS / 2, -BS / 2), + v3f(-BS / 2, -BS / 2, -BS / 2), }; for (v3f &vertex : vertices) { switch (face) { - case D6D_ZP: - vertex.rotateXZBy(180); break; - case D6D_YP: - vertex.rotateYZBy( 90); break; - case D6D_XP: - vertex.rotateXZBy( 90); break; - case D6D_ZN: - vertex.rotateXZBy( 0); break; - case D6D_YN: - vertex.rotateYZBy(-90); break; - case D6D_XN: - vertex.rotateXZBy(-90); break; + case D6D_ZP: + vertex.rotateXZBy(180); + break; + case D6D_YP: + vertex.rotateYZBy(90); + break; + case D6D_XP: + vertex.rotateXZBy(90); + break; + case D6D_ZN: + vertex.rotateXZBy(0); + break; + case D6D_YN: + vertex.rotateYZBy(-90); + break; + case D6D_XN: + vertex.rotateXZBy(-90); + break; } } drawQuad(vertices, dir); @@ -733,33 +780,34 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode() static const float b = 0.876f * (BS / 2.0f); static const aabb3f frame_edges[FRAMED_EDGE_COUNT] = { - aabb3f( b, b, -a, a, a, a), // y+ - aabb3f(-a, b, -a, -b, a, a), // y+ - aabb3f( b, -a, -a, a, -b, a), // y- - aabb3f(-a, -a, -a, -b, -b, a), // y- - aabb3f( b, -a, b, a, a, a), // x+ - aabb3f( b, -a, -a, a, a, -b), // x+ - aabb3f(-a, -a, b, -b, a, a), // x- - aabb3f(-a, -a, -a, -b, a, -b), // x- - aabb3f(-a, b, b, a, a, a), // z+ - aabb3f(-a, -a, b, a, -b, a), // z+ - aabb3f(-a, -a, -a, a, -b, -b), // z- - aabb3f(-a, b, -a, a, a, -b), // z- + aabb3f(b, b, -a, a, a, a), // y+ + aabb3f(-a, b, -a, -b, a, a), // y+ + aabb3f(b, -a, -a, a, -b, a), // y- + aabb3f(-a, -a, -a, -b, -b, a), // y- + aabb3f(b, -a, b, a, a, a), // x+ + aabb3f(b, -a, -a, a, a, -b), // x+ + aabb3f(-a, -a, b, -b, a, a), // x- + aabb3f(-a, -a, -a, -b, a, -b), // x- + aabb3f(-a, b, b, a, a, a), // z+ + aabb3f(-a, -a, b, a, -b, a), // z+ + aabb3f(-a, -a, -a, a, -b, -b), // z- + aabb3f(-a, b, -a, a, a, -b), // z- }; // tables of neighbour (connect if same type and merge allowed), // checked with g_26dirs // 1 = connect, 0 = face visible - bool nb[FRAMED_NEIGHBOR_COUNT] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool nb[FRAMED_NEIGHBOR_COUNT] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 1 = check - static const bool check_nb_vertical [FRAMED_NEIGHBOR_COUNT] = - {0,1,0,0,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; - static const bool check_nb_horizontal [FRAMED_NEIGHBOR_COUNT] = - {1,0,1,1,0,1, 0,0,0,0, 1,1,1,1, 0,0,0,0}; - static const bool check_nb_all [FRAMED_NEIGHBOR_COUNT] = - {1,1,1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1}; + static const bool check_nb_vertical[FRAMED_NEIGHBOR_COUNT] = { + 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static const bool check_nb_horizontal[FRAMED_NEIGHBOR_COUNT] = { + 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}; + static const bool check_nb_all[FRAMED_NEIGHBOR_COUNT] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; const bool *check_nb = check_nb_all; // neighbours checks for frames visibility @@ -783,18 +831,29 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode() // edge visibility static const u8 nb_triplet[FRAMED_EDGE_COUNT][3] = { - {1, 2, 7}, {1, 5, 6}, {4, 2, 15}, {4, 5, 14}, - {2, 0, 11}, {2, 3, 13}, {5, 0, 10}, {5, 3, 12}, - {0, 1, 8}, {0, 4, 16}, {3, 4, 17}, {3, 1, 9}, + {1, 2, 7}, + {1, 5, 6}, + {4, 2, 15}, + {4, 5, 14}, + {2, 0, 11}, + {2, 3, 13}, + {5, 0, 10}, + {5, 3, 12}, + {0, 1, 8}, + {0, 4, 16}, + {3, 4, 17}, + {3, 1, 9}, }; tile = tiles[1]; for (int edge = 0; edge < FRAMED_EDGE_COUNT; edge++) { bool edge_invisible; if (nb[nb_triplet[edge][2]]) - edge_invisible = nb[nb_triplet[edge][0]] & nb[nb_triplet[edge][1]]; + edge_invisible = + nb[nb_triplet[edge][0]] & nb[nb_triplet[edge][1]]; else - edge_invisible = nb[nb_triplet[edge][0]] ^ nb[nb_triplet[edge][1]]; + edge_invisible = + nb[nb_triplet[edge][0]] ^ nb[nb_triplet[edge][1]]; if (edge_invisible) continue; drawAutoLightedCuboid(frame_edges[edge]); @@ -807,26 +866,32 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode() tile = glass_tiles[face]; // Face at Z- v3f vertices[4] = { - v3f(-a, a, -g), - v3f( a, a, -g), - v3f( a, -a, -g), - v3f(-a, -a, -g), + v3f(-a, a, -g), + v3f(a, a, -g), + v3f(a, -a, -g), + v3f(-a, -a, -g), }; for (v3f &vertex : vertices) { switch (face) { - case D6D_ZP: - vertex.rotateXZBy(180); break; - case D6D_YP: - vertex.rotateYZBy( 90); break; - case D6D_XP: - vertex.rotateXZBy( 90); break; - case D6D_ZN: - vertex.rotateXZBy( 0); break; - case D6D_YN: - vertex.rotateYZBy(-90); break; - case D6D_XN: - vertex.rotateXZBy(-90); break; + case D6D_ZP: + vertex.rotateXZBy(180); + break; + case D6D_YP: + vertex.rotateYZBy(90); + break; + case D6D_XP: + vertex.rotateXZBy(90); + break; + case D6D_ZN: + vertex.rotateXZBy(0); + break; + case D6D_YN: + vertex.rotateYZBy(-90); + break; + case D6D_XN: + vertex.rotateXZBy(-90); + break; } } v3s16 dir = g_6dirs[face]; @@ -841,12 +906,9 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode() // convert it to -0.5 .. 0.5 float vlev = (param2 / 63.0f) * 2.0f - 1.0f; getSpecialTile(0, &tile); - drawAutoLightedCuboid(aabb3f(-(nb[5] ? g : b), - -(nb[4] ? g : b), - -(nb[3] ? g : b), - (nb[2] ? g : b), - (nb[1] ? g : b) * vlev, - (nb[0] ? g : b))); + drawAutoLightedCuboid(aabb3f(-(nb[5] ? g : b), -(nb[4] ? g : b), + -(nb[3] ? g : b), (nb[2] ? g : b), (nb[1] ? g : b) * vlev, + (nb[0] ? g : b))); } } @@ -862,44 +924,49 @@ void MapblockMeshGenerator::drawTorchlikeNode() u8 wall = n.getWallMounted(nodedef); u8 tileindex = 0; switch (wall) { - case DWM_YP: tileindex = 1; break; // ceiling - case DWM_YN: tileindex = 0; break; // floor - default: tileindex = 2; // side (or invalid—should we care?) + case DWM_YP: + tileindex = 1; + break; // ceiling + case DWM_YN: + tileindex = 0; + break; // floor + default: + tileindex = 2; // side (or invalid—should we care?) } useTile(tileindex, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING); float size = BS / 2 * f->visual_scale; v3f vertices[4] = { - v3f(-size, size, 0), - v3f( size, size, 0), - v3f( size, -size, 0), - v3f(-size, -size, 0), + v3f(-size, size, 0), + v3f(size, size, 0), + v3f(size, -size, 0), + v3f(-size, -size, 0), }; for (v3f &vertex : vertices) { switch (wall) { - case DWM_YP: - vertex.Y += -size + BS/2; - vertex.rotateXZBy(-45); - break; - case DWM_YN: - vertex.Y += size - BS/2; - vertex.rotateXZBy(45); - break; - case DWM_XP: - vertex.X += -size + BS/2; - break; - case DWM_XN: - vertex.X += -size + BS/2; - vertex.rotateXZBy(180); - break; - case DWM_ZP: - vertex.X += -size + BS/2; - vertex.rotateXZBy(90); - break; - case DWM_ZN: - vertex.X += -size + BS/2; - vertex.rotateXZBy(-90); + case DWM_YP: + vertex.Y += -size + BS / 2; + vertex.rotateXZBy(-45); + break; + case DWM_YN: + vertex.Y += size - BS / 2; + vertex.rotateXZBy(45); + break; + case DWM_XP: + vertex.X += -size + BS / 2; + break; + case DWM_XN: + vertex.X += -size + BS / 2; + vertex.rotateXZBy(180); + break; + case DWM_ZP: + vertex.X += -size + BS / 2; + vertex.rotateXZBy(90); + break; + case DWM_ZN: + vertex.X += -size + BS / 2; + vertex.rotateXZBy(-90); } } drawQuad(vertices); @@ -913,39 +980,45 @@ void MapblockMeshGenerator::drawSignlikeNode() float size = BS / 2 * f->visual_scale; // Wall at X+ of node v3f vertices[4] = { - v3f(BS / 2 - offset, size, size), - v3f(BS / 2 - offset, size, -size), - v3f(BS / 2 - offset, -size, -size), - v3f(BS / 2 - offset, -size, size), + v3f(BS / 2 - offset, size, size), + v3f(BS / 2 - offset, size, -size), + v3f(BS / 2 - offset, -size, -size), + v3f(BS / 2 - offset, -size, size), }; for (v3f &vertex : vertices) { switch (wall) { - case DWM_YP: - vertex.rotateXYBy( 90); break; - case DWM_YN: - vertex.rotateXYBy(-90); break; - case DWM_XP: - vertex.rotateXZBy( 0); break; - case DWM_XN: - vertex.rotateXZBy(180); break; - case DWM_ZP: - vertex.rotateXZBy( 90); break; - case DWM_ZN: - vertex.rotateXZBy(-90); break; + case DWM_YP: + vertex.rotateXYBy(90); + break; + case DWM_YN: + vertex.rotateXYBy(-90); + break; + case DWM_XP: + vertex.rotateXZBy(0); + break; + case DWM_XN: + vertex.rotateXZBy(180); + break; + case DWM_ZP: + vertex.rotateXZBy(90); + break; + case DWM_ZN: + vertex.rotateXZBy(-90); + break; } } drawQuad(vertices); } -void MapblockMeshGenerator::drawPlantlikeQuad(float rotation, float quad_offset, - bool offset_top_only) +void MapblockMeshGenerator::drawPlantlikeQuad( + float rotation, float quad_offset, bool offset_top_only) { v3f vertices[4] = { - v3f(-scale, -BS / 2 + 2.0 * scale * plant_height, 0), - v3f( scale, -BS / 2 + 2.0 * scale * plant_height, 0), - v3f( scale, -BS / 2, 0), - v3f(-scale, -BS / 2, 0), + v3f(-scale, -BS / 2 + 2.0 * scale * plant_height, 0), + v3f(scale, -BS / 2 + 2.0 * scale * plant_height, 0), + v3f(scale, -BS / 2, 0), + v3f(-scale, -BS / 2, 0), }; if (random_offset_Y) { PseudoRandom yrng(face_num++ | p.X << 16 | p.Z << 8 | p.Y << 24); @@ -1016,15 +1089,15 @@ void MapblockMeshGenerator::drawPlantlike() break; case PLANT_STYLE_HASH: - drawPlantlikeQuad( 1, BS / 4); - drawPlantlikeQuad( 91, BS / 4); + drawPlantlikeQuad(1, BS / 4); + drawPlantlikeQuad(91, BS / 4); drawPlantlikeQuad(181, BS / 4); drawPlantlikeQuad(271, BS / 4); break; case PLANT_STYLE_HASH2: - drawPlantlikeQuad( 1, -BS / 2, true); - drawPlantlikeQuad( 91, -BS / 2, true); + drawPlantlikeQuad(1, -BS / 2, true); + drawPlantlikeQuad(91, -BS / 2, true); drawPlantlikeQuad(181, -BS / 2, true); drawPlantlikeQuad(271, -BS / 2, true); break; @@ -1052,14 +1125,14 @@ void MapblockMeshGenerator::drawPlantlikeRootedNode() p.Y--; } -void MapblockMeshGenerator::drawFirelikeQuad(float rotation, float opening_angle, - float offset_h, float offset_v) +void MapblockMeshGenerator::drawFirelikeQuad( + float rotation, float opening_angle, float offset_h, float offset_v) { v3f vertices[4] = { - v3f(-scale, -BS / 2 + scale * 2, 0), - v3f( scale, -BS / 2 + scale * 2, 0), - v3f( scale, -BS / 2, 0), - v3f(-scale, -BS / 2, 0), + v3f(-scale, -BS / 2 + scale * 2, 0), + v3f(scale, -BS / 2 + scale * 2, 0), + v3f(scale, -BS / 2, 0), + v3f(-scale, -BS / 2, 0), }; for (v3f &vertex : vertices) { @@ -1131,19 +1204,37 @@ void MapblockMeshGenerator::drawFencelikeNode() tile_rot.rotation = 1; static const f32 post_rad = BS / 8; - static const f32 bar_rad = BS / 16; - static const f32 bar_len = BS / 2 - post_rad; + static const f32 bar_rad = BS / 16; + static const f32 bar_len = BS / 2 - post_rad; // The post - always present - static const aabb3f post(-post_rad, -BS / 2, -post_rad, - post_rad, BS / 2, post_rad); + static const aabb3f post( + -post_rad, -BS / 2, -post_rad, post_rad, BS / 2, post_rad); static const f32 postuv[24] = { - 0.375, 0.375, 0.625, 0.625, - 0.375, 0.375, 0.625, 0.625, - 0.000, 0.000, 0.250, 1.000, - 0.250, 0.000, 0.500, 1.000, - 0.500, 0.000, 0.750, 1.000, - 0.750, 0.000, 1.000, 1.000, + 0.375, + 0.375, + 0.625, + 0.625, + 0.375, + 0.375, + 0.625, + 0.625, + 0.000, + 0.000, + 0.250, + 1.000, + 0.250, + 0.000, + 0.500, + 1.000, + 0.500, + 0.000, + 0.750, + 1.000, + 0.750, + 0.000, + 1.000, + 1.000, }; tile = tile_rot; drawAutoLightedCuboid(post, postuv); @@ -1156,17 +1247,35 @@ void MapblockMeshGenerator::drawFencelikeNode() MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); const ContentFeatures *f2 = &nodedef->get(n2); if (f2->drawtype == NDT_FENCELIKE) { - static const aabb3f bar_x1(BS / 2 - bar_len, BS / 4 - bar_rad, -bar_rad, - BS / 2 + bar_len, BS / 4 + bar_rad, bar_rad); + static const aabb3f bar_x1(BS / 2 - bar_len, BS / 4 - bar_rad, -bar_rad, + BS / 2 + bar_len, BS / 4 + bar_rad, bar_rad); static const aabb3f bar_x2(BS / 2 - bar_len, -BS / 4 - bar_rad, -bar_rad, - BS / 2 + bar_len, -BS / 4 + bar_rad, bar_rad); + BS / 2 + bar_len, -BS / 4 + bar_rad, bar_rad); static const f32 xrailuv[24] = { - 0.000, 0.125, 1.000, 0.250, - 0.000, 0.250, 1.000, 0.375, - 0.375, 0.375, 0.500, 0.500, - 0.625, 0.625, 0.750, 0.750, - 0.000, 0.500, 1.000, 0.625, - 0.000, 0.875, 1.000, 1.000, + 0.000, + 0.125, + 1.000, + 0.250, + 0.000, + 0.250, + 1.000, + 0.375, + 0.375, + 0.375, + 0.500, + 0.500, + 0.625, + 0.625, + 0.750, + 0.750, + 0.000, + 0.500, + 1.000, + 0.625, + 0.000, + 0.875, + 1.000, + 1.000, }; drawAutoLightedCuboid(bar_x1, xrailuv); drawAutoLightedCuboid(bar_x2, xrailuv); @@ -1178,17 +1287,35 @@ void MapblockMeshGenerator::drawFencelikeNode() n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); f2 = &nodedef->get(n2); if (f2->drawtype == NDT_FENCELIKE) { - static const aabb3f bar_z1(-bar_rad, BS / 4 - bar_rad, BS / 2 - bar_len, - bar_rad, BS / 4 + bar_rad, BS / 2 + bar_len); + static const aabb3f bar_z1(-bar_rad, BS / 4 - bar_rad, BS / 2 - bar_len, + bar_rad, BS / 4 + bar_rad, BS / 2 + bar_len); static const aabb3f bar_z2(-bar_rad, -BS / 4 - bar_rad, BS / 2 - bar_len, - bar_rad, -BS / 4 + bar_rad, BS / 2 + bar_len); + bar_rad, -BS / 4 + bar_rad, BS / 2 + bar_len); static const f32 zrailuv[24] = { - 0.1875, 0.0625, 0.3125, 0.3125, // cannot rotate; stretch - 0.2500, 0.0625, 0.3750, 0.3125, // for wood texture instead - 0.0000, 0.5625, 1.0000, 0.6875, - 0.0000, 0.3750, 1.0000, 0.5000, - 0.3750, 0.3750, 0.5000, 0.5000, - 0.6250, 0.6250, 0.7500, 0.7500, + 0.1875, + 0.0625, + 0.3125, + 0.3125, // cannot rotate; stretch + 0.2500, + 0.0625, + 0.3750, + 0.3125, // for wood texture instead + 0.0000, + 0.5625, + 1.0000, + 0.6875, + 0.0000, + 0.3750, + 1.0000, + 0.5000, + 0.3750, + 0.3750, + 0.5000, + 0.5000, + 0.6250, + 0.6250, + 0.7500, + 0.7500, }; drawAutoLightedCuboid(bar_z1, zrailuv); drawAutoLightedCuboid(bar_z2, zrailuv); @@ -1202,48 +1329,51 @@ bool MapblockMeshGenerator::isSameRail(v3s16 dir) return true; const ContentFeatures &def2 = nodedef->get(node2); return ((def2.drawtype == NDT_RAILLIKE) && - (def2.getGroup(raillike_groupname) == raillike_group)); + (def2.getGroup(raillike_groupname) == raillike_group)); } -namespace { - static const v3s16 rail_direction[4] = { - v3s16( 0, 0, 1), - v3s16( 0, 0, -1), - v3s16(-1, 0, 0), - v3s16( 1, 0, 0), - }; - static const int rail_slope_angle[4] = {0, 180, 90, -90}; +namespace +{ +static const v3s16 rail_direction[4] = { + v3s16(0, 0, 1), + v3s16(0, 0, -1), + v3s16(-1, 0, 0), + v3s16(1, 0, 0), +}; +static const int rail_slope_angle[4] = {0, 180, 90, -90}; - enum RailTile { - straight, - curved, - junction, - cross, - }; - struct RailDesc { - int tile_index; - int angle; - }; - static const RailDesc rail_kinds[16] = { - // +x -x -z +z - //------------- - {straight, 0}, // . . . . - {straight, 0}, // . . . +Z - {straight, 0}, // . . -Z . - {straight, 0}, // . . -Z +Z - {straight, 90}, // . -X . . - { curved, 180}, // . -X . +Z - { curved, 270}, // . -X -Z . +enum RailTile +{ + straight, + curved, + junction, + cross, +}; +struct RailDesc +{ + int tile_index; + int angle; +}; +static const RailDesc rail_kinds[16] = { + // +x -x -z +z + //------------- + {straight, 0}, // . . . . + {straight, 0}, // . . . +Z + {straight, 0}, // . . -Z . + {straight, 0}, // . . -Z +Z + {straight, 90}, // . -X . . + {curved, 180}, // . -X . +Z + {curved, 270}, // . -X -Z . {junction, 180}, // . -X -Z +Z - {straight, 90}, // +X . . . - { curved, 90}, // +X . . +Z - { curved, 0}, // +X . -Z . - {junction, 0}, // +X . -Z +Z - {straight, 90}, // +X -X . . - {junction, 90}, // +X -X . +Z + {straight, 90}, // +X . . . + {curved, 90}, // +X . . +Z + {curved, 0}, // +X . -Z . + {junction, 0}, // +X . -Z +Z + {straight, 90}, // +X -X . . + {junction, 90}, // +X -X . +Z {junction, 270}, // +X -X -Z . - { cross, 0}, // +X -X -Z +Z - }; + {cross, 0}, // +X -X -Z +Z +}; } void MapblockMeshGenerator::drawRaillikeNode() @@ -1260,8 +1390,7 @@ void MapblockMeshGenerator::drawRaillikeNode() sloped = true; angle = rail_slope_angle[dir]; } - if (rail_above || - isSameRail(rail_direction[dir]) || + if (rail_above || isSameRail(rail_direction[dir]) || isSameRail(rail_direction[dir] + v3s16(0, -1, 0))) code |= 1 << dir; } @@ -1276,13 +1405,13 @@ void MapblockMeshGenerator::drawRaillikeNode() useTile(tile_index, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING); static const float offset = BS / 64; - static const float size = BS / 2; + static const float size = BS / 2; float y2 = sloped ? size : -size; v3f vertices[4] = { - v3f(-size, y2 + offset, size), - v3f( size, y2 + offset, size), - v3f( size, -size + offset, -size), - v3f(-size, -size + offset, -size), + v3f(-size, y2 + offset, size), + v3f(size, y2 + offset, size), + v3f(size, -size + offset, -size), + v3f(-size, -size + offset, -size), }; if (angle) for (v3f &vertex : vertices) @@ -1290,25 +1419,20 @@ void MapblockMeshGenerator::drawRaillikeNode() drawQuad(vertices); } -namespace { - static const v3s16 nodebox_tile_dirs[6] = { - v3s16(0, 1, 0), - v3s16(0, -1, 0), - v3s16(1, 0, 0), - v3s16(-1, 0, 0), - v3s16(0, 0, 1), - v3s16(0, 0, -1) - }; - - // we have this order for some reason... - static const v3s16 nodebox_connection_dirs[6] = { - v3s16( 0, 1, 0), // top - v3s16( 0, -1, 0), // bottom - v3s16( 0, 0, -1), // front - v3s16(-1, 0, 0), // left - v3s16( 0, 0, 1), // back - v3s16( 1, 0, 0), // right - }; +namespace +{ +static const v3s16 nodebox_tile_dirs[6] = {v3s16(0, 1, 0), v3s16(0, -1, 0), + v3s16(1, 0, 0), v3s16(-1, 0, 0), v3s16(0, 0, 1), v3s16(0, 0, -1)}; + +// we have this order for some reason... +static const v3s16 nodebox_connection_dirs[6] = { + v3s16(0, 1, 0), // top + v3s16(0, -1, 0), // bottom + v3s16(0, 0, -1), // front + v3s16(-1, 0, 0), // left + v3s16(0, 0, 1), // back + v3s16(1, 0, 0), // right +}; } void MapblockMeshGenerator::drawNodeboxNode() @@ -1340,11 +1464,10 @@ void MapblockMeshGenerator::drawNodeboxNode() void MapblockMeshGenerator::drawMeshNode() { u8 facedir = 0; - scene::IMesh* mesh; + scene::IMesh *mesh; bool private_mesh; // as a grab/drop pair is not thread-safe - if (f->param_type_2 == CPT2_FACEDIR || - f->param_type_2 == CPT2_COLORED_FACEDIR) { + if (f->param_type_2 == CPT2_FACEDIR || f->param_type_2 == CPT2_COLORED_FACEDIR) { facedir = n.getFaceDir(nodedef); } else if (f->param_type_2 == CPT2_WALLMOUNTED || f->param_type_2 == CPT2_COLORED_WALLMOUNTED) { @@ -1384,14 +1507,14 @@ void MapblockMeshGenerator::drawMeshNode() vertex.Color = blendLightColor(vertex.Pos, vertex.Normal); vertex.Pos += origin; } - collector->append(tile, vertices, vertex_count, - buf->getIndices(), buf->getIndexCount()); + collector->append(tile, vertices, vertex_count, buf->getIndices(), + buf->getIndexCount()); } else { // Don't modify the mesh, it may not be private here. // Instead, let the collector process colors, etc. - collector->append(tile, vertices, vertex_count, - buf->getIndices(), buf->getIndexCount(), origin, - color, f->light_source); + collector->append(tile, vertices, vertex_count, buf->getIndices(), + buf->getIndexCount(), origin, color, + f->light_source); } } if (private_mesh) @@ -1409,12 +1532,12 @@ void MapblockMeshGenerator::drawNode() { // skip some drawtypes early switch (f->drawtype) { - case NDT_NORMAL: // Drawn by MapBlockMesh - case NDT_AIRLIKE: // Not drawn at all - case NDT_LIQUID: // Drawn by MapBlockMesh - return; - default: - break; + case NDT_NORMAL: // Drawn by MapBlockMesh + case NDT_AIRLIKE: // Not drawn at all + case NDT_LIQUID: // Drawn by MapBlockMesh + return; + default: + break; } origin = intToFloat(p, BS); if (data->m_smooth_lighting) @@ -1422,20 +1545,48 @@ void MapblockMeshGenerator::drawNode() else light = LightPair(getInteriorLight(n, 1, nodedef)); switch (f->drawtype) { - case NDT_FLOWINGLIQUID: drawLiquidNode(); break; - case NDT_GLASSLIKE: drawGlasslikeNode(); break; - case NDT_GLASSLIKE_FRAMED: drawGlasslikeFramedNode(); break; - case NDT_ALLFACES: drawAllfacesNode(); break; - case NDT_TORCHLIKE: drawTorchlikeNode(); break; - case NDT_SIGNLIKE: drawSignlikeNode(); break; - case NDT_PLANTLIKE: drawPlantlikeNode(); break; - case NDT_PLANTLIKE_ROOTED: drawPlantlikeRootedNode(); break; - case NDT_FIRELIKE: drawFirelikeNode(); break; - case NDT_FENCELIKE: drawFencelikeNode(); break; - case NDT_RAILLIKE: drawRaillikeNode(); break; - case NDT_NODEBOX: drawNodeboxNode(); break; - case NDT_MESH: drawMeshNode(); break; - default: errorUnknownDrawtype(); break; + case NDT_FLOWINGLIQUID: + drawLiquidNode(); + break; + case NDT_GLASSLIKE: + drawGlasslikeNode(); + break; + case NDT_GLASSLIKE_FRAMED: + drawGlasslikeFramedNode(); + break; + case NDT_ALLFACES: + drawAllfacesNode(); + break; + case NDT_TORCHLIKE: + drawTorchlikeNode(); + break; + case NDT_SIGNLIKE: + drawSignlikeNode(); + break; + case NDT_PLANTLIKE: + drawPlantlikeNode(); + break; + case NDT_PLANTLIKE_ROOTED: + drawPlantlikeRootedNode(); + break; + case NDT_FIRELIKE: + drawFirelikeNode(); + break; + case NDT_FENCELIKE: + drawFencelikeNode(); + break; + case NDT_RAILLIKE: + drawRaillikeNode(); + break; + case NDT_NODEBOX: + drawNodeboxNode(); + break; + case NDT_MESH: + drawMeshNode(); + break; + default: + errorUnknownDrawtype(); + break; } } @@ -1446,12 +1597,12 @@ void MapblockMeshGenerator::drawNode() void MapblockMeshGenerator::generate() { for (p.Z = 0; p.Z < MAP_BLOCKSIZE; p.Z++) - for (p.Y = 0; p.Y < MAP_BLOCKSIZE; p.Y++) - for (p.X = 0; p.X < MAP_BLOCKSIZE; p.X++) { - n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p); - f = &nodedef->get(n); - drawNode(); - } + for (p.Y = 0; p.Y < MAP_BLOCKSIZE; p.Y++) + for (p.X = 0; p.X < MAP_BLOCKSIZE; p.X++) { + n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p); + f = &nodedef->get(n); + drawNode(); + } } void MapblockMeshGenerator::renderSingle(content_t node) |