因为WorldWindAndroid版是利用Opengl ES实现绘图的,所以大体的框架还是确定的,那就是实现GLSurfaceView.Renderer接口下的三个方法:OnSurfaceCreated,OnDrawFrame和OnSurfaceChanged,而这一实现是在WorldWindow类中!
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Specify the default World Wind OpenGL state.
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnableVertexAttribArray(0);
GLES20.glDisable(GLES20.GL_DITHER);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
// Clear any cached OpenGL resources and state, which are now invalid.
this.dc.contextLost();
// Set the World Window's depth bits.
int[] depthBits = new int[1];
GLES20.glGetIntegerv(GLES20.GL_DEPTH_BITS, depthBits, 0);
this.mainThreadHandler.sendMessage(
Message.obtain(this.mainThreadHandler, MSG_ID_SET_DEPTH_BITS /*msg.what*/, depthBits[0] /*msg.obj*/));
// Clear the render resource cache on the main thread.
this.mainThreadHandler.sendEmptyMessage(MSG_ID_CLEAR_CACHE /*msg.what*/);
}
/**
* Implements the GLSurfaceView.Renderer.onSurfaceChanged interface which is called on the GLThread when the window
* size changes.
*/
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
// Set the World Window's new viewport dimensions.
Viewport newViewport = new Viewport(0, 0, width, height);
this.mainThreadHandler.sendMessage(
Message.obtain(this.mainThreadHandler, MSG_ID_SET_VIEWPORT /*msg.what*/, newViewport /*msg.obj*/));
// Redraw this World Window with the new viewport.
this.mainThreadHandler.sendEmptyMessage(MSG_ID_REQUEST_REDRAW /*msg.what*/);
}
/**
* Implements the GLSurfaceView.Renderer.onDrawFrame interface which is called on the GLThread when rendering is
* requested.
*/
@Override
public void onDrawFrame(GL10 unused) {
// Remove and process pick the frame from the front of the pick queue, recycling it back into the pool. Continue
// requesting frames on the OpenGL thread until the pick queue is empty. This is critical for correct operation.
// All frames must be processed or threads waiting on a frame to finish may block indefinitely.
Frame pickFrame = this.pickQueue.poll();
if (pickFrame != null) {
try {
this.drawFrame(pickFrame);
} catch (Exception e) {
Logger.logMessage(Logger.ERROR, "WorldWindow", "onDrawFrame",
"Exception while processing pick in OpenGL thread", e);
} finally {
pickFrame.signalDone();
pickFrame.recycle();
super.requestRender();
}
}
// Remove and switch to to the frame at the front of the frame queue, recycling the previous frame back into the
// pool. Continue requesting frames on the OpenGL thread until the frame queue is empty.
Frame nextFrame = this.frameQueue.poll();
if (nextFrame != null) {
if (this.currentFrame != null) {
this.currentFrame.recycle();
}
this.currentFrame = nextFrame;
super.requestRender();
}
// Process and display the Drawables accumulated in the last frame taken from the front of the queue. This frame
// may be drawn multiple times if the OpenGL thread executes more often than the World Window enqueues frames.
try {
if (this.currentFrame != null) {
this.drawFrame(this.currentFrame);
}
} catch (Exception e) {
Logger.logMessage(Logger.ERROR, "WorldWindow", "onDrawFrame",
"Exception while drawing frame in OpenGL thread", e);
}
}
而要使用WorldWind来完成绘图,需要自定义一个Fragment子类,如开发示例BasicGlobleFragment.java。
public class BasicGlobeFragment extends Fragment {
private WorldWindow wwd;
public BasicGlobeFragment() {
}
/**
* Creates a new WorldWindow (GLSurfaceView) object.
*/
public WorldWindow createWorldWindow() {
// Create the WorldWindow (a GLSurfaceView) which displays the globe.
this.wwd = new WorldWindow(getContext());
// Setup the WorldWindow's layers.
this.wwd.getLayers().addLayer(new BackgroundLayer());
this.wwd.getLayers().addLayer(new BlueMarbleLandsatLayer());
return this.wwd;
}
/**
* Gets the WorldWindow (GLSurfaceView) object.
*/
public WorldWindow getWorldWindow() {
return this.wwd;
}
/**
* Adds the WorldWindow to this Fragment's layout.
*/
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_globe, container, false);
FrameLayout globeLayout = (FrameLayout) rootView.findViewById(R.id.globe);
// Add the WorldWindow view object to the layout that was reserved for the globe.
globeLayout.addView(this.createWorldWindow());
return rootView;
}
/**
* Resumes the WorldWindow's rendering thread
*/
@Override
public void onResume() {
super.onResume();
this.wwd.onResume(); // resumes a paused rendering thread
}
/**
* Pauses the WorldWindow's rendering thread
*/
@Override
public void onPause() {
super.onPause();
this.wwd.onPause(); // pauses the rendering thread
}
}
关于Fragment可以参考:
菜鸟教程:Fragment基本概述
对于图层的渲染在BasicFrameController.java
@Override
public void renderFrame(RenderContext rc) {
rc.terrainTessellator.tessellate(rc);
if (rc.pickMode) {
this.renderTerrainPickedObject(rc);
}
rc.layers.render(rc);
rc.sortDrawables();
}