Jungle biome/whatever thing
authorPerttu Ahola <celeron55@gmail.com>
Fri, 22 Jul 2011 23:04:24 +0000 (02:04 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Fri, 22 Jul 2011 23:04:24 +0000 (02:04 +0300)
data/junglegrass.png [new file with mode: 0644]
data/jungletree.png [new file with mode: 0644]
data/jungletree_top.png [new file with mode: 0644]
src/content_mapblock.cpp
src/content_mapnode.cpp
src/content_mapnode.h
src/mapgen.cpp
src/mapnode.h

diff --git a/data/junglegrass.png b/data/junglegrass.png
new file mode 100644 (file)
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 (file)
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 (file)
index 0000000..2a9b513
Binary files /dev/null and b/data/jungletree_top.png differ
index d8bf71dc032ad3d77da461e9f19d763aeffe6c11..730907222cf3db279a2f4ccfe5c99948e40addc9 100644 (file)
@@ -198,6 +198,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; z<MAP_BLOCKSIZE; z++)
        for(s16 y=0; y<MAP_BLOCKSIZE; y++)
        for(s16 x=0; x<MAP_BLOCKSIZE; x++)
@@ -966,6 +977,57 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                collector.append(material_papyrus, vertices, 4, indices, 6);
                        }
                }
+               else if(n.d == CONTENT_JUNGLEGRASS)
+               {
+                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       video::SColor c(255,l,l,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.d == CONTENT_RAIL)
                {
                        u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
index 79e10fd617abfd4dbdbffb4b61f8ce866fdc0dfd..be7f95adcd6edfe8f217843d0f2911b624f47d5d 100644 (file)
@@ -136,12 +136,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
index e53624c21597d5cb19d6e62d1299d387254d253a..f7d3269ea1c14cf443817ab21c62c82ce01e9da2 100644 (file)
@@ -57,6 +57,8 @@ void content_mapnode_init();
 #define CONTENT_PAPYRUS 28
 #define CONTENT_BOOKSHELF 29
 #define CONTENT_RAIL 30
+#define CONTENT_JUNGLETREE 31
+#define CONTENT_JUNGLEGRASS 32
 
 #endif
 
index 8dda93c960e30a74cd4cd2d55e30b11ba741e882..0bb6560a8abc31d4b137dfe539090c59bcc1b698 100644 (file)
@@ -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<trunk_h; ii++)
+       {
+               if(vmanip.m_area.contains(p1))
+                       vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
+               p1.Y++;
+       }
+
+       // p1 is now the last piece of the trunk
+       p1.Y -= 1;
+
+       VoxelArea leaves_a(v3s16(-3,-2,-3), v3s16(3,2,3));
+       //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
+       Buffer<u8> leaves_d(leaves_a.getVolume());
+       for(s32 i=0; i<leaves_a.getVolume(); i++)
+               leaves_d[i] = 0;
+
+       // Force leaves at near the end of the trunk
+       {
+               s16 d = 1;
+               for(s16 z=-d; z<=d; z++)
+               for(s16 y=-d; y<=d; y++)
+               for(s16 x=-d; x<=d; x++)
+               {
+                       leaves_d[leaves_a.index(v3s16(x,y,z))] = 1;
+               }
+       }
+
+       // Add leaves randomly
+       for(u32 iii=0; iii<30; iii++)
+       {
+               s16 d = 1;
+
+               v3s16 p(
+                       myrand_range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X-d),
+                       myrand_range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y-d),
+                       myrand_range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z-d)
+               );
+
+               for(s16 z=0; z<=d; z++)
+               for(s16 y=0; y<=d; y++)
+               for(s16 x=0; x<=d; x++)
+               {
+                       leaves_d[leaves_a.index(p+v3s16(x,y,z))] = 1;
+               }
+       }
+
+       // Blit leaves to vmanip
+       for(s16 z=leaves_a.MinEdge.Z; z<=leaves_a.MaxEdge.Z; z++)
+       for(s16 y=leaves_a.MinEdge.Y; y<=leaves_a.MaxEdge.Y; y++)
+       for(s16 x=leaves_a.MinEdge.X; x<=leaves_a.MaxEdge.X; x++)
+       {
+               v3s16 p(x,y,z);
+               p += p1;
+               if(vmanip.m_area.contains(p) == false)
+                       continue;
+               u32 vi = vmanip.m_area.index(p);
+               if(vmanip.m_data[vi].d != CONTENT_AIR
+                               && vmanip.m_data[vi].d != CONTENT_IGNORE)
+                       continue;
+               u32 i = leaves_a.index(x,y,z);
+               if(leaves_d[i] == 1)
+                       vmanip.m_data[vi] = leavesnode;
+       }
+}
+
 void make_papyrus(VoxelManipulator &vmanip, v3s16 p0)
 {
        MapNode papyrusnode(CONTENT_PAPYRUS);
@@ -1004,13 +1090,26 @@ double tree_amount_2d(u64 seed, v2s16 p)
        double noise = noise2d_perlin(
                        0.5+(float)p.X/125, 0.5+(float)p.Y/125,
                        seed+2, 4, 0.66);
-       double zeroval = -0.35;
+       double zeroval = -0.39;
        if(noise < zeroval)
                return 0;
        else
                return 0.04 * (noise-zeroval) / (1.0-zeroval);
 }
 
+double surface_humidity_2d(u64 seed, v2s16 p)
+{
+       double noise = noise2d_perlin(
+                       0.5+(float)p.X/500, 0.5+(float)p.Y/500,
+                       seed+72384, 4, 0.66);
+       noise = (noise + 1.0)/2.0;
+       if(noise < 0.0)
+               noise = 0.0;
+       if(noise > 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; i<tree_count; i++)
@@ -1938,7 +2045,8 @@ void make_block(BlockMakeData *data)
                        {
                                u32 i = data->vmanip->m_area.index(p);
                                MapNode *n = &data->vmanip->m_data[i];
-                               if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_IGNORE)
+                               //if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_IGNORE)
+                               if(content_features(n->d).is_ground_content)
                                {
                                        found = true;
                                        break;
@@ -1965,7 +2073,11 @@ void make_block(BlockMakeData *data)
                                else if((n->d == CONTENT_MUD || n->d == 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->d == CONTENT_SAND && y > WATER_LEVEL + 2)
@@ -1976,6 +2088,54 @@ void make_block(BlockMakeData *data)
                        }
                }
 
+               /*
+                       Add jungle grass
+               */
+               if(is_jungle)
+               {
+                       PseudoRandom grassrandom(blockseed);
+                       for(u32 i=0; i<surface_humidity*5*tree_count; i++)
+                       {
+                               s16 x = grassrandom.range(node_min.X, node_max.X);
+                               s16 z = grassrandom.range(node_min.Z, node_max.Z);
+                               s16 y = find_ground_level_from_noise(data->seed, 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->d).is_ground_content
+                                                       || n->d == 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)].d != 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
index 33128049a2599692bf35212d671991e7b6401e2d..ebca3755a020fde3b04defe363e2d6c663a651d4 100644 (file)
@@ -119,7 +119,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;