Skip to content

HardCoreCodin/SlimEngine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SlimEngine_logo

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

Architecture:

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.

Usage:

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

Features:

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)

MSAA


Well documented example applications cover the features:

  • 3D Viewports:
    1_viewport_HUD
    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.

    1_viewport_updateAndRender_code 1_viewport_initialization_code 1_viewport_HUD_update_code 1_viewport_setup_code

  • Viewport: Navigation
    1_scene
    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.

    2_navigation_setup_code 2_navigation_mouse_code

  • Cameras: Viewport binding
    1_scene
    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

    3_cameras_update_code 3_cameras_setup_code

  • Shapes: Setup and drawing parametric primitives (Grid, Box, Curves, etc.)
    1_scene
    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.

    4_scene_initialization_and_viewport_drawing_code 4_scene_viewport_drawing_code

  • Scene: Object selection and manipulation (Translation, Rotation and Scale)
    5_manipulation
    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.

    4_manipulation_update_code 4_manipulation_scene_setup_code

  • Scene: Mesh loading from file, instancing and wire-frame drawing
    6_mesh_with_normals
    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.
    6_mesh_instancing
    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.

    6_mesh_drawing_code 6_mesh_setup_code

  • Scene: Saving to and loading from .scene files
    7_scene
    Scenes can be saved to a file and later loaded back in-place.

    7_scene_io_code 7_scene_message_code

  • obj2mesh: Also privided is a separate CLI tool for converting .obj files to .mesh files.
    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)

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:

  1. FPS navigation (WASD + mouse look + zooming)
  2. 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)

Perspective Projection Visualization :

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 space key cycles to the next visualization.
  • The R key toggles on/off a slow orbiting of the main camera about its target position.
  • The Tab key toggles on/off a secondary viewport showing what the secondary camera sees, except for the last visualization where it toggles the Matrix HUD instead.

Intro:

intro

Projective Space:

projective_space

  • The 3 key (re)starts the transition of 'lines through the origin' emanating from the secondary camera's origin.

Space Warping:

space_warping

  • The 1 key transitions the frustum from view-space directly to NDC-space (box centered at the camera).
  • The 2 key transitions the frustum from view-space to clip-space and then to NDC-space (only works in 2-step mode).
  • The 3 toggles on/off the 2-step mode and the display of the frustum of the intermediary clip-space.
  • The 4 toggles on/off the volumetric visualization of space-warping transformation (using a 3D grid of locators).

View Frustum:

view_frustum

  • The 1 key transitions the frustum from view-space to NDC-space taking the clipped geometry with it.
  • Holding ctrl the mouse wheel moved the near clipping plane back and forth.
  • Holding shift the mouse wheel moved the far clipping plane back and forth.
  • Holding alt the 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.

Projection Matrix:

projection_matrix

  • Holding ctrl the mouse wheel moved the near clipping plane back and forth.
  • Holding shift the mouse wheel moved the far clipping plane back and forth.
  • Holding alt the 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: holding ctrl constrains the movement to only be along the Z axis
    holding shift constrains the movement to only be along the Y (or W) axis, and
    holding shift+ctrl constrains the movement to only be along the X axis, and
  • The T key shows the transition of the next transformation step and adds its matrix to the HUD.
    shift+T adds the matrix of the current 'manual' transformation instead.
    ctrl+T removed the last-added transformation matrix.
  • The O key toggles between working with an NDC space of a full-cube (OpenGL/Vulkan) of a half-cube (Direct3D).
  • The V key toggles the visibility of the geometry (yellow box and white grid).
  • The L key toggles the visibility of the NDC box's vertex coordinates (labels).
  • The Z key toggles the visibility of the auxiliary plane that controls the view-frustum's shape.
  • The F key toggles the visibility of the focal-length's ratio (labels).
  • The A key toggles the visibility of the aspect ratio's similar triangles (labels).
  • The X key toggles the visibility of the diagonals of the perfectly-diagonal pyramid.
  • The S key toggles the visibility of the arrows showing the X and Y scaling factors (labels).
  • The G key toggles the visibility of grids representing the XY and ZY planes.
  • The 1 key transitions the frustum from view-space to NDC-space taking the clipped geometry with it.
  • The 2 key slices the view of 4D space to XZW thereafter.
  • The 3 key reveals the projective space (centered at the origin).
  • The 4 key reveals a projective point (a line through the origin).
  • The 5 key reveals the projective reference plane at a W height of 1.
  • The 4 key (second time) moves a projective point (a line through the origin) along the ref. plane.
  • The 5 key (second time) shows a projective normalization, pushing a projective point down to the ref. plane.
  • The 6 key reveals the projective points (lines through the origin) of the NDC rectangular slice's corners.
  • The 7 key reveals the projective trajectories possible for the corners of the view frustum's slice's corners.
  • The 8 key reveals the wobbling quadrangle formed by the target corner-positions on the projective points.
  • The 9 key pauses the wobbling and sliding of the target projective points along their lines through the origin.
  • The 0 key drops the wobbled quadrangle by projectively normalizing the corners down to the ref. plane.
  • The D key reveals vectors showing the diagonal of the lines through the origin and the NDC corners.
  • The C key reveals the chosen trajectory for the view frustum's corners onto the NDC's projective points.
  • The B key reveals the labels of the chosen trajectory, showing the measures of transformations needed.
  • The H key reveals the top-view's labels for the Z-scaling (after the shear).
  • The K key toggles the 'alternative' Z-scale when in cube-NDC mode (OpenGL).
  • The J key toggles the Z-flip mode (OpenGL).
  • The M key toggles the 'final' matrix in the top-left corner of the matrix HUD (instead of the custum one).

About

A minimalist library with basic facilities for developing interactive real-time 3D applications, with a strong emphasis on simplicity and ease of use.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published