Jump to content

Editor Plugin with access to IG?


photo

Recommended Posts

Posted

Hi,

I'm trying to create an Editor plugin, which could also access the IG manager. Is this possible?

Adding UnigineIG in the list of plugins loaded by the Editor doesn't work. So, how do the "Tools/Image Generator Plugin/*" actually work, if UnigineIG is not loaded???

Mostly, I need to access the IG Converter, date and time.

Also, how can I know if a component is running inside the Editor or the final app?

Thanks!

Posted

Hello! 

At the moment, there is no way to control the IGEditorPlugin.
Part of the IG code is directly compiled into the editor's plugin with some stubs.
So far, we haven't considered the scenario where someone might create their own tools for the editor with IG.

Could you please clarify your goal? Perhaps I can help you achieve it without direct access to IG.

 

3 hours ago, Amerio.Stephane said:

Mostly, I need to access the IG Converter, date and time.

you can use GeodeticsPlugin API to convert geodetic and world coordinates.

here is code snippet how to initialize geodetic plugin with terrain origin

void Manager::init_geodetic_plugin()
{
	geodetic_plugin = GeodeticsTransformer::get();
	if (!geodetic_plugin)
	{
		Engine::get()->addPlugin("UnigineGeodetics");
		geodetic_plugin = GeodeticsTransformer::get();
	}
	if (geodetic_plugin)
	{
		int epsg = -1;
		String wkt2;
		if (terrain_global)
		{
			if (terrain_global->hasVariable("sandworm_epsg"))
			{
				epsg = terrain_global->getVariable("sandworm_epsg").getInt();
				wkt2 = terrain_global->getVariable("sandworm_projection").getString();
				geodetic_origin = terrain_global->getVariable("sandworm_origin").getDVec3();

				if (!geodetic_plugin->setProjectionEpsg(epsg, geodetic_origin))
				{
					if (!geodetic_plugin->setProjectionWkt(wkt2.get(), geodetic_origin))
					{
						Log::warning("%s: can't set projection epsg %d wkt %s (TerrainGlobal)\n", __UNIGINE_FUNC__, epsg, wkt2.get());
						return;
					}
				}
				geodetic_inited = true;
			}
		} else
		{
			if (terrain_landscape && terrain_landscape->hasVariable("sandworm_epsg"))
			{
				epsg = terrain_landscape->getVariable("sandworm_epsg").getInt();
				wkt2 = terrain_landscape->getVariable("sandworm_projection").getString();
				geodetic_origin = terrain_landscape->getVariable("sandworm_origin").getDVec3();

				if (!geodetic_plugin->setProjectionEpsg(epsg, geodetic_origin))
				{
					if (!geodetic_plugin->setProjectionWkt(wkt2.get(), geodetic_origin))
					{
						Log::warning("%s: can't set projection epsg %d wkt %s (LandscapeTerrain)\n", __UNIGINE_FUNC__, epsg, wkt2.get());
						return;
					}
				}
				geodetic_inited = true;
			}
		}
		if (epsg == -1)
		{
			Log::warning("%s can't find LandscapeLayerMap or ObjectTerrainGlobal with 'sandworm_epsg' variable\n", __UNIGINE_FUNC__);
		}

	} else
	{
		Log::warning("%s: can't initialize GeodeticPlugin\n", __UNIGINE_FUNC__);
	}
}

 

3 hours ago, Amerio.Stephane said:

Also, how can I know if a component is running inside the Editor or the final app?

you can check Editor::isLoaded flag

#include <UnigineEditor.h>

if (Unigine::Editor::isLoaded())
	return;

 

  • Like 1
Posted

I'm trying to move a lot of our component into an editor plugin, so it would be easier to fine tune them. But almost all of them rely on the IG plugin, either for the Converter, or for identifying an Entity. I think this last part is impossible, as an entity is really only created at runtime, so I'll work around it. For the converter, for example, we need to intersect with the terrain and get the real world 'Up', 'East', etc; Also intersecting with the terrain to identify the terrain masks (for rotorwash). Debugging this in runtime is quite time consuming.

Sidenote: a lot of our components have the IG_MASTER_ONLY macro, but this crashes when IG is not loaded. Fine, we'll protect it, but a better code check inside the macro would be better (more readable). Same for IGNetwork component, etc, which all assume the IG plugin is loaded.

Posted

Not sure if GeodeticsTransformer will suit our need.

- Is there something else to do to init it with only the GeodeticPivot in the scene?

- How do I get the in-world North, East, Up vectors {x,y,z} in the 3D world for a given geo (lat,lon,alt) position?

A lot of function are missing, when compared to IG Converter...

Posted
class Converter
{
public:
	static Converter *get()
	{
		static Converter instance;
		return &instance;
	}

	void worldInit()
	{
		geopivot = static_ptr_cast<GeodeticPivot>(World::getNodeByType(Node::GEODETIC_PIVOT));
		is_curved_terrain = terrain_global && terrain_global->findAncestor(Node::GEODETIC_PIVOT) != -1;
	}

	// position
	dvec3 worldToGeodetic(const Vec3 &world_pos) const
	{
		if (geopivot)
		{
			if (is_curved_terrain)
				return geopivot->toGeodetic(translate(world_pos));
			else
				return geopivot->mapFlatToGeodetic(world_pos + Vec3(0, 0, geopivot->getOrigin().z));
		}
		return dvec3(world_pos);
	}

	Vec3 geodeticToWorld(const dvec3 &geo_pos) const
	{
		if (geopivot)
		{
			if (is_curved_terrain)
				return Vec3(geopivot->toWorld(geo_pos).getTranslate());
			else // flat terrain
			{
				dvec3 result = geopivot->mapGeodeticToFlat(geo_pos);
				result.z -= geopivot->getOrigin().z;
				return Vec3(result);
			}
		}
		return Vec3(geo_pos);
	}

	UNIGINE_INLINE Vec3 ENUtoNED(const Vec3 &enu_pos) const { return Vec3(enu_pos.y, enu_pos.x, -enu_pos.z); }
	UNIGINE_INLINE Vec3 NEDtoENU(const Vec3 &ned_pos) const { return Vec3(ned_pos.y, ned_pos.x, -ned_pos.z); }
	UNIGINE_INLINE Vec3 IGtoENU(const Vec3 &ig_pos) const { return coordinate_system == COORDINATE_SYSTEM_ENU ? ig_pos : NEDtoENU(ig_pos); }
	UNIGINE_INLINE Vec3 ENUtoIG(const Vec3 &enu_pos) const { return coordinate_system == COORDINATE_SYSTEM_ENU ? enu_pos : ENUtoNED(enu_pos); }

	UNIGINE_INLINE vec3 ENUtoNED(const vec3 &enu_pos) const { return vec3(enu_pos.y, enu_pos.x, -enu_pos.z); }
	UNIGINE_INLINE vec3 NEDtoENU(const vec3 &ned_pos) const { return vec3(ned_pos.y, ned_pos.x, -ned_pos.z); }
	UNIGINE_INLINE vec3 IGtoENU(const vec3 &ig_pos) const { return coordinate_system == COORDINATE_SYSTEM_ENU ? ig_pos : NEDtoENU(ig_pos); }
	UNIGINE_INLINE vec3 ENUtoIG(const vec3 &enu_pos) const { return coordinate_system == COORDINATE_SYSTEM_ENU ? enu_pos : ENUtoNED(enu_pos); }

	// rotation
	quat getZeroRotation(const dvec3 &geo_pos) const
	{
		if (geopivot)
		{
			if (is_curved_terrain)
			{
				dmat4 transform = geopivot->toWorld(geo_pos);
				return quat(transform);
			} else // flat terrain
			{
				// convert curved rotation to flat (forward.z = 0)
				mat3 rot = mat3(geopivot->toWorld(geo_pos));
				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);
			}
		}
		return quat_identity;
	}
	vec3 getZeroUpDirection(const dvec3 &geo_pos) const
	{
		vec3 up = vec3_up;
		if (geopivot)
		{
			if (is_curved_terrain)
			{
				dmat4 transform = geopivot->toWorld(geo_pos);
				up = vec3(transform.getColumn3(2));
			}
		}
		return up;
	}
	Mat4 getZeroBasis(const dvec3 &geo_pos) const;
	{
		if (geopivot)
		{
			if (is_curved_terrain)
			{
				return Mat4(geopivot->toWorld(geo_pos));
			} else // flat terrain
			{
				// convert curved rotation to flat (forward.z = 0)
				dmat4 transform = geopivot->toWorld(geo_pos);
				dvec3 up = dvec3_up;
				dvec3 forward = transform.getColumn3(1);
				forward.z = 0;
				forward = normalize(forward);
				dvec3 right = cross(forward, up);
				transform.setColumn3(0, right);
				transform.setColumn3(1, forward);
				transform.setColumn3(2, up);
				return Mat4(transform);
			}
		}
		return Mat4(translate(geo_pos));
	}

	quat eulerENUToRotation(const vec3 &euler) const { return quat(composeRotationZYX(euler)); }
	quat eulerNEDToRotation(const vec3 &euler) const
	{
		return quat(0.0f, 0.0f, -1.0f, euler.z) * quat(1.0f, 0.0f, 0.0f, euler.y) * quat(0.0f, 1.0f, 0.0f, euler.x);
	}
	quat eulerIGToRotation(const vec3 &euler) const
	{
		return coordinate_system == COORDINATE_SYSTEM_ENU ? eulerENUToRotation(euler) : eulerNEDToRotation(euler);
	}

	vec3 rotationToEulerENU(const quat &rotation) const { return decomposeRotationZYX(mat3(rotation)); }
	vec3 rotationToEulerNED(const quat &rotation) const
	{
		mat3 t = mat3(rotation);

		vec3 r = vec3_zero;
		if (t.m20 < 1.0f)
		{
			if (t.m20 > -1.0f)
			{
				r.x = -Math::atan2(t.m20, t.m22);
				r.y = Math::asin(t.m21);
				r.z = Math::atan2(t.m01, t.m11);
			} else
			{
				r.x = Math::Consts::PI05;
				r.z = -Math::atan2(-t.m01, t.m02);
			}
		} else
		{
			r.x = -Math::Consts::PI05;
			r.z = Math::atan2(t.m01, -t.m02);
		}
		return r * Math::Consts::RAD2DEG;
	}
	vec3 rotationToEulerIG(const quat &rotation) const
	{ return coordinate_system == COORDINATE_SYSTEM_ENU ? rotationToEulerENU(rotation) : rotationToEulerNED(rotation); }


	UNIGINE_INLINE void setCoordinateSystem(COORDINATE_SYSTEM coord_system) { coordinate_system = coord_system; }
	UNIGINE_INLINE COORDINATE_SYSTEM getCoordinateSystem() const { return coordinate_system; }

private:
	Converter();
	COORDINATE_SYSTEM coordinate_system = COORDINATE_SYSTEM_NED;

	GeodeticPivotPtr geopivot;
	bool is_curved_terrain = false;
};

 

  • Like 1
Posted

wow, that's quite complete now :) Thanks!!!

×
×
  • Create New...