Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Jan 27, 2025
1 parent bb75e42 commit 47de485
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
14 changes: 8 additions & 6 deletions MakieCore/src/basic_plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -613,17 +613,19 @@ representation and may behave a bit differently than usual.
"A function that controls which values in the input data are mapped to invisible (air) voxels."
is_air = x -> isnothing(x) || ismissing(x) || isnan(x)
"""
Defines a map from voxel ids (and optionally sides) to uv coordinates. These uv coordinates
are then used to sample a 2D texture passed through `color` for texture mapping.
Deprecated - use uv_transform
"""
uvmap = nothing
"""
TODO:
Defines a mapping from voxel ids (and optionally sides) to uv coordinates. These uv coordinates
are then used to sample a 2D texture passed through `color` for texture mapping.
To use texture mapping `uv_transform` needs to be defined and `color` needs to be an image.
The `uv_transform` can be given as a `Vector` where each index maps to a `UInt8` voxel id (skipping 0),
or as a `Matrix` where the second index maps to a side following the order `(-x, -y, -z, +x, +y, +z)`.
Each element acts as a `Mat{2, 3, Float32}` which is applied to `Vec3f(uv, 1)`, where uv's are generated to run from 0..1 for each voxel.
The result is then used to sample the texture.
UV transforms have a bunch of shorthands you can use, for example `(Point2f(x, y), Vec2f(xscale, yscale))`.
They are listed in `?Makie.uv_transform`.
"""
uv_transform = nothing

"Controls whether the texture map is sampled with interpolation (i.e. smoothly) or not (i.e. pixelated)."
interpolate = false
"""
Expand Down
44 changes: 28 additions & 16 deletions docs/src/reference/plots/voxels.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,34 @@ This means id 1 maps to lowclip, 2..254 to colors of the colormap and 255 to hig
`colorrange` and `colorscale` are ignored in this case.


#### Texturemaps
#### Texture maps

You can also map a texture to voxels based on their id (and optionally the direction the face is facing).
For this `plot.color` needs to be an image (matrix of colors) and `plot.uvmap` needs to be defined.
The `uvmap` can take two forms here.
The first is a `Vector{Vec4f}` which maps voxel ids (starting at 1) to normalized uv coordinates, formatted left-right-bottom-top.
For this `plot.color` needs to be an image (matrix of colors) and `plot.uv_transform` needs to be defined.
The `uv_transform` can either be defined as a Vector per voxel or as a Matrix per voxel and side.
Each element acts as a 2x3 transformation matrix, applied to `Vec3f(uv, 1)`.
That way it can apply scaling, rotation, mirroring, translation etc.
The input uv coordinates are normalized to a 0..1 range for each voxel and oriented such that the v direction matches +z and u extends to the right.
For the top and bottom sides of a voxel u and v align with +x and +y.

```@figure backend=GLMakie
using FileIO
texture = rotr90(FileIO.load(Makie.assetpath("debug_texture.png")))
voxels(ones(UInt8, 1,1,1), uv_transform = [I], color = texture)
```

Here is an example of per-voxel texture mapping.
The texture includes 10 sprites along x direction and 9 along y direction, each with the same square size.

```@figure backend=GLMakie
using FileIO
# load a sprite sheet with 10 x 9 textures
texture = FileIO.load(Makie.assetpath("voxel_spritesheet.png"))
# create a map idx -> LRBT coordinate of the textures, normalized to a 0..1 range
uv_map = [
Vec4f(x, x+1/10, y, y+1/9)
# create a mapping of voxel id -> (translation, scale)
# This is equivalent to using `Makie.Mat{2, 3, Float32}(1/10, 0, 0, 1/9, x, y)`
uvt = [(Point2f(x, y), Vec2f(1/10, 1/9))
for x in range(0.0, 1.0, length = 11)[1:end-1]
for y in range(0.0, 1.0, length = 10)[1:end-1]
]
Expand All @@ -99,10 +111,10 @@ chunk = UInt8[
]
# draw
f, a, p = voxels(chunk, uvmap = uv_map, color = texture)
voxels(chunk, uv_transform = uvt, color = texture)
```

The second format allows you define sides in the second dimension of the uvmap.
To define texture per side we use a `Matrix` instead, where the first index is the voxel id and the second the side.
The order of sides is: -x, -y, -z, +x, +y, +z.

```@figure backend=GLMakie
Expand All @@ -112,25 +124,25 @@ texture = FileIO.load(Makie.assetpath("voxel_spritesheet.png"))
# idx -> uv LRBT map for convenience. Note the change in order loop order
uvs = [
Vec4f(x, x+1/10, y, y+1/9)
(Point2f(x, y), Vec2f(1/10, 1/9))
for y in range(0.0, 1.0, length = 10)[1:end-1]
for x in range(0.0, 1.0, length = 11)[1:end-1]
]
# Create uvmap with sides (-x -y -z x y z) in second dimension
uv_map = Matrix{Vec4f}(undef, 4, 6)
uv_map[1, :] = [uvs[9], uvs[9], uvs[8], uvs[9], uvs[9], uvs[8]] # 1 -> birch
uv_map[2, :] = [uvs[11], uvs[11], uvs[10], uvs[11], uvs[11], uvs[10]] # 2 -> oak
uv_map[3, :] = [uvs[2], uvs[2], uvs[2], uvs[2], uvs[2], uvs[18]] # 3 -> crafting table
uv_map[4, :] = [uvs[1], uvs[1], uvs[1], uvs[1], uvs[1], uvs[1]] # 4 -> planks
uvt = Matrix{Any}(undef, 4, 6)
uvt[1, :] = [uvs[9], uvs[9], uvs[8], uvs[9], uvs[9], uvs[8]] # 1 -> birch
uvt[2, :] = [uvs[11], uvs[11], uvs[10], uvs[11], uvs[11], uvs[10]] # 2 -> oak
uvt[3, :] = [uvs[2], uvs[2], uvs[2], uvs[2], uvs[2], uvs[18]] # 3 -> crafting table
uvt[4, :] = [uvs[1], uvs[1], uvs[1], uvs[1], uvs[1], uvs[1]] # 4 -> planks
chunk = UInt8[
1 0 1; 0 0 0; 1 0 1;;;
0 0 0; 0 0 0; 0 0 0;;;
2 0 2; 0 0 0; 3 0 4;;;
]
f, a, p = voxels(chunk, uvmap = uv_map, color = texture)
voxels(chunk, uv_transform = uvt, color = texture)
```

The textures used in these examples are from [Kenney's Voxel Pack](https://www.kenney.nl/assets/voxel-pack).
Expand Down

0 comments on commit 47de485

Please sign in to comment.