123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643 |
- /*
- Minetest
- Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>,
- 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
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #include "irr_v3d.h"
- #include <stack>
- #include "util/pointer.h"
- #include "util/numeric.h"
- #include "util/mathconstants.h"
- #include "map.h"
- #include "environment.h"
- #include "nodedef.h"
- #include "treegen.h"
- namespace treegen
- {
- void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
- bool is_apple_tree, INodeDefManager *ndef, int seed)
- {
- /*
- NOTE: Tree-placing code is currently duplicated in the engine
- and in games that have saplings; both are deprecated but not
- replaced yet
- */
- MapNode treenode(ndef->getId("mapgen_tree"));
- MapNode leavesnode(ndef->getId("mapgen_leaves"));
- MapNode applenode(ndef->getId("mapgen_apple"));
- PseudoRandom pr(seed);
- s16 trunk_h = pr.range(4, 5);
- v3s16 p1 = p0;
- for(s16 ii=0; ii<trunk_h; ii++)
- {
- if(vmanip.m_area.contains(p1))
- if(ii == 0 || vmanip.getNodeNoExNoEmerge(p1).getContent() == CONTENT_AIR)
- vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
- p1.Y++;
- }
- // p1 is now the last piece of the trunk
- p1.Y -= 1;
- VoxelArea leaves_a(v3s16(-2,-1,-2), v3s16(2,2,2));
- //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
- Buffer<u8> leaves_d(leaves_a.getVolume());
- for(s32 i=0; i<leaves_a.getVolume(); i++)
- leaves_d[i] = 0;
- // Force leaves at near the end of the trunk
- {
- s16 d = 1;
- for(s16 z=-d; z<=d; z++)
- for(s16 y=-d; y<=d; y++)
- for(s16 x=-d; x<=d; x++)
- {
- leaves_d[leaves_a.index(v3s16(x,y,z))] = 1;
- }
- }
- // Add leaves randomly
- for(u32 iii=0; iii<7; iii++)
- {
- s16 d = 1;
- v3s16 p(
- pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X-d),
- pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y-d),
- pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z-d)
- );
- for(s16 z=0; z<=d; z++)
- for(s16 y=0; y<=d; y++)
- for(s16 x=0; x<=d; x++)
- {
- leaves_d[leaves_a.index(p+v3s16(x,y,z))] = 1;
- }
- }
- // Blit leaves to vmanip
- for(s16 z=leaves_a.MinEdge.Z; z<=leaves_a.MaxEdge.Z; z++)
- for(s16 y=leaves_a.MinEdge.Y; y<=leaves_a.MaxEdge.Y; y++)
- for(s16 x=leaves_a.MinEdge.X; x<=leaves_a.MaxEdge.X; x++)
- {
- v3s16 p(x,y,z);
- p += p1;
- if(vmanip.m_area.contains(p) == false)
- continue;
- u32 vi = vmanip.m_area.index(p);
- if(vmanip.m_data[vi].getContent() != CONTENT_AIR
- && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
- continue;
- u32 i = leaves_a.index(x,y,z);
- if(leaves_d[i] == 1) {
- bool is_apple = pr.range(0,99) < 10;
- if(is_apple_tree && is_apple) {
- vmanip.m_data[vi] = applenode;
- } else {
- vmanip.m_data[vi] = leavesnode;
- }
- }
- }
- }
- // L-System tree LUA spawner
- treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
- {
- ServerMap *map = &env->getServerMap();
- std::map<v3s16, MapBlock*> modified_blocks;
- ManualMapVoxelManipulator vmanip(map);
- v3s16 tree_blockp = getNodeBlockPos(p0);
- treegen::error e;
- vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
- e = make_ltree (vmanip, p0, ndef, tree_definition);
- if (e != SUCCESS)
- return e;
- vmanip.blitBackAll(&modified_blocks);
- // update lighting
- std::map<v3s16, MapBlock*> lighting_modified_blocks;
- lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
- map->updateLighting(lighting_modified_blocks, modified_blocks);
- // Send a MEET_OTHER event
- MapEditEvent event;
- event.type = MEET_OTHER;
- for(std::map<v3s16, MapBlock*>::iterator
- i = modified_blocks.begin();
- i != modified_blocks.end(); ++i)
- {
- event.modified_blocks.insert(i->first);
- }
- map->dispatchEvent(&event);
- return SUCCESS;
- }
- //L-System tree generator
- treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
- TreeDef tree_definition)
- {
- MapNode dirtnode(ndef->getId("mapgen_dirt"));
- int seed;
- if (tree_definition.explicit_seed)
- {
- seed = tree_definition.seed+14002;
- }
- else
- {
- seed = p0.X*2 + p0.Y*4 + p0.Z; // use the tree position to seed PRNG
- }
- PseudoRandom ps(seed);
- // chance of inserting abcd rules
- double prop_a = 9;
- double prop_b = 8;
- double prop_c = 7;
- double prop_d = 6;
- //randomize tree growth level, minimum=2
- s16 iterations = tree_definition.iterations;
- if (tree_definition.iterations_random_level>0)
- iterations -= ps.range(0,tree_definition.iterations_random_level);
- if (iterations<2)
- iterations=2;
- s16 MAX_ANGLE_OFFSET = 5;
- double angle_in_radians = (double)tree_definition.angle*M_PI/180;
- double angleOffset_in_radians = (s16)(ps.range(0,1)%MAX_ANGLE_OFFSET)*M_PI/180;
- //initialize rotation matrix, position and stacks for branches
- core::matrix4 rotation;
- 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;
- //generate axiom
- std::string axiom = tree_definition.initial_axiom;
- for(s16 i=0; i<iterations; i++)
- {
- std::string temp = "";
- for(s16 j=0; j<(s16)axiom.size(); j++)
- {
- char axiom_char = axiom.at(j);
- switch (axiom_char)
- {
- case 'A':
- temp+=tree_definition.rules_a;
- break;
- case 'B':
- temp+=tree_definition.rules_b;
- break;
- case 'C':
- temp+=tree_definition.rules_c;
- break;
- case 'D':
- temp+=tree_definition.rules_d;
- break;
- case 'a':
- if (prop_a >= ps.range(1,10))
- temp+=tree_definition.rules_a;
- break;
- case 'b':
- if (prop_b >= ps.range(1,10))
- temp+=tree_definition.rules_b;
- break;
- case 'c':
- if (prop_c >= ps.range(1,10))
- temp+=tree_definition.rules_c;
- break;
- case 'd':
- if (prop_d >= ps.range(1,10))
- temp+=tree_definition.rules_d;
- break;
- default:
- temp+=axiom_char;
- break;
- }
- }
- axiom=temp;
- }
- //make sure tree is not floating in the air
- if (tree_definition.trunk_type == "double")
- {
- 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);
- }
- else 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 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
- 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 degrees
- - - yaw the turtle left by angle degrees
- & - pitch the turtle down by angle degrees
- ^ - pitch the turtle up by angle degrees
- / - roll the turtle to the right by angle degrees
- * - roll the turtle to the left by angle degrees
- [ - save in stack current state info
- ] - recover from stack state info
- */
- s16 x,y,z;
- for(s16 i=0; i<(s16)axiom.size(); i++)
- {
- char axiom_char = axiom.at(i);
- core::matrix4 temp_rotation;
- temp_rotation.makeIdentity();
- v3f dir;
- switch (axiom_char)
- {
- case 'G':
- 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);
- }
- else 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':
- 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))
- {
- 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);
- }
- else 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; x++)
- for(y=-size; y<=size; y++)
- for(z=-size; z<=size; z++)
- if (abs(x) == size && abs(y) == size && abs(z) == size)
- {
- tree_leaves_placement(vmanip,v3f(position.X+x+1,position.Y+y,position.Z+z),ps.next(), tree_definition);
- tree_leaves_placement(vmanip,v3f(position.X+x-1,position.Y+y,position.Z+z),ps.next(), tree_definition);
- tree_leaves_placement(vmanip,v3f(position.X+x,position.Y+y,position.Z+z+1),ps.next(), tree_definition);
- tree_leaves_placement(vmanip,v3f(position.X+x,position.Y+y,position.Z+z-1),ps.next(), tree_definition);
- }
- }
- dir = v3f(1,0,0);
- dir = transposeMatrix(rotation,dir);
- position+=dir;
- break;
- case 'f':
- tree_single_leaves_placement(vmanip,v3f(position.X,position.Y,position.Z),ps.next() ,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);
- break;
- case ']':
- if (stack_orientation.empty())
- return UNBALANCED_BRACKETS;
- rotation=stack_orientation.top();
- stack_orientation.pop();
- position=stack_position.top();
- stack_position.pop();
- break;
- case '+':
- temp_rotation.makeIdentity();
- temp_rotation=setRotationAxisRadians(temp_rotation, angle_in_radians+angleOffset_in_radians,v3f(0,0,1));
- rotation*=temp_rotation;
- break;
- case '-':
- temp_rotation.makeIdentity();
- temp_rotation=setRotationAxisRadians(temp_rotation, angle_in_radians+angleOffset_in_radians,v3f(0,0,-1));
- rotation*=temp_rotation;
- break;
- case '&':
- temp_rotation.makeIdentity();
- temp_rotation=setRotationAxisRadians(temp_rotation, angle_in_radians+angleOffset_in_radians,v3f(0,1,0));
- rotation*=temp_rotation;
- break;
- case '^':
- temp_rotation.makeIdentity();
- temp_rotation=setRotationAxisRadians(temp_rotation, angle_in_radians+angleOffset_in_radians,v3f(0,-1,0));
- rotation*=temp_rotation;
- break;
- case '*':
- temp_rotation.makeIdentity();
- temp_rotation=setRotationAxisRadians(temp_rotation, angle_in_radians,v3f(1,0,0));
- rotation*=temp_rotation;
- break;
- case '/':
- temp_rotation.makeIdentity();
- temp_rotation=setRotationAxisRadians(temp_rotation, angle_in_radians,v3f(-1,0,0));
- rotation*=temp_rotation;
- break;
- default:
- break;
- }
- }
- return SUCCESS;
- }
- void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
- MapNode node)
- {
- 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)] = node;
- }
- void tree_trunk_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.trunknode;
- }
- void tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
- PseudoRandom ps ,TreeDef &tree_definition)
- {
- MapNode leavesnode=tree_definition.leavesnode;
- if (ps.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_chance>0)
- {
- if (ps.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)] = leavesnode;
- }
- else if (ps.range(1,100) > 20)
- vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
- }
- void tree_single_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
- PseudoRandom ps, TreeDef &tree_definition)
- {
- MapNode leavesnode=tree_definition.leavesnode;
- if (ps.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)
- {
- double c = cos(angle);
- double s = sin(angle);
- double t = 1.0 - c;
- double tx = t * axis.X;
- double ty = t * axis.Y;
- double tz = t * axis.Z;
- double sx = s * axis.X;
- double sy = s * axis.Y;
- double sz = s * axis.Z;
- M[0] = tx * axis.X + c;
- M[1] = tx * axis.Y + sz;
- M[2] = tx * axis.Z - sy;
- M[4] = ty * axis.X - sz;
- M[5] = ty * axis.Y + c;
- M[6] = ty * axis.Z + sx;
- M[8] = tz * axis.X + sy;
- M[9] = tz * axis.Y - sx;
- M[10] = tz * axis.Z + c;
- return M;
- }
- v3f transposeMatrix(irr::core::matrix4 M, v3f v)
- {
- v3f translated;
- double x = M[0] * v.X + M[4] * v.Y + M[8] * v.Z +M[12];
- double y = M[1] * v.X + M[5] * v.Y + M[9] * v.Z +M[13];
- double z = M[2] * v.X + M[6] * v.Y + M[10] * v.Z +M[14];
- translated.X=x;
- translated.Y=y;
- translated.Z=z;
- return translated;
- }
- void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
- INodeDefManager *ndef, int seed)
- {
- /*
- NOTE: Tree-placing code is currently duplicated in the engine
- and in games that have saplings; both are deprecated but not
- replaced yet
- */
- content_t c_tree = ndef->getId("mapgen_jungletree");
- content_t c_leaves = ndef->getId("mapgen_jungleleaves");
- if (c_tree == CONTENT_IGNORE)
- c_tree = ndef->getId("mapgen_tree");
- if (c_leaves == CONTENT_IGNORE)
- c_leaves = ndef->getId("mapgen_leaves");
- MapNode treenode(c_tree);
- MapNode leavesnode(c_leaves);
- PseudoRandom pr(seed);
- for(s16 x=-1; x<=1; x++)
- for(s16 z=-1; z<=1; z++)
- {
- if(pr.range(0, 2) == 0)
- continue;
- v3s16 p1 = p0 + v3s16(x,0,z);
- v3s16 p2 = p0 + v3s16(x,-1,z);
- u32 vi1 = vmanip.m_area.index(p1);
- u32 vi2 = vmanip.m_area.index(p2);
-
- if (vmanip.m_area.contains(p2) &&
- vmanip.m_data[vi2].getContent() == CONTENT_AIR)
- vmanip.m_data[vi2] = treenode;
- else if (vmanip.m_area.contains(p1) &&
- vmanip.m_data[vi1].getContent() == CONTENT_AIR)
- vmanip.m_data[vi1] = treenode;
- }
- vmanip.m_data[vmanip.m_area.index(p0)] = treenode;
- s16 trunk_h = pr.range(8, 12);
- v3s16 p1 = p0;
- for (s16 ii=0; ii<trunk_h; ii++)
- {
- if (vmanip.m_area.contains(p1)) {
- u32 vi = vmanip.m_area.index(p1);
- if (vmanip.m_data[vi].getContent() == CONTENT_AIR)
- vmanip.m_data[vi] = treenode;
- }
- p1.Y++;
- }
- // p1 is now the last piece of the trunk
- p1.Y -= 1;
- VoxelArea leaves_a(v3s16(-3,-2,-3), v3s16(3,2,3));
- //SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
- Buffer<u8> leaves_d(leaves_a.getVolume());
- for(s32 i=0; i<leaves_a.getVolume(); i++)
- leaves_d[i] = 0;
- // Force leaves at near the end of the trunk
- {
- s16 d = 1;
- for(s16 z=-d; z<=d; z++)
- for(s16 y=-d; y<=d; y++)
- for(s16 x=-d; x<=d; x++)
- {
- leaves_d[leaves_a.index(v3s16(x,y,z))] = 1;
- }
- }
- // Add leaves randomly
- for(u32 iii=0; iii<30; iii++)
- {
- s16 d = 1;
- v3s16 p(
- pr.range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X-d),
- pr.range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y-d),
- pr.range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z-d)
- );
- for(s16 z=0; z<=d; z++)
- for(s16 y=0; y<=d; y++)
- for(s16 x=0; x<=d; x++)
- {
- leaves_d[leaves_a.index(p+v3s16(x,y,z))] = 1;
- }
- }
- // Blit leaves to vmanip
- for(s16 z=leaves_a.MinEdge.Z; z<=leaves_a.MaxEdge.Z; z++)
- for(s16 y=leaves_a.MinEdge.Y; y<=leaves_a.MaxEdge.Y; y++)
- for(s16 x=leaves_a.MinEdge.X; x<=leaves_a.MaxEdge.X; x++)
- {
- v3s16 p(x,y,z);
- p += p1;
- if(vmanip.m_area.contains(p) == false)
- continue;
- u32 vi = vmanip.m_area.index(p);
- if (vmanip.m_data[vi].getContent() != CONTENT_AIR &&
- vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
- continue;
- u32 i = leaves_a.index(x,y,z);
- if(leaves_d[i] == 1)
- vmanip.m_data[vi] = leavesnode;
- }
- }
- }; // namespace treegen
|