Minimalist base-project for interactive graphical applications (2D/3D)
Written in plain C (compatible with C++)
Pure-software (no hardware acceleration of any kind)
Focuses on simplicity, ease of use and brain-dead setup (single header file, no dependencies)
Built on: SlimApp
Used in: SlimTracin and SlimRaster
SlimEngine is platform-agnostic by design, though currently only supports Windows.
The platform layer only uses operating-system headers - no standard library used.
The application layer itself has no 3rd-party dependencies - only uses standard math headers.
It is just a library that the platform layer uses - it has no knowledge of the platform.
More details on this architecture here.
The single header file variant includes everything.
Otherwise, specific headers can be included from the directory of headers.
The main entry point for the app needs to be defined explicitly (see SlimApp).
SlimEngine comes with pre-configured CMake targets for all examples.
For manual builds on Windows, the typical system libraries need to be linked
(winmm.lib, gdi32.lib, shell32.lib, user32.lib) and the SUBSYSTEM needs to be set to WINDOWS
All examples were tested in all combinations of:
Source: Single header file (SlimEngine.h), Directory of headers (specific includes)
Compiler: MSVC, MinGW, CLang
Language: C, C++
CPU Arch: x86, x64
SlimEngine extends SlimApp and so inherits all it's features
Additional features include facilities for interactive 3D applications:
- A scene with cameras, meshes and parametric curves
- Scene selection and interactive transformations (moving, rotating and scaling)
- 3D Viewport with a HUD and rich mouse/keyboard navigation
- 3D Line drawing for wireframe rendering (optionally multi-sampled for very clean lines)
Well documented example applications cover the features:
-
3D Viewports:

Viewports come with a HUD that can be toggled on/off
SlimEngine comes with an empty scene, apart from a default camera bound to a default viewport.
The window content is bound to the default viewport, so they resize together.
Customizing the scene/viewport can be done in callbacks that get invoked when they're ready.
The HUD is fully customizable, and can hold any number of lines set at viewport-initialization time. -
Viewport: Navigation

Viewport navigation actions can be composed to set-up WASD(FPS)/DCC(orb) navigation style(s).
Keyboard navigation is agnostic to key-binding and is trivial to map keys to.
It supports moving forward, backwards, left, right, up and down and turning left or right.
Mouse navigation controls the viewport's camera and is more granular.
It can pan, zoom, dolly, orient or orbit the camera around a target. -
Cameras: Viewport binding

The scene can have any number of cameras which can be bound to any viewport dynamically.
The camera can be drawn as part of the drawing of the scene -
Shapes: Setup and drawing parametric primitives (Grid, Box, Curves, etc.)

SlimEngine allocates and initializes the scene based on quantities set at app-initialization time.
Wireframe drawing of the scene to the viewport can be set-up to occur on window-redraw. -
Scene: Object selection and manipulation (Translation, Rotation and Scale)

Scene objects can be dragged around the screen, moving them parallel to the viewing plane.
Selecting an object displays it's bouding box, enabling for per-axis translation, rotation and scaling. -
Scene: Mesh loading from file, instancing and wire-frame drawing

Meshes can be loaded from binary files, with vertex positions, normals and texture coordinates.
They can be moves and transformed just like any other kind of primitive.

A mesh can have multiple instances, each with their own transformation and colors.
Simply have multiple mesh primitives all set with same mesh id.
Memory is allocated automatically for the meshes by reading their headers before loading. -
Scene: Saving to and loading from
.scenefiles

Scenes can be saved to a file and later loaded back in-place. -
obj2mesh: Also privided is a separate CLI tool for converting
.objfiles to.meshfiles.
It is also written in plain C (so is compatible with C++)
Usage:./obj2mesh src.obj trg.mesh- invert_winding_order : Reverses the vertex ordering (for objs exported with clockwise order)
- invert_winding_order : Reverses the vertex ordering (for objs exported with clockwise order)
SlimEngine does not come with any GUI functionality at this point.
Some example apps have an optional HUD (heads up display) that shows additional information.
It can be toggled on or off using thetab key.
All examples are interactive using SlimEngine's facilities having 2 interaction modes:
- FPS navigation (WASD + mouse look + zooming)
- DCC application (default)
Double clicking the left mouse button anywhere within the window toggles between these 2 modes.
Entering FPS mode captures the mouse movement for the window and hides the cursor.
Navigation is then as in a typical first-person game (plus lateral movement and zooming):
Move the mouse to freely look around (even if the cursor would leave the window border)
Scroll the mouse wheel to zoom in and out (changes the field of view of the perspective)
Hold W to move forward
Hold S to move backward
Hold A to move left
Hold D to move right
Hold R to move up
Hold F to move down
Exit this mode by double clicking the left mouse button.
The default interaction mode is similar to a typical DCC application (i.e: Maya):
The mouse is not captured to the window and the cursor is visible.
Holding the right mouse button and dragging the mouse orbits the camera around a target.
Holding the middle mouse button and dragging the mouse pans the camera (left, right, up and down).
Scrolling the mouse wheel dollys the camera forward and backward.
Clicking the left mouse button selects an object in the scene that is under the cursor.
Holding the left mouse button while hovering an object and then dragging the mouse,
moves the object parallel to the screen.
Holding alt highlights the currently selecte object by drawing a bounding box around it.
While alt is still held, if the cursor hovers the selected object's bounding box,
mouse interaction transforms the object along the plane of the bounding box that the cursor hovers on:
Holding the left mouse button and dragging the mouse moves the object.
Holding the right mouse button and dragging the mouse rotates the object.
Holding the middle mouse button and dragging the mouse scales the object.
(mouse wheel interaction is disabled while alt is held)
In addition to examples of specific features, a more real-world application is also included here:
It is the full source code used for all interactive visualizations in a video about Perspective Projection
The video was a submission to 3Blue1Brown's Summer of Math Explainers (a.k.a: SoME1) competition.
It covers how perspective projection works when using graphics hardware, in its native 4D projective space.
Since it's using SlimEngine it has no dependencies and is structures as a single compilation unit (Unity Build).
It can therefore be easilly compiled with any C/C++ compiler by just compiling the 'perspective_projection.c' file.
As with the other examples, a CMake target is already set up for it here.
There are 5 separate visualizations:
- Intro : A rotating cube being projected onto a projection plane.
- Projective Space : A projective space centered on the secondary camera.
- Space Warping : The volumetric warping of space and the transformations of the frustum-bounds.
- View Frustum : Interactive view frustum with clipping planes and an NDC box centered on the secondary camera.
- Projection Matrix : The main section of the video deriving the transformation matrices geometrically.
In all visualizations:
- Camera controls are exactly as detailed above for the rest of the examples.
- The
spacekey cycles to the next visualization. - The
Rkey toggles on/off a slow orbiting of the main camera about its target position. - The
Tabkey toggles on/off a secondary viewport showing what the secondary camera sees, except for the last visualization where it toggles the Matrix HUD instead.
- The
3key (re)starts the transition of 'lines through the origin' emanating from the secondary camera's origin.
- The
1key transitions the frustum from view-space directly to NDC-space (box centered at the camera). - The
2key transitions the frustum from view-space to clip-space and then to NDC-space (only works in 2-step mode). - The
3toggles on/off the 2-step mode and the display of the frustum of the intermediary clip-space. - The
4toggles on/off the volumetric visualization of space-warping transformation (using a 3D grid of locators).
- The
1key transitions the frustum from view-space to NDC-space taking the clipped geometry with it. - Holding
ctrlthe mouse wheel moved the near clipping plane back and forth. - Holding
shiftthe mouse wheel moved the far clipping plane back and forth. - Holding
altthe mouse wheel zooms the camera in/out by increasing/decreasing the focal length. - Clicking anywhere within the bounds of the secondary viewport (when it's visible, toggled by
Tab)
make the secondary viewport 'active' so that all camera controls affect the secondary camera.
Clicking anywhere outside the bounds makes the primary camera active again.
- Holding
ctrlthe mouse wheel moved the near clipping plane back and forth. - Holding
shiftthe mouse wheel moved the far clipping plane back and forth. - Holding
altthe mouse wheel zooms the camera in/out by increasing/decreasing the focal length. - The X, Y/W and Z basis vectors can be manipulated (by moving their arrow-heads) thereby transforming the space.
This also correspondingly updates the current manual matrix (top-left corner of the matrix HUD, if visible).
Just click-dragging them moves them parallel to the view, but: holdingctrlconstrains the movement to only be along the Z axis
holdingshiftconstrains the movement to only be along the Y (or W) axis, and
holdingshift+ctrlconstrains the movement to only be along the X axis, and - The
Tkey shows the transition of the next transformation step and adds its matrix to the HUD.
shift+Tadds the matrix of the current 'manual' transformation instead.
ctrl+Tremoved the last-added transformation matrix. - The
Okey toggles between working with an NDC space of a full-cube (OpenGL/Vulkan) of a half-cube (Direct3D). - The
Vkey toggles the visibility of the geometry (yellow box and white grid). - The
Lkey toggles the visibility of the NDC box's vertex coordinates (labels). - The
Zkey toggles the visibility of the auxiliary plane that controls the view-frustum's shape. - The
Fkey toggles the visibility of the focal-length's ratio (labels). - The
Akey toggles the visibility of the aspect ratio's similar triangles (labels). - The
Xkey toggles the visibility of the diagonals of the perfectly-diagonal pyramid. - The
Skey toggles the visibility of the arrows showing the X and Y scaling factors (labels). - The
Gkey toggles the visibility of grids representing the XY and ZY planes. - The
1key transitions the frustum from view-space to NDC-space taking the clipped geometry with it. - The
2key slices the view of 4D space to XZW thereafter. - The
3key reveals the projective space (centered at the origin). - The
4key reveals a projective point (a line through the origin). - The
5key reveals the projective reference plane at a W height of 1. - The
4key (second time) moves a projective point (a line through the origin) along the ref. plane. - The
5key (second time) shows a projective normalization, pushing a projective point down to the ref. plane. - The
6key reveals the projective points (lines through the origin) of the NDC rectangular slice's corners. - The
7key reveals the projective trajectories possible for the corners of the view frustum's slice's corners. - The
8key reveals the wobbling quadrangle formed by the target corner-positions on the projective points. - The
9key pauses the wobbling and sliding of the target projective points along their lines through the origin. - The
0key drops the wobbled quadrangle by projectively normalizing the corners down to the ref. plane. - The
Dkey reveals vectors showing the diagonal of the lines through the origin and the NDC corners. - The
Ckey reveals the chosen trajectory for the view frustum's corners onto the NDC's projective points. - The
Bkey reveals the labels of the chosen trajectory, showing the measures of transformations needed. - The
Hkey reveals the top-view's labels for the Z-scaling (after the shear). - The
Kkey toggles the 'alternative' Z-scale when in cube-NDC mode (OpenGL). - The
Jkey toggles the Z-flip mode (OpenGL). - The
Mkey toggles the 'final' matrix in the top-left corner of the matrix HUD (instead of the custum one).






















