Claude/minecraft heightmap generator dhk a4#13
Merged
stephenkall merged 17 commits intomainfrom May 8, 2026
Merged
Conversation
Feature 1: New STL prompt 'sea_level_offset' — carves an ocean basin N blocks deep below sea level. Ocean cells are set to stl_zero = sea_level - offset, all terrain is clamped to that floor, and h_min_global = stl_zero. The printed basin is exactly offset * z_scale mm deep so resin fills flush to sea level. Feature 2: Optional JSON polygon mask file. Each polygon's convex hull is computed and all heightmap cells inside are forced to sea_level and marked as ocean. Uses scipy ConvexHull + Delaunay.find_simplex for point-in-hull test. World origin (min_cx * 16, min_cz * 16) is stored in checkpoint params after stage_load so coordinate conversion survives resume. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Heightmap saturation: land heights were normalized against the 98th percentile of all pixels including ocean cells (at sea_level=0). For flat worlds, mountains occupy the top 5-15% of land, so they all clamped to full red. Fix: exclude ocean pixels from land stats and use hi_pct=100.0 (full range normalization). Same fix applied to below-sea gradient. Sea level offset: previous implementation deepened the ocean basin by clamping heights in mesh.py. Correct semantics: pretend sea level is N blocks lower, so shallow seafloor (cells > effective_sea_level) is exposed as terrain. build_ocean_mask, remove_micro_islands, and apply_ocean_mask all now use effective_sea_level = sea_level - offset. The printed ocean basin naturally forms at the effective sea level floor; fill with resin and its surface aligns with the real sea level on the model. Config file: at startup, user can optionally provide a path to a previously saved config.json to pre-fill all prompts. After answering all prompts, config is saved to <out_dir>/config.json automatically. Checkpoint detection now runs regardless of whether a config was loaded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Unattended mode: pass --config=path.json on the CLI (or enter a path at the config prompt) to run fully non-interactively. All prompts are skipped and values are taken directly from the JSON. Missing required fields (save_path, out_dir) produce a clear error and exit. The checkpoint resume prompt is also skipped when a config is loaded. Config bug fix: checkpoint detection inside collect_params is now guarded by `if saved is None:` again, so loading a config file is never silently overridden by a stale checkpoint in the same output directory. Smart checkpoint invalidation: after cp.load(), the new run's params are compared against the stored ones. Only the affected downstream stages are unmarked: - save_path / ground_only / detect_floating changed → unmark from loaded - ocean/masking params changed → unmark from processed - sigma/gamma/image dims changed → unmark image only - STL dims (z, base, max_verts) changed → unmark stl - tile dims changed → unmark mosaic + delete tile files Keep intermediate files: heightmap_raw.npy, heightmap_work.npy, and ocean_mask.npy are no longer deleted after a successful run. This allows re-running with a different sigma/gamma to regenerate only image+STL+tiles without re-parsing 1444 region files. stage_process restores the detected sea_level into params during the resume (skip) path so stage_image always has a correct sea level reference. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er reprocess - ocean.py: skip polygons entirely outside heightmap bounds (negative mgrid dims) - mc_to_stl.py: restore _min_cx/_min_cz from checkpoint on resume - mc_to_stl.py: unmark image/stl/mosaic after stage_process completes fresh so stale outputs from a prior crashed/wrong run are always regenerated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…utput Bug fix: _min_cx/_min_cz (block-coord origin for polygon masking) were lost whenever stage_load resumed from cache, because cp.set_params() in main() overwrote checkpoint state before stage_load had a chance to restore them. Fix: preserve all _-prefixed internal keys from checkpoint before overwriting, and restore _min_cx/_min_cz in stage_load's resume path. Feature: generate_image() now also writes heightmap_gray.png alongside the color PNG. Ocean = black, land = linear grayscale (darkest=lowest, white=highest). stage_image regenerates if grayscale is missing (upgrade path). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The root cause: build_ocean_mask was called with effective_sea_level (= sea_level - offset). On the Westeros/Essos map, ocean water sits at Y=63 (standard MC sea level). With offset=2, effective=61, so ALL surface water (Y=62-63) was excluded from the ocean mask and appeared as flat green land in the image. Only deep water at Y≤61 (21%) was masked blue — the polygon (ignore.json) appeared as the only ocean because it forced cells into the mask explicitly. Fix: decouple ocean DETECTION from ocean FLATTENING. - build_ocean_mask and remove_micro_islands now use sea_level (original), so the full coastline is always detected correctly. - apply_ocean_mask still uses effective_sea_level, so the STL basin is sea_level_offset blocks deeper than sea level (fill with resin). - apply_polygon_masks now uses effective_sea_level for consistency. - stage_image now passes sea_level (not eff_sl) to generate_image, so the colour reference matches the real coastline. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ng + blue ocean Replace red-green-blue elevation gradient with: - Grayscale land (2nd-98th percentile normalised, lighter = higher) - Directional hillshading replicating Unmined's CalcShading algorithm (3x3 weighted kernel, sun_angle=120deg, factor range ~0.66-1.34) - Uniform steel-blue ocean overlay - Drop unused gamma parameter (no longer needed for grayscale scheme) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rm grayscale - Always resample to exact (out_w × out_h): previously zoom was skipped when scale >= 0.999, so images stayed at native block resolution even when max_px was configured for larger/smaller output - Apply 3x3 median filter before rendering to remove isolated deep-pixel anomalies (cave mouths, ravines, missing chunks) that survived Gaussian - Remove hillshading — color now maps purely to elevation with no directional bias, making the image a reliable working reference - Both heightmap.png and heightmap_gray.png now use the same 2nd-98th percentile normalisation (gray previously used full min..max range) - Remove unused _unmined_hillshade helper and gamma parameter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- force_scan: bypass stale stored Heightmaps NBT by always scanning block sections (matches Unmined behaviour); disables chunk cache - crop_poly: 4-corner quadrilateral in block coords filters region files and masks outside-polygon pixels to global min height - image: use strict global min→black, max→white instead of 2nd-98th percentile, eliminating the mountain plateau at 255 - mesh: flip rows before meshing so north maps to Y=max (back of print bed), fixing the Y-axis mirror in single STL and mosaic tiles Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- image: new elevation color scheme (dark blue → sea green → red);
ocean cells remain steel-blue; both PNG outputs support RGBA alpha
when rectangular_crop=False (outside crop polygon → transparent)
- mesh: replace max_z_mm with z_exaggeration (float, default 1.0 = same
scale as XY); actual Z = h_range * xy_scale * z_exaggeration
- config: unified sectioned JSON format with "configuration", "crop_area"
(single polygon), and "sea_masking" (list of polygons) sections;
backward compat reads old flat format automatically; polygon_json file
is inlined into sea_masking on first run
- ocean: apply_polygon_masks accepts new [[x,z],...] format alongside
legacy {"coordinates":...} dicts
- loader: _crop_to_polygon returns crop_mask (bool array); load_save
returns (hm, meta, crop_mask) 3-tuple
- stage_load: saves crop_mask to .crop_mask.npy; reloads on resume
- stage_image: receives crop_mask; passes rectangular_crop flag
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The sea-masking prompt was refactored to use input() directly in interactive mode, leaving _ask_str with no callers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pressions Problem: regions below sea level that are terra (not water) were marked as ocean. Solution: add detect_water_blocks mode that scans block types during parsing. - anvil.py: add _is_water() and _water_map_from_sections() to identify water blocks - anvil.py: add parse_region_with_water() returning both heightmaps and water maps - loader.py: extend _parse_worker() and load_save() to optionally build water maps - loader.py: add _assemble_water_map() to stitch water chunks into full array - ocean.py: add water_map parameter to build_ocean_mask(); filters candidates - mc_to_stl.py: add detect_water_blocks prompt and parameter passing - mc_to_stl.py: stage_load() and stage_process() handle water_map caching When detect_water_blocks=True (opt-in), ocean detection requires BOTH: 1. height <= sea_level AND 2. block type is water This prevents terra depressions (e.g. canyons) below sea level from being marked ocean. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…anations - Add 'Water block detection' section explaining detect_water_blocks - Add 'Force scan' section explaining how to fix stale chunk data - Update 'Heightmap image' section with rectangular_crop explanation - Update 'STL physical dimensions' with z_exaggeration examples and border_width - Add 'Crop polygon and sea masking' section with format examples - Rewrite 'Example config.json' with inline comments for each parameter - Add 'Key parameter explanations' section summarizing all config options - Update Tested worlds section to reflect WesterosEssos at 16k scale Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
More options and diagnostics