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
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

0 comments on commit 0066bd7

Please sign in to comment.