Tile is a hobbyist 3D engine written in C mimicking the Blitz3D and Nuclear Fusion APIs, with some twists, for OpenGL. This is just a "for fun" project.
License: ZLib. (i.e., "basically public domain.")
This project gets updated at random.
You will want msys2 on Windows. Please choose the 64-bit version.
Build "Mk" first.
cc mk.c -o mkAfter that, just run Mk.
./mkThe output of the engine test will be bin/mswin-x64/engine-test-dbg.exe on
Windows, or bin/linux-x64/engine-test-dbg on Linux. Aside from macOS, no other
platform has been tested at this time. (Though I would like to make sure
everything works on FreeBSD, (maybe NetBSD, Dragonfly, etc), and Haiku,
eventually...)
Input:
#include <tile.h>
/* ... snip ... */
int main() {
double newTime, oldTime, deltaTime;
/* initialization */
tlInit();
/* version control info */
#if BUILDGEN_GITINFO_AVAILABLE
printf( "git-info:\n" );
printf( "\tbranch: %s\n", BUILDGEN_GITINFO_BRANCH );
printf( "\tcommit: %s\n", BUILDGEN_GITINFO_COMMIT );
printf( "\ttstamp: %s\n", BUILDGEN_GITINFO_TSTAMP );
printf( "\n" );
#endif
tlSetCameraAutoAspect(1280.0/720.0, kTlAspect_Fit);
g_shape = tlNewFigureEightTorus(tlFirstBrush(), 1.0f, 36);
g_cube = tlNewCube(tlFirstBrush(), 1.0f);
tlSetEntityPosition(g_cube, 0.5f,0.0f,5.0f);
g_child = tlNewCube(tlFirstBrush(), 0.25f);
tlSetEntityPosition(g_child, 0.7f,0.7f,0.7f);
tlSetEntityParent(g_child, g_cube);
g_plane = tlNewPlane(tlFirstBrush(), 10.0f, 10.0f);
tlSetEntityPosition(g_plane, 0.0f,-3.5f,10.0f);
tlTurnEntityX(g_plane, 90.0f);
tlSetEntityParentGlobal(g_cube, g_plane);
/* main loop */
do {
/* update */
if( !update( tlGetDeltaTime() ) ) {
break;
}
} while( tlLoop() );
/* done */
return EXIT_SUCCESS;
}Output:
See the header files in pkg/tile/include/tile/ for documentation. (Not that there's much noted, and a lot of the APIs do what they say on the tin.)
The organization of the engine is roughly as follows:
- The engine is the glue that ties all the components together.
- It initializes a screen, which is the main window into the world. In rather, likely, the only window into the world.
- Additionally, the engine initializes the rendering API. This is the low-level "abstract" renderer, that looks suspiciously exactly like OpenGL.
- You create entities (oh wow, actual documentation in that file) which are the base objects of your 3D world. They are comprised of various components.
- Your window to the world is explored with a camera, which is just an entity with a view component attached.
- Visible entities are made up of surfaces, which are visually affected by brushes and lights.
- You can control your world via keyboard and mouse through the event system.
That's about it for now. Some stuff in the pipeline is getting restructured, and other things are just generally incomplete.
In case it matters to you, the entity rotation order is ZXY. This is the same
rotation order used by Nuclear Fusion (and IIRC, Unity). Optimized maths
available in a super secret file you'll never find if you're certain it's not in
a file labelled "math" with some relevant file extension like ".c." Though,
in hindsight, the compiler would probably optimize away all those multiplies by
0 and 1, so I probably didn't have to bother doing that by hand. Oh well, it's
easier to look at and reason about this way. (For me, anyhow.)
Again, this is just a project that I'm hacking together for fun. I document capriciously.
Random trivia: This was originally a single file project of about 3000 lines.
I was originally going to do a 2D tilemapping test. I got distracted. (The test did get completed outside of this project though.)
Anyway, since this was originally going to be for a tilemapping test, the name "tile" was selected. Despite it spiralling into something else entirely, I stuck with the name.
CMake is smelly and gross.
jk.
I wrote Mk because at the time (2012~) CMake was really very unpleasant to use, and I wanted a mostly configure-less build system that worked on the platforms I cared about. If anybody's interested in writing a CMakeLists.txt for this then feel free to. If it's reasonably slim, and does everything Mk does, then I'd be happy to include it.
You probably shouldn't. This is just a personal project, for fun. It is not production code, nor is it well tested.
This project may be useful to you if the style of code and license matches what you're after, and it does exactly what you want. Or perhaps it may be useful as inspiration to write something better. No matter the case, it should be something that you've recognized as being, in some way, useful to you.
In my case, it's a useful testbed for random API designs and for fun distractions or tinkering. Maybe it can be that for you as well, or maybe not.
It just sort of turned out that way. I was using C almost exclusively at the time. I do feel that C++ is a way more realistic choice, and using it would certainly cut down on the amount of time and effort it takes to get anything done. Way safer in general, too.
I have considered porting it to Rust and Swift. That would take a lot of time, especially for a Rust port, so I would rather not for now. Maybe some day...
Oops. Probably an oversight on my end. File an issue and I'll look into it.
