• 学习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];
    }
    

     效果图如下

  • 相关阅读:
    转【程序员七问】
    【转】又一次线上 OOM 排查经过
    【转】java:多网卡环境下获取MAC地址
    eclipse 国际化 $NON-NLS-1$ 含义
    eclipse 重构代码自动抽取函数
    转:GEF 英文全称Graphical Editor Framework
    转:Eclipse使用Git图解教程
    转:Java通过百度地图API获取地址经纬度
    转:Lucene学习——IKAnalyzer中文分词(一)
    转:Maven项目中获取classpath和资源文件的路径
  • 原文地址:https://www.cnblogs.com/neverMore-face/p/10149605.html
Copyright © 2020-2023  润新知