aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.cpp2
-rw-r--r--src/content_mapblock.cpp12
-rw-r--r--src/mapblock_mesh.cpp51
-rw-r--r--src/mapblock_mesh.h4
-rw-r--r--src/mesh.cpp216
-rw-r--r--src/mesh.h21
-rw-r--r--src/nodedef.cpp48
-rw-r--r--src/nodedef.h8
-rw-r--r--src/script/common/c_content.cpp3
-rw-r--r--src/script/cpp_api/s_node.cpp1
10 files changed, 361 insertions, 5 deletions
diff --git a/src/client.cpp b/src/client.cpp
index 4a00283ee..0bc2e66a5 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -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"))
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index c84e75ac0..53b9874d4 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -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;}
}
}
}
diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp
index d75d3e148..a7fafa683 100644
--- a/src/mapblock_mesh.cpp
+++ b/src/mapblock_mesh.cpp
@@ -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);
+ }
+}
diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h
index c52954998..e1cccc64e 100644
--- a/src/mapblock_mesh.h
+++ b/src/mapblock_mesh.h
@@ -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
diff --git a/src/mesh.cpp b/src/mesh.cpp
index 3200d5fa6..19d75f9f5 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -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;
+}
diff --git a/src/mesh.h b/src/mesh.h
index a89bea385..7539298cb 100644
--- a/src/mesh.h
+++ b/src/mesh.h
@@ -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
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index f1a7ad694..ef61d0722 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -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
}
diff --git a/src/nodedef.h b/src/nodedef.h
index b737e0237..2400f5f73 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -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;
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index 2f749043e..4737f1993 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -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
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index 05f908004..e3d3fb58b 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -45,6 +45,7 @@ struct EnumString ScriptApiNode::es_DrawType[] =
{NDT_FENCELIKE, "fencelike"},
{NDT_RAILLIKE, "raillike"},
{NDT_NODEBOX, "nodebox"},
+ {NDT_MESH, "mesh"},
{0, NULL},
};