Beispiel #1
0
NEINLINE neBool SameSide(const neV3 & p1, const neV3 & p2, const neV3 & a, const neV3 & edge)
{
	neV3 cp1 = edge.Cross(p1 - a);
	
	neV3 cp2 = edge.Cross(p2 - a);

	f32 dot = cp1.Dot(cp2);

	return (dot >= 0.0f);
}
Beispiel #2
0
NEINLINE void ApplyCollisionImpulseFast(neRigidBody_ * rb, const neV3 & impulse, const neV3 & contactPoint, s32 currentRecord, neBool immediate = true)
{
	neV3 dv, da;

	dv = impulse * rb->oneOnMass;

	da = contactPoint.Cross(impulse);

//	if (immediate)
		rb->Derive().linearVel += dv;
//	else
//	{
//		rb->totalDV += dv;
//		rb->impulseCount++;
//	}

//	rb->dvRecord[currentRecord] += dv;

//	neV3 dav = rb->Derive().Iinv * da;

//	rb->davRecord[currentRecord] += dav;

//	if (immediate)
	{
		rb->State().angularMom += da;

		rb->Derive().angularVel = rb->Derive().Iinv * rb->State().angularMom;
	}
//	else
//	{
//		rb->totalDA += da;
//		
//		rb->twistCount++;
//	}
}
Beispiel #3
0
void FindMinMaxBound(neTriangleTree * tree, neSimpleArray<s32>& triIndex, neV3 & minBound, neV3 & maxBound)
{
	s32 i;
	
	minBound.Set(1.0e6f, 1.0e6f, 1.0e6f);

	maxBound.Set(-1.0e6f, -1.0e6f, -1.0e6f);

	for(i = 0; i < triIndex.GetUsedCount(); i++)
	{
		neTriangle_ & t = tree->triangles[triIndex[i]];

		for (s32 j = 0; j < 3; j++)
		{
			minBound.SetMin(minBound, tree->vertices[t.indices[j]]);

			maxBound.SetMax(maxBound, tree->vertices[t.indices[j]]);
		}
	}
}
Beispiel #4
0
void ChooseAxis(neV3 & x, neV3 & y, const neV3 & normal)
{
	neV3 mag;

	mag[0] = neAbs(normal[0]);
	mag[1] = neAbs(normal[1]);
	mag[2] = neAbs(normal[2]);

	if (mag[0] > mag[1])
	{
		if (mag[0] > mag[2])
		{
			x[0] = (normal[1] + normal[2]) / normal[0] * -1.0f;
			x[1] = 1.0f;
			x[2] = 1.0f;
		}
		else
		{
			x[2] = (normal[0] + normal[1]) / normal[2] * -1.0f;
			x[0] = 1.0f;
			x[1] = 1.0f;
		}
	}
	else if (mag[1] > mag[2])
	{
		x[1] = (normal[0] + normal[2]) / normal[1] * -1.0f;
		x[0] = 1.0f;
		x[2] = 1.0f;
	}
	else
	{
		x[2] = (normal[0] + normal[1]) / normal[2] * -1.0f;
		x[0] = 1.0f;
		x[1] = 1.0f;
	}
	x.Normalize();
	y = normal.Cross(x);
}
NEINLINE bool BoxTestParam::MeasurePlanePenetration(ConvexTestResult & result, const neV3 & normal, f32 d)
{
    f32 dot = normal.Dot(trans->pos);

    f32 penetrated = dot - d;

    neV3 contactPoint = trans->pos;

    neV3 contactNormal;

    if (penetrated < 0.0f)
    {
        contactNormal = normal * -1.0f;
    }
    else
    {
        contactNormal = normal;
        penetrated *= -1.0f;
    }
    neV3 progression = contactNormal * radii;

    neV3 sign;

    sign[0] = progression[0] > 0.0f ? 1.0f: -1.0f;
    sign[1] = progression[1] > 0.0f ? 1.0f: -1.0f;
    sign[2] = progression[2] > 0.0f ? 1.0f: -1.0f;

    penetrated += (progression[0] * sign[0]);
    penetrated += (progression[1] * sign[1]);
    penetrated += (progression[2] * sign[2]);

    contactPoint -= (radii[0] * sign[0]);
    contactPoint -= (radii[1] * sign[1]);
    contactPoint -= (radii[2] * sign[2]);

    if (penetrated < 0.0f)
        return false;

    if (penetrated < result.depth)
    {
        result.depth = penetrated;
        result.contactA = contactPoint;
        result.contactB = contactPoint + contactNormal * penetrated;//need to project point onto triangle face
        result.valid = true;
        result.contactNormal = contactNormal;
        //ChooseAxis(result.contactX, result.contactY, result.contactNormal);
    }
    return true;
}
Beispiel #6
0
void neTreeNode::SelectBound(const neV3 & com, neV3 & minBound, neV3 & maxBound, s32 sector)
{
	switch (sector)
	{
	case 0:
		minBound.Set(bounds[0][0], bounds[1][0], bounds[2][0]);
		maxBound.Set(com[0], bounds[1][1], com[2]);
		break;
	case 1:
		minBound.Set(com[0], bounds[1][0], bounds[2][0]);
		maxBound.Set(bounds[0][1], bounds[1][1], com[2]);
		break;
	case 2:
		minBound.Set(com[0], bounds[1][0], com[2]);
		maxBound.Set(bounds[0][1], bounds[1][1], bounds[2][1]);
		break;
	case 3:
		minBound.Set(bounds[0][0], bounds[1][0], com[2]);
		maxBound.Set(com[0], bounds[1][1], bounds[2][1]);
		break;
	}
}
Beispiel #7
0
bool TestDCDTri(ConvexTestResult & res, TConvex & convexA, neT3 & transA, const neV3 & insidePoint)
{
	res.valid = false;

	neV3 aPoint = transA.pos;

	neV3 av; av.Set(0.1f);

	aPoint += av;

	neV3 bPoint =  insidePoint;

	BigC = aPoint - bPoint;

	BigCLength = BigC.Length();

	neV3 * aVertArray = NULL, * bVertArray = NULL;

	TConvex dummyB; dummyB.type = TConvex::TRIANGLE;

	if (convexA.type == TConvex::BOX)
	{
		for (s32 i = 0; i < BOX_NUM_VERTS; i++)
		{
			_boxVertexPosP[i] = _boxVertexPos0[i] * convexA.as.box.boxSize;
		}
		aVertArray = _boxVertexPosP;
	}
	neT3 transB; transB.SetIdentity();

	SearchResult srBoxFaceTriVert(convexA, &transA, dummyB, &transB, aVertArray, bVertArray);

	neBool assigned;

	neBool r = srBoxFaceTriVert.SearchFV(0, assigned);

	if (!r)
		{return false;}

/*	bPoint = insidePoint;// + _triNormals[1];
	BigC = bPoint - aPoint;
	BigCLength = BigC.Length();
*/
	BigC *= -1.0f;

	SearchResult srBoxVertTriFace(dummyB, &transB, convexA, &transA, bVertArray, aVertArray);

	if (!(r = srBoxVertTriFace.TestFace(0, assigned)))
		return false;

	//BigC *= -1.0f;
/*
	bPoint = insidePoint + _triNormals[0];
	BigC = bPoint - aPoint;
	BigCLength = BigC.Length();
*/
	neBool assigned2;

	if (!(r = srBoxVertTriFace.TestFace(1, assigned2)))
		return false;

	assigned |= assigned2;

	BigC *= -1.0f;
/*
	bPoint = insidePoint;
	BigC = aPoint - bPoint;
	BigCLength = BigC.Length();
*/

	neBool need2Swap = false;

	SearchResult srBoxTriEE(convexA, &transA, dummyB, &transB, aVertArray, bVertArray);

	s32 eeflag = 0;

	s32 pindex, qindex;

	if (srBoxVertTriFace.dMax > srBoxFaceTriVert.dMax)
	{
		need2Swap = true;

		srBoxTriEE.dMax = srBoxVertTriFace.dMax;

		eeflag = 1;

		pindex = srBoxVertTriFace.indexB; // vertex of Convex

		qindex = srBoxVertTriFace.indexA; // face of Triangle
	}
	else
	{
		srBoxTriEE.dMax = srBoxFaceTriVert.dMax;

		pindex = srBoxFaceTriVert.indexA; // face of Convex

		qindex = srBoxFaceTriVert.indexB; // vertex of Triangle
	}
	//BigC *= -1.0f;

	if (!srBoxTriEE.SearchEETri(eeflag, pindex, qindex, assigned))
	{
		return false;
	}
	if (!assigned)
	{
FV_Backup:
		if (!need2Swap)
		{
			ASSERT(srBoxFaceTriVert.typeA == SearchResult::FACE && srBoxFaceTriVert.typeB == SearchResult::VERTEX);

			res.valid = true;

			res.contactNormal = srBoxFaceTriVert.face.normal * -1.0f;

			res.depth = srBoxFaceTriVert.face.k;

			res.contactB = srBoxFaceTriVert.objB.GetVertWorld(srBoxFaceTriVert.indexB);

			res.contactA = res.contactB + srBoxFaceTriVert.face.normal * srBoxFaceTriVert.face.k;
		}
		else
		{
			ASSERT(srBoxVertTriFace.typeA == SearchResult::FACE && srBoxVertTriFace.typeB == SearchResult::VERTEX);

			res.valid = true;

			res.contactNormal = srBoxVertTriFace.face.normal;

			res.depth = srBoxVertTriFace.face.k;

			res.contactA = srBoxVertTriFace.objB.GetVertWorld(srBoxVertTriFace.indexB);

			res.contactB = res.contactA + srBoxVertTriFace.face.normal * srBoxVertTriFace.face.k;
		}
	}
	else
	{
		ASSERT(srBoxTriEE.typeA == SearchResult::EDGE &&
				srBoxTriEE.typeB == SearchResult::EDGE);

		neV3 edgeA[2];
		neV3 edgeB[2];

		srBoxTriEE.objA.GetWorldEdgeVerts(srBoxTriEE.indexA, edgeA[0], edgeA[1]);

		srBoxTriEE.objB.GetWorldEdgeVerts(srBoxTriEE.indexB, edgeB[0], edgeB[1]);

		bool r = CalcContactEE(edgeA[0], edgeA[1], edgeB[0], edgeB[1], res.contactA, res.contactB);

		if (r)
		{
			if (srBoxTriEE.face.k > 0.0f)
			{
				res.contactNormal = srBoxTriEE.face.normal * -1.0f;

				res.depth = srBoxTriEE.face.k;
			}
			else
			{
				res.contactNormal = srBoxTriEE.face.normal;

				res.depth = srBoxTriEE.face.k * -1.0f;
			}

			res.valid = true;
		}
		else
		{
			//return false;
			goto FV_Backup;
		}
	}
	return true;
}
Beispiel #8
0
bool TestDCD(neCollisionResult & result, TConvex & convexA, neT3 & transA, TConvex & convexB, neT3 & transB, const neV3 & backupVector)
{
	_num_edge_test = 0;

	_num_face_test = 0;

	result.penetrate = false;
	
	neV3 aPoint = transA.pos;

	neV3 av; av.Set(0.1f);

	aPoint += av;

	neV3 bPoint = transB.pos;

	av.Set(0.2f);

	bPoint += av;

	BigC = aPoint - bPoint;

	BigCLength = BigC.Length();

	neV3 * aVertArray = NULL, * bVertArray = NULL;

	if (convexA.type == TConvex::BOX)
	{
		for (s32 i = 0; i < BOX_NUM_VERTS; i++)
		{
			_boxVertexPosP[i] = _boxVertexPos0[i] * convexA.as.box.boxSize;
		}
		aVertArray = _boxVertexPosP;
	}
	if (convexB.type == TConvex::BOX)
	{
		for (s32 i = 0; i < BOX_NUM_VERTS; i++)
		{
			_boxVertexPosQ[i] = _boxVertexPos0[i] * convexB.as.box.boxSize;
		}
		bVertArray = _boxVertexPosQ;
	}

	SearchResult srFV(convexA, &transA, convexB, &transB, aVertArray, bVertArray);

	neBool showDebug = 0;
	
	neBool showDebug2  = (srFV.objA.mesh.numVerts > 8 && srFV.objB.mesh.numVerts > 8);
	
	neBool assigned;

	neBool res = srFV.SearchFV(0, assigned);

	if (!res)
	{
		if (showDebug)
		{TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);}

		return false;
	}
	SearchResult srVF(convexB, &transB, convexA, &transA, bVertArray, aVertArray);

	srVF.dMax = srFV.dMax;

	BigC *= -1.0f;

	s32 whichF = srFV.objB.mesh.edges[srFV.objB.mesh.verts[srFV.indexB].neighbourEdges[0]].f1;

	res = srVF.SearchFV(whichF, assigned);
	
	if (!res)
	{
		if (showDebug)
			{TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);}

		return false;
	}

	bool need2Swap = false;

	SearchResult srEE(convexA, &transA, convexB, &transB, aVertArray, bVertArray);

	s32 eeflag = 0;
	
	s32 pindex, qindex;

	if (srVF.dMax > srFV.dMax)
	{
		need2Swap = true;

		srEE.dMax = srVF.dMax;

		eeflag = 1;

		pindex = srVF.indexB;

		qindex = srVF.indexA;
	}
	else
	{
		srEE.dMax = srFV.dMax;

		pindex = srFV.indexA;

		qindex = srFV.indexB;
	}
	BigC *= -1.0f;

	if (!srEE.SearchEE(eeflag, pindex, qindex, assigned))
	{
		if (showDebug)
			{TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);}

		return false;
	}
	if (showDebug2)
	{
		TOKAMAK_OUTPUT_2("%d, %d \n", _num_face_test, _num_edge_test);
	}
	if (!assigned)
	{
		if (!need2Swap)
		{
			ASSERT(srFV.typeA == SearchResult::FACE && srFV.typeB == SearchResult::VERTEX);

			result.penetrate = true;

			result.collisionFrame[2] = srFV.face.normal * -1.0f;

			result.depth = srFV.face.k;

			result.contactB = srFV.objB.GetVertWorld(srFV.indexB);

			result.contactA = result.contactB + srFV.face.normal * srFV.face.k;
		}
		else
		{
			ASSERT(srVF.typeA == SearchResult::FACE && srVF.typeB == SearchResult::VERTEX);

			result.penetrate = true;

			result.collisionFrame[2] = srVF.face.normal;

			result.depth = srVF.face.k;

			result.contactA = srVF.objB.GetVertWorld(srVF.indexB);

			result.contactB = result.contactA + srVF.face.normal * srVF.face.k;
		}
	}
	else
	{
		ASSERT(srEE.typeA == SearchResult::EDGE &&
				srEE.typeB == SearchResult::EDGE);

		neV3 edgeA[2];
		neV3 edgeB[2];

		srEE.objA.GetWorldEdgeVerts(srEE.indexA, edgeA[0], edgeA[1]);

		srEE.objB.GetWorldEdgeVerts(srEE.indexB, edgeB[0], edgeB[1]);

		bool r = CalcContactEE(edgeA[0], edgeA[1], edgeB[0], edgeB[1], result.contactA, result.contactB);

		if (r)
		{
			if (srEE.face.k > 0.0f)
			{
				result.collisionFrame[2] = srEE.face.normal * -1.0f;

				result.depth = srEE.face.k;
			}
			else
			{
				result.collisionFrame[2] = srEE.face.normal;

				result.depth = srEE.face.k * -1.0f;
			}

			result.penetrate = true;
		}
		else
		{
			return false;
		}
	}

	return true;
}