From e58a55aa82dfc66325a694dcc3519d3c0f3388a6 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Thu, 10 Dec 2015 22:58:11 -0800 Subject: Make plantlike drawtype more fun Adds several new ways that the plantlike drawtype mesh can be changed. This requires paramtype2 = "meshoptions" to be set in the node definition. The drawtype for these nodes should be "plantlike". These modifications are all done using param2. This field is now a complex bitfield that allows some or more of the combinations to be chosen, and the mesh draw code will choose the options based as neeeded for each plantlike node. bit layout: bits 0, 1 and 2 (values 0x1 through 0x7) are for choosing the plant mesh shape: 0 - ordinary plantlike plant ("x" shaped) 1 - ordinary plant, but rotated 45 degrees ("+" shaped) 2 - a plant with 3 faces ("*" shaped) 3 - a plant with 4 faces ("#" shaped) 4 - a plant with 4 faces ("#" shaped, leaning outwards) 5 through 7 are unused and reserved for future mesh shapes. bit 3 (0x8) causes the plant to be randomly offset in the x,z plane. The plant should fall within the 1x1x1 nodebox if regularly sized. bit 4 (0x10) causes the plant mesh to grow by sqrt(2), and will cause the plant mesh to fill out 1x1x1, and appear slightly larger. Texture makers will want to make their plant texture 23x16 pixels to have the best visual fit in 1x1x1 size. bit 5 (0x20) causes each face of the plant to have a slight negative Y offset in position, descending up to 0.125 downwards into the node below. Because this is per face, this causes the plant model to be less symmetric. bit 6 (0x40) through bit 7 (0x80) are unused and reserved for future use. !(https://youtu.be/qWuI664krsI) --- src/content_mapblock.cpp | 152 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 141 insertions(+), 11 deletions(-) (limited to 'src/content_mapblock.cpp') diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 6a83bd8f3..b86b97822 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "gamedef.h" #include "log.h" +#include "noise.h" // Create a cuboid. @@ -1104,6 +1105,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data, break;} case NDT_PLANTLIKE: { + PseudoRandom rng(x<<8 | z | y<<16); + TileSpec tile = getNodeTileN(n, p, 0, data); tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY; @@ -1111,9 +1114,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data, video::SColor c = MapBlock_LightColor(255, l, f.light_source); float s = BS / 2 * f.visual_scale; + // add sqrt(2) visual scale + if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x10) != 0)) + s *= 1.41421; + + float random_offset_X = .0; + float random_offset_Z = .0; + if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x8) != 0)) { + random_offset_X = BS * ((rng.next() % 16 / 16.0) * 0.29 - 0.145); + random_offset_Z = BS * ((rng.next() % 16 / 16.0) * 0.29 - 0.145); + } - for (int j = 0; j < 2; j++) - { + for (int j = 0; j < 4; j++) { video::S3DVertex vertices[4] = { video::S3DVertex(-s,-BS/2, 0, 0,0,0, c, 0,1), @@ -1121,28 +1133,146 @@ void mapblock_mesh_generate_special(MeshMakeData *data, video::S3DVertex( s,-BS/2 + s*2,0, 0,0,0, c, 1,0), video::S3DVertex(-s,-BS/2 + s*2,0, 0,0,0, c, 0,0), }; + float rotate_degree = 0; + u8 p2mesh = 0; if (f.param_type_2 == CPT2_DEGROTATE) rotate_degree = n.param2 * 2; - - if (j == 0) { - for(u16 i = 0; i < 4; i++) - vertices[i].Pos.rotateXZBy(46 + rotate_degree); - } else if (j == 1) { - for(u16 i = 0; i < 4; i++) - vertices[i].Pos.rotateXZBy(-44 + rotate_degree); + else if (f.param_type_2 != CPT2_MESHOPTIONS) { + if (j == 0) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(46 + rotate_degree); + } else if (j == 1) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(-44 + rotate_degree); + } + } else { + p2mesh = n.param2 & 0x7; + switch (p2mesh) { + case 0: + // x + if (j == 0) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(46); + } else if (j == 1) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(-44); + } + break; + case 1: + // + + if (j == 0) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(91); + } else if (j == 1) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(1); + } + break; + case 2: + // * + if (j == 0) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(121); + } else if (j == 1) { + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(241); + } else { // (j == 2) + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(1); + } + break; + case 3: + // # + switch (j) { + case 0: + for (u16 i = 0; i < 4; i++) { + vertices[i].Pos.rotateXZBy(1); + vertices[i].Pos.Z += BS / 4; + } + break; + case 1: + for (u16 i = 0; i < 4; i++) { + vertices[i].Pos.rotateXZBy(91); + vertices[i].Pos.X += BS / 4; + } + break; + case 2: + for (u16 i = 0; i < 4; i++) { + vertices[i].Pos.rotateXZBy(181); + vertices[i].Pos.Z -= BS / 4; + } + break; + case 3: + for (u16 i = 0; i < 4; i++) { + vertices[i].Pos.rotateXZBy(271); + vertices[i].Pos.X -= BS / 4; + } + break; + } + break; + case 4: + // outward leaning #-like + switch (j) { + case 0: + for (u16 i = 2; i < 4; i++) + vertices[i].Pos.Z -= BS / 2; + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(1); + break; + case 1: + for (u16 i = 2; i < 4; i++) + vertices[i].Pos.Z -= BS / 2; + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(91); + break; + case 2: + for (u16 i = 2; i < 4; i++) + vertices[i].Pos.Z -= BS / 2; + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(181); + break; + case 3: + for (u16 i = 2; i < 4; i++) + vertices[i].Pos.Z -= BS / 2; + for (u16 i = 0; i < 4; i++) + vertices[i].Pos.rotateXZBy(271); + break; + } + break; + } } - for (int i = 0; i < 4; i++) - { + for (int i = 0; i < 4; i++) { vertices[i].Pos *= f.visual_scale; vertices[i].Pos.Y += BS/2 * (f.visual_scale - 1); vertices[i].Pos += intToFloat(p, BS); + // move to a random spot to avoid moire + if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x8) != 0)) { + vertices[i].Pos.X += random_offset_X; + vertices[i].Pos.Z += random_offset_Z; + } + // randomly move each face up/down + if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x20) != 0)) { + PseudoRandom yrng(j | x<<16 | z<<8 | y<<24 ); + vertices[i].Pos.Y -= BS * ((yrng.next() % 16 / 16.0) * 0.125); + } } u16 indices[] = {0, 1, 2, 2, 3, 0}; // Add to mesh collector collector.append(tile, vertices, 4, indices, 6); + + // stop adding faces for meshes with less than 4 faces + if (f.param_type_2 == CPT2_MESHOPTIONS) { + if (((p2mesh == 0) || (p2mesh == 1)) && (j == 1)) + break; + else if ((p2mesh == 2) && (j == 2)) + break; + } else if (j == 1) { + break; + } + } break;} case NDT_FIRELIKE: -- cgit v1.2.3 From d83bcf2c50af3fec37ac8d202064bd2ad92a6d8e Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Mon, 12 Sep 2016 16:04:13 -0700 Subject: Plantlike meshoptions: fix degrotate. (#4512) This snuck in with the meshoptions patch and accidentally kills degrotate plants. Thanks to @hybriddog for finding this. --- src/content_mapblock.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/content_mapblock.cpp') diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index b86b97822..173649aee 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -1138,7 +1138,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, u8 p2mesh = 0; if (f.param_type_2 == CPT2_DEGROTATE) rotate_degree = n.param2 * 2; - else if (f.param_type_2 != CPT2_MESHOPTIONS) { + if (f.param_type_2 != CPT2_MESHOPTIONS) { if (j == 0) { for (u16 i = 0; i < 4; i++) vertices[i].Pos.rotateXZBy(46 + rotate_degree); -- cgit v1.2.3 From 1079aeaa13a94c67c1e0a0bd1c461e14841a1eec Mon Sep 17 00:00:00 2001 From: paramat Date: Mon, 3 Oct 2016 00:56:17 +0100 Subject: Mapblock_mesh_generate_special: Improve performance Remove uses of std::map. Make sure we use ContentFeatures reference not value. Original commit by gregorycu. --- src/content_mapblock.cpp | 51 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 15 deletions(-) (limited to 'src/content_mapblock.cpp') diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 173649aee..8ce0f1e0a 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -172,6 +172,15 @@ static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef, *neighbors |= v; } +// For use in mapblock_mesh_generate_special +// X,Y,Z of position must be -1,0,1 +// This expression is a simplification of +// 3 * 3 * (pos.X + 1) + 3 * (pos.Y + 1) + (pos.Z + 1) +static inline int NeighborToIndex(const v3s16 &pos) +{ + return 9 * pos.X + 3 * pos.Y + pos.Z + 13; +} + /* TODO: Fix alpha blending for special nodes Currently only the last element rendered is blended correct @@ -401,9 +410,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Neighbor liquid levels (key = relative position) // Includes current node - std::map neighbor_levels; - std::map neighbor_contents; - std::map neighbor_flags; + + struct NeighborData { + f32 level; + content_t content; + u8 flags; + }; + NeighborData neighbor_data_matrix[27]; + const u8 neighborflag_top_is_same_liquid = 0x01; v3s16 neighbor_dirs[9] = { v3s16(0,0,0), @@ -449,9 +463,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data, flags |= neighborflag_top_is_same_liquid; } - neighbor_levels[neighbor_dirs[i]] = level; - neighbor_contents[neighbor_dirs[i]] = content; - neighbor_flags[neighbor_dirs[i]] = flags; + NeighborData &neighbor_data = + neighbor_data_matrix[NeighborToIndex(neighbor_dirs[i])]; + + neighbor_data.level = level; + neighbor_data.content = content; + neighbor_data.flags = flags; } // Corner heights (average between four liquids) @@ -472,10 +489,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data, for(u32 j=0; j<4; j++) { v3s16 neighbordir = cornerdir - halfdirs[j]; - content_t content = neighbor_contents[neighbordir]; + + NeighborData &neighbor_data = + neighbor_data_matrix[NeighborToIndex(neighbordir)]; + content_t content = neighbor_data.content; // If top is liquid, draw starting from top of node - if(neighbor_flags[neighbordir] & - neighborflag_top_is_same_liquid) + if (neighbor_data.flags & neighborflag_top_is_same_liquid) { cornerlevel = 0.5*BS; valid_count = 1; @@ -491,7 +510,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Flowing liquid has level information else if(content == c_flowing) { - cornerlevel += neighbor_levels[neighbordir]; + cornerlevel += neighbor_data.level; valid_count++; } else if(content == CONTENT_AIR) @@ -526,15 +545,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data, { v3s16 dir = side_dirs[i]; + NeighborData& neighbor_data = + neighbor_data_matrix[NeighborToIndex(dir)]; /* If our topside is liquid and neighbor's topside is liquid, don't draw side face */ - if(top_is_same_liquid && - neighbor_flags[dir] & neighborflag_top_is_same_liquid) + if (top_is_same_liquid && + neighbor_data.flags & neighborflag_top_is_same_liquid) continue; - content_t neighbor_content = neighbor_contents[dir]; + content_t neighbor_content = neighbor_data.content; const ContentFeatures &n_feat = nodedef->get(neighbor_content); // Don't draw face if neighbor is blocking the view @@ -1506,8 +1527,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data, continue; MapNode n_xy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x + xz, y + y0, z)); MapNode n_zy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y + y0, z + xz)); - ContentFeatures def_xy = nodedef->get(n_xy); - ContentFeatures def_zy = nodedef->get(n_zy); + const ContentFeatures &def_xy = nodedef->get(n_xy); + const ContentFeatures &def_zy = nodedef->get(n_zy); // Check if current node would connect with the rail is_rail_x[index] = ((def_xy.drawtype == NDT_RAILLIKE -- cgit v1.2.3