Stone Devlog: Objectively

 Buckle up, this post is going to a wordy one. Now that the knapping system is in a state that can be considered existent, I started pondering my next steps. Turns out there are a lot of possibilities, so I wanted to take some time to lay some of them out in a bit of a todo list. Let's get into it.


1. Data Traversal

First up, we have a pivotal component in making the system more robust: actually being able to interpret the data that comprises the stone. Currently, the most I'm doing is getting the position of mouse clicks on the surface of the stone and converting that to the local space of the underlying data structure. From there, I just create a plane and perform an indiscriminate split. I've toyed around with subtraction using other shapes, but the results aren't particularly promising.

Knapping with Sphere and Ellipsoid subtractions

What we need is a way to analyze the volume data to determine how to subtract from it. The dataset consists of undirected shortest distances to the nearest surface, so it will be a little tricky to work with, but it's doable. A simple example would be following the distance as it increases to get to the center of mass. Ultimately, it is a grid of increasing and decreasing values, so it should be possible to traverse with any sort of depth-first search.

Traversing the data is only the first step, however. We could flood fill and identify the grid spaces the lie within the volume, but so what? That's when we have to start putting on our designer hats. Right now I'm thinking I will drive a straight line into the volume based on some 'striking force' and then follow the shortest distance out of the shape. From there it'll determine what to do next. I'll have an entry point and an exit point that I can connect to figure out how much of the stone to flake off. If the exit path doubles back on the entry path, that part of the stone may be too dense to break. Alternatively, if the striking force plows straight through the stone, maybe it just shatters. This will hopefully give us a decent starting point to begin nailing down the look and feel of the system. There is a lot of nuance to real-life flint knapping that I would like to integrate into the system in some capacity, but first I need to achieve a proper controllable system.


2. Texturing

Next up, we have one of my greatest enemies: aesthetics. Currently, I'm applying the same basic colored material to every mesh generated by my contouring algorithm. It would be really cool if I could start with a rough outer texture that breaks away to reveal a smoother inner texture. That might be a bit ambitious considering at the moment I can't even put a texture on the mesh at all.

To knock this one off the todo list is going to take a few stages of research. Texturing, shaders, splatting, tri-planar mapping, and figuring out how to apply it all to a procedural mesh rather than the heightmap terrain everyone else uses voxels for. This one isn't as immediately impactful, but it's going to be crucial sooner or later.


3. Alternate/Improved Contouring Methods

Remember when I decided to just run with what I had working so I could actually start on the knapping system? If I need to stall for bit, I can dig back into contouring algorithms for another round of abuse. There are still some extra bells and whistles to look into such as adaptive resolution using octrees or figuring out that QEF stuff. I also have some dumb ideas to try and bend a contouring algorithm to my particular use case. Not the highest priority, but eventually I will need to be able to produce better geometry.


4. Performance Improvements

It's almost unheard of that I get to a point in my projects where I even have to consider optimization. It's especially strange considering I barely have something playable. This project sure is wacky. 

Currently, I'm using a discrete grid of values initialized by sampling a signed distance function. To sample a point that lies between these discrete sample points, I use trilinear interpolation. Surprisingly, it actually works pretty well. When the sample resolution and discrete grid resolution match, it is fairly quick, thanks to an early return that bypasses the trilinear interpolation. At a sample resolution of 4, regenerating the mesh after each modification in the showcase I shared last time took about 0.3 seconds. That's still a ways off from running in real time, but reasonable to cover up with an animation and visual effects. If I take out that early return though, the time jumps to about 0.75 seconds. Yikes.

There's a few things we can do to improve things. For starters, I wrote the trilinear interpolation implementation myself, so there's bound to be some improvements to be made there. Though, to be fair, we are comparing the speed of multiple calculations to the speed of a table look up, multiplied out almost 900 thousand times. It might be worth looking into reducing the number of calls there...

Many improvements will ultimately be dependent on our contouring algorithm. There's no sense in massively overhauling our Dual Contouring implementation if we're just going to replace it with another implementation down the line. If we start looking into new contouring algorithms, we can also look into multi-threading or offloading a lot of these operations to the GPU. Two birds with one stone, and I'm sure that wouldn't be painful at all to look into it.


5. Volumetric Stone Generation

Short and sweet here, I need a new stone generation that works with my volumetric data representation. While generating decent stones is somewhat dependent on being able to produce better geometry, the stone generation plus texturing is going to a major deciding factor in the visual style of the game as a whole. With that in mind, I probably shouldn't rush into trying to make the "final" stone generation, but I'd like to have something more interesting than an ellipsoid as I try to figure out the look and feel of the knapping system.


6. Volumetric Voronoi Cells

Just like the stone generation, here's another straightforward todo item. I'm essentially retreading the same ground I did when I initially started this endeavor. I'm not entirely sure if I will still try using Voronoi cells for the knapping system, but mesh shattering was too much fun not to have as an option. Plus, Voronoi shattering was my first big win with the boundary representation, so let's bring it to my volumetric representation too.


7. Serialization

Eventually I'm going need to be able to save and load the objects I make with this system. Checking off this item sooner rather than later may end up being beneficial in the development process. I'd be able to save an object and load it in to use over an over again to test knapping techniques or try out different contouring algorithms. As an added bonus, I already have some idea of how to accomplish this one, so it's not a bad idea to get a jump start on it.


8. Geometric Evaluation

Bear with my here, what if instead of fiddling with the knapping system, we just move on to a different part of the game. After a stone is knapped, the next step would be to dust off my DCEL data structure and try to identify the edges and pointy bits. Obviously, the less-than-ideal geometry produced by our contouring algorithm is problematic for this, but I think I could manage. This one should probably at least wait for serialization, though.



That's about all for now. This post ended up excruciatingly long and ramble-y. At least now I have my thoughts written down and can refer back to this post when I inevitably lose track of where I'm at. Next time I think we will talk about how I intend to knock some of these items off the list. Stay tuned.