Add meshnode drawtype.
authorRealBadAngel <maciej.kasatkin@o2.pl>
Wed, 15 Oct 2014 02:13:53 +0000 (04:13 +0200)
committerRealBadAngel <maciej.kasatkin@o2.pl>
Sat, 18 Oct 2014 14:42:23 +0000 (16:42 +0200)
doc/lua_api.txt
src/client.cpp
src/content_mapblock.cpp
src/mapblock_mesh.cpp
src/mapblock_mesh.h
src/mesh.cpp
src/mesh.h
src/nodedef.cpp
src/nodedef.h
src/script/common/c_content.cpp
src/script/cpp_api/s_node.cpp

index 131a63fa55f480b2ddf1df398367bbeb91aa4911..8f77366f7f4bee61a36a2c7f564c757193c53bc1 100644 (file)
@@ -103,6 +103,7 @@ mods
 |   |-- screenshot.png
 |   |-- description.txt
 |   |-- init.lua
+|   |-- models
 |   |-- textures
 |   |   |-- modname_stuff.png
 |   |   `-- modname_something_else.png
@@ -137,6 +138,9 @@ init.lua:
   minetest.setting_get(name) and minetest.setting_getbool(name) can be used
   to read custom or existing settings at load time, if necessary.
 
+models:
+       Models for entities or meshnodes.
+
 textures, sounds, media:
   Media files (textures, sounds, whatever) that will be transferred to the
   client and will be available for use by the mod.
@@ -430,6 +434,7 @@ Look for examples in games/minimal or games/minetest_game.
 - fencelike
 - raillike
 - nodebox -- See below. EXPERIMENTAL
+- mesh -- use models for nodes
 
 *_optional drawtypes need less rendering time if deactivated (always client side)
 
@@ -469,6 +474,12 @@ A box of a regular node would look like:
 
 type = "leveled" is same as "fixed", but y2 will be automatically set to level from param2
 
+Meshes
+-----------
+If drawtype "mesh" is used tiles should hold model materials textures.
+Only static meshes are implemented.
+For supported model formats see Irrlicht engine documentation.
+    
 Ore types
 ---------------
 These tell in what manner the ore is generated.
@@ -2405,7 +2416,7 @@ Node definition (register_node)
 
     drawtype = "normal", -- See "Node drawtypes"
     visual_scale = 1.0,
-    ^ Supported for drawtypes "plantlike", "signlike", "torchlike".
+    ^ Supported for drawtypes "plantlike", "signlike", "torchlike", "mesh".
     ^ For plantlike, the image will start at the bottom of the node; for the
     ^ other drawtypes, the image will be centered on the node.
     ^ Note that positioning for "torchlike" may still change.
@@ -2439,6 +2450,7 @@ Node definition (register_node)
     light_source = 0, -- Amount of light emitted by node
     damage_per_second = 0, -- If player is inside node, this damage is caused
     node_box = {type="regular"}, -- See "Node boxes"
+    mesh = "model",
     selection_box = {type="regular"}, -- See "Node boxes"
     ^ If drawtype "nodebox" is used and selection_box is nil, then node_box is used
     legacy_facedir_simple = false, -- Support maps made in and before January 2012
index 4a00283eeaa1b44816a2c1fcaf584c8161e9523a..0bc2e66a52efed56a35d4bf06bcf9e2e74c0ab69 100644 (file)
@@ -2678,7 +2678,7 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
 
        // Update node textures and assign shaders to each tile
        infostream<<"- Updating node textures"<<std::endl;
-       m_nodedef->updateTextures(m_tsrc, m_shsrc);
+       m_nodedef->updateTextures(this);
 
        // Preload item textures and meshes if configured to
        if(g_settings->getBool("preload_item_visuals"))
index c84e75ac072f527a91da53df1ba58525d53fdb95..53b9874d4971dde18b2b27dcdfaa7eb457d410f8 100644 (file)
@@ -1715,6 +1715,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                makeCuboid(&collector, box, tiles, 6, c, txc);
                        }
                break;}
+               case NDT_MESH:
+               {
+                       v3f pos = intToFloat(p, BS);
+                       video::SColor c = MapBlock_LightColor(255, getInteriorLight(n, 1, nodedef), f.light_source);
+                       u8 facedir = n.getFaceDir(nodedef);
+                       for(u16 j = 0; j < f.mesh_ptr[facedir]->getMeshBufferCount(); j++) {
+                               scene::IMeshBuffer *buf = f.mesh_ptr[facedir]->getMeshBuffer(j);
+                               collector.append(getNodeTileN(n, p, j, data),
+                                       (video::S3DVertex *)buf->getVertices(), buf->getVertexCount(),
+                                       buf->getIndices(), buf->getIndexCount(), pos, c);
+                       }
+               break;}
                }
        }
 }
index d75d3e1484971984d74024d427c6610cfdae647a..a7fafa68341fd8b549ddff135eef8177f82fb240 100644 (file)
@@ -1428,3 +1428,54 @@ void MeshCollector::append(const TileSpec &tile,
                p->vertices.push_back(vertices[i]);
        }
 }
+
+/*
+       MeshCollector - for meshnodes and converted drawtypes.
+*/
+
+void MeshCollector::append(const TileSpec &tile,
+               const video::S3DVertex *vertices, u32 numVertices,
+               const u16 *indices, u32 numIndices,
+               v3f pos, video::SColor c)
+{
+       if(numIndices > 65535)
+       {
+               dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
+               return;
+       }
+
+       PreMeshBuffer *p = NULL;
+       for(u32 i=0; i<prebuffers.size(); i++)
+       {
+               PreMeshBuffer &pp = prebuffers[i];
+               if(pp.tile != tile)
+                       continue;
+               if(pp.indices.size() + numIndices > 65535)
+                       continue;
+
+               p = &pp;
+               break;
+       }
+
+       if(p == NULL)
+       {
+               PreMeshBuffer pp;
+               pp.tile = tile;
+               prebuffers.push_back(pp);
+               p = &prebuffers[prebuffers.size()-1];
+       }
+
+       u32 vertex_count = p->vertices.size();
+       for(u32 i=0; i<numIndices; i++)
+       {
+               u32 j = indices[i] + vertex_count;
+               p->indices.push_back(j);
+       }
+       for(u32 i=0; i<numVertices; i++)
+       {
+               video::S3DVertex vert = vertices[i];
+               vert.Pos += pos;
+               vert.Color = c;         
+               p->vertices.push_back(vert);
+       }
+}
index c5295499884d63c39d13080f85bf972c1488cb7b..e1cccc64e1156061d69905be4951cdcdccdea4b2 100644 (file)
@@ -174,6 +174,10 @@ struct MeshCollector
        void append(const TileSpec &material,
                        const video::S3DVertex *vertices, u32 numVertices,
                        const u16 *indices, u32 numIndices);
+       void append(const TileSpec &material,
+                       const video::S3DVertex *vertices, u32 numVertices,
+                       const u16 *indices, u32 numIndices,
+                       v3f pos, video::SColor c);
 };
 
 // This encodes
index 3200d5fa6c2fd453fc44ab4bc97ca117e563e1f0..19d75f9f5e7c3480a868b91e426351f4bf853488 100644 (file)
@@ -408,3 +408,219 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
                }
        }
 }
+
+void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
+{              
+       int axisdir = facedir>>2;
+       facedir &= 0x03;
+
+       u16 mc = mesh->getMeshBufferCount();
+       for(u16 j = 0; j < mc; j++)
+       {
+               scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
+               video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+               u16 vc = buf->getVertexCount();
+               for(u16 i=0; i<vc; i++)
+               {
+                       switch (axisdir)
+                       {
+                       case 0:
+                               if(facedir == 1)
+                                       vertices[i].Pos.rotateXZBy(-90);
+                               else if(facedir == 2)
+                                       vertices[i].Pos.rotateXZBy(180);
+                               else if(facedir == 3)
+                                       vertices[i].Pos.rotateXZBy(90);
+                               break;
+                       case 1: // z+
+                               vertices[i].Pos.rotateYZBy(90);
+                               if(facedir == 1)
+                                       vertices[i].Pos.rotateXYBy(90);
+                               else if(facedir == 2)
+                                       vertices[i].Pos.rotateXYBy(180);
+                               else if(facedir == 3)
+                                       vertices[i].Pos.rotateXYBy(-90);
+                               break;
+                       case 2: //z-
+                               vertices[i].Pos.rotateYZBy(-90);
+                               if(facedir == 1)
+                                       vertices[i].Pos.rotateXYBy(-90);
+                               else if(facedir == 2)
+                                       vertices[i].Pos.rotateXYBy(180);
+                               else if(facedir == 3)
+                                       vertices[i].Pos.rotateXYBy(90);
+                               break;
+                       case 3:  //x+
+                               vertices[i].Pos.rotateXYBy(-90);
+                               if(facedir == 1)
+                                       vertices[i].Pos.rotateYZBy(90);
+                               else if(facedir == 2)
+                                       vertices[i].Pos.rotateYZBy(180);
+                               else if(facedir == 3)
+                                       vertices[i].Pos.rotateYZBy(-90);
+                               break;
+                       case 4:  //x-
+                               vertices[i].Pos.rotateXYBy(90);
+                               if(facedir == 1)
+                                       vertices[i].Pos.rotateYZBy(-90);
+                               else if(facedir == 2)
+                                       vertices[i].Pos.rotateYZBy(180);
+                               else if(facedir == 3)
+                                       vertices[i].Pos.rotateYZBy(90);
+                               break;
+                       case 5:
+                               vertices[i].Pos.rotateXYBy(-180);
+                               if(facedir == 1)
+                                       vertices[i].Pos.rotateXZBy(90);
+                               else if(facedir == 2)
+                                       vertices[i].Pos.rotateXZBy(180);
+                               else if(facedir == 3)
+                                       vertices[i].Pos.rotateXZBy(-90);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+}
+
+void recalculateBoundingBox(scene::IMesh *src_mesh)
+{
+       core::aabbox3d<f32> bbox;
+       bbox.reset(0,0,0);
+       for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
+       {
+               scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
+               buf->recalculateBoundingBox();
+               if(j == 0)
+                       bbox = buf->getBoundingBox();
+               else
+                       bbox.addInternalBox(buf->getBoundingBox());
+       }
+       src_mesh->setBoundingBox(bbox);
+}
+
+scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
+{
+       scene::SMesh* dst_mesh = new scene::SMesh();
+       for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
+       {
+               scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
+               video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+               u16 *indices = (u16*)buf->getIndices();
+               scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
+               temp_buf->append(vertices, buf->getVertexCount(),
+                       indices, buf->getIndexCount());
+               dst_mesh->addMeshBuffer(temp_buf);
+               temp_buf->drop();
+       }
+       return dst_mesh;                                        
+}
+
+scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
+{
+       scene::SMesh* dst_mesh = new scene::SMesh();
+       for (u16 j = 0; j < 6; j++)
+       {
+               scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+               dst_mesh->addMeshBuffer(buf);
+               buf->drop();
+       }
+       
+       video::SColor c(255,255,255,255);       
+
+       std::vector<aabb3f> boxes = f->node_box.fixed;
+               
+       for(std::vector<aabb3f>::iterator
+                       i = boxes.begin();
+                       i != boxes.end(); i++)
+       {
+               aabb3f box = *i;
+
+               f32 temp;
+               if (box.MinEdge.X > box.MaxEdge.X)
+                       {
+                               temp=box.MinEdge.X;
+                               box.MinEdge.X=box.MaxEdge.X;
+                               box.MaxEdge.X=temp;
+                       }
+               if (box.MinEdge.Y > box.MaxEdge.Y)
+                       {
+                               temp=box.MinEdge.Y;
+                               box.MinEdge.Y=box.MaxEdge.Y;
+                               box.MaxEdge.Y=temp;
+                       }
+               if (box.MinEdge.Z > box.MaxEdge.Z)
+                       {
+                               temp=box.MinEdge.Z;
+                               box.MinEdge.Z=box.MaxEdge.Z;
+                               box.MaxEdge.Z=temp;
+                       }
+               // Compute texture coords
+               f32 tx1 = (box.MinEdge.X/BS)+0.5;
+               f32 ty1 = (box.MinEdge.Y/BS)+0.5;
+               f32 tz1 = (box.MinEdge.Z/BS)+0.5;
+               f32 tx2 = (box.MaxEdge.X/BS)+0.5;
+               f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
+               f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
+               f32 txc[24] = {
+                       // up
+                       tx1, 1-tz2, tx2, 1-tz1,
+                       // down
+                       tx1, tz1, tx2, tz2,
+                       // right
+                       tz1, 1-ty2, tz2, 1-ty1,
+                       // left
+                       1-tz2, 1-ty2, 1-tz1, 1-ty1,
+                       // back
+                       1-tx2, 1-ty2, 1-tx1, 1-ty1,
+                       // front
+                       tx1, 1-ty2, tx2, 1-ty1,
+               };
+               v3f min = box.MinEdge;
+               v3f max = box.MaxEdge;
+
+               video::S3DVertex vertices[24] =
+               {
+                       // up
+                       video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]),
+                       video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]),
+                       video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]),
+                       video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]),
+                       // down
+                       video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]),
+                       video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]),
+                       video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]),
+                       video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]),
+                       // right
+                       video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]),
+                       video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]),
+                       video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]),
+                       video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]),
+                       // left
+                       video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]),
+                       video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]),
+                       video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]),
+                       video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]),
+                       // back
+                       video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]),
+                       video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]),
+                       video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]),
+                       video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[16],txc[19]),
+                       // front
+                       video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]),
+                       video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]),
+                       video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]),
+                       video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
+               };
+
+               u16 indices[] = {0,1,2,2,3,0};
+
+               for(u16 j = 0; j < 24; j += 4)
+               {
+                       scene::IMeshBuffer *buf = dst_mesh->getMeshBuffer(j / 4);
+                       buf->append(vertices + j, 4, indices, 6);
+               }
+       }
+       return dst_mesh;                                        
+}
index a89bea3856a8761ac4b2ad47522b749c8b70160a..7539298cb8c1fd5758a0eb2ae2653f0b0cb8e940 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define MESH_HEADER
 
 #include "irrlichttypes_extrabloated.h"
+#include "nodedef.h"
 #include <string>
 
 /*
@@ -68,5 +69,25 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
                const video::SColor &colorX,
                const video::SColor &colorY,
                const video::SColor &colorZ);
+/*
+       Rotate the mesh by 6d facedir value.
+       Method only for meshnodes, not suitable for entities.
+*/
+void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir);
+
+/*
+       Clone the mesh.
+*/
+scene::IMesh* cloneMesh(scene::IMesh *src_mesh);
+
+/*
+       Convert nodebox drawtype node to mesh.
+*/
+scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f);
+
+/*
+       Update bounding box for a mesh.
+*/
+void recalculateBoundingBox(scene::IMesh *src_mesh);
 
 #endif
index f1a7ad6946281803a7daa857ad4a12e7f14784db..ef61d0722a5b34314f14017ea80ae8b8bb127f74 100644 (file)
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "itemdef.h"
 #ifndef SERVER
 #include "tile.h"
+#include "mesh.h"
 #endif
 #include "log.h"
 #include "settings.h"
@@ -31,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/serialize.h"
 #include "exceptions.h"
 #include "debug.h"
+#include "gamedef.h"
 
 /*
        NodeBox
@@ -195,6 +197,11 @@ void ContentFeatures::reset()
        // Unknown nodes can be dug
        groups["dig_immediate"] = 2;
        drawtype = NDT_NORMAL;
+       mesh = "";
+#ifndef SERVER
+       for(u32 i = 0; i < 24; i++)
+               mesh_ptr[i] = NULL;
+#endif
        visual_scale = 1.0;
        for(u32 i = 0; i < 6; i++)
                tiledef[i] = TileDef();
@@ -295,6 +302,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
        writeU8(os, waving);
        // Stuff below should be moved to correct place in a version that otherwise changes
        // the protocol version
+       os<<serializeString(mesh);
 }
 
 void ContentFeatures::deSerialize(std::istream &is)
@@ -363,6 +371,7 @@ void ContentFeatures::deSerialize(std::istream &is)
        try{
                // Stuff below should be moved to correct place in a version that
                // otherwise changes the protocol version
+       mesh = deSerializeString(is);
        }catch(SerializationError &e) {};
 }
 
@@ -386,7 +395,7 @@ public:
        virtual content_t set(const std::string &name, const ContentFeatures &def);
        virtual content_t allocateDummy(const std::string &name);
        virtual void updateAliases(IItemDefManager *idef);
-       virtual void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc);
+       virtual void updateTextures(IGameDef *gamedef);
        void serialize(std::ostream &os, u16 protocol_version);
        void deSerialize(std::istream &is);
 
@@ -669,11 +678,14 @@ void CNodeDefManager::updateAliases(IItemDefManager *idef)
 }
 
 
-void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc)
+void CNodeDefManager::updateTextures(IGameDef *gamedef)
 {
 #ifndef SERVER
        infostream << "CNodeDefManager::updateTextures(): Updating "
                "textures in node definitions" << std::endl;
+       
+       ITextureSource *tsrc = gamedef->tsrc();
+       IShaderSource *shdsrc = gamedef->getShaderSource();
 
        bool new_style_water           = g_settings->getBool("new_style_water");
        bool new_style_leaves          = g_settings->getBool("new_style_leaves");
@@ -771,6 +783,10 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
                        f->backface_culling = false;
                        f->solidness = 0;
                        break;
+               case NDT_MESH:
+                       f->solidness = 0;
+                       f->backface_culling = false;
+                       break;
                case NDT_TORCHLIKE:
                case NDT_SIGNLIKE:
                case NDT_FENCELIKE:
@@ -810,6 +826,34 @@ void CNodeDefManager::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
                                tile_shader[j], use_normal_texture,
                                f->tiledef_special[j].backface_culling, f->alpha, material_type);
                }
+
+               // Meshnode drawtype
+               // Read the mesh and apply scale
+               if ((f->drawtype == NDT_MESH) && (f->mesh != "")) {
+                       f->mesh_ptr[0] = gamedef->getMesh(f->mesh);
+                       scaleMesh(f->mesh_ptr[0], v3f(f->visual_scale,f->visual_scale,f->visual_scale));
+                       recalculateBoundingBox(f->mesh_ptr[0]);
+               }
+
+               //Convert regular nodebox nodes to meshnodes
+               //Change the drawtype and apply scale
+               if ((f->drawtype == NDT_NODEBOX) && 
+                               ((f->node_box.type == NODEBOX_REGULAR) || (f->node_box.type == NODEBOX_FIXED)) &&
+                               (!f->node_box.fixed.empty())) {
+                       f->drawtype = NDT_MESH;
+                       f->mesh_ptr[0] = convertNodeboxNodeToMesh(f);
+                       scaleMesh(f->mesh_ptr[0], v3f(f->visual_scale,f->visual_scale,f->visual_scale));
+                       recalculateBoundingBox(f->mesh_ptr[0]);
+               }
+
+               //Cache 6dfacedir rotated clones of meshes
+               if (f->mesh_ptr[0] && (f->param_type_2 == CPT2_FACEDIR)) {
+                               for (u16 j = 1; j < 24; j++) {
+                                       f->mesh_ptr[j] = cloneMesh(f->mesh_ptr[0]);
+                                       rotateMeshBy6dFacedir(f->mesh_ptr[j], j);
+                                       recalculateBoundingBox(f->mesh_ptr[j]);
+                               }
+                       }
        }
 #endif
 }
index b737e02379f77a5adf2f956acba25a9f6c42469f..2400f5f7330646d501703d88a27d81eeb12b59c3 100644 (file)
@@ -152,6 +152,7 @@ enum NodeDrawType
        NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes,
        NDT_GLASSLIKE_FRAMED_OPTIONAL,  // enabled -> connected, disabled -> Glass-like
                                                                        // uses 2 textures, one for frames, second for faces
+       NDT_MESH, // Uses static meshes
 };
 
 #define CF_SPECIAL_COUNT 6
@@ -187,6 +188,10 @@ struct ContentFeatures
 
        // Visual definition
        enum NodeDrawType drawtype;
+       std::string mesh;
+#ifndef SERVER
+       scene::IMesh *mesh_ptr[24];
+#endif 
        float visual_scale; // Misc. scale parameter
        TileDef tiledef[6];
        TileDef tiledef_special[CF_SPECIAL_COUNT]; // eg. flowing liquid
@@ -328,8 +333,7 @@ public:
        /*
                Update tile textures to latest return values of TextueSource.
        */
-       virtual void updateTextures(ITextureSource *tsrc,
-               IShaderSource *shdsrc)=0;
+       virtual void updateTextures(IGameDef *gamedef)=0;
 
        virtual void serialize(std::ostream &os, u16 protocol_version)=0;
        virtual void deSerialize(std::istream &is)=0;
index 2f749043ef6cd0d0afec5c18c3aebff9855adba8..4737f19933916e513272abf7af5894175d359ad0 100644 (file)
@@ -281,6 +281,9 @@ ContentFeatures read_content_features(lua_State *L, int index)
                        ScriptApiNode::es_DrawType,NDT_NORMAL);
        getfloatfield(L, index, "visual_scale", f.visual_scale);
 
+       /* Meshnode model filename */
+       getstringfield(L, index, "mesh", f.mesh);
+
        // tiles = {}
        lua_getfield(L, index, "tiles");
        // If nil, try the deprecated name "tile_images" instead
index 05f9080048f8a717200cc372e8ab7336eeb73787..e3d3fb58bdf0be434ef5290a1f93e86ef5b79151 100644 (file)
@@ -45,6 +45,7 @@ struct EnumString ScriptApiNode::es_DrawType[] =
                {NDT_FENCELIKE, "fencelike"},
                {NDT_RAILLIKE, "raillike"},
                {NDT_NODEBOX, "nodebox"},
+               {NDT_MESH, "mesh"},
                {0, NULL},
        };