protected void renderSky(RenderContext rc) { Pool<DrawableSkyAtmosphere> pool = rc.getDrawablePool(DrawableSkyAtmosphere.class); DrawableSkyAtmosphere drawable = DrawableSkyAtmosphere.obtain(pool); int size = 128; drawable.program = (SkyProgram) rc.getShaderProgram(SkyProgram.KEY); if (drawable.program == null) { drawable.program = (SkyProgram) rc.putShaderProgram(SkyProgram.KEY, new SkyProgram(rc.resources)); } drawable.vertexPoints = rc.getBufferObject(VERTEX_POINTS_KEY); if (drawable.vertexPoints == null) { drawable.vertexPoints = rc.putBufferObject(VERTEX_POINTS_KEY, this.assembleVertexPoints(rc, size, size, (float) drawable.program.getAltitude())); } drawable.triStripElements = rc.getBufferObject(TRI_STRIP_ELEMENTS_KEY); if (drawable.triStripElements == null) { drawable.triStripElements = rc.putBufferObject(TRI_STRIP_ELEMENTS_KEY, this.assembleTriStripElements(size, size)); } drawable.lightDirection.set(this.activeLightDirection); drawable.globeRadius = rc.globe.getEquatorialRadius(); rc.offerSurfaceDrawable(drawable, Double.POSITIVE_INFINITY /*z-order after all other surface drawables*/); }
protected void renderGround(RenderContext rc) { if (rc.terrain.getSector().isEmpty()) { return; // no terrain surface to render on } Pool<DrawableGroundAtmosphere> pool = rc.getDrawablePool(DrawableGroundAtmosphere.class); DrawableGroundAtmosphere drawable = DrawableGroundAtmosphere.obtain(pool); drawable.program = (GroundProgram) rc.getShaderProgram(GroundProgram.KEY); if (drawable.program == null) { drawable.program = (GroundProgram) rc.putShaderProgram(GroundProgram.KEY, new GroundProgram(rc.resources)); } drawable.lightDirection.set(this.activeLightDirection); drawable.globeRadius = rc.globe.getEquatorialRadius(); // Use this layer's night image when the light location is different than the eye location. if (this.nightImageSource != null && this.lightLocation != null) { drawable.nightTexture = rc.getTexture(this.nightImageSource); if (drawable.nightTexture == null) { drawable.nightTexture = rc.retrieveTexture(this.nightImageSource, this.nightImageOptions); } } else { drawable.nightTexture = null; } rc.offerSurfaceDrawable(drawable, Double.POSITIVE_INFINITY /*z-order after all other surface drawables*/); }
rc.geographicToCartesian(this.position.latitude, this.position.longitude, this.position.altitude, this.altitudeMode, renderData.placePoint); if (!rc.projectWithDepth(renderData.placePoint, depthOffset, renderData.screenPlacePoint)) { return; // clipped by the near plane or the far plane int drawableCount = rc.drawableCount(); if (rc.pickMode) { renderData.pickedObjectId = rc.nextPickedObjectId(); renderData.pickColor = PickedObject.identifierToUniqueColor(renderData.pickedObjectId, renderData.pickColor); if (rc.pickMode && rc.drawableCount() != drawableCount) { rc.offerPickedObject(PickedObject.fromRenderable(renderData.pickedObjectId, this, rc.currentLayer));
protected SurfaceTextureProgram getShaderProgram(RenderContext rc) { SurfaceTextureProgram program = (SurfaceTextureProgram) rc.getShaderProgram(SurfaceTextureProgram.KEY); if (program == null) { program = (SurfaceTextureProgram) rc.putShaderProgram(SurfaceTextureProgram.KEY, new SurfaceTextureProgram(rc.resources)); } return program; } }
public BufferObject getPointBuffer(RenderContext rc) { if (this.points == null) { return null; } BufferObject bufferObject = rc.getBufferObject(this.pointBufferKey); if (bufferObject != null) { return bufferObject; } // TODO consider a pool of terrain tiles // TODO consider a pool of terrain tile vertex buffers int size = this.points.length * 4; FloatBuffer buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()).asFloatBuffer(); buffer.put(this.points).rewind(); return rc.putBufferObject(this.pointBufferKey, new BufferObject(GLES20.GL_ARRAY_BUFFER, size, buffer)); } }
double cameraDistance; if (this.isSurfaceShape) { Pool<DrawableSurfaceShape> pool = rc.getDrawablePool(DrawableSurfaceShape.class); drawable = DrawableSurfaceShape.obtain(pool); drawState = ((DrawableSurfaceShape) drawable).drawState; ((DrawableSurfaceShape) drawable).sector.set(this.boundingSector); } else { Pool<DrawableShape> pool = rc.getDrawablePool(DrawableShape.class); drawable = DrawableShape.obtain(pool); drawState = ((DrawableShape) drawable).drawState; drawState.program = (BasicShaderProgram) rc.getShaderProgram(BasicShaderProgram.KEY); if (drawState.program == null) { drawState.program = (BasicShaderProgram) rc.putShaderProgram(BasicShaderProgram.KEY, new BasicShaderProgram(rc.resources)); drawState.vertexBuffer = rc.getBufferObject(this.vertexBufferKey); if (drawState.vertexBuffer == null) { int size = this.vertexArray.size() * 4; buffer.put(this.vertexArray.array(), 0, this.vertexArray.size()); drawState.vertexBuffer = new BufferObject(GLES20.GL_ARRAY_BUFFER, size, buffer.rewind()); rc.putBufferObject(this.vertexBufferKey, drawState.vertexBuffer); drawState.elementBuffer = rc.getBufferObject(this.elementBufferKey); if (drawState.elementBuffer == null) { int size = (this.interiorElements.size() * 2) + (this.outlineElements.size() * 2) + (this.verticalElements.size() * 2); buffer.put(this.verticalElements.array(), 0, this.verticalElements.size());
protected void renderTerrainPickedObject(RenderContext rc) { if (rc.terrain.getSector().isEmpty()) { return; // no terrain to pick } // Acquire a unique picked object ID for terrain. int pickedObjectId = rc.nextPickedObjectId(); // Enqueue a drawable for processing on the OpenGL thread that displays terrain in the unique pick color. Pool<DrawableSurfaceColor> pool = rc.getDrawablePool(DrawableSurfaceColor.class); DrawableSurfaceColor drawable = DrawableSurfaceColor.obtain(pool); drawable.color = PickedObject.identifierToUniqueColor(pickedObjectId, drawable.color); drawable.program = (BasicShaderProgram) rc.getShaderProgram(BasicShaderProgram.KEY); if (drawable.program == null) { drawable.program = (BasicShaderProgram) rc.putShaderProgram(BasicShaderProgram.KEY, new BasicShaderProgram(rc.resources)); } rc.offerSurfaceDrawable(drawable, Double.NEGATIVE_INFINITY /*z-order before all other surface drawables*/); // If the pick ray intersects the terrain, enqueue a picked object that associates the terrain drawable with its // picked object ID and the intersection position. if (rc.pickRay != null && rc.terrain.intersect(rc.pickRay, this.pickPoint)) { rc.globe.cartesianToGeographic(this.pickPoint.x, this.pickPoint.y, this.pickPoint.z, this.pickPos); this.pickPos.altitude = 0; // report the actual altitude, which may not lie on the terrain's surface rc.offerPickedObject(PickedObject.fromTerrain(pickedObjectId, this.pickPos)); } }
@Override protected void doRender(RenderContext rc) { if (this.sector.isEmpty()) { return; // nothing to render } if (!rc.terrain.getSector().intersects(this.sector)) { return; // no terrain surface to render on } Texture texture = rc.getTexture(this.imageSource); // try to get the texture from the cache if (texture == null) { texture = rc.retrieveTexture(this.imageSource, this.imageOptions); // puts retrieved textures in the cache } if (texture == null) { return; // no texture to draw } // Enqueue a drawable surface texture for processing on the OpenGL thread. SurfaceTextureProgram program = this.getShaderProgram(rc); Pool<DrawableSurfaceTexture> pool = rc.getDrawablePool(DrawableSurfaceTexture.class); DrawableSurfaceTexture drawable = DrawableSurfaceTexture.obtain(pool).set(program, this.sector, texture, texture.getTexCoordTransform()); rc.offerSurfaceDrawable(drawable, 0 /*z-order*/); // Enqueue a picked object that associates the drawable surface texture with this surface image. if (rc.pickMode) { int pickedObjectId = rc.nextPickedObjectId(); PickedObject.identifierToUniqueColor(pickedObjectId, drawable.color); rc.offerPickedObject(PickedObject.fromRenderable(pickedObjectId, this, rc.currentLayer)); } }
rc.geographicToCartesian(this.position.latitude, this.position.longitude, this.position.altitude, this.altitudeMode, placePoint); if (!rc.projectWithDepth(placePoint, depthOffset, screenPlacePoint)) { return; // clipped by the near plane or the far plane int drawableCount = rc.drawableCount(); if (rc.pickMode) { this.pickedObjectId = rc.nextPickedObjectId(); this.pickColor = PickedObject.identifierToUniqueColor(this.pickedObjectId, this.pickColor); rc.geographicToCartesian(this.position.latitude, this.position.longitude, 0, WorldWind.CLAMP_TO_GROUND, groundPoint); Pool<DrawableLines> pool = rc.getDrawablePool(DrawableLines.class); DrawableLines drawable = DrawableLines.obtain(pool); this.prepareDrawableLeader(rc, drawable); rc.offerShapeDrawable(drawable, this.cameraDistance); this.activeTexture = rc.getTexture(this.activeAttributes.imageSource); // try to get the texture from the cache Pool<DrawableScreenTexture> pool = rc.getDrawablePool(DrawableScreenTexture.class); DrawableScreenTexture drawable = DrawableScreenTexture.obtain(pool); this.prepareDrawableIcon(rc, drawable); rc.offerShapeDrawable(drawable, this.cameraDistance); if (rc.pickMode && rc.drawableCount() != drawableCount) { rc.offerPickedObject(PickedObject.fromRenderable(this.pickedObjectId, this, rc.currentLayer));
@Override protected void doRender(RenderContext rc) { if (rc.terrain.getSector().isEmpty()) { return; // no terrain to render } // Use WorldWind's basic GLSL program. BasicShaderProgram program = (BasicShaderProgram) rc.getShaderProgram(BasicShaderProgram.KEY); if (program == null) { program = (BasicShaderProgram) rc.putShaderProgram(BasicShaderProgram.KEY, new BasicShaderProgram(rc.resources)); } Pool<DrawableTessellation> pool = rc.getDrawablePool(DrawableTessellation.class); Drawable drawable = DrawableTessellation.obtain(pool).set(program, this.color); rc.offerSurfaceDrawable(drawable, 1.0 /*z-order after surface textures*/); } }
protected void addTile(RenderContext rc, ImageTile tile) { ImageSource imageSource = tile.getImageSource(); if (imageSource == null) { return; // no image source indicates an empty level or an image missing from the tiled data store } Texture texture = rc.getTexture(imageSource); // try to get the texture from the cache if (texture == null) { texture = rc.retrieveTexture(imageSource, this.imageOptions); // puts retrieved textures in the cache } if (texture != null) { // use the tile's own texture Pool<DrawableSurfaceTexture> pool = rc.getDrawablePool(DrawableSurfaceTexture.class); Drawable drawable = DrawableSurfaceTexture.obtain(pool).set(this.activeProgram, tile.sector, texture, texture.getTexCoordTransform()); rc.offerSurfaceDrawable(drawable, 0 /*z-order*/); } else if (this.ancestorTile != null) { // use the ancestor tile's texture, transformed to fill the tile sector this.ancestorTexCoordMatrix.set(this.ancestorTexture.getTexCoordTransform()); this.ancestorTexCoordMatrix.multiplyByTileTransform(tile.sector, this.ancestorTile.sector); Pool<DrawableSurfaceTexture> pool = rc.getDrawablePool(DrawableSurfaceTexture.class); Drawable drawable = DrawableSurfaceTexture.obtain(pool).set(this.activeProgram, tile.sector, this.ancestorTexture, this.ancestorTexCoordMatrix); rc.offerSurfaceDrawable(drawable, 0 /*z-order*/); } }
protected void makeDrawable(RenderContext rc) { Texture texture = rc.getText(this.text, this.activeAttributes); if (texture == null && rc.frustum.containsPoint(renderData.placePoint)) { texture = rc.renderText(this.text, this.activeAttributes); } else if (texture == null) { return; Pool<DrawableScreenTexture> pool = rc.getDrawablePool(DrawableScreenTexture.class); DrawableScreenTexture drawable = DrawableScreenTexture.obtain(pool); drawable.program = (BasicShaderProgram) rc.getShaderProgram(BasicShaderProgram.KEY); if (drawable.program == null) { drawable.program = (BasicShaderProgram) rc.putShaderProgram(BasicShaderProgram.KEY, new BasicShaderProgram(rc.resources)); rc.offerShapeDrawable(drawable, renderData.cameraDistance);
Texture texture = rc.getTexture(this.activeAttributes.interiorImageSource); if (texture == null) { texture = rc.retrieveTexture(this.activeAttributes.interiorImageSource, defaultInteriorImageOptions); double metersPerPixel = rc.pixelSizeAtDistance(this.cameraDistance); this.computeRepeatingTexCoordTransform(texture, metersPerPixel, this.texCoordMatrix); drawState.texture(texture);
@Override protected void doRender(RenderContext rc) { // Don't render anything if the shape is not visible. if (!this.intersectsFrustum(rc)) { return; } // Select the currently active attributes. Don't render anything if the attributes are unspecified. this.determineActiveAttributes(rc); if (this.activeAttributes == null) { return; } // Keep track of the drawable count to determine whether or not this shape has enqueued drawables. int drawableCount = rc.drawableCount(); if (rc.pickMode) { this.pickedObjectId = rc.nextPickedObjectId(); this.pickColor = PickedObject.identifierToUniqueColor(this.pickedObjectId, this.pickColor); } // Enqueue drawables for processing on the OpenGL thread. this.makeDrawable(rc); // Enqueue a picked object that associates the shape's drawables with its picked object ID. if (rc.pickMode && rc.drawableCount() != drawableCount) { rc.offerPickedObject(PickedObject.fromRenderable(this.pickedObjectId, this, rc.currentLayer)); } }
protected void addTile(RenderContext rc, TerrainTile tile) { // Prepare the terrain tile and add it. this.prepareTile(rc, tile); this.currentTerrain.addTile(tile); // Prepare a drawable for the terrain tile for processing on the OpenGL thread. Pool<BasicDrawableTerrain> pool = rc.getDrawablePool(BasicDrawableTerrain.class); BasicDrawableTerrain drawable = BasicDrawableTerrain.obtain(pool); this.prepareDrawableTerrain(rc, tile, drawable); rc.offerDrawableTerrain(drawable, tile.getDistanceToCamera()); }
/** * Calculate the number of times to split the edges of the shape for geometry assembly. * * @param rc current RenderContext * * @return an even number of intervals */ protected int computeIntervals(RenderContext rc) { int intervals = MIN_INTERVALS; if (intervals >= this.maximumIntervals) { return intervals; // use at least the minimum number of intervals } Vec3 centerPoint = rc.geographicToCartesian(this.center.latitude, this.center.longitude, this.center.altitude, this.altitudeMode, scratchPoint); double maxRadius = Math.max(this.majorRadius, this.minorRadius); double cameraDistance = centerPoint.distanceTo(rc.cameraPoint) - maxRadius; if (cameraDistance <= 0) { return this.maximumIntervals; // use the maximum number of intervals when the camera is very close } double metersPerPixel = rc.pixelSizeAtDistance(cameraDistance); double circumferencePixels = this.computeCircumference() / metersPerPixel; double circumferenceIntervals = circumferencePixels / this.maximumPixelsPerInterval; double subdivisions = Math.log(circumferenceIntervals / intervals) / Math.log(2); int subdivisionCount = Math.max(0, (int) Math.ceil(subdivisions)); intervals <<= subdivisionCount; // subdivide the base intervals to achieve the desired number of intervals return Math.min(intervals, this.maximumIntervals); // don't exceed the maximum number of intervals }
protected void determineModelToTexCoord(RenderContext rc) { Vec3 point = rc.geographicToCartesian(this.center.latitude, this.center.longitude, this.center.altitude, this.altitudeMode, scratchPoint); this.modelToTexCoord = rc.globe.cartesianToLocalTransform(point.x, point.y, point.z, this.modelToTexCoord); this.modelToTexCoord.invertOrthonormal(); }
protected void addTileOrDescendants(RenderContext rc, ImageTile tile) { if (!tile.intersectsSector(this.levelSet.sector) || !tile.intersectsFrustum(rc, rc.frustum)) { return; // ignore the tile and its descendants if it's not needed or not visible } if (tile.level.isLastLevel() || !tile.mustSubdivide(rc, this.detailControl)) { this.addTile(rc, tile); return; // use the tile if it does not need to be subdivided } ImageTile currentAncestorTile = this.ancestorTile; Texture currentAncestorTexture = this.ancestorTexture; ImageSource tileImageSource = tile.getImageSource(); if (tileImageSource != null) { // tile has an image source; its level is not empty Texture tileTexture = rc.getTexture(tileImageSource); if (tileTexture != null) { // tile has a texture; use it as a fallback tile for descendants this.ancestorTile = tile; this.ancestorTexture = tileTexture; } } for (Tile child : tile.subdivideToCache(this.tileFactory, this.tileCache, 4)) { // each tile has a cached size of 1 this.addTileOrDescendants(rc, (ImageTile) child); // recursively process the tile's children } this.ancestorTile = currentAncestorTile; // restore the last fallback tile, even if it was null this.ancestorTexture = currentAncestorTexture; }
this.activeTexture = rc.retrieveTexture(this.activeAttributes.imageSource, null); // puts retrieved textures in the cache
protected int addVertex(RenderContext rc, double latitude, double longitude, double altitude, int type) { int vertex = this.vertexArray.size() / VERTEX_STRIDE; Vec3 point = rc.geographicToCartesian(latitude, longitude, altitude, this.altitudeMode, this.point); Vec3 texCoord2d = this.texCoord2d.set(point).multiplyByMatrix(this.modelToTexCoord); this.tessCoords[1] = latitude; this.tessCoords[2] = altitude; GLU.gluTessVertex(rc.getTessellator(), this.tessCoords, 0 /*coords_offset*/, vertex); point = rc.geographicToCartesian(latitude, longitude, 0, WorldWind.CLAMP_TO_GROUND, this.point); this.vertexArray.add((float) (point.x - this.vertexOrigin.x)); this.vertexArray.add((float) (point.y - this.vertexOrigin.y));