2016-06-18 35 views
7

Worldwind za punkt Placemark renderable posiada funkcję Aby usunąć linię z oznaczenia miejsca do terenu poprzez wywołanie setLineEnabled jak w tym zrzucie:Worldwind Linia od symbolu do Terrain

enter image description here

Co Próbuję do jest dodanie takiej linii, która działa również z możliwym do renderowania symbolem taktycznym. Moją pierwszą myślą było po prostu pożyczyć logikę, aby to zrobić z możliwego renderowania PointPlacemark i dodać go do renderowalnej wersji AbstractTacticalSymbol. Próbowałem tego i jak dotąd nie udało mi się.

Oto co zrobiłem do tej pory:

  1. dodanych w tym do OrderedSymbol Klasa:

    public Vec4 terrainPoint; 
    
  2. Zaktualizowane computeSymbolPoints obliczyć 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. dodanych w tym logika (pobrana z PointPlacemark.java i zaktualizowana dla complian ce do AbstractTacticalSymbol.java). Zauważ, że ustawiłem lineEnabled na true, więc domyślnie powinien on narysować linię.

    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. Dodany to wezwanie do początku metody drawOrderedRenderable:

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

Wierzę, że ta ściśle odzwierciedla co PointPlacemark robi, aby uzyskać linię do stawienia teren, ale to, co mam kiedy uruchomić przykład TacticalSymbols z moimi zmianami:

enter image description here

Oto cały plik AbsractTacticalSymbol z moich (prób) zmian: http://pastebin.com/aAC7zn0p (jej zbyt duże dla SO)

Odpowiedz

5

Ok, więc tutaj problemem jest mieszanie między ortograficznych i perspektywy projekcji w ramach. Co najważniejsze, jeśli spojrzymy na PointPlaceMark za beginDrawing widzimy:

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); 
} 

to wszystko. Ale jeśli spojrzymy na AbstractTacticalSymbol na beginDrawing widzimy dużo więcej kodu, w szczególności te dwie linie:

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

Które przełączyć projekcję OpenGL z perspektywy do trybu ortogonalnego, dwa dziko różnych technik projekcyjnych, które nie mieszają się bardzo no, z wyjątkiem kilku ważnych przypadków: jednego z nich renderowania interfejsu użytkownika na scenie 3D, na przykład: renderowania ikon! video showing the difference between orthographic and perspective rendering

Uważam, że nie jest to łatwe do wyjaśnienia w słowach, ale renderowanie perspektywiczne daje perspektywę, a rendering ortograficzny nie, więc dostajesz coś podobnego do gry 2D, która działa dobrze dla interfejsu użytkownika, ale nie dla realistycznych obrazów 3D .

Ale PointPlaceMark renderuje również ikonę, więc gdzie ten plik przełącza się między dwoma trybami projekcji?Okazuje się, że robią to w doDrawOrderedRenderablepo dzwoniąc pod numer drawLine (wiersz 976).

A więc dlaczego to się nie zgadza? Teraz w ramach jest dużo magii, więc nie mam pewności, co się stanie, ale mam szeroki pomysł, co jest nie tak. Źle się dzieje, ponieważ projekcja perspektywiczna pozwala na dostarczanie współrzędnych w szalenie różny sposób do rzutu prostopadłego (w ramach), w tym przypadku być może dostarczenie (x, y, z) do renderowania rzutowania renderuje punkt (X, Y, Z) przestrzeń światowa, podczas gdy renderowanie ortograficzne renderuje na (x, y, z) przestrzeni ekranu (lub przestrzeni klipów, nie jestem w tym zawodowcem). Kiedy narysujesz teraz linię od ikony do ziemi, na współrzędnych (300000,300000, z), będą one oczywiście wypadały z ekranu i nie będą widoczne, ponieważ nie masz ekranu o 300000 x 3000000 pikseli . Możliwe też, że oba podejścia umożliwiają dostarczanie współrzędnych w przestrzeni świata (choć wydaje się to mało prawdopodobne), w tym przypadku obraz poniżej ilustruje problem. Obie kamery są skierowane w tym samym kierunku w polach poniżej, ale widzą różne rzeczy.

Perspective vs Orthographic Zwróć szczególnie uwagę, w jaki sposób renderowanie perspektywiczne pozwala zobaczyć znacznie więcej pól.

Tak, ponieważ kod renderowania rozpoczyna się w rzucie perspektywicznym w metodzie render(), ustalenie to jest tak proste, jak opóźnianie ortograficznego rzutu zacząć po mamy narysowane linię, podobnie jak w kodzie PointPlaceMark użytkownika. To jest dokładnie to, co robię here (linie od 1962 do 1968), to po prostu przesuwanie kilku linii kodu poza ortograficzną projekcją, więc przed beginDrawing prawie skończyłeś.

Teraz to rozwiązanie nie jest zbyt eleganckie, ponieważ funkcjonalność kodu zależy teraz w dużej mierze od kolejności, w jakiej jest wykonywany, co generalnie jest bardzo podatne na błędy. Częściowo jest to spowodowane prostą poprawką, którą stworzyłem, ale głównie dlatego, że framework jest zgodny z przestarzałymi standardami OpenGL do zmiany perspektywy (między innymi), więc nie mogę stworzyć naprawdę doskonałego rozwiązania, niezależnie od tego, czy takie rozwiązanie byłoby w moim umiejętności.

W zależności od swoich preferencji możesz chcieć pracować z dziedziczeniem, aby utworzyć nadklasę lub interfejs SymbolWithLine lub pracować z kompozycją, aby dodać tę funkcję. Lub możesz zostawić to tak, jeśli nie będziesz potrzebować tej funkcjonalności w wielu innych klasach. W każdym razie mam nadzieję, że to wystarczająca ilość informacji, aby rozwiązać ten problem.

jak na swój wniosek, następujące linie pokazują, szerokość linii i linia zmienia kolor (line 1965):

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

Line color and width

Updated code for AbstractTacticalSymbol

Nie jestem pewien, czy ten kwalifikuje jako "odpowiedź kanoniczna", ale z chęcią zaktualizuję odpowiedź dowolnymi sugestiami lub wyjaśnię nieco więcej moich wyjaśnień. Myślę, że sedno odpowiedzi leży w zrozumieniu projekcji odwzorowania ortograficznego i perspektywicznego, ale nie jest to miejsce, w którym mogę odpowiedzieć na to pytanie kanonicznie.

+2

Dziękujemy za spojrzenie. Właśnie tego szukałem (zrzut ekranu) - wraz z możliwością kontrolowania szerokości i koloru linii. Jeśli nie masz nic przeciwko, wyjaśnisz zmiany, które trzeba wprowadzić? – systemoutprintln

+0

Zaktualizowałem swoją odpowiedź z wyjaśnieniem. – TWT

+3

To wyjaśnienie pomaga niezmiernie. Jeszcze raz dziękuję. – systemoutprintln