diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 5b69b4a5da182..d8f1ff3b69fcc 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -1781,11 +1781,3 @@ void MapblockMeshGenerator::generate() drawNode(); } } - -void MapblockMeshGenerator::renderSingle(content_t node, u8 param2) -{ - cur_node.p = {0, 0, 0}; - cur_node.n = MapNode(node, 0xff, param2); - cur_node.f = &nodedef->get(cur_node.n); - drawNode(); -} diff --git a/src/client/content_mapblock.h b/src/client/content_mapblock.h index 2bfbbdc614483..a4ed6a0fce83a 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -47,7 +47,6 @@ class MapblockMeshGenerator public: MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output); void generate(); - void renderSingle(content_t node, u8 param2 = 0x00); private: MeshMakeData *const data; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 05f9e73cc0af1..a47bf5ae93bc0 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -31,7 +31,9 @@ MeshMakeData::MeshMakeData(const NodeDefManager *ndef, m_side_length(side_length), m_mesh_grid(mesh_grid), m_nodedef(ndef) -{} +{ + assert(m_side_length > 0); +} void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos) { @@ -55,6 +57,24 @@ void MeshMakeData::fillBlockData(const v3s16 &bp, MapNode *data) m_vmanip.copyFrom(data, data_area, v3s16(0,0,0), blockpos_nodes, data_size); } +void MeshMakeData::fillSingleNode(MapNode data, MapNode padding) +{ + m_blockpos = {0, 0, 0}; + + m_vmanip.clear(); + // area around 0,0,0 so that this positon has neighbors + const s16 sz = 3; + m_vmanip.addArea({v3s16(-sz), v3s16(sz)}); + + u32 count = m_vmanip.m_area.getVolume(); + for (u32 i = 0; i < count; i++) { + m_vmanip.m_data[i] = padding; + m_vmanip.m_flags[i] &= ~VOXELFLAG_NO_DATA; + } + + m_vmanip.setNodeNoEmerge({0, 0, 0}, data); +} + void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos) { if (crack_level >= 0) @@ -628,6 +648,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs MeshCollector collector(m_bounding_sphere_center, offset); { + // Generate everything MapblockMeshGenerator(data, &collector).generate(); } @@ -940,21 +961,22 @@ video::SColor encode_light(u16 light, u8 emissive_light) u8 get_solid_sides(MeshMakeData *data) { - std::unordered_map results; v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE; const NodeDefManager *ndef = data->m_nodedef; - u8 result = 0x3F; // all sides solid; + const u16 side = data->m_side_length; + assert(data->m_vmanip.m_area.contains(blockpos_nodes + v3s16(side - 1))); - for (s16 i = 0; i < data->m_side_length && result != 0; i++) - for (s16 j = 0; j < data->m_side_length && result != 0; j++) { + u8 result = 0x3F; // all sides solid + for (s16 i = 0; i < side && result != 0; i++) + for (s16 j = 0; j < side && result != 0; j++) { v3s16 positions[6] = { v3s16(0, i, j), - v3s16(data->m_side_length - 1, i, j), + v3s16(side - 1, i, j), v3s16(i, 0, j), - v3s16(i, data->m_side_length - 1, j), + v3s16(i, side - 1, j), v3s16(i, j, 0), - v3s16(i, j, data->m_side_length - 1) + v3s16(i, j, side - 1) }; for (u8 k = 0; k < 6; k++) { diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 47941386ea780..55aa172bdb418 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -62,6 +62,11 @@ struct MeshMakeData void fillBlockDataBegin(const v3s16 &blockpos); void fillBlockData(const v3s16 &bp, MapNode *data); + /* + Prepare block data for rendering a single node located at (0,0,0). + */ + void fillSingleNode(MapNode data, MapNode padding = MapNode(CONTENT_AIR)); + /* Set the (node) position of a crack */ diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 4c4042ad48ab5..f03de2a5bdc7e 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -21,24 +21,12 @@ #include #include "client/renderingengine.h" -#define WIELD_SCALE_FACTOR 30.0 -#define WIELD_SCALE_FACTOR_EXTRUDED 40.0 +#define WIELD_SCALE_FACTOR 30.0f +#define WIELD_SCALE_FACTOR_EXTRUDED 40.0f #define MIN_EXTRUSION_MESH_RESOLUTION 16 #define MAX_EXTRUSION_MESH_RESOLUTION 512 -/*! - * Applies overlays, textures and optionally materials to the given mesh and - * extracts tile colors for colorization. - * \param mattype overrides the buffer's material type, but can also - * be NULL to leave the original material. - * \param colors returns the colors of the mesh buffers in the mesh. - */ -static void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, - bool set_material, const video::E_MATERIAL_TYPE *mattype, - std::vector *colors, bool apply_scale = false); - - static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y) { const f32 r = 0.5; @@ -237,19 +225,6 @@ WieldMeshSceneNode::~WieldMeshSceneNode() g_extrusion_mesh_cache = nullptr; } -void WieldMeshSceneNode::setCube(const ContentFeatures &f, - v3f wield_scale) -{ - scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube(); - scene::SMesh *copy = cloneMesh(cubemesh); - cubemesh->drop(); - postProcessNodeMesh(copy, f, false, &m_material_type, &m_colors, true); - copy->recalculateBoundingBox(); - changeToMesh(copy); - copy->drop(); - m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR); -} - void WieldMeshSceneNode::setExtruded(const std::string &imagename, const std::string &overlay_name, v3f wield_scale, ITextureSource *tsrc, u8 num_frames) @@ -264,6 +239,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, core::dimension2d dim = texture->getSize(); // Detect animation texture and pull off top frame instead of using entire thing + // FIXME: this is quite unportable, we should be working with the original TileLayer if there's one if (num_frames > 1) { u32 frame_height = dim.Height / num_frames; dim = core::dimension2d(dim.Width, frame_height); @@ -275,6 +251,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, mesh->getMeshBuffer(0)->getMaterial().setTexture(0, tsrc->getTexture(imagename)); if (overlay_texture) { + // duplicate the extruded mesh for the overlay scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); copy->getMaterial().setTexture(0, overlay_texture); mesh->addMeshBuffer(copy); @@ -306,16 +283,10 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, } } -static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, +static scene::SMesh *createGenericNodeMesh(Client *client, MapNode n, std::vector *colors, const ContentFeatures &f) { - MeshMakeData mesh_make_data(client->ndef(), 1, client->getMeshGrid()); - MeshCollector collector(v3f(0.0f * BS), v3f()); - mesh_make_data.m_generate_minimap = false; - mesh_make_data.m_smooth_lighting = false; - mesh_make_data.m_enable_water_reflections = false; - MapblockMeshGenerator gen(&mesh_make_data, &collector); - + n.setParam1(0xff); if (n.getParam2()) { // keep it } else if (f.param_type_2 == CPT2_WALLMOUNTED || @@ -329,7 +300,13 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, } else if (f.drawtype == NDT_SIGNLIKE || f.drawtype == NDT_TORCHLIKE) { n.setParam2(1); } - gen.renderSingle(n.getContent(), n.getParam2()); + + MeshCollector collector(v3f(0), v3f()); + { + MeshMakeData mmd(client->ndef(), 1, MeshGrid{1}); + mmd.fillSingleNode(n); + MapblockMeshGenerator(&mmd, &collector).generate(); + } colors->clear(); scene::SMesh *mesh = new scene::SMesh(); @@ -399,15 +376,12 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che } // Handle nodes - // See also CItemDefManager::createClientCached() if (def.type == ITEM_NODE) { - bool cull_backface = f.needsBackfaceCulling(); - // Select rendering method switch (f.drawtype) { case NDT_AIRLIKE: setExtruded("no_texture_airlike.png", "", - v3f(1.0, 1.0, 1.0), tsrc, 1); + v3f(1), tsrc, 1); break; case NDT_SIGNLIKE: case NDT_TORCHLIKE: @@ -417,38 +391,33 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che v3f wscale = wield_scale; if (f.drawtype == NDT_FLOWINGLIQUID) wscale.Z *= 0.1f; - setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id), - tsrc->getTextureName(f.tiles[0].layers[1].texture_id), + const TileLayer &l0 = f.tiles[0].layers[0]; + const TileLayer &l1 = f.tiles[0].layers[1]; + setExtruded(tsrc->getTextureName(l0.texture_id), + tsrc->getTextureName(l1.texture_id), wscale, tsrc, - f.tiles[0].layers[0].animation_frame_count); + l0.animation_frame_count); // Add color - const TileLayer &l0 = f.tiles[0].layers[0]; m_colors.emplace_back(l0.has_color, l0.color); - const TileLayer &l1 = f.tiles[0].layers[1]; m_colors.emplace_back(l1.has_color, l1.color); break; } case NDT_PLANTLIKE_ROOTED: { - setExtruded(tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), - "", wield_scale, tsrc, - f.special_tiles[0].layers[0].animation_frame_count); - // Add color + // use the plant tile const TileLayer &l0 = f.special_tiles[0].layers[0]; + setExtruded(tsrc->getTextureName(l0.texture_id), + "", wield_scale, tsrc, + l0.animation_frame_count); m_colors.emplace_back(l0.has_color, l0.color); break; } - case NDT_NORMAL: - case NDT_ALLFACES: - case NDT_LIQUID: - setCube(f, wield_scale); - break; default: { - // Render non-trivial drawtypes like the actual node + // Render all other drawtypes like the actual node MapNode n(id); if (def.place_param2) n.setParam2(*def.place_param2); - mesh = createSpecialNodeMesh(client, n, &m_colors, f); + mesh = createGenericNodeMesh(client, n, &m_colors, f); changeToMesh(mesh); mesh->drop(); m_meshnode->setScale( @@ -461,9 +430,9 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che u32 material_count = m_meshnode->getMaterialCount(); for (u32 i = 0; i < material_count; ++i) { video::SMaterial &material = m_meshnode->getMaterial(i); + // FIXME: overriding this breaks different alpha modes the mesh may have material.MaterialType = m_material_type; material.MaterialTypeParam = 0.5f; - material.BackfaceCulling = cull_backface; material.forEachTexture([this] (auto &tex) { setMaterialFilters(tex, m_bilinear_filter, m_trilinear_filter, m_anisotropic_filter); @@ -574,8 +543,6 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) // Shading is on by default result->needs_shading = true; - bool cull_backface = f.needsBackfaceCulling(); - // If inventory_image is defined, it overrides everything else const std::string inventory_image = item.getInventoryImage(idef); const std::string inventory_overlay = item.getInventoryOverlay(idef); @@ -592,51 +559,32 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) result->needs_shading = false; } else if (def.type == ITEM_NODE) { switch (f.drawtype) { - case NDT_NORMAL: - case NDT_ALLFACES: - case NDT_LIQUID: - case NDT_FLOWINGLIQUID: { - scene::IMesh *cube = g_extrusion_mesh_cache->createCube(); - mesh = cloneMesh(cube); - cube->drop(); - if (f.drawtype == NDT_FLOWINGLIQUID) { - scaleMesh(mesh, v3f(1.2, 0.03, 1.2)); - translateMesh(mesh, v3f(0, -0.57, 0)); - } else - scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); - // add overlays - postProcessNodeMesh(mesh, f, false, nullptr, - &result->buffer_colors, true); - if (f.drawtype == NDT_ALLFACES) - scaleMesh(mesh, v3f(f.visual_scale)); - break; - } case NDT_PLANTLIKE: { + const TileLayer &l0 = f.tiles[0].layers[0]; + const TileLayer &l1 = f.tiles[0].layers[1]; mesh = getExtrudedMesh(tsrc, - tsrc->getTextureName(f.tiles[0].layers[0].texture_id), - tsrc->getTextureName(f.tiles[0].layers[1].texture_id)); + tsrc->getTextureName(l0.texture_id), + tsrc->getTextureName(l1.texture_id)); // Add color - const TileLayer &l0 = f.tiles[0].layers[0]; result->buffer_colors.emplace_back(l0.has_color, l0.color); - const TileLayer &l1 = f.tiles[0].layers[1]; result->buffer_colors.emplace_back(l1.has_color, l1.color); break; } case NDT_PLANTLIKE_ROOTED: { - mesh = getExtrudedMesh(tsrc, - tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), ""); - // Add color + // Use the plant tile const TileLayer &l0 = f.special_tiles[0].layers[0]; + mesh = getExtrudedMesh(tsrc, + tsrc->getTextureName(l0.texture_id), ""); result->buffer_colors.emplace_back(l0.has_color, l0.color); break; } default: { - // Render non-trivial drawtypes like the actual node + // Render all other drawtypes like the actual node MapNode n(id); if (def.place_param2) n.setParam2(*def.place_param2); - mesh = createSpecialNodeMesh(client, n, &result->buffer_colors, f); + mesh = createGenericNodeMesh(client, n, &result->buffer_colors, f); scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); break; } @@ -645,13 +593,13 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); video::SMaterial &material = buf->getMaterial(); + // FIXME: overriding this breaks different alpha modes the mesh may have material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; material.MaterialTypeParam = 0.5f; material.forEachTexture([] (auto &tex) { tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; tex.MagFilter = video::ETMAGF_NEAREST; }); - material.BackfaceCulling = cull_backface; } rotateMeshXZby(mesh, -45); @@ -672,7 +620,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename, const std::string &overlay_name) { // check textures - video::ITexture *texture = tsrc->getTextureForMesh(imagename); + video::ITexture *texture = tsrc->getTexture(imagename); if (!texture) { return NULL; } @@ -707,59 +655,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; material.MaterialTypeParam = 0.5f; } - scaleMesh(mesh, v3f(2.0, 2.0, 2.0)); + scaleMesh(mesh, v3f(2)); return mesh; } - -static void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, - bool set_material, const video::E_MATERIAL_TYPE *mattype, - std::vector *colors, bool apply_scale) -{ - // FIXME: this function is weirdly inconsistent with what MapBlockMesh does. - // also set_material is never true - - const u32 mc = mesh->getMeshBufferCount(); - // Allocate colors for existing buffers - colors->resize(mc); - - for (u32 i = 0; i < mc; ++i) { - const TileSpec *tile = &(f.tiles[i]); - scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); - for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { - const TileLayer *layer = &tile->layers[layernum]; - if (layer->texture_id == 0) - continue; - if (layernum != 0) { - // FIXME: why do this? - scene::IMeshBuffer *copy = cloneMeshBuffer(buf); - copy->getMaterial() = buf->getMaterial(); - mesh->addMeshBuffer(copy); - copy->drop(); - buf = copy; - colors->emplace_back(layer->has_color, layer->color); - } else { - (*colors)[i] = ItemPartColor(layer->has_color, layer->color); - } - - video::SMaterial &material = buf->getMaterial(); - if (set_material) - layer->applyMaterialOptions(material); - if (mattype) { - material.MaterialType = *mattype; - } - if (layer->animation_frame_count > 1) { - const FrameSpec &animation_frame = (*layer->frames)[0]; - material.setTexture(0, animation_frame.texture); - } else { - material.setTexture(0, layer->texture); - } - - if (apply_scale && tile->world_aligned) { - u32 n = buf->getVertexCount(); - for (u32 k = 0; k != n; ++k) - buf->getTCoords(k) /= layer->scale; - } - } - } -} diff --git a/src/client/wieldmesh.h b/src/client/wieldmesh.h index a3d8c3af196f9..0b65dfbd93fa1 100644 --- a/src/client/wieldmesh.h +++ b/src/client/wieldmesh.h @@ -92,7 +92,6 @@ class WieldMeshSceneNode : public scene::ISceneNode WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1); virtual ~WieldMeshSceneNode(); - void setCube(const ContentFeatures &f, v3f wield_scale); void setExtruded(const std::string &imagename, const std::string &overlay_image, v3f wield_scale, ITextureSource *tsrc, u8 num_frames); void setItem(const ItemStack &item, Client *client, diff --git a/src/nodedef.h b/src/nodedef.h index d819be8158c3d..24bb0c4605977 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -474,21 +474,6 @@ struct ContentFeatures } } - bool needsBackfaceCulling() const - { - switch (drawtype) { - case NDT_TORCHLIKE: - case NDT_SIGNLIKE: - case NDT_FIRELIKE: - case NDT_RAILLIKE: - case NDT_PLANTLIKE: - case NDT_PLANTLIKE_ROOTED: - case NDT_MESH: - return false; - default: - return true; - } - } bool isLiquid() const{ return (liquid_type != LIQUID_NONE); diff --git a/src/voxel.h b/src/voxel.h index 63775040db9bd..c47f97a300e40 100644 --- a/src/voxel.h +++ b/src/voxel.h @@ -459,7 +459,9 @@ class VoxelManipulator { if(!m_area.contains(p)) return false; - m_data[m_area.index(p)] = n; + const s32 index = m_area.index(p); + m_data[index] = n; + m_flags[index] &= ~VOXELFLAG_NO_DATA; return true; }