Skip to content

Render a minimap of the world - MINALAC-86 - #161

Open
naulan-chrzaszcz wants to merge 2 commits into
mainfrom
naulan/minimap
Open

Render a minimap of the world - MINALAC-86#161
naulan-chrzaszcz wants to merge 2 commits into
mainfrom
naulan/minimap

Conversation

@naulan-chrzaszcz

@naulan-chrzaszcz naulan-chrzaszcz commented Nov 28, 2025

Copy link
Copy Markdown
Member

Issue

MINALAC-86

Changes

Creation of a data structure for representing a 3D world as a miniaturized 2D representation.
This data structure is a class named Minimap.
The Minimap class includes a heightmap to enable 2.5D rendering.
It also includes a resampling system allowing both downscaling and upscaling.

The Minimap itself does not perform operations; these are handled by external tasks, which are as follows:

Before explaining the tasks that allow operations on the minimap, I need to introduce a different behavior for tasks. Some tasks are executed during each tile (this has not changed), but now there are also tasks that can be executed anywhere, including outside tiles.

Tasks that are executed during each tile:

  • populateMinimap: fills a specified minimap with colors. Example configuration:
populateMinimap:
  type: populateMinimap
  minimap: overworld
  color:
    a: #FFFFFF

Tasks that are exécutes anywhere:

  • applyShadingMinimap: applies a 2.5D effect by using the minimap’s heightmap to cast shadows on the terrain.
    The sun direction and shadow intensity can be adjusted.
  shadingMinimap:
    type: applyShadingMinimap
    minimap: overworld
    shadowIntensity: 0.6
    sunDirection: 180
  • saveMinimap: exports the data of a minimap into a file format supported by the Java ImageIO class.
  saveMinimap:
    type: saveMinimap
    minimap: overworld
    format: png
    destination: overworld-minimap.png

Of course, multiple Minimaps can be created using a MinimapStore:

minimaps:
  overworld: {}
  onlyWater:
    size: 200

Minimaps declared in the MinimapStore are accessible throughout the entire generation process.

Feature description

PopulateMinimapTask

Cette tâche calcule la couleur finale pour les coordonnées de chaque voxel.
Elle implémente la composition alpha (Alpha Compositing) pour mélanger les voxels semi-transparents (comme l'eau ou le verre) jusqu'à ce que le pixel atteigne une opacité totale.

SaveMinimapTask

Exporte la minimap générée dans un fichier au format d'image supporté par la classe Java ImageIO, à l'emplacement spécifié relativement au dossier du monde.
Applique une ombre basé sur la hauteur lors de exportation.

Note

Chaque tâche décrite dispose de son paramétrage dédié.

Minimap & MinimapStore

Minimap permet la projection du monde 3D en une image 2D. Pour gérer de très grands mondes tout en respectant une limite maxSize, chaque pixel distribue ses données sur les 4 pixels les plus proches en utilisant des poids bilinéaires.

Le MinimapStore est ajouté à Generation pour contenir et gérer plusieurs instances de minimaps.

Note

La classe Minimap ne dispose pas de paramétrage propre ; ce sont les tâches PopulateMinimapTask et SaveMinimapTask qui permettent d'effectuer des opérations sur ses données.

Voxel

Cette interface permet d'identifier via un String (pour l'instant) un Placeable.
Permet d'exposer l'attribut type de MCVoxel et de MTVoxel.

ColorDeserializer

...

Showcase

Montagne de La Meije
overworld-minimap
Saint-Mandé - IGN
overworld-minimap

Self-checks

  • The code has unit tests associated
  • The code has Javadoc Comments associated
  • Complex / Unexpected code is explained / justified with a small comment
  • Relevant documentation inside the /docs folder has been updated
  • All examples in examples/ work the same (or have been adapted if subject to changes in this PR)
  • Git history is clean (each commit accomplish a single task and describe it accordingly)
  • The texts have been proofread (documentation, error messages, logs, comments...)

@github-actions

github-actions Bot commented Nov 28, 2025

Copy link
Copy Markdown

[Maven Build Status]

📑 Commit: cd163ec10951ef2a32543f60b0f6497e89e441d1
⌚️ Date: 2026-07-23T12:25:15 (CEST)
🛠️ Status: ✅ Success

📦 Download artifact: Generator.jar

@naulan-chrzaszcz
naulan-chrzaszcz force-pushed the naulan/minimap branch 8 times, most recently from 2d43f7f to b7506da Compare February 3, 2026 11:55

@pyrollo pyrollo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quelques commentaires déjà

Comment thread examples/formats/minetest.yaml Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/outputs/Voxel.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/tasks/PopulateMinimapTask.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/world/VoxelWorld.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/generation/Generation.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/generation/Minimap.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/generation/Minimap.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/tasks/PopulateMinimapTask.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/tasks/PopulateMinimapTask.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/tasks/PopulateMinimapTask.java Outdated
@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Proposition paramétrage:

# minetest.yaml

&main-minimap-colors
- *voxel-stone: [122, 74, 57]
---
# full.yaml

# ...
minimaps:
  main:
    size: 1000
    shadows: true
    colors: *main-minimap-colors

forEachTile:
  # ...
  populateMinimap:
    type: populateMinimap
    minimap: main
    after:
      - renderWater
      - renderForest
      - renderGround
      - renderBuildings

@ignfab/minalac

@indyteo

indyteo commented Feb 5, 2026

Copy link
Copy Markdown
Member

D'abord une remarque basique sur ce paramétrage :
En fait, au niveau des couleurs, tu seras limité car dans notre paramétrage ("à cause" de Jackson) tu ne peux avoir que des scalaires en clé (nombre, string...), pas d'objet. Du coup, il se peut que certains voxels ne puissent pas être représentés en clé. En plus, en cas de doublon (genre 2 ancres différentes sont associées au même voxel subitement), ça ferait une erreur.
Je verrais plutôt quelque chose de la sorte :

references:
  - &main-minimap-colors
    - voxel: *voxel-stone
      color: [ 122, 74, 57 ]
    - voxels: [ *voxel-tree-1, *voxel-tree-2 ]
      color: #00ff00
    - filter: # notion de "voxel/placeable filter" qui pourra être factorisée avec le only/neverInsteadOf (difficulté possible : dépend du format)
        node: wood_slab
        ignoreParam1: true
        ignoreParam2: true
      color: brown

Bien entendu la partie filter serait ajoutée plus tard, mais ce que je voulais montrer c'était qu'adopter cette structure nous permettrait de le faire, contrairement au mapping 1:1 simple.

Ensuite, question simple : Comment sont traités les voxels inconnus (pour lesquels aucune couleur n'a été associée ici) ? Peut-être qu'un paramètre "unknownVoxelColor" pourrait être indiqué sur la minimap (et dont la valeur serait "transparent" par défaut).
Similairement, on peut se poser la question concernant la couleur du fond (l'équivalent du defaultValue sur les heightmaps, ici "defaultColor"), qui pourrait être un paramètre, également "transparent" par défaut.

Après, une interrogation un peu plus délicate (ou pas ?) : On peut paramétrer la taille de la minimap, mais est-ce qu'on pourrait facilement paramétrer sa fenêtre aussi ? C'est-à-dire, la zone qui est représentée sur la minimap. Ça pourrait être à partir d'une taille en voxels autour du centre de la génération, avec un offset optionnel, par exemple.
Je pense que ça ne poserait pas de gros problème, mais il faudra revoir la logique du calcul qui transforme les positions dans le monde en positions dans la minimap, et intégrer une logique de "cette position est en dehors de la minimap, on ignore"...

Enfin, une remarque que je me suis fait mais qui pourra être utile plus tard (toutefois je ne pense pas qu'elle pose le moindre soucis au niveau de la conception actuelle, je pense que ça marchera sans problème le jour où on décidera de l'implémenter), c'est de pouvoir "dessiner" en quelque sorte sur la minimap, avec des tâches un peu comme celles qui font le rendu. En gros, importer les polygones des limites administratives, et les rendre sur la minimap, sans pour autant qu'ils apparaissent en jeu. Ou alors ajouter des lignes de hauteur, ou des toponymes, pictogrammes... qui ne sont pas issus de voxels dans le monde, mais ajouté en surplus sur la minimap.
On pourrait même s'en servir pour intégrer un petit logo "IGN" dans un coin :)

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Comment sont traités les voxels inconnus (pour lesquels aucune couleur n'a été associée ici) ?

@pyrollo avait comme idée que lors qu'un voxel ne possède pas de couleur, l'alpha sera a 0.

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

En gros, importer les polygones des limites administratives, et les rendre sur la minimap, sans pour autant qu'ils apparaissent en jeu. Ou alors ajouter des lignes de hauteur, ou des toponymes, pictogrammes... qui ne sont pas issus de voxels dans le monde, mais ajouté en surplus sur la minimap.

L'idée est pas mal, je le note pour plus tard.

@indyteo

indyteo commented Feb 5, 2026

Copy link
Copy Markdown
Member

@pyrollo avait comme idée que lors qu'un voxel ne possède pas de couleur, l'alpha sera a 0.

C'est un choix qui me parait pertinent oui, mais qui n'empêche pas pour autant de le rendre paramétrable (et la valeur par défaut de ce paramètre serait "transparent"). Un intérêt que je vois par exemple serait :
Je veux visualiser sur ma minimap tous les éléments en sursol, c'est-à-dire tout ce qui est en plus du sol. Je mets donc une couleur transparente à l'air, l'eau, la terre et la pierre, puis le mets la couleur par défaut des voxels à une couleur solide (genre noir). J'obtiens donc un masque de tous les voxels, sans le sol.

Je ne dis pas que ça serait particulièrement utile pour nous, mais juste que c'est trivial à implémenter (je pense), et ça offre cette possibilité en plus, sans imposer de paramétrage supplémentaire si on n'en n'a pas besoin

@indyteo

indyteo commented Feb 5, 2026

Copy link
Copy Markdown
Member

La question de la minimap soulève une question plus large relative à la sémantique des voxels. Un bâtiment pourrait être construit avec un mélange de stone et stonebricks, tandis que le sol aurait de la dirt et de la stone, et ainsi on retrouverait un voxel "stone" qui serait le même, mais dont la sémantique devrait être différente.

En soit, le problème ne se poserait que lorsqu'on voudrait faire disparaître les bâtiments mais pas le sol, ou inversement. Dans un premier temps on peut se contenter d'ignorer le problème en disant que l'usage premier des minimaps est de représenter le contenu réel du monde, et on verra plus tard si l'usage évolue

@naulan-chrzaszcz
naulan-chrzaszcz force-pushed the naulan/minimap branch 5 times, most recently from c4c976f to fb55c41 Compare February 26, 2026 13:44
@naulan-chrzaszcz
naulan-chrzaszcz force-pushed the naulan/minimap branch 5 times, most recently from 6773373 to cd9381f Compare March 6, 2026 08:27
@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Quand j'utilise l'algorithme de l'interpolation bilinéaire, voici mes resultats :

Exemple d'upscaling :

  • Taille du monde : 500*250
  • Taille max de la minimap : 1000px
  • Resultat :
overworld-minimap

Exemple downscaling :

  • La taille du monde : 2000*1000
  • La taille max de la minimap (pour width et height) : 1000
  • Resultat :
overworld-minimap

@naulan-chrzaszcz naulan-chrzaszcz left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Des commentaires à moi même

Comment thread src/main/java/com/ignfab/minalac/generator/MinalacGenerator.java Outdated
Comment thread docs/usage/parameters/Minimap.md Outdated
Comment thread docs/usage/parameters/Tasks.md Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/tasks/SaveMinimapTask.java Outdated
Comment thread docs/usage/parameters/Minimap.md Outdated
Comment thread docs/usage/parameters/Parameters.md Outdated
Comment thread docs/usage/parameters/Tasks.md
Comment thread docs/usage/parameters/Tasks.md Outdated
@indyteo

indyteo commented Jul 2, 2026

Copy link
Copy Markdown
Member

Quand j'utilise l'algorithme de l'interpolation bilinéaire, voici mes resultats :

Hmm intéressant, ça veut donc dire que j'ai dû oublier quelque chose. Ou alors ça révèle un problème dans l'implémentation de l'interpolation bilinéaire, mais ça avait l'air plutôt correct la dernière fois que j'avais regardé. Dans tous les cas comme j'ai dit, maintenant que tu as un algorithme qui marche bien, garde-le et on verra ensuite ce qu'on peut/veut faire.

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Hmm intéressant, ça veut donc dire que j'ai dû oublier quelque chose. Ou alors ça révèle un problème dans l'implémentation de l'interpolation bilinéaire, mais ça avait l'air plutôt correct la dernière fois que j'avais regardé. Dans tous les cas comme j'ai dit, maintenant que tu as un algorithme qui marche bien, garde-le et on verra ensuite ce qu'on peut/veut faire.

Je vais ressayer voir si mon code pour l'interpolation bilinéaire n'est pas foireux (au cas où)

@pyrollo

pyrollo commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Pourquoi je dis ça, parce qu'avec le MNT par exemple on est déjà capable de le rééchantillonner à n'importe quelle échelle puisqu'on supporte la rotation. Et notre code consiste en une simple interpolation bilinéaire.

Je pense que la solution doit être simple, mais il y a une différence notable entre ce qu'on fait pour le MNT et ce qui est fait ici.

Pour rééchantillonnage du MNT, on parcourt la destination or ici, on parcourt la source. Donc tout est un peu différent.

Toutes ces circonvolutions par différents algorithmes ne résoudront pas le problème de base qui est un problème de parcours tout simplement ( = dans quels pixels mon voxel va aterrir).

Comment thread src/main/java/com/ignfab/minalac/generator/generation/minimaps/Minimap.java Outdated
@indyteo

indyteo commented Jul 2, 2026

Copy link
Copy Markdown
Member

Toutes ces circonvolutions par différents algorithmes ne résoudront pas le problème de base qui est un problème de parcours tout simplement ( = dans quels pixels mon voxel va aterrir).

En fait oui voilà c'est ça le problème. De mémoire ton interpolation bilinéaire faisait un calcul "hardcodé" pour répartir le voxel entre 4 pixels de la minimap, ce qui marchera forcément en downscaling puisqu'au mieux ton voxel est pile poil sur 1 pixel et les 3 autres ont un poids de 0, et au pire il est entre les 4 donc réparti sur ces 4 avec des poids appropriés.
Là, pour l'upscaling, ta logique d'interpolation peut rester la même, sauf qu'elle ne doit pas se faire uniquement sur 4 pixels, elle doit couvrir tous les pixels intersectant avec le voxel (vu du dessus). Et donc, si un voxel est 2x plus gros qu'un pixel, et qu'il est pile poil entre 4 pixels (donc centre du voxel entre les pixels), ça aurait marché (et chacun aurait reçu la couleur à poids égal), mais je crois qu'on est plutôt dans un cas où le centre du voxel est aligné avec le centre d'un pixel, donc à une échelle 2 il intersecte 9 pixels (dis-moi si c'est clair ou si besoin d'un dessin), qui devrait tous recevoir la couleur du voxel (avec un poids de 1 pour celui du milieu, et des poids de 0.5 et 0.25 pour les côtés et les angles).
Donc la difficulté réside dans le fait de trouver la bonne "emprise" du voxel sur ta minimap, c'est-à-dire quels pixels doivent être affectés par sa couleur.

Bon ça c'était la théorie, en pratique gardes ton algorithme actuel (sauf si il détruit les performances, certes), et on verra plus tard si on a envie de revenir là dessus

@pyrollo

pyrollo commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Bon ça c'était la théorie, en pratique gardes ton algorithme actuel (sauf si il détruit les performances, certes), et on verra plus tard si on a envie de revenir là dessus

A mon avis, ce serait bien mieux de revenir à l'algo bilinéaire qui a l'avantage d'être plus simple.

EDIT: ha ! c'est déjà fait :)

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

EDIT: ha ! c'est déjà fait :)

Spoiler : fonctionne pas. (J'ai juste poussé tel quel, je regarde ce que je peux faire de mon côté '-_-)

@indyteo

indyteo commented Jul 2, 2026

Copy link
Copy Markdown
Member

Spoiler : fonctionne pas.

La raison est expliquée dans mon message juste au dessus (c'est ce qu'à évoqué Pierre-Yves en parlant de "parcours"). J'ai essayé de formuler une explication un peu compréhensible, essayes de voir si tu arrives à comprendre ce que j'ai raconté, sinon dis-moi je ferais un dessin ça devrait aider

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Spoiler : fonctionne pas.

La raison est expliquée dans mon message juste au dessus (c'est ce qu'à évoqué Pierre-Yves en parlant de "parcours"). J'ai essayé de formuler une explication un peu compréhensible, essayes de voir si tu arrives à comprendre ce que j'ai raconté, sinon dis-moi je ferais un dessin ça devrait aider

Okay pour un dessin

@indyteo

indyteo commented Jul 2, 2026

Copy link
Copy Markdown
Member
image

En noir, la grille représente les pixels de la minimap. Les points gris en leur centre sont les références de leurs coordonnées.

En rouge, tu vois 2 voxels représentés dans un cas de downsampling (avec un facteur 0.5, donc 1 voxel fait la moitié de la taille d'un pixel). Le voxel rouge du haut est entre 2 pixels, celui du bas est entre 4 pixels. Tu vois bien que tu peux réduire autant que tu veux la taille des voxels par rapport aux pixels (donc "downsampler" autant que tu veux), tu n'auras au pire que 4 pixels entre lesquels répartir ton voxel. Donc, ton approche hard-codée avec interpolation bilinéaire entre 4 coins marchera toujours.

En bleu, tu vois 1 voxel représenté dans un cas d'upsampling (avec un facteur 2, donc 1 voxel fait le double de la taille d'un pixel). Le voxel bleu intersecte avec 9 pixels. Et plus tu vas augmenter la taille des voxels par rapport aux pixels (donc "upsampler"), plus ton voxel couvrira de pixels. Il te faut donc une approche dans laquelle tu vas parcourir tous les pixels qui intersectent avec le voxel pour leur affecter tout ou partie de sa couleur (avec un poids qui dépend de l'interpolation).

@naulan-chrzaszcz

naulan-chrzaszcz commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

Bon pour conclure avec mes comparaison d'algorithme, j'ai perdu du temps.
Je voulais trouver un algorithme qui avait une page wikipédia (pour simplifier la documentation et la comprehension de l'algorithme), mais, mes recherches sur plusieurs IA n'a pas conclus vers quelque chose.
Donc, ce qu'on fait c'est de l'interpolation bilineaire mais pas vraiment.

Pour le rendu du derniers algorithme testé, qui sera définitif pour le minimap (pour cette PR en tout cas) :

Exemple d'upscaling :

  • Taille du monde : 500*250
  • Taille max de la minimap : 1000px
  • Résultat :
overworld-minimap

Exemple de downsampling :

  • Taille du monde : 2000*1000
  • Taille max de la minimap : 1000px
  • Résultat :
overworld-minimap

Mise a part si il y a des optimisations a faire sur l'algo utilisé, je ne change plus cette partie de la minimap.

Pour plus de rendu avec l'algorithme : #161 (comment)

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

J'ai quelque relecture à faire sur mon code.
Et quelque request changes à appliquer pour que cette PR soit prête pour une deuxième passe par vous 👍

@indyteo

indyteo commented Jul 3, 2026

Copy link
Copy Markdown
Member

Bravo, ça rend super bien et d'après ce que je vois de tes rendus, ça semble être correct pour la gestion du resampling. Bien joué !

Je ferais une relecture tout à l'heure si j'ai le temps (et que tu as fini ta relecture à toi), sinon peut-être dans l'avion demain ça m'occupera x)

@pyrollo

pyrollo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor
* Taille du monde : 500*250

* Taille max de la minimap : 1000px

Fais tout de même un test avec un upscaling de malade pour vérifier que ça marche (genre 10x ou 20x)

@pyrollo

pyrollo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Et attention, dans tes deux tests, tu utilises des valeurs bien particulières qui peuvent masquer des problèmes (tu fais /2 et *2). Donc utilise des trucs plus tordus, tu risques d'avoir de nouvelles surprises.

Comment thread src/main/java/com/ignfab/minalac/generator/generation/minimaps/Minimap.java Outdated
@pyrollo

pyrollo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Ton défaut de pixels bleu et rose semble ne se produire que sur des surfaces claires. Peut être un indice que c'est une question de calcul de couleur ?

image

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Bon j’abandone cette PR pendant un p'tit moment

@naulan-chrzaszcz

Copy link
Copy Markdown
Member Author

Ton défaut de pixels bleu et rose semble ne se produire que sur des surfaces claires. Peut être un indice que c'est une question de calcul de couleur ?
image

C'est fixé sur mon dernier push

@pyrollo

pyrollo commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Ton défaut de pixels bleu et rose semble ne se produire que sur des surfaces claires. Peut être un indice que c'est une question de calcul de couleur ?

C'est fixé sur mon dernier push

C'était dû à quoi ?

@pyrollo

pyrollo commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Bon j’abandone cette PR pendant un p'tit moment

On en fait quoi du coup ?

@zhak5388 zhak5388 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quelques questions, remarques et commentaires (Donc tout n'est pas à prendre en compte) [J'ai pas regardé les tests sur la Minimap]

Commit : cc8eb67

```yaml
minimaps:
# A minimap named 'overworld' using the default settings
overworld: {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simple commentaire. Je tatillonne, je ne suis pas fan de l'écriture {}: ça parait pas intuitif de faire ça pour mettre les valeurs par défaut. Et puis, on l'a très peu utilisé.

En tout cas, c'est correct, et il y a pas le choix de l'utiliser si minimap n'a aucun champ obligatoire (Et ça vaudrait pas le coup de rendre un champ obligatoire)

Comment thread src/main/java/com/ignfab/minalac/generator/generation/minimaps/Minimap.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/generation/minimaps/Minimap.java Outdated
Comment thread src/main/java/com/ignfab/minalac/generator/tasks/PopulateMinimapTask.java Outdated
*
* @see <a href="https://en.wikipedia.org/wiki/Alpha_compositing">Alpha Compositing</a>
*/
private Color alphaComposite(Color previousColor, Color currentColor) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je suis curieux, ça donne quoi avec une surface d'eau peu profonde, on voit un peu le fond?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D'ailleurs, l'histoire des pixels bleus d'en haut c'était quoi?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

D'ailleurs, l'histoire des pixels bleus d'en haut c'était quoi?

C'est les bits d'une couleur qui débordent sur le canal voisin.

Quand tu fais la moyenne des couleurs, il peut arriver que ca soit > 255 donc, j'dois secu le resultat entre une intervale (0 ; 255).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je suis curieux, ça donne quoi avec une surface d'eau peu profonde, on voit un peu le fond?

image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L'eau est au max 4 blocs de profondeur

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La moyenne de valeurs comprises entre X et Y est nécessairement comprise entre X et Y. Est-ce que tu vois ce que je veux dire ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, pour l'eau, merci! (J'avais pas suffisament zoomé haha)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Et oui, pareil, j'arrive pas comprendre comment la moyenne des couleurs peut donner une valeur supérieure à 255 si chaque couleur a une valeur max de 255, il y avait des couleurs qui faisaient plus de 255?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Et oui, pareil, j'arrive pas comprendre comment la moyenne des couleurs peut donner une valeur supérieure à 255 si chaque couleur a une valeur max de 255, il y avait des couleurs qui faisaient plus de 255?

Je travaille avec des nombres a virgule, donc, ils se peut que quelque fois ca soit > 255.

double slopeFactor = 1.0 + Math.atan(computeDirectionalSlope(x, y) * shadowIntensity) / Math.PI;

MinimapCell cell = minimap.get(x, y);
cell.set(

@zhak5388 zhak5388 Jul 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Du coup, je met le yaml demandé ici!

Le NullPointerException est ici. (Testé sur la version cd163ec)

Caused by: java.lang.NullPointerException: Cannot invoke "com.ignfab.minalac.generator.generation.minimaps.MinimapCell.getRed()" because "cell" is null

Le fichier full.yaml :

heightmaps:
  ground:
    default: 0
  water:
    default: 0

minimaps:
  overworld: {}

forEachTile:

  generateWorld:
    type: schedule
    do:
      altitude:
        type: sequence
        do:
        - type: fetchData
          modelType: altitude
          provider:
            type: wmsFloat
            url: https://data.geopf.fr/wms-r/wms
            layer: RGEALTI-MNT_PYR-ZIP_FXX_LAMB93_WMS
        - type: populateHeightmap
          models:
            type: altitude
          heightmap: ground
        - type: setSpawn
          heightmap:
            sum: [ground, 1]
          x: 0
          y: 0

      fetchBuildings:
        type: fetchData
        modelType: buildings
        provider:
          type: wfs
          url: https://data.geopf.fr/wfs/wfs
          features: BDTOPO_V3:batiment
          maxFeaturesPerQuery: 500
        postProcessing:
          - type: copy
            metadata: hauteur
            to: height
          - type: parse
            metadata: height
            as: decimal
            ifMissing: ignore
            ifNotParsable: removeMetadata
          - type: truncate
            metadata: height
            method: round
            ifMissing: ignore
          - type: default
            metadata: height
            value: 5
            as: integer

      fetchWater:
        type: fetchData
        modelType: water
        provider:
          type: wfs
          url: https://data.geopf.fr/wfs/wfs
          features: BDTOPO_V3:surface_hydrographique

      fetchRoads:
        type: fetchData
        modelType: road
        provider:
          type: wfs
          url: https://data.geopf.fr/wfs/wfs
          features: BDTOPO_V3:troncon_de_route

      flattenWater:
        after:
          - fetchWater
          - altitude
        type: copyHeightmap
        models:
          type: water
        from:
          localMin: ground
          range: 9
        to: ground

      renderGround:
        after:
          - altitude
          - flattenWater
        type: renderHeightmap
        at: ground
        place:
          structure:
            - put: wool:pink
              at: [0, 0, 0]
            - put: wool:pink
              at: [0, 0, -3..-1]
            - put: wool:pink
              at: [0, 0, -20..-4]

      computeBuildingsAltitude:
        after:
          - fetchBuildings
          - renderGround
        type: computeHeightmapStats
        models:
          type: buildings
        heightmap: ground
        compute:
          minimum: minimum-ground-altitude
          maximum: ground-floor-altitude

      flattenGroundBuildings:
        after:
          - computeBuildingsAltitude
        type: fillBetweenHeightmapAndMetadata
        models:
          type: buildings
        heightmap: ground
        altitudeMetadata: ground-floor-altitude
        placeAbove: *voxel-empty
        placeBelow: *voxel-building-ground

      renderBuildings:
        after: flattenGroundBuildings
        type: renderBuildings
        models:
          type: buildings
          filter:
            metadata: height
            greaterThan: 0
        roof: *voxel-cobble
        wall: *voxel-stone
        window: *voxel-glass

      forest:
        type: sequence
        using: renderGround
        do:
          - type: fetchData
            modelType: vegetation
            provider:
              type: wfs
              url: https://data.geopf.fr/wfs/wfs
              features: BDTOPO_V3:zone_de_vegetation
          - type: renderSurfaces
            after: renderGround
            models:
              type: vegetation
              filter:
                metadata: nature
                in:
                  - "Bois"
                  - "Forêt fermée de conifères"
                  - "Forêt fermée de feuillus"
                  - "Forêt fermée mixte"
                  - "Forêt ouverte"
                  - "Zone arborée"
            heightmap: ground
            place:
              - pattern:
                  seed: forest-grass
                  chance: 0.1
                  place:
                    structure:
                      - at: [0, 0, 1]
                        put: *forest-grass
              - *voxel-forest-ground
              - pattern:
                  seed: forest-tree1
                  chance: 0.01
                  place: *forest-tree1
              - pattern:
                  seed: tree2
                  chance: 0.003
                  place: *forest-tree2

      populateWaterPresence:
        after: fetchWater
        type: copyHeightmap
        models:
          type: water
        from: 1
        to: water

      computeWaterDepth:
        after: populateWaterPresence
        type: copyHeightmap
        models:
          type: water
        from:
          remap:
            manhattan: water
            maximumDistance: 12
            targetValue: 0
          mapping:
            0: 0
            1: 1
            2: 8
            3..3: 10
            4..6: 11
            7..12: 12
        to: water

      renderWater:
        after:
          - renderGround
          - computeWaterDepth
          # Vegetation and water vector data overlap in certain areas. (Because of vegetation representing canopy)
          # The dependency and air voxel below should be removed when cropping is implemented on vector data.
          - forest
        type: renderHeightmap
        minimum:
          sum:
            - ground
            - 1
            - product: [ -1, water ]
        maximum: ground
        place:
          structure:
            - put: *voxel-water
              at: [ 0, 0, 0 ]
            # This a dirt fix to remove vegetation on water
            - put: *voxel-air
              at: [ 0, 0, 1..12 ]

      path:
        after:
          - fetchRoads
          - renderGround
          - forest
        type: renderLines
        models:
          type: road
          filter:
            metadata: nature
            in: [ "Chemin", "Sentier", "Route empierrée" ]
        structure:
          - put: *path
            at: [ 0, -1..1, 0]
          - put: *voxel-air
            at: [ 0, -1..1, 1..2 ]

      renderBridges:
        after: path
        type: renderLines
        models:
          type: road
          filter:
            metadata: nature
            in: [ "Bretelle", "Rond-point", "Route à 1 chaussée", "Route à 2 chaussées", "Type autoroutier"]
        renderOnlyWhenAbove:
          sum:
            - ground
            - 1
        structure:
          # Half bridge structure (sectional view)
          axes: [ z, y ]
          blueprint:
            - "▒▒         ▒▒"
            - "▒▒▒▒▒▒▒▒▒▒▒▒▒"
          with:
            "": *voxel-stone
          zOffset: -1

      renderRoadsPass1:
        after: renderBridges
        type: renderLines
        models:
          type: road
          filter:
            metadata: nature
            in: [ "Bretelle", "Rond-point", "Route à 1 chaussée", "Route à 2 chaussées", "Type autoroutier"]
        structure:
          # Road border lines and air to clean eventual voxels (sectional view)
          axes: [ z, y ]
          blueprint:
            - "·········"
            - "·········"
            - "█·······█"
          with:
            "": *road-paint
            "·": *voxel-air

      renderRoadsPass2:
        after: renderRoadsPass1
        type: renderLines
        models:
          type: road
          filter:
            metadata: nature
            in: [ "Bretelle", "Rond-point", "Route à 1 chaussée", "Route à 2 chaussées", "Type autoroutier"]
        structure:
          # Road central line and tar (view from above)
          axes: [ x, y ]
          blueprint:
            - "░░░█░░░"
            - "░░░█░░░"
            - "░░░█░░░"
            - "░░░░░░░"
            - "░░░░░░░"
          with:
            "": *road-paint
            "": *road-tar

  populateOverworldMinimap:
    after: generateWorld
    type: populateMinimap
    minimap: overworld
    colors: *minimap-color-palette

afterAllTiles:

  minimaps:
    type: sequence
    do:
      - type: applyShadingMinimap
        minimap: overworld
      - type: saveMinimap
        minimap: overworld
        destination: overworld-minimap.png
        format: png

Commande lancée :

mvn -Dmaven.test.skip=true clean package && ./generate.sh minetest full ign  $HOME/.minetest/worlds/testo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: medium Neither small nor big change, will require some time to review To review type: enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants