Ejemplo n.º 1
0
bool MFCollision_RaySphereTest(const MFVector& rayPos, const MFVector& rayDir, const MFVector& spherePos, float radius, MFRayIntersectionResult *pResult)
{
	MFVector diff = rayPos - spherePos;

	// calcuate the coefficients
	float a = rayDir.MagSquared3();
	float b = (2.0f*rayDir).Dot3(diff);
	float c = diff.MagSquared3() - radius*radius;

	// calculate the stuff under the root sign, if it's negative no (real) solutions exist
	float d = b*b - 4.0f*a*c;
	if(d < 0.0f) // this means ray misses cylinder
		return false;

	float root = MFSqrt(d);
	float rcp2a = MFRcp(2.0f*a);
	float t1 = (-b - root)*rcp2a;
	float t2 = (-b + root)*rcp2a;

	if(t2 < 0.0f || t1 > 1.0f)
		return false;

	if(pResult)
	{
		pResult->time = MFMax(t1, 0.0f);
		pResult->surfaceNormal.Mad3(rayDir, pResult->time, diff);
		pResult->surfaceNormal.Normalise3();
	}

	return true;
}
Ejemplo n.º 2
0
MFQuaternion MFMatrix::GetRotationQ() const
{
	MFQuaternion q;
	float trace = m[0] + m[5] + m[10] + 1.0f;

	if(trace > 0.0f)
	{
		float s = MFRSqrt(trace) * 0.5f;
		q.w = 0.25f / s;
		q.x = (m[9] - m[6]) * s;
		q.y = (m[2] - m[8]) * s;
		q.z = (m[4] - m[1]) * s;
	}
	else
	{
		if(m[0] > m[5] && m[0] > m[10])
		{
			float s = 2.0f * MFSqrt(1.0f + m[0] - m[5] - m[10]);
			float invS = 1.0f / s;
			q.x = 0.25f * s;
			q.y = (m[1] + m[4]) * invS;
			q.z = (m[2] + m[8]) * invS;
			q.w = (m[6] - m[9]) * invS;
		}
		else if(m[5] > m[10])
		{
			float s = 2.0f * MFSqrt(1.0f + m[5] - m[0] - m[10]);
			float invS = 1.0f / s;
			q.x = (m[1] + m[4]) * invS;
			q.y = 0.25f * s;
			q.z = (m[6] + m[9]) * invS;
			q.w = (m[2] - m[8]) * invS;
		}
		else
		{
			float s = 2.0f * MFSqrt(1.0f + m[10] - m[0] - m[5]);
			float invS = 1.0f / s;
			q.x = (m[2] + m[8] ) * invS;
			q.y = (m[6] + m[9] ) * invS;
			q.z = 0.25f * s;
			q.w = (m[1] - m[4] ) * invS;
		}
	}

	return q;
}
Ejemplo n.º 3
0
void MFParticleSystem_DrawRotating(MFParticleSystem *pParticleSystem, const MFMatrix &ltv)
{
	int numParticles = pParticleSystem->particles.GetLength();
	if(!numParticles)
		return;

	float fadeStart = pParticleSystem->params.life - pParticleSystem->params.fadeDelay;

	MFMaterial_SetMaterial(pParticleSystem->pMaterial);

	MFPrimitive(PT_TriList, 0);
	MFBegin(numParticles * 6);

	MFParticle **ppI = pParticleSystem->particles.Begin();

	while(*ppI)
	{
		MFParticle *pParticle = *ppI;

		float dt = MFSystem_TimeDelta();

		pParticle->rot += pParticleSystem->params.rotationRate * dt;
		pParticle->size += pParticleSystem->params.scaleRate * dt;
		pParticle->velocity += pParticleSystem->params.force * dt;
		pParticle->pos += pParticle->velocity * dt;

		float t = pParticle->size * 0.5f;
		float rad = MFSqrt(t*t*2);
		float xoff = MFCos(-pParticle->rot + 0.7853981f)*rad;
		float yoff = MFSin(-pParticle->rot + 0.7853981f)*rad;
		float alpha = MFMin(pParticle->life / fadeStart, 1.0f);

		MFVector pos = ApplyMatrixH(pParticle->pos, ltv);

		MFSetColourV(MakeVector(pParticle->colour, pParticle->colour.w * alpha));
		MFSetTexCoord1(1, 0);
		MFSetPosition(pos.x + xoff, pos.y + yoff, pos.z);
		MFSetTexCoord1(0, 1);
		MFSetPosition(pos.x - xoff, pos.y - yoff, pos.z);
		MFSetTexCoord1(0, 0);
		MFSetPosition(pos.x - yoff, pos.y + xoff, pos.z);
		MFSetTexCoord1(1, 0);
		MFSetPosition(pos.x + xoff, pos.y + yoff, pos.z);
		MFSetTexCoord1(1, 1);
		MFSetPosition(pos.x + yoff, pos.y - xoff, pos.z);
		MFSetTexCoord1(0, 1);
		MFSetPosition(pos.x - xoff, pos.y - yoff, pos.z);

		pParticle->life -= dt;
		if(pParticle->life < 0.0f)
			pParticleSystem->particles.Destroy(ppI);

		ppI++;
	}

	MFEnd();
}
Ejemplo n.º 4
0
void MFInputInternal_ApplySphericalDeadZone(float *pX, float *pY)
{
	float length = *pX**pX + *pY**pY;

	if(length)
	{
		length = MFSqrt(length);

		float scale = 1.0f / length * MFClamp(0.0f, (length - gGamepadDeadZone) / (1.0f - gGamepadDeadZone), 1.0f);

		*pX *= scale;
		*pY *= scale;
	}
}
Ejemplo n.º 5
0
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");
	}
}
Ejemplo n.º 6
0
bool MFCollision_RayCylinderTest(const MFVector& rayPos, const MFVector& rayDir, const MFVector& cylinderPos, const MFVector& cylinderDir, float cylinderRadius, bool capped, MFRayIntersectionResult *pResult, float *pCylinderTime)
{
	MFVector local = rayPos - cylinderPos;

	float rayD = rayDir.Dot3(cylinderDir);
	float T0 = local.Dot3(cylinderDir);

	// bring T0 into 0.0-1.0 range
	float invMagSq = MFRcp(cylinderDir.MagSquared3());
	rayD *= invMagSq;
	T0 *= invMagSq;

	// calculate some intermediate vectors
	MFVector v1 = rayDir - rayD*cylinderDir;
	MFVector v2 = local - T0*cylinderDir;

	// calculate coeff in quadratic formula
	float a = v1.MagSquared3();
	float b = (2.0f*v1).Dot3(v2);
	float c = v2.MagSquared3() - cylinderRadius*cylinderRadius;

	// calculate the stuff under the root sign, if it's negative no (real) solutions exist
	float d = b*b - 4.0f*a*c;
	if(d < 0.0f) // this means ray misses cylinder
		return false;

	float root = MFSqrt(d);
	float rcp2a = MFRcp(2.0f*a);
	float t1 = (-b - root)*rcp2a;
	float t2 = (-b + root)*rcp2a;

	if(t1 > 1.0f || t2 < 0.0f)
		return false; // the cylinder is beyond the ray..

	if(capped || pCylinderTime || pResult)
	{
		float t = MFMax(t1, 0.0f);

		// get the t for the cylinders ray
		MFVector intersectedRay;
		intersectedRay.Mad3(rayDir, t, local);

		float ct = intersectedRay.Dot3(cylinderDir) * invMagSq;

		if(capped && (ct < 0.0f || ct > 1.0f))
		{
			// we need to test the caps

			// TODO: this is REALLY slow!! can be majorly improved!!

			// generate a plane for the cap
			MFVector point, plane;

			if(rayD > 0.0f)
			{
				// the near one
				point = cylinderPos;
				plane = MFCollision_MakePlaneFromPointAndNormal(point, -cylinderDir);
			}
			else
			{
				// the far one
				point = cylinderPos + cylinderDir;
				plane = MFCollision_MakePlaneFromPointAndNormal(point, cylinderDir);
			}

			// test the ray against the plane
			bool collide = MFCollision_RayPlaneTest(rayPos, rayDir, plane, pResult);

			if(collide)
			{
				// calculate the intersection point
				intersectedRay.Mad3(rayDir, pResult->time, rayPos);
				intersectedRay.Sub3(intersectedRay, point);

				// and see if its within the cylinders radius
				if(intersectedRay.MagSquared3() <= cylinderRadius * cylinderRadius)
				{
					return true;
				}
			}

			return false;
		}

		if(pResult)
		{
			pResult->time = t;
			pResult->surfaceNormal.Mad3(cylinderDir, -ct, intersectedRay);
			pResult->surfaceNormal.Normalise3();
		}

		if(pCylinderTime)
		{
			*pCylinderTime = ct;
		}
	}

	return true;
}