Minor design question (dynamic_cast or not?)

Started by
7 comments, last by B_old 13 years, 6 months ago
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. :)
Advertisement
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;           entity->update();       }   }   std::vector<ParticleSystem *> particles;   std::vector<Actor *> actors;}
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?
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.
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?
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.
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.

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).
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!

This topic is closed to new replies.

Advertisement