[Bf-committers] Particle experiments - looking for feedback
Alex Mole
bf-committers@blender.org
Sun, 02 May 2004 11:32:51 +0100
Hi Leon
[apologies for huge post...]
reblended.com is back up again now :)
I have a few optimisation tips for this code, which should easily speed
it up enough that you'll be able to treat all quads as tris.
For every particle, every deflection mesh gets converted to world
coordinates. This means potentially a lot of duplicated effort [not too
much for single quads, but to bounce it off interesting meshes and use
it to its full potential, there will be a lot]. Have you considered
transforming each particle by the inverse of the object's matrix and
carrying out the calculations in object-local space [and then
transforming back again once you're done]? That means at most 4 matrix
mults per mesh, and most likely only 2. This would probably speed it up
by an order of magnitude :)
The other point I'd make is that pointintriangle() uses an algorithm
that is easy to understand, but has been shown to be much slower than
what is possible. Möller&Trumbore presented this much faster technique
for testing whether a line segment crosses a triangle [in this case the
line segment is the line from the old position to the new position]. You
can have a look to find others at
http://www.acm.org/pubs/tog/editors/erich/ptinpoly/
pseudocode:
params: o = start pos, b = end pos, v0,v1,v2 = triangle vertices
def LineTriIntersect (o, b, v0, v1, v2)
[returns ({REJECT,INTERSECT}, u, v, t)]
e1 = v1 - v0
e2 = v2 - v0
d = b - o
p = d x e2
a = e1 . p
if (a > -E and a < E) return (REJECT, 0, 0, 0)
f = 1 / a
s = o - v0
u = f * (s . p)
if (u < 0.0 or u > 1.0) return (REJECT, 0, 0, 0)
q = s x e1
t = f * (e2 . q)
if (t < 0.0 or t > 1.0) return (REJECT, 0, 0, 0)
v = f * (d . q)
if (v < 0.0 or v > 1.0) return (REJECT, 0, 0, 0)
return (INTERSECT, u, v, t)
u&v are the barycentric coordinates of intersection on the triangle, and
t is the parametric point of intersection on the line, so that:
point_of_intersection = start_point + t*(end_point-start_point)
There are almost certainly faster methods of doing this still, but the
above will be substantially better than the angle-summing method :)
I'm happy to help with the implementation of this stuff [and I'm happy
for you to just ignore it, as you probably have better things to do than
reimplement your work ;)]
One other tip, that applies to all graphics coders, is to get hold of a
copy of Real Time Rendering by Möller and Haines
(http://www.amazon.com/exec/obidos/tg/detail/-/1568811829/qid=1083493711/sr=8-1/ref=pd_ka_1/104-4857886-1060759?v=glance&s=books&n=507846)
It is *by far* the best book I've seen on the topic, and covers all
manner of rendering techniques, intersection tests, higher-order
surfaces, etc. etc.). I really can't reccommend it enough :)
Cheers-
Alex