コード例 #1
0
ファイル: dgGoogol.cpp プロジェクト: ColinGilbert/noobEngine
	dgGoogol dgGoogol::operator+ (const dgGoogol &A) const
	{
		dgGoogol tmp;
		dgAssert (dgInt64 (m_mantissa[0]) >= 0);
		dgAssert (dgInt64 (A.m_mantissa[0]) >= 0);

		if (m_mantissa[0] && A.m_mantissa[0]) {
			dgUnsigned64 mantissa0[DG_GOOGOL_SIZE];
			dgUnsigned64 mantissa1[DG_GOOGOL_SIZE];
			dgUnsigned64 mantissa[DG_GOOGOL_SIZE];

			CopySignedMantissa (mantissa0);
			A.CopySignedMantissa (mantissa1);

			dgInt32 exponetDiff = m_exponent - A.m_exponent;
			dgInt32 exponent = m_exponent;
			if (exponetDiff > 0) {
				ShiftRightMantissa (mantissa1, exponetDiff);
			} else if (exponetDiff < 0) {
				exponent = A.m_exponent;
				ShiftRightMantissa (mantissa0, -exponetDiff);
			} 

			dgUnsigned64 carrier = 0;
			for (dgInt32 i = DG_GOOGOL_SIZE - 1; i >= 0; i --) {
				dgUnsigned64 m0 = mantissa0[i];
				dgUnsigned64 m1 = mantissa1[i];
				mantissa[i] = m0 + m1 + carrier;
				carrier = CheckCarrier (m0, m1) | CheckCarrier (m0 + m1, carrier);
			}

			dgInt8 sign = 0;
			if (dgInt64 (mantissa[0]) < 0) {
				sign = 1;
				NegateMantissa (mantissa);
			}

			dgInt32 bits = NormalizeMantissa (mantissa);
			if (bits <= (-64 * DG_GOOGOL_SIZE)) {
				tmp.m_sign = 0;
				tmp.m_exponent = 0;
			} else {
				tmp.m_sign = sign;
				tmp.m_exponent =  dgInt16 (exponent + bits);
			}

			memcpy (tmp.m_mantissa, mantissa, sizeof (m_mantissa));


		} else if (A.m_mantissa[0]) {
			tmp = A;
		} else {
			tmp = *this;
		}

		dgAssert (dgInt64 (tmp.m_mantissa[0]) >= 0);
		return tmp;
	}
コード例 #2
0
ファイル: dgGoogol.cpp プロジェクト: ColinGilbert/noobEngine
	dgGoogol::dgGoogol(dgFloat64 value)
		:m_sign(0)
		,m_exponent(0)
	{
		dgInt32 exp;
		dgFloat64 mantissa = fabs (frexp(value, &exp));

		m_exponent = dgInt16 (exp);
		m_sign = (value >= 0) ? 0 : 1;

		memset (m_mantissa, 0, sizeof (m_mantissa));
		m_mantissa[0] = (dgInt64 (dgFloat64 (dgUnsigned64(1)<<62) * mantissa));

		// it looks like GCC have problems with this
		//dgAssert (m_mantissa[0] >= 0);
		dgAssert ((m_mantissa[0] & dgUnsigned64(1)<<63) == 0);
	}
コード例 #3
0
ファイル: dgGoogol.cpp プロジェクト: ColinGilbert/noobEngine
	dgGoogol dgGoogol::operator* (const dgGoogol &A) const
	{
		dgAssert (dgInt64 (m_mantissa[0]) >= 0);
		dgAssert (dgInt64 (A.m_mantissa[0]) >= 0);

		if (m_mantissa[0] && A.m_mantissa[0]) {
			dgUnsigned64 mantissaAcc[DG_GOOGOL_SIZE * 2];
			memset (mantissaAcc, 0, sizeof (mantissaAcc));
			for (dgInt32 i = DG_GOOGOL_SIZE - 1; i >= 0; i --) {
				dgUnsigned64 a = m_mantissa[i];
				if (a) {
					dgUnsigned64 mantissaScale[2 * DG_GOOGOL_SIZE];
					memset (mantissaScale, 0, sizeof (mantissaScale));
					A.ScaleMantissa (&mantissaScale[i], a);

					dgUnsigned64 carrier = 0;
					for (dgInt32 j = 0; j < 2 * DG_GOOGOL_SIZE; j ++) {
						const dgInt32 k = 2 * DG_GOOGOL_SIZE - 1 - j;
						dgUnsigned64 m0 = mantissaAcc[k];
						dgUnsigned64 m1 = mantissaScale[k];
						mantissaAcc[k] = m0 + m1 + carrier;
						carrier = CheckCarrier (m0, m1) | CheckCarrier (m0 + m1, carrier);
					}
				}
			}

			dgUnsigned64 carrier = 0;
			dgInt32 bits = dgUnsigned64(LeadingZeros (mantissaAcc[0]) - 2);
			for (dgInt32 i = 0; i < 2 * DG_GOOGOL_SIZE; i ++) {
				const dgInt32 k = 2 * DG_GOOGOL_SIZE - 1 - i;
				dgUnsigned64 a = mantissaAcc[k];
				mantissaAcc[k] = (a << dgUnsigned64(bits)) | carrier;
				carrier = a >> dgUnsigned64(64 - bits);
			}

			dgInt32 exp = m_exponent + A.m_exponent - (bits - 2);

			dgGoogol tmp;
			tmp.m_sign = m_sign ^ A.m_sign;
			tmp.m_exponent = dgInt16 (exp);
			memcpy (tmp.m_mantissa, mantissaAcc, sizeof (m_mantissa));

			return tmp;
		} 
コード例 #4
0
bool dgCollisionConvexHull::Create (dgInt32 count, dgInt32 strideInBytes, const dgFloat32* const vertexArray, dgFloat32 tolerance)
{
	dgInt32 stride = strideInBytes / sizeof (dgFloat32);
	dgStack<dgFloat64> buffer(3 * 2 * count);
	for (dgInt32 i = 0; i < count; i ++) {
		buffer[i * 3 + 0] = vertexArray[i * stride + 0];
		buffer[i * 3 + 1] = vertexArray[i * stride + 1];
		buffer[i * 3 + 2] = vertexArray[i * stride + 2];
	}

	dgConvexHull3d* convexHull =  new (GetAllocator()) dgConvexHull3d (GetAllocator(), &buffer[0], 3 * sizeof (dgFloat64), count, tolerance);
	if (!convexHull->GetCount()) {
		// this is a degenerated hull hull to add some thickness and for a thick plane
		delete convexHull;

		dgStack<dgVector> tmp(3 * count);
		for (dgInt32 i = 0; i < count; i ++) {
			tmp[i][0] = dgFloat32 (buffer[i*3 + 0]);
			tmp[i][1] = dgFloat32 (buffer[i*3 + 1]);
			tmp[i][2] = dgFloat32 (buffer[i*3 + 2]);
			tmp[i][2] = dgFloat32 (0.0f);
		}
	
		dgObb sphere;
		sphere.SetDimensions (&tmp[0][0], sizeof (dgVector), count);

		dgInt32 index = 0;
		dgFloat32 size = dgFloat32 (1.0e10f);
		for (dgInt32 i = 0; i < 3; i ++) {
			if (sphere.m_size[i] < size) {
				index = i;
				size = sphere.m_size[i];
			}
		}
		dgVector normal (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
		normal[index] = dgFloat32 (1.0f);
		dgVector step = sphere.RotateVector (normal.Scale3 (dgFloat32 (0.05f)));
		for (dgInt32 i = 0; i < count; i ++) {
			dgVector p1 (tmp[i] + step);
			dgVector p2 (tmp[i] - step);

			buffer[i * 3 + 0] = p1.m_x;
			buffer[i * 3 + 1] = p1.m_y;
			buffer[i * 3 + 2] = p1.m_z;
			buffer[(i + count) * 3 + 0] = p2.m_x;
			buffer[(i + count) * 3 + 1] = p2.m_y;
			buffer[(i + count) * 3 + 2] = p2.m_z;
		}
		count *= 2;
		convexHull =  new (GetAllocator()) dgConvexHull3d (GetAllocator(), &buffer[0], 3 * sizeof (dgFloat64), count, tolerance);
		if (!convexHull->GetCount()) {
			delete convexHull;
			return false;
		}
	}

	// check for degenerated faces
	for (bool success = false; !success;  ) {
		success = true;
		const dgBigVector* const hullVertexArray = convexHull->GetVertexPool();

		dgStack<dgInt8> mask(convexHull->GetVertexCount());
		memset (&mask[0], 1, mask.GetSizeInBytes());
		for (dgConvexHull3d::dgListNode* node = convexHull->GetFirst(); node; node = node->GetNext()) {
			dgConvexHull3DFace& face = node->GetInfo();
			const dgBigVector& p0 = hullVertexArray[face.m_index[0]];
			const dgBigVector& p1 = hullVertexArray[face.m_index[1]];
			const dgBigVector& p2 = hullVertexArray[face.m_index[2]];
			dgBigVector p1p0 (p1 - p0);
			dgBigVector p2p0 (p2 - p0);
			dgBigVector normal (p2p0 * p1p0);
			dgFloat64 mag2 = normal % normal;
			if (mag2 < dgFloat64 (1.0e-6f * 1.0e-6f)) {
				success = false;
				dgInt32 index = -1;
				dgBigVector p2p1 (p2 - p1);
				dgFloat64 dist10 = p1p0 % p1p0;
				dgFloat64 dist20 = p2p0 % p2p0;
				dgFloat64 dist21 = p2p1 % p2p1;
				if ((dist10 >= dist20) && (dist10 >= dist21)) {
					index = 2;
				} else if ((dist20 >= dist10) && (dist20 >= dist21)) {
					index = 1;
				} else if ((dist21 >= dist10) && (dist21 >= dist20)) {
					index = 0;
				}
				dgAssert (index != -1);
				mask[face.m_index[index]] = 0;
			}
		}
		if (!success) {
			dgInt32 count = 0;
			dgInt32 vertexCount = convexHull->GetVertexCount();
			for (dgInt32 i = 0; i < vertexCount; i ++) {
				if (mask[i]) {
					buffer[count * 3 + 0] = hullVertexArray[i].m_x;
					buffer[count * 3 + 1] = hullVertexArray[i].m_y;
					buffer[count * 3 + 2] = hullVertexArray[i].m_z;
					count ++;
				}
			}
			delete convexHull;
			convexHull =  new (GetAllocator()) dgConvexHull3d (GetAllocator(), &buffer[0], 3 * sizeof (dgFloat64), count, tolerance);
		}
	}

	dgAssert (convexHull);
	dgInt32 vertexCount = convexHull->GetVertexCount();
	if (vertexCount < 4) {
		delete convexHull;
		return false;
	}
	

	const dgBigVector* const hullVertexArray = convexHull->GetVertexPool();

	dgPolyhedra polyhedra (GetAllocator());
	polyhedra.BeginFace();
	for (dgConvexHull3d::dgListNode* node = convexHull->GetFirst(); node; node = node->GetNext()) {
		dgConvexHull3DFace& face = node->GetInfo();
		polyhedra.AddFace (face.m_index[0], face.m_index[1], face.m_index[2]);
	}
	polyhedra.EndFace();

	if (vertexCount > 4) {
//		bool edgeRemoved = false;
//		while (RemoveCoplanarEdge (polyhedra, hullVertexArray)) {
//			edgeRemoved = true;
//		}
//		if (edgeRemoved) {
//			if (!CheckConvex (polyhedra, hullVertexArray)) {
//				delete convexHull;
//				return false;
//			}
//		}
		while (RemoveCoplanarEdge (polyhedra, hullVertexArray));
	}

	dgStack<dgInt32> vertexMap(vertexCount);
	memset (&vertexMap[0], -1, vertexCount * sizeof (dgInt32));

	dgInt32 mark = polyhedra.IncLRU();
	dgPolyhedra::Iterator iter (polyhedra);
	for (iter.Begin(); iter; iter ++) {
		dgEdge* const edge = &iter.GetNode()->GetInfo();
		if (edge->m_mark != mark) {
			if (vertexMap[edge->m_incidentVertex] == -1) {
				vertexMap[edge->m_incidentVertex] = m_vertexCount;
				m_vertexCount ++;
			}
			dgEdge* ptr = edge;
			do {
				ptr->m_mark = mark;
				ptr->m_userData = m_edgeCount;
				m_edgeCount ++;
				ptr = ptr->m_twin->m_next;
			} while (ptr != edge) ;
		}
	} 

	m_vertex = (dgVector*) m_allocator->Malloc (dgInt32 (m_vertexCount * sizeof (dgVector)));
	m_simplex = (dgConvexSimplexEdge*) m_allocator->Malloc (dgInt32 (m_edgeCount * sizeof (dgConvexSimplexEdge)));
	m_vertexToEdgeMapping = (const dgConvexSimplexEdge**) m_allocator->Malloc (dgInt32 (m_vertexCount * sizeof (dgConvexSimplexEdge*)));

	for (dgInt32 i = 0; i < vertexCount; i ++) {
		if (vertexMap[i] != -1) {
			m_vertex[vertexMap[i]] = hullVertexArray[i];
			m_vertex[vertexMap[i]].m_w = dgFloat32 (0.0f);
		}
	}
	delete convexHull;

	vertexCount = m_vertexCount;
	mark = polyhedra.IncLRU();;
	for (iter.Begin(); iter; iter ++) {
		dgEdge* const edge = &iter.GetNode()->GetInfo();
		if (edge->m_mark != mark) {
			dgEdge *ptr = edge;
			do {
				ptr->m_mark = mark;
				dgConvexSimplexEdge* const simplexPtr = &m_simplex[ptr->m_userData];
				simplexPtr->m_vertex = vertexMap[ptr->m_incidentVertex];
				simplexPtr->m_next = &m_simplex[ptr->m_next->m_userData];
				simplexPtr->m_prev = &m_simplex[ptr->m_prev->m_userData];
				simplexPtr->m_twin = &m_simplex[ptr->m_twin->m_userData];

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

	
	m_faceCount = 0;
	dgStack<char> faceMarks (m_edgeCount);
	memset (&faceMarks[0], 0, m_edgeCount * sizeof (dgInt8));

	dgStack<dgConvexSimplexEdge*> faceArray (m_edgeCount);
	for (dgInt32 i = 0; i < m_edgeCount; i ++) {
		dgConvexSimplexEdge* const face = &m_simplex[i];
		if (!faceMarks[i]) {
			dgConvexSimplexEdge* ptr = face;
			do {
				dgAssert ((ptr - m_simplex) >= 0);
				faceMarks[dgInt32 (ptr - m_simplex)] = '1';
				ptr = ptr->m_next;
			} while (ptr != face);

			faceArray[m_faceCount] = face;
			m_faceCount ++;
		}
	}
	m_faceArray = (dgConvexSimplexEdge **) m_allocator->Malloc(dgInt32 (m_faceCount * sizeof(dgConvexSimplexEdge *)));
	memcpy (m_faceArray, &faceArray[0], m_faceCount * sizeof(dgConvexSimplexEdge *));
	
	if (vertexCount > DG_CONVEX_VERTEX_CHUNK_SIZE) {
		// create a face structure for support vertex
		dgStack<dgConvexBox> boxTree (vertexCount);
		dgTree<dgVector,dgInt32> sortTree(GetAllocator());
		dgStack<dgTree<dgVector,dgInt32>::dgTreeNode*> vertexNodeList(vertexCount);

		dgVector minP ( dgFloat32 (1.0e15f),  dgFloat32 (1.0e15f),  dgFloat32 (1.0e15f), dgFloat32 (0.0f)); 
		dgVector maxP (-dgFloat32 (1.0e15f), -dgFloat32 (1.0e15f), -dgFloat32 (1.0e15f), dgFloat32 (0.0f)); 	
		for (dgInt32 i = 0; i < vertexCount; i ++) {
			const dgVector& p = m_vertex[i];
			vertexNodeList[i] = sortTree.Insert (p, i);
			minP.m_x = dgMin (p.m_x, minP.m_x); 
			minP.m_y = dgMin (p.m_y, minP.m_y); 
			minP.m_z = dgMin (p.m_z, minP.m_z); 
			
			maxP.m_x = dgMax (p.m_x, maxP.m_x); 
			maxP.m_y = dgMax (p.m_y, maxP.m_y); 
			maxP.m_z = dgMax (p.m_z, maxP.m_z); 
		}

		boxTree[0].m_box[0] = minP;
		boxTree[0].m_box[1] = maxP;
		boxTree[0].m_leftBox = -1;
		boxTree[0].m_rightBox = -1;
		boxTree[0].m_vertexStart = 0;
		boxTree[0].m_vertexCount = vertexCount;
		dgInt32 boxCount = 1;

		dgInt32 stack = 1;
		dgInt32 stackBoxPool[64];
		stackBoxPool[0] = 0;

		while (stack) {
			stack --;
			dgInt32 boxIndex = stackBoxPool[stack];
			dgConvexBox& box = boxTree[boxIndex];
			if (box.m_vertexCount > DG_CONVEX_VERTEX_CHUNK_SIZE) {
				dgVector median (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
				dgVector varian (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
				for (dgInt32 i = 0; i < box.m_vertexCount; i ++) {
					dgVector& p = vertexNodeList[box.m_vertexStart + i]->GetInfo();
					minP.m_x = dgMin (p.m_x, minP.m_x); 
					minP.m_y = dgMin (p.m_y, minP.m_y); 
					minP.m_z = dgMin (p.m_z, minP.m_z); 

					maxP.m_x = dgMax (p.m_x, maxP.m_x); 
					maxP.m_y = dgMax (p.m_y, maxP.m_y); 
					maxP.m_z = dgMax (p.m_z, maxP.m_z); 

					median += p;
					varian += p.CompProduct3 (p);
				}

				varian = varian.Scale3 (dgFloat32 (box.m_vertexCount)) - median.CompProduct3(median);
				dgInt32 index = 0;
				dgFloat64 maxVarian = dgFloat64 (-1.0e10f);
				for (dgInt32 i = 0; i < 3; i ++) {
					if (varian[i] > maxVarian) {
						index = i;
						maxVarian = varian[i];
					}
				}
				dgVector center = median.Scale3 (dgFloat32 (1.0f) / dgFloat32 (box.m_vertexCount));
				dgFloat32 test = center[index];

				dgInt32 i0 = 0;
				dgInt32 i1 = box.m_vertexCount - 1;
				do {    
					for (; i0 <= i1; i0 ++) {
						dgFloat32 val = vertexNodeList[box.m_vertexStart + i0]->GetInfo()[index];
						if (val > test) {
							break;
						}
					}

					for (; i1 >= i0; i1 --) {
						dgFloat32 val = vertexNodeList[box.m_vertexStart + i1]->GetInfo()[index];
						if (val < test) {
							break;
						}
					}

					if (i0 < i1)	{
						dgSwap(vertexNodeList[box.m_vertexStart + i0], vertexNodeList[box.m_vertexStart + i1]);
						i0++; 
						i1--;
					}
				} while (i0 <= i1);

				if (i0 == 0){
					i0 = box.m_vertexCount / 2;
				}
				if (i0 >= (box.m_vertexCount - 1)){
					i0 = box.m_vertexCount / 2;
				}


				{
					dgVector minP ( dgFloat32 (1.0e15f),  dgFloat32 (1.0e15f),  dgFloat32 (1.0e15f), dgFloat32 (0.0f)); 
					dgVector maxP (-dgFloat32 (1.0e15f), -dgFloat32 (1.0e15f), -dgFloat32 (1.0e15f), dgFloat32 (0.0f)); 	
					for (dgInt32 i = i0; i < box.m_vertexCount; i ++) {
						const dgVector& p = vertexNodeList[box.m_vertexStart + i]->GetInfo();
						minP.m_x = dgMin (p.m_x, minP.m_x); 
						minP.m_y = dgMin (p.m_y, minP.m_y); 
						minP.m_z = dgMin (p.m_z, minP.m_z); 

						maxP.m_x = dgMax (p.m_x, maxP.m_x); 
						maxP.m_y = dgMax (p.m_y, maxP.m_y); 
						maxP.m_z = dgMax (p.m_z, maxP.m_z); 
					}

					box.m_rightBox = boxCount;
					boxTree[boxCount].m_box[0] = minP;
					boxTree[boxCount].m_box[1] = maxP;
					boxTree[boxCount].m_leftBox = -1;
					boxTree[boxCount].m_rightBox = -1;
					boxTree[boxCount].m_vertexStart = box.m_vertexStart + i0;
					boxTree[boxCount].m_vertexCount = box.m_vertexCount - i0;
					stackBoxPool[stack] = boxCount;
					stack ++;
					boxCount ++;
				}

				{
					dgVector minP ( dgFloat32 (1.0e15f),  dgFloat32 (1.0e15f),  dgFloat32 (1.0e15f), dgFloat32 (0.0f)); 
					dgVector maxP (-dgFloat32 (1.0e15f), -dgFloat32 (1.0e15f), -dgFloat32 (1.0e15f), dgFloat32 (0.0f)); 	
					for (dgInt32 i = 0; i < i0; i ++) {
						const dgVector& p = vertexNodeList[box.m_vertexStart + i]->GetInfo();
						minP.m_x = dgMin (p.m_x, minP.m_x); 
						minP.m_y = dgMin (p.m_y, minP.m_y); 
						minP.m_z = dgMin (p.m_z, minP.m_z); 

						maxP.m_x = dgMax (p.m_x, maxP.m_x); 
						maxP.m_y = dgMax (p.m_y, maxP.m_y); 
						maxP.m_z = dgMax (p.m_z, maxP.m_z); 
					}

					box.m_leftBox = boxCount;
					boxTree[boxCount].m_box[0] = minP;
					boxTree[boxCount].m_box[1] = maxP;
					boxTree[boxCount].m_leftBox = -1;
					boxTree[boxCount].m_rightBox = -1;
					boxTree[boxCount].m_vertexStart = box.m_vertexStart;
					boxTree[boxCount].m_vertexCount = i0;
					stackBoxPool[stack] = boxCount;
					stack ++;
					boxCount ++;
				}
			}
		}

		for (dgInt32 i = 0; i < m_vertexCount; i ++) {
			m_vertex[i] = vertexNodeList[i]->GetInfo();
			vertexNodeList[i]->GetInfo().m_w = dgFloat32 (i);
		}

		m_supportTreeCount = boxCount;
		m_supportTree = (dgConvexBox*) m_allocator->Malloc(dgInt32 (boxCount * sizeof(dgConvexBox)));		
		memcpy (m_supportTree, &boxTree[0], boxCount * sizeof(dgConvexBox));

		for (dgInt32 i = 0; i < m_edgeCount; i ++) {
			dgConvexSimplexEdge* const ptr = &m_simplex[i];
			dgTree<dgVector,dgInt32>::dgTreeNode* const node = sortTree.Find(ptr->m_vertex);
			dgInt32 index = dgInt32 (node->GetInfo().m_w);
			ptr->m_vertex = dgInt16 (index);
		}
	}

	for (dgInt32 i = 0; i < m_edgeCount; i ++) {
		dgConvexSimplexEdge* const edge = &m_simplex[i];
		m_vertexToEdgeMapping[edge->m_vertex] = edge;
	}


	SetVolumeAndCG ();
	return true;
}
コード例 #5
0
dgCollisionDeformableMesh::dgCollisionDeformableMesh(dgWorld* const world, dgMeshEffect* const mesh, dgCollisionID collsionID)
	:dgCollisionConvex (mesh->GetAllocator(), 0, collsionID)
	,m_particles (mesh->GetVertexCount ())
	,m_visualSegments(mesh->GetAllocator())
	,m_skinThickness(DG_DEFORMABLE_DEFAULT_SKIN_THICKNESS)
	,m_nodesCount(0)
	,m_trianglesCount(0)
	,m_visualVertexCount(0)
	,m_world (world)
	,m_myBody(NULL)
	,m_indexList(NULL)
	,m_faceNormals(NULL)
	,m_rootNode(NULL)
	,m_nodesMemory(NULL)
	,m_visualVertexData(NULL)
	,m_onDebugDisplay(NULL)
	,m_isdoubleSided(false)
{
	m_rtti |= dgCollisionDeformableMesh_RTTI;

	dgDeformableBodiesUpdate& softBodyList = *m_world;
	softBodyList.AddShape (this);

	dgMeshEffect meshCopy (*mesh);
	meshCopy.Triangulate();

	m_trianglesCount = meshCopy.GetTotalFaceCount (); 
	m_nodesMemory = (dgDeformableNode*) dgMallocStack((m_trianglesCount * 2 - 1) * sizeof (dgDeformableNode));
	m_indexList = (dgInt32*) dgMallocStack (3 * m_trianglesCount * sizeof (dgInt32));
	m_faceNormals = (dgVector*) dgMallocStack (m_trianglesCount * sizeof (dgVector));

	dgInt32 stride = meshCopy.GetVertexStrideInByte() / sizeof (dgFloat64);  
	dgFloat64* const vertex = meshCopy.GetVertexPool();  

	for (dgInt32 i = 0; i < m_particles.m_count; i ++) {
		m_particles.m_unitMass[i] = dgFloat32 (1.0f);
		m_particles.m_veloc[i] = dgVector (dgFloat32 (0.0f));
		m_particles.m_posit[i] = dgVector (&vertex[i * stride]) & dgVector::m_triplexMask;
	}

	dgInt32 indexCount = meshCopy.GetTotalIndexCount (); 
	dgStack<dgInt32> faceArray (m_trianglesCount);
	dgStack<dgInt32> materials (m_trianglesCount);
	dgStack<void*>indexArray (indexCount);
	meshCopy.GetFaces (&faceArray[0], &materials[0], &indexArray[0]);
	for (dgInt32 i = 0; i < m_trianglesCount; i ++) {
		dgInt32 count = faceArray[i];
		dgAssert (faceArray[i]);
		for (dgInt32 j = 0; j < count; j ++) {
			dgInt32 k = meshCopy.GetVertexIndex(indexArray[i * 3 + j]);
			m_indexList[i * 3 + j] = k;
		}

//dgTrace (("%d %d %d\n", m_indexList[i * 3 + 0], m_indexList[i * 3 + 1], m_indexList[i * 3 + 2]));

		dgDeformableNode& node = m_nodesMemory[i];
		node.m_left = NULL;
		node.m_right = NULL;
		node.m_parent = NULL;
		node.m_indexStart = i * 3;
		node.CalculateBox(m_particles.m_posit, &m_indexList[i * 3]);
	}

	m_nodesCount = m_trianglesCount;
	m_rootNode = BuildTopDown (m_nodesCount, m_nodesMemory, NULL);

	ImproveTotalFitness();
	SetCollisionBBox (m_rootNode->m_minBox, m_rootNode->m_maxBox);

	// create visual vertex data
	m_visualVertexCount = meshCopy.GetPropertiesCount();
	m_visualVertexData = (dgVisualVertexData*) dgMallocStack(m_visualVertexCount * sizeof (dgVisualVertexData));

	for (dgInt32 i = 0; i < m_visualVertexCount; i ++) {
		dgMeshEffect::dgVertexAtribute& attribute = meshCopy.GetAttribute (i);
		m_visualVertexData[i].m_uv0[0] = dgFloat32 (attribute.m_u0);
		m_visualVertexData[i].m_uv0[1] = dgFloat32 (attribute.m_v0);
	}

	for (void* point = meshCopy.GetFirstPoint(); point; point = meshCopy.GetNextPoint(point)) {
		dgInt32 pointIndex = meshCopy.GetPointIndex (point);
		dgInt32 vertexIndex = meshCopy.GetVertexIndexFromPoint (point);
		m_visualVertexData[pointIndex].m_vertexIndex = vertexIndex;
	}

	for (dgInt32 i = 0; i < m_trianglesCount; i ++) {
		dgInt32 mat = materials[i];
		if (mat != -1) {
			dgInt32 count = 0;
			for (dgInt32 j = i; j < m_trianglesCount; j ++) {
				dgInt32 mat1 = materials[j];
				if (mat == mat1) {
					materials[j] = -1;
					count ++;
				}
			}

			dgMeshSegment& segment = m_visualSegments.Append()->GetInfo();
			segment.m_material = mat;
			segment.m_indexCount = count * 3;
			segment.m_indexList = (dgInt32*) dgMallocStack( 2 * segment.m_indexCount * sizeof (dgInt32));

			dgInt32 index0 = 0;
			dgInt32 index1 = m_trianglesCount * 3;
			for (dgInt32 j = i; j < m_trianglesCount; j ++) {
				if (materials[j] == -1) {
					dgInt32 m0 = meshCopy.GetPointIndex(indexArray[j * 3 + 0]);
					dgInt32 m1 = meshCopy.GetPointIndex(indexArray[j * 3 + 1]);
					dgInt32 m2 = meshCopy.GetPointIndex(indexArray[j * 3 + 2]);

					segment.m_indexList[index0 + 0] = dgInt16 (m0);
					segment.m_indexList[index0 + 1] = dgInt16 (m1);
					segment.m_indexList[index0 + 2] = dgInt16 (m2);
					index0 += 3;

					segment.m_indexList[index1 + 0] = dgInt16 (m0);
					segment.m_indexList[index1 + 1] = dgInt16 (m2);
					segment.m_indexList[index1 + 2] = dgInt16 (m1);
					index1 += 3;
				}
			}
		}
	}
//	SetVolumeAndCG ();
}