photo

GeodeticPivot inconsistency

Recommended Posts

Hello,

I get some inconsistency when using GeodeticPivot API.

I set up in my world a GeodeticPivot with a FLAT earth, and this coords:

<node type="GeodeticPivot" id="652109397" name="GeodeticPivot">
	<origin_basis>0</origin_basis>
	<origin>43.673721464400003 5.3756460969999997 0</origin>
	<semimajor_axis>6378137</semimajor_axis>
	<flattening>0.0033528106647474822</flattening>
	<variables>
		<flat type="0">1</flat>
	</variables>
	<transform>0.999999940395 0 0 0.0 0 0.999999940395 0 0.0 0 0 0.999999940395 0.0 0 0 0 1.0</transform>
</node>

 (basically, a default GeodeticPivot with custom lat/lon and set to Flat)

When using the API, I get 3 different and inconsistent result:

auto geo = checked_ptr_cast<GeodeticPivot>(World::getNodeByName("GeodeticPivot"));

Mat4 transform = geo->toWorld(Vec3(p.lat, p.lon, p.alt));
p.pos = transform * Vec3(0, 0, 0);
cout << "toWorld: " << p.pos.x << " " << p.pos.y << " " << p.pos.z << endl;

p.pos = geo->mapGeodeticToFlat(Vec3(p.lat, p.lon, p.alt));
cout << "mapGeodeticToFlat: " << p.pos.x << " " << p.pos.y << " " << p.pos.z << endl;

geo->mapGeodeticsToFlat(&(p.lat), &(p.lon), 1, &p.pos.x, &p.pos.y);
p.pos.z = p.alt;
cout << "mapGeodeticsToFlat: " << p.pos.x << " "<<p.pos.y << " " << p.pos.z << endl;

this outputs:

Input: lon=5.3756460970, lat=43.6737214644, alt=333.607
expected:  0.0000 0.0000 333.607

toWorld: 0.0013992 1.10225 333.605                <-- y is very wrong. alt is wrong too (but minor)
mapGeodeticToFlat: -0.207946 -0.268311 333.608    <-- more correct, but not yet there. alt is wrong?
mapGeodeticsToFlat: -0.207946 -0.268253 333.607   <-- y is different now. alt more correct.
  1. The expected result is 0/0/333.607 as the input is exactly the GeodeticPivot center
  2. all three fct should return the same result (the difference can be small, except for toWorld where it can diverge for large values)
  3. is there an API to know if the geodeticpivot is flat or curved?

Thanks for your help!

 

Share this post


Link to post

Hello Stephane,

GeodeticPivot is developed to provide visual curving and GPU-friendliness as the main goal. It defines a flat space which is used for projection and provides translation function which guarantee that origin geo location translates to zero ellipsoid (curved ones) coordinates and up-vector visually directed upward. But it may be not strictly (0,0,1) so it is not guaranteed that (0, 0, altitude) point will be located at the original geo position. That why you've got XY-shift with toWorld function.
It's also apparently not guaranteed that GeodeticPivot has zero flat space coordinates. You can get its flat space coordinates with geo->mapEllipsoidToFlat(Vec3_zero). Although it can be safely assumed that flat coordinates points with same XY coordinates have the same LatLon coordinates.

I hope that clarify things a bit.

If GeodeticPivot is flat can be known with the following snippet

bool is_flat = geodetic_pivot->hasVariable("flat") &&
    geodetic_pivot->getVariable("flat").isInt() &&
    geodetic_pivot->getVariable("flat").getInt();

This is the editor's auxiliary information which is not used at runtime

Share this post


Link to post

Hi Andrey,

To be clear, this post is not about the actual intensity of the delta, but because there is a delta at all! I'm fearing an internal code discrepancy that could lead to much more than a few cm differences and hard to track bugs.

But somewhat it still bothers me inside that mapGeodeticToFlat and mapGeodeticsToFlat returns different results (albeit small differences) when really one is just the same as the other.

Also, if we have to put a static object at the exact same coord of an entity sent by cigi/dis, which function should we call to ensure we get the exact same spot?

Thanks a lot for the explanation, though!

Share this post


Link to post

mapGeodeticToFlat and mapGeodeticsToFlat give different result because input is different. mapGeodeticsToFlat doesn't take into account altitude and mapGeodeticToFlat does. That introduces small inaccuracy

Share this post


Link to post
16 hours ago, Amerio.Stephane said:

Also, if we have to put a static object at the exact same coord of an entity sent by cigi/dis, which function should we call to ensure we get the exact same spot?

these are internal methods from ig

void Entity::calculate_ltp(const dvec3 &geo_pos)
{
  Manager *ig = Manager::get();
  GeodeticPivotPtr geopivot = ig->getGeodeticPivot();
  if (geopivot)
  {
      if (ig->isTerrainCurved()) // curved - terrain under geodetic_pivot //bool curved_terrain = terrain && terrain->findAncestor(Node::GEODETIC_PIVOT) != -1;
      {
          // world, curved terrain
          dmat4 transform = geopivot->toWorld(geo_pos);
          pos = Vec3(transform.getTranslate());
          rot = quat(transform);
      }
      else
      {
          // world, flat terrain
          pos = geopivot->mapGeodeticToFlat(geo_pos);
          pos.z -= geopivot->getOrigin().z;
          rot = Utils::getFlatRotation(geopivot, geo_pos);
      }
    // result transformation will be Mat4 transform = Mat4(rot, pos);
  }
  else 
    //...
}


quat Utils::getFlatRotation(const Unigine::GeodeticPivotPtr &geodetic_pivot, const Unigine::Math::Vec3 &geo_position)
{
	// convert curved rotation to flat (forward.z = 0)
	mat3 rot = mat3(geodetic_pivot->toWorld(geo_position));
	vec3 up = vec3::UP;
	vec3 forward = rot.getColumn(1);
	forward.z = 0;
	forward = normalize(forward);
	vec3 right = cross(forward, up);
	rot.setColumn(0, right);
	rot.setColumn(1, forward);
	rot.setColumn(2, up);
	
	return quat(rot);
}

 

  • Like 1

Share this post


Link to post

Hi cash-metall, thanks a lot for the code sample!

Also, I see there that you test the curved state just by looking at the hierarchy? I guess this is purely a convention? Or did I miss something in the doc?

Thanks!

Share this post


Link to post
1 hour ago, Amerio.Stephane said:

Also, I see there that you test the curved state just by looking at the hierarchy? I guess this is purely a convention? Or did I miss something in the doc?

Terrain, water, clouds and some other types are automatically “curve” if they are children of a geodetic_pivot.

https://developer.unigine.com/en/docs/2.11/objects/geodetics/geodeticpivot/?rlang=cpp#working

Share this post


Link to post