Объединение основной анимации с OpenGL ES - PullRequest
11 голосов
/ 21 декабря 2010

Редактировать: Полагаю, вместо длинного объяснения, приведенного ниже, я также могу спросить: отправка -setNeedsDisplay в экземпляр CAEAGLLayer не приводит к перерисовке слоя (то есть -drawInContext: называется). Вместо этого я получаю это сообщение консоли:

<GLLayer: 0x4d500b0>: calling -display has no effect.

Есть ли способ обойти эту проблему? Могу ли я вызвать -drawInContext: при вызове -setNeedsDisplay? Длинное объяснение ниже:


У меня есть сцена OpenGL, которую я хотел бы анимировать с помощью анимации Core Animation.

Следуя стандартному подходу к анимации пользовательских свойств в CALayer, я создал подкласс CAEAGLLayer и определил в нем свойство sceneCenterPoint, значение которого должно быть анимированным. Мой слой также содержит ссылку на рендерер OpenGL:

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "ES2Renderer.h"

@interface GLLayer : CAEAGLLayer
{
    ES2Renderer *renderer;
}

@property (nonatomic, retain) ES2Renderer *renderer;
@property (nonatomic, assign) CGPoint sceneCenterPoint;

Затем я объявляю свойство @dynamic, чтобы CA мог создать средства доступа, переопределить +needsDisplayForKey: и реализовать -drawInContext:, чтобы передать текущее значение свойства sceneCenterPoint средству визуализации и попросить его отрендерить сцену: 1027 *

#import "GLLayer.h"

@implementation GLLayer

@synthesize renderer;
@dynamic sceneCenterPoint;

+ (BOOL) needsDisplayForKey:(NSString *)key
{
    if ([key isEqualToString:@"sceneCenterPoint"]) {
        return YES;
    } else {
        return [super needsDisplayForKey:key];
    }
}

- (void) drawInContext:(CGContextRef)ctx
{
    self.renderer.centerPoint = self.sceneCenterPoint;
    [self.renderer render];
}
...

(Если у вас есть доступ к видео сеанса WWDC 2009, вы можете просмотреть эту технику в сеансе 303 («Анимированный рисунок»)).

Теперь, когда я создаю явную анимацию для слоя на keyPath @"sceneCenterPoint", Core Animation должна вычислить интерполированные значения для пользовательских свойств и вызвать -drawInContext: для каждого шага анимации:

- (IBAction)animateButtonTapped:(id)sender
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sceneCenterPoint"];
    animation.duration = 1.0;
    animation.fromValue = [NSValue valueWithCGPoint:CGPointZero];
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0f, 1.0f)];
    [self.glView.layer addAnimation:animation forKey:nil];
}

По крайней мере, так будет с обычным CALayer подклассом. Когда я подкласс CAEAGLLayer, я получаю этот вывод на консоли для каждого шага анимации:

2010-12-21 13:59:22.180 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
2010-12-21 13:59:22.198 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
2010-12-21 13:59:22.216 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
2010-12-21 13:59:22.233 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
...

Так что, возможно, по соображениям производительности, для слоев OpenGL, -drawInContext: не вызывается, потому что эти слои не используют стандартный метод -display для рисования сами. Кто-нибудь может это подтвердить? Есть ли способ обойти это?

Или я не могу использовать технику, которую я изложил выше? Это означало бы, что мне придется реализовать анимацию вручную в рендерере OpenGL (что возможно, но не так элегантно, как в IMO).

Ответы [ 2 ]

6 голосов
/ 06 января 2011

Вы можете переопределить display вместо drawInContext. Во время анимации анимированное значение находится на уровне представления.

- (void) display
{
    GLLayer* myPresentationLayer = (GLLayer*)[self presentationLayer];
    self.renderer.centerPoint = myPresentationLayer.sceneCenterPoint;
    [self.renderer render];
}

В конце уровень представления будет иметь значение уровня модели, поэтому вам нужно будет установить конечное значение на уровне модели перед запуском анимации.

4 голосов
/ 27 декабря 2010

Вы пытались сделать родительский слой выше слоя OpenGL и анимировать его вместо этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...