#include <actions.h>
Public Member Functions | |
~PAAvoid () | |
void | Exec (const PDTriangle &dom, ParticleGroup &group, ParticleList::iterator ibegin, ParticleList::iterator iend) |
void | Exec (const PDRectangle &dom, ParticleGroup &group, ParticleList::iterator ibegin, ParticleList::iterator iend) |
void | Exec (const PDPlane &dom, ParticleGroup &group, ParticleList::iterator ibegin, ParticleList::iterator iend) |
void | Exec (const PDSphere &dom, ParticleGroup &group, ParticleList::iterator ibegin, ParticleList::iterator iend) |
void | Exec (const PDDisc &dom, ParticleGroup &group, ParticleList::iterator ibegin, ParticleList::iterator iend) |
Public Attributes | |
pDomain * | position |
float | look_ahead |
float | magnitude |
float | epsilon |
EXEC_METHOD |
Definition at line 45 of file actions.h.
PAAvoid::~PAAvoid | ( | ) | [inline] |
void PAAvoid::Exec | ( | const PDTriangle & | dom, | |
ParticleGroup & | group, | |||
ParticleList::iterator | ibegin, | |||
ParticleList::iterator | iend | |||
) |
Definition at line 31 of file actions.cpp.
References PDTriangle::D, PActionBase::dt, epsilon, fsqr(), pVec::length(), pVec::length2(), look_ahead, magnitude, NewBasis(), pVec::normalize(), PDTriangle::nrm, PDTriangle::p, Particle::pos, pSameSign(), PDTriangle::u, PDTriangle::uNrm, PDTriangle::v, Particle::vel, and PDTriangle::vNrm.
00032 { 00033 float magdt = magnitude * dt; 00034 00035 const pVec &u = dom.u; 00036 const pVec &v = dom.v; 00037 00038 // The normalized bases are needed inside the loop. 00039 const pVec &un = dom.uNrm; 00040 const pVec &vn = dom.vNrm; 00041 00042 // f is the third (non-basis) triangle edge. 00043 pVec f = v - u; 00044 pVec fn = f; 00045 fn.normalize(); 00046 00047 // Compute the inverse matrix of the plane basis. 00048 pVec s1, s2; 00049 NewBasis(u, v, s1, s2); 00050 00051 for (ParticleList::iterator it = ibegin; it != iend; it++) { 00052 Particle &m = (*it); 00053 00054 // See if particle's current and look_ahead positions cross plane. 00055 // If not, couldn't hit, so keep going. 00056 pVec pnext = m.pos + m.vel * dt * look_ahead; 00057 00058 // nrm stores the plane normal (the a,b,c of the plane eqn). 00059 // Old and new distances: dist(p,plane) = n * p + d 00060 float distold = m.pos * dom.nrm + dom.D; 00061 float distnew = pnext * dom.nrm + dom.D; 00062 00063 if(pSameSign(distold, distnew)) 00064 continue; 00065 00066 float nv = dom.nrm * m.vel; 00067 float t = -distold / nv; // Time steps before hit 00068 00069 pVec phit = m.pos + m.vel * t; // Actual intersection point 00070 pVec offset = phit - dom.p; // Offset from origin in plane 00071 00072 // Dot product with basis vectors of old frame 00073 // in terms of new frame gives position in uv frame. 00074 float upos = offset * s1; 00075 float vpos = offset * s2; 00076 00077 // Did it cross plane outside triangle? 00078 if(upos < 0 || vpos < 0 || (upos + vpos) > 1) 00079 continue; 00080 00081 // A hit! A most palpable hit! 00082 // Compute distance to the three edges. 00083 pVec uofs = (un * (un * offset)) - offset; 00084 float udistSqr = uofs.length2(); 00085 pVec vofs = (vn * (vn * offset)) - offset; 00086 float vdistSqr = vofs.length2(); 00087 00088 pVec foffset = offset - u; 00089 pVec fofs = (fn * (fn * foffset)) - foffset; 00090 float fdistSqr = fofs.length2(); 00091 00092 // S is the safety vector toward the closest point on boundary. 00093 pVec S; 00094 if(udistSqr <= vdistSqr && udistSqr <= fdistSqr) S = uofs; 00095 else if(vdistSqr <= fdistSqr) S = vofs; 00096 else S = fofs; 00097 00098 // Blend S with m.vel. 00099 S.normalize(); 00100 00101 float vm = m.vel.length(); 00102 pVec Vn = m.vel / vm; 00103 00104 pVec dir = (S * (magdt / (fsqr(t)+epsilon))) + Vn; 00105 m.vel = dir * (vm / dir.length()); // Speed of m.vel, but in direction dir. 00106 } 00107 }
void PAAvoid::Exec | ( | const PDRectangle & | dom, | |
ParticleGroup & | group, | |||
ParticleList::iterator | ibegin, | |||
ParticleList::iterator | iend | |||
) |
Definition at line 109 of file actions.cpp.
References PDRectangle::D, PActionBase::dt, epsilon, fsqr(), pVec::length(), pVec::length2(), look_ahead, magnitude, NewBasis(), pVec::normalize(), PDRectangle::nrm, PDRectangle::p, Particle::pos, pSameSign(), PDRectangle::u, PDRectangle::uNrm, PDRectangle::v, Particle::vel, and PDRectangle::vNrm.
00110 { 00111 float magdt = magnitude * dt; 00112 00113 const pVec &u = dom.u; 00114 const pVec &v = dom.v; 00115 00116 // The normalized bases are needed inside the loop. 00117 const pVec &un = dom.uNrm; 00118 const pVec &vn = dom.vNrm; 00119 00120 // Compute the inverse matrix of the plane basis. 00121 pVec s1, s2; 00122 NewBasis(u, v, s1, s2); 00123 00124 for (ParticleList::iterator it = ibegin; it != iend; it++) { 00125 Particle &m = (*it); 00126 00127 // See if particle's current and look_ahead positions cross plane. 00128 // If not, couldn't hit, so keep going. 00129 pVec pnext = m.pos + m.vel * dt * look_ahead; 00130 00131 // nrm stores the plane normal (the a,b,c of the plane eqn). 00132 // Old and new distances: dist(p,plane) = n * p + d 00133 float distold = m.pos * dom.nrm + dom.D; 00134 float distnew = pnext * dom.nrm + dom.D; 00135 00136 if(pSameSign(distold, distnew)) 00137 continue; 00138 00139 float nv = dom.nrm * m.vel; 00140 float t = -distold / nv; 00141 00142 pVec phit = m.pos + m.vel * t; // Actual intersection point 00143 pVec offset = phit - dom.p; // Offset from origin in plane 00144 00145 // Dot product with basis vectors of old frame 00146 // in terms of new frame gives position in uv frame. 00147 float upos = offset * s1; 00148 float vpos = offset * s2; 00149 00150 // Did it cross plane outside rectangle? 00151 if(upos < 0 || vpos < 0 || upos > 1 || vpos > 1) 00152 continue; 00153 00154 // A hit! A most palpable hit! 00155 // Compute distance to the three edges. 00156 pVec uofs = (un * (un * offset)) - offset; 00157 float udistSqr = uofs.length2(); 00158 pVec vofs = (vn * (vn * offset)) - offset; 00159 float vdistSqr = vofs.length2(); 00160 00161 pVec foffset = (u + v) - offset; 00162 pVec fofs = (un * (un * foffset)) - foffset; 00163 float fdistSqr = fofs.length2(); 00164 pVec gofs = (un * (un * foffset)) - foffset; 00165 float gdistSqr = gofs.length2(); 00166 00167 pVec S; 00168 if(udistSqr <= vdistSqr && udistSqr <= fdistSqr 00169 && udistSqr <= gdistSqr) S = uofs; 00170 else if(vdistSqr <= fdistSqr && vdistSqr <= gdistSqr) S = vofs; 00171 else if(fdistSqr <= gdistSqr) S = fofs; 00172 else S = gofs; 00173 00174 // Blend S with m.vel. 00175 S.normalize(); 00176 00177 float vm = m.vel.length(); 00178 pVec Vn = m.vel / vm; 00179 00180 pVec dir = (S * (magdt / (fsqr(t)+epsilon))) + Vn; 00181 m.vel = dir * (vm / dir.length()); // Speed of m.vel, but in direction dir. 00182 } 00183 }
void PAAvoid::Exec | ( | const PDPlane & | dom, | |
ParticleGroup & | group, | |||
ParticleList::iterator | ibegin, | |||
ParticleList::iterator | iend | |||
) |
Definition at line 185 of file actions.cpp.
References PDPlane::D, PActionBase::dt, epsilon, fsqr(), pVec::length(), look_ahead, magnitude, PDPlane::nrm, Particle::pos, pSameSign(), and Particle::vel.
00186 { 00187 float magdt = magnitude * dt; 00188 00189 for (ParticleList::iterator it = ibegin; it != iend; it++) { 00190 Particle &m = (*it); 00191 00192 // See if particle's current and look_ahead positions cross plane. 00193 // If not, couldn't hit, so keep going. 00194 pVec pnext = m.pos + m.vel * dt * look_ahead; 00195 00196 // nrm stores the plane normal (the a,b,c of the plane eqn). 00197 // Old and new distances: dist(p,plane) = n * p + d 00198 float distold = m.pos * dom.nrm + dom.D; 00199 float distnew = pnext * dom.nrm + dom.D; 00200 00201 if(pSameSign(distold, distnew)) 00202 continue; 00203 00204 float nv = dom.nrm * m.vel; 00205 float t = -distold / nv; 00206 00207 // Blend S with m.vel. 00208 const pVec &S = dom.nrm; 00209 00210 float vm = m.vel.length(); 00211 pVec Vn = m.vel / vm; 00212 00213 pVec dir = (S * (magdt / (fsqr(t)+epsilon))) + Vn; 00214 m.vel = dir * (vm / dir.length()); // Speed of m.vel, but in direction dir. 00215 } 00216 }
void PAAvoid::Exec | ( | const PDSphere & | dom, | |
ParticleGroup & | group, | |||
ParticleList::iterator | ibegin, | |||
ParticleList::iterator | iend | |||
) |
Definition at line 219 of file actions.cpp.
References PDSphere::ctr, PActionBase::dt, epsilon, fsqr(), pVec::length(), look_ahead, magnitude, pVec::normalize(), Particle::pos, PDSphere::radOutSqr, sqrtf(), and Particle::vel.
00220 { 00221 float magdt = magnitude * dt; 00222 00223 for (ParticleList::iterator it = ibegin; it != iend; it++) { 00224 Particle &m = (*it); 00225 00226 // First do a ray-sphere intersection test and see if it's soon enough. 00227 // Can I do this faster without t? 00228 float vm = m.vel.length(); 00229 pVec Vn = m.vel / vm; 00230 00231 pVec L = dom.ctr - m.pos; 00232 float v = L * Vn; 00233 00234 float disc = dom.radOutSqr - (L * L) + fsqr(v); 00235 if(disc < 0) 00236 continue; // I'm not heading toward it. 00237 00238 // Compute length for second rejection test. 00239 float t = v - sqrtf(disc); 00240 if(t < 0 || t > (vm * look_ahead)) 00241 continue; 00242 00243 // Get a vector to safety. 00244 pVec C = Cross(Vn, L); 00245 C.normalize(); 00246 pVec S = Cross(Vn, C); 00247 00248 pVec dir = (S * (magdt / (fsqr(t)+epsilon))) + Vn; 00249 m.vel = dir * (vm / dir.length()); // Speed of m.vel, but in direction dir. 00250 } 00251 }
void PAAvoid::Exec | ( | const PDDisc & | dom, | |
ParticleGroup & | group, | |||
ParticleList::iterator | ibegin, | |||
ParticleList::iterator | iend | |||
) |
Definition at line 253 of file actions.cpp.
References PDDisc::D, PActionBase::dt, epsilon, fsqr(), pVec::length(), pVec::length2(), look_ahead, magnitude, PDDisc::nrm, PDDisc::p, Particle::pos, pSameSign(), PDDisc::radOutSqr, and Particle::vel.
00254 { 00255 float magdt = magnitude * dt; 00256 00257 for (ParticleList::iterator it = ibegin; it != iend; it++) { 00258 Particle &m = (*it); 00259 00260 // See if particle's current and look_ahead positions cross plane. 00261 // If not, couldn't hit, so keep going. 00262 pVec pnext = m.pos + m.vel * dt * look_ahead; 00263 00264 // nrm stores the plane normal (the a,b,c of the plane eqn). 00265 // Old and new distances: dist(p,plane) = n * p + d 00266 float distold = m.pos * dom.nrm + dom.D; 00267 float distnew = pnext * dom.nrm + dom.D; 00268 00269 if(pSameSign(distold, distnew)) 00270 continue; 00271 00272 float nv = dom.nrm * m.vel; 00273 float t = -distold / nv; 00274 00275 pVec phit = m.pos + m.vel * t; // Actual intersection point 00276 pVec offset = phit - dom.p; // Offset from origin in plane 00277 00278 float radSqr = offset.length2(); 00279 00280 // Are we going to hit the disc ring? If so, always turn to the OUTSIDE of the ring. 00281 if(radSqr < dom.radInSqr || radSqr > dom.radOutSqr) 00282 continue; 00283 00284 // Blend S with m.vel. 00285 pVec S = offset; 00286 00287 float vm = m.vel.length(); 00288 pVec Vn = m.vel / vm; 00289 00290 pVec dir = (S * (magdt / (fsqr(t)+epsilon))) + Vn; 00291 m.vel = dir * (vm / dir.length()); // Speed of m.vel, but in direction dir. 00292 } 00293 }
float PAAvoid::look_ahead |
float PAAvoid::magnitude |
float PAAvoid::epsilon |