A set of open c++ game development tools that are lightweight, easy-to-integrate and free to use. Currently hosting a magicavoxel .vox full scene loader.

Overview

open game tools

Open game tools is a set of unencumbered, free, lightweight, easy-to-integrate tools for use in game development.

So far it contains:

  • ogt_vox.h a MagicaVoxel scene reader, writer and merger
  • ogt_voxel_meshify.h a few routines to convert voxel grid data to triangle mesh.
  • vox2fbx.cpp an application to extract models from .vox and save them to ascii fbx
  • voxseparate.cpp an application to extract models from .vox and save them to separate .vox files.

Please consider contributing fixes, extensions, bug reports or feature requests to this project. If you have example scenes that fail to load or save correctly, feel free to send them to me and I'd be happy to investigate and make fixes for you.

See CONTRIBUTING.md for more details.

ogt_vox: MagicaVoxel scene reader, writer and merger

A C++ reader, writer and scene merger for MagicaVoxel's vox file format.

Scene reading (.vox)

With this library, reading a .vox file will result in a ogt_vox_scene structure which you use to:

  • enumerate all or a subset of instance placements within a vox file.
  • get the transforms for those instances as a matrix flattened relative to the scene file, or relative to their group hierarchy
  • access the voxel model referenced by those placements ie. the 3d color grid.
  • access the palette colors
  • access layer, group and visible/hidden state for instances / groups.

I use this library to deep-reference models in .vox files and turn them into triangle meshes in my engine's importer/cooker. I also use it in an in-engine wizard to import all instance/scene data into your own engine scene format. This can allow your artists to use MagicaVoxel as a level editor, or simply a tool for managing a kit, palette of module-set to be used within levels or objects within your own editor.

Scene Writing (.vox)

The C++ writer for MagicaVoxel's vox file format takes a user-constructed ogt_vox_scene structure and serializes it to .vox file format. When saved out to disk, it'll be loadable in MagicaVoxel.

My own testing involved going through all of my on-disk vox files, and verified they load in MagicaVoxel 0.99.3-alpha. The files are usually smaller than the source .vox though because they will not preserve all the chunks within the original .vox file.

Scene Merging (.vox)

You can load multiple .vox files simultaneously to obtain multiple ogt_vox_scene structures. You can then merge them into a single ogt_vox_scene and save it out.

If they have different palettes, the merger will do closest-color matches to try preserve the original colors in the output file.

If you find yourself needing to combine multiple files with very similar but non-identical palettes then this is probably the tool for you. If you need to combine multiple files with completely different palettes that have only a few entries used, then this may also be for you!

It should always work, but it may not give a good color fit if the voxel files you use most of their colors and have their own very different palettes. If you want to simply replace the merged file with a very specific palette, you can provide that to the merge function too.

In the future, I might add a more holistic algorithm that prioritizes allocation to the final palette of colors based on their distance from other colors.

Usage

See demo_vox.cpp for a simple example.

  1. Include ogt_vox.h directly from one of your C or CPP files:

         #define OGT_VOX_IMPLEMENTATION
         #include "ogt_vox.h"
  2. Use your own file utilities to load a .vox file into a memory buffer. eg.

     FILE* fp = fopen("file.vox", "rb");
     uint32_t buffer_size = _filelength(_fileno(fp));
     uint8_t* buffer = new uint8_t[buffer_size];
     fread(buffer, buffer_size, 1, fp);
     fclose(fp);
  3. Pass the buffer into ogt_vox_read_scene to get a scene object eg.

     const ogt_vox_scene* scene = ogt_vox_read_scene(buffer, buffer_size);
     // the buffer can be safely deleted once the scene is instantiated.
     delete[] buffer;
  4. Now read all the information you need from the scene object and use it to import voxel data/instances. eg. Here, I just print some basic information:

     printf("# models: %u\n",  scene->num_models);
     printf("# instances: %u\n", scene->num_instances);
  5. Shut down the scene to release the memory it allocated. eg.

    ogt_vox_destroy_scene(scene);

Note

The reader, writer and merge functionaliy supports the most relevant chunks as described here:

MATL chunks are only supporting for loading APIs, but is expected that saving and merging will come in a later change. CAVEAT: loading of MATL chunks are most accurate when written by recent Magicavoxel versions (0.99.6.2 and 0.99.6.3 at time of writing). Chunks written by earlier versions may not be decoded accurately.

rOBJ/MATT chunks are not supported in any capacity for now. If there is interest, do let us know in the Issues section.

ogt_voxel_meshify: converts voxel grid data to triangle mesh data

This module contains 3 routines for converting paletted voxel grid data to triangle mesh data.

  • ogt_mesh_from_paletted_voxels_simple: returns the most naieve mesh possible, which will be tessellated at voxel granularity. image

  • ogt_mesh_from_paletted_voxels_greedy: uses a greedy box-expansion pass to replce rectangular regions of voxels of the same color with a larger polygon that covers the box. It will generally produce t-junctions which can make rasterization not water-tight based on your camera/project/distances. image

  • ogt_mesh_from_paletted_voxels_polygon: will polygonize and triangulate connected voxels that are of the same color. The boundary of the polygon will be tessellated only to the degree that is necessary to there are tessellations at color discontinuities. Generally produces slightly more triangles that greedy meshing but it is mostly water-tight, except for a very small number of cases. image

More documentation and a demo will be added soon.

vox2fbx: Tool for extracting meshifying models from Magicavoxel .vox and saving them to .fbx

This is a command-line tool which will find all named voxel grid models in a vox file, turn them into a mesh using one of 3 algorithms (simple, greedy or polygon) each of which produce different density mesh with varying levels of water-tightness (ie. t-junctions), then save those meshes out to individual fbx files.

It can be used from command-line with these args:

  • --mesh_algorithm : (default: polygon) sets the meshing mode where is one of: simple, greedy or polygon
  • --named-models-only : (default: disabled) will only generate an fbx for models in the vox file that have named instances
  • --y-as-up : (default: disabled) rotate model on export so that y is up

It can also be used from windows explorer by dragging-and-drop your .vox files onto it, and it will produce an output fbx file for each grid model in each .vox file.

voxseparate: Tool for extracting models from a multi-model Magicavoxel .vox and saving them to individual .vox files

Provide input .vox files on the command line, and output files will be written out to the same directory, with autogenerated names based on the names of instances of models within these input .vox files.

It can also be used from windows explorer by dragging-and-drop your .vox files onto it, and it will produce an output vox file for each model in each .vox file.

Projects using open game tools

Acknowledgements

Thanks to @ephtracy. So much would not have been possible without your generosity in releasing the tool free to the public, releasing information about the file format and patiently answering my DMs on twitter.

Thanks to @nothings for sharing your single-headers as well as the philosophy behind them. The latter has been invaluable to my personal growth.

Thanks to @ndreca_com for feedback on the ogt_vox library!

Thanks to all contributors so far!

Comments
  • Feature request: Merging models

    Feature request: Merging models

    I'm hoping it would be an easy task to merge multiple models into a single model. I'm looking for functionality similar to MagicaVoxel's 'union' (U) function when selecting a root node.

    opened by cshlin 16
  • ogt_vox: added initial support for CHUNK_ID_MATL

    ogt_vox: added initial support for CHUNK_ID_MATL

    The CHUNK_ID_MATL appears to be the current approach for extended material information in MagicaVoxel, with CHUNK_ID_MATT being obsolete - the former is present in all .vox files exported currently, but not the later.

    I have added initial support for reading this chunk in this PR, which is intended primarily as a discussion for the implementation approach prior to my making any changes along with adding support for writing these values back.

    An alternative approach might be to keep the material data as a dictionary of parameters - the size of the smallest dict for each material (default diffuse) is 36bytes, and the current structure is 64 bytes, so if most materials are diffuse using dicts might be a small saving in space.

    opened by dougbinks 7
  • ogt_vox: Order of input models is changes on save/load

    ogt_vox: Order of input models is changes on save/load

    The order of models that I hand over to ogt_vox_write_scene is changed in ogt_vox_read_scene. It would be nice if I could disable this feature with a flag.

    opened by mgerhardy 5
  • ogt_vox : implement animation looping and sampling

    ogt_vox : implement animation looping and sampling

    This seems to work on a number of import tests I've done locally. @mgerhardy @dougbinks please take a look and let me know if this works okay within your codebases too. Thanks!

    There is a small API incompatibility if you already grabbed the initial animation support -- I've wrapped animations into their own structs instead of having keyframes+count embedded within instances/groups, but it should be a fairly straightforward thing to fix up.

    Please let me know if you have any additional thoughts before I merge. Will try do so early next week, thanks!

    opened by jpaver 4
  • ogt_vox: Hints about applying the transform

    ogt_vox: Hints about applying the transform

    Maybe it's obvious for everybody except me, but I thought that sharing my current implementation might help others and is a good opportunity to get some feedback on my solution:

    const glm::vec4 pivot(
    	floor(model->size_x / 2.0f),
    	floor(model->size_y / 2.0f),
    	floor(model->size_z / 2.0f), 
    	0.0f
    );
    
    /**
     * @brief Calculate the scene graph object transformation. Used for the voxel and the AABB of the volume.
     *
     * @param mat The world space model matrix (rotation and translation) for the chunk
     * @param pos The position inside the untransformed chunk (local position)
     * @param pivot The pivot to do the rotation around. This is the @code chunk_size - 1 + 0.5 @endcode. Please
     * note that the @c w component must be @c 0.0
     * @return glm::vec4 The transformed world position
     */
    static inline glm::vec4 transform(const glm::mat4x4 &mat, const glm::ivec3 &pos, const glm::vec4 &pivot) {
    	return glm::floor(mat * (glm::vec4((float)pos.x + 0.5f, (float)pos.y + 0.5f, (float)pos.z + 0.5f, 1.0f) - pivot));
    }
    
    const uint8_t *ogtVoxels = model->voxel_data
    for (uint32_t k = 0; k < model->size_z; ++k) {
    	for (uint32_t j = 0; j < model->size_y; ++j) {
    		for (uint32_t i = 0; i < model->size_x; ++i, ++ogtVoxel) {
    			if (ogtVoxel[0] == 0) {
    				continue;
    			}
    			const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, _palette[ogtVoxel[0]]);
    			const glm::ivec3& pos = transform(ogtMat, glm::ivec3(i, j, k), pivot);
    			const glm::ivec3& poszUp = transform(zUpMat, pos, glm::ivec4(0));
    			v->setVoxel(poszUp, voxel);
    		}
    	}
    }
    

    the zUpMat is just to bring everything into my own coordinate system (y upwards)

    const glm::mat4 zUpMat = glm::rotate(glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    

    If I am doing something stupid here, please let me know. If not it might help others.

    Find the full source code at https://github.com/mgerhardy/vengi/blob/master/src/modules/voxelformat/VoxFormat.cpp

    opened by mgerhardy 4
  • Any writing of voxels object to Wavefront obj?

    Any writing of voxels object to Wavefront obj?

    Hello,

    Great project! I looked at the source code and did not find a way to write the voxels into a mesh OBJ file. Is that correct? I know Magikavoxel can do it but I want to automate this. Is this hard to implement from the current state of the project? I never really worked with it but if I have time maybe I can have a look at it? Just a bit busy right now.

    Best, Quentin

    opened by GrapixLeGrand 3
  • Retrieving the palette index from the mesh generator

    Retrieving the palette index from the mesh generator

    Hello, thanks for this awesome library!

    While working on using this library to import .vox models into Godot, it seems like I faced a limitation regarding how meshes are returned to the user. While using ogt_mesh_from_paletted_voxels_polygon I figured out I could not find a way to access the palette index associated to a given generated vertex. However, it would be very useful to me to retrieve the corresponding material properties (metalness, emissive, etc...).

    Please let me know if I am right here, and there indeed no easy way to retrieve this. If I am and you are interested, I would be happy to contribute a simple enhancement to the library, likely by adding a palette index property in ogt_mesh_vertex (Or maybe removing the color property, since it could be retrieved from the palette anyway ?).

    opened by groud 3
  • draft: Voxel tessellation filter.

    draft: Voxel tessellation filter.

    Hey @jpaver time for me to bug you again 😄

    This time I added a function pointer parameter to ogt_stream_from_paletted_voxels_simple to allow a user function to specify conditions for which tessellation for any given voxel should be skipped. For me this is useful to dynamically filter out specific voxel types at tessellation time, so the user can view different sets of voxel types which comprise the volume.

    Just let me know if you'd like me to change anything.

    opened by mrpossoms 3
  • ogt: add ogt_stream_from_paletted_voxels_simple api

    ogt: add ogt_stream_from_paletted_voxels_simple api

    Added new function ogt_stream_from_paletted_voxels_simple which is a simple variant of ogt_mesh_from_paletted_voxels_simple that does not return an ogt_mesh, but rather calls into a user-provided function.

    The use case for this is to

    1. provide a way for caller to modify geometry for each x/y/z voxel that generates geometry by using the x/y/z information to lookup additional non-voxel-field data.
    2. not have to allocate ogt_mesh_vertex data for the entire voxel field, which can be useful if direclty converting to a custom vertex format without basically doubling the memory footprint.

    Internally, ogt_mesh_from_paletted_voxels_simple simply uses ogt_stream_from_paletted_voxels_simple to build up the ogt_mesh now.

    opened by jpaver 3
  • Meshify User Callback

    Meshify User Callback

    Added callback to context and ogt_mesh_from_paletted_voxels_simple to allow caller code to intercept / modify vertex information when a voxel has been tesselated.

    This is useful for ogt users who may have state data in addition to the voxel volume which may influence the appearance of the voxels, or even their own vertex definitions.

    opened by mrpossoms 3
  • ogt_vox: expose animation looping status

    ogt_vox: expose animation looping status

    This appears to exist as _loop=1 on nTRN and nSHP chunk node dicts, so should be read/merged/written on both groups (transform anims) and instances (transform and model animations).

    opened by jpaver 2
  • ogt_vox: setting k_read_scene_flags_groups false looses hidden and layer information

    ogt_vox: setting k_read_scene_flags_groups false looses hidden and layer information

    If k_read_scene_flags_groups is set to false loading the scene will loose information about hidden groups or group layers & thus groups which are in hidden layers.

    This is because in addition to flattening the transform hierarchy the instance group_index is set to 0.

    I am not sure of the best way to resolve this. Preserving the group_index might work but would potentially break some code, flattening the hidden information might work but a group can be in a layer different to it's children so that also needs to be taken into account. A new flag might be needed (perhaps k_flatten_hidden which flattens both layer and group hidden).

    For my own code I am now going to flatten the transform hierarchy myself to work around this.

    opened by dougbinks 0
  • ogt_vox: instance order differences between file versions

    ogt_vox: instance order differences between file versions

    In MV vox files the instance order is important for the correct rendering of overlapping voxels. The first instance will 'replace' voxels in later instances. This instance order applies to groups and within groups.

    Currently it seems that the instance order read by ogt_vox for version 200 files is inverted with respect to version 150 files. I haven't yet looked into whether this is ogt_vox or the actual file order.

    My quick fix was to add a read for the version and switch order (extra note: it could be useful if the version was stored as part of the scene). I will look into this issue in more depth soon.

    opened by dougbinks 3
  • ogt_vox : materials are not merged correctly

    ogt_vox : materials are not merged correctly

    Currently, the materials are well loaded with load_vox_scene but are not merged correctly in ogt_vox_merge_scenes. Thus no materials other than diffuse (default) exist in the merged scene.

    opened by jibjoub 1
  • ogt_vox : add formal test cases

    ogt_vox : add formal test cases

    • to prevent regressions with further dev, we'd like coverage on: -- files produced by various magicavoxel versions. eg. early versions that don't produce nSHP/nTRN/nGRP chunks. -- groups vs flattening -- animation sampling
    • we may also want to try some fuzzer testing.
    opened by jpaver 0
  • ogt_vox: group instances are not preserved when writing scenes

    ogt_vox: group instances are not preserved when writing scenes

    I recently learned Magicavoxel supports copying groups by reference, which means the underlying scene hierarchy is a directed-acyclic-graph that has leaf nodes or group nodes with multiple parents ie. diamond patterns in the graph.

    ogt_vox exposes the scene hierarchy as a tree with instances as the leaf nodes and with groups as the branches, so has no diamond patterns.

    ogt_vox_read_scene does in fact work when loading scenes that contain group references, it just does not preserve the group information when the scene is re-saved out via ogt_vox_write_scene.

    We should look into options for supporting this, and whether it can be done without changes to client code that uses ogt_vox.

    opened by jpaver 0
  • ogt_vox: getting access to the dict key/value entries

    ogt_vox: getting access to the dict key/value entries

    Getting access to the key/value entries of every dict in a scene would be nice - this would e.g. allow to do something with the rOBJ chunks, but at least write them back properly to the file (because most of the are unknown or different from version to version anyway)

    opened by mgerhardy 0
Owner
I am a former pro game developer/techologist, now working outside games. I'm still a hobbyist game developer and working on my own indie game(s).
null
Cocos2d-x is a suite of open-source, cross-platform, game-development tools used by millions of developers all over the world.

Cocos2d-x is a suite of open-source, cross-platform, game-development tools used by millions of developers all over the world.

cocos2d 16.7k Dec 2, 2022
StereoKit is an easy-to-use open source mixed reality library for building HoloLens and VR applications with C# and OpenXR!

StereoKit is an easy-to-use open source mixed reality library for building HoloLens and VR applications with C# and OpenXR! Inspired by libraries like XNA and Processing, StereoKit is meant to be fun to use and easy to develop with, yet still quite capable of creating professional and business ready software.

Nick Klingensmith 720 Dec 3, 2022
A basic 3D scene implemented with various engines, frameworks or APIs.

Here be dragons Hic sunt dracones. This repository contains multiple implementations of the same 3D scene, using different APIs and frameworks on vari

Simon Rodriguez 1.7k Dec 3, 2022
3D Solar System Scene

This was my Computer Graphics' project. In this i used OpenGL and Glut to create a 3D Solar System Scene. Its without textures and wrapping. Just the most basic functionalities.

Hassan Shahzad 7 Jun 20, 2022
Open source Altium Database Library with over 147,000 high quality components and full 3d models.

Open source Altium Database Library with over 147,000 high quality components and full 3d models.

Mark 1.3k Dec 3, 2022
GUI frontend for moonlight-embedded, (currently) runs on webOS

Moonlight TV Moonlight TV is a GUI front end for Moonlight GameStream Client. With some components from moonlight-embedded. It was originally designed

Mariotaku 423 Nov 28, 2022
My computer graphics playground. Currently has a raytracer implemented with D3D11 compute shader.

Graphics Playground I use this project as my "toy" engine. I'll be implementing various graphics projects in this repository. The code here is not sui

Berk Emre Sarıbaş 4 Aug 26, 2021
Lightweight OpenCL-Wrapper to greatly simplify OpenCL software development with C++ while keeping functionality and performance

OpenCL-Wrapper OpenCL is the most powerful programming language ever created. Yet the OpenCL C++ bindings are very cumbersome and the code overhead pr

Moritz Lehmann 86 Nov 27, 2022
A completely free, open-source, 2D game engine built on proven torque technology.

Torque2D 4.0 Early Access 1 MIT Licensed Open Source version of Torque2D from GarageGames. Maintained by the Torque Game Engines team and contribution

Torque Game Engines 652 Dec 3, 2022
OpenCorr is an open source C++ library for development of 2D, 3D/stereo, and volumetric digital image correlation

OpenCorr OpenCorr is an open source C++ library for development of 2D, 3D/stereo, and volumetric digital image correlation. It aims to provide a devel

Zhenyu Jiang 64 Nov 30, 2022
Powerful, easy to use, and portable visualization toolkit for mixed 3D and 2D content

Powerful, easy to use, and portable visualization toolkit for mixed 3D and 2D content

Microsoft 133 Nov 19, 2022
C Wavefront OBJ loader for OpenGL

OBJ GL Loader v2 Quite fast .OBJ loader written in C How to use it Put objgl2.c and objgl2.h files in Your project and include them. To put it simply:

null 9 Oct 14, 2022
Vizzu is a free, open-source Javascript/C++ library for animated data visualizations and data stories.

Vizzu is a free, open-source Javascript/C++ library utilizing a generic dataviz engine that generates many types of charts and seamlessly animates between them

Vizzu 1.6k Dec 1, 2022
Full-body tracking in VR using AprilTag markers.

Full-body tracking in VR using AprilTag markers.

null 869 Dec 2, 2022
Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform AAA Open 3D Engine

Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform 3D engine that enables developers and content creators to build AAA games, cinema-quality 3D worlds, and high-fidelity simulations without any fees or commercial obligations.

O3DE 5.7k Nov 24, 2022
The DirectX Shader Compiler project includes a compiler and related tools used to compile High-Level Shader Language (HLSL) programs into DirectX Intermediate Language (DXIL) representation

DirectX Shader Compiler The DirectX Shader Compiler project includes a compiler and related tools used to compile High-Level Shader Language (HLSL) pr

Microsoft 2.4k Nov 24, 2022
Mandelbrot set visualization in OpenGL

Mandelbort-Set done in OpenGL Steps to build and run ( program tested only on Linux-Ubuntu 18.04,20.04 ) install the necessary packages- glut,glfw,glm

Paleti Krishnasai 2 Feb 13, 2022
Dear PyGui 3D Engine (early development) and Graphics API demos.

Marvel This repo is the working location of the eventual Dear PyGui 3D Engine. It also contains several single file examples of creating a triangle wi

Jonathan Hoffstadt 85 Nov 23, 2022