mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-30 19:22:14 +00:00
Clean up tiledef/layer handling in wield mesh
This commit is contained in:
parent
9972639e26
commit
6d87c219a2
4 changed files with 83 additions and 52 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue