objloader so slow with huge animation how can i accelerate it

my steps

  1. i am making a model and i giving a rig and making animation 1000 1200 frame in blender and i export these .obj files therefore i have to load 1000-1200 .obj files
  2. i am using objloader in c++ and i am sending gpu with opengl VBO way
  3. i didnt use multithreading with objloader
  4. all files install in 80 seconds (one file has 2000face all triangle)

how can i accelerate it ?

  1. i have to use multithreading ? is it only way ? then i cant use std::string and std::vector right ?
  2. can i take only rig positions from blender and can i use them over only one .obj file in opengl with gltranslate and glrotate to move? against load all animation model ?
  3. any suggestion please :slight_smile:
    i am beginner if you help me i will be happy thanks a lot

Let me see if I understand. You have one skin mesh rigged to a joint skeleton, and one skeletal animation defined for that skeleton. And it sounds like you’re trying to export that animation as 1000-1200 object files, one per timestep?

If so, it sounds like you need to teach your app how to render skin meshes posed with skeletal animations. With that, you’d export 1 skin mesh model and 1 animation. Then at render time, just pose the model with the animation.

You’d probably need to add skeletal animation to your application. You typically can’t do this with fixed-function matrix operations (glRotate() etc). There are plenty of online tutorials, but this isn’t trivial.

If you want to use vertex animation, you should convert the OBJ files to a more suitable format. E.g. a binary format which you can just fread() in a couple of steps. The required data consists of:

  1. [li] The number of frames, vertices and triangles, which determine the sizes of the arrays which follow.
    [/li]
    [li] An array of integers containing the topology (the index array passed to glDrawElements()). This should be the same for every frame.
    [/li][var]GLuint indices[num_triangles][3][/var]

    [li] An array of floats containing the vertex positions for each frame.
    [/li][var]GLfloat position[num_frames][num_vertices][3][/var]

Converting ~1000 OBJ files won’t be any quicker than loading them, but you’ll only need to perform that conversion once.

Vertex animation worked fine for many of the early 3D games of the late 1990s (Quake 1/2, Unreal), although they probably had fewer vertices and fewer frames. Also, they typically only stored keyframes and used linear interpolation for intermediate frames (if you take this approach, you’ll probably need more keyframes than you would for skeletal animation).

.obj is always going to be slow. It’s a plain text format that must be parsed and validated, so it doesn’t scale to non-trivial use cases. The only reason to use .obj for non-trivial production work is if you love writing text parsers.

Use a binary format instead.

i think i need to add much more frame and another models. Therefore i need to learn how to use skeletal animation right? my current way is vertex animation right ? i think skeletal way much more suitable for huge model and frame , because i will import only one frame my models and i will import rig positions(skeletal positions) and i dont need import anything ? skelatal animation will import fast because data of frames of skelatal positions < data of frames of faces ?

for example :
plain text speed = x
binary speed = ?

and which function need? can i read .text file inside binary numbers with std::ifstream fin(“test.txt”); ? or file need to be .bin ? is it different

It seems like we may have a language difference here. Let me re-state what I “think” you’re saying:

Is this close? The answer to all of these questions is yes. However, reduced loading time is only one side benefit of loading and animating with skeletal animation.

You also get a “huge” reduction in the amount of CPU and GPU memory required to represent an animation. With the “load a posed mesh per animation frame” method (what I “think” you’re doing now with the OBJ files), you end up storing/loading your character’s mesh model N times. With that method, if you want to animate another character’s mesh model with that same animation, that adds N copies of that new character mesh model as well. So for M models which can each be animated by N animations each having T frames, you have MNT pre-posed mesh models stored on disk that you have to load into memory before rendering (and figure out how to render efficiently). By comparison, with skeletal animation, you load 1 model per skin mesh, 1 animation track (pose data) per animation, and pose the skin mesh dynamically at render time (either on the GPU or on the CPU). Multiple skin meshes can also share animation track data by being rigged to a shared joint skeleton, so that’s yet another memory savings (and a “huge” DCC time savings on the 3D animator’s part).

With skeletal animation, the engine can also do things like keyframe interpolation, where you dynamically interpolate a unique pose per rendered OpenGL-rendered frame based on the current time by blending pose data for different animation track keyframes together. With support for this in your engine, you may only need to export 10 frames to get smooth playback for a particular animation rather than 30-60, further saving memory (and memory bandwidth). Recall that with the “load a posed mesh per animation frame” method, the rate at which the animation updates (e.g. 10Hz, or 20Hz) can be rendered ends up being limited by what rate you exported those mesh “keyframes” at. With skeletal, that information isn’t “pre-baked” into your loaded data. That is, you can match the animation update rate dynamically to exactly your rendered frame rate (e.g. 60Hz, 120Hz, dynamic, etc.)

You can also blend different animations together dynamically based on what the character is doing in your game. Etc… And I’m just barely scratching the surface here.

As GClements said, learning skeletal animation isn’t trivial, but if your requirements need it, it’s worth the effort. There are plenty of good tutorials and “spin-up” information if you know where to look. If you’re interested in some of these, just say so.

Also keep in mind that you don’t necessarily need to implement this all from scratch. There are libraries (both open source and commercial) which can automate much of this. However, you’ll still need to understand the skeletal animation data model and data flow clearly to apply them.

Thank you too much for a long answer but my english is not so good, so i didnt understand some parts sorry for that. I need to show with one example to ask to you “i understand right”.

first my current way vertex animation i cant modify after init

init()
{
send to save data with "VBO way" to vram of gpu when vram full, continue from ram
}

display()
{
glDrawArrays();
}

main()
{

init();

while(1)
{ display(); }

}

and you mean skeletal way dont need to save data i can modify vertices when i am drawing and modify process will be fast and it can draw 60fps 120fps

init()
{
NULL
}

display()
{
if(data==0){send data to gpu}
else if(data==1){modify data}
glDrawArrays();
}

main()
{

init();

while(1)
{ display(); }

}

did i understand right ? sorry for bad english and stealing your time

Try pasting the URL for this thread:

into:

Then select your language, and click “Translate”.

…and you mean skeletal way dont need to save data i can modify vertices when i am drawing and modify process will be fast and it can draw 60fps 120fps

Yes.

…with reasonable assumptions (decent GPU, reasonable skinning implementation, reasonable limit on number of characters using that skinning method, etc.).

However, you do need to “save data” and load it into your engine. But you only need to save and load one mesh per character, not one mesh per character per animation frame.