ComponentInstance processing order


#1

Hey,

I’m designing an entity which has a couple of components which I need to process in deterministic order to ensure the (outputted laser) frames are in sync.

Say I have the following components,

  • PhysicalLineComponent (physical simulation of a big string)
  • LineSegmentComponent (x8) (extracts PolyLines from the string above by slicing it into eight segments)
  • LineProjectionMappingComponent (x8) (handles projection mapping calibration xform).
  • LaserOutputComponent (x8)

How (besides targeting a super high fps) do I ensure the components process from top to bottom, ensuring minimal latency, and more importantly, all the eight laser outputs are in sync?

Regards,
Marcel


Optional dependent component
#2

Hey,

To ensure the right processing order make your components point to each other in the right orrder. I have done something similar in the LineBlendDemo, So, if component B needs component A, add a ComponentPtr to Component B that links to component A. This ensures that A is created before B, etc. Use napkin or json to edit the link. Also, place component B under component A in JSON.

If Component B needs two components of type A, create 2 links, the first link is initialized before the second one. The resource manager builds a dependency graph before initializing components, to ensure that they are initialized in the right order. It also uses this order when a change is detected and a graph is reconstructed. Using component pointers is the only way to guarantee the right order of initialization.

When there is no relationship between components the resource manager will initialize the components based on the order of declaration in the json file. But again, use component ptrs, mainly because:

  • They ensure objects are created and initialized in the right order
  • Therefore update() follows suit, as update() is called based on order of initialization
  • Component ptrs are resolved for you, you know therefore that your instance points to a valid component.

Component Resource:

	// property: Link to selection component one
	ComponentPtr<LineSelectionComponent> mSelectionComponentOne;

	// property: Link to selection component two
	ComponentPtr<LineSelectionComponent> mSelectionComponentTwo;

Component Instance:

	ComponentInstancePtr<LineSelectionComponent>    mSelectorOne = { this, &LineBlendComponent::mSelectionComponentOne };		// First line selection component
	ComponentInstancePtr<LineSelectionComponent>	mSelectorTwo = { this, &LineBlendComponent::mSelectionComponentTwo };		// Second line selection component

Alternatively, you can override the Component::getDependentComponents() method: This tells the system that in order for component B to work, component A needs to be present without having to specify a link. For example, the OrbitController requires a KeyInputComponent and TransformComponent , in order to function correctly. The system will initialize the input and transform components before the controller, and update accordingly.

void OrbitController::getDependentComponents(std::vector<rtti::TypeInfo>& components) const
{
	components.push_back(RTTI_OF(TransformComponent));
	components.push_back(RTTI_OF(KeyInputComponent));
}

Lineblend demo uses a stack of components to process a line that is send to a laser based on this principle.


#3

Quick note regarding order of declaration in JSON and Napkin. Napkin shows the components based on alphabetical order, this is not the same as the component order in JSON. The order in JSON is leading.

When you add a component using Napkin, it is appended to the list in JSON, as expected, but could show up somewhere else in the tree (in Napkin). I find this annoying and is on my list to be addressed. Order of creation / appending is therefore important. If you want to change the order you have to do it in JSON.

Quick callback to @bas, so he knows we’re currently discussing this.


#4

Thanks for notifying me, I wasn’t aware the order or elements was being used structurally.

So for Napkin, do we want:

  • no sorting
  • or an additional way to revert to ‘internal’ ordering of components?
    Currently, clicking a column header allows you to sort by that column, so I could easily add a column showing the index of each component.
    On top of that you’d probably want to be able to reorder the elements by dragging.

Just some thoughts


#5

I like sorting, so option two sounds good to me! Being able to drag to re-order components would be great as well.


#6

I’m not sure how I feel about component order in the list determining component processing order. It seems too implicit to me. I like hard guarantees. :slight_smile: I think it would work for just about any use-case though (and it’s nowhere near as silly and confusing as Max’ implicitly using horizontal node placement for ordering…). Adding an explicit ‘index’ or priority value instead of JSON order would also work. I don’t know what that means for you internally. Probably a sort of the component list upon deserialization.

Note that alphabetical ordering and dragging components up/down would be incompatible with each other. The user would first have to sort by index, which then unlocks reordering components.


#7

You can always disable reordering when the list isn’t sorted based on index. But this sounds overly modal and hard for a user to understand.

Defining an explicit index could help and crossed my mind before, but also introduces another parameter that the user has to be aware of. It does however solve the entire order problem and can be applied (as mentioned) as a post processing step. We would have to add support to the serializer for this but shouldn’t be too much work.

Another option could be to never sort components in napkon but do allow sorting of entities en resources. This ensures the right loading order (except from dependencies based on linking).


#8

The user should be made aware of the necessity and possibility of sorting when working on projects where lowest possible latency is a requirement, or when things need to happen synchronously as in my case. Having an explicit property for sorting would serve this purpose. I think I like the idea of an extra property over an implicit rule. I like the certainty of knowing when a system behaves in a specified way.

It will add one more property to each and every component in the JSON file, but perhaps at least for component processing order Napkin could make the exception to only serialize it when not default?


#9

Did a quick debugging session on my end using the lineblend demo, which uses component ptrs and component dependencies. Looks like the JSON component declaration is always leading. This is even the case when components that link to each other are initialized in a different order.

So: this invalidates my previous comment and solves our issue. What we need to do is make sure that Napkin always displays the components (associated with an Entity) in their correct order (@bas) . This allows for re-ordering components in Napkin as well. But the order you see in JSON will also specify the order of update in the running app. The result is WYSIWYG

The actual reason for this is that after the JSON document is read the Components (as resources) are created and added to the entity immediately, before resolving links. After this links are resolved and the instances are spawned, ensuring the order remains the same. (in a nutshell that is :wink:


#10

Regarding entities, the order of declaration of entities in the Scene is also the order of update in the running app.


#11

I’m working on drag&drop reordering of Entities/Components, so stay tuned!