2016-06-18 3 views
7

Worldwind의 포인트 장소의 렌더링 가능한이 스크린 샷으로 setLineEnabled를 호출하여 지형 아래로 위치 표시에서 선을 드롭 할 수있는 기능이 있습니다Worldwind 라인 지형

enter image description here

내가 노력하고있어를 Tactical Symbol 렌더링과 함께 작동하는 이와 같은 라인을 추가하십시오. 내 첫 번째 생각은 PointPlacemark 렌더링에서이 작업을 수행하는 로직을 빌려서 AbstractTacticalSymbol 렌더링 가능에 추가하는 것입니다. 나는 그것을 시도하고 나는 지금까지 성공적이지 못했다.

  1. 추가를 OrderedSymbol 클래스에이 :

    public Vec4 terrainPoint; 
    
  2. 업데이트 computeSymbolPoints이 terrainPoint

    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); 
    
    } 
    
  3. 추가 된이를 계산하기 위해 여기

    내가 지금까지 한 일이다 논리 (PointPlacemark.java에서 가져 와서 준수하도록 업데이트 됨) ce to 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()); 
        } 
    } 
    
  4. 추가 drawOrderedRenderable 방법의 시작이 호출 :

    boolean drawLine = this.isDrawLine(dc, osym); 
    if (drawLine) 
        this.drawLine(dc, pickCandidates, osym); 
    

나는이 밀접 PointPlacemark 지형 표시에 선을 얻기 위해 무엇을하고 있는지 반영 생각하지만, 이것은 무엇이다 변경 사항이 적용된 TacticalSymbols 예제를 실행하면 다음과 같이 표시됩니다.

enter image description here

답변

5

확인 http://pastebin.com/aAC7zn0p (SO에 대한 너무 큰), 그래서 여기에 문제는 프레임 워크 내에서 직교과 관점 돌출부 사이의 혼합입니다 : 10

은 여기 내 (시도) 변경 전 AbsractTacticalSymbol 파일입니다. 우리가 PointPlaceMark의 beginDrawing를 보면 결정적으로, 우리는 다음을 참조하십시오 그것 뿐이다

GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. 

int attrMask = 
     GL2.GL_DEPTH_BUFFER_BIT // for depth test, depth mask and depth func 
      ... bunch more bits being set ... 

gl.glPushAttrib(attrMask); 

if (!dc.isPickingMode()) 
{ 
    gl.glEnable(GL.GL_BLEND); 
    OGLUtil.applyBlending(gl, false); 
} 

합니다. 매우 혼합하지 않는 직교 모드, 두 격렬하게 다른 투사 기술에 관점에서 OpenGL을 투영을 전환

this.BEogsh.pushProjectionIdentity(gl); 
gl.glOrtho(0d, viewport.getWidth(), 0d, viewport.getHeight(), 0d, -1d); 

: 우리가 AbstractTacticalSymbol의 beginDrawing를 보면하지만 우리는 특히이 두 줄, 훨씬 더 많은 코드를 볼 수 글쎄, 몇 가지 주목할만한 경우를 제외하고 : 그들 중 하나는 3D 장면을 통해 UI를 렌더링, 예를 들면 : 렌더링 아이콘! video showing the difference between orthographic and perspective rendering

단어로 설명하는 것이 어색하지만 원근감 렌더링은 원근감을 제공하고 정사각형 렌더링은 제공하지 않으므로 2D 게임과 비슷한 것을 얻을 수 있습니다. 2D 게임은 UI에서는 잘 작동하지만 사실적인 3D 이미지에는 적합하지 않습니다. .

그러나 PointPlaceMark도 아이콘을 렌더링하므로 해당 파일은 두 투영 모드를 어디에서 전환합니까?그들이 drawLine (라인 976) 전화 후 그 밝혀졌습니다.

그럼 왜 잘못 될까요? 이제는 프레임 워크 내부에서 많은 마법이 진행되므로 어떤 일이 발생하는지 정확히 알 수는 없지만 잘못된 점에 대해서는 광범위한 생각을 가지고 있습니다. 원근 투영을 사용하면 투영 렌더링에 (x, y, z)를 제공하면 (X, Y, Z) 점을 렌더링하는 투영법이 정육면 투영 (프레임 워크에서)과 크게 다른 방식으로 좌표를 제공 할 수 있기 때문에 잘못되었습니다.) 세계 공간, 정사영 렌더링은 (x, y, z) 화면 공간 (또는 클립 공간, 나는 이것을 프로가 아닙니다)에서 렌더링합니다. 따라서 좌표 (300000300000, z)에서 아이콘에서지면으로 선을 그릴 때 300,000x3000000 픽셀의 화면이 없으므로 화면에서 벗어나 보이지 않게됩니다 . 두 가지 방법 모두 좌표가 세계 공간에서 제공되도록 허용 할 수도 있습니다. (이 경우는 그렇지 않겠지 만)이 경우 아래 그림은 문제를 보여줍니다. 두 카메라는 아래 상자에서 같은 방향을 가리키고 있지만 다른 것을 보게됩니다.

Perspective vs Orthographic 특히 원근감 렌더링을 사용하면 훨씬 많은 상자를 볼 수 있습니다. 렌더링 코드가 고정의 render() 방법에 원근 투영에서 시작하기 때문에

그래서, 이것은 우리가 PointPlaceMark의 코드와 같은 라인을 그려 한 후 을 시작 직교 투영을 지연만큼 간단합니다. 그게 정확히 here (1962 ~ 1968 행)입니다. 직교 투영 외부에서 몇 줄의 코드를 움직이는 것이므로 beginDrawing 전에 거의 완료되었습니다.

이제 코드의 기능이 실행 순서에 크게 좌우되기 때문에이 솔루션은 그리 우아하지 않습니다. 일반적으로 오류가 발생하기 쉽습니다. 이것은 부분적으로는 내가 만든 간단한 수정 때문이지만, 프레임 워크가 (다른 것들 중에서) 원근감 전환을위한 비추천 OpenGL 표준을 준수하기 때문에 대부분 솔루션이 내 시스템 내부에 있는지 여부에 관계없이 진정한 솔루션을 만들 수 없습니다. 능력.

선호도에 따라 상속을 사용하여 SymbolWithLine 수퍼 클래스 또는 인터페이스를 만들거나 기능을 추가하기 위해 작곡 작업을 할 수 있습니다. 또는이 기능을 다른 많은 클래스와 함께 사용할 필요가없는 경우에도 이와 같이 둘 수 있습니다. 어쨌든이 문제가 해결 될 수있는 충분한 정보가되기를 바랍니다.

this.lineColor = Color.CYAN; 
this.lineWidth = 3; 
this.drawLine(dc, this.pickSupport, osym); 

Line color and width

Updated code for AbstractTacticalSymbol

나는이 자격이 있는지 확실하지 않다 :

는 귀하의 요청에 따라, 다음 라인은 라인 폭과 라인 색상 변경을 (1965 선) 보여 "정식 답변"이라고 말하면서, 나는 어떤 제안이라도 대답을 업데이트하거나 내 설명을 좀더 명확히 해줄 수있어서 기쁘다. 나는 답의 핵심은 정사영 대 투시 투영에 대한 이해에 있다고 생각하지만 이것은 실제로 그 질문에 대한 정식 답변을위한 장소가 아니라고 생각합니다.

+2

감사합니다. 이것은 정확히 내가 뭘 찾고 있었는지 (스크린 샷) - 라인 너비와 색상을 제어하는 ​​능력과 함께. 괜찮으 시다면 변경해야 할 사항을 설명해주십시오. – systemoutprintln

+0

내 대답을 설명으로 업데이트했습니다. – TWT

+3

그 설명은 대단히 도움이됩니다. 다시 감사합니다. – systemoutprintln