diff options
-rw-r--r-- | src/treegen.cpp | 756 | ||||
-rw-r--r-- | src/treegen.h | 5 |
2 files changed, 495 insertions, 266 deletions
diff --git a/src/treegen.cpp b/src/treegen.cpp index 5c95b250e..1c915ca39 100644 --- a/src/treegen.cpp +++ b/src/treegen.cpp @@ -45,80 +45,75 @@ void make_tree(MMVManip &vmanip, v3s16 p0, 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; + for (s16 ii = 0; ii < trunk_h; ii++) { + if (vmanip.m_area.contains(p1)) { + u32 vi = vmanip.m_area.index(p1); + vmanip.m_data[vi] = 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)); + 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++) + 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; - } + 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; - + for (u32 iii = 0; iii < 7; iii++) { 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) + 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; + 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; + 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++) { + v3s16 pmin(leaves_a.MinEdge.X, y, z); + u32 i = leaves_a.index(pmin); + u32 vi = vmanip.m_area.index(pmin + p1); + for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { + v3s16 p(x, y, z); + if (vmanip.m_area.contains(p + p1) == true && + (vmanip.m_data[vi].getContent() == CONTENT_AIR || + vmanip.m_data[vi].getContent() == CONTENT_IGNORE)) { + 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; + } } + vi++; + i++; } } } + // L-System tree LUA spawner -treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition) +treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, + INodeDefManager *ndef, TreeDef tree_definition) { ServerMap *map = &env->getServerMap(); std::map<v3s16, MapBlock*> modified_blocks; @@ -126,8 +121,8 @@ treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *nd 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); + 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; @@ -140,30 +135,25 @@ treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *nd // 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) - { + 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(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, - TreeDef tree_definition) +treegen::error make_ltree(MMVManip &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; - } + seed = tree_definition.seed + 14002; else - { - seed = p0.X*2 + p0.Y*4 + p0.Z; // use the tree position to seed PRNG - } + seed = p0.X * 2 + p0.Y * 4 + p0.Z; // use the tree position to seed PRNG PseudoRandom ps(seed); // chance of inserting abcd rules @@ -174,18 +164,18 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, //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; + 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; + 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)); + rotation = setRotationAxisRadians(rotation, M_PI / 2, v3f(0, 0, 1)); v3f position; position.X = p0.X; position.Y = p0.Y; @@ -195,63 +185,85 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, //generate axiom std::string axiom = tree_definition.initial_axiom; - for(s16 i=0; i<iterations; i++) - { + for (s16 i = 0; i < iterations; i++) { std::string temp = ""; - for(s16 j=0; j<(s16)axiom.size(); j++) - { + for (s16 j = 0; j < (s16)axiom.size(); j++) { char axiom_char = axiom.at(j); - switch (axiom_char) - { + switch (axiom_char) { case 'A': - temp+=tree_definition.rules_a; + temp += tree_definition.rules_a; break; case 'B': - temp+=tree_definition.rules_b; + temp += tree_definition.rules_b; break; case 'C': - temp+=tree_definition.rules_c; + temp += tree_definition.rules_c; break; case 'D': - temp+=tree_definition.rules_d; + temp += tree_definition.rules_d; break; case 'a': - if (prop_a >= ps.range(1,10)) - temp+=tree_definition.rules_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; + 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; + 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; + if (prop_d >= ps.range(1, 10)) + temp += tree_definition.rules_d; break; default: - temp+=axiom_char; + temp += axiom_char; break; } } - axiom=temp; + 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); + 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 @@ -283,84 +295,179 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, */ s16 x,y,z; - for(s16 i=0; i<(s16)axiom.size(); i++) - { + 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) - { + switch (axiom_char) { case 'G': - dir = v3f(1,0,0); - dir = transposeMatrix(rotation,dir); - position+=dir; + 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); + 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; + 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) - { + 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); - } + 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; + 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; + 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; + 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 @@ -371,40 +478,46 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, case ']': if (stack_orientation.empty()) return UNBALANCED_BRACKETS; - rotation=stack_orientation.top(); + rotation = stack_orientation.top(); stack_orientation.pop(); - position=stack_position.top(); + 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; + 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; + 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; + 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; + 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; + 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; + temp_rotation = setRotationAxisRadians(temp_rotation, + angle_in_radians, v3f(-1, 0, 0)); + rotation *= temp_rotation; break; default: break; @@ -414,85 +527,87 @@ treegen::error make_ltree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, return SUCCESS; } -void tree_node_placement(MMVManip &vmanip, v3f p0, - MapNode node) + +void tree_node_placement(MMVManip &vmanip, v3f p0, MapNode node) { - v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z)); - if(vmanip.m_area.contains(p1) == false) + 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 + 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(MMVManip &vmanip, v3f p0, - TreeDef &tree_definition) + +void tree_trunk_placement(MMVManip &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) + 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 + 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(MMVManip &vmanip, v3f p0, - PseudoRandom ps ,TreeDef &tree_definition) + 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) + 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 + 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) + 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) + } else if (ps.range(1, 100) > 20) { vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; + } } + void tree_single_leaves_placement(MMVManip &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) + 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) + 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(MMVManip &vmanip, v3f p0, - TreeDef &tree_definition) + +void tree_fruit_placement(MMVManip &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) + 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) + 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); @@ -520,20 +635,21 @@ irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3 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; + translated.X = x; + translated.Y = y; + translated.Z = z; return translated; } -void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, - INodeDefManager *ndef, int seed) + +void make_jungletree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, int seed) { /* NOTE: Tree-placing code is currently duplicated in the engine @@ -551,18 +667,17 @@ void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, 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) + 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); + 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].getContent() == CONTENT_AIR) vmanip.m_data[vi2] = treenode; else if (vmanip.m_area.contains(p1) && vmanip.m_data[vi1].getContent() == CONTENT_AIR) @@ -572,12 +687,10 @@ void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, s16 trunk_h = pr.range(8, 12); v3s16 p1 = p0; - for (s16 ii=0; ii<trunk_h; ii++) - { + 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; + vmanip.m_data[vi] = treenode; } p1.Y++; } @@ -585,58 +698,171 @@ void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, // p1 is now the last piece of the trunk p1.Y -= 1; - VoxelArea leaves_a(v3s16(-3,-2,-3), v3s16(3,2,3)); + 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++) + 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; - } + 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; - + for (u32 iii = 0; iii < 30; iii++) { 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) + 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; + 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; + 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++) { + v3s16 pmin(leaves_a.MinEdge.X, y, z); + u32 i = leaves_a.index(pmin); + u32 vi = vmanip.m_area.index(pmin + p1); + for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { + v3s16 p(x, y, z); + if (vmanip.m_area.contains(p + p1) == true && + (vmanip.m_data[vi].getContent() == CONTENT_AIR || + vmanip.m_data[vi].getContent() == CONTENT_IGNORE)) { + if (leaves_d[i] == 1) + vmanip.m_data[vi] = leavesnode; + } + vi++; + i++; + } + } +} + + +void make_pine_tree(MMVManip &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 + */ + MapNode treenode(ndef->getId("mapgen_pinetree")); + MapNode leavesnode(ndef->getId("mapgen_pine_needles")); + MapNode snownode(ndef->getId("mapgen_snow")); + + PseudoRandom pr(seed); + s16 trunk_h = pr.range(9, 13); + v3s16 p1 = p0; + for (s16 ii = 0; ii < trunk_h; ii++) { + if (vmanip.m_area.contains(p1)) { + u32 vi = vmanip.m_area.index(p1); + vmanip.m_data[vi] = treenode; + } + p1.Y++; + } + + // Make p1 the top node of the trunk + p1.Y -= 1; + + VoxelArea leaves_a(v3s16(-3, -6, -3), v3s16(3, 3, 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; + + // Upper branches + s16 dev = 3; + for (s16 yy = -1; yy <= 1; yy++) { + for (s16 zz = -dev; zz <= dev; zz++) { + u32 i = leaves_a.index(v3s16(-dev, yy, zz)); + u32 ia = leaves_a.index(v3s16(-dev, yy+1, zz)); + for (s16 xx = -dev; xx <= dev; xx++) { + if (pr.range(0, 20) <= 19 - dev) { + leaves_d[i] = 1; + leaves_d[ia] = 2; + } + i++; + ia++; + } + } + dev--; + } + + // Centre top nodes + u32 i = leaves_a.index(v3s16(0, 1, 0)); + leaves_d[i] = 1; + i = leaves_a.index(v3s16(0, 2, 0)); + leaves_d[i] = 1; + i = leaves_a.index(v3s16(0, 3, 0)); + leaves_d[i] = 2; + + // Lower branches + s16 my = -6; + for (u32 iii = 0; iii < 20; iii++) { + s16 xi = pr.range(-3, 2); + s16 yy = pr.range(-6, -5); + s16 zi = pr.range(-3, 2); + if (yy > my) + my = yy; + for (s16 zz = zi; zz <= zi + 1; zz++) { + u32 i = leaves_a.index(v3s16(xi, yy, zz)); + u32 ia = leaves_a.index(v3s16(xi, yy + 1, zz)); + for (s16 xx = xi; xx <= xi + 1; xx++) { + leaves_d[i] = 1; + if (leaves_d[ia] == 0) + leaves_d[ia] = 2; + i++; + ia++; + } + } + } + + dev = 2; + for (s16 yy = my + 1; yy <= my + 2; yy++) { + for (s16 zz = -dev; zz <= dev; zz++) { + u32 i = leaves_a.index(v3s16(-dev, yy, zz)); + u32 ia = leaves_a.index(v3s16(-dev, yy + 1, zz)); + for (s16 xx = -dev; xx <= dev; xx++) { + if (pr.range(0, 20) <= 19 - dev) { + leaves_d[i] = 1; + leaves_d[ia] = 2; + } + i++; + ia++; + } + } + dev--; + } + + // 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++) { + v3s16 pmin(leaves_a.MinEdge.X, y, z); + u32 i = leaves_a.index(pmin); + u32 vi = vmanip.m_area.index(pmin + p1); + for (s16 x = leaves_a.MinEdge.X; x <= leaves_a.MaxEdge.X; x++) { + v3s16 p(x, y, z); + if (vmanip.m_area.contains(p + p1) == true && + (vmanip.m_data[vi].getContent() == CONTENT_AIR || + vmanip.m_data[vi].getContent() == CONTENT_IGNORE || + vmanip.m_data[vi] == snownode)) { + if (leaves_d[i] == 1) + vmanip.m_data[vi] = leavesnode; + else if (leaves_d[i] == 2) + vmanip.m_data[vi] = snownode; + } + vi++; + i++; + } } } diff --git a/src/treegen.h b/src/treegen.h index febbc29ee..4b0089d1e 100644 --- a/src/treegen.h +++ b/src/treegen.h @@ -62,7 +62,10 @@ namespace treegen { void make_tree(MMVManip &vmanip, v3s16 p0, bool is_apple_tree, INodeDefManager *ndef, int seed); // Add jungle tree - void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, + void make_jungletree(MMVManip &vmanip, v3s16 p0, + INodeDefManager *ndef, int seed); + // Add pine tree + void make_pine_tree(MMVManip &vmanip, v3s16 p0, INodeDefManager *ndef, int seed); // Add L-Systems tree (used by engine) |