2009-04-08 7 views
3

Fondamentalement, je dessine un cube 3D, je peux le faire tourner mais je veux pouvoir le toucher et savoir où sur la surface de mon cube l'utilisateur a touché. J'utilise pour configurer, générer et tourner. Il est basé sur le code Molecules et NeHe tutorial # 5.Comment implémenter la vérification de jet de rayon AABB sur l'iPhone

Toute aide, liens, tutoriels et code seraient grandement appréciés. J'ai beaucoup d'expérience en développement, mais rien de bien sur OpenGL et 3D.

// 
// GLViewController.h 
// NeHe Lesson 05 
// 
// Created by Jeff LaMarche on 12/12/08. 
// Copyright Jeff LaMarche Consulting 2008. All rights reserved. 
// 

#import "GLViewController.h" 
#import "GLView.h" 

@implementation GLViewController 
- (void)drawBox 
{ 
    static const GLfloat cubeVertices[] = { 
     -1.0f, 1.0f, 1.0f, 
     1.0f, 1.0f, 1.0f, 
     1.0f,-1.0f, 1.0f, 
     -1.0f,-1.0f, 1.0f, 
     -1.0f, 1.0f,-1.0f, 
     1.0f, 1.0f,-1.0f, 
     1.0f,-1.0f,-1.0f, 
     -1.0f,-1.0f,-1.0f 
    }; 
    static const GLubyte cubeNumberOfIndices = 36; 

    const GLubyte cubeVertexFaces[] = { 
     0, 1, 5, // Half of top face 
     0, 5, 4, // Other half of top face 

     4, 6, 5, // Half of front face 
     4, 6, 7, // Other half of front face 

     0, 1, 2, // Half of back face 
     0, 3, 2, // Other half of back face 

     1, 2, 5, // Half of right face 
     2, 5, 6, // Other half of right face 

     0, 3, 4, // Half of left face 
     7, 4, 3, // Other half of left face 

     3, 6, 2, // Half of bottom face 
     6, 7, 3, // Other half of bottom face 

    }; 
    const GLubyte cubeFaceColors[] = { 
     0, 255, 0, 255, 
     255, 125, 0, 255, 
     255, 0, 0, 255, 
     255, 255, 0, 255, 
     0, 0, 255, 255, 
     255, 0, 255, 255 
    }; 


    glEnableClientState(GL_VERTEX_ARRAY); 

    glVertexPointer(3, GL_FLOAT, 0, cubeVertices); 
    int colorIndex = 0; 
    for(int i = 0; i < cubeNumberOfIndices; i += 3) 
    { 
     glColor4ub(cubeFaceColors[colorIndex], cubeFaceColors[colorIndex+1], cubeFaceColors[colorIndex+2], cubeFaceColors[colorIndex+3]); 
     int face = (i/3.0); 
     if (face%2 != 0.0) 
      colorIndex+=4; 

     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &cubeVertexFaces[i]); 
    } 

    glDisableClientState(GL_VERTEX_ARRAY); 
} 

//move this to a data model later! 
- (GLfixed)floatToFixed:(GLfloat)aValue; 
{ 
    return (GLfixed) (aValue * 65536.0f); 
} 

- (void)drawViewByRotatingAroundX:(float)xRotation rotatingAroundY:(float)yRotation scaling:(float)scaleFactor translationInX:(float)xTranslation translationInY:(float)yTranslation view:(GLView*)view; 
{ 
    glMatrixMode(GL_MODELVIEW); 
    GLfixed currentModelViewMatrix[16] = { 45146, 47441, 2485, 0, 
              -25149, 26775,-54274, 0, 
              -40303, 36435, 36650, 0, 
                0, 0,  0, 65536 }; 
    /* 
    GLfixed currentModelViewMatrix[16] = { 0, 0, 0, 0, 
              0, 0, 0, 0, 
              0, 0, 0, 0, 
              0, 0, 0, 65536 }; 
    */ 
    //glLoadIdentity(); 
    //glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -10.0f, 4.0f); 

    // Reset rotation system 
    if (isFirstDrawing) 
    { 
     //glLoadIdentity(); 
     glMultMatrixx(currentModelViewMatrix); 
     [self configureLighting]; 
     isFirstDrawing = NO; 
    } 

    // Scale the view to fit current multitouch scaling 
    GLfixed fixedPointScaleFactor = [self floatToFixed:scaleFactor]; 
    glScalex(fixedPointScaleFactor, fixedPointScaleFactor, fixedPointScaleFactor);  

    // Perform incremental rotation based on current angles in X and Y 
    glGetFixedv(GL_MODELVIEW_MATRIX, currentModelViewMatrix); 

    GLfloat totalRotation = sqrt(xRotation*xRotation + yRotation*yRotation); 

    glRotatex([self floatToFixed:totalRotation], 
       (GLfixed)((xRotation/totalRotation) * (GLfloat)currentModelViewMatrix[1] + (yRotation/totalRotation) * (GLfloat)currentModelViewMatrix[0]), 
       (GLfixed)((xRotation/totalRotation) * (GLfloat)currentModelViewMatrix[5] + (yRotation/totalRotation) * (GLfloat)currentModelViewMatrix[4]), 
       (GLfixed)((xRotation/totalRotation) * (GLfloat)currentModelViewMatrix[9] + (yRotation/totalRotation) * (GLfloat)currentModelViewMatrix[8]) 
      ); 

    // Translate the model by the accumulated amount 
    glGetFixedv(GL_MODELVIEW_MATRIX, currentModelViewMatrix); 
    float currentScaleFactor = sqrt(pow((GLfloat)currentModelViewMatrix[0]/65536.0f, 2.0f) + pow((GLfloat)currentModelViewMatrix[1]/65536.0f, 2.0f) + pow((GLfloat)currentModelViewMatrix[2]/65536.0f, 2.0f));  

    xTranslation = xTranslation/(currentScaleFactor * currentScaleFactor); 
    yTranslation = yTranslation/(currentScaleFactor * currentScaleFactor); 
    // Grab the current model matrix, and use the (0,4,8) components to figure the eye's X axis in the model coordinate system, translate along that 
    glTranslatef(xTranslation * (GLfloat)currentModelViewMatrix[0]/65536.0f, xTranslation * (GLfloat)currentModelViewMatrix[4]/65536.0f, xTranslation * (GLfloat)currentModelViewMatrix[8]/65536.0f); 
    // Grab the current model matrix, and use the (1,5,9) components to figure the eye's Y axis in the model coordinate system, translate along that 
    glTranslatef(yTranslation * (GLfloat)currentModelViewMatrix[1]/65536.0f, yTranslation * (GLfloat)currentModelViewMatrix[5]/65536.0f, yTranslation * (GLfloat)currentModelViewMatrix[9]/65536.0f); 

    // Black background, with depth buffer enabled 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    [self drawBox]; 
} 

- (void)configureLighting; 
{ 
    const GLfixed   lightAmbient[] = {13107, 13107, 13107, 65535}; 
    const GLfixed   lightDiffuse[] = {65535, 65535, 65535, 65535}; 
    const GLfixed   matAmbient[] = {65535, 65535, 65535, 65535}; 
    const GLfixed   matDiffuse[] = {65535, 65535, 65535, 65535};  
    const GLfixed   lightPosition[] = {30535, -30535, 0, 0}; 
    const GLfixed   lightShininess = 20;  

    glEnable(GL_LIGHTING); 
    glEnable(GL_LIGHT0); 
    glEnable(GL_COLOR_MATERIAL); 
    glMaterialxv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient); 
    glMaterialxv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse); 
    glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, lightShininess); 
    glLightxv(GL_LIGHT0, GL_AMBIENT, lightAmbient); 
    glLightxv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); 
    glLightxv(GL_LIGHT0, GL_POSITION, lightPosition);  

    glEnable(GL_DEPTH_TEST); 

    glShadeModel(GL_SMOOTH); 
    glEnable(GL_NORMALIZE);   
} 

-(void)setupView:(GLView*)view 
{ 
    const GLfloat zNear = 0.1, 
    zFar = 1000.0, 
    fieldOfView = 60.0; 
    GLfloat size; 

    glMatrixMode(GL_PROJECTION); 
    glEnable(GL_DEPTH_TEST); 
    size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView)/2.0); 
    CGRect rect = view.bounds; 
    glFrustumf(-size, size, -size/(rect.size.width/rect.size.height), size/
       (rect.size.width/rect.size.height), zNear, zFar); 
    glViewport(0, 0, rect.size.width, rect.size.height); 
    glScissor(0, 0, rect.size.width, rect.size.height); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 

    glTranslatef(0.0f, 0.0f, -6.0f); 
    isFirstDrawing = YES; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
} 

- (void)dealloc 
{ 
    [super dealloc]; 
} 

@end 

Répondre

1

Afin de mettre en œuvre Ray CAST vérification a frappé, vous devriez vérifier ces sources:
http://www.mvps.org/directx/articles/rayproj.htm
http://bookofhook.com/mousepick.pdf
http://eigenclass.blogspot.com/2008/10/opengl-es-picking-using-ray-boundingbox.html

Fondamentalement, tout d'abord, créez un rayon 3D à partir d'une touche 2D. Ensuite, utilisez ce rayon pour vérifier l'intersection avec les objets de votre monde. Vous devez créer l'inverse matriciel de votre matrice actuelle, et à partir de la matrice inverse, vous pouvez créer des positions de début et de fin en utilisant votre plan de plan rapproché et lointain. puis, lors du calcul des points proches et lointains, vous devez appliquer les paramètres de projection. BTW: Dans mon projet, la reconnaissance de mon point est basée sur la comparaison de pixels uniques couleur plutôt que sur la vérification de jet de rayons. Il est beaucoup plus facile de mettre en œuvre un contrôle de frappe avec simplement trouver des couleurs uniques. Seulement une suggestion, j'espère que ça aide :) acclamations,
Guvener

Questions connexes