Announcement

Collapse
No announcement yet.

Adding the Sky Gradient to WWJ

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Adding the Sky Gradient to WWJ

    Following on my first try at a renderable layer for WWJ, i'm in the process of porting the Sky Gradient code too... but am having some kind of 'reference center' problem (not seen in the screenshot though).



    The code renders a sphere portion centered on the eye (camera) so that it intersect the globe exactly at the horizon. It is constructed at the origine, rotated to account for the camera position latitude and longitude, and then translated toward the camera.

    This code worked in WW and WW2DPlusOne and it works too in WWJ except the 'sky' sphere position seems to be 'shifted' by some amount and doesnt render in the right position. It gets better when the camera comes close to the ground.

    I'm wrondering if there is some sort of 'floating reference center' that should be accounted for at some point ? tag ?

    Note: i'm expecting some problems with the ellipsoidal globe since the sky geometry is a regular sphere here. I will deal with it after it falls in the right place first.
    Last edited by patmurris; 05-22-2007, 08:34 PM.
    My World Wind Java Blog & WW.net Plugins page

  • #2
    First of all, thank you for your posts! Using the previous one I was able to understand a lot about how to add "things" to the scenario.

    I'm experiencing too some positioning problems. I'm exercising by writing a layer that draw parallels and meridians. I just modified your code and replaced the stars with a mesh. Now I managed to render a spherical grid, but:

    1. the sphere is not centered with the Earth;
    2. I had to use equatorialRadius() * 1.5 to roughly match the Earth radius

    Now I'll try to attach a screenshot.
    Last edited by fabrizio.giudici; 05-22-2007, 08:28 PM.

    Comment


    • #3
      Here it is:

      Comment


      • #4
        I'm glad you could get started with the StarsLayer code
        Does your grid position shift when the camera moves or tilt ?
        Last edited by patmurris; 05-22-2007, 08:35 PM.
        My World Wind Java Blog & WW.net Plugins page

        Comment


        • #5
          Originally posted by patmurris View Post
          I'm glad you could get started with the StarsLayer code
          Does your grid position shift when the camera moves or tilt ?
          I don't know. Indeed it was my very first impression, but then you made me discover that its shifted. So it could be a perspective thing. Now I'll try to manually recenter it and let's see.

          Comment


          • #6
            I've found this method:

            Code:
            Point pos = dc.getGlobe().computePointFromPosition(Angle.fromDegreesLatitude(lat), Angle.fromDegreesLongitude(lon), h);
            which centers correctly the stuff. Strangely enough, I had to set h = 3400000 to fit the Earth size - I expected 0 if it referred to the ASL, or 6349etc if to the center of the planet.

            But there are problems still. Rotating the Earth, the meridians "slide" over the terrain ; if I tilt the view by means of shift+up/down, the grid completely detaches from the Earth

            Comment


            • #7
              Originally posted by fabrizio.giudici View Post
              Rotating the Earth, the meridians "slide" over the terrain ; if I tilt the view by means of shift+up/down, the grid completely detaches from the Earth
              thats what i was refering to by 'floating reference center'...
              We need tag advise here...
              My World Wind Java Blog & WW.net Plugins page

              Comment


              • #8
                Check the Polyline class in geom. It draw GL lines according to points positions (lat/lon/elevation). Cartesian corrdinates are computed with

                Code:
                dc.getGlobe().computePointFromPosition(p.getLatitude(), 
                    p.getLongitude(), p.getElevation());
                It computes a local reference center that is substracted from all vertices coordinates when building the geometry and then is 'pushed' during rendering :

                Code:
                dc.getView().pushReferenceCenter(dc, this.referenceCenter);
                My World Wind Java Blog & WW.net Plugins page

                Comment


                • #9
                  Please post your graticule code and we'll try to help.

                  In order to achieve precision over great distances, most geometry is calculated relative to a local origin. But code that doesn't need to worry about very fine precision doesn't need to concern itself with that. At least we thought we designed it that way.

                  A caution: A graticule is a lot more than lines around the globe. If you simply use lines some distance above the surface, the lines shift relative to the ground as you move. For me, the equator should touch the same ground no matter how I view it. Lines also pierce the terrain unless they're so far off the surface as to miss Mt. Everest, or they follow the terrain, which we implemented but decided was still unacceptable. We know what to do; we just haven't done it yet.

                  Comment


                  • #10
                    Here is my actual version of the sky gradient (zip 3k).
                    I guess the way i compute cartesian coordinates and 'move' the geometry before drawing has something wrong. Maybe i dont use the right values from the current view... see comments in the source.

                    If you can have a look. Thanks.
                    My World Wind Java Blog & WW.net Plugins page

                    Comment


                    • #11
                      I'm not familiar with celestial coordinate systems so I can't verify your math. One thing I do notice, however, is that the order of the transforms you apply is the reverse of the order in which you describe them. OpenGL concatenates left to right: ABCv, where A, B and C are transforms specified in that order and v is the vertex. So in your code that goes:
                      rotate
                      rotate
                      translate
                      OpenGL applies them to vertices as
                      rotate * rotate * translate * vertex
                      The vertex is translated and then rotated, which looks like not what you want. You're also not setting the modelview transform to identity after you push it, so you're concatenating your new transforms with the pre-existing ones. I'm also leary of the code that sets a new view projection. You should not have to do that, and you really have to know what you're doing (and we're doing) to modify it from what the view has already computed. Is the sole purpose to set the far clipping plane back farther? If so, are you sure you need to do that?

                      Comment


                      • #12
                        Originally posted by tag View Post
                        Please post your graticule code and we'll try to help.
                        Great support, thanks! :-) Here's my code, based on patmurris' code for rendering stars.

                        Code:
                        package it.tidalwave.geo.viewer.worldwindprovider.layer;
                        
                        import javax.media.opengl.GL;
                        import gov.nasa.worldwind.DrawContext;
                        import gov.nasa.worldwind.geom.Angle;
                        import gov.nasa.worldwind.geom.Point;
                        
                        public class CartographicGridRenderable extends RenderableSupport
                          {
                            protected double[] computeFrustumLimits (final DrawContext dc) 
                              {
                                // final double r = dc.getGlobe().getEquatorialRadius();
                                final Point center = dc.getGlobe().getCenter();
                                final double near = 1000; 
                                final double far = dc.getView().getEyePoint().distanceTo(center);
                                return new double[]{ near, far };
                              }
                        
                            protected void createGList (final DrawContext dc, final GL gl)
                              {
                                float Vdec = 0.9f;
                                float hhh = 3300000 + 400000; // 3400000;
                                for (double lat = -80; lat <= 80; lat += 5)
                                  {
                                    gl.glBegin(GL.GL_LINE_STRIP);
                                    gl.glColor3f((float)Vdec, (float)Vdec, (float)0); 
                                    
                                    for (double lon = -180; lon < 180; lon += 1)
                                      {
                                        final Point pos = dc.getGlobe().computePointFromPosition(Angle.fromDegreesLatitude(lat), Angle.fromDegreesLongitude(lon), hhh);
                        //                final Point pos = dc.getSurfaceGeometry().getSurfacePoint(Angle.fromDegreesLatitude(lat), Angle.fromDegreesLongitude(lon));
                                        gl.glVertex3d(pos.getX(), pos.getY(), pos.getZ());
                                      }
                                    
                                    gl.glEnd();
                                  }
                        
                                for (double lon = -180; lon <= 180; lon += 5)
                                  {
                                    gl.glBegin(GL.GL_LINE_STRIP);
                                    gl.glColor3f((float)Vdec, (float)Vdec, (float)0); 
                                    
                                    for (double lat = -80; lat <= 80; lat += 1)
                                      {
                                        final Point pos = dc.getGlobe().computePointFromPosition(Angle.fromDegreesLatitude(lat), Angle.fromDegreesLongitude(lon), hhh);
                        //                final Point pos = dc.getSurfaceGeometry().getSurfacePoint(Angle.fromDegreesLatitude(lat), Angle.fromDegreesLongitude(lon));
                                        gl.glVertex3d(pos.getX(), pos.getY(), pos.getZ());
                                      }
                                    
                                    gl.glEnd();
                                  }
                              }
                          }
                        
                        package it.tidalwave.geo.viewer.worldwindprovider.layer;
                        
                        import javax.media.opengl.GL;
                        import gov.nasa.worldwind.DrawContext;
                        import gov.nasa.worldwind.Renderable;
                        import gov.nasa.worldwind.geom.Point;
                        
                        public abstract class RenderableSupport implements Renderable
                          {
                            protected int glListId = -1;
                              
                            public void render (final DrawContext dc) 
                              {
                                if (glListId == -1)
                                  {
                                    makeGList(dc);
                                  }
                                
                                final GL gl = dc.getGL();
                                gl.glPushAttrib(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT
                                                | GL.GL_POLYGON_BIT | GL.GL_TEXTURE_BIT | GL.GL_ENABLE_BIT
                                                | GL.GL_CURRENT_BIT);
                                gl.glPushMatrix();
                                    
                                try
                                  {
                                    gl.glDisable(GL.GL_TEXTURE_2D);     
                                    gl.glDisable(GL.GL_DEPTH_TEST);      
                                    gl.glMatrixMode(GL.GL_PROJECTION);
                                    gl.glLoadIdentity();
                                    double limits[] = computeFrustumLimits(dc);
                                    dc.getGLU().gluPerspective(dc.getView().getFieldOfView().degrees,
                                                    dc.getView().getViewport().getWidth() / dc.getView().getViewport().getHeight(),
                                                    limits[0], limits[1]);
                                    gl.glCallList(glListId);
                                  }
                                 
                                finally
                                  {
                                    gl.glPopMatrix();
                                    gl.glPopAttrib();
                                  }
                              }
                            
                            abstract protected void createGList (final DrawContext dc, final GL gl);
                            
                            abstract protected double[] computeFrustumLimits (final DrawContext dc);
                            
                            private void makeGList (final DrawContext dc)
                              {
                                GL gl = dc.getGL();
                                glListId = gl.glGenLists(1);
                                // FIXME: what about garbaging the old one? 
                                gl.glNewList(glListId, GL.GL_COMPILE);
                                createGList(dc, gl);
                                gl.glEndList();      
                              }
                          }

                        Comment


                        • #13
                          polyline grid

                          You don't need to define a new layer type to do what you are trying to do. Just use RenderableLayer and Polyline, like this (screenshot attached):

                          RenderableLayer shapeLayer = new RenderableLayer();

                          // Generate meridians
                          ArrayList<Position> positions = new ArrayList<Position>(3);
                          for (double lon = -180; lon < 180; lon += 10)
                          {
                          Angle longitude = Angle.fromDegrees(lon);
                          positions.clear();
                          positions.add(new Position(Angle.NEG90, longitude, 10e3));
                          positions.add(new Position(Angle.ZERO, longitude, 10e3));
                          positions.add(new Position(Angle.POS90, longitude, 10e3));
                          Polyline polyline = new Polyline(positions);
                          polyline.setNumEdgeIntervals(36);
                          shapeLayer.addRenderable(polyline);
                          }

                          // Generate parallels
                          for (double lat = -85; lat < 90; lat += 10)
                          {
                          Angle latitude = Angle.fromDegrees(lat);
                          positions.clear();
                          positions.add(new Position(latitude, Angle.NEG180, 10e3));
                          positions.add(new Position(latitude, Angle.ZERO, 10e3));
                          positions.add(new Position(latitude, Angle.POS180, 10e3));
                          Polyline polyline = new Polyline(positions);
                          polyline.setNumEdgeIntervals(36);
                          shapeLayer.addRenderable(polyline);
                          }

                          // Insert the layer into the layer list just before the compass.
                          int compassPosition = 0;
                          LayerList layers = this.wwd.getModel().getLayers();
                          for (Layer layer : layers)
                          {
                          if (layer instanceof CompassLayer)
                          compassPosition = layers.indexOf(layer);
                          }
                          layers.add(compassPosition, shapeLayer);
                          }

                          This is not the best way to draw a global, elevated grid. Ideally you'd create one ring and instantiate it with a transform for each circle. But an interface deficiency in the current release prevents doing that cleanly. On the upside, doing it with the code above makes each line individually pickable, if that's of value to your application.

                          I'm noticing that people are jumping immediately to implementing a layer to incorporate new functionality. I'm guessing that this is a holdover from WW.Net, where that's what you had to do. But we're designing the WWJ API to avoid the need for that in many cases. So rather than creating a new layer type, first try to see if you can do what you want by, for instance, adding shapes to RenderableLayer. The built-in shapes give you features that you'll want but won't want to duplicate, such as polygon and line edges that follow great circles rather than straight lines, and selection (picking).

                          I still don't understand the original problem of "sliding." My guess is that you are seeing the problem I described earlier: elevated graticule lines will appear to shift when you look at them from different directions. This is simply because they are fixed 3D geometry placed above the surface, like a bridge, and have no special semantics that makes them behave as you'd want graticule lines to behave.

                          Comment


                          • #14
                            Thank you for the reply, I'll try it tomorrow.

                            For what concerns your doubts, I'm aware of the perspective errors and such, but what I was seeing was something much more dramatic. In any case, let's see what happens with the new code.

                            Comment


                            • #15
                              Thanks a lot tag for taking the time and posting your comments.

                              I'll have to assimilate a couple things... i've always had a hard time figuring the transforms order - not mentioning which axes to rotate and which way I guess i got lucky to see anything at all using them in reverse order!

                              About 'extending' the far clipping plane... how should one proceed if need be ?
                              My World Wind Java Blog & WW.net Plugins page

                              Comment

                              Working...
                              X