Geode and GeoTransform placement

classic Classic list List threaded Threaded
19 messages Options
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Geode and GeoTransform placement

I am working with drawing various different 3D shapes in our modeling software and I am struggling with what is and is not possible with these different structures. I have used both osgEarth::Geometry and osg::Geometry (now LineDrawable) to try and draw things. Our software uses openGL currently and porting things over using the same methods is what we have decided on so, with that in mind I have been using this parent and child structure:

GeoTransform (top level) > MatrixTransform (when needed) > Geode > LineDrawable > Vec3Array (vertices)

I have been taking the SpatialReference MapNode->getMapSRS()->getGeogaphicSRS() and using that as part of a GeoPoint for GeoTransform->setPosition(). What I want to know is is there way to not need the GeoTransform and to only use the LineDrawable + Geode to set the position of things on our MapNode? And if so what coordinate system is it in? My understanding is using the GeoTransform makes all the points in the LineDrawable relative to its position in its specified SRS. The ability to use straight ECEF coordinates is really the end goal. If that can be achieved with the GeoTransform or without and how is what I would like to know.
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Miles,

In the default configuration (a WGS84 globe) the coordinate system is indeed ECEF. You can use a LineDrawable directly without any transforms if you want, but...

Modern graphics hardware is limited to 32-bit vertex positions, which gives you about 7 significant digits of precision. ECEF coordinates are large enough that they require more than that to be accurate; so when the GPU does its calculations, the lack of precision causes visual problems. It looks like your geometry is "jittering" when you move the camera.

If you intend to only view the data from a distance (like from orbit) you might get away with it. The problem gets worse the closer you zoom in.

CPU-side transforms that localize the data around a reference point solve this problem.

Good luck!
Glenn Waldron / Pelican Mapping
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

First, if I wanted to use just a LineaDrawable (or osg::Geomeetry) as a child to a Geode and add that to a MapNode, it assumes ECEF as the coordinates from vertices then? Just want to be sure on this.

Second, in regards to the visual problems, currently when I am drawing some curved lines they are showing up as squiggles rather than straight. I have attached images below of how I expect it to look (left) and how it is looking (right) using the GeoTransformed LineDrawables. Any idea what the issue could be? And if looking at code would help I can post that as well.
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Miles,

Yes. The coordinate system at the MapNode is ECEF.

By the way, you do not need a Geode. You can use LineDrawable (or any osg::Geometry) directly. The requirement to parent drawables with Geode was remove from OSG several versions ago.

The visual anomaly is vertex jitter due to limited GPU precision. Use a transform (MatrixTransform, GeoTransform, etc.) with localized coordinates to resolve.

Hope this helps.
Glenn Waldron / Pelican Mapping
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

I tried what you said about lowering the number of digits by taking our ECEF coordinates from meters to kilometers and adjusting the scaling accordingly but it did not make a difference for the "jitter". What did make a difference, however, was changing the line width. Here is the code of what I am doing to see if you can tell what the problem may be stemming from. Also anything I am doing that could be streamlined in any way I will gladly accept as advice:

const SpatialReference *GeoSRS = MapNodePtr->getMapSRS ()->getGeographicSRS ();
GeoTransform *Sensor = new GeoTransform ();
osg::Geode *SensorGeode = new osg::Geode ();
LineDrawable *Lines= new LineDrawable ();
osg::Vec3Array *Verts= new osg::Vec3Array ();

for (i=0; i < NumArcPts; i++)
   {
   Verts->push_back (osg::Vec3 (ECEF[i].X, ECEF.[i]Y, ECEF[i].Z));
   }

osg::Vec4Array *Color = new osg::Vec4Array ();
Color->push_back (osg::Vec4 (0.0, 1.0, 0.0, 1.0));
Lines->setVertexArray (Verts);
Lines->setColorBinding (osg::Geometry::BIND_OVERALL);
Lines->addPrimitiveSet (new osg::DrawArrays (GL_LINE_STRIP, 0 Verts->size()));
Lines->setLineWidth (1); //The higher this number, the more wavy the lines become
SensorGeode->addChild (Lines);
Sensor->addChild (SensorGeode);
Sensor->setPosition (GeoPoint (GeoSRS, Lon, Lat, Alt));
Sensor->getOrCreateStateSet ()->setRenderBinDetails (10, "DepthSortedBin");
Sensor->getOrCreateStateSet ()->setMode (GL_BLEND, 1);
MapNodePtr->addChild (Sensor);

Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

I didn't tell you to reduce the number of digits. Shifting the decimal point doesn't give you more precision. You need to localize vertex coordinates under a double-precision Transform.
Glenn Waldron / Pelican Mapping
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

I was always using a GeoTransform is the thing here. So these points are already being localized from there. Is there a different type of Transform I need to be using? And even besides that, why would changing the line width have such an effect on the way the lines are drawn/viewed?
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Any answer I get can for the above questions? I currently do not have jittery lines but want to know what the reason for how I fixed it means.
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Don't know the answer, sorry.
If you post a complete .cpp reproducing the issue, someone can take a look at it - thanks.
Glenn Waldron / Pelican Mapping
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

I have created a small program to illustrate what was happening with this. I have a control case for both a straight line and a curve with the Line Width set to 1 and then a set of both with it set to 10.

The straight line case does not exhibit the wavy line effect, but when zooming out it begins to spin rather than stay in place. The curve case exhibits the same behavior I am having in my actual build which is the lines become wavy, more overt the larger the line width is. In either case, I cannot be sure the lines are a different width at all. This is an issue I need either fixing or an explanation/workaround for osgEarth to work for our program.

Thanks!

LineTest.cpp
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Miles,
Your cpp crashes on startup.

Never call setColorArray, setVertexArray, etc. on a LineDrawable. All that is handled internally. I suppose we should hide those from the API.

Use setColor, pushVertex, et al. instead. If you want to being in an external vertex array, you can call importVertexArray().
Glenn Waldron / Pelican Mapping
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

It ran for me before I sent it over, so I am not sure what happened there. It would need all the osgearth libraries and 3rd parties, but otherwise it is a simple program.

I attempted to use pushVertex before actually to replace needing to use osg::Vec3Arrays at all, but when it pushed vertices it did it 4 times in a row when I debugged it for some reason. Have you ever heard of that happening? If I can recreate it I will pass it along to you in a cpp as well. SetColor did not seem to work for me either because I had errors during compile using setColorBinding.
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Using ImportVertexArray did fix the wavy line issue (and actually changes the line thickness) though so I am good on this issue now.

Thanks!
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

In reply to this post by Miles
That is the correct behavior. Each vertex is pushed onto the array 4 times. The shader needs duplicate verts per point because of the way it expands them into screen-space triangles at render time.
Glenn Waldron / Pelican Mapping
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

In reply to this post by Miles
Hello.

Turns out this solution worked for my small test case, but not quite what I was hoping for my main work. I had initially misunderstood that importVertexArray worked just like pushVertex. This cannot work for me, unless there are workarounds you know of for assessing the vertex points like they are not quadrupled. How exactly would you draw a triangle strip when you have 4x as many vertex points per spatial point since a triangle strip works by drawing 3 adjacent points and then using the 2 latter points in addition to the next one in the list of vertices. With your 4x point implementation that is not possible. Even if I could get to the last value of 4 the next point points will inevitably be the same which is useless, it will just draw lines and never fill correctly. You may end up with all the triangles visually, but because individually none of them are actually triangles, it will not display correctly.
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Miles,

You can access an individual point on the line by calling getVertex() or setVertex().

I guess I don't understand what you are trying to do. LineDrawable draws lines. Not triangle strips or filled primitives. What am I missing?

Glenn Waldron / Pelican Mapping
2LR 2LR
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

In reply to this post by Miles
Just to chime in here...

importVertexArray() isn't designed to be used on a per vertex basis like pushVertex(). You usually work on an osg::Vec3Array object and then use importVertexArray() to place the array into the LineDrawable object.

Secondly, importVertexArray() isn't applicable to polygons so the comment regarding triangle strips is superfluous to the discussion at hand. importVertexArray() is only applicable to LineDrawable and PointDrawable classes...

Shayne
Miles Miles
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

In reply to this post by gwaldron
This is the structure of my pieces I am trying to draw:

Vec3Array->push_back(Vec3 Point); //How every many points there are
LineDrawable->setVertexArray(Vec3Array);
LineDrawable->addPrimitiveSet (new osg::DrawArrays (GL_LINE_STRIP, 0, Vec3Array->size()));
GeoTransform->addChild(LineDrawable);

In the Primitive Set we changed the DrawArrays input variables to be GL_TRIANGLE_STRIP, GL_LINE_LOOP, GL_POLYGON and GL_QUADS. We also use loops to set the beginning vertex and size variables depending on what points we want to use. But having duplicates makes that impossible. So is there another object besides LineDrawable you would suggest using in order to gain the same ability we currently have to not have 4x the vertices whilst also having the ability to set the Line Width correctly like pushVertex/importVertexArray do?
Using osgEarth to create a full functioning 3D modelling apparatus for simulation with TBE.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Geode and GeoTransform placement

Miles,

LineDrawable draws lines. Not tristrips, not polygons, and not quads. Just lines. If you want to draw that other stuff, use an osg::Geometry.

If you DO want to draw lines, push your verts and go. You can call setFirst() and setCount() to offset which part of the line string/loop you want to draw. If you make a change, call dirty() to refresh the rendering. That is all -- no primitive sets, no vertex arrays, no worrying about the internal layout.

lineDrawable->pushVertex(...); // add all your verts.
GeoTransform->addChild(lineDrawable);

In fact, I recently pushed an update to LineDrawable that restricts access to all the underlying structures since they are internal and should never be messed with.

The proper usage of LineDrawable is demonstrated in the osgearth_drawables.cpp example. Please study the code there for more guidance.
Glenn Waldron / Pelican Mapping