Skip to content

Commit

Permalink
Add support for using arbitrary meshes as items
Browse files Browse the repository at this point in the history
  • Loading branch information
Sapier authored and Sapier committed Dec 29, 2015
1 parent f14e7ba commit 91bafce
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 10 deletions.
61 changes: 52 additions & 9 deletions src/content_cao.cpp
Expand Up @@ -954,15 +954,43 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IItemDefManager *idef = m_gamedef->idef();
ItemStack item(m_prop.textures[0], 1, 0, "", idef);

m_wield_meshnode = new WieldMeshSceneNode(
smgr->getRootSceneNode(), smgr, -1);
m_wield_meshnode->setItem(item, m_gamedef);

m_wield_meshnode->setScale(v3f(m_prop.visual_size.X/2,
m_prop.visual_size.Y/2,
m_prop.visual_size.X/2));
u8 li = m_last_light;
m_wield_meshnode->setColor(video::SColor(255,li,li,li));
if (!item.getDefinition(idef).meshname.empty())
{
scene::IAnimatedMesh *mesh = m_gamedef->getMesh(item.getDefinition(idef).meshname);
if(mesh)
{
m_animated_meshnode = smgr->addAnimatedMeshSceneNode(mesh, NULL);

m_animated_meshnode->grab();
mesh->drop(); // The scene node took hold of it
m_animated_meshnode->animateJoints(); // Needed for some animations
m_animated_meshnode->setScale(v3f(m_prop.visual_size.X,
m_prop.visual_size.Y,
m_prop.visual_size.X));
u8 li = m_last_light;
setMeshColor(m_animated_meshnode->getMesh(), video::SColor(255,li,li,li));

bool backface_culling = m_prop.backface_culling;
if (m_is_player)
backface_culling = false;

m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
m_animated_meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, backface_culling);
}
}
else {
m_wield_meshnode = new WieldMeshSceneNode(
smgr->getRootSceneNode(), smgr, -1);
m_wield_meshnode->setItem(item, m_gamedef);
m_wield_meshnode->setScale(v3f(m_prop.visual_size.X/2,
m_prop.visual_size.Y/2,
m_prop.visual_size.X/2));
u8 li = m_last_light;
m_wield_meshnode->setColor(video::SColor(255,li,li,li));
}
}
} else {
infostream<<"GenericCAO::addToScene(): \""<<m_prop.visual
Expand Down Expand Up @@ -1402,6 +1430,21 @@ void GenericCAO::updateTextures(const std::string &mod)
m_animated_meshnode->getMaterial(i).SpecularColor = m_prop.colors[i];
}
}
else if (m_prop.visual == "wielditem") {
IItemDefManager *idef = m_gamedef->idef();
ItemStack item(m_prop.textures[0], 1, 0, "", idef);

if (!item.getDefinition(idef).meshname.empty()) {

unsigned int materialcount = m_animated_meshnode->getMaterialCount();

for (unsigned int i = 0; i < materialcount; i++) {
m_animated_meshnode->getMaterial(i)
.setTexture(0, tsrc->getTexture(item
.getDefinition(idef).meshtexture));
}
}
}
}
if(m_meshnode)
{
Expand Down
110 changes: 109 additions & 1 deletion src/itemdef.cpp
Expand Up @@ -77,6 +77,8 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
sound_place = def.sound_place;
sound_place_failed = def.sound_place_failed;
range = def.range;
meshname = def.meshname;
meshtexture = def.meshtexture;
return *this;
}

Expand Down Expand Up @@ -157,6 +159,10 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
os << serializeString(sound_place_failed.name);
writeF1000(os, sound_place_failed.gain);
}

//TODO check for protocol version?
os<<serializeString(meshname);
os<<serializeString(meshtexture);
}

void ItemDefinition::deSerialize(std::istream &is)
Expand Down Expand Up @@ -214,6 +220,10 @@ void ItemDefinition::deSerialize(std::istream &is)
sound_place_failed.name = deSerializeString(is);
sound_place_failed.gain = readF1000(is);
} catch(SerializationError &e) {};

//TODO check for protocol?
meshname = deSerializeString(is);
meshtexture = deSerializeString(is);
}

/*
Expand Down Expand Up @@ -341,7 +351,7 @@ CItemDefManager::ClientCached* CItemDefManager::createClientCachedDirect(const s

// Create an inventory texture
cc->inventory_texture = NULL;
if (def.inventory_image != "")
if (!def.inventory_image.empty())
cc->inventory_texture = tsrc->getTexture(def.inventory_image);

// Additional processing for nodes:
Expand All @@ -352,6 +362,10 @@ CItemDefManager::ClientCached* CItemDefManager::createClientCachedDirect(const s
if (def.type == ITEM_NODE) {
createNodeItemTexture(name, def, nodedef, cc, gamedef, tsrc);
}
else if (def.type == ITEM_CRAFT) {
if ( !def.meshname.empty())
createMeshItemTexture(name, def, nodedef, cc, gamedef, tsrc);
}

// Put in cache
m_clientcached.set(name, cc);
Expand Down Expand Up @@ -650,6 +664,100 @@ void CItemDefManager::createNodeItemTexture(const std::string& name,
if (node_mesh)
node_mesh->drop();
}

/******************************************************************************/
void CItemDefManager::renderMeshToTexture(const ItemDefinition& def, scene::IMesh* mesh,
ClientCached* cc, ITextureSource* tsrc) const
{
video::ITexture *itemimage = cc->inventory_texture;

/*
Draw node mesh into a render target texture
*/
TextureFromMeshParams params;
params.mesh = mesh;
params.dim.set(64, 64);
params.rtt_texture_name = "INVENTORY_" + def.name + "_RTT";
params.delete_texture_on_shutdown = true;
params.camera_position.set(0, 1.0, -1.5);
params.camera_position.rotateXZBy(45);
params.camera_lookat.set(0, 0, 0);
// Set orthogonal projection
params.camera_projection_matrix.buildProjectionMatrixOrthoLH(1.65, 1.65, 0,
100);
params.ambient_light.set(1.0, 0.9, 0.9, 0.9);
params.light_position.set(10, 100, -50);
params.light_color.set(1.0, 0.5, 0.5, 0.5);
params.light_radius = 1000;
cc->inventory_texture = tsrc->generateTextureFromMesh(params);

// render-to-target didn't work
if (cc->inventory_texture == NULL) {

cc->inventory_texture = itemimage;
}
}

/******************************************************************************/
void CItemDefManager::createMeshItemTexture(const std::string& name,
const ItemDefinition& def, INodeDefManager* nodedef,
ClientCached* cc, IGameDef* gamedef, ITextureSource* tsrc) const
{
// Get node properties
content_t id = nodedef->getId(name);
const ContentFeatures& f = nodedef->get(id);

if (def.meshname == "")
return;

video::ITexture *texture = tsrc->getTexture(def.meshtexture);

infostream<<"CItemDefManager::createMeshItemTexture(): mesh"<<std::endl;

scene::IAnimatedMesh *mesh = gamedef->getMesh(def.meshname);
if(mesh)
{

video::SColor c(255, 255, 255, 255);
setMeshColor(mesh, c);

rotateMeshXZby(mesh, 180);

// scale and translate the mesh so it's a
// unit cube centered on the origin
scaleMesh(mesh, v3f(1.0 / BS, 1.0 / BS, 1.0 / BS));

// Customize materials
for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) {

video::SMaterial &material = mesh->getMeshBuffer(i)->getMaterial();
material.setTexture(0, texture);
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
}

/*
Draw node mesh into a render target texture
*/
renderMeshToTexture(def, mesh, cc, tsrc);

/*
Use the ingot mesh as the wield mesh
*/

cc->wield_mesh = mesh;
cc->wield_mesh->grab();
// no way reference count can be smaller than 2 in this place!
assert(cc->wield_mesh->getReferenceCount() >= 2);

if (mesh)
mesh->drop();

}
else
errorstream<<"CItemDefManager::createMeshItemTexture(): Could not load mesh "<<def.meshname<<std::endl;
}
#endif

/******************************************************************************/
Expand Down
9 changes: 9 additions & 0 deletions src/itemdef.h
Expand Up @@ -66,6 +66,8 @@ struct ItemDefinition
std::string inventory_image; // Optional for nodes, mandatory for tools/craftitems
std::string wield_image; // If empty, inventory_image or mesh (only nodes) is used
v3f wield_scale;
std::string meshname; // name of internal mesh (or meshfile to use TBD)
std::string meshtexture; // meshtexture

/*
Item stack and interaction properties
Expand Down Expand Up @@ -211,6 +213,13 @@ class CItemDefManager: public IWritableItemDefManager
const ItemDefinition& def, INodeDefManager* nodedef,
ClientCached* cc, IGameDef* gamedef, ITextureSource* tsrc) const;

void createMeshItemTexture(const std::string& name,
const ItemDefinition& def, INodeDefManager* nodedef,
ClientCached* cc, IGameDef* gamedef, ITextureSource* tsrc) const;

void renderMeshToTexture(const ItemDefinition& def, scene::IMesh* mesh,
ClientCached* cc, ITextureSource* tsrc) const;

ClientCached* createClientCachedDirect(const std::string &name,
IGameDef *gamedef) const;

Expand Down
2 changes: 2 additions & 0 deletions src/script/common/c_content.cpp
Expand Up @@ -58,6 +58,8 @@ ItemDefinition read_item_definition(lua_State* L,int index,
getstringfield(L, index, "description", def.description);
getstringfield(L, index, "inventory_image", def.inventory_image);
getstringfield(L, index, "wield_image", def.wield_image);
getstringfield(L, index, "mesh", def.meshname);
getstringfield(L, index, "meshtexture", def.meshtexture);

lua_getfield(L, index, "wield_scale");
if(lua_istable(L, -1)){
Expand Down
14 changes: 14 additions & 0 deletions src/wieldmesh.cpp
Expand Up @@ -386,6 +386,20 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
}
return;
}
else if (idef->getWieldMesh(def.name, gamedef) != 0) {
irr::scene::IMesh * mesh = idef->getWieldMesh(def.name, gamedef);
m_meshnode->setMesh(mesh);
u32 material_count = m_meshnode->getMaterialCount();
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);
material.MaterialType = m_material_type;
material.setTexture(0, tsrc->getTexture(def.meshtexture));
}
return;
}
else if (def.inventory_image != "") {
setExtruded(def.inventory_image, def.wield_scale, tsrc, 1);
return;
Expand Down

0 comments on commit 91bafce

Please sign in to comment.