Sign in to follow this  
B_old

Minor design question (dynamic_cast or not?)

Recommended Posts

Context:
I want to draw several transparent entities and need to order entities, that are not of the same type, by distance to the eye. I have "particle systems" and "actors", both derived from "entity".

Plan:
Sort a list of entities containing both particles and actors. Walk through the list and check each element for its type. When the type changes, send all entities collected so far to the appropriate renderer (particle renderer or actor renderer).

My entities can't render themselves so a simple virtual method won't do. And I think I'd like to keep it that way, because it seems easier to batch (particles) in this manner.

Question:
What to do you think of it? Any idea how I could conveniently avoid a dynamic_cast? I'm not overly concerned about performance issues, but I'm curious how you would go about it.

Thanks for reading. :)

Share this post


Link to post
Share on other sites
If particles and actors are so different, store two lists instead. You can still use generic helper functions that make use of the common entity type:

class Example {
public:
void update() {
update(particles);
update(actors);
}

void draw(ActorRenderer &actorRenderer, ParticleRenderer &particleRenderer) {
// draw each list seperately
}

private:
template<typename T>
static void update(std::vector<T *> &entities) {
for(int i = 0 ; i < entities.size() ; ++i) {
Entity *entity = entities[i];
entity->update();
}
}

std::vector<ParticleSystem *> particles;
std::vector<Actor *> actors;
}

Share this post


Link to post
Share on other sites
Hm. This is more or less how I am doing things now.
My main problem is how to sort those different entities in a coherent manner. Is this somehow solved in the update method in your example?

Share this post


Link to post
Share on other sites
You could possibly add some kind of flag to each entity. F ex. 0 to actors and 1 to particles and use if()then{} statement. Or try sorting entities in a vector that from 1 to Na you store actors and from Na+1 to size(vector) you store particles.

Share this post


Link to post
Share on other sites
Quote:
Original post by Misery
You could possibly add some kind of flag to each entity. F ex. 0 to actors and 1 to particles and use if()then{} statement. Or try sorting entities in a vector that from 1 to Na you store actors and from Na+1 to size(vector) you store particles.

I don't understand the second part of your suggestion. What if the order is "actor, particle system, actor" from the viewers point of view. Than I have to draw in that order to avoid artifacts.
I could use the flag and a static_cast. How does typeid + static_cast compare to dynamic_cast in terms of performance btw?

Share this post


Link to post
Share on other sites
If you're using depth buffering, there shouldn't be any artifacts caused by the drawing order.

If you just want to sort by distance to camera, why do you need to know the type? Give the base Entity class a getDistance() function and use it as a sorting criteria. Such a function doesn't need to be virtual.

Share this post


Link to post
Share on other sites
Quote:
Original post by Gage64
If you're using depth buffering, there shouldn't be any artifacts caused by the drawing order.

If I use depth-reads it could be that stuff behind a transparent object doesn't get drawn because of the depth-buffer. So I disable depth-reads. The correct result still depends on the drawing order now, otherwise transparent objects that are actually behind another transparent object could appear to be in front.

Quote:
Original post by Gage64
If you just want to sort by distance to camera, why do you need to know the type? Give the base Entity class a getDistance() function and use it as a sorting criteria. Such a function doesn't need to be virtual.

I don't need the type for the sorting. But after the sorting when I wan't to draw the sorted stuff in the correct order I need to know what it is I'm actually drawing.

Share this post


Link to post
Share on other sites
You said earlier:

Quote:
My entities can't render themselves so a simple virtual method won't do.


So the entities need some additional information to be rendered. But why can't that information be passed to the virtual function as parameters?

If you really want to avoid virtual functions, you can use separate containers like rip-off suggested. To sort them you can do something similar to merge-sort. You first sort each container, and then you traverse both containers in parallel, comparing two elements and drawing the closer one (this is like the merging step).

Share this post


Link to post
Share on other sites
Quote:
Original post by Gage64
If you really want to avoid virtual functions, you can use separate containers like rip-off suggested. To sort them you can do something similar to merge-sort. You first sort each container, and then you traverse both containers in parallel, comparing two elements and drawing the closer one (this is like the merging step).

Now I understand. This seems worth a try. Thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this