veloren_world/site2/plot/
desert_city_temple.rs

1use super::*;
2use crate::{
3    Land,
4    util::{RandomField, Sampler},
5};
6use common::terrain::{Block, BlockKind};
7use rand::prelude::*;
8use std::sync::Arc;
9use vek::*;
10
11/// Represents house data generated by the `generate()` method
12pub struct DesertCityTemple {
13    /// Tile position of the door tile
14    pub door_tile: Vec2<i32>,
15    /// Axis aligned bounding region for the house
16    bounds: Aabr<i32>,
17    /// Approximate altitude of the door tile
18    pub(crate) alt: i32,
19}
20
21impl DesertCityTemple {
22    pub fn generate(
23        land: &Land,
24        _rng: &mut impl Rng,
25        site: &Site,
26        door_tile: Vec2<i32>,
27        door_dir: Vec2<i32>,
28        tile_aabr: Aabr<i32>,
29        alt: Option<i32>,
30    ) -> Self {
31        let door_tile_pos = site.tile_center_wpos(door_tile);
32        let bounds = Aabr {
33            min: site.tile_wpos(tile_aabr.min),
34            max: site.tile_wpos(tile_aabr.max),
35        };
36
37        Self {
38            bounds,
39            door_tile: door_tile_pos,
40            alt: alt.unwrap_or_else(|| {
41                land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
42            }),
43        }
44    }
45}
46
47impl Structure for DesertCityTemple {
48    #[cfg(feature = "use-dyn-lib")]
49    const UPDATE_FN: &'static [u8] = b"render_desertcitytemple\0";
50
51    #[cfg_attr(feature = "be-dyn-lib", export_name = "render_desertcitytemple")]
52    fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
53        let sandstone = Fill::Sampling(Arc::new(|center| {
54            Some(match (RandomField::new(0).get(center)) % 37 {
55                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
56                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
57                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
58                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
59                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
60            })
61        }));
62        let sandstone_broken = Fill::Sampling(Arc::new(|center| {
63            Some(match (RandomField::new(0).get(center)) % 42 {
64                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
65                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
66                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
67                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
68                36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
69                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
70            })
71        }));
72        let base = self.alt + 1;
73        let center = self.bounds.center();
74        let diameter =
75            10 + (self.bounds.max.x - self.bounds.min.x).min(self.bounds.max.y - self.bounds.min.y);
76        // Fence
77        painter
78            .aabb(Aabb {
79                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
80                max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
81            })
82            .union(painter.aabb(Aabb {
83                min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
84                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
85            }))
86            .union(painter.aabb(Aabb {
87                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
88                max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
89            }))
90            .union(painter.aabb(Aabb {
91                min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
92                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
93            }))
94            .fill(sandstone_broken);
95        painter
96            .aabb(Aabb {
97                min: Vec2::new(self.bounds.min.x + 1, center.y - 8).with_z(base),
98                max: Vec2::new(self.bounds.max.x, center.y + 8).with_z(base + 7),
99            })
100            .clear();
101        painter
102            .aabb(Aabb {
103                min: Vec2::new(center.x - 7, self.bounds.min.y + 1).with_z(base),
104                max: Vec2::new(center.x + 9, self.bounds.max.y).with_z(base + 7),
105            })
106            .clear();
107        // Foundation
108        painter
109            .aabb(Aabb {
110                min: (self.bounds.min + 1).with_z(base - 20),
111                max: (self.bounds.max).with_z(base),
112            })
113            .fill(sandstone.clone());
114
115        // Temple
116        let temple_color = match (RandomField::new(0).get((center - 3).with_z(base))) % 2 {
117            0 => Fill::Brick(BlockKind::Rock, Rgb::new(100, 101, 250), 3),
118            _ => Fill::Brick(BlockKind::Rock, Rgb::new(63, 49, 63), 24),
119        };
120        let temple_size = diameter / 3;
121        let floaty_block = Fill::Brick(BlockKind::GlowingWeakRock, Rgb::new(253, 240, 149), 2);
122        let temple = Aabb {
123            min: (center - temple_size).with_z(base),
124            max: (center + temple_size - 1).with_z(base + temple_size + 1),
125        };
126
127        // temple with roof carve out
128        painter.aabb(temple).fill(sandstone.clone());
129        // roof decoration
130        painter
131            .aabb(Aabb {
132                min: (center - temple_size - 1).with_z(base + temple_size + 1),
133                max: (center + temple_size).with_z(base + temple_size + 4),
134            })
135            .fill(sandstone.clone());
136        painter
137            .aabb(Aabb {
138                min: (center - temple_size).with_z(base + temple_size + 2),
139                max: (center + temple_size - 1).with_z(base + temple_size + 4),
140            })
141            .clear();
142        painter
143            .aabb(Aabb {
144                min: Vec2::new(center.x - temple_size - 1, center.y - (temple_size / 4) - 2)
145                    .with_z(base + temple_size + 3),
146                max: Vec2::new(center.x + temple_size, center.y + (temple_size / 4) + 1)
147                    .with_z(base + temple_size + 4),
148            })
149            .clear();
150        painter
151            .aabb(Aabb {
152                min: Vec2::new(center.x - (temple_size / 4) - 2, center.y - temple_size - 1)
153                    .with_z(base + temple_size + 3),
154                max: Vec2::new(center.x + (temple_size / 4) + 1, center.y + temple_size)
155                    .with_z(base + temple_size + 4),
156            })
157            .clear();
158
159        // roof carve out
160        painter
161            .aabb(Aabb {
162                min: (center - temple_size + 1).with_z(base + temple_size),
163                max: (center + temple_size - 2).with_z(base + temple_size + 3),
164            })
165            .clear();
166        //corner pillars
167        for dir in SQUARE_4 {
168            let corner_pos = center - temple_size;
169            let pillar_center = corner_pos + (dir * ((2 * temple_size) - 1));
170            // Pillar foot
171            painter
172                .aabb(Aabb {
173                    min: (pillar_center - 4).with_z(base),
174                    max: (pillar_center + 4).with_z(base + 4),
175                })
176                .fill(sandstone.clone());
177
178            // Pillar
179            painter
180                .aabb(Aabb {
181                    min: (pillar_center - 3).with_z(base + 4),
182                    max: (pillar_center + 3).with_z(base + temple_size + 3),
183                })
184                .fill(sandstone.clone());
185            // Pillar Top
186            painter
187                .aabb(Aabb {
188                    min: (pillar_center - 4).with_z(base + temple_size + 3),
189                    max: (pillar_center + 4).with_z(base + temple_size + 6),
190                })
191                .fill(sandstone.clone());
192
193            painter
194                .aabb(Aabb {
195                    min: (pillar_center - 3).with_z(base + temple_size + 4),
196                    max: (pillar_center + 3).with_z(base + temple_size + 6),
197                })
198                .clear();
199
200            // clear parts of pillar top for roof carve out
201            painter
202                .aabb(Aabb {
203                    min: (center - temple_size).with_z(base + temple_size + 3),
204                    max: (center + temple_size - 1).with_z(base + temple_size + 6),
205                })
206                .clear()
207        }
208
209        // temple decor carve out
210        // apply three carve options (horizontal, vertical, none) with two spread
211        // options (for horizontal and vertical)
212        for s in 0..2 {
213            // decor carve out style
214            let spread_select = ((RandomField::new(0).get((center - 1).with_z(base))) % 2) as i32;
215            let spread = 3 * spread_select;
216            let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
217            match carve_style {
218                //vertical
219                0 => {
220                    // decor carve outs1
221                    for c in 0..(temple_size - 5) {
222                        painter
223                            .aabb(Aabb {
224                                min: Vec2::new(
225                                    center.x - temple_size + 5 + (2 * c),
226                                    center.y - temple_size,
227                                )
228                                .with_z(base + 2),
229                                max: Vec2::new(
230                                    center.x - temple_size + 6 + (2 * c),
231                                    center.y + temple_size - 1,
232                                )
233                                .with_z(base + temple_size - 1),
234                            })
235                            .clear();
236                    }
237                    for c in 0..(temple_size - 5) {
238                        painter
239                            .aabb(Aabb {
240                                min: Vec2::new(
241                                    center.x - temple_size,
242                                    center.y - temple_size + 5 + (2 * c),
243                                )
244                                .with_z(base + 2),
245                                max: Vec2::new(
246                                    center.x + temple_size - 1,
247                                    center.y - temple_size + 6 + (2 * c),
248                                )
249                                .with_z(base + temple_size - 1),
250                            })
251                            .clear();
252                    }
253                },
254                1 => {
255                    // horizontal
256                    for c in 0..((temple_size / 2) - 2) {
257                        painter
258                            .aabb(Aabb {
259                                min: Vec2::new(center.x - temple_size + 5, center.y - temple_size)
260                                    .with_z(base + 2 + ((spread + 2) * c)),
261                                max: Vec2::new(
262                                    center.x + temple_size - 6,
263                                    center.y + temple_size - 1,
264                                )
265                                .with_z(base + 3 + ((spread + 2) * c) + spread_select),
266                            })
267                            .clear();
268                    }
269                    for c in 0..((temple_size / 2) - 2) {
270                        painter
271                            .aabb(Aabb {
272                                min: Vec2::new(center.x - temple_size, center.y - temple_size + 5)
273                                    .with_z(base + 2 + ((spread + 2) * c)),
274                                max: Vec2::new(
275                                    center.x + temple_size - 1,
276                                    center.y + temple_size - 6,
277                                )
278                                .with_z(base + 3 + ((spread + 2) * c) + spread_select),
279                            })
280                            .clear();
281                    }
282                },
283                _ => {},
284            }
285        }
286        // color inlays1
287        painter
288            .aabb(Aabb {
289                min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
290                    .with_z(base + 2),
291                max: Vec2::new(center.x + temple_size - 3, center.y - temple_size + 3)
292                    .with_z(base + temple_size - 1),
293            })
294            .fill(temple_color.clone());
295
296        painter
297            .aabb(Aabb {
298                min: Vec2::new(center.x - temple_size + 2, center.y + temple_size - 4)
299                    .with_z(base + 2),
300                max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
301                    .with_z(base + temple_size - 1),
302            })
303            .fill(temple_color.clone());
304        // color inlays2
305        painter
306            .aabb(Aabb {
307                min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
308                    .with_z(base + 2),
309                max: Vec2::new(center.x - temple_size + 3, center.y + temple_size - 3)
310                    .with_z(base + temple_size - 1),
311            })
312            .fill(temple_color.clone());
313        painter
314            .aabb(Aabb {
315                min: Vec2::new(center.x + temple_size - 4, center.y - temple_size + 2)
316                    .with_z(base + 2),
317                max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
318                    .with_z(base + temple_size - 1),
319            })
320            .fill(temple_color.clone());
321        // carve outside plane1
322        painter
323            .aabb(Aabb {
324                min: Vec2::new(center.x - temple_size + 6, center.y - temple_size).with_z(base + 3),
325                max: Vec2::new(center.x + temple_size - 7, center.y - temple_size + 1)
326                    .with_z(base + temple_size - 2),
327            })
328            .clear();
329        painter
330            .aabb(Aabb {
331                min: Vec2::new(center.x - temple_size + 6, center.y + temple_size - 2)
332                    .with_z(base + 3),
333                max: Vec2::new(center.x + temple_size - 7, center.y + temple_size - 1)
334                    .with_z(base + temple_size - 2),
335            })
336            .clear();
337        // carve outside plane2
338        painter
339            .aabb(Aabb {
340                min: Vec2::new(center.x - temple_size, center.y - temple_size + 6).with_z(base + 3),
341                max: Vec2::new(center.x - temple_size + 1, center.y + temple_size - 7)
342                    .with_z(base + temple_size - 2),
343            })
344            .clear();
345        painter
346            .aabb(Aabb {
347                min: Vec2::new(center.x + temple_size - 2, center.y - temple_size + 6)
348                    .with_z(base + 3),
349                max: Vec2::new(center.x + temple_size - 1, center.y + temple_size - 7)
350                    .with_z(base + temple_size - 2),
351            })
352            .clear();
353        // Temple Top Socket
354        painter
355            .cylinder(Aabb {
356                min: (center - temple_size + 3).with_z(base + temple_size),
357                max: (center + temple_size - 4).with_z(base + temple_size + 1),
358            })
359            .fill(sandstone.clone());
360        // Temple Top
361        let top = painter.sphere(Aabb {
362            min: (center - temple_size + 3).with_z(base),
363            max: (center + temple_size - 4).with_z(base + (2 * temple_size) - 7),
364        });
365        top.fill(sandstone.clone());
366
367        // temple top decoration
368        // apply two decoration options (horizontal, vertical, none) with two spread
369        // options for hor/ver options
370        for s in 0..2 {
371            // decor carve out style
372            let spread_select =
373                ((RandomField::new(0).get((center - 1 - s).with_z(base))) % 2) as i32;
374            let spread = 3 * spread_select;
375            let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
376            match carve_style {
377                //vertical
378                0 => {
379                    // decor carve outs1
380                    for c in 0..(temple_size - 2) {
381                        painter
382                            .aabb(Aabb {
383                                min: Vec2::new(
384                                    center.x - temple_size + 2 + ((spread + 2) * c),
385                                    center.y - temple_size,
386                                )
387                                .with_z(base + temple_size),
388                                max: Vec2::new(
389                                    center.x - temple_size + 3 + ((spread + 2) * c) + spread_select,
390                                    center.y + temple_size - 1,
391                                )
392                                .with_z(base + (2 * temple_size)),
393                            })
394                            .intersect(top)
395                            .fill(temple_color.clone());
396                    }
397                },
398                1 => {
399                    for c in 0..(temple_size - 2) {
400                        painter
401                            .aabb(Aabb {
402                                min: Vec2::new(
403                                    center.x - temple_size,
404                                    center.y - temple_size + 2 + ((spread + 2) * c),
405                                )
406                                .with_z(base + temple_size),
407                                max: Vec2::new(
408                                    center.x + temple_size - 1,
409                                    center.y - temple_size + 3 + ((spread + 2) * c) + spread_select,
410                                )
411                                .with_z(base + (2 * temple_size)),
412                            })
413                            .intersect(top)
414                            .fill(temple_color.clone());
415                    }
416                },
417                _ => {},
418            }
419        }
420        // Temple Top Socket
421        painter
422            .cylinder(Aabb {
423                min: (center - temple_size + 3).with_z(base + temple_size),
424                max: (center + temple_size - 4).with_z(base + temple_size + 1),
425            })
426            .fill(sandstone.clone());
427        // clear top
428        painter
429            .sphere(Aabb {
430                min: (center - temple_size + 4).with_z(base + 1),
431                max: (center + temple_size - 5).with_z(base + (2 * temple_size) - 8),
432            })
433            .clear();
434
435        // round or rectangle entries
436        let entry_select = ((RandomField::new(0).get((center + 1).with_z(base))) % 2) as i32;
437        match entry_select {
438            0 => {
439                //round Temple entries1
440                painter
441                    .aabb(Aabb {
442                        min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
443                        max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 4),
444                    })
445                    .fill(sandstone.clone());
446                painter
447                    .aabb(Aabb {
448                        min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base),
449                        max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 4),
450                    })
451                    .clear();
452
453                painter
454                    .aabb(Aabb {
455                        min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base + 4),
456                        max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 7),
457                    })
458                    .fill(sandstone.clone());
459                painter
460                    .aabb(Aabb {
461                        min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 4),
462                        max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 7),
463                    })
464                    .clear();
465
466                painter
467                    .aabb(Aabb {
468                        min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 7),
469                        max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 9),
470                    })
471                    .fill(sandstone.clone());
472                painter
473                    .aabb(Aabb {
474                        min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 7),
475                        max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 9),
476                    })
477                    .clear();
478
479                painter
480                    .aabb(Aabb {
481                        min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 9),
482                        max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 10),
483                    })
484                    .fill(sandstone.clone());
485
486                // round Temple entries2
487                painter
488                    .aabb(Aabb {
489                        min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
490                        max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 4),
491                    })
492                    .fill(sandstone.clone());
493                painter
494                    .aabb(Aabb {
495                        min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base),
496                        max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 4),
497                    })
498                    .clear();
499
500                painter
501                    .aabb(Aabb {
502                        min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base + 4),
503                        max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 7),
504                    })
505                    .fill(sandstone.clone());
506                painter
507                    .aabb(Aabb {
508                        min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 4),
509                        max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 7),
510                    })
511                    .clear();
512
513                painter
514                    .aabb(Aabb {
515                        min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 7),
516                        max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 9),
517                    })
518                    .fill(sandstone.clone());
519                painter
520                    .aabb(Aabb {
521                        min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 7),
522                        max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 9),
523                    })
524                    .clear();
525
526                painter
527                    .aabb(Aabb {
528                        min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 9),
529                        max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 10),
530                    })
531                    .fill(sandstone.clone());
532            },
533            _ => {
534                //rectangle Temple entries1
535                painter
536                    .aabb(Aabb {
537                        min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
538                        max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 8),
539                    })
540                    .fill(sandstone.clone());
541                painter
542                    .aabb(Aabb {
543                        min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base),
544                        max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 6),
545                    })
546                    .clear();
547
548                //rectangle Temple entries1
549                painter
550                    .aabb(Aabb {
551                        min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
552                        max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 8),
553                    })
554                    .fill(sandstone.clone());
555                painter
556                    .aabb(Aabb {
557                        min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base),
558                        max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 6),
559                    })
560                    .clear();
561            },
562        }
563
564        // carve temple
565        painter
566            .aabb(Aabb {
567                min: (center - temple_size + 4).with_z(base),
568                max: (center + temple_size - 5).with_z(base + temple_size - 1),
569            })
570            .clear();
571
572        // floating sculpture, placeholder for sun god
573
574        painter
575            .sphere(Aabb {
576                min: (center - 3).with_z(base),
577                max: (center + 2).with_z(base + 5),
578            })
579            .fill(sandstone.clone());
580        painter
581            .sphere(Aabb {
582                min: (center - 3).with_z(base + 4),
583                max: (center + 2).with_z(base + 9),
584            })
585            .fill(sandstone.clone());
586        painter
587            .sphere(Aabb {
588                min: (center - 3).with_z(base + 8),
589                max: (center + 2).with_z(base + 13),
590            })
591            .fill(sandstone.clone());
592        painter
593            .sphere(Aabb {
594                min: (center - 4).with_z(base + 14),
595                max: (center + 3).with_z(base + 15),
596            })
597            .fill(sandstone.clone());
598        painter
599            .sphere(Aabb {
600                min: (center - 3).with_z(base + 16),
601                max: (center + 2).with_z(base + 21),
602            })
603            .fill(floaty_block.clone());
604
605        // floating sculptures
606        for dir in SQUARE_4 {
607            let corner_pos = center - temple_size / 2;
608            let sclpt_center = corner_pos + (dir * (temple_size));
609
610            painter
611                .sphere(Aabb {
612                    min: (sclpt_center - 2).with_z(base),
613                    max: (sclpt_center + 1).with_z(base + 3),
614                })
615                .fill(sandstone.clone());
616            painter
617                .sphere(Aabb {
618                    min: (sclpt_center - 2).with_z(base + 2),
619                    max: (sclpt_center + 1).with_z(base + 5),
620                })
621                .fill(sandstone.clone());
622            painter
623                .sphere(Aabb {
624                    min: (sclpt_center - 3).with_z(base + 5),
625                    max: (sclpt_center + 2).with_z(base + 6),
626                })
627                .fill(sandstone.clone());
628            painter
629                .sphere(Aabb {
630                    min: (sclpt_center - 3).with_z(base + 7),
631                    max: (sclpt_center + 2).with_z(base + 8),
632                })
633                .fill(sandstone.clone());
634            painter
635                .sphere(Aabb {
636                    min: (sclpt_center - 2).with_z(base + 9),
637                    max: (sclpt_center + 1).with_z(base + 12),
638                })
639                .fill(floaty_block.clone());
640        }
641    }
642}