private HitObject[] GenerateHitTargetHits(Table.Table table, IItem item)
        {
            var addedEdges = new EdgeSet();
            var hitMesh    = _meshGenerator.GetRenderObjects(table, Origin.Original, false).RenderObjects[0].Mesh;
            var hitObjects = GenerateCollidables(hitMesh, addedEdges, _data.IsLegacy, table, item).ToList();

            var tempMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(_data.RotZ));
            var fullMatrix = new Matrix3D().Multiply(tempMatrix);

            if (!_data.IsLegacy)
            {
                var rgv3D          = new Vertex3D[DropTargetHitPlaneVertices.Length];
                var hitShapeOffset = 0.18f;
                if (_data.TargetType == TargetType.DropTargetBeveled)
                {
                    hitShapeOffset = 0.25f;
                }
                if (_data.TargetType == TargetType.DropTargetFlatSimple)
                {
                    hitShapeOffset = 0.13f;
                }

                // now create a special hit shape with hit event enabled to prevent a hit event when hit from behind
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; i++)
                {
                    var dropTargetHitPlaneVertex = DropTargetHitPlaneVertices[i];
                    var vert = new Vertex3D(
                        dropTargetHitPlaneVertex.X,
                        dropTargetHitPlaneVertex.Y + hitShapeOffset,
                        dropTargetHitPlaneVertex.Z
                        );

                    vert.X *= _data.Size.X;
                    vert.Y *= _data.Size.Y;
                    vert.Z *= _data.Size.Z;
                    vert.MultiplyMatrix(fullMatrix);
                    rgv3D[i] = new Vertex3D(
                        vert.X + _data.Position.X,
                        vert.Y + _data.Position.Y,
                        vert.Z * table.GetScaleZ() + _data.Position.Z + table.TableHeight
                        );
                }

                for (var i = 0; i < DropTargetHitPlaneIndices.Length; i += 3)
                {
                    var i0 = DropTargetHitPlaneIndices[i];
                    var i1 = DropTargetHitPlaneIndices[i + 1];
                    var i2 = DropTargetHitPlaneIndices[i + 2];

                    // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order
                    var rgv3D2 = new[] { rgv3D[i0], rgv3D[i2], rgv3D[i1] };

                    hitObjects.Add(SetupHitObject(new HitTriangle(rgv3D2, ItemType.HitTarget, item), true, table));
                    hitObjects.AddRange(addedEdges.AddHitEdge(i0, i1, rgv3D2[0], rgv3D2[2], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table)));
                    hitObjects.AddRange(addedEdges.AddHitEdge(i1, i2, rgv3D2[2], rgv3D2[1], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table)));
                    hitObjects.AddRange(addedEdges.AddHitEdge(i2, i0, rgv3D2[1], rgv3D2[0], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table)));
                }

                // add collision vertices
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; ++i)
                {
                    hitObjects.Add(SetupHitObject(new HitPoint(rgv3D[i], ItemType.HitTarget, item), true, table));
                }
            }
            return(hitObjects.ToArray());
        }
        internal void GenerateColliders(float playfieldHeight, ICollection <ICollider> colliders)
        {
            var localToPlayfield = MeshGenerator.GetTransformationMatrix();

            // QUICK FIX and TODO for Cupiii

            /* hitmesh should not be generated by the Mesh generator. Drop Targets need special Hitshapes, that shoujld be very simple and cannot be activated from behind.
             * var hitMesh = MeshGenerator.GetMesh();
             * for (var i = 0; i < hitMesh.Vertices.Length; i++) {
             *      hitMesh.Vertices[i].MultiplyMatrix(localToPlayfield);
             * }
             *
             * var addedEdges = EdgeSet.Get();
             *
             * GenerateCollidables(hitMesh, addedEdges, Data.IsLegacy, colliders);
             */
            var addedEdges = EdgeSet.Get();

            var tempMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(Data.RotZ));
            var fullMatrix = new Matrix3D().Multiply(tempMatrix);

            //if (!Data.IsLegacy)    // Always generate special hitshapes (QUICKFIX)
            {
                var rgv3D          = new Vertex3D[DropTargetHitPlaneVertices.Length];
                var hitShapeOffset = 0.18f;
                if (Data.TargetType == TargetType.DropTargetBeveled)
                {
                    hitShapeOffset = 0.25f;
                }
                if (Data.TargetType == TargetType.DropTargetFlatSimple)
                {
                    hitShapeOffset = 0.13f;
                }

                // now create a special hit shape with hit event enabled to prevent a hit event when hit from behind
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; i++)
                {
                    var dropTargetHitPlaneVertex = DropTargetHitPlaneVertices[i];
                    var vert = new Vertex3D(
                        dropTargetHitPlaneVertex.x,
                        dropTargetHitPlaneVertex.y + hitShapeOffset,
                        dropTargetHitPlaneVertex.z
                        );

                    vert.X  *= Data.ScaleX;
                    vert.Y  *= Data.ScaleY;
                    vert.Z  *= Data.ScaleZ;
                    vert     = vert.MultiplyMatrix(fullMatrix);
                    rgv3D[i] = new Vertex3D(
                        vert.X + Data.PositionX,
                        vert.Y + Data.PositionY,
                        vert.Z + Data.PositionZ + playfieldHeight
                        );
                }

                for (var i = 0; i < DropTargetHitPlaneIndices.Length; i += 3)
                {
                    var i0 = DropTargetHitPlaneIndices[i];
                    var i1 = DropTargetHitPlaneIndices[i + 1];
                    var i2 = DropTargetHitPlaneIndices[i + 2];

                    // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order
                    var rgv0 = rgv3D[i0].ToUnityFloat3();
                    var rgv1 = rgv3D[i1].ToUnityFloat3();
                    var rgv2 = rgv3D[i2].ToUnityFloat3();

                    colliders.Add(new TriangleCollider(rgv0, rgv2, rgv1, GetColliderInfo(true)));

                    if (addedEdges.ShouldAddHitEdge(i0, i1))
                    {
                        colliders.Add(new Line3DCollider(rgv0, rgv2, GetColliderInfo(true)));
                    }
                    if (addedEdges.ShouldAddHitEdge(i1, i2))
                    {
                        colliders.Add(new Line3DCollider(rgv2, rgv1, GetColliderInfo(true)));
                    }
                    if (addedEdges.ShouldAddHitEdge(i2, i0))
                    {
                        colliders.Add(new Line3DCollider(rgv1, rgv0, GetColliderInfo(true)));
                    }
                }

                // add collision vertices
                for (var i = 0; i < DropTargetHitPlaneVertices.Length; ++i)
                {
                    colliders.Add(new PointCollider(rgv3D[i].ToUnityFloat3(), GetColliderInfo(true)));
                }
            }
        }