raylib: [models] MTL files fail to load automatically on Android

  • I tested it on latest raylib version from master branch
  • I checked there is no similar issue already reported
  • My code has no errors or misuse of raylib

Issue description

The MTL files linked to an OBJ file fail to load automatically on Android when loading the OBJ file, whereas for the same example, it works on PC.

Android logs:

2023-06-28 15:05:28.324 22364-22505 raylib                  com.raylib.objmtltest                I  FILEIO: [suv.obj] Text file loaded successfully
2023-06-28 15:05:28.342 22364-22505 raylib                  com.raylib.objmtltest                I  MODEL: [suv.obj] OBJ data loaded successfully: 5 meshes/0 materials
2023-06-28 15:05:28.342 22364-22505 raylib                  com.raylib.objmtltest                I  MODEL: No materials, putting all meshes in a default material
2023-06-28 15:05:28.344 22364-22505 raylib                  com.raylib.objmtltest                I  VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
2023-06-28 15:05:28.344 22364-22505 raylib                  com.raylib.objmtltest                W  MATERIAL: [suv.obj] Failed to load material data, default to white material

Desktop logs:

INFO: FILEIO: [suv.obj] Text file loaded successfully
INFO: MODEL: [suv.obj] OBJ data loaded successfully: 5 meshes/8 materials
INFO: MODEL: model has 8 material meshes
INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 3] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 4] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 5] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 6] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 7] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 8] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 9] Mesh uploaded successfully to VRAM (GPU)

Issue Screenshot

Android: android-screenshot

Desktop: desktop-screenshot

Code Example

Example Android/Desktop (.zip)

#include "raylib.h"
#include "raymath.h"

int main()
{
    InitWindow(800, 450, "raylib - OBJ/MTL test");

    Camera camera = { };
    camera.position = { 10.0f, 10.0f, 10.0f };
    camera.target = { 0.0f, 0.0f, 0.0f };
    camera.up = { 0.0f, 1.0f, 0.0f };
    camera.fovy = 45.0f;
    camera.projection = CAMERA_PERSPECTIVE;

    Model models = LoadModel("suv.obj");
    {
        BoundingBox bb = GetModelBoundingBox(models);
        Vector3 center = { };
        center.x = bb.min.x  + (((bb.max.x - bb.min.x)/2));
        center.z = bb.min.z  + (((bb.max.z - bb.min.z)/2));
        Matrix matTranslate = MatrixTranslate(-center.x, 0, -center.z);
        models.transform = matTranslate;
    }

    SetTargetFPS(60);

    while (!WindowShouldClose())
    {
        UpdateCamera(&camera, CAMERA_ORBITAL);

        BeginDrawing();
        ClearBackground(RAYWHITE);
            BeginMode3D(camera);
                DrawModel(models, { 0, 0, 0 }, 1.0f, WHITE);
                DrawGrid(10, 1.0);
            EndMode3D();
        EndDrawing();
    }

    UnloadModel(models);
    CloseWindow();

    return 0;
}

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 24 (22 by maintainers)

Most upvoted comments

Yes, a new C obj loader library is required with improvements over tinyobj_loader_c.h but implementation from scratch requires a considerable amount of work. Requirements:

  • Single-file header-only library
  • No external dependencies, only libc
  • Allow loading from memory and avoiding stdio (if desired)
  • Allow external filename returned for external management (for mtl and textures)
  • Allow custom memory allocators
  • Custom text parsers? (Avoid sscanf() and similar)
  • Fallback mechanisms in case of errors
  • Support faces triangulation for quads

Creating and maintaining that library requires some work…

Related comment: https://github.com/raysan5/raylib/issues/2219#issuecomment-1004250177

@Bigfoot71

Done, I tried converting LF to CRLF using VSCode, but it didn’t work. Then I used the dos2unix package via Mingw, and that didn’t work either.

Based on the fact that a \r showed up in a filename in the model-loading process, I am unclear how converting all LF to CRLF is going to help with that. It seems to me that you might want to do the opposite and use dos2unix rather than unix2dos.

It looks like there is a parsing problem in the model loading code. A sane solution, generally, is to treat all \r' and \n` codes as white space and be flexible about treating runs of whitespace as a single whitespace. I assume the “parser” in model loading is more rigid than that. My guesswork only.

Runs of the failing program having varying success/failure patterns from one run to the next signals that there may be an uninitialized variable or an over-run value somewhere. This could happen with a pointer misuse too (e.g., using the pointer instead of what it is pointed at, or even vice versa). It might even matter whether char is handled as a signed or unsigned small int.

Final observation. In the distant past, there was a time when \r alone was used the same as \n is in Unix, not in a pair. Also, use of \r alone can be intentional to overwrite a line in output to a stdout terminal, as when presenting a countdown, or other busy behavior, without scrolling down the screen. That usually works independent of whether \n is converted to a single LF or a CRLF in the stream to the device. Here, I suppose, it might be important to know whether the compiler used handles \r properly if at all or whether there is an ill-escaped usage.

Hi everyone.

Took a look with the android debugger and it seems like indeed there’s an issue with how tinyobj_loader parses that particular obj given in your example @Bigfoot71 . Here’s what has been parsed in tinyobj_parse_obj()

image

So, the resulting filename contains a trailing CR (\r) which is in turn given to android_fopen and then to android’s AAssetManager_open function which seems to fail because of it.

Doing quick and dirty removal of this trailing CR loads the file successfully, but app crashes somewhere else which I did not investigate why. Maybe there’s something horribly wrong with that obj file? or the obj loader needs refinement. For now, I do not know.