#include "util/numeric.h"
#include <map>
#include <IMeshManipulator.h>
+#include "client/renderingengine.h"
#define WIELD_SCALE_FACTOR 30.0
#define WIELD_SCALE_FACTOR_EXTRUDED 40.0
m_meshnode->setReadOnlyMaterials(false);
m_meshnode->setVisible(false);
dummymesh->drop(); // m_meshnode grabbed it
+
+ m_shadow = RenderingEngine::get_shadow_renderer();
}
WieldMeshSceneNode::~WieldMeshSceneNode()
{
sanity_check(g_extrusion_mesh_cache);
+
+ // Remove node from shadow casters. m_shadow might be an invalid pointer!
+ if (auto shadow = RenderingEngine::get_shadow_renderer())
+ shadow->removeNodeFromShadowList(m_meshnode);
+
if (g_extrusion_mesh_cache->drop())
g_extrusion_mesh_cache = nullptr;
}
}
material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter);
// mipmaps cause "thin black line" artifacts
-#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
material.setFlag(video::EMF_USE_MIP_MAPS, false);
-#endif
if (m_enable_shaders) {
material.setTexture(2, tsrc->getShaderFlagsTexture(false));
}
}
}
-scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector<ItemPartColor> *colors)
+static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
+ std::vector<ItemPartColor> *colors, const ContentFeatures &f)
{
- MeshMakeData mesh_make_data(client, false, false);
+ MeshMakeData mesh_make_data(client, false);
MeshCollector collector;
mesh_make_data.setSmoothLighting(false);
- MapblockMeshGenerator gen(&mesh_make_data, &collector);
- gen.renderSingle(id);
+ MapblockMeshGenerator gen(&mesh_make_data, &collector,
+ client->getSceneManager()->getMeshManipulator());
+
+ if (n.getParam2()) {
+ // keep it
+ } else if (f.param_type_2 == CPT2_WALLMOUNTED ||
+ f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
+ if (f.drawtype == NDT_TORCHLIKE ||
+ f.drawtype == NDT_SIGNLIKE ||
+ f.drawtype == NDT_NODEBOX ||
+ f.drawtype == NDT_MESH) {
+ n.setParam2(4);
+ }
+ } else if (f.drawtype == NDT_SIGNLIKE || f.drawtype == NDT_TORCHLIKE) {
+ n.setParam2(1);
+ }
+ gen.renderSingle(n.getContent(), n.getParam2());
+
colors->clear();
scene::SMesh *mesh = new scene::SMesh();
for (auto &prebuffers : collector.prebuffers)
p.layer.texture = frame.texture;
p.layer.normal_texture = frame.normal_texture;
}
- for (video::S3DVertex &v : p.vertices)
+ for (video::S3DVertex &v : p.vertices) {
v.Color.setAlpha(255);
+ }
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
buf->Material.setTexture(0, p.layer.texture);
p.layer.applyMaterialOptions(buf->Material);
// Handle nodes
// See also CItemDefManager::createClientCached()
if (def.type == ITEM_NODE) {
- if (f.mesh_ptr[0]) {
- // e.g. mesh nodes and nodeboxes
- mesh = cloneMesh(f.mesh_ptr[0]);
- postProcessNodeMesh(mesh, f, m_enable_shaders, true,
- &m_material_type, &m_colors);
+ 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);
+ break;
+ case NDT_SIGNLIKE:
+ case NDT_TORCHLIKE:
+ case NDT_RAILLIKE:
+ case NDT_PLANTLIKE:
+ case NDT_FLOWINGLIQUID: {
+ v3f wscale = def.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),
+ wscale, tsrc,
+ f.tiles[0].layers[0].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),
+ "", def.wield_scale, tsrc,
+ f.special_tiles[0].layers[0].animation_frame_count);
+ // Add color
+ const TileLayer &l0 = f.special_tiles[0].layers[0];
+ m_colors.emplace_back(l0.has_color, l0.color);
+ break;
+ }
+ case NDT_NORMAL:
+ case NDT_ALLFACES:
+ case NDT_LIQUID:
+ setCube(f, def.wield_scale);
+ break;
+ default: {
+ // Render non-trivial drawtypes like the actual node
+ MapNode n(id);
+ n.setParam2(def.place_param2);
+
+ mesh = createSpecialNodeMesh(client, n, &m_colors, f);
changeToMesh(mesh);
mesh->drop();
- // mesh is pre-scaled by BS * f->visual_scale
m_meshnode->setScale(
- def.wield_scale * WIELD_SCALE_FACTOR
- / (BS * f.visual_scale));
- } else {
- switch (f.drawtype) {
- case NDT_AIRLIKE: {
- changeToMesh(nullptr);
- break;
- }
- case NDT_PLANTLIKE: {
- setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
- tsrc->getTextureName(f.tiles[0].layers[1].texture_id),
- def.wield_scale, tsrc,
- f.tiles[0].layers[0].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),
- "", def.wield_scale, tsrc,
- f.special_tiles[0].layers[0].animation_frame_count);
- // Add color
- const TileLayer &l0 = f.special_tiles[0].layers[0];
- m_colors.emplace_back(l0.has_color, l0.color);
- break;
- }
- case NDT_NORMAL:
- case NDT_ALLFACES:
- case NDT_LIQUID:
- case NDT_FLOWINGLIQUID: {
- setCube(f, def.wield_scale);
- break;
- }
- default: {
- mesh = createSpecialNodeMesh(client, id, &m_colors);
- changeToMesh(mesh);
- mesh->drop();
- m_meshnode->setScale(
- def.wield_scale * WIELD_SCALE_FACTOR
- / (BS * f.visual_scale));
- }
- }
+ def.wield_scale * WIELD_SCALE_FACTOR
+ / (BS * f.visual_scale));
+ break;
+ }
}
+
u32 material_count = m_meshnode->getMaterialCount();
for (u32 i = 0; i < material_count; ++i) {
video::SMaterial &material = m_meshnode->getMaterial(i);
material.MaterialType = m_material_type;
material.MaterialTypeParam = 0.5f;
- material.setFlag(video::EMF_BACK_FACE_CULLING, true);
+ material.setFlag(video::EMF_BACK_FACE_CULLING, cull_backface);
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
}
return;
- }
- else if (!def.inventory_image.empty()) {
- setExtruded(def.inventory_image, def.inventory_overlay, def.wield_scale,
- tsrc, 1);
+ } else {
+ if (!def.inventory_image.empty()) {
+ setExtruded(def.inventory_image, def.inventory_overlay, def.wield_scale,
+ tsrc, 1);
+ } else {
+ setExtruded("no_texture.png", "", def.wield_scale, tsrc, 1);
+ }
+
m_colors.emplace_back();
// overlay is white, if present
m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
material.EmissiveColor = color;
}
}
-
- setColor(color);
+ else {
+ setColor(color);
+ }
}
void WieldMeshSceneNode::render()
// need to normalize normals when lighting is enabled (because of setScale())
m_meshnode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, m_lighting);
m_meshnode->setVisible(true);
+
+ if (m_shadow) {
+ // Add mesh to shadow caster
+ m_shadow->addNodeToShadowList(m_meshnode);
+
+ // Set shadow texture
+ for (u32 i = 0; i < m_meshnode->getMaterialCount(); i++)
+ m_meshnode->setMaterialTexture(3, m_shadow->get_texture());
+ }
}
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
content_t id = ndef->getId(def.name);
FATAL_ERROR_IF(!g_extrusion_mesh_cache, "Extrusion mesh cache is not yet initialized");
-
+
scene::SMesh *mesh = nullptr;
// Shading is on by default
result->needs_shading = true;
+ bool cull_backface = f.needsBackfaceCulling();
+
// If inventory_image is defined, it overrides everything else
if (!def.inventory_image.empty()) {
mesh = getExtrudedMesh(tsrc, def.inventory_image,
result->buffer_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
// Items with inventory images do not need shading
result->needs_shading = false;
+ } else if (def.type == ITEM_NODE && f.drawtype == NDT_AIRLIKE) {
+ // Fallback image for airlike node
+ mesh = getExtrudedMesh(tsrc, "no_texture_airlike.png",
+ def.inventory_overlay);
+ result->needs_shading = false;
} else if (def.type == ITEM_NODE) {
- if (f.mesh_ptr[0]) {
- mesh = cloneMesh(f.mesh_ptr[0]);
- scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
+ 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, false, nullptr,
- &result->buffer_colors);
- } else {
- switch (f.drawtype) {
- case NDT_PLANTLIKE: {
- mesh = getExtrudedMesh(tsrc,
- tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
- tsrc->getTextureName(f.tiles[0].layers[1].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
- const TileLayer &l0 = f.special_tiles[0].layers[0];
- result->buffer_colors.emplace_back(l0.has_color, l0.color);
- break;
- }
- 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();
- scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
- // add overlays
- postProcessNodeMesh(mesh, f, false, false, nullptr,
- &result->buffer_colors);
- break;
- }
- default: {
- mesh = createSpecialNodeMesh(client, id, &result->buffer_colors);
- scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
- }
- }
+ &result->buffer_colors, true);
+ if (f.drawtype == NDT_ALLFACES)
+ scaleMesh(mesh, v3f(f.visual_scale));
+ break;
+ }
+ case NDT_PLANTLIKE: {
+ mesh = getExtrudedMesh(tsrc,
+ tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
+ tsrc->getTextureName(f.tiles[0].layers[1].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
+ const TileLayer &l0 = f.special_tiles[0].layers[0];
+ result->buffer_colors.emplace_back(l0.has_color, l0.color);
+ break;
+ }
+ default: {
+ // Render non-trivial drawtypes like the actual node
+ MapNode n(id);
+ n.setParam2(def.place_param2);
+
+ mesh = createSpecialNodeMesh(client, n, &result->buffer_colors, f);
+ scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
+ break;
+ }
}
u32 mc = mesh->getMeshBufferCount();
material.MaterialTypeParam = 0.5f;
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
- material.setFlag(video::EMF_BACK_FACE_CULLING, true);
+ material.setFlag(video::EMF_BACK_FACE_CULLING, cull_backface);
material.setFlag(video::EMF_LIGHTING, false);
}