2 #include "server/biomes.h"
3 #include "server/server_node.h"
4 #include "server/server_terrain.h"
5 #include "server/tree.h"
6 #include "server/voxel_procedural.h"
13 static TerrainNode create_tree_node(__attribute__((unused)) v3s32 pos, v3f32 color, ProceduralTreeArg *arg)
15 return server_node_create_tree(arg->type, (TreeData) {
24 static bool oak_condition(TreeArgsCondition *args)
26 return args->biome == BIOME_HILLS;
29 static void oak_tree_leaf(VoxelProcedural *proc, v3s32 root)
31 if (!voxel_procedural_is_alive(proc))
34 voxel_procedural_push(proc);
35 voxel_procedural_cube(proc, (void *) &create_tree_node,
36 &(ProceduralTreeArg) {NODE_OAK_LEAVES, root});
37 voxel_procedural_pop(proc);
39 voxel_procedural_push(proc);
40 voxel_procedural_x(proc, 0.5f);
41 voxel_procedural_sx(proc, 0.9f);
42 voxel_procedural_sy(proc, 0.9f);
43 voxel_procedural_sz(proc, 0.8f);
44 voxel_procedural_ry(proc, 25.0f);
45 voxel_procedural_x(proc, 0.4f);
46 oak_tree_leaf(proc, root);
47 voxel_procedural_pop(proc);
50 static void oak_tree_top(VoxelProcedural *proc, v3s32 root)
52 if (!voxel_procedural_is_alive(proc))
55 voxel_procedural_push(proc);
56 for (int i = 0; i < 8; i++) {
57 voxel_procedural_rz(proc, 360.0f / 8.0f);
58 voxel_procedural_push(proc);
59 voxel_procedural_life(proc, 8);
60 voxel_procedural_sy(proc, 2.0f);
61 voxel_procedural_z(proc, voxel_procedural_random(proc, 0.0f, 5.0f));
62 voxel_procedural_s(proc, 5.0f);
63 voxel_procedural_light(proc, -0.4f);
64 voxel_procedural_sat(proc, 0.5f);
65 voxel_procedural_hue(proc, voxel_procedural_random(proc, 60.0f, 20.0f));
66 voxel_procedural_ry(proc, -45.0f);
67 oak_tree_leaf(proc, root);
68 voxel_procedural_pop(proc);
70 voxel_procedural_pop(proc);
73 static void oak_tree_part(VoxelProcedural *proc, v3s32 root, f32 n)
75 if (!voxel_procedural_is_alive(proc))
78 voxel_procedural_push(proc);
79 for (int i = 1; i <= n; i++) {
80 voxel_procedural_z(proc, 1.0f);
81 voxel_procedural_rz(proc, voxel_procedural_random(proc, 30.0f, 10.0f));
82 voxel_procedural_rx(proc, voxel_procedural_random(proc, 0.0f, 10.0f));
84 voxel_procedural_push(proc);
85 voxel_procedural_s(proc, 4.0f);
86 voxel_procedural_x(proc, 0.1f);
87 voxel_procedural_light(proc, voxel_procedural_random(proc, 0.0f, 0.1f));
88 voxel_procedural_cylinder(proc, (void *) &create_tree_node,
89 &(ProceduralTreeArg) {NODE_OAK_WOOD, root});
90 voxel_procedural_pop(proc);
92 if (i == (int) (n - 2.0f)) {
93 voxel_procedural_push(proc);
94 oak_tree_top(proc, root);
95 voxel_procedural_pop(proc);
98 voxel_procedural_pop(proc);
101 static void oak_tree(v3s32 root, List *changed_chunks)
103 VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, root);
105 voxel_procedural_hue(proc, 40.0f);
106 voxel_procedural_light(proc, -0.5f);
107 voxel_procedural_sat(proc, 0.5f);
109 f32 n = voxel_procedural_random(proc, 40.0f, 10.0f);
111 voxel_procedural_push(proc);
112 for (int i = 1; i <= 3; i++) {
113 voxel_procedural_rz(proc, voxel_procedural_random(proc, 120.0f, 45.0f));
114 voxel_procedural_push(proc);
115 voxel_procedural_y(proc, 0.5f);
116 voxel_procedural_light(proc, voxel_procedural_random(proc, -0.3f, 0.05f));
117 oak_tree_part(proc, root, n);
118 voxel_procedural_pop(proc);
120 voxel_procedural_pop(proc);
122 voxel_procedural_delete(proc);
127 static bool pine_condition(TreeArgsCondition *args)
129 return args->biome == BIOME_MOUNTAIN;
132 static void pine_tree(v3s32 pos, List *changed_chunks)
134 s32 tree_top = (noise2d(pos.x, pos.z, 0, seed + OFFSET_PINETREE_HEIGHT) * 0.5 + 0.5) * (35.0 - 20.0) + 20.0 + pos.y;
135 for (v3s32 tree_pos = pos; tree_pos.y < tree_top; tree_pos.y++) {
136 f64 branch_length = noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + OFFSET_PINETREE_BRANCH) * 3.0;
145 s32 dir = (noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + OFFSET_PINETREE_BRANCH_DIR) * 0.5 + 0.5) * 4.0;
147 for (v3s32 branch_pos = tree_pos; branch_length > 0; branch_length--, branch_pos = v3s32_add(branch_pos, dirs[dir]))
148 server_terrain_gen_node(branch_pos, server_node_create(NODE_PINE_WOOD),
149 STAGE_TREES, changed_chunks);
151 server_terrain_gen_node(tree_pos, server_node_create(NODE_PINE_WOOD),
152 STAGE_TREES, changed_chunks);
158 static bool palm_condition(TreeArgsCondition *args)
160 return args->biome == BIOME_OCEAN
161 && ocean_get_node_at((v3s32) {args->pos.x, args->pos.y - 0, args->pos.z}, 1, args->row_data) == NODE_AIR
162 && ocean_get_node_at((v3s32) {args->pos.x, args->pos.y - 1, args->pos.z}, 0, args->row_data) == NODE_SAND;
165 static void palm_branch(VoxelProcedural *proc, v3s32 root)
167 if (!voxel_procedural_is_alive(proc))
170 voxel_procedural_cube(proc, (void *) &create_tree_node,
171 &(ProceduralTreeArg) {NODE_PALM_LEAVES, root});
173 voxel_procedural_push(proc);
174 voxel_procedural_z(proc, 0.5f);
175 voxel_procedural_s(proc, 0.8f);
176 voxel_procedural_rx(proc, voxel_procedural_random(proc, 20.0f, 4.0f));
177 voxel_procedural_z(proc, 0.5f);
178 palm_branch(proc, root);
179 voxel_procedural_pop(proc);
182 static void palm_tree(v3s32 root, List *changed_chunks)
184 VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, (v3s32) {root.x, root.y - 1, root.z});
186 f32 s = voxel_procedural_random(proc, 8.0f, 2.0f);
188 voxel_procedural_push(proc);
189 for (int i = 1; i <= s; i++) {
190 voxel_procedural_z(proc, 1.0f);
191 voxel_procedural_push(proc);
192 voxel_procedural_s(proc, 1.0f);
193 voxel_procedural_light(proc, voxel_procedural_random(proc, -0.8f, 0.1f));
194 voxel_procedural_sat(proc, 0.5f);
195 voxel_procedural_cube(proc, (void *) &create_tree_node,
196 &(ProceduralTreeArg) {NODE_PALM_WOOD, root});
197 voxel_procedural_pop(proc);
199 voxel_procedural_pop(proc);
201 voxel_procedural_z(proc, s);
202 voxel_procedural_sat(proc, 1.0f),
203 voxel_procedural_light(proc, -0.5f);
204 voxel_procedural_hue(proc, voxel_procedural_random(proc, 50.0f, 30.0f));
206 voxel_procedural_push(proc);
207 for (int i = 0; i < 6; i++) {
208 voxel_procedural_rz(proc, 360.0f / 6.0f);
209 voxel_procedural_rz(proc, voxel_procedural_random(proc, 0.0f, 10.0f));
210 voxel_procedural_push(proc);
211 voxel_procedural_light(proc, voxel_procedural_random(proc, 0.0f, 0.3f));
212 voxel_procedural_rx(proc, 90.0f);
213 voxel_procedural_s(proc, 2.0f);
214 palm_branch(proc, root);
215 voxel_procedural_pop(proc);
217 voxel_procedural_pop(proc);
219 voxel_procedural_delete(proc);
222 TreeDef tree_def[NUM_TREES] = {
226 .probability = 0.0005f,
227 .area_probability = 0.3f,
228 .offset = OFFSET_OAKTREE,
229 .area_offset = OFFSET_OAKTREE_AREA,
230 .condition = &oak_condition,
231 .generate = &oak_tree,
236 .probability = 0.01f,
237 .area_probability = 0.1f,
238 .offset = OFFSET_PINETREE,
239 .area_offset = OFFSET_PINETREE_AREA,
240 .condition = &pine_condition,
241 .generate = &pine_tree,
246 .probability = 0.005f,
247 .area_probability = 0.5f,
248 .offset = OFFSET_PALMTREE,
249 .area_offset = OFFSET_PALMTREE_AREA,
250 .condition = &palm_condition,
251 .generate = &palm_tree,