LCOV - code coverage report
Current view: top level - src - treegen.cpp (source / functions) Hit Total Coverage
Test: report Lines: 1 531 0.2 %
Date: 2015-07-11 18:23:49 Functions: 2 14 14.3 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>,
       4             :                           2012-2013 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #include "irr_v3d.h"
      21             : #include <stack>
      22             : #include "util/pointer.h"
      23             : #include "util/numeric.h"
      24             : #include "util/mathconstants.h"
      25             : #include "map.h"
      26             : #include "environment.h"
      27             : #include "nodedef.h"
      28             : #include "treegen.h"
      29             : 
      30             : namespace treegen
      31             : {
      32             : 
      33           0 : void make_tree(MMVManip &vmanip, v3s16 p0,
      34             :                 bool is_apple_tree, INodeDefManager *ndef, int seed)
      35             : {
      36             :         /*
      37             :                 NOTE: Tree-placing code is currently duplicated in the engine
      38             :                 and in games that have saplings; both are deprecated but not
      39             :                 replaced yet
      40             :         */
      41           0 :         MapNode treenode(ndef->getId("mapgen_tree"));
      42           0 :         MapNode leavesnode(ndef->getId("mapgen_leaves"));
      43           0 :         MapNode applenode(ndef->getId("mapgen_apple"));
      44             : 
      45           0 :         PseudoRandom pr(seed);
      46           0 :         s16 trunk_h = pr.range(4, 5);
      47           0 :         v3s16 p1 = p0;
      48           0 :         for (s16 ii = 0; ii < trunk_h; ii++) {
      49           0 :                 if (vmanip.m_area.contains(p1)) {
      50           0 :                         u32 vi = vmanip.m_area.index(p1);
      51           0 :                         vmanip.m_data[vi] = treenode;
      52             :                 }
      53           0 :                 p1.Y++;
      54             :         }
      55             : 
      56             :         // p1 is now the last piece of the trunk
      57           0 :         p1.Y -= 1;
      58             : 
      59           0 :         VoxelArea leaves_a(v3s16(-2, -1, -2), v3s16(2, 2, 2));
      60             :         //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
      61           0 :         Buffer<u8> leaves_d(leaves_a.getVolume());
      62           0 :         for (s32 i = 0; i < leaves_a.getVolume(); i++)
      63           0 :                 leaves_d[i] = 0;
      64             : 
      65             :         // Force leaves at near the end of the trunk
      66           0 :         s16 d = 1;
      67           0 :         for (s16 z = -d; z <= d; z++)
      68           0 :         for (s16 y = -d; y <= d; y++)
      69           0 :         for (s16 x = -d; x <= d; x++) {
      70           0 :                 leaves_d[leaves_a.index(v3s16(x, y, z))] = 1;
      71             :         }
      72             : 
      73             :         // Add leaves randomly
      74           0 :         for (u32 iii = 0; iii < 7; iii++) {
      75             :                 v3s16 p(
      76           0 :                         pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X - d),
      77           0 :                         pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y - d),
      78           0 :                         pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z - d)
      79           0 :                 );
      80             : 
      81           0 :                 for (s16 z = 0; z <= d; z++)
      82           0 :                 for (s16 y = 0; y <= d; y++)
      83           0 :                 for (s16 x = 0; x <= d; x++) {
      84           0 :                         leaves_d[leaves_a.index(p + v3s16(x, y, z))] = 1;
      85             :                 }
      86             :         }
      87             : 
      88             :         // Blit leaves to vmanip
      89           0 :         for (s16 z = leaves_a.MinEdge.Z; z <= leaves_a.MaxEdge.Z; z++)
      90           0 :         for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) {
      91           0 :                 v3s16 pmin(leaves_a.MinEdge.X, y, z);
      92           0 :                 u32 i = leaves_a.index(pmin);
      93           0 :                 u32 vi = vmanip.m_area.index(pmin + p1);
      94           0 :                 for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) {
      95           0 :                         v3s16 p(x, y, z);
      96           0 :                         if (vmanip.m_area.contains(p + p1) == true &&
      97           0 :                                         (vmanip.m_data[vi].getContent() == CONTENT_AIR ||
      98           0 :                                         vmanip.m_data[vi].getContent() == CONTENT_IGNORE)) {
      99           0 :                                 if (leaves_d[i] == 1) {
     100           0 :                                         bool is_apple = pr.range(0, 99) < 10;
     101           0 :                                         if (is_apple_tree && is_apple)
     102           0 :                                                 vmanip.m_data[vi] = applenode;
     103             :                                         else
     104           0 :                                                 vmanip.m_data[vi] = leavesnode;
     105             :                                 }
     106             :                         }
     107           0 :                         vi++;
     108           0 :                         i++;
     109             :                 }
     110             :         }
     111           0 : }
     112             : 
     113             : 
     114             : // L-System tree LUA spawner
     115           0 : treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0,
     116             :                 INodeDefManager *ndef, TreeDef tree_definition)
     117             : {
     118           0 :         ServerMap *map = &env->getServerMap();
     119           0 :         std::map<v3s16, MapBlock*> modified_blocks;
     120           0 :         MMVManip vmanip(map);
     121           0 :         v3s16 tree_blockp = getNodeBlockPos(p0);
     122             :         treegen::error e;
     123             : 
     124           0 :         vmanip.initialEmerge(tree_blockp - v3s16(1, 1, 1), tree_blockp + v3s16(1, 3, 1));
     125           0 :         e = make_ltree(vmanip, p0, ndef, tree_definition);
     126           0 :         if (e != SUCCESS)
     127           0 :                 return e;
     128             : 
     129           0 :         vmanip.blitBackAll(&modified_blocks);
     130             : 
     131             :         // update lighting
     132           0 :         std::map<v3s16, MapBlock*> lighting_modified_blocks;
     133           0 :         lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
     134           0 :         map->updateLighting(lighting_modified_blocks, modified_blocks);
     135             :         // Send a MEET_OTHER event
     136           0 :         MapEditEvent event;
     137           0 :         event.type = MEET_OTHER;
     138           0 :         for (std::map<v3s16, MapBlock*>::iterator
     139           0 :                         i = modified_blocks.begin();
     140           0 :                         i != modified_blocks.end(); ++i)
     141           0 :                 event.modified_blocks.insert(i->first);
     142           0 :         map->dispatchEvent(&event);
     143           0 :         return SUCCESS;
     144             : }
     145             : 
     146             : 
     147             : //L-System tree generator
     148           0 : treegen::error make_ltree(MMVManip &vmanip, v3s16 p0,
     149             :                 INodeDefManager *ndef, TreeDef tree_definition)
     150             : {
     151           0 :         MapNode dirtnode(ndef->getId("mapgen_dirt"));
     152             :         int seed;
     153           0 :         if (tree_definition.explicit_seed)
     154           0 :                 seed = tree_definition.seed + 14002;
     155             :         else
     156           0 :                 seed = p0.X * 2 + p0.Y * 4 + p0.Z;  // use the tree position to seed PRNG
     157           0 :         PseudoRandom ps(seed);
     158             : 
     159             :         // chance of inserting abcd rules
     160           0 :         double prop_a = 9;
     161           0 :         double prop_b = 8;
     162           0 :         double prop_c = 7;
     163           0 :         double prop_d = 6;
     164             : 
     165             :         //randomize tree growth level, minimum=2
     166           0 :         s16 iterations = tree_definition.iterations;
     167           0 :         if (tree_definition.iterations_random_level > 0)
     168           0 :                 iterations -= ps.range(0, tree_definition.iterations_random_level);
     169           0 :         if (iterations < 2)
     170           0 :                 iterations = 2;
     171             : 
     172           0 :         s16 MAX_ANGLE_OFFSET = 5;
     173           0 :         double angle_in_radians = (double)tree_definition.angle * M_PI / 180;
     174           0 :         double angleOffset_in_radians = (s16)(ps.range(0, 1) % MAX_ANGLE_OFFSET) * M_PI / 180;
     175             : 
     176             :         //initialize rotation matrix, position and stacks for branches
     177           0 :         core::matrix4 rotation;
     178           0 :         rotation = setRotationAxisRadians(rotation, M_PI / 2, v3f(0, 0, 1));
     179           0 :         v3f position;
     180           0 :         position.X = p0.X;
     181           0 :         position.Y = p0.Y;
     182           0 :         position.Z = p0.Z;
     183           0 :         std::stack <core::matrix4> stack_orientation;
     184           0 :         std::stack <v3f> stack_position;
     185             : 
     186             :         //generate axiom
     187           0 :         std::string axiom = tree_definition.initial_axiom;
     188           0 :         for (s16 i = 0; i < iterations; i++) {
     189           0 :                 std::string temp = "";
     190           0 :                 for (s16 j = 0; j < (s16)axiom.size(); j++) {
     191           0 :                         char axiom_char = axiom.at(j);
     192           0 :                         switch (axiom_char) {
     193             :                         case 'A':
     194           0 :                                 temp += tree_definition.rules_a;
     195           0 :                                 break;
     196             :                         case 'B':
     197           0 :                                 temp += tree_definition.rules_b;
     198           0 :                                 break;
     199             :                         case 'C':
     200           0 :                                 temp += tree_definition.rules_c;
     201           0 :                                 break;
     202             :                         case 'D':
     203           0 :                                 temp += tree_definition.rules_d;
     204           0 :                                 break;
     205             :                         case 'a':
     206           0 :                                 if (prop_a >= ps.range(1, 10))
     207           0 :                                         temp += tree_definition.rules_a;
     208           0 :                                 break;
     209             :                         case 'b':
     210           0 :                                 if (prop_b >= ps.range(1, 10))
     211           0 :                                         temp += tree_definition.rules_b;
     212           0 :                                 break;
     213             :                         case 'c':
     214           0 :                                 if (prop_c >= ps.range(1, 10))
     215           0 :                                         temp += tree_definition.rules_c;
     216           0 :                                 break;
     217             :                         case 'd':
     218           0 :                                 if (prop_d >= ps.range(1, 10))
     219           0 :                                         temp += tree_definition.rules_d;
     220           0 :                                 break;
     221             :                         default:
     222           0 :                                 temp += axiom_char;
     223           0 :                                 break;
     224             :                         }
     225             :                 }
     226           0 :                 axiom = temp;
     227             :         }
     228             : 
     229             :         //make sure tree is not floating in the air
     230           0 :         if (tree_definition.trunk_type == "double") {
     231           0 :                 tree_node_placement(
     232             :                         vmanip,
     233           0 :                         v3f(position.X + 1, position.Y - 1, position.Z),
     234             :                         dirtnode
     235           0 :                 );
     236           0 :                 tree_node_placement(
     237             :                         vmanip,
     238           0 :                         v3f(position.X, position.Y - 1, position.Z + 1),
     239             :                         dirtnode
     240           0 :                 );
     241           0 :                 tree_node_placement(
     242             :                         vmanip,
     243           0 :                         v3f(position.X + 1, position.Y - 1, position.Z + 1),
     244             :                         dirtnode
     245           0 :                 );
     246           0 :         } else if (tree_definition.trunk_type == "crossed") {
     247           0 :                 tree_node_placement(
     248             :                         vmanip,
     249           0 :                         v3f(position.X + 1, position.Y - 1, position.Z),
     250             :                         dirtnode
     251           0 :                 );
     252           0 :                 tree_node_placement(
     253             :                         vmanip,
     254           0 :                         v3f(position.X - 1, position.Y - 1, position.Z),
     255             :                         dirtnode
     256           0 :                 );
     257           0 :                 tree_node_placement(
     258             :                         vmanip,
     259           0 :                         v3f(position.X, position.Y - 1, position.Z + 1),
     260             :                         dirtnode
     261           0 :                 );
     262           0 :                 tree_node_placement(
     263             :                         vmanip,
     264           0 :                         v3f(position.X, position.Y - 1, position.Z - 1),
     265             :                         dirtnode
     266           0 :                 );
     267             :         }
     268             : 
     269             :         /* build tree out of generated axiom
     270             : 
     271             :         Key for Special L-System Symbols used in Axioms
     272             : 
     273             :     G  - move forward one unit with the pen up
     274             :     F  - move forward one unit with the pen down drawing trunks and branches
     275             :     f  - move forward one unit with the pen down drawing leaves (100% chance)
     276             :     T  - move forward one unit with the pen down drawing trunks only
     277             :     R  - move forward one unit with the pen down placing fruit
     278             :     A  - replace with rules set A
     279             :     B  - replace with rules set B
     280             :     C  - replace with rules set C
     281             :     D  - replace with rules set D
     282             :     a  - replace with rules set A, chance 90%
     283             :     b  - replace with rules set B, chance 80%
     284             :     c  - replace with rules set C, chance 70%
     285             :     d  - replace with rules set D, chance 60%
     286             :     +  - yaw the turtle right by angle degrees
     287             :     -  - yaw the turtle left by angle degrees
     288             :     &  - pitch the turtle down by angle degrees
     289             :     ^  - pitch the turtle up by angle degrees
     290             :     /  - roll the turtle to the right by angle degrees
     291             :     *  - roll the turtle to the left by angle degrees
     292             :     [  - save in stack current state info
     293             :     ]  - recover from stack state info
     294             : 
     295             :     */
     296             : 
     297             :         s16 x,y,z;
     298           0 :         for (s16 i = 0; i < (s16)axiom.size(); i++) {
     299           0 :                 char axiom_char = axiom.at(i);
     300           0 :                 core::matrix4 temp_rotation;
     301           0 :                 temp_rotation.makeIdentity();
     302           0 :                 v3f dir;
     303           0 :                 switch (axiom_char) {
     304             :                 case 'G':
     305           0 :                         dir = v3f(1, 0, 0);
     306           0 :                         dir = transposeMatrix(rotation, dir);
     307           0 :                         position += dir;
     308           0 :                         break;
     309             :                 case 'T':
     310           0 :                         tree_trunk_placement(
     311             :                                 vmanip,
     312             :                                 v3f(position.X, position.Y, position.Z),
     313             :                                 tree_definition
     314           0 :                         );
     315           0 :                         if (tree_definition.trunk_type == "double" &&
     316           0 :                                         !tree_definition.thin_branches) {
     317           0 :                                 tree_trunk_placement(
     318             :                                         vmanip,
     319           0 :                                         v3f(position.X + 1, position.Y, position.Z),
     320             :                                         tree_definition
     321           0 :                                 );
     322           0 :                                 tree_trunk_placement(
     323             :                                         vmanip,
     324           0 :                                         v3f(position.X, position.Y, position.Z + 1),
     325             :                                         tree_definition
     326           0 :                                 );
     327           0 :                                 tree_trunk_placement(
     328             :                                         vmanip,
     329           0 :                                         v3f(position.X + 1, position.Y, position.Z + 1),
     330             :                                         tree_definition
     331           0 :                                 );
     332           0 :                         } else if (tree_definition.trunk_type == "crossed" &&
     333           0 :                                         !tree_definition.thin_branches) {
     334           0 :                                 tree_trunk_placement(
     335             :                                         vmanip,
     336           0 :                                         v3f(position.X + 1, position.Y, position.Z),
     337             :                                         tree_definition
     338           0 :                                 );
     339           0 :                                 tree_trunk_placement(
     340             :                                         vmanip,
     341           0 :                                         v3f(position.X - 1, position.Y, position.Z),
     342             :                                         tree_definition
     343           0 :                                 );
     344           0 :                                 tree_trunk_placement(
     345             :                                         vmanip,
     346           0 :                                         v3f(position.X, position.Y, position.Z + 1),
     347             :                                         tree_definition
     348           0 :                                 );
     349           0 :                                 tree_trunk_placement(
     350             :                                         vmanip,
     351           0 :                                         v3f(position.X, position.Y, position.Z - 1),
     352             :                                         tree_definition
     353           0 :                                 );
     354             :                         }
     355           0 :                         dir = v3f(1, 0, 0);
     356           0 :                         dir = transposeMatrix(rotation, dir);
     357           0 :                         position += dir;
     358           0 :                         break;
     359             :                 case 'F':
     360           0 :                         tree_trunk_placement(
     361             :                                 vmanip,
     362             :                                 v3f(position.X, position.Y, position.Z),
     363             :                                 tree_definition
     364           0 :                         );
     365           0 :                         if ((stack_orientation.empty() &&
     366           0 :                                         tree_definition.trunk_type == "double") ||
     367           0 :                                         (!stack_orientation.empty() &&
     368           0 :                                         tree_definition.trunk_type == "double" &&
     369           0 :                                         !tree_definition.thin_branches)) {
     370           0 :                                 tree_trunk_placement(
     371             :                                         vmanip,
     372           0 :                                         v3f(position.X +1 , position.Y, position.Z),
     373             :                                         tree_definition
     374           0 :                                 );
     375           0 :                                 tree_trunk_placement(
     376             :                                         vmanip,
     377           0 :                                         v3f(position.X, position.Y, position.Z + 1),
     378             :                                         tree_definition
     379           0 :                                 );
     380           0 :                                 tree_trunk_placement(
     381             :                                         vmanip,
     382           0 :                                         v3f(position.X + 1, position.Y, position.Z + 1),
     383             :                                         tree_definition
     384           0 :                                 );
     385           0 :                         } else if ((stack_orientation.empty() &&
     386           0 :                                         tree_definition.trunk_type == "crossed") ||
     387           0 :                                         (!stack_orientation.empty() &&
     388           0 :                                         tree_definition.trunk_type == "crossed" &&
     389           0 :                                         !tree_definition.thin_branches)) {
     390           0 :                                 tree_trunk_placement(
     391             :                                         vmanip,
     392           0 :                                         v3f(position.X + 1, position.Y, position.Z),
     393             :                                         tree_definition
     394           0 :                                 );
     395           0 :                                 tree_trunk_placement(
     396             :                                         vmanip,
     397           0 :                                         v3f(position.X - 1, position.Y, position.Z),
     398             :                                         tree_definition
     399           0 :                                 );
     400           0 :                                 tree_trunk_placement(
     401             :                                         vmanip,
     402           0 :                                         v3f(position.X, position.Y, position.Z + 1),
     403             :                                         tree_definition
     404           0 :                                 );
     405           0 :                                 tree_trunk_placement(
     406             :                                         vmanip,
     407           0 :                                         v3f(position.X, position.Y, position.Z - 1),
     408             :                                         tree_definition
     409           0 :                                 );
     410           0 :                         } if (stack_orientation.empty() == false) {
     411           0 :                                 s16 size = 1;
     412           0 :                                 for (x = -size; x <= size; x++)
     413           0 :                                 for (y = -size; y <= size; y++)
     414           0 :                                 for (z = -size; z <= size; z++) {
     415           0 :                                         if (abs(x) == size &&
     416           0 :                                                         abs(y) == size &&
     417           0 :                                                         abs(z) == size) {
     418           0 :                                                 tree_leaves_placement(
     419             :                                                         vmanip,
     420           0 :                                                         v3f(position.X + x + 1, position.Y + y,
     421           0 :                                                                         position.Z + z),
     422             :                                                         ps.next(),
     423             :                                                         tree_definition
     424           0 :                                                 );
     425           0 :                                                 tree_leaves_placement(
     426             :                                                         vmanip,
     427           0 :                                                         v3f(position.X + x - 1, position.Y + y,
     428           0 :                                                                         position.Z + z),
     429             :                                                         ps.next(),
     430             :                                                         tree_definition
     431           0 :                                                 );
     432           0 :                                                 tree_leaves_placement(
     433           0 :                                                         vmanip,v3f(position.X + x, position.Y + y,
     434           0 :                                                                         position.Z + z + 1),
     435             :                                                         ps.next(),
     436             :                                                         tree_definition
     437           0 :                                                 );
     438           0 :                                                 tree_leaves_placement(
     439           0 :                                                         vmanip,v3f(position.X + x, position.Y + y,
     440           0 :                                                                         position.Z + z - 1),
     441             :                                                         ps.next(),
     442             :                                                         tree_definition
     443           0 :                                                 );
     444             :                                         }
     445             :                                 }
     446             :                         }
     447           0 :                         dir = v3f(1, 0, 0);
     448           0 :                         dir = transposeMatrix(rotation, dir);
     449           0 :                         position += dir;
     450           0 :                         break;
     451             :                 case 'f':
     452           0 :                         tree_single_leaves_placement(
     453             :                                 vmanip,
     454             :                                 v3f(position.X, position.Y, position.Z),
     455             :                                 ps.next(),
     456             :                                 tree_definition
     457           0 :                         );
     458           0 :                         dir = v3f(1, 0, 0);
     459           0 :                         dir = transposeMatrix(rotation, dir);
     460           0 :                         position += dir;
     461           0 :                         break;
     462             :                 case 'R':
     463           0 :                         tree_fruit_placement(
     464             :                                 vmanip,
     465             :                                 v3f(position.X, position.Y, position.Z),
     466             :                                 tree_definition
     467           0 :                         );
     468           0 :                         dir = v3f(1, 0, 0);
     469           0 :                         dir = transposeMatrix(rotation, dir);
     470           0 :                         position += dir;
     471           0 :                         break;
     472             : 
     473             :                 // turtle orientation commands
     474             :                 case '[':
     475           0 :                         stack_orientation.push(rotation);
     476           0 :                         stack_position.push(position);
     477           0 :                         break;
     478             :                 case ']':
     479           0 :                         if (stack_orientation.empty())
     480           0 :                                 return UNBALANCED_BRACKETS;
     481           0 :                         rotation = stack_orientation.top();
     482           0 :                         stack_orientation.pop();
     483           0 :                         position = stack_position.top();
     484           0 :                         stack_position.pop();
     485           0 :                         break;
     486             :                 case '+':
     487           0 :                         temp_rotation.makeIdentity();
     488           0 :                         temp_rotation = setRotationAxisRadians(temp_rotation,
     489           0 :                                         angle_in_radians + angleOffset_in_radians, v3f(0, 0, 1));
     490           0 :                         rotation *= temp_rotation;
     491           0 :                         break;
     492             :                 case '-':
     493           0 :                         temp_rotation.makeIdentity();
     494           0 :                         temp_rotation = setRotationAxisRadians(temp_rotation,
     495           0 :                                         angle_in_radians + angleOffset_in_radians, v3f(0, 0, -1));
     496           0 :                         rotation *= temp_rotation;
     497           0 :                         break;
     498             :                 case '&':
     499           0 :                         temp_rotation.makeIdentity();
     500           0 :                         temp_rotation = setRotationAxisRadians(temp_rotation,
     501           0 :                                         angle_in_radians + angleOffset_in_radians, v3f(0, 1, 0));
     502           0 :                         rotation *= temp_rotation;
     503           0 :                         break;
     504             :                 case '^':
     505           0 :                         temp_rotation.makeIdentity();
     506           0 :                         temp_rotation = setRotationAxisRadians(temp_rotation,
     507           0 :                                         angle_in_radians + angleOffset_in_radians, v3f(0, -1, 0));
     508           0 :                         rotation *= temp_rotation;
     509           0 :                         break;
     510             :                 case '*':
     511           0 :                         temp_rotation.makeIdentity();
     512           0 :                         temp_rotation = setRotationAxisRadians(temp_rotation,
     513           0 :                                         angle_in_radians, v3f(1, 0, 0));
     514           0 :                         rotation *= temp_rotation;
     515           0 :                         break;
     516             :                 case '/':
     517           0 :                         temp_rotation.makeIdentity();
     518           0 :                         temp_rotation = setRotationAxisRadians(temp_rotation,
     519           0 :                                         angle_in_radians, v3f(-1, 0, 0));
     520           0 :                         rotation *= temp_rotation;
     521           0 :                         break;
     522             :                 default:
     523           0 :                         break;
     524             :                 }
     525             :         }
     526             : 
     527           0 :         return SUCCESS;
     528             : }
     529             : 
     530             : 
     531           0 : void tree_node_placement(MMVManip &vmanip, v3f p0, MapNode node)
     532             : {
     533           0 :         v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z));
     534           0 :         if (vmanip.m_area.contains(p1) == false)
     535           0 :                 return;
     536           0 :         u32 vi = vmanip.m_area.index(p1);
     537           0 :         if (vmanip.m_data[vi].getContent() != CONTENT_AIR
     538           0 :                         && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
     539           0 :                 return;
     540           0 :         vmanip.m_data[vmanip.m_area.index(p1)] = node;
     541             : }
     542             : 
     543             : 
     544           0 : void tree_trunk_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition)
     545             : {
     546           0 :         v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z));
     547           0 :         if (vmanip.m_area.contains(p1) == false)
     548           0 :                 return;
     549           0 :         u32 vi = vmanip.m_area.index(p1);
     550           0 :         if (vmanip.m_data[vi].getContent() != CONTENT_AIR
     551           0 :                         && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
     552           0 :                 return;
     553           0 :         vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.trunknode;
     554             : }
     555             : 
     556             : 
     557           0 : void tree_leaves_placement(MMVManip &vmanip, v3f p0,
     558             :                 PseudoRandom ps, TreeDef &tree_definition)
     559             : {
     560           0 :         MapNode leavesnode = tree_definition.leavesnode;
     561           0 :         if (ps.range(1, 100) > 100 - tree_definition.leaves2_chance)
     562           0 :                 leavesnode = tree_definition.leaves2node;
     563           0 :         v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z));
     564           0 :         if (vmanip.m_area.contains(p1) == false)
     565           0 :                 return;
     566           0 :         u32 vi = vmanip.m_area.index(p1);
     567           0 :         if (vmanip.m_data[vi].getContent() != CONTENT_AIR
     568           0 :                         && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
     569           0 :                 return;
     570           0 :         if (tree_definition.fruit_chance > 0) {
     571           0 :                 if (ps.range(1, 100) > 100 - tree_definition.fruit_chance)
     572           0 :                         vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode;
     573             :                 else
     574           0 :                         vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
     575           0 :         } else if (ps.range(1, 100) > 20) {
     576           0 :                 vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
     577             :         }
     578             : }
     579             : 
     580             : 
     581           0 : void tree_single_leaves_placement(MMVManip &vmanip, v3f p0,
     582             :                 PseudoRandom ps, TreeDef &tree_definition)
     583             : {
     584           0 :         MapNode leavesnode = tree_definition.leavesnode;
     585           0 :         if (ps.range(1, 100) > 100 - tree_definition.leaves2_chance)
     586           0 :                 leavesnode = tree_definition.leaves2node;
     587           0 :         v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z));
     588           0 :         if (vmanip.m_area.contains(p1) == false)
     589           0 :                 return;
     590           0 :         u32 vi = vmanip.m_area.index(p1);
     591           0 :         if (vmanip.m_data[vi].getContent() != CONTENT_AIR
     592           0 :                         && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
     593           0 :                 return;
     594           0 :         vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
     595             : }
     596             : 
     597             : 
     598           0 : void tree_fruit_placement(MMVManip &vmanip, v3f p0, TreeDef &tree_definition)
     599             : {
     600           0 :         v3s16 p1 = v3s16(myround(p0.X), myround(p0.Y), myround(p0.Z));
     601           0 :         if (vmanip.m_area.contains(p1) == false)
     602           0 :                 return;
     603           0 :         u32 vi = vmanip.m_area.index(p1);
     604           0 :         if (vmanip.m_data[vi].getContent() != CONTENT_AIR
     605           0 :                         && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
     606           0 :                 return;
     607           0 :         vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode;
     608             : }
     609             : 
     610             : 
     611           0 : irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis)
     612             : {
     613           0 :         double c = cos(angle);
     614           0 :         double s = sin(angle);
     615           0 :         double t = 1.0 - c;
     616             : 
     617           0 :         double tx  = t * axis.X;
     618           0 :         double ty  = t * axis.Y;
     619           0 :         double tz  = t * axis.Z;
     620           0 :         double sx  = s * axis.X;
     621           0 :         double sy  = s * axis.Y;
     622           0 :         double sz  = s * axis.Z;
     623             : 
     624           0 :         M[0] = tx * axis.X + c;
     625           0 :         M[1] = tx * axis.Y + sz;
     626           0 :         M[2] = tx * axis.Z - sy;
     627             : 
     628           0 :         M[4] = ty * axis.X - sz;
     629           0 :         M[5] = ty * axis.Y + c;
     630           0 :         M[6] = ty * axis.Z + sx;
     631             : 
     632           0 :         M[8]  = tz * axis.X + sy;
     633           0 :         M[9]  = tz * axis.Y - sx;
     634           0 :         M[10] = tz * axis.Z + c;
     635           0 :         return M;
     636             : }
     637             : 
     638             : 
     639           0 : v3f transposeMatrix(irr::core::matrix4 M, v3f v)
     640             : {
     641           0 :         v3f translated;
     642           0 :         double x = M[0] * v.X + M[4] * v.Y + M[8]  * v.Z +M[12];
     643           0 :         double y = M[1] * v.X + M[5] * v.Y + M[9]  * v.Z +M[13];
     644           0 :         double z = M[2] * v.X + M[6] * v.Y + M[10] * v.Z +M[14];
     645           0 :         translated.X = x;
     646           0 :         translated.Y = y;
     647           0 :         translated.Z = z;
     648           0 :         return translated;
     649             : }
     650             : 
     651             : 
     652           0 : void make_jungletree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, int seed)
     653             : {
     654             :         /*
     655             :                 NOTE: Tree-placing code is currently duplicated in the engine
     656             :                 and in games that have saplings; both are deprecated but not
     657             :                 replaced yet
     658             :         */
     659           0 :         MapNode treenode(ndef->getId("mapgen_jungletree"));
     660           0 :         MapNode leavesnode(ndef->getId("mapgen_jungleleaves"));
     661             : 
     662           0 :         PseudoRandom pr(seed);
     663           0 :         for (s16 x= -1; x <= 1; x++)
     664           0 :         for (s16 z= -1; z <= 1; z++) {
     665           0 :                 if (pr.range(0, 2) == 0)
     666           0 :                         continue;
     667           0 :                 v3s16 p1 = p0 + v3s16(x, 0, z);
     668           0 :                 v3s16 p2 = p0 + v3s16(x, -1, z);
     669           0 :                 u32 vi1 = vmanip.m_area.index(p1);
     670           0 :                 u32 vi2 = vmanip.m_area.index(p2);
     671             : 
     672           0 :                 if (vmanip.m_area.contains(p2) &&
     673           0 :                                 vmanip.m_data[vi2].getContent() == CONTENT_AIR)
     674           0 :                         vmanip.m_data[vi2] = treenode;
     675           0 :                 else if (vmanip.m_area.contains(p1) &&
     676           0 :                                 vmanip.m_data[vi1].getContent() == CONTENT_AIR)
     677           0 :                         vmanip.m_data[vi1] = treenode;
     678             :         }
     679           0 :         vmanip.m_data[vmanip.m_area.index(p0)] = treenode;
     680             : 
     681           0 :         s16 trunk_h = pr.range(8, 12);
     682           0 :         v3s16 p1 = p0;
     683           0 :         for (s16 ii = 0; ii < trunk_h; ii++) {
     684           0 :                 if (vmanip.m_area.contains(p1)) {
     685           0 :                         u32 vi = vmanip.m_area.index(p1);
     686           0 :                         vmanip.m_data[vi] = treenode;
     687             :                 }
     688           0 :                 p1.Y++;
     689             :         }
     690             : 
     691             :         // p1 is now the last piece of the trunk
     692           0 :         p1.Y -= 1;
     693             : 
     694           0 :         VoxelArea leaves_a(v3s16(-3, -2, -3), v3s16(3, 2, 3));
     695             :         //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
     696           0 :         Buffer<u8> leaves_d(leaves_a.getVolume());
     697           0 :         for (s32 i = 0; i < leaves_a.getVolume(); i++)
     698           0 :                 leaves_d[i] = 0;
     699             : 
     700             :         // Force leaves at near the end of the trunk
     701           0 :         s16 d = 1;
     702           0 :         for (s16 z = -d; z <= d; z++)
     703           0 :         for (s16 y = -d; y <= d; y++)
     704           0 :         for (s16 x = -d; x <= d; x++) {
     705           0 :                 leaves_d[leaves_a.index(v3s16(x,y,z))] = 1;
     706             :         }
     707             : 
     708             :         // Add leaves randomly
     709           0 :         for (u32 iii = 0; iii < 30; iii++) {
     710             :                 v3s16 p(
     711           0 :                         pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X - d),
     712           0 :                         pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y - d),
     713           0 :                         pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z - d)
     714           0 :                 );
     715             : 
     716           0 :                 for (s16 z = 0; z <= d; z++)
     717           0 :                 for (s16 y = 0; y <= d; y++)
     718           0 :                 for (s16 x = 0; x <= d; x++) {
     719           0 :                         leaves_d[leaves_a.index(p + v3s16(x, y, z))] = 1;
     720             :                 }
     721             :         }
     722             : 
     723             :         // Blit leaves to vmanip
     724           0 :         for (s16 z = leaves_a.MinEdge.Z; z <= leaves_a.MaxEdge.Z; z++)
     725           0 :         for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) {
     726           0 :                 v3s16 pmin(leaves_a.MinEdge.X, y, z);
     727           0 :                 u32 i = leaves_a.index(pmin);
     728           0 :                 u32 vi = vmanip.m_area.index(pmin + p1);
     729           0 :                 for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) {
     730           0 :                         v3s16 p(x, y, z);
     731           0 :                         if (vmanip.m_area.contains(p + p1) == true &&
     732           0 :                                         (vmanip.m_data[vi].getContent() == CONTENT_AIR ||
     733           0 :                                         vmanip.m_data[vi].getContent() == CONTENT_IGNORE)) {
     734           0 :                                 if (leaves_d[i] == 1)
     735           0 :                                         vmanip.m_data[vi] = leavesnode;
     736             :                         }
     737           0 :                         vi++;
     738           0 :                         i++;
     739             :                 }
     740             :         }
     741           0 : }
     742             : 
     743             : 
     744           0 : void make_pine_tree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, int seed)
     745             : {
     746             :         /*
     747             :                 NOTE: Tree-placing code is currently duplicated in the engine
     748             :                 and in games that have saplings; both are deprecated but not
     749             :                 replaced yet
     750             :         */
     751           0 :         MapNode treenode(ndef->getId("mapgen_pinetree"));
     752           0 :         MapNode leavesnode(ndef->getId("mapgen_pine_needles"));
     753           0 :         MapNode snownode(ndef->getId("mapgen_snow"));
     754             : 
     755           0 :         PseudoRandom pr(seed);
     756           0 :         s16 trunk_h = pr.range(9, 13);
     757           0 :         v3s16 p1 = p0;
     758           0 :         for (s16 ii = 0; ii < trunk_h; ii++) {
     759           0 :                 if (vmanip.m_area.contains(p1)) {
     760           0 :                         u32 vi = vmanip.m_area.index(p1);
     761           0 :                         vmanip.m_data[vi] = treenode;
     762             :                 }
     763           0 :                 p1.Y++;
     764             :         }
     765             : 
     766             :         // Make p1 the top node of the trunk
     767           0 :         p1.Y -= 1;
     768             : 
     769           0 :         VoxelArea leaves_a(v3s16(-3, -6, -3), v3s16(3, 3, 3));
     770             :         //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
     771           0 :         Buffer<u8> leaves_d(leaves_a.getVolume());
     772           0 :         for (s32 i = 0; i < leaves_a.getVolume(); i++)
     773           0 :                 leaves_d[i] = 0;
     774             : 
     775             :         // Upper branches
     776           0 :         s16 dev = 3;
     777           0 :         for (s16 yy = -1; yy <= 1; yy++) {
     778           0 :                 for (s16 zz = -dev; zz <= dev; zz++) {
     779           0 :                         u32 i = leaves_a.index(v3s16(-dev, yy, zz));
     780           0 :                         u32 ia = leaves_a.index(v3s16(-dev, yy+1, zz));
     781           0 :                         for (s16 xx = -dev; xx <= dev; xx++) {
     782           0 :                                 if (pr.range(0, 20) <= 19 - dev) {
     783           0 :                                         leaves_d[i] = 1;
     784           0 :                                         leaves_d[ia] = 2;
     785             :                                 }
     786           0 :                                 i++;
     787           0 :                                 ia++;
     788             :                         }
     789             :                 }
     790           0 :                 dev--;
     791             :         }
     792             : 
     793             :         // Centre top nodes
     794           0 :         u32 i = leaves_a.index(v3s16(0, 1, 0));
     795           0 :         leaves_d[i] = 1;
     796           0 :         i = leaves_a.index(v3s16(0, 2, 0));
     797           0 :         leaves_d[i] = 1;
     798           0 :         i = leaves_a.index(v3s16(0, 3, 0));
     799           0 :         leaves_d[i] = 2;
     800             : 
     801             :         // Lower branches
     802           0 :         s16 my = -6;
     803           0 :         for (u32 iii = 0; iii < 20; iii++) {
     804           0 :                 s16 xi = pr.range(-3, 2);
     805           0 :                 s16 yy = pr.range(-6, -5);
     806           0 :                 s16 zi = pr.range(-3, 2);
     807           0 :                 if (yy > my)
     808           0 :                         my = yy;
     809           0 :                 for (s16 zz = zi; zz <= zi + 1; zz++) {
     810           0 :                         u32 i = leaves_a.index(v3s16(xi, yy, zz));
     811           0 :                         u32 ia = leaves_a.index(v3s16(xi, yy + 1, zz));
     812           0 :                         for (s16 xx = xi; xx <= xi + 1; xx++) {
     813           0 :                                 leaves_d[i] = 1;
     814           0 :                                 if (leaves_d[ia] == 0)
     815           0 :                                         leaves_d[ia] = 2;
     816           0 :                                 i++;
     817           0 :                                 ia++;
     818             :                         }
     819             :                 }
     820             :         }
     821             : 
     822           0 :         dev = 2;
     823           0 :         for (s16 yy = my + 1; yy <= my + 2; yy++) {
     824           0 :                 for (s16 zz = -dev; zz <= dev; zz++) {
     825           0 :                         u32 i = leaves_a.index(v3s16(-dev, yy, zz));
     826           0 :                         u32 ia = leaves_a.index(v3s16(-dev, yy + 1, zz));
     827           0 :                         for (s16 xx = -dev; xx <= dev; xx++) {
     828           0 :                                 if (pr.range(0, 20) <= 19 - dev) {
     829           0 :                                         leaves_d[i] = 1;
     830           0 :                                         leaves_d[ia] = 2;
     831             :                                 }
     832           0 :                                 i++;
     833           0 :                                 ia++;
     834             :                         }
     835             :                 }
     836           0 :                 dev--;
     837             :         }
     838             : 
     839             :         // Blit leaves to vmanip
     840           0 :         for (s16 z = leaves_a.MinEdge.Z; z <= leaves_a.MaxEdge.Z; z++)
     841           0 :         for (s16 y = leaves_a.MinEdge.Y; y <= leaves_a.MaxEdge.Y; y++) {
     842           0 :                 v3s16 pmin(leaves_a.MinEdge.X, y, z);
     843           0 :                 u32 i = leaves_a.index(pmin);
     844           0 :                 u32 vi = vmanip.m_area.index(pmin + p1);
     845           0 :                 for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) {
     846           0 :                         v3s16 p(x, y, z);
     847           0 :                         if (vmanip.m_area.contains(p + p1) == true &&
     848           0 :                                         (vmanip.m_data[vi].getContent() == CONTENT_AIR ||
     849           0 :                                         vmanip.m_data[vi].getContent() == CONTENT_IGNORE ||
     850           0 :                                         vmanip.m_data[vi] == snownode)) {
     851           0 :                                 if (leaves_d[i] == 1)
     852           0 :                                         vmanip.m_data[vi] = leavesnode;
     853           0 :                                 else if (leaves_d[i] == 2)
     854           0 :                                         vmanip.m_data[vi] = snownode;
     855             :                         }
     856           0 :                         vi++;
     857           0 :                         i++;
     858             :                 }
     859             :         }
     860           0 : }
     861             : 
     862           3 : }; // namespace treegen

Generated by: LCOV version 1.11