更新时间:2020-06-23

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);

}

效果如图:

71be14b8e365e10c8f09cce5f5cabe2a.png

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐