Various bits of progress on the 'Hull Breach' project. Follow us on Bluesky as well! Mini-versions of the updates go there as well as possibly some extra, small things. https://bsky.app/profile/hullbreach.bsky.social
Don't wanna be here? Send us removal request.
Text
Update 2 - Destruction Progress
(AKA Slice & Dice Update)
Hey! For those of you who checked out the last post, you'll remember that I mentioned I would be working on implementing a system for some dynamic destruction. Well, I've been medium-hard at work (didn't quite get to work as much as desired since the last post) and I've gotten the plane-slicing mechanism working as expected! For the sake of the demonstration, the 'bottom' half of the cut ('up' is relative to the left side of the cut) is removed, but the principle is the same with either direction.
Here's some gifs showing either direction of the cut:
Slice
and Dice
I'm quite happy with the results! There's quite a few bugs in how I've set up the implementation of this right now, and the code itself is a bit of an undocumented wasteland, however it's given me confidence that my approach should work reasonably well! You might also be able to tell but the cut surface does in fact support different materials! I need to do some more investigation on a few quirks related to that, but that should be really useful for anyone who wants not quite the 'smooth' looking cuts that I will be using-- you can just make use of a cut texture with some more normal map and emission goodness. I can't give any estimate whatsoever on when I'll have a nice, clean version of this that I can actually make available as an open-source library, but it is exciting to see things come together after the polygons have haunted my dreams. Note: This is not a joke-- I have literally run through meshes while trying to sleep.
To touch back on the previous post, there were actually a few tweaks to the original strategy and I can go into a bit more technical detail for those of you strange enough to enjoy this stuff too!
So, in the original strategy, I had a 4 step plan that kind of broke it down. Those steps were quite simplified, and I didn't go into a ton of detail on them, but I can basically break down Step 2/3 in a bit more detail.
As a refresher, those steps are, functionally, creating a plane along our desired cut path. To give a representation of this, here's the following gif:
The technique effectively involves creating a plane that slices across the mesh in the direction of the cut. This plane only exists in the code, but it is useful because it allows us to check the above/below status using the dot products. I'm not remotely equipped to talk about vector stuff as despite learning it in school, it has more-or-less slipped from my sieve-like brain. Basically, if we get a positive number, we know it lies above the plane, and a negative means below. Zero indicates that it lies directly on the plane.
From there, we get the triangles that make up the mesh. For people not familiar with how computer graphics are generated, here is my caveman-understanding of it; basically every 3D object is just made up of a bunch of triangles and some graphical witchcraft. This means that while something like a cube might seem like it just has 8 points, to the computer it actually has 24-- 4 for each face, constructing 2 triangles. The same can more or less be applied to any shape-- the more triangles you give it the more detailed shapes you can make. This also means more stuff for your GPU (which handles most of these triangles) to deal with. Because of this, we want to make sure we don't generate a bunch of extra points to handle.
So, we have the triangles-- awesome! Now we mark the ones above and below the plane (green and red respectively). We then mark the triangles that are broken-- meaning they are being cut by the plane. These are shown in orange. We then run through and find the intersection points of these segments. We can then hang onto these points, as well as the points that make up that segment. Provided we store it, we can then basically shift the opposite side point to that intersection point. This means that the mesh created above the plane effectively has the endpoint pushed up to the plane, and the mesh below has the endpoint pushed down. Importantly, we also make sure to ignore the 'middle lines,' as we really only care about the outer points-- almost as though there are no triangles there.
We then reconstruct triangles for all of those newly shifted faces to ensure we aren't making extras. We can then make note of all of the points that were modified and build out the cut face. We can then build that with a new material if desired, and then replace the original mesh with the upper mesh, and then spawn the lower mesh at the same position. We now have 2 meshes that effectively represent a mesh cut in half! You'll probably notice that this basically increases our triangle count by 2 * Nf, where Nf is the number of faces sliced through by the plane. More importantly, however, is that this is able to be run in real-time! In these simple test environments, even very quick repeated slices have no noticeable impact on performance. This gives me confidence that the more advanced cutting, which will functionally just be using this and some less-complicated formulas to make more detailed breaks and cuts, will not have any major performance concerns.
It is worth noting that I have a pretty-good PC-- not top-of-the-line, but solid enough beast, so of course more testing would be required to get a good idea of general performance.
------------------------------------------------------------------------------
So what's next? Well, that will be a lovely rewrite of the code as it is an absolute mess, as well as trying to implement some of the more advanced destruction. So far, I haven't actually mentioned what this destruction will be, but the idea is to make use of some Voronoi cells. Even if you aren't sure what that means by the name alone, you've definitely seen examples of this before. Some good examples are something like a dragonfly's wings or the area around the veins of leaves. Effectively, you plop some points down and grow a circle around them. When those circles touch each other, they share the edge, causing them to develop a big web of nice, convex polygons. Depending on the arrangement you use, you can get some really interesting shapes with this. In fact, if you've seen Unreal Engine's destruction, you've probably seen this in action. They use pre-compiled destruction meshes for the Chaos Destruction system, and they make use of Voronoi noise to generate the shapes of the broken up polygons.
I'll get into some more detailed bits of this with the next post-- I have no idea how long that will take, but hopefully I'll be able to show off some much fancier stuff next time! Thanks for reading!
1 note
·
View note
Text
First Update!
Hello! I'm Duncan, and this is where I'm going to be posting updates for my personal, hopefully-to-be-completed-one-day game project!
The quick sales pitch: Heat Signature with a dash of Hardspace: Shipbreaker.
The less-quick sales pitch: A game where you play a highly disposable (and incredibly indebted) fixer who solves a big problem that a lot of individuals and companies have in the time of FTL travel; sometimes you would very much like something, but unfortunately it is on someone else's ship. In fact, it is often not just on someone else's ship, but in fact behind large amounts of personnel who may hold some strong objections to removing it from their ship. Or, they may in fact be the asset that needs retrieving and may not be particularly interested in coming quietly. Your goal? Completing the objectives set forth in your contract, employing whichever methods suit your particular tastes as well as the contract's stipulations-- some might want you to use a more delicate touch, while others want to send a message. Do what you can to earn as much as you can and maybe even pay off your debt-- or just try and enjoy the relative impunity you operate under.
Things are very much in the planning and testing phase right now. So, without further ado, let's get into one of the big things being worked on right now: Destruction.
------------------------CLANG - what was that?!-------------------------
The game is being developed in Godot 4, which is a fantastic engine for people who are a bit less experienced in the development space. It does have a few major downsides though, and one of the huge ones is a lack of assets and libraries. This makes it a little bit harder to get things moving and also means that there is the need to kind of develop quite a few things completely from scratch.
One thing that people who have messed with things like Godot and Unity in the past would probably understand is that you really want your collision objects to be convex. Basically, nice and solid, no holes or dips. You can stick a line in anywhere and it will only ever exit in one spot. In fact, you cannot even have rigidbodies with concave collisions in Godot. This is because it's really hard to calculate concave collisions, and really expensive on a computational level. This translates to: please have mercy on my framerate.
This generally isn't a huge problem, and there's plenty of ways to get around this, like just using static bodies, manipulating collision masks (which I actually will be using for a few neat things!), or you make sure that your concave objects, like a tunnel, or a doorway, are composed of convex polygons. A square room, for example, isn't just one big cube typically, it's six squares representing each face, 6 distinct collision objects.
It might be useful, then, to have some ways to break a concave shape into convex ones. And you'd be right! In fact, you'd be so right, that you'd assume it was a problem we've completely solved. And you would not be correct unfortunately! It's a topic that has a truly gargantuan amount of research poured into it. Google "Convex Decomposition" if you want to learn more about the subject-- it is genuinely very interesting-- there are people far more qualified than me to talk about it.
I have some plans in mind to solve the problem in a way that is performant for my needs, and I will also be (hopefully, providing it doesn't end up being utterly impractical) releasing these tools on their own within Godot so that other people can use them for free as well!
Actually writing out the code for it is... interesting, to say the least, as I am not gifted in the ways of geometry, and did not know too much about mesh generation until recently. However, I am currently working at implementing a very quick-and-dirty 'hole cutting' method right now.
Here is a gif that shows off the basic process for how it works:
Here's an explanation of how the general process will work:
Figure out your hole shape-- in this case, it's a square hole made by the rod punching through the prism. Get the points along the corners as well as your direction. In this case, we've got the 4 points on the face closest to the camera and pointed towards the left face.
Make a plane that is flush with the first 2 points and in the direction of the cut. Everything to one side gets snipped off of the first mesh and moved into another one (we don't actually separate them, but it is separated for easier visualization). Additionally, make a note of the first point in the hole and its intersection point-- in this case, bottom left point of the hole and about 3/4 of the way along the bottom of the prism.
Now-- repeat this step until you get to the last point of the hole; create a plane flush with the side, snip off everything on one side, and move to the next side. Connect everything up. Additionally, if this is the last repeat of this step, make a note of if you have intersected the two points from step 2. If so, you can drop the intersection point from step 2.
For the last points, just connect the previous point, the first point, and the intersection point from the previous point and the first intersection if it wasn't dropped.
After you've gotten all those pieces, you can just replace the original mesh with the 4 new ones. Tada! You have what looks like a hole through a mesh, but in reality it's 4 segments. If you're so inclined, you can also make the surface of the cut its own material-- maybe you want the 'inside' of a wall to look different.
Now, this solution isn't perfect. It cannot be multi-threaded in this fashion, since the sequential cuts depend on the prior cut to happen. I have a few other methods that could actually be done simultaneously, but this one is pretty easy to visualize and for the purposes of the game it should be completely functional. The astute among you may also realize that this will not work for concave holes without a few changes-- this is actually not the hardest fix, but it won't be relevant for the purposes of this type of destruction. It might be included in the library, though!
My next goal is to actually get this method implemented in Godot so that I can show it in action! This will also get me a bit more comfortable with mesh manipulation.
After that, we will be able to get to some really exciting stuff as well with some more... dynamic destruction. Cutting holes is all fine and dandy, but what about smashing them? Hopefully you'll see some more on that in the future!
4 notes
·
View notes