I take it from the latest lepton announcement that you want to change
the name from 'attractor' to 'magnet'? Sounds good - gives you the
potential to have particles with positive/negative charge and have one
set attracted and another repelled to/from the same domain. It does
change the way the attraction is computed slightly - in gravitation
the particle's mass cancels out when you calculate its acceleration,
with an electrostatic type interaction you need a charge and a mass to
compute the acceleration.
I've had a busy summer (southern hemisphere), so this is the first
look I've had at this stuff in a while. From memory still on the list
for this controller were:
1. Attract to the nearest domain point, not the centre.
2. Unit tests.
I have a deadline in a couple of days, once met I should have the
headspace to tackle these.
Cheers,
-------------------------
Andrew Charles
On Mon, Jan 12, 2009 at 10:40 PM, Andrew Charles <ac1...@gmail.com> wrote:
> As discussed, here's a 3D attract/repel controller example, along with
> a patch for the latest trunk. The exponent is now a parameter, and it
> now draws billboard quads.
Ok, it works for me. I think it would look better if the smaller
circles (electrons?) were fuzzy-edged so that the streaming particles
look more like the trail of a comet. Kinda like larger versions of the
lead sparks in the fireworks example. It might also be more
interesting if the larger particles were dynamic. Maybe they should
move or appear and disappear, I'm not sure.
Another option might be to create an example with plane domains at top
an bottom and have their attraction fields fluctuate out of phase,
causing the particles to alternate between being attracted up or down.
With particle trails that might look interesting.
> I take it from the latest lepton announcement that you want to change
> the name from 'attractor' to 'magnet'? Sounds good - gives you the
> potential to have particles with positive/negative charge and have one
> set attracted and another repelled to/from the same domain.
The intent of the name change was to make it clear that the controller
could repel and attract. I hadn't thought of particles having a
charge, but I think that's a good idea. It could be used to create
some neat electrostatic type simulations. Think styrofoam pellets
suspended in a fluctuating electric field or something like that.
> It does
> change the way the attraction is computed slightly - in gravitation
> the particle's mass cancels out when you calculate its acceleration,
> with an electrostatic type interaction you need a charge and a mass to
> compute the acceleration.
Right, but I'm not sure we'd always want the mass to matter. For
example we might sometimes want to simulate gravity or anti-gravity
like forces, it probably should be configurable whether to consider
mass when you calculate the acceleration. The goal here is not really
to simulate reality, but to allow effects of various realisms.
> I've had a busy summer (southern hemisphere), so this is the first
> look I've had at this stuff in a while. From memory still on the list
> for this controller were:
>
> 1. Attract to the nearest domain point, not the centre.
> 2. Unit tests.
>
> I have a deadline in a couple of days, once met I should have the
> headspace to tackle these.
I'm glad to see you back, I wasn't sure if you'd simply lost patience
with me ;^). I've been happy to have time these last few weeks to push
things ahead again, and get back into it.
What I'd like to see is a method added to the domain interface, and
each current domain implementation, that returns the closest point in
the domain to a provided arbitrary point in space. This could be used
for various purposes, but it would first be used to calculate the
distance from particles to the domain surface for the magnet
controller. In python the interface would be something like:
def closest_point_to(self, point):
"""Return the closest point inside the domain to the provided point.
If the specified point is inside the domain, the same point is returned.
If there are multiple closest points, one is returned at random,
thus multiple calls to this method with certain inputs may return
different outputs in certain circumstances
"""
The last part of the docstring above is to cover edge cases like
asking for the closest point of a spherical shell from the sphere's
center point. This is a pragmatic solution, ideally it would return a
thin spherical shell with the inner radius of the sphere that was
queried, but that is much more complicated for the caller and doesn't
buy much IMO. I think simulating particles realistically inside of a
spherical shell magnet is out of scope.
Also it would be useful for the magnet controller to have an optional
hard cutoff distance. Particles beyond this distance are not affected
by the controller. This serves as both a performance optimization and
a way to create intentionally unrealistic "step fields" that act more
like a compliant rubber ball or ball or tar then a real magnet.
All of the existing domains are implemented in C now, so the api
change above will need to be done in the C code. I'll see if I have
time to implement this in the near term, or go ahead if you have the
inclination. I especially think domains like planes and lines will be
able to do interesting things when coupled with a magnet controller.
Later when we have cones and cylinders more interesting effects will
be possible.
I see in your python code, you have some comments regarding optimizing
vector and sqrt math. Don't worry about that, when complete the
controller will be ported to C for speed where we already have
optimized routines to handle those. Later I will be exposing a more
useful vector class, which will aid in speedy interaction between
python code and the native lepton code.
Take care and thanks for the contribution,
-Casey
Adding a mass attribute to particles - it's a slippery slope, and if 9
times out of 10 controllers just use the default mass it seems
wasteful. On the other hand it makes implementing other
physically-motivated forces more straightforward (springs for
cloth/fur, lennard-jones type forces for fluid effects). It's not
strictly necessary for an electrostatic type force anyway - all
particles can just have a default mass of 1.0 - I can't think of any
visual effects for which you need variable mass.
I'll have a go at implementing closest_point_to - my C is a little
rusty (would you believe most of my coding these days is in IDL, a
Matlab-like high-level language that only meterologists and
astronomers use), but it's like riding a bike. Let you know how I'm
travelling in a couple of days or so.
Andrew
The particles already support mass, though no controller currently
considers it. The upcoming wind controller will use it, and I agree it
could be useful for fluid effects. I'll leave it up to you if you want
to leverage it for magnet.
> I'll have a go at implementing closest_point_to - my C is a little
> rusty (would you believe most of my coding these days is in IDL, a
> Matlab-like high-level language that only meterologists and
> astronomers use), but it's like riding a bike. Let you know how I'm
> travelling in a couple of days or so.
The method I have been using to port is to first get a decent set of
passing tests against a python implementation, then migrate it over
and work it until the tests pass again. You should be able to start by
copying one of the existing controller types and modifying it to suit.
There's a decent amount of python api boiler-plate that varies little
between the controllers.
-Casey
For starters, I wrote the method to simply return the center of the domain:
static PyObject *
SphereDomain_closest_point_to(SphereDomainObject *self, PyObject *args)
{
return PyTuple_Pack(3, &self->center.x, &self->center.y, &self->center.z);
}
When called from python, this returns a tuple of 3 seemingly not-quite
random numbers. Not sure what I'm doing wrong - fell free to point it
out.
Andrew
My initial plan was to simply call the sphere's intersect routine on
the line segment defined by the center of the sphere domain, and the
point's position. I'm playing with this at the moment, not sure it's
the best approach due to the tuple packing and value building needed
to pass arguments from closest_point() to intersect()
-Andrew
I was wondering if you were getting any traction on implementing this.
I'm working on some new domains and I can probably take a stab at
adding a closest_point() method to the existing ones as well. Let me
know if that would be helpful.
-Casey
-Andrew
I'm surprised at how differently it behaves - with a central
attraction you get nice sweeping elliptical curves, and orbits - with
the closest point attraction it's much more like a magnet - particles
tend to stick to the domain. It's so different visually that it makes
me wonder whether attraction to the centre should be a keyword option,
or a different controller altogether.
-Andrew
On Sun, Feb 8, 2009 at 4:16 PM, Andrew Charles <ac1...@gmail.com> wrote:
>
> The nearest point attraction is working for the sphere domain, but I
> am still cleaning up the C code.
Ok, don't fuss too much about it, shoot me a patch when you get it
reasonable and we can discuss from there. Are you working from svn?
That will make it very easy to track my changes and generate patches.
> I'm surprised at how differently it behaves - with a central
> attraction you get nice sweeping elliptical curves, and orbits - with
> the closest point attraction it's much more like a magnet - particles
> tend to stick to the domain. It's so different visually that it makes
> me wonder whether attraction to the centre should be a keyword option,
> or a different controller altogether.
I'm not surprised that it behaves differently, that was my intention.
To get what you originally wanted I don't think you need a different
controller, but a different domain. What would work I think is a Point
domain. It would be trivial to implement, it just wasn't useful for
the existing controllers and emitters, but I could see it being useful
here. You should be able to approximate it with a zero radius (or
nearly zero) sphere domain to test. Regardless I think a point domain
would be good to have.
-Casey
Here' a patch to get from the current trunk to my working copy.
The sphere intersection logic is now in vector.h. I'm not entirely
happy with simply returning the starting point of the line segment if
no intersection is found, but it works for now, and seems consistent
with the line intersection code.
However ... the sphere intersection is failing the tangent test case,
for reasons not obvious to me. Depending on when I can get my son to
bed I might be able to take another look at why it's failing tonight.
The examples (magnet2d.py and magnet.py) are no longer pretty, but as
visual tests they should work.
All the best,
-Andrew
I had in mind the possibility for different particle groups to be
attracted with different strengths, but parameterizing the particle
charge in the magnet function doesn't accomplish this.
5,000 has no particular significance other than looking good in the
magnet example. 50,000 seems a bit strong and 5,00 a bit weak.
-Andrew
If folks think it's worthwhile, I'll create a separate google group to
send checkin messages to. Right now they only get sent to me. Of
course you can see checkins on the project site, but that seems kinda
tedious 8^)
-Casey
I'd like to see Magnet make it into this release. If you like I can
port over your Python implementation to C, unless you are already
working on that. I will be working on closest_point_to)_
implementations for the other domains as well.
-Casey
I'd like to release in the next few days. It will be a 0.9a release
since it has new features and some api changes. The release deadline
is artificial, of course, but I find I am much more productive with
some kind of schedule.
> Depending on the schedule I'll do the port, or just focus on the
> example. My google code account is the same as this mail account -
> ac1201.
I added you as a project member. How about you check in the python
version as-is, then work on the example and any Magnet changes in
python. I have one more domain I am working on and then I'd like to
implement closest_point_to() for the remaining ones. If I get done
with those things quickly I can do the Magnet port, but we can move
forward with it in python for now.
-Casey
OK I definetely don't have time to tackle the C port in that case.
> I added you as a project member. How about you check in the python
> version as-is, then work on the example and any Magnet changes in
> python. I have one more domain I am working on and then I'd like to
> implement closest_point_to() for the remaining ones. If I get done
> with those things quickly I can do the Magnet port, but we can move
> forward with it in python for now.
Sounds good, I'll do a quick tidy-up then check the Magnet in.
-Andrew
I'm on holidays at the moment so very little network access - can't
connect with linux so can't use my svn client to check files in. Will
try later today at another cafe. In case it doesn't work, here are the
files, zipped, and the diffs (from r160) for the python implementation
of magnet and two examples. magnet2d.py is more a functionality test
example, might not be suitable for release.
One of the magnet controller tests is failing (error is about 3 *
epsilon), I think the normalize_fast routine's precision is to blame.
Cheers,
Andrew
I was doing some profiling of the InvSqrt code vs. the full-precision
sqrtf. The latter compiles to a single SSE instruction now, so it
actually beats the former by about 2x. I'll probably be ripping out
the InvSqrt code as a result unless someone is going to run on a
platform where it's actually a win (I'm thinking no). There's actually
an even faster reciprocal sqrt estimate SSE instruction that I'll
probably play with for future. Right now there are bigger performance
fish to fry, such as argument parsing. That's going to be a priority
for me for beyond 0.9 since we pass lots of vectors around between C
routines and all that parsing is very inefficient.
I've also been chewing on ideas for efficient particle-particle
collision algorithms. Having that capability would be very cool.
Before I get there though, there is some other lower-hanging fruit,
mostly in the form of additional controllers I'd like to have. One we
get 0.9 out I'll revisit the laundry list and see what looks
interesting, if anyone else has specific wants and needs, suggestions
are welcome.
-Casey
For particle-particle interactions, a simple verlet list is a good
benchmark, and probably beats more sophisticated spatial partitioning
methods for systems at least a few hundred particles in size. The
books I have that suggest this are over ten years old, so it's
possible there are newer algorithms that are always better. The verlet
list algorithm (named after French physicist Loup Verlet is basically:
1. Compute squared distances between all pairs
2. Exclude all pairs further apart than tolerance + interaction cutoff
3. Compute interaction
4. If any pair distance has changed by more than tolerance, rebuild
the list from step 1.
5. Otherwise just re-prune the list (step 2) and reuse it.
-Andrew
Ok, I haven't gotten to it yet, so that's fine. I did make some
headway in my travels on the Cone domain, its nearly ready for checkin
now. After that I'm going to get closest_point_to() implemented
everywhere.
For collision I've been looking at recursive dimensional clustering
coupled with an iterative sort performed along one dimension per
frame. However, I think your suggestion would make an excellent
baseline to compare against other methods and would be relatively
straightforward to implement. Seems like a good place to start.
-Casey
The magnitude of an inverse exponential force is given by k/r**a.
The elements of the unit vector in the direction of r are (dx/r, dy/r, dz/r) .
If r**a and r**(a + 1) are equally expensive, you could do the
calculation faster as you suggest in your last code snippet, but
change the name of mag because it's not the magnitude of the force any
more.
dv = (k / r**a) * normalize(r) would also work but this involves
another square root, and we already have the length of r. Even though
their implementations have been tuned up, square roots are still
expensive, right? I've verified that all three of these methods
behave in exactly the same way
If there's not much performance difference either way it's probably
clearer to keep the definition of the value of the force magnitude
seperate from the unit vector calculation.
If the force were a sine wave central force with mag = sin(r), you would have
dv/dt = sin(r)*(dx/r,dy/r,dz/r)
and you wouldn't be able to simplify it.
Andrew
The big green particle in the centre dominates a bit - I think it
looks better when it is smaller.
Cheers,
Andrew
Yeah I thought that worked out well.
> The big green particle in the centre dominates a bit - I think it
> looks better when it is smaller.
I think it might be a difference in monitor gamma. With my monitor in
"calibrated mode" it looks fine, but with the default RGB setting it
looks a lot bigger. Unlike in SDL/pygame, you can't adjust the gamma
from pyglet. We have a binary, so I'm inclined to leave it for 0.9a,
something we can address later if we like.
-Casey
>> The big green particle in the centre dominates a bit - I think it
>> looks better when it is smaller.
>
> I think it might be a difference in monitor gamma. With my monitor in
> "calibrated mode" it looks fine, but with the default RGB setting it
> looks a lot bigger. Unlike in SDL/pygame, you can't adjust the gamma
> from pyglet. We have a binary, so I'm inclined to leave it for 0.9a,
> something we can address later if we like.
Sounds good, it's a small thing anyway. I had a quick look at the
pyglet list archives and Alex stated fairly categorically that he
wasn't interested (August last year) in adding gamma correction to
pyglet.
-Andrew