silk

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2022 License: Apache-2.0 Imports: 4 Imported by: 0

README

Go Reference SCS - Engineering

Silk

Silk is an N-dimensional implementation of the wave function collapse algorithm. This utility was largely inspired by the work of Maxim Gumin and his WaveFunctionCollapse repository.

Silk aims not only to provide a flexible implementation of the algorithm, but also provide out-of-the-box for some common data types/use-cases. Currently Silk only supports generating 2D images, but a user is able to implement their own silk.Shuttle for other data types/dimensions.

Silk CLI

Silk comes with a CLI that can use the provided silk.Shuttle implementations to generate outputs. The CLI can be installed with:

go install github.com/split-cube-studios/silk/cmd/silk

Below is the output of silk help:

NAME:
   silk - Generate procedural data with wave function collapse.

USAGE:
   silk [global options] command [command options] [arguments...]

COMMANDS:
   image    Generate an image.
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --help, -h    show help (default: false)
   --seed value  Seed value for the random number generator. (default: 1665169812)

Silk uses subcommands for different datatypes, which each may have different flags. See silk help <command> for more information.

Silk API

Silk can also be used as a library. The silk package provides the core functionality of the algorithm, while the silk/pkg/shuttle package provides some common implementations of the silk.Shuttle interface.

Below is an example of using Silk to generate a 2D image:

package main

import (
    "image"
    "image/color"
    "image/png"
    "os"

    "github.com/split-cube-studios/silk"
    "github.com/split-cube-studios/silk/pkg/shuttle"
)

func main() {

    f, err := os.Open("input.png")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    img, _, err := image.Decode(f)
    if err != nil {
        panic(err)
    }
    
    size := 128
    loom := silk.NewLoom(
        []int{size, size},
        shuttle.NewImageShuttle(
            img,
            shuttle.ImageShuttleOptions{
				W: size,
				H: size,
			},
        ),
    )

    if err := loom.Weave(); err != nil {
        panic(err)
    }
}

Samples

Command Input Output (Progression) Output (Final)
silk image --input ./samples/lines.png -a -r xy Input Output Output
silk image --input ./samples/island.png -a -r x Input Output Output

Contributing

Contributions are welcome! Contribution guides are coming soon.

Documentation

Overview

Package silk provides an N-dimensional implementation of the wave function collapse algorithm. This package was largely inspired by the work of Maxim Gumin seen here: https://github.com/mxgmn/WaveFunctionCollapse.

The package provides two levels of abstraction around the algorithm. The first (and primary) way to use silk is through the Loom type. The Loom type internally configures and collapses a wave function through a simple API. The Loom type uses a Shuttle interface to produce a propogator for the wave, as well as interpret the wave result. Out-of-the-box shuttles are provided under github.com/split-cube-studios/silk/pkg/shuttle.

Below is a simple example of how one may use silk in their own project:

size := []int{128, 128} // size can be any number of dimensions
loom := silk.NewLoom(size, myShuttle) // myShuttle may be a custom implementation, or one of the provided shuttles
if err := loom.Weave(); err != nil {
	panic(err)
}

Index

Constants

This section is empty.

Variables

View Source
var ErrWaveFullyCollapsed = errors.New("wave fully collapsed")

ErrWaveFullyCollapsed is returned from Wave.Step when called on a fully collapsed wave function.

View Source
var ErrWaveParadox = errors.New("wave paradox")

ErrWaveParadox is returned from Wave.Step when a paradox is encountered.

Functions

func CoordsToIndex

func CoordsToIndex(coords, dims []int) int

CoordsToIndex converts a set of n-dimensional coordinates to an index.

Types

type Loom

type Loom struct {
	Shuttle
	*Wave
}

Loom is the primary way to use silk. A loom is initialized with a shuttle and a set of working dimensions. When *Loom.Weave() is called, the loom will collapse the wave function completely and pass each observation result to the shuttle.

func NewLoom

func NewLoom(dims []int, shuttle Shuttle) *Loom

NewLoom initializes a new *Loom with the given shuttle and working dimensions.

func (*Loom) Weave

func (l *Loom) Weave() error

Weave will collapse the wave function completely. As the wave function collapses, the shuttle will be called with the result of each observation.

type ObservationHeuristic

type ObservationHeuristic byte

ObservationHeuristic a type is the mode of state selection for observation.

const (
	// HeuristicRandom selects a random state.
	ObservationHeuristicRandom ObservationHeuristic = iota
	// HeuristicMinEntropy selects the state with the lowest entropy.
	ObservationHeuristicMinEntropy
	// HeuristicMaxEntropy selects the state with the highest entropy.
	ObservationHeuristicMaxEntropy
)

type Shuttle

type Shuttle interface {
	// Propogator accesses the shuttle's wave propogator and returns
	// a slice of all compatible states c for a given state t in direction d.
	Propogator(d, t int) []int
	// ObservationHeuristic returns which heuristic to use for the wave's observations.
	ObservationHeuristic() ObservationHeuristic
	// Weights returns a slice of weights for each state.
	Weights() []float64
	// Directions returns a slice of directional offsets for traversing the wave function.
	// Each offset in the slice is a vector of offsets along each dimension.
	// Opposite directions are sequential, ie index 0 and index 1 are opposite directions.
	// For example, a 2D wave function with 4 directions could return:
	// [][]int{
	// 	[]int{0, -1},
	// 	[]int{0, 1},
	// 	[]int{1, 0},
	// 	[]int{-1, 0},
	// }
	Directions() [][]int
	// Weave is called for each observation of a wave function.
	// The shuttle should interpret the wave function and produce an output.
	// The done parameter indicates whether the full collapse has completed.
	Weave(coefficients [][]bool, done bool) error
}

Shuttle is an interface responsible for defining wave propogation rules, as well as interpreting the results of a wave function.

In a general sense, a shuttle describes the data a wave function represents. For example, a shuttle output may be a 2D image, and the wave function might represent the image's pixel values.

type ShuttlePatternProvider

type ShuttlePatternProvider struct {
	// ShuttlePatternProviderOptions are the options used to initialize the provider.
	ShuttlePatternProviderOptions

	// Patterns is a slice of all possible patterns.
	Patterns [][]int
	// Weights is a slice of weights for each pattern.
	Weights []float64
	// Directions is a slice of directional offsets for traversing the wave function.
	Directions [][]int
	// contains filtered or unexported fields
}

ShuttlePatternProvider exposes helper functions for pattern/feature extraction. The provider operates on N-dimensional slices of integers. Each integer represents a possible state in the wave function. If the provider does not support the needs of a given project, the user is able to use custom logic in their shuttle implementation. PRs are also welcome!

func NewShuttlePatternProvider

func NewShuttlePatternProvider(opts ShuttlePatternProviderOptions) *ShuttlePatternProvider

NewShuttlePatternProvider initializes a new shuttle pattern provider with the given options.

func (*ShuttlePatternProvider) WavePropogator

func (p *ShuttlePatternProvider) WavePropogator() WavePropogator

WavePropogator returns a propogator function for the pattern provider's input data.

type ShuttlePatternProviderOptions

type ShuttlePatternProviderOptions struct {
	// N is the size of the pattern. N defaults to 3.
	N int
	// Dims is a slice of dimensions for the input data.
	Dims []int
	// Data is a slice of integers representing the input data.
	Data []int
	// Reflections is a slice of axis indices to reflect patterns across.
	Reflections []int
}

ShuttlePatternProviderOptions are options for the shuttle pattern provider.

Features/patterns are extracted from the input data in length N volumes in the given dimensions. The extraction process uses a sliding window, so features may overlap. Features are then deemed compatible if their values overlap in a given direction.

Using the weight of each feature and the compatibility of each feature pair, a WavePropogator is generated for the shuttle.

type Wave

type Wave struct {
	WavePropogator
	ObservationHeuristic
	// contains filtered or unexported fields
}

Wave is a silk wave function. A wave may be N-dimensional. Waves can be collapsed iteratively or all at once with a given heuristic.

func NewWave

func NewWave(p WavePropogator, h ObservationHeuristic, weights []float64, dims []int, directions [][]int, cb WaveObservationCallbackFn) *Wave

NewWave creates a new silk wave function. The wave function is N-dimensional. An optional callback can be provided, which will be called upon each observation.

func (*Wave) Observe

func (w *Wave) Observe(n int) error

Observe will observe the wave function n amount of times. Each observation will collapse regions of the wave to a single state. Observe will run until the wave function is fully collapsed when n is -1. ErrWaveFullyCollapsed is returned when Observe is called on a fully collapsed wave function, or when n is -1 and the collapse comes to completion. ErrWaveParadox is returned when a paradox is encountered.

func (*Wave) ObserverBus

func (w *Wave) ObserverBus() <-chan float64

ObserverBus returns a channel which indicates the progress of the wave function collapse.

type WaveObservationCallbackFn

type WaveObservationCallbackFn func(coefficients [][]bool, done bool) error

WaveObservationCallbackFn is a callback function which is called upon each observation step.

type WavePropogator

type WavePropogator func(d, t int) []int

WavePropogator is a function which access a static or dynamic wave propogator matrix. The matrix contains compatibility rules for neighboring states in the wave function. The wave propogator matrix is a 3-dimensional matrix of size [d][t][c], where d is the direction, t is the state, and c is the compatible state.

Directories

Path Synopsis
cmd
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL