学习OpenGL:笔记六

绘制一个圆柱体

使用代码绘制一个圆柱体。

分解圆柱体

先把圆柱体进行分解,可以看成上下两个圆和中间一个展开的矩形组成。

                                

 

我们可以将圆柱体看做三个几何体来绘制,绘制两个圆形和一个卷成桶状的矩形。我们将圆形半径定义为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 *)(&centerVertex);
 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];
}

 效果图如下

posted @ 2018-12-20 15:23  _NeverMore  阅读(376)  评论(0编辑  收藏  举报