/**<Summary> * Calculate the extent of the passed GamedObject * in the calling GameObject Coordinate System * </Summary> */ Vector3D GameObject::getTransformedExtents(SharedPointer<GameObject> i_other) { Vector3D i_otherExtentInThis; Matrix4x4 i_otherCentrePositionInThis = Matrix4x4(getTranslatedPosition(i_other->getPosition())); //Tranforming the Extents coordinate of passed gameObject in calling gameObject coordinate system Vector3D i_otherXExtentPositionInThis = getTranslatedPosition(i_other->getPosition() + Vector3D(i_other->mCollidingBox->getExtendX(), 0, 0)); Vector3D i_otherYExtentPositionInThis = getTranslatedPosition(i_other->getPosition() + Vector3D(0, i_other->mCollidingBox->getExtendY(), 0)); Vector3D i_otherZExtentPositionInThis = getTranslatedPosition(i_other->getPosition() + Vector3D(0, 0, i_other->mCollidingBox->getExtendZ())); Vector3D i_otherXExtentVectorInThis = i_otherXExtentPositionInThis - i_otherCentrePositionInThis.getPositionFromMatrix4x4(); Vector3D i_otherYExtentVectorInThis = i_otherYExtentPositionInThis - i_otherCentrePositionInThis.getPositionFromMatrix4x4(); Vector3D i_otherZExtentVectorInThis = i_otherZExtentPositionInThis - i_otherCentrePositionInThis.getPositionFromMatrix4x4(); //Creating the passed gameObject extent Vectors in calling gameObject coordinate system i_otherExtentInThis.setX(abs( i_otherXExtentVectorInThis.dotProduct(Vector3D(1.0f, 0.0f, 0.0f)) + i_otherYExtentVectorInThis.dotProduct(Vector3D(1.0f, 0.0f, 0.0f)) + i_otherZExtentVectorInThis.dotProduct(Vector3D(1.0f, 0.0f, 0.0f)) )); i_otherExtentInThis.setY(abs( i_otherXExtentVectorInThis.dotProduct(Vector3D(0.0f, 1.0f, 0.0f)) + i_otherYExtentVectorInThis.dotProduct(Vector3D(0.0f, 1.0f, 0.0f)) + i_otherZExtentVectorInThis.dotProduct(Vector3D(0.0f, 1.0f, 0.0f)) )); i_otherExtentInThis.setZ(abs( i_otherXExtentVectorInThis.dotProduct(Vector3D(0.0f, 0.0f, 1.0f)) + i_otherYExtentVectorInThis.dotProduct(Vector3D(0.0f, 0.0f, 1.0f)) + i_otherZExtentVectorInThis.dotProduct(Vector3D(0.0f, 0.0f, 1.0f)) )); //returning the extent of passed gameObject in calling gameObject coordinate system return i_otherExtentInThis; }
void PhysicsEngine::collisionTestFastParticles() { raySphereRelative.resizeToSizeIfRequiredWithBatchSize(fastParticles.getCount(), SphereRayHelper::batchSize); Array<int> collisionTestResult; collisionTestResult.setNumberOfElements(fastParticles.getCount(), false); for( int index = 0; index < physicsBodies.getCount(); index++ ) { SharedPointer<PhysicsBody> currentBody = physicsBodies[index]; float collisionSphereRadius = currentBody->boundingSphereRadius; SphereRayHelper::transferFastParticlesToRaySphereSoa(fastParticles, collisionSphereRadius, currentBody->getPosition(), raySphereRelative); SphereRayHelper::doBatchedCollisionTests(raySphereRelative); SphereRayHelper::checkForCollisions(raySphereRelative, fastParticles, collisionTestResult); // process the collision test result for( int collisionTestResultIndex = 0; collisionTestResultIndex < fastParticles.getCount(); collisionTestResultIndex++ ) { if( collisionTestResult[collisionTestResultIndex] != 0 ) { fastParticles[collisionTestResultIndex]->nextHitAnything = true; fastParticles[collisionTestResultIndex]->nextHitBody = currentBody; // NOTE< for now just against/for the bounding sphere > // TODO< calculate the hit position? > } } } }
/** *<summary> * Check separation Axis test between passed GameObject(A) and calling GameObject(B) * You may need to call it twice - for checking collision of B in A's coordinate system *</Summary> */ bool GameObject::separationAxisTest(SharedPointer<GameObject> i_other, float& o_collisionTime, float & o_separationTime, myEngine::typedefs::Axis &o_collisionAxis) //Move to Collsion System to make it better - To-Do { bool isColliding = false; float tCollisionInX = 0.0f; float tSeparationInX = 0.0f; float tCollisionInY = 0.0f; float tSeparationInY = 0.0f; float tCollisionInZ = 0.0f; float tSeparationInZ = 0.0f; //Position of other GameObject in this Vector3D i_otherCenterPositionInThis = getTranslatedPosition(i_other->getPosition()); //Extent of other gameObject in this Vector3D i_otherExtentInThis = getTransformedExtents(i_other); //Transformed velocity of calling gamobject in its own coordiante system Vector3D thisVelocityInThis = getTranslationMatrix() *physicsComponent->getCurrentVelocity(); //Velocity of other GameObject in calling gameObject coordinate system Vector3D i_otherVelocityInThis = getTranslationMatrix() * i_other->physicsComponent->getCurrentVelocity(); //Relative velocity of other gamObject in freezed gameObject coordinate system i.e. in calling gameObject coordiante system Vector3D i_otherChangedVelocityInThis = i_otherVelocityInThis - thisVelocityInThis; //Expanding the extents of calling gameObject float thisChangedXExtent = getCollider()->getExtendX() + i_otherExtentInThis.getX(); float thisChangedYExtent = getCollider()->getExtendY() + i_otherExtentInThis.getY(); float thisChangedZExtent = getCollider()->getExtendZ() + i_otherExtentInThis.getZ(); bool finalCollisionTimeInitialized = false; //Swept collision for each axes //Checking in X-Axis switch (i_otherCenterPositionInThis.getX() >= 0 ) { case true: if (i_otherCenterPositionInThis.getX() <= thisChangedXExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getX() != 0) { tCollisionInX = abs(((0 + thisChangedXExtent) - i_otherCenterPositionInThis.getX()) / i_otherChangedVelocityInThis.getX()); tSeparationInX = abs((i_otherCenterPositionInThis.getX() - (0 - thisChangedXExtent)) / i_otherChangedVelocityInThis.getX()); o_collisionTime = tCollisionInX; o_separationTime = tSeparationInX; o_collisionAxis = myEngine::typedefs::XAxis; finalCollisionTimeInitialized = true; } } else return false; break; case false: if (abs(i_otherCenterPositionInThis.getX()) <= thisChangedXExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getX() != 0) { tCollisionInX = abs((i_otherCenterPositionInThis.getX() - (0 - thisChangedXExtent)) / i_otherChangedVelocityInThis.getX()); tSeparationInX = abs(((0 + thisChangedXExtent) - i_otherCenterPositionInThis.getX()) / i_otherChangedVelocityInThis.getX()); o_collisionTime = tCollisionInX; o_separationTime = tSeparationInX; o_collisionAxis = myEngine::typedefs::XAxis; finalCollisionTimeInitialized = true; } } else return false; break; } //Check in Y-axis in case X-Axis collision is true switch (i_otherCenterPositionInThis.getY() >= 0) { case true: if (i_otherCenterPositionInThis.getY() <= thisChangedYExtent) { //To-Do - time of collision -Done but need testing if (i_otherChangedVelocityInThis.getY() != 0) { tCollisionInY = abs(((0 + thisChangedYExtent) - i_otherCenterPositionInThis.getY()) / i_otherChangedVelocityInThis.getY()); tSeparationInY = abs((i_otherCenterPositionInThis.getY() - (0 - thisChangedYExtent)) / i_otherChangedVelocityInThis.getY()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInY; o_separationTime = tSeparationInY; o_collisionAxis = myEngine::typedefs::YAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInY; o_collisionAxis = myEngine::typedefs::YAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInY; } } } else return false; break; case false: if (abs(i_otherCenterPositionInThis.getY()) <= thisChangedYExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getY() != 0) { tCollisionInY = abs((i_otherCenterPositionInThis.getY() - (0 - thisChangedYExtent)) / i_otherChangedVelocityInThis.getY()); tSeparationInY = abs(((0 + thisChangedYExtent) - i_otherCenterPositionInThis.getY()) / i_otherChangedVelocityInThis.getY()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInY; o_separationTime = tSeparationInY; o_collisionAxis = myEngine::typedefs::YAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInY; o_collisionAxis = myEngine::typedefs::YAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInY; } } } else return false; break; } //Check in Z-axis in case X-Axis and Y-Axis collision is true switch (i_otherCenterPositionInThis.getZ() >= 0) { case true: if (i_otherCenterPositionInThis.getZ() <= thisChangedZExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getZ() != 0) { tCollisionInZ = abs(((0 + thisChangedZExtent) - i_otherCenterPositionInThis.getZ()) / i_otherChangedVelocityInThis.getZ()); tSeparationInZ = abs((i_otherCenterPositionInThis.getZ() - (0 - thisChangedZExtent)) / i_otherChangedVelocityInThis.getZ()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInZ; o_separationTime = tSeparationInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInZ; } } } else return false; break; case false: if (abs(i_otherCenterPositionInThis.getZ()) <= thisChangedZExtent) { //To-Do - time of collision - Done but need testing if (i_otherChangedVelocityInThis.getZ() != 0) { tCollisionInZ = abs((i_otherCenterPositionInThis.getZ() - (0 - thisChangedZExtent)) / i_otherChangedVelocityInThis.getZ()); tSeparationInZ = abs(((0 + thisChangedZExtent) - i_otherCenterPositionInThis.getZ()) / i_otherChangedVelocityInThis.getZ()); if (!finalCollisionTimeInitialized) { o_collisionTime = tCollisionInZ; o_separationTime = tSeparationInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } else { if (tCollisionInY < o_collisionTime) { o_collisionTime = tCollisionInZ; o_collisionAxis = myEngine::typedefs::ZAxis; } if (tSeparationInY < o_separationTime) o_separationTime = tSeparationInZ; } } } else return false; break; } //returning if all if's are false i.e. collsion occured in this coordinate system return true; }