X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fwieldmesh.cpp;h=0394cc9eadd1e8761af042049ccb3ef3343342f5;hb=5a6618cc57097e1e7205ad6b1d967a3ad79d016e;hp=c305238feee409dfcedf25ccd4b6dee4f9644cf9;hpb=8e7449e09253e138716d8dbad6a2ab5c6e089e28;p=minetest.git diff --git a/src/wieldmesh.cpp b/src/wieldmesh.cpp index c305238fe..0394cc9ea 100644 --- a/src/wieldmesh.cpp +++ b/src/wieldmesh.cpp @@ -17,8 +17,9 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "settings.h" #include "wieldmesh.h" +#include "settings.h" +#include "shader.h" #include "inventory.h" #include "client.h" #include "itemdef.h" @@ -145,10 +146,8 @@ class ExtrusionMeshCache: public IReferenceCounted // Destructor virtual ~ExtrusionMeshCache() { - for (std::map::iterator - it = m_extrusion_meshes.begin(); - it != m_extrusion_meshes.end(); ++it) { - it->second->drop(); + for (auto &extrusion_meshe : m_extrusion_meshes) { + extrusion_meshe.second->drop(); } m_cube->drop(); } @@ -192,17 +191,10 @@ class ExtrusionMeshCache: public IReferenceCounted ExtrusionMeshCache *g_extrusion_mesh_cache = NULL; -WieldMeshSceneNode::WieldMeshSceneNode( - scene::ISceneNode *parent, - scene::ISceneManager *mgr, - s32 id, - bool lighting -): - scene::ISceneNode(parent, mgr, id), - m_meshnode(NULL), +WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting): + scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF), - m_lighting(lighting), - m_bounding_box(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + m_lighting(lighting) { m_enable_shaders = g_settings->getBool("enable_shaders"); m_anisotropic_filter = g_settings->getBool("anisotropic_filter"); @@ -211,7 +203,7 @@ WieldMeshSceneNode::WieldMeshSceneNode( // If this is the first wield mesh scene node, create a cache // for extrusion meshes (and a cube mesh), otherwise reuse it - if (g_extrusion_mesh_cache == NULL) + if (!g_extrusion_mesh_cache) g_extrusion_mesh_cache = new ExtrusionMeshCache(); else g_extrusion_mesh_cache->grab(); @@ -232,40 +224,32 @@ WieldMeshSceneNode::~WieldMeshSceneNode() { sanity_check(g_extrusion_mesh_cache); if (g_extrusion_mesh_cache->drop()) - g_extrusion_mesh_cache = NULL; + g_extrusion_mesh_cache = nullptr; } -void WieldMeshSceneNode::setCube(const TileSpec tiles[6], - v3f wield_scale, ITextureSource *tsrc) +void WieldMeshSceneNode::setCube(const ContentFeatures &f, + v3f wield_scale) { scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube(); - changeToMesh(cubemesh); + scene::SMesh *copy = cloneMesh(cubemesh); cubemesh->drop(); - + postProcessNodeMesh(copy, f, false, true, &m_material_type, &m_colors); + changeToMesh(copy); + copy->drop(); m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR); - - // Customize materials - for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) { - assert(i < 6); - video::SMaterial &material = m_meshnode->getMaterial(i); - if (tiles[i].animation_frame_count == 1) { - material.setTexture(0, tiles[i].texture); - } else { - FrameSpec animation_frame = tiles[i].frames[0]; - material.setTexture(0, animation_frame.texture); - } - tiles[i].applyMaterialOptions(material); - } } void WieldMeshSceneNode::setExtruded(const std::string &imagename, - v3f wield_scale, ITextureSource *tsrc, u8 num_frames) + const std::string &overlay_name, v3f wield_scale, ITextureSource *tsrc, + u8 num_frames) { video::ITexture *texture = tsrc->getTexture(imagename); if (!texture) { - changeToMesh(NULL); + changeToMesh(nullptr); return; } + video::ITexture *overlay_texture = + overlay_name.empty() ? NULL : tsrc->getTexture(overlay_name); core::dimension2d dim = texture->getSize(); // Detect animation texture and pull off top frame instead of using entire thing @@ -273,34 +257,46 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, u32 frame_height = dim.Height / num_frames; dim = core::dimension2d(dim.Width, frame_height); } - scene::IMesh *mesh = g_extrusion_mesh_cache->create(dim); + scene::IMesh *original = g_extrusion_mesh_cache->create(dim); + scene::SMesh *mesh = cloneMesh(original); + original->drop(); + //set texture + mesh->getMeshBuffer(0)->getMaterial().setTexture(0, + tsrc->getTexture(imagename)); + if (overlay_texture) { + scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); + copy->getMaterial().setTexture(0, overlay_texture); + mesh->addMeshBuffer(copy); + copy->drop(); + } changeToMesh(mesh); mesh->drop(); m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR_EXTRUDED); - // Customize material - video::SMaterial &material = m_meshnode->getMaterial(0); - material.setTexture(0, tsrc->getTextureForMesh(imagename)); - material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; - material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; - material.MaterialType = m_material_type; - material.setFlag(video::EMF_BACK_FACE_CULLING, true); - // Enable bi/trilinear filtering only for high resolution textures - if (dim.Width > 32) { - material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter); - material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter); - } else { - material.setFlag(video::EMF_BILINEAR_FILTER, false); - material.setFlag(video::EMF_TRILINEAR_FILTER, false); - } - material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter); - // mipmaps cause "thin black line" artifacts + // Customize materials + for (u32 layer = 0; layer < m_meshnode->getMaterialCount(); layer++) { + video::SMaterial &material = m_meshnode->getMaterial(layer); + material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; + material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; + material.MaterialType = m_material_type; + material.setFlag(video::EMF_BACK_FACE_CULLING, true); + // Enable bi/trilinear filtering only for high resolution textures + if (dim.Width > 32) { + material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter); + material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter); + } else { + material.setFlag(video::EMF_BILINEAR_FILTER, false); + material.setFlag(video::EMF_TRILINEAR_FILTER, false); + } + 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); + material.setFlag(video::EMF_USE_MIP_MAPS, false); #endif - if (m_enable_shaders) { - material.setTexture(2, tsrc->getShaderFlagsTexture(false)); + if (m_enable_shaders) { + material.setTexture(2, tsrc->getShaderFlagsTexture(false)); + } } } @@ -319,85 +315,127 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client) m_material_type = shdrsrc->getShaderInfo(shader_id).material; } + // Color-related + m_colors.clear(); + m_base_color = idef->getItemstackColor(item, client); + // If wield_image is defined, it overrides everything else - if (def.wield_image != "") { - setExtruded(def.wield_image, def.wield_scale, tsrc, 1); + if (!def.wield_image.empty()) { + setExtruded(def.wield_image, def.wield_overlay, def.wield_scale, tsrc, + 1); + m_colors.emplace_back(); + // overlay is white, if present + m_colors.emplace_back(true, video::SColor(0xFFFFFFFF)); return; } + // Handle nodes // See also CItemDefManager::createClientCached() - else if (def.type == ITEM_NODE) { + if (def.type == ITEM_NODE) { if (f.mesh_ptr[0]) { // e.g. mesh nodes and nodeboxes - changeToMesh(f.mesh_ptr[0]); - // mesh_ptr[0] is pre-scaled by BS * f->visual_scale + scene::SMesh *mesh = cloneMesh(f.mesh_ptr[0]); + postProcessNodeMesh(mesh, f, m_enable_shaders, true, + &m_material_type, &m_colors); + 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 if (f.drawtype == NDT_AIRLIKE) { - changeToMesh(NULL); - } else if (f.drawtype == NDT_PLANTLIKE) { - setExtruded(tsrc->getTextureName(f.tiles[0].texture_id), def.wield_scale, tsrc, f.tiles[0].animation_frame_count); - } else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) { - setCube(f.tiles, def.wield_scale, tsrc); } else { - MeshMakeData mesh_make_data(client, false); - MapNode mesh_make_node(id, 255, 0); - mesh_make_data.fillSingleNode(&mesh_make_node); - MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0)); - changeToMesh(mapblock_mesh.getMesh()); - translateMesh(m_meshnode->getMesh(), v3f(-BS, -BS, -BS)); - m_meshnode->setScale( - def.wield_scale * WIELD_SCALE_FACTOR - / (BS * f.visual_scale)); + 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: { + setCube(f, def.wield_scale); + break; + } + default: { + MeshMakeData mesh_make_data(client, false); + MapNode mesh_make_node(id, 255, 0); + mesh_make_data.fillSingleNode(&mesh_make_node); + MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0)); + scene::SMesh *mesh = cloneMesh(mapblock_mesh.getMesh()); + translateMesh(mesh, v3f(-BS, -BS, -BS)); + postProcessNodeMesh(mesh, f, m_enable_shaders, true, + &m_material_type, &m_colors); + changeToMesh(mesh); + mesh->drop(); + m_meshnode->setScale( + def.wield_scale * WIELD_SCALE_FACTOR + / (BS * f.visual_scale)); + } + } } u32 material_count = m_meshnode->getMaterialCount(); - if (material_count > 6) { - errorstream << "WieldMeshSceneNode::setItem: Invalid material " - "count " << material_count << ", truncating to 6" << std::endl; - material_count = 6; - } for (u32 i = 0; i < material_count; ++i) { video::SMaterial &material = m_meshnode->getMaterial(i); material.setFlag(video::EMF_BACK_FACE_CULLING, true); material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter); material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter); - bool animated = (f.tiles[i].animation_frame_count > 1); - if (animated) { - FrameSpec animation_frame = f.tiles[i].frames[0]; - material.setTexture(0, animation_frame.texture); - } else { - material.setTexture(0, f.tiles[i].texture); - } - material.MaterialType = m_material_type; - if (m_enable_shaders) { - if (f.tiles[i].normal_texture) { - if (animated) { - FrameSpec animation_frame = f.tiles[i].frames[0]; - material.setTexture(1, animation_frame.normal_texture); - } else { - material.setTexture(1, f.tiles[i].normal_texture); - } - } - material.setTexture(2, f.tiles[i].flags_texture); - } } return; } - else if (def.inventory_image != "") { - setExtruded(def.inventory_image, def.wield_scale, tsrc, 1); + else if (!def.inventory_image.empty()) { + setExtruded(def.inventory_image, def.inventory_overlay, def.wield_scale, + tsrc, 1); + m_colors.emplace_back(); + // overlay is white, if present + m_colors.emplace_back(true, video::SColor(0xFFFFFFFF)); return; } // no wield mesh found - changeToMesh(NULL); + changeToMesh(nullptr); } -void WieldMeshSceneNode::setColor(video::SColor color) +void WieldMeshSceneNode::setColor(video::SColor c) { assert(!m_lighting); - setMeshColor(m_meshnode->getMesh(), color); - shadeMeshFaces(m_meshnode->getMesh()); + scene::IMesh *mesh = m_meshnode->getMesh(); + if (!mesh) + return; + + u8 red = c.getRed(); + u8 green = c.getGreen(); + u8 blue = c.getBlue(); + u32 mc = mesh->getMeshBufferCount(); + for (u32 j = 0; j < mc; j++) { + video::SColor bc(m_base_color); + if ((m_colors.size() > j) && (m_colors[j].override_base)) + bc = m_colors[j].color; + video::SColor buffercolor(255, + bc.getRed() * red / 255, + bc.getGreen() * green / 255, + bc.getBlue() * blue / 255); + scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); + colorizeMeshBuffer(buf, &buffercolor); + } } void WieldMeshSceneNode::render() @@ -408,25 +446,13 @@ void WieldMeshSceneNode::render() void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh) { - if (mesh == NULL) { + if (!mesh) { scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube(); m_meshnode->setVisible(false); m_meshnode->setMesh(dummymesh); dummymesh->drop(); // m_meshnode grabbed it } else { - if (m_lighting) { - m_meshnode->setMesh(mesh); - } else { - /* - Lighting is disabled, this means the caller can (and probably will) - call setColor later. We therefore need to clone the mesh so that - setColor will only modify this scene node's mesh, not others'. - */ - scene::IMeshManipulator *meshmanip = SceneManager->getMeshManipulator(); - scene::IMesh *new_mesh = meshmanip->createMeshCopy(mesh); - m_meshnode->setMesh(new_mesh); - new_mesh->drop(); // m_meshnode grabbed it - } + m_meshnode->setMesh(mesh); } m_meshnode->setMaterialFlag(video::EMF_LIGHTING, m_lighting); @@ -435,7 +461,7 @@ void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh) m_meshnode->setVisible(true); } -scene::IMesh *getItemMesh(Client *client, const ItemStack &item) +void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) { ITextureSource *tsrc = client->getTextureSource(); IItemDefManager *idef = client->getItemDefManager(); @@ -450,97 +476,200 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item) g_extrusion_mesh_cache->grab(); } - scene::IMesh *mesh; + scene::SMesh *mesh = nullptr; + + // Shading is on by default + result->needs_shading = true; // If inventory_image is defined, it overrides everything else - if (def.inventory_image != "") { - mesh = getExtrudedMesh(tsrc, def.inventory_image); - return mesh; + if (!def.inventory_image.empty()) { + mesh = getExtrudedMesh(tsrc, def.inventory_image, + def.inventory_overlay); + result->buffer_colors.emplace_back(); + // overlay is white, if present + 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) { if (f.mesh_ptr[0]) { mesh = cloneMesh(f.mesh_ptr[0]); scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); - setMeshColor(mesh, video::SColor (255, 255, 255, 255)); - } else if (f.drawtype == NDT_PLANTLIKE) { - mesh = getExtrudedMesh(tsrc, - tsrc->getTextureName(f.tiles[0].texture_id)); - return mesh; - } else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES - || f.drawtype == NDT_LIQUID || f.drawtype == NDT_FLOWINGLIQUID) { - mesh = cloneMesh(g_extrusion_mesh_cache->createCube()); - scaleMesh(mesh, v3f(1.2, 1.2, 1.2)); + postProcessNodeMesh(mesh, f, false, false, nullptr, + &result->buffer_colors); } else { - MeshMakeData mesh_make_data(client, false); - MapNode mesh_make_node(id, 255, 0); - mesh_make_data.fillSingleNode(&mesh_make_node); - MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0)); - mesh = cloneMesh(mapblock_mesh.getMesh()); - translateMesh(mesh, v3f(-BS, -BS, -BS)); - scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); - rotateMeshXZby(mesh, -45); - rotateMeshYZby(mesh, -30); - - u32 mc = mesh->getMeshBufferCount(); - for (u32 i = 0; i < mc; ++i) { - video::SMaterial &material1 = - mesh->getMeshBuffer(i)->getMaterial(); - video::SMaterial &material2 = - mapblock_mesh.getMesh()->getMeshBuffer(i)->getMaterial(); - material1.setTexture(0, material2.getTexture(0)); - material1.setTexture(1, material2.getTexture(1)); - material1.setTexture(2, material2.getTexture(2)); - material1.setTexture(3, material2.getTexture(3)); - material1.MaterialType = material2.MaterialType; + 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: { + MeshMakeData mesh_make_data(client, false); + MapNode mesh_make_node(id, 255, 0); + mesh_make_data.fillSingleNode(&mesh_make_node); + MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0)); + mesh = cloneMesh(mapblock_mesh.getMesh()); + translateMesh(mesh, v3f(-BS, -BS, -BS)); + scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); + + u32 mc = mesh->getMeshBufferCount(); + for (u32 i = 0; i < mc; ++i) { + video::SMaterial &material1 = + mesh->getMeshBuffer(i)->getMaterial(); + video::SMaterial &material2 = + mapblock_mesh.getMesh()->getMeshBuffer(i)->getMaterial(); + material1.setTexture(0, material2.getTexture(0)); + material1.setTexture(1, material2.getTexture(1)); + material1.setTexture(2, material2.getTexture(2)); + material1.setTexture(3, material2.getTexture(3)); + material1.MaterialType = material2.MaterialType; + } + // add overlays (since getMesh() returns + // the base layer only) + postProcessNodeMesh(mesh, f, false, false, nullptr, + &result->buffer_colors); + } } - return mesh; } - shadeMeshFaces(mesh); - rotateMeshXZby(mesh, -45); - rotateMeshYZby(mesh, -30); - u32 mc = mesh->getMeshBufferCount(); for (u32 i = 0; i < mc; ++i) { - video::SMaterial &material = mesh->getMeshBuffer(i)->getMaterial(); + scene::IMeshBuffer *buf = mesh->getMeshBuffer(i); + video::SMaterial &material = buf->getMaterial(); material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 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_LIGHTING, false); - if (f.tiles[i].animation_frame_count > 1) { - FrameSpec animation_frame = f.tiles[i].frames[0]; - material.setTexture(0, animation_frame.texture); - } else { - material.setTexture(0, f.tiles[i].texture); - } } - return mesh; + + rotateMeshXZby(mesh, -45); + rotateMeshYZby(mesh, -30); } - return NULL; + result->mesh = mesh; } -scene::IMesh * getExtrudedMesh(ITextureSource *tsrc, - const std::string &imagename) + + +scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, + const std::string &imagename, const std::string &overlay_name) { + // check textures video::ITexture *texture = tsrc->getTextureForMesh(imagename); if (!texture) { return NULL; } + video::ITexture *overlay_texture = + (overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name); + // get mesh core::dimension2d dim = texture->getSize(); - scene::IMesh *mesh = cloneMesh(g_extrusion_mesh_cache->create(dim)); - - // Customize material - video::SMaterial &material = mesh->getMeshBuffer(0)->getMaterial(); - material.setTexture(0, tsrc->getTexture(imagename)); - material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; - material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; - 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_LIGHTING, false); - material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + scene::IMesh *original = g_extrusion_mesh_cache->create(dim); + scene::SMesh *mesh = cloneMesh(original); + original->drop(); + + //set texture + mesh->getMeshBuffer(0)->getMaterial().setTexture(0, + tsrc->getTexture(imagename)); + if (overlay_texture) { + scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); + copy->getMaterial().setTexture(0, overlay_texture); + mesh->addMeshBuffer(copy); + copy->drop(); + } + // Customize materials + for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) { + video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial(); + material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; + material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; + 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_LIGHTING, false); + material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + } scaleMesh(mesh, v3f(2.0, 2.0, 2.0)); return mesh; } + +void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, + bool use_shaders, bool set_material, const video::E_MATERIAL_TYPE *mattype, + std::vector *colors) +{ + u32 mc = mesh->getMeshBufferCount(); + // Allocate colors for existing buffers + colors->clear(); + for (u32 i = 0; i < mc; ++i) + colors->push_back(ItemPartColor()); + + 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) { + scene::IMeshBuffer *copy = cloneMeshBuffer(buf); + copy->getMaterial() = buf->getMaterial(); + mesh->addMeshBuffer(copy); + copy->drop(); + buf = copy; + colors->push_back( + ItemPartColor(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 (use_shaders) { + if (layer->normal_texture) { + if (layer->animation_frame_count > 1) { + const FrameSpec &animation_frame = (*layer->frames)[0]; + material.setTexture(1, animation_frame.normal_texture); + } else + material.setTexture(1, layer->normal_texture); + } + material.setTexture(2, layer->flags_texture); + } + } + } +}