gpt4 book ai didi

c++ - iOS 上的跨平台渲染器 : control the main loop from C++ class

转载 作者:行者123 更新时间:2023-11-30 03:51:06 24 4
gpt4 key购买 nike

我正在将基于 OpenGL 的渲染器(用 C++ 编写)移植到 iOS 并遇到以下问题:

在 Windows 上,我的渲染器类有一个 _renderProject(例如我正在制作的游戏)和一个同样有 GLFW 窗口的 _view 对象。我在渲染器中按如下方式进行循环:

void Renderer::runRenderer()
{
while (_running && _view->isRunning())
{
draw((_view->getTime() - _initialTime));
}
}

绘图函数如下所示:

void Renderer::draw(double currentTime)
{
[...]
// Call loop function of the project
if (_renderProject)
_renderProject->loopFunction(currentTime - _elapsedTime, currentTime);
[...]
}

现在我想为 iOS 做同样的事情,但我不知道如何在渲染器类中进行循环。我想使用 CADisplayLink 但我不知道如何从那里调用 C++ memeber 函数。

更新

按照@Kazuki Sakamoto 编写的代码,我将代码更改为:

/* Main Loop using CADisplayLink */

typedef void (^block_t)(double);
@interface RendererCaller : NSObject
{
CADisplayLink *_displayLink;
}
@property (nonatomic, copy) block_t updateBlock;
@end

@implementation RendererCaller

- (void)start:(block_t)block
{
self.updateBlock = block;
// check whether the loop is already running
if(_displayLink == nil)
{
// specify update method
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];

// add the display link to the run loop (will be called 60 times per second)
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
}

- (void)stop
{
// check whether the loop is already stopped
if (_displayLink != nil) {
// if the display link is present, it gets invalidated (loop stops)
[_displayLink invalidate];
_displayLink = nil;
}
}

- (void)update:(CADisplayLink *)sender
{
double time = [sender timestamp];
updateBlock(time); /// ERROR, it doesn't know "updateBlock"
}

@end

/* Renderer */

void Renderer::runRenderer()
{
if (_rendererCaller == nil) _rendererCaller = [[RendererCaller alloc] init];
[_rendererCaller start:^(double time) {
this->draw(time);
}];
}

void Renderer::stopRenderer()
{
[_rendererCaller stop];
}

void Renderer::terminateRenderer()
{
stopRenderer();
_rendererCaller = nil;
[...]
}

void Renderer::draw(double time)
{
[...]
if (_renderProject)
_renderProject->loopFunction(time - _elapsedTime, time);
[...]
}

我在以下行中收到错误:updateBlock(time);

更新 2出于某种原因,我不得不将其更改为 _updateBlock(time); 但现在可以了!太感谢了!你今天真让我开心 :-)

最佳答案

你快到了。创建一个 Objective-C 类来调用 C++ 方法。

例如,Cocos2d-x在Objective-C++源代码(.mm文件)中创建了CCDirectorCaller Objective-C类。

https://github.com/cocos2d/cocos2d-x/blob/v3/cocos/platform/ios/CCDirectorCaller-ios.mm

已添加

您想将 CADisplayLink 用于 OpenGL ES 渲染循环。而且您还想使用 C++ 主循环。对吧?

CADisplayLink 需要 NSRunLoop。它还需要一个 Objective-C 对象,用于 targetselector。因此,您必须至少为 CADisplayLink 创建一个 Objective-C 类。

另见 Friday Q&A 2010-01-01: NSRunLoop Internals .

因此,在主线程中有主要的 NSRunLoopCADisplayLink。主 NSRunLoop 中的无限循环并不是一个好主意,因为 NSRunLoop 由于无限循环而无法循环。这很明显。因此,如果你真的想使用你的 C++ 主循环,你应该创建一个线程。

      The main thread                  Other thread

+-----------+ +-------------+
| | | |
V | V |
the main NSRunLoop | C++ main loop |
| | | |
| CADisplayLink | |
| call target's method | |
| | | |
| | | |
+-----------+ +-------------|

如果您想使用 CADisplayLink 计划进行渲染,您需要在主 NSRunLoop 和 C++ 主循环之间实现一些会合线程同步模式。

这已经够复杂了。这就是为什么我建议您创建一个 Objective-C 类来调用 C++ 方法,而不是 C++ 主循环。

I had to make the draw function of the renderer public and the renderer class itself singleton

不是真的。

// **pseudo code**

// In Objective-C++ source code
typedef void (^block_t)(double);
@interface RendererCaller : NSObject
@property (nonatomic, copy) block_t updateBlock;
@end

@implementation RendererCaller
- (void)start:(block_t)block
{
self.updateBlock = block;
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
...
}
- (void)update:(CADisplayLink *)sender
{
updateBlock(elapsed time using sender);
}
@end

void Renderer::startMainLoop()
{
RendererCaller *rendererCaller = [[RendererCaller alloc] init];
[rendererCaller start:^(double elapsed){
this->draw(elapsed);
}];
}

关于c++ - iOS 上的跨平台渲染器 : control the main loop from C++ class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31486310/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com