VoxyPy
VoxyPy is a data structure for operations on Voxel models and .vox
files.
It uses NumPy for data storage and transformation.
Reading and writing .vox
files is achieved using a heavily modified version of numpy-vox-io for IO operations.
You can view the code, submit bugs/issues, and leave comments at the VoxyPy GitLab repo.
Note
This project is under active development.
Quickstart
from voxypy.models import Entity, Voxel
dense = np.zeros((10, 10, 10), dtype=int)
entity = Entity(data=dense)
entity.set(x=1, y=2, z=3, 42)
voxel = entity.get(1, 2, 3) # Voxel object with value 42
voxel.add(1) # Voxel object with value 43
new_voxel = Voxel(255)
new_voxel.add(1) # Returns Voxel object with value 1
entity.set(5, 5, 5, new_voxel)
entity.set(5, 5, 5, 69)
entity = Entity().from_file('old_entity.vox')
# optional
entity.set_palette_from_file('palette.png')
entity.save('new_entity.vox')
Voxel
Voxel is a small class representing one cell in an Entity.
Voxel colors are represented as indices from 0 to 255, where 0 means blank. These indices refer to actual RGB colors in a 1x255 .png
file. So, for example, if the 10th pixel in the texture is red, then a voxel with value 10 will render as red.
The Voxel equality operator works with ints and Voxels. Voxels can also be cast to ints.
Methods
_init__(color=0)
- Voxel object with color color. 0 is blank.color - 0-255
get()
- int value of voxel’scolor
.set(color=0)
- Voxel object with color color. 0 is blank.color - 0-255
add(amount=1)
- Addsamount
to voxel’scolor
.Adding 1 to 255 causes the color to wrap to 1 instead of 0. See Voxel for info about voxel colors.
subtract(amount=1)
- Subtractsamount
from voxel’scolor
.Just a wrapper for
add
.
from voxypy.models import Voxel
v1 = Voxel(1)
v2 = Voxel(1)
v1 == v2 # True
v1 == 1 # True
int(v1) == 1 # True
v1 != 0 # True
Entity
An Entity is (conceptually) a 3d array of Voxels.
Under the hood, an Entity is actually a wrapper for a 3d NumPy ndarray of int
s. Values are converted to Voxels during get
and set
methods. Voxels and ints can be used interchangeably in almost every case.
Initialization
import numpy as np
from voxypy.models import Entity
# Empty model with shape (1, 2, 3)
entity = Entity(1, 2, 3)
# Entity from numpy array
data = np.array([1, 2, 3, 4]).reshape((2, 2, 1))
entity = Entity(data=data) # Shape is automatically set from array
# or with color palette
palette = [(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)]
entity = Entity(data=data, palette=palette)
# or from an existing .vox file
entity = Entity().from_file('entity.vox')
Providing mismatched dimensions for x, y, z
and data
will throw an error.
Tricks
The methods get_dense
and from_dense
can be combined to allow invocation of any NumPy ndarray method
entity = (x=10, y=10, z=10) # 10x10x10 Entity full of zeros.
ones = entity.get_dense().fill(1) # 10x10x10 ndarray full of ones.
entity.from_dense(ones) # 10x10x10 Entity full of ones.
# one liner
entity.from_dense(entity.get_dense().fill(1))
Methods
get(x, y, z)
- A Voxel object from Entity at[x, y, z]
x, y, z - Coordinates.
set(x, y, z, color)
- Sets Entity at[x, y, z]
tocolor
and returns self.x, y, z - Coordinates.
color - Either int(0-255) or a Voxel.
get_dense()
- Returns a NumPy ndarray ofdtype=int
, where each int is a voxel color index.from_dense(dense)
- Overwrites Entity voxels with new data. Does not overwrite palette.dense - 3d NumPy ndarray with
dtype=int
write(filename)
- Writes entity to a .vox file.filename - String name of a file.
save(filename)
- Wrapper forwrite()
filename - String name of a file.
from_file(filename)
- Reads.vox
file into an Entity, replacing existing data.If the
.vox
file includes a color palette, it will also be read.filename - String name of a file.
layers()
- Generator for list of z-layers.get_layer(z)
- Returns layer at heightz
.set_layer(z, layer)
- Sets layerz
of Entity to the contents oflayer
. Dimensions must match.z - Z level at which to insert layer.
layer - 2d NumPy ndarray with
dtype=int
flip()
- Flips the entity along the Z (gravity) axis.set_palette_from_file(filename)
- Overwrites the entity’s color palette with a new one from a png file.filename - String name of a file.
set_palette(palette)
- Overwrites the entity’s color palette with one that you pass in.Palettes are validated and padded to fill missing color indices.
palette - List of 4-tuples (R, G, B, A=255)
get_palette(padded=True)
- Returns the entity’s color palette in a list of tuples.padded - If True, color at index 0 will be blank. This is handy because index 0 is interpreted as blank in voxel editors.
nonzero()
- Returns a list of tuples of the coordinates of the Entity which are not blank.For example,
[(0, 0, 0), (0, 0, 1) ... ]
Helpful Links
Change Log
0.2.3
Added nonzero() to Entity
0.2.2
Fixed bad structure
0.2.1
Fixed missing
imageio
andPillow
requirements
0.2.0
Moved Entity and Voxel from
voxypy.models.models
tovoxypy.models
Reworked palette behavior
Removed
palette_file
from EntityPalette IO works with MagicaVoxel 0.99.6.4
Added Sphinx/RTD docs at https://voxypy.readthedocs.io/en/latest/index.html