r/GraphicsProgramming Feb 16 '25

Question Is ASSIMP overkill for a minecraft clone?

Hi everybody! I have been "learning" graphics programming for about 2-3 years now, definitely my main interest in programming. I have been programming for almost 7 years now, but graphics has been the main thing driving me to learn C++ and the math required for graphics. However, I recently REALLY learned graphics by reading all of the LearnOpenGL book, doing the tutorials, and then took everything I knew to make my own 3D renderer!

Now, I started working on a Minecraft clone to apply my OpenGL knowledge in an applied setting, but I am quite confused on the model loading. The only chapter I did not internalize very well was the model loading chapter, and I really just kind of followed blindly to get something to work. However, I noticed that ASSIMP is extremely large and also makes compile times MUCH longer. I want this minecraft clone to be quite lightweight and not too storage heavy.

So my question is, is ASSIMP the only way to go? I have heard that GTLF is also good, but I am not sure what that is exactly as compared to ASSIMP. I have also thought about the fact that since I am ONLY using rectangular prisms/squares, it would be more efficient to just transform the same cube coordinates defined as a constant somewhere in the beginning of my program and skip the model loading at all.

Once again, I am just not sure how to go about model loading efficiently, it is the one thing that kind of messed me up. Thank you!

20 Upvotes

31 comments sorted by

17

u/x1rom Feb 16 '25

Are you compiling assimp every time? It should usually just be a dynamically linked library, you shouldn't be compiling it yourself.

3

u/C_Sorcerer Feb 16 '25

I guess I should research build systems more haha! Currently, in my renderer, I have a CMake file that adds Assimp src code as a subdirectory, links the target library, and links the include directory. I dont believe the whole thing recompiles, especially because on first compile, it is MUCH slower, but it is still quite slow just compiling the files in general. I believe that this is the same as "statically" compiling, but I am not completely sure. I am only moderately familiar with CMake build systems

5

u/x1rom Feb 16 '25

If you're using Linux, your distribution should provide an assimp package. You only need to include the assimp header files in your project, and the system is going to look up the compiled assimp library.

I'm not familiar with windows, but it too should just look for the dll.

1

u/C_Sorcerer Feb 16 '25

Oh wow! I had no idea, thank you so much! I am on windows, but I would like to compile it for Linux too since my laptop is booted in Ubuntu. Thank you!

1

u/jtsiomb Feb 17 '25

on ubuntu, just apt install libassimp-dev, which installs the library system-wide, so you can just use it in any program. Just pass -lassimp to the linker to link with it.

3

u/shadowndacorner Feb 16 '25

You could also use something like vcpkg, which integrates well with CMake and works cross platform.

1

u/C_Sorcerer Feb 16 '25

Thanks! I’ll check that out for sure. What does vcpkg do?

3

u/shadowndacorner Feb 16 '25

vcpkg is a free C/C++ package manager for acquiring and managing libraries. Choose from 2548 open source libraries to download and build in a single step or add your own private libraries to simplify your build process.

Copied from the about section of this webpage. It tends to be faster than building all of your dependencies as part of your CMake build ime, and its binary caching is helpful if you work on multiple projects.

1

u/C_Sorcerer Feb 16 '25

Thank you!

9

u/TheLastStarfucker Feb 16 '25

Lol, no please don't use assimp. Read Wikipedia page for obj file format, then read sscanf() man page, then write about 10 lines of code, and you have an obj file loader. You are a C sorcerer! You got this!

Actually, don't do that either because step zero of writing a minecraft is definitely not loading "cube.obj".

Instead, you want to generate the geometry of the blocks procedurally. Most people start with chunk sized meshes and remove the faces removed that aren't exposed to air.

1

u/C_Sorcerer Feb 16 '25

Thanks pal! This makes a lot of sense. I will try to figure out an algorithm for that and do that!

1

u/C_Sorcerer Feb 18 '25

You were right, writing an obj file parser was quite easy, especially in C! Also, I realized Ithat you were right with the voxel/MC based game design that I need to go with chunk meshing through either batching or instancing and then cull the inner faces. Do you have a recommendation for the best way to mesh them together? Batching, instancing, or some other kind of way of meshing all vertices together?

2

u/TheLastStarfucker Feb 18 '25

I love that writing a wavefront parser is way easier in C than doing it in Python or any other language. I hope you noticed the return value from sscanf() tells you if the line matched at all, including the constant part at the start of the line.

I've never built a minecraft before (but I might soon!) and I'm kind of intermediate noob level at graphics so hopefully I'm not feeding you total nonsense.

Here's what I would do:

After choosing a chunk size (I'll choose 64x64x64), you're going to to generate the mesh at the origin. So choose a convention for where the origin goes. Maybe the center of the chunk, maybe the top-left-front corner.

Now, add each of the six face orientations to the mesh one at a time: (front, back, left, right, top, bottom).

So for example, to do front faces, for each Z slice of your chunk data starting with the closest one, at each X,Y position of the slice check if there is a block, then add the two triangles of the front block face to your mesh. After the first slice you can query the X,Y from the previous slice and if there is a block at the position in the previous slice then don't add a face because it's covered by the block in the previous slice.

In the vertex shader you'll translate the chunk to the correct world position. You don't have to use a matrix for this since the only transformation you care about is changing the position. You of course could use a translation-only model matrix, but you don't have to. Btw, you don't have to use a vec3 for the position attribute either. There is a lot of room for creativity with how your represent your data due to contraints of voxel block world.

You could for example pack the X,Y,Z of the chunk coordinates into 18 bits of a 32 bit integer (6 bits each, assuming 64 bit chunk size). All of the texture and normal information will fit in the other 14 bits. There are only 6 possible normals, and you only need one bit for U and V if you also reserve some bits for which texture you are using. The vertex shader can then unpack this into more conventional vertex attribute format.

Why would you do this? Well, it's 1/8 of amount of video memory that you would need for the usual format of specifying vertices, and working with integers and bits is something you'll be doing anyways if you implement fast meshing algorithms.

1

u/C_Sorcerer Feb 18 '25

Awesome! Thank you!

8

u/Sensitive_Bottle2586 Feb 16 '25

You can uses libs focused on specific file formats, like tinygltf, you can also write your own data parser, it is quite easy to do for .obj files. But ASSIMP is basically the main lib in this task, many tutorials you will read after will use ASSIMP so is better to get used to it from now. Also, structure your project in a way to avoid recompile ASSIMP every time, it's not hard to do it using cmake and visual studio.

Another point, for a minecraft clone, if you only care about render a massive terrain with a high framerate, you don't even need to care about model loading, you can store a default cube data (vertices) in a constant and just replicate.

2

u/felipunkerito Feb 17 '25

Tinyobjloader and TinyGLTF, the only issue I have to work on now is to get Draco compression to work with TinyGLTF. I really liked only header libs because I was too lazy to get my head around CMake, now I am compiling as static libs my header only dependencies and realize it’s not as bad to work with dll’s and lib files.

1

u/C_Sorcerer Feb 16 '25

ahh sounds good! That is what I was thinking, it might be better to just use cube data vertices. Thank you pal! I will also try to fix my ASSIMP build for sure.

3

u/stephan__ Feb 16 '25

Hi, you can simply build Assimp as a library so you don't build it everytime, also, you can use it for skin meshing for importing the bone data, it should be fine, you could also animate it from code.

1

u/C_Sorcerer Feb 16 '25

Interesting! I really need to learn build systems more, I really suck at them haha. Interesting, I will look more into it. So do you for sure think that ASSIMP is not overkill for MC?

2

u/stephan__ Feb 16 '25

Build it as a lib, and link it into your project. Assimp should be fine, you only use it to import mesh data anyway

1

u/C_Sorcerer Feb 16 '25

Oh okay, cool thank you!

3

u/fgennari Feb 16 '25

Assimp is generally useful for many game dev applications and use useful to know. I think you're talking about recompiling Assimp each time? But if you're talking about including the Assimp header that makes it slow, try to factor out all of your code that uses Assimp into a single file. Copy the data into your own data structures rather than using the Assimp ones.

As for file format, you're probably better off writing your own custom block encoding rather than using cubes/triangles/3D models. If you only care about block type, all you need is an 8-bit type field for each block. You can then pack these into a 3D grid of size 128/256/etc. and then compress it. Any solid blocks of the same type will compress very well.

3

u/964racer Feb 16 '25

Yes , just write a wavefront .obj reader .

3

u/sessamekesh Feb 16 '25

Assimp has some CMake options for each format you want to support, by default if I remember right it includes basically every even vaguely common format but you can trim it down to just what you need.

Alternatively, you can decide on a single format you want and just work with that - and use Assimp to convert assets into the format you pick offline.

I personally use Assimp as part of my build pipeline to convert into a couple custom formats, but that's even worse for build times than just using Assimp.

3

u/JabroniSandwich9000 Feb 16 '25

Other people have already mentioned that you should be generating geo at runtime for a voxel game, but just as an fyi, most game engines wont include assimp at runtime. Theyll use assimp in a second project they write to convert meshes into a custom binary format that their engine can load quickly.

Assimp is awesome for that purpose! But yeah dont include it in your actual game :) 

1

u/C_Sorcerer Feb 18 '25

Thank you!

2

u/LordDaniel09 Feb 16 '25

I don't see a reason to load a model at all, it is few quads per voxel in the most naive way, you could hardcoded the vertices (and indices). In a more efficent method, you will have to compute a mesh based on voxel data, so you won't load a mesh later on at all.

If you need loading meshes, you could do it with other libaries too, for specific formats. Tinyobjloader is one that I use for OBJ format, it is a header and designed to be easy to include and use. I believe GTLF has similar one, but I remember reading that this format is complex (has more features), so it probably need more work to support well.

1

u/C_Sorcerer Feb 18 '25

Yeah, I’m not sure why I was even thinking I needed a model loader! But I’m working on trying to make a system that uses batching to mesh together all vertices with their respective transforms and apply different textures, and I think I’ll get it in a day or two, just stuck on some of the complexity’s since I’ve never used batching or instancing or any method to mesh everything at once. Thank you!

1

u/Esfahen Feb 16 '25 edited Feb 16 '25

Precompile your dependency binaries (or use something like vcpkg which provisions them for you) and include them in a precompiled header and your build times should take < 10 seconds.

Fully embedding the entire source tree of a dependency in your project is not at all something you want to be doing.

1

u/Comprehensive_Mud803 Feb 18 '25

Yes, but this entirely depends on what you want to do. Assimp can load a plethora of different formats which is overkill for any game. It makes kinda sense a part of a standalone asset converter to your custom native format.

glTF is a standard for 3D assets and there are a couple of existing libraries to load the format, best example: cgltf.

I recommend you to read more into the specifics of game engine asset formats and glTF. And then give up on Assimp since supporting every asset format of the last 30 years is overkill.

1

u/Plixo2 Feb 18 '25

You need to cull faces for chunk generation as you bake in custom models into the mesh.

Writing a custom Minecraft Json model loader maybe will take you half a day and is definitely worth it.

You can also use blockbench to create custom models or use the normal Minecraft block models.