浏览器版本低!无法浏览完整内容,建议升级或更换浏览器。

Android 地图SDK

百度地图SDK是一套应用程序接口, 通过调用地图SDK接口,开发者可以轻松访问百度地图的服务和数据,构建功能丰富、交互性强的地图类应用程序。

OpenGL绘制(绘制3D模型)

百度地图SDK为广大开发者开放了OpenGL绘制接口,帮助开发者在地图上实现更灵活的样式绘制,丰富地图使用效果体验。

自4.2.0起, 地图SDK支持 OpenGLES 2.0,请使用onMapDrawFrame(MapStatus drawingMapStatus),地图渲染每一帧画面过程中,以及每次需要重绘地图时(例如添加覆盖物)都会调用此接口。开发者可以在这个接口中进行opengl的绘制。自4.2.0起,旧版的onMapDrawFrame(GL10 gl, MapStatus drawingMapStatus)废弃。

绘制折线

下面将以在地图上绘制折线为例,向大家介绍如何使用OpenGL绘制接口:

// 定义地图绘制每一帧时 OpenGL 绘制的回调接口

OnMapDrawFrameCallback callback = new OnMapDrawFrameCallback() {
    public void onMapDrawFrame(MapStatus drawingMapStatus)     {
        if (mBaiduMap.getProjection() != null) {
             drawFrame(drawingMapStatus);
         }
    }
} 
// 设置地图绘制每一帧时的回调接口

mMapView = (MapView) findViewById(R.id.bmapView);

mBaiduMap = mMapView.getMap();

mBaiduMap.setOnMapDrawFrameCallback(this);

 // 采用屏幕坐标, 有抖动,有累计误差

	private void drawFrame(MapStatus drawingMapStatus) {
 
        PointF p1f = mBaiduMap.getProjection().toOpenGLNormalization(latlng2 , drawingMapStatus);
        PointF p2f = mBaiduMap.getProjection().toOpenGLNormalization(latlng3 , drawingMapStatus);
 
        float mVerticesData[] = new float[] { p1f.x, p1f.y, 0.0f, p2f.x, p1f.y, 0.0f, p1f.x,
				p2f.y, 0.0f, p2f.x, p2f.y, 0.0f };
		mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
				.order(ByteOrder.nativeOrder()).asFloatBuffer();
		mVertices.put(mVerticesData).position(0);
 
        mTexCoords = ByteBuffer.allocateDirect(mTexCoordsData.length * 2)
                .order(ByteOrder.nativeOrder()).asShortBuffer();
        mTexCoords.put(mTexCoordsData).position(0);
        if(!mBfirst) {
            comipleShaderAndLinkProgram();
            loadTexture();
            mBfirst = true;
        }
 
        GLES20.glUseProgram(mProgramObject);
 
		GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices);
        GLES20.glEnableVertexAttribArray(0);
 
        GLES20.glVertexAttribPointer(1, 2, GLES20.GL_SHORT, false, 0, mTexCoords);
        GLES20.glEnableVertexAttribArray(1);
 
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID);
 
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
	}
 
 
	private void comipleShaderAndLinkProgram() {
		final String vShaderStr = "attribute vec4 a_position;    \n"
				+"attribute vec2 a_texCoords; \n"
				+"varying vec2 v_texCoords; \n"
				+ "void main()                  \n"
				+ "{                            \n"
				+ "   gl_Position = a_position;  \n"
				+"    v_texCoords = a_texCoords; \n"
				+ "}                            \n";
		final String fShaderStr = "precision mediump float;                     \n"
				+"uniform sampler2D u_Texture; \n"
				+"varying vec2 v_texCoords; \n"
				+ "void main()                                  \n"
				+ "{                                            \n"
				+ "  gl_FragColor = texture2D(u_Texture, v_texCoords) ;\n"
				+ "}                                            \n";
		int vertexShader;
		int fragmentShader;
		int programObject;
		int[] linked = new int[1];
		// Load the vertex/fragment shaders
		vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vShaderStr);
		fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fShaderStr);
		// Create the program object
		programObject = GLES20.glCreateProgram();
		if (programObject == 0) {
			return ;
 
		}
 
		GLES20.glAttachShader(programObject, vertexShader);
		GLES20.glAttachShader(programObject, fragmentShader);
		// Bind vPosition to attribute 0
		GLES20.glBindAttribLocation(programObject, 0, "a_position");
		GLES20.glBindAttribLocation(programObject, 1, "a_texCoords");
		// Link the program
		GLES20.glLinkProgram(programObject);
		// Check the link status
		GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0);
		if (linked[0] == 0) {
			Log.e(LTAG, "Error linking program:");
			Log.e(LTAG, GLES20.glGetProgramInfoLog(programObject));
			GLES20.glDeleteProgram(programObject);
			return  ;
		}
		mProgramObject = programObject;
	}
	private int loadShader(int shaderType, String shaderSource) {
		int shader;
		int[] compiled = new int[1];
		// Create the shader object
		shader = GLES20.glCreateShader(shaderType);
		if (shader == 0) {
			return 0;
 
		}
		// Load the shader source
		GLES20.glShaderSource(shader, shaderSource);
		// Compile the shader
		GLES20.glCompileShader(shader);
		// Check the compile status
		GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
		if (compiled[0] == 0) {
			Log.e(LTAG, GLES20.glGetShaderInfoLog(shader));
			GLES20.glDeleteShader(shader);
			return 0;
		}
		return shader;
	}
	private void loadTexture() {
		bitmap = BitmapFactory.decodeResource(this.getResources(),
				R.drawable.ground_overlay);
		if (bitmap != null) {
			int []texID = new int[1];
			GLES20.glGenTextures(1, texID, 0);
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texID[0]);
			mTexID = texID[0];
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
					GLES20.GL_LINEAR);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
					GLES20.GL_LINEAR);
 
			GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
					GLES20.GL_REPEAT);
			GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
					GLES20.GL_REPEAT);
 
			GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
			bitmap.recycle();
		}
	}
 
// 计算折线 OpenGL 坐标

public void calPolylinePoint(MapStatus mspStatus) {
    PointF[] polyPoints = new PointF[latLngPolygon.size()];
    vertexs = new float[3 * latLngPolygon.size()];
    int i = 0;
    for (LatLng xy : latLngPolygon) {
        // 将地理坐标转换成 openGL 坐标
        polyPoints[i] = mBaiduMap.getProjection().toOpenGLLocation(xy, mspStatus);
        vertexs[i * 3] = polyPoints[i].x;
        vertexs[i * 3 + 1] = polyPoints[i].y;
        vertexs[i * 3 + 2] = 0.0f;
        i++;
    }
    for (int j = 0; j < vertexs.length; j++) {
        Log.d(LTAG, "vertexs[" + j + "]: " + vertexs[j]);
    }
    vertexBuffer = makeFloatBuffer(vertexs);
}
 
//创建OpenGL绘制时的顶点Buffer

private FloatBuffer makeFloatBuffer(float[] fs) {
    ByteBuffer bb = ByteBuffer.allocateDirect(fs.length * 4);
    bb.order(ByteOrder.nativeOrder());
    FloatBuffer fb = bb.asFloatBuffer();
    fb.put(fs);
    fb.position(0);
    return fb;
}

结果如下图所示:

DrawLine1.png

详细的绘制代码请查看Demo。