mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 11:17:05 -04:00
95 lines
3.4 KiB
Zig
95 lines
3.4 KiB
Zig
const std = @import("std");
|
|
|
|
const main = @import("root");
|
|
const random = main.random;
|
|
const ZonElement = main.ZonElement;
|
|
const terrain = main.server.terrain;
|
|
const CaveBiomeMapView = terrain.CaveBiomeMap.CaveBiomeMapView;
|
|
const CaveMapView = terrain.CaveMap.CaveMapView;
|
|
const GenerationMode = terrain.biomes.SimpleStructureModel.GenerationMode;
|
|
const vec = main.vec;
|
|
const Vec3d = vec.Vec3d;
|
|
const Vec3f = vec.Vec3f;
|
|
const Vec3i = vec.Vec3i;
|
|
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
|
|
|
|
pub const id = "cubyz:flower_patch";
|
|
|
|
pub const generationMode = .floor;
|
|
|
|
const FlowerPatch = @This();
|
|
|
|
block: main.blocks.Block,
|
|
width: f32,
|
|
variation: f32,
|
|
density: f32,
|
|
|
|
pub fn loadModel(arenaAllocator: NeverFailingAllocator, parameters: ZonElement) *FlowerPatch {
|
|
const self = arenaAllocator.create(FlowerPatch);
|
|
self.* = .{
|
|
.block = main.blocks.parseBlock(parameters.get([]const u8, "block", "")),
|
|
.width = parameters.get(f32, "width", 5),
|
|
.variation = parameters.get(f32, "variation", 1),
|
|
.density = parameters.get(f32, "density", 0.5),
|
|
};
|
|
return self;
|
|
}
|
|
|
|
pub fn generate(self: *FlowerPatch, mode: GenerationMode, x: i32, y: i32, z: i32, chunk: *main.chunk.ServerChunk, caveMap: CaveMapView, caveBiomeMap: CaveBiomeMapView, seed: *u64, _: bool) void {
|
|
const width = self.width + (random.nextFloat(seed) - 0.5)*self.variation;
|
|
const orientation = 2*std.math.pi*random.nextFloat(seed);
|
|
const ellipseParam = 1 + random.nextFloat(seed);
|
|
|
|
// Orientation of the major and minor half axis of the ellipse.
|
|
// For now simply use a minor axis 1/ellipseParam as big as the major.
|
|
const xMain = @sin(orientation)/width;
|
|
const yMain = @cos(orientation)/width;
|
|
const xSecn = ellipseParam*@cos(orientation)/width;
|
|
const ySecn = -ellipseParam*@sin(orientation)/width;
|
|
|
|
const xMin = @max(0, x - @as(i32, @intFromFloat(@ceil(width))));
|
|
const xMax = @min(chunk.super.width, x + @as(i32, @intFromFloat(@ceil(width))));
|
|
const yMin = @max(0, y - @as(i32, @intFromFloat(@ceil(width))));
|
|
const yMax = @min(chunk.super.width, y + @as(i32, @intFromFloat(@ceil(width))));
|
|
|
|
var baseHeight = z;
|
|
if(mode != .water_surface) {
|
|
if(caveMap.isSolid(x, y, baseHeight)) {
|
|
baseHeight = caveMap.findTerrainChangeAbove(x, y, baseHeight) - 1;
|
|
} else {
|
|
baseHeight = caveMap.findTerrainChangeBelow(x, y, baseHeight);
|
|
}
|
|
}
|
|
|
|
var px = chunk.startIndex(xMin);
|
|
while(px < xMax) : (px += 1) {
|
|
var py = chunk.startIndex(yMin);
|
|
while(py < yMax) : (py += 1) {
|
|
const mainDist = xMain*@as(f32, @floatFromInt(x - px)) + yMain*@as(f32, @floatFromInt(y - py));
|
|
const secnDist = xSecn*@as(f32, @floatFromInt(x - px)) + ySecn*@as(f32, @floatFromInt(y - py));
|
|
const distSqr = mainDist*mainDist + secnDist*secnDist;
|
|
if(distSqr <= 1) {
|
|
if((1 - distSqr)*self.density < random.nextFloat(seed)) continue;
|
|
var startHeight = z;
|
|
|
|
if(mode == .water_surface) {
|
|
if(caveBiomeMap.getSurfaceHeight(chunk.super.pos.wx + px, chunk.super.pos.wy + py) >= 0) continue;
|
|
startHeight = z -% 1;
|
|
} else {
|
|
if(caveMap.isSolid(px, py, startHeight)) {
|
|
startHeight = caveMap.findTerrainChangeAbove(px, py, startHeight) -% 1;
|
|
} else {
|
|
startHeight = caveMap.findTerrainChangeBelow(px, py, startHeight);
|
|
}
|
|
}
|
|
|
|
startHeight = chunk.startIndex(startHeight + chunk.super.pos.voxelSize);
|
|
if(@abs(startHeight -% baseHeight) > 5) continue;
|
|
if(chunk.liesInChunk(px, py, startHeight)) {
|
|
chunk.updateBlockInGeneration(px, py, startHeight, self.block);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|