X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftreegen.cpp;h=bd4a2f2c9b9760d0a439f8b9f63922e32907b864;hb=56195dc2e45b85b7177cfa97aade77e92cff8805;hp=54cee0fefba098f20f2b87dd04f4bbd881dd0515;hpb=5d18dc358b7f890f837e63ba717cfa9f2ac9e0af;p=oweals%2Fminetest.git diff --git a/src/treegen.cpp b/src/treegen.cpp index 54cee0fef..bd4a2f2c9 100644 --- a/src/treegen.cpp +++ b/src/treegen.cpp @@ -1,7 +1,7 @@ /* -Minetest-c55 -Copyright (C) 2010-2012 celeron55, Perttu Ahola , - 2012 RealBadAngel, Maciej Kasatkin +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola , + 2012-2013 RealBadAngel, Maciej Kasatkin This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or @@ -19,9 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_v3d.h" #include +#include "util/pointer.h" #include "util/numeric.h" #include "util/mathconstants.h" -#include "noise.h" #include "map.h" #include "environment.h" #include "nodedef.h" @@ -31,13 +31,19 @@ namespace treegen { void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, - bool is_apple_tree, INodeDefManager *ndef) + bool is_apple_tree, INodeDefManager *ndef, int seed) { + /* + NOTE: Tree-placing code is currently duplicated in the engine + and in games that have saplings; both are deprecated but not + replaced yet + */ MapNode treenode(ndef->getId("mapgen_tree")); MapNode leavesnode(ndef->getId("mapgen_leaves")); MapNode applenode(ndef->getId("mapgen_apple")); - s16 trunk_h = myrand_range(4, 5); + PseudoRandom pr(seed); + s16 trunk_h = pr.range(4, 5); v3s16 p1 = p0; for(s16 ii=0; iigetServerMap(); - core::map modified_blocks; + std::map modified_blocks; ManualMapVoxelManipulator vmanip(map); v3s16 tree_blockp = getNodeBlockPos(p0); - vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); - make_ltree (vmanip, p0, ndef, tree_definition); + treegen::error e; + + vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1)); + e = make_ltree (vmanip, p0, ndef, tree_definition); + if (e != SUCCESS) + return e; + vmanip.blitBackAll(&modified_blocks); // update lighting - core::map lighting_modified_blocks; - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue()); - } + std::map lighting_modified_blocks; + lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end()); map->updateLighting(lighting_modified_blocks, modified_blocks); // Send a MEET_OTHER event MapEditEvent event; event.type = MEET_OTHER; - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - v3s16 p = i.getNode()->getKey(); - event.modified_blocks.insert(p, true); + event.modified_blocks.insert(i->first); } map->dispatchEvent(&event); + return SUCCESS; } //L-System tree generator -void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef, +treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition) { MapNode dirtnode(ndef->getId("mapgen_dirt")); + int seed; + if (tree_definition.explicit_seed) + { + seed = tree_definition.seed+14002; + } + else + { + seed = p0.X*2 + p0.Y*4 + p0.Z; // use the tree position to seed PRNG + } + PseudoRandom ps(seed); // chance of inserting abcd rules double prop_a = 9; @@ -159,18 +175,21 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd //randomize tree growth level, minimum=2 s16 iterations = tree_definition.iterations; if (tree_definition.iterations_random_level>0) - iterations -= myrand_range(0,tree_definition.iterations_random_level); + iterations -= ps.range(0,tree_definition.iterations_random_level); if (iterations<2) iterations=2; s16 MAX_ANGLE_OFFSET = 5; double angle_in_radians = (double)tree_definition.angle*M_PI/180; - double angleOffset_in_radians = (s16)(myrand_range(0,1)%MAX_ANGLE_OFFSET)*M_PI/180; + double angleOffset_in_radians = (s16)(ps.range(0,1)%MAX_ANGLE_OFFSET)*M_PI/180; //initialize rotation matrix, position and stacks for branches core::matrix4 rotation; - rotation=setRotationAxisRadians(rotation, M_PI/2,v3f(0,0,1)); - v3f position = v3f(0,0,0); + rotation = setRotationAxisRadians(rotation, M_PI/2,v3f(0,0,1)); + v3f position; + position.X = p0.X; + position.Y = p0.Y; + position.Z = p0.Z; std::stack stack_orientation; std::stack stack_position; @@ -197,19 +216,19 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd temp+=tree_definition.rules_d; break; case 'a': - if (prop_a >= myrand_range(1,10)) + if (prop_a >= ps.range(1,10)) temp+=tree_definition.rules_a; break; case 'b': - if (prop_b >= myrand_range(1,10)) + if (prop_b >= ps.range(1,10)) temp+=tree_definition.rules_b; break; case 'c': - if (prop_c >= myrand_range(1,10)) + if (prop_c >= ps.range(1,10)) temp+=tree_definition.rules_c; break; case 'd': - if (prop_d >= myrand_range(1,10)) + if (prop_d >= ps.range(1,10)) temp+=tree_definition.rules_d; break; default: @@ -221,20 +240,29 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd } //make sure tree is not floating in the air - if (tree_definition.thin_trunks == false) + if (tree_definition.trunk_type == "double") { - make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); - make_tree_node_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); - make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode); - make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z-1),dirtnode); + tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z),dirtnode); + tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z+1),dirtnode); + tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z+1),dirtnode); + } + else if (tree_definition.trunk_type == "crossed") + { + tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z),dirtnode); + tree_node_placement(vmanip,v3f(position.X-1,position.Y-1,position.Z),dirtnode); + tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z+1),dirtnode); + tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z-1),dirtnode); } /* build tree out of generated axiom Key for Special L-System Symbols used in Axioms - G - move forward one unit with the pin down - F - move forward one unit with the pin up + G - move forward one unit with the pen up + F - move forward one unit with the pen down drawing trunks and branches + f - move forward one unit with the pen down drawing leaves (100% chance) + T - move forward one unit with the pen down drawing trunks only + R - move forward one unit with the pen down placing fruit A - replace with rules set A B - replace with rules set B C - replace with rules set C @@ -264,43 +292,85 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd switch (axiom_char) { case 'G': - dir = v3f(-1,0,0); + dir = v3f(1,0,0); + dir = transposeMatrix(rotation,dir); + position+=dir; + break; + case 'T': + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition); + if (tree_definition.trunk_type == "double" && !tree_definition.thin_branches) + { + tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z+1),tree_definition); + } + else if (tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches) + { + tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X-1,position.Y,position.Z),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z-1),tree_definition); + } + dir = v3f(1,0,0); dir = transposeMatrix(rotation,dir); position+=dir; break; case 'F': - make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z),tree_definition); - if (tree_definition.thin_trunks == false) + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition); + if ((stack_orientation.empty() && tree_definition.trunk_type == "double") || + (!stack_orientation.empty() && tree_definition.trunk_type == "double" && !tree_definition.thin_branches)) { - make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); - make_tree_trunk_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); - make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition); - make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z-1),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z+1),tree_definition); + } + else if ((stack_orientation.empty() && tree_definition.trunk_type == "crossed") || + (!stack_orientation.empty() && tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches)) + { + tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X-1,position.Y,position.Z),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition); + tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z-1),tree_definition); } if (stack_orientation.empty() == false) { s16 size = 1; - for(x=-size; x 100-tree_definition.leaves2_chance) + leavesnode=tree_definition.leaves2node; v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z)); if(vmanip.m_area.contains(p1) == false) return; u32 vi = vmanip.m_area.index(p1); if(vmanip.m_data[vi].getContent() != CONTENT_AIR && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) - return; - if (tree_definition.fruit_tree) + return; + if (tree_definition.fruit_chance>0) { - if (myrand_range(1,100) > 90+tree_definition.iterations) + if (ps.range(1,100) > 100-tree_definition.fruit_chance) vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; else - vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; + vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; } - else if (myrand_range(1,100) > 20) - vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; + else if (ps.range(1,100) > 20) + vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; +} + +void tree_single_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0, + PseudoRandom ps, TreeDef &tree_definition) +{ + MapNode leavesnode=tree_definition.leavesnode; + if (ps.range(1,100) > 100-tree_definition.leaves2_chance) + leavesnode=tree_definition.leaves2node; + v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z)); + if(vmanip.m_area.contains(p1) == false) + return; + u32 vi = vmanip.m_area.index(p1); + if(vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) + return; + vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; +} + +void tree_fruit_placement(ManualMapVoxelManipulator &vmanip, v3f p0, + TreeDef &tree_definition) +{ + v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z)); + if(vmanip.m_area.contains(p1) == false) + return; + u32 vi = vmanip.m_area.index(p1); + if(vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) + return; + vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; } irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis) @@ -428,33 +532,53 @@ v3f transposeMatrix(irr::core::matrix4 M, v3f v) return translated; } -#if 0 -static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, - INodeDefManager *ndef) +void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, + INodeDefManager *ndef, int seed) { - MapNode treenode(ndef->getId("mapgen_jungletree")); - MapNode leavesnode(ndef->getId("mapgen_leaves")); - + /* + NOTE: Tree-placing code is currently duplicated in the engine + and in games that have saplings; both are deprecated but not + replaced yet + */ + content_t c_tree = ndef->getId("mapgen_jungletree"); + content_t c_leaves = ndef->getId("mapgen_jungleleaves"); + if (c_tree == CONTENT_IGNORE) + c_tree = ndef->getId("mapgen_tree"); + if (c_leaves == CONTENT_IGNORE) + c_leaves = ndef->getId("mapgen_leaves"); + + MapNode treenode(c_tree); + MapNode leavesnode(c_leaves); + + PseudoRandom pr(seed); for(s16 x=-1; x<=1; x++) for(s16 z=-1; z<=1; z++) { - if(myrand_range(0, 2) == 0) + if(pr.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; + u32 vi1 = vmanip.m_area.index(p1); + u32 vi2 = vmanip.m_area.index(p2); + + if (vmanip.m_area.contains(p2) && + vmanip.m_data[vi2].getContent() == CONTENT_AIR) + vmanip.m_data[vi2] = treenode; + else if (vmanip.m_area.contains(p1) && + vmanip.m_data[vi1].getContent() == CONTENT_AIR) + vmanip.m_data[vi1] = treenode; } + vmanip.m_data[vmanip.m_area.index(p0)] = treenode; - s16 trunk_h = myrand_range(8, 12); + s16 trunk_h = pr.range(8, 12); v3s16 p1 = p0; - for(s16 ii=0; ii