dgInt32 dgCollisionChamferCylinder::CalculatePlaneIntersection (const dgVector& normal, const dgVector& origin, dgVector* const contactsOut) const
{
	dgInt32 count = 0;
	const dgFloat32 inclination = dgFloat32 (0.9999f);
	if (normal.m_x < -inclination) {
		dgMatrix matrix(normal);
		dgFloat32 x = dgSqrt (dgMax (m_height * m_height - origin.m_x * origin.m_x, dgFloat32 (0.0f)));
		matrix.m_posit.m_x = origin.m_x;
		dgVector scale(m_radius + x);
		const int n = sizeof (m_unitCircle) / sizeof (m_unitCircle[0]);
		for (dgInt32 i = 0; i < n; i++) {
			contactsOut[i] = matrix.TransformVector(m_unitCircle[i] * scale) & dgVector::m_triplexMask;
		}
		count = RectifyConvexSlice(n, normal, contactsOut);
	} else if (normal.m_x > inclination) {
		dgMatrix matrix(normal);
		dgFloat32 x = dgSqrt (dgMax (m_height * m_height - origin.m_x * origin.m_x, dgFloat32 (0.0f)));
		matrix.m_posit.m_x = origin.m_x;
		dgVector scale(m_radius + x);
		const int n = sizeof (m_unitCircle) / sizeof (m_unitCircle[0]);
		for (dgInt32 i = 0; i < n; i++) {
			contactsOut[i] = matrix.TransformVector(m_unitCircle[i] * scale) & dgVector::m_triplexMask;
		}
		count = RectifyConvexSlice(n, normal, contactsOut);
	} else {
		count = 1;
		contactsOut[0] = SupportVertex (normal, NULL);
	}
	return count;
}
dgInt32 dgCollisionChamferCylinder::CalculatePlaneIntersection (const dgVector& normal, const dgVector& origin, dgVector* const contactsOut, dgFloat32 normalSign) const
{
	dgInt32 count = 0;
	if (dgAbsf (normal.m_x) < dgFloat32 (0.999f)) { 
		count = 1;
		contactsOut[0] = SupportVertex (normal, NULL);
	} else {
		count = dgCollisionConvex::CalculatePlaneIntersection (normal, origin, contactsOut, normalSign);
	}
	return count;
}
dgVector dgCollisionTaperedCylinder::ConvexConicSupporVertex (const dgVector& point, const dgVector& dir) const
{
	dgVector p (SupportVertex(dir, NULL));
	if (dgAbsf(dir.m_x) > dgFloat32 (0.9997f)) {
		p.m_y = point.m_y;
		p.m_z = point.m_z;
	} else {
		dgVector n (dir.m_x, dgSqrt (dir.m_y * dir.m_y + dir.m_z * dir.m_z), dgFloat32 (0.0f), dgFloat32 (0.0f));
		dgFloat32 project = n % m_dirVector;
		if (project > dgFloat32 (0.9998f)) {
			p.m_x = point.m_x;	
		}
	}
	return p;

}
dgVector dgCollisionTaperedCapsule::ConvexConicSupporVertex (const dgVector& point, const dgVector& dir) const
{
	dgAssert (dgAbsf (dir % dir - dgFloat32 (1.0f)) < dgFloat32 (1.0e-3f));
	dgVector p (SupportVertex(dir, NULL));

	dgVector n (dir.m_x, dgSqrt (dir.m_y * dir.m_y + dir.m_z * dir.m_z), dgFloat32 (0.0), dgFloat32 (0.0f));
	dgAssert (dgAbsf (n % n - dgFloat32 (1.0f)) < dgFloat32 (1.0e-3f));
	
	dgFloat32 project = m_sideNormal % n;
	if (project > dgFloat32 (0.9998f)) {
		dgFloat32 t = dgFloat32 (0.5f) * (point.m_x + m_height) / m_height;
		dgFloat32 r = m_radio1 + (m_radio0 - m_radio1) * t;
		p = dir.Scale3 (r);
		p.m_x += point.m_x;
	}
	return p;
}
Пример #5
0
dgInt32 dgConvexHull4d::InitVertexArray(dgHullVector* const points, const dgBigVector* const vertexCloud, dgInt32 count, void* const memoryPool, dgInt32 maxMemSize)
{
	for (dgInt32 i = 0; i < count; i ++) {
		points[i] = vertexCloud[i];
		points[i].m_index = i;
		points[i].m_mark = 0;
	}

	dgSort(points, count, ConvexCompareVertex);
	dgInt32 indexCount = 0;
	for (int i = 1; i < count; i ++) {
		for (; i < count; i ++) {
			if (ConvexCompareVertex (&points[indexCount], &points[i], NULL)) {
				indexCount ++;
				points[indexCount] = points[i];
				break;
			}
		}
	}
	count = indexCount + 1;
	if (count < 4) {
		m_count = 0;
		return count;
	}

	dgAABBPointTree4d* tree = BuildTree (NULL, points, count, 0, (dgInt8**) &memoryPool, maxMemSize);

	dgBigVector boxSize (tree->m_box[1] - tree->m_box[0]);	
	boxSize.m_w = dgFloat64 (0.0f);
	m_diag = dgFloat32 (sqrt (boxSize.DotProduct4(boxSize).m_x));

	m_points[4].m_x = dgFloat64 (0.0f);
	dgHullVector* const convexPoints = &m_points[0]; 
	dgStack<dgBigVector> normalArrayPool (256);
	dgBigVector* const normalArray = &normalArrayPool[0];
	dgInt32 normalCount = BuildNormalList (&normalArray[0]);

	dgInt32 index = SupportVertex (&tree, points, normalArray[0]);
	convexPoints[0] = points[index];
	points[index].m_mark = 1;

	bool validTetrahedrum = false;
	dgBigVector e1 (dgFloat64 (0.0f), dgFloat64 (0.0f), dgFloat64 (0.0f), dgFloat64 (0.0f)) ;
	for (dgInt32 i = 1; i < normalCount; i ++) {
		dgInt32 index = SupportVertex (&tree, points, normalArray[i]);
		dgAssert (index >= 0);
		e1 = points[index] - convexPoints[0];
		e1.m_w = dgFloat64 (0.0f);
		dgFloat64 error2 = e1.DotProduct4(e1).m_x;
		if (error2 > (dgFloat32 (1.0e-4f) * m_diag * m_diag)) {
			convexPoints[1] = points[index];
			points[index].m_mark = 1;
			validTetrahedrum = true;
			break;
		}
	}
	if (!validTetrahedrum) {
		m_count = 0;
		return count;
	}


	dgInt32 bestIndex = -1;
	dgFloat64 bestValue = dgFloat64 (1.0f);
	validTetrahedrum = false;
	dgFloat64 lenght2 = e1.DotProduct4(e1).m_x;
	dgBigVector e2(dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));;
	for (dgInt32 i = 2; i < normalCount; i ++) {
		dgInt32 index = SupportVertex (&tree, points, normalArray[i]);
		dgAssert (index >= 0);
		dgAssert (index < count);
		e2 = points[index] - convexPoints[0];
		e2.m_w = dgFloat64 (0.0f);
		dgFloat64 den = e2.DotProduct4(e2).m_x;
		if (fabs (den) > (dgFloat64 (1.0e-6f) * m_diag)) {
			den = sqrt (lenght2 * den);
			dgFloat64 num = e2.DotProduct4(e1).m_x;
			dgFloat64 cosAngle = fabs (num / den);
			if (cosAngle < bestValue) {
				bestValue = cosAngle;
				bestIndex = index;
			}

			if (cosAngle < 0.9f) {
				break;
			}
		}
	}

	if (bestValue < dgFloat64 (0.999f)) {
		convexPoints[2] = points[bestIndex];
		points[bestIndex].m_mark = 1;
		validTetrahedrum = true;
	}

	if (!validTetrahedrum) {
		m_count = 0;
		return count;
	}

	validTetrahedrum = false;
	dgBigVector e3(dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));;
	for (dgInt32 i = 3; i < normalCount; i ++) {
		dgInt32 index = SupportVertex (&tree, points, normalArray[i]);
		dgAssert (index >= 0);
		dgAssert (index < count);

		e3 = points[index] - convexPoints[0];
		e3.m_w = dgFloat64 (0.0f);
		dgFloat64 volume = (e1 * e2) % e3;		
		if (fabs (volume) > (dgFloat64 (1.0e-4f) * m_diag * m_diag * m_diag)) {
			convexPoints[3] = points[index];
			points[index].m_mark = 1;
			validTetrahedrum = true;
			break;
		}
	}

	m_count = 4;
	if (!validTetrahedrum) {
		m_count = 0;
	}
	
	return count;
}
Пример #6
0
dgVector dgCollisionSphere::ConvexConicSupporVertex (const dgVector& point, const dgVector& dir) const
{
	return SupportVertex(dir, NULL);
}
Пример #7
0
dgVector dgCollisionBVH::SupportVertexSpecial(const dgVector& dir, dgInt32* const vertexIndex) const
{
	dgAssert(0);
	return SupportVertex(dir, vertexIndex);
}
Пример #8
0
dgCollisionConvexHull::dgCollisionConvexHull(dgMemoryAllocator* const allocator, dgUnsigned32 signature, dgInt32 count, dgInt32 strideInBytes, dgFloat32 tolerance, const dgFloat32* vertexArray, const dgMatrix& matrix)
	:dgCollisionConvex(allocator, signature, matrix, m_convexHullCollision)
{
	m_faceCount = 0;
	m_edgeCount = 0;
	m_vertexCount = 0;
	m_vertex = NULL;
	m_simplex = NULL;
	m_faceArray = NULL;
	m_boundPlanesCount = 0;

	m_rtti |= dgCollisionConvexHull_RTTI;


	Create (count, strideInBytes, vertexArray, tolerance);

	dgInt32 planeCount = 0;
	dgPlaneLocation planesArray[1024];
	const dgConvexSimplexEdge* const* faceArray = m_faceArray;
	for (dgInt32 i = 0; i < m_faceCount; i ++) {
		const dgConvexSimplexEdge* const face = faceArray[i];

		dgInt32 i0 = face->m_prev->m_vertex;
		dgInt32 i1 = face->m_vertex;
		dgInt32 i2 = face->m_next->m_vertex;
		const dgBigVector p0 (m_vertex[i0]);
		const dgBigVector p1 (m_vertex[i1]);
		const dgBigVector p2 (m_vertex[i2]);

		dgBigVector normal1 ((p1 - p0) * (p2 - p0));

		dgVector normal ((m_vertex[i1] - m_vertex[i0]) * (m_vertex[i2] - m_vertex[i0]));
		normal = normal.Scale (dgFloat32 (1.0f) / dgSqrt (normal % normal));
		dgInt32 add = 1;
		for (dgInt32 j = 0; j < 3; j ++) {
			if (dgAbsf (normal[j]) > dgFloat32 (0.98f)) {
				add = 0;
			}
		}

		if (add) {
			for (dgInt32 j = 0; j < planeCount; j ++) {
				dgFloat32 coplanar;
				coplanar = normal % planesArray[j];
				if (coplanar > 0.98f) {
					add = 0;
					break;
				}
			}

			if (add) {
				dgPlane plane (normal, dgFloat32 (0.0f));
				dgVector planeSupport (SupportVertex (plane));
				plane.m_w = - (plane % planeSupport);
//				_ASSERTE (plane.Evalue(m_boxOrigin) < 0.0f);
				dgPlane& tmpPlane = planesArray[planeCount];
				tmpPlane = plane;
				planesArray[planeCount].m_index = i;
				planesArray[planeCount].m_face = face;
				planeCount ++;
				_ASSERTE (planeCount < (sizeof (planesArray) / sizeof (planesArray[0])));
			}
		}
	}

	m_boundPlanesCount = 0;
	for (dgInt32 i = 0; i < planeCount; i ++) {
		dgPlaneLocation& plane = planesArray[i];
		if (plane.m_face == m_faceArray[plane.m_index]) {
			Swap (m_faceArray[plane.m_index], m_faceArray[m_boundPlanesCount]);
		} else {
			dgInt32 j;
			for (j = m_boundPlanesCount; j < m_faceCount; j ++) {
				if (plane.m_face == m_faceArray[j]) {
					Swap (m_faceArray[j], m_faceArray[m_boundPlanesCount]);
					break;
				}
			}
			_ASSERTE (j < m_faceCount);
		}
		m_boundPlanesCount ++;
	}

	m_destructionImpulse = dgFloat32 (1.0e20f);
}
dgVector dgCollisionCone::SupportVertexSimd (const dgVector& dir) const
{
	return SupportVertex (dir);
}
dgVector dgCollisionChamferCylinder::SupportVertexSimd (const dgVector& dir) const
{
	return SupportVertex (dir);
}
Пример #11
0
dgInt32 dgCollisionBox::CalculatePlaneIntersection (const dgVector& normal, const dgVector& point, dgVector* const contactsOut) const
{
	dgVector support[4];
	dgInt32 featureCount = 3;
	
	const dgConvexSimplexEdge** const vertToEdgeMapping = GetVertexToEdgeMapping();
	if (vertToEdgeMapping) {
		dgInt32 edgeIndex;
		//support[0] = SupportVertex (normal.Scale4(normalSign), &edgeIndex);
		support[0] = SupportVertex (normal, &edgeIndex);

		dgFloat32 dist = normal.DotProduct4(support[0] - point).GetScalar();
		if (dist <= DG_IMPULSIVE_CONTACT_PENETRATION) {
			dgVector normalAlgin (normal.Abs());
			if (!((normalAlgin.m_x > dgFloat32 (0.9999f)) || (normalAlgin.m_y > dgFloat32 (0.9999f)) || (normalAlgin.m_z > dgFloat32 (0.9999f)))) {
				// 0.25 degrees
				const dgFloat32 tiltAngle = dgFloat32 (0.005f);
				const dgFloat32 tiltAngle2 = tiltAngle * tiltAngle ;
				dgPlane testPlane (normal, - (normal.DotProduct4(support[0]).GetScalar()));

				featureCount = 1;
				const dgConvexSimplexEdge* const edge = vertToEdgeMapping[edgeIndex];
				const dgConvexSimplexEdge* ptr = edge;
				do {
					const dgVector& p = m_vertex[ptr->m_twin->m_vertex];
					dgFloat32 test1 = testPlane.Evalue(p);
					dgVector dist (p - support[0]);
					dgFloat32 angle2 = test1 * test1 / (dist.DotProduct4(dist).GetScalar());
					if (angle2 < tiltAngle2) {
						support[featureCount] = p;
						featureCount ++;
					}
					ptr = ptr->m_twin->m_next;
				} while ((ptr != edge) && (featureCount < 3));
			}
		}
	}

	dgInt32 count = 0;
	switch (featureCount)
	{
		case 1:
		{
			contactsOut[0] = support[0] - normal.CompProduct4(normal.DotProduct4(support[0] - point));
			count = 1;
			break;
		}

		case 2:
		{
			contactsOut[0] = support[0] - normal.CompProduct4(normal.DotProduct4(support[0] - point));
			contactsOut[1] = support[1] - normal.CompProduct4(normal.DotProduct4(support[1] - point));
			count = 2;
			break;
		}

		default:
		{
			dgFloat32 test[8];
			dgAssert(normal.m_w == dgFloat32(0.0f));
			dgPlane plane(normal, -(normal.DotProduct4(point).GetScalar()));
			for (dgInt32 i = 0; i < 8; i++) {
				dgAssert(m_vertex[i].m_w == dgFloat32(0.0f));
				test[i] = plane.DotProduct4(m_vertex[i] | dgVector::m_wOne).m_x;
			}

			dgConvexSimplexEdge* edge = NULL;
			for (dgInt32 i = 0; i < dgInt32 (sizeof (m_edgeEdgeMap) / sizeof (m_edgeEdgeMap[0])); i ++) {
				dgConvexSimplexEdge* const ptr = m_edgeEdgeMap[i];
				dgFloat32 side0 = test[ptr->m_vertex];
				dgFloat32 side1 = test[ptr->m_twin->m_vertex];
				if ((side0 * side1) < dgFloat32 (0.0f)) {
					edge = ptr;
					break;
				}
			}

			if (edge) {
				if (test[edge->m_vertex] < dgFloat32 (0.0f)) {
					edge = edge->m_twin;
				}
				dgAssert (test[edge->m_vertex] > dgFloat32 (0.0f));

				dgConvexSimplexEdge* ptr = edge;
				dgConvexSimplexEdge* firstEdge = NULL;
				dgFloat32 side0 = test[edge->m_vertex];
				do {
					dgAssert (m_vertex[ptr->m_twin->m_vertex].m_w == dgFloat32 (0.0f));
					dgFloat32 side1 = test[ptr->m_twin->m_vertex];
					if (side1 < side0) {
						if (side1 < dgFloat32 (0.0f)) {
							firstEdge = ptr;
							break;
						}

						side0 = side1;
						edge = ptr->m_twin;
						ptr = edge;
					}
					ptr = ptr->m_twin->m_next;
				} while (ptr != edge);

				if (firstEdge) {
					edge = firstEdge;
					ptr = edge;
					do {
						dgVector dp (m_vertex[ptr->m_twin->m_vertex] - m_vertex[ptr->m_vertex]);
						dgFloat32 t = plane.DotProduct4(dp).m_x;
						if (t >= dgFloat32 (-1.e-24f)) {
							t = dgFloat32 (0.0f);
						} else {
							t = test[ptr->m_vertex] / t;
							if (t > dgFloat32 (0.0f)) {
								t = dgFloat32 (0.0f);
							}
							if (t < dgFloat32 (-1.0f)) {
								t = dgFloat32 (-1.0f);
							}
						}

						dgAssert (t <= dgFloat32 (0.01f));
						dgAssert (t >= dgFloat32 (-1.05f));
						contactsOut[count] = m_vertex[ptr->m_vertex] - dp.Scale4 (t);
						count ++;

						dgConvexSimplexEdge* ptr1 = ptr->m_next;
						for (; ptr1 != ptr; ptr1 = ptr1->m_next) {
							dgInt32 index0 = ptr1->m_twin->m_vertex;
							if (test[index0] >= dgFloat32 (0.0f)) {
								dgAssert (test[ptr1->m_vertex] <= dgFloat32 (0.0f));
								break;
							}
						}
						dgAssert (ptr != ptr1);
						ptr = ptr1->m_twin;

					} while ((ptr != edge) && (count < 8));
				}
			}
		}
	}

	if (count > 2) {
		count = RectifyConvexSlice (count, normal, contactsOut);
	}
	return count;
}