L-Systems treegen update.

This commit is contained in:
RealBadAngel 2013-01-07 01:35:05 +01:00 committed by Ilya Zhuravlev
parent 099d7ff2ad
commit 8b75736c6f
4 changed files with 107 additions and 66 deletions

@ -1073,57 +1073,62 @@ methods:
^ clear all objects in the environments ^ clear all objects in the environments
- spawn_tree (pos, {treedef}) - spawn_tree (pos, {treedef})
^ spawns L-System tree at given pos with definition in treedef table ^ spawns L-System tree at given pos with definition in treedef table
treedef={ treedef={
axiom, - string initial tree axiom axiom, - string initial tree axiom
rules_a, - string rules set A rules_a, - string rules set A
rules_b, - string rules set B rules_b, - string rules set B
rules_c, - string rules set C rules_c, - string rules set C
rules_d, - string rules set D rules_d, - string rules set D
trunk, - string trunk node name trunk, - string trunk node name
leaves, - string leaves node name leaves, - string leaves node name
angle, - num angle in deg leaves2, - string secondary leaves node name
iterations, - num max # of iterations, usually 2 -5 leaves2_chance,- num chance (0-100) to replace leaves with leaves2
random_level, - num factor to lower nr of iterations, usually 0 - 3 angle, - num angle in deg
thin_trunks, - boolean true -> use thin trunks iterations, - num max # of iterations, usually 2 -5
fruit_tree, - boolean true -> is a fruit tree random_level, - num factor to lower nr of iterations, usually 0 - 3
fruit - string fruit node name trunk_type, - string single/double/crossed) type of trunk: 1 node, 2x2 nodes or 3x3 in cross shape
thin_branches, - boolean true -> use thin (1 node) branches
fruit, - string fruit node name
fruit_chance, - num chance (0-100) to replace leaves with fruit node
} }
Key for Special L-System Symbols used in Axioms Key for Special L-System Symbols used in Axioms
G - move forward one unit with the pin down G - move forward one unit with the pen up
F - move forward one unit with the pin up F - move forward one unit with the pen down drawing trunks and branches
A - replace with rules set A f - move forward one unit with the pen down drawing leaves
B - replace with rules set B A - replace with rules set A
C - replace with rules set C B - replace with rules set B
D - replace with rules set D C - replace with rules set C
a - replace with rules set A, chance 90% D - replace with rules set D
b - replace with rules set B, chance 80% a - replace with rules set A, chance 90%
c - replace with rules set C, chance 70% b - replace with rules set B, chance 80%
d - replace with rules set D, chance 60% c - replace with rules set C, chance 70%
+ - yaw the turtle right by angle parameter d - replace with rules set D, chance 60%
- - yaw the turtle left by angle parameter + - yaw the turtle right by angle parameter
& - pitch the turtle down by angle parameter - - yaw the turtle left by angle parameter
^ - pitch the turtle up by angle parameter & - pitch the turtle down by angle parameter
/ - roll the turtle to the right by angle parameter ^ - pitch the turtle up by angle parameter
* - roll the turtle to the left by angle parameter / - roll the turtle to the right by angle parameter
[ - save in stack current state info * - roll the turtle to the left by angle parameter
] - recover from stack state info [ - save in stack current state info
] - recover from stack state info
Example usage: spawn small apple tree Example usage: spawn small apple tree
apple_tree={ apple_tree={
axiom="FFFFFAFFBF", axiom="FFFFFAFFBF",
rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]", rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]",
rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]", rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]",
trunk="default:tree", trunk="default:tree",
leaves="default:leaves", leaves="default:leaves",
angle=30, angle=30,
iterations=2, iterations=2,
random_level=0, random_level=0,
thin_trunks=true, trunk_type="single",
fruit_tree=true, thin_branches=true,
fruit="default:apple" fruit_chance=10,
fruit="default:apple"
} }
minetest.env:spawn_tree(pos,apple_tree) minetest.env:spawn_tree(pos,apple_tree)
Deprecated: Deprecated:
- add_rat(pos): Add C++ rat object (no-op) - add_rat(pos): Add C++ rat object (no-op)

@ -4034,21 +4034,30 @@ private:
getstringfield(L, 3, "axiom", tree_def.initial_axiom); getstringfield(L, 3, "axiom", tree_def.initial_axiom);
getstringfield(L, 3, "rules_a", tree_def.rules_a); getstringfield(L, 3, "rules_a", tree_def.rules_a);
getstringfield(L, 3, "rules_b", tree_def.rules_b); getstringfield(L, 3, "rules_b", tree_def.rules_b);
getstringfield(L, 3, "rules_c", tree_def.rules_a); getstringfield(L, 3, "rules_c", tree_def.rules_c);
getstringfield(L, 3, "rules_d", tree_def.rules_b); getstringfield(L, 3, "rules_d", tree_def.rules_d);
getstringfield(L, 3, "trunk", trunk); getstringfield(L, 3, "trunk", trunk);
tree_def.trunknode=ndef->getId(trunk); tree_def.trunknode=ndef->getId(trunk);
getstringfield(L, 3, "leaves", leaves); getstringfield(L, 3, "leaves", leaves);
tree_def.leavesnode=ndef->getId(leaves); tree_def.leavesnode=ndef->getId(leaves);
tree_def.leaves2_chance=0;
getstringfield(L, 3, "leaves2", leaves);
if (leaves !="")
{
tree_def.leaves2node=ndef->getId(leaves);
getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance);
}
getintfield(L, 3, "angle", tree_def.angle); getintfield(L, 3, "angle", tree_def.angle);
getintfield(L, 3, "iterations", tree_def.iterations); getintfield(L, 3, "iterations", tree_def.iterations);
getintfield(L, 3, "random_level", tree_def.iterations_random_level); getintfield(L, 3, "random_level", tree_def.iterations_random_level);
getboolfield(L, 3, "thin_trunks", tree_def.thin_trunks); getstringfield(L, 3, "trunk_type", tree_def.trunk_type);
getboolfield(L, 3, "fruit_tree", tree_def.fruit_tree); getboolfield(L, 3, "thin_branches", tree_def.thin_branches);
if (tree_def.fruit_tree) tree_def.fruit_chance=0;
getstringfield(L, 3, "fruit", fruit);
if (fruit != "")
{ {
getstringfield(L, 3, "fruit", fruit);
tree_def.fruitnode=ndef->getId(fruit); tree_def.fruitnode=ndef->getId(fruit);
getintfield(L, 3, "fruit_chance",tree_def.fruit_chance);
} }
} }
else else

@ -118,7 +118,7 @@ void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeD
core::map<v3s16, MapBlock*> modified_blocks; core::map<v3s16, MapBlock*> modified_blocks;
ManualMapVoxelManipulator vmanip(map); ManualMapVoxelManipulator vmanip(map);
v3s16 tree_blockp = getNodeBlockPos(p0); v3s16 tree_blockp = getNodeBlockPos(p0);
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,2,1));
make_ltree (vmanip, p0, ndef, tree_definition); make_ltree (vmanip, p0, ndef, tree_definition);
vmanip.blitBackAll(&modified_blocks); vmanip.blitBackAll(&modified_blocks);
@ -221,7 +221,13 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
} }
//make sure tree is not floating in the air //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,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode);
make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode);
}
if (tree_definition.trunk_type == "crossed")
{ {
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-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);
@ -233,8 +239,9 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
Key for Special L-System Symbols used in Axioms Key for Special L-System Symbols used in Axioms
G - move forward one unit with the pin down G - move forward one unit with the pen up
F - move forward one unit with the pin 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
A - replace with rules set A A - replace with rules set A
B - replace with rules set B B - replace with rules set B
C - replace with rules set C C - replace with rules set C
@ -264,13 +271,21 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
switch (axiom_char) switch (axiom_char)
{ {
case 'G': case 'G':
dir = v3f(-1,0,0); dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir); dir = transposeMatrix(rotation,dir);
position+=dir; position+=dir;
break; break;
case 'F': case 'F':
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,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),tree_definition);
if (tree_definition.thin_trunks == false) 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,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition);
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition);
}
if ((stack_orientation.empty() && tree_definition.trunk_type == "crossed") ||
(!stack_orientation.empty() && tree_definition.trunk_type == "crossed" && !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-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);
@ -295,6 +310,12 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
dir = transposeMatrix(rotation,dir); dir = transposeMatrix(rotation,dir);
position+=dir; position+=dir;
break; break;
case 'f':
make_tree_leaves_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z),tree_definition);
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
// turtle commands // turtle commands
case '[': case '[':
stack_orientation.push(rotation); stack_orientation.push(rotation);
@ -371,6 +392,9 @@ void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0, void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition) TreeDef &tree_definition)
{ {
MapNode leavesnode=tree_definition.leavesnode;
if (myrand_range(1,100) > 100-tree_definition.leaves2_chance)
leavesnode=tree_definition.leaves2node;
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z)); v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
if(vmanip.m_area.contains(p1) == false) if(vmanip.m_area.contains(p1) == false)
return; return;
@ -378,15 +402,15 @@ void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
if(vmanip.m_data[vi].getContent() != CONTENT_AIR if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE) && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
return; return;
if (tree_definition.fruit_tree) if (tree_definition.fruit_chance>0)
{ {
if (myrand_range(1,100) > 90+tree_definition.iterations) if (myrand_range(1,100) > 100-tree_definition.fruit_chance)
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode;
else 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) else if (myrand_range(1,100) > 20)
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
} }
irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis) irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis)
@ -517,4 +541,4 @@ static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
} }
#endif #endif
}; // namespace treegen }; // namespace treegen

@ -38,12 +38,15 @@ std::string rules_c;
std::string rules_d; std::string rules_d;
MapNode trunknode; MapNode trunknode;
MapNode leavesnode; MapNode leavesnode;
MapNode leaves2node;
int leaves2_chance;
int angle; int angle;
int iterations; int iterations;
int iterations_random_level; int iterations_random_level;
bool thin_trunks; std::string trunk_type;
bool fruit_tree; bool thin_branches;
MapNode fruitnode; MapNode fruitnode;
int fruit_chance;
}; };
// Add default tree // Add default tree