LCOV - code coverage report
Current view: top level - src - mg_ore.cpp (source / functions) Hit Total Coverage
Test: report Lines: 1 194 0.5 %
Date: 2015-07-11 18:23:49 Functions: 2 17 11.8 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2014 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #include "mg_ore.h"
      21             : #include "mapgen.h"
      22             : #include "noise.h"
      23             : #include "util/numeric.h"
      24             : #include "map.h"
      25             : #include "log.h"
      26             : 
      27             : FlagDesc flagdesc_ore[] = {
      28             :         {"absheight", OREFLAG_ABSHEIGHT},
      29             :         {NULL,        0}
      30             : };
      31             : 
      32             : 
      33             : ///////////////////////////////////////////////////////////////////////////////
      34             : 
      35             : 
      36           0 : OreManager::OreManager(IGameDef *gamedef) :
      37           0 :         ObjDefManager(gamedef, OBJDEF_ORE)
      38             : {
      39           0 : }
      40             : 
      41             : 
      42           0 : size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
      43             : {
      44           0 :         size_t nplaced = 0;
      45             : 
      46           0 :         for (size_t i = 0; i != m_objects.size(); i++) {
      47           0 :                 Ore *ore = (Ore *)m_objects[i];
      48           0 :                 if (!ore)
      49           0 :                         continue;
      50             : 
      51           0 :                 nplaced += ore->placeOre(mg, blockseed, nmin, nmax);
      52           0 :                 blockseed++;
      53             :         }
      54             : 
      55           0 :         return nplaced;
      56             : }
      57             : 
      58             : 
      59           0 : void OreManager::clear()
      60             : {
      61           0 :         for (size_t i = 0; i < m_objects.size(); i++) {
      62           0 :                 Ore *ore = (Ore *)m_objects[i];
      63           0 :                 delete ore;
      64             :         }
      65           0 :         m_objects.clear();
      66           0 : }
      67             : 
      68             : 
      69             : ///////////////////////////////////////////////////////////////////////////////
      70             : 
      71             : 
      72           0 : Ore::Ore()
      73             : {
      74           0 :         flags = 0;
      75           0 :         noise = NULL;
      76           0 : }
      77             : 
      78             : 
      79           0 : Ore::~Ore()
      80             : {
      81           0 :         delete noise;
      82           0 : }
      83             : 
      84             : 
      85           0 : void Ore::resolveNodeNames()
      86             : {
      87           0 :         getIdFromNrBacklog(&c_ore, "", CONTENT_AIR);
      88           0 :         getIdsFromNrBacklog(&c_wherein);
      89           0 : }
      90             : 
      91             : 
      92           0 : size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
      93             : {
      94           0 :         int in_range = 0;
      95             : 
      96           0 :         in_range |= (nmin.Y <= y_max && nmax.Y >= y_min);
      97           0 :         if (flags & OREFLAG_ABSHEIGHT)
      98           0 :                 in_range |= (nmin.Y >= -y_max && nmax.Y <= -y_min) << 1;
      99           0 :         if (!in_range)
     100           0 :                 return 0;
     101             : 
     102             :         int actual_ymin, actual_ymax;
     103           0 :         if (in_range & ORE_RANGE_MIRROR) {
     104           0 :                 actual_ymin = MYMAX(nmin.Y, -y_max);
     105           0 :                 actual_ymax = MYMIN(nmax.Y, -y_min);
     106             :         } else {
     107           0 :                 actual_ymin = MYMAX(nmin.Y, y_min);
     108           0 :                 actual_ymax = MYMIN(nmax.Y, y_max);
     109             :         }
     110           0 :         if (clust_size >= actual_ymax - actual_ymin + 1)
     111           0 :                 return 0;
     112             : 
     113           0 :         nmin.Y = actual_ymin;
     114           0 :         nmax.Y = actual_ymax;
     115           0 :         generate(mg->vm, mg->seed, blockseed, nmin, nmax, mg->biomemap);
     116             : 
     117           0 :         return 1;
     118             : }
     119             : 
     120             : 
     121             : ///////////////////////////////////////////////////////////////////////////////
     122             : 
     123             : 
     124           0 : void OreScatter::generate(MMVManip *vm, int mapseed, u32 blockseed,
     125             :         v3s16 nmin, v3s16 nmax, u8 *biomemap)
     126             : {
     127           0 :         PseudoRandom pr(blockseed);
     128           0 :         MapNode n_ore(c_ore, 0, ore_param2);
     129             : 
     130           0 :         u32 sizex  = (nmax.X - nmin.X + 1);
     131           0 :         u32 volume = (nmax.X - nmin.X + 1) *
     132           0 :                                  (nmax.Y - nmin.Y + 1) *
     133           0 :                                  (nmax.Z - nmin.Z + 1);
     134           0 :         u32 csize     = clust_size;
     135           0 :         u32 orechance = (csize * csize * csize) / clust_num_ores;
     136           0 :         u32 nclusters = volume / clust_scarcity;
     137             : 
     138           0 :         for (u32 i = 0; i != nclusters; i++) {
     139           0 :                 int x0 = pr.range(nmin.X, nmax.X - csize + 1);
     140           0 :                 int y0 = pr.range(nmin.Y, nmax.Y - csize + 1);
     141           0 :                 int z0 = pr.range(nmin.Z, nmax.Z - csize + 1);
     142             : 
     143           0 :                 if ((flags & OREFLAG_USE_NOISE) &&
     144           0 :                         (NoisePerlin3D(&np, x0, y0, z0, mapseed) < nthresh))
     145           0 :                         continue;
     146             : 
     147           0 :                 if (biomemap && !biomes.empty()) {
     148           0 :                         u32 index = sizex * (z0 - nmin.Z) + (x0 - nmin.X);
     149           0 :                         std::set<u8>::iterator it = biomes.find(biomemap[index]);
     150           0 :                         if (it == biomes.end())
     151           0 :                                 continue;
     152             :                 }
     153             : 
     154           0 :                 for (u32 z1 = 0; z1 != csize; z1++)
     155           0 :                 for (u32 y1 = 0; y1 != csize; y1++)
     156           0 :                 for (u32 x1 = 0; x1 != csize; x1++) {
     157           0 :                         if (pr.range(1, orechance) != 1)
     158           0 :                                 continue;
     159             : 
     160           0 :                         u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
     161           0 :                         if (!CONTAINS(c_wherein, vm->m_data[i].getContent()))
     162           0 :                                 continue;
     163             : 
     164           0 :                         vm->m_data[i] = n_ore;
     165             :                 }
     166             :         }
     167           0 : }
     168             : 
     169             : 
     170             : ///////////////////////////////////////////////////////////////////////////////
     171             : 
     172             : 
     173           0 : void OreSheet::generate(MMVManip *vm, int mapseed, u32 blockseed,
     174             :         v3s16 nmin, v3s16 nmax, u8 *biomemap)
     175             : {
     176           0 :         PseudoRandom pr(blockseed + 4234);
     177           0 :         MapNode n_ore(c_ore, 0, ore_param2);
     178             : 
     179           0 :         int max_height = clust_size;
     180           0 :         int y_start = pr.range(nmin.Y, nmax.Y - max_height);
     181             : 
     182           0 :         if (!noise) {
     183           0 :                 int sx = nmax.X - nmin.X + 1;
     184           0 :                 int sz = nmax.Z - nmin.Z + 1;
     185           0 :                 noise = new Noise(&np, 0, sx, sz);
     186             :         }
     187           0 :         noise->seed = mapseed + y_start;
     188           0 :         noise->perlinMap2D(nmin.X, nmin.Z);
     189             : 
     190           0 :         size_t index = 0;
     191           0 :         for (int z = nmin.Z; z <= nmax.Z; z++)
     192           0 :         for (int x = nmin.X; x <= nmax.X; x++, index++) {
     193           0 :                 float noiseval = noise->result[index];
     194           0 :                 if (noiseval < nthresh)
     195           0 :                         continue;
     196             : 
     197           0 :                 if (biomemap && !biomes.empty()) {
     198           0 :                         std::set<u8>::iterator it = biomes.find(biomemap[index]);
     199           0 :                         if (it == biomes.end())
     200           0 :                                 continue;
     201             :                 }
     202             : 
     203           0 :                 int height = max_height * (1. / pr.range(1, 3));
     204           0 :                 int y0 = y_start + np.scale * noiseval; //pr.range(1, 3) - 1;
     205           0 :                 int y1 = y0 + height;
     206           0 :                 for (int y = y0; y != y1; y++) {
     207           0 :                         u32 i = vm->m_area.index(x, y, z);
     208           0 :                         if (!vm->m_area.contains(i))
     209           0 :                                 continue;
     210           0 :                         if (!CONTAINS(c_wherein, vm->m_data[i].getContent()))
     211           0 :                                 continue;
     212             : 
     213           0 :                         vm->m_data[i] = n_ore;
     214             :                 }
     215             :         }
     216           0 : }
     217             : 
     218             : 
     219             : ///////////////////////////////////////////////////////////////////////////////
     220             : 
     221           0 : void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed,
     222             :         v3s16 nmin, v3s16 nmax, u8 *biomemap)
     223             : {
     224           0 :         PseudoRandom pr(blockseed + 2404);
     225           0 :         MapNode n_ore(c_ore, 0, ore_param2);
     226             : 
     227           0 :         u32 sizex  = (nmax.X - nmin.X + 1);
     228           0 :         u32 volume = (nmax.X - nmin.X + 1) *
     229           0 :                                  (nmax.Y - nmin.Y + 1) *
     230           0 :                                  (nmax.Z - nmin.Z + 1);
     231           0 :         u32 csize  = clust_size;
     232           0 :         u32 nblobs = volume / clust_scarcity;
     233             : 
     234           0 :         if (!noise)
     235           0 :                 noise = new Noise(&np, mapseed, csize, csize, csize);
     236             : 
     237           0 :         for (u32 i = 0; i != nblobs; i++) {
     238           0 :                 int x0 = pr.range(nmin.X, nmax.X - csize + 1);
     239           0 :                 int y0 = pr.range(nmin.Y, nmax.Y - csize + 1);
     240           0 :                 int z0 = pr.range(nmin.Z, nmax.Z - csize + 1);
     241             : 
     242           0 :                 if (biomemap && !biomes.empty()) {
     243           0 :                         u32 bmapidx = sizex * (z0 - nmin.Z) + (x0 - nmin.X);
     244           0 :                         std::set<u8>::iterator it = biomes.find(biomemap[bmapidx]);
     245           0 :                         if (it == biomes.end())
     246           0 :                                 continue;
     247             :                 }
     248             : 
     249           0 :                 bool noise_generated = false;
     250           0 :                 noise->seed = blockseed + i;
     251             : 
     252           0 :                 size_t index = 0;
     253           0 :                 for (u32 z1 = 0; z1 != csize; z1++)
     254           0 :                 for (u32 y1 = 0; y1 != csize; y1++)
     255           0 :                 for (u32 x1 = 0; x1 != csize; x1++, index++) {
     256           0 :                         u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1);
     257           0 :                         if (!CONTAINS(c_wherein, vm->m_data[i].getContent()))
     258           0 :                                 continue;
     259             : 
     260             :                         // Lazily generate noise only if there's a chance of ore being placed
     261             :                         // This simple optimization makes calls 6x faster on average
     262           0 :                         if (!noise_generated) {
     263           0 :                                 noise_generated = true;
     264           0 :                                 noise->perlinMap3D(x0, y0, z0);
     265             :                         }
     266             : 
     267           0 :                         float noiseval = noise->result[index];
     268             : 
     269           0 :                         float xdist = x1 - csize / 2;
     270           0 :                         float ydist = y1 - csize / 2;
     271           0 :                         float zdist = z1 - csize / 2;
     272             : 
     273           0 :                         noiseval -= (sqrt(xdist * xdist + ydist * ydist + zdist * zdist) / csize);
     274             : 
     275           0 :                         if (noiseval < nthresh)
     276           0 :                                 continue;
     277             : 
     278           0 :                         vm->m_data[i] = n_ore;
     279             :                 }
     280             :         }
     281           0 : }
     282             : 
     283             : 
     284             : ///////////////////////////////////////////////////////////////////////////////
     285             : 
     286           0 : OreVein::OreVein()
     287             : {
     288           0 :         noise2 = NULL;
     289           0 : }
     290             : 
     291             : 
     292           0 : OreVein::~OreVein()
     293             : {
     294           0 :         delete noise2;
     295           0 : }
     296             : 
     297             : 
     298           0 : void OreVein::generate(MMVManip *vm, int mapseed, u32 blockseed,
     299             :         v3s16 nmin, v3s16 nmax, u8 *biomemap)
     300             : {
     301           0 :         PseudoRandom pr(blockseed + 520);
     302           0 :         MapNode n_ore(c_ore, 0, ore_param2);
     303             : 
     304           0 :         u32 sizex = (nmax.X - nmin.X + 1);
     305             : 
     306           0 :         if (!noise) {
     307           0 :                 int sx = nmax.X - nmin.X + 1;
     308           0 :                 int sy = nmax.Y - nmin.Y + 1;
     309           0 :                 int sz = nmax.Z - nmin.Z + 1;
     310           0 :                 noise  = new Noise(&np, mapseed, sx, sy, sz);
     311           0 :                 noise2 = new Noise(&np, mapseed + 436, sx, sy, sz);
     312             :         }
     313           0 :         bool noise_generated = false;
     314             : 
     315           0 :         size_t index = 0;
     316           0 :         for (int z = nmin.Z; z <= nmax.Z; z++)
     317           0 :         for (int y = nmin.Y; y <= nmax.Y; y++)
     318           0 :         for (int x = nmin.X; x <= nmax.X; x++, index++) {
     319           0 :                 u32 i = vm->m_area.index(x, y, z);
     320           0 :                 if (!vm->m_area.contains(i))
     321           0 :                         continue;
     322           0 :                 if (!CONTAINS(c_wherein, vm->m_data[i].getContent()))
     323           0 :                         continue;
     324             : 
     325           0 :                 if (biomemap && !biomes.empty()) {
     326           0 :                         u32 bmapidx = sizex * (z - nmin.Z) + (x - nmin.X);
     327           0 :                         std::set<u8>::iterator it = biomes.find(biomemap[bmapidx]);
     328           0 :                         if (it == biomes.end())
     329           0 :                                 continue;
     330             :                 }
     331             : 
     332             :                 // Same lazy generation optimization as in OreBlob
     333           0 :                 if (!noise_generated) {
     334           0 :                         noise_generated = true;
     335           0 :                         noise->perlinMap3D(nmin.X, nmin.Y, nmin.Z);
     336           0 :                         noise2->perlinMap3D(nmin.X, nmin.Y, nmin.Z);
     337             :                 }
     338             : 
     339             :                 // randval ranges from -1..1
     340           0 :                 float randval   = (float)pr.next() / (pr.RANDOM_RANGE / 2) - 1.f;
     341           0 :                 float noiseval  = contour(noise->result[index]);
     342           0 :                 float noiseval2 = contour(noise2->result[index]);
     343           0 :                 if (noiseval * noiseval2 + randval * random_factor < nthresh)
     344           0 :                         continue;
     345             : 
     346           0 :                 vm->m_data[i] = n_ore;
     347             :         }
     348           3 : }

Generated by: LCOV version 1.11