Question

I am trying to import model to renderer by using assimp lib in IOS. My model file's size is 2mb;

i can successful import models by not using threads.

But when i run my codes inside a thread, assimp fails to import.

Assimp::Importer* importer =  new Assimp::Importer();
scene = importer->ReadFile(modelPath.data,aiProcessPreset_TargetRealtime_MaxQuality);

so basicly this scene becames nil if i use thread.

am i using threads wrong?

What is the point i am missing out?

you can see more code from this link: http://pastebin.com/aLjx7dvZ

to maintain the simplicity of question i did not post full code.

Was it helpful?

Solution

First of all you need a EAGLContext in each of your thread you want to work with openGL. Multiple context will ensure there are no conflicts in state changes, bindings and such when dealing with multiple threads. For instance if your main thread will be trying to draw an object it will probably bind some buffer and possibly some textures and more, the background thread will try to load an object which again will have to bind some buffers, textures... Since you do not have a control of what operation executes at what time (because of multithreading) you need multiple contexts so such conflicts will not occur. That means you need to create a new context every time you create a new thread:

EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:sharegroup]; //ignore sharegroup for now

and set it to current on the thread itself

[EAGLContext setCurrentContext:context];

By doing so there will be no relation between the 2 threads as far as openGL goes. That resolves the conflicting problem but presents a new problem where you can not use resources created on background thread anywhere else but the thread it was created on. So for purpose of loading objects in background and using them on main thread there is a thing called share group. You should create only 1 instance and use it as a parameter for all background threads when creating new contexts (as in snippet already mentioned).

EAGLSharegroup *sharegroup = [[EAGLSharegroup alloc] init];

EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:sharegroup];

This should solve your main problem but looking at your code there might be a few more. You need to ensure that resources being created on background thread are not used before finished. You are using some global object (rather pointer) on which you assign the newly created resources but initialize the data later in the same method. If that same pointer is being used by another thread it might happen you will swap it in unfortunate time resulting (in your case) in main thread trying to draw an uninitialized object. Now even if you move that global assignment to the end of the method things can get unstable if those resources are in use. To do that correctly I suggest you load the object on your background thread independently to any global variables at all and perform selector with object on main thread, to notify it the loading is finish and do the swapping on the main thread itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top