//
//  GLDrawViewController.m
//  QMapKitDemo
//
//  Created by Keith Cao on 2020/4/21.
//  Copyright © 2020 tencent. All rights reserved.
//

#import "GLDrawViewController.h"
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <GLKit/GLKit.h>

const GLuint totalVertexCount = 8;  //总顶点数
const GLuint indexCount       = 36; //索引数

const float kEdgeLength  = 100; // 边长

@interface GLDrawViewController ()
{
    float _vertext[totalVertexCount * 3];
    short _indecies[indexCount];
    float _color[totalVertexCount * 4];
    
    float _scale[16];

    NSUInteger _cubePointCount;
    
    GLuint _program;
    GLuint _vertexLocation;
    GLuint _indicesLocation;
    GLuint _colorLocation;
    
    GLuint _viewMatrixLocation;
    GLuint _projectionMatrixLocation;
    GLuint _scaleMatrixLocation;
}

@property CLLocationCoordinate2D cubeCenter;

@end

@implementation GLDrawViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.mapView.zoomLevel = 20;
	
	self.mapView.overlooking = 40;
    
    self.mapView.centerCoordinate = CLLocationCoordinate2DMake(39.984889,116.307465);
    self.cubeCenter = CLLocationCoordinate2DMake(39.984889,116.307465);
}

// 地图渲染每一帧过程中都会调用此接口
- (void)mapViewDrawFrame:(QMapView *)mapView
{
    [self drawCube];
}

#pragma mark -

- (void)drawCube
{
    if (_program == 0) {
        [self initShader];
        [self initVertext];
    }
    
    // 显示屏幕point宽度时需要乘以此scale
    float scalePerPoint = [self.mapView glPointRatio];
    
    GLboolean depthMask = 0;
    glGetBooleanv(GL_DEPTH_WRITEMASK,&depthMask);
    
    glUseProgram(_program);
    
    glEnable(GL_DEPTH_TEST);
    if (depthMask == GL_FALSE) {
        glDepthMask(GL_TRUE);
    }
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glEnableVertexAttribArray(_vertexLocation);
    glVertexAttribPointer(_vertexLocation, 3, GL_FLOAT, false, 0, _vertext);
    
    glEnableVertexAttribArray(_colorLocation);
    glVertexAttribPointer(_colorLocation, 4, GL_FLOAT, false, 0, _color);

    // 当前地图view矩阵
    float * map_viewMatrix = [self.mapView glViewMatrix];
    
    // 当前地图projection矩阵
    float * map_projectionMatrix = [self.mapView glProjectionMatrix];
    float viewMatrix[16], projectionMatrix[16];
    
    GLKMatrix4 pm = GLKMatrix4MakeWithArray(map_projectionMatrix);
    
    GLKMatrix4 vm = GLKMatrix4MakeWithArray(map_viewMatrix);
    
    // 当前级别下的像素宽
    GLKMatrix4 sm = GLKMatrix4MakeScale(scalePerPoint, scalePerPoint, scalePerPoint);

    for (int i = 0; i < 16; i++)
    {
        viewMatrix[i] = vm.m[i];
        projectionMatrix[i] = pm.m[i];
        // 当前级别下的像素宽
        _scale[i] = sm.m[i];
    }
    
    glUniformMatrix4fv(_scaleMatrixLocation, 1, false, _scale);
    
    glUniformMatrix4fv(_viewMatrixLocation, 1, false, viewMatrix);
    
    glUniformMatrix4fv(_projectionMatrixLocation, 1, false, projectionMatrix);
    
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, _indecies);
    
    glDisableVertexAttribArray(_vertexLocation);
    
    glDisableVertexAttribArray(_colorLocation);
    
    GLenum err = glGetError();
    assert(err == GL_NO_ERROR) ;
    
    glDisable(GL_DEPTH_TEST);
    glDepthMask(depthMask);
    
}

- (void)initShader
{
    NSString *vertexShader = @"precision highp float;\n\
    attribute vec3 qVertex;\n\
    attribute vec4 qColor;\n\
    uniform mat4 qViewMatrix;\n\
    uniform mat4 qProjectionMatrix;\n\
    uniform mat4 qTransformMatrix;\n\
    uniform mat4 qScaleMatrix;\n\
    varying vec4 color;\n\
    void main(){\n\
    gl_Position = qProjectionMatrix * qViewMatrix * qScaleMatrix * vec4(qVertex, 1.0);\n\
    color = qColor;\n\
    }";
    
    NSString *fragmentShader = @"\n\
    precision highp float;\n\
    varying vec4 color;\n\
    void main(){\n\
    gl_FragColor = color;\n\
    }";
    
    
    _program = glCreateProgram();
    
    GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
    
    GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
    
    GLint vlength = (GLint)[vertexShader length];
    
    GLint flength = (GLint)[fragmentShader length];
    
    
    const GLchar *vByte = [vertexShader UTF8String];
    const GLchar *fByte = [fragmentShader UTF8String];
    
    glShaderSource(vShader, 1, &vByte, &vlength);
    
    glShaderSource(fShader, 1, &fByte, &flength);
    
    glCompileShader(vShader);
    
    glCompileShader(fShader);
    
    glAttachShader(_program, vShader);
    
    glAttachShader(_program, fShader);
    
    glLinkProgram(_program);
    
    _vertexLocation  = glGetAttribLocation(_program, "qVertex");
    
    
    _viewMatrixLocation = glGetUniformLocation(_program,"qViewMatrix");
    
    
    _projectionMatrixLocation = glGetUniformLocation(_program,"qProjectionMatrix");
    
    
    _scaleMatrixLocation = glGetUniformLocation(_program, "qScaleMatrix");
    
    _colorLocation = glGetAttribLocation(_program,"qColor");
    
}

- (void)initVertext
{
    /* 创建vertex。 */
    float vertext[] = {
        0.0, 0.0, 0.0,
        1.0, 0.0, 0.0,
        1.0,  1.0, 0.0,
        0.0,  1.0, 0.0,
        0.0, 0.0,  1.0,
        1.0, 0.0,  1.0,
        1.0,  1.0,  1.0,
        0.0,  1.0,  1.0,
    };
    
    for (int i = 0; i < 24; i++) {
        _vertext[i] = vertext[i] * kEdgeLength;
    }
    
    short indices[] = {
        0, 4, 5,
        0, 5, 1,
        1, 5, 6,
        1, 6, 2,
        2, 6, 7,
        2, 7, 3,
        3, 7, 4,
        3, 4, 0,
        4, 7, 6,
        4, 6, 5,
        3, 0, 1,
        3, 1, 2,
    };
    
    for (int i = 0; i < 36; i++) {
        _indecies[i] = indices[i];
    }
    
    float colors[] = {
        1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 red
        0.0f, 1.0f, 0.0f, 1.0f, // vertex 1 green
        0.0f, 0.0f, 1.0f, 1.0f, // vertex 2 blue
        1.0f, 1.0f, 0.0f, 1.0f, // vertex 3
        0.0f, 1.0f, 1.0f, 1.0f, // vertex 4
        1.0f, 0.0f, 1.0f, 1.0f, // vertex 5
        0.3f, 0.3f, 0.3f, 1.0f, // vertex 6
        1.0f, 1.0f, 1.0f, 1.0f, // vertex 7
    };
    
    for (int i = 0; i < 32; i++) {
        _color[i] = colors[i];
    }
    
    float scale[] = {
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f
    };
    
    for (int i = 0; i < 16; i++) {
        _scale[i] = scale[i];
    }
}
@end
