forked from Mirrorlandia_minetest/minetest
L-Systems treegen update.
This commit is contained in:
parent
099d7ff2ad
commit
8b75736c6f
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user