/*
Minetest-c55
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>,
- 2012 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
+ 2012-2013 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <irr_v3d.h>
+#include "irr_v3d.h"
#include <stack>
+#include "util/numeric.h"
+#include "util/mathconstants.h"
#include "noise.h"
#include "map.h"
#include "environment.h"
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,3,1));
make_ltree (vmanip, p0, ndef, tree_definition);
vmanip.blitBackAll(&modified_blocks);
//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 <core::matrix4> stack_orientation;
std::stack <v3f> stack_position;
}
//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);
+ }
+ 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
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);
+ }
+ 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);
+ }
+ 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<size+1; x++)
- for(y=-size; y<size+1; y++)
- for(z=-size; z<size+1; z++)
- if (abs(x) == size and abs(y) == size and abs(z) == size)
+ for(x=-size; x<=size; x++)
+ for(y=-size; y<=size; y++)
+ for(z=-size; z<=size; z++)
+ if (abs(x) == size && abs(y) == size && abs(z) == size)
{
- make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x+1,p0.Y+position.Y+y,p0.Z+position.Z+z),tree_definition);
- make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x-1,p0.Y+position.Y+y,p0.Z+position.Z+z),tree_definition);
- make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x,p0.Y+position.Y+y,p0.Z+position.Z+z+1),tree_definition);
- make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x,p0.Y+position.Y+y,p0.Z+position.Z+z-1),tree_definition);
+ tree_leaves_placement(vmanip,v3f(position.X+x+1,position.Y+y,position.Z+z),tree_definition);
+ tree_leaves_placement(vmanip,v3f(position.X+x-1,position.Y+y,position.Z+z),tree_definition);
+ tree_leaves_placement(vmanip,v3f(position.X+x,position.Y+y,position.Z+z+1),tree_definition);
+ tree_leaves_placement(vmanip,v3f(position.X+x,position.Y+y,position.Z+z-1),tree_definition);
}
}
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
- // turtle commands
+ case 'f':
+ tree_single_leaves_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition);
+ dir = v3f(1,0,0);
+ dir = transposeMatrix(rotation,dir);
+ position+=dir;
+ break;
+ case 'R':
+ tree_fruit_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition);
+ dir = v3f(1,0,0);
+ dir = transposeMatrix(rotation,dir);
+ position+=dir;
+ break;
+
+ // turtle orientation commands
case '[':
stack_orientation.push(rotation);
stack_position.push(position);
}
}
-void make_tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
MapNode node)
{
- v3s16 p1 = v3s16(round(p0.X),round(p0.Y),round(p0.Z));
+ 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);
vmanip.m_data[vmanip.m_area.index(p1)] = node;
}
-void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition)
{
- v3s16 p1 = v3s16(round(p0.X),round(p0.Y),round(p0.Z));
+ 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);
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.trunknode;
}
-void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
+void tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition)
{
- v3s16 p1 = v3s16(round(p0.X),round(p0.Y),round(p0.Z));
+ 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;
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 (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;
+}
+
+void tree_single_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;
+ 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)