Skip to content
W2.Wizard edited this page Oct 17, 2022 · 39 revisions

Welcome to the MLX42 wiki!

Why was MLX42 developed?

MLX42 is the proposed successor to the MiniLibX library which was written and by Olivier Crouzet, almost 20 years ago back in Epitech.

Most students agree that the library is written in a, well, subpar state and isn't the most optimal in terms of usability and documentation.

While it is "stable" and does compile there are many pitfalls with the library including the lack of good documentation, weird function prototypes and/or slow performance, e.g: putpixel. Additionally it is pretty much no longer truly being maintained nor is it open-source with the exception of the Linux version. Which I consider to not be the solution as its not using the native UI Framework and is just a different iteration of MiniLibX same goes for the Swift version. They aren't the solution to the problem, just different flavors of the same thing.

Most of my 42 peers simply stated that "it is what it is" once I discovered this library. However, personally, I refused to let this cycle continue. So I made it my goal that during one of many Lockdowns to start exploring OpenGL in order to finally fix the mistakes. I wrote it in OpenGL because using Vulkan is a bit overkill as well as being a lot more complex and not as approachable to students.

In my eyes, the 42 Network deserves high quality tools to teach people properly.

What does it improve? What makes it "better"

A list of improvements include:

  • It is easy and straight-forward to install & compile.
  • It is cross-platform (Linux, Windows & MacOS)
  • Error handling, no more straight up segfaults.
  • Clear and understandable English written documentation.
  • No Leaks, compiles with -fsanitize=address effortlessly.
  • No abstracted data types, only things relevant to OpenGL are abstracted.
  • Open-source, find a bug? Send a PR to this repo!
  • Useful extra features such as:
    • Apply a custom application icon for your program.
    • Apply a custom cursor, finally you can have a cool fire sword cursor!
    • Universal enums for keycodes, mouse buttons, no more searching what keycode is for what OS.
    • Easy input handling, no more 3 different types of inputs (Events, masks, hooks). Just a single hook or if statement.
    • Custom XPM image format (XPM42).
    • An actual efficient mlx_putpixel function.
    • Ability to retrieve the delta time, now you can make fancy interpolations.
    • Ability to retrieve monitor width and height as well getting and setting window position.
    • Ability to focus the window.
    • Ability to resize the window.

F.A.Q

Q: "ItS NoT In ThE SuBjeCt!"

A: So what ? Subjects can change and so if something is not working correctly it should be replaced. Sure you can argue this point but you can also be the reason that it CAN be in the subject instead. Have an open mind :)

Q: "Ok, so, can I use it ?"

A: Officially, no. However, ask your head of studies first before about using it, see what they think. Some students might be evangelical enthusiasts about what is stated in the subject and are technically in every right to fail you as long as this library is not endorsed, if you were to ask me (W2) then yes why not?

Q: "Is it faster?"

A: From my personal projects there was a considerable peformance gain, especially when compiled with -Ofast. Projects such as FDF could rotate their maps mind blowingly smooth and even larger maps with a width and height of 1000+ points moved rotated relatively smooth, in short, yes.

Q: "Can I just drag and drop it into my old project and just not do anything?"

A: Well, um uh, no ?? That's not how libraries work. Sure they target and do sort of the same thing but the functions each library provides are too different, even a little bit in terms of behavior. And no there is no easy way to convert from the "old" to the "new" it will be somewhat tedious work.

Q: "We should be able to deal with the fact that MiniLibX is not perfect, it is by design and makes us better programmers."

A: Struggle does bring out the best in most people but it is also not ideal in this case. I think so at least, that its really expected that libraries that are publicly available should be usable, stable, easy to use and well documented. Nobody uses a library because it is annoying to work with it and afterwards think to themselves they have learned something after they are done struggling. The only thing people learn from this is how to navigate around the short comings instead.

Q: "Why not use some other library? Why this one and not any other library."

A: It is your choice what to use! I wrote this in my free time in an attempt to introduce some good change and to improve the learning experience at 42. If you don't like my library at least let me know what it is so I can improve on it.

Q: "Do you hate MiniLibX? Is this some personal vendetta, do you work for the CIA ?"

A: No, I just want to improve 42, that's it.

Repo code style

Since the removal of the norme this repo follows a coding style that should be respected to keep it readable and easily maintainable.

General code style

  • Each file must have a 42 code header.
  • If a file has mulitple functions of which some are in the internal header and others in the public header. They must be divided with a comment stating what is 'public' or 'private' with the private ones being at the top and public at the bottom. This is to clearly distinct what is where.
  • For value types use the types defined in stdint.h.
  • The pointer symbol must be ATTACHED to the TYPE! void* ptr instead of void *ptr
  • Typedefs, except for function ptrs, must end with _t.
  • Bracket on a newline!!! This is not java...

General writing

Bad example

When writing code in a function try to create evenly spaced sections of code, it should read like paragraphs. The example below is dense, ugly, unreadable and has no clear sections as to what is what, ew!

glActiveTexture(GL_TEXTURE0);
glGenVertexArrays(1, &(context->vao));
glGenVertexArrays(1, &(context->vao));
glGenBuffers(1, &(context->vbo));
glBindVertexArray(context->vao);
glBindBuffer(GL_ARRAY_BUFFER, context->vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(t_vert), NULL);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(t_vert), (void *)(sizeof(float) * 3));
glEnableVertexAttribArray(1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUniform1i(glGetUniformLocation(context->shaderprogram, "OutTexture"), 0);
glfwSetWindowSizeCallback(mlx->window, &mlx_on_resize);
mlx_on_resize(mlx->window, mlx->width, mlx->height);

Good Example

In comparison we can see certain things happen in their own 'paragraphs' so to say. First we create the buffer, set the layout, ...

Some lines can have comments that can be useful and provide a quick basic idea what is happening, of course, not every line needs to have obvious comments. They should rather be there to explain why or what we do in specific cases.

glActiveTexture(GL_TEXTURE0);
glGenVertexArrays(1, &(mlxctx->vao));
glGenVertexArrays(1, &(mlxctx->vao));
glGenBuffers(1, &(mlxctx->vbo));
glBindVertexArray(mlxctx->vao);
glBindBuffer(GL_ARRAY_BUFFER, mlxctx->vbo);

// Vertex XYZ coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), NULL);
glEnableVertexAttribArray(0);

// UV Coordinates
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void *)(sizeof(float) * 3));
glEnableVertexAttribArray(1);

glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "OutTexture"), 0);

// NOTE: Call manually once to calculate View Projection Matrix
glfwSetWindowSizeCallback(mlx->window, &mlx_on_resize);
mlx_on_resize(mlx->window, mlx->width, mlx->height);

Functions

  • The functions must have something to do in regards to the file name, e.g: xpm.c has functions regarding xpm's.
  • Each file can have any amount of functions, try to keep it reasonable! Try to keep it under 6 for instance.
  • Function names must be written in snake_case.
  • Functions have no line limit, however they shouldn't try to fullfill a specific task entirely in one go if it means a lot of code, try to split up the responsiblities.
  • Functions must start with the prefix mlx_.
  • Additionlly they should be named in a way that efficiently describes what their main task is and shouldn't be mlx_super_long_names_that_take_up_a_lot_of_space.
  • Returns must have brackets e.g: return (var);
  • Returns may use the comma operator. E.g: Free and error in one line.
  • Functions that get used multiple times should have a Doxygen comment on them, one time functions may or may not have them if it helps explain the function itself.
  • All public functions, that is the end-user can access them MUST have doxygen documentation!

Variables

  • Single line definitions are allowed as well as multiple declarations in one line.
  • Try to keep the variable count to a minimum, don't create redundant variables if the answer can be simplified.
  • Variables in functions should not be indented with tabs, just spaces const int32_t i = 0;

Structs

  • Struct names should be prefixed with mlx_ to avoid type collisions with what the user might have.
  • Variables in a struct must be indented with tabs:
typedef struct mlx_texture
{
    uint32_t	width;
    uint32_t	height;
    uint8_t*	pixels;
    uint8_t	bytes_per_pixel;
}   mlx_texture_t;
Clone this wiki locally