Skip to content

Commit

Permalink
Add meshnode drawtype.
Browse files Browse the repository at this point in the history
  • Loading branch information
RealBadAngel committed Oct 18, 2014
1 parent d1ccc64 commit 0066bd7
Show file tree
Hide file tree
Showing 11 changed files with 374 additions and 6 deletions.
14 changes: 13 additions & 1 deletion doc/lua_api.txt
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
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
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
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
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
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;
}

12 comments on commit 0066bd7

@4aiman
Copy link
Contributor

@4aiman 4aiman commented on 0066bd7 Oct 31, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this enables me to convert some weird complex nodeboxes to some static meshes which can use less vertexes/edges/faces. And that was intended to speedup the game.
Am I right or do I miss something about it?

@Calinou
Copy link
Member

@Calinou Calinou commented on 0066bd7 Nov 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this enables me to convert some weird complex nodeboxes to some static meshes which can use less vertexes/edges/faces. And that was intended to speedup the game.
Am I right or do I miss something about it?

Yes, you are right, but the vertex/triangle count stays the same. No mesh optimization or duplicate removals are done.

@4aiman
Copy link
Contributor

@4aiman 4aiman commented on 0066bd7 Nov 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Calinou
It seems you've got me wrong.
What I meant was:
Statement: I Can I create a model of a triangular pyramid and use it instead of a nodebox.
Question: Will there be only 4 vertexes or MT will try to "convert" my model to a nodebox thus making thousands of vertexes (like in more blocks mod)?

@Jordach
Copy link
Contributor

@Jordach Jordach commented on 0066bd7 Nov 5, 2014 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@4aiman
Copy link
Contributor

@4aiman 4aiman commented on 0066bd7 Nov 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jordach
Did you try to use this feature?
I've tried but MT draws a cube instead an acyual model.
I've used *.x and *.3ds formats...

@NathanSalapat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@4aiman I'm sure you are, but are you using a fresh version? I've been using the daily PPA for Ubuntu and have had the meshes working for a while. I'm using OBJ format on my models.

@Calinou
Copy link
Member

@Calinou Calinou commented on 0066bd7 Nov 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there be only 4 vertexes or MT will try to "convert" my model to a nodebox thus making thousands of vertexes (like in more blocks mod)?

I am using VanessaE's slopes in the More Blocks branch, which are 3D models in .obj format.

@4aiman
Copy link
Contributor

@4aiman 4aiman commented on 0066bd7 Nov 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Calinou, does that count as an answer to you? :)
I've asked about the engine's behaviour. You've told me what you're using.
Or was that 'yes' for the first part of my message? :)

@NathanSalapat
I thought I was using the 2-days-old build. Turned out I was wrong.
But now I have a different problem: models are too big. Is there any way to control that?

@Calinou where can I find that moreblocks of Vanessa to find out about meshnode drawtype more?

@NathanSalapat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if you can control the scale in the lua, but a cube 1x1x1 in Blender is the same size as a block in minetest.

This might be the moreblock thing @Calinou is referencing. https://forum.minetest.net/viewtopic.php?f=9&t=10428

@RHRhino
Copy link

@RHRhino RHRhino commented on 0066bd7 Nov 8, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@4aiman: Meshes are useing .obj, not .x or .3ds. In Minetest your "triangular pyramid" Tetrahedron? will also have just 4 vertices like in Blender. This is the new of this commit. You can scale the mesh in blender or in your mod with visual_scale like every other node. Check out VanessaE's slope_test mod.
@NathanSalapat: 1 Blender unit = 0.1 Minetest unit. The Blender Default Cube has 2x2x2 blender units.

@4aiman
Copy link
Contributor

@4aiman 4aiman commented on 0066bd7 Nov 8, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RHRhino: Meshes CAN use all of those - tested and working. Also, please, if you suggest looking for smth, then provide a link to it - just like NathanSalapat did :)
Blender unit = 0.1 minetest unit? Are you serious? Try to export to b3d and see the difference. Please, don't say what you just did without pointing out that there are at least 3 types of units in blender and that some exporterter still treat 1BU as a 1m.

@NathanSalapat: Thanks a lot!

@ShadowNinja
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RHRhino: 1 blender unit is scaled to one Minetest unit now.
Unfortunately I don't think this scaling is done for entity meshes.

Please sign in to comment.