Skip to content
This repository has been archived by the owner on Dec 22, 2024. It is now read-only.

Commit

Permalink
v0.2.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
matanlurey committed Aug 4, 2024
1 parent 7eba996 commit befafb2
Show file tree
Hide file tree
Showing 24 changed files with 452 additions and 85 deletions.
Binary file modified .DS_Store
Binary file not shown.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## 0.2.0

**New features**:

- Added `ScalarField`, a 2-dimensional field of scalar values, typically built
from patterns or noise functions, and `buildPlaneMap`, a utility function to
build a flat plane from a `ScalarField`, useful for terrain generation.

**Breaking changes**:

- Added `<Plattern>.get2df`, as an alternative to `get2d` that takes floating
point coordinates, which is required for some use cases such the aformentioned
`buildPlaneMap`. `get2d` still exists and is recommended for integer
coordinates, and is automatically converted to `get2df` when needed.

**Bug fixes**:

- Fixed a variety of small math bugs that are hard to describe in detail.

## 0.1.0+1

- Update preview images in README.
Expand Down
14 changes: 7 additions & 7 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ pattern function:

## `Checkerboard`

![Checkerboard](https://github.com/user-attachments/assets/5d3dace2-b78d-4bc7-81c3-3eb3f0847b48)
![Checkerboard](https://github.com/user-attachments/assets/b2800c02-6c49-44d0-a159-a5721682d283)

## `White`

![White](https://github.com/user-attachments/assets/5d4989b3-5ffd-46b5-9c90-116019464ff6)
![White](https://github.com/user-attachments/assets/665131a8-0571-4200-8487-3f6f179f11b1)

## `Value`

![Value](https://github.com/user-attachments/assets/6c93d6d0-67d1-4bb9-a8fc-6cc00b451a5c))
![Value](https://github.com/user-attachments/assets/fd03f266-785b-4fbd-b532-d8421864f9fb)

## `Perlin`

![Perlin](https://github.com/user-attachments/assets/3600cdf8-d5af-44a6-adb9-cbc642c7b136)
![Perlin](https://github.com/user-attachments/assets/23214d88-4143-44e5-97bb-40c40d02e529)

## `Simplex`

![Simplex](https://github.com/user-attachments/assets/ec9c44c1-fe6d-4ae4-99cc-09527229797e)
![Simplex](https://github.com/user-attachments/assets/5168bc86-9915-4664-ae8d-3752e2bd3651)

## `Worley.distance`

![Worley.distance](https://github.com/user-attachments/assets/db03f26d-a763-4024-8adc-7bc6b2ea0f3a)
![Worley.distance](https://github.com/user-attachments/assets/234d1f60-238c-438c-8c27-407140309b6d)

## `Worley.value`

![Worley.value](https://github.com/user-attachments/assets/67cd0601-fd3f-42b6-9f5d-660d43c9ab67)
![Worley.value](https://github.com/user-attachments/assets/61475af8-1b95-4123-978a-b287cf3213c3)
16 changes: 11 additions & 5 deletions example/generate_pngs.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env dart
#!/usr/bin/env dart --enable-asserts

import 'dart:math';

Expand All @@ -23,18 +23,24 @@ void main(List<String> args) async {

final output = p.join('example', 'out');

const width = 256;
const height = 256;
const width = 512;
const height = 512;
Future<void> generate(
String name,
Pattern2d Function(Random) generate,
) async {
final pattern = generate(random).normalized;
final planar = buildFlatPlane(
width,
height,
generate(random).normalized.get2df,
xBounds: (-5, 5),
yBounds: (-5, 5),
);
final image = i.Image(width: width, height: height);
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
// 0.0 = black, 1.0 = white
final value = pattern.get2d(x, y);
final value = planar.get(x, y);
final color = (value * 255).toInt();
image.setPixel(x, y, i.ColorRgb8(color, color, color));
}
Expand Down
Binary file modified example/out/checkerboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/out/perlin_noise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/out/simplex_noise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/out/value_noise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/out/white_noise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/out/worley_distance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/out/worley_value.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/mirage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export 'src/noise/value.dart';
export 'src/noise/white.dart';
export 'src/noise/worley.dart';
export 'src/patterns.dart';
export 'src/scalar.dart';
47 changes: 30 additions & 17 deletions lib/src/generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'package:meta/meta.dart';
/// ## Implementing
///
/// To implement a new pattern generator, create a new class that implements or
/// mixes in this interface, and implement [get2d].
/// mixes in this interface, and implement [get2df].
@Immutable('Recommended to be immutable for predictable behavior.')
abstract mixin class Pattern2d {
/// Creates a new pattern that delegates to a function to calculate the output
Expand All @@ -30,17 +30,26 @@ abstract mixin class Pattern2d {
/// print(pattern.get(1, 2)); // 3.0
/// ```
const factory Pattern2d.from(
double Function(int x, int y) get,
double Function(double x, double y) get,
) = _DelegatePattern2d;

/// Returns the value of the pattern at the given coordinates.
/// Returns the value of the pattern at the given fixed-point coordinates.
///
/// The value returned is typically within the range of `[-1.0, 1.0]`, where:
///
/// - `-1.0` represents the lowest value of the pattern;
/// - `0.0` represents the middle value of the pattern;
/// - `1.0` represents the highest value of the pattern.
double get2d(int x, int y);
double get2d(int x, int y) => get2df(x.toDouble(), y.toDouble());

/// Returns the value of the pattern at the given floating-point coordinates.
///
/// The value returned is typically within the range of `[-1.0, 1.0]`, where:
///
/// - `-1.0` represents the lowest value of the pattern;
/// - `0.0` represents the middle value of the pattern;
/// - `1.0` represents the highest value of the pattern.
double get2df(double x, double y);

/// Returns a new pattern that maps the output of this pattern using the given
/// function.
Expand Down Expand Up @@ -215,10 +224,10 @@ abstract mixin class Pattern2d {

final class _DelegatePattern2d with Pattern2d {
const _DelegatePattern2d(this._get);
final double Function(int x, int y) _get;
final double Function(double x, double y) _get;

@override
double get2d(int x, int y) => _get(x, y);
double get2df(double x, double y) => _get(x, y);
}

final class _MappedPattern2d with Pattern2d {
Expand All @@ -227,7 +236,7 @@ final class _MappedPattern2d with Pattern2d {
final double Function(double) _mapper;

@override
double get2d(int x, int y) => _mapper(_pattern.get2d(x, y));
double get2df(double x, double y) => _mapper(_pattern.get2df(x, y));
}

final class _ScaledPattern2d with Pattern2d {
Expand All @@ -236,16 +245,16 @@ final class _ScaledPattern2d with Pattern2d {
final double _scale;

@override
double get2d(int x, int y) => _pattern.get2d(x, y) * _scale;
double get2df(double x, double y) => _pattern.get2df(x, y) * _scale;
}

final class _NormalizedPattern with Pattern2d {
const _NormalizedPattern(this._pattern);
final Pattern2d _pattern;

@override
double get2d(int x, int y) {
final value = _pattern.get2d(x, y);
double get2df(double x, double y) {
final value = _pattern.get2df(x, y);
return (value + 1.0) / 2.0;
}
}
Expand All @@ -255,23 +264,23 @@ final class _InvertedPattern with Pattern2d {
final Pattern2d _pattern;

@override
double get2d(int x, int y) => -_pattern.get2d(x, y);
double get2df(double x, double y) => -_pattern.get2df(x, y);
}

final class _TransposedPattern2d with Pattern2d {
const _TransposedPattern2d(this._pattern);
final Pattern2d _pattern;

@override
double get2d(int x, int y) => _pattern.get2d(y, x);
double get2df(double x, double y) => _pattern.get2df(y, x);
}

final class _AbsolutePattern2d with Pattern2d {
const _AbsolutePattern2d(this._pattern);
final Pattern2d _pattern;

@override
double get2d(int x, int y) => _pattern.get2d(x, y).abs();
double get2df(double x, double y) => _pattern.get2df(x, y).abs();
}

final class _AddPattern2d with Pattern2d {
Expand All @@ -280,7 +289,7 @@ final class _AddPattern2d with Pattern2d {
final Pattern2d _b;

@override
double get2d(int x, int y) => _a.get2d(x, y) + _b.get2d(x, y);
double get2df(double x, double y) => _a.get2df(x, y) + _b.get2df(x, y);
}

final class _SubtractPattern2d with Pattern2d {
Expand All @@ -289,7 +298,7 @@ final class _SubtractPattern2d with Pattern2d {
final Pattern2d _b;

@override
double get2d(int x, int y) => _a.get2d(x, y) - _b.get2d(x, y);
double get2df(double x, double y) => _a.get2df(x, y) - _b.get2df(x, y);
}

final class _MaxPattern2d with Pattern2d {
Expand All @@ -298,7 +307,9 @@ final class _MaxPattern2d with Pattern2d {
final Pattern2d _b;

@override
double get2d(int x, int y) => math.max(_a.get2d(x, y), _b.get2d(x, y));
double get2df(double x, double y) {
return math.max(_a.get2df(x, y), _b.get2df(x, y));
}
}

final class _MinPattern2d with Pattern2d {
Expand All @@ -307,5 +318,7 @@ final class _MinPattern2d with Pattern2d {
final Pattern2d _b;

@override
double get2d(int x, int y) => math.min(_a.get2d(x, y), _b.get2d(x, y));
double get2df(double x, double y) {
return math.min(_a.get2df(x, y), _b.get2df(x, y));
}
}
13 changes: 8 additions & 5 deletions lib/src/math.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ extension type const Vec2._((double, double) _) {
static const v11 = (1.0, 1.0) as Vec2;

/// Creates a new 2D vector.
factory Vec2(double x, double y) => (x, y) as Vec2;
///
/// The components must be finite.
factory Vec2(double x, double y) {
assert(x.isFinite && y.isFinite, 'Vector components must be finite');
return (x, y) as Vec2;
}

/// Creates a new 2D vector from two integers.
factory Vec2.fromInts(int x, int y) => Vec2(x.toDouble(), y.toDouble());
Expand Down Expand Up @@ -208,8 +213,6 @@ extension type const IVec2._((int, int) _) {
/// Returns a list of the vector components.
List<int> toList() => [x, y];

/// Reinprets the vector as a 2D floating-point vector.
Vec2 reinterpret() {
return Vec2(reinterpretAsDouble(x), reinterpretAsDouble(y));
}
/// Returns as a 2D floating-point vector.
Vec2 toVec2() => Vec2(x.toDouble(), y.toDouble());
}
6 changes: 3 additions & 3 deletions lib/src/noise/perlin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'package:mirage/mirage.dart';
/// underlying grid structure, and is considered slower than [Simplex] for
/// similar quality output.
///
/// ![Example](https://github.com/user-attachments/assets/3600cdf8-d5af-44a6-adb9-cbc642c7b136)
/// ![Example](https://github.com/user-attachments/assets/23214d88-4143-44e5-97bb-40c40d02e529)
final class Perlin with Pattern2d {
/// Creates a new perlin noise generator.
///
Expand All @@ -29,11 +29,11 @@ final class Perlin with Pattern2d {
final NoiseHasher _hasher;

@override
double get2d(int x, int y) => _perlin2d(Vec2.fromInts(x, y));
double get2df(double x, double y) => _perlin2d(Vec2(x, y));

double _perlin2d(Vec2 point) {
final corner = point.floorToInt();
final distance = point - corner.reinterpret();
final distance = point - corner.toVec2();

double gradient(Vec2 offset) {
final point = distance - offset;
Expand Down
7 changes: 3 additions & 4 deletions lib/src/noise/simplex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:mirage/mirage.dart';
/// and organic patterns but with better performance and fewer directional
/// artifacts; often considered the best general-purpose noise algorithm.
///
/// ![Example](https://github.com/user-attachments/assets/ec9c44c1-fe6d-4ae4-99cc-09527229797e)
/// ![Example](https://github.com/user-attachments/assets/5168bc86-9915-4664-ae8d-3752e2bd3651)
final class Simplex with Pattern2d {
/// Creates a new simplex noise generator.
///
Expand All @@ -24,9 +24,8 @@ final class Simplex with Pattern2d {
final NoiseHasher _hasher;

@override
double get2d(int x, int y) {
final point = Vec2.fromInts(x, y);
final (noise, _) = _simplex2d(point);
double get2df(double x, double y) {
final (noise, _) = _simplex2d(Vec2(x, y));
return noise;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/noise/value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import 'package:mirage/mirage.dart';
/// but can exhibit visible grid artifacts due to linear interpolation, and is
/// considered less smooth than [Perlin] or [Simplex] noise.
///
/// ![Example](https://github.com/user-attachments/assets/6c93d6d0-67d1-4bb9-a8fc-6cc00b451a5c)
/// ![Example](https://github.com/user-attachments/assets/fd03f266-785b-4fbd-b532-d8421864f9fb)
final class Value with Pattern2d {
/// Creates a new value noise generator.
///
Expand All @@ -27,7 +27,7 @@ final class Value with Pattern2d {
final NoiseHasher _hasher;

@override
double get2d(int x, int y) => _value2d(Vec2.fromInts(x, y));
double get2df(double x, double y) => _value2d(Vec2(x, y));

double _value2d(Vec2 point) {
final corner = point.floor();
Expand Down
4 changes: 2 additions & 2 deletions lib/src/noise/white.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'package:mirage/mirage.dart';
/// pattern if and only if the same seed is used and the same number of values
/// are generated in the same order.
///
/// ![Example](https://github.com/user-attachments/assets/5d4989b3-5ffd-46b5-9c90-116019464ff6)
/// ![Example](https://github.com/user-attachments/assets/665131a8-0571-4200-8487-3f6f179f11b1)
///
/// ## Example
///
Expand All @@ -26,5 +26,5 @@ final class White with Pattern2d {
final Random _random;

@override
double get2d(int x, int y) => _random.nextDouble() * 2.0 - 1.0;
double get2df(double x, double y) => _random.nextDouble() * 2.0 - 1.0;
}
Loading

0 comments on commit befafb2

Please sign in to comment.