绘制一个圆柱体
使用代码绘制一个圆柱体。
分解圆柱体
先把圆柱体进行分解,可以看成上下两个圆和中间一个展开的矩形组成。
我们可以将圆柱体看做三个几何体来绘制,绘制两个圆形和一个卷成桶状的矩形。我们将圆形半径定义为radius
,矩形高为height
,宽既是圆形的周长。
绘制圆形
圆形其实就是一个正n边形,n无穷大,可以采取多边形逼近的方式绘制圆形,比如我们可以构建一个正36边形来表示一个圆。利用这个原理来绘制圆。定义构成圆形的边数为sideCount
。
先定义一个点数据的结构体:
typedef struct { GLfloat x; GLfloat y; GLfloat z; GLfloat normalX; GLfloat normalY; GLfloat normalZ; GLfloat u; GLfloat v; } GLVertex;
圆柱体中心坐标 (0,0,0)圆柱体高是 height
圆柱体上下两个圆面的y坐标
float y1 = self.height / 2.0; float y2 = -self.height / 2.0;
绘制圆形的中心点坐标:
GLVertex centerVertex = GLVertexMake(0, y1, 0, 0, 1, 0, 0.5, 0.5);
把中心点数据加入顶点数据
void * pVertex = (void *)(¢erVertex); NSUInteger size = sizeof(GLVertex); [self.vertexData appendBytes:pVertex length:size];
把sideCount边形的每个点计算出来
for (int i = self.sideCount; i >= 0; --i) { GLfloat angle = i / (float)self.sideCount * M_PI * 2; GLVertex vertex = GLVertexMake(cos(angle) * self.radius, y1, sin(angle) * self.radius, 0, 1, 0, (cos(angle) + 1 ) / 2.0, (sin(angle) + 1 ) / 2.0); void * pVertex = (void *)(&vertex); NSUInteger size = sizeof(GLVertex); [self.vertexData appendBytes:pVertex length:size]; }
同理把下方的圆形顶点数据也计算出来。
绘制矩形
可以把中间的矩形看做self.sideCount
个矩形组成的几何体。只需要按照顺序依次追加顶点即可
float yUP = self.height / 2.0; float yDOWN = -self.height / 2.0; for (int i = 0; i <= self.sideCount; ++i) { GLfloat angle = i / (float)self.sideCount * M_PI * 2; GLKVector3 vertexNormal = GLKVector3Normalize(GLKVector3Make(cos(angle) * self.radius, 0, sin(angle) * self.radius)); GLVertex vertexUp = GLVertexMake(cos(angle) * self.radius, yUP, sin(angle) * self.radius, vertexNormal.x, vertexNormal.y, vertexNormal.z, i / (float)self.sideCount, 0); GLVertex vertexDown = GLVertexMake(cos(angle) * self.radius, yDOWN, sin(angle) * self.radius, vertexNormal.x, vertexNormal.y, vertexNormal.z, i / (float)self.sideCount, 1); void * pVertex1 = (void *)(&vertexDown); NSUInteger size = sizeof(GLVertex); [self.vertexData appendBytes:pVertex1 length:size]; void * pVertex2 = (void *)(&vertexDown); [self.vertexData appendBytes:pVertex2 length:size]; }
绘制圆柱体
- (void)draw:(GLContext *)glContext { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); [glContext setUniformMatrix4fv:@"modelMatrix" value:self.modelMatrix]; bool canInvert; GLKMatrix4 normalMatrix = GLKMatrix4InvertAndTranspose(self.modelMatrix, &canInvert); [glContext setUniformMatrix4fv:@"normalMatrix" value:canInvert ? normalMatrix : GLKMatrix4Identity]; [glContext bindTexture:self.diffuseTexture to:GL_TEXTURE0 uniformName:@"diffuseMap"]; [glContext drawGeometry:self.topCircle]; [glContext drawGeometry:self.bottomCircle]; [glContext drawGeometry:self.middleCylinder]; }
效果图如下