### `sheet`
Creates a sheet of ore in a blob shape according to the 2D perlin noise
-described by `noise_params`. This is essentially an improved version of
-the so-called "stratus" ore seen in some unofficial mods.
+described by `noise_params` and `noise_threshold`. This is essentially an
+improved version of the so-called "stratus" ore seen in some unofficial mods.
This sheet consists of vertical columns of uniform randomly distributed height,
varying between the inclusive range `column_height_min` and `column_height_max`.
The ore parameters `clust_scarcity` and `clust_num_ores` are ignored for this ore type.
+### `puff`
+Creates a sheet of ore in a cloud-like puff shape.
+
+As with the `sheet` ore type, the size and shape of puffs are described by
+`noise_params` and `noise_threshold` and are placed at random vertical positions
+within the currently generated chunk.
+
+The vertical top and bottom displacement of each puff are determined by the noise
+parameters `np_puff_top` and `np_puff_bottom`, respectively.
+
+
### `blob`
Creates a deformed sphere of ore according to 3d perlin noise described by
`noise_params`. The maximum size of the blob is `clust_size`, and
`clust_scarcity` has the same meaning as with the `scatter` type.
-### `vein
+### `vein`
Creates veins of ore varying in density by according to the intersection of two
instances of 3d perlin noise with diffferent seeds, both described by
`noise_params`. `random_factor` varies the influence random chance has on
Useful for having ore in sky realms without having to duplicate ore entries.
+### `puff_cliffs`
+If set, puff ore generation will not taper down large differences in displacement
+when approaching the edge of a puff. This flag has no effect for ore types other
+than `puff`.
+
+### `puff_additive_composition`
+By default, when noise described by `np_puff_top` or `np_puff_bottom` results in a
+negative displacement, the sub-column at that point is not generated. With this
+attribute set, puff ore generation will instead generate the absolute difference in
+noise displacement values. This flag has no effect for ore types other than `puff`.
+
Decoration types
----------------
The varying types of decorations that can be placed.
#include "log.h"
FlagDesc flagdesc_ore[] = {
- {"absheight", OREFLAG_ABSHEIGHT},
- {NULL, 0}
+ {"absheight", OREFLAG_ABSHEIGHT},
+ {"puff_cliffs", OREFLAG_PUFF_CLIFFS},
+ {"puff_additive_composition", OREFLAG_PUFF_ADDITIVE},
+ {NULL, 0}
};
///////////////////////////////////////////////////////////////////////////////
+OrePuff::OrePuff() :
+ Ore()
+{
+ noise_puff_top = NULL;
+ noise_puff_bottom = NULL;
+}
+
+
+OrePuff::~OrePuff()
+{
+ delete noise_puff_top;
+ delete noise_puff_bottom;
+}
+
+
+void OrePuff::generate(MMVManip *vm, int mapseed, u32 blockseed,
+ v3s16 nmin, v3s16 nmax, u8 *biomemap)
+{
+ PseudoRandom pr(blockseed + 4234);
+ MapNode n_ore(c_ore, 0, ore_param2);
+
+ int y_start = pr.range(nmin.Y, nmax.Y);
+
+ if (!noise) {
+ int sx = nmax.X - nmin.X + 1;
+ int sz = nmax.Z - nmin.Z + 1;
+ noise = new Noise(&np, 0, sx, sz);
+ noise_puff_top = new Noise(&np_puff_top, 0, sx, sz);
+ noise_puff_bottom = new Noise(&np_puff_bottom, 0, sx, sz);
+ }
+
+ noise->seed = mapseed + y_start;
+ noise->perlinMap2D(nmin.X, nmin.Z);
+ bool noise_generated = false;
+
+ size_t index = 0;
+ for (int z = nmin.Z; z <= nmax.Z; z++)
+ for (int x = nmin.X; x <= nmax.X; x++, index++) {
+ float noiseval = noise->result[index];
+ if (noiseval < nthresh)
+ continue;
+
+ if (biomemap && !biomes.empty()) {
+ std::set<u8>::iterator it = biomes.find(biomemap[index]);
+ if (it == biomes.end())
+ continue;
+ }
+
+ if (!noise_generated) {
+ noise_generated = true;
+ noise_puff_top->perlinMap2D(nmin.X, nmin.Z);
+ noise_puff_bottom->perlinMap2D(nmin.X, nmin.Z);
+ }
+
+ float ntop = noise_puff_top->result[index];
+ float nbottom = noise_puff_bottom->result[index];
+
+ if (!(flags & OREFLAG_PUFF_CLIFFS)) {
+ float ndiff = noiseval - nthresh;
+ if (ndiff < 1.0f) {
+ ntop *= ndiff;
+ nbottom *= ndiff;
+ }
+ }
+
+ int ymid = y_start;
+ int y0 = ymid - nbottom;
+ int y1 = ymid + ntop;
+
+ if ((flags & OREFLAG_PUFF_ADDITIVE) && (y0 > y1))
+ SWAP(int, y0, y1);
+
+ for (int y = y0; y <= y1; y++) {
+ u32 i = vm->m_area.index(x, y, z);
+ if (!vm->m_area.contains(i))
+ continue;
+ if (!CONTAINS(c_wherein, vm->m_data[i].getContent()))
+ continue;
+
+ vm->m_data[i] = n_ore;
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+
void OreBlob::generate(MMVManip *vm, int mapseed, u32 blockseed,
v3s16 nmin, v3s16 nmax, u8 *biomemap)
{
///////////////////////////////////////////////////////////////////////////////
-OreVein::OreVein()
+OreVein::OreVein() :
+ Ore()
{
noise2 = NULL;
}
/////////////////// Ore generation flags
-// Use absolute value of height to determine ore placement
-#define OREFLAG_ABSHEIGHT 0x01
-#define OREFLAG_USE_NOISE 0x08
+#define OREFLAG_ABSHEIGHT 0x01
+#define OREFLAG_PUFF_CLIFFS 0x02
+#define OREFLAG_PUFF_ADDITIVE 0x04
+#define OREFLAG_USE_NOISE 0x08
#define ORE_RANGE_ACTUAL 1
#define ORE_RANGE_MIRROR 2
-
enum OreType {
ORE_SCATTER,
ORE_SHEET,
+ ORE_PUFF,
ORE_BLOB,
ORE_VEIN,
};
v3s16 nmin, v3s16 nmax, u8 *biomemap);
};
+class OrePuff : public Ore {
+public:
+ static const bool NEEDS_NOISE = true;
+
+ NoiseParams np_puff_top;
+ NoiseParams np_puff_bottom;
+ Noise *noise_puff_top;
+ Noise *noise_puff_bottom;
+
+ OrePuff();
+ virtual ~OrePuff();
+
+ virtual void generate(MMVManip *vm, int mapseed, u32 blockseed,
+ v3s16 nmin, v3s16 nmax, u8 *biomemap);
+};
+
class OreBlob : public Ore {
public:
static const bool NEEDS_NOISE = true;
return new OreScatter;
case ORE_SHEET:
return new OreSheet;
+ case ORE_PUFF:
+ return new OrePuff;
case ORE_BLOB:
return new OreBlob;
case ORE_VEIN:
{
{ORE_SCATTER, "scatter"},
{ORE_SHEET, "sheet"},
+ {ORE_PUFF, "puff"},
{ORE_BLOB, "blob"},
{ORE_VEIN, "vein"},
{0, NULL},
"ore_type", es_OreType, ORE_SCATTER);
Ore *ore = oremgr->create(oretype);
if (!ore) {
- errorstream << "register_ore: ore_type " << oretype << " not implemented";
+ errorstream << "register_ore: ore_type " << oretype << " not implemented\n";
return 0;
}
lua_pop(L, 1);
//// Get type-specific parameters
- if (oretype == ORE_SHEET) {
- OreSheet *oresheet = (OreSheet *)ore;
-
- oresheet->column_height_min = getintfield_default(L, index,
- "column_height_min", 1);
- oresheet->column_height_max = getintfield_default(L, index,
- "column_height_max", ore->clust_size);
- oresheet->column_midpoint_factor = getfloatfield_default(L, index,
- "column_midpoint_factor", 0.5f);
- } else if (oretype == ORE_VEIN) {
- OreVein *orevein = (OreVein *)ore;
-
- orevein->random_factor = getfloatfield_default(L, index,
- "random_factor", 1.f);
+ switch (oretype) {
+ case ORE_SHEET: {
+ OreSheet *oresheet = (OreSheet *)ore;
+
+ oresheet->column_height_min = getintfield_default(L, index,
+ "column_height_min", 1);
+ oresheet->column_height_max = getintfield_default(L, index,
+ "column_height_max", ore->clust_size);
+ oresheet->column_midpoint_factor = getfloatfield_default(L, index,
+ "column_midpoint_factor", 0.5f);
+
+ break;
+ }
+ case ORE_PUFF: {
+ OrePuff *orepuff = (OrePuff *)ore;
+
+ lua_getfield(L, index, "np_puff_top");
+ read_noiseparams(L, -1, &orepuff->np_puff_top);
+ lua_pop(L, 1);
+
+ lua_getfield(L, index, "np_puff_bottom");
+ read_noiseparams(L, -1, &orepuff->np_puff_bottom);
+ lua_pop(L, 1);
+
+ break;
+ }
+ case ORE_VEIN: {
+ OreVein *orevein = (OreVein *)ore;
+
+ orevein->random_factor = getfloatfield_default(L, index,
+ "random_factor", 1.f);
+
+ break;
+ }
+ default:
+ break;
}
ObjDefHandle handle = oremgr->add(ore);