2 #include "server/biomes.h"
3 #include "server/server_terrain.h"
4 #include "server/trees.h"
5 #include "server/voxel_procedural.h"
9 static bool oak_condition(TreeArgsCondition *args)
11 return args->biome == BIOME_HILLS;
14 static void oak_tree_leaf(VoxelProcedural *proc)
16 if (!voxel_procedural_is_alive(proc))
19 voxel_procedural_push(proc);
20 voxel_procedural_cube(proc, NODE_OAK_LEAVES, true);
21 voxel_procedural_pop(proc);
23 voxel_procedural_push(proc);
24 voxel_procedural_x(proc, 0.5f);
25 voxel_procedural_sx(proc, 0.9f);
26 voxel_procedural_sy(proc, 0.9f);
27 voxel_procedural_sz(proc, 0.8f);
28 voxel_procedural_ry(proc, 25.0f);
29 voxel_procedural_x(proc, 0.4f);
31 voxel_procedural_pop(proc);
34 static void oak_tree_top(VoxelProcedural *proc)
36 if (!voxel_procedural_is_alive(proc))
39 voxel_procedural_push(proc);
40 for (int i = 0; i < 8; i++) {
41 voxel_procedural_rz(proc, 360.0f / 8.0f);
42 voxel_procedural_push(proc);
43 voxel_procedural_life(proc, 8);
44 voxel_procedural_sy(proc, 2.0f);
45 voxel_procedural_z(proc, voxel_procedural_random(proc, 0.0f, 5.0f));
46 voxel_procedural_s(proc, 5.0f);
47 voxel_procedural_light(proc, -0.4f);
48 voxel_procedural_sat(proc, 0.5f);
49 voxel_procedural_hue(proc, voxel_procedural_random(proc, 60.0f, 20.0f));
50 voxel_procedural_ry(proc, -45.0f);
52 voxel_procedural_pop(proc);
54 voxel_procedural_pop(proc);
57 static void oak_tree_part(VoxelProcedural *proc, f32 n)
59 if (!voxel_procedural_is_alive(proc))
62 voxel_procedural_push(proc);
63 for (int i = 1; i <= n; i++) {
64 voxel_procedural_z(proc, 1.0f);
65 voxel_procedural_rz(proc, voxel_procedural_random(proc, 30.0f, 10.0f));
66 voxel_procedural_rx(proc, voxel_procedural_random(proc, 0.0f, 10.0f));
68 voxel_procedural_push(proc);
69 voxel_procedural_s(proc, 4.0f);
70 voxel_procedural_x(proc, 0.1f);
71 voxel_procedural_light(proc, voxel_procedural_random(proc, 0.0f, 0.1f));
72 voxel_procedural_cylinder(proc, NODE_OAK_WOOD, true);
73 voxel_procedural_pop(proc);
75 if (i == (int) (n - 2.0f)) {
76 voxel_procedural_push(proc);
78 voxel_procedural_pop(proc);
81 voxel_procedural_pop(proc);
84 static void oak_tree(v3s32 pos, List *changed_chunks)
86 VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, pos);
88 voxel_procedural_hue(proc, 40.0f);
89 voxel_procedural_light(proc, -0.5f);
90 voxel_procedural_sat(proc, 0.5f);
92 f32 n = voxel_procedural_random(proc, 40.0f, 10.0f);
94 voxel_procedural_push(proc);
95 for (int i = 1; i <= 3; i++) {
96 voxel_procedural_rz(proc, voxel_procedural_random(proc, 120.0f, 45.0f));
97 voxel_procedural_push(proc);
98 voxel_procedural_y(proc, 0.5f);
99 voxel_procedural_light(proc, voxel_procedural_random(proc, -0.3f, 0.05f));
100 oak_tree_part(proc, n);
101 voxel_procedural_pop(proc);
103 voxel_procedural_pop(proc);
105 voxel_procedural_delete(proc);
110 static bool pine_condition(TreeArgsCondition *args)
112 return args->biome == BIOME_MOUNTAIN;
115 static void pine_tree(v3s32 pos, List *changed_chunks)
117 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;
118 for (v3s32 tree_pos = pos; tree_pos.y < tree_top; tree_pos.y++) {
119 f64 branch_length = noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + OFFSET_PINETREE_BRANCH) * 3.0;
128 s32 dir = (noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + OFFSET_PINETREE_BRANCH_DIR) * 0.5 + 0.5) * 4.0;
130 for (v3s32 branch_pos = tree_pos; branch_length > 0; branch_length--, branch_pos = v3s32_add(branch_pos, dirs[dir]))
131 server_terrain_gen_node(branch_pos,
132 terrain_node_create(NODE_PINE_WOOD, (Blob) {0, NULL}),
133 STAGE_TREES, changed_chunks);
135 server_terrain_gen_node(tree_pos,
136 terrain_node_create(NODE_PINE_WOOD, (Blob) {0, NULL}),
137 STAGE_TREES, changed_chunks);
143 static bool palm_condition(TreeArgsCondition *args)
145 return args->biome == BIOME_OCEAN
146 && ocean_get_node_at((v3s32) {args->pos.x, args->pos.y - 0, args->pos.z}, 1, args->row_data) == NODE_AIR
147 && ocean_get_node_at((v3s32) {args->pos.x, args->pos.y - 1, args->pos.z}, 0, args->row_data) == NODE_SAND;
150 static void palm_branch(VoxelProcedural *proc)
152 if (!voxel_procedural_is_alive(proc))
155 voxel_procedural_cube(proc, NODE_PALM_LEAVES, true);
156 voxel_procedural_push(proc);
157 voxel_procedural_z(proc, 0.5f);
158 voxel_procedural_s(proc, 0.8f);
159 voxel_procedural_rx(proc, voxel_procedural_random(proc, 20.0f, 4.0f));
160 voxel_procedural_z(proc, 0.5f);
162 voxel_procedural_pop(proc);
165 static void palm_tree(v3s32 pos, List *changed_chunks)
167 VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, (v3s32) {pos.x, pos.y - 1, pos.z});
169 f32 s = voxel_procedural_random(proc, 8.0f, 2.0f);
171 voxel_procedural_push(proc);
172 for (int i = 1; i <= s; i++) {
173 voxel_procedural_z(proc, 1.0f);
174 voxel_procedural_push(proc);
175 voxel_procedural_s(proc, 1.0f);
176 voxel_procedural_light(proc, voxel_procedural_random(proc, -0.8f, 0.1f));
177 voxel_procedural_sat(proc, 0.5f);
178 voxel_procedural_cube(proc, NODE_PALM_WOOD, true);
179 voxel_procedural_pop(proc);
181 voxel_procedural_pop(proc);
183 voxel_procedural_z(proc, s);
184 voxel_procedural_sat(proc, 1.0f),
185 voxel_procedural_light(proc, -0.5f);
186 voxel_procedural_hue(proc, voxel_procedural_random(proc, 50.0f, 30.0f));
188 voxel_procedural_push(proc);
189 for (int i = 0; i < 6; i++) {
190 voxel_procedural_rz(proc, 360.0f / 6.0f);
191 voxel_procedural_rz(proc, voxel_procedural_random(proc, 0.0f, 10.0f));
192 voxel_procedural_push(proc);
193 voxel_procedural_light(proc, voxel_procedural_random(proc, 0.0f, 0.3f));
194 voxel_procedural_rx(proc, 90.0f);
195 voxel_procedural_s(proc, 2.0f);
197 voxel_procedural_pop(proc);
199 voxel_procedural_pop(proc);
201 voxel_procedural_delete(proc);
204 TreeDef tree_defs[NUM_TREES] = {
208 .probability = 0.0005f,
209 .area_probability = 0.3f,
210 .offset = OFFSET_OAKTREE,
211 .area_offset = OFFSET_OAKTREE_AREA,
212 .condition = &oak_condition,
213 .generate = &oak_tree,
218 .probability = 0.01f,
219 .area_probability = 0.1f,
220 .offset = OFFSET_PINETREE,
221 .area_offset = OFFSET_PINETREE_AREA,
222 .condition = &pine_condition,
223 .generate = &pine_tree,
228 .probability = 0.005f,
229 .area_probability = 0.5f,
230 .offset = OFFSET_PALMTREE,
231 .area_offset = OFFSET_PALMTREE_AREA,
232 .condition = &palm_condition,
233 .generate = &palm_tree,