Home » Community » Forums » » Designing an Extensible Particle System using C++ and Templates
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

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
Post Reply 
Cool. Very cool.


pan narrans | My Website | Study + Hard Work + Loud Profanity = Good Code

 User Rating: 1788   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Very interesting, thanks :-)

 User Rating: 1026   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Now isn't that ugly?


Yes. I'd just use linked lists of effects, but that's me. :c/

 User Rating: 1060   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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

 User Rating: 1145   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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]

 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

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

 User Rating: 1015    Report this Post to a Moderator | Link

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

 User Rating: 1543   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

quote:
Original post by 23yrold3yrold
In "Additional Resources", is it me or is the "Trent Polack's: Game Tutorial #03" link broken?



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()

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

quote:
Original post by 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".



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()

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

quote:
Original post by Seriema
We'd like to hear your comments on this *hehe good luck*



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]

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

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 What I really wanted to know, using your template method, how would one save a particle system to file and then recreate it? Using our method of interfaces and class hiearchies we solved that by giving each part a "name" (GravityModifier, ColorModifier) and using factories. But how would one do that with templates?..

"No lies of sugar can sweeten the sournes of reality"

}+TITANIUM+{ A.K.A. DXnewbie[onMIRC]

 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

quote:
Original post by Seriema

I'm sorry if my last post was a little confusing, it was 02.00 over here What I really wanted to know, using your template method, how would one save a particle system to file and then recreate it? Using our method of interfaces and class hiearchies we solved that by giving each part a "name" (GravityModifier, ColorModifier) and using factories. But how would one do that with templates?..




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()

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

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.

 User Rating: 1015    Report this Post to a Moderator | Link

I would have used one "policy" for initialization and another for updates, myself I don't think the benefits of one class per particle member variable outweigh the benefits of slightly cleaner code from 2 classes instead of 14 or so. Then just make a new class for each particle type.

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:
This looks like one of those wonderful ideas that would just never be used in real life.
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]

 User Rating: 1543   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

quote:
Original post by 23yrold3yrold
I hate Hungarian Notation too ....


Ehh... I don't use it now, hate it as well too Learnt pretty much between then I wrote it, and now (die hungarian notations! throw specifications!"

quote:
Original post by 23yrold3yrold
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)

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 ), or alternatively, grab the particles via GetParticles() and ParticlesCount(), and draw with those information.

VirtuallyOnline.ReadMyRecommendedBooks().ReadTheWeeklyGameDevChatStats().ReadTheCurrentlyEmptyForums()

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

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?

 User Rating: 1015    Report this Post to a Moderator | Link

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

 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by Anonymous Poster
Nice article! I really need to read this book on design patterns!


Erm, it's actually call Modern C++ Design by Alexanderscu Andrei

quote:
Original post by Anonymous Poster
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?

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.




 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

quote:
Original post by 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


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]

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

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

 User Rating: 1543   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

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!

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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]

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
from article
Should we copulate the rendering to the particle system?


oh behave!

 User Rating: 1214   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Br1
...


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*

 User Rating: 1217   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: