Cross-platform renderer on iOS: control the main loop from C++ class -


i’m porting opengl-based renderer (written in c++) ios , ran following problem:

on windows renderer-class has _renderproject (e.g. game i’m making) , _view object again has glfw window. loop in renderer follows:

void renderer::runrenderer() {    while (_running && _view->isrunning())    {        draw((_view->gettime() - _initialtime));    } } 

the draw function looks this:

void renderer::draw(double currenttime) {     [...]     // call loop function of project     if (_renderproject)         _renderproject->loopfunction(currenttime - _elapsedtime, currenttime);     [...] } 

now want same thing ios don’t know how loop in renderer class. use cadisplaylink don't know how call c++ memeber function there.

update

following code written @kazuki sakamoto changed code this:

/* 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 loop running     if(_displaylink == nil)     {         // specify update method         _displaylink = [cadisplaylink displaylinkwithtarget:self selector:@selector(update:)];          // add display link run loop (will called 60 times per second)         [_displaylink addtorunloop:[nsrunloop currentrunloop] formode:nsdefaultrunloopmode];     } }  - (void)stop {     // check whether loop stopped     if (_displaylink != nil) {         // if display link present, gets invalidated (loop stops)         [_displaylink invalidate];         _displaylink = nil;     } }  - (void)update:(cadisplaylink *)sender {     double time = [sender timestamp];     updateblock(time);   /// error, 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);     [...] } 

i error in following line: updateblock(time);

update 2 had change _updateblock(time); reason works! thank much! made day today :-)

you're there. create objective-c class call c++ method.

for example, cocos2d-x created ccdirectorcaller objective-c class in objective-c++ source code (.mm file).

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

added

you want use cadisplaylink opengl es render loop. , want use c++ main loop. right?

cadisplaylink needs nsrunloop. needs objective-c object, target , selector. thus, must create @ least 1 objective-c class cadisplaylink.

see friday q&a 2010-01-01: nsrunloop internals.

so, there main nsrunloop cadisplaylink in main thread. infinite loop in main nsrunloop not totally idea because nsrunloop can't loop due infinite loop. obvious. thus, if want use c++ main loop, should create thread.

      main thread                  other thread         +-----------+                   +-------------+        |           |                   |             |        v           |                   v             | main nsrunloop |                c++ main loop    |        |           |                   |             |        |     cadisplaylink             |             |        |       call target's method    |             |        |           |                   |             |        |           |                   |             |        +-----------+                   +-------------| 

and if want use cadisplaylink schedule rendering, need implement rendezvous thread synchronization pattern between main nsrunloop , c++ main loop.

it's complicated enough. that's why recommend create objective-c class call c++ method, not c++ main loop.

i had make draw function of renderer public , renderer class singleton

not really.

// **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);     }]; } 

Comments

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -