Jump to content

IG CIGI Symbols


photo

Recommended Posts

Hi,

Could you provide an detailed example of the content of CIGI messages to be sent in order to display CIGI symbols (text and lines)?

I tried displaying text and lines with HEmu by sending Symbol Surface Definition, Symbol Control, Symbol Text and Symbol Line. I tried both View attached and Entity attached, but no symbol was displayed (2.13.1 and 2.15.1).

Thanks!

Link to comment

That doesn't look like it, but maybe I'm wrong. Frsit, we are using plain CIGI message to (try to) draw symbol surfaces, no code here. And this is with a brand new project IG project, no user code at all.

For example, trying to draw a red diagonal line over the viewport should be:

image.thumb.png.02f4abb38ff375ccc5c2504b03591dcf.png

But nothing is visible.

When trying to draw text with 

image.png.d907042eef38059aab4c468beda516b1.png

I also get nothing, and a warning message in the cmd window:

CigiThread::process(): can't create Host packet (OPCode: 0)
packet type 0(0bytes) prev packet 30(24bytes) src_size 224

 

So... Could you please show us a sequence of CIGI messages that produces a symbol on screen (text and lines). I must be missing something obvious?

Thanks!

Link to comment

Hello! 

at the moment cigi connector does not read symbol messages - this is a bug.

you can try to read and send via api

// AppSystemLogic.h
//...
  	// cigi
	void init_cigi();
	Unigine::Plugins::IG::CIGI::Connector *cigi;
	void symbol_surface_def(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
	void symbol_text_def(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
	void symbol_circle_def(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
	void symbol_line_def(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
	void symbol_clone(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
	void symbol_control(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
	void symbol_short_control(Unigine::Plugins::IG::CIGI::CigiHostPacket* packet);
//...

// AppSystemLogic.cpp
using namespace Unigine;
using namespace Plugins;
using namespace Math;
using namespace IG;
// ...
void AppSystemLogic::init_cigi()
{
	int index = Engine::get()->findPlugin("CIGIConnector");

	// check CIGIConnector plugin load
	if (index < 0)
		return;

	// get CIGI interface
	cigi = IG::CIGI::Connector::get();


	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_SURFACE_DEF, MakeCallback(this, &AppSystemLogic::symbol_surface_def));
	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_CIRCLE_DEF, MakeCallback(this, &AppSystemLogic::symbol_circle_def));
	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_CLONE, MakeCallback(this, &AppSystemLogic::symbol_clone));
	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_CONTROL, MakeCallback(this, &AppSystemLogic::symbol_control));
	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_LINE_DEF, MakeCallback(this, &AppSystemLogic::symbol_line_def));
	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_SHORT_CONTROL, MakeCallback(this, &AppSystemLogic::symbol_short_control));
	cigi->addOnReceivePacketCallback(CIGI::CIGI_OPCODE_SYMBOL_TEXT_DEF, MakeCallback(this, &AppSystemLogic::symbol_text_def));
}

void AppSystemLogic::symbol_surface_def(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	Plugins::IG::CIGI::CigiSymbolSurfaceDef *def = dynamic_cast<Plugins::IG::CIGI::CigiSymbolSurfaceDef *>(packet);
	if (def == nullptr)
		return;
	SymbolsPlane *plane = nullptr;

	// 1 != CIGI_STATE_DESTROYED!
	if (def->getSurfaceState() == 1)
	{
		ig_manager->getSymbolsController()->removePlane(def->getSurfaceID());
	} else
	{
		//0 - entity, 1- view.
		if (def->getAttachType() == 0)
		{
			Entity *entity = ig_manager->getEntity(def->getEntityID());
			plane = ig_manager->getSymbolsController()->createPlane(def->getSurfaceID(), entity);
			plane->setBillboard(def->getBillboard() == 1, def->getPerspective() == 1);
			plane->setPosition(def->getOffset());
			plane->setRotation(ig_manager->getConverter()->eulerNEDToRotation(def->getRotation()));
			plane->setPhysicalSize(def->getWidth(), def->getHeight());
			plane->setUVSize(def->getMin().x, def->getMin().y, def->getMax().x, def->getMax().y);
		} else
		{
			View *view = ig_manager->getView(def->getEntityID());
			plane = ig_manager->getSymbolsController()->createPlane(def->getSurfaceID(), view);
			vec3 t1 = def->getOffset();
			vec3 t2 = def->getRotation();
			// left = t1.x | right = t1.y | top = t1.z | bottom = t2.x
			float width = Gui::get()->getWidth() - t1.x - t1.y;
			float height = Gui::get()->getHeight() - t1.z - t2.x;
			plane->setScreenSize(width, height, t1.x, t1.z);
			plane->setUVSize(def->getMin().x, def->getMin().y, def->getMax().x, def->getMax().y);
		}
	}
}

void AppSystemLogic::symbol_text_def(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	CIGI::CigiSymbolTextDef *def = dynamic_cast<CIGI::CigiSymbolTextDef *>(packet);
	if (def == nullptr)
		return;

	SymbolText *symbol = dynamic_cast<SymbolText *>(ig_manager->getSymbolsController()->createSymbol(SymbolsController::SYMBOL_TYPE_TEXT, def->getSymbolID()));
	if (symbol == nullptr)
	{
		Log::error("%s:: cant create SymbolText\n", __FUNCTION__);
		return;
	}
	int alignV = def->getAlignment() / 3;
	int alignH = def->getAlignment() % 3;

	symbol->setAlign(SymbolText::ALIGN_HORIZONTAL(alignH), SymbolText::ALIGN_VERTICAL(alignV));
	symbol->setOrientation(SymbolText::ORIENTATION(def->getOrientation()));

	symbol->setFont(def->getFontID());
	symbol->setFontSize(def->getFontSize());

	symbol->setText(def->getText().get());
}

void AppSystemLogic::symbol_circle_def(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	CIGI::CigiSymbolCircleDef *def = dynamic_cast<CIGI::CigiSymbolCircleDef *>(packet);
	if (def == nullptr)
		return;

	int num = def->getNumCircles();

	for (int i = 0; i < num; ++i)
	{
		SymbolCircle *symbol = dynamic_cast<SymbolCircle *>(ig_manager->getSymbolsController()->createSymbol(SymbolsController::SYMBOL_TYPE_CIRCLE, def->getSymbolID()));
		if (symbol == nullptr)
		{
			Log::error("%s:: cant create SymbolText\n", __FUNCTION__);
			return;
		}
		symbol->setFill(def->getDrawStyle());
		symbol->setLineWidth(def->getLineWidth());
		symbol->setCenter(def->getCenter(i).x, def->getCenter(i).y);
		symbol->setRadius(def->getOuterRadius(i));
		float innerRadius = def->getInnerRadius(i);
		if (compare(innerRadius, 0.0f) || innerRadius > def->getOuterRadius(i))
			innerRadius = -1.0f;
		symbol->setInnerRadius(innerRadius);
		symbol->setSector(def->getStartAngle(i), def->getEndAngle(i));
	}
}

void AppSystemLogic::symbol_line_def(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	CIGI::CigiSymbolLineDef *def = dynamic_cast<CIGI::CigiSymbolLineDef *>(packet);
	if (def == nullptr)
		return;

	SymbolPolyline *symbol = dynamic_cast<SymbolPolyline *>(ig_manager->getSymbolsController()->createSymbol(SymbolsController::SYMBOL_TYPE_POLYLINE, def->getSymbolID()));
	if (symbol == nullptr)
	{
		Log::error("%s:: cant create SymbolText\n", __FUNCTION__);
		return;
	}

	switch (def->getPrimitiveType())
	{
		case 3:
			symbol->setClosed(true);
			break;
		case 4:
			symbol->setFill(true);
			break;
		case 5:
			symbol->setFill(true);
			symbol->setVertexOrderStrip(true);
			break;
		case 6:
			symbol->setFill(true);
			break;
	}

	symbol->setLineWidth(def->getLineWidth());

	int num = def->getNumVertex();
	for (int i = 0; i < num; ++i)
	{
		symbol->addPoint(def->getVertex(i).x, def->getVertex(i).y);
	}
}

void AppSystemLogic::symbol_clone(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	CIGI::CigiSymbolClone *clone_packet = dynamic_cast<CIGI::CigiSymbolClone *>(packet);
	if (clone_packet == nullptr)
		return;

	// TODO IG TEMPLATE SYMBOL???
	// clone_packet->getSourceType();

	Symbol *symbol = ig_manager->getSymbolsController()->cloneSymbol(clone_packet->getSourceID(), clone_packet->getSymbolID());
	if (!symbol)
	{
		Log::error("%s:: cant clone symbol %d, to %d\n", __FUNCTION__, clone_packet->getSourceID(), clone_packet->getSymbolID());
		return;
	}

	symbol->setVisible(false);
}

void AppSystemLogic::symbol_control(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	CIGI::CigiSymbolControl *control = dynamic_cast<CIGI::CigiSymbolControl *>(packet);
	if (control == nullptr)
		return;


	if (control->getSymbolState() == CIGI::CIGI_STATE_DESTROYED)
	{
		ig_manager->getSymbolsController()->removeSymbol(control->getSymbolID());
	} else
	{
		Symbol *symbol = ig_manager->getSymbolsController()->getSymbol(control->getSymbolID());

		if (!symbol)
		{
			Log::error("%s:: cant get symbol %d \n", __FUNCTION__, control->getSymbolID());
			return;
		}

		symbol->setVisible(control->getSymbolState() != 0);

		if (control->getAttachState())
		{
			Symbol *parent = ig_manager->getSymbolsController()->getSymbol(control->getParentID());
			if (!parent)
			{
				Log::error("%s:: cant get parent symbol %d \n", __FUNCTION__, control->getParentID());
				return;
			}
			symbol->setParent(parent);
		} else
		{
			symbol->setParent(nullptr);
		}


		symbol->setColorInherit(control->getInheritColor());

		if (symbol->getParent() == nullptr)
		{
			SymbolsPlane *plane = ig_manager->getSymbolsController()->getPlane(control->getSurfaceID());
			plane->addSymbol(symbol);
		}

		symbol->setOrder(control->getLayer());

		if (control->getFlashControl())
			symbol->resetFlashProgram();
		int flash = control->getFlashDuty();
		Vector<float> flash_cicle;
		if (flash == 0)
		{
			symbol->setVisible(false);
			symbol->setFlashProgram(flash_cicle);
		} else if (flash == 100)
		{
			symbol->setVisible(true);
			symbol->setFlashProgram(flash_cicle);
		} else
		{
			flash_cicle.append(control->getFlashPeriod() * control->getFlashDuty() * 0.01f);
			flash_cicle.append(control->getFlashPeriod() * (1 - control->getFlashDuty() * 0.01f));
			symbol->setFlashProgram(flash_cicle);
		}

		symbol->setOffset(control->getPosition().x, control->getPosition().y);
		symbol->setRotation(control->getRotation());

		symbol->setColor(control->getColor());
		symbol->setScale(control->getScale().x, control->getScale().y);
	}
}

void AppSystemLogic::symbol_short_control(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	auto process = [this](int parameter, unsigned int data, Symbol *symbol) {
		switch (parameter)
		{
			case 1: {
				//surface
				if (symbol->getParent() == nullptr)
				{
					SymbolsPlane *plane = ig_manager->getSymbolsController()->getPlane(int(data));
					if (!plane)
					{
						Log::error("%s:: cant get symbols plane %d \n", __FUNCTION__, int(data));
						return;
					}
					plane->addSymbol(symbol);
				}
				break;
			}
			case 2: {
				Symbol *parent = ig_manager->getSymbolsController()->getSymbol(int(data));
				if (!parent)
				{
					Log::error("%s:: cant get parent symbol %d \n", __FUNCTION__, int(data));
					return;
				}
				symbol->setParent(parent);
				break;
			}
			case 3: { //layer
				symbol->setOrder(int(data));
				break;
			}
			case 4: { //flash duty
				// TODO how to set flash duty, without flash period??
				break;
			}
			case 5: { //flash period
				// TODO how to set flash period, without flash duty??
				break;
			}
			case 6: {
				//pos u
				float v = symbol->getOffset().y;
				symbol->setOffset(*(float *)(&data), v);
				break;
			}
			case 7: {
				//pos v
				float u = symbol->getOffset().x;
				symbol->setOffset(u, *(float *)(&data));
				break;
			}
			case 8: {
				//rotate
				symbol->setRotation(*(float *)(&data));
				break;
			}
			case 9: {
				//color
				vec4 color;
				// NOTE: check it
				unsigned char *src = (unsigned char *)(&data);
				color.x = (src[0] / 255.0f);
				color.y = (src[1] / 255.0f);
				color.z = (src[2] / 255.0f);
				color.w = (src[3] / 255.0f);
				symbol->setColor(color);
				break;
			}
			case 10: {
				//scale u
				float v = symbol->getScale().y;
				symbol->setScale(*(float *)(&data), v);
				break;
			}
			case 11: {
				//scale v
				float u = symbol->getScale().x;
				symbol->setScale(u, *(float *)(&data));
				break;
			}
		}
	};

	CIGI::CigiSymbolShortControl *control = dynamic_cast<CIGI::CigiSymbolShortControl *>(packet);
	if (control == nullptr)
		return;

	if (control->getSymbolState() == CIGI::CIGI_STATE_DESTROYED)
	{
		ig_manager->getSymbolsController()->removeSymbol(control->getSymbolID());
	} else
	{
		Symbol *symbol = ig_manager->getSymbolsController()->getSymbol(control->getSymbolID());

		if (!symbol)
		{
			Log::error("%s:: cant get symbol %d \n", __FUNCTION__, control->getSymbolID());
			return;
		}

		symbol->setVisible(control->getSymbolState() != 0);

		if (!control->getAttachState())
		{
			symbol->setParent(nullptr);
		}

		if (control->getFlashControl())
			symbol->resetFlashProgram();

		symbol->setColorInherit(control->getInheritColor());

		process(control->getSelect1(), control->getData1(), symbol);
		process(control->getSelect2(), control->getData2(), symbol);
	}
}


// ...

 

as far as I remember in CIGI HEMU had some problems with sending symbol packets.  especially:
- SYMBOL_LINE_DEF
- SYMBOL_CIRCLE_DEF
if these packets do not work, check through WireShark that HEMU is indeed sending packets correctly.

  • Thanks 1
Link to comment

So... just tested, and still nothing on screen :(

You were correct though about HEmu as it spits invalid cigi packets. So I used our own CIGI sender, and still nothing. I attach here the three packets sent (symbol surface definition, symbol text definition, symbol control) in case you see a mistake here. Could you send me your test packets ?

Note: I added a log trace in your callbacks and observed the log is printed twice for each message received. So your callbacks are called twice. Is it normal?

cigi_symbols.pcapng

Link to comment

I checked your case - the problem is in the font size.
we don't take into account the UV scale of the surface when calculating the font - it is always drawn in real size.

image.png

image.png

Align and Orientation for TextSymbol is also does not work properly.

As for double processing of packet - I can't reproduce this behavior. Сheck if init_cigi (addOnReceivePacketCallback) is called twice and adds callbacks a second time?

  • Thanks 1
Link to comment

Hi, it works with the size now! So okay, we'll have to set the UV size as the pixel size instead. Ok for now...

For the double-call, sorry it was on my side, as you guessed.

One more trouble: if I send a new text definition to change the text content for an existing symbol, then it disappears. I have to resend the symbol control after updating the the text. Is it the expected behavior?

Thanks!

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

One more trouble: if I send a new text definition to change the text content for an existing symbol, then it disappears. I have to resend the symbol control after updating the the text. Is it the expected behavior?

not really.
createSymbol deletes a symbol if it has already been created.
Try to take the symbol first, and if it doesn't exist, create it.

 

void AppSystemLogic::symbol_text_def(Unigine::Plugins::IG::CIGI::CigiHostPacket *packet)
{
	CIGI::CigiSymbolTextDef *def = dynamic_cast<CIGI::CigiSymbolTextDef *>(packet);
	if (def == nullptr)
		return;

  SymbolText *symbol = dynamic_cast<SymbolText *>(ig_manager->getSymbolsController()->getSymbol(def->getSymbolID()));
  if (!symbol)
	symbol = dynamic_cast<SymbolText *>(ig_manager->getSymbolsController()->createSymbol(SymbolsController::SYMBOL_TYPE_TEXT, def->getSymbolID()));
	if (!symbol)
	{
		Log::error("%s:: cant create SymbolText\n", __FUNCTION__);
		return;
	}
//....

 

 

  • Thanks 1
Link to comment

Indeed that fixed it. I did the same for the other symbols. Hope the next version will integrate these and the fixed font size :) but it'll be ok for now.

Thanks!

Link to comment
  • 3 weeks later...

Hi,

I found a new issue with CIGI symbols. When the surface is defined as attached to the View, a rescale of the window does not trigger a rescale of the symbol surface.

For example, if the surface is defined as view attached with UV=min(0,0)-max(1,1) and a text is displayed at UV(0.5,0.5) (the center), the text appears correctly in the center. But if I rescale the window (for example by maximizing the window) then the text is no longer in the center.

How to fix this with the current code? Could this be fixed in the next version?

Thanks!

Link to comment
On 5/13/2022 at 4:18 PM, Amerio.Stephane said:

a rescale of the window does not trigger a rescale of the symbol surface.

yes, you are right - window rescale doesnt trigger anything.

screen size takes only when you send plane define packet.

// left = t1.x | right = t1.y | top = t1.z | bottom = t2.x
float width = Gui::get()->getWidth() - t1.x - t1.y;
float height = Gui::get()->getHeight() - t1.z - t2.x;
plane->setScreenSize(width, height, t1.x, t1.z);

you can resend packet with plane defenition or try to catch rescale

 

Vector<int> planes;

void symbol_surface_def ()
{
//....
auto *view = ig_manager->getView(def->getEntityID());
plane = ig_manager->getSymbolsController()->createPlane(def->getSurfaceID(), view);

// save ids of view-attached plane
if (!planes.contains(def->getSurfaceID()))
	planes.append(def->getSurfaceID());

//.....
}


int w = 0;
int h = 0;
void update() // somewhere in update
{
	int new_w = App::getWidth();
	int new_h = App::getHeigth();
	if (new_w != w || new_h != h) // if sceen changed
	{
		for (auto it : planes)
		{
			auto plane = ig_manager->getSymbolsController()->getPlane(it);
			if (!plane)
				continue;

			// recalc screensize
			vec4 screen_size = plane->getScreenSize();
			screen_size.x = new_w - (w-screen_size.x);
			screen_size.y = new_h - (h-screen_size.y);
			plane->setScreenSize(screen_size);
		}

		w = new_w;
		h = new_h;
	}

}

 

  • Thanks 1
Link to comment

Hi, the latest window resize fix works correctly, thanks.

But now we found out that a CIGI reset will crash in IG_double_x64d.dll with no usable stack trace if a symbol has been defined.

Reproduction:

  • launch with IG and CIGIConnector plugins
  • send a SymbolSurfaceDefinition(View attached), a TextDefinition, a SymbolControl: text should be visible on screen
  • Send a CIGI IG Ctrl reset -> crash

Note: I tried to move all symbol code to a WorldLogic instead of a SystemLogic, and removing all callbacks and calling removeSymbol for all surfaceId but it still crashes.

Edited by Amerio.Stephane
Link to comment
20 hours ago, Amerio.Stephane said:

Reproduction:

  • launch with IG and CIGIConnector plugins
  • send a SymbolSurfaceDefinition(View attached), a TextDefinition, a SymbolControl: text should be visible on screen
  • Send a CIGI IG Ctrl reset -> crash

I cannot reproduce this crash. Symbols are destroyed on reset - may be you keep pointer on some of them?

can you send any crash stacktrace (even useless)? 

 

Link to comment

Hi, you actually need to have an active entity for the crash to happen

image.png.a25e203d671d5394437182d77e2745d0.png

(note: you have a typo in your SymbolsController::onEntityDestro*y*ed)

Link to comment
  • 2 weeks later...
×
×
  • Create New...