2009-04-08 2 views
3

기본적으로 3D 큐브를 그립니다. 회전 할 수는 있지만 터치 할 수 있고 큐브 표면에서 사용자가 터치 한 위치를 알고 싶을 수 있습니다.iPhone에서 AABB 레이 캐스트 히트 검사를 구현하는 방법

설정, 생성 및 회전에 사용하고 있습니다. 그것의 분자 코드와 NeHe 튜토리얼 # 5를 기반으로합니다.

모든 도움말, 링크, 자습서 및 코드는 크게 감사하겠습니다. 나는 많은 개발 경험을 가지고 있지만 openGL과 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 

답변

1

는 이러한 소스를 확인해야합니다, 확인을 누르 캐스트 :
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

는 기본적으로, 첫째, 2 차원 터치에서 3D 선을 만들 수 있습니다. 그런 다음 그 광선을 사용하여 세상의 물체와의 교차점을 확인하십시오. 현재 행렬의 역행렬을 만들어야하며, 역행렬에서 근거리 및 원거리 클립 평면을 사용하여 시작 및 끝 위치를 만들 수 있습니다. 근거리 및 원거리 점을 계산할 때 투영 설정을 적용해야합니다.

목표 : 내 프로젝트에서 내 포인트 인식은 레이 캐스트 히트 검사가 아닌 색상 고유 픽셀 비교를 기반으로합니다. 독특한 색을 찾는 것만으로 히트 체크를 구현하는 것이 훨씬 쉽습니다. 제안 만하면 도움이 되길 바랍니다. 건배,
Guvener

관련 문제