Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add meshnode drawtype. #1738

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion doc/lua_api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ mods
| |-- screenshot.png
| |-- description.txt
| |-- init.lua
| |-- models
| |-- textures
| | |-- modname_stuff.png
| | `-- modname_something_else.png
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
12 changes: 12 additions & 0 deletions src/content_mapblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;}
}
}
}
Expand Down
51 changes: 51 additions & 0 deletions src/mapblock_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
4 changes: 4 additions & 0 deletions src/mapblock_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
216 changes: 216 additions & 0 deletions src/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Loading