L-Systems treegen update.
authorRealBadAngel <mk@realbadangel.pl>
Mon, 7 Jan 2013 00:35:05 +0000 (01:35 +0100)
committerIlya Zhuravlev <zhuravlevilya@ya.ru>
Mon, 7 Jan 2013 14:13:14 +0000 (18:13 +0400)
doc/lua_api.txt
src/scriptapi.cpp
src/treegen.cpp
src/treegen.h

index 34738974ad7f8d7fb93816967381bc124592b847..b0c1b41a3682e39758f4fcb11d0b6f1544a56052 100644 (file)
@@ -1073,57 +1073,62 @@ methods:
   ^ clear all objects in the environments 
 - spawn_tree (pos, {treedef})
   ^ spawns L-System tree at given pos with definition in treedef table
-  treedef={
-      axiom,        - string    initial tree axiom
-      rules_a,      - string    rules set A
-      rules_b,      - string    rules set B
-      rules_c,      - string    rules set C
-      rules_d,      - string    rules set D
-      trunk,        - string    trunk node name
-      leaves,       - string    leaves node name
-      angle,        - num       angle in deg
-      iterations,   - num       max # of iterations, usually 2 -5
-      random_level, - num       factor to lower nr of iterations, usually 0 - 3
-      thin_trunks,  - boolean   true -> use thin trunks
-      fruit_tree,   - boolean   true -> is a fruit tree
-      fruit         - string    fruit node name
+treedef={
+  axiom,         - string  initial tree axiom
+  rules_a,       - string  rules set A
+  rules_b,       - string  rules set B
+  rules_c,       - string  rules set C
+  rules_d,       - string  rules set D
+  trunk,         - string  trunk node name
+  leaves,        - string  leaves node name
+  leaves2,       - string  secondary leaves node name
+  leaves2_chance,- num     chance (0-100) to replace leaves with leaves2
+  angle,         - num     angle in deg
+  iterations,    - num     max # of iterations, usually 2 -5
+  random_level,  - num     factor to lower nr of iterations, usually 0 - 3
+  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
-    G  - move forward one unit with the pin down
-    F  - move forward one unit with the pin up
-    A  - replace with rules set A
-    B  - replace with rules set B
-    C  - replace with rules set C
-    D  - replace with rules set D
-    a  - replace with rules set A, chance 90%
-    b  - replace with rules set B, chance 80%
-    c  - replace with rules set C, chance 70%
-    d  - replace with rules set D, chance 60%
-    +  - yaw the turtle right by angle parameter
-    -  - yaw the turtle left by angle parameter
-    &  - pitch the turtle down by angle parameter
-    ^  - pitch the turtle up by angle parameter
-    /  - roll the turtle to the right by angle parameter
-    *  - roll the turtle to the left by angle parameter
-    [  - save in stack current state info
-    ]  - recover from stack state info
-
-  Example usage: spawn small apple tree
-  apple_tree={
-      axiom="FFFFFAFFBF",
-      rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]",
-      rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]",
-      trunk="default:tree",
-      leaves="default:leaves",
-      angle=30,
-      iterations=2,
-      random_level=0,
-      thin_trunks=true,
-      fruit_tree=true,
-      fruit="default:apple"
+Key for Special L-System Symbols used in Axioms
+  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
+  A  - replace with rules set A
+  B  - replace with rules set B
+  C  - replace with rules set C
+  D  - replace with rules set D
+  a  - replace with rules set A, chance 90%
+  b  - replace with rules set B, chance 80%
+  c  - replace with rules set C, chance 70%
+  d  - replace with rules set D, chance 60%
+  +  - yaw the turtle right by angle parameter
+  -  - yaw the turtle left by angle parameter
+  &  - pitch the turtle down by angle parameter
+  ^  - pitch the turtle up by angle parameter
+  /  - roll the turtle to the right by angle parameter
+  *  - roll the turtle to the left by angle parameter
+  [  - save in stack current state info
+  ]  - recover from stack state info
+
+Example usage: spawn small apple tree
+apple_tree={
+  axiom="FFFFFAFFBF",
+  rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]",
+  rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]",
+  trunk="default:tree",
+  leaves="default:leaves",
+  angle=30,
+  iterations=2,
+  random_level=0,
+  trunk_type="single",
+  thin_branches=true,
+  fruit_chance=10,
+  fruit="default:apple"
   }
-  minetest.env:spawn_tree(pos,apple_tree)
+minetest.env:spawn_tree(pos,apple_tree)
 
 Deprecated:
 - add_rat(pos): Add C++ rat object (no-op)
index 04f741ad3974a143d7224179b28b7da4780dffee..60e5b55f4f998c32af4399975e23f2d036d76261 100644 (file)
@@ -4034,21 +4034,30 @@ private:
                        getstringfield(L, 3, "axiom", tree_def.initial_axiom);
                        getstringfield(L, 3, "rules_a", tree_def.rules_a);
                        getstringfield(L, 3, "rules_b", tree_def.rules_b);
-                       getstringfield(L, 3, "rules_c", tree_def.rules_a);
-                       getstringfield(L, 3, "rules_d", tree_def.rules_b);
+                       getstringfield(L, 3, "rules_c", tree_def.rules_c);
+                       getstringfield(L, 3, "rules_d", tree_def.rules_d);
                        getstringfield(L, 3, "trunk", trunk);
                        tree_def.trunknode=ndef->getId(trunk);
                        getstringfield(L, 3, "leaves", 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, "iterations", tree_def.iterations);
                        getintfield(L, 3, "random_level", tree_def.iterations_random_level);
-                       getboolfield(L, 3, "thin_trunks", tree_def.thin_trunks);
-                       getboolfield(L, 3, "fruit_tree", tree_def.fruit_tree);
-                       if (tree_def.fruit_tree)
+                       getstringfield(L, 3, "trunk_type", tree_def.trunk_type);
+                       getboolfield(L, 3, "thin_branches", tree_def.thin_branches);
+                       tree_def.fruit_chance=0;
+                       getstringfield(L, 3, "fruit", fruit);
+                       if (fruit != "")
                        {
-                               getstringfield(L, 3, "fruit", fruit);
                                tree_def.fruitnode=ndef->getId(fruit);
+                               getintfield(L, 3, "fruit_chance",tree_def.fruit_chance);
                        }
                }
                else
index 54cee0fefba098f20f2b87dd04f4bbd881dd0515..49f0666bc3e9b0f80c938d2673aa7b6fc05ab8da 100644 (file)
@@ -118,7 +118,7 @@ void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeD
        core::map<v3s16, MapBlock*> modified_blocks;
        ManualMapVoxelManipulator vmanip(map);
        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);
        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
-       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);
@@ -233,8 +239,9 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
 
        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
     A  - replace with rules set A
     B  - replace with rules set B
     C  - replace with rules set C
@@ -264,13 +271,21 @@ 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 '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)
+                       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);
@@ -295,6 +310,12 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
                        dir = transposeMatrix(rotation,dir);
                        position+=dir;
                        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
                case '[':
                        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,
                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));
        if(vmanip.m_area.contains(p1) == false)
                return;
@@ -378,15 +402,15 @@ void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
        if(vmanip.m_data[vi].getContent() != CONTENT_AIR
                        && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
                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;
                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;
+               vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
 }
 
 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
 
-}; // namespace treegen
\ No newline at end of file
+}; // namespace treegen
index 62a220ee2e706087de701c5d753ae00a8e32c685..1435d6bb200d4ec773b8d27d17bbb721b04144ea 100644 (file)
@@ -38,12 +38,15 @@ std::string rules_c;
 std::string rules_d;
 MapNode trunknode;
 MapNode leavesnode;
+MapNode leaves2node;
+int leaves2_chance;
 int angle;
 int iterations;
 int iterations_random_level;
-bool thin_trunks;
-bool fruit_tree;
+std::string trunk_type;
+bool thin_branches;
 MapNode fruitnode;
+int fruit_chance;
 };
 
        // Add default tree