328 lines
10 KiB
Objective-C
328 lines
10 KiB
Objective-C
//
|
|
// MATraceReplayOverlayRender.m
|
|
// MAMapKit
|
|
//
|
|
// Created by shaobin on 2017/4/20.
|
|
// Copyright © 2017年 Amap. All rights reserved.
|
|
//
|
|
|
|
#import "MATraceReplayOverlayRender.h"
|
|
#import "MATraceReplayOverlay.h"
|
|
#import "MATraceReplayOverlay+Addition.h"
|
|
#import <GLKit/GLKit.h>
|
|
#import <OpenGLES/ES2/gl.h>
|
|
#import <DDCategoryKit_Private/UIImage+DDCategory.h>
|
|
|
|
typedef struct _MADrawPoint {
|
|
float x;
|
|
float y;
|
|
} MADrawPoint;
|
|
|
|
@interface MATraceReplayOverlayRenderer () {
|
|
MAMultiColoredPolylineRenderer *_proxyRender;
|
|
NSTimeInterval _prevTime;
|
|
|
|
MAPolylineRenderer *_patchLineRender;
|
|
|
|
CGPoint _imageMapPoints[4];
|
|
GLuint _textureName;
|
|
GLuint _programe;
|
|
GLuint _uniform_viewMatrix_location;
|
|
GLuint _uniform_projMatrix_location;
|
|
GLuint _attribute_position_location;
|
|
GLuint _attribute_texCoord_location;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation MATraceReplayOverlayRenderer
|
|
|
|
- (id)initWithOverlay:(id<MAOverlay>)overlay {
|
|
if(![overlay isKindOfClass:[MATraceReplayOverlay class]]) {
|
|
return nil;
|
|
}
|
|
|
|
self = [super initWithOverlay:overlay];
|
|
if(self) {
|
|
MATraceReplayOverlay *traceOverlay = (MATraceReplayOverlay*)overlay;
|
|
_proxyRender = [[MAMultiColoredPolylineRenderer alloc] initWithMultiPolyline:[traceOverlay getMultiPolyline]];
|
|
_proxyRender.gradient = NO;
|
|
_proxyRender.strokeColors = @[[UIColor grayColor], [UIColor greenColor]];
|
|
_proxyRender.strokeColor = _proxyRender.strokeColors.lastObject;
|
|
|
|
_patchLineRender = [[MAPolylineRenderer alloc] initWithPolyline:[traceOverlay getPatchPolyline]];
|
|
_patchLineRender.strokeColor = _proxyRender.strokeColors.lastObject;
|
|
|
|
_carImage = [UIImage dd_imageNamed:@"DDMAMap/my_location" bundleName:@"DDMAMapKit_Private" aClass:[self class]];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
if(_textureName) {
|
|
glDeleteTextures(1, &_textureName);
|
|
_textureName = 0;
|
|
}
|
|
}
|
|
|
|
- (void)glRender
|
|
{
|
|
MATraceReplayOverlay *traceOverlay = (MATraceReplayOverlay*)self.overlay;
|
|
|
|
CGFloat zoomLevel = [self getMapZoomLevel];
|
|
if(_prevTime == 0) {
|
|
_prevTime = CFAbsoluteTimeGetCurrent();
|
|
[traceOverlay drawStepWithTime:0 zoomLevel:zoomLevel];
|
|
} else {
|
|
NSTimeInterval curTime = CFAbsoluteTimeGetCurrent();
|
|
[traceOverlay drawStepWithTime:curTime - _prevTime zoomLevel:zoomLevel];
|
|
_prevTime = curTime;
|
|
}
|
|
|
|
if(self.carImage && [traceOverlay getMultiPolyline].pointCount > 0) {
|
|
[_proxyRender glRender];
|
|
[_patchLineRender glRender];
|
|
|
|
[self renderCarImage];
|
|
} else {
|
|
[_proxyRender glRender];
|
|
}
|
|
}
|
|
|
|
- (void)setRendererDelegate:(id<MAOverlayRenderDelegate>)rendererDelegate {
|
|
[super setRendererDelegate:rendererDelegate];
|
|
_proxyRender.rendererDelegate = rendererDelegate;
|
|
_patchLineRender.rendererDelegate = rendererDelegate;
|
|
}
|
|
|
|
- (void)setLineWidth:(CGFloat)lineWidth {
|
|
[super setLineWidth:lineWidth];
|
|
_proxyRender.lineWidth = lineWidth;
|
|
_patchLineRender.lineWidth = lineWidth;
|
|
}
|
|
|
|
- (void)setStrokeColors:(NSArray *)strokeColors {
|
|
if(strokeColors.count != 2) {
|
|
return;
|
|
}
|
|
_proxyRender.strokeColors = strokeColors;
|
|
|
|
if(strokeColors.count > 0) {
|
|
_proxyRender.strokeColor = strokeColors.lastObject;
|
|
_patchLineRender.strokeColor = strokeColors.lastObject;
|
|
}
|
|
}
|
|
|
|
- (NSArray *)strokeColors {
|
|
return _proxyRender.strokeColors;
|
|
}
|
|
|
|
- (void)setStrokeColor:(UIColor *)strokeColor {
|
|
[super setStrokeColor:strokeColor];
|
|
[_proxyRender setStrokeColor:strokeColor];
|
|
[_patchLineRender setStrokeColor:strokeColor];
|
|
}
|
|
|
|
- (UIColor *)strokeColor {
|
|
return _proxyRender.strokeColor;
|
|
}
|
|
|
|
- (void)reset {
|
|
_prevTime = 0;
|
|
}
|
|
|
|
- (void)renderCarImage {
|
|
if(_textureName == 0) {
|
|
NSError *error = nil;
|
|
GLKTextureInfo *texInfo = [GLKTextureLoader textureWithCGImage:self.carImage.CGImage options:nil error:&error];
|
|
_textureName = texInfo.name;
|
|
}
|
|
|
|
if(_programe == 0) {
|
|
_programe = [self loadGLESPrograme];
|
|
}
|
|
|
|
if(_textureName == 0 || _programe == 0) {
|
|
return;
|
|
}
|
|
|
|
MATraceReplayOverlay *traceOverlay = (MATraceReplayOverlay*)self.overlay;
|
|
MAMapPoint carPoint = [traceOverlay getCarPosition];
|
|
CLLocationDirection rotate = [traceOverlay getRunningDirection];
|
|
|
|
double zoomLevel = [self getMapZoomLevel];
|
|
double zoomScale = pow(2, zoomLevel);
|
|
|
|
CGSize imageSize = self.carImage.size;
|
|
|
|
double halfWidth = imageSize.width * (1 << 20) / zoomScale/2;
|
|
double halfHeight = imageSize.height * (1 << 20) / zoomScale/2;
|
|
|
|
_imageMapPoints[0].x = -halfWidth;
|
|
_imageMapPoints[0].y = halfHeight;
|
|
_imageMapPoints[1].x = halfWidth;
|
|
_imageMapPoints[1].y = halfHeight;
|
|
_imageMapPoints[2].x = halfWidth;
|
|
_imageMapPoints[2].y = -halfHeight;
|
|
_imageMapPoints[3].x = -halfWidth;
|
|
_imageMapPoints[3].y = -halfHeight;
|
|
|
|
|
|
MADrawPoint points[4] = { 0 };
|
|
for(int i = 0; i < 4; ++i) {
|
|
CGPoint tempPoint = _imageMapPoints[i];
|
|
if(traceOverlay.enableAutoCarDirection) {
|
|
tempPoint = CGPointApplyAffineTransform(_imageMapPoints[i], CGAffineTransformMakeRotation(rotate));
|
|
}
|
|
|
|
tempPoint.x += carPoint.x;
|
|
tempPoint.y += carPoint.y;
|
|
CGPoint p = [self glPointForMapPoint:MAMapPointMake(tempPoint.x, tempPoint.y)];
|
|
points[i].x = p.x;
|
|
points[i].y = p.y;
|
|
}
|
|
|
|
float *viewMatrix = [self getViewMatrix];
|
|
float *projectionMatrix = [self getProjectionMatrix];
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);//纹理和顶点皆已做过预乘alpha值处理
|
|
|
|
|
|
glUseProgram(_programe);
|
|
glBindTexture(GL_TEXTURE_2D, _textureName);
|
|
|
|
//glUseProgram(shaderToUse.programName);
|
|
glEnableVertexAttribArray(_attribute_position_location);
|
|
glEnableVertexAttribArray(_attribute_texCoord_location);
|
|
|
|
glUniformMatrix4fv(_uniform_viewMatrix_location, 1, false, viewMatrix);
|
|
glUniformMatrix4fv(_uniform_projMatrix_location, 1, false, projectionMatrix);
|
|
|
|
MADrawPoint textureCoords[4] = {
|
|
0.0, 1.0,
|
|
1.0, 1.0,
|
|
1.0, 0.0,
|
|
0.0, 0.0
|
|
};
|
|
glVertexAttribPointer(_attribute_position_location, 2, GL_FLOAT, false, sizeof(MADrawPoint), &(points[0]));
|
|
glVertexAttribPointer(_attribute_texCoord_location, 2, GL_FLOAT, false, sizeof(MADrawPoint), &(textureCoords[0]));
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
glDisableVertexAttribArray(_attribute_position_location);
|
|
glDisableVertexAttribArray(_attribute_texCoord_location);
|
|
|
|
glDisable(GL_BLEND);
|
|
glDepthMask(GL_TRUE);
|
|
glUseProgram(0);
|
|
}
|
|
|
|
- (GLuint)loadGLESPrograme {
|
|
NSString *vertexShaderSrc = @"precision highp float;\n\
|
|
attribute vec2 attrVertex;\n\
|
|
attribute vec2 attrTextureCoord;\n\
|
|
uniform mat4 inViewMatrix;\n\
|
|
uniform mat4 inProjMatrix;\n\
|
|
varying vec2 textureCoord;\n\
|
|
void main(){\n\
|
|
gl_Position = inProjMatrix * inViewMatrix * (vec4(attrVertex, 1.0, 1.0));\n\
|
|
textureCoord = attrTextureCoord;\n\
|
|
}";
|
|
|
|
NSString *fragShaderSrc = @"precision highp float;\n\
|
|
varying vec2 textureCoord;\n\
|
|
uniform sampler2D inTextureUnit;\n\
|
|
void main(){\n\
|
|
gl_FragColor = texture2D(inTextureUnit, textureCoord);\n\
|
|
}";
|
|
|
|
GLuint prgName = 0;
|
|
prgName = glCreateProgram();
|
|
|
|
if(prgName <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
GLint logLength = 0, status = 0;
|
|
//////////////////////////////////////
|
|
// Specify and compile VertexShader //
|
|
//////////////////////////////////////
|
|
const GLchar* vertexShaderSrcStr = (const GLchar*)[vertexShaderSrc UTF8String];
|
|
|
|
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
glShaderSource(vertexShader, 1, (const GLchar **)&(vertexShaderSrcStr), NULL);
|
|
glCompileShader(vertexShader);
|
|
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
|
|
|
|
if (logLength > 0) {
|
|
GLchar *log = (GLchar*) malloc(logLength);
|
|
glGetShaderInfoLog(vertexShader, logLength, &logLength, log);
|
|
NSLog(@"Vtx Shader compile log:%s\n", log);
|
|
free(log);
|
|
}
|
|
|
|
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
|
if (status == 0) {
|
|
NSLog(@"Failed to compile vtx shader:\n%s\n", vertexShaderSrcStr);
|
|
return 0;
|
|
}
|
|
|
|
glAttachShader(prgName, vertexShader);
|
|
glDeleteShader(vertexShader);
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// Specify and compile Fragment Shader //
|
|
/////////////////////////////////////////
|
|
const GLchar* fragmentShaderSrcStr = (const GLchar*)[fragShaderSrc UTF8String];
|
|
|
|
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
glShaderSource(fragShader, 1, (const GLchar **)&(fragmentShaderSrcStr), NULL);
|
|
glCompileShader(fragShader);
|
|
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
|
|
if (logLength > 0) {
|
|
GLchar *log = (GLchar*)malloc(logLength);
|
|
glGetShaderInfoLog(fragShader, logLength, &logLength, log);
|
|
NSLog(@"Frag Shader compile log:\n%s\n", log);
|
|
free(log);
|
|
}
|
|
|
|
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &status);
|
|
if (status == 0) {
|
|
NSLog(@"Failed to compile frag shader:\n%s\n", fragmentShaderSrcStr);
|
|
return 0;
|
|
}
|
|
|
|
glAttachShader(prgName, fragShader);
|
|
glDeleteShader(fragShader);
|
|
|
|
//////////////////////
|
|
// Link the program //
|
|
//////////////////////
|
|
glLinkProgram(prgName);
|
|
glGetProgramiv(prgName, GL_INFO_LOG_LENGTH, &logLength);
|
|
if (logLength > 0) {
|
|
GLchar *log = (GLchar*)malloc(logLength);
|
|
glGetProgramInfoLog(prgName, logLength, &logLength, log);
|
|
NSLog(@"Program link log:\n%s\n", log);
|
|
free(log);
|
|
}
|
|
|
|
glGetProgramiv(prgName, GL_LINK_STATUS, &status);
|
|
if (status == 0) {
|
|
NSLog(@"Failed to link program");
|
|
return 0;
|
|
}
|
|
|
|
_uniform_viewMatrix_location = glGetUniformLocation(prgName, "inViewMatrix");
|
|
_uniform_projMatrix_location = glGetUniformLocation(prgName, "inProjMatrix");
|
|
|
|
_attribute_position_location = glGetAttribLocation(prgName, "attrVertex");
|
|
_attribute_texCoord_location = glGetAttribLocation(prgName, "attrTextureCoord");
|
|
|
|
return prgName;
|
|
}
|
|
@end
|