public static void ExtrudeText(this MeshBuilder builder, string text, string font, FontStyle fontStyle, FontWeight fontWeight, double fontSize, Vector3D textDirection, Point3D p0, Point3D p1)
        {
            var outlineList = GetTextOutlines(text, font, fontStyle, fontWeight, fontSize);

            // Build the polygon to mesh (using Triangle.NET to triangulate)
            var polygon = new TriangleNet.Geometry.Polygon();
            int marker = 0;

            foreach (var outlines in outlineList)
            {
                var outerOutline = outlines.OrderBy(x => x.AreaOfSegment()).Last();

                for (int i = 0; i < outlines.Count; i++)
                {
                    var outline = outlines[i];
                    var isHole = i != outlines.Count - 1 && IsPointInPolygon(outerOutline, outline[0]);
                    polygon.AddContour(outline.Select(p => new Vertex(p.X, p.Y)), marker++, isHole);
                    builder.AddExtrudedSegments(outline.ToSegments().ToList(), textDirection, p0, p1);
                }
            }

            var mesher = new GenericMesher();
            var options = new ConstraintOptions();
            var mesh = mesher.Triangulate(polygon, options);

            var u = textDirection;
            u.Normalize();
            var z = p1 - p0;
            z.Normalize();
            var v = Vector3D.CrossProduct(z, u);

            // Convert the triangles
            foreach (var t in mesh.Triangles)
            {
                var v0 = t.GetVertex(0);
                var v1 = t.GetVertex(1);
                var v2 = t.GetVertex(2);

                // Add the top triangle.
                // Project the X/Y vertices onto a plane defined by textdirection, p0 and p1.
                builder.AddTriangle(v0.Project(p0, u, v, z, 1), v1.Project(p0, u, v, z, 1), v2.Project(p0, u, v, z, 1));

                // Add the bottom triangle.
                builder.AddTriangle(v2.Project(p0, u, v, z, 0), v1.Project(p0, u, v, z, 0), v0.Project(p0, u, v, z, 0));
            }
        }
		public unsafe static void AddTriangle(this TriangleMesh obj, ref OpenTK.Vector3 vertex0, ref OpenTK.Vector3 vertex1, ref OpenTK.Vector3 vertex2, bool removeDuplicateVertices)
		{
			fixed (OpenTK.Vector3* vertex0Ptr = &vertex0)
			{
				fixed (OpenTK.Vector3* vertex1Ptr = &vertex1)
				{
					fixed (OpenTK.Vector3* vertex2Ptr = &vertex2)
					{
						obj.AddTriangle(ref *(BulletSharp.Math.Vector3*)vertex0Ptr, ref *(BulletSharp.Math.Vector3*)vertex1Ptr, ref *(BulletSharp.Math.Vector3*)vertex2Ptr, removeDuplicateVertices);
					}
				}
			}
		}
 public static void AddTriangle(this IDrawTrianglesMessage msg, Vector3D v0, Vector3D v1, Vector3D v2)
 {
     msg.AddTriangle(ref v0, ref v1, ref v2);
 }