Implement shoppa border generation default
authorunC0Rr
Tue, 04 Feb 2025 15:53:16 +0100
changeset 16086 ee8b894272d0
parent 16085 f79c6c715132
child 16087 8da5a118120b
Implement shoppa border generation
qmlfrontend/engine_instance.cpp
rust/mapgen/src/lib.rs
rust/mapgen/src/theme.rs
--- a/qmlfrontend/engine_instance.cpp	Tue Feb 04 15:52:02 2025 +0100
+++ b/qmlfrontend/engine_instance.cpp	Tue Feb 04 15:53:16 2025 +0100
@@ -110,7 +110,7 @@
 void EngineInstance::setOpenGLContext(QOpenGLContext* context) {
   currentOpenglContext = context;
 
-  auto size = context->surface()->size();
+  const auto size = context->surface()->size();
   setup_current_gl_context(m_instance.get(), static_cast<quint16>(size.width()),
                            static_cast<quint16>(size.height()),
                            &getProcAddress);
--- a/rust/mapgen/src/lib.rs	Tue Feb 04 15:52:02 2025 +0100
+++ b/rust/mapgen/src/lib.rs	Tue Feb 04 15:53:16 2025 +0100
@@ -23,6 +23,7 @@
 
 use rand::prelude::IndexedRandom;
 use std::{borrow::Borrow, collections::hash_map::HashMap};
+use std::fmt::Debug;
 use vec2d::Vec2D;
 
 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
@@ -66,7 +67,10 @@
         let mut texture = Vec2D::new(&land.size().size(), 0);
 
         if let Some(land_sprite) = theme.land_texture() {
-            for (sprite_row, (land_row, tex_row)) in land_sprite.rows().cycle().zip(land.rows().zip(texture.rows_mut()))
+            for (sprite_row, (land_row, tex_row)) in land_sprite
+                .rows()
+                .cycle()
+                .zip(land.rows().zip(texture.rows_mut()))
             {
                 let mut x_offset = 0;
                 while sprite_row.len() < land.width() - x_offset {
@@ -91,39 +95,44 @@
                     );
                 }
             }
+        } else {
+            eprintln!("No land texture, expect empty land");
         }
 
-        if let Some(border_sprite) = theme.border_texture() {
-            assert!(border_sprite.height() <= 512);
-            let border_width = (border_sprite.height() / 2) as u8;
-            let border_sprite = border_sprite.to_tiled();
+        if true {
+           shoppa_border(parameters.basic(), &land, &mut texture, 8);
+        } else {
+            if let Some(border_sprite) = theme.border_texture() {
+                assert!(border_sprite.height() <= 512);
+                let border_width = (border_sprite.height() / 2) as u8;
+                let border_sprite = border_sprite.to_tiled();
 
-            let mut offsets = vec![255u8; land.width()];
+                let mut offsets = vec![255u8; land.width()];
 
-            land_border_pass(
-                parameters.basic(),
-                land.rows().rev().zip(texture.rows_mut().rev()),
-                &mut offsets,
-                border_width,
-                |x, y| {
-                    border_sprite.get_pixel(
-                        x % border_sprite.width() as usize,
-                        border_sprite.height() as usize - 1 - y,
-                    )
-                },
-            );
+                land_border_pass(
+                    parameters.basic(),
+                    land.rows().rev().zip(texture.rows_mut().rev()),
+                    &mut offsets,
+                    border_width,
+                    |x, y| {
+                        border_sprite.get_pixel(
+                            x % border_sprite.width() as usize,
+                            border_sprite.height() as usize - 1 - y,
+                        )
+                    },
+                );
 
-            offsets.iter_mut().for_each(|v| *v = 255);
+                offsets.iter_mut().for_each(|v| *v = 255);
 
-            land_border_pass(
-                parameters.basic(),
-                land.rows().zip(texture.rows_mut()),
-                &mut offsets,
-                border_width,
-                |x, y| border_sprite.get_pixel(x % border_sprite.width() as usize, y),
-            );
+                land_border_pass(
+                    parameters.basic(),
+                    land.rows().zip(texture.rows_mut()),
+                    &mut offsets,
+                    border_width,
+                    |x, y| border_sprite.get_pixel(x % border_sprite.width() as usize, y),
+                );
+            }
         }
-
         texture
     }
 }
@@ -276,6 +285,88 @@
     }
 }
 
+fn shoppa_border<LandT>(
+    basic_value: LandT,
+    land: &Land2D<LandT>,
+    texture: &mut Vec2D<u32>,
+    depth: u8,
+) where
+    LandT: Copy + Default + PartialEq,
+{
+    //land.rows().rev().zip(texture.rows_mut().rev()),
+    let mut depth_field = Vec2D::new(&land.size().size(), 0u8);
+
+    for (d, l) in depth_field
+        .as_mut_slice()
+        .iter_mut()
+        .zip(land.raw_pixels().iter())
+    {
+        *d = if *l == basic_value { depth } else { 0 };
+    }
+
+    let chunk_size = depth_field.width();
+    for i in 1..depth_field.height() {
+        let split_index = i * chunk_size;
+        let (left, right) = depth_field.as_mut_slice().split_at_mut(split_index);
+
+        let prev_chunk = &left[(i - 1) * chunk_size..i * chunk_size];
+        let cur_chunk = &mut right[..chunk_size];
+        process_shoppa_row_pair(prev_chunk, cur_chunk);
+    }
+
+    for i in (1..depth_field.height()).rev() {
+        let split_index = i * chunk_size;
+        let (left, right) = depth_field.as_mut_slice().split_at_mut(split_index);
+
+        let cur_chunk = &mut left[(i - 1) * chunk_size..i * chunk_size];
+        let prev_chunk = &right[..chunk_size];
+        process_shoppa_row_pair(prev_chunk, cur_chunk);
+    }
+    
+    for r in depth_field.rows_mut() {
+        let mut it = r.iter_mut();
+        let mut p = *it.next().unwrap();
+        for c in it {
+            if p < *c {
+                *c = p + 1;
+            }
+            
+            p = *c
+        }
+        
+        let mut it = r.iter_mut().rev();
+        let mut p = *it.next().unwrap();
+        for c in it {
+            if p < *c {
+                *c = p + 1;
+            }
+
+            p = *c
+        }
+    }
+
+    for (row_index, (tex_row, depth_row)) in texture.rows_mut().zip(depth_field.rows()).enumerate()
+    {
+        for (column_index, (tex, &d)) in tex_row.iter_mut().zip(depth_row.iter()).enumerate() {
+            if d > 0 && d < depth {
+                *tex = if ((row_index + column_index) / 8) & 1 != 0 {
+                    0xff00ffff
+                } else {
+                    0xff000000
+                };
+            }
+        }
+    }
+}
+
+fn process_shoppa_row_pair(prev_chunk: &[u8], cur_chunk: &mut [u8]) {
+    for (&p, c) in prev_chunk.iter().zip(cur_chunk.iter_mut()) {
+        if p < *c {
+            *c = p + 1;
+        }
+    }
+}
+
 fn tex_row_copy<LandT>(
     basic_value: LandT,
     land_row: &[LandT],
--- a/rust/mapgen/src/theme.rs	Tue Feb 04 15:52:02 2025 +0100
+++ b/rust/mapgen/src/theme.rs	Tue Feb 04 15:53:16 2025 +0100
@@ -1,5 +1,7 @@
+use integral_geometry::Size;
 use integral_geometry::{Point, Rect};
 use png::{ColorType, Decoder, DecodingError};
+use std::slice::ChunksExact;
 use std::{
     fs::{read_dir, File},
     io,
@@ -7,8 +9,6 @@
     path::Path,
     slice::{from_raw_parts, from_raw_parts_mut},
 };
-use std::slice::ChunksExact;
-use integral_geometry::Size;
 use vec2d::Vec2D;
 
 pub struct ThemeSprite {