Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rmodels] OBJ models with multiple materials/meshes not loading correctly #3576

Closed
4 tasks done
njegg opened this issue Nov 25, 2023 · 17 comments
Closed
4 tasks done
Assignees

Comments

@njegg
Copy link

njegg commented Nov 25, 2023

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

Issue description

I have a model made in blender with multiple meshes and materials that load correctly in raylib 4.5, but after updating to 5.0 everything is in one material. I have provided a minimal example with a simple 2 mesh/material model.

Environment

Tried on multiple machines and operating systems

Issue Screenshot

4.5
4.5
master/5.0
master

Code Example

model.zip

#include "src/raylib.h"

int main(void)
{
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "model loading");

    Camera camera = { 0 };
    camera.position = (Vector3){ 2.0f, 2.0f, 2.0f };
    camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
    camera.fovy = 45.0f;
    camera.projection = CAMERA_PERSPECTIVE;

    Model model = LoadModel("tomato.obj");

    Vector3 position = {0};

    DisableCursor();

    SetTargetFPS(60);

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

        BeginDrawing();

            ClearBackground(RAYWHITE);

            BeginMode3D(camera);

                DrawModel(model, (Vector3) {0}, 1.0f, WHITE);
                DrawGrid(20, 10.0f);

            EndMode3D();

        EndDrawing();
    }

    UnloadModel(model);
    CloseWindow();

    return 0;
}
@raysan5
Copy link
Owner

raysan5 commented Nov 25, 2023

@njegg OBJ loading was redesigned due to other issues when mixing different number of materials and meshes. It probably needs another redesign.

@interkosmos
Copy link
Contributor

Model loading breaks when calling LoadModel():

$ ./truck
INFO: Initializing raylib 5.1-dev
INFO: Platform backend: DESKTOP (GLFW)
INFO: Supported raylib modules:
INFO:     > rcore:..... loaded (mandatory)
INFO:     > rlgl:...... loaded (mandatory)
INFO:     > rshapes:... loaded (optional)
INFO:     > rtextures:. loaded (optional)
INFO:     > rtext:..... loaded (optional)
INFO:     > rmodels:... loaded (optional)
INFO:     > raudio:.... loaded (optional)
INFO: DISPLAY: Trying to enable MSAA x4
INFO: DISPLAY: Trying to enable VSYNC
INFO: DISPLAY: Device initialized successfully
INFO:     > Display size: 1920 x 1080
INFO:     > Screen size:  800 x 450
INFO:     > Render size:  800 x 450
INFO:     > Viewport offsets: 0, 0
INFO: GLAD: OpenGL extensions loaded successfully
INFO: GL: Supported extensions count: 226
INFO: GL: OpenGL device information:
INFO:     > Vendor:   Intel
INFO:     > Renderer: Mesa Intel(R) HD Graphics 620 (KBL GT2)
INFO:     > Version:  4.6 (Core Profile) Mesa 22.3.7
INFO:     > GLSL:     4.60
INFO: GL: VAO extension detected, VAO functions loaded successfully
INFO: GL: NPOT textures extension detected, full NPOT textures supported
INFO: GL: DXT compressed textures supported
INFO: GL: ETC2/EAC compressed textures supported
INFO: PLATFORM: DESKTOP (GLFW): Initialized successfully
INFO: TEXTURE: [ID 1] Texture loaded successfully (1x1 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 1] Default texture loaded successfully
INFO: SHADER: [ID 1] Vertex shader compiled successfully
INFO: SHADER: [ID 2] Fragment shader compiled successfully
INFO: SHADER: [ID 3] Program shader loaded successfully
INFO: SHADER: [ID 3] Default shader loaded successfully
INFO: RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)
INFO: RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)
INFO: RLGL: Default OpenGL state initialized successfully
INFO: TEXTURE: [ID 2] Texture loaded successfully (128x128 | GRAY_ALPHA | 1 mipmaps)
INFO: FONT: Default font loaded successfully (224 glyphs)
INFO: FILEIO: [./share/truck.obj] Text file loaded successfully
INFO: MODEL: [./share/truck.obj] OBJ data loaded successfully: 5 meshes/8 materials

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x827820369 in ???
#1  0x82781f495 in ???
#2  0x8227fdb5f in ???
#3  0x8227fd11e in ???
#4  0x7ffffffff8a2 in ???
#5  0x457fb1 in LoadOBJ
    at /tmp/raylib-master/src/rmodels.c:3995
#6  0x457808 in LoadModel
    at /tmp/raylib-master/src/rmodels.c:1037
#7  0x402e0e in MAIN__
    at examples/truck.f90:36
#8  0x4032b6 in main
    at examples/truck.f90:12

@raysan5 raysan5 changed the title [rmodels] Models with multiple materials/meshes not loading correctly on 5.0/master [rmodels] OBJ models with multiple materials/meshes not loading correctly Dec 11, 2023
@hbiblia
Copy link

hbiblia commented Dec 15, 2023

Le voy a tirar un ojo !

@x1nixmzeng
Copy link

x1nixmzeng commented Feb 14, 2024

I have the same issue. My OBJ models are exported from Blender triangulated - the else statement here is the issue - the tri count is actually an offset when there are two or more models in the same file:

raylib/src/rmodels.c

Lines 4070 to 4076 in dc7f81a

// WARNING: We need to calculate the mesh triangles manually using meshes[i].face_offset
// because in case of triangulated quads, meshes[i].length actually report quads,
// despite the triangulation that is efectively considered on attrib.num_faces
unsigned int tris = 0;
if (i == model.meshCount - 1) tris = attrib.num_faces - meshes[i].face_offset;
else tris = meshes[i + 1].face_offset;

Here's an example - it crashes the demo here too - https://www.raylib.com/examples/models/loader.html?name=models_loading

obj_multiple_models.zip

My fix is to use the length (despite the comment) warning about quads

else tris = meshes[i].length;

@BobSleigh38
Copy link

Hello
I also have issues loading a model with 3 materials defined by an obj+mtl files.
Only the first material appearing in mtl file is used for the entire model.
BUT !
If I add this
model.meshMaterial[0]=0;
model.meshMaterial[1]=1;
model.meshMaterial[2]=2;
Then my model displays completely fine, with the right 3 materials ...

@0xSPIRIT
Copy link

0xSPIRIT commented Mar 9, 2024

I had a similar issue, and the above code by BobSleigh38 didn't work for me with the materials not being set properly to the meshes. What I did was just export in Blender as a .glb file instead of an .obj file (so this isn't really a fix to this issue, rather a workaround).

When I initially did this however, all my meshes were centered at (0,0,0) and with normalized scales, so my fix was just to select all the objects in Blender (A), and apply the transforms by pressing Ctrl+A and selecting All Transforms like so:

image

Here's my export settings in Blender...
image

@x1nixmzeng
Copy link

If it helps anyone else, for OBJ model loaded I ended up using this single file library to load OBJ models into raylib: https://github.com/Not-Nik/rlobj

Not sure the author would agree to swapping it out, but for anything more complicated than a single object it's required

@orcmid
Copy link
Contributor

orcmid commented Mar 11, 2024

@x1nixmzeng

Not sure the author would agree to swapping it out, but for anything more complicated than a single object it's required

The license for rlobj is a bit sketchy. There is a statement about an exception at the repository but there is no such statement in the license document itself. The exception is also for (indirectly-)named individuals, not arbitrary users of raylib. I'm not sure it could even be incorporated here as an external.

@raysan5
Copy link
Owner

raysan5 commented Mar 12, 2024

@x1nixmzeng, @orcmid is right, the license does not seem to be compatible with raylib.

@raysan5 raysan5 self-assigned this Apr 21, 2024
@AITYunivers
Copy link

Is there any progress being done on this?

@JeffM2501
Copy link
Contributor

The OBJ format is broken for any file that uses multiple materials. Making it as a format in the current state useless.
Raylib reads the other materials but does not even bother to assign them.
The changes made for 5.0 were very bad and cause many more problems than they solve.
If we want to keep OBJ as a format, we need to upgrade to the current TinyOBJ and process the material assignments that are in the shape structure.
If we do not do this then OBJ is not a useful format in raylib since raylib will not respect the data. If we are unwilling to fix this then OBJ should be removed from the library, and made an external drop in header.
It is not useful for any real work beyond simple primitives in it's current format.

@JeffM2501
Copy link
Contributor

I am working on new code for raylib to read the data from TinyOBJ.
The loader has the data needed, it just needs to be converted properly into multiple meshes. The old code made too many assumptions and took some shortcuts that can be made.

image
This is a simple test drawing the data from tiny obj using the batch system, it's clear all the data is correct, thus it's there, we just need to get it into mesh buffers.

Splitting the mesh by material is required for OBJ to work simply due to how the OBJ format is defined. To OBJ the entire file is one mesh with N groups, each group can have N material assignments. To represent this as a raylib mesh, each group must be split into sub-meshes when the material changes, since a raylib mesh can only have one material. It is insufficient to combine sub meshes with the same material into one, since the group split must also be maintained. A user may need to manipulate individual groups.
To do this the mesh must be scanned multiple times to get the actual number of meshes and number of triangles per mesh.

As a side note, we may want to see about adding an array of mesh names to the model structure so that people can know what groups each mesh in the model came from, but that is not required for this fix.

It's tedious code but very possible. I will continue to work on it and make a PR when I have something.
It will involve an entirely new LoadOBJ function.

@JeffM2501
Copy link
Contributor

I have written a new LoadOBJ in this branch. It till needs massive testing and Debugging.
https://github.com/JeffM2501/raylib/tree/LoadObjNew

@JhottMaster
Copy link

JhottMaster commented Aug 22, 2024

I literally just ran into this issue after trying to load an .obj file I created in Blender. Very interested in what you're doing, @JeffM2501 ! In the mean time maybe I should try to convert my .obj files to gltx or some other supported function?

@JeffM2501
Copy link
Contributor

Yes use glb when possible, obj is an old and fragile format.

@raysan5
Copy link
Owner

raysan5 commented Aug 24, 2024

I'm closing this issue, feel free to send a PR when ready for further discussion there.

@coderextreme
Copy link

I’m eager to try material exports from blender. .gltf does not look reasonable in naylib. I’m using a icosphere at level 5 (I think 5 is highest you can go, I tried 10 and I had to kill my blender. Currently I only have one material…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests