bool MFCollision_SphereSphereTest(const MFVector &pos1, float radius1, const MFVector &pos2, float radius2, MFCollisionResult *pResult) { MFVector diff = pos2 - pos1; if(!pResult) { return diff.MagSquared3() < radius1*radius1 + radius2*radius2; } else { float length = diff.Magnitude3(); float totalRadius = radius1 + radius2; pResult->bCollide = length < totalRadius; if(pResult->bCollide) { pResult->depth = totalRadius - length; pResult->normal = -diff.Normalise3(); pResult->intersectionPoint = diff * ((length / totalRadius) * (radius1 / radius2)); } return pResult->bCollide; } }
void MFCollision_CalculateDynamicBoundingVolume(MFCollisionItem *pItem) { switch(pItem->pTemplate->type) { case MFCT_Mesh: { MFCollisionMesh *pMesh = (MFCollisionMesh*)pItem->pTemplate->pCollisionTemplateData; MFBoundingVolume &vol = pItem->pTemplate->boundingVolume; vol.min = vol.max = vol.boundingSphere = MakeVector(pMesh->pTriangles[0].verts[0], 0.0f); for(int a=0; a<pMesh->numTris; a++) { MFCollisionTriangle &tri = pMesh->pTriangles[a]; for(int b=0; b<3; b++) { vol.min = MFMin(vol.min, tri.verts[b]); vol.max = MFMin(vol.max, tri.verts[b]); vol.min.w = vol.max.w = 0.0f; // if point is outside bounding sphere MFVector diff = tri.verts[b] - vol.boundingSphere; float mag = diff.MagSquared3(); if(mag > vol.boundingSphere.w*vol.boundingSphere.w) { // fit sphere to include point mag = MFSqrt(mag) - vol.boundingSphere.w; mag *= 0.5f; diff.Normalise3(); vol.boundingSphere.Mad3(diff, mag, vol.boundingSphere); vol.boundingSphere.w += mag; } } } break; } default: MFDebug_Assert(false, "Invalid item type"); } }
MF_API void MFParticleSystem_AddParticle(MFParticleEmitter *pEmitter) { MFParticleEmitterParameters *pE = &pEmitter->params; MFParticleSystem *pParticleSystem = pE->pParticleSystem; MFParticle *pNew = NULL; if(pParticleSystem->particles.GetLength() < pParticleSystem->params.maxActiveParticles) pNew = pParticleSystem->particles.Create(); if(pNew) { MFParticleParameters *pP = &pParticleSystem->params; pNew->colour = pP->colour; pNew->life = pP->life; pNew->rot = 0.0f; pNew->size = pP->size; switch(pE->type) { case MFET_Point: pNew->pos = pE->position.GetTrans(); break; case MFET_Sphere: case MFET_Disc: { MFVector offset; do { offset = MakeVector(MFRand_Range(-pE->radius, pE->radius), MFRand_Range(-pE->radius, pE->radius), MFRand_Range(-pE->radius, pE->radius)); } while(offset.MagSquared3() > pE->radius*pE->radius); if(pE->type == MFET_Disc) { // flatten it on to the disc float dist = offset.Dot3(pE->position.GetYAxis()); offset -= pE->position.GetYAxis()*dist; } pNew->pos = pE->position.GetTrans() + offset; break; } } switch(pE->behaviour) { case MFEB_Direction: pNew->velocity.Normalise3(pE->startVector); break; case MFEB_TargetAttract: pNew->velocity.Normalise3(pE->startVector - pE->position.GetTrans()); break; case MFEB_TargetRepel: pNew->velocity.Normalise3(pE->position.GetTrans() - pE->startVector); break; } pNew->velocity *= pE->velocity + MFRand_Range(-pE->velocityScatter, pE->velocityScatter); if(pE->directionScatter) { MFVector scatter; do { scatter = MakeVector(MFRand_Range(-1, 1), MFRand_Range(-1, 1), MFRand_Range(-1, 1)); float dist = scatter.Dot3(pE->position.GetYAxis()); scatter -= pE->position.GetYAxis()*dist; } while(scatter.MagSquared3() < 0.000001f); scatter.Normalise3(); MFMatrix scatterMat; scatterMat.SetRotation(scatter, MFRand_Unit()*pE->directionScatter); pNew->velocity = ApplyMatrixH(pNew->velocity, scatterMat); } } }