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; }
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); }
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; }
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; }
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 (); }