diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/404.html b/404.html new file mode 100644 index 0000000000..ee7db289e0 --- /dev/null +++ b/404.html @@ -0,0 +1,1097 @@ + + + +
+ + + + + + + + + + + + + + + + + + +See compilation and dependencies.
+We are using the default opengl right handed coordinate system with x going right, y going upwards and z point towards you.
+We are using column major matrices.
+ +If you are going to contribute, make sure that you are adding unittests, too. I won't make promises about not breaking anything +if there aren't unittests that are telling me that I've broken something.
+To add a unittest, each module (src/modules/XXX
) has a tests/
subdirectory. The CMakeLists.txt
in the module directory adds the source files from that folder.
set(TEST_SRCS
+ [...]
+)
+gtest_suite_begin(tests-${LIB} TEMPLATE ${ROOT_DIR}/src/modules/core/tests/main.cpp.in)
+gtest_suite_sources(tests-${LIB} ${TEST_SRCS})
+gtest_suite_deps(tests-${LIB} ${LIB})
+gtest_suite_end(tests-${LIB})
+
+Rule of thumb - stick to the existing coding style - you can also use the clang-format
settings to format your code. In general
+you should not include any whitespace or formatting changes if they don't belong to your code changes.
If you do a formatting change, this should not be mixed with code changes - make a dedicated commit for the formatting.
+Avoid using the STL were possible - see Orthodox C++.
+Commit messages should match the usual git commit message guidelines. Keep the summary short - put an UPPERCASE prefix in front +of it and try to explain why the change was made - not what you changed (because that is part of the commit diff already).
+The prefix is usually the module name. E.g. if you are changing code in src/modules/voxelformat
the prefix would be VOXELFORMAT
. A commit message could look like this:
VOXELFORMAT: summary
+
+detail message line 1
+detail message line 2
+
+Name | +Description | +
---|---|
app | +Basic application classes | +
command | +Bind c++ functionality to console commands | +
commonlua | +Basic lua bindings and helper | +
core | +String, collections and other foundation classes | +
http | +Http download module | +
image | +Image loading and writing | +
io | +Stream and file handling | +
math | +Based on glm | +
memento | +The undo/redo states for a scene graph instance | +
metric | +telegraf, influx and other metrics | +
noise | +Different noise implementations | +
palette | +Palette formats and helper | +
render | +General renderer implementations and helpers | +
scenegraph | +Scene graph and scene graph node implementation | +
testcore | +Visual test helpers | +
ui | +DearImgui based ui code | +
util | ++ |
video | +Window and renderer module | +
voxel | +The voxel engine code based on PolyVox | +
voxelcollection | +Browse online and local voxel collections | +
voxelfont | +TTF font to voxel | +
voxelformat | +Several volume and mesh based file formats to load or generate voxels | +
voxelgenerator | +LUA generator, space colonization, tree- and shape generators | +
voxelpathtracer | +Path tracer | +
voxelrender | +Voxel renderer | +
voxelutil | +Pathfinding, raycasting, image and general util functions | +
A more detailed changelog can be found on github.
+Join our discord server.
+See the documentation for further details.
+Known issues.
+General:
+bbmodel
Blockbench formatvxb
Sandbox Block formatg_import
globalg_sys
, g_io
)glb
voxformat_voxelizemode
1
md2
scale and translate value importsmdl
filespng
slices3ds
filesvxl
)vxl
saving for negative coordinatesVoxConvert:
+--image-as-XXX
parameters (now part of the png
format)--colored-heightmap
(this is auto-detected in the png
format now)VoxEdit:
+General:
+3zh
format supportase
and aseprite
formatvoxformat_emptypaletteindex
animate.lua
scriptimageasvolume.lua
) for importing 2d images with depthv3b
format support (compressed v3a
file)writeString
lua stream binding has a new default value - check the docsVoxConvert:
+--dump
and added --json <full>
to generate a scene graph structureVoxBrowser:
+VoxEdit:
+General:
+voxformat_optimize
)vxl
(Command and Conquer)vox
file loading for files that don't contain instances, but only modelsvxc
thumbnail supportVoxEdit:
+General:
+fbx
loadingsmtpl
formatlitematic
Minecraftqb
filesqb
version numberthing
file supportpo
files)3zh
filesvoxformat_rgbweightedaverage
to control the color contributions for a triangleVoxConvert:
+--input
--slice
when --output
is a png fileVoxEdit:
+modelmerge all
parameter to merge all nodes at oncepresentation
command to cycle through all models in a sceneve_regionsizes
cvar handlingThumbnailer:
+Packaging:
+io.github.vengi_voxel.vengi.voxedit
for DBUS compatibilityGeneral:
+VoxBrowser:
+VoxEdit:
+General:
+hollow()
to lua bindingssimilarcolor.lua
vxl/hva
loading and savingpcubes
write supportvoxformat_withnormals
)scn
) volume loading supportsment
, smd2
and smd3
supportVoxBrowser:
+VoxConvert:
+--print-formats
parameter to print all formats as json the ease the parsing for third party tools--output
parameters to write one (or more) input files into different formats in one stepVoxEdit:
+Thumbnailer:
+++moved the github project into an organization named vengi-voxel - the url changed to https://github.com/vengi-voxel/vengi.
+
General:
+kvx
, kv6
, kfa
and vox
ply
format got support for converting polygons into trianglespcubes
and 3zh
supportase
palettepal
palettegpl
palette format to support the Aseprite alpha channel extensionvengi-voxconvert --completion bash
(or zsh
)b64
mapsgltf
loadinggltf
filesVoxConvert:
+--export-models
to work with the output format given by --output
--filter-property
to filter by node property key<:value>
VoxEdit:
+clear
and fill
commandsThumbnailer:
+Breaking changes:
+g_
prefix to them. You have to adopt your scripts
+ to work with the latest version with vengi (if you use them):scenegraph
is now g_scenegraph
palettemgr
is now g_palette
noise
is now g_noise
cmd
is now g_cmd
var
is now g_var
XvecX
is now g_XvecX
(ivec3
is for example g_ivec3
)General:
+voxformat_pointcloudsize
for point cloud formatsply
) mesh and point cloud support (ascii and binary)kvx
fileskvx
format (used in e.g. voxel doom and eduke3d)v3a
formatVoxEdit:
+General:
+voxformat_voxelizemode
to 1)VoxEdit:
+General:
+md2
) supportvoxformat_marchingcubes
and replaced with voxel_meshmode
(set to 1
to use marching cubes)gradient.lua
csm
and nvm
format supportlayer
is model
now, ...)vbx
) supportxraw
formatVoxConvert:
+--input
handling if the value is a directory--wildcard
to specify a wildcard in cases where the --input
value is a directory--surface-only
parameter that removes any non surface voxel.--dump-mesh
to also show mesh details (like vertex count).VoxEdit:
+Thumbnailer:
+General:
+palette
cvar as a destination palette again by setting voxformat_createpalette
to false
core_colorreduction
vengi
VoxConvert:
+--help
)VoxEdit:
+robo
, chess
, head
and chr_knight
)ve_regionsizes
cvar)General:
+VoxEdit:
+Thumbnailer:
+General:
+Packaging:
+io.github.vengi-voxel.vengi.voxedit
)VoxEdit:
+General:
+pal
) and Gimp (gpl
) palette loadingVoxEdit:
+General:
+VoxEdit:
+tab
VoxConvert:
+--dump
to also show the key frames and the voxel count--src-palette
(src palette is always used)General:
+ui_style
)VoxEdit:
+VoxConvert:
+--image-as-plane
and --image-as-heightmap
parameters++renamed the github project to vengi - the url changed to https://github.com/vengi-voxel/vengi.
+
Build:
+GAMES
was set to OFF
General:
+VoxConvert:
+--input
can now also handle directoriesVoxEdit:
+General:
+VoxConvert:
+--crop
parameter that reduces the volumes to their real voxel sizes--split
option to cut volumes into smaller pieces--export-models
to export all the models of a scene into single files--dump
to dump the scene graph of the input file--resize
to resize the volumes by the given x, y and z valuesVoxEdit:
+General:
+VoxConvert:
+--force
handling for target files--translate
command line option--pivot
command line option--src-palette
is used and it's no hard error anymore if this failsVoxEdit:
+General:
+VoxConvert:
+--filter
)Thumbnailer:
+VoxEdit:
+General:
+Thumbnailer:
+VoxEdit:
+General:
+UI:
+VoxEdit:
+General:
+General:
+VoxEdit:
+General:
+--version
and -v
commandline option to show the current version of each applicationVoxEdit:
+Tools:
+General:
+General:
+Backend:
+General:
+VoxEdit:
+General:
+VoxEdit:
+Client:
+Server:
+VoxEdit:
+VoxConvert:
+palette
)General:
+General:
+Server:
+VoxEdit:
+scale
console command to produce LODsVoxConvert:
+Assets:
+VoxEdit:
+thicken
commandGeneral:
+VoxConvert:
+Client:
+VoxEdit:
+thicken
console commandGeneral:
+Server/Client:
+Voxel rendering:
+VoxEdit:
+The project should work on Linux, Windows and OSX. It should work with any ide that is either supported by cmake or has direct cmake support. Personally I'm using vscode with clangd at the moment. But also the command line with plain old make
.
There is a Makefile
wrapper around the build system. You can just run make
in the project root folder.
Every project has some extra CMake targets. There are e.g. voxedit-run
, voxedit-debug
and voxedit-perf
if the needed tools were found during cmake's configure phase.
That means that you can compile a single target by typing make voxedit
, run it by typing make voxedit-run
, debug it by typing make voxedit-debug
and profile it by
+typing make voxedit-perf
. There are also other targets for valgrind - just use the tab completion in the build folder to get a list.
The project can be built with every ide that supports cmake. QTCreator, Eclipse CDT, vscode or Visual Studio. Just install cmake, generate the project files, and open them in your ide.
+++Set up ninja to speed up the whole build-link-run cycle a lot!
+
Inside vscode you have to install the c++ plugins. The easiest might be to install the c++ plugins from microsoft. Just make sure the cmake plugin is part of the collection.
+If you have problems with the intellisense plugin from microsoft, you can also use the clangd plugin.
+Open your git clone directory in vscode and let it configure via cmake. It will pick ninja and the visual studio compiler automatically.
+In order to use the Makefile
, you should install ninja (see above), gnu make, start Native Tools Command Prompt from your start menu, and just run make
in that shell in your git clone directory. Keep in mind that ninja, make and cmake must be available via PATH environment variable.
Check out the Linux section about more details regarding the Makefile
targets.
++Here is a step-by-step guide from a user to compile vengi on a windows machine via command line make. After you've downloaded the above mentioned software, run the following steps:
++
+- Install CMake
+- Win+R > type
+sysdm.cpl
> Advanced > Environment Variables...- Click "New" and add this to your
+PATH
:C:/Program Files (x86)/GnuWin32/bin
- Add
+ninja.exe
toPATH
or if you're lazy paste it intoC:/Program Files (x86)/GnuWin32/bin
- Install Visual Studio Community
+- You need to add at least 2 Workloads before installation: "MSVC" & "C++ Address Sanitizer"
+- Navigate find the C/C++ compiler
+cl.exe
somewhere inC:/Program Files/Microsoft Visual Studio/<year>/Community/VC/Tools/MSVC/<version>/bin/Hostx64/x64/cl.exe
and copy this path. Example:C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe
- Copy the path in the folder address bar and add 3 more environment variables
+CC
andCMAKE_C_COMPILER
andCMAKE_CXX_COMPILER
with this path value.- Then add just the directory (without
+cl.exe
) into thePATH
environment variable- Open Visual Studio Community > Skip Sign-In > Skip this for Now
+- Restart computer
+- Windows > Search >
+x64
> open:x64 Native Tools Command Prompt for VS 2022
- +
cd
to the vengi folder- Type
+make
to configure and build or build specific targets likemake voxedit
ormake voxconvert
+ + +
+If you want to go further, install vcpkg - see dependencies for the command line - but you can skip here if you don't want vcpkg.
+
You can generate your xcode project via cmake or build like this:
+mkdir build
+cd build
+cmake ..
+cmake --build .
+
+If you are using the cmake Makefile generator, you get the same targets as for Linux above. You can also just type make voxedit-run
to compile and run only VoxEdit.
If you encounter any problems, it's also a good start to check out the build pipelines of the project. +This is always the most up-to-date information about how-to-build-the-project that you will find. But +also please don't hesitate to ask for help on our discord server.
+You can enforce the use of the bundled libs by putting a <LIB>_LOCAL=1
in your cmake cache.
+Example: By putting LUA54_LOCAL=1
into your cmake cache, you enforce the use of the bundled lua sources from contrib/libs/lua54
.
Run make doc
from the project root to execute doxygen. After that install the mcss theme as described here: mcss.mosra.cz/documentation/.
The engine can get configured by so called cvars (configuration variables). These variables can be modified from within +the game via key bindings, built-in console, the ui or scripts.
+To get a list of supported cvars (they might differ from application to application), type the command cvarlist
to the
+built-in console - or execute the application with --help
(Example: vengi-voxedit.exe --help
).
The variables can get their initial value from various sources. The highest order is the command line. If you specify it on +the command line, every other method will not be used. If the engine finds the cvar name in your environment variables, this +one will take precedence over the one the is found in the configuration file. Next is the configuration file - this one will +take precedence over the default settings that are specified in the code.
+The environment variable can be either lower case or upper case. For example it will work if you have CL_GAMMA
or cl_gamma
+exported. The lower case variant has the higher priority.
./vengi-voxvonvert -set voxformat_scale 2.0 [...]
+
+export VOXFORMAT_SCALE=2.0
+./vengi-voxconvert [...]
+
+~/.local/share/vengi/voxconvert/voxconvert.vars
C:/Users/bob/AppData/Roaming/vengi/voxconvert/voxconvert.vars
/Users/bob/Library/Application Support/vengi/voxconvert/voxconvert.vars
You can get a list of search paths by calling the particular application with the --help
parameter on the command line. This will print a list of search paths. You can even add your own paths by setting the cvar core_path
.
++For packagers it might be interesting to set the
+PKGDATADIR
cmake variable.
To get a list of supported commands (they might differ from application to application), type the command cmdlist
to the built-in console.
You can also get a list when doing ./vengi-app --help
on the command line.
You can also modify or add key bindings to commands. Type bindlist
to the console to get a list of the current active bindings
+(and also here: they might differ from application to application). The command bind
can be used to configure keybindings on-the-fly. These bindings are saved to a file on shutdown.
VoxEdit has an ui panel to show the configured keybindings - see controls for more details.
+You can either log via syslog (on unix) or to stdout (this might of course differ from platform to platform).
+The log level is configured by the core_loglevel
variable. The lower the value, the more you see. 1
is the highest log level
+(trace), where 5 is the lowest log level (error).
trace
: 1debug
: 2info
: 3warn
: 4error
: 5To get a rough usage overview, you can start any application with --help
. It will print out the commands and configuration variables
+with a description and hints how to modify/use them.
Name | +Description | +
---|---|
cl_vsync |
+enable or disable v-sync | +
cl_gamma |
+tweak the gamma value that is applied last on rendering | +
cl_display |
+the display index if you are using multiple monitors [0-numDisplays) |
+
A few cvars exists to tweak the export or import of several formats.
+Some of these settings are only for voxel format, others are only for the mesh formats like ply, gltf, stl, fbx and obj.
+Name | +Description | +Example | +
---|---|---|
core_colorreduction |
+This can be used to tweak the color reduction by switching to a different algorithm. Possible values are Octree , Wu , NeuQuant , KMeans and MedianCut . This is useful for mesh based formats or RGBA based formats like e.g. AceOfSpades vxl. |
+Octree | +
voxel_meshmode |
+Set to 1 to use the marching cubes algorithm to produce the mesh | +0/1 | +
voxformat_ambientocclusion |
+Don't export extra quads for ambient occlusion voxels | +true/false | +
voxformat_colorasfloat |
+Export the vertex colors as float or - if set to false - as byte values (GLTF/Unreal) | +true/false | +
voxformat_createpalette |
+Setting this to false will use use the palette configured by palette cvar and use those colors as a target. This is mostly useful for meshes with either texture or vertex colors or when importing rgba colors. This is not used for palette based formats - but also for RGBA based formats. |
+true/false | +
voxformat_emptypaletteindex |
+By default this is -1 which means that no color is skipped. Pick 0-255 to remove that palette index from the final saved file. NOTE: this only works for formats that don't force the empty voxel to be 0 or 255 (or any other index) already |
++ |
voxformat_fillhollow |
+Fill the inner parts of completely close objects, when voxelizing a mesh format. To fill the inner parts for non mesh formats, you can use the fillhollow.lua script. | +true/false | +
voxformat_gltf_khr_materials_pbrspecularglossiness |
+Apply KHR_materials_pbrSpecularGlossiness extension on saving gltf files | +true/false | +
voxformat_gltf_khr_materials_specular |
+Apply KHR_materials_specular extension on saving gltf files | +true/false | +
voxformat_mergequads |
+Merge similar quads to optimize the mesh | +true/false | +
voxformat_merge |
+Merge all models into one object | +true/false | +
voxformat_optimize |
+Apply mesh optimizations when saving mesh based formats | +true/false | +
voxformat_pointcloudsize |
+Specify the side length for the voxels when loading a point cloud | +1 | +
voxformat_qbtpalettemode |
+Use palette mode in qubicle qbt export | +true/false | +
voxformat_qbtmergecompounds |
+Merge compounds in qbt export | +true/false | +
voxformat_qbsavelefthanded |
+Save qubicle format as left handed | +true/false | +
voxformat_qbsavecompressed |
+Save qubicle with RLE compression | +true/false | +
voxformat_reusevertices |
+Reuse vertices or always create new ones | +true/false | +
voxformat_rgbflattenfactor |
+To flatten the RGB colors when importing volumes (0-255) from RGBA or mesh based formats | +1 | +
voxformat_rgbweightedaverage |
+If multiple triangles contribute to the same voxel the color values are averaged based on their area contribution | +true/false | +
voxformat_scale |
+Scale the vertices for voxelization on all axis by the given factor | +1.0 | +
voxformat_scale_x |
+Scale the vertices for voxelization on X axis by the given factor | +1.0 | +
voxformat_scale_y |
+Scale the vertices for voxelization on Y axis by the given factor | +1.0 | +
voxformat_scale_z |
+Scale the vertices for voxelization on Z axis by the given factor | +1.0 | +
voxformat_withmaterials |
+Export material properties for formats that supports this | +true/false | +
voxformat_transform_mesh |
+Apply the keyframe transform to the mesh | +true/false | +
voxformat_quads |
+Export to quads | +true/false | +
voxformat_voxcreategroups |
+Magicavoxel vox groups | +true/false | +
voxformat_voxcreatelayers |
+Magicavoxel vox layers | +true/false | +
voxformat_voxelizemode |
+0 = high quality, 1 = faster and less memory |
+0/1 | +
voxformat_vxlnormaltype |
+Normal type for VXL format - 2 (TS) or 4 (RedAlert2) | +2/4 | +
voxformat_withcolor |
+Export vertex colors | +true/false | +
voxformat_withnormals |
+Export smoothed normals for cubic surface meshes (marching cubes always uses normals) | +true/false | +
voxformat_withtexcoords |
+Export texture coordinates | +true/false | +
Some of these dependencies might not be available as packages in your toolchain - most +of them are also bundled with the application. But local installed headers always have +the higher priority. Usually you don't have to install anything of these.
+apt-get install binutils-dev libunwind-dev libglm-dev lua5.4 liblua5.4-dev libfreetype-dev libsdl2-dev wayland-protocols pkg-config libjpeg-dev
+
+pacman -Sy git make cmake ninja sdl2 clang
+
+brew install sdl2 jpeg-turbo freetype cmake ninja pkg-config
+
+vcpkg install pkg-config sdl2 libjpeg-turbo lua glm glslang gtest freetype
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Everything is stored in little endian.
+The VENGI format is designed to store scene graph data including node properties, animations, voxel data, and palette information. The data is stored in a compressed format using ZIP compression.
+A VENGI file consists of the following main sections:
+VENG
.3
.Nodes are composed of data chunks that each start with a FourCC code.
+NODE
: Indicates the beginning of a scene graph node.PROP
: Contains properties of a node (only present if there are properties).DATA
: Contains voxel data of a node (only if type is Model
).PALC
: Contains palette colors (only present if PALI is not).PALI
: Contains a palette identifier (only present if PALC is not).ANIM
: Contains animation data for a node.KEYF[]
: Contains keyframe data for an animation.ENDA
: Marks the end of an animation chunk.NODE[]
: child nodes (only present if there are child nodes)ENDN
: Marks the end of a node chunk.0x56454E47
('VENG'
)3
- already part of the compressed data)Each node chunk begins with the NODE
FourCC and includes the following information:
-1
if no node is referenced)Node types are:
+Root
Model
ModelReference
Group
Camera
Point
Each node has the FourCC ENDN
at its end
++You should not rely on the order of chunks when loading a
+vengi
file.
Node properties are stored in the PROP
chunk.
++Note: This chunk is only available if the node has properties.
+
PROP
Voxel data is stored in the DATA
chunk.
++Note: This chunk is only available if the node is a model node.
+
DATA
The voxel data is stored like this:
+for(x = mins.x; x <= maxs.x; ++x)
+ for(y = mins.y; y <= maxs.y; ++y)
+ for(z = mins.z; z <= maxs.z; ++z)
+ writeVoxelInformation(x, y, z)
+
+Palette colors are stored in the PALC
chunk (or in PALI
- see below):
PALC
Palette identifier is stored in the PALI
chunk.
++Note: This is only used if the palette is a built-in vengi [palette] (Palette.md) - otherwise the
+PALC
chunk is used.
PALI
This is used for internal palettes.
+Animations are stored in the ANIM
chunk:
ANIM
KEYF
chunk:KEYF
The end of the animation chunk is marked by the ENDA
FourCC.
++The vengi format is the best supported format. Saving into any other format might lose several details from your scene. This depends on the capabilities of the format and the completeness of the implementation for supporting that particular format.
+
Name | +Extension | +Loading | +Saving | +Thumbnails | +Palette | +Animations | +
---|---|---|---|---|---|---|
AceOfSpades | +kv6 | +X | +X | ++ | X | ++ |
AceOfSpades | +vxl | +X | +X | ++ | X | ++ |
AnimaToon | +scn | +X | ++ | + | + | X | +
BinVox | +binvox | +X | +X | ++ | + | + |
Build engine | +kvx | +X | +X | ++ | X | ++ |
Chronovox | +csm | +X | ++ | + | + | + |
CubeWorld | +cub | +X | +X | ++ | X | ++ |
Cubzh | +3zh | +X | +X | +X | +X | ++ |
Cubzh World | +b64 | +X | ++ | + | + | + |
Goxel | +gox | +X | +X | +X | +X | ++ |
MagicaVoxel | +vox | +X | +X | ++ | X | ++ |
Magicavoxel XRAW | +xraw | +X | +X | ++ | X | ++ |
Minecraft level dat | +dat | +X | ++ | + | + | + |
Minecraft region | +mca | +X | ++ | + | X | ++ |
Minecraft schematic | +schematic | +X | ++ | + | X | ++ |
Minetest | +mts | +X | ++ | + | X | ++ |
Nicks Voxel Model | +nvm | +X | ++ | + | + | + |
Particubes | +pcubes | +X | +X | +X | +X | ++ |
Portable Network Graphics | +png | +X | +X | ++ | + | + |
Qubicle Binary | +qb | +X | +X | ++ | X | ++ |
Qubicle Binary Tree | +qbt | +X | +X | ++ | X | ++ |
Qubicle Exchange | +qef | +X | +X | ++ | + | + |
Qubicle Project | +qbcl | +X | +X | +X | +X | ++ |
Rooms.xyz Thing | +thing | +X | ++ | + | X | ++ |
SLAB6 vox | +vox | +X | +X | ++ | X | ++ |
Sandbox VoxEdit Block | +vxb | +X | +X | ++ | X | ++ |
Sandbox VoxEdit Collection | +vxc | +X | ++ | X | ++ | + |
Sandbox VoxEdit Hierarchy | +vxr | +X | +X | ++ | + | X | +
Sandbox VoxEdit Model | +vxm | +X | +X | ++ | X | ++ |
Sandbox VoxEdit Tilemap | +vxt | +X | ++ | + | + | + |
Sproxel csv | +csv | +X | +X | ++ | X | ++ |
StarMade Blueprint | +sment | +X | ++ | + | X | ++ |
StarMade Template | +smtpl | +X | +X | ++ | X | ++ |
Tiberian Sun | +vxl | +X | +X | ++ | X | +X | +
Vengi | +vengi | +X | +X | ++ | X | +X | +
Voxel3D | +v3a | +X | +X | ++ | + | + |
VoxelBuilder | +vbx | +X | ++ | + | + | + |
VoxelMax | +vmax.zip | +X | ++ | X | +X | ++ |
aseprite | +aseprite | +X | ++ | + | X | ++ |
Name | +Extension | +Loading | +Saving | +Animations | +
---|---|---|---|---|
Autodesk 3D Studio | +3ds | +X | ++ | + |
Blockbench | +bbmodel | +X | ++ | + |
FBX | +fbx | +X | +X | ++ |
GL Transmission Format | +gltf | +X | +X | +X | +
Polygon File Format | +ply | +X | +X | ++ |
Quake 1 | +bsp | +X | ++ | + |
Quake 1 Model | +mdl | +X | ++ | + |
Quake 2 Model | +md2 | +X | ++ | + |
Standard Triangle Language | +stl | +X | +X | ++ |
UFO:Alien Invasion | +bsp | +X | ++ | + |
Wavefront Object | +obj | +X | +X | ++ |
Point cloud support for ply
and gtlf
is implemented, too.
Name | +Extension | +Loading | +Saving | +
---|---|---|---|
Adobe Swatch Exchange | +ase | +X | +X | +
CSV Palette | +csv | +X | +X | +
Gimp Palette | +gpl | +X | +X | +
JASC Palette | +pal | +X | +X | +
Paint.NET Palette | +txt | +X | +X | +
Photoshop Palette | +aco | +X | +X | +
Pixelorama | +json | +X | +X | +
Portable Network Graphics | +png | +X | +X | +
Qubicle Palette | +qsm | +X | ++ |
RGB Palette | +pal | +X | +X | +
++The
+gpl
format also supports the Aseprite extension for alpha values
Name | +Extension | +
---|---|
Bitmap | +bmp | +
DDS | +dds | +
Graphics Interchange Format | +gif | +
JPEG | +jpeg | +
PKM | +pkm | +
PVR | +pvr | +
Photoshop | +psd | +
Portable Anymap | +pnm | +
Portable Network Graphics | +png | +
Radiance rgbE | +hdr | +
Softimage PIC | +pic | +
Targa image file | +tga | +
There is a console command (called xs
) in voxedit and a command line parameter in voxconvert to execute lua scripts for generating voxels. This command expects the lua script filename (.lua
can be omitted) and the additional arguments for the main()
method.
++If you are new to lua you can read more about it on lua-users.
+
++voxedit
+Calling
+xs <script> help
(in the script console) will print the supported arguments for the given script file in voxedit.
++voxconvert
++
./vengi-voxconvert --script "<script> help" --scriptcolor 1 --input in.qb --output out.qb
+
--scriptcolor
defines the color palette index that is given to the script as parameter.
By default the script files will be searched in a scripts
folder next to where the binary is located and in the usual search paths (see configuration for more details). You can also give the full path to the script file.
There are two functions in each script. One is called arguments
and one main
. arguments
returns a list of parameters for the main
function. The default parameters for main
are node
, region
and color
. color
is the palette index starting from 0
(the selected color in the palette panel in voxedit
or the specified color index in voxconvert
as given by --scriptcolor
).
So the first few parameters are the same for each script call. And the script defines any additional parameter for the main
function by returing values in the arguments
function.
function main(node, region, color)
+ local volume = node:volume()
+ local mins = region:mins()
+ local maxs = region:maxs()
+ for x = mins.x, maxs.x do
+ for y = mins.y, maxs.y do
+ for z = mins.z, maxs.z do
+ volume:setVoxel(x, y, z, color)
+ end
+ end
+ end
+end
+
+Execute this via console xs scriptfile
function arguments()
+ return {
+ { name = 'n', desc = 'height level delta', type = 'int', default = '2' }
+ }
+end
+
+function main(node, region, color, n)
+ [...]
+end
+
+Execute this via console xs scriptfile 1
where 1
will be the value of n
. Omitting the 1
will add the default
value from the argument list.
local function basename(str)
+ local name = string.gsub(str, "(.*/)(.*)", "%2")
+ return name
+end
+
+function main(_, _, _)
+ local url = "https://github.com/vengi-voxel/vengi/raw/9c101f32b84f949ed82f7545883e80a318760580/data/voxel/guybrush.vox"
+ local filename = basename(url)
+ local stream = g_http.get(url)
+ g_import.scene(filename, stream)
+end
+
+function main(node, region, color)
+ -- find match (palette index) for red in the current palette (RGB value)
+ -- this value can be used in e.g. volume:setVoxel(x, y, z, match)
+ local match = node:palette():match(255, 0, 0)
+ [...]
+end
+
+This will find the best match in the currently used palette and return the index.
+Supported type
s are:
int
: min
, max
values are supported, too
float
: min
, max
values are supported, too
enum
: enum
as a property specifies a list of string separated by ,
str
: string input
colorindex
: a color index from current palette (clamped)
bool
:
The desc
ription field is just for the user interface of the script parameter list.
A default
value can get set, too.
The order in the arguments table defines the order in which the arguments are passed over to the script.
+g_scenegraph
lets you access different nodes or create new ones.
The functions are:
+align()
: Allow to align all nodes on the floor next to each other without overlapping.
new(name, [region], [visible], [type=group])
: Creates a new node with the given name
, the size and position according to the region
and an optional visible
parameter. If region
is given a model is created - otherwise a group node. Valid values for type
are group
, point
and camera
(the default is group
).
get([nodeId])
: Returns the node
for the given nodeId
- if the nodeId
is not given, it will return the current active node. Which by default is the node for the volume the script is currently executed for.
getByName(name)
: Returns nil
if no node with the given name exists
getByUUID(uuid)
: Returns nil
if no node with the given uuid exists
activeAnimation()
: Return the current active animation
setAnimation(string)
: Activate the animation
addAnimation(string)
: Add a new animation
duplicateAnimation(animation, newAnimationName)
: Add a new animation by duplicating the given animation
hasAnimation(string)
: Check if the animation exists
nodeIds()
: Returns a table with all node ids of the current scene graph.
local allNodeIds = g_scenegraph.nodeIds()
+for i, nodeId in ipairs(allNodeIds) do
+ -- Do something with each nodeId
+end
+
+updateTransforms()
: Update the key frame transforms when they are dirty after changing values (see Keyframe
)addAnimation(string)
: Add a new animation
addKeyFrame(frame)
: Add a new key frame for frame number and return it. E.g. addFrame(20)
will add a new key frame for the frame 20.
hasKeyFrameForFrame(frame)
:
id()
: Returns the id of the current node
clone()
: Clones the current node
uuid()
: Returns the uuid of the current node
isCamera()
: Returns true if the node is a camera node
isGroup()
: Returns true if the node is a group node
isModel()
: Returns true if the node is a model node (it has a volume attached)
isPoint()
: Returns true if the node is a point node
isReference()
: Returns true if the node is a model reference
keyFrame(keyFrameIdx)
: Returns an existing keyframe (see below)
keyFrameForFrame(frame)
: Returns an existing keyframe that has a frame number <= the given frame
name()
: Returns the current name of the node.
setName(string)
: Set the name of the node.
palette()
: Returns the current palette of the node.
parent()
: Returns the id of the parent node - or -1
if no parent exists (root node)
removeKeyFrameForFrame(frame)
: Remove the keyframe for the given frame. Throws an error if no key frame with the given frame exists.
removeKeyFrame(keyFrameIdx)
: Remove the existing key frame at the given index. Throws an error if the index is invalid or the key frame doesn't exist.
setPalette(palette, [remap])
: Change the palette or if remap is given and is true it remaps to the new palette
setPivot(vec3)
, setPivot(x, y, z)
:
volume()
: Gives you access to the volume of a model node.
Access these functions like this:
+local scenegraphnode = [...]
+local name = scenegraphnode:name()
+
+++Valid interpolation strings
++
+- Instant
+- Linear
+- QuadEaseIn
+- QuadEaseOut
+- QuadEaseInOut
+- CubicEaseIn
+- CubicEaseOut
+- CubicEaseInOut
+
index()
: Returns the key frame index
frame()
: Returns the frame for this key frame object
interpolation()
: Returns interpolation string
setInterpolation(string)
: Set the interpolation for this key frame - must be a valid string
localScale()
: Returns the local scale vector
setLocalScale(vec3)
, setLocalScale(x, y, z)
:
localOrientation()
: Returns a quaternion object
setLocalOrientation(quat)
, setLocalOrientation(x, y, z, w)
:
localTranslation()
: Returns a vec3 object
setLocalTranslation(vec3)
, setLocalTranslation(x, y, z)
:
worldScale()
: Returns a vec3 object
setWorldScale(vec3)
, setWorldScale(x, y, z)
:
worldOrientation()
: Returns a quaternion object
setWorldOrientation(quat)
, setWorldOrientation(x, y, z, w)
:
worldTranslation()
: Returns a vec3 object
setWorldTranslation(vec3)
, setWorldTranslation(x, y, z)
:
++NOTE After you've modified something on a key frame, you have to call
+g_scenegraph.updateTransforms()
!
The node palette (node:palette()
) has several methods to work with colors. E.g. to find a closest possible match for the given palette index.
The functions are:
+color(paletteIndex)
: Pushes the vec4 of the color behind the palette index (0-255
) as float values between 0.0
and 1.0
.
rgba(paletteIndex)
: Pushes the four values of the color behind the palette index (0-255
).
colors()
: Returns the palette RGBA colors as vec4 values between 0.0
and 1.0
.
load(palette)
: Allows to load a built-in palette or a filename to a supported palette format.
material(paletteIndex, material)
: Get the value of the material property for the given palette index.
++Valid material names
+
match(r, g, b, [skipIndex])
: Returns the closest possible palette color match for the given RGB (0-255
) color. The returned palette index is in the range 0-255
. This value can then be used for the setVoxel
method. skipIndex
is not taken into account when doing the search.
setColor(paletteIndex, red, green, blue, [alpha])
: Change the color of a palette entry to the given rgba values in the range [0-255]
.
setMaterial(paletteIndex, material, value)
: Set the value of the material property for the given palette index.
++Valid material names
+
similar(paletteindex, [coloramount])
: Return a table with similar colors given by their palette index.
They are available as e.g. palette:color([...])
, palette:match([...])
and so on.
You can create new palettes with the g_palette
global by calling e.g.
local pal = g_palette.new()
+pal.load("built-in:minecraft")
+
+The global g_noise
supports a few noise generators:
noise2(v)
, noise3(v)
, noise4(v)
: Simplex noise. Uses the given vec2
, vec3
or vec4
and returns a float value between 0.0
and 1.0
.
fBm2(v, octaves, lacunarity, gain)
, fBm3(v, octaves, lacunarity, gain)
, fBm4(v, octaves, lacunarity, gain)
: Simplex noise fractal brownian motion sum. Uses the given vec2
, vec3
or vec4
and returns a float value between 0.0
and 1.0
.
ridgedMF2(v, offset, octaves, lacunarity, gain)
, ridgedMF3(v, offset, octaves, lacunarity, gain)
, ridgedMF4(v, offset, octaves, lacunarity, gain)
: Simplex ridged multi-fractal noise sum. Uses the given vec2
, vec3
or vec4
and returns a float value between 0.0
and 1.0
.
swissTurbulence(vec2, offset, octaves, lacunarity, gain, warp)
: blog post
voronoi(vec3, [frequency, seed, enableDistance])
: Voronoi noise.
worley2(v)
, worley3(v)
: Simplex cellular/worley noise. Uses the given vec2
or vec3
and returns a float value between 0.0
and 1.0
.
They are available as e.g. g_noise.noise2([...])
, g_noise.fBm3([...])
and so on.
The global g_shape
supports a few shape generators:
cylinder(centerBottom, axis, radius, height, voxel)
: Create a cylinder at the given position. The position is the center of the bottom plate with the given axis
(y
is default) as the direction.
torus(center, minorRadius, majorRadius, voxel)
: Create a torus at the given position with the position being the center of the object.
ellipse(centerBottom, axis, width, height, depth, voxel)
: Create an ellipse at the given position. The position is the center of the bottom plate with the given axis
(y
is default) as the direction.
dome(centerBottom, axis, negative, width, height, depth, voxel)
: Create a dome at the given position. The position is the center of the bottom plate with the given axis
(y
is default) as the direction. negative
: if true the dome will be placed in the negative direction of the axis.
cone(centerBottom, axis, negative, width, height, depth, voxel)
: Create a cone at the given position. The position is the center of the bottom plate with the given axis
(y
is default) as the direction. negative
: if true the cone will be placed in the negative direction of the axis.
line(start, end, voxel)
: Create a line.
cube(position, width, height, depth, voxel)
: Create a cube with the given dimensions. The position is the lower left corner.
bezier(start, end, control, voxel)
: Create a bezier curve with the given start
, end
and control
point
They are available as e.g. g_shape.line([...])
, g_shape.ellipse([...])
and so on.
contains(region)
: Check whether the current region contains the given one. The test is inclusive such that a region is considered to be inside of itself.
intersects(region)
: Check whether the current region intersects with the given one.
mins()
: The lower boundary of the region (inclusive).
maxs()
: The upper boundary of the region (inclusive).
size()
: The size of the region in voxels (ivec3
).
setMins(mins)
: The lower boundary of the region - given as ivec3
(atm only available for palettes created with new
).
setMaxs(maxs)
: The upper boundary of the region - given as ivec3
(atm only available for palettes created with new
).
x()
: The lower x boundary of the region.
y()
: The lower y boundary of the region.
z()
: The lower z bounary of the region.
width()
: The width of the region measured in voxels.
height()
: The height of the region measured in voxels.
depth()
: The depth of the region measured in voxels.
Access these functions like this:
+local region = [...]
+local mins = region:mins()
+
+To create new regions, you can use the g_region.new
function which needs the lower and upper boundaries. For example
local myregion = g_region.new(0, 0, 0, 1, 1, 1) -- creates a region with 8 voxels
+
+local myregion = g_region.new(0, 0, 0, 0, 0, 0) -- creates a region with 1 voxels
+
+voxel(x, y, z)
: Returns the palette index of the voxel at the given position in the volume [0-255]
. Or -1
if there is no voxel.
region()
: Return the region of the volume.
text(ttffont, text, [x], [y], [z], [size=16], [thickness=1], [spacing=0])
: Renders the given text
. x
, y
, and z
are the region lower boundary coordinates by default.
fillHollow([color])
: Tries to fill all hollows in the volume.
hollow()
: Removes non visible voxels.
importHeightmap(filename, [underground], [surface])
: Imports the given image as heightmap into the current volume. Use the underground
and surface
voxel colors for this (or pick some defaults if they were not specified). Also see importColoredHeightmap
if you want to colorize your surface.
importColoredHeightmap(filename, [underground])
: Imports the given image as heightmap into the current volume. Use the underground
voxel colors for this and determine the surface colors from the RGB channel of the given image. Other than with importHeightmap
the height is encoded in the alpha channel with this method.
importImageAsVolume(filename, [filename_depthmap], [palette], [depth], [bothsides])
: Imports the given image as volume with the depth values read from the given depth map image file. If no filename_depthmap
is given we are looking for the the same filename as given via filename
but with a -dm
as postfix. Example: filename
is foo.png
- then the default filename_depthmap
is foo-dm.png
.
crop()
: Crop the volume and remove empty spaces.
mirrorAxis([axis])
: Mirror along the given axis - y
is default.
move(x, [y], [z])
: Move the voxels by the given units without modifying the boundaries of the volume.
rotateAxis([axis])
: Rotate along the given axis - y
is default.
translate(x, [y, z])
: Translates the region of the volume. Keep in mind that this is not supported by every output format.
resize(x, [y, z, extendMins])
: Resize the volume by the given sizes. If extendsMins
is true
the region dimensions are also increased on the lower corner.
setVoxel(x, y, z, color)
: Set the given color at the given coordinates in the volume. color
must be in the range [0-255]
or -1
to delete the voxel.
Access these functions like this:
+local volume = [...]
+local region = volume:region()
+
+Available vector types are vec2
, vec3
, vec4
and their integer types ivec2
, ivec3
, ivec4
.
Access these functions like this:
+local v1 = g_ivec3.new(1, 1, 1)
+
+There are 3 possible components for this vector. You can also call g_ivec3.new(1)
to fill all three values with a one. Or call it like this: g_ivec3.new(1, 2)
to create a vector with the three components of 1, 2, 2
.
For creating quaternions, you can use g_quat.new()
rotateXYZ(x, y, z)
: Rotates the object along the X, Y, and Z axes by the specified angles.
rotateXY(x, y)
rotateYZ(y, z)
rotateXZ(x, z)
rotateX(x)
: Rotates the object along the X axis by the specified angle.
rotateY(y)
: Rotates the object along the Y axis by the specified angle.
rotateZ(z)
: Rotates the object along the Z axis by the specified angle.
You can perform http requests from within the lua script to query apis or download files
+local stream, responseHeaders = g_http.get("https://example.localhost")
+local str = stream:readString()
+print(str)
+for k, v in pairs(responseHeaders) do
+ print("key: " .. k .. ", value: " .. v)
+end
+
+local requestHeaders = {}
+local stream, responseHeaders = g_http.get("https://example.localhost", requestHeaders)
+
+local body = "my body"
+local stream, responseHeaders = g_http.post("https://example.localhost", body)
+local str = stream:readString()
+print(str)
+for k, v in pairs(responseHeaders) do
+ print("key: " .. k .. ", value: " .. v)
+end
+
+post(url, body, headers
: Execute a post request
get(url, headers)
: Execute a get request
g_import
is a global that offers the ability to load images and palettes or imports scene graphs/formats from e.g. http downloads.
image(filename, stream)
: Returns an image that was loaded.
palette(filename, stream)
: Returns a palette that was loaded.
scene(filename, stream)
: Imports the scene from the given stream into the existing scene (g_scenegraph
).
imageAsPlane(filename, image)
: Imports the given image as plane into the current scene graph and returns the node.
Images are loaded by the g_import
global.
name()
: Returns the name of the image
save(filename)
: Save the image as file (png
and jpeg
)
When using e.g. the g_http
requests, you get stream objects as return values.
readString([0-terminated:false])
: Reads a string from the stream. If the optional parameter 0-terminated
is set to true
, it reads until a null character is encountered otherwise it will read the whole stream as a string.
readUInt8()
: Reads an unsigned 8-bit integer from the stream.
readInt8()
: Reads a signed 8-bit integer from the stream.
readUInt16()
: Reads an unsigned 16-bit integer from the stream.
readInt16()
: Reads a signed 16-bit integer from the stream.
readUInt32()
: Reads an unsigned 32-bit integer from the stream.
readInt32()
: Reads a signed 32-bit integer from the stream.
readUInt64()
: Reads an unsigned 64-bit integer from the stream.
readInt64()
: Reads a signed 64-bit integer from the stream.
readFloat()
: Reads a 32-bit floating-point number from the stream.
readDouble()
: Reads a 64-bit floating-point number from the stream.
writeString(str, [0-terminated:false])
: Writes a string to the stream. If the optional parameter 0-terminated
is set to true
, it writes a null character at the end of the string.
writeUInt8(value)
: Writes an unsigned 8-bit integer to the stream.
writeInt8(value)
: Writes a signed 8-bit integer to the stream.
writeUInt16(value)
: Writes an unsigned 16-bit integer to the stream.
writeInt16(value)
: Writes a signed 16-bit integer to the stream.
writeUInt32(value)
: Writes an unsigned 32-bit integer to the stream.
writeInt32(value)
: Writes a signed 32-bit integer to the stream.
writeUInt64(value)
: Writes an unsigned 64-bit integer to the stream.
writeInt64(value)
: Writes a signed 64-bit integer to the stream.
writeFloat(value)
: Writes a 32-bit floating-point number to the stream.
writeDouble(value)
: Writes a 64-bit floating-point number to the stream.
eos()
: returns whether the stream has reached its end
seek(offset, mode)
: change the position in the stream
tell()
: returns the current position in the stream
pos()
: alias for tell()
size()
: returns the size of the stream
g_var.int("cl_gamma")
+
+create(name, value, help = nil, nopersist = false, secret = false)
: Create a new cvar that is persisted by default.
str()
: Returns the string value of the cvar
bool()
: Returns the bool value of the cvar
int()
: Returns the int value of the cvar
float()
: Returns the float values of the cvar
setStr(value: string)
: Sets the string value of the cvar
setBool(value: bool)
: Sets the bool value of the cvar
setInt(value: number)
: Sets the int value of the cvar
setFloat(value: number)
: Sets the float values of the cvar
++To get a full list of cvars use the console command
+cvarlist
.
g_cmd.execute("echo test")
+
+execute(cmdline: string)
: Execute any of the known commands++To get a full list of commands use the console command
+cmdlist
.
To use the built-in logging facilities use g_log
with info
, debug
, warn
and error
The system module is available with g_sys
- and includes the following functions
sleep(ms)
: Sleep the given millisecondsy
going upwards - see basics for further details.Add animations to an existing model if you name the nodes properly.
+xs animate.lua
Generates a new voxel on top of others with the current selected color and the specified height.
+ +xs cover.lua 1
Generate grass on top of voxels.
+ +xs grass.lua
Generates a grid with given color, thickness and size.
+ +xs grid.lua 1 1 5 5 5
Generates perlin noise with the frequency and amplitude as parameters with the current selected color.
+ +xs noise.lua 0.3 1.0
Generates a pyramid with the current selected color and with each level being 3 voxels high.
+ +xs pyramid.lua 3
Thickens the voxel - take 1 voxel and convert to 8 voxels (creates a new node for the result).
++
xs thicken.lua 1
There are other scripts available in the repository.
+This module is here to ease the process of visiting all the voxels in a volume
+++Keep in mind the
+-1
is an empty voxel
local vol = require "modules.volume"
+
+function main(node, region, color, emptycnt, octaves, lacunarity, gain, threshold)
+ local visitor = function (volume, x, y, z)
+ local color = volume:voxel(x, y, z)
+ if color == -1 then
+ -- empty voxel
+ else
+ -- solid voxel
+ end
+ end
+
+ local condition = function (volume, x, y, z)
+ -- add your checks here
+ return true
+ end
+ vol.conditionYXZ(node:volume(), region, visitor, condition)
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Each color entry in the palette can have several material properties. Most of them are not handled in the vengi renderers, but can be useful when exporting the voxels to other formats.
+++The material support in vengi is modelled after magicavoxel.
+
The following material names are imported from magicavoxel and a few of them are exported to the GLTF-format.
+Material name | +GLTF mapping | +
---|---|
metal |
+pbrMetallicRoughness | +
roughness |
+KHR_materials_pbrSpecularGlossiness, pbrMetallicRoughness | +
specular |
+KHR_materials_specular | +
indexOfRefraction |
+KHR_materials_ior | +
attenuation |
+KHR_materials_volume | +
flux |
++ |
emit |
+Emission texture | +
lowDynamicRange |
++ |
density |
+KHR_materials_pbrSpecularGlossiness | +
sp |
++ |
glossiness |
+KHR_materials_pbrSpecularGlossiness | +
media |
++ |
You can also modify these values via scripting.
+Some of the material properties are exported to GLTF 2.0 or some of the extensions:
+ + + + + + + + + + + + + + +The engine is built around a palette of 256 colors. Custom palettes are supported. The images should have a 1x256 pixel dimension.
+You can import palettes from a lot of different image, palette or voxel volume formats (if supported).
+Each color entry can get material properties.
+The palette can usually be specified by the cvar palette
and can either be a full path to a png file or an identifier.
+If you decide to use the identifier - e.g. nippon
the palette
cvar is set to this value and the engine will automatically search
+all registered file system paths for a file named palette-nippon.png
.
There are several built-in palettes available that can also be used as an identifier.
+built-in:commandandconquer
built-in:magicavoxel
built-in:minecraft
built-in:nippon
built-in:quake1
built-in:starmade
You can also download and import palettes from Lospec by specifying a palette like this:
+lospec:paletteid
This would try to download a palette with the id paletteid
from lospec.com in the Gimp (gpl
) format and automatically imports it.
There are several color or palette related cvars available:
+voxformat_createpalette
: Allows you to disable the palette creation and use the palette specified via palette
cvarcore_colorreduction
: Allows you to specify a color reduction value when e.g. importing RGB(A) based voxel or mesh formats. Possible values are: Octree
, Wu
, MedianCut
, KMeans
, NeuQuant
.You can find the detailed description and more cvars by using e.g. the voxconvert --help
parameter
Command & Conquer supports voxel normals. vengi-voxedit
got a few features to support this. Change the view mode to Command & Conquer to see a normal palette panel and to be able to render the normals for the voxels.
This tool parses GLSL shader files (mainly *.vert
, *.frag
, *.geom
and *.comp
) and generates C++ source files for them.
++You automatically get the shaders added back to the code after saving a shader file and trigger a re-build.
+
The cmake macros expect the shader source below the module in a shaders/
directory.
set(SHADERS first second)
+engine_generate_shaders(mymodulename ${SHADERS})
+
+The shaders given in this example would be located at src/modules/mymodulename/shaders/first.*
. The tool automatically detects the type of programs that should be connected in the final shader.
The code is generated into the build directory in generated/shaders
.
The generator uses ShaderTemplate.h.in
and UniformBufferTemplate.h.in
as a base to generate the C++ source files.
There are several variables in the template file that are replaced by the generator.
+$includes$
$namespace$
$name$
$setters$
$attributes$
$uniforms$
$uniformarrayinfo$
$shutdown$
$uniformbuffers$
The parser includes a preprocessor.
+You can export constants from the GLSL shader code to the generated C++ code by using $constant
.
Use $constant varname 42
to generate a method that returns 42 with a name getVarname
Usually you don't have to use branching and uniforms for feature toggles. You can use cvars with the flag CV_SHADER
set. If you are going to change one of these cvars, the shaders are recompiled with the value of the cvar given as preprocessor define.
This means that you can do stuff like:
+#if cl_shadowmap == 1
+ [...]
+#else
+ [...]
+#endif
+
+The #define
of cl_shadowmap
is done by the shader system at compile time.
The applications are directly reading po
files.
++What are
+po
files? +po
(portable object) files are used by the gettext translation system and a lot of tools exist to edit them (e.g. poedit)
To create a new translation you should use the pot
file located in data/shared
in the repository.
After you've created a new po
file, copy them into any of the search paths (either directly, or in a folder named po
) and give it the name as specified here.
++Example: Name it after the pattern
+ll_CC
wherell
is an ISO-639 two-letter language code, andCC
is an ISO-3166 two-letter country code.
If you create a new translation it would be nice if you would contribute it to the project.
+++Translators don't have to do this
+
After new string were added in the code, you have to update the pot
file to make those strings available to the translators.
There is a Makefile
target called pot
- so if you have gnu make installed, just run make pot
in the root of the project. Otherwise use the tool xgettext
to extract the strings from the source code.
use the _
macro to mark a string as being translatable. E.g. _("my string")
For only extracting them, but not translating them, you can use N_("my string")
. Now my string
appears in the pot
file, but the location where the string is stored, is still the english string my string
- not anything translated.
By adding a context to the translators you could make things clearer, e.g. use C_("Some string that describes the translatable string", "my string")
to add a msgctxt
line to the pot file. And there is also a NC_
version that works like the above mentioned N_
.
These tests are dedicated test applications. They are no unit tests.
+Unit tests are in their own module and available via
+make tests
+
+Run these test applications with
+make __directoryname__-run
+
+or by directly executing the generated binary after compiling them.
+A test application that applies bloom to an image
+Test camera options and collisions.
+Uses GLSL compute shader to render a circle.
+Test the dearimgui integration
+Renders the octree internals.
+Visit the frustum in the octree.
+Renders a plane object.
+Just an empty template for new test applications.
+Renders a test 2d image.
+ + + + + + + + + + + + + +