2011-04-27 126 views
1

我需要程序生成的OpenGL ES球體 - 我搜索並發現了this OGL code,並且認爲它看起來很整潔,所以我將它修改爲改爲OGLES。我刪除了僅OGL的glBegin(),glEnd()並將原始的drawtri和drawsphere修改爲generatetri和generateSpherePoints。這些新函數將GLfloat值分配給球體法線和頂點的靜態數組,這意味着我可以隨時調用一個新的函數drawSphere(),並且這些點不需要重新計算。我還添加了x,y,z參數來生成SpherePoints,從而允許指定非零球體中心。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 – 2011-04-27 19:43:14

+0

感謝Julio - 正如我在原始的OGL代碼搜索中看到的那個鏈接,但是由於作者聲明性能很差,所以避免了它。我想,只要我按照我的方式緩存點,我使用哪種方法並不重要。我將根據下面的cduhn的建議,使用NSZombie來尋找問題。 – KomodoDave 2011-04-27 22:54:35

回答

0

EXC_BAD_ACCESS表示您的代碼嘗試訪問它不擁有的內存地址。造成這種情況的最常見原因是內存管理代碼中的一個錯誤,它導致對象在仍處於使用狀態時被釋放。例如,你的代碼可能沒有保留它需要的對象,或者它可能過早地釋放了一個對象。

在這種情況下,我猜想你正在繪製的視圖可能已被過早釋放。但是不要猜測,你應該使用NSZombieEnabled工具來確定代碼試圖訪問哪個釋放對象。請參閱iOS Development Guide section on Debugging Applications

+0

Ack,當然 - NSZombie這次雖然我已經使用過幾次,但是謝謝指出它。值得注意的是,在XCode中手動指定它是一個壞主意,因爲如果在部署應用程序時忘記禁用它,則會對性能產生顯着影響 - 在Xcode 4中使用它的正確方法是選擇Profile而不是Run,然後選擇iOS模擬器 - >全部 - >殭屍。無論如何,我會試一試,看看它是否能夠識別問題。 – KomodoDave 2011-04-27 22:53:21

+0

很高興知道。自從Xcode 4以來,我一直沒有使用它。感謝您的提示。 – cduhn 2011-04-28 02:13:04