A ported helper class from Bullet physics that builds a convex hull (ShapeHull) for a given ConvexShape. It samples unit-sphere directions (with optional preferred penetration directions), obtains support points, runs a hull library to generate vertices and indices, and exposes counts and lists of the result.
/* * C# / XNA port of Bullet (c) 2011 Mark Neale <[email protected]> * * Bullet Continuous Collision Detection and Physics Library * Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ // Adapted from BulletXNA 73b2e1b9: namespace isolation, no XNA rendering, one type per file. #nullable disable #pragma warning disable CS1591, CS0168, CS0219, CS0414, CS0660, CS0661, CS0659, CS0693, CS8981, CS0108, CS0114 using System; using System.Collections.Generic; using HumanoidRetargeter.Core.Formats.Mmd.Bullet.LinearMath; namespace HumanoidRetargeter.Core.Formats.Mmd.Bullet.BulletCollision; internal class ShapeHull { public ShapeHull(ConvexShape convexShape) { m_shape = convexShape; } public bool BuildHull(float margin) { int numSampleDirections = NUM_UNITSPHERE_POINTS; { int numPDA = m_shape.GetNumPreferredPenetrationDirections(); if (numPDA != 0) { for (int i = 0; i < numPDA; i++) { IndexedVector3 norm; m_shape.GetPreferredPenetrationDirection(i, out norm); UnitSpherePoints[numSampleDirections] = norm; numSampleDirections++; } } } IndexedVector3[] supportPoints = new IndexedVector3[NUM_UNITSPHERE_POINTS + ConvexShape.MAX_PREFERRED_PENETRATION_DIRECTIONS * 2]; for (int i = 0; i < numSampleDirections; i++) { supportPoints[i] = m_shape.LocalGetSupportingVertex(ref UnitSpherePoints[i]); } HullDesc hd = new HullDesc(); hd.mFlags = HullFlag.QF_TRIANGLES; hd.mVcount = numSampleDirections; for (int i = 0; i < numSampleDirections; ++i) { hd.mVertices.Add(supportPoints[i]); } HullLibrary hl = new HullLibrary(); HullResult hr = new HullResult(); if (hl.CreateConvexHull(hd, hr) == HullError.QE_FAIL) { return false; } for (int i = 0; i < hr.mNumOutputVertices; i++) { m_vertices[i] = hr.m_OutputVertices[i]; } int numIndices = hr.mNumIndices; for (int i = 0; i < numIndices; i++) { m_indices[i] = hr.m_Indices[i]; } // free temporary hull result that we just copied hl.ReleaseResult(hr); return true; } public int NumTriangles() { return m_indices.Count / 3; } public int NumVertices() { return m_vertices.Count; } public int NumIndices() { return m_indices.Count; } public IList<IndexedVector3> m_vertices = new ObjectArray<IndexedVector3>(); public IList<int> m_indices = new ObjectArray<int>(); public ConvexShape m_shape; const int NUM_UNITSPHERE_POINTS = 42; //static IndexedVector3[] UnitSpherePoints = new IndexedVector3[NUM_UNITSPHERE_POINTS + ConvexShape.MAX_PREFERRED_PENETRATION_DIRECTIONS * 2]; static IndexedVector3[] UnitSpherePoints = new IndexedVector3[] { new IndexedVector3(0.000000f, -0.000000f, -1.000000f), new IndexedVector3(0.723608f, -0.525725f, -0.447219f), new IndexedVector3(-0.276388f, -0.850649f, -0.447219f), new IndexedVector3(-0.894426f, -0.000000f, -0.447216f), new IndexedVector3(-0.276388f, 0.850649f, -0.447220f), new IndexedVector3(0.723608f, 0.525725f, -0.447219f), new IndexedVector3(0.276388f, -0.850649f, 0.447220f), new IndexedVector3(-0.723608f, -0.525725f, 0.447219f), new IndexedVector3(-0.723608f, 0.525725f, 0.447219f), new IndexedVector3(0.276388f, 0.850649f, 0.447219f), new IndexedVector3(0.894426f, 0.000000f, 0.447216f), new IndexedVector3(-0.000000f, 0.000000f, 1.000000f), new IndexedVector3(0.425323f, -0.309011f, -0.850654f), new IndexedVector3(-0.162456f, -0.499995f, -0.850654f), new IndexedVector3(0.262869f, -0.809012f, -0.525738f), new IndexedVector3(0.425323f, 0.309011f, -0.850654f), new IndexedVector3(0.850648f, -0.000000f, -0.525736f), new IndexedVector3(-0.525730f, -0.000000f, -0.850652f), new IndexedVector3(-0.688190f, -0.499997f, -0.525736f), new IndexedVector3(-0.162456f, 0.499995f, -0.850654f), new IndexedVector3(-0.688190f, 0.499997f, -0.525736f), new IndexedVector3(0.262869f, 0.809012f, -0.525738f), new IndexedVector3(0.951058f, 0.309013f, 0.000000f), new IndexedVector3(0.951058f, -0.309013f, 0.000000f), new IndexedVector3(0.587786f, -0.809017f, 0.000000f), new IndexedVector3(0.000000f, -1.000000f, 0.000000f), new IndexedVector3(-0.587786f, -0.809017f, 0.000000f), new IndexedVector3(-0.951058f, -0.309013f, -0.000000f), new IndexedVector3(-0.951058f, 0.309013f, -0.000000f), new IndexedVector3(-0.587786f, 0.809017f, -0.000000f), new IndexedVector3(-0.000000f, 1.000000f, -0.000000f), new IndexedVector3(0.587786f, 0.809017f, -0.000000f), new IndexedVector3(0.688190f, -0.499997f, 0.525736f), new IndexedVector3(-0.262869f, -0.809012f, 0.525738f), new IndexedVector3(-0.850648f, 0.000000f, 0.525736f), new IndexedVector3(-0.262869f, 0.809012f, 0.525738f), new IndexedVector3(0.688190f, 0.499997f, 0.525736f), new IndexedVector3(0.525730f, 0.000000f, 0.850652f), new IndexedVector3(0.162456f, -0.499995f, 0.850654f), new IndexedVector3(-0.425323f, -0.309011f, 0.850654f), new IndexedVector3(-0.425323f, 0.309011f, 0.850654f), new IndexedVector3(0.162456f, 0.499995f, 0.850654f), IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero, IndexedVector3.Zero }; }