1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-30 19:22:14 +00:00
This commit is contained in:
sfan5 2025-09-30 15:06:37 +03:00 committed by GitHub
commit 71f6af95be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 83 additions and 52 deletions

View file

@ -671,6 +671,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
// Add to MapBlockMesh in order to animate these tiles // Add to MapBlockMesh in order to animate these tiles
m_animation_info.emplace(std::make_pair(layer, i), AnimationInfo(p.layer)); m_animation_info.emplace(std::make_pair(layer, i), AnimationInfo(p.layer));
// Replace tile texture with the first animation frame // Replace tile texture with the first animation frame
assert(p.layer.frames);
p.layer.texture = (*p.layer.frames)[0].texture; p.layer.texture = (*p.layer.frames)[0].texture;
} }

View file

@ -79,7 +79,8 @@ public:
*/ */
u32 getTextureId(const std::string &name); u32 getTextureId(const std::string &name);
// Finds out the name of a cached texture. /// @brief Finds out the name of a cached texture.
/// @note DO NOT USE IN NEW CODE
std::string getTextureName(u32 id); std::string getTextureName(u32 id);
/* /*

View file

@ -119,6 +119,18 @@ static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
return mesh; return mesh;
} }
static video::ITexture *extractTexture(const TileDef &def, const TileLayer &layer,
ITextureSource *tsrc)
{
// If animated take first frame from tile layer (so we don't have to handle
// that manually), otherwise look up by name.
if (!layer.empty() && (layer.material_flags & MATERIAL_FLAG_ANIMATION))
return (*layer.frames)[0].texture;
if (!def.name.empty())
return tsrc->getTextureForMesh(def.name);
return nullptr;
}
/* /*
Caches extrusion meshes so that only one of them per resolution Caches extrusion meshes so that only one of them per resolution
is needed. Also caches one cube (for convenience). is needed. Also caches one cube (for convenience).
@ -235,31 +247,41 @@ WieldMeshSceneNode::~WieldMeshSceneNode()
g_extrusion_mesh_cache = nullptr; g_extrusion_mesh_cache = nullptr;
} }
void WieldMeshSceneNode::setExtruded(const std::string &imagename, void WieldMeshSceneNode::setExtruded(const TileDef &d0, const TileLayer &l0,
const std::string &overlay_name, v3f wield_scale, ITextureSource *tsrc, const TileDef &d1, const TileLayer &l1,
u8 num_frames) v3f wield_scale, ITextureSource *tsrc)
{
setExtruded(extractTexture(d0, l0, tsrc),
extractTexture(d1, l1, tsrc), wield_scale);
// Add color
m_buffer_info.clear();
m_buffer_info.emplace_back(l0.has_color, l0.color);
m_buffer_info.emplace_back(l1.has_color, l1.color);
}
void WieldMeshSceneNode::setExtruded(const std::string &image,
const std::string &overlay, v3f wield_scale, ITextureSource *tsrc)
{
video::ITexture *texture = tsrc->getTexture(image);
video::ITexture *overlay_texture =
overlay.empty() ? nullptr : tsrc->getTexture(overlay);
setExtruded(texture, overlay_texture, wield_scale);
}
void WieldMeshSceneNode::setExtruded(video::ITexture *texture,
video::ITexture *overlay_texture, v3f wield_scale)
{ {
video::ITexture *texture = tsrc->getTexture(imagename);
if (!texture) { if (!texture) {
changeToMesh(nullptr); changeToMesh(nullptr);
return; return;
} }
video::ITexture *overlay_texture =
overlay_name.empty() ? NULL : tsrc->getTexture(overlay_name);
core::dimension2d<u32> dim = texture->getSize(); core::dimension2d<u32> 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<u32>(dim.Width, frame_height);
}
scene::IMesh *original = g_extrusion_mesh_cache->create(dim); scene::IMesh *original = g_extrusion_mesh_cache->create(dim);
scene::SMesh *mesh = cloneStaticMesh(original); scene::SMesh *mesh = cloneStaticMesh(original);
original->drop(); original->drop();
//set texture
mesh->getMeshBuffer(0)->getMaterial().setTexture(0, mesh->getMeshBuffer(0)->getMaterial().setTexture(0, texture);
tsrc->getTexture(imagename));
if (overlay_texture) { if (overlay_texture) {
// duplicate the extruded mesh for the overlay // duplicate the extruded mesh for the overlay
scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0));
@ -370,7 +392,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
// If wield_image needs to be checked and is defined, it overrides everything else // If wield_image needs to be checked and is defined, it overrides everything else
if (!wield_image.empty() && check_wield_image) { if (!wield_image.empty() && check_wield_image) {
setExtruded(wield_image, wield_overlay, wield_scale, tsrc, 1); setExtruded(wield_image, wield_overlay, wield_scale, tsrc);
m_buffer_info.emplace_back(); m_buffer_info.emplace_back();
// overlay is white, if present // overlay is white, if present
m_buffer_info.emplace_back(true, video::SColor(0xFFFFFFFF)); m_buffer_info.emplace_back(true, video::SColor(0xFFFFFFFF));
@ -385,7 +407,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
switch (f.drawtype) { switch (f.drawtype) {
case NDT_AIRLIKE: case NDT_AIRLIKE:
setExtruded("no_texture_airlike.png", "", setExtruded("no_texture_airlike.png", "",
v3f(1), tsrc, 1); v3f(1), tsrc);
break; break;
case NDT_SIGNLIKE: case NDT_SIGNLIKE:
case NDT_TORCHLIKE: case NDT_TORCHLIKE:
@ -395,24 +417,14 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
v3f wscale = wield_scale; v3f wscale = wield_scale;
if (f.drawtype == NDT_FLOWINGLIQUID) if (f.drawtype == NDT_FLOWINGLIQUID)
wscale.Z *= 0.1f; wscale.Z *= 0.1f;
const TileLayer &l0 = f.tiles[0].layers[0]; setExtruded(f.tiledef[0], f.tiles[0].layers[0],
const TileLayer &l1 = f.tiles[0].layers[1]; f.tiledef_overlay[0], f.tiles[0].layers[1], wscale, tsrc);
setExtruded(tsrc->getTextureName(l0.texture_id),
tsrc->getTextureName(l1.texture_id),
wscale, tsrc,
l0.animation_frame_count);
// Add color
m_buffer_info.emplace_back(l0.has_color, l0.color);
m_buffer_info.emplace_back(l1.has_color, l1.color);
break; break;
} }
case NDT_PLANTLIKE_ROOTED: { case NDT_PLANTLIKE_ROOTED: {
// use the plant tile // use the plant tile
const TileLayer &l0 = f.special_tiles[0].layers[0]; setExtruded(f.tiledef_special[0], f.special_tiles[0].layers[0],
setExtruded(tsrc->getTextureName(l0.texture_id), TileDef(), TileLayer(), wield_scale, tsrc);
"", wield_scale, tsrc,
l0.animation_frame_count);
m_buffer_info.emplace_back(l0.has_color, l0.color);
break; break;
} }
default: { default: {
@ -450,9 +462,9 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
const std::string inventory_image = item.getInventoryImage(idef); const std::string inventory_image = item.getInventoryImage(idef);
if (!inventory_image.empty()) { if (!inventory_image.empty()) {
const std::string inventory_overlay = item.getInventoryOverlay(idef); const std::string inventory_overlay = item.getInventoryOverlay(idef);
setExtruded(inventory_image, inventory_overlay, def.wield_scale, tsrc, 1); setExtruded(inventory_image, inventory_overlay, def.wield_scale, tsrc);
} else { } else {
setExtruded("no_texture.png", "", def.wield_scale, tsrc, 1); setExtruded("no_texture.png", "", def.wield_scale, tsrc);
} }
m_buffer_info.emplace_back(); m_buffer_info.emplace_back();
@ -571,9 +583,9 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
case NDT_PLANTLIKE: { case NDT_PLANTLIKE: {
const TileLayer &l0 = f.tiles[0].layers[0]; const TileLayer &l0 = f.tiles[0].layers[0];
const TileLayer &l1 = f.tiles[0].layers[1]; const TileLayer &l1 = f.tiles[0].layers[1];
mesh = getExtrudedMesh(tsrc, mesh = getExtrudedMesh(
tsrc->getTextureName(l0.texture_id), extractTexture(f.tiledef[0], l0, tsrc),
tsrc->getTextureName(l1.texture_id)); extractTexture(f.tiledef[1], l1, tsrc));
// Add color // Add color
result->buffer_info.emplace_back(l0.has_color, l0.color); result->buffer_info.emplace_back(l0.has_color, l0.color);
result->buffer_info.emplace_back(l1.has_color, l1.color); result->buffer_info.emplace_back(l1.has_color, l1.color);
@ -582,8 +594,9 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
case NDT_PLANTLIKE_ROOTED: { case NDT_PLANTLIKE_ROOTED: {
// Use the plant tile // Use the plant tile
const TileLayer &l0 = f.special_tiles[0].layers[0]; const TileLayer &l0 = f.special_tiles[0].layers[0];
mesh = getExtrudedMesh(tsrc, mesh = getExtrudedMesh(
tsrc->getTextureName(l0.texture_id), ""); extractTexture(f.tiledef_special[0], l0, tsrc), nullptr
);
result->buffer_info.emplace_back(l0.has_color, l0.color); result->buffer_info.emplace_back(l0.has_color, l0.color);
break; break;
} }
@ -623,18 +636,20 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
result->mesh = mesh; result->mesh = mesh;
} }
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
const std::string &imagename, const std::string &overlay_name) const std::string &imagename, const std::string &overlay_name)
{ {
// check textures
video::ITexture *texture = tsrc->getTexture(imagename); video::ITexture *texture = tsrc->getTexture(imagename);
if (!texture) {
return NULL;
}
video::ITexture *overlay_texture = video::ITexture *overlay_texture =
(overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name); overlay_name.empty() ? nullptr : tsrc->getTexture(overlay_name);
return getExtrudedMesh(texture, overlay_texture);
}
scene::SMesh *getExtrudedMesh(video::ITexture *texture,
video::ITexture *overlay_texture)
{
if (!texture)
return nullptr;
// get mesh // get mesh
core::dimension2d<u32> dim = texture->getSize(); core::dimension2d<u32> dim = texture->getSize();
@ -642,15 +657,14 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
scene::SMesh *mesh = cloneStaticMesh(original); scene::SMesh *mesh = cloneStaticMesh(original);
original->drop(); original->drop();
//set texture mesh->getMeshBuffer(0)->getMaterial().setTexture(0, texture);
mesh->getMeshBuffer(0)->getMaterial().setTexture(0,
tsrc->getTexture(imagename));
if (overlay_texture) { if (overlay_texture) {
scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0)); scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0));
copy->getMaterial().setTexture(0, overlay_texture); copy->getMaterial().setTexture(0, overlay_texture);
mesh->addMeshBuffer(copy); mesh->addMeshBuffer(copy);
copy->drop(); copy->drop();
} }
// Customize materials // Customize materials
for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) { for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) {
video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial(); video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial();

View file

@ -23,6 +23,7 @@ namespace scene
struct ItemStack; struct ItemStack;
struct TileDef;
class Client; class Client;
class ITextureSource; class ITextureSource;
class ShadowRenderer; class ShadowRenderer;
@ -98,8 +99,16 @@ public:
WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1); WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1);
virtual ~WieldMeshSceneNode(); virtual ~WieldMeshSceneNode();
void setExtruded(const std::string &imagename, const std::string &overlay_image, // Set appearance from node def
v3f wield_scale, ITextureSource *tsrc, u8 num_frames); // d0, l0 = base tile
// d1, l1 = overlay tile
void setExtruded(const TileDef &d0, const TileLayer &l0,
const TileDef &d1, const TileLayer &l1,
v3f wield_scale, ITextureSource *tsrc);
// Set apperance from texture name
void setExtruded(const std::string &image, const std::string &overlay,
v3f wield_scale, ITextureSource *tsrc);
void setItem(const ItemStack &item, Client *client, void setItem(const ItemStack &item, Client *client,
bool check_wield_image = true); bool check_wield_image = true);
@ -116,6 +125,9 @@ public:
virtual const aabb3f &getBoundingBox() const { return m_bounding_box; } virtual const aabb3f &getBoundingBox() const { return m_bounding_box; }
private: private:
void setExtruded(video::ITexture *base, video::ITexture *overlay,
v3f wield_scale);
void changeToMesh(scene::IMesh *mesh); void changeToMesh(scene::IMesh *mesh);
// Child scene node with the current wield mesh // Child scene node with the current wield mesh
@ -139,12 +151,15 @@ private:
// Bounding box culling is disabled for this type of scene node, // Bounding box culling is disabled for this type of scene node,
// so this variable is just required so we can implement // so this variable is just required so we can implement
// getBoundingBox() and is set to an empty box. // getBoundingBox() and is set to an empty box.
aabb3f m_bounding_box{{0, 0, 0}}; const aabb3f m_bounding_box{{0, 0, 0}};
ShadowRenderer *m_shadow; ShadowRenderer *m_shadow;
}; };
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result); void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result);
scene::SMesh *getExtrudedMesh(video::ITexture *texture,
video::ITexture *overlay_texture);
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename, scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename,
const std::string &overlay_name); const std::string &overlay_name);