|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| Designing an Extensible Particle System using C++ and Templates |
|
![]() pan narrans Staff Member since: 6/4/2002 From: Leeds, United Kingdom |
||||
|
|
||||
| Cool. Very cool. pan narrans | My Website | Study + Hard Work + Loud Profanity = Good Code |
||||
|
||||
![]() Jarski Member since: 9/5/2000 From: Oulu, Finland |
||||
|
|
||||
| Very interesting, thanks :-) |
||||
|
||||
![]() Penance Member since: 5/15/2002 |
||||
|
|
||||
quote: Yes. I'd just use linked lists of effects, but that's me. :c/ |
||||
|
||||
![]() SirKnight Member since: 1/7/2001 |
||||
|
|
||||
| I love when I click on "Printable Version" and try to print and about 1/4 of the right side of the page is cut off. Printable Version my a$$. :/ Anyway, cool article! I like it a lot. -SirKnight |
||||
|
||||
![]() Seriema Member since: 6/15/2001 From: Stockholm, Sweden |
||||
|
|
||||
| great article! Me and me friend were pounding our brains away trying to come and think of a templated particle system that could be scalled. Especially particle members. We would like to add force if we felt we needed it, or acceleration if we neede that instead. But that would fall on naming. Say the particlesystem would want to move the particle, would it move it with force and mass or by acceleration? All the possible combinations just made us cry like little babies *ok, not really..* We thought, well say we document all the possible names, how would one modifier (like gravity) know if there was a mass? etc. The second problem we encountered was: files. The designer/animator/artist is going to want to specify his particle effects, and he's (or she's!) no coder *dang* The d/a/a would like to open some tool, enter som values, and see a cool particle effect. How would that work with templates, that need to be "created" by the compiler? We could maybe typedef some common particle systems and make edit boxes for them. But what a hassle that would be! (ever worked with an artist? "can we have this? and that? could you squeze Doom3 into that texture?" Sure that's all solvable, but we didn't find a solution we liked. But our real problem came: the d/a/a has somehow made a particlesystem he/she likes and has set its parameters in _this_ file, how would our engine read that and create the appropriate particlesystem? Typedefs kinda died because artists are kinda too imaginitive for that We'd like to hear your comments on this *hehe good luck* "No lies of sugar can sweeten the sournes of reality" }+TITANIUM+{ A.K.A. DXnewbie[onMIRC] |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| the idea is nice, but it's taken too far. you got a little bit carried away with making it "generic" and "configurable" and improving "flexibility" and "reusablity". "If you take taste too far, it stops being tasteful." - Michael Manring |
||||
|
||||
![]() 23yrold3yrold GDNet+ Member since: 2/10/2001 From: Vector Sigma |
||||
|
|
||||
| In "Additional Resources", is it me or is the "Trent Polack's: Game Tutorial #03" link broken? Chris Barry (crbarry at mts.net) My Personal Programming Depot |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: That it is. Last I heard, Trent requested his article to be taken down from NeHe. However, at the time of submitting the article, it was still a valid link. Sorry guys. VirtuallyOnline.ReadMyRecommendedBooks().ReadTheWeeklyGameDevChatStats().ReadTheCurrentlyEmptyForums() |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: I have to admit, it was a bit too carried away. I was a bit over crazed with templates at that time. All in all, it turned out pretty well still, though if I could, I might do things slightly differently now. (Ideas are there, but not tested yet. Too much work to do, just too darn much :x) VirtuallyOnline.ReadMyRecommendedBooks().ReadTheWeeklyGameDevChatStats().ReadTheCurrentlyEmptyForums() |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: Ok, the first part. You could 'merged' a couple of MovePolicy into Composite Policies, and pass that as a Move Policy to the template. That is, of course, assuming that these movement factors can be calculated indendepently. The drawback of this templated design is of course that, you must provide policies that worked on an available property of the particle. Hence, if you want to have mass, you create a particle with a mass property, and provide a Gravity Movement policy that works on it. Hope that can answer the your first question. (because I am still a bit unsure of the question) The answer to the second question was actually the predecessor of this templated particle system I had. It started out as a normal particle system with particle of fixed(and maybe even possibly huge) number of properties. Then I defined an abstract Modifier class, which acts on each of the particle. Thus, at runtime, I can actually add and remove modifiers(or policies), loop through the particles and operate the 'runtime policy' on the particles. It's very extensible at runtime, though the drawback I had, of course, was performance. Still fine for a single particle system of a moderate number of particles, but when scaled.... yikes Perhaps you can go with the second approach and see if you can think of some ingenious ways to optimize it The beauty of this template design is you get all the possibilities at the best performance, at the expense of having to define multiple policies. VirtuallyOnline.ReadMyRecommendedBooks().ReadTheWeeklyGameDevChatStats().ReadTheCurrentlyEmptyForums() [edited by - dot on August 21, 2003 3:23:00 AM] |
||||
|
||||
![]() Seriema Member since: 6/15/2001 From: Stockholm, Sweden |
||||
|
|
||||
| We have actually made a particle system like the second one. With hiearchies for policies. So modifiers can be added or removed during runtime and so on. There is a speed loss.. Mainly on calculating stuff that hasn't changed. Like adding color to the particle, when there is no color to add (adding 0,0,0,0). That depended on a uniform approach we made for optimizing when using many modifiers (instead of having 5 modifiers going through each particle, all 5 just modified _one_ particle and then that particle would affect all others). Else I don't really know what made it so slow. If it had to many properties or if it was because of the virtual functions on each modifier, creator, and renderer. I'm sorry if my last post was a little confusing, it was 02.00 over here "No lies of sugar can sweeten the sournes of reality" }+TITANIUM+{ A.K.A. DXnewbie[onMIRC] |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: Ok right now, I can think of having each policy having a 'persist' to and from function, which takes in an istream and ostream respectively(implemented similarly to the PerpareAction, where they get propagated down to each policy). Thus, given a particle system with predetermined policies, you can persist to/from the a stream(files in this case). Of course, still, that is not as extensible as an all-in-kitchen sink of your runtime determined particle system. VirtuallyOnline.ReadMyRecommendedBooks().ReadTheWeeklyGameDevChatStats().ReadTheCurrentlyEmptyForums() |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| This looks like one of those wonderful ideas that would just never be used in real life. Why? Because it's just too damn hard. Make a generic particle system and then just modify it to fit your needs. |
||||
|
||||
![]() 23yrold3yrold GDNet+ Member since: 2/10/2001 From: Vector Sigma |
||||
|
|
||||
| I would have used one "policy" for initialization and another for updates, myself Anyway, I didn't say it before; cool article BTW, I had a thought for drawing; make the particle drawing function a member of the particle structure, and loop through them all in a Draw function in ParticleGroup. I don't think you mentioned drawing in any way, but that was the best way I could think of (I coded up an Allegro implementation of this last night). Anyone think of a better way? quote:Yeah, I hate Hungarian Notation too Chris Barry (crbarry at mts.net) My Personal Programming Depot [edited by - 23yrold3yrold on August 21, 2003 6:46:53 PM] |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: Ehh... I don't use it now, hate it as well too quote: I didn't have drawing inside the system, because that makes the system a tad bit too coupled with graphics(which in most of the case, you would prefer so). Feel free to customize and add a policy for that(which I definitely prefer people to do, then just take the source codes and use as it is. This is more of an introduction of concept, then introducing the ONE true way, note that's why I didn't provide actual source for download. I want you to read through, decide if it's nice, and implement a similar one VirtuallyOnline.ReadMyRecommendedBooks().ReadTheWeeklyGameDevChatStats().ReadTheCurrentlyEmptyForums() |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| Nice article! I really need to read this book on design patterns! Probably a dumb question on your code examples: What's that PrepareAction() thing? It's never really used in any of the example action-policies. I wonder what it might be useful for - initialisation of the action to be performed? Any examples? |
||||
|
||||
![]() Anonymous Poster |
||||
|
||||
| very interesting article. Thank you very much for your wonderful ideas, even if they are possibly a litte bit too generous, i think ;-) greets, smasher1985 |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: Erm, it's actually call Modern C++ Design by Alexanderscu Andrei quote: Ok, when I was doing the particle system, I wanted to add a retracting effect. After every 50 count, the exploding particles would actually retract, and after every 50 count again, explode. Thus I need a way to tell the actions that this is a 'frame' has passed. |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: Perhaps I forgot to state in the article that it was more of an introduction of concept, using policies in your design. And the particle system was simply an example where policies could be used. The particle system is not meant to be a plug-and-use code (hence no source download provided) It's meant for a read, and stimulation of the mind, and introduction to the policy concept. Following this, I might come up with an article on perhaps making use of expression templates in graphics as well, and again, it will be an introduction to a 'mean', not an 'end' [edited by - dot on August 22, 2003 9:27:44 AM] |
||||
|
||||
![]() 23yrold3yrold GDNet+ Member since: 2/10/2001 From: Vector Sigma |
||||
|
|
||||
| I mentioned before I made an Allegro implementation, just for testing. I posted that source and a link to your tutorial on my stomping grounds for discussion purposes, so you can consider this further feedback if you want Chris Barry (crbarry at mts.net) My Personal Programming Depot |
||||
|
||||
![]() serious spaam Member since: 8/23/2003 From: Germany |
||||
|
|
||||
| a very interesting approach to an extensible particle system or as a famous physicist might have said: 'keep your particle system as extensible as you need, but not more' anyway good article, good work! |
||||
|
||||
![]() Br1 Member since: 2/7/2002 From: Montevideo, Uruguay |
||||
|
|
||||
| Hello. First of all let me tell you I've never written a particle engine, but I've read Modern C++ Design. Excuse in advance any english mistake I may make. If the text seems rude at times it is not my intention but my bad english comunication skills. Please take no offense, but I think the solution is too complicated, and less generic than desirable. I'll explain each point. It's complicated because you have to write a lot of policies and that means it can't take advantage of previously written code as easely as I think is possible. Adaptors policies are needed that call your old code. The particle system takes a template parameter of type particle of which it requiers too much. It needs to have members life and position. This coupling is unnecesary. Also, the policies cannot be initilized with the code as presented. This could be fixed receiving instances of the policies at construction, but then the structure of the construction of composite policies has to mimic the structure of the template parameters and the repetition is bad. An alternative that i thought of is as follows:
template <class T>
class bag {
public:
void clear() { container.clear(); }
iterator begin() { return container.begin(); }
iterator end() { return container.end(); }
size_type max_size( ) const;
void add(const T& t) { container.push_back(t); }
template<class F>
void for_each(F f) {
for (iterator i = container.begin(); i != container.end(); /* none */) {
if (F(*it)) {
swap(*it, container.back()); // does self swapping work?
container.pop_back();
}
else
++i;
}
}
public:
typedef vector<T> container_type;
typedef container_type::iterator iterator;
typedef container_type::size_type size_type;
private:
container_type container;
};
struct Particle {
Vec3d pos;
int life;
};
class ParticleGroup : private bag<Particle> {
void initialize() {
// ...
}
bool action(Particle& p) { // returns true if the particle is to be destroyed
// ...
}
ParticlGroup() { initialize(); }
Update() { for_each(boost::bind(ParticleGroup::action, this, _1)); }
void emit(Vec3d p, int amount) {
for(int i = 0; i < amount; ++i) add(Particle(p));
}
};
I think this is better because: 1. initialize has a context, class ParticleGroup, with data members and everything it may need. Static policies can only access global mem. 2. for_each recieves a functor that returns bool signaling whether the particle is done. I can pass anything including boost::function, for polimorphism and functors made with boost::lambda, phoenix or fc++. The type of the functor is automattically detectd by c++, I don't have to spècify complex policy types. The downside of this is lack of the classic iterator advantage, being able to iterate several collections at the same time. If only traversing is needed (no deletion) iterators are exposed by bag, but it didn't ocurred to me a way to make iterators deleteable without adding member functions to the iterator, ala JAVA. So, what do you think? Bruno [edited by - br1 on August 31, 2003 1:43:19 PM] [edited by - br1 on August 31, 2003 1:46:46 PM] [edited by - br1 on August 31, 2003 1:47:26 PM] |
||||
|
||||
![]() krez GDNet+ Member since: 10/10/2001 From: NJ - The Garbage State |
||||
|
|
||||
quote: oh behave! |
||||
|
||||
![]() dot Member since: 7/15/1999 From: Singapore, Singapore |
||||
|
|
||||
quote: Ok, first off, I must really say again, the article was actually an attempt to introduce the concept of policies to the gamedev community. Never was intended for plug and play. Just hoping to open up the minds and kick start some other possibility they can come up with. This is just a possibility of how templates and policies *may* help in your future design. Thinking now, I might make a couple of changes to the implementation. For one, I might introduce a Trait class to describe the particle, and delegate most functions to it. Next could be have the particle system as an adapter to a container, similar to your design. Except container is actually a template parameter. That way, one can choose to use a std::vector, a boost::array, or even if he wants, deque or list. Not to mention reuse stl algorithms and functors instead of having those loops heh. By the way, your implementation looks interesting... food for thought *sorry for the late reply, thought the thread was dead :x* |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|