Worldwind 的 Point PlaceMark 可渲染具有通过调用setLineEnabled将线从 Placemark 下拉到地形的功能,如下图所示:
我想要做的是添加一条这样的线,它也适用于可渲染的战术符号。我的第一个想法是从PointPlacemark可渲染对象中借用执行此操作的逻辑,并将其添加到AbstractTacticalSymbol可渲染对象中。我已经尝试过了,到目前为止我一直没有成功。
这是我到目前为止所做的:
将此添加到 OrderedSymbol 类:
public Vec4 terrainPoint;
更新了 computeSymbolPoints 以计算地形点
protected void computeSymbolPoints(DrawContext dc, OrderedSymbol osym) { osym.placePoint = null; osym.screenPoint = null; osym.terrainPoint = null; osym.eyeDistance = 0; Position pos = this.getPosition(); if (pos == null) return; if (this.altitudeMode == WorldWind.CLAMP_TO_GROUND || dc.is2DGlobe()) { osym.placePoint = dc.computeTerrainPoint(pos.getLatitude(), pos.getLongitude(), 0); } else if (this.altitudeMode == WorldWind.RELATIVE_TO_GROUND) { osym.placePoint = dc.computeTerrainPoint(pos.getLatitude(), pos.getLongitude(), pos.getAltitude()); } else // Default to ABSOLUTE { double height = pos.getElevation() * dc.getVerticalExaggeration(); osym.placePoint = dc.getGlobe().computePointFromPosition(pos.getLatitude(), pos.getLongitude(), height); } if (osym.placePoint == null) return; // Compute the symbol's screen location the distance between the eye point and the place point. osym.screenPoint = dc.getView().project(osym.placePoint); osym.eyeDistance = osym.placePoint.distanceTo3(dc.getView().getEyePoint()); // Compute a terrain point if needed. if (this.isLineEnabled() && this.altitudeMode != WorldWind.CLAMP_TO_GROUND && !dc.is2DGlobe()) osym.terrainPoint = dc.computeTerrainPoint(pos.getLatitude(), pos.getLongitude(), 0); }
添加此逻辑(取自 PointPlacemark.java 并更新以符合 AbstractTacticalSymbol.java)。请注意,我已将 lineEnabled 设置为 true,因此默认情况下它应该画线。
boolean lineEnabled = true; double lineWidth = 1; protected int linePickWidth = 10; Color lineColor = Color.white; /** * Indicates whether a line from the placemark point to the corresponding position on the terrain is drawn. * * @return true if the line is drawn, otherwise false. */ public boolean isLineEnabled() { return lineEnabled; } /** * Specifies whether a line from the placemark point to the corresponding position on the terrain is drawn. * * @param lineEnabled true if the line is drawn, otherwise false. */ public void setLineEnabled(boolean lineEnabled) { this.lineEnabled = lineEnabled; } /** * Determines whether the placemark's optional line should be drawn and whether it intersects the view frustum. * * @param dc the current draw context. * * @return true if the line should be drawn and it intersects the view frustum, otherwise false. */ protected boolean isDrawLine(DrawContext dc, OrderedSymbol opm) { if (!this.isLineEnabled() || dc.is2DGlobe() || this.getAltitudeMode() == WorldWind.CLAMP_TO_GROUND || opm.terrainPoint == null) return false; if (dc.isPickingMode()) return dc.getPickFrustums().intersectsAny(opm.placePoint, opm.terrainPoint); else return dc.getView().getFrustumInModelCoordinates().intersectsSegment(opm.placePoint, opm.terrainPoint); } /** * Draws the placemark's line. * * @param dc the current draw context. * @param pickCandidates the pick support object to use when adding this as a pick candidate. */ protected void drawLine(DrawContext dc, PickSupport pickCandidates, OrderedSymbol opm) { GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. if ((!dc.isDeepPickingEnabled())) gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(GL.GL_LEQUAL); gl.glDepthMask(true); try { dc.getView().pushReferenceCenter(dc, opm.placePoint); // draw relative to the place point this.setLineWidth(dc); this.setLineColor(dc, pickCandidates); gl.glBegin(GL2.GL_LINE_STRIP); gl.glVertex3d(Vec4.ZERO.x, Vec4.ZERO.y, Vec4.ZERO.z); gl.glVertex3d(opm.terrainPoint.x - opm.placePoint.x, opm.terrainPoint.y - opm.placePoint.y, opm.terrainPoint.z - opm.placePoint.z); gl.glEnd(); } finally { dc.getView().popReferenceCenter(dc); } } /** * Sets the width of the placemark's line during rendering. * * @param dc the current draw context. */ protected void setLineWidth(DrawContext dc) { Double lineWidth = this.lineWidth; if (lineWidth != null) { GL gl = dc.getGL(); if (dc.isPickingMode()) { gl.glLineWidth(lineWidth.floatValue() + linePickWidth); } else gl.glLineWidth(lineWidth.floatValue()); if (!dc.isPickingMode()) { gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_FASTEST); gl.glEnable(GL.GL_LINE_SMOOTH); } } } /** * Sets the color of the placemark's line during rendering. * * @param dc the current draw context. * @param pickCandidates the pick support object to use when adding this as a pick candidate. */ protected void setLineColor(DrawContext dc, PickSupport pickCandidates) { GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. if (!dc.isPickingMode()) { Color color = this.lineColor; gl.glColor4ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue(), (byte) color.getAlpha()); } else { Color pickColor = dc.getUniquePickColor(); Object delegateOwner = this.getDelegateOwner(); pickCandidates.addPickableObject(pickColor.getRGB(), delegateOwner != null ? delegateOwner : this, this.getPosition()); gl.glColor3ub((byte) pickColor.getRed(), (byte) pickColor.getGreen(), (byte) pickColor.getBlue()); } }
将此调用添加到 drawOrderedRenderable 方法的开头:
boolean drawLine = this.isDrawLine(dc, osym); if (drawLine) this.drawLine(dc, pickCandidates, osym);
我相信这密切反映了 PointPlacemark 正在做什么以使线到地形出现,但这是我在运行TacticalSymbols示例时得到的结果:
这是带有我(尝试的)更改的整个 AbsractTacticalSymbol 文件:http://pastebin.com/aAC7zn0p ( 对于 SO 来说太大了)