diff --git a/data/junglegrass.png b/data/junglegrass.png new file mode 100644 index 0000000..eea87c0 Binary files /dev/null and b/data/junglegrass.png differ diff --git a/data/jungletree.png b/data/jungletree.png new file mode 100644 index 0000000..ccd20ac Binary files /dev/null and b/data/jungletree.png differ diff --git a/data/jungletree_top.png b/data/jungletree_top.png new file mode 100644 index 0000000..2a9b513 Binary files /dev/null and b/data/jungletree_top.png differ diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 4a9fa5e..3044c8b 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_mapnode.h" #include "main.h" // For g_settings and g_texturesource #include "mineral.h" +#include "mapblock_mesh.h" // For MapBlock_LightColor() #ifndef SERVER // Create a cuboid. @@ -198,6 +199,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data, AtlasPointer pa_papyrus = g_texturesource->getTexture( g_texturesource->getTextureId("papyrus.png")); material_papyrus.setTexture(0, pa_papyrus.atlas); + + // junglegrass material + video::SMaterial material_junglegrass; + material_junglegrass.setFlag(video::EMF_LIGHTING, false); + material_junglegrass.setFlag(video::EMF_BILINEAR_FILTER, false); + material_junglegrass.setFlag(video::EMF_FOG_ENABLE, true); + material_junglegrass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_junglegrass = g_texturesource->getTexture( + g_texturesource->getTextureId("junglegrass.png")); + material_junglegrass.setTexture(0, pa_junglegrass.atlas); + for(s16 z=0; zm_daynight_ratio)); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); float d = (float)BS/16; // Wall at X+ of node @@ -341,7 +353,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Otherwise use the light of this node (the water) else l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(WATER_ALPHA,l,l,l); + video::SColor c = MapBlock_LightColor(WATER_ALPHA, l); // Neighbor water levels (key = relative position) // Includes current node @@ -607,7 +619,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, continue; u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(WATER_ALPHA,l,l,l); + video::SColor c = MapBlock_LightColor(WATER_ALPHA, l); video::S3DVertex vertices[4] = { @@ -642,7 +654,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, { /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/ u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<6; j++) { @@ -709,7 +721,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.getContent() == CONTENT_GLASS) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<6; j++) { @@ -772,7 +784,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.getContent() == CONTENT_FENCE) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); const f32 post_rad=(f32)BS/10; const f32 bar_rad=(f32)BS/20; @@ -861,7 +873,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else l = 255;*/ u8 l = 255; - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); // Get the right texture TileSpec ts = n.getTile(dir); @@ -920,7 +932,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.getContent() == CONTENT_PAPYRUS) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<4; j++) { @@ -967,10 +979,61 @@ void mapblock_mesh_generate_special(MeshMakeData *data, collector.append(material_papyrus, vertices, 4, indices, 6); } } + else if(n.getContent() == CONTENT_JUNGLEGRASS) + { + u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); + video::SColor c = MapBlock_LightColor(255, l); + + for(u32 j=0; j<4; j++) + { + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, + pa_papyrus.x0(), pa_papyrus.y1()), + video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, + pa_papyrus.x1(), pa_papyrus.y1()), + video::S3DVertex(BS/2,BS/1,0, 0,0,0, c, + pa_papyrus.x1(), pa_papyrus.y0()), + video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c, + pa_papyrus.x0(), pa_papyrus.y0()), + }; + + if(j == 0) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(45); + } + else if(j == 1) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-45); + } + else if(j == 2) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(135); + } + else if(j == 3) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-135); + } + + for(u16 i=0; i<4; i++) + { + vertices[i].Pos *= 1.3; + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_junglegrass, vertices, 4, indices, 6); + } + } else if(n.getContent() == CONTENT_RAIL) { u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); bool is_rail_x [] = { false, false }; /* x-1, x+1 */ bool is_rail_z [] = { false, false }; /* z-1, z+1 */ diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 8701ab8..146b806 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -195,12 +195,34 @@ void content_mapnode_init() f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; setWoodLikeDiggingProperties(f->digging_properties, 1.0); + i = CONTENT_JUNGLETREE; + f = &content_features(i); + f->setAllTextures("jungletree.png"); + f->setTexture(0, "jungletree_top.png"); + f->setTexture(1, "jungletree_top.png"); + f->param_type = CPT_MINERAL; + //f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_JUNGLEGRASS; + f = &content_features(i); + f->setInventoryTexture("junglegrass.png"); + f->light_propagates = true; + f->param_type = CPT_LIGHT; + //f->is_ground_content = true; + f->air_equivalent = false; // grass grows underneath + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->solidness = 0; // drawn separately, makes no faces + f->walkable = false; + setWoodLikeDiggingProperties(f->digging_properties, 0.10); + i = CONTENT_LEAVES; f = &content_features(i); f->light_propagates = true; //f->param_type = CPT_MINERAL; f->param_type = CPT_LIGHT; - f->is_ground_content = true; + //f->is_ground_content = true; if(new_style_leaves) { f->solidness = 0; // drawn separately, makes no faces diff --git a/src/content_mapnode.h b/src/content_mapnode.h index 02c604c..51cf064 100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@ -44,6 +44,8 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); #define CONTENT_FURNACE 16 #define CONTENT_FENCE 21 #define CONTENT_RAIL 30 +#define CONTENT_JUNGLETREE 31 +#define CONTENT_JUNGLEGRASS 32 // 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable #define CONTENT_GRASS 0x800 //1 diff --git a/src/keycode.cpp b/src/keycode.cpp index f014914..d6472d2 100644 --- a/src/keycode.cpp +++ b/src/keycode.cpp @@ -233,3 +233,4 @@ void clearKeyCache() { g_key_setting_cache.clear(); } + diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 45cd8d9..465170c 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -140,9 +140,24 @@ void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs) } } -inline video::SColor lightColor(u8 alpha, u8 light) +video::SColor MapBlock_LightColor(u8 alpha, u8 light) { +#if 0 return video::SColor(alpha,light,light,light); +#endif + //return video::SColor(alpha,light,light,MYMAX(0, (s16)light-25)+25); + /*return video::SColor(alpha,light,light,MYMAX(0, + pow((float)light/255.0, 0.8)*255.0));*/ +#if 1 + // Emphase blue a bit in darker places + float lim = 80; + float power = 0.7; + if(light > lim) + return video::SColor(alpha,light,light,light); + else + return video::SColor(alpha,light,light,MYMAX(0, + pow((float)light/lim, power)*lim)); +#endif } struct FastFace @@ -198,7 +213,7 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, float w = tile.texture.size.X; float h = tile.texture.size.Y; - /*video::SColor c = lightColor(alpha, li); + /*video::SColor c = MapBlock_LightColor(alpha, li); face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c, core::vector2d(x0+w*abs_scale, y0+h)); @@ -210,16 +225,16 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, core::vector2d(x0+w*abs_scale, y0));*/ face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), - lightColor(alpha, li0), + MapBlock_LightColor(alpha, li0), core::vector2d(x0+w*abs_scale, y0+h)); face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), - lightColor(alpha, li1), + MapBlock_LightColor(alpha, li1), core::vector2d(x0, y0+h)); face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), - lightColor(alpha, li2), + MapBlock_LightColor(alpha, li2), core::vector2d(x0, y0)); face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), - lightColor(alpha, li3), + MapBlock_LightColor(alpha, li3), core::vector2d(x0+w*abs_scale, y0)); face.tile = tile; diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h index 591172b..d43c19a 100644 --- a/src/mapblock_mesh.h +++ b/src/mapblock_mesh.h @@ -121,6 +121,9 @@ private: core::array m_prebuffers; }; +// Helper functions +video::SColor MapBlock_LightColor(u8 alpha, u8 light); + class MapBlock; struct MeshMakeData @@ -137,6 +140,7 @@ struct MeshMakeData void fill(u32 daynight_ratio, MapBlock *block); }; +// This is the highest-level function in here scene::SMesh* makeMapBlockMesh(MeshMakeData *data); #endif diff --git a/src/mapgen.cpp b/src/mapgen.cpp index bc4f822..0ba7f91 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -152,6 +152,92 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0) } } +static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0) +{ + MapNode treenode(CONTENT_JUNGLETREE); + MapNode leavesnode(CONTENT_LEAVES); + + for(s16 x=-1; x<=1; x++) + for(s16 z=-1; z<=1; z++) + { + if(myrand_range(0, 2) == 0) + continue; + v3s16 p1 = p0 + v3s16(x,0,z); + v3s16 p2 = p0 + v3s16(x,-1,z); + if(vmanip.m_area.contains(p2) + && vmanip.m_data[vmanip.m_area.index(p2)] == CONTENT_AIR) + vmanip.m_data[vmanip.m_area.index(p2)] = treenode; + else if(vmanip.m_area.contains(p1)) + vmanip.m_data[vmanip.m_area.index(p1)] = treenode; + } + + s16 trunk_h = myrand_range(8, 12); + v3s16 p1 = p0; + for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]); + Buffer leaves_d(leaves_a.getVolume()); + for(s32 i=0; i 1.0) + noise = 1.0; + return noise; +} + #if 0 double randomstone_amount_2d(u64 seed, v2s16 p) { @@ -1909,11 +2008,19 @@ void make_block(BlockMakeData *data) } /* - Add trees + Calculate some stuff */ + float surface_humidity = surface_humidity_2d(data->seed, p2d_center); + bool is_jungle = surface_humidity > 0.75; // Amount of trees u32 tree_count = block_area_nodes * tree_amount_2d(data->seed, p2d_center); + if(is_jungle) + tree_count *= 5; + + /* + Add trees + */ PseudoRandom treerandom(blockseed); // Put trees in random places on part of division for(u32 i=0; igetContent() == CONTENT_MUD || n->getContent() == CONTENT_GRASS) && y > WATER_LEVEL + 2) { p.Y++; - make_tree(vmanip, p); + //if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5) + if(is_jungle == false) + make_tree(vmanip, p); + else + make_jungletree(vmanip, p); } // Cactii grow only on sand, on land else if(n->getContent() == CONTENT_SAND && y > WATER_LEVEL + 2) @@ -1976,6 +2087,54 @@ void make_block(BlockMakeData *data) } } + /* + Add jungle grass + */ + if(is_jungle) + { + PseudoRandom grassrandom(blockseed); + for(u32 i=0; iseed, v2s16(x,z), 4); + if(y < WATER_LEVEL) + continue; + if(y < node_min.Y || y > node_max.Y) + continue; + /* + Find exact ground level + */ + v3s16 p(x,y+6,z); + bool found = false; + for(; p.Y >= y-6; p.Y--) + { + u32 i = data->vmanip->m_area.index(p); + MapNode *n = &data->vmanip->m_data[i]; + if(content_features(*n).is_ground_content + || n->getContent() == CONTENT_JUNGLETREE) + { + found = true; + break; + } + } + // If not found, handle next one + if(found == false) + continue; + p.Y++; + if(vmanip.m_area.contains(p) == false) + continue; + if(vmanip.m_data[vmanip.m_area.index(p)].getContent() != CONTENT_AIR) + continue; + /*p.Y--; + if(vmanip.m_area.contains(p)) + vmanip.m_data[vmanip.m_area.index(p)] = CONTENT_MUD; + p.Y++;*/ + if(vmanip.m_area.contains(p)) + vmanip.m_data[vmanip.m_area.index(p)] = CONTENT_JUNGLEGRASS; + } + } + #if 0 /* Add some kind of random stones diff --git a/src/mapnode.h b/src/mapnode.h index 3b7ef58..956de68 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -115,7 +115,8 @@ struct ContentFeatures TileSpec tiles[6]; video::ITexture *inventory_texture; - + + // True for all ground-like things like stone and mud, false for eg. trees bool is_ground_content; bool light_propagates; bool sunlight_propagates;