org.lwjgl.demo.util.IOUtil.*

Started by chris_c, November 21, 2014, 10:33:01

Previous topic - Next topic

chris_c

Shouldn't low level ("bare metal") stuff like this be part of say lwjgl.util ?

you can't use some of the glfw bindings with either that or your own version, and expecting someone new (to lwjgl - and potentially Java?) could cause issues.

Light weight doesn't have to mean low level does it ? - for example I don't think GLES is low level but messing with byte buffers and byte order does seem so!

Would it be going too far even, to abstract it further - for example by having an overload of GLFWimage that accepted something higher level that just a byte buffer (as well as allowing the "raw" GLFWimage) ?

I assume GLFWimage is also the preferred way to handle textures.

I'm in no way criticising - rather wanting to stimulate some discussion on what could be a sticking point for new users.

spasi

Hey chris_c, this is a valid and interesting question. I'll try to address your points, but consider this just my personal opinion at the moment. I'm currently focused on core LWJGL development and work on the utility package will start at a later stage. I was expecting community feedback on this matter, which you just gave, so thanks for that.

Low-level

I'm afraid lightweight in LWJGL's case does mean low-level. The API bindings themselves are as low-level as you can get. You directly deal with pointers, C structs and concurrency issues. No matter how rich a utility package is, you cannot use OpenGL or OpenCL without having to deal with such low-level details. It is also impossible for LWJGL, as a library, to guarantee crash-free operation; the APIs we expose make it too easy to directly mess with memory, one wrong offset and you segfault. Without a good understanding of the APIs and full control of memory layout, you cannot effectively use LWJGL.

It is the job of higher-level frameworks and game engines to encapsulate low-level details and provide a safe development environment. If we try to do it in LWJGL, we'll either end-up with a half-arsed solution, or a full-blown engine. The former sucks, the latter is outside the scope of the library (and would take forever).

GLFWImage

GLFWImage is a simple struct:

typedef struct GLFWimage
{
    int width;
    int height;
    unsigned char* pixels;
} GLFWimage;


A struct is not a class, it's basically a "schema" of a particular piece of memory. LWJGL uses ByteBuffers to access that memory and auto-generated classes that understand the schema. In this case, the class is org.lwjgl.system.glfw.GLFWimage. This struct is currently only used for defining custom cursors in GLFW. It will also probably used for window icons (currently unsupported). A GLFWimage has absolutely nothing to do with textures, it's used by GLFW, not OpenGL.

Resource loading

Resource loading is something everyone does differently, because they have different requirements. Bulk loading or streaming? How much buffering? What image formats to support? What about geometry data, materials, shaders? Are they compressed and if yes with which codec? No matter what LWJGL supports, there will always be something missing.

In this particular case, I'm using ImageIO for convenience. This has the implication of also loading the AWT toolkit, which is an entire beast, not everyone will appreciate the extra overhead. There is also a major conflict with GLFW on OS X (the Events demo currently crashes because of that). Finally, the performance and memory allocation characteristics of this implementation might not be acceptable for some users.

Quality

This is again related to limited development time and hugely varying needs. The utility package in LWJGL 2.x was, in all honesty, horrible. Bad API, limited features, bugs, everything you don't want in a project. It was also not maintained after the initial effort (I'm also guilty of that with the mapped package). I don't want this to happen again. Especially when new users have the impression that, since it's in the library, it must be the preferred way and should be used.

Anything we add to LWJGL should be high-quality code, that does one thing and does it well. If we cannot guarantee that, we're open to the above issues.

tl;dr

I would like LWJGL to be easier to use, but not "too easy". By making the decision to use LWJGL directly you've already gone "hardcore", there's no way around that. Graphics, audio and parallel computing are difficult and I don't want half the library to pretend that they aren't. Instead, my preferred way to address this problem would be:

a) Make general improvements. One example is the new bindings generator in LWJGL 3. Compared to LWJGL 2, it produces 100% consistent bindings across all APIs, with more useful alternative methods. Another example is the auto-generated struct classes, they could be improved for better usability.

b) Make localized improvements like this issue (in the core library, not in a utility package) to address Java-native interop difficulties.

c) Produce tons of documentation, demos and example code patterns/templates. It's much better if the user understands the code and is able to adjust it to their particular needs.

chris_c

Thanks for taking the time to make such a great answer! much appreciated...  :)