void dgPolygonSoupDatabaseBuilder::EndAndOptimize(bool optimize)
{
	if (m_faceCount) {
		dgStack<hacd::HaI32> indexMapPool (m_indexCount + m_vertexCount);

		hacd::HaI32* const indexMap = &indexMapPool[0];
		m_vertexCount = dgVertexListToIndexList (&m_vertexPoints[0].m_x, sizeof (dgBigVector), 3, m_vertexCount, &indexMap[0], hacd::HaF32 (1.0e-4f));

		hacd::HaI32 k = 0;
		for (hacd::HaI32 i = 0; i < m_faceCount; i ++) {
			k ++;
			hacd::HaI32 count = m_faceVertexCount[i];
			for (hacd::HaI32 j = 1; j < count; j ++) {
				hacd::HaI32 index = m_vertexIndex[k];
				index = indexMap[index];
				m_vertexIndex[k] = index;
				k ++;
			}
		}

		OptimizeByIndividualFaces();
		if (optimize) {
			OptimizeByGroupID();
			OptimizeByIndividualFaces();
		}
	}
}
void dgPolygonSoupDatabaseBuilder::End(bool optimize)
{
	Optimize(optimize);

	// build the normal array and adjacency array
	// calculate all face the normals
	hacd::HaI32 indexCount = 0;
	m_normalPoints[m_faceCount].m_x = hacd::HaF64 (0.0f);
	for (hacd::HaI32 i = 0; i < m_faceCount; i ++) {
		hacd::HaI32 faceIndexCount = m_faceVertexCount[i];

		hacd::HaI32* const ptr = &m_vertexIndex[indexCount + 1];
		dgBigVector v0 (&m_vertexPoints[ptr[0]].m_x);
		dgBigVector v1 (&m_vertexPoints[ptr[1]].m_x);
		dgBigVector e0 (v1 - v0);
		dgBigVector normal (hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (0.0f));
		for (hacd::HaI32 j = 2; j < faceIndexCount - 1; j ++) {
			dgBigVector v2 (&m_vertexPoints[ptr[j]].m_x);
			dgBigVector e1 (v2 - v0);
			normal += e0 * e1;
			e0 = e1;
		}
		normal = normal.Scale (dgRsqrt (normal % normal));

		m_normalPoints[i].m_x = normal.m_x;
		m_normalPoints[i].m_y = normal.m_y;
		m_normalPoints[i].m_z = normal.m_z;
		indexCount += faceIndexCount;
	}
	// compress normals array
	m_normalIndex[m_faceCount] = 0;
	m_normalCount = dgVertexListToIndexList(&m_normalPoints[0].m_x, sizeof (dgBigVector), 3, m_faceCount, &m_normalIndex[0], hacd::HaF32 (1.0e-4f));
}
void dgPolygonSoupDatabaseBuilder::PackArray()
{
	dgStack<hacd::HaI32> indexMapPool (m_vertexCount);
	hacd::HaI32* const indexMap = &indexMapPool[0];
	m_vertexCount = dgVertexListToIndexList (&m_vertexPoints[0].m_x, sizeof (dgBigVector), 3, m_vertexCount, &indexMap[0], hacd::HaF32 (1.0e-6f));

	hacd::HaI32 k = 0;
	for (hacd::HaI32 i = 0; i < m_faceCount; i ++) {
		k ++;

		hacd::HaI32 count = m_faceVertexCount[i];
		for (hacd::HaI32 j = 1; j < count; j ++) {
			hacd::HaI32 index = m_vertexIndex[k];
			index = indexMap[index];
			m_vertexIndex[k] = index;
			k ++;
		}
	}

	m_run = DG_POINTS_RUN;
}
Exemple #4
0
void dgCollisionSphere::Init (dgFloat32 radius, dgMemoryAllocator* allocator)
{
	m_rtti |= dgCollisionSphere_RTTI;
	m_radius = radius;

	m_edgeCount = DG_SPHERE_EDGE_COUNT;
	m_vertexCount = DG_SPHERE_VERTEX_COUNT;
	dgCollisionConvex::m_vertex = m_vertex;

	if (!m_shapeRefCount) {

		dgInt32 indexList[256];
		dgVector tmpVectex[256];

		dgVector p0 ( dgFloat32 (1.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f)); 
		dgVector p1 (-dgFloat32 (1.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f)); 
		dgVector p2 ( dgFloat32 (0.0f), dgFloat32 (1.0f), dgFloat32 (0.0f), dgFloat32 (0.0f)); 
		dgVector p3 ( dgFloat32 (0.0f),-dgFloat32 (1.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
		dgVector p4 ( dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (1.0f), dgFloat32 (0.0f));
		dgVector p5 ( dgFloat32 (0.0f), dgFloat32 (0.0f),-dgFloat32 (1.0f), dgFloat32 (0.0f));

		dgInt32 i = 1;
		dgInt32 count = 0;
		TesselateTriangle (i, p4, p0, p2, count, tmpVectex);
		TesselateTriangle (i, p4, p2, p1, count, tmpVectex);
		TesselateTriangle (i, p4, p1, p3, count, tmpVectex);
		TesselateTriangle (i, p4, p3, p0, count, tmpVectex);
		TesselateTriangle (i, p5, p2, p0, count, tmpVectex);
		TesselateTriangle (i, p5, p1, p2, count, tmpVectex);
		TesselateTriangle (i, p5, p3, p1, count, tmpVectex);
		TesselateTriangle (i, p5, p0, p3, count, tmpVectex);

		//dgAssert (count == EDGE_COUNT);
		dgInt32 vertexCount = dgVertexListToIndexList (&tmpVectex[0].m_x, sizeof (dgVector), 3 * sizeof (dgFloat32), 0, count, indexList, 0.001f); 

		dgAssert (vertexCount == DG_SPHERE_VERTEX_COUNT);
		for (dgInt32 i = 0; i < vertexCount; i ++) {
			m_unitSphere[i] = tmpVectex[i];
		}
		dgPolyhedra polyhedra(m_allocator);

		polyhedra.BeginFace();
		for (dgInt32 i = 0; i < count; i += 3) {
#ifdef _DEBUG
			dgEdge* const edge = polyhedra.AddFace (indexList[i],  indexList[i + 1], indexList[i + 2]);
			dgAssert (edge);
#else 
			polyhedra.AddFace (indexList[i],  indexList[i + 1], indexList[i + 2]);
#endif
		}
		polyhedra.EndFace();

		dgUnsigned64 i1 = 0;
		dgPolyhedra::Iterator iter (polyhedra);
		for (iter.Begin(); iter; iter ++) {
			dgEdge* const edge = &(*iter);
			edge->m_userData = i1;
			i1 ++;
		}

		for (iter.Begin(); iter; iter ++) {
			dgEdge* const edge = &(*iter);

			dgConvexSimplexEdge* const ptr = &m_edgeArray[edge->m_userData];

			ptr->m_vertex = edge->m_incidentVertex;
			ptr->m_next = &m_edgeArray[edge->m_next->m_userData];
			ptr->m_prev = &m_edgeArray[edge->m_prev->m_userData];
			ptr->m_twin = &m_edgeArray[edge->m_twin->m_userData];
		}
	}

	for (dgInt32 i = 0; i < DG_SPHERE_VERTEX_COUNT; i ++) {
		m_vertex[i] = m_unitSphere[i].Scale4 (m_radius);
	}

	m_shapeRefCount ++;
	dgCollisionConvex::m_simplex = m_edgeArray;
	SetVolumeAndCG ();
}
dgMeshEffect * dgMeshEffect::CreateVoronoiConvexDecomposition (dgMemoryAllocator * const allocator, dgInt32 pointCount, dgInt32 pointStrideInBytes, const dgFloat32 * const pointCloud, dgInt32 materialId, const dgMatrix & textureProjectionMatrix)
{
   dgFloat32 normalAngleInRadians = 30.0f * 3.1416f / 180.0f;
   dgStack<dgBigVector> buffer (pointCount + 16);
   dgBigVector * const pool = &buffer[0];
   dgInt32 count = 0;
   dgFloat64 quantizeFactor = dgFloat64 (16.0f);
   dgFloat64 invQuantizeFactor = dgFloat64 (1.0f) / quantizeFactor;
   dgInt32 stride = pointStrideInBytes / sizeof (dgFloat32);
   dgBigVector pMin (dgFloat32 (1.0e10f), dgFloat32 (1.0e10f), dgFloat32 (1.0e10f), dgFloat32 (0.0f));
   dgBigVector pMax (dgFloat32 (-1.0e10f), dgFloat32 (-1.0e10f), dgFloat32 (-1.0e10f), dgFloat32 (0.0f));
   for (dgInt32 i = 0; i < pointCount; i ++)
   {
      dgFloat64 x = pointCloud[i * stride + 0];
      dgFloat64 y	= pointCloud[i * stride + 1];
      dgFloat64 z	= pointCloud[i * stride + 2];
      x = floor (x * quantizeFactor) * invQuantizeFactor;
      y = floor (y * quantizeFactor) * invQuantizeFactor;
      z = floor (z * quantizeFactor) * invQuantizeFactor;
      dgBigVector p (x, y, z, dgFloat64 (0.0f));
      pMin = dgBigVector (dgMin (x, pMin.m_x), dgMin (y, pMin.m_y), dgMin (z, pMin.m_z), dgFloat64 (0.0f));
      pMax = dgBigVector (dgMax (x, pMax.m_x), dgMax (y, pMax.m_y), dgMax (z, pMax.m_z), dgFloat64 (0.0f));
      pool[count] = p;
      count ++;
   }
   // add the bbox as a barrier
   pool[count + 0] = dgBigVector ( pMin.m_x, pMin.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 1] = dgBigVector ( pMax.m_x, pMin.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 2] = dgBigVector ( pMin.m_x, pMax.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 3] = dgBigVector ( pMax.m_x, pMax.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 4] = dgBigVector ( pMin.m_x, pMin.m_y, pMax.m_z, dgFloat64 (0.0f));
   pool[count + 5] = dgBigVector ( pMax.m_x, pMin.m_y, pMax.m_z, dgFloat64 (0.0f));
   pool[count + 6] = dgBigVector ( pMin.m_x, pMax.m_y, pMax.m_z, dgFloat64 (0.0f));
   pool[count + 7] = dgBigVector ( pMax.m_x, pMax.m_y, pMax.m_z, dgFloat64 (0.0f));
   count += 8;
   dgStack<dgInt32> indexList (count);
   count = dgVertexListToIndexList (&pool[0].m_x, sizeof (dgBigVector), 3, count, &indexList[0], dgFloat64 (5.0e-2f));
   dgAssert (count >= 8);
   dgFloat64 maxSize = dgMax (pMax.m_x - pMin.m_x, pMax.m_y - pMin.m_y, pMax.m_z - pMin.m_z);
   pMin -= dgBigVector (maxSize, maxSize, maxSize, dgFloat64 (0.0f));
   pMax += dgBigVector (maxSize, maxSize, maxSize, dgFloat64 (0.0f));
   // add the a guard zone, so that we do no have to clip
   dgInt32 guadVertexKey = count;
   pool[count + 0] = dgBigVector ( pMin.m_x, pMin.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 1] = dgBigVector ( pMax.m_x, pMin.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 2] = dgBigVector ( pMin.m_x, pMax.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 3] = dgBigVector ( pMax.m_x, pMax.m_y, pMin.m_z, dgFloat64 (0.0f));
   pool[count + 4] = dgBigVector ( pMin.m_x, pMin.m_y, pMax.m_z, dgFloat64 (0.0f));
   pool[count + 5] = dgBigVector ( pMax.m_x, pMin.m_y, pMax.m_z, dgFloat64 (0.0f));
   pool[count + 6] = dgBigVector ( pMin.m_x, pMax.m_y, pMax.m_z, dgFloat64 (0.0f));
   pool[count + 7] = dgBigVector ( pMax.m_x, pMax.m_y, pMax.m_z, dgFloat64 (0.0f));
   count += 8;
   dgDelaunayTetrahedralization delaunayTetrahedras (allocator, &pool[0].m_x, count, sizeof (dgBigVector), dgFloat32 (0.0f));
   delaunayTetrahedras.RemoveUpperHull ();
   //	delaunayTetrahedras.Save("xxx0.txt");
   dgInt32 tetraCount = delaunayTetrahedras.GetCount();
   dgStack<dgBigVector> voronoiPoints (tetraCount + 32);
   dgStack<dgDelaunayTetrahedralization::dgListNode *> tetradrumNode (tetraCount);
   dgTree<dgList<dgInt32>, dgInt32> delanayNodes (allocator);
   dgInt32 index = 0;
   const dgHullVector * const delanayPoints = delaunayTetrahedras.GetHullVertexArray();
   for (dgDelaunayTetrahedralization::dgListNode * node = delaunayTetrahedras.GetFirst(); node; node = node->GetNext())
   {
      dgConvexHull4dTetraherum & tetra = node->GetInfo();
      voronoiPoints[index] = tetra.CircumSphereCenter (delanayPoints);
      tetradrumNode[index] = node;
      for (dgInt32 i = 0; i < 4; i ++)
      {
         dgTree<dgList<dgInt32>, dgInt32>::dgTreeNode * header = delanayNodes.Find (tetra.m_faces[0].m_index[i]);
         if (!header)
         {
            dgList<dgInt32> list (allocator);
            header = delanayNodes.Insert (list, tetra.m_faces[0].m_index[i]);
         }
         header->GetInfo().Append (index);
      }
      index ++;
   }
   dgMeshEffect * const voronoiPartition = new (allocator) dgMeshEffect (allocator);
   voronoiPartition->BeginPolygon();
   dgFloat64 layer = dgFloat64 (0.0f);
   dgTree<dgList<dgInt32>, dgInt32>::Iterator iter (delanayNodes);
   for (iter.Begin(); iter; iter ++)
   {
      dgTree<dgList<dgInt32>, dgInt32>::dgTreeNode * const nodeNode = iter.GetNode();
      const dgList<dgInt32> & list = nodeNode->GetInfo();
      dgInt32 key = nodeNode->GetKey();
      if (key < guadVertexKey)
      {
         dgBigVector pointArray[512];
         dgInt32 indexArray[512];
         dgInt32 count = 0;
         for (dgList<dgInt32>::dgListNode * ptr = list.GetFirst(); ptr; ptr = ptr->GetNext())
         {
            dgInt32 i = ptr->GetInfo();
            pointArray[count] = voronoiPoints[i];
            count ++;
            dgAssert (count < dgInt32 (sizeof (pointArray) / sizeof (pointArray[0])));
         }
         count = dgVertexListToIndexList (&pointArray[0].m_x, sizeof (dgBigVector), 3, count, &indexArray[0], dgFloat64 (1.0e-3f));
         if (count >= 4)
         {
            dgMeshEffect convexMesh (allocator, &pointArray[0].m_x, count, sizeof (dgBigVector), dgFloat64 (0.0f));
            if (convexMesh.GetCount())
            {
               convexMesh.CalculateNormals (normalAngleInRadians);
               convexMesh.UniformBoxMapping (materialId, textureProjectionMatrix);
               for (dgInt32 i = 0; i < convexMesh.m_pointCount; i ++)
                  convexMesh.m_points[i].m_w = layer;
               for (dgInt32 i = 0; i < convexMesh.m_atribCount; i ++)
                  convexMesh.m_attrib[i].m_vertex.m_w = layer;
               voronoiPartition->MergeFaces (&convexMesh);
               layer += dgFloat64 (1.0f);
            }
         }
      }
   }
   voronoiPartition->EndPolygon (dgFloat64 (1.0e-8f), false);
   //	voronoiPartition->SaveOFF("xxx0.off");
   //voronoiPartition->ConvertToPolygons();
   return voronoiPartition;
}