| 1515 | } |
| 1516 | |
| 1517 | void ApplyVortex(dmArray<Particle>& particles, Property* modifier_properties, const Point3& position, const Quat& rotation, float scale, float emitter_t, float dt) |
| 1518 | { |
| 1519 | uint32_t particle_count = particles.Size(); |
| 1520 | const Property& magnitude_property = modifier_properties[MODIFIER_KEY_MAGNITUDE]; |
| 1521 | const Property& max_distance_property = modifier_properties[MODIFIER_KEY_MAX_DISTANCE]; |
| 1522 | uint32_t segment_index = dmMath::Min((uint32_t)(emitter_t * PROPERTY_SAMPLE_COUNT), PROPERTY_SAMPLE_COUNT - 1); |
| 1523 | float magnitude; |
| 1524 | SAMPLE_PROP(magnitude_property.m_Segments[segment_index], emitter_t, magnitude) |
| 1525 | float mag_spread = magnitude_property.m_Spread; |
| 1526 | // We temporarily only sample the first frame until we have decided what to animate over |
| 1527 | float max_distance = max_distance_property.m_Segments[0].m_Y * scale; |
| 1528 | float max_sq_distance = max_distance * max_distance; |
| 1529 | Vector3 axis = rotate(rotation, VORTEX_LOCAL_AXIS); |
| 1530 | Vector3 start = rotate(rotation, VORTEX_LOCAL_START_DIR); |
| 1531 | float applied_factor = dt * scale; |
| 1532 | for (uint32_t i = 0; i < particle_count; ++i) |
| 1533 | { |
| 1534 | Particle* particle = &particles[i]; |
| 1535 | // delta from vortex position |
| 1536 | Vector3 delta = particle->GetPosition() - position; |
| 1537 | // normal from vortex axis (non-unit) |
| 1538 | Vector3 normal = delta - projection(Point3(delta), axis) * axis; |
| 1539 | // tangent is the direction of the vortex acceleration |
| 1540 | Vector3 tangent = cross(axis, normal); |
| 1541 | // In case the particle is directed along the axis, give it a guaranteed orthogonal start |
| 1542 | tangent = NonZeroVector3(tangent, lengthSqr(tangent), start); |
| 1543 | // tangent is now guaranteed to be non-zero |
| 1544 | tangent = normalize(tangent); |
| 1545 | // use normal for max distance test |
| 1546 | float normal_sq_len = lengthSqr(normal); |
| 1547 | float acceleration = dmMath::Select(max_sq_distance - normal_sq_len, magnitude + mag_spread * particle->GetSpreadFactor(), 0.0f); |
| 1548 | particle->SetVelocity(particle->GetVelocity() + tangent * acceleration * applied_factor); |
| 1549 | } |
| 1550 | } |
| 1551 | |
| 1552 | #undef SAMPLE_PROP |
| 1553 | |