2011-04-27 2 views
1

절차 적으로 생성 된 OpenGL ES 영역이 필요합니다. 나는 주위를 검색하고 this OGL code을 발견했으며이를 수정하여 깔끔하게 보였습니다. 대신 OGLES가되어야합니다. OGL 전용 glBegin(), glEnd()를 제거하고 원래 drawtri 및 drawsphere를 generatetri 및 generateSpherePoints로 수정했습니다. 이 새로운 함수는 구형 법선과 정점에 대한 정적 배열에 GLfloat 값을 할당합니다. 즉, 새로운 함수 drawSphere()를 호 출하며 점을 다시 계산할 필요가 없습니다. 또한 x, y, z 매개 변수를 generateSpherePoints에 추가하여 0이 아닌 구면 중심을 지정할 수있게했습니다.OpenGL ES (iOS) : glDrawArrays의 EXC_BAD_ACCESS가 구형 드로잉을 호출합니다.

문제는 내 OGLES 버전이 glDrawArrays 행에서 XCode의 EXC_BAD_ACCESS를 제공한다는 것입니다. 디버거를 통해 필자는 'sphereNormals'및 'sphereVertices'배열을 검사하고 원하는대로 잘 채워지는 것처럼 보입니다. 나는 누군가가 그 문제가 무엇인지를 제안 할 수 있다면 매우 감사 할 것입니다, 지금 당장 나는 단서가 없습니다!

#define SX .525731112119133606 
#define SZ .850650808352039932 

/* Drawing Sphere */ 
static GLfloat vdata[12][3] = {  
    {-SX, 0.0, SZ}, {SX, 0.0, SZ}, {-SX, 0.0, -SZ}, {SX, 0.0, -SZ},  
    {0.0, SZ, SX}, {0.0, SZ, -SX}, {0.0, -SZ, SX}, {0.0, -SZ, -SX},  
    {SZ, SX, 0.0}, {-SZ, SX, 0.0}, {SZ, -SX, 0.0}, {-SZ, -SX, 0.0} 
}; 

static GLuint tindices[20][3] = { 
    {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},  
    {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},  
    {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6}, 
    {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} }; 

void normalize(GLfloat *a) { 
    GLfloat d=sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]); 
    a[0]/=d; a[1]/=d; a[2]/=d; 
} 

static const int ndiv = 5; 
static const int vecSize = 3; 
static const int isoVertexCount = 3; 
static const int spherePointsSectionCount = 20; 
static const int pointSectionSize = 9216;// value MUST be updated to be result of calcPointSectionSize(ndiv) 
static const int pointCount = 184320;// value MUST be updated to be spherePointsSectionCount*pointSectionSize; 
static const int sphereVertsCount = 61440; // value MUST be updated to be pointCount/vecSize; 
static GLfloat spherePoints[184320]; // size MUST be updated to be pointCount value 
static GLfloat sphereNormals[184320]; // size MUST be updated to be pointCount value 

int calcPointSectionSize(int div) { 
    return vecSize*isoVertexCount*powf(4.0f,(float)(div)); 
} 

// OpenGL ES doesn't support glBegin(), glEnd() so must use glDrawArrays() instead 
void generatetri(GLfloat *a, GLfloat *b, GLfloat *c, int div, float r, int pos) { 
    if (div<=0) { 
     int X = 0, Y = 1, Z = 2; 
     sphereNormals[pos+X] = a[X]; 
     sphereNormals[pos+Y] = a[Y]; 
     sphereNormals[pos+Z] = a[Z]; 
     spherePoints[pos+X] = a[X]*r; 
     spherePoints[pos+Y] = a[Y]*r; 
     spherePoints[pos+Z] = a[Z]*r; 
     sphereNormals[pos+vecSize+X] = b[X]; 
     sphereNormals[pos+vecSize+Y] = b[Y]; 
     sphereNormals[pos+vecSize+Z] = b[Z]; 
     spherePoints[pos+vecSize+X] = b[X]*r; 
     spherePoints[pos+vecSize+Y] = b[Y]*r; 
     spherePoints[pos+vecSize+Z] = b[Z]*r; 
     sphereNormals[pos+2*vecSize+X] = c[X]; 
     sphereNormals[pos+2*vecSize+Y] = c[Y]; 
     sphereNormals[pos+2*vecSize+Z] = c[Z]; 
     spherePoints[pos+2*vecSize+X] = c[X]*r; 
     spherePoints[pos+2*vecSize+Y] = c[Y]*r; 
     spherePoints[pos+2*vecSize+Z] = c[Z]*r; 
     /* 
     glNormal3fv(a); glVertex3f(a[0]*r, a[1]*r, a[2]*r); 
     glNormal3fv(b); glVertex3f(b[0]*r, b[1]*r, b[2]*r); 
     glNormal3fv(c); glVertex3f(c[0]*r, c[1]*r, c[2]*r); 
     */ 
    } else { 
     GLfloat ab[3], ac[3], bc[3]; 
     for (int i=0;i<3;i++) { 
      ab[i]=(a[i]+b[i])/2; 
      ac[i]=(a[i]+c[i])/2; 
      bc[i]=(b[i]+c[i])/2; 
     } 
     normalize(ab); normalize(ac); normalize(bc); 
     const int pointSectionSize = calcPointSectionSize(div-1); 
     generatetri(a, ab, ac, div-1, r, pos+0*pointSectionSize); 
     generatetri(b, bc, ab, div-1, r, pos+1*pointSectionSize); 
     generatetri(c, ac, bc, div-1, r, pos+2*pointSectionSize); 
     generatetri(ab, bc, ac, div-1, r, pos+3*pointSectionSize); 
    } 
} 

void generateSpherePoints(float x, float y, float z, float radius) { 
    for (int i=0;i<20;i++) { 
     GLfloat *va = vdata[tindices[i][0]]; 
     GLfloat *vb = vdata[tindices[i][1]]; 
     GLfloat *vc = vdata[tindices[i][2]]; 
     GLfloat a[3] = {va[0]+x,va[1]+y,va[2]+z}; 
     GLfloat b[3] = {vb[0]+x,vb[1]+y,vb[2]+z}; 
     GLfloat c[3] = {vc[0]+x,vc[1]+y,vc[2]+z}; 
     generatetri(a, b, c, ndiv, radius, i*pointSectionSize); 
    } 
} 

void drawSphere() { 
    glEnableClientState(GL_NORMAL_ARRAY); 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glNormalPointer(GL_FLOAT, 0, sphereNormals); 
    glVertexPointer(3, GL_FLOAT, 0, spherePoints); 
    glDrawArrays(GL_TRIANGLES, 0, sphereVertsCount); 
    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_NORMAL_ARRAY); 
} 
+0

코드가 좋았습니다. 이미 테스트 한 것과 동일한 iOS 코드를 사용하는 것이 더 나을 것입니다. http://iphonedevelopment.blogspot.com/2009/05/procedural-spheres-in-opengl-es.html –

+0

감사합니다. 훌리오 (Julio) - OGL 코드에 대한 원래의 인터넷 검색 중 링크를 보았지만 성능이 떨어 졌다고 저자가 말한 이후로 피할 수있었습니다. 내가 가진 방식으로 포인트를 캐시하는 한 내가 사용하는 방법은 중요하지 않다고 생각합니다. 아래의 cduhn의 제안에 따라 NSZombie를 사용하여 문제를 사냥 할 것입니다. – KomodoDave

답변

0

EXC_BAD_ACCESS는 코드가 소유하지 않은 메모리 주소에 액세스하려고 시도하고 있음을 의미합니다. 이것의 가장 일반적인 원인은 메모리 관리 코드에서 오류가 발생하여 개체가 아직 사용 중일 때 할당이 해제됩니다. 예를 들어, 코드가 필요한 객체를 보유하지 못했거나 객체를 조기에 공개했을 수 있습니다.

이 경우, 사용자가 그리려는 뷰가 너무 일찍 할당 취소되었을 수 있습니다. 추측하기보다는 NSZombieEnabled 기능을 사용하여 코드가 액세스하려고 시도하는 할당 해제 된 객체를 파악해야합니다. iOS Development Guide section on Debugging Applications을 참조하십시오.

+0

Ack, 물론 - NSZombie는 전에도 여러 번 사용해 왔지만 이번에는 내 마음을 빼앗 겼습니다. 지적 해 주셔서 고맙습니다. Xcode에서의 수동 사양은 나쁜 아이디어입니다. 응용 프로그램을 배포 할 때 Xcode를 사용하지 않도록 설정하는 것을 잊어 버리면 성능에 큰 영향을 미치므로 Xcode 4에서 사용하는 올바른 방법은 실행 대신 프로필을 선택하는 것입니다. iOS 시뮬레이터 -> 모두 -> 좀비를 선택하십시오. 어쨌든, 나는 그것을 줄 것이고 그것이 문제를 확인하는지 볼 것입니다. – KomodoDave

+0

잘 알고 있습니다. 나는 Xcode 4 이후 그것을 사용하지 않았다. 팁 주셔서 감사. – cduhn