全部服务产品
开发者频道
定价
登录
OpenGL绘制
下载开发文档
OpenGL绘制(绘制3D模型)

百度地图SDK为开发者开放了OpenGL绘制接口,以帮助开发者在地图上实现灵活的样式绘制,丰富地图的显示效果和使用体验。
自V4.2.0起,百度地图SDK支持OpenGLES 2.0,请开发者调用OnMapDrawFrameCallback接口的onMapDrawFrame(MapStatus drawingMapStatus)方法来进行绘制,在地图渲染每一帧的过程中,以及每次需要重绘地图时(如添加覆盖物),该接口都会被调用。
自V4.2.0起,旧版的onMapDrawFrame(GL10 gl, MapStatus drawingMapStatus)方法废弃。

绘制3D立方体

下面代码以在地图上绘制3D立方体为例,介绍如何使用OpenGL绘制接口。

定义3D立方体着色器类

private class CubeShader {
int mVertex;
int mMvpMatrix;
int mColor;
int mProgram;
public CubeShader() {
}
String vertexShader = "precision highp float;\n" +
" attribute vec3 mVertex;//顶点数组,三维坐标\n" +
" attribute vec4 mColor;//颜色数组,三维坐标\n" +
" uniform mat4 mMvpMatrix;//mvp矩阵\n" +
" varying vec4 color;//\n" +
" void main(){\n" +
" gl_Position = mMvpMatrix * vec4(mVertex, 1.0);\n" +
" color = mColor;\n" +
" }";
String fragmentShader = "//有颜色 没有纹理\n" +
" precision highp float;\n" +
" varying vec4 color;//\n" +
" void main(){\n" +
" gl_FragColor = color;\n" +
" }";
public void init() {
int vertexLocation = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexLocation, vertexShader);
GLES20.glCompileShader(vertexLocation);
int fragmentLocation = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentLocation, fragmentShader);
GLES20.glCompileShader(fragmentLocation);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexLocation);
GLES20.glAttachShader(mProgram, fragmentLocation);
GLES20.glLinkProgram(mProgram);
mVertex = GLES20.glGetAttribLocation(mProgram, "mVertex");
mMvpMatrix = GLES20.glGetUniformLocation(mProgram,"mMvpMatrix");
mColor = GLES20.glGetAttribLocation(mProgram,"mColor");
}
}

准备立方体数据并初始化

1、声明所需数据及属性

// 3D立方体顶点绘制顺序列表
private short[] mDrawIndices = {
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
};
// 3D立方体8个顶点颜色值
private float[] mVertexColors = {
1f, 1f, 0f, 1f,
0f, 1f, 1f, 1f,
1f, 0f, 1f, 1f,
0f, 0f, 0f, 1f,
1f, 1f, 1f, 1f,
1f, 0f, 0f, 1f,
0f, 1f, 0f, 1f,
0f, 0f, 1f, 1f
};
// 立方体顶点坐标Buffer
private FloatBuffer mVertextBuffer;
// 顶点绘制顺序Buffer
private ShortBuffer mIndexBuffer;
// 立方体顶点颜色Buffer
private FloatBuffer mColorBuffer;
// 3D立方体着色器
private CubeShader mCubeShader;

2、初始化数据

private void initCubeModelData(float width, float height, float depth) {
// 对标墨卡托坐标
width = width * 10000 / 2;
height = height * 10000 / 2;
depth = depth * 10000 / 2;
// 立方体8个顶点坐标
float[] vertices = {
-width, -height, -0,
width, -height, -0,
width, height, -0,
-width, height, -0,
-width, -height, depth,
width, -height, depth,
width, height, depth,
-width, height, depth,
};
mVertextBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mVertextBuffer.put(vertices).position(0);
// 立方体顶点绘制顺序Buffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(mDrawIndices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
mIndexBuffer = byteBuffer.asShortBuffer();
mIndexBuffer.put(mDrawIndices);
mIndexBuffer.position(0);
// 立方体顶点颜色Buffer
ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(mVertexColors.length * 4);
byteBuffer1.order(ByteOrder.nativeOrder());
mColorBuffer = byteBuffer1.asFloatBuffer();
mColorBuffer.put(mVertexColors);
mColorBuffer.position(0);
}

调用OnMapDrawFrameCallback接口绘制

1、创建OnMapDrawFrameCallback实例

BaiduMap.OnMapDrawFrameCallback callback = new BaiduMap.OnMapDrawFrameCallback() {
//废弃
@Override
public void onMapDrawFrame(GL10 gl, MapStatus drawingMapStatus) {
}
@Override
public void onMapDrawFrame(MapStatus drawingMapStatus) {
if (null == mBaiduMap.getProjection()) {
return;
}
drawFrameFor3DCube(drawingMapStatus, 0.2f, 0.2f, 0.3f);
}
};

2、设置OnMapDrawFrameCallback接口

mBaiduMap.setOnMapDrawFrameCallback(callback);

3、绘制方法

/**
* 绘制3D立方体
* @param drawingMapStatus
*/
private void drawCube(MapStatus drawingMapStatus) {
if (null == mCubeShader || null == drawingMapStatus) {
return;
}
// Step1 初始化数据
float[] mvpMatrix = new float[16];
Matrix.setIdentityM(mvpMatrix, 0);
// 获取投影矩阵
float[] projectMatrix = mBaiduMap.getProjectionMatrix();
// 获取视图矩阵
float[] viewMatrix = mBaiduMap.getViewMatrix();
Matrix.multiplyMM(mvpMatrix,0, projectMatrix,0, viewMatrix,0);
// 绑定地图移动
PointF p1f = mBaiduMap.getProjection().toOpenGLLocation(latlng1, drawingMapStatus);
Matrix.translateM(mvpMatrix, 0 , p1f.x, p1f.y, 0);
// 设置缩放比例
int scale = 1;
Matrix.scaleM(mvpMatrix, 0 , scale, scale, scale);
// Step2 开始绘制设置
GLES20.glUseProgram(mCubeShader.mProgram);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// 顶点指针
GLES20.glEnableVertexAttribArray(mCubeShader.mVertex);
GLES20.glVertexAttribPointer(mCubeShader.mVertex, 3, GLES20.GL_FLOAT, false, 0, mVertextBuffer);
// 颜色指针
GLES20.glEnableVertexAttribArray(mCubeShader.mColor);
GLES20.glVertexAttribPointer(mCubeShader.mColor, 4, GLES20.GL_FLOAT,false, 0, mColorBuffer);
GLES20.glUniformMatrix4fv(mCubeShader.mMvpMatrix, 1, false, mvpMatrix, 0);
// 开始画
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mDrawIndices.length, GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);
GLES20.glDisableVertexAttribArray(mCubeShader.mVertex);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
}

效果如图:

设置OnMapDrawFrameCallback接口

上一篇

自定义瓦片图层

下一篇

绘制3D棱柱

本篇文章对您是否有帮助?