//----------------------------------------------------------------------- void BoxCollider::_affect(ParticleTechnique* particleTechnique, Particle* particle, Real timeElapsed) { mPredictedPosition = particle->position + mVelocityScale * particle->direction; bool collision = false; /** Collision detection is a two-step. First, we determine whether the particle is now colliding. If it is, the particle is re-positioned. However, a timeElapsed value is used, which is not the same as the one that was used at the moment before the particle was colliding. Therefore, we rather want to predict particle collision in front. This probably isn't the fastest solution. The same approach was used for the other colliders. */ switch(mIntersectionType) { case BaseCollider::IT_POINT: { // Validate for a point-box intersection if (mInnerCollision != mBox.intersects(particle->position)) { // Collision detected (re-position the particle) particle->position -= mVelocityScale * particle->direction; collision = true; } else if (mInnerCollision != mBox.intersects(mPredictedPosition)) { // Collision detected collision = true; } } break; case BaseCollider::IT_BOX: { // Validate for a box-box intersection if (particle->particleType != Particle::PT_VISUAL) break; VisualParticle* visualParticle = static_cast<VisualParticle*>(particle); AxisAlignedBox box; populateAlignedBox(box, visualParticle->position, visualParticle->width, visualParticle->height, visualParticle->depth); if (mInnerCollision != box.intersects(mBox)) { // Collision detected (re-position the particle) particle->position -= mVelocityScale * particle->direction; collision = true; } else { AxisAlignedBox box; populateAlignedBox(box, mPredictedPosition, visualParticle->width, visualParticle->height, visualParticle->depth); if (mInnerCollision != box.intersects(mBox)) { // Collision detected collision = true; } } } break; } if (collision) { calculateDirectionAfterCollision(particle); calculateRotationSpeedAfterCollision(particle); particle->addEventFlags(Particle::PEF_COLLIDED); } }
void PUParticle3DPlaneCollider::updatePUAffector( PUParticle3D *particle, float deltaTime ) { //for (auto iter : _particleSystem->getParticles()) { //PUParticle3D *particle = iter; _predictedPosition = particle->position + _velocityScale * particle->direction; bool collision = false; switch(_intersectionType) { case PUParticle3DBaseCollider::IT_POINT: { // Validate for a point-plane intersection (on the plane or the back side) // First determine whether it is now colliding (some affector made the particle move), else // determine whether it WILL be colliding if (_plane.getDistance(particle->position) <= 0.0f) { // Collision detected (re-position the particle) particle->position -= _velocityScale * particle->direction; collision = true; } else if (_plane.getDistance(_predictedPosition) <= 0.0f) { // Collision detected collision = true; } } break; case PUParticle3DBaseCollider::IT_BOX: { AABB box; populateAlignedBox(box, particle->position, particle->width, particle->height, particle->depth); //FIXME //if (box.intersects(_plane)) //{ // // Collision detected (re-position the particle) // particle->position -= _velocityScale * particle->direction; // collision = true; //} //else //{ // populateAlignedBox(box, // _predictedPosition, // particle->width, // particle->height, // particle->depth); // if (box.intersects(_plane)) // { // // Collision detected // collision = true; // } //} } break; } if (collision) { calculateDirectionAfterCollision(particle, deltaTime); calculateRotationSpeedAfterCollision(particle); particle->addEventFlags(PUParticle3D::PEF_COLLIDED); } } }
void PUBoxCollider::updatePUAffector( PUParticle3D *particle, float deltaTime ) { //for (auto iter : _particleSystem->getParticles()) { //PUParticle3D *particle = iter; _predictedPosition = particle->position + _velocityScale * particle->direction; bool collision = false; /** Collision detection is a two-step. First, we determine whether the particle is now colliding. If it is, the particle is re-positioned. However, a timeElapsed value is used, which is not the same as the one that was used at the moment before the particle was colliding. Therefore, we rather want to predict particle collision in front. This probably isn't the fastest solution. The same approach was used for the other colliders. */ switch(_intersectionType) { case PUBaseCollider::IT_POINT: { // Validate for a point-box intersection if (_innerCollision != _box.containPoint(particle->position)) { // Collision detected (re-position the particle) particle->position -= _velocityScale * particle->direction; collision = true; } else if (_innerCollision != _box.containPoint(_predictedPosition)) { // Collision detected collision = true; } } break; case PUBaseCollider::IT_BOX: { AABB box; populateAlignedBox(box, particle->position, particle->width, particle->height, particle->depth); if (_innerCollision != box.intersects(_box)) { // Collision detected (re-position the particle) particle->position -= _velocityScale * particle->direction; collision = true; } else { populateAlignedBox(box, _predictedPosition, particle->width, particle->height, particle->depth); if (_innerCollision != box.intersects(_box)) { // Collision detected collision = true; } } } break; } if (collision) { calculateDirectionAfterCollision(particle); calculateRotationSpeedAfterCollision(particle); particle->addEventFlags(PUParticle3D::PEF_COLLIDED); } } }
void PUParticle3DSphereCollider::updatePUAffector( PUParticle3D *particle, float deltaTime ) { //for (auto iter : _particleSystem->getParticles()) { //PUParticle3D *particle = iter; _predictedPosition = particle->position + _velocityScale * particle->direction; bool collision = false; Vec3 distance = particle->position - _derivedPosition; float distanceLength = distance.length(); float scaledRadius = 0.3333f * (_affectorScale.x + _affectorScale.y + _affectorScale.z) * _radius; // Scaling changed in V 1.3.1 switch(_intersectionType) { case PUParticle3DBaseCollider::IT_POINT: { // Validate for a point-sphere intersection if (_innerCollision == (distanceLength > scaledRadius)) { // Collision detected (re-position the particle) particle->position -= _velocityScale * particle->direction; collision = true; } else { distance = _predictedPosition - _derivedPosition; distanceLength = distance.length(); if (_innerCollision == (distanceLength > scaledRadius)) { // Collision detected collision = true; } } } break; case PUParticle3DBaseCollider::IT_BOX: { //// Validate for a box-sphere intersection //if (particle->particleType != Particle::PT_VISUAL) // break; AABB box; populateAlignedBox(box, particle->position, particle->width, particle->height, particle->depth); //FIXME //if (_innerCollision != box.intersects(_sphere)) //{ // // Collision detected (re-position the particle) // particle->position -= _velocityScale * particle->direction; // collision = true; //} //else //{ // AABB box; // populateAlignedBox(box, // _predictedPosition, // particle->width, // particle->height, // particle->depth); // if (_innerCollision != box.intersects(_sphere)) // { // // Collision detected // collision = true; // } //} } break; } if (collision) { calculateDirectionAfterCollision(particle, distance, distanceLength); calculateRotationSpeedAfterCollision(particle); particle->addEventFlags(PUParticle3D::PEF_COLLIDED); } } }