我试图在IOS中使用assimp lib将模型导入渲染器。 我的模型文件大小为2mb;
我可以通过不使用线程成功导入模型。
但是当我在一个线程中运行我的代码时,assimp无法导入。
Assimp::Importer* importer = new Assimp::Importer();
scene = importer->ReadFile(modelPath.data,aiProcessPreset_TargetRealtime_MaxQuality);
基本上,如果我使用线程,这个场景就成了nil。
我使用的线程错了吗?
我错过了什么意思?
您可以在此链接中看到更多代码:http://pastebin.com/aLjx7dvZ
为了保持问题的简单性,我没有发布完整的代码。
答案 0 :(得分:1)
首先,您需要在每个要使用openGL的线程中使用EAGLContext。多个上下文将确保在处理多个线程时状态更改,绑定等没有冲突。例如,如果您的主线程将尝试绘制一个对象,它可能会绑定一些缓冲区,可能还有一些纹理和更多,后台线程将尝试加载一个对象,再次将绑定一些缓冲区,纹理...自从你无法控制在什么时间执行的操作(由于多线程),您需要多个上下文,因此不会发生此类冲突。这意味着每次创建新线程时都需要创建一个新的上下文:
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:sharegroup]; //ignore sharegroup for now
并在线程本身将其设置为当前
[EAGLContext setCurrentContext:context];
通过这样做,就openGL而言,2个线程之间没有任何关系。这解决了冲突的问题但提出了一个新问题,在这个问题上你不能使用在后台线程上创建的资源,除了创建它的线程。因此,为了在后台加载对象并在主线程上使用它们,有一个叫做共享组的东西。在创建新的上下文时,您应该只创建一个实例并将其用作所有后台线程的参数(如已在前面提到的片段中所示)。
EAGLSharegroup *sharegroup = [[EAGLSharegroup alloc] init];
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:sharegroup];
这可以解决您的主要问题,但查看您的代码可能会有更多。您需要确保在完成之前不使用在后台线程上创建的资源。您正在使用一些全局对象(而不是指针),您可以在其上分配新创建的资源,但稍后在同一方法中初始化数据。如果另一个线程正在使用同一个指针,那么你可能会在不幸的时候交换它(在你的情况下)导致主线程试图绘制一个未初始化的对象。现在,即使您将该全局赋值移动到方法的末尾,如果正在使用这些资源,事情也会变得不稳定。为了正确地做到这一点,我建议您将后台线程上的对象独立地加载到任何全局变量,并在主线程上执行带有对象的选择器,以通知它加载完成并在主线程上进行交换。