]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/server/trees.c
Add trees
[dragonblocks_alpha.git] / src / server / trees.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "server/biomes.h"
4 #include "server/mapgen.h"
5 #include "server/trees.h"
6 #include "server/voxelctx.h"
7 #include "util.h"
8
9 // oak
10
11 static bool oak_condition(unused v3s32 pos, unused f64 humidity, unused f64 temperature, Biome biome, unused f64 factor, unused MapBlock *block, unused void *row_data, unused void *block_data)
12 {
13         return biome == BIOME_HILLS;
14 }
15
16 static void oak_tree_leaf(Voxelctx *ctx)
17 {
18         if (! voxelctx_is_alive(ctx))
19                 return;
20
21         voxelctx_push(ctx);
22                 voxelctx_cube(ctx, NODE_OAK_LEAVES, true);
23         voxelctx_pop(ctx);
24
25         voxelctx_push(ctx);
26                 voxelctx_x(ctx, 0.5f);
27                 voxelctx_sx(ctx, 0.9f);
28                 voxelctx_sy(ctx, 0.9f);
29                 voxelctx_sz(ctx, 0.8f);
30                 voxelctx_ry(ctx, 25.0f);
31                 voxelctx_x(ctx, 0.4f);
32                 oak_tree_leaf(ctx);
33         voxelctx_pop(ctx);
34 }
35
36 static void oak_tree_top(Voxelctx *ctx)
37 {
38         if (! voxelctx_is_alive(ctx))
39                 return;
40
41         voxelctx_push(ctx);
42         for (int i = 0; i < 8; i++) {
43                 voxelctx_rz(ctx, 360.0f / 8.0f);
44                 voxelctx_push(ctx);
45                         voxelctx_life(ctx, 8);
46                         voxelctx_sy(ctx, 2.0f);
47                         voxelctx_z(ctx, voxelctx_random(ctx, 0.0f, 5.0f));
48                         voxelctx_s(ctx, 5.0f);
49                         voxelctx_light(ctx, -0.4f);
50                         voxelctx_sat(ctx, 0.5f);
51                         voxelctx_hue(ctx, voxelctx_random(ctx, 60.0f, 20.0f));
52                         voxelctx_ry(ctx, -45.0f);
53                         oak_tree_leaf(ctx);
54                 voxelctx_pop(ctx);
55         }
56         voxelctx_pop(ctx);
57 }
58
59 static void oak_tree_part(Voxelctx *ctx, f32 n)
60 {
61         if (! voxelctx_is_alive(ctx))
62                 return;
63
64         voxelctx_push(ctx);
65         for (int i = 1; i <= n; i++) {
66                 voxelctx_z(ctx, 1.0f);
67                 voxelctx_rz(ctx, voxelctx_random(ctx, 30.0f, 10.0f));
68                 voxelctx_rx(ctx, voxelctx_random(ctx, 0.0f, 10.0f));
69
70                 voxelctx_push(ctx);
71                         voxelctx_s(ctx, 4.0f);
72                         voxelctx_x(ctx, 0.1f);
73                         voxelctx_light(ctx, voxelctx_random(ctx, 0.0f, 0.1f));
74                         //voxelctx_cylinder(ctx, NODE_OAK_WOOD, true);
75                         voxelctx_cube(ctx, NODE_OAK_WOOD, true);
76                 voxelctx_pop(ctx);
77
78                 if (i == (int) (n - 2.0f)) {
79                         voxelctx_push(ctx);
80                                 oak_tree_top(ctx);
81                         voxelctx_pop(ctx);
82                 }
83         }
84         voxelctx_pop(ctx);
85 }
86
87 static void oak_tree(v3s32 pos, List *changed_blocks)
88 {
89         Voxelctx *ctx = voxelctx_create(changed_blocks, MGS_TREES, pos);
90
91         voxelctx_hue(ctx, 40.0f);
92         voxelctx_light(ctx, -0.5f);
93         voxelctx_sat(ctx, 0.5f);
94
95         /*voxelctx_s(ctx, 50);
96         voxelctx_ry(ctx, 45);
97
98         voxelctx_push(ctx);
99                 voxelctx_cube(ctx, NODE_OAK_LEAVES, true);
100         voxelctx_pop(ctx);
101
102         voxelctx_delete(ctx);
103         if (true)
104                 return;*/
105
106         f32 n = voxelctx_random(ctx, 40.0f, 10.0f);
107
108         voxelctx_push(ctx);
109         for (int i = 1; i <= 3; i++) {
110                 voxelctx_rz(ctx, voxelctx_random(ctx, 120.0f, 45.0f));
111                 voxelctx_push(ctx);
112                         voxelctx_y(ctx, 0.5f);
113                         voxelctx_light(ctx, voxelctx_random(ctx, -0.3f, 0.05f));
114                         oak_tree_part(ctx, n);
115                 voxelctx_pop(ctx);
116         }
117         voxelctx_pop(ctx);
118
119         voxelctx_delete(ctx);
120 }
121
122 // pine
123
124 static bool pine_condition(unused v3s32 pos, unused f64 humidity, unused f64 temperature, Biome biome, unused f64 factor, unused MapBlock *block, unused void *row_data, unused void *block_data)
125 {
126         return biome == BIOME_MOUNTAIN;
127 }
128
129 static void pine_tree(v3s32 pos, List *changed_blocks)
130 {
131         s32 tree_top = (noise2d(pos.x, pos.z, 0, seed + SO_PINETREE_HEIGHT) * 0.5 + 0.5) * (35.0 - 20.0) + 20.0 + pos.y;
132         for (v3s32 tree_pos = pos; tree_pos.y < tree_top; tree_pos.y++) {
133                 f64 branch_length = noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + SO_PINETREE_BRANCH) * 3.0;
134
135                 v3s32 dirs[4] = {
136                         {+0, +0, +1},
137                         {+1, +0, +0},
138                         {+0, +0, -1},
139                         {-1, +0, +0},
140                 };
141
142                 s32 dir = (noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + SO_PINETREE_BRANCH_DIR) * 0.5 + 0.5) * 4.0;
143
144                 for (v3s32 branch_pos = tree_pos; branch_length > 0; branch_length--, branch_pos = v3s32_add(branch_pos, dirs[dir]))
145                         mapgen_set_node(branch_pos, map_node_create(NODE_PINE_WOOD, NULL, 0), MGS_TREES, changed_blocks);
146
147                 mapgen_set_node(tree_pos, map_node_create(NODE_PINE_WOOD, NULL, 0), MGS_TREES, changed_blocks);
148         }
149 }
150
151 // palm
152
153 static bool palm_condition(v3s32 pos, unused f64 humidity, unused f64 temperature, Biome biome, unused f64 factor, unused MapBlock *block, void *row_data, unused void *block_data)
154 {
155         return biome == BIOME_OCEAN
156                 && ocean_get_node_at((v3s32) {pos.x, pos.y - 0, pos.z}, 1, row_data) == NODE_AIR
157                 && ocean_get_node_at((v3s32) {pos.x, pos.y - 1, pos.z}, 0, row_data) == NODE_SAND;
158 }
159
160 static void palm_branch(Voxelctx *ctx)
161 {
162         if (! voxelctx_is_alive(ctx))
163                 return;
164
165         voxelctx_cube(ctx, NODE_PALM_LEAVES, true);
166         voxelctx_push(ctx);
167                 voxelctx_z(ctx, 0.5f);
168                 voxelctx_s(ctx, 0.8f);
169                 voxelctx_rx(ctx, voxelctx_random(ctx, 20.0f, 4.0f));
170                 voxelctx_z(ctx, 0.5f);
171                 palm_branch(ctx);
172         voxelctx_pop(ctx);
173 }
174
175 static void palm_tree(v3s32 pos, List *changed_blocks)
176 {
177         Voxelctx *ctx = voxelctx_create(changed_blocks, MGS_TREES, (v3s32) {pos.x, pos.y - 1, pos.z});
178
179         f32 s = voxelctx_random(ctx, 8.0f, 2.0f);
180
181         voxelctx_push(ctx);
182         for (int i = 1; i <= s; i++) {
183                 voxelctx_z(ctx, 1.0f);
184                 voxelctx_push(ctx);
185                         voxelctx_s(ctx, 1.0f);
186                         voxelctx_light(ctx, voxelctx_random(ctx, -0.8f, 0.1f));
187                         voxelctx_sat(ctx, 0.5f);
188                         voxelctx_cube(ctx, NODE_PALM_WOOD, true);
189                 voxelctx_pop(ctx);
190         }
191         voxelctx_pop(ctx);
192
193         voxelctx_z(ctx, s);
194         voxelctx_sat(ctx, 1.0f),
195         voxelctx_light(ctx, -0.5f);
196         voxelctx_hue(ctx, voxelctx_random(ctx, 50.0f, 30.0f));
197
198         voxelctx_push(ctx);
199         for (int i = 0; i < 6; i++) {
200                 voxelctx_rz(ctx, 360.0f / 6.0f);
201                 voxelctx_rz(ctx, voxelctx_random(ctx, 0.0f, 10.0f));
202                 voxelctx_push(ctx);
203                         voxelctx_light(ctx, voxelctx_random(ctx, 0.0f, 0.3f));
204                         voxelctx_rx(ctx, 90.0f);
205                         voxelctx_s(ctx, 2.0f);
206                         palm_branch(ctx);
207                 voxelctx_pop(ctx);
208         }
209         voxelctx_pop(ctx);
210
211         voxelctx_delete(ctx);
212 }
213
214 TreeDef tree_definitions[NUM_TREES] = {
215         // oak
216         {
217                 .spread = 64.0f,
218                 .probability = 0.0005f,
219                 .area_probability = 0.3f,
220                 .offset = SO_OAKTREE,
221                 .area_offset = SO_OAKTREE_AREA,
222                 .condition = &oak_condition,
223                 .generate = &oak_tree,
224         },
225         // pine
226         {
227                 .spread = 256.0f,
228                 .probability = 0.01f,
229                 .area_probability = 0.1f,
230                 .offset = SO_PINETREE,
231                 .area_offset = SO_PINETREE_AREA,
232                 .condition = &pine_condition,
233                 .generate = &pine_tree,
234         },
235         // palm
236         {
237                 .spread = 16.0f,
238                 .probability = 0.005f,
239                 .area_probability = 0.5f,
240                 .offset = SO_PALMTREE,
241                 .area_offset = SO_PALMTREE_AREA,
242                 .condition = &palm_condition,
243                 .generate = &palm_tree,
244         },
245 };
246