]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/server/trees.c
Add items
[dragonblocks_alpha.git] / src / server / trees.c
1 #include <stdlib.h>
2 #include "server/biomes.h"
3 #include "server/server_terrain.h"
4 #include "server/trees.h"
5 #include "server/voxel_procedural.h"
6
7 // oak
8
9 static bool oak_condition(TreeArgsCondition *args)
10 {
11         return args->biome == BIOME_HILLS;
12 }
13
14 static void oak_tree_leaf(VoxelProcedural *proc)
15 {
16         if (!voxel_procedural_is_alive(proc))
17                 return;
18
19         voxel_procedural_push(proc);
20                 voxel_procedural_cube(proc, NODE_OAK_LEAVES, true);
21         voxel_procedural_pop(proc);
22
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);
30                 oak_tree_leaf(proc);
31         voxel_procedural_pop(proc);
32 }
33
34 static void oak_tree_top(VoxelProcedural *proc)
35 {
36         if (!voxel_procedural_is_alive(proc))
37                 return;
38
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);
51                         oak_tree_leaf(proc);
52                 voxel_procedural_pop(proc);
53         }
54         voxel_procedural_pop(proc);
55 }
56
57 static void oak_tree_part(VoxelProcedural *proc, f32 n)
58 {
59         if (!voxel_procedural_is_alive(proc))
60                 return;
61
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));
67
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);
74
75                 if (i == (int) (n - 2.0f)) {
76                         voxel_procedural_push(proc);
77                                 oak_tree_top(proc);
78                         voxel_procedural_pop(proc);
79                 }
80         }
81         voxel_procedural_pop(proc);
82 }
83
84 static void oak_tree(v3s32 pos, List *changed_chunks)
85 {
86         VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, pos);
87
88         voxel_procedural_hue(proc, 40.0f);
89         voxel_procedural_light(proc, -0.5f);
90         voxel_procedural_sat(proc, 0.5f);
91
92         f32 n = voxel_procedural_random(proc, 40.0f, 10.0f);
93
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);
102         }
103         voxel_procedural_pop(proc);
104
105         voxel_procedural_delete(proc);
106 }
107
108 // pine
109
110 static bool pine_condition(TreeArgsCondition *args)
111 {
112         return args->biome == BIOME_MOUNTAIN;
113 }
114
115 static void pine_tree(v3s32 pos, List *changed_chunks)
116 {
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;
120
121                 v3s32 dirs[4] = {
122                         {+0, +0, +1},
123                         {+1, +0, +0},
124                         {+0, +0, -1},
125                         {-1, +0, +0},
126                 };
127
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;
129
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);
134
135                 server_terrain_gen_node(tree_pos,
136                         terrain_node_create(NODE_PINE_WOOD, (Blob) {0, NULL}),
137                         STAGE_TREES, changed_chunks);
138         }
139 }
140
141 // palm
142
143 static bool palm_condition(TreeArgsCondition *args)
144 {
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;
148 }
149
150 static void palm_branch(VoxelProcedural *proc)
151 {
152         if (!voxel_procedural_is_alive(proc))
153                 return;
154
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);
161                 palm_branch(proc);
162         voxel_procedural_pop(proc);
163 }
164
165 static void palm_tree(v3s32 pos, List *changed_chunks)
166 {
167         VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, (v3s32) {pos.x, pos.y - 1, pos.z});
168
169         f32 s = voxel_procedural_random(proc, 8.0f, 2.0f);
170
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);
180         }
181         voxel_procedural_pop(proc);
182
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));
187
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);
196                         palm_branch(proc);
197                 voxel_procedural_pop(proc);
198         }
199         voxel_procedural_pop(proc);
200
201         voxel_procedural_delete(proc);
202 }
203
204 TreeDef tree_defs[NUM_TREES] = {
205         // oak
206         {
207                 .spread = 64.0f,
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,
214         },
215         // pine
216         {
217                 .spread = 256.0f,
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,
224         },
225         // palm
226         {
227                 .spread = 16.0f,
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,
234         },
235 };
236