Well I had quite the run around with Mesh save/load involving valgrind and all sorts of wild debugging. For one, somehow I wound up with circular header includes or something, so I wound up having to forward declare some types just to get it to compile. Somehow that happened when trying to switch Mesh import/export to the
After that I found myself in another predicament where everything compiled but it segfaulted, and gave a really really wild stacktrace in gdb. That was caused by a function not having a return when it should have returned
int. Returning int fixed that issue, and all was well. Need to figure out how to make that be a compile error with g++/gcc so that I don’t have that issue. I’ve know for a while that there are some functions that didnt’ have a return statement, but none of them thus far have caused an actual issue that I’m aware of, so possibly going and running
cppcheck or making that a compile error would be helpful to fix all of those possible bugs.
To some extent the lua API is written so that it works fine if you don’t make mistakes when using it, if you do, expect wild segfaulting and nonsense.
in any case, Mesh loading works! was able to save a cube, and then load the same cube back and apply a material to it. Next up is material save/load
Then after mesh save/loading, I need/want to be able to save/load the materials that were assigned to the meshes. So now I’m trying to do the same convert from my silly
uint8arr_to_glmvec3 type stuff to the new
SerDes stuff for my import/export material methods I made eons ago. Finding similar compilation errors as before, but now that I figured out the solutions for the Mesh, then it should be similar for material to fix them.
The once Material save/load works, it should be possible for meshes to save their own materials out and then load them back. Then Next after that is Model save/load
Okay model save/load has been having me flip flop on how I want to do it, because it’s hard to figure out how I want to do it if separately at all from the Mesh save/load.
This is partly because of 2 reasons:
- Models can consist of multiple meshes, Do I represent that as each individual mesh in each their own entity or do I combine it all into one entity or what?
- What if the material loading doesn’t work for the model, or I want to set individual materials for each mesh in the model, how do I save that, along with letting me load back the model again if the source model file changes?
- what if the material loaded from the model is fine for a few instances, but what if I want to go change the material on one or all of the meshes in a later entity using the same model? I can’t change the model because I would likely want the model to be able to be shared across multiple entities/meshes.
So what is the solution? I think the solution would likely be to just take models, and load them into a bunch of meshes, each with their own assigned material. and then just save/load the meshes as part of the scene, ignoring that they came from a model at all. This means that I would simply not care about the models at all in scene save/load, but instead I would just write some sort of logic in the Lua scripts that implement the editor to track tying the models to the meshes to allow reloading meshes when the source models have changed.
This may sound a bit like just putting off the whole issue until later, but I actually see it as having a few benefits. I mean in the shipping game would I really care/need to ship the model source files themselves? why wouldn’t I just save them out to my own format to load them from, so I can load faster/with fewer steps? In the final game you’re likely never going to need to reload the mesh from a source mesh file.
Additionally, if I do need the ability to do that, I just take whatever logic I implemented in the editor for doing that, and I can copy /paste it into the game logic lua scripts. So really no feature issues here, just make the lua scripts care about it.
Additionally, loading things through assimp requires stepping it through intermediary
aiMaterial, and ton of other types that I don’t use in my engine to render crap out, so really this will skip that whole middle step, granted this does mean that right now all models/meshes are saved/loaded with Json of all things, which is likely a larger file size than even a obj, but it loads directly into the formats I need, with all of the data that I need. That means that it’s likely the best for me right now, and will have less overhead of loading things from file, then looping through all the vertices to convert it to my own data structures, instead now it will just load from file, no extra steps. Later on I can implement Binary save/load and it’ll likely be smaller file sizes, and maybe faster loading because of that, but its still better imo than having overhead of converting between data structures after loading from file.
Back onto the topic of Nuklear and UI stuffs. Still haven’t gotten to implementation yet, trying to sort out the save/load first since UI isn’t technically in the 0.0.1 release, I just want to get going on it sooner so that I can have a UI for my editor stuff, which will make editing/creating things much faster than the current console commands, which means I could get that much closer to making a game in this engine.
I think I’ve sort of figured out how I want to do UI, basically the UI needs to be rendering by calling nuklear methods for each item/element of the UI, which means that somehow I need Lua to be able to do that. I think to make it makes the most sense to create some kind of UI manager which will take some sort of data structure or structures populated by the Lua, and then will basically iterate through them to call the Nuklear commands, and then the UI would be drawn via Nuklear’s drawing methods, which means that all Lua would have to do is basically set up the structure, say what Lua method to call when there is some input on the UI widgets, and then it goes into a entity or something somewhere which gets pulled into the RenderState and then rendered from there.
I will say this process of implementing Nuklear compared to if I used my own UI system does seem a bit more convoluted, because basically the steps are:
- generate data structure for the UI/menu in lua and stick it into a component or some shit to be saved/loaded as well as pulled in to be rendered
- in the Update Thread pull the UI data into the
RenderState to be passed to the render thread
- in render thread, convert the data structure into nuklear calls. Along the way add callbacks for UI input to the stack of tasks to happen in the update thread
- then render the nuklear crap also in the rendering thread.
This means that basically the render thread now has to not just render all the rendering crap, but also call the methods to populate the nuklear UI, as well as to render the Nuklear UI. Not sure if that’s more overhead than if I used my own system or not, since I would basically be going from data -> rendered right away. However Nuklear seems still like the best option for now, because of the sheer quantity of already implemented UI widgets and input boxes, along with it all being skinnable already. It just makes sense to use Nuklear for now and eat the overhead costs if any. Maybe if I get to profiling everything later and find out that it’s taking too long on just the nuklear calls and rendering in the render thread, maybe then I’ll change it.
But it also may be worth, instead of just doing the nuklear calls in the render thread, I could likely just save a nuklear context in the RenderState, and call all the Nuklear UI widget calls in the Update thread instead, and just pass the context to the render thread to do the actual rendering, so the UI population would happen on a different thread than the rendering. Hard to say, right now without many models, Rendering goes as fast as it wants, Update thread is tick limited, although I’ve noticed differences between Linux and Windows in what speed it claims to be going, on Windows it was going half the tick speed I told it to, so then I changed it to be 60 ticks a second on windows, and now it’s basically double that on Linux. Not sure that matters so much, I don’t think it should matter anyways.
Also I’ll likely want a way to configure the UI look from Lua. there are ways you can do different skinning, and apparently you can get a modified version of Nuklear to look like this:
If that’s not like, a regular ass game menu then I don’t know what is. So if I can make something that looks like that or works like that with Nuklear, then I think we’re golden. might need to do some hacky stuff to make it work with controller but obviously its been done before.
A Rendering Conundrum
So some time after I had the mesh save/load working, I noticed that I was no longer having the lighting work on the mesh I was testing with (the usual brick textured cube you see if you scroll wayyy back.) I’m pretty sure right when I tested the mesh save/load it was working, but now it isn’t.
So I set up renderdoc and took a capture of it to try to see what is wrong, and I found this when I looked at the normal texture used to compute lighting:
For those of you unfamiliar with what normals should look like when rendered to a texture, this is not it, there are somehow is no normal data for the mesh.
And of course, a little analysis later, and I found this in my git log:
+ --Mesh.Save(mesh, "MESH_01.bin");
So I commented out the line that generates the normals of the mesh, not sure if I saved it or not, so I’m uncommenting it, and going to save out the data, and see if the lighting works then. could be the saved mesh just got saved without normals.
EDIT: I did some more investigation, the save/load was working fine, but I hadn’t yet actually added any normals to a mesh before with the add normals command, I had only had the mesh generate them procedurally. the issue proved to be within my add normals and I found one in the add colors methods on my mesh.
Basically I had used the
.data() of a
std::vector<glm::vec3> but I used it on the argument passed to the method, when I should have used the
.data() call on the vector that was saved as a member of the mesh class. Problem solved!
Next steps: wrap up testing the material save/load, then I think I’ll call it quits on model save/load for now until I get the editor commands/UI more figured out. maybe I’ll implement Lua bindings to be able to load meshes/materials from models, that will help me verify my whole Assimp loading stuff is working in this version. I tested that in a previous engine iteration years ago, so likely a good idea to test it with some actual models.
Then also, get going on the nuklear stuff, and also check up on my Quire issue tracking, and wrap up the 0.0.1 release, tag it, and bump the version. once material/mesh save/load is all tested, as far as I’m concerned that’s a wrap on 0.0.1!!!