# HG changeset patch # User unC0Rr # Date 1672825341 -3600 # Node ID 33798b649d9cb7a71606191eb33fa2ff86dc702d # Parent 230dc46487eab58dbc8d163624f9bfed428f98f8 Use rust land generator in hwengine diff -r 230dc46487ea -r 33798b649d9c .gitignore --- a/.gitignore Wed Jan 04 10:40:40 2023 +0100 +++ b/.gitignore Wed Jan 04 10:42:21 2023 +0100 @@ -32,7 +32,7 @@ misc/libphysfs/Xcode/build/ misc/libphyslayer/Xcode/build/ moc_*.cxx_parameters -relre:^release\/ +relre:^release/ *.log *.cmd *.diff diff -r 230dc46487ea -r 33798b649d9c hedgewars/uLand.pas --- a/hedgewars/uLand.pas Wed Jan 04 10:40:40 2023 +0100 +++ b/hedgewars/uLand.pas Wed Jan 04 10:42:21 2023 +0100 @@ -793,7 +793,7 @@ begin WriteLnToConsole('Generating land...'); case cMapGen of - mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); + mgRandom: CreateTemplatedLand(cFeatureSize, cSeed, PathPrefix, Theme); mgMaze : begin ResizeLand(4096,2048); GenMaze; end; mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; mgDrawn : GenDrawnMap; @@ -801,7 +801,7 @@ else OutError('Unknown mapgen', true); end; - if cMapGen <> mgForts then + if (cMapGen <> mgForts) and (cMapGen <> mgRandom) then GenLandSurface end; @@ -948,7 +948,7 @@ begin WriteLnToConsole('Generating preview...'); case cMapGen of - mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); + mgRandom: CreateTemplatedLand(cFeatureSize, cSeed, PathPrefix, Theme); mgMaze: begin ResizeLand(4096,2048); GenMaze; end; mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; mgDrawn: begin GenDrawnMap; end; @@ -1007,7 +1007,7 @@ begin WriteLnToConsole('Generating preview...'); case cMapGen of - mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); + mgRandom: CreateTemplatedLand(cFeatureSize, cSeed, PathPrefix, Theme); mgMaze: begin ResizeLand(4096,2048); GenMaze; end; mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; mgDrawn: begin GenDrawnMap; end; diff -r 230dc46487ea -r 33798b649d9c hedgewars/uLandUtils.pas --- a/hedgewars/uLandUtils.pas Wed Jan 04 10:40:40 2023 +0100 +++ b/hedgewars/uLandUtils.pas Wed Jan 04 10:42:21 2023 +0100 @@ -2,6 +2,7 @@ interface uses SDLh; +procedure CreateTemplatedLand(featureSize: Longword; seed, dataPath, theme: shortstring); procedure ResizeLand(width, height: LongWord); procedure DisposeLand(); procedure InitWorldEdges(); @@ -20,8 +21,11 @@ uses uUtils, uConsts, uVariables, uTypes; const LibFutureName = 'hwengine_future'; -function create_game_field(width, height: Longword): pointer; cdecl; external LibFutureName; + +function create_empty_game_field(width, height: Longword): pointer; cdecl; external LibFutureName; +procedure get_game_field_parameters(game_field: pointer; var width: LongInt; var height: LongInt); cdecl; external LibFutureName; procedure dispose_game_field(game_field: pointer); cdecl; external LibFutureName; + function land_get(game_field: pointer; x, y: LongInt): Word; cdecl; external LibFutureName; procedure land_set(game_field: pointer; x, y: LongInt; value: Word); cdecl; external LibFutureName; function land_row(game_field: pointer; row: LongInt): PWordArray; cdecl; external LibFutureName; @@ -31,6 +35,8 @@ procedure land_pixel_set(game_field: pointer; x, y: LongInt; value: Longword); cdecl; external LibFutureName; function land_pixel_row(game_field: pointer; row: LongInt): PLongwordArray; cdecl; external LibFutureName; +function generate_templated_game_field(feature_size: Longword; seed, data_path, theme_name: PChar): pointer; cdecl; external LibFutureName; + var gameField: pointer; function LandGet(y, x: LongInt): Word; @@ -68,6 +74,23 @@ LandPixelRow:= land_pixel_row(gameField, row) end; +procedure CreateTemplatedLand(featureSize: Longword; seed, dataPath, theme: shortstring); +begin + seed[byte(seed[0]) + 1]:= #0; + theme[byte(theme[0]) + 1]:= #0; + + gameField:= generate_templated_game_field(featureSize, @seed[1], Str2PChar(dataPath), @theme[1]); + get_game_field_parameters(gameField, LAND_WIDTH, LAND_HEIGHT); + + // let's assume those are powers of two + LAND_WIDTH_MASK:= not(LAND_WIDTH-1); + LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); + + SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); + + initScreenSpaceVars(); +end; + procedure ResizeLand(width, height: LongWord); var potW, potH: LongInt; begin @@ -81,7 +104,7 @@ LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); cWaterLine:= LAND_HEIGHT; - gameField:= create_game_field(LAND_WIDTH, LAND_HEIGHT); + gameField:= create_empty_game_field(LAND_WIDTH, LAND_HEIGHT); SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); // 0.5 is already approaching on unplayable if (width div 4096 >= 2) or (height div 2048 >= 2) then cMaxZoomLevel:= cMaxZoomLevel/2; diff -r 230dc46487ea -r 33798b649d9c rust/land2d/src/lib.rs --- a/rust/land2d/src/lib.rs Wed Jan 04 10:40:40 2023 +0100 +++ b/rust/land2d/src/lib.rs Wed Jan 04 10:42:21 2023 +0100 @@ -1,5 +1,5 @@ use std::{cmp, ops::Index, ops::IndexMut}; - +use vec2d::Vec2D; use integral_geometry::{ArcPoints, EquidistantPoints, Line, Point, PotSize, Rect, Size, SizeMask}; pub struct Land2D { @@ -295,6 +295,23 @@ } } +impl From> for Land2D { + fn from(vec: Vec2D) -> Self { + let actual_size = vec.size(); + let pot_size = actual_size.next_power_of_two(); + + assert_eq!(actual_size, pot_size.size()); + + let top_left = Point::new(0, 0); + let play_box = Rect::from_size(top_left, actual_size); + Self { + play_box, + pixels: vec, + mask: pot_size.to_mask(), + } + } +} + #[cfg(test)] mod tests { use super::*; diff -r 230dc46487ea -r 33798b649d9c rust/lib-hwengine-future/Cargo.toml --- a/rust/lib-hwengine-future/Cargo.toml Wed Jan 04 10:40:40 2023 +0100 +++ b/rust/lib-hwengine-future/Cargo.toml Wed Jan 04 10:42:21 2023 +0100 @@ -9,6 +9,9 @@ [dependencies] land2d = { path = "../land2d" } integral-geometry = { path = "../integral-geometry" } +mapgen = { path = "../mapgen" } +landgen = { path = "../landgen" } +lfprng = { path = "../lfprng" } [lib] name = "hwengine_future" diff -r 230dc46487ea -r 33798b649d9c rust/lib-hwengine-future/src/lib.rs --- a/rust/lib-hwengine-future/src/lib.rs Wed Jan 04 10:40:40 2023 +0100 +++ b/rust/lib-hwengine-future/src/lib.rs Wed Jan 04 10:42:21 2023 +0100 @@ -1,5 +1,10 @@ use integral_geometry::{Point, Size}; use land2d; +use landgen::{template_based::TemplatedLandGenerator, LandGenerationParameters, LandGenerator}; +use lfprng::LaggedFibonacciPRNG; +use mapgen::{theme::Theme, MapGenerator}; +use std::fs; +use std::{ffi::CStr, path::Path}; #[repr(C)] pub struct GameField { @@ -8,7 +13,19 @@ } #[no_mangle] -pub extern "C" fn create_game_field(width: u32, height: u32) -> *mut GameField { +pub extern "C" fn get_game_field_parameters( + game_field: &GameField, + width: *mut i32, + height: *mut i32, +) { + unsafe { + *width = game_field.collision.width() as i32; + *height = game_field.collision.height() as i32; + } +} + +#[no_mangle] +pub extern "C" fn create_empty_game_field(width: u32, height: u32) -> *mut GameField { let game_field = Box::new(GameField { collision: land2d::Land2D::new(Size::new(width as usize, height as usize), 0), pixels: land2d::Land2D::new(Size::new(width as usize, height as usize), 0), @@ -18,6 +35,53 @@ } #[no_mangle] +pub extern "C" fn generate_templated_game_field( + feature_size: u32, + seed: *const i8, + data_path: *const i8, + theme_name: *const i8, +) -> *mut GameField { + let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap(); + let data_path = Path::new(&data_path); + + let seed: &str = unsafe { CStr::from_ptr(seed) }.to_str().unwrap(); + let theme_name: &str = unsafe { CStr::from_ptr(theme_name) }.to_str().unwrap(); + + let mut random_numbers_gen = LaggedFibonacciPRNG::new(seed.as_bytes()); + + let yaml_templates = + fs::read_to_string(data_path.join(Path::new("map_templates.yaml")).as_path()) + .expect("Error reading map templates file"); + let mut map_gen = MapGenerator::new(); + map_gen.import_yaml_templates(&yaml_templates); + + let distance_divisor = feature_size.pow(2) / 8 + 10; + let params = LandGenerationParameters::new(0u16, 0x8000u16, distance_divisor, false, false); + let template = map_gen + .get_template("medium", &mut random_numbers_gen) + .expect("Error reading map templates file") + .clone(); + let landgen = TemplatedLandGenerator::new(template); + let collision = landgen.generate_land(¶ms, &mut random_numbers_gen); + + let theme = Theme::load( + data_path + .join(Path::new("Themes")) + .join(Path::new(theme_name)) + .as_path(), + ) + .unwrap(); + let pixels = map_gen.make_texture(&collision, ¶ms, &theme); + + let game_field = Box::new(GameField { + collision, + pixels: pixels.into(), + }); + + Box::leak(game_field) +} + +#[no_mangle] pub extern "C" fn land_get(game_field: &mut GameField, x: i32, y: i32) -> u16 { game_field.collision.map(y, x, |p| *p) }