Объединение основной анимации с OpenGL ES

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

 : вызов -display не имеет никакого эффекта.  не называется). Вместо этого я получаю это консольное сообщение: 

 : вызов -display не имеет никакого эффекта.  не называется). Вместо этого я получаю это консольное сообщение: 

 : вызов -display не имеет никакого эффекта.

Есть ли способ обойти эту проблему? Могу ли я вызвать -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 рендереру и попросить его отобразить сцену:

#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] :
2010-12-21 13: 59: 22.198 CoreAnimationOpenGL [7496: 207] : вызов -display не имеет никакого эффекта.
2010-12-21 13: 59: 22.216 CoreAnimationOpenGL [7496: 207] : вызов -display не имеет никакого эффекта.
2010-12-21 13: 59: 22.233 CoreAnimationOpenGL [7496: 207] : вызов -display не имеет никакого эффекта.
...

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

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

11
задан Ole Begemann 21 December 2010 в 16:02
поделиться