Code/HumanoidRetargeter/Core/Formats/Mmd/Bullet/BulletCollision/ShapeHull.cs

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.

Native Interop
/*
 * 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
	};
}