2012-12-19 3 views
0

J'ai sous-classé un GLKView et je voudrais le faire pivoter autour de l'axe des x. J'ai essayé d'appliquer la méthode dans le tutoriel de Raywenderlich, sans résultats. La différence est que j'ai un GLKView et qu'il arrive à tout faire avec un GLKViewController (+ son délégué). Donc je n'ai pas la méthode de mise à jour du délégué etc. etc. Je n'ai presque pas eu d'expérience avec OpenGL (je débute), donc j'espère rencontrer des lumières ici.Comment faire pivoter un GLKView autour de l'axe x?

ViewController.m

EAGLContext * context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 
    BlogCell *view = [[BlogCell alloc] initWithFrame:CGRectMake(0, 200, 320, 80) context:context]; 
    view.drawableMultisample = GLKViewDrawableMultisample4X; 
    view.context = context; 
    view.delegate = view; 
    [view setupGL]; 
    [self.view addSubview:view]; 

MyGLKViewSubclass.m

- (void)setupGL { 

    [EAGLContext setCurrentContext:self.context]; 
    glEnable(GL_CULL_FACE); 


    self.effect = [[GLKBaseEffect alloc] init]; 

    NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithBool:YES], 
           GLKTextureLoaderOriginBottomLeft, 
           nil]; 

    NSError * error; 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"]; 
    GLKTextureInfo * info = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error]; 
    if (info == nil) { 
     NSLog(@"Error loading file: %@", [error localizedDescription]); 
    } 
    self.effect.texture2d0.name = info.name; 
    self.effect.texture2d0.enabled = true; 

    glGenVertexArraysOES(1, &vertexArray); 
    glBindVertexArrayOES(vertexArray); 

    glGenBuffers(1, &vertexBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 


    glGenBuffers(1, &indexBuffer); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW); 

    glEnableVertexAttribArray(GLKVertexAttribColor); 
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Color)); 


    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition, 
          3,   
          GL_FLOAT, 
          GL_FALSE,  
          sizeof(Vertex), 
          (const GLvoid *) offsetof(Vertex, Position) 
         ); 

    glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, TexCoord)); 


    glBindVertexArrayOES(0); 

    rotMatrix = GLKMatrix4Identity; 

} 




- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { 

    self.contentScaleFactor = 2.0; 
    self.opaque = NO; 
    self.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 

    glClear(GL_COLOR_BUFFER_BIT); 

    [self.effect prepareToDraw]; 

    glBindVertexArrayOES(vertexArray); 
    glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0); 


} 

C'est là que je voudrais tourner mon objet

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 

    UITouch * touch = [touches anyObject]; 
    CGPoint location = [touch locationInView:[touch view]]; 
    CGPoint lastLoc = [touch previousLocationInView:[touch view]]; 
    CGPoint diff = CGPointMake(lastLoc.x - location.x, lastLoc.y - location.y); 

    float rotX = -1 * GLKMathDegreesToRadians(diff.y/2.0); 
    float rotY = -1 * GLKMathDegreesToRadians(diff.x/2.0); 

    GLKVector3 xAxis = GLKVector3Make(1, 0, 0); 
    rotMatrix = GLKMatrix4Rotate(rotMatrix, rotX, xAxis.x, xAxis.y, xAxis.z); 
    GLKVector3 yAxis = GLKVector3Make(0, 1, 0); 
    rotMatrix = GLKMatrix4Rotate(rotMatrix, rotY, yAxis.x, yAxis.y, yAxis.z); 
    [self update]; 

} 

Répondre

0

Vous ne semblez avoir rien pour exécuter votre boucle de tirage. Mettez dans votre viewDidLoad:

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)]; 
displayLink.frameInterval = 2; 
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

Définir DisplayLink comme une propriété dans votre tête et changer le @selector (rendre :) à votre fonction de rendu (ne marche pas doivent être que glkview un puisque vous n'utilisez pas un GLKViewController).

+0

Nous vous remercions de votre réponse. J'ai essayé votre code, malheureusement en vain. Ce qui fonctionne pour moi utilise '[self display]' chaque fois que j'ai besoin que mon GLKView soit redessiné. En passant, je place le délégué dans GLKView lui-même, donc sa méthode déléguée sera appelée quand j'appelle la méthode 'display'. Est-ce une mauvaise approche? –

+0

La boucle d'exécution displayLink correspond à la même boucle d'exécution que celle fournie par la combinaison GLKViewController/GLKView. Avec CADisplayLink, vous avez une vue granulaire du nombre de cycles qui se sont produits depuis la dernière actualisation; mais, cette information est sans importance pour tous ceux que je connais. Avec GLKViewController, je peux définir le nombre d'images par seconde pour une vidéo donnée; les vidéos lues à 15 ips n'ont pas besoin d'être restituées à 60 ips. Être capable de réduire le fps fait pour une application plus vive que sans. –

0

Il y a quatre exigences pour faire tourner un GLKView: 1. Code lié Rotation-doit être placé à l'intérieur du contrôleur de vue 2. 90 ° doit être ajouté à la rotation pour l'orientation paysage 3. code lié à la rotation doit être d'une enfermé dans un bloc d'animation UIView 4. les degrés doivent être exprimés en radians, et comme un nombre négatif

Voici le code je, avec succès:

dans le fichier de mise en œuvre de GLKViewController (.m):

static inline double radians (double degrees) { return degrees * M_PI/180; } 

. . .

if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) || (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))) { 
    [UIView animateWithDuration:0.0 animations:^{ 
     ((PlayerView *)self.view).transform = CGAffineTransformMakeRotation(radians(-90.0)); 
     ((PlayerView *)self.view).frame = [[UIScreen mainScreen] bounds]; 
    } completion:^(BOOL finished) { }]; 
} else if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) || (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))) { 
    [UIView animateWithDuration:0.0 animations:^{ 
     ((PlayerView *)self.view).transform = CGAffineTransformMakeRotation(radians(-180.0)); 
     ((PlayerView *)self.view).frame = [[UIScreen mainScreen] bounds]; 
    } completion:^(BOOL finished) { }]; 
} else { 
    NSLog(@"--------------------------- orientation could not be determined"); 
} 

Ces exigences peuvent sembler un peu suspectes; mais, je vous garantis que vous ne le ferez pas tourner autrement, et maintenez la cohérence à toutes les orientations et tous les aspects.

0

Encore mieux que de faire pivoter la vue pour faire pivoter les coordonnées quadratiques; Bien que cela ne soit pas démontré dans les exemples de code ou de documentation d'Apple, leur documentation recommande de faire tourner la sortie en faisant tourner le GLKView.

Voici toutes les permutations pour les paramètres de coordonnées texture quad:

static const GLfloat noRotationTextureCoordinates[] = { 
    0.0f, 0.0f, 
    1.0f, 0.0f, 
    0.0f, 1.0f, 
    1.0f, 1.0f, 
}; 

static const GLfloat rotateLeftTextureCoordinates[] = { 
    1.0f, 0.0f, 
    1.0f, 1.0f, 
    0.0f, 0.0f, 
    0.0f, 1.0f, 
}; 

static const GLfloat rotateRightTextureCoordinates[] = { 
    0.0f, 1.0f, 
    0.0f, 0.0f, 
    1.0f, 1.0f, 
    1.0f, 0.0f, 
}; 

static const GLfloat verticalFlipTextureCoordinates[] = { 
    0.0f, 1.0f, 
    1.0f, 1.0f, 
    0.0f, 0.0f, 
    1.0f, 0.0f, 
}; 

static const GLfloat horizontalFlipTextureCoordinates[] = { 
    1.0f, 0.0f, 
    0.0f, 0.0f, 
    1.0f, 1.0f, 
    0.0f, 1.0f, 
}; 

static const GLfloat rotateRightVerticalFlipTextureCoordinates[] = { 
    0.0f, 0.0f, 
    0.0f, 1.0f, 
    1.0f, 0.0f, 
    1.0f, 1.0f, 
}; 

static const GLfloat rotateRightHorizontalFlipTextureCoordinates[] = { 
    1.0f, 1.0f, 
    1.0f, 0.0f, 
    0.0f, 1.0f, 
    0.0f, 0.0f, 
}; 

static const GLfloat rotate180TextureCoordinates[] = { 
    1.0f, 1.0f, 
    0.0f, 1.0f, 
    1.0f, 0.0f, 
    0.0f, 0.0f, 
}; 

Pour utiliser ce dans le GLKView utilisé dans leur AVBasicVideo ...exemple d'application, par exemple:

  1. Utilisation self.bounds.size au lieu du self.presentationRect.size afin que votre sortie remplisse tout l'écran quelle que soit sa rotation:

    CGRect vertexSamplingRect = AVMakeRectWithAspectRatioInsideRect(self.bounds.size, self.eaglLayer.bounds); 
    
  2. Pour une valeur de 1,0, l'utilisation maximum; pour 0.0, utilisez min;

    GLfloat quadTextureData [] = { CGRectGetMaxX (textureSamplingRect), CGRectGetMinY (textureSamplingRect), CGRectGetMaxX (textureSamplingRect), CGRectGetMaxY (textureSamplingRect), CGRectGetMinX (textureSamplingRect), CGRectGetMinY (textureSamplingRect), CGRectGetMinX (textureSamplingRect), CGRectGetMaxY (textureSamplingRect) };

Questions connexes