Amerio.Stephane Posted June 26, 2020 Share Posted June 26, 2020 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. The expected result is 0/0/333.607 as the input is exactly the GeodeticPivot center all three fct should return the same result (the difference can be small, except for toWorld where it can diverge for large values) is there an API to know if the geodeticpivot is flat or curved? Thanks for your help! Link to comment
andrey-kozlov Posted July 2, 2020 Share Posted July 2, 2020 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 Link to comment
Amerio.Stephane Posted July 2, 2020 Author Share Posted July 2, 2020 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! Link to comment
andrey-kozlov Posted July 2, 2020 Share Posted July 2, 2020 mapGeodeticToFlat and mapGeodeticsToFlat give different result because input is different. mapGeodeticsToFlat doesn't take into account altitude and mapGeodeticToFlat does. That introduces small inaccuracy Link to comment
cash-metall Posted July 3, 2020 Share Posted July 3, 2020 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); } 1 Link to comment
Amerio.Stephane Posted July 3, 2020 Author Share Posted July 3, 2020 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! Link to comment
cash-metall Posted July 3, 2020 Share Posted July 3, 2020 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 Link to comment
Recommended Posts