Code Monkey home page Code Monkey logo

wavefunctioncollapse's Introduction

WaveFunctionCollapse implementation in C

This project was based on the Maxim Gumin's wave function algorithm.

The program determines a bitmap based on the input consisting of smaller tiles (.png) as well as a set of constraints (.xml). The purpose is to create an image that is locally similar to the input images.

Table of contents

Introduction

The name of the algorithm stems from the Quantum Mechanics, where it refers to a behaviour of minuscule particles which gradually determines their position in space. Similar in a broad sense, WaveFunctionCollapse (WFC) determines the orientation and coordinates of input tiles based on initial constraints. Let us consider a simplified example:

  1. The bitmap consists of two spaces for tiles, which can be occupied by any of the four tiles with equal probabilities. The entropy of each space is 4 now. In our model, the algorithm will always choose the minimum not-equal-to-one entropy space and then choose randomly.

  2. Let us say that the right space was chosen with a head occupying it. Now only straight and tail tiles satisfy the neighbourhood rules. The choice of the head tile propagates itself throughout the grid.

  3. The tail is chosen at random. Valid image is determined, collapse terminates.

This execution principle is extended for custom tilesets and sizes of grids. Have a look at the image generated by the tiles inspired by Imperial College London, our home institution:

As you can probably spot, tiles can be rotated and flipped, the grid does not have to be a square, any rectangular shape can be specified.

Local similarity

This means in principle that:

Tiles from the tileset built up the image (ideally all tile types are present in the image at least once, subject to constraints).

Algorithm

Input

The input consists of several files separated into two groups: constraints and images.

Constraints

Constrains is a single .xml file formatted as the following example:

<!-- dir = path_to_directory_with_png_files 
     size_x = width
     size_y = height
     -->

<tiles dir="./graphics/huxley_tiles/" size_x="10" size_y="10">
  
  <!-- each tile box follows the same pattern -->
  
  <!-- neccessary arguments
        file = name of the file 
        top/right/bottom/left = string that will be checked for equality, tiles with equal 
          values can be placed next to each other -->
  
  <!-- optional arguments -->
  
  <!-- flip: 
    1 - add a vertically flipped tile to the tileset
    2 - add a horizontally flipped tile
    3 - add both of the flips -->
  
  <!-- rotate:
    1 - 90 degrees
    2 - 180 degrees
    3 - 270 degrees -->
  
  <tile file="sky.png" top="sky" right="sky" bottom="sky" left="sky"/>

  <tile file="qtr_base.png" top="qtr" right="qtr_base" bottom="pavement" left="sky" flip="2"/>
  <tile file="qtr_balcony.png" top="qtr" right="qtr_balcony" bottom="qtr" left="sky" flip="2"/>
  <tile file="qtr_top_balcony.png" top="qtr_1" right="qtr_top_balcony" bottom="qtr" left="sky" flip="2"/>
  <tile file="qtr_dome.png" top="qtr_2" right="qtr_dome" bottom="qtr_1" left="sky" flip="2"/>
  <tile file="qtr_spire.png" top = "sky" right="qtr_spire" bottom ="qtr_2" left="sky" flip="2" rotate = "1"/>

  <!-- optional constraints that set grid space to a particular tile type
    file = name of the file
    x/y - coordinates of the space (origin is upper left!)
    -->
  
  <constraint file="telephone.png" x="3" y ="9"/>
  
</tiles>

Images

This is a subdirectory with png files of the same width and height (and all square). See the graphics folder in the source.

Execution

  1. Read the input with optional rotations, flips and constraints.
  2. Initialise a 2D array of 64 bitstrings (each bit corresponding to a tile type). True represents that a tile can occupy given space, false - the opposite. We will want all of those to have exactly one-bit set. Without specified constraints, all bitstrings will be set to 11111...
  3. Loop:

3a. Observation: Find elements of minimum entropy greater not equal to 1 (these spaces are already collapsed). If this is positive, go to the next step, otherwise, abort (a valid solution was not found).

3b. Choose the element at random and collapse it (make its entropy 1).

  1. If successfully terminated, we have a valid image generated.

Output

We have implemented a live updated working of the algorithm. It shows the average of pixel colours of each tile possible in an element. Here is an example:

Also the output will be saved as an image in the output.jpg file in the root directory.

Possible extensions

The current state of the project represents 2 weeks of teamwork. We are aware that there are multiple aspects which could be improved, most notably:

  • Setting the relative frequency of the tiles
  • Extending the program to more dimensions (3D)
  • Providing an interactive interface for users
  • Adding more tilesets

If you feel like you would like to contribute, please do not hesitate to message us or submit a pull request. We will gladly provide you with expertise and cooperation!

Getting started

Unfortunately, there is currently no support for Windows, if you would like to contribute in this area please message us!

First you will need to install needed libraries in your terminal:


Ubuntu/Linux:

sudo apt-get install libxml2
sudo apt-get install imagemagick

macOS:

brew install libxml2
brew install imagemagick && brew link imagemagick --force

To build the project using Make run:

make

Provided make ran successfully, run_wfc has been created in the main folder. You can now run the program:

./run_wfc path/to/tileset.xml

We've set up a few sample tilesets for you to try out:

./run_wfc sample_inputs/python.xml
./run_wfc sample_inputs/rpg_map.xml
./run_wfc sample_inputs/huxley.xml

Documentation

The official report is available here, please jump straight to section 3 for relevant information.

References

Credits and licences

Authors:

This project is licensed under the terms of the MIT license, excluding the files listed below:

Tile art in graphics/rpg\_map is Overworld rpg tileset by Tayoko (licensed under CC BY-SA 3.0) available at opengameart.org/content/overworld-rpg-tileset

wavefunctioncollapse's People

Contributors

naras91 avatar skrroll avatar stefanradziuk avatar woocashh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

wavefunctioncollapse's Issues

Minimal C++ compiler compatibility

I'm forced to build with clang++. Every calloc/malloc require typecasting for building with c++.
So I had to typecast every calloc and unfortunately I have to do this every time when you update.
It would be great if you can add the typecasts for minimum C++ compatibility.

Ex:
Coords *minima = calloc(sizeX * sizeY, sizeof(Coords));
to
Coords *minima = (Coords *)calloc(sizeX * sizeY, sizeof(Coords));

About the license...

I'm planning to implement this project(by given you a proper credits of course) as a free(open source) C native extension to Defold game engine.
I couldn't find any license info. Is it MIT? Do you have any license/usage restriction?

MacOS build fail with GLUT Fatal Error

I'm trying to build on MacOS but having a issue with GLUT.
I searched but couldn't find a proper solution. Any idea why is this happens?

GLUT Fatal Error: internal error: NSInternalInconsistencyException, reason: NSWindow drag regions should only be invalidated on the Main Thread!

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.