SFML community forums

Help => General => Topic started by: Blader on September 22, 2016, 08:17:08 am

Title: Why not decouple transform \ render?
Post by: Blader on September 22, 2016, 08:17:08 am
Hey guys, I would like to start a discussion about why all things drawable inherit from transformable. To me it makes sense to use composition to give drawables a transform. E.g. sf::Sprite HAS A transform rather than sf::Sprite IS A transform.

First my use case:


To that end I re-wrote those classes into what I call 'SmartDrawables and SmartTransformables'. They aren't really smart they just allow me to write this:


sf::SmartTransformable rootTransform;
sf::SmartTransformable someTransform;

sf::Sprite rootSprite(rootTransform, texture);
sf::Sprite someSprite(someTransform, texture);

rootTransform.addChild(someTransform);

// In an update somewhere.
rootTransform.rotate(0.1f);
rootTransform.updateTransforms(); // Goes through the heirarchy.

window.draw(someSprite); // Draw in whatever order we want, regardless of parent->child relationship.
window.draw(rootSprite);
 

So my questions:


A pic is attached, the blue one represents the child and is being rendered below the parent.
Title: Re: Why not decouple transform \ render?
Post by: Laurent on September 22, 2016, 09:31:10 am
Hi

SFML doesn't force any design. You can perfectly use external transforms (in sf::RenderState) and leave the internal ones to identity. This is the typical solution for hierarchies, and it is even shown in tutorials:

http://www.sfml-dev.org/tutorials/2.4/graphics-transform.php#object-hierarchies-scene-graph
Title: Re: Why not decouple transform \ render?
Post by: Blader on September 23, 2016, 02:27:23 am
Quote
SFML doesn't force any design

The given drawables are given a design choice and that is to inherit from Transformable rather than contain one, why is that? I assume it's purely from ease of use perspective rather than good coding perspective.


Quote
You can perfectly use external transforms (in sf::RenderState) and leave the internal ones to identity.

Yes, I do this in my code now. Yeah the typical solution creates a situation of a set rendering order in the hierarchies, something I don't want. That's why I started this discussion on a non-typical implementation.

So I guess a simplified question would be: Using that node class as an example, is it better to do my implementation (Making a transformable directly have parent\child relationships and removing the inheritance usage of Transformable) or use that node class and changing it to separate where the combinedTransform is calculated and the drawing occurs?
Title: Re: Why not decouple transform \ render?
Post by: Laurent on September 23, 2016, 07:44:59 am
Quote
The given drawables are given a design choice
It doesn't force you to use the built-in transform if you don't want to. If you want maximum power and flexibility you can use the render-state's transform, and manage the link with the drawable as you want.

Quote
inherit from Transformable rather than contain one, why is that?
What would the API look like if entities contained a transform rather than being transformable? Something like entity.setTransform(sf::Transform)?

Quote
So I guess a simplified question would be: Using that node class as an example, is it better to do my implementation (Making a transformable directly have parent\child relationships and removing the inheritance usage of Transformable) or use that node class and changing it to separate where the combinedTransform is calculated and the drawing occurs?
I'd say it's easier to calculate the transform elsewhere. You can also collect the nodes and reorder them as you want for rendering. There are many possible implementations.
Title: Re: Why not decouple transform \ render?
Post by: Blader on September 23, 2016, 08:03:16 am
Quote
inherit from Transformable rather than contain one, why is that?
What would the API look like if entities contained a transform rather than being transformable? Something like entity.setTransform(sf::Transform)?

I don't see a reason to set a transform after creation although there might be a use case, I prefer to force it as a dependency as it is required. Although I may be wrong! E.g this is my code copy-pasted:

SmartDrawable::SmartDrawable(SmartTransformable& transformable) : sf::Drawable(),
                m_smartTransformable(transformable)
{
}



Quote
So I guess a simplified question would be: Using that node class as an example, is it better to do my implementation (Making a transformable directly have parent\child relationships and removing the inheritance usage of Transformable) or use that node class and changing it to separate where the combinedTransform is calculated and the drawing occurs?
I'd say it's easier to calculate the transform elsewhere. You can also collect the nodes and reorder them as you want for rendering. There are many possible implementations.

Unless you split the transform calculation and node drawing you can't reorder nodes as that might mess up some specific child->parent relationship. E.g an orb that hovers in front of \ behind a character while also inheriting it's transform wouldn't want to be re-ordered to be the characters parent.
Title: Re: Why not decouple transform \ render?
Post by: Laurent on September 23, 2016, 08:29:11 am
Quote
I don't see a reason to set a transform after creation although there might be a use case, I prefer to force it as a dependency as it is required
So the transform is kept external, the entity doesn't own it? I see a lot of problems associated to this, and I don't see any benefit.

Quote
Unless you split the transform calculation and node drawing you can't reorder nodes as that might mess up some specific child->parent relationship. E.g an orb that hovers in front of \ behind a character while also inheriting it's transform wouldn't want to be re-ordered to be the characters parent.
I was just talking about drawing order. That's what most scene-graphs do: they traverse the hierarchy and collect all relevant nodes, and then reorder the collected drawable entities to optimize rendering (mostly to create batches of geometry that use the same render-states).